private void ProjectIndexedPaths(JObject soupElt, Dictionary <string, object> contentValues, IndexSpec indexSpec)
        {
            object value = Project(soupElt, indexSpec.Path);

            if (value == null)
            {
                return;
            }
            if (contentValues == null)
            {
                contentValues = new Dictionary <string, object>();
            }
            if (SmartStoreType.SmartInteger.ColumnType.Equals(indexSpec.SmartType.ColumnType))
            {
                contentValues.Add(indexSpec.ColumnName, Int32.Parse(value.ToString()));
            }
            else if (SmartStoreType.SmartString.ColumnType.Equals(indexSpec.SmartType.ColumnType))
            {
                contentValues.Add(indexSpec.ColumnName, value.ToString());
            }
            else if (SmartStoreType.SmartFloating.ColumnType.Equals(indexSpec.SmartType.ColumnType))
            {
                contentValues.Add(indexSpec.ColumnName, Double.Parse(value.ToString()));
            }
        }
        /// <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();
            }
        }
        /// <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();
                            }
                        }
                    }
                }
            }
        }
 private void ProjectIndexedPaths(JObject soupElt, Dictionary<string, object> contentValues, IndexSpec indexSpec)
 {
     object value = Project(soupElt, indexSpec.Path);
     if (value == null)
         return;
     if (contentValues == null)
     {
         contentValues = new Dictionary<string, object>();
     }
     if (SmartStoreType.SmartInteger.ColumnType.Equals(indexSpec.SmartType.ColumnType))
     {
         contentValues.Add(indexSpec.ColumnName, Int32.Parse(value.ToString()));
     }
     else if (SmartStoreType.SmartString.ColumnType.Equals(indexSpec.SmartType.ColumnType))
     {
         contentValues.Add(indexSpec.ColumnName, value.ToString());
     }
     else if (SmartStoreType.SmartFloating.ColumnType.Equals(indexSpec.SmartType.ColumnType))
     {
         contentValues.Add(indexSpec.ColumnName, Double.Parse(value.ToString()));
     }
 }
        /// <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();
            }
        }
        /// <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);
                }
            }
        }
 public static Dictionary<string, IndexSpec> MapForIndexSpecs(IndexSpec[] indexSpecs)
 {
     return indexSpecs.ToDictionary(indexSpec => indexSpec.Path);
 }
 public void CacheIndexSpecs(string soupName, IndexSpec[] indexSpecs)
 {
     SoupNameToIndexSpecsMap.Add(soupName, indexSpecs);
 }