[prev in list] [next in list] [prev in thread] [next in thread] 

List:       fdo-commits
Subject:    [fdo-commits] r5815 - trunk/Providers/SQLite/Src/Provider
From:       svn_fdo () osgeo ! org
Date:       2010-11-18 18:31:30
Message-ID: 20101118183130.74D81390613 () trac ! osgeo ! org
[Download RAW message or body]

Author: romicadascalescu
Date: 2010-11-18 10:31:30 -0800 (Thu, 18 Nov 2010)
New Revision: 5815

Modified:
   trunk/Providers/SQLite/Src/Provider/SltCommands.h
   trunk/Providers/SQLite/Src/Provider/SltConversionUtils.cpp
   trunk/Providers/SQLite/Src/Provider/SltConversionUtils.h
   trunk/Providers/SQLite/Src/Provider/SltProvider.cpp
   trunk/Providers/SQLite/Src/Provider/SltProvider.h
Log:
#504 SQLite provider. Improvements:
 - Improve performance checking on insert if values changed & avoid releasing the \
schema when temp table are created

Modified: trunk/Providers/SQLite/Src/Provider/SltCommands.h
===================================================================
--- trunk/Providers/SQLite/Src/Provider/SltCommands.h	2010-11-18 14:56:20 UTC (rev \
                5814)
+++ trunk/Providers/SQLite/Src/Provider/SltCommands.h	2010-11-18 18:31:30 UTC (rev \
5815) @@ -448,7 +448,70 @@
 ///\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
  ///\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
  ///\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
 +// Class used only to detect if the property values collection has changed between 
+// two or more consecutive inserts. No other special handling is done here
+class SltPropertyValueCollection : public FdoPropertyValueCollection
+{
+private:
+    bool m_collChanged;
+protected:
+    SltPropertyValueCollection()
+    {
+        m_collChanged = false;
+    }
+    virtual ~SltPropertyValueCollection()
+    {
+    }
 
+    virtual void Dispose()
+    {
+        delete this;
+    }
+public:
+    static SltPropertyValueCollection* Create()
+    {
+        return new SltPropertyValueCollection();
+    }
+    virtual void SetItem(FdoInt32 index, FdoPropertyValue* value)
+    {
+        m_collChanged = true;
+        FdoCollection<FdoPropertyValue, FdoCommandException>::SetItem(index, value);
+    }
+    virtual FdoInt32 Add(FdoPropertyValue* value)
+    {
+        m_collChanged = true;
+        return FdoCollection<FdoPropertyValue, FdoCommandException>::Add(value);
+    }
+    virtual void Insert(FdoInt32 index, FdoPropertyValue* value)
+    {
+        m_collChanged = true;
+        FdoCollection<FdoPropertyValue, FdoCommandException>::Insert(index, value);
+    }
+    virtual void Clear()
+    {
+        m_collChanged = true;
+        FdoCollection<FdoPropertyValue, FdoCommandException>::Clear();
+    }
+    virtual void Remove(const FdoPropertyValue* value)
+    {
+        m_collChanged = true;
+        FdoCollection<FdoPropertyValue, FdoCommandException>::Remove(value);
+    }
+    virtual void RemoveAt(FdoInt32 index)
+    {
+        m_collChanged = true;
+        FdoCollection<FdoPropertyValue, FdoCommandException>::RemoveAt(index);
+    }
+    bool GetCollectionChanged()
+    {
+        return m_collChanged;
+    }
+    void SetCollectionChanged(bool value)
+    {
+        m_collChanged = value;
+    }
+};
+
 //Insert is special. We attempt to speed up inserts if the caller is cooperating.
 //The contract is as follows -- as long as the caller reuses the SltInsert object,
 //he is working with a compiled query and within a single transaction. Whenever
@@ -459,7 +522,7 @@
         SltInsert(SltConnection* connection) 
             : SltCommand<FdoIInsert>(connection)
         {
-            m_properties = FdoPropertyValueCollection::Create();
+            m_properties = SltPropertyValueCollection::Create();
             m_pCompiledSQL = NULL;
 			m_idProp = NULL;
             m_db = m_connection->GetDbConnection();
@@ -544,16 +607,21 @@
             }
             else
             {
-                size_t count = (size_t)m_properties->GetCount();
-
-                //detect changes to the property value collection that may have been
-                //done between calls to Execute(). Not recommended to do that, but \
                it happens...
-                if (count != m_propNames.size())
+                // Provider will detect any add/move/insert/delete of properties \
only +                // It's not detecting if a property value changed the name \
while in collection +                // see below the comments.
+                if (m_properties->GetCollectionChanged())
                 {
                     FlushSQL();
                     return Execute();
                 }
-
+                // Do we really need this check? e.g. 50 properties for each insert \
we do 50 string compare +                // I would say no because usually you \
add/move/delete property values +                // and not take a property value and \
set the name after is already in the collection +                // Sure someone can \
do that but it will be a rare case, and to cover rare cases  +                // and \
pay for all other cases... in the end is a API style usage :) +#ifdef \
EXTRA_CHECK_PROPVALUENAME_CHG +                size_t count = \
(size_t)m_properties->GetCount();  for (size_t i=0; i<count; i++)
                 {
                     FdoPtr<FdoPropertyValue> pv = m_properties->GetItem(i);
@@ -564,6 +632,7 @@
                         return Execute();
                     }
                 }
+#endif
             }
 
             // in case active transaction was closed by the user reopen it
@@ -649,6 +718,7 @@
 
             m_pCompiledSQL = NULL;
             m_propNames.clear();
+            m_properties->SetCollectionChanged(false);
         }
 
 
@@ -662,6 +732,7 @@
 
             sbval.Append(") VALUES(");
 
+            m_properties->SetCollectionChanged(false);
             for (int i=0; i<m_properties->GetCount(); i++)
             {
                 FdoPtr<FdoPropertyValue> pv = m_properties->GetItem(i);
@@ -707,7 +778,7 @@
 
 		// used only to get the inserted ID if needed
         FdoDataPropertyDefinition*  m_idProp;
-        FdoPropertyValueCollection* m_properties;
+        SltPropertyValueCollection* m_properties;
 
         std::string                 m_fcname;
         std::string                 m_fcmainname;
@@ -827,10 +898,36 @@
             if (rc == SQLITE_DONE)
             {
                 const char* sql = m_sb.Data();
-                if (StringStartsWith(sql, "create"))
-                    m_connection->FreeCachedSchema(true);
-                else if (StringStartsWith(sql, "drop") || StringStartsWith(sql, \
                "alter"))
-                    m_connection->FreeCachedSchema(false);
+                const char* lastPos = NULL;
+                if (StringStartsWith(sql, "create", &lastPos)) // handle CREATE \
[TEMP]/[TEMPORARY] TABLE +                {
+                    // if we clear the schema and the table is not in the schema we \
do it for nothing +                    // in case we create a non temp table free the \
cached schema +                    if (!StringStartsWith(lastPos, "TEMP"))
+                        m_connection->FreeCachedSchema();
+                }
+                else if (StringStartsWith(sql, "drop", &lastPos)) // DROP VIEW/TABLE \
[IF EXIST] database.tablename +                {
+                    std::string name;
+                    if (StringStartsWith(lastPos, "table", &lastPos) || \
StringStartsWith(lastPos, "view", &lastPos)) +                    {
+                        if (StringStartsWith(lastPos, "if ", &lastPos)) // skip IF
+                            lastPos = SkipTokenString(lastPos); // skip EXISTS
+                        name = GetTableNameToken(lastPos);
+                    }
+                    // if we clear the schema and the table is not in the schema we \
do it for nothing +                    if (name.size())
+                        m_connection->ClearClassFromCachedSchema(name.c_str(), \
true); +                }
+                else if (StringStartsWith(sql, "alter", &lastPos))
+                {
+                    std::string name;
+                    lastPos = SkipTokenString(lastPos); // skip TABLE
+                    name = GetTableNameToken(lastPos);
+                    // if we clear the schema and the table is not in the schema we \
do it for nothing +                    if (name.size())
+                        m_connection->ClearClassFromCachedSchema(name.c_str(), \
false); +                }
                 // "CREATE/ALTER/DROP* will set sqlite3_changes = 0 so result will \
be 0  // INSERT/UPDATE/DELETE* will return affected rows 
                 // in case of error an exception will be thrown

Modified: trunk/Providers/SQLite/Src/Provider/SltConversionUtils.cpp
===================================================================
--- trunk/Providers/SQLite/Src/Provider/SltConversionUtils.cpp	2010-11-18 14:56:20 \
                UTC (rev 5814)
+++ trunk/Providers/SQLite/Src/Provider/SltConversionUtils.cpp	2010-11-18 18:31:30 \
UTC (rev 5815) @@ -77,8 +77,45 @@
     return -1;
 }
 
-bool StringStartsWith(const char* str, const char* val)
+// returns a table name been able to process formats like: 
+// name, "name", main."name", main.name, "main"."name"
+std::string GetTableNameToken(const char* str)
 {
+    const char* strTmp = str;
+    while (*strTmp == ' ' && *strTmp != '\0') strTmp++;
+    str = strTmp;
+    bool startDq = false;
+    while(*strTmp != '\0')
+    {
+        if (*strTmp == '\"')
+            startDq = !startDq;
+        if (*strTmp == ' ' && !startDq)
+            break;        
+        strTmp++;
+    }
+    if (str == strTmp)
+        return std::string("");
+    if (StringStartsWith(str, "main."))
+        str = str + 5;
+    else if (StringStartsWith(str, "\"main\"."))
+        str = str + 7;
+    if (*str == '\"')
+        return std::string(str+1, (int)(strTmp-str-2));
+    else
+        return std::string(str, (int)(strTmp-str));
+}
+
+// skips a predefined token whihc cannot contain space character
+const char* SkipTokenString(const char* str)
+{
+    const char* strTmp = str;
+    while (*strTmp == ' ' && *strTmp != '\0') strTmp++;
+    while(*strTmp != '\0' && *strTmp != ' ') strTmp++;
+    return strTmp;
+}
+
+bool StringStartsWith(const char* str, const char* val, const char** lastPos)
+{
     assert( str!=NULL );
     const char* strTmp = str;
     while (*strTmp == ' ' && *strTmp != '\0') strTmp++;
@@ -86,7 +123,11 @@
     while(sqlite3UpperToLower[*strTmp++] == sqlite3UpperToLower[*valTmp++])
     {
         if (*valTmp == '\0')
+        {
+            if (lastPos != NULL)
+                *lastPos = strTmp;
             return true;
+        }
     }
     return false;
 }

Modified: trunk/Providers/SQLite/Src/Provider/SltConversionUtils.h
===================================================================
--- trunk/Providers/SQLite/Src/Provider/SltConversionUtils.h	2010-11-18 14:56:20 UTC \
                (rev 5814)
+++ trunk/Providers/SQLite/Src/Provider/SltConversionUtils.h	2010-11-18 18:31:30 UTC \
(rev 5815) @@ -67,7 +67,9 @@
 SLT_API void BindPropVals(FdoParameterValueCollection* props, sqlite3_stmt* stmt, \
bool useParmName, int geomFormat);  SLT_API void BindPropValue(sqlite3_stmt* stmt, \
int i, FdoLiteralValue* lv, int geomFormat);  SLT_API int StringContains(const char* \
                str, const char* val);
-SLT_API bool StringStartsWith(const char* str, const char* val);
+SLT_API bool StringStartsWith(const char* str, const char* val, const char** lastPos \
= NULL); +SLT_API const char* SkipTokenString(const char* str);
+SLT_API std::string GetTableNameToken(const char* str);
 
 SLT_API TokenDateFormatType StringToDateFormat(const char* specifier);
 

Modified: trunk/Providers/SQLite/Src/Provider/SltProvider.cpp
===================================================================
--- trunk/Providers/SQLite/Src/Provider/SltProvider.cpp	2010-11-18 14:56:20 UTC (rev \
                5814)
+++ trunk/Providers/SQLite/Src/Provider/SltProvider.cpp	2010-11-18 18:31:30 UTC (rev \
5815) @@ -4103,36 +4103,54 @@
     return (xyTolerance > 0.0);
 }
 
-void SltConnection::FreeCachedSchema (bool isAddition)
+void SltConnection::ClearClassFromCachedSchema(const char* table, bool fullDrop)
 {
-    if (isAddition)
+    // do we have this class in the current schema?
+    if (!fullDrop)
     {
-        // The cached FDO schema will need to be refreshed
-        FDO_SAFE_RELEASE(m_pSchema);
-        m_pSchema = NULL;
+        MetadataCache::iterator iter = m_mNameToMetadata.find((char*)table);
+        if (iter != m_mNameToMetadata.end())
+        {
+            // in case we do just clean it up.
+            FDO_SAFE_RELEASE(m_pSchema);
+            m_pSchema = NULL;
+
+            delete iter->second;
+            free(iter->first); //it was created via strdup, must use free()
+            m_mNameToMetadata.erase(iter);
+        }
     }
-    else // should we improve this? for now let's not do it.
+    else
     {
-        FDO_SAFE_RELEASE(m_pSchema);
-        m_pSchema = NULL;
-        //free the spatial indexes
-        for (SpatialIndexCache::iterator iter = m_mNameToSpatialIndex.begin();
-             iter != m_mNameToSpatialIndex.end(); iter++)
-        {
-            iter->second->Release();
-            free((char*)iter->first); //it was created via strdup, must use free()
-        }
-
-        m_mNameToSpatialIndex.clear();
-
         //clear the cached schema metadata
-        for (MetadataCache::iterator iter = m_mNameToMetadata.begin();
-             iter != m_mNameToMetadata.end(); iter++)
+        for (MetadataCache::iterator iter = iter = m_mNameToMetadata.begin();
+            iter != m_mNameToMetadata.end(); iter++)
         {
              delete iter->second;
              free(iter->first); //it was created via strdup, must use free()
         }
-
         m_mNameToMetadata.clear();
+        // in case we do just clean it up.
+        FDO_SAFE_RELEASE(m_pSchema);
+        m_pSchema = NULL;
     }
+    SpatialIndexCache::iterator iterSp = m_mNameToSpatialIndex.find((char*)table);
+    if (iterSp != m_mNameToSpatialIndex.end())
+    {
+        SpatialIndex* si = iterSp->second->GetSpatialIndex();
+        if (si)
+        {
+            // we cannot release it since there might be cached statements keeping \
the SI locked +            si->ResetToEmpty();
+            if (!fullDrop) // we had alter
+                RebuildSpatialOperator(iterSp->second);
+        }
+    }
 }
+
+void SltConnection::FreeCachedSchema ()
+{
+    // The cached FDO schema will need to be refreshed
+    FDO_SAFE_RELEASE(m_pSchema);
+    m_pSchema = NULL;
+}

Modified: trunk/Providers/SQLite/Src/Provider/SltProvider.h
===================================================================
--- trunk/Providers/SQLite/Src/Provider/SltProvider.h	2010-11-18 14:56:20 UTC (rev \
                5814)
+++ trunk/Providers/SQLite/Src/Provider/SltProvider.h	2010-11-18 18:31:30 UTC (rev \
5815) @@ -262,7 +262,8 @@
     int GetDefaultSpatialContext();
     bool SupportsTolerance();
     bool AddSupportForTolerance();
-    void FreeCachedSchema (bool isAddition);
+    void FreeCachedSchema ();
+    void ClearClassFromCachedSchema(const char* table, bool fullDrop);
 
 private :
 

_______________________________________________
fdo-commits mailing list
fdo-commits@lists.osgeo.org
http://lists.osgeo.org/mailman/listinfo/fdo-commits


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic