Author: brane Date: Mon Nov 12 15:36:47 2012 New Revision: 1408325 URL: http://svn.apache.org/viewvc?rev=1408325&view=rev Log: On the wc-collate-path branch: Enable GLOB and LIKE operator replacements.
* subversion/libsvn_subr/sqlite.c (SQLITE_MAX_LIKE_PATTERN_LENGTH): Limit the pattern lengths. (svn_sqlite__db_t): Add third buffer, sqlext_buf3, for glob/like; (glob_like_ucs_nfd_common): Common wrapper for svn_utf__glob. (glob_ucs_nfd, like_ucs_nfd): GLOB and LIKE user functions. (svn_sqlite__open): Initialize all sqlext_* buffers to 800 bytes. Register GLOB and LIKE operator replacements. Modified: subversion/branches/wc-collate-path/subversion/libsvn_subr/sqlite.c Modified: subversion/branches/wc-collate-path/subversion/libsvn_subr/sqlite.c URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_subr/sqlite.c?rev=1408325&r1=1408324&r2=1408325&view=diff ============================================================================== --- subversion/branches/wc-collate-path/subversion/libsvn_subr/sqlite.c (original) +++ subversion/branches/wc-collate-path/subversion/libsvn_subr/sqlite.c Mon Nov 12 15:36:47 2012 @@ -57,6 +57,11 @@ extern const sqlite3_api_routines *const #error SQLite is too old -- version 3.7.12 is the minimum required version #endif +/* Limit the length of a GLOB or LIKE pattern. */ +#ifndef SQLITE_MAX_LIKE_PATTERN_LENGTH +# define SQLITE_MAX_LIKE_PATTERN_LENGTH 50000 +#endif + const char * svn_sqlite__compiled_version(void) { @@ -105,6 +110,7 @@ struct svn_sqlite__db_t /* Buffers for SQLite extensoins. */ svn_stringbuf_t *sqlext_buf1; svn_stringbuf_t *sqlext_buf2; + svn_stringbuf_t *sqlext_buf3; }; struct svn_sqlite__stmt_t @@ -881,6 +887,74 @@ collate_ucs_nfd(void *baton, return result; } +static void +glob_like_ucs_nfd_common(sqlite3_context *context, + int argc, sqlite3_value **argv, + svn_boolean_t sql_like) +{ + svn_sqlite__db_t *const db = sqlite3_user_data(context); + + const char *const pattern = (void*)sqlite3_value_text(argv[0]); + const apr_size_t pattern_len = sqlite3_value_bytes(argv[0]); + const char *const string = (void*)sqlite3_value_text(argv[1]); + const apr_size_t string_len = sqlite3_value_bytes(argv[1]); + + const char *escape = NULL; + apr_size_t escape_len = 0; + + svn_boolean_t match; + svn_error_t *err; + + if (pattern_len > SQLITE_MAX_LIKE_PATTERN_LENGTH) + { + sqlite3_result_error(context, "LIKE or GLOB pattern too complex", -1); + return; + } + + if (argc == 3 && sql_like) + { + escape = (void*)sqlite3_value_text(argv[2]); + escape_len = sqlite3_value_bytes(argv[2]); + } + + if (pattern && string) + { + err = svn_utf__glob(pattern, pattern_len, string, string_len, + escape, escape_len, sql_like, + db->sqlext_buf1, db->sqlext_buf2, db->sqlext_buf3, + &match); + + if (err) + { + const char *errmsg; + svn_stringbuf_ensure(db->sqlext_buf1, 511); + errmsg = svn_err_best_message(err, + db->sqlext_buf1->data, + db->sqlext_buf1->blocksize); + svn_error_clear(err); + sqlite3_result_error(context, errmsg, -1); + return; + } + + sqlite3_result_int(context, match); + } +} + +/* Unicode normalizing implementation of GLOB */ +static void +glob_ucs_nfd(sqlite3_context *context, + int argc, sqlite3_value **argv) +{ + glob_like_ucs_nfd_common(context, argc, argv, FALSE); +} + +/* Unicode normalizing implementation of LIKE */ +static void +like_ucs_nfd(sqlite3_context *context, + int argc, sqlite3_value **argv) +{ + glob_like_ucs_nfd_common(context, argc, argv, TRUE); +} svn_error_t * svn_sqlite__open(svn_sqlite__db_t **db, const char *path, @@ -895,12 +969,25 @@ svn_sqlite__open(svn_sqlite__db_t **db, SVN_ERR(internal_open(&(*db)->db3, path, mode, scratch_pool)); - (*db)->sqlext_buf1 = svn_stringbuf_create_ensure(4096, result_pool); - (*db)->sqlext_buf2 = svn_stringbuf_create_ensure(4096, result_pool); + /* Create extension buffers with space for 200 UCS-4 characters. */ + (*db)->sqlext_buf1 = svn_stringbuf_create_ensure(799, result_pool); + (*db)->sqlext_buf2 = svn_stringbuf_create_ensure(799, result_pool); + (*db)->sqlext_buf3 = svn_stringbuf_create_ensure(799, result_pool); + + /* Register collation and LIKE and GLOB operator replacements. */ SQLITE_ERR(sqlite3_create_collation((*db)->db3, "svn-ucs-nfd", SQLITE_UTF8, *db, collate_ucs_nfd), *db); + SQLITE_ERR(sqlite3_create_function((*db)->db3, "glob", 2, SQLITE_UTF8, + *db, glob_ucs_nfd, NULL, NULL), + *db); + SQLITE_ERR(sqlite3_create_function((*db)->db3, "like", 2, SQLITE_UTF8, + *db, like_ucs_nfd, NULL, NULL), + *db); + SQLITE_ERR(sqlite3_create_function((*db)->db3, "like", 3, SQLITE_UTF8, + *db, like_ucs_nfd, NULL, NULL), + *db); #ifdef SQLITE3_DEBUG sqlite3_trace((*db)->db3, sqlite_tracer, (*db)->db3);