annotate sqlite/func.c @ 1621:fae6e0cfcc77 trunk

[svn] - Reapply r2161
author nhjm449
date Tue, 05 Sep 2006 19:57:18 -0700
parents b6b61becdf4e
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1434
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1 /*
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
2 ** 2002 February 23
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
3 **
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
4 ** The author disclaims copyright to this source code. In place of
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
5 ** a legal notice, here is a blessing:
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
6 **
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
7 ** May you do good and not evil.
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
8 ** May you find forgiveness for yourself and forgive others.
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
9 ** May you share freely, never taking more than you give.
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
10 **
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
11 *************************************************************************
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
12 ** This file contains the C functions that implement various SQL
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
13 ** functions of SQLite.
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
14 **
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
15 ** There is only one exported symbol in this file - the function
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
16 ** sqliteRegisterBuildinFunctions() found at the bottom of the file.
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
17 ** All other code has file scope.
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
18 **
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
19 ** $Id: func.c,v 1.128 2006/05/11 13:25:39 drh Exp $
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
20 */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
21 #include "sqliteInt.h"
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
22 #include <ctype.h>
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
23 /* #include <math.h> */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
24 #include <stdlib.h>
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
25 #include <assert.h>
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
26 #include "vdbeInt.h"
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
27 #include "os.h"
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
28
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
29 /*
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
30 ** Return the collating function associated with a function.
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
31 */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
32 static CollSeq *sqlite3GetFuncCollSeq(sqlite3_context *context){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
33 return context->pColl;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
34 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
35
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
36 /*
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
37 ** Implementation of the non-aggregate min() and max() functions
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
38 */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
39 static void minmaxFunc(
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
40 sqlite3_context *context,
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
41 int argc,
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
42 sqlite3_value **argv
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
43 ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
44 int i;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
45 int mask; /* 0 for min() or 0xffffffff for max() */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
46 int iBest;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
47 CollSeq *pColl;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
48
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
49 if( argc==0 ) return;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
50 mask = sqlite3_user_data(context)==0 ? 0 : -1;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
51 pColl = sqlite3GetFuncCollSeq(context);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
52 assert( pColl );
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
53 assert( mask==-1 || mask==0 );
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
54 iBest = 0;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
55 if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
56 for(i=1; i<argc; i++){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
57 if( sqlite3_value_type(argv[i])==SQLITE_NULL ) return;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
58 if( (sqlite3MemCompare(argv[iBest], argv[i], pColl)^mask)>=0 ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
59 iBest = i;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
60 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
61 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
62 sqlite3_result_value(context, argv[iBest]);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
63 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
64
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
65 /*
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
66 ** Return the type of the argument.
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
67 */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
68 static void typeofFunc(
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
69 sqlite3_context *context,
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
70 int argc,
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
71 sqlite3_value **argv
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
72 ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
73 const char *z = 0;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
74 switch( sqlite3_value_type(argv[0]) ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
75 case SQLITE_NULL: z = "null"; break;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
76 case SQLITE_INTEGER: z = "integer"; break;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
77 case SQLITE_TEXT: z = "text"; break;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
78 case SQLITE_FLOAT: z = "real"; break;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
79 case SQLITE_BLOB: z = "blob"; break;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
80 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
81 sqlite3_result_text(context, z, -1, SQLITE_STATIC);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
82 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
83
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
84
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
85 /*
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
86 ** Implementation of the length() function
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
87 */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
88 static void lengthFunc(
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
89 sqlite3_context *context,
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
90 int argc,
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
91 sqlite3_value **argv
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
92 ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
93 int len;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
94
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
95 assert( argc==1 );
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
96 switch( sqlite3_value_type(argv[0]) ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
97 case SQLITE_BLOB:
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
98 case SQLITE_INTEGER:
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
99 case SQLITE_FLOAT: {
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
100 sqlite3_result_int(context, sqlite3_value_bytes(argv[0]));
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
101 break;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
102 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
103 case SQLITE_TEXT: {
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
104 const unsigned char *z = sqlite3_value_text(argv[0]);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
105 for(len=0; *z; z++){ if( (0xc0&*z)!=0x80 ) len++; }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
106 sqlite3_result_int(context, len);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
107 break;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
108 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
109 default: {
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
110 sqlite3_result_null(context);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
111 break;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
112 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
113 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
114 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
115
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
116 /*
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
117 ** Implementation of the abs() function
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
118 */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
119 static void absFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
120 assert( argc==1 );
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
121 switch( sqlite3_value_type(argv[0]) ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
122 case SQLITE_INTEGER: {
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
123 i64 iVal = sqlite3_value_int64(argv[0]);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
124 if( iVal<0 ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
125 if( (iVal<<1)==0 ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
126 sqlite3_result_error(context, "integer overflow", -1);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
127 return;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
128 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
129 iVal = -iVal;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
130 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
131 sqlite3_result_int64(context, iVal);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
132 break;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
133 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
134 case SQLITE_NULL: {
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
135 sqlite3_result_null(context);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
136 break;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
137 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
138 default: {
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
139 double rVal = sqlite3_value_double(argv[0]);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
140 if( rVal<0 ) rVal = -rVal;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
141 sqlite3_result_double(context, rVal);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
142 break;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
143 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
144 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
145 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
146
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
147 /*
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
148 ** Implementation of the substr() function
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
149 */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
150 static void substrFunc(
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
151 sqlite3_context *context,
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
152 int argc,
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
153 sqlite3_value **argv
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
154 ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
155 const unsigned char *z;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
156 const unsigned char *z2;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
157 int i;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
158 int p1, p2, len;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
159
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
160 assert( argc==3 );
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
161 z = sqlite3_value_text(argv[0]);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
162 if( z==0 ) return;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
163 p1 = sqlite3_value_int(argv[1]);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
164 p2 = sqlite3_value_int(argv[2]);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
165 for(len=0, z2=z; *z2; z2++){ if( (0xc0&*z2)!=0x80 ) len++; }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
166 if( p1<0 ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
167 p1 += len;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
168 if( p1<0 ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
169 p2 += p1;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
170 p1 = 0;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
171 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
172 }else if( p1>0 ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
173 p1--;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
174 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
175 if( p1+p2>len ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
176 p2 = len-p1;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
177 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
178 for(i=0; i<p1 && z[i]; i++){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
179 if( (z[i]&0xc0)==0x80 ) p1++;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
180 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
181 while( z[i] && (z[i]&0xc0)==0x80 ){ i++; p1++; }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
182 for(; i<p1+p2 && z[i]; i++){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
183 if( (z[i]&0xc0)==0x80 ) p2++;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
184 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
185 while( z[i] && (z[i]&0xc0)==0x80 ){ i++; p2++; }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
186 if( p2<0 ) p2 = 0;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
187 sqlite3_result_text(context, (char*)&z[p1], p2, SQLITE_TRANSIENT);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
188 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
189
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
190 /*
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
191 ** Implementation of the round() function
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
192 */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
193 static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
194 int n = 0;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
195 double r;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
196 char zBuf[500]; /* larger than the %f representation of the largest double */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
197 assert( argc==1 || argc==2 );
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
198 if( argc==2 ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
199 if( SQLITE_NULL==sqlite3_value_type(argv[1]) ) return;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
200 n = sqlite3_value_int(argv[1]);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
201 if( n>30 ) n = 30;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
202 if( n<0 ) n = 0;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
203 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
204 if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
205 r = sqlite3_value_double(argv[0]);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
206 sqlite3_snprintf(sizeof(zBuf),zBuf,"%.*f",n,r);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
207 sqlite3AtoF(zBuf, &r);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
208 sqlite3_result_double(context, r);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
209 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
210
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
211 /*
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
212 ** Implementation of the upper() and lower() SQL functions.
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
213 */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
214 static void upperFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
215 unsigned char *z;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
216 int i;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
217 if( argc<1 || SQLITE_NULL==sqlite3_value_type(argv[0]) ) return;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
218 z = sqliteMalloc(sqlite3_value_bytes(argv[0])+1);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
219 if( z==0 ) return;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
220 strcpy((char*)z, (char*)sqlite3_value_text(argv[0]));
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
221 for(i=0; z[i]; i++){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
222 z[i] = toupper(z[i]);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
223 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
224 sqlite3_result_text(context, (char*)z, -1, SQLITE_TRANSIENT);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
225 sqliteFree(z);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
226 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
227 static void lowerFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
228 unsigned char *z;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
229 int i;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
230 if( argc<1 || SQLITE_NULL==sqlite3_value_type(argv[0]) ) return;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
231 z = sqliteMalloc(sqlite3_value_bytes(argv[0])+1);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
232 if( z==0 ) return;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
233 strcpy((char*)z, (char*)sqlite3_value_text(argv[0]));
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
234 for(i=0; z[i]; i++){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
235 z[i] = tolower(z[i]);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
236 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
237 sqlite3_result_text(context, (char*)z, -1, SQLITE_TRANSIENT);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
238 sqliteFree(z);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
239 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
240
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
241 /*
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
242 ** Implementation of the IFNULL(), NVL(), and COALESCE() functions.
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
243 ** All three do the same thing. They return the first non-NULL
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
244 ** argument.
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
245 */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
246 static void ifnullFunc(
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
247 sqlite3_context *context,
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
248 int argc,
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
249 sqlite3_value **argv
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
250 ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
251 int i;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
252 for(i=0; i<argc; i++){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
253 if( SQLITE_NULL!=sqlite3_value_type(argv[i]) ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
254 sqlite3_result_value(context, argv[i]);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
255 break;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
256 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
257 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
258 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
259
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
260 /*
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
261 ** Implementation of random(). Return a random integer.
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
262 */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
263 static void randomFunc(
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
264 sqlite3_context *context,
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
265 int argc,
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
266 sqlite3_value **argv
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
267 ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
268 sqlite_int64 r;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
269 sqlite3Randomness(sizeof(r), &r);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
270 if( (r<<1)==0 ) r = 0; /* Prevent 0x8000.... as the result so that we */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
271 /* can always do abs() of the result */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
272 sqlite3_result_int64(context, r);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
273 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
274
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
275 /*
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
276 ** Implementation of the last_insert_rowid() SQL function. The return
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
277 ** value is the same as the sqlite3_last_insert_rowid() API function.
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
278 */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
279 static void last_insert_rowid(
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
280 sqlite3_context *context,
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
281 int arg,
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
282 sqlite3_value **argv
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
283 ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
284 sqlite3 *db = sqlite3_user_data(context);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
285 sqlite3_result_int64(context, sqlite3_last_insert_rowid(db));
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
286 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
287
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
288 /*
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
289 ** Implementation of the changes() SQL function. The return value is the
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
290 ** same as the sqlite3_changes() API function.
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
291 */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
292 static void changes(
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
293 sqlite3_context *context,
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
294 int arg,
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
295 sqlite3_value **argv
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
296 ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
297 sqlite3 *db = sqlite3_user_data(context);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
298 sqlite3_result_int(context, sqlite3_changes(db));
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
299 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
300
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
301 /*
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
302 ** Implementation of the total_changes() SQL function. The return value is
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
303 ** the same as the sqlite3_total_changes() API function.
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
304 */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
305 static void total_changes(
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
306 sqlite3_context *context,
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
307 int arg,
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
308 sqlite3_value **argv
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
309 ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
310 sqlite3 *db = sqlite3_user_data(context);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
311 sqlite3_result_int(context, sqlite3_total_changes(db));
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
312 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
313
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
314 /*
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
315 ** A structure defining how to do GLOB-style comparisons.
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
316 */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
317 struct compareInfo {
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
318 u8 matchAll;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
319 u8 matchOne;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
320 u8 matchSet;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
321 u8 noCase;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
322 };
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
323
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
324 static const struct compareInfo globInfo = { '*', '?', '[', 0 };
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
325 /* The correct SQL-92 behavior is for the LIKE operator to ignore
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
326 ** case. Thus 'a' LIKE 'A' would be true. */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
327 static const struct compareInfo likeInfoNorm = { '%', '_', 0, 1 };
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
328 /* If SQLITE_CASE_SENSITIVE_LIKE is defined, then the LIKE operator
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
329 ** is case sensitive causing 'a' LIKE 'A' to be false */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
330 static const struct compareInfo likeInfoAlt = { '%', '_', 0, 0 };
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
331
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
332 /*
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
333 ** X is a pointer to the first byte of a UTF-8 character. Increment
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
334 ** X so that it points to the next character. This only works right
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
335 ** if X points to a well-formed UTF-8 string.
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
336 */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
337 #define sqliteNextChar(X) while( (0xc0&*++(X))==0x80 ){}
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
338 #define sqliteCharVal(X) sqlite3ReadUtf8(X)
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
339
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
340
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
341 /*
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
342 ** Compare two UTF-8 strings for equality where the first string can
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
343 ** potentially be a "glob" expression. Return true (1) if they
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
344 ** are the same and false (0) if they are different.
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
345 **
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
346 ** Globbing rules:
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
347 **
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
348 ** '*' Matches any sequence of zero or more characters.
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
349 **
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
350 ** '?' Matches exactly one character.
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
351 **
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
352 ** [...] Matches one character from the enclosed list of
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
353 ** characters.
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
354 **
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
355 ** [^...] Matches one character not in the enclosed list.
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
356 **
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
357 ** With the [...] and [^...] matching, a ']' character can be included
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
358 ** in the list by making it the first character after '[' or '^'. A
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
359 ** range of characters can be specified using '-'. Example:
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
360 ** "[a-z]" matches any single lower-case letter. To match a '-', make
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
361 ** it the last character in the list.
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
362 **
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
363 ** This routine is usually quick, but can be N**2 in the worst case.
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
364 **
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
365 ** Hints: to match '*' or '?', put them in "[]". Like this:
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
366 **
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
367 ** abc[*]xyz Matches "abc*xyz" only
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
368 */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
369 static int patternCompare(
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
370 const u8 *zPattern, /* The glob pattern */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
371 const u8 *zString, /* The string to compare against the glob */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
372 const struct compareInfo *pInfo, /* Information about how to do the compare */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
373 const int esc /* The escape character */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
374 ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
375 register int c;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
376 int invert;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
377 int seen;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
378 int c2;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
379 u8 matchOne = pInfo->matchOne;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
380 u8 matchAll = pInfo->matchAll;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
381 u8 matchSet = pInfo->matchSet;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
382 u8 noCase = pInfo->noCase;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
383 int prevEscape = 0; /* True if the previous character was 'escape' */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
384
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
385 while( (c = *zPattern)!=0 ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
386 if( !prevEscape && c==matchAll ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
387 while( (c=zPattern[1]) == matchAll || c == matchOne ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
388 if( c==matchOne ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
389 if( *zString==0 ) return 0;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
390 sqliteNextChar(zString);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
391 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
392 zPattern++;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
393 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
394 if( c && esc && sqlite3ReadUtf8(&zPattern[1])==esc ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
395 u8 const *zTemp = &zPattern[1];
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
396 sqliteNextChar(zTemp);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
397 c = *zTemp;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
398 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
399 if( c==0 ) return 1;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
400 if( c==matchSet ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
401 assert( esc==0 ); /* This is GLOB, not LIKE */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
402 while( *zString && patternCompare(&zPattern[1],zString,pInfo,esc)==0 ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
403 sqliteNextChar(zString);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
404 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
405 return *zString!=0;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
406 }else{
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
407 while( (c2 = *zString)!=0 ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
408 if( noCase ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
409 c2 = sqlite3UpperToLower[c2];
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
410 c = sqlite3UpperToLower[c];
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
411 while( c2 != 0 && c2 != c ){ c2 = sqlite3UpperToLower[*++zString]; }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
412 }else{
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
413 while( c2 != 0 && c2 != c ){ c2 = *++zString; }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
414 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
415 if( c2==0 ) return 0;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
416 if( patternCompare(&zPattern[1],zString,pInfo,esc) ) return 1;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
417 sqliteNextChar(zString);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
418 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
419 return 0;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
420 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
421 }else if( !prevEscape && c==matchOne ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
422 if( *zString==0 ) return 0;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
423 sqliteNextChar(zString);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
424 zPattern++;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
425 }else if( c==matchSet ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
426 int prior_c = 0;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
427 assert( esc==0 ); /* This only occurs for GLOB, not LIKE */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
428 seen = 0;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
429 invert = 0;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
430 c = sqliteCharVal(zString);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
431 if( c==0 ) return 0;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
432 c2 = *++zPattern;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
433 if( c2=='^' ){ invert = 1; c2 = *++zPattern; }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
434 if( c2==']' ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
435 if( c==']' ) seen = 1;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
436 c2 = *++zPattern;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
437 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
438 while( (c2 = sqliteCharVal(zPattern))!=0 && c2!=']' ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
439 if( c2=='-' && zPattern[1]!=']' && zPattern[1]!=0 && prior_c>0 ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
440 zPattern++;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
441 c2 = sqliteCharVal(zPattern);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
442 if( c>=prior_c && c<=c2 ) seen = 1;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
443 prior_c = 0;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
444 }else if( c==c2 ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
445 seen = 1;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
446 prior_c = c2;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
447 }else{
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
448 prior_c = c2;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
449 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
450 sqliteNextChar(zPattern);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
451 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
452 if( c2==0 || (seen ^ invert)==0 ) return 0;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
453 sqliteNextChar(zString);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
454 zPattern++;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
455 }else if( esc && !prevEscape && sqlite3ReadUtf8(zPattern)==esc){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
456 prevEscape = 1;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
457 sqliteNextChar(zPattern);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
458 }else{
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
459 if( noCase ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
460 if( sqlite3UpperToLower[c] != sqlite3UpperToLower[*zString] ) return 0;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
461 }else{
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
462 if( c != *zString ) return 0;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
463 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
464 zPattern++;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
465 zString++;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
466 prevEscape = 0;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
467 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
468 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
469 return *zString==0;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
470 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
471
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
472 /*
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
473 ** Count the number of times that the LIKE operator (or GLOB which is
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
474 ** just a variation of LIKE) gets called. This is used for testing
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
475 ** only.
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
476 */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
477 #ifdef SQLITE_TEST
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
478 int sqlite3_like_count = 0;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
479 #endif
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
480
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
481
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
482 /*
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
483 ** Implementation of the like() SQL function. This function implements
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
484 ** the build-in LIKE operator. The first argument to the function is the
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
485 ** pattern and the second argument is the string. So, the SQL statements:
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
486 **
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
487 ** A LIKE B
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
488 **
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
489 ** is implemented as like(B,A).
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
490 **
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
491 ** This same function (with a different compareInfo structure) computes
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
492 ** the GLOB operator.
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
493 */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
494 static void likeFunc(
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
495 sqlite3_context *context,
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
496 int argc,
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
497 sqlite3_value **argv
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
498 ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
499 const unsigned char *zA = sqlite3_value_text(argv[0]);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
500 const unsigned char *zB = sqlite3_value_text(argv[1]);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
501 int escape = 0;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
502 if( argc==3 ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
503 /* The escape character string must consist of a single UTF-8 character.
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
504 ** Otherwise, return an error.
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
505 */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
506 const unsigned char *zEsc = sqlite3_value_text(argv[2]);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
507 if( sqlite3utf8CharLen((char*)zEsc, -1)!=1 ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
508 sqlite3_result_error(context,
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
509 "ESCAPE expression must be a single character", -1);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
510 return;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
511 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
512 escape = sqlite3ReadUtf8(zEsc);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
513 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
514 if( zA && zB ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
515 struct compareInfo *pInfo = sqlite3_user_data(context);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
516 #ifdef SQLITE_TEST
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
517 sqlite3_like_count++;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
518 #endif
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
519 sqlite3_result_int(context, patternCompare(zA, zB, pInfo, escape));
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
520 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
521 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
522
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
523 /*
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
524 ** Implementation of the NULLIF(x,y) function. The result is the first
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
525 ** argument if the arguments are different. The result is NULL if the
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
526 ** arguments are equal to each other.
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
527 */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
528 static void nullifFunc(
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
529 sqlite3_context *context,
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
530 int argc,
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
531 sqlite3_value **argv
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
532 ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
533 CollSeq *pColl = sqlite3GetFuncCollSeq(context);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
534 if( sqlite3MemCompare(argv[0], argv[1], pColl)!=0 ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
535 sqlite3_result_value(context, argv[0]);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
536 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
537 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
538
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
539 /*
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
540 ** Implementation of the VERSION(*) function. The result is the version
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
541 ** of the SQLite library that is running.
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
542 */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
543 static void versionFunc(
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
544 sqlite3_context *context,
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
545 int argc,
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
546 sqlite3_value **argv
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
547 ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
548 sqlite3_result_text(context, sqlite3_version, -1, SQLITE_STATIC);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
549 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
550
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
551
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
552 /*
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
553 ** EXPERIMENTAL - This is not an official function. The interface may
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
554 ** change. This function may disappear. Do not write code that depends
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
555 ** on this function.
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
556 **
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
557 ** Implementation of the QUOTE() function. This function takes a single
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
558 ** argument. If the argument is numeric, the return value is the same as
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
559 ** the argument. If the argument is NULL, the return value is the string
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
560 ** "NULL". Otherwise, the argument is enclosed in single quotes with
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
561 ** single-quote escapes.
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
562 */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
563 static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
564 if( argc<1 ) return;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
565 switch( sqlite3_value_type(argv[0]) ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
566 case SQLITE_NULL: {
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
567 sqlite3_result_text(context, "NULL", 4, SQLITE_STATIC);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
568 break;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
569 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
570 case SQLITE_INTEGER:
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
571 case SQLITE_FLOAT: {
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
572 sqlite3_result_value(context, argv[0]);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
573 break;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
574 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
575 case SQLITE_BLOB: {
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
576 static const char hexdigits[] = {
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
577 '0', '1', '2', '3', '4', '5', '6', '7',
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
578 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
579 };
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
580 char *zText = 0;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
581 int nBlob = sqlite3_value_bytes(argv[0]);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
582 char const *zBlob = sqlite3_value_blob(argv[0]);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
583
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
584 zText = (char *)sqliteMalloc((2*nBlob)+4);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
585 if( !zText ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
586 sqlite3_result_error(context, "out of memory", -1);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
587 }else{
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
588 int i;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
589 for(i=0; i<nBlob; i++){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
590 zText[(i*2)+2] = hexdigits[(zBlob[i]>>4)&0x0F];
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
591 zText[(i*2)+3] = hexdigits[(zBlob[i])&0x0F];
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
592 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
593 zText[(nBlob*2)+2] = '\'';
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
594 zText[(nBlob*2)+3] = '\0';
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
595 zText[0] = 'X';
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
596 zText[1] = '\'';
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
597 sqlite3_result_text(context, zText, -1, SQLITE_TRANSIENT);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
598 sqliteFree(zText);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
599 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
600 break;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
601 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
602 case SQLITE_TEXT: {
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
603 int i,j,n;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
604 const unsigned char *zArg = sqlite3_value_text(argv[0]);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
605 char *z;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
606
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
607 for(i=n=0; zArg[i]; i++){ if( zArg[i]=='\'' ) n++; }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
608 z = sqliteMalloc( i+n+3 );
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
609 if( z==0 ) return;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
610 z[0] = '\'';
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
611 for(i=0, j=1; zArg[i]; i++){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
612 z[j++] = zArg[i];
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
613 if( zArg[i]=='\'' ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
614 z[j++] = '\'';
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
615 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
616 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
617 z[j++] = '\'';
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
618 z[j] = 0;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
619 sqlite3_result_text(context, z, j, SQLITE_TRANSIENT);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
620 sqliteFree(z);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
621 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
622 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
623 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
624
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
625 #ifdef SQLITE_SOUNDEX
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
626 /*
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
627 ** Compute the soundex encoding of a word.
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
628 */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
629 static void soundexFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
630 char zResult[8];
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
631 const u8 *zIn;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
632 int i, j;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
633 static const unsigned char iCode[] = {
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
634 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
635 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
636 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
637 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
638 0, 0, 1, 2, 3, 0, 1, 2, 0, 0, 2, 2, 4, 5, 5, 0,
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
639 1, 2, 6, 2, 3, 0, 1, 0, 2, 0, 2, 0, 0, 0, 0, 0,
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
640 0, 0, 1, 2, 3, 0, 1, 2, 0, 0, 2, 2, 4, 5, 5, 0,
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
641 1, 2, 6, 2, 3, 0, 1, 0, 2, 0, 2, 0, 0, 0, 0, 0,
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
642 };
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
643 assert( argc==1 );
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
644 zIn = (u8*)sqlite3_value_text(argv[0]);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
645 for(i=0; zIn[i] && !isalpha(zIn[i]); i++){}
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
646 if( zIn[i] ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
647 zResult[0] = toupper(zIn[i]);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
648 for(j=1; j<4 && zIn[i]; i++){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
649 int code = iCode[zIn[i]&0x7f];
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
650 if( code>0 ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
651 zResult[j++] = code + '0';
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
652 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
653 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
654 while( j<4 ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
655 zResult[j++] = '0';
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
656 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
657 zResult[j] = 0;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
658 sqlite3_result_text(context, zResult, 4, SQLITE_TRANSIENT);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
659 }else{
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
660 sqlite3_result_text(context, "?000", 4, SQLITE_STATIC);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
661 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
662 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
663 #endif
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
664
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
665 #ifdef SQLITE_TEST
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
666 /*
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
667 ** This function generates a string of random characters. Used for
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
668 ** generating test data.
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
669 */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
670 static void randStr(sqlite3_context *context, int argc, sqlite3_value **argv){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
671 static const unsigned char zSrc[] =
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
672 "abcdefghijklmnopqrstuvwxyz"
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
673 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
674 "0123456789"
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
675 ".-!,:*^+=_|?/<> ";
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
676 int iMin, iMax, n, r, i;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
677 unsigned char zBuf[1000];
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
678 if( argc>=1 ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
679 iMin = sqlite3_value_int(argv[0]);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
680 if( iMin<0 ) iMin = 0;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
681 if( iMin>=sizeof(zBuf) ) iMin = sizeof(zBuf)-1;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
682 }else{
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
683 iMin = 1;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
684 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
685 if( argc>=2 ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
686 iMax = sqlite3_value_int(argv[1]);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
687 if( iMax<iMin ) iMax = iMin;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
688 if( iMax>=sizeof(zBuf) ) iMax = sizeof(zBuf)-1;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
689 }else{
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
690 iMax = 50;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
691 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
692 n = iMin;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
693 if( iMax>iMin ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
694 sqlite3Randomness(sizeof(r), &r);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
695 r &= 0x7fffffff;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
696 n += r%(iMax + 1 - iMin);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
697 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
698 assert( n<sizeof(zBuf) );
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
699 sqlite3Randomness(n, zBuf);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
700 for(i=0; i<n; i++){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
701 zBuf[i] = zSrc[zBuf[i]%(sizeof(zSrc)-1)];
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
702 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
703 zBuf[n] = 0;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
704 sqlite3_result_text(context, (char*)zBuf, n, SQLITE_TRANSIENT);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
705 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
706 #endif /* SQLITE_TEST */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
707
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
708 #ifdef SQLITE_TEST
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
709 /*
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
710 ** The following two SQL functions are used to test returning a text
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
711 ** result with a destructor. Function 'test_destructor' takes one argument
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
712 ** and returns the same argument interpreted as TEXT. A destructor is
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
713 ** passed with the sqlite3_result_text() call.
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
714 **
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
715 ** SQL function 'test_destructor_count' returns the number of outstanding
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
716 ** allocations made by 'test_destructor';
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
717 **
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
718 ** WARNING: Not threadsafe.
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
719 */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
720 static int test_destructor_count_var = 0;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
721 static void destructor(void *p){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
722 char *zVal = (char *)p;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
723 assert(zVal);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
724 zVal--;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
725 sqliteFree(zVal);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
726 test_destructor_count_var--;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
727 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
728 static void test_destructor(
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
729 sqlite3_context *pCtx,
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
730 int nArg,
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
731 sqlite3_value **argv
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
732 ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
733 char *zVal;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
734 int len;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
735 sqlite3 *db = sqlite3_user_data(pCtx);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
736
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
737 test_destructor_count_var++;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
738 assert( nArg==1 );
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
739 if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
740 len = sqlite3ValueBytes(argv[0], ENC(db));
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
741 zVal = sqliteMalloc(len+3);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
742 zVal[len] = 0;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
743 zVal[len-1] = 0;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
744 assert( zVal );
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
745 zVal++;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
746 memcpy(zVal, sqlite3ValueText(argv[0], ENC(db)), len);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
747 if( ENC(db)==SQLITE_UTF8 ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
748 sqlite3_result_text(pCtx, zVal, -1, destructor);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
749 #ifndef SQLITE_OMIT_UTF16
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
750 }else if( ENC(db)==SQLITE_UTF16LE ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
751 sqlite3_result_text16le(pCtx, zVal, -1, destructor);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
752 }else{
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
753 sqlite3_result_text16be(pCtx, zVal, -1, destructor);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
754 #endif /* SQLITE_OMIT_UTF16 */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
755 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
756 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
757 static void test_destructor_count(
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
758 sqlite3_context *pCtx,
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
759 int nArg,
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
760 sqlite3_value **argv
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
761 ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
762 sqlite3_result_int(pCtx, test_destructor_count_var);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
763 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
764 #endif /* SQLITE_TEST */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
765
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
766 #ifdef SQLITE_TEST
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
767 /*
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
768 ** Routines for testing the sqlite3_get_auxdata() and sqlite3_set_auxdata()
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
769 ** interface.
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
770 **
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
771 ** The test_auxdata() SQL function attempts to register each of its arguments
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
772 ** as auxiliary data. If there are no prior registrations of aux data for
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
773 ** that argument (meaning the argument is not a constant or this is its first
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
774 ** call) then the result for that argument is 0. If there is a prior
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
775 ** registration, the result for that argument is 1. The overall result
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
776 ** is the individual argument results separated by spaces.
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
777 */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
778 static void free_test_auxdata(void *p) {sqliteFree(p);}
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
779 static void test_auxdata(
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
780 sqlite3_context *pCtx,
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
781 int nArg,
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
782 sqlite3_value **argv
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
783 ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
784 int i;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
785 char *zRet = sqliteMalloc(nArg*2);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
786 if( !zRet ) return;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
787 for(i=0; i<nArg; i++){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
788 char const *z = (char*)sqlite3_value_text(argv[i]);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
789 if( z ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
790 char *zAux = sqlite3_get_auxdata(pCtx, i);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
791 if( zAux ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
792 zRet[i*2] = '1';
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
793 if( strcmp(zAux, z) ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
794 sqlite3_result_error(pCtx, "Auxilary data corruption", -1);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
795 return;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
796 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
797 }else{
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
798 zRet[i*2] = '0';
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
799 zAux = sqliteStrDup(z);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
800 sqlite3_set_auxdata(pCtx, i, zAux, free_test_auxdata);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
801 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
802 zRet[i*2+1] = ' ';
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
803 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
804 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
805 sqlite3_result_text(pCtx, zRet, 2*nArg-1, free_test_auxdata);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
806 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
807 #endif /* SQLITE_TEST */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
808
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
809 #ifdef SQLITE_TEST
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
810 /*
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
811 ** A function to test error reporting from user functions. This function
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
812 ** returns a copy of it's first argument as an error.
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
813 */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
814 static void test_error(
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
815 sqlite3_context *pCtx,
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
816 int nArg,
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
817 sqlite3_value **argv
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
818 ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
819 sqlite3_result_error(pCtx, (char*)sqlite3_value_text(argv[0]), 0);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
820 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
821 #endif /* SQLITE_TEST */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
822
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
823 /*
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
824 ** An instance of the following structure holds the context of a
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
825 ** sum() or avg() aggregate computation.
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
826 */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
827 typedef struct SumCtx SumCtx;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
828 struct SumCtx {
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
829 double rSum; /* Floating point sum */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
830 i64 iSum; /* Integer sum */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
831 i64 cnt; /* Number of elements summed */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
832 u8 overflow; /* True if integer overflow seen */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
833 u8 approx; /* True if non-integer value was input to the sum */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
834 };
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
835
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
836 /*
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
837 ** Routines used to compute the sum, average, and total.
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
838 **
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
839 ** The SUM() function follows the (broken) SQL standard which means
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
840 ** that it returns NULL if it sums over no inputs. TOTAL returns
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
841 ** 0.0 in that case. In addition, TOTAL always returns a float where
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
842 ** SUM might return an integer if it never encounters a floating point
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
843 ** value. TOTAL never fails, but SUM might through an exception if
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
844 ** it overflows an integer.
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
845 */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
846 static void sumStep(sqlite3_context *context, int argc, sqlite3_value **argv){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
847 SumCtx *p;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
848 int type;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
849 assert( argc==1 );
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
850 p = sqlite3_aggregate_context(context, sizeof(*p));
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
851 type = sqlite3_value_numeric_type(argv[0]);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
852 if( p && type!=SQLITE_NULL ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
853 p->cnt++;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
854 if( type==SQLITE_INTEGER ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
855 i64 v = sqlite3_value_int64(argv[0]);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
856 p->rSum += v;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
857 if( (p->approx|p->overflow)==0 ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
858 i64 iNewSum = p->iSum + v;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
859 int s1 = p->iSum >> (sizeof(i64)*8-1);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
860 int s2 = v >> (sizeof(i64)*8-1);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
861 int s3 = iNewSum >> (sizeof(i64)*8-1);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
862 p->overflow = (s1&s2&~s3) | (~s1&~s2&s3);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
863 p->iSum = iNewSum;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
864 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
865 }else{
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
866 p->rSum += sqlite3_value_double(argv[0]);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
867 p->approx = 1;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
868 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
869 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
870 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
871 static void sumFinalize(sqlite3_context *context){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
872 SumCtx *p;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
873 p = sqlite3_aggregate_context(context, 0);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
874 if( p && p->cnt>0 ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
875 if( p->overflow ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
876 sqlite3_result_error(context,"integer overflow",-1);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
877 }else if( p->approx ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
878 sqlite3_result_double(context, p->rSum);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
879 }else{
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
880 sqlite3_result_int64(context, p->iSum);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
881 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
882 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
883 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
884 static void avgFinalize(sqlite3_context *context){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
885 SumCtx *p;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
886 p = sqlite3_aggregate_context(context, 0);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
887 if( p && p->cnt>0 ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
888 sqlite3_result_double(context, p->rSum/(double)p->cnt);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
889 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
890 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
891 static void totalFinalize(sqlite3_context *context){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
892 SumCtx *p;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
893 p = sqlite3_aggregate_context(context, 0);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
894 sqlite3_result_double(context, p ? p->rSum : 0.0);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
895 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
896
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
897 /*
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
898 ** The following structure keeps track of state information for the
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
899 ** count() aggregate function.
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
900 */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
901 typedef struct CountCtx CountCtx;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
902 struct CountCtx {
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
903 i64 n;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
904 };
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
905
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
906 /*
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
907 ** Routines to implement the count() aggregate function.
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
908 */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
909 static void countStep(sqlite3_context *context, int argc, sqlite3_value **argv){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
910 CountCtx *p;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
911 p = sqlite3_aggregate_context(context, sizeof(*p));
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
912 if( (argc==0 || SQLITE_NULL!=sqlite3_value_type(argv[0])) && p ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
913 p->n++;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
914 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
915 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
916 static void countFinalize(sqlite3_context *context){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
917 CountCtx *p;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
918 p = sqlite3_aggregate_context(context, 0);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
919 sqlite3_result_int64(context, p ? p->n : 0);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
920 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
921
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
922 /*
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
923 ** Routines to implement min() and max() aggregate functions.
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
924 */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
925 static void minmaxStep(sqlite3_context *context, int argc, sqlite3_value **argv){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
926 Mem *pArg = (Mem *)argv[0];
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
927 Mem *pBest;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
928
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
929 if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
930 pBest = (Mem *)sqlite3_aggregate_context(context, sizeof(*pBest));
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
931 if( !pBest ) return;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
932
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
933 if( pBest->flags ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
934 int max;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
935 int cmp;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
936 CollSeq *pColl = sqlite3GetFuncCollSeq(context);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
937 /* This step function is used for both the min() and max() aggregates,
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
938 ** the only difference between the two being that the sense of the
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
939 ** comparison is inverted. For the max() aggregate, the
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
940 ** sqlite3_user_data() function returns (void *)-1. For min() it
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
941 ** returns (void *)db, where db is the sqlite3* database pointer.
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
942 ** Therefore the next statement sets variable 'max' to 1 for the max()
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
943 ** aggregate, or 0 for min().
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
944 */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
945 max = ((sqlite3_user_data(context)==(void *)-1)?1:0);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
946 cmp = sqlite3MemCompare(pBest, pArg, pColl);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
947 if( (max && cmp<0) || (!max && cmp>0) ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
948 sqlite3VdbeMemCopy(pBest, pArg);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
949 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
950 }else{
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
951 sqlite3VdbeMemCopy(pBest, pArg);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
952 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
953 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
954 static void minMaxFinalize(sqlite3_context *context){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
955 sqlite3_value *pRes;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
956 pRes = (sqlite3_value *)sqlite3_aggregate_context(context, 0);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
957 if( pRes ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
958 if( pRes->flags ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
959 sqlite3_result_value(context, pRes);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
960 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
961 sqlite3VdbeMemRelease(pRes);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
962 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
963 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
964
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
965
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
966 /*
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
967 ** This function registered all of the above C functions as SQL
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
968 ** functions. This should be the only routine in this file with
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
969 ** external linkage.
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
970 */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
971 void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
972 static const struct {
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
973 char *zName;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
974 signed char nArg;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
975 u8 argType; /* 0: none. 1: db 2: (-1) */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
976 u8 eTextRep; /* 1: UTF-16. 0: UTF-8 */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
977 u8 needCollSeq;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
978 void (*xFunc)(sqlite3_context*,int,sqlite3_value **);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
979 } aFuncs[] = {
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
980 { "min", -1, 0, SQLITE_UTF8, 1, minmaxFunc },
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
981 { "min", 0, 0, SQLITE_UTF8, 1, 0 },
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
982 { "max", -1, 2, SQLITE_UTF8, 1, minmaxFunc },
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
983 { "max", 0, 2, SQLITE_UTF8, 1, 0 },
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
984 { "typeof", 1, 0, SQLITE_UTF8, 0, typeofFunc },
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
985 { "length", 1, 0, SQLITE_UTF8, 0, lengthFunc },
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
986 { "substr", 3, 0, SQLITE_UTF8, 0, substrFunc },
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
987 #ifndef SQLITE_OMIT_UTF16
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
988 { "substr", 3, 0, SQLITE_UTF16LE, 0, sqlite3utf16Substr },
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
989 #endif
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
990 { "abs", 1, 0, SQLITE_UTF8, 0, absFunc },
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
991 { "round", 1, 0, SQLITE_UTF8, 0, roundFunc },
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
992 { "round", 2, 0, SQLITE_UTF8, 0, roundFunc },
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
993 { "upper", 1, 0, SQLITE_UTF8, 0, upperFunc },
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
994 { "lower", 1, 0, SQLITE_UTF8, 0, lowerFunc },
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
995 { "coalesce", -1, 0, SQLITE_UTF8, 0, ifnullFunc },
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
996 { "coalesce", 0, 0, SQLITE_UTF8, 0, 0 },
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
997 { "coalesce", 1, 0, SQLITE_UTF8, 0, 0 },
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
998 { "ifnull", 2, 0, SQLITE_UTF8, 1, ifnullFunc },
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
999 { "random", -1, 0, SQLITE_UTF8, 0, randomFunc },
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1000 { "nullif", 2, 0, SQLITE_UTF8, 1, nullifFunc },
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1001 { "sqlite_version", 0, 0, SQLITE_UTF8, 0, versionFunc},
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1002 { "quote", 1, 0, SQLITE_UTF8, 0, quoteFunc },
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1003 { "last_insert_rowid", 0, 1, SQLITE_UTF8, 0, last_insert_rowid },
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1004 { "changes", 0, 1, SQLITE_UTF8, 0, changes },
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1005 { "total_changes", 0, 1, SQLITE_UTF8, 0, total_changes },
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1006 #ifdef SQLITE_SOUNDEX
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1007 { "soundex", 1, 0, SQLITE_UTF8, 0, soundexFunc},
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1008 #endif
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1009 #ifdef SQLITE_TEST
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1010 { "randstr", 2, 0, SQLITE_UTF8, 0, randStr },
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1011 { "test_destructor", 1, 1, SQLITE_UTF8, 0, test_destructor},
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1012 { "test_destructor_count", 0, 0, SQLITE_UTF8, 0, test_destructor_count},
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1013 { "test_auxdata", -1, 0, SQLITE_UTF8, 0, test_auxdata},
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1014 { "test_error", 1, 0, SQLITE_UTF8, 0, test_error},
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1015 #endif
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1016 };
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1017 static const struct {
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1018 char *zName;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1019 signed char nArg;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1020 u8 argType;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1021 u8 needCollSeq;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1022 void (*xStep)(sqlite3_context*,int,sqlite3_value**);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1023 void (*xFinalize)(sqlite3_context*);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1024 } aAggs[] = {
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1025 { "min", 1, 0, 1, minmaxStep, minMaxFinalize },
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1026 { "max", 1, 2, 1, minmaxStep, minMaxFinalize },
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1027 { "sum", 1, 0, 0, sumStep, sumFinalize },
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1028 { "total", 1, 0, 0, sumStep, totalFinalize },
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1029 { "avg", 1, 0, 0, sumStep, avgFinalize },
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1030 { "count", 0, 0, 0, countStep, countFinalize },
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1031 { "count", 1, 0, 0, countStep, countFinalize },
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1032 };
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1033 int i;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1034
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1035 for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1036 void *pArg = 0;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1037 switch( aFuncs[i].argType ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1038 case 1: pArg = db; break;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1039 case 2: pArg = (void *)(-1); break;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1040 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1041 sqlite3CreateFunc(db, aFuncs[i].zName, aFuncs[i].nArg,
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1042 aFuncs[i].eTextRep, pArg, aFuncs[i].xFunc, 0, 0);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1043 if( aFuncs[i].needCollSeq ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1044 FuncDef *pFunc = sqlite3FindFunction(db, aFuncs[i].zName,
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1045 strlen(aFuncs[i].zName), aFuncs[i].nArg, aFuncs[i].eTextRep, 0);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1046 if( pFunc && aFuncs[i].needCollSeq ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1047 pFunc->needCollSeq = 1;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1048 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1049 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1050 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1051 #ifndef SQLITE_OMIT_ALTERTABLE
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1052 sqlite3AlterFunctions(db);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1053 #endif
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1054 #ifndef SQLITE_OMIT_PARSER
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1055 sqlite3AttachFunctions(db);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1056 #endif
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1057 for(i=0; i<sizeof(aAggs)/sizeof(aAggs[0]); i++){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1058 void *pArg = 0;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1059 switch( aAggs[i].argType ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1060 case 1: pArg = db; break;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1061 case 2: pArg = (void *)(-1); break;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1062 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1063 sqlite3CreateFunc(db, aAggs[i].zName, aAggs[i].nArg, SQLITE_UTF8,
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1064 pArg, 0, aAggs[i].xStep, aAggs[i].xFinalize);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1065 if( aAggs[i].needCollSeq ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1066 FuncDef *pFunc = sqlite3FindFunction( db, aAggs[i].zName,
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1067 strlen(aAggs[i].zName), aAggs[i].nArg, SQLITE_UTF8, 0);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1068 if( pFunc && aAggs[i].needCollSeq ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1069 pFunc->needCollSeq = 1;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1070 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1071 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1072 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1073 sqlite3RegisterDateTimeFunctions(db);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1074 #ifdef SQLITE_SSE
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1075 (void)sqlite3SseFunctions(db);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1076 #endif
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1077 #ifdef SQLITE_CASE_SENSITIVE_LIKE
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1078 sqlite3RegisterLikeFunctions(db, 1);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1079 #else
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1080 sqlite3RegisterLikeFunctions(db, 0);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1081 #endif
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1082 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1083
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1084 /*
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1085 ** Set the LIKEOPT flag on the 2-argument function with the given name.
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1086 */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1087 static void setLikeOptFlag(sqlite3 *db, const char *zName, int flagVal){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1088 FuncDef *pDef;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1089 pDef = sqlite3FindFunction(db, zName, strlen(zName), 2, SQLITE_UTF8, 0);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1090 if( pDef ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1091 pDef->flags = flagVal;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1092 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1093 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1094
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1095 /*
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1096 ** Register the built-in LIKE and GLOB functions. The caseSensitive
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1097 ** parameter determines whether or not the LIKE operator is case
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1098 ** sensitive. GLOB is always case sensitive.
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1099 */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1100 void sqlite3RegisterLikeFunctions(sqlite3 *db, int caseSensitive){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1101 struct compareInfo *pInfo;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1102 if( caseSensitive ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1103 pInfo = (struct compareInfo*)&likeInfoAlt;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1104 }else{
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1105 pInfo = (struct compareInfo*)&likeInfoNorm;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1106 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1107 sqlite3CreateFunc(db, "like", 2, SQLITE_UTF8, pInfo, likeFunc, 0, 0);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1108 sqlite3CreateFunc(db, "like", 3, SQLITE_UTF8, pInfo, likeFunc, 0, 0);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1109 sqlite3CreateFunc(db, "glob", 2, SQLITE_UTF8,
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1110 (struct compareInfo*)&globInfo, likeFunc, 0,0);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1111 setLikeOptFlag(db, "glob", SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1112 setLikeOptFlag(db, "like",
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1113 caseSensitive ? (SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE) : SQLITE_FUNC_LIKE);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1114 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1115
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1116 /*
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1117 ** pExpr points to an expression which implements a function. If
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1118 ** it is appropriate to apply the LIKE optimization to that function
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1119 ** then set aWc[0] through aWc[2] to the wildcard characters and
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1120 ** return TRUE. If the function is not a LIKE-style function then
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1121 ** return FALSE.
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1122 */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1123 int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1124 FuncDef *pDef;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1125 if( pExpr->op!=TK_FUNCTION ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1126 return 0;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1127 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1128 if( pExpr->pList->nExpr!=2 ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1129 return 0;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1130 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1131 pDef = sqlite3FindFunction(db, (char*)pExpr->token.z, pExpr->token.n, 2,
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1132 SQLITE_UTF8, 0);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1133 if( pDef==0 || (pDef->flags & SQLITE_FUNC_LIKE)==0 ){
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1134 return 0;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1135 }
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1136
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1137 /* The memcpy() statement assumes that the wildcard characters are
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1138 ** the first three statements in the compareInfo structure. The
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1139 ** asserts() that follow verify that assumption
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1140 */
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1141 memcpy(aWc, pDef->pUserData, 3);
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1142 assert( (char*)&likeInfoAlt == (char*)&likeInfoAlt.matchAll );
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1143 assert( &((char*)&likeInfoAlt)[1] == (char*)&likeInfoAlt.matchOne );
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1144 assert( &((char*)&likeInfoAlt)[2] == (char*)&likeInfoAlt.matchSet );
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1145 *pIsNocase = (pDef->flags & SQLITE_FUNC_CASE)==0;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1146 return 1;
b6b61becdf4e [svn] - add sqlite/ directory
nenolod
parents:
diff changeset
1147 }