Fixing recursive folder matching in ActionLog and FileState

Change-Id: Idc4e8dbdbccbbf83fd520e268011b2c06ddccbab
diff --git a/src/action-log.cc b/src/action-log.cc
index 2d8ebc1..9d96efc 100644
--- a/src/action-log.cc
+++ b/src/action-log.cc
@@ -663,7 +663,7 @@
                           "       file_hash,strftime('%s', file_mtime),file_chmod,file_seg_num, "
                           "       parent_device_name,parent_seq_no "
                           "   FROM ActionLog "
-                          "   WHERE is_prefix (?, directory)=1 "
+                          "   WHERE is_dir_prefix (?, directory)=1 "
                           "   ORDER BY action_timestamp DESC "
                           "   LIMIT ? OFFSET ?", -1, &stmt, 0); // there is a small ambiguity with is_prefix matching, but should be ok for now
       _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_OK, sqlite3_errmsg (m_db));
diff --git a/src/db-helper.cc b/src/db-helper.cc
index 538e137..dca3bdc 100644
--- a/src/db-helper.cc
+++ b/src/db-helper.cc
@@ -68,8 +68,13 @@
                              << errmsg_info_str ("Cannot create function ``directory_name''"));
     }
 
-  // Alex: determine if tables initialized. if not, initialize... not sure what is the best way to go...
-  // for now, just attempt to create everything
+  res = sqlite3_create_function (m_db, "is_dir_prefix", 2, SQLITE_ANY, 0, DbHelper::is_dir_prefix_xFun, 0, 0);
+  if (res != SQLITE_OK)
+    {
+      BOOST_THROW_EXCEPTION (Error::Db ()
+                             << errmsg_info_str ("Cannot create function ``is_dir_prefix''"));
+    }
+
   sqlite3_exec (m_db, INIT_DATABASE.c_str (), NULL, NULL, NULL);
   _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_OK, sqlite3_errmsg (m_db));
 }
@@ -208,3 +213,45 @@
       sqlite3_result_text (context, dirPath.c_str (), dirPath.size (), SQLITE_TRANSIENT);
     }
 }
+
+void
+DbHelper::is_dir_prefix_xFun (sqlite3_context *context, int argc, sqlite3_value **argv)
+{
+  int len1 = sqlite3_value_bytes (argv[0]);
+  int len2 = sqlite3_value_bytes (argv[1]);
+
+  if (len1 == 0)
+    {
+      sqlite3_result_int (context, 1);
+      return;
+    }
+
+  if (len1 > len2) // first parameter should be at most equal in length to the second one
+    {
+      sqlite3_result_int (context, 0);
+      return;
+    }
+
+  if (memcmp (sqlite3_value_blob (argv[0]), sqlite3_value_blob (argv[1]), len1) == 0)
+    {
+      if (len1 == len2)
+        {
+          sqlite3_result_int (context, 1);
+        }
+      else
+        {
+          if (reinterpret_cast<const char*> (sqlite3_value_blob (argv[1]))[len1] == '/')
+            {
+              sqlite3_result_int (context, 1);
+            }
+          else
+            {
+              sqlite3_result_int (context, 0);
+            }
+        }
+    }
+  else
+    {
+      sqlite3_result_int (context, 0);
+    }
+}
diff --git a/src/db-helper.h b/src/db-helper.h
index 0bc1a56..abd9a90 100644
--- a/src/db-helper.h
+++ b/src/db-helper.h
@@ -51,6 +51,9 @@
   static void
   directory_name_xFun (sqlite3_context *context, int argc, sqlite3_value **argv);
 
+  static void
+  is_dir_prefix_xFun (sqlite3_context *context, int argc, sqlite3_value **argv);
+
 protected:
   sqlite3 *m_db;
 };
diff --git a/src/file-state.cc b/src/file-state.cc
index 6ace814..d361eb7 100644
--- a/src/file-state.cc
+++ b/src/file-state.cc
@@ -303,7 +303,7 @@
       sqlite3_prepare_v2 (m_db,
                           "SELECT filename,version,device_name,seq_no,file_hash,strftime('%s', file_mtime),file_chmod,file_seg_num,is_complete "
                           "   FROM FileState "
-                          "   WHERE type = 0 AND is_prefix (?, directory)=1 "
+                          "   WHERE type = 0 AND is_dir_prefix (?, directory)=1 "
                           "   ORDER BY filename "
                           "   LIMIT ? OFFSET ?", -1, &stmt, 0); // there is a small ambiguity with is_prefix matching, but should be ok for now
       _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_OK, sqlite3_errmsg (m_db));