private static void DropSoup(string databasePath, string soupName)
 {
     lock (smartlock)
     {
         DBHelper db            = DBHelper.GetInstance(databasePath);
         string   soupTableName = db.GetSoupTableName(soupName);
         if (!String.IsNullOrWhiteSpace(soupTableName))
         {
             SQLiteResult result   = db.Execute("DROP TABLE IF EXISTS " + soupTableName);
             bool         success  = result == SQLiteResult.DONE;
             var          soupDrop = new Dictionary <string, object> {
                 { SoupNameCol, soupName }
             };
             try
             {
                 db.BeginTransaction();
                 success &= db.Delete(SoupNamesTable, soupDrop);
                 success &= db.Delete(SoupIndexMapTable, soupDrop);
             }
             finally
             {
                 if (success)
                 {
                     db.CommitTransaction();
                     db.RemoveFromCache(soupName);
                 }
                 else
                 {
                     db.RollbackTransaction();
                 }
             }
         }
     }
 }
 public bool Delete(string soupName, long[] soupEntryIds, Boolean handleTx)
 {
     lock (smartlock)
     {
         bool     success       = false;
         DBHelper db            = DBHelper.GetInstance(DatabasePath);
         string   soupTableName = db.GetSoupTableName(soupName);
         if (String.IsNullOrWhiteSpace(soupTableName))
         {
             throw new SmartStoreException("Soup: " + soupName + " does not exist");
         }
         if (handleTx)
         {
             db.BeginTransaction();
         }
         try
         {
             success = db.Delete(soupTableName, GetSoupEntryIdsPredicate(soupEntryIds));
         }
         finally
         {
             if (handleTx)
             {
                 db.CommitTransaction();
             }
         }
         return(success);
     }
 }
        /// <summary>
        ///     Create soup index map table to keep track of soups' index specs
        ///     Create soup name map table to keep track of soup name to table name mappings
        ///     Called when the database is first created
        /// </summary>
        public void CreateMetaTables()
        {
            lock (smartlock)
            {
                DBHelper db = DBHelper.GetInstance(DatabasePath);
                // Create soup_index_map table
                var sb = new StringBuilder();
                db.BeginTransaction();
                sb.Append("CREATE TABLE IF NOT EXISTS ").Append(SoupIndexMapTable).Append(" (")
                .Append(SoupNameCol).Append(" TEXT")
                .Append(",").Append(PathCol).Append(" TEXT")
                .Append(",").Append(ColumnNameCol).Append(" TEXT")
                .Append(",").Append(ColumnTypeCol).Append(" TEXT")
                .Append(")");
                db.Execute(sb.ToString());
                db.Execute(String.Format("CREATE INDEX IF NOT EXISTS {0} on {1} ( {2} )", SoupIndexMapTable + "_0",
                                         SoupIndexMapTable, SoupNameCol));

                // Create soup_names table
                // The table name for the soup will simply be table_<soupId>
                sb = new StringBuilder();
                sb.Append("CREATE TABLE IF NOT EXISTS ").Append(SoupNamesTable).Append(" (")
                .Append(IdCol).Append(" INTEGER PRIMARY KEY AUTOINCREMENT")
                .Append(",").Append(SoupNameCol).Append(" TEXT")
                .Append(")");
                db.Execute(sb.ToString());

                db.CommitTransaction();
                // Create alter_soup_status table
                CreateLongOperationsStatusTable(db);
            }
        }
        public JObject Update(String soupName, JObject soupElt, long soupEntryId, bool handleTx)
        {
            lock (smartlock)
            {
                DBHelper db            = Database;
                string   soupTableName = db.GetSoupTableName(soupName);
                if (String.IsNullOrWhiteSpace(soupTableName))
                {
                    throw new SmartStoreException("Soup: " + soupName + " does not exist");
                }
                IndexSpec[] indexSpecs = db.GetIndexSpecs(soupName);
                long        now        = CurrentTimeMillis;
                if (soupElt[SoupEntryId] == null)
                {
                    soupElt.Add(SoupEntryId, soupEntryId);
                }
                else
                {
                    soupElt[SoupEntryId] = soupEntryId;
                }
                if (soupElt[SoupLastModifiedDate] == null)
                {
                    soupElt.Add(SoupLastModifiedDate, now);
                }
                else
                {
                    soupElt[SoupLastModifiedDate] = now;
                }


                var contentValues = new Dictionary <string, object>
                {
                    { SoupCol, soupElt.ToString() },
                    { LastModifiedCol, now }
                };
                foreach (IndexSpec indexSpec in indexSpecs)
                {
                    ProjectIndexedPaths(soupElt, contentValues, indexSpec);
                }
                if (handleTx)
                {
                    db.BeginTransaction();
                }
                bool success = db.Update(soupTableName, contentValues, IdPredicate, soupEntryId.ToString());
                if (success)
                {
                    if (handleTx)
                    {
                        db.CommitTransaction();
                    }
                    return(soupElt);
                }
                if (handleTx)
                {
                    db.RollbackTransaction();
                }
                return(null);
            }
        }
        public JObject Create(string soupName, JObject soupElt, bool handleTx)
        {
            lock (smartlock)
            {
                DBHelper    db            = DBHelper.GetInstance(DatabasePath);
                string      soupTableName = db.GetSoupTableName(soupName);
                IndexSpec[] indexSpecs    = db.GetIndexSpecs(soupName);
                if (handleTx)
                {
                    db.BeginTransaction();
                }
                long now         = CurrentTimeMillis;
                long soupEntryId = db.GetNextId(soupTableName);

                soupElt[SoupEntryId]          = soupEntryId;
                soupElt[SoupLastModifiedDate] = now;
                var contentValues = new Dictionary <string, object>
                {
                    { IdCol, soupEntryId },
                    { CreatedCol, now },
                    { LastModifiedCol, now },
                    { SoupCol, soupElt.ToString() }
                };
                foreach (IndexSpec indexSpec in indexSpecs)
                {
                    ProjectIndexedPaths(soupElt, contentValues, indexSpec);
                }

                bool success = db.Insert(soupTableName, contentValues) == soupEntryId;

                if (success)
                {
                    if (handleTx)
                    {
                        db.CommitTransaction();
                    }
                    return(soupElt);
                }
                if (handleTx)
                {
                    db.RollbackTransaction();
                }
                return(null);
            }
        }
 /// <summary>
 ///     Clear all rows from a soup
 /// </summary>
 /// <param name="soupName"></param>
 public void ClearSoup(string soupName)
 {
     lock (smartlock)
     {
         DBHelper db            = DBHelper.GetInstance(DatabasePath);
         string   soupTableName = db.GetSoupTableName(soupName);
         if (String.IsNullOrWhiteSpace(soupTableName))
         {
             throw new SmartStoreException("Soup: " + soupName + " does not exist");
         }
         db.BeginTransaction();
         try
         {
             db.Delete(soupName);
         }
         finally
         {
             db.CommitTransaction();
         }
     }
 }
        /// <summary>
        ///     Create table for soupName with a column for the soup itself and columns for paths specified in indexSpecs
        ///     Create indexes on the new table to make lookup faster
        ///     Create rows in soup index map table for indexSpecs
        /// </summary>
        /// <param name="soupName"></param>
        /// <param name="indexSpecs"></param>
        public void RegisterSoup(String soupName, IndexSpec[] indexSpecs)
        {
            lock (smartlock)
            {
                if (soupName == null)
                {
                    throw new SmartStoreException("Null soup name");
                }
                if (indexSpecs.Length == 0)
                {
                    throw new SmartStoreException("No indexSpecs specified for soup: " + soupName);
                }
                if (HasSoup(soupName))
                {
                    return;                    // soup already exist - do nothing
                }
                // First get a table name
                String soupTableName = null;
                var    soupMapValues = new Dictionary <string, object> {
                    { SoupNameCol, soupName }
                };
                DBHelper db = DBHelper.GetInstance(DatabasePath);
                try
                {
                    db.BeginTransaction();
                    long soupId = db.Insert(SoupNamesTable, soupMapValues);
                    soupTableName = GetSoupTableName(soupId);
                }
                finally
                {
                    db.CommitTransaction();
                }

                if (!String.IsNullOrWhiteSpace(soupTableName))
                {
                    // Do the rest - create table / indexes
                    RegisterSoupUsingTableName(soupName, indexSpecs, soupTableName);
                }
            }
        }
        /// <summary>
        ///     Re-index all soup elements for passed indexPaths
        /// </summary>
        /// <param name="soupName"></param>
        /// <param name="indexPaths"></param>
        /// <param name="handleTx"></param>
        public void ReIndexSoup(string soupName, string[] indexPaths, bool handleTx)
        {
            lock (smartlock)
            {
                DBHelper db            = DBHelper.GetInstance(DatabasePath);
                string   soupTableName = db.GetSoupTableName(soupName);
                if (String.IsNullOrWhiteSpace(soupTableName))
                {
                    throw new SmartStoreException("Soup: " + soupName + " does not exist");
                }
                Dictionary <string, IndexSpec> mapAllSpecs = IndexSpec.MapForIndexSpecs(GetSoupIndexSpecs(soupName));
                IndexSpec[] indexSpecs =
                    (from indexPath in indexPaths where mapAllSpecs.ContainsKey(indexPath) select mapAllSpecs[indexPath])
                    .ToArray();
                if (indexSpecs.Length == 0)
                {
                    return; // nothing to do
                }
                if (handleTx)
                {
                    db.BeginTransaction();
                }

                using (
                    ISQLiteStatement stmt = db.Query(soupTableName, new[] { IdCol, SoupCol }, String.Empty, String.Empty,
                                                     String.Empty))
                {
                    if (stmt.DataCount > 0)
                    {
                        try
                        {
                            do
                            {
                                string soupEntryId = stmt.GetText(0);
                                string soupRaw     = stmt.GetText(1);

                                try
                                {
                                    JObject soupElt       = JObject.Parse(soupRaw);
                                    var     contentValues = new Dictionary <string, object>();
                                    foreach (IndexSpec indexSpec in indexSpecs)
                                    {
                                        ProjectIndexedPaths(soupElt, contentValues, indexSpec);
                                    }
                                    db.Update(soupTableName, contentValues, IdPredicate, soupEntryId + String.Empty);
                                }
                                catch (JsonException e)
                                {
                                    Debug.WriteLine("SmartStore.ReIndexSoup: Could not parse soup element " +
                                                    soupEntryId +
                                                    "\n" + e.Message);
                                }
                            } while (stmt.Step() == SQLiteResult.ROW);
                        }
                        finally
                        {
                            if (handleTx)
                            {
                                db.CommitTransaction();
                            }
                        }
                    }
                }
            }
        }
        /// <summary>
        ///     Helper method for registerSoup
        /// </summary>
        /// <param name="soupName"></param>
        /// <param name="indexSpecs"></param>
        /// <param name="soupTableName"></param>
        private void RegisterSoupUsingTableName(string soupName, IndexSpec[] indexSpecs, string soupTableName)
        {
            DBHelper db = DBHelper.GetInstance(DatabasePath);
            // Prepare SQL for creating soup table and its indices
            var createTableStmt     = new StringBuilder();                       // to create new soup table
            var createIndexStmts    = new List <String>();                       // to create indices on new soup table
            var soupIndexMapInserts = new List <Dictionary <string, object> >(); // to be inserted in soup index map table

            createTableStmt.Append("CREATE TABLE ").Append(soupTableName).Append(" (")
            .Append(IdCol).Append(" INTEGER PRIMARY KEY AUTOINCREMENT")
            .Append(", ").Append(SoupCol).Append(" TEXT")
            .Append(", ").Append(CreatedCol).Append(" INTEGER")
            .Append(", ").Append(LastModifiedCol).Append(" INTEGER");

            int i = 0;
            var indexSpecsToCache = new IndexSpec[indexSpecs.Length];

            foreach (IndexSpec indexSpec in indexSpecs)
            {
                // for create table
                String columnName = soupTableName + "_" + i;
                String columnType = indexSpec.SmartType.ColumnType;
                createTableStmt.Append(", ").Append(columnName).Append(" ").Append(columnType);

                // for insert
                var values = new Dictionary <string, object>
                {
                    { SoupNameCol, soupName },
                    { PathCol, indexSpec.Path },
                    { ColumnNameCol, columnName },
                    { ColumnTypeCol, indexSpec.SmartType.ColumnType }
                };
                soupIndexMapInserts.Add(values);

                // for create index
                String indexName = soupTableName + "_" + i + "_idx";
                createIndexStmts.Add(String.Format("CREATE INDEX {0} on {1} ( {2} )", indexName, soupTableName,
                                                   columnName));

                // for the cache
                indexSpecsToCache[i] = new IndexSpec(indexSpec.Path, indexSpec.SmartType, columnName);

                i++;
            }
            createTableStmt.Append(")");

            // Run SQL for creating soup table and its indices
            db.Execute(createTableStmt.ToString());
            foreach (String createIndexStmt in createIndexStmts)
            {
                db.Execute(createIndexStmt);
            }
            try
            {
                db.BeginTransaction();
                foreach (var values in soupIndexMapInserts)
                {
                    db.Insert(SoupIndexMapTable, values);
                }

                // Add to soupNameToTableNamesMap
                db.CacheTableName(soupName, soupTableName);

                // Add to soupNameToIndexSpecsMap
                db.CacheIndexSpecs(soupName, indexSpecsToCache);
            }
            finally
            {
                db.CommitTransaction();
            }
        }