Back to index

lightning-sunbird  0.9+nobinonly
mozSqlResult.h
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 #ifndef mozSqlResult_h
00037 #define mozSqlResult_h                                                  
00038 
00039 #include "nsCRT.h"
00040 #include "nsFixedSizeAllocator.h"
00041 #include "nsVoidArray.h"
00042 #include "nsCOMArray.h"
00043 #include "nsHashtable.h"
00044 #include "nsCOMPtr.h"
00045 #include "nsWeakReference.h"
00046 #include "nsISimpleEnumerator.h"
00047 #include "nsIRDFService.h"
00048 #include "nsIRDFDataSource.h"
00049 #include "nsIRDFRemoteDataSource.h"
00050 #include "nsITreeView.h"
00051 #include "nsITreeSelection.h"
00052 #include "nsITreeBoxObject.h"
00053 #include "nsIDateTimeFormat.h"
00054 #include "nsIInputStream.h"
00055 #include "mozISqlConnection.h"
00056 #include "mozISqlDataSource.h"
00057 #include "mozISqlResult.h"
00058 #include "mozISqlResultEnumerator.h"
00059 #include "mozISqlInputStream.h"
00060 
00061 #define CELL_FLAG_NULL          0x80
00062 #define CELL_FLAG_DEFAULT       0x40
00063 #define CELL_FLAG_MASK          ~(CELL_FLAG_NULL | CELL_FLAG_DEFAULT)
00064 
00065 class ColumnInfo {
00066   public:
00067     static ColumnInfo*
00068     Create(nsFixedSizeAllocator& aAllocator,
00069            PRUnichar* aName,
00070           PRInt32 aType,
00071           PRInt32 aSize,
00072           PRInt32 aMod,
00073            PRBool aIsPrimaryKey,
00074            nsIRDFResource* aProperty) {
00075       void* place = aAllocator.Alloc(sizeof(ColumnInfo));
00076       return place ? ::new(place) ColumnInfo(aName, aType, aSize, aMod, aIsPrimaryKey, aProperty) : nsnull;
00077     }
00078 
00079     static void
00080     Destroy(nsFixedSizeAllocator& aAllocator, ColumnInfo* aColumnInfo) {
00081       aColumnInfo->~ColumnInfo();
00082       aAllocator.Free(aColumnInfo, sizeof(ColumnInfo));
00083     }
00084 
00085     ColumnInfo(PRUnichar* aName, PRInt32 aType, PRInt32 aSize, PRInt32 aMod,
00086                PRBool aIsPrimaryKey, nsIRDFResource* aProperty)
00087       : mName(aName),
00088         mType(aType),
00089         mSize(aSize),
00090         mMod(aMod),
00091         mIsPrimaryKey(aIsPrimaryKey),
00092        mProperty(aProperty) {
00093       NS_IF_ADDREF(mProperty);
00094     }
00095 
00096     ~ColumnInfo() {
00097       if (mName)
00098         nsMemory::Free(mName);
00099       NS_IF_RELEASE(mProperty);
00100     }
00101 
00102     PRUnichar*          mName;
00103     PRInt32             mType;
00104     PRInt32             mSize;
00105     PRInt32             mMod;
00106     PRBool              mIsPrimaryKey;
00107     nsIRDFResource*     mProperty;
00108 
00109   private:
00110     // Hide so that only Create() and Destroy() can be used to
00111     // allocate and deallocate from the heap
00112     static void* operator new(size_t) CPP_THROW_NEW { return 0; } 
00113     static void operator delete(void*, size_t) {}
00114 };
00115 
00116 class Cell {
00117   public:
00118     static Cell*
00119     Create(nsFixedSizeAllocator& aAllocator,
00120            PRInt32 aType) {
00121       void* place = aAllocator.Alloc(sizeof(Cell));
00122       return place ? ::new(place) Cell(aType) : nsnull;
00123     }
00124 
00125     static Cell*
00126     Create(nsFixedSizeAllocator& aAllocator,
00127            PRInt32 aType,
00128            Cell* aSrcCell) {
00129       void* place = aAllocator.Alloc(sizeof(Cell));
00130       if (! place)
00131         return nsnull;
00132       Cell* newCell = ::new(place) Cell(aType);
00133       Copy(aSrcCell, newCell);
00134       return newCell;
00135     }
00136 
00137     static void
00138     Copy(Cell* aSrcCell, Cell* aDestCell) {
00139       if (aSrcCell->IsNull())
00140         aDestCell->SetNull(PR_TRUE);
00141       else {
00142         aDestCell->SetNull(PR_FALSE);
00143         PRInt32 type = aSrcCell->GetType();
00144         if (type == mozISqlResult::TYPE_STRING)
00145           aDestCell->SetString(nsCRT::strdup(aSrcCell->mString));
00146         else if (type == mozISqlResult::TYPE_INT)
00147           aDestCell->mInt = aSrcCell->mInt;
00148         else if (type == mozISqlResult::TYPE_FLOAT ||
00149                  type == mozISqlResult::TYPE_DECIMAL)
00150           aDestCell->mFloat = aSrcCell->mFloat;
00151         else if (type == mozISqlResult::TYPE_DATE ||
00152                  type == mozISqlResult::TYPE_TIME ||
00153                  type == mozISqlResult::TYPE_DATETIME)
00154           aDestCell->mDate = aSrcCell->mDate;
00155         else if (type == mozISqlResult::TYPE_BOOL)
00156           aDestCell->mBool = aSrcCell->mBool;
00157       }
00158     }
00159 
00160     static void
00161     Destroy(nsFixedSizeAllocator& aAllocator, Cell* aCell) {
00162       aCell->~Cell();
00163       aAllocator.Free(aCell, sizeof(Cell));
00164     }
00165 
00166     Cell(PRInt32 aType)
00167       : mString(nsnull),
00168         mType(aType | CELL_FLAG_NULL) {
00169     }
00170 
00171     ~Cell() {
00172       if ((GetType() == mozISqlResult::TYPE_STRING) && mString) {
00173         nsMemory::Free(mString);
00174       }
00175     }
00176 
00177     void SetString(PRUnichar* aString) {
00178      if (mString)
00179         nsMemory::Free(mString);
00180       mString = aString;
00181     }
00182 
00183     PRInt32 GetType() {
00184       return mType & CELL_FLAG_MASK;
00185     }
00186 
00187     void SetNull(PRBool aNull) {
00188       mType &= CELL_FLAG_MASK;
00189       if (aNull)
00190         mType |= CELL_FLAG_NULL;
00191     }
00192 
00193     void SetDefault(PRBool aDefault) {
00194       mType &= CELL_FLAG_MASK;
00195       if (aDefault)
00196         mType |= CELL_FLAG_DEFAULT;
00197     }
00198 
00199     PRBool IsNull() {
00200       return mType & CELL_FLAG_NULL;
00201     }
00202 
00203     PRBool IsDefault() {
00204       return mType & CELL_FLAG_DEFAULT;
00205     }
00206 
00207     union {
00208       PRUnichar*        mString;
00209       PRInt32           mInt;
00210       float             mFloat;
00211       PRInt64           mDate;
00212       PRBool            mBool;
00213     };
00214 
00215   private:
00216     static void* operator new(size_t) CPP_THROW_NEW { return 0; } 
00217     static void operator delete(void*, size_t) {}
00218 
00219     PRInt8              mType;
00220 };
00221 
00222 class Row {
00223   public:
00224     static Row*
00225     Create(nsFixedSizeAllocator& aAllocator,
00226            nsIRDFResource* aSource,
00227            nsVoidArray& aColumnInfo) {
00228       void* place = aAllocator.Alloc(sizeof(Row));
00229       if (! place)
00230         return nsnull;
00231       Row* newRow = ::new(place) Row(aSource, aColumnInfo.Count());
00232       for (PRInt32 i = 0; i < aColumnInfo.Count(); i++) {
00233         Cell* newCell = Cell::Create(aAllocator, ((ColumnInfo*)aColumnInfo[i])->mType);
00234         newRow->mCells[i] = newCell;
00235       }
00236       return newRow;
00237     }
00238 
00239     static Row*
00240     Create(nsFixedSizeAllocator& aAllocator,
00241            nsIRDFResource* aSource,
00242            nsVoidArray& aColumnInfo,
00243            Row* aSrcRow) {
00244       void* place = aAllocator.Alloc(sizeof(Row));
00245       if (! place)
00246         return nsnull;
00247       Row* newRow = ::new(place) Row(aSource, aColumnInfo.Count());
00248       for (PRInt32 i = 0; i < aColumnInfo.Count(); i++) {
00249         Cell* srcCell = aSrcRow->mCells[i];
00250         Cell* newCell = Cell::Create(aAllocator, ((ColumnInfo*)aColumnInfo[i])->mType, srcCell);
00251         newRow->mCells[i] = newCell;
00252       }
00253       return newRow;
00254     }
00255 
00256     static void
00257     Copy(PRInt32 aColumnCount, Row* aSrcRow, Row* aDestRow) {
00258       for (PRInt32 i = 0; i < aColumnCount; i++) {
00259         Cell* srcCell = aSrcRow->mCells[i];
00260         Cell* destCell = aDestRow->mCells[i];
00261         Cell::Copy(srcCell, destCell);
00262       }
00263     }
00264 
00265     static void
00266     Destroy(nsFixedSizeAllocator& aAllocator, PRInt32 aColumnCount, Row* aRow) {
00267       for (PRInt32 i = 0; i < aColumnCount; i++)
00268         Cell::Destroy(aAllocator, aRow->mCells[i]);
00269       aRow->~Row();
00270       aAllocator.Free(aRow, sizeof(*aRow));
00271     }
00272 
00273     Row(nsIRDFResource* aSource, PRInt32 aColumnCount)
00274       : mSource(aSource)
00275     {
00276       NS_IF_ADDREF(mSource);
00277       mCells = new Cell*[aColumnCount];
00278     }
00279 
00280     ~Row() {
00281       delete[] mCells;
00282       NS_IF_RELEASE(mSource);
00283     }
00284     
00285     nsIRDFResource*     mSource;
00286     Cell**              mCells;
00287   private:
00288     static void* operator new(size_t) CPP_THROW_NEW { return 0; } 
00289     static void operator delete(void*, size_t) {}
00290 };
00291 
00292 class mozSqlResult : public mozISqlResult,
00293                      public mozISqlDataSource,
00294                      public nsIRDFDataSource,
00295                      public nsIRDFRemoteDataSource,
00296                      public nsINativeTreeView
00297 {
00298   public:
00299     mozSqlResult(mozISqlConnection* aConnection,
00300                  const nsAString& aQuery);
00301     nsresult Init();
00302     nsresult Rebuild();
00303     virtual ~mozSqlResult();
00304 
00305     NS_DECL_ISUPPORTS
00306 
00307     //NS_DECL_MOZISQLRESULT
00308     NS_IMETHOD GetDisplayNullAsText(PRBool *aDisplayNullAsText);
00309     NS_IMETHOD SetDisplayNullAsText(PRBool aDisplayNullAsText);
00310     NS_IMETHOD GetConnection(mozISqlConnection * *aConnection);
00311     NS_IMETHOD GetQuery(nsAString & aQuery);
00312     NS_IMETHOD GetTableName(nsAString & aTableName);
00313     //NS_IMETHOD GetRowCount(PRInt32 *aRowCount);
00314     NS_IMETHOD GetColumnCount(PRInt32 *aColumnCount);
00315     NS_IMETHOD GetColumnName(PRInt32 aColumnIndex, nsAString & _retval);
00316     NS_IMETHOD GetColumnIndex(const nsAString & aColumnName, PRInt32 *_retval);
00317     NS_IMETHOD GetColumnType(PRInt32 aColumnIndex, PRInt32 *_retval);
00318     NS_IMETHOD GetColumnTypeAsString(PRInt32 aColumnIndex, nsAString & _retval);
00319     NS_IMETHOD GetColumnDisplaySize(PRInt32 aColumnIndex, PRInt32 *_retval);
00320     NS_IMETHOD Enumerate(mozISqlResultEnumerator **_retval);
00321     NS_IMETHOD Open(mozISqlInputStream **_retval);
00322     NS_IMETHOD Reload(void);
00323 
00324     NS_DECL_MOZISQLDATASOURCE
00325 
00326     NS_DECL_NSIRDFDATASOURCE
00327 
00328     NS_DECL_NSIRDFREMOTEDATASOURCE
00329 
00330     NS_DECL_NSITREEVIEW
00331     // nsINativeTreeView: Untrusted code can use us
00332     NS_IMETHOD EnsureNative() { return NS_OK; }
00333 
00334     friend class mozSqlResultEnumerator;
00335     friend class mozSqlResultStream;
00336 
00337   protected:
00338     virtual nsresult BuildColumnInfo() = 0 ;
00339     virtual nsresult BuildRows() = 0;
00340     virtual void ClearNativeResult() = 0;
00341 
00342     void ClearColumnInfo();
00343     void ClearRows();
00344 
00345     nsresult EnsureTableName();
00346     virtual nsresult EnsurePrimaryKeys();
00347 
00348     void AppendValue(Cell* aCell, nsAutoString& aValues);
00349     virtual nsresult AppendKeys(Row* aRow, nsAutoString& aKeys);
00350     nsresult GetValues(Row* aRow, mozISqlResult** aResult, PRBool aUseID);
00351     nsresult CopyValues(mozISqlResult* aResult, Row* aRow);
00352 
00353     virtual nsresult CanInsert(PRBool* _retval) = 0;
00354     virtual nsresult CanUpdate(PRBool* _retval) = 0;
00355     virtual nsresult CanDelete(PRBool* _retval) = 0;
00356 
00357     nsresult InsertRow(Row* aSrcRow, PRInt32* _retval);
00358     nsresult UpdateRow(PRInt32 aRowIndex, Row* aSrcRow, PRInt32* _retval);
00359     nsresult DeleteRow(PRInt32 aRowIndex, PRInt32* _retval);
00360     nsresult GetCondition(Row* aRow, nsAString& aCurrentCondition);
00361 
00362     static PRInt32                      gRefCnt;
00363     static nsIRDFService*               gRDFService;
00364     static nsIDateTimeFormat*           gFormat;
00365     static nsIRDFResource*              kSQL_ResultRoot;
00366     static nsIRDFResource*              kNC_Child;
00367     static nsIRDFLiteral*               kNullLiteral;
00368     static nsIRDFLiteral*               kEmptyLiteral;
00369     static nsIRDFLiteral*               kTrueLiteral;
00370     static nsIRDFLiteral*               kFalseLiteral;
00371 
00372     PRBool                              mDisplayNullAsText;
00373     nsCOMPtr<mozISqlConnection>         mConnection;
00374     nsString                            mErrorMessage;
00375     nsString                            mQuery;
00376     nsString                            mTableName;
00377     nsFixedSizeAllocator                mAllocator;
00378     nsAutoVoidArray                     mColumnInfo;
00379     nsVoidArray                         mRows;
00380     nsObjectHashtable                   mSources;
00381     nsCOMArray<nsIRDFObserver>          mObservers;
00382     nsCOMPtr<nsITreeSelection>          mSelection;
00383     nsCOMPtr<nsITreeBoxObject>          mBoxObject;
00384     nsCOMPtr<mozISqlResultEnumerator>   mPrimaryKeys;
00385     PRInt32                             mCanInsert;
00386     PRInt32                             mCanUpdate;
00387     PRInt32                             mCanDelete;
00388 };
00389 
00390 class mozSqlResultEnumerator : public mozISqlResultEnumerator,
00391                                public nsISimpleEnumerator
00392 {
00393   public:
00394     mozSqlResultEnumerator(mozSqlResult* aResult);
00395     virtual ~mozSqlResultEnumerator();
00396 
00397     NS_DECL_ISUPPORTS
00398 
00399     NS_DECL_MOZISQLRESULTENUMERATOR
00400 
00401     NS_DECL_NSISIMPLEENUMERATOR
00402 
00403   private:
00404     mozSqlResult*               mResult;
00405     PRInt32                     mCurrentIndex;
00406     Row*                        mCurrentRow;
00407     Row*                        mBuffer;
00408 };
00409 
00410 class mozSqlResultStream : public mozISqlInputStream,
00411                            public nsIInputStream
00412 {
00413   public:
00414     mozSqlResultStream(mozSqlResult* aResult);
00415     virtual ~mozSqlResultStream();
00416 
00417     NS_DECL_ISUPPORTS
00418 
00419     NS_DECL_MOZISQLINPUTSTREAM
00420 
00421     NS_DECL_NSIINPUTSTREAM
00422 
00423   protected:
00424     nsresult EnsureBuffer();
00425 
00426   private:
00427     mozSqlResult*               mResult;
00428     nsCAutoString               mBuffer;
00429     PRBool                      mInitialized;
00430     PRUint32                    mPosition;
00431 };
00432 
00433 #endif // mozSqlResult_h