Back to index

lightning-sunbird  0.9+nobinonly
mozSqlResultPgsql.cpp
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is mozilla.org code.
00015  *
00016  * The Initial Developer of the Original Code is Jan Varga
00017  * Portions created by the Initial Developer are Copyright (C) 2003
00018  * the Initial Developer. All Rights Reserved.
00019  *
00020  * Contributor(s):
00021  *
00022  * Alternatively, the contents of this file may be used under the terms of
00023  * either the GNU General Public License Version 2 or later (the "GPL"), or
00024  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00025  * in which case the provisions of the GPL or the LGPL are applicable instead
00026  * of those above. If you wish to allow use of your version of this file only
00027  * under the terms of either the GPL or the LGPL, and not to allow others to
00028  * use your version of this file under the terms of the MPL, indicate your
00029  * decision by deleting the provisions above and replace them with the notice
00030  * and other provisions required by the GPL or the LGPL. If you do not delete
00031  * the provisions above, a recipient may use your version of this file under
00032  * the terms of any one of the MPL, the GPL or the LGPL.
00033  *
00034  * ***** END LICENSE BLOCK ***** */
00035 
00036 #include "prprf.h"
00037 #include "nsReadableUtils.h"
00038 #include "mozSqlResultPgsql.h"
00039 
00040 mozSqlResultPgsql::mozSqlResultPgsql(mozISqlConnection* aConnection,
00041                                      const nsAString& aQuery)
00042   : mozSqlResult(aConnection, aQuery),
00043     mResult(nsnull),
00044     mTypes(nsnull)
00045 {
00046 }
00047 
00048 void
00049 mozSqlResultPgsql::SetResult(PGresult* aResult,
00050                              PGresult* aTypes)
00051 {
00052   mResult = aResult;
00053   mTypes = aTypes;
00054 }
00055 
00056 mozSqlResultPgsql::~mozSqlResultPgsql()
00057 {
00058   ClearNativeResult();
00059 }
00060 
00061 NS_IMPL_ADDREF_INHERITED(mozSqlResultPgsql, mozSqlResult)
00062 NS_IMPL_RELEASE_INHERITED(mozSqlResultPgsql, mozSqlResult)
00063 
00064 // QueryInterface
00065 NS_INTERFACE_MAP_BEGIN(mozSqlResultPgsql)
00066   NS_INTERFACE_MAP_ENTRY(mozISqlResultPgsql)
00067 NS_INTERFACE_MAP_END_INHERITING(mozSqlResult)
00068 
00069 PRInt32
00070 mozSqlResultPgsql::GetColType(PRInt32 aColumnIndex)
00071 {
00072   PRInt32 oid = PQftype(mResult, aColumnIndex);
00073 
00074   for (PRInt32 i = 0; i < PQntuples(mTypes); i++) {
00075     char* value = PQgetvalue(mTypes, i, 0);
00076     PRInt32 o;
00077     PR_sscanf(value, "%d", &o);
00078     if (o == oid) {
00079       char* type = PQgetvalue(mTypes, i, 1);
00080       if (! strcmp(type, "int2"))
00081         return mozISqlResult::TYPE_INT;
00082       else if (! strcmp(type, "int4"))
00083         return mozISqlResult::TYPE_INT;
00084       else if (! strcmp(type, "float4"))
00085         return mozISqlResult::TYPE_STRING;
00086       else if (! strcmp(type, "numeric"))
00087         return mozISqlResult::TYPE_STRING;
00088       else if (! strcmp(type, "date"))
00089         return mozISqlResult::TYPE_STRING;
00090       else if (! strcmp(type, "time"))
00091         return mozISqlResult::TYPE_STRING;
00092       else if (! strcmp(type, "timestamp"))
00093         return mozISqlResult::TYPE_STRING;
00094       else if (! strcmp(type, "bool"))
00095         return mozISqlResult::TYPE_BOOL;
00096       else
00097         return mozISqlResult::TYPE_STRING;
00098     }
00099   }
00100 
00101   return mozISqlResult::TYPE_STRING;
00102 }
00103 
00104 nsresult
00105 mozSqlResultPgsql::BuildColumnInfo()
00106 {
00107   for (PRInt32 i = 0; i < PQnfields(mResult); i++) {
00108     char* n = PQfname(mResult, i);
00109     PRUnichar* name = UTF8ToNewUnicode(nsDependentCString(n));
00110     PRInt32 type = GetColType(i);
00111     PRInt32 size = PQfsize(mResult, i);
00112     PRInt32 mod = PQfmod(mResult, i);
00113 
00114     nsCAutoString uri(NS_LITERAL_CSTRING("http://www.mozilla.org/SQL-rdf#"));
00115     uri.Append(n);
00116     nsCOMPtr<nsIRDFResource> property;
00117     gRDFService->GetResource(uri, getter_AddRefs(property));
00118 
00119     ColumnInfo* columnInfo = ColumnInfo::Create(mAllocator, name, type, size, mod, PR_FALSE, property);
00120     mColumnInfo.AppendElement(columnInfo); 
00121   }
00122 
00123   return NS_OK;
00124 }
00125 
00126 nsresult
00127 mozSqlResultPgsql::BuildRows()
00128 {
00129   for(PRInt32 i = 0; i < PQntuples(mResult); i++) {
00130     nsCOMPtr<nsIRDFResource> resource;
00131     nsresult rv = gRDFService->GetAnonymousResource(getter_AddRefs(resource));
00132     if (NS_FAILED(rv)) return rv;
00133 
00134     Row* row = Row::Create(mAllocator, resource, mColumnInfo);
00135 
00136     for (PRInt32 j = 0; j < mColumnInfo.Count(); j++) {
00137       if (! PQgetisnull(mResult, i, j)) {
00138         char* value = PQgetvalue(mResult, i, j);
00139         Cell* cell = row->mCells[j];
00140         cell->SetNull(PR_FALSE);
00141         PRInt32 type = cell->GetType();
00142         if (type == mozISqlResult::TYPE_STRING)
00143           cell->SetString(UTF8ToNewUnicode(nsDependentCString(value)));
00144         else if (type == mozISqlResult::TYPE_INT)
00145           PR_sscanf(value, "%d", &cell->mInt);
00146         else if (type == mozISqlResult::TYPE_FLOAT)
00147           PR_sscanf(value, "%f", &cell->mFloat);
00148         else if (type == mozISqlResult::TYPE_DECIMAL)
00149           PR_sscanf(value, "%f", &cell->mFloat);
00150         else if (type == mozISqlResult::TYPE_DATE ||
00151                  type == mozISqlResult::TYPE_TIME ||
00152                  type == mozISqlResult::TYPE_DATETIME)
00153           PR_ParseTimeString(value, PR_FALSE, &cell->mDate);
00154         else if (type == mozISqlResult::TYPE_BOOL)
00155           cell->mBool = !strcmp(value, "t");
00156       }
00157     }
00158 
00159     mRows.AppendElement(row);
00160     nsVoidKey key(resource);
00161     mSources.Put(&key, row);
00162   }
00163 
00164   return NS_OK;
00165 }
00166 
00167 void
00168 mozSqlResultPgsql::ClearNativeResult()
00169 {
00170   if (mResult) {
00171     PQclear(mResult);
00172     mResult = nsnull;
00173   }
00174   if (mTypes) {
00175     PQclear(mTypes);
00176     mTypes = nsnull;
00177   }
00178 }
00179 
00180 nsresult
00181 mozSqlResultPgsql::EnsureTablePrivileges()
00182 {
00183   nsresult rv = EnsureTableName();
00184   if (NS_FAILED(rv))
00185     return rv;
00186 
00187   NS_NAMED_LITERAL_STRING(select, "select ");
00188   NS_NAMED_LITERAL_STRING(func, "has_table_privilege(SESSION_USER, '");
00189   NS_NAMED_LITERAL_STRING(comma, ", ");
00190   NS_NAMED_LITERAL_STRING(ins, "', 'INSERT')");
00191   NS_NAMED_LITERAL_STRING(upd, "', 'UPDATE')");
00192   NS_NAMED_LITERAL_STRING(del, "','DELETE')");
00193 
00194   nsCOMPtr<mozISqlResult> result;
00195   rv = mConnection->ExecuteQuery(
00196     select + func + mTableName + ins +
00197     comma + func + mTableName + upd +
00198     comma + func + mTableName + del,
00199     getter_AddRefs(result));
00200   if (NS_FAILED(rv)) {
00201     mConnection->GetErrorMessage(mErrorMessage);
00202     return rv;
00203   }
00204 
00205   nsCOMPtr<mozISqlResultEnumerator> enumerator;
00206   rv = result->Enumerate(getter_AddRefs(enumerator));
00207   if (NS_FAILED(rv))
00208     return rv;
00209 
00210   rv = enumerator->First();
00211   if (NS_FAILED(rv))
00212     return rv;
00213 
00214   rv = enumerator->GetBool(0, &mCanInsert);
00215   if (NS_FAILED(rv))
00216     return rv;
00217   rv = enumerator->GetBool(1, &mCanUpdate);
00218   if (NS_FAILED(rv))
00219     return rv;
00220   return enumerator->GetBool(2, &mCanDelete);
00221 }
00222 
00223 nsresult
00224 mozSqlResultPgsql::CanInsert(PRBool* _retval)
00225 {
00226   if (mCanInsert >= 0) {
00227     *_retval = mCanInsert;
00228     return NS_OK;
00229   }
00230 
00231   nsresult rv = EnsureTablePrivileges();
00232   if (NS_FAILED(rv))
00233     return rv;
00234   *_retval = mCanInsert;
00235 
00236   return NS_OK;
00237 }
00238 
00239 nsresult
00240 mozSqlResultPgsql::CanUpdate(PRBool* _retval)
00241 {
00242   if (mCanUpdate >= 0) {
00243     *_retval = mCanUpdate;
00244     return NS_OK;
00245   }
00246 
00247   nsresult rv = EnsureTablePrivileges();
00248   if (NS_FAILED(rv))
00249     return rv;
00250   *_retval = mCanUpdate;
00251 
00252   return NS_OK;
00253 }
00254 
00255 nsresult
00256 mozSqlResultPgsql::CanDelete(PRBool* _retval)
00257 {
00258   if (mCanDelete >= 0) {
00259     *_retval = mCanDelete;
00260     return NS_OK;
00261   }
00262 
00263   nsresult rv = EnsureTablePrivileges();
00264   if (NS_FAILED(rv))
00265     return rv;
00266   *_retval = mCanDelete;
00267 
00268   return NS_OK;
00269 }