Back to index

lightning-sunbird  0.9+nobinonly
mozSqlResult.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 <stdio.h>
00037 #include "nsCRT.h"
00038 #include "nsIVariant.h"
00039 #include "nsReadableUtils.h"
00040 #include "nsUnicharUtils.h"
00041 #include "rdf.h"
00042 #include "nsIServiceManager.h"
00043 #include "nsRDFCID.h"
00044 #include "nsDateTimeFormatCID.h"
00045 #include "mozSqlResult.h"
00046 #include "mozSqlConnection.h"
00047 #include "nsITreeColumns.h"
00048 
00049 static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
00050 static NS_DEFINE_CID(kDateTimeFormatCID, NS_DATETIMEFORMAT_CID);
00051 
00052 PRInt32                 mozSqlResult::gRefCnt = 0;
00053 nsIRDFService*          mozSqlResult::gRDFService;
00054 nsIDateTimeFormat*      mozSqlResult::gFormat;
00055 nsIRDFResource*         mozSqlResult::kSQL_ResultRoot;
00056 nsIRDFResource*         mozSqlResult::kNC_Child;
00057 nsIRDFLiteral*          mozSqlResult::kNullLiteral;
00058 nsIRDFLiteral*          mozSqlResult::kEmptyLiteral;
00059 nsIRDFLiteral*          mozSqlResult::kTrueLiteral;
00060 nsIRDFLiteral*          mozSqlResult::kFalseLiteral;
00061 
00062 mozSqlResult::mozSqlResult(mozISqlConnection* aConnection,
00063                          const nsAString& aQuery)
00064   : mDisplayNullAsText(PR_FALSE),
00065     mConnection(aConnection),
00066     mQuery(aQuery),
00067     mSources(nsnull, nsnull, nsnull, nsnull),
00068     mCanInsert(-1),
00069     mCanUpdate(-1),
00070     mCanDelete(-1)
00071 {
00072 }
00073 
00074 nsresult
00075 mozSqlResult::Init()
00076 {
00077   nsresult rv;
00078 
00079   if (gRefCnt++ == 0) {
00080     rv = CallGetService(kRDFServiceCID, &gRDFService);
00081     if (NS_FAILED(rv)) return rv;
00082 
00083     rv = CallCreateInstance(kDateTimeFormatCID, &gFormat);
00084     if (NS_FAILED(rv)) return rv;
00085 
00086     rv = gRDFService->GetResource(NS_LITERAL_CSTRING("SQL:ResultRoot"),
00087                                   &kSQL_ResultRoot);
00088     if (NS_FAILED(rv)) return rv;
00089     rv = gRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "child"),
00090                                   &kNC_Child);
00091     if (NS_FAILED(rv)) return rv;
00092 
00093     rv = gRDFService->GetLiteral(NS_LITERAL_STRING("null").get(), &kNullLiteral);
00094     if (NS_FAILED(rv)) return rv;
00095     rv = gRDFService->GetLiteral(EmptyString().get(), &kEmptyLiteral);
00096     if (NS_FAILED(rv)) return rv;
00097     rv = gRDFService->GetLiteral(NS_LITERAL_STRING("true").get(), &kTrueLiteral);
00098     if (NS_FAILED(rv)) return rv;
00099     rv = gRDFService->GetLiteral(NS_LITERAL_STRING("false").get(), &kFalseLiteral);
00100     if (NS_FAILED(rv)) return rv;
00101   }
00102 
00103   static const size_t kBucketSizes[] = {
00104     sizeof(ColumnInfo),
00105     sizeof(Cell),
00106     sizeof(Row)
00107   };
00108   static const PRInt32 kNumBuckets = sizeof(kBucketSizes) / sizeof(size_t);
00109   static const PRInt32 kInitialSize = 16;
00110 
00111   mAllocator.Init("mozSqlResult", kBucketSizes, kNumBuckets, kInitialSize);
00112 
00113   return Rebuild();
00114 }
00115 
00116 nsresult
00117 mozSqlResult::Rebuild()
00118 {
00119   ClearRows();
00120   ClearColumnInfo();
00121 
00122   nsresult rv = BuildColumnInfo();
00123   if (NS_FAILED(rv)) return rv;
00124 
00125   rv = BuildRows();
00126   if (NS_FAILED(rv)) return rv;
00127 
00128   ClearNativeResult();
00129 
00130   return NS_OK;
00131 }
00132 
00133 mozSqlResult::~mozSqlResult()
00134 {
00135   ClearRows();
00136   ClearColumnInfo();
00137 
00138   if (--gRefCnt == 0) {
00139     NS_IF_RELEASE(kFalseLiteral);
00140     NS_IF_RELEASE(kTrueLiteral);
00141     NS_IF_RELEASE(kEmptyLiteral);
00142     NS_IF_RELEASE(kNullLiteral);
00143     NS_IF_RELEASE(kNC_Child);
00144     NS_IF_RELEASE(kSQL_ResultRoot);
00145 
00146     NS_IF_RELEASE(gFormat);
00147     NS_IF_RELEASE(gRDFService);
00148     gRDFService = nsnull;
00149   }
00150 }
00151 
00152 
00153 NS_IMPL_THREADSAFE_ISUPPORTS5(mozSqlResult,
00154                               mozISqlResult,
00155                               mozISqlDataSource,
00156                               nsIRDFDataSource,
00157                               nsIRDFRemoteDataSource,
00158                               nsITreeView)
00159 
00160 NS_IMETHODIMP
00161 mozSqlResult::GetDisplayNullAsText(PRBool* aDisplayNullAsText)
00162 {
00163   *aDisplayNullAsText = mDisplayNullAsText;
00164   return NS_OK;
00165 }
00166 
00167 NS_IMETHODIMP
00168 mozSqlResult::SetDisplayNullAsText(PRBool aDisplayNullAsText)
00169 {
00170   mDisplayNullAsText = aDisplayNullAsText;
00171   return NS_OK;
00172 }
00173 
00174 NS_IMETHODIMP
00175 mozSqlResult::GetConnection(mozISqlConnection** aConnection)
00176 {
00177   NS_ADDREF(*aConnection = mConnection);
00178   return NS_OK;
00179 }
00180 
00181 NS_IMETHODIMP
00182 mozSqlResult::GetQuery(nsAString& aQuery)
00183 {
00184   aQuery = mQuery;
00185   return NS_OK;
00186 }
00187 
00188 NS_IMETHODIMP
00189 mozSqlResult::GetTableName(nsAString& aTableName)
00190 {
00191   nsresult rv = EnsureTableName();
00192   if (NS_FAILED(rv))
00193     return rv;
00194   aTableName = mTableName;
00195   return NS_OK;
00196 }
00197 
00198 NS_IMETHODIMP
00199 mozSqlResult::GetRowCount(PRInt32 *aRowCount)
00200 {
00201   *aRowCount = mRows.Count();
00202   return NS_OK;
00203 }
00204 
00205 NS_IMETHODIMP
00206 mozSqlResult::GetColumnCount(PRInt32 *aColumnCount)
00207 {
00208   *aColumnCount = mColumnInfo.Count();
00209   return NS_OK;
00210 }
00211 
00212 NS_IMETHODIMP
00213 mozSqlResult::GetColumnName(PRInt32 aColumnIndex, nsAString& _retval)
00214 {
00215   _retval.Assign(((ColumnInfo*)mColumnInfo[aColumnIndex])->mName);
00216   return NS_OK;
00217 }
00218 
00219 NS_IMETHODIMP
00220 mozSqlResult::GetColumnIndex(const nsAString & aColumnName, PRInt32 *_retval)
00221 {
00222   *_retval = -1;
00223 
00224   for (PRInt32 i = 0; i < mColumnInfo.Count(); i++) {
00225     PRUnichar* name = ((ColumnInfo*)mColumnInfo[i])->mName;
00226     if (aColumnName.Equals(name)) {
00227       *_retval = i;
00228       break;
00229     }
00230   }
00231 
00232   return NS_OK;
00233 }
00234 
00235 NS_IMETHODIMP
00236 mozSqlResult::GetColumnType(PRInt32 aColumnIndex, PRInt32* _retval)
00237 {
00238   if (aColumnIndex < 0 || aColumnIndex >= mColumnInfo.Count())
00239     return NS_ERROR_INVALID_ARG;
00240 
00241   *_retval = ((ColumnInfo*)mColumnInfo[aColumnIndex])->mType;
00242 
00243   return NS_OK;
00244 }
00245 
00246 NS_IMETHODIMP
00247 mozSqlResult::GetColumnTypeAsString(PRInt32 aColumnIndex, nsAString& _retval)
00248 {
00249   if (aColumnIndex < 0 || aColumnIndex >= mColumnInfo.Count())
00250     return NS_ERROR_INVALID_ARG;
00251 
00252   PRInt32 type = ((ColumnInfo*)mColumnInfo[aColumnIndex])->mType;
00253   switch (type) {
00254     case mozISqlResult::TYPE_STRING:
00255       _retval.AssignLiteral("string");
00256       break;
00257     case mozISqlResult::TYPE_INT:
00258       _retval.AssignLiteral("int");
00259       break;
00260     case mozISqlResult::TYPE_FLOAT:
00261       _retval.AssignLiteral("float");
00262       break;
00263     case mozISqlResult::TYPE_DECIMAL:
00264       _retval.AssignLiteral("decimal");
00265       break;
00266     case mozISqlResult::TYPE_DATE:
00267       _retval.AssignLiteral("date");
00268       break;
00269     case mozISqlResult::TYPE_TIME:
00270       _retval.AssignLiteral("time");
00271       break;
00272     case mozISqlResult::TYPE_DATETIME:
00273       _retval.AssignLiteral("datetime");
00274       break;
00275     case mozISqlResult::TYPE_BOOL:
00276       _retval.AssignLiteral("bool");
00277       break;
00278   }
00279 
00280   return NS_OK;
00281 }
00282 
00283 NS_IMETHODIMP
00284 mozSqlResult::GetColumnDisplaySize(PRInt32 aColumnIndex, PRInt32* _retval)
00285 {
00286   if (aColumnIndex < 0 || aColumnIndex >= mColumnInfo.Count())
00287     return NS_ERROR_INVALID_ARG;
00288 
00289   ColumnInfo* columnInfo = ((ColumnInfo*)mColumnInfo[aColumnIndex]);
00290   PRInt32 mod = columnInfo->mMod - 4;
00291 
00292   switch (columnInfo->mType) {
00293     case mozISqlResult::TYPE_STRING:
00294       *_retval = mod;
00295       break;
00296     case mozISqlResult::TYPE_INT:
00297       *_retval = 11; // -2147483648 to +2147483647
00298       break;
00299     case mozISqlResult::TYPE_FLOAT:
00300       *_retval = 11;
00301       break;
00302     case mozISqlResult::TYPE_DECIMAL:
00303       *_retval = ((mod >> 16) & 0xffff) + 1 + (mod & 0xffff);
00304       break;
00305     case mozISqlResult::TYPE_DATE:
00306       *_retval = 14; // "01/01/4713 BC" - "31/12/32767 AD"
00307       break;
00308     case mozISqlResult::TYPE_TIME:
00309       *_retval = 8;  // 00:00:00-23:59:59
00310       break;
00311     case mozISqlResult::TYPE_DATETIME:
00312       *_retval = 22;
00313       break;
00314     case mozISqlResult::TYPE_BOOL:
00315       *_retval = 1;
00316       break;
00317     default:
00318       *_retval = columnInfo->mSize;
00319   }
00320 
00321   return NS_OK;
00322 }
00323 
00324 NS_IMETHODIMP
00325 mozSqlResult::Enumerate(mozISqlResultEnumerator** _retval)
00326 {
00327   mozISqlResultEnumerator* enumerator = new mozSqlResultEnumerator(this);
00328   if (! enumerator)
00329     return NS_ERROR_OUT_OF_MEMORY;
00330   NS_ADDREF(*_retval = enumerator);
00331   return NS_OK;
00332 }
00333 
00334 NS_IMETHODIMP
00335 mozSqlResult::Open(mozISqlInputStream** _retval)
00336 {
00337   mozSqlResultStream* stream = new mozSqlResultStream(this);
00338   if (! stream)
00339     return NS_ERROR_OUT_OF_MEMORY;
00340   NS_ADDREF(*_retval = stream);
00341   return NS_OK;
00342 }
00343 
00344 NS_IMETHODIMP
00345 mozSqlResult::Reload()
00346 {
00347   mozISqlResult* result = this;
00348   nsresult rv = mConnection->ExecuteQuery(mQuery, &result);
00349   if (NS_FAILED(rv))
00350     return rv;
00351   NS_RELEASE(result);
00352 
00353   return NS_OK;
00354 }
00355 
00356 
00357 NS_IMETHODIMP
00358 mozSqlResult::GetResourceAtIndex(PRInt32 aRowIndex, nsIRDFResource** _retval)
00359 {
00360   if (aRowIndex < 0 || aRowIndex >= mRows.Count())
00361     return NS_ERROR_INVALID_ARG;
00362 
00363   NS_ADDREF(*_retval = ((Row*)mRows[aRowIndex])->mSource);
00364   return NS_OK;
00365 }
00366 
00367 NS_IMETHODIMP
00368 mozSqlResult::GetIndexOfResource(nsIRDFResource *aResource, PRInt32* _retval)
00369 {
00370   *_retval = -1;
00371 
00372   for (PRInt32 i = 0; i < mRows.Count(); i++) {
00373     if (((Row*)mRows[i])->mSource == aResource) {
00374       *_retval = i;
00375       break;
00376     }
00377   }
00378 
00379   return NS_OK;
00380 }
00381 
00382 
00383 NS_IMETHODIMP
00384 mozSqlResult::GetURI(char **aURI)
00385 {
00386   *aURI = nsCRT::strdup("rdf:result");
00387   if (! *aURI)
00388     return NS_ERROR_OUT_OF_MEMORY;
00389   
00390   return NS_OK;
00391 }
00392 
00393 NS_IMETHODIMP
00394 mozSqlResult::GetSource(nsIRDFResource* aPoperty,
00395                         nsIRDFNode* aTarget,
00396                         PRBool aTruthValue,
00397                         nsIRDFResource** _retval)
00398 {
00399   return NS_ERROR_NOT_IMPLEMENTED;
00400 }
00401 
00402 NS_IMETHODIMP
00403 mozSqlResult::GetSources(nsIRDFResource* aProperty,
00404                          nsIRDFNode* aTarget,
00405                          PRBool aTruthValue,
00406                          nsISimpleEnumerator** _retval)
00407 {
00408   return NS_ERROR_NOT_IMPLEMENTED;
00409 }
00410 
00411 NS_IMETHODIMP
00412 mozSqlResult::GetTarget(nsIRDFResource* aSource,
00413                         nsIRDFResource* aProperty,
00414                         PRBool aTruthValue,
00415                         nsIRDFNode** _retval)
00416 {
00417   *_retval = nsnull;
00418 
00419   nsVoidKey key(aSource);
00420   Row* row = NS_STATIC_CAST(Row*, mSources.Get(&key));
00421   if (! row)
00422     return NS_RDF_NO_VALUE;
00423 
00424   PRInt32 columnIndex = -1;
00425   for (PRInt32 i = 0; i < mColumnInfo.Count(); i++) {
00426     nsIRDFResource* property = ((ColumnInfo*)mColumnInfo[i])->mProperty;
00427     if (property == aProperty) {
00428       columnIndex = i;
00429       break;
00430     }
00431   }
00432   if (columnIndex == -1)
00433     return NS_RDF_NO_VALUE;
00434 
00435   nsCOMPtr<nsIRDFNode> node;
00436 
00437   Cell* cell = row->mCells[columnIndex];
00438   if (cell->IsNull())
00439     if (mDisplayNullAsText)
00440       node = kNullLiteral;
00441     else
00442       node = kEmptyLiteral;
00443   else {
00444     PRInt32 type = cell->GetType();
00445     if (type == mozISqlResult::TYPE_STRING) {
00446       nsCOMPtr<nsIRDFLiteral> literal;
00447       gRDFService->GetLiteral(cell->mString, getter_AddRefs(literal));
00448       node = literal;
00449     }
00450     else if (type == mozISqlResult::TYPE_INT) {
00451       nsCOMPtr<nsIRDFInt> literal;
00452       gRDFService->GetIntLiteral(cell->mInt, getter_AddRefs(literal));
00453       node = literal;
00454     }
00455     else if (type == mozISqlResult::TYPE_FLOAT ||
00456              type == mozISqlResult::TYPE_DECIMAL) {
00457       nsCOMPtr<nsIRDFInt> literal;
00458       gRDFService->GetIntLiteral(cell->mInt, getter_AddRefs(literal));
00459       node = literal;
00460     }
00461     else if (type == mozISqlResult::TYPE_DATE ||
00462              type == mozISqlResult::TYPE_TIME ||
00463              type == mozISqlResult::TYPE_DATETIME) {
00464       nsCOMPtr<nsIRDFDate> literal;
00465       gRDFService->GetDateLiteral(cell->mDate, getter_AddRefs(literal));
00466       node = literal;
00467     }
00468     else if (type == mozISqlResult::TYPE_BOOL)
00469       node = cell->mBool ? kTrueLiteral : kFalseLiteral;
00470   }
00471 
00472   NS_IF_ADDREF(*_retval = node);
00473   
00474   return NS_OK;
00475 }
00476 
00477 NS_IMETHODIMP
00478 mozSqlResult::GetTargets(nsIRDFResource* aSource,
00479                          nsIRDFResource* aProperty,
00480                          PRBool aTruthValue,
00481                          nsISimpleEnumerator** _retval)
00482 {
00483   if (aSource == kSQL_ResultRoot &&
00484       aProperty == kNC_Child &&
00485       aTruthValue) {
00486     nsISimpleEnumerator* enumerator = new mozSqlResultEnumerator(this);
00487     if (! enumerator)
00488       return NS_ERROR_OUT_OF_MEMORY;
00489 
00490     NS_ADDREF(*_retval = enumerator);
00491 
00492     return NS_OK;
00493   }    
00494 
00495   return NS_RDF_NO_VALUE;
00496 }
00497 
00498 NS_IMETHODIMP
00499 mozSqlResult::Assert(nsIRDFResource* aSource,
00500                      nsIRDFResource* aProperty,
00501                      nsIRDFNode* aTarget,
00502                      PRBool aTruthValue)
00503 {
00504   return NS_ERROR_NOT_IMPLEMENTED;
00505 }
00506 
00507 
00508 NS_IMETHODIMP
00509 mozSqlResult::Unassert(nsIRDFResource* aSource,
00510                        nsIRDFResource* aProperty,
00511                        nsIRDFNode* aTarget)
00512 {
00513   return NS_ERROR_NOT_IMPLEMENTED;
00514 }
00515 
00516 NS_IMETHODIMP
00517 mozSqlResult::Change(nsIRDFResource* aSource,
00518                      nsIRDFResource* aProperty,
00519                      nsIRDFNode* aOldTarget,
00520                      nsIRDFNode* aNewTarget)
00521 {
00522   return NS_ERROR_NOT_IMPLEMENTED;
00523 }
00524 
00525 NS_IMETHODIMP
00526 mozSqlResult::Move(nsIRDFResource* aOldSource,
00527                    nsIRDFResource* aNewSource,
00528                    nsIRDFResource* aProperty,
00529                    nsIRDFNode* aTarget)
00530 {
00531   return NS_ERROR_NOT_IMPLEMENTED;
00532 }
00533 
00534 NS_IMETHODIMP
00535 mozSqlResult::HasAssertion(nsIRDFResource* aSource,
00536                            nsIRDFResource* aProperty,
00537                            nsIRDFNode *aTarget,
00538                            PRBool aTruthValue,
00539                            PRBool* _retval)
00540 {
00541   *_retval = PR_FALSE;
00542 
00543   if (aSource == kSQL_ResultRoot &&
00544       aProperty == kNC_Child &&
00545       aTruthValue) {
00546     nsVoidKey key(aTarget);
00547     Row* row = NS_STATIC_CAST(Row*, mSources.Get(&key));
00548     if (row)
00549       *_retval = PR_TRUE;
00550   }
00551 
00552   return NS_OK;
00553 }
00554 
00555 NS_IMETHODIMP
00556 mozSqlResult::AddObserver(nsIRDFObserver *aObserver)
00557 {
00558   mObservers.AppendObject(aObserver);
00559 
00560   return NS_OK;
00561 }
00562 
00563 NS_IMETHODIMP
00564 mozSqlResult::RemoveObserver(nsIRDFObserver *aObserver)
00565 {
00566   mObservers.RemoveObject(aObserver);
00567 
00568   return NS_OK;
00569 }
00570 
00571 NS_IMETHODIMP
00572 mozSqlResult::HasArcIn(nsIRDFNode* aNode,
00573                        nsIRDFResource* aArc,
00574                        PRBool* _retval)
00575 {
00576   return NS_ERROR_NOT_IMPLEMENTED;
00577 }                                                                                       
00578 
00579 NS_IMETHODIMP
00580 mozSqlResult::HasArcOut(nsIRDFResource* aSource,
00581                         nsIRDFResource*aArc,
00582                         PRBool* _retval)
00583 {                                                                                               
00584   return NS_ERROR_NOT_IMPLEMENTED;
00585 }
00586 
00587 NS_IMETHODIMP
00588 mozSqlResult::ArcLabelsIn(nsIRDFNode* aTarget,
00589                           nsISimpleEnumerator** _retval)
00590 {
00591   return NS_ERROR_NOT_IMPLEMENTED;
00592 }
00593 
00594 NS_IMETHODIMP
00595 mozSqlResult::ArcLabelsOut(nsIRDFResource* aSource,
00596                            nsISimpleEnumerator** _retval)
00597 {
00598   return NS_ERROR_NOT_IMPLEMENTED;
00599 }
00600 
00601 NS_IMETHODIMP
00602 mozSqlResult::GetAllResources(nsISimpleEnumerator** _retval)
00603 {
00604   nsISimpleEnumerator* enumerator = new mozSqlResultEnumerator(this);
00605   if (! enumerator)
00606     return NS_ERROR_OUT_OF_MEMORY;
00607 
00608   NS_ADDREF(*_retval = enumerator);
00609 
00610   return NS_OK;
00611 }
00612 
00613 
00614 NS_IMETHODIMP
00615 mozSqlResult::GetAllCmds(nsIRDFResource* aSource,
00616                          nsISimpleEnumerator** _retval)
00617 {
00618   return NS_ERROR_NOT_IMPLEMENTED;
00619 }
00620 
00621 NS_IMETHODIMP
00622 mozSqlResult::IsCommandEnabled(nsISupportsArray* aSources,
00623                                nsIRDFResource* aCommand,
00624                                nsISupportsArray* aArguments,
00625                                PRBool* _retval)
00626 {
00627   return NS_ERROR_NOT_IMPLEMENTED;
00628 }
00629 
00630 NS_IMETHODIMP
00631 mozSqlResult::DoCommand(nsISupportsArray* aSources,
00632                         nsIRDFResource* aCommand,
00633                         nsISupportsArray* aArguments)
00634 {
00635   return NS_ERROR_NOT_IMPLEMENTED;
00636 }
00637 
00638 NS_IMETHODIMP
00639 mozSqlResult::BeginUpdateBatch()
00640 {
00641   for (PRInt32 i = 0; i < mObservers.Count(); i++) {
00642     mObservers[i]->OnBeginUpdateBatch(this);
00643   }
00644   return NS_OK;
00645 }
00646 
00647 NS_IMETHODIMP
00648 mozSqlResult::EndUpdateBatch()
00649 {
00650   for (PRInt32 i = 0; i < mObservers.Count(); i++) {
00651     mObservers[i]->OnEndUpdateBatch(this);
00652   }
00653   return NS_OK;
00654 }
00655 
00656 
00657 NS_IMETHODIMP
00658 mozSqlResult::GetLoaded(PRBool* aResult)
00659 {
00660   *aResult = PR_TRUE;
00661   return NS_OK;
00662 }
00663 
00664 NS_IMETHODIMP
00665 mozSqlResult::Init(const char* aURI)
00666 {
00667   return NS_ERROR_NOT_IMPLEMENTED;
00668 }
00669 
00670 NS_IMETHODIMP
00671 mozSqlResult::Refresh(PRBool aBlocking)
00672 {
00673   if (aBlocking)
00674     return Reload();
00675   return NS_ERROR_NOT_IMPLEMENTED;
00676 }
00677 
00678 NS_IMETHODIMP
00679 mozSqlResult::Flush()
00680 {
00681   return NS_ERROR_NOT_IMPLEMENTED;
00682 }
00683 
00684 NS_IMETHODIMP
00685 mozSqlResult::FlushTo(const char *aURI)
00686 {
00687   return NS_ERROR_NOT_IMPLEMENTED;
00688 }
00689 
00690 
00691 /*
00692 NS_IMETHODIMP
00693 mozSqlResult::GetRowCount(PRInt32 *aRowCount)
00694 {
00695   *aRowCount = mRows.Count();
00696   return NS_OK;
00697 }
00698 */
00699 
00700 NS_IMETHODIMP
00701 mozSqlResult::GetSelection(nsITreeSelection * *aSelection)
00702 {
00703   NS_IF_ADDREF(*aSelection = mSelection);
00704   return NS_OK;
00705 }
00706 
00707 NS_IMETHODIMP
00708 mozSqlResult::SetSelection(nsITreeSelection * aSelection)
00709 {
00710   mSelection = aSelection;
00711   return NS_OK;
00712 }
00713 
00714 NS_IMETHODIMP
00715 mozSqlResult::GetRowProperties(PRInt32 index, nsISupportsArray *properties)
00716 {
00717   return NS_OK;
00718 }
00719 
00720 NS_IMETHODIMP
00721 mozSqlResult::GetCellProperties(PRInt32 row, nsITreeColumn* col, nsISupportsArray *properties)
00722 {
00723   return NS_OK;
00724 }
00725 
00726 NS_IMETHODIMP
00727 mozSqlResult::GetColumnProperties(nsITreeColumn* aCol, nsISupportsArray *properties)
00728 {
00729   return NS_OK;
00730 }
00731 
00732 NS_IMETHODIMP
00733 mozSqlResult::IsContainer(PRInt32 index, PRBool *_retval)
00734 {
00735   *_retval = PR_FALSE;
00736   return NS_OK;
00737 }
00738 
00739 NS_IMETHODIMP
00740 mozSqlResult::IsContainerOpen(PRInt32 index, PRBool *_retval)
00741 {
00742   *_retval = PR_FALSE;
00743   return NS_OK;
00744 }
00745 
00746 NS_IMETHODIMP
00747 mozSqlResult::IsContainerEmpty(PRInt32 index, PRBool *_retval)
00748 {
00749   *_retval = PR_FALSE;
00750   return NS_OK;
00751 }
00752 
00753 NS_IMETHODIMP
00754 mozSqlResult::IsSeparator(PRInt32 index, PRBool *_retval)
00755 {
00756   *_retval = PR_FALSE;
00757   return NS_OK;
00758 }
00759 
00760 NS_IMETHODIMP
00761 mozSqlResult::IsSorted(PRBool *_retval)
00762 {
00763   *_retval = PR_FALSE;
00764   return NS_OK;
00765 }
00766 
00767 NS_IMETHODIMP
00768 mozSqlResult::CanDrop(PRInt32 index, PRInt32 orientation, PRBool *_retval)
00769 {
00770   *_retval = PR_FALSE;
00771   return NS_OK;
00772 }
00773 
00774 NS_IMETHODIMP
00775 mozSqlResult::Drop(PRInt32 row, PRInt32 orientation)
00776 {
00777   return NS_OK;
00778 }
00779 
00780 NS_IMETHODIMP
00781 mozSqlResult::GetParentIndex(PRInt32 rowIndex, PRInt32 *_retval)
00782 {
00783   *_retval = -1;
00784   return NS_OK;
00785 }
00786 
00787 NS_IMETHODIMP
00788 mozSqlResult::HasNextSibling(PRInt32 rowIndex, PRInt32 afterIndex, PRBool *_retval)
00789 {
00790   *_retval = PR_FALSE;
00791   return NS_OK;
00792 }
00793 
00794 NS_IMETHODIMP
00795 mozSqlResult::GetLevel(PRInt32 index, PRInt32 *_retval)
00796 {
00797   *_retval = 0;
00798   return NS_OK;
00799 }
00800 
00801 NS_IMETHODIMP
00802 mozSqlResult::GetImageSrc(PRInt32 row, nsITreeColumn* col, nsAString & _retval)
00803 {
00804   _retval.Truncate();
00805   return NS_OK;
00806 }
00807 
00808 NS_IMETHODIMP
00809 mozSqlResult::GetProgressMode(PRInt32 row, nsITreeColumn* col, PRInt32 *_retval)
00810 {
00811   *_retval = 0;
00812   return NS_OK;
00813 }
00814 
00815 NS_IMETHODIMP
00816 mozSqlResult::GetCellValue(PRInt32 row, nsITreeColumn* col, nsAString & _retval)
00817 {
00818   PRInt32 columnIndex;
00819   col->GetIndex(&columnIndex);
00820 
00821   Cell* cell = ((Row*)mRows[row])->mCells[columnIndex];
00822   if (! cell->IsNull()) {
00823     PRInt32 type = cell->GetType();
00824     if (type == mozISqlResult::TYPE_BOOL) {
00825       if (cell->mBool)
00826         _retval.AssignLiteral("true");
00827       else
00828         _retval.AssignLiteral("false");
00829     }
00830   }
00831   return NS_OK;
00832 }
00833 
00834 NS_IMETHODIMP
00835 mozSqlResult::GetCellText(PRInt32 row, nsITreeColumn* col, nsAString & _retval)
00836 {
00837   PRInt32 columnIndex;
00838   col->GetIndex(&columnIndex);
00839 
00840   Cell* cell = ((Row*)mRows[row])->mCells[columnIndex];
00841   if (cell->IsNull()) {
00842     if (mDisplayNullAsText)
00843       _retval.AssignLiteral("null");
00844   }
00845   else {
00846     PRInt32 type = cell->GetType();
00847     if (type == mozISqlResult::TYPE_STRING)
00848       _retval.Assign(cell->mString);
00849     else if (type == mozISqlResult::TYPE_INT) {
00850       nsAutoString s;
00851       s.AppendInt(cell->mInt);
00852       _retval.Assign(s);
00853     }
00854     else if (type == mozISqlResult::TYPE_FLOAT ||
00855              type == mozISqlResult::TYPE_DECIMAL) {
00856       nsAutoString s;
00857       s.AppendFloat(cell->mFloat);
00858       _retval.Assign(s);
00859     }
00860     else if (type == mozISqlResult::TYPE_DATE ||
00861              type == mozISqlResult::TYPE_TIME ||
00862              type == mozISqlResult::TYPE_DATETIME) {
00863       nsAutoString value;
00864       mozSqlResult::gFormat->FormatPRTime(nsnull,
00865                                           type != mozISqlResult::TYPE_TIME ? kDateFormatShort : kDateFormatNone,
00866                                           type != mozISqlResult::TYPE_DATE ? kTimeFormatSeconds : kTimeFormatNone,
00867                                           PRTime(cell->mDate),
00868                                           value);
00869       _retval.Assign(value);
00870     }
00871     else if (type == mozISqlResult::TYPE_BOOL) {
00872       if (cell->mBool)
00873         _retval.AssignLiteral("true");
00874       else
00875         _retval.AssignLiteral("false");
00876     }
00877   }
00878   return NS_OK;
00879 }
00880 
00881 NS_IMETHODIMP
00882 mozSqlResult::SetTree(nsITreeBoxObject *tree)
00883 {
00884   mBoxObject = tree;
00885   return NS_OK;
00886 }
00887 
00888 NS_IMETHODIMP
00889 mozSqlResult::ToggleOpenState(PRInt32 index)
00890 {
00891   return NS_OK;
00892 }
00893 
00894 NS_IMETHODIMP
00895 mozSqlResult::CycleHeader(nsITreeColumn* aCol)
00896 {
00897   return NS_OK;
00898 }
00899 
00900 NS_IMETHODIMP
00901 mozSqlResult::SelectionChanged()
00902 {
00903   return NS_OK;
00904 }
00905 
00906 NS_IMETHODIMP
00907 mozSqlResult::CycleCell(PRInt32 row, nsITreeColumn* aCol)
00908 {
00909   return NS_OK;
00910 }
00911 
00912 NS_IMETHODIMP
00913 mozSqlResult::IsEditable(PRInt32 row, nsITreeColumn* col, PRBool *_retval)
00914 {
00915   return CanUpdate(_retval);
00916 }
00917 
00918 NS_IMETHODIMP
00919 mozSqlResult::SetCellValue(PRInt32 row, nsITreeColumn* col, const nsAString& value)
00920 {
00921   PRInt32 columnIndex;
00922   col->GetIndex(&columnIndex);
00923 
00924   Row* srcRow = (Row*)mRows[row];
00925   Row* buffer = Row::Create(mAllocator, nsnull, mColumnInfo, srcRow);
00926 
00927   Cell* cell = buffer->mCells[columnIndex];
00928 
00929   if (value.EqualsLiteral("true")) {
00930     cell->mBool = PR_TRUE;
00931   }
00932   else if (value.EqualsLiteral("false")) {
00933     cell->mBool = PR_FALSE;
00934   }
00935   
00936   PRInt32 count;
00937   nsresult rv = UpdateRow(row, buffer, &count);
00938   if (NS_FAILED(rv))
00939     return rv;
00940 
00941   if (mBoxObject)
00942     mBoxObject->InvalidateCell(row, col);
00943 
00944   return NS_OK;
00945 }
00946 
00947 NS_IMETHODIMP
00948 mozSqlResult::SetCellText(PRInt32 row, nsITreeColumn* col, const nsAString& value)
00949 {
00950   return NS_OK;
00951 }
00952 
00953 NS_IMETHODIMP
00954 mozSqlResult::PerformAction(const PRUnichar *action)
00955 {
00956   return NS_OK;
00957 }
00958 
00959 NS_IMETHODIMP
00960 mozSqlResult::PerformActionOnRow(const PRUnichar *action, PRInt32 row)
00961 {
00962   return NS_OK;
00963 }
00964 
00965 NS_IMETHODIMP
00966 mozSqlResult::PerformActionOnCell(const PRUnichar *action, PRInt32 row, nsITreeColumn* aCol)
00967 {
00968   return NS_OK;
00969 }
00970 
00971 
00972 void
00973 mozSqlResult::ClearColumnInfo()
00974 {
00975   for (PRInt32 i = 0; i < mColumnInfo.Count(); i++) {
00976     ColumnInfo* columnInfo = (ColumnInfo*)mColumnInfo[i];
00977     ColumnInfo::Destroy(mAllocator, columnInfo);
00978   }
00979   mColumnInfo.Clear();
00980 }
00981 
00982 void
00983 mozSqlResult::ClearRows()
00984 {
00985   for (PRInt32 i = 0; i < mRows.Count(); i++) {
00986     Row* row = (Row*)mRows[i];
00987     Row::Destroy(mAllocator, mColumnInfo.Count(), row);
00988   }
00989   mRows.Clear();
00990   mSources.Reset();
00991 }
00992 
00993 nsresult
00994 mozSqlResult::EnsureTableName()
00995 {
00996   if (!mTableName.IsEmpty())
00997     return NS_OK;
00998 
00999   nsAString::const_iterator start, end;
01000   mQuery.BeginReading(start);
01001   mQuery.EndReading(end);
01002 
01003   NS_NAMED_LITERAL_STRING(from, "from");
01004   nsAString::const_iterator iter = end;
01005   if (FindInReadable(from, start, iter, nsCaseInsensitiveStringComparator())) {
01006     while (iter != end && nsCRT::IsAsciiSpace(*iter))
01007       ++iter;
01008     start = iter;
01009     while (iter != end && !nsCRT::IsAsciiSpace(*iter))
01010       ++iter;
01011     mTableName.Assign(Substring(start, iter));
01012   }
01013   else
01014     return NS_ERROR_FAILURE;
01015 
01016   return NS_OK;
01017 }
01018 
01019 nsresult
01020 mozSqlResult::EnsurePrimaryKeys()
01021 {
01022   if (mPrimaryKeys)
01023     return NS_OK;
01024 
01025   nsAutoString schema;
01026   nsAutoString table;
01027   nsAString::const_iterator start, s;
01028   nsAString::const_iterator end, e;
01029   mTableName.BeginReading(start);
01030   mTableName.EndReading(end);
01031   s = start;
01032   e = end;
01033   if (FindInReadable(NS_LITERAL_STRING("."), s, e)) {
01034     schema.Assign(Substring(start, s));
01035     table.Assign(Substring(e, end));
01036   }
01037   else {
01038     table.Assign(mTableName);
01039   }
01040 
01041   nsCOMPtr<mozISqlResult> result;
01042   nsresult rv = mConnection->GetPrimaryKeys(schema, table, getter_AddRefs(result));
01043   if (NS_FAILED(rv))
01044     return rv;
01045 
01046   nsCOMPtr<mozISqlResultEnumerator> primaryKeys;
01047   rv = result->Enumerate(getter_AddRefs(primaryKeys));
01048   if (NS_FAILED(rv))
01049     return rv;
01050 
01051   rv = primaryKeys->First();
01052   if (NS_FAILED(rv))
01053     return rv;
01054 
01055   mPrimaryKeys = primaryKeys;
01056   return NS_OK;
01057 }
01058 
01059 void
01060 mozSqlResult::AppendValue(Cell* aCell, nsAutoString& aValues)
01061 {
01062   if (aCell->IsNull())
01063     aValues.AppendLiteral("NULL");
01064   else if (aCell->IsDefault())
01065     aValues.AppendLiteral("DEFAULT");
01066   else {
01067     PRInt32 type = aCell->GetType();
01068     if (type == mozISqlResult::TYPE_STRING) {
01069       aValues.Append(PRUnichar('\''));
01070       aValues.Append(aCell->mString);
01071       aValues.Append(PRUnichar('\''));
01072     }
01073     else if (type == mozISqlResult::TYPE_INT)
01074       aValues.AppendInt(aCell->mInt);
01075     else if (type == mozISqlResult::TYPE_FLOAT ||
01076              type == mozISqlResult::TYPE_DECIMAL)
01077       aValues.AppendFloat(aCell->mFloat);
01078     else if (type == mozISqlResult::TYPE_DATE ||
01079              type == mozISqlResult::TYPE_TIME ||
01080              type == mozISqlResult::TYPE_DATETIME) {
01081       aValues.Append(PRUnichar('\''));
01082       nsAutoString value;
01083       gFormat->FormatPRTime(nsnull,
01084                             type != mozISqlResult::TYPE_TIME ? kDateFormatLong : kDateFormatNone,
01085                             type != mozISqlResult::TYPE_DATE ? kTimeFormatSeconds : kTimeFormatNone,
01086                             PRTime(aCell->mDate),
01087                             value);
01088       aValues.Append(value);
01089       aValues.Append(PRUnichar('\''));
01090     }
01091     else if (type == mozISqlResult::TYPE_BOOL) {
01092       aValues.Append(PRUnichar('\''));
01093       aValues.AppendInt(aCell->mBool);
01094       aValues.Append(PRUnichar('\''));
01095     }
01096   }
01097 }
01098 
01099 nsresult
01100 mozSqlResult::AppendKeys(Row* aRow, nsAutoString& aKeys)
01101 {
01102   mPrimaryKeys->BeforeFirst();
01103 
01104   PRBool hasNext = PR_FALSE;
01105   do {
01106     if (hasNext)
01107       aKeys.AppendLiteral(" AND ");
01108 
01109     mPrimaryKeys->Next(&hasNext);
01110 
01111     nsAutoString value;
01112     mPrimaryKeys->GetString(2, value);
01113     aKeys.Append(value);
01114     aKeys.Append(PRUnichar('='));
01115 
01116     PRInt32 index;
01117     GetColumnIndex(value, &index);
01118     if (index == -1) {
01119       mErrorMessage.AssignLiteral("MOZSQL: The result doesn't contain all primary key fields");
01120       return NS_ERROR_FAILURE;
01121     }
01122 
01123     Cell* cell = aRow->mCells[index];
01124     AppendValue(cell, aKeys);
01125 
01126   } while(hasNext);
01127 
01128   return NS_OK;
01129 }
01130 
01131 nsresult
01132 mozSqlResult::GetValues(Row* aRow, mozISqlResult** aResult, PRBool aUseID)
01133 {
01134   nsAutoString query(mQuery);
01135   nsAString::const_iterator start;
01136   nsAString::const_iterator end;
01137   query.BeginReading(start);
01138   query.EndReading(end);
01139 
01140   NS_NAMED_LITERAL_STRING(where, "WHERE");
01141   nsAString::const_iterator s = start;
01142   nsAString::const_iterator e = end;
01143   if (FindInReadable(where, s, e, nsCaseInsensitiveStringComparator())) {
01144     nsAutoString keys(PRUnichar(' '));
01145 
01146     if (aUseID) {
01147       nsAutoString IDName;
01148       ((mozSqlConnection*)mConnection.get())->GetIDName(IDName);
01149       PRInt32 lastID;
01150       mConnection->GetLastID(&lastID);
01151       keys.Append(IDName);
01152       keys.Append(PRUnichar('='));
01153       keys.AppendInt(lastID);
01154     }
01155     else {
01156       nsresult rv = AppendKeys(aRow, keys);
01157       if (NS_FAILED(rv))
01158         return rv;
01159     }
01160 
01161     keys.AppendLiteral(" AND ");
01162     query.Insert(keys, Distance(start, e));
01163   }
01164   else {
01165     NS_NAMED_LITERAL_STRING(from, "FROM");
01166     s = start;
01167     e = end;
01168     if (FindInReadable(from, s, e, nsCaseInsensitiveStringComparator())) {
01169       while (e != end && nsCRT::IsAsciiSpace(*e))
01170         ++e;
01171       while (e != end && !nsCRT::IsAsciiSpace(*e))
01172         ++e;
01173       nsAutoString keys(NS_LITERAL_STRING(" WHERE "));
01174 
01175       if (aUseID) {
01176         nsAutoString IDName;
01177         ((mozSqlConnection*)mConnection.get())->GetIDName(IDName);
01178         PRInt32 lastID;
01179         mConnection->GetLastID(&lastID);
01180         keys.Append(IDName);
01181         keys.Append(PRUnichar('='));
01182         keys.AppendInt(lastID);
01183       }
01184       else {
01185         nsresult rv = AppendKeys(aRow, keys);
01186         if (NS_FAILED(rv))
01187           return rv;
01188       }
01189 
01190       query.Insert(keys, Distance(start, e));
01191     }
01192   }
01193 
01194 
01195   nsCOMPtr<mozISqlResult> result;
01196   nsresult rv = mConnection->ExecuteQuery(query, getter_AddRefs(result));
01197 
01198   if (NS_FAILED(rv)) {
01199     mConnection->GetErrorMessage(mErrorMessage);
01200     return rv;
01201   }
01202 
01203   NS_ADDREF(*aResult = result);
01204 
01205   return NS_OK;
01206 }
01207 
01208 nsresult
01209 mozSqlResult::CopyValues(mozISqlResult* aResult, Row* aRow)
01210 {
01211   nsCOMPtr<mozISqlResultEnumerator> enumerator;
01212   nsresult rv = aResult->Enumerate(getter_AddRefs(enumerator));
01213   if (NS_FAILED(rv))
01214     return rv;
01215 
01216   rv = enumerator->First();
01217   if (NS_FAILED(rv))
01218     return rv;
01219 
01220   PRInt32 columnCount;
01221   aResult->GetColumnCount(&columnCount);
01222   for (PRInt32 i = 0; i < columnCount; i++) {
01223     Cell* cell = aRow->mCells[i];
01224     PRBool isNull;
01225     enumerator->IsNull(i, &isNull);
01226     if (isNull)
01227       cell->SetNull(PR_TRUE);
01228     else {
01229       cell->SetNull(PR_FALSE);
01230       PRInt32 type;
01231       aResult->GetColumnType(i, &type);
01232       if (type == mozISqlResult::TYPE_STRING) {
01233         nsAutoString value;
01234         enumerator->GetString(i, value);
01235         cell->SetString(ToNewUnicode(value));
01236       }
01237       else if (type == mozISqlResult::TYPE_INT)
01238         enumerator->GetInt(i, &cell->mInt);
01239       else if (type == mozISqlResult::TYPE_FLOAT)
01240         enumerator->GetFloat(i, &cell->mFloat);
01241       else if (type == mozISqlResult::TYPE_DECIMAL)
01242         enumerator->GetDecimal(i, &cell->mFloat);
01243       else if (type == mozISqlResult::TYPE_DATE)
01244         enumerator->GetDate(i, &cell->mDate);
01245       else if (type == mozISqlResult::TYPE_TIME)
01246         enumerator->GetDate(i, &cell->mDate);
01247       else if (type == mozISqlResult::TYPE_DATETIME)
01248         enumerator->GetDate(i, &cell->mDate);
01249       else if (type == mozISqlResult::TYPE_BOOL)
01250         enumerator->GetBool(i, &cell->mBool);
01251     }
01252   }
01253 
01254   return NS_OK;
01255 }
01256 
01257 nsresult
01258 mozSqlResult::InsertRow(Row* aSrcRow, PRInt32* _retval)
01259 {
01260   *_retval = -1;
01261 
01262   nsresult rv = EnsureTableName();
01263   if (NS_FAILED(rv))
01264     return rv;
01265 
01266   rv = EnsurePrimaryKeys();
01267   if (NS_FAILED(rv))
01268     return rv;
01269 
01270   nsAutoString names;
01271   nsAutoString values;
01272 
01273   names.Append(PRUnichar('('));
01274   values.Append(PRUnichar('('));
01275   PRInt32 i;
01276   for (i = 0; i < mColumnInfo.Count(); i++) {
01277     if (i) {
01278       names.AppendLiteral(", ");
01279       values.AppendLiteral(", ");
01280     }
01281     names.Append(((ColumnInfo*)mColumnInfo[i])->mName);
01282 
01283     Cell* cell = aSrcRow->mCells[i];
01284     AppendValue(cell, values);
01285   }
01286   names.Append(PRUnichar(')'));
01287   values.Append(PRUnichar(')'));
01288 
01289   PRInt32 affectedRows;
01290   rv = mConnection->ExecuteUpdate(NS_LITERAL_STRING("INSERT INTO ") +
01291     mTableName + names + NS_LITERAL_STRING(" VALUES") + values, &affectedRows);
01292 
01293   if (NS_FAILED(rv)) {
01294     mConnection->GetErrorMessage(mErrorMessage);
01295     return rv;
01296   }
01297 
01298   nsAutoString IDName;
01299   ((mozSqlConnection*)mConnection.get())->GetIDName(IDName);
01300 
01301   // assume that if the IDName is empty that we don't need to re-get the last row
01302   if (!IDName.IsEmpty()){
01303     nsCOMPtr<mozISqlResult> result;
01304     rv = GetValues(aSrcRow, getter_AddRefs(result), PR_TRUE);
01305     if (NS_FAILED(rv))
01306       return rv;
01307 
01308     PRInt32 rowCount;
01309     result->GetRowCount(&rowCount);
01310     if (rowCount == 0) {
01311       *_retval = 0;
01312       return NS_OK;
01313     }
01314 
01315     rv = CopyValues(result, aSrcRow);
01316     if (NS_FAILED(rv))
01317       return rv;
01318   }
01319 
01320   nsCOMPtr<nsIRDFResource> resource;
01321   gRDFService->GetAnonymousResource(getter_AddRefs(resource));
01322 
01323   Row* row = Row::Create(mAllocator, resource, mColumnInfo, aSrcRow);
01324   mRows.AppendElement(row);
01325   nsVoidKey key(resource);
01326   mSources.Put(&key, row);
01327 
01328   for (i = 0; i < mObservers.Count(); i++)
01329     mObservers[i]->OnAssert(this, kSQL_ResultRoot, kNC_Child, resource);
01330 
01331   if (mBoxObject)
01332     mBoxObject->RowCountChanged(mRows.Count() - 1, 1);
01333 
01334   *_retval = 1;
01335   return NS_OK;
01336 }
01337 
01338 nsresult
01339 mozSqlResult::UpdateRow(PRInt32 aRowIndex, Row* aSrcRow, PRInt32* _retval)
01340 {
01341   *_retval = -1;
01342 
01343   nsresult rv = EnsureTableName();
01344   if (NS_FAILED(rv))
01345     return rv;
01346 
01347   rv = EnsurePrimaryKeys();
01348   if (NS_FAILED(rv))
01349     return rv;
01350 
01351   nsAutoString values;
01352   PRInt32 i;
01353   for (i = 0; i < mColumnInfo.Count(); i++) {
01354     if (i)
01355       values.AppendLiteral(", ");
01356     values.Append(((ColumnInfo*)mColumnInfo[i])->mName);
01357     values.Append(PRUnichar('='));
01358 
01359     Cell* cell = aSrcRow->mCells[i];
01360     AppendValue(cell, values);
01361   }
01362 
01363   Row* row = (Row*)mRows[aRowIndex];
01364 
01365   nsAutoString keys;
01366   rv = AppendKeys(row, keys);
01367   if (NS_FAILED(rv))
01368     return rv;
01369 
01370   PRInt32 affectedRows;
01371   rv = mConnection->ExecuteUpdate(NS_LITERAL_STRING("UPDATE ") + mTableName +
01372     NS_LITERAL_STRING(" SET ") + values + NS_LITERAL_STRING(" WHERE ") + keys,
01373     &affectedRows);
01374 
01375   if (NS_FAILED(rv)) {
01376     mConnection->GetErrorMessage(mErrorMessage);
01377     return rv;
01378   }
01379 
01380   nsCOMPtr<mozISqlResult> result;
01381   rv = GetValues(aSrcRow, getter_AddRefs(result), PR_FALSE);
01382   if (NS_FAILED(rv))
01383     return rv;
01384 
01385   PRInt32 rowCount;
01386   result->GetRowCount(&rowCount);
01387   if (rowCount == 0) {
01388     mRows.RemoveElementAt(aRowIndex);
01389     nsVoidKey key(row->mSource);
01390     mSources.Remove(&key);
01391 
01392     for (PRInt32 i = 0; i < mObservers.Count(); i++)
01393       mObservers[i]->OnUnassert(this, kSQL_ResultRoot, kNC_Child, row->mSource);
01394 
01395     if (mBoxObject)
01396       mBoxObject->RowCountChanged(aRowIndex, -1);
01397 
01398     Row::Destroy(mAllocator, mColumnInfo.Count(), row);
01399 
01400     *_retval = 0;
01401     return NS_OK;
01402   }
01403 
01404   rv = CopyValues(result, row);
01405   if (NS_FAILED(rv))
01406     return rv;
01407 
01408   for (i = 0; i < mColumnInfo.Count(); i++) {
01409     nsCOMPtr<nsIRDFNode> oldNode;
01410     nsCOMPtr<nsIRDFNode> newNode;
01411 
01412     Cell* cell = row->mCells[i];
01413     if (cell->IsNull())
01414       if (mDisplayNullAsText)
01415         newNode = kNullLiteral;
01416       else
01417         newNode = kEmptyLiteral;
01418     else {
01419       PRInt32 type = cell->GetType();
01420       if (type == mozISqlResult::TYPE_STRING) {
01421         nsCOMPtr<nsIRDFLiteral> literal;
01422         PRUnichar* value = cell->mString;
01423         gRDFService->GetLiteral(value, getter_AddRefs(literal));
01424         newNode = literal;
01425       }
01426       else if (type == mozISqlResult::TYPE_INT) {
01427         nsCOMPtr<nsIRDFInt> literal;
01428         PRInt32 value = cell->mInt;
01429         gRDFService->GetIntLiteral(value, getter_AddRefs(literal));
01430         newNode = literal;
01431       }
01432       else if (type == mozISqlResult::TYPE_FLOAT ||
01433                type == mozISqlResult::TYPE_DECIMAL) {
01434         nsCOMPtr<nsIRDFInt> literal;
01435         PRInt32 value = cell->mInt;
01436         gRDFService->GetIntLiteral(value, getter_AddRefs(literal));
01437         newNode = literal;
01438       }
01439       else if (type == mozISqlResult::TYPE_DATE ||
01440                type == mozISqlResult::TYPE_TIME ||
01441                type == mozISqlResult::TYPE_DATETIME) {
01442         nsCOMPtr<nsIRDFDate> literal;
01443         PRInt64 value = cell->mDate;
01444         gRDFService->GetDateLiteral(value, getter_AddRefs(literal));
01445         newNode = literal;
01446       }
01447       else if (type == mozISqlResult::TYPE_BOOL)
01448         newNode = cell->mBool ? kTrueLiteral : kFalseLiteral;
01449     }
01450 
01451     for (PRInt32 j = 0; j < mObservers.Count(); j++) {
01452       nsIRDFResource* source = row->mSource;
01453       nsIRDFResource* property = ((ColumnInfo*)mColumnInfo[i])->mProperty;
01454       mObservers[j]->OnChange(this, source, property, oldNode, newNode);
01455     }
01456   }
01457 
01458   if (mBoxObject)
01459     mBoxObject->InvalidateRow(aRowIndex);
01460 
01461   *_retval = 1;
01462   return NS_OK;
01463 }
01464 
01465 nsresult
01466 mozSqlResult::DeleteRow(PRInt32 aRowIndex, PRInt32* _retval)
01467 {
01468   *_retval = -1;
01469 
01470   nsresult rv = EnsureTableName();
01471   if (NS_FAILED(rv))
01472     return rv;
01473 
01474   rv = EnsurePrimaryKeys();
01475   if (NS_FAILED(rv))
01476     return rv;
01477 
01478   Row* row = (Row*)mRows[aRowIndex];
01479 
01480   nsAutoString keys;
01481   rv = AppendKeys(row, keys);
01482   if (NS_FAILED(rv))
01483     return rv;
01484 
01485   PRInt32 affectedRows;
01486   rv = mConnection->ExecuteUpdate(NS_LITERAL_STRING("DELETE FROM ") +
01487     mTableName + NS_LITERAL_STRING(" WHERE ") + keys, &affectedRows);
01488 
01489   if (NS_FAILED(rv)) {
01490     mConnection->GetErrorMessage(mErrorMessage);
01491     return rv;
01492   }
01493 
01494   mRows.RemoveElementAt(aRowIndex);
01495   nsVoidKey key(row->mSource);
01496   mSources.Remove(&key);
01497 
01498   for (PRInt32 i = 0; i < mObservers.Count(); i++)
01499     mObservers[i]->OnUnassert(this, kSQL_ResultRoot, kNC_Child, row->mSource);
01500 
01501   if (mBoxObject)
01502     mBoxObject->RowCountChanged(aRowIndex, -1);
01503 
01504   Row::Destroy(mAllocator, mColumnInfo.Count(), row);
01505 
01506   *_retval = 1;
01507   return NS_OK;
01508 }
01509 
01510 nsresult
01511 mozSqlResult::GetCondition(Row* aRow, nsAString& aCurrentCondition)
01512 {
01513   nsresult rv = EnsureTableName();
01514   if (NS_FAILED(rv))
01515     return rv;
01516 
01517   rv = EnsurePrimaryKeys();
01518   if (NS_FAILED(rv))
01519     return rv;
01520 
01521   nsAutoString keys;
01522   rv = AppendKeys(aRow, keys);
01523   if (NS_FAILED(rv))
01524     return rv;
01525 
01526   aCurrentCondition = keys;
01527 
01528   return NS_OK;
01529 }
01530 
01531 
01532 mozSqlResultEnumerator::mozSqlResultEnumerator(mozSqlResult* aResult)
01533   : mResult(aResult),
01534     mCurrentIndex(-1),
01535     mCurrentRow(nsnull)
01536 {
01537   NS_ADDREF(mResult);
01538 
01539   mBuffer = Row::Create(mResult->mAllocator, nsnull, mResult->mColumnInfo);
01540 }
01541 
01542 mozSqlResultEnumerator::~mozSqlResultEnumerator()
01543 {
01544   Row::Destroy(mResult->mAllocator, mResult->mColumnInfo.Count(), mBuffer);
01545 
01546   NS_RELEASE(mResult);
01547 }
01548 
01549 
01550 NS_IMPL_ISUPPORTS2(mozSqlResultEnumerator,
01551                    mozISqlResultEnumerator,
01552                    nsISimpleEnumerator)
01553 
01554 NS_IMETHODIMP
01555 mozSqlResultEnumerator::GetErrorMessage(nsAString& aErrorMessage)
01556 {
01557   aErrorMessage = mResult->mErrorMessage;
01558   return NS_OK;
01559 }
01560 
01561 NS_IMETHODIMP
01562 mozSqlResultEnumerator::Next(PRBool* _retval)
01563 {
01564   if (mCurrentIndex + 1 > mResult->mRows.Count() - 1)
01565     return NS_ERROR_FAILURE;
01566 
01567   mCurrentIndex++;
01568   mCurrentRow = (Row*)mResult->mRows[mCurrentIndex];
01569 
01570   *_retval = mCurrentIndex < mResult->mRows.Count() - 1;
01571   return NS_OK;
01572 }
01573 
01574 NS_IMETHODIMP
01575 mozSqlResultEnumerator::Previous(PRBool* _retval)
01576 {
01577   if (mCurrentIndex - 1 < 0)
01578     return NS_ERROR_FAILURE;
01579 
01580   mCurrentIndex--;
01581   mCurrentRow = (Row*)mResult->mRows[mCurrentIndex];
01582 
01583   *_retval = mCurrentIndex > 0;
01584   return NS_OK;
01585 }
01586 
01587 NS_IMETHODIMP
01588 mozSqlResultEnumerator::BeforeFirst()
01589 {
01590   mCurrentIndex = -1;
01591   mCurrentRow = nsnull;
01592 
01593   return NS_OK;
01594 }
01595 
01596 NS_IMETHODIMP
01597 mozSqlResultEnumerator::First()
01598 {
01599   if (mResult->mRows.Count() == 0)
01600     return NS_ERROR_FAILURE;
01601 
01602   mCurrentIndex = 0;
01603   mCurrentRow = (Row*)mResult->mRows[mCurrentIndex];
01604 
01605   return NS_OK;
01606 }
01607 
01608 NS_IMETHODIMP
01609 mozSqlResultEnumerator::Last()
01610 {
01611   if (mResult->mRows.Count() == 0)
01612     return NS_ERROR_FAILURE;
01613 
01614   mCurrentIndex = mResult->mRows.Count() - 1;
01615   mCurrentRow = (Row*)mResult->mRows[mCurrentIndex];
01616 
01617   return NS_OK;
01618 }
01619 
01620 NS_IMETHODIMP
01621 mozSqlResultEnumerator::Relative(PRInt32 aRows)
01622 {
01623   if (mResult->mRows.Count() == 0)
01624     return NS_ERROR_FAILURE;
01625 
01626   PRInt32 newIndex = mCurrentIndex + aRows;
01627   if (newIndex < 0 || newIndex > mResult->mRows.Count() - 1)
01628     return NS_ERROR_FAILURE;
01629 
01630   mCurrentIndex = newIndex;
01631   mCurrentRow = (Row*)mResult->mRows[mCurrentIndex];
01632 
01633   return NS_OK;
01634 }
01635 
01636 NS_IMETHODIMP
01637 mozSqlResultEnumerator::Absolute(PRInt32 aRowIndex)
01638 {
01639   if (mResult->mRows.Count() == 0)
01640     return NS_ERROR_FAILURE;
01641 
01642   if (aRowIndex < 0 || aRowIndex > mResult->mRows.Count() - 1)
01643     return NS_ERROR_FAILURE;
01644 
01645   mCurrentIndex = aRowIndex;
01646   mCurrentRow = (Row*)mResult->mRows[mCurrentIndex];
01647 
01648   return NS_OK;
01649 }
01650 
01651 NS_IMETHODIMP
01652 mozSqlResultEnumerator::IsNull(PRInt32 aColumnIndex, PRBool* _retval)
01653 {
01654   if (! mCurrentRow)
01655     return NS_ERROR_FAILURE;
01656 
01657   Cell* cell = mCurrentRow->mCells[aColumnIndex];
01658   *_retval = cell->IsNull();
01659 
01660   return NS_OK;
01661 }
01662 
01663 NS_IMETHODIMP
01664 mozSqlResultEnumerator::GetVariant(PRInt32 aColumnIndex, nsIVariant** _retval)
01665 {
01666   if (! mCurrentRow)
01667     return NS_ERROR_FAILURE;
01668 
01669   nsresult rv;
01670   nsCOMPtr<nsIWritableVariant> variant = do_CreateInstance(NS_VARIANT_CONTRACTID, &rv);
01671   if (NS_FAILED(rv)) return rv;
01672 
01673   Cell* cell = mCurrentRow->mCells[aColumnIndex];
01674   if (! cell->IsNull()) {
01675     PRInt32 type = cell->GetType();
01676     if (type == mozISqlResult::TYPE_STRING)
01677       variant->SetAsWString(cell->mString);
01678     else if (type == mozISqlResult::TYPE_INT)
01679       variant->SetAsInt32(cell->mInt);
01680     else if (type == mozISqlResult::TYPE_FLOAT ||
01681              type == mozISqlResult::TYPE_DECIMAL)
01682       variant->SetAsFloat(cell->mFloat);
01683     else if (type == mozISqlResult::TYPE_DATE ||
01684              type == mozISqlResult::TYPE_TIME ||
01685              type == mozISqlResult::TYPE_DATETIME) {
01686       nsAutoString value;
01687       mozSqlResult::gFormat->FormatPRTime(nsnull,
01688                                           type != mozISqlResult::TYPE_TIME ? kDateFormatShort : kDateFormatNone,
01689                                           type != mozISqlResult::TYPE_DATE ? kTimeFormatSeconds : kTimeFormatNone,
01690                                           PRTime(cell->mDate),
01691                                           value);
01692       variant->SetAsAString(value);
01693     }
01694     else if (type == mozISqlResult::TYPE_BOOL)
01695       variant->SetAsBool(cell->mBool);
01696   }
01697 
01698   NS_ADDREF(*_retval = variant);
01699 
01700   return NS_OK;
01701 }
01702 
01703 NS_IMETHODIMP
01704 mozSqlResultEnumerator::GetString(PRInt32 aColumnIndex, nsAString& _retval)
01705 {
01706   if (! mCurrentRow)
01707     return NS_ERROR_FAILURE;
01708 
01709   Cell* cell = mCurrentRow->mCells[aColumnIndex];
01710 
01711   if (cell->GetType() != mozISqlResult::TYPE_STRING)
01712     return NS_ERROR_FAILURE;
01713 
01714   if (! cell->IsNull())
01715     _retval.Assign(cell->mString);
01716 
01717   return NS_OK;
01718 }
01719 
01720 NS_IMETHODIMP
01721 mozSqlResultEnumerator::GetInt(PRInt32 aColumnIndex, PRInt32* _retval)
01722 {
01723   if (aColumnIndex < 0 || aColumnIndex >= mResult->mColumnInfo.Count())
01724     return NS_ERROR_INVALID_ARG;
01725 
01726   if (! mCurrentRow)
01727     return NS_ERROR_FAILURE;
01728 
01729   Cell* cell = mCurrentRow->mCells[aColumnIndex];
01730 
01731   if (cell->GetType() != mozISqlResult::TYPE_INT)
01732     return NS_ERROR_FAILURE;
01733 
01734   *_retval = cell->IsNull() ? 0 : cell->mInt;
01735 
01736   return NS_OK;
01737 }
01738 
01739 NS_IMETHODIMP
01740 mozSqlResultEnumerator::GetFloat(PRInt32 aColumnIndex, float* _retval)
01741 {
01742   if (aColumnIndex < 0 || aColumnIndex >= mResult->mColumnInfo.Count())
01743     return NS_ERROR_INVALID_ARG;
01744 
01745   if (! mCurrentRow)
01746     return NS_ERROR_FAILURE;
01747 
01748   Cell* cell = mCurrentRow->mCells[aColumnIndex];
01749 
01750   if (cell->GetType() != mozISqlResult::TYPE_FLOAT)
01751     return NS_ERROR_FAILURE;
01752 
01753   *_retval = cell->IsNull() ? 0 : cell->mFloat;
01754 
01755   return NS_OK;
01756 }
01757 
01758 NS_IMETHODIMP
01759 mozSqlResultEnumerator::GetDecimal(PRInt32 aColumnIndex, float* _retval)
01760 {
01761   if (aColumnIndex < 0 || aColumnIndex >= mResult->mColumnInfo.Count())
01762     return NS_ERROR_INVALID_ARG;
01763 
01764   if (! mCurrentRow)
01765     return NS_ERROR_FAILURE;
01766 
01767   Cell* cell = mCurrentRow->mCells[aColumnIndex];
01768 
01769   if (cell->GetType() != mozISqlResult::TYPE_DECIMAL)
01770     return NS_ERROR_FAILURE;
01771 
01772   *_retval = cell->IsNull() ? 0 : cell->mFloat;
01773 
01774   return NS_OK;
01775 }
01776 
01777 NS_IMETHODIMP
01778 mozSqlResultEnumerator::GetDate(PRInt32 aColumnIndex, PRInt64* _retval)
01779 {
01780   if (aColumnIndex < 0 || aColumnIndex >= mResult->mColumnInfo.Count())
01781     return NS_ERROR_INVALID_ARG;
01782 
01783   if (! mCurrentRow)
01784     return NS_ERROR_FAILURE;
01785 
01786   Cell* cell = mCurrentRow->mCells[aColumnIndex];
01787 
01788   if (cell->GetType() != mozISqlResult::TYPE_DATE)
01789     return NS_ERROR_FAILURE;
01790 
01791   *_retval = cell->IsNull() ? 0 : cell->mDate;
01792 
01793   return NS_OK;
01794 }
01795 
01796 NS_IMETHODIMP
01797 mozSqlResultEnumerator::GetBool(PRInt32 aColumnIndex, PRBool* _retval)
01798 {
01799   if (aColumnIndex < 0 || aColumnIndex >= mResult->mColumnInfo.Count())
01800     return NS_ERROR_INVALID_ARG;
01801 
01802   if (! mCurrentRow)
01803     return NS_ERROR_FAILURE;
01804 
01805   Cell* cell = mCurrentRow->mCells[aColumnIndex];
01806 
01807   if (cell->GetType() != mozISqlResult::TYPE_BOOL)
01808     return NS_ERROR_FAILURE;
01809 
01810   *_retval = cell->IsNull() ? 0 : cell->mBool;
01811 
01812   return NS_OK;
01813 }
01814 
01815 NS_IMETHODIMP
01816 mozSqlResultEnumerator::SetNull(PRInt32 aColumnIndex)
01817 {
01818   if (aColumnIndex < 0 || aColumnIndex >= mResult->mColumnInfo.Count())
01819     return NS_ERROR_INVALID_ARG;
01820 
01821   if (! mBuffer)
01822     return NS_ERROR_FAILURE;
01823 
01824   Cell* cell = mBuffer->mCells[aColumnIndex];
01825   cell->SetNull(PR_TRUE);
01826 
01827   return NS_OK;
01828 }
01829 
01830 NS_IMETHODIMP
01831 mozSqlResultEnumerator::SetDefault(PRInt32 aColumnIndex)
01832 {
01833   if (aColumnIndex < 0 || aColumnIndex >= mResult->mColumnInfo.Count())
01834     return NS_ERROR_INVALID_ARG;
01835 
01836   if (! mBuffer)
01837     return NS_ERROR_FAILURE;
01838 
01839   Cell* cell = mBuffer->mCells[aColumnIndex];
01840   cell->SetDefault(PR_TRUE);
01841 
01842   return NS_OK;
01843 }
01844 
01845 
01846 NS_IMETHODIMP
01847 mozSqlResultEnumerator::Copy(PRInt32 aColumnIndex)
01848 {
01849   if (aColumnIndex < 0 || aColumnIndex >= mResult->mColumnInfo.Count())
01850     return NS_ERROR_INVALID_ARG;
01851 
01852   if (! mCurrentRow)
01853     return NS_ERROR_FAILURE;
01854   if (! mBuffer)
01855     return NS_ERROR_FAILURE;
01856 
01857   Cell* currentCell = mCurrentRow->mCells[aColumnIndex];
01858   Cell* bufferCell = mBuffer->mCells[aColumnIndex];
01859   Cell::Copy(currentCell, bufferCell);
01860 
01861   return NS_OK;
01862 }
01863 
01864 NS_IMETHODIMP
01865 mozSqlResultEnumerator::SetVariant(PRInt32 aColumnIndex, nsIVariant* aValue)
01866 {
01867   if (aColumnIndex < 0 || aColumnIndex >= mResult->mColumnInfo.Count())
01868     return NS_ERROR_INVALID_ARG;
01869 
01870   if (! mBuffer)
01871     return NS_ERROR_FAILURE;
01872 
01873   Cell* cell = mBuffer->mCells[aColumnIndex];
01874   cell->SetNull(PR_FALSE);
01875   PRInt32 type = cell->GetType();
01876   if (type == mozISqlResult::TYPE_STRING) {
01877     PRUnichar* value;
01878     aValue->GetAsWString(&value);
01879     cell->SetString(value);
01880   }
01881   else if (type == mozISqlResult::TYPE_INT) {
01882     PRInt32 value;
01883     aValue->GetAsInt32(&value);
01884     cell->mInt = value;
01885   }
01886   else if (type == mozISqlResult::TYPE_FLOAT ||
01887            type == mozISqlResult::TYPE_DECIMAL) {
01888     float value;
01889     aValue->GetAsFloat(&value);
01890     cell->mFloat = value;
01891   }
01892   else if (type == mozISqlResult::TYPE_DATE ||
01893            type == mozISqlResult::TYPE_TIME ||
01894            type == mozISqlResult::TYPE_DATETIME) {
01895     nsCAutoString value;
01896     aValue->GetAsACString(value);
01897     PR_ParseTimeString(value.get(), PR_FALSE, &cell->mDate);
01898   }
01899   else if (type == mozISqlResult::TYPE_BOOL) {
01900     PRBool value;
01901     aValue->GetAsBool(&value);
01902     cell->mBool = value;
01903   }
01904 
01905   return NS_OK;
01906 }
01907 
01908 NS_IMETHODIMP
01909 mozSqlResultEnumerator::SetString(PRInt32 aColumnIndex, const nsAString& aValue)
01910 {
01911   if (aColumnIndex < 0 || aColumnIndex >= mResult->mColumnInfo.Count())
01912     return NS_ERROR_INVALID_ARG;
01913 
01914   if (! mBuffer)
01915     return NS_ERROR_FAILURE;
01916 
01917   Cell* cell = mBuffer->mCells[aColumnIndex];
01918 
01919   if (cell->GetType() != mozISqlResult::TYPE_STRING)
01920     return NS_ERROR_FAILURE;
01921 
01922   cell->SetNull(PR_FALSE);
01923   cell->SetString(ToNewUnicode(aValue));
01924 
01925   return NS_OK;
01926 }
01927 
01928 NS_IMETHODIMP
01929 mozSqlResultEnumerator::SetInt(PRInt32 aColumnIndex, PRInt32 aValue)
01930 {
01931   if (aColumnIndex < 0 || aColumnIndex >= mResult->mColumnInfo.Count())
01932     return NS_ERROR_INVALID_ARG;
01933 
01934   if (! mBuffer)
01935     return NS_ERROR_FAILURE;
01936 
01937   Cell* cell = mBuffer->mCells[aColumnIndex];
01938 
01939   if (cell->GetType() != mozISqlResult::TYPE_INT)
01940     return NS_ERROR_FAILURE;
01941 
01942   cell->SetNull(PR_FALSE);
01943   cell->mInt = aValue;
01944 
01945   return NS_OK;
01946 }
01947 
01948 NS_IMETHODIMP
01949 mozSqlResultEnumerator::SetFloat(PRInt32 aColumnIndex, float aValue)
01950 {
01951   if (aColumnIndex < 0 || aColumnIndex >= mResult->mColumnInfo.Count())
01952     return NS_ERROR_INVALID_ARG;
01953 
01954   if (! mBuffer)
01955     return NS_ERROR_FAILURE;
01956 
01957   Cell* cell = mBuffer->mCells[aColumnIndex];
01958 
01959   if (cell->GetType() != mozISqlResult::TYPE_FLOAT)
01960     return NS_ERROR_FAILURE;
01961 
01962   cell->SetNull(PR_FALSE);
01963   cell->mFloat = aValue;
01964 
01965   return NS_OK;
01966 }
01967 
01968 NS_IMETHODIMP
01969 mozSqlResultEnumerator::SetDecimal(PRInt32 aColumnIndex, float aValue)
01970 {
01971   if (aColumnIndex < 0 || aColumnIndex >= mResult->mColumnInfo.Count())
01972     return NS_ERROR_INVALID_ARG;
01973 
01974   if (! mBuffer)
01975     return NS_ERROR_FAILURE;
01976 
01977   Cell* cell = mBuffer->mCells[aColumnIndex];
01978 
01979   if (cell->GetType() != mozISqlResult::TYPE_DECIMAL)
01980     return NS_ERROR_FAILURE;
01981 
01982   cell->SetNull(PR_FALSE);
01983   cell->mFloat = aValue;
01984 
01985   return NS_OK;
01986 }
01987 
01988 NS_IMETHODIMP
01989 mozSqlResultEnumerator::SetDate(PRInt32 aColumnIndex, PRInt64 aValue)
01990 {
01991   if (aColumnIndex < 0 || aColumnIndex >= mResult->mColumnInfo.Count())
01992     return NS_ERROR_INVALID_ARG;
01993 
01994   if (! mBuffer)
01995     return NS_ERROR_FAILURE;
01996 
01997   Cell* cell = mBuffer->mCells[aColumnIndex];
01998 
01999   if (cell->GetType() != mozISqlResult::TYPE_DATE)
02000     return NS_ERROR_FAILURE;
02001 
02002   cell->SetNull(PR_FALSE);
02003   cell->mDate = aValue;
02004 
02005   return NS_OK;
02006 }
02007 
02008 NS_IMETHODIMP
02009 mozSqlResultEnumerator::SetBool(PRInt32 aColumnIndex, PRBool aValue)
02010 {
02011   if (aColumnIndex < 0 || aColumnIndex >= mResult->mColumnInfo.Count())
02012     return NS_ERROR_INVALID_ARG;
02013 
02014   if (! mBuffer)
02015     return NS_ERROR_FAILURE;
02016 
02017   Cell* cell = mBuffer->mCells[aColumnIndex];
02018 
02019   if (cell->GetType() != mozISqlResult::TYPE_BOOL)
02020     return NS_ERROR_FAILURE;
02021 
02022   cell->SetNull(PR_FALSE);
02023   cell->mBool = aValue;
02024 
02025   return NS_OK;
02026 }
02027 
02028 NS_IMETHODIMP
02029 mozSqlResultEnumerator::SetNullValues()
02030 {
02031   for (PRInt32 i = 0; i < mResult->mColumnInfo.Count(); i++) {
02032     Cell* cell = mBuffer->mCells[i];
02033     cell->SetNull(PR_TRUE);
02034   }
02035 
02036   return NS_OK;
02037 }
02038 
02039 NS_IMETHODIMP
02040 mozSqlResultEnumerator::SetDefaultValues()
02041 {
02042   for (PRInt32 i = 0; i < mResult->mColumnInfo.Count(); i++) {
02043     Cell* cell = mBuffer->mCells[i];
02044     cell->SetDefault(PR_TRUE);
02045   }
02046 
02047   return NS_OK;
02048 }
02049 
02050 NS_IMETHODIMP
02051 mozSqlResultEnumerator::CopyValues()
02052 {
02053   if (! mCurrentRow)
02054     return NS_ERROR_FAILURE;
02055 
02056   Row::Copy(mResult->mColumnInfo.Count(), mCurrentRow, mBuffer);
02057 
02058   return NS_OK;
02059 }
02060 
02061 NS_IMETHODIMP
02062 mozSqlResultEnumerator::CanInsert(PRBool* _retval)
02063 {
02064   return mResult->CanInsert(_retval);
02065 }
02066 
02067 NS_IMETHODIMP
02068 mozSqlResultEnumerator::CanUpdate(PRBool* _retval)
02069 {
02070   return mResult->CanUpdate(_retval);
02071 }
02072 
02073 NS_IMETHODIMP
02074 mozSqlResultEnumerator::CanDelete(PRBool* _retval)
02075 {
02076   return mResult->CanDelete(_retval);
02077 }
02078 
02079 NS_IMETHODIMP
02080 mozSqlResultEnumerator::InsertRow(PRInt32* _retval)
02081 {
02082   return mResult->InsertRow(mBuffer, _retval);
02083 }
02084 
02085 NS_IMETHODIMP
02086 mozSqlResultEnumerator::UpdateRow(PRInt32* _retval)
02087 {
02088   return mResult->UpdateRow(mCurrentIndex, mBuffer, _retval);
02089 }
02090 
02091 NS_IMETHODIMP
02092 mozSqlResultEnumerator::DeleteRow(PRInt32* _retval)
02093 {
02094   nsresult rv = mResult->DeleteRow(mCurrentIndex, _retval);
02095   if (NS_FAILED(rv)) return rv;
02096 
02097   mCurrentIndex = -1;
02098   mCurrentRow = nsnull;
02099 
02100   return NS_OK;
02101 }
02102 
02103 NS_IMETHODIMP
02104 mozSqlResultEnumerator::GetCurrentCondition(nsAString& aCurrentCondition)
02105 {
02106   if (! mCurrentRow)
02107     return NS_ERROR_FAILURE;
02108 
02109   return mResult->GetCondition(mCurrentRow, aCurrentCondition);
02110 }
02111 
02112 
02113 NS_IMETHODIMP mozSqlResultEnumerator::HasMoreElements(PRBool* _retval)
02114 {                                                                                               
02115   *_retval = mCurrentIndex < mResult->mRows.Count() - 1;
02116   
02117   return NS_OK;
02118 }
02119 
02120 NS_IMETHODIMP mozSqlResultEnumerator::GetNext(nsISupports** _retval)
02121 {
02122   PRBool hasNext;
02123   Next(&hasNext);
02124 
02125   NS_ADDREF(*_retval = mCurrentRow->mSource);
02126 
02127   return NS_OK;
02128 }
02129 
02130 
02131 mozSqlResultStream::mozSqlResultStream(mozSqlResult* aResult)
02132   : mResult(aResult),
02133     mInitialized(PR_FALSE),
02134     mPosition(0)
02135 {
02136   NS_ADDREF(mResult);
02137 }
02138 
02139 
02140 mozSqlResultStream::~mozSqlResultStream()
02141 {
02142   NS_RELEASE(mResult);
02143 }
02144 
02145 
02146 NS_IMPL_ISUPPORTS2(mozSqlResultStream,
02147                    mozISqlInputStream,
02148                    nsIInputStream)
02149 
02150 
02151 NS_IMETHODIMP
02152 mozSqlResultStream::GetColumnHeader(PRInt32 aColumnIndex, nsAString& aHeader)
02153 {
02154   return NS_OK;
02155 }
02156 
02157 NS_IMETHODIMP
02158 mozSqlResultStream::SetColumnHeader(PRInt32 aColumnIndex, const nsAString& aHeader)
02159 {
02160   return NS_OK;
02161 }
02162 
02163 
02164 NS_IMETHODIMP
02165 mozSqlResultStream::Close()
02166 {
02167   return NS_OK;
02168 }
02169 
02170 NS_IMETHODIMP
02171 mozSqlResultStream::Available(PRUint32* _retval)
02172 {
02173   nsresult rv = EnsureBuffer();
02174   if (NS_FAILED(rv))
02175     return rv;
02176 
02177   *_retval = mBuffer.Length() - mPosition;
02178 
02179   return NS_OK;
02180 }
02181 
02182 NS_IMETHODIMP
02183 mozSqlResultStream::Read(char* aBuffer, PRUint32 aCount, PRUint32* _retval)
02184 {
02185   if (aCount == 0) {
02186     *_retval = 0;
02187     return NS_OK;
02188   }
02189 
02190   nsresult rv = EnsureBuffer();
02191   if (NS_FAILED(rv))
02192     return rv;
02193 
02194   if (aCount > mBuffer.Length() - mPosition)
02195     aCount = mBuffer.Length() - mPosition;
02196 
02197   memcpy(aBuffer, mBuffer.get() + mPosition, aCount);
02198   mPosition += aCount;
02199 
02200   *_retval = aCount;
02201 
02202   return NS_OK;
02203 }
02204 
02205 NS_IMETHODIMP
02206 mozSqlResultStream::ReadSegments(nsWriteSegmentFun aWriter, void* aClosure, PRUint32 aCount, PRUint32* _retval)
02207 {
02208   if (aCount == 0) {
02209     *_retval = 0;
02210     return NS_OK;
02211   }
02212 
02213   nsresult rv = EnsureBuffer();
02214   if (NS_FAILED(rv))
02215     return rv;
02216 
02217   if (aCount > mBuffer.Length() - mPosition)
02218     aCount = mBuffer.Length() - mPosition;
02219 
02220   rv = aWriter(this, aClosure, mBuffer.get() + mPosition, 0, aCount, _retval);
02221   if (NS_SUCCEEDED(rv))
02222     mPosition += aCount;
02223 
02224   return NS_OK;
02225 }
02226 
02227 NS_IMETHODIMP
02228 mozSqlResultStream::IsNonBlocking(PRBool* _retval)
02229 {
02230   *_retval = PR_TRUE;
02231   return NS_OK;
02232 }
02233 
02234 
02235 nsresult
02236 mozSqlResultStream::EnsureBuffer()
02237 {
02238   if (!mInitialized) {
02239     mBuffer.AppendLiteral("<?xml version=\"1.0\"?>\n");
02240     mBuffer.AppendLiteral("<document>\n<body>\n");
02241     PRInt32 rowCount = mResult->mRows.Count();
02242     PRInt32 columnCount = mResult->mColumnInfo.Count();
02243     for (PRInt32 i = 0; i < rowCount; i++) {
02244       mBuffer.AppendLiteral("<row>\n");
02245       Row* row = (Row*)mResult->mRows[i];
02246       for (PRInt32 j = 0; j < columnCount; j++) {
02247         mBuffer.AppendLiteral("<cell>\n");
02248         Cell* cell = row->mCells[j];
02249         if (cell->IsNull())
02250           mBuffer.AppendLiteral("null");
02251         else {
02252           PRInt32 type = cell->GetType();
02253           if (type == mozISqlResult::TYPE_STRING)
02254             mBuffer.Append(NS_ConvertUCS2toUTF8(cell->mString));
02255           else if (type == mozISqlResult::TYPE_INT)
02256             mBuffer.AppendInt(cell->mInt);
02257           else if (type == mozISqlResult::TYPE_FLOAT ||
02258                    type == mozISqlResult::TYPE_DECIMAL)
02259             mBuffer.AppendFloat(cell->mFloat);
02260           else if (type == mozISqlResult::TYPE_DATE ||
02261                    type == mozISqlResult::TYPE_TIME ||
02262                    type == mozISqlResult::TYPE_DATETIME) {
02263             nsAutoString value;
02264             mozSqlResult::gFormat->FormatPRTime(nsnull,
02265                                   type != mozISqlResult::TYPE_TIME ? kDateFormatLong : kDateFormatNone,
02266                                   type != mozISqlResult::TYPE_DATE ? kTimeFormatSeconds : kTimeFormatNone,
02267                                   PRTime(cell->mDate),
02268                                   value);
02269             mBuffer.Append(NS_ConvertUCS2toUTF8(value));
02270           }
02271           else if (type == mozISqlResult::TYPE_BOOL) {
02272             if (cell->mBool)
02273               mBuffer.AppendLiteral("true");
02274             else
02275               mBuffer.AppendLiteral("false");
02276           }
02277         }
02278         mBuffer.AppendLiteral("</cell>\n");
02279       }
02280       mBuffer.AppendLiteral("</row>\n");
02281     }
02282     mBuffer.AppendLiteral("</body>\n</document>\n");
02283 
02284     mInitialized = PR_TRUE;
02285   }
02286 
02287   return NS_OK;
02288 }