diff options
author | drh <drh@noemail.net> | 2020-03-05 16:13:24 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2020-03-05 16:13:24 +0000 |
commit | 42a630b1daf1df13850095251cc73be84dbdeac8 (patch) | |
tree | cc6212d1cf798a2e3d8d8ce7d98c016a7056519c /src | |
parent | 4cf2121e1c0adfcae41d89426e1e5e81ca4721a9 (diff) | |
download | sqlite-42a630b1daf1df13850095251cc73be84dbdeac8.tar.gz sqlite-42a630b1daf1df13850095251cc73be84dbdeac8.zip |
Change the sqlite3.pDfltColl (the default collating sequence for the
database connection) so that it is the collating sequence appropriate for
the database encoding, not the UTF8 collating sequence. This helps to
ensure that the database encoding collation is always used, even for
expressions that do not have an defined collating sequence.
Ticket [1b8d7264567eb6fc].
FossilOrigin-Name: 4a5851893c3d71cc823b6ab5df5e58a852cd322fff26290f1ea05b63d67f564a
Diffstat (limited to 'src')
-rw-r--r-- | src/callback.c | 19 | ||||
-rw-r--r-- | src/main.c | 9 | ||||
-rw-r--r-- | src/pragma.c | 5 | ||||
-rw-r--r-- | src/prepare.c | 6 | ||||
-rw-r--r-- | src/sqliteInt.h | 3 |
5 files changed, 27 insertions, 15 deletions
diff --git a/src/callback.c b/src/callback.c index 3d991901d..421cef281 100644 --- a/src/callback.c +++ b/src/callback.c @@ -163,18 +163,31 @@ CollSeq *sqlite3FindCollSeq( int create /* True to create CollSeq if doesn't already exist */ ){ CollSeq *pColl; + assert( SQLITE_UTF8==1 && SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 ); + assert( enc>=SQLITE_UTF8 && enc<=SQLITE_UTF16BE ); if( zName ){ pColl = findCollSeqEntry(db, zName, create); + if( pColl ) pColl += enc-1; }else{ pColl = db->pDfltColl; } - assert( SQLITE_UTF8==1 && SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 ); - assert( enc>=SQLITE_UTF8 && enc<=SQLITE_UTF16BE ); - if( pColl ) pColl += enc-1; return pColl; } /* +** Change the text encoding for a database connection. This means that +** the pDfltColl must change as well. +*/ +void sqlite3SetTextEncoding(sqlite3 *db, u8 enc){ + assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE ); + db->enc = enc; + /* EVIDENCE-OF: R-08308-17224 The default collating function for all + ** strings is BINARY. + */ + db->pDfltColl = sqlite3FindCollSeq(db, enc, sqlite3StrBINARY, 0); +} + +/* ** This function is responsible for invoking the collation factory callback ** or substituting a collation sequence of a different encoding when the ** requested collation sequence is not available in the desired encoding. diff --git a/src/main.c b/src/main.c index 74b532667..98e030fad 100644 --- a/src/main.c +++ b/src/main.c @@ -3199,11 +3199,6 @@ static int openDatabase( if( db->mallocFailed ){ goto opendb_out; } - /* EVIDENCE-OF: R-08308-17224 The default collating function for all - ** strings is BINARY. - */ - db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, sqlite3StrBINARY, 0); - assert( db->pDfltColl!=0 ); /* Parse the filename/URI argument ** @@ -3248,7 +3243,9 @@ static int openDatabase( } sqlite3BtreeEnter(db->aDb[0].pBt); db->aDb[0].pSchema = sqlite3SchemaGet(db, db->aDb[0].pBt); - if( !db->mallocFailed ) ENC(db) = SCHEMA_ENC(db); + if( !db->mallocFailed ){ + sqlite3SetTextEncoding(db, SCHEMA_ENC(db)); + } sqlite3BtreeLeave(db->aDb[0].pBt); db->aDb[1].pSchema = sqlite3SchemaGet(db, 0); diff --git a/src/pragma.c b/src/pragma.c index 60e18e7f0..504f51ec0 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -1837,8 +1837,9 @@ void sqlite3Pragma( if( canChangeEnc ){ for(pEnc=&encnames[0]; pEnc->zName; pEnc++){ if( 0==sqlite3StrICmp(zRight, pEnc->zName) ){ - SCHEMA_ENC(db) = ENC(db) = - pEnc->enc ? pEnc->enc : SQLITE_UTF16NATIVE; + u8 enc = pEnc->enc ? pEnc->enc : SQLITE_UTF16NATIVE; + SCHEMA_ENC(db) = enc; + sqlite3SetTextEncoding(db, enc); break; } } diff --git a/src/prepare.c b/src/prepare.c index 2d928f16e..67995f33c 100644 --- a/src/prepare.c +++ b/src/prepare.c @@ -267,15 +267,15 @@ int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFlags){ */ if( meta[BTREE_TEXT_ENCODING-1] ){ /* text encoding */ if( iDb==0 ){ -#ifndef SQLITE_OMIT_UTF16 u8 encoding; +#ifndef SQLITE_OMIT_UTF16 /* If opening the main database, set ENC(db). */ encoding = (u8)meta[BTREE_TEXT_ENCODING-1] & 3; if( encoding==0 ) encoding = SQLITE_UTF8; - ENC(db) = encoding; #else - ENC(db) = SQLITE_UTF8; + encoding = SQLITE_UTF8; #endif + sqlite3SetTextEncoding(db, encoding); }else{ /* If opening an attached database, the encoding much match ENC(db) */ if( meta[BTREE_TEXT_ENCODING-1]!=ENC(db) ){ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 517bb40b8..814a7d806 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1422,7 +1422,7 @@ void sqlite3CryptFunc(sqlite3_context*,int,sqlite3_value**); struct sqlite3 { sqlite3_vfs *pVfs; /* OS Interface */ struct Vdbe *pVdbe; /* List of active virtual machines */ - CollSeq *pDfltColl; /* The default collating sequence (BINARY) */ + CollSeq *pDfltColl; /* BINARY collseq for the database encoding */ sqlite3_mutex *mutex; /* Connection mutex */ Db *aDb; /* All backends */ int nDb; /* Number of backends currently in use */ @@ -4465,6 +4465,7 @@ int sqlite3ReadSchema(Parse *pParse); CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int); int sqlite3IsBinary(const CollSeq*); CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName); +void sqlite3SetTextEncoding(sqlite3 *db, u8); CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr); CollSeq *sqlite3ExprNNCollSeq(Parse *pParse, Expr *pExpr); int sqlite3ExprCollSeqMatch(Parse*,Expr*,Expr*); |