Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | The LIKE optimization does the right thing when collating sequences are present. LIKE expressions where the left-hand side has COLLATE NOCASE are optimized in the default case. (CVS 2637) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
ef84ff795c85e9d28f1cac84ff42d8d4 |
User & Date: | drh 2005-08-28 17:00:23.000 |
References
2015-03-06
| ||
13:14 | • New ticket [05f43be8fd] Incorrect use of index with LIKE operators when the LHS is a blob. (artifact: 9a374a0d2d user: drh) | |
Context
2005-08-29
| ||
16:40 | Initialize a local variable to avoid a nuisance compiler warning. Ticket #1394. (CVS 2638) (check-in: 9b914901a1 user: drh tags: trunk) | |
2005-08-28
| ||
17:00 | The LIKE optimization does the right thing when collating sequences are present. LIKE expressions where the left-hand side has COLLATE NOCASE are optimized in the default case. (CVS 2637) (check-in: ef84ff795c user: drh tags: trunk) | |
01:38 | Improvements to the formatting and layout of the code in the previous checkin. (CVS 2636) (check-in: 73b430de0c user: drh tags: trunk) | |
Changes
Changes to src/func.c.
︙ | ︙ | |||
12 13 14 15 16 17 18 | ** This file contains the C functions that implement various SQL ** functions of SQLite. ** ** There is only one exported symbol in this file - the function ** sqliteRegisterBuildinFunctions() found at the bottom of the file. ** All other code has file scope. ** | | | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | ** This file contains the C functions that implement various SQL ** functions of SQLite. ** ** There is only one exported symbol in this file - the function ** sqliteRegisterBuildinFunctions() found at the bottom of the file. ** All other code has file scope. ** ** $Id: func.c,v 1.106 2005/08/28 17:00:23 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> #include <math.h> #include <stdlib.h> #include <assert.h> #include "vdbeInt.h" |
︙ | ︙ | |||
1037 1038 1039 1040 1041 1042 1043 | sqlite3RegisterLikeFunctions(db, 0); #endif } /* ** Set the LIKEOPT flag on the 2-argument function with the given name. */ | | | | < | < > | | | | 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 | sqlite3RegisterLikeFunctions(db, 0); #endif } /* ** Set the LIKEOPT flag on the 2-argument function with the given name. */ static void setLikeOptFlag(sqlite3 *db, const char *zName, int flagVal){ FuncDef *pDef; pDef = sqlite3FindFunction(db, zName, strlen(zName), 2, SQLITE_UTF8, 0); if( pDef ){ pDef->flags = flagVal; } } /* ** Register the built-in LIKE and GLOB functions. The caseSensitive ** parameter determines whether or not the LIKE operator is case ** sensitive. GLOB is always case sensitive. */ void sqlite3RegisterLikeFunctions(sqlite3 *db, int caseSensitive){ struct compareInfo *pInfo; if( caseSensitive ){ pInfo = (struct compareInfo*)&likeInfoAlt; }else{ pInfo = (struct compareInfo*)&likeInfoNorm; } sqlite3_create_function(db, "like", 2, SQLITE_UTF8, pInfo, likeFunc, 0, 0); sqlite3_create_function(db, "like", 3, SQLITE_UTF8, pInfo, likeFunc, 0, 0); sqlite3_create_function(db, "glob", 2, SQLITE_UTF8, (struct compareInfo*)&globInfo, likeFunc, 0,0); setLikeOptFlag(db, "glob", SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE); setLikeOptFlag(db, "like", caseSensitive ? (SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE) : SQLITE_FUNC_LIKE); } /* ** pExpr points to an expression which implements a function. If ** it is appropriate to apply the LIKE optimization to that function ** then set aWc[0] through aWc[2] to the wildcard characters and ** return TRUE. If the function is not a LIKE-style function then ** return FALSE. */ int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){ FuncDef *pDef; if( pExpr->op!=TK_FUNCTION ){ return 0; } if( pExpr->pList->nExpr!=2 ){ return 0; } pDef = sqlite3FindFunction(db, pExpr->token.z, pExpr->token.n, 2, SQLITE_UTF8, 0); if( pDef==0 || (pDef->flags & SQLITE_FUNC_LIKE)==0 ){ return 0; } /* The memcpy() statement assumes that the wildcard characters are ** the first three statements in the compareInfo structure. The ** asserts() that follow verify that assumption */ memcpy(aWc, pDef->pUserData, 3); assert( (char*)&likeInfoAlt == (char*)&likeInfoAlt.matchAll ); assert( &((char*)&likeInfoAlt)[1] == (char*)&likeInfoAlt.matchOne ); assert( &((char*)&likeInfoAlt)[2] == (char*)&likeInfoAlt.matchSet ); *pIsNocase = (pDef->flags & SQLITE_FUNC_CASE)==0; return 1; } |
Changes to src/main.c.
︙ | ︙ | |||
10 11 12 13 14 15 16 | ** ************************************************************************* ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ** ************************************************************************* ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** ** $Id: main.c,v 1.299 2005/08/28 17:00:23 drh Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> /* ** The following constant value is used by the SQLITE_BIGENDIAN and |
︙ | ︙ | |||
690 691 692 693 694 695 696 697 698 699 700 701 702 703 | */ static int openDatabase( const char *zFilename, /* Database filename UTF-8 encoded */ sqlite3 **ppDb /* OUT: Returned database handle */ ){ sqlite3 *db; int rc, i; /* Allocate the sqlite data structure */ db = sqliteMalloc( sizeof(sqlite3) ); if( db==0 ) goto opendb_out; db->priorNewRowid = 0; db->magic = SQLITE_MAGIC_BUSY; db->nDb = 2; | > | 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 | */ static int openDatabase( const char *zFilename, /* Database filename UTF-8 encoded */ sqlite3 **ppDb /* OUT: Returned database handle */ ){ sqlite3 *db; int rc, i; CollSeq *pColl; /* Allocate the sqlite data structure */ db = sqliteMalloc( sizeof(sqlite3) ); if( db==0 ) goto opendb_out; db->priorNewRowid = 0; db->magic = SQLITE_MAGIC_BUSY; db->nDb = 2; |
︙ | ︙ | |||
725 726 727 728 729 730 731 732 733 734 735 736 737 738 | assert( rc!=SQLITE_OK ); db->magic = SQLITE_MAGIC_CLOSED; goto opendb_out; } /* Also add a UTF-8 case-insensitive collation sequence. */ sqlite3_create_collation(db, "NOCASE", SQLITE_UTF8, 0, nocaseCollatingFunc); /* Open the backend database driver */ rc = sqlite3BtreeFactory(db, zFilename, 0, MAX_PAGES, &db->aDb[0].pBt); if( rc!=SQLITE_OK ){ sqlite3Error(db, rc, 0); db->magic = SQLITE_MAGIC_CLOSED; goto opendb_out; | > > > > > > > | 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 | assert( rc!=SQLITE_OK ); db->magic = SQLITE_MAGIC_CLOSED; goto opendb_out; } /* Also add a UTF-8 case-insensitive collation sequence. */ sqlite3_create_collation(db, "NOCASE", SQLITE_UTF8, 0, nocaseCollatingFunc); /* Set flags on the built-in collating sequences */ db->pDfltColl->type = SQLITE_COLL_BINARY; pColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "NOCASE", 6, 0); if( pColl ){ pColl->type = SQLITE_COLL_NOCASE; } /* Open the backend database driver */ rc = sqlite3BtreeFactory(db, zFilename, 0, MAX_PAGES, &db->aDb[0].pBt); if( rc!=SQLITE_OK ){ sqlite3Error(db, rc, 0); db->magic = SQLITE_MAGIC_CLOSED; goto opendb_out; |
︙ | ︙ | |||
897 898 899 900 901 902 903 | return SQLITE_BUSY; } sqlite3ExpirePreparedStatements(db); } pColl = sqlite3FindCollSeq(db, (u8)enc, zName, strlen(zName), 1); if( 0==pColl ){ | | | 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 | return SQLITE_BUSY; } sqlite3ExpirePreparedStatements(db); } pColl = sqlite3FindCollSeq(db, (u8)enc, zName, strlen(zName), 1); if( 0==pColl ){ rc = SQLITE_NOMEM; }else{ pColl->xCmp = xCompare; pColl->pUser = pCtx; pColl->enc = enc; } sqlite3Error(db, rc, 0); return rc; |
︙ | ︙ |
Changes to src/sqliteInt.h.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** ** @(#) $Id: sqliteInt.h,v 1.404 2005/08/28 17:00:23 drh Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ /* ** These #defines should enable >2GB file support on Posix if the ** underlying operating system supports it. If the OS lacks |
︙ | ︙ | |||
507 508 509 510 511 512 513 | void (*xFinalize)(sqlite3_context*); /* Aggregate finializer */ char zName[1]; /* SQL name of the function. MUST BE LAST */ }; /* ** Possible values for FuncDef.flags */ | | > | 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 | void (*xFinalize)(sqlite3_context*); /* Aggregate finializer */ char zName[1]; /* SQL name of the function. MUST BE LAST */ }; /* ** Possible values for FuncDef.flags */ #define SQLITE_FUNC_LIKE 0x01 /* Candidate for the LIKE optimization */ #define SQLITE_FUNC_CASE 0x02 /* Case-sensitive LIKE-type function */ /* ** information about each column of an SQL table is held in an instance ** of this structure. */ struct Column { char *zName; /* Name of this column */ |
︙ | ︙ | |||
547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 | ** If both CollSeq.xCmp and CollSeq.xCmp16 are NULL, it means that the ** collating sequence is undefined. Indices built on an undefined ** collating sequence may not be read or written. */ struct CollSeq { char *zName; /* Name of the collating sequence, UTF-8 encoded */ u8 enc; /* Text encoding handled by xCmp() */ void *pUser; /* First argument to xCmp() */ int (*xCmp)(void*,int, const void*, int, const void*); }; /* ** A sort order can be either ASC or DESC. */ #define SQLITE_SO_ASC 0 /* Sort in ascending order */ #define SQLITE_SO_DESC 1 /* Sort in ascending order */ /* | > > > > > > > > > | 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 | ** If both CollSeq.xCmp and CollSeq.xCmp16 are NULL, it means that the ** collating sequence is undefined. Indices built on an undefined ** collating sequence may not be read or written. */ struct CollSeq { char *zName; /* Name of the collating sequence, UTF-8 encoded */ u8 enc; /* Text encoding handled by xCmp() */ u8 type; /* One of the SQLITE_COLL_... values below */ void *pUser; /* First argument to xCmp() */ int (*xCmp)(void*,int, const void*, int, const void*); }; /* ** Allowed values of CollSeq flags: */ #define SQLITE_COLL_BINARY 1 /* The default memcmp() collating sequence */ #define SQLITE_COLL_NOCASE 2 /* The built-in NOCASE collating sequence */ #define SQLITE_COLL_REVERSE 3 /* The built-in REVERSE collating sequence */ #define SQLITE_COLL_USER 0 /* Any other user-defined collating sequence */ /* ** A sort order can be either ASC or DESC. */ #define SQLITE_SO_ASC 0 /* Sort in ascending order */ #define SQLITE_SO_DESC 1 /* Sort in ascending order */ /* |
︙ | ︙ | |||
1579 1580 1581 1582 1583 1584 1585 | char sqlite3AffinityType(const Token*); void sqlite3Analyze(Parse*, Token*, Token*); int sqlite3InvokeBusyHandler(BusyHandler*); int sqlite3FindDb(sqlite3*, Token*); void sqlite3AnalysisLoad(sqlite3*,int iDB); void sqlite3DefaultRowEst(Index*); void sqlite3RegisterLikeFunctions(sqlite3*, int); | | | 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 | char sqlite3AffinityType(const Token*); void sqlite3Analyze(Parse*, Token*, Token*); int sqlite3InvokeBusyHandler(BusyHandler*); int sqlite3FindDb(sqlite3*, Token*); void sqlite3AnalysisLoad(sqlite3*,int iDB); void sqlite3DefaultRowEst(Index*); void sqlite3RegisterLikeFunctions(sqlite3*, int); int sqlite3IsLikeFunction(sqlite3*,Expr*,int*,char*); #ifdef SQLITE_SSE #include "sseInt.h" #endif #endif |
Changes to src/where.c.
︙ | ︙ | |||
12 13 14 15 16 17 18 | ** This module contains C code that generates VDBE code used to process ** the WHERE clause of SQL statements. This module is reponsible for ** generating the code that loops through a table looking for applicable ** rows. Indices are selected and used to speed the search when doing ** so is applicable. Because this module is responsible for selecting ** indices, you might also think of this module as the "query optimizer". ** | | | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | ** This module contains C code that generates VDBE code used to process ** the WHERE clause of SQL statements. This module is reponsible for ** generating the code that loops through a table looking for applicable ** rows. Indices are selected and used to speed the search when doing ** so is applicable. Because this module is responsible for selecting ** indices, you might also think of this module as the "query optimizer". ** ** $Id: where.c,v 1.166 2005/08/28 17:00:25 drh Exp $ */ #include "sqliteInt.h" /* ** The number of bits in a Bitmask. "BMS" means "BitMask Size". */ #define BMS (sizeof(Bitmask)*8) |
︙ | ︙ | |||
475 476 477 478 479 480 481 482 | int *pnPattern, /* Number of non-wildcard prefix characters */ int *pisComplete /* True if the only wildcard is % in the last character */ ){ const char *z; Expr *pRight, *pLeft; ExprList *pList; int c, cnt; char wc[3]; | > > > | > > > > > > > > | 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 | int *pnPattern, /* Number of non-wildcard prefix characters */ int *pisComplete /* True if the only wildcard is % in the last character */ ){ const char *z; Expr *pRight, *pLeft; ExprList *pList; int c, cnt; int noCase; char wc[3]; CollSeq *pColl; if( !sqlite3IsLikeFunction(db, pExpr, &noCase, wc) ){ return 0; } pList = pExpr->pList; pRight = pList->a[0].pExpr; if( pRight->op!=TK_STRING ){ return 0; } pLeft = pList->a[1].pExpr; if( pLeft->op!=TK_COLUMN ){ return 0; } pColl = pLeft->pColl; if( pColl==0 ){ pColl = db->pDfltColl; } if( (pColl->type!=SQLITE_COLL_BINARY || noCase) && (pColl->type!=SQLITE_COLL_NOCASE || !noCase) ){ return 0; } sqlite3DequoteExpr(pRight); z = pRight->token.z; for(cnt=0; (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2]; cnt++){} if( cnt==0 || 255==(u8)z[cnt] ){ return 0; } |
︙ | ︙ |
Changes to test/like.test.
︙ | ︙ | |||
9 10 11 12 13 14 15 | # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is testing the LIKE and GLOB operators and # in particular the optimizations that occur to help those operators # run faster. # | | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is testing the LIKE and GLOB operators and # in particular the optimizations that occur to help those operators # run faster. # # $Id: like.test,v 1.3 2005/08/28 17:00:26 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Create some sample data to work with. # do_test like-1.0 { |
︙ | ︙ | |||
307 308 309 310 311 312 313 314 | queryplan { SELECT x FROM t1 WHERE x LIKE ('ab' || 'c%') ORDER BY 1 } } {abc abcd nosort {} i1} do_test like-4.6 { set sqlite_like_count } 12 | > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 | queryplan { SELECT x FROM t1 WHERE x LIKE ('ab' || 'c%') ORDER BY 1 } } {abc abcd nosort {} i1} do_test like-4.6 { set sqlite_like_count } 12 # Collating sequences on the index disable the LIKE optimization. # Or if the NOCASE collating sequence is used, the LIKE optimization # is enabled when case_sensitive_like is OFF. # do_test like-5.1 { execsql {PRAGMA case_sensitive_like=off} set sqlite_like_count 0 queryplan { SELECT x FROM t1 WHERE x LIKE 'abc%' ORDER BY 1 } } {ABC {ABC abc xyz} abc abcd nosort {} i1} do_test like-5.2 { set sqlite_like_count } 12 do_test like-5.3 { execsql { CREATE TABLE t2(x COLLATE NOCASE); INSERT INTO t2 SELECT * FROM t1; CREATE INDEX i2 ON t2(x COLLATE NOCASE); } set sqlite_like_count 0 queryplan { SELECT x FROM t2 WHERE x LIKE 'abc%' ORDER BY 1 } } {abc ABC {ABC abc xyz} abcd nosort {} i2} do_test like-5.4 { set sqlite_like_count } 0 do_test like-5.5 { execsql { PRAGMA case_sensitive_like=on; } set sqlite_like_count 0 queryplan { SELECT x FROM t2 WHERE x LIKE 'abc%' ORDER BY 1 } } {abc abcd nosort {} i2} do_test like-5.6 { set sqlite_like_count } 12 do_test like-5.7 { execsql { PRAGMA case_sensitive_like=off; } set sqlite_like_count 0 queryplan { SELECT x FROM t2 WHERE x GLOB 'abc*' ORDER BY 1 } } {abc abcd nosort {} i2} do_test like-5.8 { set sqlite_like_count } 12 finish_test |
Changes to www/lang.tcl.
1 2 3 | # # Run this Tcl script to generate the lang-*.html files. # | | | 1 2 3 4 5 6 7 8 9 10 11 | # # Run this Tcl script to generate the lang-*.html files. # set rcsid {$Id: lang.tcl,v 1.98 2005/08/28 17:00:26 drh Exp $} source common.tcl if {[llength $argv]>0} { set outputdir [lindex $argv 0] } else { set outputdir "" } |
︙ | ︙ | |||
209 210 211 212 213 214 215 | in that one database are analyzed. If the argument is a table name, then only indices associated with that one table are analyzed.</p> <p>The initial implementation stores all statistics in a single table named <b>sqlite_stat1</b>. Future enhancements may create additional tables with the same name pattern except with the "1" changed to a different digit. The <b>sqlite_stat1</b> table cannot | > | | 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 | in that one database are analyzed. If the argument is a table name, then only indices associated with that one table are analyzed.</p> <p>The initial implementation stores all statistics in a single table named <b>sqlite_stat1</b>. Future enhancements may create additional tables with the same name pattern except with the "1" changed to a different digit. The <b>sqlite_stat1</b> table cannot be <a href="#droptable">DROP</a>ped, but it all the content can be <a href="#delete">DELETE</a>d which has the same effect.</p> } Section {ATTACH DATABASE} attach Syntax {sql-statement} { ATTACH [DATABASE] <database-filename> AS <database-name> |
︙ | ︙ |
Changes to www/pragma.tcl.
1 2 3 | # # Run this Tcl script to generate the pragma.html file. # | | | 1 2 3 4 5 6 7 8 9 10 11 | # # Run this Tcl script to generate the pragma.html file. # set rcsid {$Id: pragma.tcl,v 1.16 2005/08/28 17:00:26 drh Exp $} source common.tcl header {Pragma statements supported by SQLite} proc Section {name {label {}}} { puts "\n<hr />" if {$label!=""} { puts "<a name=\"$label\"></a>" |
︙ | ︙ | |||
103 104 105 106 107 108 109 110 111 112 113 114 115 116 | uses more memory, you can increase the cache size for a possible speed improvement.</p> <p>When you change the cache size using the cache_size pragma, the change only endures for the current session. The cache size reverts to the default value when the database is closed and reopened. Use the <a href="#pragma_default_cache_size"><b>default_cache_size</b></a> pragma to check the cache size permanently.</p></li> <a name="pragma_count_changes"></a> <li><p><b>PRAGMA count_changes; <br>PRAGMA count_changes = </b><i>0 | 1</i><b>;</b></p> <p>Query or change the count-changes flag. Normally, when the count-changes flag is not set, INSERT, UPDATE and DELETE statements return no data. When count-changes is set, each of these commands | > > > > > > > > > > | 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | uses more memory, you can increase the cache size for a possible speed improvement.</p> <p>When you change the cache size using the cache_size pragma, the change only endures for the current session. The cache size reverts to the default value when the database is closed and reopened. Use the <a href="#pragma_default_cache_size"><b>default_cache_size</b></a> pragma to check the cache size permanently.</p></li> <a name="pragma_case_sensitive_like"></a> <li><p><b>PRAGMA case_sensitive_like; <br>PRAGMA case_sensitive_like = </b><i>0 | 1</i><b>;</b></p> <p>The default behavior of the LIKE operator is to ignore case for latin1 characters. Hence, by default <b>'a' LIKE 'A'</b> is true. The case_sensitive_like pragma can be turned on to change this behavior. When case_sensitive_like is enabled, <b>'a' LIKE 'A'</b> is false but <b>'a' LIKE 'a'</b> is still true.</p> </li> <a name="pragma_count_changes"></a> <li><p><b>PRAGMA count_changes; <br>PRAGMA count_changes = </b><i>0 | 1</i><b>;</b></p> <p>Query or change the count-changes flag. Normally, when the count-changes flag is not set, INSERT, UPDATE and DELETE statements return no data. When count-changes is set, each of these commands |
︙ | ︙ |