Exemplo n.º 1
0
int sqlopen(char *database,char *user,char *password,DB *db,int flags)
{
	if(sqlite3_open(database,db)!=SQLITE_OK)
	{
		printf("sql open of %s failed\n",database);
		goto out0;
	}
	sqlite3_create_collation(*db,"dmoz",SQLITE_UTF8,NULL,collate);
	if(flags&SQLFLAGS_HIGHMEM)
	{
		if(sqlrun(*db,"PRAGMA cache_size=4000"))goto out1;
	}
	else if(flags&SQLFLAGS_LOWMEM)
	{
		if(sqlrun(*db,"PRAGMA cache_size=0"))goto out1;
	}
	if(flags&SQLFLAGS_BEGIN)
	{
		if(sqlrun(*db,"BEGIN"))goto out1;
	}
	return 0;
out1:	sqlite3_close(*db);
out0:	*db=NULL;
	return -1;
}
Exemplo n.º 2
0
static void pdo_sqlite_cleanup_callbacks(pdo_sqlite_db_handle *H)
{
	struct pdo_sqlite_func *func;

	while (H->funcs) {
		func = H->funcs;
		H->funcs = func->next;

		if (H->db) {
			/* delete the function from the handle */
			sqlite3_create_function(H->db,
				func->funcname,
				func->argc,
				SQLITE_UTF8,
				func,
				NULL, NULL, NULL);
		}

		efree((char*)func->funcname);
		if (!Z_ISUNDEF(func->func)) {
			zval_ptr_dtor(&func->func);
		}
		if (!Z_ISUNDEF(func->step)) {
			zval_ptr_dtor(&func->step);
		}
		if (!Z_ISUNDEF(func->fini)) {
			zval_ptr_dtor(&func->fini);
		}
		efree(func);
	}

	while (H->collations) {
		struct pdo_sqlite_collation *collation;
		collation = H->collations;
		H->collations = collation->next;

		if (H->db) {
			/* delete the collation from the handle */
			sqlite3_create_collation(H->db,
				collation->name,
				SQLITE_UTF8,
				collation,
				NULL);
		}

		efree((char*)collation->name);
		if (!Z_ISUNDEF(collation->callback)) {
			zval_ptr_dtor(&collation->callback);
		}
		efree(collation);
	}
}
Exemplo n.º 3
0
/*
** Register a new collation sequence with the database handle db.
*/
int sqlite3_create_collation16(
  sqlite3* db,
  const char *zName,
  int enc,
  void* pCtx,
  int(*xCompare)(void*,int,const void*,int,const void*)
){
  char const *zName8;
  sqlite3_value *pTmp;
  if( sqlite3SafetyCheck(db) ){
    return SQLITE_MISUSE;
  }
  pTmp = sqlite3GetTransientValue(db);
  sqlite3ValueSetStr(pTmp, -1, zName, SQLITE_UTF16NATIVE, SQLITE_STATIC);
  zName8 = sqlite3ValueText(pTmp, SQLITE_UTF8);
  return sqlite3_create_collation(db, zName8, enc, pCtx, xCompare);
}
Exemplo n.º 4
0
__declspec(dllexport) int WINAPI sqlite3_create_collation_interop(sqlite3* db, const char *zName, int eTextRep, void* pvUser, SQLITECOLLATION func, void **ppCookie)
{
  int n;
  SQLITECOLLATION *p = (SQLITECOLLATION *)malloc(sizeof(SQLITECOLLATION));
  
  p[0] = func;

  *ppCookie = 0;

  n = sqlite3_create_collation(db, zName, eTextRep, p, sqlite3_interop_collationfunc);
  if (n != 0)
    free(p);
  else
    *ppCookie = p;

  return n;
}
Exemplo n.º 5
0
/* {{{ bool SQLite::sqliteCreateCollation(string name, mixed callback)
   Registers a collation with the sqlite db handle */
static PHP_METHOD(SQLite, sqliteCreateCollation)
{
	struct pdo_sqlite_collation *collation;
	zval *callback;
	char *collation_name;
	size_t collation_name_len;
	zend_string *cbname = NULL;
	pdo_dbh_t *dbh;
	pdo_sqlite_db_handle *H;
	int ret;

	ZEND_PARSE_PARAMETERS_START(2, 2)
		Z_PARAM_STRING(collation_name, collation_name_len)
		Z_PARAM_ZVAL_DEREF(callback)
	ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);

	dbh = Z_PDO_DBH_P(getThis());
	PDO_CONSTRUCT_CHECK;

	if (!zend_is_callable(callback, 0, &cbname)) {
		php_error_docref(NULL, E_WARNING, "function '%s' is not callable", ZSTR_VAL(cbname));
		zend_string_release(cbname);
		RETURN_FALSE;
	}
	zend_string_release(cbname);

	H = (pdo_sqlite_db_handle *)dbh->driver_data;

	collation = (struct pdo_sqlite_collation*)ecalloc(1, sizeof(*collation));

	ret = sqlite3_create_collation(H->db, collation_name, SQLITE_UTF8, collation, php_sqlite3_collation_callback);
	if (ret == SQLITE_OK) {
		collation->name = estrdup(collation_name);

		ZVAL_COPY(&collation->callback, callback);

		collation->next = H->collations;
		H->collations = collation;

		RETURN_TRUE;
	}

	efree(collation);
	RETURN_FALSE;
}
Exemplo n.º 6
0
/* call-seq: db.collation(name, comparator)
 *
 * Add a collation with name +name+, and a +comparator+ object.  The
 * +comparator+ object should implement a method called "compare" that takes
 * two parameters and returns an integer less than, equal to, or greater than
 * 0.
 */
static VALUE collation(VALUE self, VALUE name, VALUE comparator)
{
  sqlite3RubyPtr ctx;
  Data_Get_Struct(self, sqlite3Ruby, ctx);
  REQUIRE_OPEN_DB(ctx);

  CHECK(ctx->db, sqlite3_create_collation(
        ctx->db,
        StringValuePtr(name),
        SQLITE_UTF8,
        (void *)comparator,
        NIL_P(comparator) ? NULL : rb_comparator_func));

  /* Make sure our comparator doesn't get garbage collected. */
  rb_hash_aset(rb_iv_get(self, "@collations"), name, comparator);

  return self;
}
int sqlite3_extension_init(
  sqlite3 *db,
  char **pzErrMsg,
  const sqlite3_api_routines *pApi
){
  const char *e_msg;
  int e_offset;
  //these global variables are required within callnumber.c
  re_is_cn = pcre_compile(P_IS_CN, 0, &e_msg, &e_offset, NULL);
  if (re_is_cn == NULL){
    printf("Error compiling P_IS_CN at character: %d\n. Message: %s\n", e_offset, e_msg);
    exit(1);
  }
  pe_is_cn = pcre_study(re_is_cn, 0, &e_msg);

  SQLITE_EXTENSION_INIT2(pApi)

  sqlite3_create_collation(db, "LCCN", SQLITE_UTF8, NULL, compare_callnumber_strings_sqlite);
  sqlite3_create_function(db, "NORMALIZE_LCCN", 1, SQLITE_UTF8, NULL, normalize_callnumber_sqlite, NULL, NULL);

  return 0;
}
Exemplo n.º 8
0
/**
 * Initializes database connection. This function creates all the temporary
 * tables used by the registry. It also registers the user functions and
 * collations declared here, making them available.
 *
 * @param [in] db      database to initialize
 * @param [out] errPtr on error, a description of the error that occurred
 * @return             true if success; false if failure
 */
int init_db(sqlite3* db, reg_error* errPtr) {
    static char* queries[] = {
        "BEGIN",

        /* items cache */
        "CREATE TEMPORARY TABLE items (refcount, proc UNIQUE, name, url, path, "
            "worker, options, variants)",

        /* indexes list */
        "CREATE TEMPORARY TABLE indexes (file, name, attached)",

        "COMMIT",
        NULL
    };

    /* I'm not error-checking these. I don't think I need to. */
    sqlite3_create_function(db, "REGEXP", 2, SQLITE_UTF8, NULL, sql_regexp,
            NULL, NULL);

    sqlite3_create_collation(db, "VERSION", SQLITE_UTF8, NULL, sql_version);

    return do_queries(db, queries, errPtr);
}
Exemplo n.º 9
0
/*
** This routine does the work of opening a database on behalf of
** sqlite3_open() and sqlite3_open16(). The database filename "zFilename"
** is UTF-8 encoded.
*/
static int openDatabase(
  const char *zFilename, /* Database filename UTF-8 encoded */
  sqlite3 **ppDb         /* OUT: Returned database handle */
){
  sqlite3 *db;
  int rc, i;

  /* Allocate the sqlite data structure */
  db = sqliteMalloc( sizeof(sqlite3) );
  if( db==0 ) goto opendb_out;
  db->priorNewRowid = 0;
  db->magic = SQLITE_MAGIC_BUSY;
  db->nDb = 2;
  db->aDb = db->aDbStatic;
  db->enc = SQLITE_UTF8;
  db->autoCommit = 1;
  db->flags |= SQLITE_ShortColNames;
  sqlite3HashInit(&db->aFunc, SQLITE_HASH_STRING, 0);
  sqlite3HashInit(&db->aCollSeq, SQLITE_HASH_STRING, 0);
  for(i=0; i<db->nDb; i++){
    sqlite3HashInit(&db->aDb[i].tblHash, SQLITE_HASH_STRING, 0);
    sqlite3HashInit(&db->aDb[i].idxHash, SQLITE_HASH_STRING, 0);
    sqlite3HashInit(&db->aDb[i].trigHash, SQLITE_HASH_STRING, 0);
    sqlite3HashInit(&db->aDb[i].aFKey, SQLITE_HASH_STRING, 1);
  }

  /* Add the default collation sequence BINARY. BINARY works for both UTF-8
  ** and UTF-16, so add a version for each to avoid any unnecessary
  ** conversions. The only error that can occur here is a malloc() failure.
  */
  if( sqlite3_create_collation(db, "BINARY", SQLITE_UTF8, 0,binCollFunc) ||
      sqlite3_create_collation(db, "BINARY", SQLITE_UTF16, 0,binCollFunc) ||
      !(db->pDfltColl = sqlite3FindCollSeq(db, db->enc, "BINARY", 6, 0)) ){
    rc = db->errCode;
    assert( rc!=SQLITE_OK );
    db->magic = SQLITE_MAGIC_CLOSED;
    goto opendb_out;
  }

  /* Also add a UTF-8 case-insensitive collation sequence. */
  sqlite3_create_collation(db, "NOCASE", SQLITE_UTF8, 0, nocaseCollatingFunc);

  /* Open the backend database driver */
  rc = sqlite3BtreeFactory(db, zFilename, 0, MAX_PAGES, &db->aDb[0].pBt);
  if( rc!=SQLITE_OK ){
    sqlite3Error(db, rc, 0);
    db->magic = SQLITE_MAGIC_CLOSED;
    goto opendb_out;
  }

  /* The default safety_level for the main database is 'full'; for the temp
  ** database it is 'NONE'. This matches the pager layer defaults.
  */
  db->aDb[0].zName = "main";
  db->aDb[0].safety_level = 3;
#ifndef SQLITE_OMIT_TEMPDB
  db->aDb[1].zName = "temp";
  db->aDb[1].safety_level = 1;
#endif


  /* Register all built-in functions, but do not attempt to read the
  ** database schema yet. This is delayed until the first time the database
  ** is accessed.
  */
  sqlite3RegisterBuiltinFunctions(db);
  sqlite3Error(db, SQLITE_OK, 0);
  db->magic = SQLITE_MAGIC_OPEN;

opendb_out:
  if( sqlite3_errcode(db)==SQLITE_OK && sqlite3_malloc_failed ){
    sqlite3Error(db, SQLITE_NOMEM, 0);
  }
  *ppDb = db;
#ifndef SQLITE_OMIT_GLOBALRECOVER
  if( db ){
    sqlite3OsEnterMutex();
    db->pNext = pDbList;
    pDbList = db;
    sqlite3OsLeaveMutex();
  }
#endif
  return sqlite3_errcode(db);
}
JNIEXPORT void JNICALL Java_com_couchbase_lite_android_SQLiteJsonCollator_nativeRegister
(JNIEnv *env, jclass cls, jobject sqliteDatabase, jstring sqliteDatabaseClassName, jint sdkVersion) {
    int (*sqlite3_create_collation)(sqlite3*,const char *,int,void *,int (*)(void*, int, const void*, int, const void*)) = NULL;
    void* handle = NULL;
    bool useSQLCipher = false;
    const char* cSqliteDatabaseClassName = env->GetStringUTFChars(sqliteDatabaseClassName, NULL);
    if (strcmp(cSqliteDatabaseClassName, "android/database/sqlite/SQLiteDatabase") == 0) {
        handle = dlopen("/system/lib/libsqlite.so", RTLD_LAZY);
    } else if (strcmp(cSqliteDatabaseClassName, "net/sqlcipher/database/SQLiteDatabase") == 0) {
        handle = dlopen("libsqlcipher_android.so", RTLD_LAZY);
        useSQLCipher = true;
    } else {
        LOGE("Unknown SQLiteDatabase Class Name");
        return;
    }
    
    *(void **)(&sqlite3_create_collation) = dlsym(handle, "sqlite3_create_collation");
    if(!sqlite3_create_collation) {
        LOGE("Failed to find sqlite3_create_collation: %s", dlerror());
        return;
    }
    
    // Find the SQLiteDatabase class:
    jclass clazz = env->FindClass(cSqliteDatabaseClassName);
    if (!clazz) {
        LOGE("Can't find SQLiteDatabase class");
        return;
    }
    env->ReleaseStringUTFChars(sqliteDatabaseClassName, cSqliteDatabaseClassName);
    
    bool useOldApi = useSQLCipher || sdkVersion < 16;
    
    // Find the field holding the sqlite3 handle:
    sqlite3 *sqliteHandle = NULL;
    if (useOldApi) {
        jfieldID offset_db_handle = env->GetFieldID(clazz, "mNativeHandle", "I");
        if (offset_db_handle == NULL) {
            LOGE("Can't find SQLiteDatabase.mNativeHandle\n");
            return;
        }
        sqliteHandle = (sqlite3 *)env->GetIntField(sqliteDatabase, offset_db_handle);
    } else {
        jfieldID offset_tl = env->GetFieldID(clazz, "mThreadSession", "Ljava/lang/ThreadLocal;");
        if(offset_tl == NULL) {
            LOGE("Can't find SQLiteDatabae.mThreadSession\n");
            return;
        }
        jobject tl = env->GetObjectField(sqliteDatabase, offset_tl);
        
        jclass tl_clazz = env->FindClass("java/lang/ThreadLocal");
        if (tl_clazz == NULL) {
            LOGE("Can't find java/lang/ThreadLocal\n");
            return;
        }
        
        jmethodID get_mid = env->GetMethodID(tl_clazz, "get", "()Ljava/lang/Object;");
        if (get_mid == NULL) {
            LOGE("Can't find ThreadLocal.get\n");
            return;
        }
        jobject session = env->CallObjectMethod(tl, get_mid);
        
        jclass sqls_clazz = env->FindClass("android/database/sqlite/SQLiteSession");
        if (sqls_clazz == NULL) {
            LOGE("Can't find android/database/sqlite/SQLiteSession\n");
            return;
        }
        
        jfieldID offset_mConnectionPool = env->GetFieldID(sqls_clazz, "mConnectionPool", "Landroid/database/sqlite/SQLiteConnectionPool;");
        if(offset_mConnectionPool == NULL) {
            LOGE("Can't find SQLiteSession.mConnectionPool");
            return;
        }
        jobject mcp = env->GetObjectField(session, offset_mConnectionPool);
        if(mcp == NULL) {
            LOGE("mConnectionPool was NULL");
            return;
        }
        
        jclass sqlcp_clazz = env->FindClass("android/database/sqlite/SQLiteConnectionPool");
        if (sqlcp_clazz == NULL) {
            LOGE("Can't find android/database/sqlite/SQLiteConnectionPool\n");
            return;
        }
        
        jfieldID offset_mMainConnection = env->GetFieldID(sqlcp_clazz, "mAvailablePrimaryConnection", "Landroid/database/sqlite/SQLiteConnection;");
        if(offset_mMainConnection == NULL) {
            LOGE("Can't find SQLiteConnectionPool.mAvailablePrimaryConnection");
            return;
        }
        
        jobject mc = env->GetObjectField(mcp, offset_mMainConnection);
        
        jclass sqlc_clazz = env->FindClass("android/database/sqlite/SQLiteConnection");
        if (sqlc_clazz == NULL) {
            LOGE("Can't find android/database/sqlite/SQLiteConnection\n");
            return;
        }
        
        SQLiteConnection *connection;
        
        // On Android-L and later, mConnectionPtr is a long
        jfieldID offset_db_handle = env->GetFieldID(sqlc_clazz, "mConnectionPtr", "J");
        if(offset_db_handle != NULL) {
            jlong connectionPtr = env->GetLongField(mc, offset_db_handle);
            connection = reinterpret_cast<SQLiteConnection*>(connectionPtr);
        } else {
            // trying to get mConnectionPtr as a long will cause an exception,
            // so we must clear it before doing anything else.
            env->ExceptionClear();
            
            // On previous versions of Android, it's, an int
            offset_db_handle = env->GetFieldID(sqlc_clazz, "mConnectionPtr", "I");
            
            jint connectionPtr = env->GetIntField(mc, offset_db_handle);
            
            connection = reinterpret_cast<SQLiteConnection*>(connectionPtr);
        }
        
        sqliteHandle = connection->db;
    }
    
    sqlite3_create_collation(sqliteHandle, "JSON", SQLITE_UTF8,
                             kJsonCollator_Unicode, CollateJSON);
    sqlite3_create_collation(sqliteHandle, "JSON_RAW", SQLITE_UTF8,
                             kJsonCollator_Raw, CollateJSON);
    sqlite3_create_collation(sqliteHandle, "JSON_ASCII", SQLITE_UTF8,
                             kJsonCollator_ASCII, CollateJSON);
}
JNIEXPORT void JNICALL Java_com_couchbase_touchdb_RevCollator_nativeRegister
  (JNIEnv *env, jclass cls, jobject sqliteDatabase, jint version) {
	int (*sqlite3_create_collation)(sqlite3*,const char *,int,void *,int (*)(void*, int, const void*, int, const void*)) = NULL;

	void* handle = dlopen("/system/lib/libsqlite.so", RTLD_LAZY);

	*(void **)(&sqlite3_create_collation) = dlsym(handle, "sqlite3_create_collation");
	if(!sqlite3_create_collation) {
		LOGE("Failed to find sqlite3_create_collation: %s", dlerror());
		return;
	}

	// find the SQLiteDatabase class
	jclass clazz = env->FindClass("android/database/sqlite/SQLiteDatabase");
	if (clazz == NULL) {
		LOGE("Can't find android/database/sqlite/SQLiteDatabase\n");
		return;
	}

	// find the field holding the handl
	sqlite3 * sqliteHandle;
	if(version < 16) {
		jfieldID offset_db_handle = env->GetFieldID(clazz, "mNativeHandle", "I");
		if (offset_db_handle == NULL) {
			LOGE("Can't find SQLiteDatabase.mNativeHandle\n");
			return;
		}
		sqliteHandle = (sqlite3 *)env->GetIntField(sqliteDatabase, offset_db_handle);
	} else {
		jfieldID offset_tl = env->GetFieldID(clazz, "mThreadSession", "Ljava/lang/ThreadLocal;");
		if(offset_tl == NULL) {
			LOGE("Can't find SQLiteDatabae.mThreadSession\n");
			return;
		}
		jobject tl = env->GetObjectField(sqliteDatabase, offset_tl);

		jclass tl_clazz = env->FindClass("java/lang/ThreadLocal");
		if (tl_clazz == NULL) {
			LOGE("Can't find java/lang/ThreadLocal\n");
			return;
		}

		jmethodID get_mid = env->GetMethodID(tl_clazz, "get", "()Ljava/lang/Object;");
		if (get_mid == NULL) {
		     LOGE("Can't find ThreadLocal.get\n");
		     return;
		}
		jobject session = env->CallObjectMethod(tl, get_mid);

		jclass sqls_clazz = env->FindClass("android/database/sqlite/SQLiteSession");
		if (sqls_clazz == NULL) {
			LOGE("Can't find android/database/sqlite/SQLiteSession\n");
			return;
		}

		jfieldID offset_mConnectionPool = env->GetFieldID(sqls_clazz, "mConnectionPool", "Landroid/database/sqlite/SQLiteConnectionPool;");
		if(offset_mConnectionPool == NULL) {
			LOGE("Can't find SQLiteSession.mConnectionPool");
			return;
		}
		jobject mcp = env->GetObjectField(session, offset_mConnectionPool);
		if(mcp == NULL) {
			LOGE("mConnectionPool was NULL");
			return;
		}

		jclass sqlcp_clazz = env->FindClass("android/database/sqlite/SQLiteConnectionPool");
		if (sqlcp_clazz == NULL) {
			LOGE("Can't find android/database/sqlite/SQLiteConnectionPool\n");
			return;
		}

		jfieldID offset_mMainConnection = env->GetFieldID(sqlcp_clazz, "mAvailablePrimaryConnection", "Landroid/database/sqlite/SQLiteConnection;");
		if(offset_mMainConnection == NULL) {
			LOGE("Can't find SQLiteConnectionPool.mAvailablePrimaryConnection");
			return;
		}

		jobject mc = env->GetObjectField(mcp, offset_mMainConnection);

		jclass sqlc_clazz = env->FindClass("android/database/sqlite/SQLiteConnection");
		if (sqlc_clazz == NULL) {
			LOGE("Can't find android/database/sqlite/SQLiteConnection\n");
			return;
		}

        SQLiteConnection* connection;

        // On Android-L and later, mConnectionPtr is a long
		jfieldID offset_db_handle = env->GetFieldID(sqlc_clazz, "mConnectionPtr", "J");
		if(offset_db_handle != NULL) {

            jlong connectionPtr = env->GetLongField(mc, offset_db_handle);
            connection = reinterpret_cast<SQLiteConnection*>(connectionPtr);

		} else {

          // trying to get mConnectionPtr as a long will cause an exception,
          // so we must clear it before doing anything else.
          env->ExceptionClear();

		  // On previous versions of Android, it's, an int
		  offset_db_handle = env->GetFieldID(sqlc_clazz, "mConnectionPtr", "I");

          jint connectionPtr = env->GetIntField(mc, offset_db_handle);

          connection = reinterpret_cast<SQLiteConnection*>(connectionPtr);

		}

		sqliteHandle = connection->db;
	}

	// Install a custom collator
	sqlite3_create_collation(sqliteHandle, "REVID", SQLITE_UTF8, NULL, collateRevIDs);
}
Exemplo n.º 12
0
svn_error_t *
svn_sqlite__open(svn_sqlite__db_t **db, const char *path,
                 svn_sqlite__mode_t mode, const char * const statements[],
                 int unused1, const char * const *unused2,
                 apr_int32_t timeout,
                 apr_pool_t *result_pool, apr_pool_t *scratch_pool)
{
  SVN_ERR(svn_atomic__init_once(&sqlite_init_state,
                                init_sqlite, NULL, scratch_pool));

  *db = apr_pcalloc(result_pool, sizeof(**db));

  SVN_ERR(internal_open(*db, path, mode, timeout, scratch_pool));

#if SQLITE_VERSION_NUMBER >= 3008000 && SQLITE_VERSION_NUMBER < 3009000
  /* disable SQLITE_ENABLE_STAT3/4 from 3.8.1 - 3.8.3 (but not 3.8.3.1+)
   * to prevent using it when it's buggy.
   * See: https://www.sqlite.org/src/info/4c86b126f2 */
  if (sqlite3_libversion_number() > 3008000 &&
      sqlite3_libversion_number() < 3008004 &&
      strcmp(sqlite3_sourceid(),"2014-02-11")<0)
    {
      sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS, (*db)->db3, 0x800);
    }
#endif

#ifdef SVN_UNICODE_NORMALIZATION_FIXES
  /* Create extension buffers with space for 200 UCS-4 characters. */
  svn_membuf__create(&(*db)->sqlext_buf1, 800, result_pool);
  svn_membuf__create(&(*db)->sqlext_buf2, 800, result_pool);
  svn_membuf__create(&(*db)->sqlext_buf3, 800, result_pool);

  /* Register collation and LIKE and GLOB operator replacements. */
  SQLITE_ERR_CLOSE(sqlite3_create_collation((*db)->db3,
                                            "svn-ucs-nfd", SQLITE_UTF8,
                                            *db, collate_ucs_nfd),
                   db, scratch_pool);
  /* ### Is it really necessary to override these functions?
         I would assume the default implementation to be collation agnostic?
         And otherwise our implementation should be...

         The default implementation is in some cases index backed, while our
         implementation can't be. With an index based on the collation it could
         be. */
  SQLITE_ERR_CLOSE(sqlite3_create_function((*db)->db3, "glob", 2,
                                           SQLITE_UTF8 | SQLITE_DETERMINISTIC,
                                           *db, glob_ucs_nfd, NULL, NULL),
                   db, scratch_pool);
  SQLITE_ERR_CLOSE(sqlite3_create_function((*db)->db3, "like", 2,
                                           SQLITE_UTF8 | SQLITE_DETERMINISTIC,
                                           *db, like_ucs_nfd, NULL, NULL),
                   db, scratch_pool);
  SQLITE_ERR_CLOSE(sqlite3_create_function((*db)->db3, "like", 3,
                                           SQLITE_UTF8 | SQLITE_DETERMINISTIC,
                                           *db, like_ucs_nfd, NULL, NULL),
                   db, scratch_pool);
#endif /* SVN_UNICODE_NORMALIZATION_FIXES */

#ifdef SQLITE3_DEBUG
  sqlite3_trace((*db)->db3, sqlite_tracer, (*db)->db3);
#endif
#ifdef SQLITE3_PROFILE
  sqlite3_profile((*db)->db3, sqlite_profiler, (*db)->db3);
#endif

  SVN_ERR_CLOSE(exec_sql(*db,
              /* The default behavior of the LIKE operator is to ignore case
                 for ASCII characters. Hence, by default 'a' LIKE 'A' is true.
                 The case_sensitive_like pragma installs a new application-
                 defined LIKE function that is either case sensitive or
                 insensitive depending on the value of the case_sensitive_like
                 pragma. */
              "PRAGMA case_sensitive_like=1;"
              /* Disable synchronization to disable the explicit disk flushes
                 that make Sqlite up to 50 times slower; especially on small
                 transactions.

                 This removes some stability guarantees on specific hardware
                 and power failures, but still guarantees atomic commits on
                 application crashes. With our dependency on external data
                 like pristine files (Wc) and revision files (repository),
                 we can't keep up these additional guarantees anyway.

                 ### Maybe switch to NORMAL(1) when we use larger transaction
                     scopes */
              "PRAGMA synchronous=OFF;"
              /* Enable recursive triggers so that a user trigger will fire
                 in the deletion phase of an INSERT OR REPLACE statement.
                 Requires SQLite >= 3.6.18  */
              "PRAGMA recursive_triggers=ON;"
              /* Enforce current Sqlite default behavior. Some distributions
                 might change the Sqlite defaults without realizing how this
                 affects application(read: Subversion) performance/behavior. */
              "PRAGMA foreign_keys=OFF;"      /* SQLITE_DEFAULT_FOREIGN_KEYS*/
              "PRAGMA locking_mode = NORMAL;" /* SQLITE_DEFAULT_LOCKING_MODE */
              /* Testing shows TRUNCATE is faster than DELETE on Windows. */
              "PRAGMA journal_mode = TRUNCATE;"
              ),
                *db);

#if defined(SVN_DEBUG)
  /* When running in debug mode, enable the checking of foreign key
     constraints.  This has possible performance implications, so we don't
     bother to do it for production...for now. */
  SVN_ERR_CLOSE(exec_sql(*db, "PRAGMA foreign_keys=ON;"),
                *db);
#endif

#ifdef SVN_SQLITE_REVERSE_UNORDERED_SELECTS
  /* When enabled, this PRAGMA causes SELECT statements without an ORDER BY
     clause to emit their results in the reverse order of what they normally
     would.  This can help detecting invalid assumptions about the result
     order.*/
  SVN_ERR_CLOSE(exec_sql(*db, "PRAGMA reverse_unordered_selects=ON;"),
                *db);
#endif

  /* Store temporary tables in RAM instead of in temporary files, but don't
     fail on this if this option is disabled in the sqlite compilation by
     setting SQLITE_TEMP_STORE to 0 (always to disk) */
  svn_error_clear(exec_sql(*db, "PRAGMA temp_store = MEMORY;"));

  /* Store the provided statements. */
  if (statements)
    {
      (*db)->statement_strings = statements;
      (*db)->nbr_statements = 0;
      while (*statements != NULL)
        {
          statements++;
          (*db)->nbr_statements++;
        }

      (*db)->prepared_stmts = apr_pcalloc(
                                  result_pool,
                                  ((*db)->nbr_statements + STMT_INTERNAL_LAST)
                                                * sizeof(svn_sqlite__stmt_t *));
    }
  else
    {
      (*db)->nbr_statements = 0;
      (*db)->prepared_stmts = apr_pcalloc(result_pool,
                                          (0 + STMT_INTERNAL_LAST)
                                                * sizeof(svn_sqlite__stmt_t *));
    }

  (*db)->state_pool = result_pool;
  apr_pool_cleanup_register(result_pool, *db, close_apr, apr_pool_cleanup_null);

  return SVN_NO_ERROR;
}
// Init method.
void sqlite_json_collator_init(sqlite3 * db, int (*unicode_string_compare)(const char *, const char*)) {
    uca_string_compare = unicode_string_compare;
	sqlite3_create_collation(db, "JSON", SQLITE_UTF8, sqlite_json_colator_Unicode, collateJSON);
	sqlite3_create_collation(db, "JSON_RAW", SQLITE_UTF8, sqlite_json_colator_Raw, collateJSON);
	sqlite3_create_collation(db, "JSON_ASCII", SQLITE_UTF8, sqlite_json_colator_ASCII, collateJSON);
}