File indexing completed on 2024-05-12 04:41:30
0001 /* This file is part of the KDE project 0002 Copyright (C) 2015 Jarosław Staniek <staniek@kde.org> 0003 0004 Contains portions of sqlite3.c licensed under public domain. The author disclaims 0005 copyright to this source code. 0006 0007 This program is free software; you can redistribute it and/or 0008 modify it under the terms of the GNU Library General Public 0009 License as published by the Free Software Foundation; either 0010 version 2 of the License, or (at your option) any later version. 0011 0012 This program is distributed in the hope that it will be useful, 0013 but WITHOUT ANY WARRANTY; without even the implied warranty of 0014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0015 Library General Public License for more details. 0016 0017 You should have received a copy of the GNU Library General Public License 0018 along with this program; see the file COPYING. If not, write to 0019 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0020 * Boston, MA 02110-1301, USA. 0021 */ 0022 0023 #include "SqliteFunctions.h" 0024 0025 #include <QDebug> 0026 0027 #include <cctype> 0028 0029 /* 0030 ** Integers of known sizes. These typedefs might change for architectures 0031 ** where the sizes very. Preprocessor macros are available so that the 0032 ** types can be conveniently redefined at compile-type. Like this: 0033 ** 0034 ** cc '-DUINTPTR_TYPE=long long int' ... 0035 */ 0036 #ifndef UINT32_TYPE 0037 # ifdef HAVE_UINT32_T 0038 # define UINT32_TYPE uint32_t 0039 # else 0040 # define UINT32_TYPE unsigned int 0041 # endif 0042 #endif 0043 #ifndef UINT16_TYPE 0044 # ifdef HAVE_UINT16_T 0045 # define UINT16_TYPE uint16_t 0046 # else 0047 # define UINT16_TYPE unsigned short int 0048 # endif 0049 #endif 0050 #ifndef INT16_TYPE 0051 # ifdef HAVE_INT16_T 0052 # define INT16_TYPE int16_t 0053 # else 0054 # define INT16_TYPE short int 0055 # endif 0056 #endif 0057 #ifndef UINT8_TYPE 0058 # ifdef HAVE_UINT8_T 0059 # define UINT8_TYPE uint8_t 0060 # else 0061 # define UINT8_TYPE unsigned char 0062 # endif 0063 #endif 0064 #ifndef INT8_TYPE 0065 # ifdef HAVE_INT8_T 0066 # define INT8_TYPE int8_t 0067 # else 0068 # define INT8_TYPE signed char 0069 # endif 0070 #endif 0071 #ifndef LONGDOUBLE_TYPE 0072 # define LONGDOUBLE_TYPE long double 0073 #endif 0074 typedef sqlite_int64 i64; /* 8-byte signed integer */ 0075 typedef sqlite_uint64 u64; /* 8-byte unsigned integer */ 0076 typedef UINT32_TYPE u32; /* 4-byte unsigned integer */ 0077 typedef UINT16_TYPE u16; /* 2-byte unsigned integer */ 0078 typedef INT16_TYPE i16; /* 2-byte signed integer */ 0079 typedef UINT8_TYPE u8; /* 1-byte unsigned integer */ 0080 typedef INT8_TYPE i8; /* 1-byte signed integer */ 0081 0082 static bool tryExec(sqlite3 *db, const char *sql) 0083 { 0084 return SQLITE_OK == sqlite3_exec(db, sql, nullptr /*callback*/, 0085 nullptr /* 1st argument to callback */, nullptr /*err*/); 0086 } 0087 0088 // BEGIN from sqlite3.c 0089 #define sqlite3Toupper(x) toupper((unsigned char)(x)) 0090 #define sqlite3Isalpha(x) isalpha((unsigned char)(x)) 0091 0092 /* 0093 ** Compute the soundex encoding of a word. 0094 ** 0095 ** IMP: R-59782-00072 The soundex(X) function returns a string that is the 0096 ** soundex encoding of the string X. 0097 */ 0098 static void soundexFunc( 0099 sqlite3_context *context, 0100 int argc, 0101 sqlite3_value **argv 0102 ){ 0103 char zResult[8]; 0104 const u8 *zIn; 0105 int i, j; 0106 static const unsigned char iCode[] = { 0107 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0108 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0109 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0110 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0111 0, 0, 1, 2, 3, 0, 1, 2, 0, 0, 2, 2, 4, 5, 5, 0, 0112 1, 2, 6, 2, 3, 0, 1, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0113 0, 0, 1, 2, 3, 0, 1, 2, 0, 0, 2, 2, 4, 5, 5, 0, 0114 1, 2, 6, 2, 3, 0, 1, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0115 }; 0116 assert( argc==1 ); 0117 zIn = (u8*)sqlite3_value_text(argv[0]); 0118 if( zIn==0 ) zIn = (u8*)""; 0119 for(i=0; zIn[i] && !sqlite3Isalpha(zIn[i]); i++){} 0120 if( zIn[i] ){ 0121 u8 prevcode = iCode[zIn[i]&0x7f]; 0122 zResult[0] = sqlite3Toupper(zIn[i]); 0123 for(j=1; j<4 && zIn[i]; i++){ 0124 int code = iCode[zIn[i]&0x7f]; 0125 if( code>0 ){ 0126 if( code!=prevcode ){ 0127 prevcode = code; 0128 zResult[j++] = code + '0'; 0129 } 0130 }else{ 0131 prevcode = 0; 0132 } 0133 } 0134 while( j<4 ){ 0135 zResult[j++] = '0'; 0136 } 0137 zResult[j] = 0; 0138 sqlite3_result_text(context, zResult, 4, SQLITE_TRANSIENT); 0139 }else{ 0140 /* IMP: R-64894-50321 The string "?000" is returned if the argument 0141 ** is NULL or contains no ASCII alphabetic characters. */ 0142 sqlite3_result_text(context, "?000", 4, SQLITE_STATIC); 0143 } 0144 } 0145 0146 bool createCustomSQLiteFunctions(sqlite3 *db) 0147 { 0148 int eTextRep = SQLITE_UTF8; 0149 #if SQLITE_VERSION_NUMBER >= 3008003 0150 eTextRep |= SQLITE_DETERMINISTIC; 0151 #endif 0152 if (!tryExec(db, "SELECT SOUNDEX()")) { 0153 int res = sqlite3_create_function_v2( 0154 db, 0155 "SOUNDEX", 0156 1, //nArg 0157 eTextRep, 0158 nullptr, // pApp 0159 soundexFunc, 0160 nullptr, // xStep 0161 nullptr, // xFinal 0162 nullptr // xDestroy 0163 ); 0164 if (res != SQLITE_OK) { 0165 return false; 0166 } 0167 } 0168 return true; 0169 } 0170 0171 // END from sqlite3.c