Bug 481178 - mozIStorageConnection createTable and tableExists should support attached databases. r=mak
authorNochum Sossonko <highmind63@gmail.com>
Wed, 09 Apr 2014 09:22:33 -0400
changeset 197880 b29ed4f8b260652f4e1e98560b19a065c5b4bc99
parent 197879 4d752223112e058383d95944535b9283c83ce9cb
child 197881 0a4b034ec82c887772625dec8e9f3acffa6c18e1
push id3624
push userasasaki@mozilla.com
push dateMon, 09 Jun 2014 21:49:01 +0000
treeherdermozilla-beta@b1a5da15899a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmak
bugs481178
milestone31.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 481178 - mozIStorageConnection createTable and tableExists should support attached databases. r=mak
storage/src/mozStorageConnection.cpp
storage/test/unit/test_storage_connection.js
--- a/storage/src/mozStorageConnection.cpp
+++ b/storage/src/mozStorageConnection.cpp
@@ -699,29 +699,41 @@ Connection::initializeInternal(nsIFile* 
 
 nsresult
 Connection::databaseElementExists(enum DatabaseElementType aElementType,
                                   const nsACString &aElementName,
                                   bool *_exists)
 {
   if (!mDBConn) return NS_ERROR_NOT_INITIALIZED;
 
-  nsCString query("SELECT name FROM (SELECT * FROM sqlite_master UNION ALL "
-                                    "SELECT * FROM sqlite_temp_master) "
-                  "WHERE type = '");
+  // When constructing the query, make sure to SELECT the correct db's sqlite_master
+  // if the user is prefixing the element with a specific db. ex: sample.test
+  nsCString query("SELECT name FROM (SELECT * FROM ");
+  nsDependentCSubstring element;
+  int32_t ind = aElementName.FindChar('.');
+  if (ind == kNotFound) {
+    element.Assign(aElementName);
+  }
+  else {
+    nsDependentCSubstring db(Substring(aElementName, 0, ind + 1));
+    element.Assign(Substring(aElementName, ind + 1, aElementName.Length()));
+    query.Append(db);
+  }
+  query.Append("sqlite_master UNION ALL SELECT * FROM sqlite_temp_master) WHERE type = '");
+
   switch (aElementType) {
     case INDEX:
       query.Append("index");
       break;
     case TABLE:
       query.Append("table");
       break;
   }
   query.Append("' AND name ='");
-  query.Append(aElementName);
+  query.Append(element);
   query.Append("'");
 
   sqlite3_stmt *stmt;
   int srv = prepareStatement(query, &stmt);
   if (srv != SQLITE_OK)
     return convertResultCode(srv);
 
   srv = stepStatement(stmt);
--- a/storage/test/unit/test_storage_connection.js
+++ b/storage/test/unit/test_storage_connection.js
@@ -142,16 +142,42 @@ add_task(function test_createTable_alrea
   try {
     msc.createTable("test", "id INTEGER PRIMARY KEY, name TEXT");
     do_throw("We shouldn't get here!");
   } catch (e) {
     do_check_eq(Cr.NS_ERROR_FAILURE, e.result);
   }
 });
 
+add_task(function test_attach_createTable_tableExists_indexExists()
+{
+  var msc = getOpenedDatabase();
+  var file = do_get_file("storage_attach.sqlite", true);
+  var msc2 = getDatabase(file);
+  msc.executeSimpleSQL("ATTACH DATABASE '" + file.path + "' AS sample");
+
+  do_check_false(msc.tableExists("sample.test"));
+  msc.createTable("sample.test", "id INTEGER PRIMARY KEY, name TEXT");
+  do_check_true(msc.tableExists("sample.test"));
+  try {
+    msc.createTable("sample.test", "id INTEGER PRIMARY KEY, name TEXT");
+    do_throw("We shouldn't get here!");
+  } catch (e if e.result == Components.results.NS_ERROR_FAILURE) {
+    // we expect to fail because this table should exist already.
+  }
+
+  do_check_false(msc.indexExists("sample.test_ind"));
+  msc.executeSimpleSQL("CREATE INDEX sample.test_ind ON test (name)");
+  do_check_true(msc.indexExists("sample.test_ind"));
+
+  msc.executeSimpleSQL("DETACH DATABASE sample");
+  msc2.close();
+  try { file.remove(false); } catch(e) { }
+});
+
 add_task(function test_lastInsertRowID()
 {
   var msc = getOpenedDatabase();
   msc.executeSimpleSQL("INSERT INTO test (name) VALUES ('foo')");
   do_check_eq(1, msc.lastInsertRowID);
 });
 
 add_task(function test_transactionInProgress_no()