diff --git a/mozilla/storage/build/Makefile.in b/mozilla/storage/build/Makefile.in index b31cb35d9fd..5a4d39fc41a 100644 --- a/mozilla/storage/build/Makefile.in +++ b/mozilla/storage/build/Makefile.in @@ -53,6 +53,8 @@ REQUIRES = \ sqlite3 \ xpcom \ string \ + js \ + xpconnect \ $(NULL) EXPORTS = mozStorageCID.h diff --git a/mozilla/storage/build/mozStorageCID.h b/mozilla/storage/build/mozStorageCID.h index 51d123622ab..e8847891a34 100644 --- a/mozilla/storage/build/mozStorageCID.h +++ b/mozilla/storage/build/mozStorageCID.h @@ -54,4 +54,10 @@ #define MOZ_STORAGE_SERVICE_CONTRACTID MOZ_STORAGE_CONTRACTID_PREFIX "/service;1" +/* dab3a846-3a59-4fc2-9745-c6ff48776f00 */ +#define MOZ_STORAGE_STATEMENT_WRAPPER_CID \ +{ 0xdab3a846, 0x3a59, 0x4fc2, {0x97, 0x45, 0xc6, 0xff, 0x48, 0x77, 0x6f, 0x00} } + +#define MOZ_STORAGE_STATEMENT_WRAPPER_CONTRACTID MOZ_STORAGE_CONTRACTID_PREFIX "/statement-wrapper;1" + #endif /* _MOZSTORAGECID_H_ */ diff --git a/mozilla/storage/build/mozStorageModule.cpp b/mozilla/storage/build/mozStorageModule.cpp index 1be5d6c4a38..dfa18951fb3 100644 --- a/mozilla/storage/build/mozStorageModule.cpp +++ b/mozilla/storage/build/mozStorageModule.cpp @@ -42,11 +42,13 @@ #include "mozStorageService.h" #include "mozStorageConnection.h" +#include "mozStorageStatementWrapper.h" #include "mozStorageCID.h" NS_GENERIC_FACTORY_CONSTRUCTOR(mozStorageService) NS_GENERIC_FACTORY_CONSTRUCTOR(mozStorageConnection) +NS_GENERIC_FACTORY_CONSTRUCTOR(mozStorageStatementWrapper) static const nsModuleComponentInfo components[] = { @@ -60,7 +62,13 @@ static const nsModuleComponentInfo components[] = MOZ_STORAGE_CONNECTION_CID, MOZ_STORAGE_CONNECTION_CONTRACTID, mozStorageConnectionConstructor + }, + + { "Unified Data Store Scriptable Statement Wrapper", + MOZ_STORAGE_STATEMENT_WRAPPER_CID, + MOZ_STORAGE_STATEMENT_WRAPPER_CONTRACTID, + mozStorageStatementWrapperConstructor } }; -NS_IMPL_NSGETMODULE(mozStorageModule, components); +NS_IMPL_NSGETMODULE(mozStorageModule, components) diff --git a/mozilla/storage/public/Makefile.in b/mozilla/storage/public/Makefile.in index 1f7562c2cd6..b669d956721 100644 --- a/mozilla/storage/public/Makefile.in +++ b/mozilla/storage/public/Makefile.in @@ -52,6 +52,7 @@ XPIDLSRCS = \ mozIStorageConnection.idl \ mozIStorageFunction.idl \ mozIStorageStatement.idl \ + mozIStorageStatementWrapper.idl \ mozIStorageDataSet.idl \ mozIStorageValueArray.idl \ $(NULL) diff --git a/mozilla/storage/public/mozIStorageStatement.idl b/mozilla/storage/public/mozIStorageStatement.idl index e6e4529ab84..e6406625953 100644 --- a/mozilla/storage/public/mozIStorageStatement.idl +++ b/mozilla/storage/public/mozIStorageStatement.idl @@ -43,6 +43,8 @@ interface mozIStorageConnection; interface mozIStorageDataSet; interface nsISimpleEnumerator; +[ptr] native sqlite3stmtptr(struct sqlite3_stmt); + [scriptable, uuid(656aa634-36e2-4977-802e-79bce39c1024)] interface mozIStorageStatement : mozIStorageValueArray { /** @@ -58,6 +60,21 @@ interface mozIStorageStatement : mozIStorageValueArray { */ readonly attribute unsigned long parameterCount; + /* + * Name of nth parameter, if given + */ + AUTF8String getParameterName(in unsigned long aParamIndex); + + /* + * Number of columns returned + */ + readonly attribute unsigned long columnCount; + + /* + * Name of nth column + */ + AUTF8String getColumnName(in unsigned long aColumnIndex); + /* * Reset parameters/statement execution */ @@ -111,5 +128,15 @@ interface mozIStorageStatement : mozIStorageValueArray { */ boolean executeStep (); -}; + /** + * The current state. Row getters are only valid while + * the statement is in the "executing" state. + */ + const long MOZ_STORAGE_STATEMENT_INVALID = 0; + const long MOZ_STORAGE_STATEMENT_READY = 1; + const long MOZ_STORAGE_STATEMENT_EXECUTING = 2; + readonly attribute long state; + + [noscript,notxpcom] sqlite3stmtptr getNativeStatementPointer(); +}; diff --git a/mozilla/storage/public/mozIStorageStatementWrapper.idl b/mozilla/storage/public/mozIStorageStatementWrapper.idl new file mode 100644 index 00000000000..b44df26fc65 --- /dev/null +++ b/mozilla/storage/public/mozIStorageStatementWrapper.idl @@ -0,0 +1,73 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Oracle Corporation code. + * + * The Initial Developer of the Original Code is + * Oracle Corporation + * Portions created by the Initial Developer are Copyright (C) 2004 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Vladimir Vukicevic + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "mozIStorageStatement.idl" + +[scriptable, uuid(02eeaf95-c3db-4182-9340-222c29f68f02)] +interface mozIStorageStatementRow : nsISupports { + // magic interface we return that implements nsIXPCScriptable, to allow + // for by-name access to rows +}; + +[scriptable, uuid(e65fe6e2-2643-463c-97e2-27665efe2386)] +interface mozIStorageStatementParams : nsISupports { + // magic interface for parameter setting that implements nsIXPCScriptable. +}; + +[scriptable, uuid(c9fc1259-a9ac-43da-912f-d321ebd0ff7a)] +interface mozIStorageStatementWrapper : nsISupports { + void initialize (in mozIStorageStatement aStatement); + + readonly attribute mozIStorageStatement statement; + + void reset (); + + boolean step (); + + /** + * The current row. Throws an exception if no row is currently available. + * Useful only from script. The value of this is only valid while the + * statement is still executing, and is on the appropriate row + */ + readonly attribute mozIStorageStatementRow row; + + /** + * The parameters. Can be set in lieu of using the call notation on this. + */ + readonly attribute mozIStorageStatementParams params; +}; diff --git a/mozilla/storage/src/Makefile.in b/mozilla/storage/src/Makefile.in index 2a1d3cb91a3..3607da1a76d 100644 --- a/mozilla/storage/src/Makefile.in +++ b/mozilla/storage/src/Makefile.in @@ -51,13 +51,16 @@ GRE_MODULE = 1 REQUIRES = xpcom \ string \ - sqlite3 \ + sqlite3 \ + js \ + xpconnect \ $(NULL) CPPSRCS = \ mozStorageService.cpp \ mozStorageConnection.cpp \ mozStorageStatement.cpp \ + mozStorageStatementWrapper.cpp \ mozStorageValueArray.cpp \ $(NULL) diff --git a/mozilla/storage/src/mozStorageConnection.cpp b/mozilla/storage/src/mozStorageConnection.cpp index fe11db653f3..b77f18bcdbf 100644 --- a/mozilla/storage/src/mozStorageConnection.cpp +++ b/mozilla/storage/src/mozStorageConnection.cpp @@ -265,20 +265,19 @@ mozStorageConnection::CreateTable(/*const nsID& aID,*/ const char *aTableName, const char *aTableSchema) { -#if 0 int srv; char *buf; int buflen = 0; - buflen = snprintf(nsnull, 0, "CREATE TABLE %s (%s)"); + buflen = snprintf(nsnull, 0, "CREATE TABLE %s (%s)", aTableName, aTableSchema); if (buflen <= 0) return NS_ERROR_FAILURE; - buf = nsMemory::Alloc(buflen + 1); + buf = (char *) nsMemory::Alloc(buflen + 1); if (!buf) return NS_ERROR_OUT_OF_MEMORY; - buflen = sprintf(buf, buflen, "CREATE TABLE %s (%s)"); + buflen = snprintf(buf, buflen+1, "CREATE TABLE %s (%s)", aTableName, aTableSchema); if (buflen <= 0) { nsMemory::Free(buf); return NS_ERROR_FAILURE; @@ -291,7 +290,6 @@ mozStorageConnection::CreateTable(/*const nsID& aID,*/ if (srv != SQLITE_OK) { return NS_ERROR_FAILURE; // XXX SQL_ERROR_TABLE_EXISTS } -#endif return NS_OK; } diff --git a/mozilla/storage/src/mozStorageStatement.cpp b/mozilla/storage/src/mozStorageStatement.cpp index 7e4181b2c00..0db8dc09bdb 100644 --- a/mozilla/storage/src/mozStorageStatement.cpp +++ b/mozilla/storage/src/mozStorageStatement.cpp @@ -40,6 +40,7 @@ #include "nsError.h" #include "nsISimpleEnumerator.h" +#include "nsMemory.h" #include "mozStorageConnection.h" #include "mozStorageStatement.h" @@ -75,76 +76,6 @@ protected: void DoRealStep(); }; -NS_IMPL_ISUPPORTS1(mozStorageStatementRowEnumerator, nsISimpleEnumerator) - -mozStorageStatementRowEnumerator::mozStorageStatementRowEnumerator (sqlite3_stmt *aDBStatement) - : mDBStatement (aDBStatement) -{ - NS_ASSERTION (aDBStatement != nsnull, "Null statement!"); - - // do the first step - DoRealStep (); - mDidStep = PR_TRUE; -} - -void -mozStorageStatementRowEnumerator::DoRealStep () -{ - int srv = sqlite3_step (mDBStatement); - - switch (srv) { - case SQLITE_ROW: - mHasMore = PR_TRUE; - break; - case SQLITE_DONE: - mHasMore = PR_FALSE; - break; - case SQLITE_BUSY: // XXX!!! - case SQLITE_MISUSE: - case SQLITE_ERROR: - default: - mHasMore = PR_FALSE; - break; - } -} - -mozStorageStatementRowEnumerator::~mozStorageStatementRowEnumerator () -{ -} - -/* nsISimpleEnumerator interface */ -NS_IMETHODIMP -mozStorageStatementRowEnumerator::HasMoreElements (PRBool *_retval) -{ - // step if we haven't already - if (!mDidStep) { - DoRealStep(); - mDidStep = PR_TRUE; - } - - *_retval = mHasMore; - return NS_OK; -} - -NS_IMETHODIMP -mozStorageStatementRowEnumerator::GetNext (nsISupports **_retval) -{ - if (!mHasMore) - return NS_ERROR_FAILURE; - - if (!mDidStep) - DoRealStep(); - mDidStep = PR_FALSE; - - // assume this is SQLITE_ROW - sqlite3_data_count (mDBStatement); - - mozStorageStatementRowValueArray *mssrva = new mozStorageStatementRowValueArray(mDBStatement); - NS_ADDREF(mssrva); - *_retval = mssrva; - - return NS_OK; -} /** ** mozStorageStatement @@ -153,7 +84,7 @@ mozStorageStatementRowEnumerator::GetNext (nsISupports **_retval) NS_IMPL_ISUPPORTS2(mozStorageStatement, mozIStorageStatement, mozIStorageValueArray) mozStorageStatement::mozStorageStatement() - : mDBConnection (nsnull), mDBStatement(nsnull) + : mDBConnection (nsnull), mDBStatement(nsnull), mColumnNames(nsnull), mExecuting(PR_FALSE) { } @@ -181,6 +112,11 @@ mozStorageStatement::Initialize(mozIStorageConnection *aDBConnection, const nsAC mParamCount = sqlite3_bind_parameter_count (mDBStatement); mResultColumnCount = sqlite3_column_count (mDBStatement); + for (unsigned int i = 0; i < mResultColumnCount; i++) { + const void *name = sqlite3_column_name16 (mDBStatement, i); + mColumnNames.AppendString(nsDependentString(NS_STATIC_CAST(const PRUnichar*, name))); + } + // doing a sqlite3_prepare sets up the execution engine // for that statement; doing a create_function after that // results in badness, because there's a selected statement. @@ -217,7 +153,57 @@ mozStorageStatement::Clone(mozIStorageStatement **_retval) NS_IMETHODIMP mozStorageStatement::GetParameterCount(PRUint32 *aParameterCount) { - return NS_ERROR_NOT_IMPLEMENTED; + NS_ASSERTION (mDBConnection && mDBStatement, "statement not initialized"); + NS_ENSURE_ARG_POINTER(aParameterCount); + + *aParameterCount = mParamCount; + return NS_OK; +} + +/* AUTF8String getParameterName(in unsigned long aParamIndex); */ +NS_IMETHODIMP +mozStorageStatement::GetParameterName(PRUint32 aParamIndex, nsACString & _retval) +{ + NS_ASSERTION (mDBConnection && mDBStatement, "statement not initialized"); + if (aParamIndex < 0 || aParamIndex >= mParamCount) + return NS_ERROR_FAILURE; // XXXerror + + const char *pname = sqlite3_bind_parameter_name(mDBStatement, aParamIndex + 1); + if (pname == NULL) { + // this thing had no name, so fake one + nsCAutoString pname(":"); + pname.AppendInt(aParamIndex); + _retval.Assign(pname); + } else { + _retval.Assign(nsDependentCString(pname)); + } + + return NS_OK; +} + +/* readonly attribute unsigned long columnCount; */ +NS_IMETHODIMP +mozStorageStatement::GetColumnCount(PRUint32 *aColumnCount) +{ + NS_ASSERTION (mDBConnection && mDBStatement, "statement not initialized"); + NS_ENSURE_ARG_POINTER(aColumnCount); + + *aColumnCount = mResultColumnCount; + return NS_OK; +} + +/* AUTF8String getColumnName(in unsigned long aColumnIndex); */ +NS_IMETHODIMP +mozStorageStatement::GetColumnName(PRUint32 aColumnIndex, nsACString & _retval) +{ + NS_ASSERTION (mDBConnection && mDBStatement, "statement not initialized"); + if (aColumnIndex < 0 || aColumnIndex >= mResultColumnCount) + return NS_ERROR_FAILURE; // XXXerror + + const char *cname = sqlite3_column_name(mDBStatement, aColumnIndex); + _retval.Assign(nsDependentCString(cname)); + + return NS_OK; } /* void reset (); */ @@ -227,6 +213,7 @@ mozStorageStatement::Reset() NS_ASSERTION (mDBConnection && mDBStatement, "statement not initialized"); sqlite3_reset(mDBStatement); + mExecuting = PR_FALSE; return NS_OK; } @@ -374,11 +361,11 @@ mozStorageStatement::Execute() mDBConnection->GetLastErrorString(errStr); PR_LOG(gStorageLog, PR_LOG_DEBUG, ("mozStorageStatement::Execute error: %s", errStr.get())); #endif + mExecuting = PR_FALSE; return NS_ERROR_FAILURE; // XXX error code } - sqlite3_reset (mDBStatement); - - return NS_OK; + + return Reset(); } /* mozIStorageDataSet executeDataSet (); */ @@ -409,20 +396,26 @@ mozStorageStatement::ExecuteStep(PRBool *_retval) // SQLITE_ROW and SQLITE_DONE are non-errors if (srv == SQLITE_ROW) { // we got a row back + mExecuting = PR_TRUE; *_retval = PR_TRUE; return NS_OK; } else if (srv == SQLITE_DONE) { // statement is done (no row returned) + mExecuting = PR_FALSE; *_retval = PR_FALSE; return NS_OK; } else if (srv == SQLITE_BUSY) { // ??? what to do? + mExecuting = PR_FALSE; return NS_ERROR_FAILURE; } else if (srv == SQLITE_MISUSE) { // bad stuff happened + mExecuting = PR_FALSE; return NS_ERROR_FAILURE; } else if (srv == SQLITE_ERROR) { // even worse stuff happened + mExecuting = PR_FALSE; + return NS_ERROR_FAILURE; } else { // something that shouldn't happen happened NS_ERROR ("sqlite3_step returned an error code we don't know about!"); @@ -432,20 +425,27 @@ mozStorageStatement::ExecuteStep(PRBool *_retval) return NS_ERROR_FAILURE; } -#if 0 -/* nsISimpleEnumerator executeEnumerator (); */ -NS_IMETHODIMP -mozStorageStatement::ExecuteEnumerator(nsISimpleEnumerator **_retval) +/* [noscript,notxpcom] sqlite3stmtptr getNativeStatementPointer(); */ +sqlite3_stmt* +mozStorageStatement::GetNativeStatementPointer() { - NS_ASSERTION (mDBConnection && mDBStatement, "statement not initialized"); + return mDBStatement; +} - mozStorageStatementRowEnumerator *mssre = new mozStorageStatementRowEnumerator (mDBStatement); - NS_ADDREF(mssre); - *_retval = mssre; +/* readonly attribute long state; */ +NS_IMETHODIMP +mozStorageStatement::GetState(PRInt32 *_retval) +{ + if (!mDBConnection || !mDBStatement) { + *_retval = MOZ_STORAGE_STATEMENT_INVALID; + } else if (mExecuting) { + *_retval = MOZ_STORAGE_STATEMENT_EXECUTING; + } else { + *_retval = MOZ_STORAGE_STATEMENT_READY; + } return NS_OK; } -#endif /*** *** mozIStorageValueArray @@ -495,6 +495,8 @@ NS_IMETHODIMP mozStorageStatement::GetAsInt32(PRUint32 aIndex, PRInt32 *_retval) { NS_ASSERTION (aIndex < mResultColumnCount, "aIndex out of range"); + if (!mExecuting) + return NS_ERROR_FAILURE; *_retval = sqlite3_column_int (mDBStatement, aIndex); @@ -506,6 +508,8 @@ NS_IMETHODIMP mozStorageStatement::GetAsInt64(PRUint32 aIndex, PRInt64 *_retval) { NS_ASSERTION (aIndex < mResultColumnCount, "aIndex out of range"); + if (!mExecuting) + return NS_ERROR_FAILURE; *_retval = sqlite3_column_int64 (mDBStatement, aIndex); @@ -517,6 +521,8 @@ NS_IMETHODIMP mozStorageStatement::GetAsDouble(PRUint32 aIndex, double *_retval) { NS_ASSERTION (aIndex < mResultColumnCount, "aIndex out of range"); + if (!mExecuting) + return NS_ERROR_FAILURE; *_retval = sqlite3_column_double (mDBStatement, aIndex); @@ -528,6 +534,8 @@ NS_IMETHODIMP mozStorageStatement::GetAsCString(PRUint32 aIndex, char **_retval) { NS_ASSERTION (aIndex < mResultColumnCount, "aIndex out of range"); + if (!mExecuting) + return NS_ERROR_FAILURE; int slen = sqlite3_column_bytes (mDBStatement, aIndex); const unsigned char *cstr = sqlite3_column_text (mDBStatement, aIndex); @@ -544,6 +552,8 @@ NS_IMETHODIMP mozStorageStatement::GetAsUTF8String(PRUint32 aIndex, nsACString & _retval) { NS_ASSERTION (aIndex < mResultColumnCount, "aIndex out of range"); + if (!mExecuting) + return NS_ERROR_FAILURE; int slen = sqlite3_column_bytes (mDBStatement, aIndex); const unsigned char *cstr = sqlite3_column_text (mDBStatement, aIndex); @@ -557,9 +567,12 @@ NS_IMETHODIMP mozStorageStatement::GetAsString(PRUint32 aIndex, nsAString & _retval) { NS_ASSERTION (aIndex < mResultColumnCount, "aIndex out of range"); + if (!mExecuting) + return NS_ERROR_FAILURE; int slen = sqlite3_column_bytes16 (mDBStatement, aIndex); - const PRUnichar *wstr = (const PRUnichar *) sqlite3_column_text16 (mDBStatement, aIndex); + const void *text = sqlite3_column_text16 (mDBStatement, aIndex); + const PRUnichar *wstr = NS_STATIC_CAST(const PRUnichar *, text); _retval.Assign (wstr, slen/2); return NS_OK; @@ -570,6 +583,8 @@ NS_IMETHODIMP mozStorageStatement::GetAsBlob(PRUint32 aIndex, PRUint8 **aData, PRUint32 *aDataSize) { NS_ASSERTION (aIndex < mResultColumnCount, "aIndex out of range"); + if (!mExecuting) + return NS_ERROR_FAILURE; int blobsize = sqlite3_column_bytes (mDBStatement, aIndex); const void *blob = sqlite3_column_blob (mDBStatement, aIndex); @@ -632,7 +647,8 @@ mozStorageStatement::AsSharedWString(PRUint32 aIndex, PRUint32 *aLength) *aLength = slen; } - return (PRUnichar *) sqlite3_column_text16 (mDBStatement, aIndex); + const void *text = sqlite3_column_text16 (mDBStatement, aIndex); + return NS_STATIC_CAST(PRUnichar *, NS_CONST_CAST(void *, text)); } /* [noscript] void asSharedBlob (in unsigned long aIndex, [shared] out voidPtr aData, out unsigned long aDataSize); */ diff --git a/mozilla/storage/src/mozStorageStatement.h b/mozilla/storage/src/mozStorageStatement.h index 9c1a58c9c38..b7f843c948f 100644 --- a/mozilla/storage/src/mozStorageStatement.h +++ b/mozilla/storage/src/mozStorageStatement.h @@ -42,6 +42,8 @@ #include "nsCOMPtr.h" #include "nsString.h" +#include "nsVoidArray.h" + #include "mozIStorageStatement.h" #include "mozIStorageConnection.h" @@ -66,6 +68,8 @@ protected: sqlite3_stmt *mDBStatement; PRUint32 mParamCount; PRUint32 mResultColumnCount; + nsStringArray mColumnNames; + PRBool mExecuting; }; #endif /* _MOZSTORAGESTATEMENT_H_ */ diff --git a/mozilla/storage/src/mozStorageStatementWrapper.cpp b/mozilla/storage/src/mozStorageStatementWrapper.cpp new file mode 100644 index 00000000000..0642850d48f --- /dev/null +++ b/mozilla/storage/src/mozStorageStatementWrapper.cpp @@ -0,0 +1,934 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Oracle Corporation code. + * + * The Initial Developer of the Original Code is + * Oracle Corporation + * Portions created by the Initial Developer are Copyright (C) 2004 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Vladimir Vukicevic + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsMemory.h" +#include "nsString.h" + +#include "mozStorageStatementWrapper.h" + +#include "jsapi.h" +#include "jsdate.h" + +#include "sqlite3.h" + +/** + ** mozStorageStatementRow + **/ +class mozStorageStatementRow : public mozIStorageStatementRow, + public nsIXPCScriptable +{ +public: + mozStorageStatementRow(sqlite3_stmt *aStatement, + int aNumColumns, + const nsStringArray *aColumnNames); + + // nsISupports interface + NS_DECL_ISUPPORTS + + // mozIStorageStatementRow interface (empty) + NS_DECL_MOZISTORAGESTATEMENTROW + + // nsIXPCScriptable interface + NS_DECL_NSIXPCSCRIPTABLE +protected: + sqlite3_stmt *mDBStatement; + int mNumColumns; + const nsStringArray *mColumnNames; +}; + +/** + ** mozStorageStatementParams + **/ +class mozStorageStatementParams : public mozIStorageStatementParams, + public nsIXPCScriptable +{ +public: + mozStorageStatementParams(mozIStorageStatement *aStatement); + + // interfaces + NS_DECL_ISUPPORTS + NS_DECL_MOZISTORAGESTATEMENTPARAMS + NS_DECL_NSIXPCSCRIPTABLE + +protected: + nsCOMPtr mStatement; + PRUint32 mParamCount; +}; + +static PRBool +JSValStorageStatementBinder (JSContext *cx, + mozIStorageStatement *aStatement, + PRUint32 aParamIndex, + jsval val) +{ + if (JSVAL_IS_INT(val)) { + int v = JSVAL_TO_INT(val); + aStatement->BindInt32Parameter(aParamIndex, v); + } else if (JSVAL_IS_DOUBLE(val)) { + double d = *JSVAL_TO_DOUBLE(val); + aStatement->BindDoubleParameter(aParamIndex, d); + } else if (JSVAL_IS_STRING(val)) { + JSString *str = JSVAL_TO_STRING(val); + aStatement->BindWStringParameter(aParamIndex, NS_STATIC_CAST(PRUnichar*, JS_GetStringChars(str))); + } else if (JSVAL_IS_BOOLEAN(val)) { + if (val == JSVAL_TRUE) { + aStatement->BindInt32Parameter(aParamIndex, 1); + } else { + aStatement->BindInt32Parameter(aParamIndex, 0); + } + } else if (JSVAL_IS_NULL(val)) { + aStatement->BindNullParameter(aParamIndex); + } else if (JSVAL_IS_OBJECT(val)) { + JSObject *obj = JSVAL_TO_OBJECT(val); + // some special things + if (js_DateIsValid (cx, obj)) { + double msecd = js_DateGetMsecSinceEpoch(cx, obj); + PRInt64 msec; + LL_D2L(msec, msecd); + + aStatement->BindInt64Parameter(aParamIndex, msec); + } else { + return PR_FALSE; + } + } else { + return PR_FALSE; + } + + return PR_TRUE; +} + + +/************************************************************************* + **** + **** mozStorageStatementWrapper + **** + *************************************************************************/ + +NS_IMPL_ISUPPORTS2(mozStorageStatementWrapper, mozIStorageStatementWrapper, nsIXPCScriptable) + +mozStorageStatementWrapper::mozStorageStatementWrapper() + : mStatement(nsnull), mDBStatement(nsnull) +{ +} + +mozStorageStatementWrapper::~mozStorageStatementWrapper() +{ + mStatement = nsnull; + mDBStatement = nsnull; +} + +NS_IMETHODIMP +mozStorageStatementWrapper::Initialize(mozIStorageStatement *aStatement) +{ + NS_ASSERTION(mStatement == nsnull, "mozStorageStatementWrapper is already initialized"); + NS_ENSURE_ARG_POINTER(aStatement); + + mStatement = aStatement; + + // fetch the actual statement out + mDBStatement = mStatement->GetNativeStatementPointer(); + + // fetch various things we care about + mStatement->GetParameterCount(&mParamCount); + mStatement->GetNumColumns(&mResultColumnCount); + + for (unsigned int i = 0; i < mResultColumnCount; i++) { + const void *name = sqlite3_column_name16 (mDBStatement, i); + mColumnNames.AppendString(nsDependentString(NS_STATIC_CAST(const PRUnichar*, name))); + } + + return NS_OK; +} + +NS_IMETHODIMP +mozStorageStatementWrapper::GetStatement(mozIStorageStatement **aStatement) +{ + NS_IF_ADDREF(*aStatement = mStatement); + return NS_OK; +} + +NS_IMETHODIMP +mozStorageStatementWrapper::Reset() +{ + if (!mStatement) + return NS_ERROR_FAILURE; + + return mStatement->Reset(); +} + +NS_IMETHODIMP +mozStorageStatementWrapper::Step(PRBool *_retval) +{ + if (!mStatement) + return NS_ERROR_FAILURE; + + return mStatement->ExecuteStep(_retval); +} + +NS_IMETHODIMP +mozStorageStatementWrapper::GetRow(mozIStorageStatementRow **aRow) +{ + NS_ENSURE_ARG_POINTER(aRow); + + if (!mStatement) + return NS_ERROR_FAILURE; + + PRInt32 state; + mStatement->GetState(&state); + if (state != mozIStorageStatement::MOZ_STORAGE_STATEMENT_EXECUTING) + return NS_ERROR_FAILURE; + + if (!mStatementRow) { + mozStorageStatementRow *row = new mozStorageStatementRow(mDBStatement, mResultColumnCount, &mColumnNames); + if (!row) + return NS_ERROR_OUT_OF_MEMORY; + mStatementRow = row; + } + + NS_ADDREF(*aRow = mStatementRow); + return NS_OK; +} + +NS_IMETHODIMP +mozStorageStatementWrapper::GetParams(mozIStorageStatementParams **aParams) +{ + NS_ENSURE_ARG_POINTER(aParams); + + if (!mStatementParams) { + mozStorageStatementParams *params = new mozStorageStatementParams(mStatement); + if (!params) + return NS_ERROR_OUT_OF_MEMORY; + mStatementParams = params; + } + + NS_ADDREF(*aParams = mStatementParams); + return NS_OK; +} + +/*** nsIXPCScriptable interface ***/ + +/* readonly attribute string className; */ +NS_IMETHODIMP +mozStorageStatementWrapper::GetClassName(char * *aClassName) +{ + NS_ENSURE_ARG_POINTER(aClassName); + *aClassName = (char *) nsMemory::Clone("mozStorageStatementWrapper", 27); + if (!*aClassName) + return NS_ERROR_OUT_OF_MEMORY; + return NS_OK; +} + +/* readonly attribute PRUint32 scriptableFlags; */ +NS_IMETHODIMP +mozStorageStatementWrapper::GetScriptableFlags(PRUint32 *aScriptableFlags) +{ + *aScriptableFlags = + nsIXPCScriptable::WANT_CALL | + nsIXPCScriptable::USE_JSSTUB_FOR_SETPROPERTY | + nsIXPCScriptable::WANT_NEWRESOLVE | + nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE; + return NS_OK; +} + +/* PRBool call (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in PRUint32 argc, in JSValPtr argv, in JSValPtr vp); */ +NS_IMETHODIMP +mozStorageStatementWrapper::Call(nsIXPConnectWrappedNative *wrapper, JSContext * cx, + JSObject * obj, PRUint32 argc, jsval * argv, jsval * vp, PRBool *_retval) +{ + if (!mStatement) { + *_retval = PR_TRUE; + return NS_ERROR_FAILURE; + } + + if (argc != mParamCount) { + *_retval = PR_FALSE; + return NS_ERROR_FAILURE; + } + + // reset + mStatement->Reset(); + + // bind parameters + for (PRUint32 i = 0; i < argc; i++) { + if (!JSValStorageStatementBinder(cx, mStatement, i, argv[i])) { + *_retval = PR_FALSE; + return NS_ERROR_FAILURE; + } + } + + // if there are no results, we just execute + if (mResultColumnCount == 0) + mStatement->Execute(); + + *vp = JSVAL_TRUE; + *_retval = PR_TRUE; + return NS_OK; +} + +/* PRBool getProperty (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in JSVal id, in JSValPtr vp); */ +NS_IMETHODIMP +mozStorageStatementWrapper::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext * cx, + JSObject * obj, jsval id, jsval * vp, PRBool *_retval) +{ + *_retval = PR_FALSE; + return NS_OK; +} + + +/* PRBool setProperty (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in JSVal id, in JSValPtr vp); */ +NS_IMETHODIMP +mozStorageStatementWrapper::SetProperty(nsIXPConnectWrappedNative *wrapper, JSContext * cx, + JSObject * obj, jsval id, jsval * vp, PRBool *_retval) +{ + *_retval = PR_FALSE; + return NS_OK; +} + +/* void preCreate (in nsISupports nativeObj, in JSContextPtr cx, in JSObjectPtr globalObj, out JSObjectPtr parentObj); */ +NS_IMETHODIMP +mozStorageStatementWrapper::PreCreate(nsISupports *nativeObj, JSContext * cx, + JSObject * globalObj, JSObject * *parentObj) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* void create (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj); */ +NS_IMETHODIMP +mozStorageStatementWrapper::Create(nsIXPConnectWrappedNative *wrapper, JSContext * cx, JSObject * obj) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* void postCreate (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj); */ +NS_IMETHODIMP +mozStorageStatementWrapper::PostCreate(nsIXPConnectWrappedNative *wrapper, JSContext * cx, JSObject * obj) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* PRBool addProperty (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in JSVal id, in JSValPtr vp); */ +NS_IMETHODIMP +mozStorageStatementWrapper::AddProperty(nsIXPConnectWrappedNative *wrapper, JSContext * cx, + JSObject * obj, jsval id, jsval * vp, PRBool *_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* PRBool delProperty (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in JSVal id, in JSValPtr vp); */ +NS_IMETHODIMP +mozStorageStatementWrapper::DelProperty(nsIXPConnectWrappedNative *wrapper, JSContext * cx, + JSObject * obj, jsval id, jsval * vp, PRBool *_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* PRBool enumerate (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj); */ +NS_IMETHODIMP +mozStorageStatementWrapper::Enumerate(nsIXPConnectWrappedNative *wrapper, JSContext * cx, + JSObject * obj, PRBool *_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* PRBool newEnumerate (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in PRUint32 enum_op, in JSValPtr statep, out JSID idp); */ +NS_IMETHODIMP +mozStorageStatementWrapper::NewEnumerate(nsIXPConnectWrappedNative *wrapper, JSContext * cx, + JSObject * obj, PRUint32 enum_op, jsval * statep, jsid *idp, PRBool *_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* PRBool newResolve (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in JSVal id, in PRUint32 flags, out JSObjectPtr objp); */ +NS_IMETHODIMP +mozStorageStatementWrapper::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext * cx, + JSObject * obj, jsval id, PRUint32 flags, JSObject * *objp, PRBool *_retval) +{ + *_retval = PR_TRUE; + return NS_OK; +} + +/* PRBool convert (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in PRUint32 type, in JSValPtr vp); */ +NS_IMETHODIMP +mozStorageStatementWrapper::Convert(nsIXPConnectWrappedNative *wrapper, JSContext * cx, + JSObject * obj, PRUint32 type, jsval * vp, PRBool *_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* void finalize (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj); */ +NS_IMETHODIMP +mozStorageStatementWrapper::Finalize(nsIXPConnectWrappedNative *wrapper, JSContext * cx, + JSObject * obj) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* PRBool checkAccess (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in JSVal id, in PRUint32 mode, in JSValPtr vp); */ +NS_IMETHODIMP +mozStorageStatementWrapper::CheckAccess(nsIXPConnectWrappedNative *wrapper, JSContext * cx, + JSObject * obj, jsval id, PRUint32 mode, jsval * vp, PRBool *_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* PRBool construct (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in PRUint32 argc, in JSValPtr argv, in JSValPtr vp); */ +NS_IMETHODIMP +mozStorageStatementWrapper::Construct(nsIXPConnectWrappedNative *wrapper, JSContext * cx, + JSObject * obj, PRUint32 argc, jsval * argv, jsval * vp, PRBool *_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* PRBool hasInstance (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in JSVal val, out PRBool bp); */ +NS_IMETHODIMP +mozStorageStatementWrapper::HasInstance(nsIXPConnectWrappedNative *wrapper, JSContext * cx, + JSObject * obj, jsval val, PRBool *bp, PRBool *_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* PRUint32 mark (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in voidPtr arg); */ +NS_IMETHODIMP +mozStorageStatementWrapper::Mark(nsIXPConnectWrappedNative *wrapper, JSContext * cx, + JSObject * obj, void * arg, PRUint32 *_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + + + +/************************************************************************* + **** + **** mozStorageStatementRow + **** + *************************************************************************/ + +NS_IMPL_ISUPPORTS2(mozStorageStatementRow, mozIStorageStatementRow, nsIXPCScriptable) + +mozStorageStatementRow::mozStorageStatementRow(sqlite3_stmt *aStatement, + int aNumColumns, + const nsStringArray *aColumnNames) + : mDBStatement(aStatement), + mNumColumns(aNumColumns), + mColumnNames(aColumnNames) +{ +} + +/* + * nsIXPCScriptable impl + */ + +/* readonly attribute string className; */ +NS_IMETHODIMP +mozStorageStatementRow::GetClassName(char * *aClassName) +{ + NS_ENSURE_ARG_POINTER(aClassName); + *aClassName = (char *) nsMemory::Clone("mozStorageStatementRow", 23); + if (!*aClassName) + return NS_ERROR_OUT_OF_MEMORY; + return NS_OK; +} + +/* readonly attribute PRUint32 scriptableFlags; */ +NS_IMETHODIMP +mozStorageStatementRow::GetScriptableFlags(PRUint32 *aScriptableFlags) +{ + *aScriptableFlags = + nsIXPCScriptable::WANT_GETPROPERTY | + nsIXPCScriptable::WANT_NEWRESOLVE | + nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE; + return NS_OK; +} + +/* PRBool getProperty (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in JSVal id, in JSValPtr vp); */ +NS_IMETHODIMP +mozStorageStatementRow::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext * cx, + JSObject * obj, jsval id, jsval * vp, PRBool *_retval) +{ + *_retval = PR_FALSE; + + if (JSVAL_IS_STRING(id)) { + nsDependentString jsid((PRUnichar *)::JS_GetStringChars(JSVAL_TO_STRING(id)), + ::JS_GetStringLength(JSVAL_TO_STRING(id))); + + for (int i = 0; i < mNumColumns; i++) { + if (jsid.Equals(*(*mColumnNames)[i])) { + int ctype = sqlite3_column_type(mDBStatement, i); + + if (ctype == SQLITE_INTEGER || ctype == SQLITE_FLOAT) { + double dval = sqlite3_column_double(mDBStatement, i); + if (!JS_NewNumberValue(cx, dval, vp)) { + *_retval = PR_FALSE; + return NS_ERROR_FAILURE; + } + } else if (ctype == SQLITE_TEXT) { + JSString *str = JS_NewUCStringCopyN(cx, + (jschar*) sqlite3_column_text16(mDBStatement, i), + sqlite3_column_bytes16(mDBStatement, i)/2); + if (!str) { + *_retval = PR_FALSE; + return NS_ERROR_FAILURE; + } + *vp = STRING_TO_JSVAL(str); + } else if (ctype == SQLITE_BLOB) { + JSString *str = JS_NewStringCopyN(cx, + (char*) sqlite3_column_blob(mDBStatement, i), + sqlite3_column_bytes(mDBStatement, i)); + if (!str) { + *_retval = PR_FALSE; + return NS_OK; + } + } else if (ctype == SQLITE_NULL) { + *vp = JSVAL_NULL; + } else { + NS_ERROR("sqlite3_column_type returned unknown column type, what's going on?"); + } + + *_retval = PR_TRUE; + break; + } + } + } + + return NS_OK; +} + + +/* PRBool setProperty (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in JSVal id, in JSValPtr vp); */ +NS_IMETHODIMP +mozStorageStatementRow::SetProperty(nsIXPConnectWrappedNative *wrapper, JSContext * cx, + JSObject * obj, jsval id, jsval * vp, PRBool *_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* void preCreate (in nsISupports nativeObj, in JSContextPtr cx, in JSObjectPtr globalObj, out JSObjectPtr parentObj); */ +NS_IMETHODIMP +mozStorageStatementRow::PreCreate(nsISupports *nativeObj, JSContext * cx, + JSObject * globalObj, JSObject * *parentObj) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* void create (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj); */ +NS_IMETHODIMP +mozStorageStatementRow::Create(nsIXPConnectWrappedNative *wrapper, JSContext * cx, JSObject * obj) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* void postCreate (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj); */ +NS_IMETHODIMP +mozStorageStatementRow::PostCreate(nsIXPConnectWrappedNative *wrapper, JSContext * cx, JSObject * obj) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* PRBool addProperty (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in JSVal id, in JSValPtr vp); */ +NS_IMETHODIMP +mozStorageStatementRow::AddProperty(nsIXPConnectWrappedNative *wrapper, JSContext * cx, + JSObject * obj, jsval id, jsval * vp, PRBool *_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* PRBool delProperty (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in JSVal id, in JSValPtr vp); */ +NS_IMETHODIMP +mozStorageStatementRow::DelProperty(nsIXPConnectWrappedNative *wrapper, JSContext * cx, + JSObject * obj, jsval id, jsval * vp, PRBool *_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* PRBool enumerate (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj); */ +NS_IMETHODIMP +mozStorageStatementRow::Enumerate(nsIXPConnectWrappedNative *wrapper, JSContext * cx, + JSObject * obj, PRBool *_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* PRBool newEnumerate (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in PRUint32 enum_op, in JSValPtr statep, out JSID idp); */ +NS_IMETHODIMP +mozStorageStatementRow::NewEnumerate(nsIXPConnectWrappedNative *wrapper, JSContext * cx, + JSObject * obj, PRUint32 enum_op, jsval * statep, jsid *idp, PRBool *_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* PRBool newResolve (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in JSVal id, in PRUint32 flags, out JSObjectPtr objp); */ +NS_IMETHODIMP +mozStorageStatementRow::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext * cx, + JSObject * obj, jsval id, PRUint32 flags, JSObject * *objp, PRBool *_retval) +{ + if (JSVAL_IS_STRING(id)) { + JSString *str = JSVAL_TO_STRING(id); + nsDependentString name((PRUnichar *)::JS_GetStringChars(str), + ::JS_GetStringLength(str)); + + for (int i = 0; i < mNumColumns; i++) { + if (name.Equals(*(*mColumnNames)[i])) { + *_retval = ::JS_DefineUCProperty(cx, obj, ::JS_GetStringChars(str), + ::JS_GetStringLength(str), + JSVAL_VOID, + nsnull, nsnull, 0); + *objp = obj; + return *_retval ? NS_OK : NS_ERROR_FAILURE; + } + } + } + + *_retval = PR_TRUE; + return NS_OK; +} + +/* PRBool convert (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in PRUint32 type, in JSValPtr vp); */ +NS_IMETHODIMP +mozStorageStatementRow::Convert(nsIXPConnectWrappedNative *wrapper, JSContext * cx, + JSObject * obj, PRUint32 type, jsval * vp, PRBool *_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* void finalize (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj); */ +NS_IMETHODIMP +mozStorageStatementRow::Finalize(nsIXPConnectWrappedNative *wrapper, JSContext * cx, + JSObject * obj) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* PRBool checkAccess (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in JSVal id, in PRUint32 mode, in JSValPtr vp); */ +NS_IMETHODIMP +mozStorageStatementRow::CheckAccess(nsIXPConnectWrappedNative *wrapper, JSContext * cx, + JSObject * obj, jsval id, PRUint32 mode, jsval * vp, PRBool *_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* PRBool call (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in PRUint32 argc, in JSValPtr argv, in JSValPtr vp); */ +NS_IMETHODIMP +mozStorageStatementRow::Call(nsIXPConnectWrappedNative *wrapper, JSContext * cx, + JSObject * obj, PRUint32 argc, jsval * argv, jsval * vp, PRBool *_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* PRBool construct (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in PRUint32 argc, in JSValPtr argv, in JSValPtr vp); */ +NS_IMETHODIMP +mozStorageStatementRow::Construct(nsIXPConnectWrappedNative *wrapper, JSContext * cx, + JSObject * obj, PRUint32 argc, jsval * argv, jsval * vp, PRBool *_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* PRBool hasInstance (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in JSVal val, out PRBool bp); */ +NS_IMETHODIMP +mozStorageStatementRow::HasInstance(nsIXPConnectWrappedNative *wrapper, JSContext * cx, + JSObject * obj, jsval val, PRBool *bp, PRBool *_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* PRUint32 mark (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in voidPtr arg); */ +NS_IMETHODIMP +mozStorageStatementRow::Mark(nsIXPConnectWrappedNative *wrapper, JSContext * cx, + JSObject * obj, void * arg, PRUint32 *_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + + + + +/************************************************************************* + **** + **** mozStorageStatementParams + **** + *************************************************************************/ + +NS_IMPL_ISUPPORTS2(mozStorageStatementParams, mozIStorageStatementParams, nsIXPCScriptable) + +mozStorageStatementParams::mozStorageStatementParams(mozIStorageStatement *aStatement) + : mStatement(aStatement) +{ + NS_ASSERTION(mStatement != nsnull, "mStatement is null"); + mStatement->GetParameterCount(&mParamCount); +} + +/* + * nsIXPCScriptable impl + */ + +/* readonly attribute string className; */ +NS_IMETHODIMP +mozStorageStatementParams::GetClassName(char * *aClassName) +{ + NS_ENSURE_ARG_POINTER(aClassName); + *aClassName = (char *) nsMemory::Clone("mozStorageStatementParams", 26); + if (!*aClassName) + return NS_ERROR_OUT_OF_MEMORY; + return NS_OK; +} + +/* readonly attribute PRUint32 scriptableFlags; */ +NS_IMETHODIMP +mozStorageStatementParams::GetScriptableFlags(PRUint32 *aScriptableFlags) +{ + *aScriptableFlags = + nsIXPCScriptable::WANT_SETPROPERTY | + nsIXPCScriptable::WANT_NEWRESOLVE | + nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE; + return NS_OK; +} + +/* PRBool getProperty (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in JSVal id, in JSValPtr vp); */ +NS_IMETHODIMP +mozStorageStatementParams::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext * cx, + JSObject * obj, jsval id, jsval * vp, PRBool *_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + + +/* PRBool setProperty (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in JSVal id, in JSValPtr vp); */ +NS_IMETHODIMP +mozStorageStatementParams::SetProperty(nsIXPConnectWrappedNative *wrapper, JSContext * cx, + JSObject * obj, jsval id, jsval * vp, PRBool *_retval) +{ + int idx = -1; + + if (JSVAL_IS_INT(id)) { + idx = JSVAL_TO_INT(id); + } else if (JSVAL_IS_STRING(id)) { + JSString *str = JSVAL_TO_STRING(id); + nsCAutoString name(":"); + name.Append(NS_ConvertUTF16toUTF8(nsDependentString((PRUnichar *)::JS_GetStringChars(str), + ::JS_GetStringLength(str)))); + + // check to see if there's a parameter with this name + + idx = sqlite3_bind_parameter_index(mStatement->GetNativeStatementPointer(), name.get()); + if (idx == 0) { + // er, not found? How'd we get past NewResolve? + *_retval = PR_FALSE; + return NS_ERROR_FAILURE; + } else { + // drop this by 1, to account for sqlite's indexes being 1-based + idx -= 1; + } + } else { + *_retval = PR_FALSE; + return NS_ERROR_FAILURE; + } + + if (idx == -1) { + *_retval = PR_FALSE; + return NS_ERROR_FAILURE; + } + + // we have a valid param index, so do the conversion from JSVal -> bind + *_retval = JSValStorageStatementBinder (cx, mStatement, idx, *vp); + + return NS_OK; +} + +/* void preCreate (in nsISupports nativeObj, in JSContextPtr cx, in JSObjectPtr globalObj, out JSObjectPtr parentObj); */ +NS_IMETHODIMP +mozStorageStatementParams::PreCreate(nsISupports *nativeObj, JSContext * cx, + JSObject * globalObj, JSObject * *parentObj) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* void create (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj); */ +NS_IMETHODIMP +mozStorageStatementParams::Create(nsIXPConnectWrappedNative *wrapper, JSContext * cx, JSObject * obj) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* void postCreate (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj); */ +NS_IMETHODIMP +mozStorageStatementParams::PostCreate(nsIXPConnectWrappedNative *wrapper, JSContext * cx, JSObject * obj) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* PRBool addProperty (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in JSVal id, in JSValPtr vp); */ +NS_IMETHODIMP +mozStorageStatementParams::AddProperty(nsIXPConnectWrappedNative *wrapper, JSContext * cx, + JSObject * obj, jsval id, jsval * vp, PRBool *_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* PRBool delProperty (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in JSVal id, in JSValPtr vp); */ +NS_IMETHODIMP +mozStorageStatementParams::DelProperty(nsIXPConnectWrappedNative *wrapper, JSContext * cx, + JSObject * obj, jsval id, jsval * vp, PRBool *_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* PRBool enumerate (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj); */ +NS_IMETHODIMP +mozStorageStatementParams::Enumerate(nsIXPConnectWrappedNative *wrapper, JSContext * cx, + JSObject * obj, PRBool *_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* PRBool newEnumerate (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in PRUint32 enum_op, in JSValPtr statep, out JSID idp); */ +NS_IMETHODIMP +mozStorageStatementParams::NewEnumerate(nsIXPConnectWrappedNative *wrapper, JSContext * cx, + JSObject * obj, PRUint32 enum_op, jsval * statep, jsid *idp, PRBool *_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* PRBool newResolve (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in JSVal id, in PRUint32 flags, out JSObjectPtr objp); */ +NS_IMETHODIMP +mozStorageStatementParams::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext * cx, + JSObject * obj, jsval id, PRUint32 flags, JSObject * *objp, PRBool *_retval) +{ + int idx = -1; + + if (JSVAL_IS_INT(id)) { + idx = JSVAL_TO_INT(id); + } else if (JSVAL_IS_STRING(id)) { + JSString *str = JSVAL_TO_STRING(id); + nsCAutoString name(":"); + name.Append(NS_ConvertUTF16toUTF8(nsDependentString((PRUnichar *)::JS_GetStringChars(str), + ::JS_GetStringLength(str)))); + + // check to see if there's a parameter with this name + idx = sqlite3_bind_parameter_index(mStatement->GetNativeStatementPointer(), name.get()); + if (idx == 0) { + // nope. + *_retval = PR_FALSE; + return NS_OK; + } else { + // set idx, so that the numbered property also gets defined + idx = idx - 1; + } + + PRBool success = ::JS_DefineUCProperty(cx, obj, ::JS_GetStringChars(str), + ::JS_GetStringLength(str), + JSVAL_VOID, + nsnull, nsnull, 0); + if (!success) { + *_retval = PR_FALSE; + return NS_ERROR_FAILURE; + } + } + + if (idx == -1) { + *_retval = PR_FALSE; + return NS_ERROR_FAILURE; + } + + // is it out of range? + if (idx < 0 || idx >= (int)mParamCount) { + *_retval = PR_FALSE; + return NS_OK; + } + + *_retval = ::JS_DefineElement(cx, obj, idx, JSVAL_VOID, nsnull, nsnull, 0); + if (*_retval) + *objp = obj; + return NS_OK; +} + +/* PRBool convert (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in PRUint32 type, in JSValPtr vp); */ +NS_IMETHODIMP +mozStorageStatementParams::Convert(nsIXPConnectWrappedNative *wrapper, JSContext * cx, + JSObject * obj, PRUint32 type, jsval * vp, PRBool *_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* void finalize (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj); */ +NS_IMETHODIMP +mozStorageStatementParams::Finalize(nsIXPConnectWrappedNative *wrapper, JSContext * cx, + JSObject * obj) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* PRBool checkAccess (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in JSVal id, in PRUint32 mode, in JSValPtr vp); */ +NS_IMETHODIMP +mozStorageStatementParams::CheckAccess(nsIXPConnectWrappedNative *wrapper, JSContext * cx, + JSObject * obj, jsval id, PRUint32 mode, jsval * vp, PRBool *_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* PRBool call (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in PRUint32 argc, in JSValPtr argv, in JSValPtr vp); */ +NS_IMETHODIMP +mozStorageStatementParams::Call(nsIXPConnectWrappedNative *wrapper, JSContext * cx, + JSObject * obj, PRUint32 argc, jsval * argv, jsval * vp, PRBool *_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* PRBool construct (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in PRUint32 argc, in JSValPtr argv, in JSValPtr vp); */ +NS_IMETHODIMP +mozStorageStatementParams::Construct(nsIXPConnectWrappedNative *wrapper, JSContext * cx, + JSObject * obj, PRUint32 argc, jsval * argv, jsval * vp, PRBool *_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* PRBool hasInstance (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in JSVal val, out PRBool bp); */ +NS_IMETHODIMP +mozStorageStatementParams::HasInstance(nsIXPConnectWrappedNative *wrapper, JSContext * cx, + JSObject * obj, jsval val, PRBool *bp, PRBool *_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* PRUint32 mark (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in voidPtr arg); */ +NS_IMETHODIMP +mozStorageStatementParams::Mark(nsIXPConnectWrappedNative *wrapper, JSContext * cx, + JSObject * obj, void * arg, PRUint32 *_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + + diff --git a/mozilla/storage/src/mozStorageStatementWrapper.h b/mozilla/storage/src/mozStorageStatementWrapper.h new file mode 100644 index 00000000000..1ac66f364d6 --- /dev/null +++ b/mozilla/storage/src/mozStorageStatementWrapper.h @@ -0,0 +1,80 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Oracle Corporation code. + * + * The Initial Developer of the Original Code is + * Oracle Corporation + * Portions created by the Initial Developer are Copyright (C) 2004 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Vladimir Vukicevic + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef _MOZSTORAGESTATEMENTWRAPPER_H_ +#define _MOZSTORAGESTATEMENTWRAPPER_H_ + +#include "mozIStorageStatement.h" +#include "mozIStorageStatementWrapper.h" +#include "nsIXPCScriptable.h" + +#include "nsVoidArray.h" + +#include "sqlite3.h" + + +/*** + *** mozStorageStatementWrapper + ***/ +class mozStorageStatementWrapper : public mozIStorageStatementWrapper, + public nsIXPCScriptable +{ +public: + mozStorageStatementWrapper(); + + // interfaces + NS_DECL_ISUPPORTS + NS_DECL_MOZISTORAGESTATEMENTWRAPPER + NS_DECL_NSIXPCSCRIPTABLE + +private: + ~mozStorageStatementWrapper(); + +protected: + // note: pointer to the concrete statement + nsCOMPtr mStatement; + sqlite3_stmt *mDBStatement; + PRUint32 mParamCount; + PRUint32 mResultColumnCount; + nsStringArray mColumnNames; + + nsCOMPtr mStatementRow; + nsCOMPtr mStatementParams; +}; + +#endif /* _MOZSTORAGESTATEMENTWRAPPER_H_ */