1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/storage/src/mozStoragePrivateHelpers.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,181 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- 1.5 + * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ : 1.6 + * This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#include "sqlite3.h" 1.11 + 1.12 +#include "jsfriendapi.h" 1.13 + 1.14 +#include "nsPrintfCString.h" 1.15 +#include "nsString.h" 1.16 +#include "nsError.h" 1.17 +#include "mozilla/Mutex.h" 1.18 +#include "mozilla/CondVar.h" 1.19 +#include "nsThreadUtils.h" 1.20 +#include "nsJSUtils.h" 1.21 + 1.22 +#include "Variant.h" 1.23 +#include "mozStoragePrivateHelpers.h" 1.24 +#include "mozIStorageStatement.h" 1.25 +#include "mozIStorageCompletionCallback.h" 1.26 +#include "mozIStorageBindingParams.h" 1.27 + 1.28 +#include "prlog.h" 1.29 +#ifdef PR_LOGGING 1.30 +extern PRLogModuleInfo* gStorageLog; 1.31 +#endif 1.32 + 1.33 +namespace mozilla { 1.34 +namespace storage { 1.35 + 1.36 +nsresult 1.37 +convertResultCode(int aSQLiteResultCode) 1.38 +{ 1.39 + // Drop off the extended result bits of the result code. 1.40 + int rc = aSQLiteResultCode & 0xFF; 1.41 + 1.42 + switch (rc) { 1.43 + case SQLITE_OK: 1.44 + case SQLITE_ROW: 1.45 + case SQLITE_DONE: 1.46 + return NS_OK; 1.47 + case SQLITE_CORRUPT: 1.48 + case SQLITE_NOTADB: 1.49 + return NS_ERROR_FILE_CORRUPTED; 1.50 + case SQLITE_PERM: 1.51 + case SQLITE_CANTOPEN: 1.52 + return NS_ERROR_FILE_ACCESS_DENIED; 1.53 + case SQLITE_BUSY: 1.54 + return NS_ERROR_STORAGE_BUSY; 1.55 + case SQLITE_LOCKED: 1.56 + return NS_ERROR_FILE_IS_LOCKED; 1.57 + case SQLITE_READONLY: 1.58 + return NS_ERROR_FILE_READ_ONLY; 1.59 + case SQLITE_IOERR: 1.60 + return NS_ERROR_STORAGE_IOERR; 1.61 + case SQLITE_FULL: 1.62 + case SQLITE_TOOBIG: 1.63 + return NS_ERROR_FILE_NO_DEVICE_SPACE; 1.64 + case SQLITE_NOMEM: 1.65 + return NS_ERROR_OUT_OF_MEMORY; 1.66 + case SQLITE_MISUSE: 1.67 + return NS_ERROR_UNEXPECTED; 1.68 + case SQLITE_ABORT: 1.69 + case SQLITE_INTERRUPT: 1.70 + return NS_ERROR_ABORT; 1.71 + case SQLITE_CONSTRAINT: 1.72 + return NS_ERROR_STORAGE_CONSTRAINT; 1.73 + } 1.74 + 1.75 + // generic error 1.76 +#ifdef DEBUG 1.77 + nsAutoCString message; 1.78 + message.AppendLiteral("SQLite returned error code "); 1.79 + message.AppendInt(rc); 1.80 + message.AppendLiteral(" , Storage will convert it to NS_ERROR_FAILURE"); 1.81 + NS_WARNING(message.get()); 1.82 +#endif 1.83 + return NS_ERROR_FAILURE; 1.84 +} 1.85 + 1.86 +void 1.87 +checkAndLogStatementPerformance(sqlite3_stmt *aStatement) 1.88 +{ 1.89 + // Check to see if the query performed sorting operations or not. If it 1.90 + // did, it may need to be optimized! 1.91 + int count = ::sqlite3_stmt_status(aStatement, SQLITE_STMTSTATUS_SORT, 1); 1.92 + if (count <= 0) 1.93 + return; 1.94 + 1.95 + const char *sql = ::sqlite3_sql(aStatement); 1.96 + 1.97 + // Check to see if this is marked to not warn 1.98 + if (::strstr(sql, "/* do not warn (bug ")) 1.99 + return; 1.100 + 1.101 + nsAutoCString message; 1.102 + message.AppendInt(count); 1.103 + if (count == 1) 1.104 + message.Append(" sort operation has "); 1.105 + else 1.106 + message.Append(" sort operations have "); 1.107 + message.Append("occurred for the SQL statement '"); 1.108 + nsPrintfCString address("0x%p", aStatement); 1.109 + message.Append(address); 1.110 + message.Append("'. See https://developer.mozilla.org/En/Storage/Warnings " 1.111 + "details."); 1.112 + NS_WARNING(message.get()); 1.113 +} 1.114 + 1.115 +nsIVariant * 1.116 +convertJSValToVariant( 1.117 + JSContext *aCtx, 1.118 + JS::Value aValue) 1.119 +{ 1.120 + if (aValue.isInt32()) 1.121 + return new IntegerVariant(aValue.toInt32()); 1.122 + 1.123 + if (aValue.isDouble()) 1.124 + return new FloatVariant(aValue.toDouble()); 1.125 + 1.126 + if (aValue.isString()) { 1.127 + nsDependentJSString value; 1.128 + if (!value.init(aCtx, aValue)) 1.129 + return nullptr; 1.130 + return new TextVariant(value); 1.131 + } 1.132 + 1.133 + if (aValue.isBoolean()) 1.134 + return new IntegerVariant(aValue.isTrue() ? 1 : 0); 1.135 + 1.136 + if (aValue.isNull()) 1.137 + return new NullVariant(); 1.138 + 1.139 + if (aValue.isObject()) { 1.140 + JSObject* obj = &aValue.toObject(); 1.141 + // We only support Date instances, all others fail. 1.142 + if (!::js_DateIsValid(obj)) 1.143 + return nullptr; 1.144 + 1.145 + double msecd = ::js_DateGetMsecSinceEpoch(obj); 1.146 + msecd *= 1000.0; 1.147 + int64_t msec = msecd; 1.148 + 1.149 + return new IntegerVariant(msec); 1.150 + } 1.151 + 1.152 + return nullptr; 1.153 +} 1.154 + 1.155 +namespace { 1.156 +class CallbackEvent : public nsRunnable 1.157 +{ 1.158 +public: 1.159 + CallbackEvent(mozIStorageCompletionCallback *aCallback) 1.160 + : mCallback(aCallback) 1.161 + { 1.162 + } 1.163 + 1.164 + NS_IMETHOD Run() 1.165 + { 1.166 + (void)mCallback->Complete(NS_OK, nullptr); 1.167 + return NS_OK; 1.168 + } 1.169 +private: 1.170 + nsCOMPtr<mozIStorageCompletionCallback> mCallback; 1.171 +}; 1.172 +} // anonymous namespace 1.173 +already_AddRefed<nsIRunnable> 1.174 +newCompletionEvent(mozIStorageCompletionCallback *aCallback) 1.175 +{ 1.176 + NS_ASSERTION(aCallback, "Passing a null callback is a no-no!"); 1.177 + nsCOMPtr<nsIRunnable> event = new CallbackEvent(aCallback); 1.178 + return event.forget(); 1.179 +} 1.180 + 1.181 + 1.182 + 1.183 +} // namespace storage 1.184 +} // namespace mozilla