wasCSharpSQLite – Blame information for rev
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | using System; |
2 | using System.Diagnostics; |
||
3 | using System.Text; |
||
4 | |||
5 | using sqlite3_int64 = System.Int64; |
||
6 | using i64 = System.Int64; |
||
7 | using u8 = System.Byte; |
||
8 | using u32 = System.UInt32; |
||
9 | using u64 = System.UInt64; |
||
10 | |||
11 | namespace Community.CsharpSqlite |
||
12 | { |
||
13 | using sqlite3_value = Sqlite3.Mem; |
||
14 | using sqlite_int64 = System.Int64; |
||
15 | |||
16 | public partial class Sqlite3 |
||
17 | { |
||
18 | /* |
||
19 | ** 2002 February 23 |
||
20 | ** |
||
21 | ** The author disclaims copyright to this source code. In place of |
||
22 | ** a legal notice, here is a blessing: |
||
23 | ** |
||
24 | ** May you do good and not evil. |
||
25 | ** May you find forgiveness for yourself and forgive others. |
||
26 | ** May you share freely, never taking more than you give. |
||
27 | ** |
||
28 | ************************************************************************* |
||
29 | ** This file contains the C functions that implement various SQL |
||
30 | ** functions of SQLite. |
||
31 | ** |
||
32 | ** There is only one exported symbol in this file - the function |
||
33 | ** sqliteRegisterBuildinFunctions() found at the bottom of the file. |
||
34 | ** All other code has file scope. |
||
35 | ************************************************************************* |
||
36 | ** Included in SQLite3 port to C#-SQLite; 2008 Noah B Hart |
||
37 | ** C#-SQLite is an independent reimplementation of the SQLite software library |
||
38 | ** |
||
39 | ** SQLITE_SOURCE_ID: 2011-06-23 19:49:22 4374b7e83ea0a3fbc3691f9c0c936272862f32f2 |
||
40 | ** |
||
41 | ************************************************************************* |
||
42 | */ |
||
43 | //#include "sqliteInt.h" |
||
44 | //#include <stdlib.h> |
||
45 | //#include <assert.h> |
||
46 | //#include "vdbeInt.h" |
||
47 | |||
48 | |||
49 | /* |
||
50 | ** Return the collating function associated with a function. |
||
51 | */ |
||
52 | static CollSeq sqlite3GetFuncCollSeq( sqlite3_context context ) |
||
53 | { |
||
54 | return context.pColl; |
||
55 | } |
||
56 | |||
57 | /* |
||
58 | ** Implementation of the non-aggregate min() and max() functions |
||
59 | */ |
||
60 | static void minmaxFunc( |
||
61 | sqlite3_context context, |
||
62 | int argc, |
||
63 | sqlite3_value[] argv |
||
64 | ) |
||
65 | { |
||
66 | int i; |
||
67 | int mask; /* 0 for min() or 0xffffffff for max() */ |
||
68 | int iBest; |
||
69 | CollSeq pColl; |
||
70 | |||
71 | Debug.Assert( argc > 1 ); |
||
72 | mask = (int)sqlite3_user_data( context ) == 0 ? 0 : -1; |
||
73 | pColl = sqlite3GetFuncCollSeq( context ); |
||
74 | Debug.Assert( pColl != null ); |
||
75 | Debug.Assert( mask == -1 || mask == 0 ); |
||
76 | testcase( mask == 0 ); |
||
77 | iBest = 0; |
||
78 | if ( sqlite3_value_type( argv[0] ) == SQLITE_NULL ) |
||
79 | return; |
||
80 | for ( i = 1; i < argc; i++ ) |
||
81 | { |
||
82 | if ( sqlite3_value_type( argv[i] ) == SQLITE_NULL ) |
||
83 | return; |
||
84 | if ( ( sqlite3MemCompare( argv[iBest], argv[i], pColl ) ^ mask ) >= 0 ) |
||
85 | { |
||
86 | iBest = i; |
||
87 | } |
||
88 | } |
||
89 | sqlite3_result_value( context, argv[iBest] ); |
||
90 | } |
||
91 | |||
92 | /* |
||
93 | ** Return the type of the argument. |
||
94 | */ |
||
95 | static void typeofFunc( |
||
96 | sqlite3_context context, |
||
97 | int NotUsed, |
||
98 | sqlite3_value[] argv |
||
99 | ) |
||
100 | { |
||
101 | string z = string.Empty; |
||
102 | UNUSED_PARAMETER( NotUsed ); |
||
103 | switch ( sqlite3_value_type( argv[0] ) ) |
||
104 | { |
||
105 | case SQLITE_INTEGER: |
||
106 | z = "integer"; |
||
107 | break; |
||
108 | case SQLITE_TEXT: |
||
109 | z = "text"; |
||
110 | break; |
||
111 | case SQLITE_FLOAT: |
||
112 | z = "real"; |
||
113 | break; |
||
114 | case SQLITE_BLOB: |
||
115 | z = "blob"; |
||
116 | break; |
||
117 | default: |
||
118 | z = "null"; |
||
119 | break; |
||
120 | } |
||
121 | sqlite3_result_text( context, z, -1, SQLITE_STATIC ); |
||
122 | } |
||
123 | |||
124 | |||
125 | /* |
||
126 | ** Implementation of the length() function |
||
127 | */ |
||
128 | static void lengthFunc( |
||
129 | sqlite3_context context, |
||
130 | int argc, |
||
131 | sqlite3_value[] argv |
||
132 | ) |
||
133 | { |
||
134 | int len; |
||
135 | |||
136 | Debug.Assert( argc == 1 ); |
||
137 | UNUSED_PARAMETER( argc ); |
||
138 | switch ( sqlite3_value_type( argv[0] ) ) |
||
139 | { |
||
140 | case SQLITE_BLOB: |
||
141 | case SQLITE_INTEGER: |
||
142 | case SQLITE_FLOAT: |
||
143 | { |
||
144 | sqlite3_result_int( context, sqlite3_value_bytes( argv[0] ) ); |
||
145 | break; |
||
146 | } |
||
147 | case SQLITE_TEXT: |
||
148 | { |
||
149 | byte[] z = sqlite3_value_blob( argv[0] ); |
||
150 | if ( z == null ) |
||
151 | return; |
||
152 | len = 0; |
||
153 | int iz = 0; |
||
154 | while ( iz < z.Length && z[iz] != '\0' ) |
||
155 | { |
||
156 | len++; |
||
157 | SQLITE_SKIP_UTF8( z, ref iz ); |
||
158 | } |
||
159 | sqlite3_result_int( context, len ); |
||
160 | break; |
||
161 | } |
||
162 | default: |
||
163 | { |
||
164 | sqlite3_result_null( context ); |
||
165 | break; |
||
166 | } |
||
167 | } |
||
168 | } |
||
169 | |||
170 | /* |
||
171 | ** Implementation of the abs() function. |
||
172 | ** |
||
173 | ** IMP: R-23979-26855 The abs(X) function returns the absolute value of |
||
174 | ** the numeric argument X. |
||
175 | */ |
||
176 | static void absFunc( |
||
177 | sqlite3_context context, |
||
178 | int argc, |
||
179 | sqlite3_value[] argv |
||
180 | ) |
||
181 | { |
||
182 | Debug.Assert( argc == 1 ); |
||
183 | UNUSED_PARAMETER( argc ); |
||
184 | switch ( sqlite3_value_type( argv[0] ) ) |
||
185 | { |
||
186 | case SQLITE_INTEGER: |
||
187 | { |
||
188 | i64 iVal = sqlite3_value_int64( argv[0] ); |
||
189 | if ( iVal < 0 ) |
||
190 | { |
||
191 | if ( ( iVal << 1 ) == 0 ) |
||
192 | { |
||
193 | /* IMP: R-35460-15084 If X is the integer -9223372036854775807 then |
||
194 | ** abs(X) throws an integer overflow error since there is no |
||
195 | ** equivalent positive 64-bit two complement value. */ |
||
196 | sqlite3_result_error( context, "integer overflow", -1 ); |
||
197 | return; |
||
198 | } |
||
199 | iVal = -iVal; |
||
200 | } |
||
201 | sqlite3_result_int64( context, iVal ); |
||
202 | break; |
||
203 | } |
||
204 | case SQLITE_NULL: |
||
205 | { |
||
206 | /* IMP: R-37434-19929 Abs(X) returns NULL if X is NULL. */ |
||
207 | sqlite3_result_null( context ); |
||
208 | break; |
||
209 | } |
||
210 | default: |
||
211 | { |
||
212 | /* Because sqlite3_value_double() returns 0.0 if the argument is not |
||
213 | ** something that can be converted into a number, we have: |
||
214 | ** IMP: R-57326-31541 Abs(X) return 0.0 if X is a string or blob that |
||
215 | ** cannot be converted to a numeric value. |
||
216 | */ |
||
217 | double rVal = sqlite3_value_double( argv[0] ); |
||
218 | if ( rVal < 0 ) |
||
219 | rVal = -rVal; |
||
220 | sqlite3_result_double( context, rVal ); |
||
221 | break; |
||
222 | } |
||
223 | } |
||
224 | } |
||
225 | |||
226 | /* |
||
227 | ** Implementation of the substr() function. |
||
228 | ** |
||
229 | ** substr(x,p1,p2) returns p2 characters of x[] beginning with p1. |
||
230 | ** p1 is 1-indexed. So substr(x,1,1) returns the first character |
||
231 | ** of x. If x is text, then we actually count UTF-8 characters. |
||
232 | ** If x is a blob, then we count bytes. |
||
233 | ** |
||
234 | ** If p1 is negative, then we begin abs(p1) from the end of x[]. |
||
235 | ** |
||
236 | ** If p2 is negative, return the p2 characters preceeding p1. |
||
237 | */ |
||
238 | static void substrFunc( |
||
239 | sqlite3_context context, |
||
240 | int argc, |
||
241 | sqlite3_value[] argv |
||
242 | ) |
||
243 | { |
||
244 | string z = string.Empty; |
||
245 | byte[] zBLOB = null; |
||
246 | string z2; |
||
247 | int len; |
||
248 | int p0type; |
||
249 | int p1, p2; |
||
250 | int negP2 = 0; |
||
251 | |||
252 | Debug.Assert( argc == 3 || argc == 2 ); |
||
253 | if ( sqlite3_value_type( argv[1] ) == SQLITE_NULL |
||
254 | || ( argc == 3 && sqlite3_value_type( argv[2] ) == SQLITE_NULL ) |
||
255 | ) |
||
256 | { |
||
257 | return; |
||
258 | } |
||
259 | p0type = sqlite3_value_type( argv[0] ); |
||
260 | p1 = sqlite3_value_int( argv[1] ); |
||
261 | if ( p0type == SQLITE_BLOB ) |
||
262 | { |
||
263 | len = sqlite3_value_bytes( argv[0] ); |
||
264 | zBLOB = argv[0].zBLOB; |
||
265 | if ( zBLOB == null ) |
||
266 | return; |
||
267 | Debug.Assert( len == zBLOB.Length ); |
||
268 | } |
||
269 | else |
||
270 | { |
||
271 | z = sqlite3_value_text( argv[0] ); |
||
272 | if ( string.IsNullOrEmpty( z ) ) |
||
273 | return; |
||
274 | len = 0; |
||
275 | if ( p1 < 0 ) |
||
276 | { |
||
277 | len = z.Length; |
||
278 | //for ( z2 = z ; z2 != "" ; len++ ) |
||
279 | //{ |
||
280 | // SQLITE_SKIP_UTF8( ref z2 ); |
||
281 | //} |
||
282 | } |
||
283 | } |
||
284 | if ( argc == 3 ) |
||
285 | { |
||
286 | p2 = sqlite3_value_int( argv[2] ); |
||
287 | if ( p2 < 0 ) |
||
288 | { |
||
289 | p2 = -p2; |
||
290 | negP2 = 1; |
||
291 | } |
||
292 | } |
||
293 | else |
||
294 | { |
||
295 | p2 = ( sqlite3_context_db_handle( context ) ).aLimit[SQLITE_LIMIT_LENGTH]; |
||
296 | } |
||
297 | if ( p1 < 0 ) |
||
298 | { |
||
299 | p1 += len; |
||
300 | if ( p1 < 0 ) |
||
301 | { |
||
302 | p2 += p1; |
||
303 | if ( p2 < 0 ) |
||
304 | p2 = 0; |
||
305 | p1 = 0; |
||
306 | } |
||
307 | } |
||
308 | else if ( p1 > 0 ) |
||
309 | { |
||
310 | p1--; |
||
311 | } |
||
312 | else if ( p2 > 0 ) |
||
313 | { |
||
314 | p2--; |
||
315 | } |
||
316 | if ( negP2 != 0 ) |
||
317 | { |
||
318 | p1 -= p2; |
||
319 | if ( p1 < 0 ) |
||
320 | { |
||
321 | p2 += p1; |
||
322 | p1 = 0; |
||
323 | } |
||
324 | } |
||
325 | Debug.Assert( p1 >= 0 && p2 >= 0 ); |
||
326 | if ( p0type != SQLITE_BLOB ) |
||
327 | { |
||
328 | //while ( z != "" && p1 != 0 ) |
||
329 | //{ |
||
330 | // SQLITE_SKIP_UTF8( ref z ); |
||
331 | // p1--; |
||
332 | //} |
||
333 | //for ( z2 = z ; z2 != "" && p2 != 0 ; p2-- ) |
||
334 | //{ |
||
335 | // SQLITE_SKIP_UTF8( ref z2 ); |
||
336 | //} |
||
337 | sqlite3_result_text( context, z, p1, p2 <= z.Length - p1 ? p2 : z.Length - p1, SQLITE_TRANSIENT ); |
||
338 | } |
||
339 | else |
||
340 | { |
||
341 | if ( p1 + p2 > len ) |
||
342 | { |
||
343 | p2 = len - p1; |
||
344 | if ( p2 < 0 ) |
||
345 | p2 = 0; |
||
346 | } |
||
347 | StringBuilder sb = new StringBuilder( zBLOB.Length ); |
||
348 | if ( zBLOB.Length == 0 || p1 > zBLOB.Length ) |
||
349 | sb.Length = 0; |
||
350 | else |
||
351 | { |
||
352 | for ( int i = p1; i < p1 + p2; i++ ) |
||
353 | { |
||
354 | sb.Append( (char)zBLOB[i] ); |
||
355 | } |
||
356 | } |
||
357 | |||
358 | sqlite3_result_blob( context, sb.ToString(), (int)p2, SQLITE_TRANSIENT ); |
||
359 | } |
||
360 | } |
||
361 | |||
362 | /* |
||
363 | ** Implementation of the round() function |
||
364 | */ |
||
365 | #if !SQLITE_OMIT_FLOATING_POINT |
||
366 | static void roundFunc( |
||
367 | sqlite3_context context, |
||
368 | int argc, |
||
369 | sqlite3_value[] argv |
||
370 | ) |
||
371 | { |
||
372 | int n = 0; |
||
373 | double r; |
||
374 | string zBuf = string.Empty; |
||
375 | Debug.Assert( argc == 1 || argc == 2 ); |
||
376 | if ( argc == 2 ) |
||
377 | { |
||
378 | if ( SQLITE_NULL == sqlite3_value_type( argv[1] ) ) |
||
379 | return; |
||
380 | n = sqlite3_value_int( argv[1] ); |
||
381 | if ( n > 30 ) |
||
382 | n = 30; |
||
383 | if ( n < 0 ) |
||
384 | n = 0; |
||
385 | } |
||
386 | if ( sqlite3_value_type( argv[0] ) == SQLITE_NULL ) |
||
387 | return; |
||
388 | r = sqlite3_value_double( argv[0] ); |
||
389 | /* If Y==0 and X will fit in a 64-bit int, |
||
390 | ** handle the rounding directly, |
||
391 | ** otherwise use printf. |
||
392 | */ |
||
393 | if ( n == 0 && r >= 0 && r < LARGEST_INT64 - 1 ) |
||
394 | { |
||
395 | r = (double)( (sqlite_int64)( r + 0.5 ) ); |
||
396 | } |
||
397 | else if ( n == 0 && r < 0 && ( -r ) < LARGEST_INT64 - 1 ) |
||
398 | { |
||
399 | r = -(double)( (sqlite_int64)( ( -r ) + 0.5 ) ); |
||
400 | } |
||
401 | else |
||
402 | { |
||
403 | zBuf = sqlite3_mprintf( "%.*f", n, r ); |
||
404 | if ( zBuf == null ) |
||
405 | { |
||
406 | sqlite3_result_error_nomem( context ); |
||
407 | return; |
||
408 | } |
||
409 | sqlite3AtoF( zBuf, ref r, sqlite3Strlen30( zBuf ), SQLITE_UTF8 ); |
||
410 | //sqlite3_free( ref zBuf ); |
||
411 | } |
||
412 | sqlite3_result_double( context, r ); |
||
413 | } |
||
414 | #endif |
||
415 | |||
416 | /* |
||
417 | ** Allocate nByte bytes of space using sqlite3_malloc(). If the |
||
418 | ** allocation fails, call sqlite3_result_error_nomem() to notify |
||
419 | ** the database handle that malloc() has failed and return NULL. |
||
420 | ** If nByte is larger than the maximum string or blob length, then |
||
421 | ** raise an SQLITE_TOOBIG exception and return NULL. |
||
422 | */ |
||
423 | //static void* contextMalloc( sqlite3_context* context, i64 nByte ) |
||
424 | //{ |
||
425 | // char* z; |
||
426 | // sqlite3* db = sqlite3_context_db_handle( context ); |
||
427 | // assert( nByte > 0 ); |
||
428 | // testcase( nByte == db->aLimit[SQLITE_LIMIT_LENGTH] ); |
||
429 | // testcase( nByte == db->aLimit[SQLITE_LIMIT_LENGTH] + 1 ); |
||
430 | // if ( nByte > db->aLimit[SQLITE_LIMIT_LENGTH] ) |
||
431 | // { |
||
432 | // sqlite3_result_error_toobig( context ); |
||
433 | // z = 0; |
||
434 | // } |
||
435 | // else |
||
436 | // { |
||
437 | // z = sqlite3Malloc( (int)nByte ); |
||
438 | // if ( !z ) |
||
439 | // { |
||
440 | // sqlite3_result_error_nomem( context ); |
||
441 | // } |
||
442 | // } |
||
443 | // return z; |
||
444 | //} |
||
445 | |||
446 | /* |
||
447 | ** Implementation of the upper() and lower() SQL functions. |
||
448 | */ |
||
449 | static void upperFunc( |
||
450 | sqlite3_context context, |
||
451 | int argc, |
||
452 | sqlite3_value[] argv |
||
453 | ) |
||
454 | { |
||
455 | string z1; |
||
456 | string z2; |
||
457 | int i, n; |
||
458 | UNUSED_PARAMETER( argc ); |
||
459 | z2 = sqlite3_value_text( argv[0] ); |
||
460 | n = sqlite3_value_bytes( argv[0] ); |
||
461 | /* Verify that the call to _bytes() does not invalidate the _text() pointer */ |
||
462 | //Debug.Assert( z2 == sqlite3_value_text( argv[0] ) ); |
||
463 | if ( z2 != null ) |
||
464 | { |
||
465 | //z1 = new byte[n];// contextMalloc(context, ((i64)n)+1); |
||
466 | //if ( z1 !=null) |
||
467 | //{ |
||
468 | // memcpy( z1, z2, n + 1 ); |
||
469 | //for ( i = 0 ; i< z1.Length ; i++ ) |
||
470 | //{ |
||
471 | //(char)sqlite3Toupper( z1[i] ); |
||
472 | //} |
||
473 | sqlite3_result_text( context, z2.Length == 0 ? string.Empty : z2.Substring( 0, n ).ToUpper(), -1, null ); //sqlite3_free ); |
||
474 | // } |
||
475 | } |
||
476 | } |
||
477 | |||
478 | static void lowerFunc( |
||
479 | sqlite3_context context, |
||
480 | int argc, |
||
481 | sqlite3_value[] argv |
||
482 | ) |
||
483 | { |
||
484 | string z1; |
||
485 | string z2; |
||
486 | int i, n; |
||
487 | UNUSED_PARAMETER( argc ); |
||
488 | z2 = sqlite3_value_text( argv[0] ); |
||
489 | n = sqlite3_value_bytes( argv[0] ); |
||
490 | /* Verify that the call to _bytes() does not invalidate the _text() pointer */ |
||
491 | //Debug.Assert( z2 == sqlite3_value_text( argv[0] ) ); |
||
492 | if ( z2 != null ) |
||
493 | { |
||
494 | //z1 = contextMalloc(context, ((i64)n)+1); |
||
495 | //if ( z1 ) |
||
496 | //{ |
||
497 | // memcpy( z1, z2, n + 1 ); |
||
498 | // for ( i = 0 ; z1[i] ; i++ ) |
||
499 | // { |
||
500 | // z1[i] = (char)sqlite3Tolower( z1[i] ); |
||
501 | // } |
||
502 | sqlite3_result_text( context, z2.Length == 0 ? string.Empty : z2.Substring( 0, n ).ToLower(), -1, null );//sqlite3_free ); |
||
503 | //} |
||
504 | } |
||
505 | } |
||
506 | |||
507 | #if FALSE //* This function is never used. */ |
||
508 | /* |
||
509 | ** The COALESCE() and IFNULL() functions used to be implemented as shown |
||
510 | ** here. But now they are implemented as VDBE code so that unused arguments |
||
511 | ** do not have to be computed. This legacy implementation is retained as |
||
512 | ** comment. |
||
513 | */ |
||
514 | /* |
||
515 | ** Implementation of the IFNULL(), NVL(), and COALESCE() functions. |
||
516 | ** All three do the same thing. They return the first non-NULL |
||
517 | ** argument. |
||
518 | */ |
||
519 | static void ifnullFunc( |
||
520 | sqlite3_context context, |
||
521 | int argc, |
||
522 | sqlite3_value[] argv |
||
523 | ) |
||
524 | { |
||
525 | int i; |
||
526 | for ( i = 0 ; i < argc ; i++ ) |
||
527 | { |
||
528 | if ( SQLITE_NULL != sqlite3_value_type( argv[i] ) ) |
||
529 | { |
||
530 | sqlite3_result_value( context, argv[i] ); |
||
531 | break; |
||
532 | } |
||
533 | } |
||
534 | } |
||
535 | #endif //* NOT USED */ |
||
536 | //#define ifnullFunc versionFunc /* Substitute function - never called */ |
||
537 | |||
538 | /* |
||
539 | ** Implementation of random(). Return a random integer. |
||
540 | */ |
||
541 | static void randomFunc( |
||
542 | sqlite3_context context, |
||
543 | int NotUsed, |
||
544 | sqlite3_value[] NotUsed2 |
||
545 | ) |
||
546 | { |
||
547 | sqlite_int64 r = 0; |
||
548 | UNUSED_PARAMETER2( NotUsed, NotUsed2 ); |
||
549 | sqlite3_randomness( sizeof( sqlite_int64 ), ref r ); |
||
550 | if ( r < 0 ) |
||
551 | { |
||
552 | /* We need to prevent a random number of 0x8000000000000000 |
||
553 | ** (or -9223372036854775808) since when you do abs() of that |
||
554 | ** number of you get the same value back again. To do this |
||
555 | ** in a way that is testable, mask the sign bit off of negative |
||
556 | ** values, resulting in a positive value. Then take the |
||
557 | ** 2s complement of that positive value. The end result can |
||
558 | ** therefore be no less than -9223372036854775807. |
||
559 | */ |
||
560 | r = -( r ^ ( ( (sqlite3_int64)1 ) << 63 ) ); |
||
561 | } |
||
562 | sqlite3_result_int64( context, r ); |
||
563 | } |
||
564 | |||
565 | /* |
||
566 | ** Implementation of randomblob(N). Return a random blob |
||
567 | ** that is N bytes long. |
||
568 | */ |
||
569 | static void randomBlob( |
||
570 | sqlite3_context context, |
||
571 | int argc, |
||
572 | sqlite3_value[] argv |
||
573 | ) |
||
574 | { |
||
575 | int n; |
||
576 | char[] p; |
||
577 | Debug.Assert( argc == 1 ); |
||
578 | UNUSED_PARAMETER( argc ); |
||
579 | n = sqlite3_value_int( argv[0] ); |
||
580 | if ( n < 1 ) |
||
581 | { |
||
582 | n = 1; |
||
583 | } |
||
584 | if ( n > sqlite3_context_db_handle(context).aLimit[SQLITE_LIMIT_LENGTH] ) |
||
585 | { |
||
586 | sqlite3_result_error_toobig( context ); |
||
587 | p = null; |
||
588 | } |
||
589 | else |
||
590 | { |
||
591 | p = new char[n]; //contextMalloc( context, n ); |
||
592 | } |
||
593 | if ( p != null ) |
||
594 | { |
||
595 | i64 _p = 0; |
||
596 | for ( int i = 0; i < n; i++ ) |
||
597 | { |
||
598 | sqlite3_randomness( sizeof( u8 ), ref _p ); |
||
599 | p[i] = (char)( _p & 0x7F ); |
||
600 | } |
||
601 | sqlite3_result_blob( context, new string( p ), n, null );//sqlite3_free ); |
||
602 | } |
||
603 | } |
||
604 | |||
605 | /* |
||
606 | ** Implementation of the last_insert_rowid() SQL function. The return |
||
607 | ** value is the same as the sqlite3_last_insert_rowid() API function. |
||
608 | */ |
||
609 | static void last_insert_rowid( |
||
610 | sqlite3_context context, |
||
611 | int NotUsed, |
||
612 | sqlite3_value[] NotUsed2 |
||
613 | ) |
||
614 | { |
||
615 | sqlite3 db = sqlite3_context_db_handle( context ); |
||
616 | UNUSED_PARAMETER2( NotUsed, NotUsed2 ); |
||
617 | /* IMP: R-51513-12026 The last_insert_rowid() SQL function is a |
||
618 | ** wrapper around the sqlite3_last_insert_rowid() C/C++ interface |
||
619 | ** function. */ |
||
620 | sqlite3_result_int64( context, sqlite3_last_insert_rowid( db ) ); |
||
621 | } |
||
622 | |||
623 | /* |
||
624 | ** Implementation of the changes() SQL function. |
||
625 | ** |
||
626 | ** IMP: R-62073-11209 The changes() SQL function is a wrapper |
||
627 | ** around the sqlite3_changes() C/C++ function and hence follows the same |
||
628 | ** rules for counting changes. |
||
629 | */ |
||
630 | static void changes( |
||
631 | sqlite3_context context, |
||
632 | int NotUsed, |
||
633 | sqlite3_value[] NotUsed2 |
||
634 | ) |
||
635 | { |
||
636 | sqlite3 db = sqlite3_context_db_handle( context ); |
||
637 | UNUSED_PARAMETER2( NotUsed, NotUsed2 ); |
||
638 | sqlite3_result_int( context, sqlite3_changes( db ) ); |
||
639 | } |
||
640 | |||
641 | /* |
||
642 | ** Implementation of the total_changes() SQL function. The return value is |
||
643 | ** the same as the sqlite3_total_changes() API function. |
||
644 | */ |
||
645 | static void total_changes( |
||
646 | sqlite3_context context, |
||
647 | int NotUsed, |
||
648 | sqlite3_value[] NotUsed2 |
||
649 | ) |
||
650 | { |
||
651 | sqlite3 db = (sqlite3)sqlite3_context_db_handle( context ); |
||
652 | UNUSED_PARAMETER2( NotUsed, NotUsed2 ); |
||
653 | /* IMP: R-52756-41993 This function is a wrapper around the |
||
654 | ** sqlite3_total_changes() C/C++ interface. */ |
||
655 | sqlite3_result_int( context, sqlite3_total_changes( db ) ); |
||
656 | } |
||
657 | |||
658 | /* |
||
659 | ** A structure defining how to do GLOB-style comparisons. |
||
660 | */ |
||
661 | struct compareInfo |
||
662 | { |
||
663 | public char matchAll; |
||
664 | public char matchOne; |
||
665 | public char matchSet; |
||
666 | public bool noCase; |
||
667 | public compareInfo( char matchAll, char matchOne, char matchSet, bool noCase ) |
||
668 | { |
||
669 | this.matchAll = matchAll; |
||
670 | this.matchOne = matchOne; |
||
671 | this.matchSet = matchSet; |
||
672 | this.noCase = noCase; |
||
673 | } |
||
674 | }; |
||
675 | |||
676 | /* |
||
677 | ** For LIKE and GLOB matching on EBCDIC machines, assume that every |
||
678 | ** character is exactly one byte in size. Also, all characters are |
||
679 | ** able to participate in upper-case-to-lower-case mappings in EBCDIC |
||
680 | ** whereas only characters less than 0x80 do in ASCII. |
||
681 | */ |
||
682 | //#if defined(SQLITE_EBCDIC) |
||
683 | //# define sqlite3Utf8Read(A,C) (*(A++)) |
||
684 | //# define GlogUpperToLower(A) A = sqlite3UpperToLower[A] |
||
685 | //#else |
||
686 | //# define GlogUpperToLower(A) if( !((A)&~0x7f) ){ A = sqlite3UpperToLower[A]; } |
||
687 | //#endif |
||
688 | |||
689 | static compareInfo globInfo = new compareInfo( '*', '?', '[', false ); |
||
690 | /* The correct SQL-92 behavior is for the LIKE operator to ignore |
||
691 | ** case. Thus 'a' LIKE 'A' would be true. */ |
||
692 | static compareInfo likeInfoNorm = new compareInfo( '%', '_', '\0', true ); |
||
693 | /* If SQLITE_CASE_SENSITIVE_LIKE is defined, then the LIKE operator |
||
694 | ** is case sensitive causing 'a' LIKE 'A' to be false */ |
||
695 | static compareInfo likeInfoAlt = new compareInfo( '%', '_', '\0', false ); |
||
696 | |||
697 | /* |
||
698 | ** Compare two UTF-8 strings for equality where the first string can |
||
699 | ** potentially be a "glob" expression. Return true (1) if they |
||
700 | ** are the same and false (0) if they are different. |
||
701 | ** |
||
702 | ** Globbing rules: |
||
703 | ** |
||
704 | ** '*' Matches any sequence of zero or more characters. |
||
705 | ** |
||
706 | ** '?' Matches exactly one character. |
||
707 | ** |
||
708 | ** [...] Matches one character from the enclosed list of |
||
709 | ** characters. |
||
710 | ** |
||
711 | ** [^...] Matches one character not in the enclosed list. |
||
712 | ** |
||
713 | ** With the [...] and [^...] matching, a ']' character can be included |
||
714 | ** in the list by making it the first character after '[' or '^'. A |
||
715 | ** range of characters can be specified using '-'. Example: |
||
716 | ** "[a-z]" matches any single lower-case letter. To match a '-', make |
||
717 | ** it the last character in the list. |
||
718 | ** |
||
719 | ** This routine is usually quick, but can be N**2 in the worst case. |
||
720 | ** |
||
721 | ** Hints: to match '*' or '?', put them in "[]". Like this: |
||
722 | ** |
||
723 | ** abc[*]xyz Matches "abc*xyz" only |
||
724 | */ |
||
725 | static bool patternCompare( |
||
726 | string zPattern, /* The glob pattern */ |
||
727 | string zString, /* The string to compare against the glob */ |
||
728 | compareInfo pInfo, /* Information about how to do the compare */ |
||
729 | u32 esc /* The escape character */ |
||
730 | ) |
||
731 | { |
||
732 | u32 c, c2; |
||
733 | int invert; |
||
734 | int seen; |
||
735 | int matchOne = (int)pInfo.matchOne; |
||
736 | int matchAll = (int)pInfo.matchAll; |
||
737 | int matchSet = (int)pInfo.matchSet; |
||
738 | bool noCase = pInfo.noCase; |
||
739 | bool prevEscape = false; /* True if the previous character was 'escape' */ |
||
740 | string inPattern = zPattern; //Entered Pattern |
||
741 | |||
742 | while ( ( c = sqlite3Utf8Read( zPattern, ref zPattern ) ) != 0 ) |
||
743 | { |
||
744 | if ( !prevEscape && c == matchAll ) |
||
745 | { |
||
746 | while ( ( c = sqlite3Utf8Read( zPattern, ref zPattern ) ) == matchAll |
||
747 | || c == matchOne ) |
||
748 | { |
||
749 | if ( c == matchOne && sqlite3Utf8Read( zString, ref zString ) == 0 ) |
||
750 | { |
||
751 | return false; |
||
752 | } |
||
753 | } |
||
754 | if ( c == 0 ) |
||
755 | { |
||
756 | return true; |
||
757 | } |
||
758 | else if ( c == esc ) |
||
759 | { |
||
760 | c = sqlite3Utf8Read( zPattern, ref zPattern ); |
||
761 | if ( c == 0 ) |
||
762 | { |
||
763 | return false; |
||
764 | } |
||
765 | } |
||
766 | else if ( c == matchSet ) |
||
767 | { |
||
768 | Debug.Assert( esc == 0 ); /* This is GLOB, not LIKE */ |
||
769 | Debug.Assert( matchSet < 0x80 ); /* '[' is a single-byte character */ |
||
770 | int len = 0; |
||
771 | while ( len < zString.Length && patternCompare( inPattern.Substring( inPattern.Length - zPattern.Length - 1 ), zString.Substring( len ), pInfo, esc ) == false ) |
||
772 | { |
||
773 | SQLITE_SKIP_UTF8( zString, ref len ); |
||
774 | } |
||
775 | return len < zString.Length; |
||
776 | } |
||
777 | while ( ( c2 = sqlite3Utf8Read( zString, ref zString ) ) != 0 ) |
||
778 | { |
||
779 | if ( noCase ) |
||
780 | { |
||
781 | if( 0==((c2)&~0x7f) ) |
||
782 | c2 = (u32)sqlite3UpperToLower[c2]; //GlogUpperToLower(c2); |
||
783 | if ( 0 == ( ( c ) & ~0x7f ) ) |
||
784 | c = (u32)sqlite3UpperToLower[c]; //GlogUpperToLower(c); |
||
785 | while ( c2 != 0 && c2 != c ) |
||
786 | { |
||
787 | c2 = sqlite3Utf8Read( zString, ref zString ); |
||
788 | if ( 0 == ( ( c2 ) & ~0x7f ) ) |
||
789 | c2 = (u32)sqlite3UpperToLower[c2]; //GlogUpperToLower(c2); |
||
790 | } |
||
791 | } |
||
792 | else |
||
793 | { |
||
794 | while ( c2 != 0 && c2 != c ) |
||
795 | { |
||
796 | c2 = sqlite3Utf8Read( zString, ref zString ); |
||
797 | } |
||
798 | } |
||
799 | if ( c2 == 0 ) |
||
800 | return false; |
||
801 | if ( patternCompare( zPattern, zString, pInfo, esc ) ) |
||
802 | return true; |
||
803 | } |
||
804 | return false; |
||
805 | } |
||
806 | else if ( !prevEscape && c == matchOne ) |
||
807 | { |
||
808 | if ( sqlite3Utf8Read( zString, ref zString ) == 0 ) |
||
809 | { |
||
810 | return false; |
||
811 | } |
||
812 | } |
||
813 | else if ( c == matchSet ) |
||
814 | { |
||
815 | u32 prior_c = 0; |
||
816 | Debug.Assert( esc == 0 ); /* This only occurs for GLOB, not LIKE */ |
||
817 | seen = 0; |
||
818 | invert = 0; |
||
819 | c = sqlite3Utf8Read( zString, ref zString ); |
||
820 | if ( c == 0 ) |
||
821 | return false; |
||
822 | c2 = sqlite3Utf8Read( zPattern, ref zPattern ); |
||
823 | if ( c2 == '^' ) |
||
824 | { |
||
825 | invert = 1; |
||
826 | c2 = sqlite3Utf8Read( zPattern, ref zPattern ); |
||
827 | } |
||
828 | if ( c2 == ']' ) |
||
829 | { |
||
830 | if ( c == ']' ) |
||
831 | seen = 1; |
||
832 | c2 = sqlite3Utf8Read( zPattern, ref zPattern ); |
||
833 | } |
||
834 | while ( c2 != 0 && c2 != ']' ) |
||
835 | { |
||
836 | if ( c2 == '-' && zPattern[0] != ']' && zPattern[0] != 0 && prior_c > 0 ) |
||
837 | { |
||
838 | c2 = sqlite3Utf8Read( zPattern, ref zPattern ); |
||
839 | if ( c >= prior_c && c <= c2 ) |
||
840 | seen = 1; |
||
841 | prior_c = 0; |
||
842 | } |
||
843 | else |
||
844 | { |
||
845 | if ( c == c2 ) |
||
846 | { |
||
847 | seen = 1; |
||
848 | } |
||
849 | prior_c = c2; |
||
850 | } |
||
851 | c2 = sqlite3Utf8Read( zPattern, ref zPattern ); |
||
852 | } |
||
853 | if ( c2 == 0 || ( seen ^ invert ) == 0 ) |
||
854 | { |
||
855 | return false; |
||
856 | } |
||
857 | } |
||
858 | else if ( esc == c && !prevEscape ) |
||
859 | { |
||
860 | prevEscape = true; |
||
861 | } |
||
862 | else |
||
863 | { |
||
864 | c2 = sqlite3Utf8Read( zString, ref zString ); |
||
865 | if ( noCase ) |
||
866 | { |
||
867 | if ( c < 0x80 ) |
||
868 | c = (u32)sqlite3UpperToLower[c]; //GlogUpperToLower(c); |
||
869 | if ( c2 < 0x80 ) |
||
870 | c2 = (u32)sqlite3UpperToLower[c2]; //GlogUpperToLower(c2); |
||
871 | } |
||
872 | if ( c != c2 ) |
||
873 | { |
||
874 | return false; |
||
875 | } |
||
876 | prevEscape = false; |
||
877 | } |
||
878 | } |
||
879 | return zString.Length == 0; |
||
880 | } |
||
881 | |||
882 | /* |
||
883 | ** Count the number of times that the LIKE operator (or GLOB which is |
||
884 | ** just a variation of LIKE) gets called. This is used for testing |
||
885 | ** only. |
||
886 | */ |
||
887 | #if SQLITE_TEST |
||
888 | #if !TCLSH |
||
889 | static int sqlite3_like_count = 0; |
||
890 | #else |
||
891 | static tcl.lang.Var.SQLITE3_GETSET sqlite3_like_count = new tcl.lang.Var.SQLITE3_GETSET( "sqlite3_like_count" ); |
||
892 | #endif |
||
893 | #endif |
||
894 | |||
895 | |||
896 | /* |
||
897 | ** Implementation of the like() SQL function. This function implements |
||
898 | ** the build-in LIKE operator. The first argument to the function is the |
||
899 | ** pattern and the second argument is the string. So, the SQL statements: |
||
900 | ** |
||
901 | ** A LIKE B |
||
902 | ** |
||
903 | ** is implemented as like(B,A). |
||
904 | ** |
||
905 | ** This same function (with a different compareInfo structure) computes |
||
906 | ** the GLOB operator. |
||
907 | */ |
||
908 | static void likeFunc( |
||
909 | sqlite3_context context, |
||
910 | int argc, |
||
911 | sqlite3_value[] argv |
||
912 | ) |
||
913 | { |
||
914 | string zA, zB; |
||
915 | u32 escape = 0; |
||
916 | int nPat; |
||
917 | sqlite3 db = sqlite3_context_db_handle( context ); |
||
918 | |||
919 | zB = sqlite3_value_text( argv[0] ); |
||
920 | zA = sqlite3_value_text( argv[1] ); |
||
921 | |||
922 | /* Limit the length of the LIKE or GLOB pattern to avoid problems |
||
923 | ** of deep recursion and N*N behavior in patternCompare(). |
||
924 | */ |
||
925 | nPat = sqlite3_value_bytes( argv[0] ); |
||
926 | testcase( nPat == db.aLimit[SQLITE_LIMIT_LIKE_PATTERN_LENGTH] ); |
||
927 | testcase( nPat == db.aLimit[SQLITE_LIMIT_LIKE_PATTERN_LENGTH] + 1 ); |
||
928 | if ( nPat > db.aLimit[SQLITE_LIMIT_LIKE_PATTERN_LENGTH] ) |
||
929 | { |
||
930 | sqlite3_result_error( context, "LIKE or GLOB pattern too complex", -1 ); |
||
931 | return; |
||
932 | } |
||
933 | //Debug.Assert( zB == sqlite3_value_text( argv[0] ) ); /* Encoding did not change */ |
||
934 | |||
935 | if ( argc == 3 ) |
||
936 | { |
||
937 | /* The escape character string must consist of a single UTF-8 character. |
||
938 | ** Otherwise, return an error. |
||
939 | */ |
||
940 | string zEsc = sqlite3_value_text( argv[2] ); |
||
941 | if ( zEsc == null ) |
||
942 | return; |
||
943 | if ( sqlite3Utf8CharLen( zEsc, -1 ) != 1 ) |
||
944 | { |
||
945 | sqlite3_result_error( context, |
||
946 | "ESCAPE expression must be a single character", -1 ); |
||
947 | return; |
||
948 | } |
||
949 | escape = sqlite3Utf8Read( zEsc, ref zEsc ); |
||
950 | } |
||
951 | if ( zA != null && zB != null ) |
||
952 | { |
||
953 | compareInfo pInfo = (compareInfo)sqlite3_user_data( context ); |
||
954 | #if SQLITE_TEST |
||
955 | #if !TCLSH |
||
956 | sqlite3_like_count++; |
||
957 | #else |
||
958 | sqlite3_like_count.iValue++; |
||
959 | #endif |
||
960 | #endif |
||
961 | sqlite3_result_int( context, patternCompare( zB, zA, pInfo, escape ) ? 1 : 0 ); |
||
962 | } |
||
963 | } |
||
964 | |||
965 | /* |
||
966 | ** Implementation of the NULLIF(x,y) function. The result is the first |
||
967 | ** argument if the arguments are different. The result is NULL if the |
||
968 | ** arguments are equal to each other. |
||
969 | */ |
||
970 | static void nullifFunc( |
||
971 | sqlite3_context context, |
||
972 | int NotUsed, |
||
973 | sqlite3_value[] argv |
||
974 | ) |
||
975 | { |
||
976 | CollSeq pColl = sqlite3GetFuncCollSeq( context ); |
||
977 | UNUSED_PARAMETER( NotUsed ); |
||
978 | if ( sqlite3MemCompare( argv[0], argv[1], pColl ) != 0 ) |
||
979 | { |
||
980 | sqlite3_result_value( context, argv[0] ); |
||
981 | } |
||
982 | } |
||
983 | |||
984 | /* |
||
985 | ** Implementation of the sqlite_version() function. The result is the version |
||
986 | ** of the SQLite library that is running. |
||
987 | */ |
||
988 | static void versionFunc( |
||
989 | sqlite3_context context, |
||
990 | int NotUsed, |
||
991 | sqlite3_value[] NotUsed2 |
||
992 | ) |
||
993 | { |
||
994 | UNUSED_PARAMETER2( NotUsed, NotUsed2 ); |
||
995 | /* IMP: R-48699-48617 This function is an SQL wrapper around the |
||
996 | ** sqlite3_libversion() C-interface. */ |
||
997 | sqlite3_result_text( context, sqlite3_libversion(), -1, SQLITE_STATIC ); |
||
998 | } |
||
999 | |||
1000 | /* |
||
1001 | ** Implementation of the sqlite_source_id() function. The result is a string |
||
1002 | ** that identifies the particular version of the source code used to build |
||
1003 | ** SQLite. |
||
1004 | */ |
||
1005 | static void sourceidFunc( |
||
1006 | sqlite3_context context, |
||
1007 | int NotUsed, |
||
1008 | sqlite3_value[] NotUsed2 |
||
1009 | ) |
||
1010 | { |
||
1011 | UNUSED_PARAMETER2( NotUsed, NotUsed2 ); |
||
1012 | /* IMP: R-24470-31136 This function is an SQL wrapper around the |
||
1013 | ** sqlite3_sourceid() C interface. */ |
||
1014 | sqlite3_result_text( context, sqlite3_sourceid(), -1, SQLITE_STATIC ); |
||
1015 | } |
||
1016 | |||
1017 | /* |
||
1018 | ** Implementation of the sqlite_log() function. This is a wrapper around |
||
1019 | ** sqlite3_log(). The return value is NULL. The function exists purely for |
||
1020 | ** its side-effects. |
||
1021 | */ |
||
1022 | static void errlogFunc( |
||
1023 | sqlite3_context context, |
||
1024 | int argc, |
||
1025 | sqlite3_value[] argv |
||
1026 | ) |
||
1027 | { |
||
1028 | UNUSED_PARAMETER( argc ); |
||
1029 | UNUSED_PARAMETER( context ); |
||
1030 | sqlite3_log( sqlite3_value_int( argv[0] ), "%s", sqlite3_value_text( argv[1] ) ); |
||
1031 | } |
||
1032 | |||
1033 | /* |
||
1034 | ** Implementation of the sqlite_compileoption_used() function. |
||
1035 | ** The result is an integer that identifies if the compiler option |
||
1036 | ** was used to build SQLite. |
||
1037 | */ |
||
1038 | #if !SQLITE_OMIT_COMPILEOPTION_DIAGS |
||
1039 | static void compileoptionusedFunc( |
||
1040 | sqlite3_context context, |
||
1041 | int argc, |
||
1042 | sqlite3_value[] argv |
||
1043 | ) |
||
1044 | { |
||
1045 | string zOptName; |
||
1046 | Debug.Assert( argc == 1 ); |
||
1047 | UNUSED_PARAMETER( argc ); |
||
1048 | /* IMP: R-39564-36305 The sqlite_compileoption_used() SQL |
||
1049 | ** function is a wrapper around the sqlite3_compileoption_used() C/C++ |
||
1050 | ** function. |
||
1051 | */ |
||
1052 | if ( ( zOptName = sqlite3_value_text( argv[0] ) ) != null ) |
||
1053 | { |
||
1054 | sqlite3_result_int( context, sqlite3_compileoption_used( zOptName ) ); |
||
1055 | } |
||
1056 | } |
||
1057 | #endif //* SQLITE_OMIT_COMPILEOPTION_DIAGS */ |
||
1058 | |||
1059 | |||
1060 | /* |
||
1061 | ** Implementation of the sqlite_compileoption_get() function. |
||
1062 | ** The result is a string that identifies the compiler options |
||
1063 | ** used to build SQLite. |
||
1064 | */ |
||
1065 | #if !SQLITE_OMIT_COMPILEOPTION_DIAGS |
||
1066 | static void compileoptiongetFunc( |
||
1067 | sqlite3_context context, |
||
1068 | int argc, |
||
1069 | sqlite3_value[] argv |
||
1070 | ) |
||
1071 | { |
||
1072 | int n; |
||
1073 | Debug.Assert( argc == 1 ); |
||
1074 | UNUSED_PARAMETER( argc ); |
||
1075 | /* IMP: R-04922-24076 The sqlite_compileoption_get() SQL function |
||
1076 | ** is a wrapper around the sqlite3_compileoption_get() C/C++ function. |
||
1077 | */ |
||
1078 | n = sqlite3_value_int( argv[0] ); |
||
1079 | sqlite3_result_text( context, sqlite3_compileoption_get( n ), -1, SQLITE_STATIC ); |
||
1080 | } |
||
1081 | #endif //* SQLITE_OMIT_COMPILEOPTION_DIAGS */ |
||
1082 | |||
1083 | /* Array for converting from half-bytes (nybbles) into ASCII hex |
||
1084 | ** digits. */ |
||
1085 | static char[] hexdigits = new char[] { |
||
1086 | '0', '1', '2', '3', '4', '5', '6', '7', |
||
1087 | '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' |
||
1088 | }; |
||
1089 | |||
1090 | /* |
||
1091 | ** EXPERIMENTAL - This is not an official function. The interface may |
||
1092 | ** change. This function may disappear. Do not write code that depends |
||
1093 | ** on this function. |
||
1094 | ** |
||
1095 | ** Implementation of the QUOTE() function. This function takes a single |
||
1096 | ** argument. If the argument is numeric, the return value is the same as |
||
1097 | ** the argument. If the argument is NULL, the return value is the string |
||
1098 | ** "NULL". Otherwise, the argument is enclosed in single quotes with |
||
1099 | ** single-quote escapes. |
||
1100 | */ |
||
1101 | static void quoteFunc( |
||
1102 | sqlite3_context context, |
||
1103 | int argc, |
||
1104 | sqlite3_value[] argv |
||
1105 | ) |
||
1106 | { |
||
1107 | Debug.Assert( argc == 1 ); |
||
1108 | UNUSED_PARAMETER( argc ); |
||
1109 | |||
1110 | switch ( sqlite3_value_type( argv[0] ) ) |
||
1111 | { |
||
1112 | case SQLITE_INTEGER: |
||
1113 | case SQLITE_FLOAT: |
||
1114 | { |
||
1115 | sqlite3_result_value( context, argv[0] ); |
||
1116 | break; |
||
1117 | } |
||
1118 | case SQLITE_BLOB: |
||
1119 | { |
||
1120 | StringBuilder zText; |
||
1121 | byte[] zBlob = sqlite3_value_blob( argv[0] ); |
||
1122 | int nBlob = sqlite3_value_bytes( argv[0] ); |
||
1123 | Debug.Assert( zBlob.Length == sqlite3_value_blob( argv[0] ).Length ); /* No encoding change */ |
||
1124 | zText = new StringBuilder( 2 * nBlob + 4 );//(char*)contextMalloc(context, (2*(i64)nBlob)+4); |
||
1125 | zText.Append( "X'" ); |
||
1126 | if ( zText != null ) |
||
1127 | { |
||
1128 | int i; |
||
1129 | for ( i = 0; i < nBlob; i++ ) |
||
1130 | { |
||
1131 | zText.Append( hexdigits[( zBlob[i] >> 4 ) & 0x0F] ); |
||
1132 | zText.Append( hexdigits[( zBlob[i] ) & 0x0F] ); |
||
1133 | } |
||
1134 | zText.Append( "'" ); |
||
1135 | //zText[( nBlob * 2 ) + 2] = '\''; |
||
1136 | //zText[( nBlob * 2 ) + 3] = '\0'; |
||
1137 | //zText[0] = 'X'; |
||
1138 | //zText[1] = '\''; |
||
1139 | sqlite3_result_text( context, zText, -1, SQLITE_TRANSIENT ); |
||
1140 | //sqlite3_free( zText ); |
||
1141 | } |
||
1142 | break; |
||
1143 | } |
||
1144 | case SQLITE_TEXT: |
||
1145 | { |
||
1146 | int i, j; |
||
1147 | int n; |
||
1148 | string zArg = sqlite3_value_text( argv[0] ); |
||
1149 | StringBuilder z; |
||
1150 | |||
1151 | if ( zArg == null || zArg.Length == 0 ) |
||
1152 | return; |
||
1153 | for ( i = 0, n = 0; i < zArg.Length; i++ ) |
||
1154 | { |
||
1155 | if ( zArg[i] == '\'' ) |
||
1156 | n++; |
||
1157 | } |
||
1158 | z = new StringBuilder( i + n + 3 );// contextMalloc(context, ((i64)i)+((i64)n)+3); |
||
1159 | if ( z != null ) |
||
1160 | { |
||
1161 | z.Append( '\'' ); |
||
1162 | for ( i = 0, j = 1; i < zArg.Length && zArg[i] != 0; i++ ) |
||
1163 | { |
||
1164 | z.Append( (char)zArg[i] ); |
||
1165 | j++; |
||
1166 | if ( zArg[i] == '\'' ) |
||
1167 | { |
||
1168 | z.Append( '\'' ); |
||
1169 | j++; |
||
1170 | } |
||
1171 | } |
||
1172 | z.Append( '\'' ); |
||
1173 | j++; |
||
1174 | //z[j] = '\0'; ; |
||
1175 | sqlite3_result_text( context, z, j, null );//sqlite3_free ); |
||
1176 | } |
||
1177 | break; |
||
1178 | } |
||
1179 | default: |
||
1180 | { |
||
1181 | Debug.Assert( sqlite3_value_type( argv[0] ) == SQLITE_NULL ); |
||
1182 | sqlite3_result_text( context, "NULL", 4, SQLITE_STATIC ); |
||
1183 | break; |
||
1184 | } |
||
1185 | } |
||
1186 | } |
||
1187 | |||
1188 | /* |
||
1189 | ** The hex() function. Interpret the argument as a blob. Return |
||
1190 | ** a hexadecimal rendering as text. |
||
1191 | */ |
||
1192 | static void hexFunc( |
||
1193 | sqlite3_context context, |
||
1194 | int argc, |
||
1195 | sqlite3_value[] argv |
||
1196 | ) |
||
1197 | { |
||
1198 | int i, n; |
||
1199 | byte[] pBlob; |
||
1200 | //string zHex, z; |
||
1201 | Debug.Assert( argc == 1 ); |
||
1202 | UNUSED_PARAMETER( argc ); |
||
1203 | pBlob = sqlite3_value_blob( argv[0] ); |
||
1204 | n = sqlite3_value_bytes( argv[0] ); |
||
1205 | Debug.Assert( n == ( pBlob == null ? 0 : pBlob.Length ) ); /* No encoding change */ |
||
1206 | StringBuilder zHex = new StringBuilder( n * 2 + 1 ); |
||
1207 | // z = zHex = contextMalloc(context, ((i64)n)*2 + 1); |
||
1208 | if ( zHex != null ) |
||
1209 | { |
||
1210 | for ( i = 0; i < n; i++ ) |
||
1211 | {//, pBlob++){ |
||
1212 | byte c = pBlob[i]; |
||
1213 | zHex.Append( hexdigits[( c >> 4 ) & 0xf] ); |
||
1214 | zHex.Append( hexdigits[c & 0xf] ); |
||
1215 | } |
||
1216 | sqlite3_result_text( context, zHex, n * 2, null ); //sqlite3_free ); |
||
1217 | } |
||
1218 | } |
||
1219 | |||
1220 | /* |
||
1221 | ** The zeroblob(N) function returns a zero-filled blob of size N bytes. |
||
1222 | */ |
||
1223 | static void zeroblobFunc( |
||
1224 | sqlite3_context context, |
||
1225 | int argc, |
||
1226 | sqlite3_value[] argv |
||
1227 | ) |
||
1228 | { |
||
1229 | i64 n; |
||
1230 | sqlite3 db = sqlite3_context_db_handle( context ); |
||
1231 | Debug.Assert( argc == 1 ); |
||
1232 | UNUSED_PARAMETER( argc ); |
||
1233 | n = sqlite3_value_int64( argv[0] ); |
||
1234 | testcase( n == db.aLimit[SQLITE_LIMIT_LENGTH] ); |
||
1235 | testcase( n == db.aLimit[SQLITE_LIMIT_LENGTH] + 1 ); |
||
1236 | if ( n > db.aLimit[SQLITE_LIMIT_LENGTH] ) |
||
1237 | { |
||
1238 | sqlite3_result_error_toobig( context ); |
||
1239 | } |
||
1240 | else |
||
1241 | { |
||
1242 | sqlite3_result_zeroblob( context, (int)n );/* IMP: R-00293-64994 */ |
||
1243 | } |
||
1244 | } |
||
1245 | |||
1246 | /* |
||
1247 | ** The replace() function. Three arguments are all strings: call |
||
1248 | ** them A, B, and C. The result is also a string which is derived |
||
1249 | ** from A by replacing every occurance of B with C. The match |
||
1250 | ** must be exact. Collating sequences are not used. |
||
1251 | */ |
||
1252 | static void replaceFunc( |
||
1253 | sqlite3_context context, |
||
1254 | int argc, |
||
1255 | sqlite3_value[] argv |
||
1256 | ) |
||
1257 | { |
||
1258 | string zStr; /* The input string A */ |
||
1259 | string zPattern; /* The pattern string B */ |
||
1260 | string zRep; /* The replacement string C */ |
||
1261 | string zOut = null; /* The output */ |
||
1262 | int nStr; /* Size of zStr */ |
||
1263 | ////int nPattern; /* Size of zPattern */ |
||
1264 | ////int nRep; /* Size of zRep */ |
||
1265 | int nOut; /* Maximum size of zOut */ |
||
1266 | //int loopLimit; /* Last zStr[] that might match zPattern[] */ |
||
1267 | int i, j = 0; /* Loop counters */ |
||
1268 | |||
1269 | Debug.Assert( argc == 3 ); |
||
1270 | UNUSED_PARAMETER( argc ); |
||
1271 | zStr = sqlite3_value_text( argv[0] ); |
||
1272 | if ( zStr == null ) |
||
1273 | return; |
||
1274 | nStr = sqlite3_value_bytes( argv[0] ); |
||
1275 | Debug.Assert( zStr == sqlite3_value_text( argv[0] ) ); /* No encoding change */ |
||
1276 | zPattern = sqlite3_value_text( argv[1] ); |
||
1277 | if ( zPattern == null ) |
||
1278 | { |
||
1279 | Debug.Assert( sqlite3_value_type( argv[1] ) == SQLITE_NULL |
||
1280 | //|| sqlite3_context_db_handle( context ).mallocFailed != 0 |
||
1281 | ); |
||
1282 | return; |
||
1283 | } |
||
1284 | if ( zPattern.Length == 0 ) |
||
1285 | { |
||
1286 | Debug.Assert( sqlite3_value_type( argv[1] ) != SQLITE_NULL ); |
||
1287 | sqlite3_result_value( context, argv[0] ); |
||
1288 | return; |
||
1289 | } |
||
1290 | ////nPattern = sqlite3_value_bytes( argv[1] ); |
||
1291 | Debug.Assert( zPattern == sqlite3_value_text( argv[1] ) ); /* No encoding change */ |
||
1292 | zRep = sqlite3_value_text( argv[2] ); |
||
1293 | if ( zRep == null ) |
||
1294 | return; |
||
1295 | ////nRep = sqlite3_value_bytes( argv[2] ); |
||
1296 | Debug.Assert( zRep == sqlite3_value_text( argv[2] ) ); |
||
1297 | nOut = nStr + 1; |
||
1298 | Debug.Assert( nOut < SQLITE_MAX_LENGTH ); |
||
1299 | if ( nOut <= sqlite3_context_db_handle( context ).aLimit[SQLITE_LIMIT_LENGTH] ) |
||
1300 | { |
||
1301 | //zOut = contextMalloc(context, (i64)nOut); |
||
1302 | //if( zOut==0 ){ |
||
1303 | // return; |
||
1304 | //} |
||
1305 | //loopLimit = nStr - nPattern; |
||
1306 | //for(i=j=0; i<=loopLimit; i++){ |
||
1307 | // if( zStr[i]!=zPattern[0] || memcmp(&zStr[i], zPattern, nPattern) ){ |
||
1308 | // zOut[j++] = zStr[i]; |
||
1309 | // }else{ |
||
1310 | // u8 *zOld; |
||
1311 | // sqlite3 db = sqlite3_context_db_handle( context ); |
||
1312 | // nOut += nRep - nPattern; |
||
1313 | //testcase( nOut-1==db->aLimit[SQLITE_LIMIT_LENGTH] ); |
||
1314 | //testcase( nOut-2==db->aLimit[SQLITE_LIMIT_LENGTH] ); |
||
1315 | //if( nOut-1>db->aLimit[SQLITE_LIMIT_LENGTH] ){ |
||
1316 | // sqlite3_result_error_toobig(context); |
||
1317 | // sqlite3_free(zOut); |
||
1318 | // return; |
||
1319 | // } |
||
1320 | // zOld = zOut; |
||
1321 | // zOut = sqlite3_realloc(zOut, (int)nOut); |
||
1322 | // if( zOut==0 ){ |
||
1323 | // sqlite3_result_error_nomem(context); |
||
1324 | // sqlite3_free(zOld); |
||
1325 | // return; |
||
1326 | // } |
||
1327 | // memcpy(&zOut[j], zRep, nRep); |
||
1328 | // j += nRep; |
||
1329 | // i += nPattern-1; |
||
1330 | // } |
||
1331 | //} |
||
1332 | //Debug.Assert( j+nStr-i+1==nOut ); |
||
1333 | //memcpy(&zOut[j], zStr[i], nStr-i); |
||
1334 | //j += nStr - i; |
||
1335 | //Debug.Assert( j<=nOut ); |
||
1336 | //zOut[j] = 0; |
||
1337 | try |
||
1338 | { |
||
1339 | zOut = zStr.Replace( zPattern, zRep ); |
||
1340 | j = zOut.Length; |
||
1341 | } |
||
1342 | catch |
||
1343 | { |
||
1344 | j = 0; |
||
1345 | } |
||
1346 | } |
||
1347 | if ( j == 0 || j > sqlite3_context_db_handle( context ).aLimit[SQLITE_LIMIT_LENGTH] ) |
||
1348 | { |
||
1349 | sqlite3_result_error_toobig( context ); |
||
1350 | } |
||
1351 | else |
||
1352 | { |
||
1353 | sqlite3_result_text( context, zOut, j, null );//sqlite3_free ); |
||
1354 | } |
||
1355 | } |
||
1356 | |||
1357 | /* |
||
1358 | ** Implementation of the TRIM(), LTRIM(), and RTRIM() functions. |
||
1359 | ** The userdata is 0x1 for left trim, 0x2 for right trim, 0x3 for both. |
||
1360 | */ |
||
1361 | static void trimFunc( |
||
1362 | sqlite3_context context, |
||
1363 | int argc, |
||
1364 | sqlite3_value[] argv |
||
1365 | ) |
||
1366 | { |
||
1367 | string zIn; /* Input string */ |
||
1368 | string zCharSet; /* Set of characters to trim */ |
||
1369 | int nIn; /* Number of bytes in input */ |
||
1370 | int izIn = 0; /* C# string pointer */ |
||
1371 | int flags; /* 1: trimleft 2: trimright 3: trim */ |
||
1372 | int i; /* Loop counter */ |
||
1373 | int[] aLen = null; /* Length of each character in zCharSet */ |
||
1374 | byte[][] azChar = null; /* Individual characters in zCharSet */ |
||
1375 | int nChar = 0; /* Number of characters in zCharSet */ |
||
1376 | byte[] zBytes = null; |
||
1377 | byte[] zBlob = null; |
||
1378 | |||
1379 | if ( sqlite3_value_type( argv[0] ) == SQLITE_NULL ) |
||
1380 | { |
||
1381 | return; |
||
1382 | } |
||
1383 | zIn = sqlite3_value_text( argv[0] ); |
||
1384 | if ( zIn == null ) |
||
1385 | return; |
||
1386 | nIn = sqlite3_value_bytes( argv[0] ); |
||
1387 | zBlob = sqlite3_value_blob( argv[0] ); |
||
1388 | //Debug.Assert( zIn == sqlite3_value_text( argv[0] ) ); |
||
1389 | if ( argc == 1 ) |
||
1390 | { |
||
1391 | int[] lenOne = new int[] { 1 }; |
||
1392 | byte[] azOne = new byte[] { (u8)' ' };//static unsigned char * const azOne[] = { (u8*)" " }; |
||
1393 | nChar = 1; |
||
1394 | aLen = lenOne; |
||
1395 | azChar = new byte[1][]; |
||
1396 | azChar[0] = azOne; |
||
1397 | zCharSet = null; |
||
1398 | } |
||
1399 | else if ( ( zCharSet = sqlite3_value_text( argv[1] ) ) == null ) |
||
1400 | { |
||
1401 | return; |
||
1402 | } |
||
1403 | else |
||
1404 | { |
||
1405 | if ( ( zBytes = sqlite3_value_blob( argv[1] ) ) != null ) |
||
1406 | { |
||
1407 | int iz = 0; |
||
1408 | for ( nChar = 0; iz < zBytes.Length; nChar++ ) |
||
1409 | { |
||
1410 | SQLITE_SKIP_UTF8( zBytes, ref iz ); |
||
1411 | } |
||
1412 | if ( nChar > 0 ) |
||
1413 | { |
||
1414 | azChar = new byte[nChar][];//contextMalloc(context, ((i64)nChar)*(sizeof(char*)+1)); |
||
1415 | if ( azChar == null ) |
||
1416 | { |
||
1417 | return; |
||
1418 | } |
||
1419 | aLen = new int[nChar]; |
||
1420 | |||
1421 | int iz0 = 0; |
||
1422 | int iz1 = 0; |
||
1423 | for ( int ii = 0; ii < nChar; ii++ ) |
||
1424 | { |
||
1425 | SQLITE_SKIP_UTF8( zBytes, ref iz1 ); |
||
1426 | aLen[ii] = iz1 - iz0; |
||
1427 | azChar[ii] = new byte[aLen[ii]]; |
||
1428 | Buffer.BlockCopy( zBytes, iz0, azChar[ii], 0, azChar[ii].Length ); |
||
1429 | iz0 = iz1; |
||
1430 | } |
||
1431 | } |
||
1432 | } |
||
1433 | } |
||
1434 | if ( nChar > 0 ) |
||
1435 | { |
||
1436 | flags = (int)sqlite3_user_data( context ); // flags = SQLITE_PTR_TO_INT(sqlite3_user_data(context)); |
||
1437 | if ( ( flags & 1 ) != 0 ) |
||
1438 | { |
||
1439 | while ( nIn > 0 ) |
||
1440 | { |
||
1441 | int len = 0; |
||
1442 | for ( i = 0; i < nChar; i++ ) |
||
1443 | { |
||
1444 | len = aLen[i]; |
||
1445 | if ( len <= nIn && memcmp( zBlob, izIn, azChar[i], len ) == 0 ) |
||
1446 | break; |
||
1447 | } |
||
1448 | if ( i >= nChar ) |
||
1449 | break; |
||
1450 | izIn += len; |
||
1451 | nIn -= len; |
||
1452 | } |
||
1453 | } |
||
1454 | if ( ( flags & 2 ) != 0 ) |
||
1455 | { |
||
1456 | while ( nIn > 0 ) |
||
1457 | { |
||
1458 | int len = 0; |
||
1459 | for ( i = 0; i < nChar; i++ ) |
||
1460 | { |
||
1461 | len = aLen[i]; |
||
1462 | if ( len <= nIn && memcmp( zBlob, izIn + nIn - len, azChar[i], len ) == 0 ) |
||
1463 | break; |
||
1464 | } |
||
1465 | if ( i >= nChar ) |
||
1466 | break; |
||
1467 | nIn -= len; |
||
1468 | } |
||
1469 | } |
||
1470 | if ( zCharSet != null ) |
||
1471 | { |
||
1472 | //sqlite3_free( ref azChar ); |
||
1473 | } |
||
1474 | } |
||
1475 | StringBuilder sb = new StringBuilder( nIn ); |
||
1476 | for ( i = 0; i < nIn; i++ ) |
||
1477 | sb.Append( (char)zBlob[izIn + i] ); |
||
1478 | sqlite3_result_text( context, sb, nIn, SQLITE_TRANSIENT ); |
||
1479 | } |
||
1480 | |||
1481 | /* IMP: R-25361-16150 This function is omitted from SQLite by default. It |
||
1482 | ** is only available if the SQLITE_SOUNDEX compile-time option is used |
||
1483 | ** when SQLite is built. |
||
1484 | */ |
||
1485 | #if SQLITE_SOUNDEX |
||
1486 | /* |
||
1487 | ** Compute the soundex encoding of a word. |
||
1488 | ** |
||
1489 | ** IMP: R-59782-00072 The soundex(X) function returns a string that is the |
||
1490 | ** soundex encoding of the string X. |
||
1491 | */ |
||
1492 | static void soundexFunc( |
||
1493 | sqlite3_context context, |
||
1494 | int argc, |
||
1495 | sqlite3_value[] argv |
||
1496 | ) |
||
1497 | { |
||
1498 | Debug.Assert(false); // TODO -- func_c |
||
1499 | char zResult[8]; |
||
1500 | const u8 *zIn; |
||
1501 | int i, j; |
||
1502 | static const unsigned char iCode[] = { |
||
1503 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
||
1504 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
||
1505 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
||
1506 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
||
1507 | 0, 0, 1, 2, 3, 0, 1, 2, 0, 0, 2, 2, 4, 5, 5, 0, |
||
1508 | 1, 2, 6, 2, 3, 0, 1, 0, 2, 0, 2, 0, 0, 0, 0, 0, |
||
1509 | 0, 0, 1, 2, 3, 0, 1, 2, 0, 0, 2, 2, 4, 5, 5, 0, |
||
1510 | 1, 2, 6, 2, 3, 0, 1, 0, 2, 0, 2, 0, 0, 0, 0, 0, |
||
1511 | }; |
||
1512 | Debug.Assert( argc==1 ); |
||
1513 | zIn = (u8*)sqlite3_value_text(argv[0]); |
||
1514 | if( zIn==0 ) zIn = (u8*)""; |
||
1515 | for(i=0; zIn[i] && !sqlite3Isalpha(zIn[i]); i++){} |
||
1516 | if( zIn[i] ){ |
||
1517 | u8 prevcode = iCode[zIn[i]&0x7f]; |
||
1518 | zResult[0] = sqlite3Toupper(zIn[i]); |
||
1519 | for(j=1; j<4 && zIn[i]; i++){ |
||
1520 | int code = iCode[zIn[i]&0x7f]; |
||
1521 | if( code>0 ){ |
||
1522 | if( code!=prevcode ){ |
||
1523 | prevcode = code; |
||
1524 | zResult[j++] = code + '0'; |
||
1525 | } |
||
1526 | }else{ |
||
1527 | prevcode = 0; |
||
1528 | } |
||
1529 | } |
||
1530 | while( j<4 ){ |
||
1531 | zResult[j++] = '0'; |
||
1532 | } |
||
1533 | zResult[j] = 0; |
||
1534 | sqlite3_result_text(context, zResult, 4, SQLITE_TRANSIENT); |
||
1535 | }else{ |
||
1536 | /* IMP: R-64894-50321 The string "?000" is returned if the argument |
||
1537 | ** is NULL or contains no ASCII alphabetic characters. */ |
||
1538 | sqlite3_result_text(context, "?000", 4, SQLITE_STATIC); |
||
1539 | } |
||
1540 | } |
||
1541 | #endif //* SQLITE_SOUNDEX */ |
||
1542 | |||
1543 | #if !SQLITE_OMIT_LOAD_EXTENSION |
||
1544 | /* |
||
1545 | ** A function that loads a shared-library extension then returns NULL. |
||
1546 | */ |
||
1547 | static void loadExt( |
||
1548 | sqlite3_context context, |
||
1549 | int argc, |
||
1550 | sqlite3_value[] argv |
||
1551 | ) |
||
1552 | { |
||
1553 | string zFile = sqlite3_value_text( argv[0] ); |
||
1554 | sqlite3 db = (sqlite3)sqlite3_context_db_handle( context ); |
||
1555 | string zErrMsg = string.Empty; |
||
1556 | |||
1557 | string zProc = argc == 2 ? zProc = sqlite3_value_text( argv[1] ) : string.Empty; |
||
1558 | if ( zFile != null && sqlite3_load_extension( db, zFile, zProc, ref zErrMsg ) != 0 ) |
||
1559 | { |
||
1560 | sqlite3_result_error( context, zErrMsg, -1 ); |
||
1561 | sqlite3DbFree( db, ref zErrMsg ); |
||
1562 | } |
||
1563 | } |
||
1564 | #endif |
||
1565 | |||
1566 | /* |
||
1567 | ** An instance of the following structure holds the context of a |
||
1568 | ** sum() or avg() aggregate computation. |
||
1569 | */ |
||
1570 | //typedef struct SumCtx SumCtx; |
||
1571 | public class SumCtx |
||
1572 | { |
||
1573 | public double rSum; /* Floating point sum */ |
||
1574 | public i64 iSum; /* Integer sum */ |
||
1575 | public i64 cnt; /* Number of elements summed */ |
||
1576 | public int overflow; /* True if integer overflow seen */ |
||
1577 | public bool approx; /* True if non-integer value was input to the sum */ |
||
1578 | public Mem _M; |
||
1579 | public Mem Context |
||
1580 | { |
||
1581 | get |
||
1582 | { |
||
1583 | return _M; |
||
1584 | } |
||
1585 | set |
||
1586 | { |
||
1587 | _M = value; |
||
1588 | if ( _M == null || _M.z == null ) |
||
1589 | iSum = 0; |
||
1590 | else |
||
1591 | iSum = Convert.ToInt64( _M.z ); |
||
1592 | } |
||
1593 | } |
||
1594 | }; |
||
1595 | |||
1596 | /* |
||
1597 | ** Routines used to compute the sum, average, and total. |
||
1598 | ** |
||
1599 | ** The SUM() function follows the (broken) SQL standard which means |
||
1600 | ** that it returns NULL if it sums over no inputs. TOTAL returns |
||
1601 | ** 0.0 in that case. In addition, TOTAL always returns a float where |
||
1602 | ** SUM might return an integer if it never encounters a floating point |
||
1603 | ** value. TOTAL never fails, but SUM might through an exception if |
||
1604 | ** it overflows an integer. |
||
1605 | */ |
||
1606 | static void sumStep( |
||
1607 | sqlite3_context context, |
||
1608 | int argc, |
||
1609 | sqlite3_value[] argv |
||
1610 | ) |
||
1611 | { |
||
1612 | SumCtx p; |
||
1613 | |||
1614 | int type; |
||
1615 | Debug.Assert( argc == 1 ); |
||
1616 | UNUSED_PARAMETER( argc ); |
||
1617 | Mem pMem = sqlite3_aggregate_context( context, 1 );//sizeof(*p)); |
||
1618 | if ( pMem._SumCtx == null ) |
||
1619 | pMem._SumCtx = new SumCtx(); |
||
1620 | p = pMem._SumCtx; |
||
1621 | if ( p.Context == null ) |
||
1622 | p.Context = pMem; |
||
1623 | type = sqlite3_value_numeric_type( argv[0] ); |
||
1624 | if ( p != null && type != SQLITE_NULL ) |
||
1625 | { |
||
1626 | p.cnt++; |
||
1627 | if ( type == SQLITE_INTEGER ) |
||
1628 | { |
||
1629 | i64 v = sqlite3_value_int64( argv[0] ); |
||
1630 | p.rSum += v; |
||
1631 | if ( !( p.approx | p.overflow != 0 ) && 0 != sqlite3AddInt64( ref p.iSum, v ) ) |
||
1632 | { |
||
1633 | p.overflow = 1; |
||
1634 | } |
||
1635 | } |
||
1636 | else |
||
1637 | { |
||
1638 | p.rSum += sqlite3_value_double( argv[0] ); |
||
1639 | p.approx = true; |
||
1640 | } |
||
1641 | } |
||
1642 | } |
||
1643 | static void sumFinalize( sqlite3_context context ) |
||
1644 | { |
||
1645 | SumCtx p = null; |
||
1646 | Mem pMem = sqlite3_aggregate_context( context, 0 ); |
||
1647 | if ( pMem != null ) |
||
1648 | p = pMem._SumCtx; |
||
1649 | if ( p != null && p.cnt > 0 ) |
||
1650 | { |
||
1651 | if ( p.overflow != 0 ) |
||
1652 | { |
||
1653 | sqlite3_result_error( context, "integer overflow", -1 ); |
||
1654 | } |
||
1655 | else if ( p.approx ) |
||
1656 | { |
||
1657 | sqlite3_result_double( context, p.rSum ); |
||
1658 | } |
||
1659 | else |
||
1660 | { |
||
1661 | sqlite3_result_int64( context, p.iSum ); |
||
1662 | } |
||
1663 | p.cnt = 0; // Reset for C# |
||
1664 | } |
||
1665 | } |
||
1666 | |||
1667 | static void avgFinalize( sqlite3_context context ) |
||
1668 | { |
||
1669 | SumCtx p = null; |
||
1670 | Mem pMem = sqlite3_aggregate_context( context, 0 ); |
||
1671 | if ( pMem != null ) |
||
1672 | p = pMem._SumCtx; |
||
1673 | if ( p != null && p.cnt > 0 ) |
||
1674 | { |
||
1675 | sqlite3_result_double( context, p.rSum / (double)p.cnt ); |
||
1676 | } |
||
1677 | } |
||
1678 | |||
1679 | static void totalFinalize( sqlite3_context context ) |
||
1680 | { |
||
1681 | SumCtx p = null; |
||
1682 | Mem pMem = sqlite3_aggregate_context( context, 0 ); |
||
1683 | if ( pMem != null ) |
||
1684 | p = pMem._SumCtx; |
||
1685 | /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */ |
||
1686 | sqlite3_result_double( context, p != null ? p.rSum : (double)0 ); |
||
1687 | } |
||
1688 | |||
1689 | /* |
||
1690 | ** The following structure keeps track of state information for the |
||
1691 | ** count() aggregate function. |
||
1692 | */ |
||
1693 | //typedef struct CountCtx CountCtx; |
||
1694 | public class CountCtx |
||
1695 | { |
||
1696 | i64 _n; |
||
1697 | Mem _M; |
||
1698 | public Mem Context |
||
1699 | { |
||
1700 | get |
||
1701 | { |
||
1702 | return _M; |
||
1703 | } |
||
1704 | set |
||
1705 | { |
||
1706 | _M = value; |
||
1707 | if ( _M == null || _M.z == null ) |
||
1708 | _n = 0; |
||
1709 | else |
||
1710 | _n = Convert.ToInt64( _M.z ); |
||
1711 | } |
||
1712 | } |
||
1713 | public i64 n |
||
1714 | { |
||
1715 | get |
||
1716 | { |
||
1717 | return _n; |
||
1718 | } |
||
1719 | set |
||
1720 | { |
||
1721 | _n = value; |
||
1722 | if ( _M != null ) |
||
1723 | _M.z = _n.ToString(); |
||
1724 | } |
||
1725 | } |
||
1726 | } |
||
1727 | |||
1728 | /* |
||
1729 | ** Routines to implement the count() aggregate function. |
||
1730 | */ |
||
1731 | static void countStep( |
||
1732 | sqlite3_context context, |
||
1733 | int argc, |
||
1734 | sqlite3_value[] argv |
||
1735 | ) |
||
1736 | { |
||
1737 | CountCtx p = new CountCtx(); |
||
1738 | p.Context = sqlite3_aggregate_context( context, 1 );//sizeof(*p)); |
||
1739 | if ( ( argc == 0 || SQLITE_NULL != sqlite3_value_type( argv[0] ) ) && p.Context != null ) |
||
1740 | { |
||
1741 | p.n++; |
||
1742 | } |
||
1743 | #if !SQLITE_OMIT_DEPRECATED |
||
1744 | /* The sqlite3_aggregate_count() function is deprecated. But just to make |
||
1745 | ** sure it still operates correctly, verify that its count agrees with our |
||
1746 | ** internal count when using count(*) and when the total count can be |
||
1747 | ** expressed as a 32-bit integer. */ |
||
1748 | Debug.Assert( argc == 1 || p == null || p.n > 0x7fffffff |
||
1749 | || p.n == sqlite3_aggregate_count( context ) ); |
||
1750 | #endif |
||
1751 | } |
||
1752 | |||
1753 | static void countFinalize( sqlite3_context context ) |
||
1754 | { |
||
1755 | CountCtx p = new CountCtx(); |
||
1756 | p.Context = sqlite3_aggregate_context( context, 0 ); |
||
1757 | sqlite3_result_int64( context, p != null ? p.n : 0 ); |
||
1758 | } |
||
1759 | |||
1760 | /* |
||
1761 | ** Routines to implement min() and max() aggregate functions. |
||
1762 | */ |
||
1763 | static void minmaxStep( |
||
1764 | sqlite3_context context, |
||
1765 | int NotUsed, |
||
1766 | sqlite3_value[] argv |
||
1767 | ) |
||
1768 | { |
||
1769 | Mem pArg = (Mem)argv[0]; |
||
1770 | Mem pBest; |
||
1771 | UNUSED_PARAMETER( NotUsed ); |
||
1772 | |||
1773 | if ( sqlite3_value_type( argv[0] ) == SQLITE_NULL ) |
||
1774 | return; |
||
1775 | pBest = (Mem)sqlite3_aggregate_context( context, 1 );//sizeof(*pBest)); |
||
1776 | //if ( pBest == null ) return; |
||
1777 | |||
1778 | if ( pBest.flags != 0 ) |
||
1779 | { |
||
1780 | bool max; |
||
1781 | int cmp; |
||
1782 | CollSeq pColl = sqlite3GetFuncCollSeq( context ); |
||
1783 | /* This step function is used for both the min() and max() aggregates, |
||
1784 | ** the only difference between the two being that the sense of the |
||
1785 | ** comparison is inverted. For the max() aggregate, the |
||
1786 | ** sqlite3_context_db_handle() function returns (void *)-1. For min() it |
||
1787 | ** returns (void *)db, where db is the sqlite3* database pointer. |
||
1788 | ** Therefore the next statement sets variable 'max' to 1 for the max() |
||
1789 | ** aggregate, or 0 for min(). |
||
1790 | */ |
||
1791 | max = sqlite3_context_db_handle( context ) != null && (int)sqlite3_user_data( context ) != 0; |
||
1792 | cmp = sqlite3MemCompare( pBest, pArg, pColl ); |
||
1793 | if ( ( max && cmp < 0 ) || ( !max && cmp > 0 ) ) |
||
1794 | { |
||
1795 | sqlite3VdbeMemCopy( pBest, pArg ); |
||
1796 | } |
||
1797 | } |
||
1798 | else |
||
1799 | { |
||
1800 | sqlite3VdbeMemCopy( pBest, pArg ); |
||
1801 | } |
||
1802 | } |
||
1803 | |||
1804 | static void minMaxFinalize( sqlite3_context context ) |
||
1805 | { |
||
1806 | sqlite3_value pRes; |
||
1807 | pRes = (sqlite3_value)sqlite3_aggregate_context( context, 0 ); |
||
1808 | if ( pRes != null ) |
||
1809 | { |
||
1810 | if ( ALWAYS( pRes.flags != 0 ) ) |
||
1811 | { |
||
1812 | sqlite3_result_value( context, pRes ); |
||
1813 | } |
||
1814 | sqlite3VdbeMemRelease( pRes ); |
||
1815 | } |
||
1816 | } |
||
1817 | |||
1818 | /* |
||
1819 | ** group_concat(EXPR, ?SEPARATOR?) |
||
1820 | */ |
||
1821 | static void groupConcatStep( |
||
1822 | sqlite3_context context, |
||
1823 | int argc, |
||
1824 | sqlite3_value[] argv |
||
1825 | ) |
||
1826 | { |
||
1827 | string zVal; |
||
1828 | //StrAccum pAccum; |
||
1829 | string zSep; |
||
1830 | int nVal, nSep; |
||
1831 | Debug.Assert( argc == 1 || argc == 2 ); |
||
1832 | if ( sqlite3_value_type( argv[0] ) == SQLITE_NULL ) |
||
1833 | return; |
||
1834 | Mem pMem = sqlite3_aggregate_context( context, 1 );//sizeof(*pAccum)); |
||
1835 | if ( pMem._StrAccum == null ) |
||
1836 | pMem._StrAccum = new StrAccum( 100 ); |
||
1837 | //pAccum = pMem._StrAccum; |
||
1838 | |||
1839 | //if ( pMem._StrAccum != null ) |
||
1840 | //{ |
||
1841 | sqlite3 db = sqlite3_context_db_handle( context ); |
||
1842 | //int firstTerm = pMem._StrAccum.useMalloc == 0 ? 1 : 0; |
||
1843 | //pMem._StrAccum.useMalloc = 2; |
||
1844 | pMem._StrAccum.mxAlloc = db.aLimit[SQLITE_LIMIT_LENGTH]; |
||
1845 | if ( pMem._StrAccum.Context == null ) // first term |
||
1846 | pMem._StrAccum.Context = pMem; |
||
1847 | else |
||
1848 | { |
||
1849 | if ( argc == 2 ) |
||
1850 | { |
||
1851 | zSep = sqlite3_value_text( argv[1] ); |
||
1852 | nSep = sqlite3_value_bytes( argv[1] ); |
||
1853 | } |
||
1854 | else |
||
1855 | { |
||
1856 | zSep = ","; |
||
1857 | nSep = 1; |
||
1858 | } |
||
1859 | sqlite3StrAccumAppend( pMem._StrAccum, zSep, nSep ); |
||
1860 | } |
||
1861 | zVal = sqlite3_value_text( argv[0] ); |
||
1862 | nVal = sqlite3_value_bytes( argv[0] ); |
||
1863 | sqlite3StrAccumAppend( pMem._StrAccum, zVal, nVal ); |
||
1864 | //} |
||
1865 | } |
||
1866 | |||
1867 | static void groupConcatFinalize( sqlite3_context context ) |
||
1868 | { |
||
1869 | //StrAccum pAccum = null; |
||
1870 | Mem pMem = sqlite3_aggregate_context( context, 0 ); |
||
1871 | if ( pMem != null ) |
||
1872 | { |
||
1873 | if ( pMem._StrAccum == null ) |
||
1874 | pMem._StrAccum = new StrAccum( 100 ); |
||
1875 | StrAccum pAccum = pMem._StrAccum; |
||
1876 | //} |
||
1877 | //if ( pAccum != null ) |
||
1878 | //{ |
||
1879 | if ( pAccum.tooBig ) |
||
1880 | { |
||
1881 | sqlite3_result_error_toobig( context ); |
||
1882 | } |
||
1883 | //else if ( pAccum.mallocFailed != 0 ) |
||
1884 | //{ |
||
1885 | // sqlite3_result_error_nomem( context ); |
||
1886 | //} |
||
1887 | else |
||
1888 | { |
||
1889 | sqlite3_result_text( context, sqlite3StrAccumFinish( pAccum ), -1, |
||
1890 | null ); //sqlite3_free ); |
||
1891 | } |
||
1892 | } |
||
1893 | } |
||
1894 | |||
1895 | /* |
||
1896 | ** This routine does per-connection function registration. Most |
||
1897 | ** of the built-in functions above are part of the global function set. |
||
1898 | ** This routine only deals with those that are not global. |
||
1899 | */ |
||
1900 | public struct sFuncs |
||
1901 | { |
||
1902 | public string zName; |
||
1903 | public sbyte nArg; |
||
1904 | public u8 argType; /* 1: 0, 2: 1, 3: 2,... N: N-1. */ |
||
1905 | public u8 eTextRep; /* 1: UTF-16. 0: UTF-8 */ |
||
1906 | public u8 needCollSeq; |
||
1907 | public dxFunc xFunc; //(sqlite3_context*,int,sqlite3_value **); |
||
1908 | |||
1909 | // Constructor |
||
1910 | public sFuncs( string zName, sbyte nArg, u8 argType, u8 eTextRep, u8 needCollSeq, dxFunc xFunc ) |
||
1911 | { |
||
1912 | this.zName = zName; |
||
1913 | this.nArg = nArg; |
||
1914 | this.argType = argType; |
||
1915 | this.eTextRep = eTextRep; |
||
1916 | this.needCollSeq = needCollSeq; |
||
1917 | this.xFunc = xFunc; |
||
1918 | } |
||
1919 | }; |
||
1920 | |||
1921 | public struct sAggs |
||
1922 | { |
||
1923 | public string zName; |
||
1924 | public sbyte nArg; |
||
1925 | public u8 argType; |
||
1926 | public u8 needCollSeq; |
||
1927 | public dxStep xStep; //(sqlite3_context*,int,sqlite3_value**); |
||
1928 | public dxFinal xFinalize; //(sqlite3_context*); |
||
1929 | // Constructor |
||
1930 | public sAggs( string zName, sbyte nArg, u8 argType, u8 needCollSeq, dxStep xStep, dxFinal xFinalize ) |
||
1931 | { |
||
1932 | this.zName = zName; |
||
1933 | this.nArg = nArg; |
||
1934 | this.argType = argType; |
||
1935 | this.needCollSeq = needCollSeq; |
||
1936 | this.xStep = xStep; |
||
1937 | this.xFinalize = xFinalize; |
||
1938 | } |
||
1939 | } |
||
1940 | static void sqlite3RegisterBuiltinFunctions( sqlite3 db ) |
||
1941 | { |
||
1942 | int rc = sqlite3_overload_function( db, "MATCH", 2 ); |
||
1943 | Debug.Assert( rc == SQLITE_NOMEM || rc == SQLITE_OK ); |
||
1944 | if ( rc == SQLITE_NOMEM ) |
||
1945 | { |
||
1946 | //// db.mallocFailed = 1; |
||
1947 | } |
||
1948 | } |
||
1949 | |||
1950 | /* |
||
1951 | ** Set the LIKEOPT flag on the 2-argument function with the given name. |
||
1952 | */ |
||
1953 | static void setLikeOptFlag( sqlite3 db, string zName, int flagVal ) |
||
1954 | { |
||
1955 | FuncDef pDef; |
||
1956 | pDef = sqlite3FindFunction( db, zName, sqlite3Strlen30( zName ), |
||
1957 | 2, SQLITE_UTF8, 0 ); |
||
1958 | if ( ALWAYS( pDef != null ) ) |
||
1959 | { |
||
1960 | pDef.flags = (byte)flagVal; |
||
1961 | } |
||
1962 | } |
||
1963 | |||
1964 | /* |
||
1965 | ** Register the built-in LIKE and GLOB functions. The caseSensitive |
||
1966 | ** parameter determines whether or not the LIKE operator is case |
||
1967 | ** sensitive. GLOB is always case sensitive. |
||
1968 | */ |
||
1969 | static void sqlite3RegisterLikeFunctions( sqlite3 db, int caseSensitive ) |
||
1970 | { |
||
1971 | compareInfo pInfo; |
||
1972 | if ( caseSensitive != 0 ) |
||
1973 | { |
||
1974 | pInfo = likeInfoAlt; |
||
1975 | } |
||
1976 | else |
||
1977 | { |
||
1978 | pInfo = likeInfoNorm; |
||
1979 | } |
||
1980 | sqlite3CreateFunc( db, "like", 2, SQLITE_UTF8, pInfo, (dxFunc)likeFunc, null, null, null ); |
||
1981 | sqlite3CreateFunc( db, "like", 3, SQLITE_UTF8, pInfo, (dxFunc)likeFunc, null, null, null ); |
||
1982 | sqlite3CreateFunc( db, "glob", 2, SQLITE_UTF8, |
||
1983 | globInfo, (dxFunc)likeFunc, null, null, null ); |
||
1984 | setLikeOptFlag( db, "glob", SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE ); |
||
1985 | setLikeOptFlag( db, "like", |
||
1986 | caseSensitive != 0 ? ( SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE ) : SQLITE_FUNC_LIKE ); |
||
1987 | } |
||
1988 | |||
1989 | /* |
||
1990 | ** pExpr points to an expression which implements a function. If |
||
1991 | ** it is appropriate to apply the LIKE optimization to that function |
||
1992 | ** then set aWc[0] through aWc[2] to the wildcard characters and |
||
1993 | ** return TRUE. If the function is not a LIKE-style function then |
||
1994 | ** return FALSE. |
||
1995 | */ |
||
1996 | static bool sqlite3IsLikeFunction( sqlite3 db, Expr pExpr, ref bool pIsNocase, char[] aWc ) |
||
1997 | { |
||
1998 | FuncDef pDef; |
||
1999 | if ( pExpr.op != TK_FUNCTION |
||
2000 | || null == pExpr.x.pList |
||
2001 | || pExpr.x.pList.nExpr != 2 |
||
2002 | ) |
||
2003 | { |
||
2004 | return false; |
||
2005 | } |
||
2006 | Debug.Assert( !ExprHasProperty( pExpr, EP_xIsSelect ) ); |
||
2007 | pDef = sqlite3FindFunction( db, pExpr.u.zToken, sqlite3Strlen30( pExpr.u.zToken ), |
||
2008 | 2, SQLITE_UTF8, 0 ); |
||
2009 | if ( NEVER( pDef == null ) || ( pDef.flags & SQLITE_FUNC_LIKE ) == 0 ) |
||
2010 | { |
||
2011 | return false; |
||
2012 | } |
||
2013 | |||
2014 | /* The memcpy() statement assumes that the wildcard characters are |
||
2015 | ** the first three statements in the compareInfo structure. The |
||
2016 | ** Debug.Asserts() that follow verify that assumption |
||
2017 | */ |
||
2018 | //memcpy( aWc, pDef.pUserData, 3 ); |
||
2019 | aWc[0] = ( (compareInfo)pDef.pUserData ).matchAll; |
||
2020 | aWc[1] = ( (compareInfo)pDef.pUserData ).matchOne; |
||
2021 | aWc[2] = ( (compareInfo)pDef.pUserData ).matchSet; |
||
2022 | // Debug.Assert((char*)&likeInfoAlt == (char*)&likeInfoAlt.matchAll); |
||
2023 | // Debug.Assert(&((char*)&likeInfoAlt)[1] == (char*)&likeInfoAlt.matchOne); |
||
2024 | // Debug.Assert(&((char*)&likeInfoAlt)[2] == (char*)&likeInfoAlt.matchSet); |
||
2025 | pIsNocase = ( pDef.flags & SQLITE_FUNC_CASE ) == 0; |
||
2026 | return true; |
||
2027 | } |
||
2028 | |||
2029 | /* |
||
2030 | ** All all of the FuncDef structures in the aBuiltinFunc[] array above |
||
2031 | ** to the global function hash table. This occurs at start-time (as |
||
2032 | ** a consequence of calling sqlite3_initialize()). |
||
2033 | ** |
||
2034 | ** After this routine runs |
||
2035 | */ |
||
2036 | static void sqlite3RegisterGlobalFunctions() |
||
2037 | { |
||
2038 | /* |
||
2039 | ** The following array holds FuncDef structures for all of the functions |
||
2040 | ** defined in this file. |
||
2041 | ** |
||
2042 | ** The array cannot be constant since changes are made to the |
||
2043 | ** FuncDef.pHash elements at start-time. The elements of this array |
||
2044 | ** are read-only after initialization is complete. |
||
2045 | */ |
||
2046 | FuncDef[] aBuiltinFunc = { |
||
2047 | FUNCTION("ltrim", 1, 1, 0, trimFunc ), |
||
2048 | FUNCTION("ltrim", 2, 1, 0, trimFunc ), |
||
2049 | FUNCTION("rtrim", 1, 2, 0, trimFunc ), |
||
2050 | FUNCTION("rtrim", 2, 2, 0, trimFunc ), |
||
2051 | FUNCTION("trim", 1, 3, 0, trimFunc ), |
||
2052 | FUNCTION("trim", 2, 3, 0, trimFunc ), |
||
2053 | FUNCTION("min", -1, 0, 1, minmaxFunc ), |
||
2054 | FUNCTION("min", 0, 0, 1, null ), |
||
2055 | AGGREGATE("min", 1, 0, 1, minmaxStep, minMaxFinalize ), |
||
2056 | FUNCTION("max", -1, 1, 1, minmaxFunc ), |
||
2057 | FUNCTION("max", 0, 1, 1, null ), |
||
2058 | AGGREGATE("max", 1, 1, 1, minmaxStep, minMaxFinalize ), |
||
2059 | FUNCTION("typeof", 1, 0, 0, typeofFunc ), |
||
2060 | FUNCTION("length", 1, 0, 0, lengthFunc ), |
||
2061 | FUNCTION("substr", 2, 0, 0, substrFunc ), |
||
2062 | FUNCTION("substr", 3, 0, 0, substrFunc ), |
||
2063 | FUNCTION("abs", 1, 0, 0, absFunc ), |
||
2064 | #if !SQLITE_OMIT_FLOATING_POINT |
||
2065 | FUNCTION("round", 1, 0, 0, roundFunc ), |
||
2066 | FUNCTION("round", 2, 0, 0, roundFunc ), |
||
2067 | #endif |
||
2068 | FUNCTION("upper", 1, 0, 0, upperFunc ), |
||
2069 | FUNCTION("lower", 1, 0, 0, lowerFunc ), |
||
2070 | FUNCTION("coalesce", 1, 0, 0, null ), |
||
2071 | FUNCTION("coalesce", 0, 0, 0, null ), |
||
2072 | /* FUNCTION(coalesce, -1, 0, 0, ifnullFunc ), */ |
||
2073 | // use versionFunc here just for a dummy placeholder |
||
2074 | new FuncDef(-1,SQLITE_UTF8,SQLITE_FUNC_COALESCE,null,null,versionFunc,null,null,"coalesce",null,null), |
||
2075 | FUNCTION("hex", 1, 0, 0, hexFunc ), |
||
2076 | /* FUNCTION(ifnull, 2, 0, 0, ifnullFunc ), */ |
||
2077 | // use versionFunc here just for a dummy placeholder |
||
2078 | new FuncDef(2,SQLITE_UTF8,SQLITE_FUNC_COALESCE,null,null,versionFunc,null,null,"ifnull",null,null), |
||
2079 | FUNCTION("random", 0, 0, 0, randomFunc ), |
||
2080 | FUNCTION("randomblob", 1, 0, 0, randomBlob ), |
||
2081 | FUNCTION("nullif", 2, 0, 1, nullifFunc ), |
||
2082 | FUNCTION("sqlite_version", 0, 0, 0, versionFunc ), |
||
2083 | FUNCTION("sqlite_source_id", 0, 0, 0, sourceidFunc ), |
||
2084 | FUNCTION("sqlite_log", 2, 0, 0, errlogFunc ), |
||
2085 | #if !SQLITE_OMIT_COMPILEOPTION_DIAGS |
||
2086 | FUNCTION("sqlite_compileoption_used",1, 0, 0, compileoptionusedFunc ), |
||
2087 | FUNCTION("sqlite_compileoption_get", 1, 0, 0, compileoptiongetFunc ), |
||
2088 | #endif //* SQLITE_OMIT_COMPILEOPTION_DIAGS */ |
||
2089 | FUNCTION("quote", 1, 0, 0, quoteFunc ), |
||
2090 | FUNCTION("last_insert_rowid", 0, 0, 0, last_insert_rowid), |
||
2091 | FUNCTION("changes", 0, 0, 0, changes ), |
||
2092 | FUNCTION("total_changes", 0, 0, 0, total_changes ), |
||
2093 | FUNCTION("replace", 3, 0, 0, replaceFunc ), |
||
2094 | FUNCTION("zeroblob", 1, 0, 0, zeroblobFunc ), |
||
2095 | #if SQLITE_SOUNDEX |
||
2096 | FUNCTION("soundex", 1, 0, 0, soundexFunc ), |
||
2097 | #endif |
||
2098 | #if !SQLITE_OMIT_LOAD_EXTENSION |
||
2099 | FUNCTION("load_extension", 1, 0, 0, loadExt ), |
||
2100 | FUNCTION("load_extension", 2, 0, 0, loadExt ), |
||
2101 | #endif |
||
2102 | AGGREGATE("sum", 1, 0, 0, sumStep, sumFinalize ), |
||
2103 | AGGREGATE("total", 1, 0, 0, sumStep, totalFinalize ), |
||
2104 | AGGREGATE("avg", 1, 0, 0, sumStep, avgFinalize ), |
||
2105 | /*AGGREGATE("count", 0, 0, 0, countStep, countFinalize ), */ |
||
2106 | /* AGGREGATE(count, 0, 0, 0, countStep, countFinalize ), */ |
||
2107 | new FuncDef( 0,SQLITE_UTF8,SQLITE_FUNC_COUNT,null,null,null,countStep,countFinalize,"count",null,null), |
||
2108 | AGGREGATE("count", 1, 0, 0, countStep, countFinalize ), |
||
2109 | AGGREGATE("group_concat", 1, 0, 0, groupConcatStep, groupConcatFinalize), |
||
2110 | AGGREGATE("group_concat", 2, 0, 0, groupConcatStep, groupConcatFinalize), |
||
2111 | |||
2112 | LIKEFUNC("glob", 2, globInfo, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE), |
||
2113 | #if SQLITE_CASE_SENSITIVE_LIKE |
||
2114 | LIKEFUNC("like", 2, likeInfoAlt, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE), |
||
2115 | LIKEFUNC("like", 3, likeInfoAlt, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE), |
||
2116 | #else |
||
2117 | LIKEFUNC("like", 2, likeInfoNorm, SQLITE_FUNC_LIKE), |
||
2118 | LIKEFUNC("like", 3, likeInfoNorm, SQLITE_FUNC_LIKE), |
||
2119 | #endif |
||
2120 | FUNCTION("regexp", 2, 0, 0, regexpFunc ),}; |
||
2121 | int i; |
||
2122 | #if SQLITE_OMIT_WSD |
||
2123 | FuncDefHash pHash = GLOBAL( FuncDefHash, sqlite3GlobalFunctions ); |
||
2124 | FuncDef[] aFunc = (FuncDef[])GLOBAL( FuncDef, aBuiltinFunc ); |
||
2125 | #else |
||
2126 | FuncDefHash pHash = sqlite3GlobalFunctions; |
||
2127 | FuncDef[] aFunc = aBuiltinFunc; |
||
2128 | #endif |
||
2129 | for ( i = 0; i < ArraySize( aBuiltinFunc ); i++ ) |
||
2130 | { |
||
2131 | sqlite3FuncDefInsert( pHash, aFunc[i] ); |
||
2132 | } |
||
2133 | sqlite3RegisterDateTimeFunctions(); |
||
2134 | #if !SQLITE_OMIT_ALTERTABLE |
||
2135 | sqlite3AlterFunctions(); |
||
2136 | #endif |
||
2137 | } |
||
2138 | } |
||
2139 | } |