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 179790 b29ed4f8b260652f4e1e98560b19a065c5b4bc99
parent 179789 4d752223112e058383d95944535b9283c83ce9cb
child 179791 0a4b034ec82c887772625dec8e9f3acffa6c18e1
push id272
push userpvanderbeken@mozilla.com
push dateMon, 05 May 2014 16:31:18 +0000
reviewersmak
bugs481178
milestone31.0a1
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()