LCOV - code coverage report
Current view: top level - storage - mozStoragePrivateHelpers.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 39 102 38.2 %
Date: 2017-07-14 16:53:18 Functions: 4 9 44.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
       2             :  * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
       3             :  * This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "sqlite3.h"
       8             : 
       9             : #include "jsfriendapi.h"
      10             : 
      11             : #include "nsPrintfCString.h"
      12             : #include "nsString.h"
      13             : #include "nsError.h"
      14             : #include "mozilla/Mutex.h"
      15             : #include "mozilla/CondVar.h"
      16             : #include "nsQueryObject.h"
      17             : #include "nsThreadUtils.h"
      18             : #include "nsJSUtils.h"
      19             : 
      20             : #include "Variant.h"
      21             : #include "mozStoragePrivateHelpers.h"
      22             : #include "mozIStorageStatement.h"
      23             : #include "mozIStorageCompletionCallback.h"
      24             : #include "mozIStorageBindingParams.h"
      25             : 
      26             : #include "mozilla/Logging.h"
      27             : extern mozilla::LazyLogModule gStorageLog;
      28             : 
      29             : namespace mozilla {
      30             : namespace storage {
      31             : 
      32             : nsresult
      33          74 : convertResultCode(int aSQLiteResultCode)
      34             : {
      35             :   // Drop off the extended result bits of the result code.
      36          74 :   int rc = aSQLiteResultCode & 0xFF;
      37             : 
      38          74 :   switch (rc) {
      39             :     case SQLITE_OK:
      40             :     case SQLITE_ROW:
      41             :     case SQLITE_DONE:
      42          74 :       return NS_OK;
      43             :     case SQLITE_CORRUPT:
      44             :     case SQLITE_NOTADB:
      45           0 :       return NS_ERROR_FILE_CORRUPTED;
      46             :     case SQLITE_PERM:
      47             :     case SQLITE_CANTOPEN:
      48           0 :       return NS_ERROR_FILE_ACCESS_DENIED;
      49             :     case SQLITE_BUSY:
      50           0 :       return NS_ERROR_STORAGE_BUSY;
      51             :     case SQLITE_LOCKED:
      52           0 :       return NS_ERROR_FILE_IS_LOCKED;
      53             :     case SQLITE_READONLY:
      54           0 :       return NS_ERROR_FILE_READ_ONLY;
      55             :     case SQLITE_IOERR:
      56           0 :       return NS_ERROR_STORAGE_IOERR;
      57             :     case SQLITE_FULL:
      58             :     case SQLITE_TOOBIG:
      59           0 :       return NS_ERROR_FILE_NO_DEVICE_SPACE;
      60             :     case SQLITE_NOMEM:
      61           0 :       return NS_ERROR_OUT_OF_MEMORY;
      62             :     case SQLITE_MISUSE:
      63           0 :       return NS_ERROR_UNEXPECTED;
      64             :     case SQLITE_ABORT:
      65             :     case SQLITE_INTERRUPT:
      66           0 :       return NS_ERROR_ABORT;
      67             :     case SQLITE_CONSTRAINT:
      68           0 :       return NS_ERROR_STORAGE_CONSTRAINT;
      69             :   }
      70             : 
      71             :   // generic error
      72             : #ifdef DEBUG
      73           0 :   nsAutoCString message;
      74           0 :   message.AppendLiteral("SQLite returned error code ");
      75           0 :   message.AppendInt(rc);
      76           0 :   message.AppendLiteral(" , Storage will convert it to NS_ERROR_FAILURE");
      77           0 :   NS_WARNING_ASSERTION(rc == SQLITE_ERROR, message.get());
      78             : #endif
      79           0 :   return NS_ERROR_FAILURE;
      80             : }
      81             : 
      82             : void
      83          17 : checkAndLogStatementPerformance(sqlite3_stmt *aStatement)
      84             : {
      85             :   // Check to see if the query performed sorting operations or not.  If it
      86             :   // did, it may need to be optimized!
      87          17 :   int count = ::sqlite3_stmt_status(aStatement, SQLITE_STMTSTATUS_SORT, 1);
      88          17 :   if (count <= 0)
      89          33 :     return;
      90             : 
      91           1 :   const char *sql = ::sqlite3_sql(aStatement);
      92             : 
      93             :   // Check to see if this is marked to not warn
      94           1 :   if (::strstr(sql, "/* do not warn (bug "))
      95           1 :     return;
      96             : 
      97             :   // CREATE INDEX always sorts (sorting is a necessary step in creating
      98             :   // an index).  So ignore the warning there.
      99           0 :   if (::strstr(sql, "CREATE INDEX") || ::strstr(sql, "CREATE UNIQUE INDEX"))
     100           0 :     return;
     101             : 
     102           0 :   nsAutoCString message("Suboptimal indexes for the SQL statement ");
     103             : #ifdef MOZ_STORAGE_SORTWARNING_SQL_DUMP
     104             :   message.Append('`');
     105             :   message.Append(sql);
     106             :   message.AppendLiteral("` [");
     107             :   message.AppendInt(count);
     108             :   message.AppendLiteral(" sort operation(s)]");
     109             : #else
     110           0 :   nsPrintfCString address("0x%p", aStatement);
     111           0 :   message.Append(address);
     112             : #endif
     113           0 :   message.AppendLiteral(" (http://mzl.la/1FuID0j).");
     114           0 :   NS_WARNING(message.get());
     115             : }
     116             : 
     117             : nsIVariant *
     118           6 : convertJSValToVariant(
     119             :   JSContext *aCtx,
     120             :   const JS::Value& aValue)
     121             : {
     122           6 :   if (aValue.isInt32())
     123           0 :     return new IntegerVariant(aValue.toInt32());
     124             : 
     125           6 :   if (aValue.isDouble())
     126           0 :     return new FloatVariant(aValue.toDouble());
     127             : 
     128           6 :   if (aValue.isString()) {
     129          10 :     nsAutoJSString value;
     130           5 :     if (!value.init(aCtx, aValue.toString()))
     131           0 :         return nullptr;
     132           5 :     return new TextVariant(value);
     133             :   }
     134             : 
     135           1 :   if (aValue.isBoolean())
     136           2 :     return new IntegerVariant(aValue.isTrue() ? 1 : 0);
     137             : 
     138           0 :   if (aValue.isNull())
     139           0 :     return new NullVariant();
     140             : 
     141           0 :   if (aValue.isObject()) {
     142           0 :     JS::Rooted<JSObject*> obj(aCtx, &aValue.toObject());
     143             :     // We only support Date instances, all others fail.
     144             :     bool valid;
     145           0 :     if (!js::DateIsValid(aCtx, obj, &valid) || !valid)
     146           0 :       return nullptr;
     147             : 
     148             :     double msecd;
     149           0 :     if (!js::DateGetMsecSinceEpoch(aCtx, obj, &msecd))
     150           0 :       return nullptr;
     151             : 
     152           0 :     msecd *= 1000.0;
     153           0 :     int64_t msec = msecd;
     154             : 
     155           0 :     return new IntegerVariant(msec);
     156             :   }
     157             : 
     158           0 :   return nullptr;
     159             : }
     160             : 
     161             : Variant_base *
     162          39 : convertVariantToStorageVariant(nsIVariant* aVariant)
     163             : {
     164          78 :   RefPtr<Variant_base> variant = do_QueryObject(aVariant);
     165          39 :   if (variant) {
     166             :     // JS helpers already convert the JS representation to a Storage Variant,
     167             :     // in such a case there's nothing left to do here, so just pass-through.
     168           0 :     return variant;
     169             :   }
     170             : 
     171          39 :   if (!aVariant)
     172           0 :     return new NullVariant();
     173             : 
     174             :   uint16_t dataType;
     175          39 :   nsresult rv = aVariant->GetDataType(&dataType);
     176          39 :   NS_ENSURE_SUCCESS(rv, nullptr);
     177             : 
     178          39 :   switch (dataType) {
     179             :     case nsIDataType::VTYPE_BOOL:
     180             :     case nsIDataType::VTYPE_INT8:
     181             :     case nsIDataType::VTYPE_INT16:
     182             :     case nsIDataType::VTYPE_INT32:
     183             :     case nsIDataType::VTYPE_UINT8:
     184             :     case nsIDataType::VTYPE_UINT16:
     185             :     case nsIDataType::VTYPE_UINT32:
     186             :     case nsIDataType::VTYPE_INT64:
     187             :     case nsIDataType::VTYPE_UINT64: {
     188             :       int64_t v;
     189          17 :       rv = aVariant->GetAsInt64(&v);
     190          17 :       NS_ENSURE_SUCCESS(rv, nullptr);
     191          17 :       return new IntegerVariant(v);
     192             :     }
     193             :     case nsIDataType::VTYPE_FLOAT:
     194             :     case nsIDataType::VTYPE_DOUBLE: {
     195             :       double v;
     196           0 :       rv = aVariant->GetAsDouble(&v);
     197           0 :       NS_ENSURE_SUCCESS(rv, nullptr);
     198           0 :       return new FloatVariant(v);
     199             :     }
     200             :     case nsIDataType::VTYPE_CHAR:
     201             :     case nsIDataType::VTYPE_CHAR_STR:
     202             :     case nsIDataType::VTYPE_STRING_SIZE_IS:
     203             :     case nsIDataType::VTYPE_UTF8STRING:
     204             :     case nsIDataType::VTYPE_CSTRING: {
     205          26 :       nsCString v;
     206          13 :       rv = aVariant->GetAsAUTF8String(v);
     207          13 :       NS_ENSURE_SUCCESS(rv, nullptr);
     208          13 :       return new UTF8TextVariant(v);
     209             :     }
     210             :     case nsIDataType::VTYPE_WCHAR:
     211             :     case nsIDataType::VTYPE_DOMSTRING:
     212             :     case nsIDataType::VTYPE_WCHAR_STR:
     213             :     case nsIDataType::VTYPE_WSTRING_SIZE_IS:
     214             :     case nsIDataType::VTYPE_ASTRING: {
     215          16 :       nsString v;
     216           8 :       rv = aVariant->GetAsAString(v);
     217           8 :       NS_ENSURE_SUCCESS(rv, nullptr);
     218           8 :       return new TextVariant(v);
     219             :     }
     220             :     case nsIDataType::VTYPE_ARRAY: {
     221             :       uint16_t type;
     222             :       nsIID iid;
     223             :       uint32_t len;
     224             :       void *rawArray;
     225             :       // Note this copies the array data.
     226           0 :       rv = aVariant->GetAsArray(&type, &iid, &len, &rawArray);
     227           0 :       NS_ENSURE_SUCCESS(rv, nullptr);
     228           0 :       if (type == nsIDataType::VTYPE_UINT8) {
     229           0 :         std::pair<uint8_t *, int> v(static_cast<uint8_t *>(rawArray), len);
     230             :         // Take ownership of the data avoiding a further copy.
     231           0 :         return new AdoptedBlobVariant(v);
     232             :       }
     233             :       MOZ_FALLTHROUGH;
     234             :     }
     235             :     case nsIDataType::VTYPE_EMPTY:
     236             :     case nsIDataType::VTYPE_EMPTY_ARRAY:
     237             :     case nsIDataType::VTYPE_VOID:
     238           1 :       return new NullVariant();
     239             :     case nsIDataType::VTYPE_ID:
     240             :     case nsIDataType::VTYPE_INTERFACE:
     241             :     case nsIDataType::VTYPE_INTERFACE_IS:
     242             :     default:
     243           0 :       NS_WARNING("Unsupported variant type");
     244           0 :       return nullptr;
     245             :   }
     246             : 
     247             :   return nullptr;
     248             : }
     249             : 
     250             : namespace {
     251           0 : class CallbackEvent : public Runnable
     252             : {
     253             : public:
     254           0 :   explicit CallbackEvent(mozIStorageCompletionCallback* aCallback)
     255           0 :     : Runnable("storage::CallbackEvent")
     256           0 :     , mCallback(aCallback)
     257             :   {
     258           0 :   }
     259             : 
     260           0 :   NS_IMETHOD Run() override
     261             :   {
     262           0 :     (void)mCallback->Complete(NS_OK, nullptr);
     263           0 :     return NS_OK;
     264             :   }
     265             : private:
     266             :   nsCOMPtr<mozIStorageCompletionCallback> mCallback;
     267             : };
     268             : } // namespace
     269             : already_AddRefed<nsIRunnable>
     270           0 : newCompletionEvent(mozIStorageCompletionCallback *aCallback)
     271             : {
     272           0 :   NS_ASSERTION(aCallback, "Passing a null callback is a no-no!");
     273           0 :   nsCOMPtr<nsIRunnable> event = new CallbackEvent(aCallback);
     274           0 :   return event.forget();
     275             : }
     276             : 
     277             : } // namespace storage
     278             : } // namespace mozilla

Generated by: LCOV version 1.13