33#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ICU)
36#include <unicode/utypes.h>
37#include <unicode/uregex.h>
38#include <unicode/ustring.h>
39#include <unicode/ucol.h>
40#include <unicode/uvernum.h>
41#if U_ICU_VERSION_MAJOR_NUM>=51
42#include <unicode/utf_old.h>
48 #include "sqlite3ext.h"
49 SQLITE_EXTENSION_INIT1
58#ifndef SQLITE_MAX_LIKE_PATTERN_LENGTH
59# define SQLITE_MAX_LIKE_PATTERN_LENGTH 50000
65static void xFree(
void *p){
74static int icuLikeCompare(
75 const uint8_t *zPattern,
76 const uint8_t *zString,
79 static const int MATCH_ONE = (UChar32)
'_';
80 static const int MATCH_ALL = (UChar32)
'%';
87 while( zPattern[iPattern]!=0 ){
91 U8_NEXT_UNSAFE(zPattern, iPattern, uPattern);
101 if( !prevEscape && uPattern==MATCH_ALL ){
109 while( (c=zPattern[iPattern]) == MATCH_ALL || c == MATCH_ONE ){
111 if( zString[iString]==0 )
return 0;
112 U8_FWD_1_UNSAFE(zString, iString);
117 if( zPattern[iPattern]==0 )
return 1;
119 while( zString[iString] ){
120 if( icuLikeCompare(&zPattern[iPattern], &zString[iString], uEsc) ){
123 U8_FWD_1_UNSAFE(zString, iString);
127 }
else if( !prevEscape && uPattern==MATCH_ONE ){
129 if( zString[iString]==0 )
return 0;
130 U8_FWD_1_UNSAFE(zString, iString);
132 }
else if( !prevEscape && uPattern==uEsc){
139 U8_NEXT_UNSAFE(zString, iString, uString);
140 uString = u_foldCase(uString, U_FOLD_CASE_DEFAULT);
141 uPattern = u_foldCase(uPattern, U_FOLD_CASE_DEFAULT);
142 if( uString!=uPattern ){
149 return zString[iString]==0;
165static void icuLikeFunc(
166 sqlite3_context *context,
170 const unsigned char *zA = sqlite3_value_text(argv[0]);
171 const unsigned char *zB = sqlite3_value_text(argv[1]);
177 if( sqlite3_value_bytes(argv[0])>SQLITE_MAX_LIKE_PATTERN_LENGTH ){
178 sqlite3_result_error(context,
"LIKE or GLOB pattern too complex", -1);
187 int nE= sqlite3_value_bytes(argv[2]);
188 const unsigned char *zE = sqlite3_value_text(argv[2]);
190 if( zE==
nullptr )
return;
191 U8_NEXT(zE, i, nE, uEsc);
193 sqlite3_result_error(context,
194 "ESCAPE expression must be a single character", -1);
200 sqlite3_result_int(context, icuLikeCompare(zA, zB, uEsc));
211static void icuFunctionError(
212 sqlite3_context *pCtx,
217 sqlite3_snprintf(128, zBuf,
"ICU error: %s(): %s", zName, u_errorName(e));
219 sqlite3_result_error(pCtx, zBuf, -1);
226static void icuRegexpDelete(
void *p){
227 URegularExpression *pExpr = (URegularExpression *)p;
250static void icuRegexpFunc(sqlite3_context *p,
int nArg, sqlite3_value **apArg){
251 UErrorCode
status = U_ZERO_ERROR;
252 URegularExpression *pExpr;
254 const UChar *zString =
static_cast<const UChar *
>(sqlite3_value_text16(apArg[1]));
265 pExpr =
static_cast<URegularExpression*
>(sqlite3_get_auxdata(p, 0));
267 const UChar *zPattern =
static_cast<const UChar *
>(sqlite3_value_text16(apArg[0]));
271 pExpr = uregex_open(zPattern, -1, 0,
nullptr, &
status);
274 sqlite3_set_auxdata(p, 0, pExpr, icuRegexpDelete);
277 icuFunctionError(p,
"uregex_open",
status);
283 uregex_setText(pExpr, zString, -1, &
status);
285 icuFunctionError(p,
"uregex_setText",
status);
290 res = uregex_matches(pExpr, 0, &
status);
292 icuFunctionError(p,
"uregex_matches",
status);
301 uregex_setText(pExpr,
nullptr, 0, &
status);
304 sqlite3_result_int(p, res ? 1 : 0);
333static void icuCaseFunc16(sqlite3_context *p,
int nArg, sqlite3_value **apArg){
339 UErrorCode
status = U_ZERO_ERROR;
340 const unsigned char *zLocale =
nullptr;
342 assert(nArg==1 || nArg==2);
344 zLocale =
static_cast<const unsigned char *
>(sqlite3_value_text(apArg[1]));
347 zInput =
static_cast<const UChar *
>(sqlite3_value_text16(apArg[0]));
351 nInput = sqlite3_value_bytes16(apArg[0]);
353 nOutput = nInput * 2 + 2;
354 zOutput =
static_cast<UChar *
>(sqlite3_malloc(nOutput));
359 if( sqlite3_user_data(p) ){
360 u_strToUpper(zOutput, nOutput/2, zInput, nInput/2,
reinterpret_cast<const char*
>(zLocale), &
status);
362 u_strToLower(zOutput, nOutput/2, zInput, nInput/2,
reinterpret_cast<const char*
>(zLocale), &
status);
366 icuFunctionError(p,
"u_strToLower()/u_strToUpper",
status);
370 sqlite3_result_text16(p, zOutput, -1, xFree);
377static void icuCollationDel(
void *pCtx){
378 UCollator *p = (UCollator *)pCtx;
386static int icuCollationColl(
393 UCollationResult res;
394 UCollator *p = (UCollator *)pCtx;
395 res = ucol_strcoll(p, (UChar *)zLeft, nLeft/2, (UChar *)zRight, nRight/2);
397 case UCOL_LESS:
return -1;
398 case UCOL_GREATER:
return +1;
399 case UCOL_EQUAL:
return 0;
401 assert(!
"Unexpected return value from ucol_strcoll()");
418static void icuLoadCollation(
421 sqlite3_value **apArg
425 sqlite3 *db = (sqlite3 *)sqlite3_user_data(p);
426 UErrorCode
status = U_ZERO_ERROR;
429 UCollator *pUCollator;
433 zLocale = (
const char *)sqlite3_value_text(apArg[0]);
434 zName = (
const char *)sqlite3_value_text(apArg[1]);
436 if( !zLocale || !zName ){
440 pUCollator = ucol_open(zLocale, &
status);
442 icuFunctionError(p,
"ucol_open",
status);
447 rc = sqlite3_create_collation_v2(db, zName, SQLITE_UTF16, (
void *)pUCollator,
448 icuCollationColl, icuCollationDel
451 ucol_close(pUCollator);
452 sqlite3_result_error(p,
"Error registering collation function", -1);
459KDB_SQLITE_ICU_EXPORT
int sqlite3IcuInit(sqlite3 *db){
465 void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
467 {
"regexp", 2, SQLITE_ANY,
nullptr, icuRegexpFunc},
469 {
"lower", 1, SQLITE_UTF16,
nullptr, icuCaseFunc16},
470 {
"lower", 2, SQLITE_UTF16,
nullptr, icuCaseFunc16},
471 {
"upper", 1, SQLITE_UTF16, (
void*)1, icuCaseFunc16},
472 {
"upper", 2, SQLITE_UTF16, (
void*)1, icuCaseFunc16},
474 {
"lower", 1, SQLITE_UTF8,
nullptr, icuCaseFunc16},
475 {
"lower", 2, SQLITE_UTF8,
nullptr, icuCaseFunc16},
476 {
"upper", 1, SQLITE_UTF8, (
void*)1, icuCaseFunc16},
477 {
"upper", 2, SQLITE_UTF8, (
void*)1, icuCaseFunc16},
479 {
"like", 2, SQLITE_UTF8,
nullptr, icuLikeFunc},
480 {
"like", 3, SQLITE_UTF8,
nullptr, icuLikeFunc},
482 {
"icu_load_collation", 2, SQLITE_UTF8, (
void*)db, icuLoadCollation},
488 for(i=0; rc==SQLITE_OK && i<(int)(
sizeof(scalars)/
sizeof(scalars[0])); i++){
489 struct IcuScalar *p = &scalars[i];
490 rc = sqlite3_create_function(
491 db, p->zName, p->nArg, p->enc, p->pContext, p->xFunc,
nullptr,
nullptr
498#if !defined SQLITE_CORE || !SQLITE_CORE
499KDB_SQLITE_ICU_EXPORT
int sqlite3_extension_init(
502 const struct sqlite3_api_routines *pApi
505 SQLITE_EXTENSION_INIT2(pApi)
506 return sqlite3IcuInit(db);
Q_SCRIPTABLE CaptureState status()