mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-05-28 00:02:28 +00:00
Upgrade SQLite to 3.40 (#699)
This commit is contained in:
parent
bcae817215
commit
0dc0758574
151 changed files with 27917 additions and 22169 deletions
366
third_party/sqlite3/func.c
vendored
366
third_party/sqlite3/func.c
vendored
|
@ -15,7 +15,7 @@
|
|||
*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "third_party/sqlite3/sqliteInt.inc"
|
||||
#include "third_party/sqlite3/sqliteInt.h"
|
||||
#ifndef SQLITE_OMIT_FLOATING_POINT
|
||||
#include "libc/math.h"
|
||||
#endif
|
||||
|
@ -98,6 +98,18 @@ static void typeofFunc(
|
|||
sqlite3_result_text(context, azType[i], -1, SQLITE_STATIC);
|
||||
}
|
||||
|
||||
/* subtype(X)
|
||||
**
|
||||
** Return the subtype of X
|
||||
*/
|
||||
static void subtypeFunc(
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
UNUSED_PARAMETER(argc);
|
||||
sqlite3_result_int(context, sqlite3_value_subtype(argv[0]));
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of the length() function
|
||||
|
@ -259,7 +271,7 @@ endInstrOOM:
|
|||
}
|
||||
|
||||
/*
|
||||
** Implementation of the printf() function.
|
||||
** Implementation of the printf() (a.k.a. format()) SQL function.
|
||||
*/
|
||||
static void printfFunc(
|
||||
sqlite3_context *context,
|
||||
|
@ -572,9 +584,9 @@ static void last_insert_rowid(
|
|||
/*
|
||||
** Implementation of the changes() SQL function.
|
||||
**
|
||||
** IMP: R-62073-11209 The changes() SQL function is a wrapper
|
||||
** around the sqlite3_changes() C/C++ function and hence follows the same
|
||||
** rules for counting changes.
|
||||
** IMP: R-32760-32347 The changes() SQL function is a wrapper
|
||||
** around the sqlite3_changes64() C/C++ function and hence follows the
|
||||
** same rules for counting changes.
|
||||
*/
|
||||
static void changes(
|
||||
sqlite3_context *context,
|
||||
|
@ -583,12 +595,12 @@ static void changes(
|
|||
){
|
||||
sqlite3 *db = sqlite3_context_db_handle(context);
|
||||
UNUSED_PARAMETER2(NotUsed, NotUsed2);
|
||||
sqlite3_result_int(context, sqlite3_changes(db));
|
||||
sqlite3_result_int64(context, sqlite3_changes64(db));
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of the total_changes() SQL function. The return value is
|
||||
** the same as the sqlite3_total_changes() API function.
|
||||
** the same as the sqlite3_total_changes64() API function.
|
||||
*/
|
||||
static void total_changes(
|
||||
sqlite3_context *context,
|
||||
|
@ -597,9 +609,9 @@ static void total_changes(
|
|||
){
|
||||
sqlite3 *db = sqlite3_context_db_handle(context);
|
||||
UNUSED_PARAMETER2(NotUsed, NotUsed2);
|
||||
/* IMP: R-52756-41993 This function is a wrapper around the
|
||||
** sqlite3_total_changes() C/C++ interface. */
|
||||
sqlite3_result_int(context, sqlite3_total_changes(db));
|
||||
/* IMP: R-11217-42568 This function is a wrapper around the
|
||||
** sqlite3_total_changes64() C/C++ interface. */
|
||||
sqlite3_result_int64(context, sqlite3_total_changes64(db));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -729,7 +741,7 @@ static int patternCompare(
|
|||
** c but in the other case and search the input string for either
|
||||
** c or cx.
|
||||
*/
|
||||
if( c<=0x80 ){
|
||||
if( c<0x80 ){
|
||||
char zStop[3];
|
||||
int bMatch;
|
||||
if( noCase ){
|
||||
|
@ -812,7 +824,13 @@ static int patternCompare(
|
|||
** non-zero if there is no match.
|
||||
*/
|
||||
int sqlite3_strglob(const char *zGlobPattern, const char *zString){
|
||||
return patternCompare((u8*)zGlobPattern, (u8*)zString, &globInfo, '[');
|
||||
if( zString==0 ){
|
||||
return zGlobPattern!=0;
|
||||
}else if( zGlobPattern==0 ){
|
||||
return 1;
|
||||
}else {
|
||||
return patternCompare((u8*)zGlobPattern, (u8*)zString, &globInfo, '[');
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -820,7 +838,13 @@ int sqlite3_strglob(const char *zGlobPattern, const char *zString){
|
|||
** a miss - like strcmp().
|
||||
*/
|
||||
int sqlite3_strlike(const char *zPattern, const char *zStr, unsigned int esc){
|
||||
return patternCompare((u8*)zPattern, (u8*)zStr, &likeInfoNorm, esc);
|
||||
if( zStr==0 ){
|
||||
return zPattern!=0;
|
||||
}else if( zPattern==0 ){
|
||||
return 1;
|
||||
}else{
|
||||
return patternCompare((u8*)zPattern, (u8*)zStr, &likeInfoNorm, esc);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1028,39 +1052,42 @@ static const char hexdigits[] = {
|
|||
};
|
||||
|
||||
/*
|
||||
** Implementation of the QUOTE() function. This function takes a single
|
||||
** argument. If the argument is numeric, the return value is the same as
|
||||
** the argument. If the argument is NULL, the return value is the string
|
||||
** "NULL". Otherwise, the argument is enclosed in single quotes with
|
||||
** single-quote escapes.
|
||||
** Append to pStr text that is the SQL literal representation of the
|
||||
** value contained in pValue.
|
||||
*/
|
||||
static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
|
||||
assert( argc==1 );
|
||||
UNUSED_PARAMETER(argc);
|
||||
switch( sqlite3_value_type(argv[0]) ){
|
||||
void sqlite3QuoteValue(StrAccum *pStr, sqlite3_value *pValue){
|
||||
/* As currently implemented, the string must be initially empty.
|
||||
** we might relax this requirement in the future, but that will
|
||||
** require enhancements to the implementation. */
|
||||
assert( pStr!=0 && pStr->nChar==0 );
|
||||
|
||||
switch( sqlite3_value_type(pValue) ){
|
||||
case SQLITE_FLOAT: {
|
||||
double r1, r2;
|
||||
char zBuf[50];
|
||||
r1 = sqlite3_value_double(argv[0]);
|
||||
sqlite3_snprintf(sizeof(zBuf), zBuf, "%!.15g", r1);
|
||||
sqlite3AtoF(zBuf, &r2, 20, SQLITE_UTF8);
|
||||
if( r1!=r2 ){
|
||||
sqlite3_snprintf(sizeof(zBuf), zBuf, "%!.20e", r1);
|
||||
const char *zVal;
|
||||
r1 = sqlite3_value_double(pValue);
|
||||
sqlite3_str_appendf(pStr, "%!.15g", r1);
|
||||
zVal = sqlite3_str_value(pStr);
|
||||
if( zVal ){
|
||||
sqlite3AtoF(zVal, &r2, pStr->nChar, SQLITE_UTF8);
|
||||
if( r1!=r2 ){
|
||||
sqlite3_str_reset(pStr);
|
||||
sqlite3_str_appendf(pStr, "%!.20e", r1);
|
||||
}
|
||||
}
|
||||
sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
|
||||
break;
|
||||
}
|
||||
case SQLITE_INTEGER: {
|
||||
sqlite3_result_value(context, argv[0]);
|
||||
sqlite3_str_appendf(pStr, "%lld", sqlite3_value_int64(pValue));
|
||||
break;
|
||||
}
|
||||
case SQLITE_BLOB: {
|
||||
char *zText = 0;
|
||||
char const *zBlob = sqlite3_value_blob(argv[0]);
|
||||
int nBlob = sqlite3_value_bytes(argv[0]);
|
||||
assert( zBlob==sqlite3_value_blob(argv[0]) ); /* No encoding change */
|
||||
zText = (char *)contextMalloc(context, (2*(i64)nBlob)+4);
|
||||
if( zText ){
|
||||
char const *zBlob = sqlite3_value_blob(pValue);
|
||||
int nBlob = sqlite3_value_bytes(pValue);
|
||||
assert( zBlob==sqlite3_value_blob(pValue) ); /* No encoding change */
|
||||
sqlite3StrAccumEnlarge(pStr, nBlob*2 + 4);
|
||||
if( pStr->accError==0 ){
|
||||
char *zText = pStr->zText;
|
||||
int i;
|
||||
for(i=0; i<nBlob; i++){
|
||||
zText[(i*2)+2] = hexdigits[(zBlob[i]>>4)&0x0F];
|
||||
|
@ -1070,42 +1097,48 @@ static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
|
|||
zText[(nBlob*2)+3] = '\0';
|
||||
zText[0] = 'X';
|
||||
zText[1] = '\'';
|
||||
sqlite3_result_text(context, zText, -1, SQLITE_TRANSIENT);
|
||||
sqlite3_free(zText);
|
||||
pStr->nChar = nBlob*2 + 3;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SQLITE_TEXT: {
|
||||
int i,j;
|
||||
u64 n;
|
||||
const unsigned char *zArg = sqlite3_value_text(argv[0]);
|
||||
char *z;
|
||||
|
||||
if( zArg==0 ) return;
|
||||
for(i=0, n=0; zArg[i]; i++){ if( zArg[i]=='\'' ) n++; }
|
||||
z = contextMalloc(context, ((i64)i)+((i64)n)+3);
|
||||
if( z ){
|
||||
z[0] = '\'';
|
||||
for(i=0, j=1; zArg[i]; i++){
|
||||
z[j++] = zArg[i];
|
||||
if( zArg[i]=='\'' ){
|
||||
z[j++] = '\'';
|
||||
}
|
||||
}
|
||||
z[j++] = '\'';
|
||||
z[j] = 0;
|
||||
sqlite3_result_text(context, z, j, sqlite3_free);
|
||||
}
|
||||
const unsigned char *zArg = sqlite3_value_text(pValue);
|
||||
sqlite3_str_appendf(pStr, "%Q", zArg);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
assert( sqlite3_value_type(argv[0])==SQLITE_NULL );
|
||||
sqlite3_result_text(context, "NULL", 4, SQLITE_STATIC);
|
||||
assert( sqlite3_value_type(pValue)==SQLITE_NULL );
|
||||
sqlite3_str_append(pStr, "NULL", 4);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of the QUOTE() function.
|
||||
**
|
||||
** The quote(X) function returns the text of an SQL literal which is the
|
||||
** value of its argument suitable for inclusion into an SQL statement.
|
||||
** Strings are surrounded by single-quotes with escapes on interior quotes
|
||||
** as needed. BLOBs are encoded as hexadecimal literals. Strings with
|
||||
** embedded NUL characters cannot be represented as string literals in SQL
|
||||
** and hence the returned string literal is truncated prior to the first NUL.
|
||||
*/
|
||||
static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
|
||||
sqlite3_str str;
|
||||
sqlite3 *db = sqlite3_context_db_handle(context);
|
||||
assert( argc==1 );
|
||||
UNUSED_PARAMETER(argc);
|
||||
sqlite3StrAccumInit(&str, db, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]);
|
||||
sqlite3QuoteValue(&str,argv[0]);
|
||||
sqlite3_result_text(context, sqlite3StrAccumFinish(&str), str.nChar,
|
||||
SQLITE_DYNAMIC);
|
||||
if( str.accError!=SQLITE_OK ){
|
||||
sqlite3_result_null(context);
|
||||
sqlite3_result_error_code(context, str.accError);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** The unicode() function. Return the integer unicode code-point value
|
||||
** for the first character of the input string.
|
||||
|
@ -1317,10 +1350,10 @@ static void trimFunc(
|
|||
){
|
||||
const unsigned char *zIn; /* Input string */
|
||||
const unsigned char *zCharSet; /* Set of characters to trim */
|
||||
int nIn; /* Number of bytes in input */
|
||||
unsigned int nIn; /* Number of bytes in input */
|
||||
int flags; /* 1: trimleft 2: trimright 3: trim */
|
||||
int i; /* Loop counter */
|
||||
unsigned char *aLen = 0; /* Length of each character in zCharSet */
|
||||
unsigned int *aLen = 0; /* Length of each character in zCharSet */
|
||||
unsigned char **azChar = 0; /* Individual characters in zCharSet */
|
||||
int nChar; /* Number of characters in zCharSet */
|
||||
|
||||
|
@ -1329,13 +1362,13 @@ static void trimFunc(
|
|||
}
|
||||
zIn = sqlite3_value_text(argv[0]);
|
||||
if( zIn==0 ) return;
|
||||
nIn = sqlite3_value_bytes(argv[0]);
|
||||
nIn = (unsigned)sqlite3_value_bytes(argv[0]);
|
||||
assert( zIn==sqlite3_value_text(argv[0]) );
|
||||
if( argc==1 ){
|
||||
static const unsigned char lenOne[] = { 1 };
|
||||
static const unsigned lenOne[] = { 1 };
|
||||
static unsigned char * const azOne[] = { (u8*)" " };
|
||||
nChar = 1;
|
||||
aLen = (u8*)lenOne;
|
||||
aLen = (unsigned*)lenOne;
|
||||
azChar = (unsigned char **)azOne;
|
||||
zCharSet = 0;
|
||||
}else if( (zCharSet = sqlite3_value_text(argv[1]))==0 ){
|
||||
|
@ -1346,15 +1379,16 @@ static void trimFunc(
|
|||
SQLITE_SKIP_UTF8(z);
|
||||
}
|
||||
if( nChar>0 ){
|
||||
azChar = contextMalloc(context, ((i64)nChar)*(sizeof(char*)+1));
|
||||
azChar = contextMalloc(context,
|
||||
((i64)nChar)*(sizeof(char*)+sizeof(unsigned)));
|
||||
if( azChar==0 ){
|
||||
return;
|
||||
}
|
||||
aLen = (unsigned char*)&azChar[nChar];
|
||||
aLen = (unsigned*)&azChar[nChar];
|
||||
for(z=zCharSet, nChar=0; *z; nChar++){
|
||||
azChar[nChar] = (unsigned char *)z;
|
||||
SQLITE_SKIP_UTF8(z);
|
||||
aLen[nChar] = (u8)(z - azChar[nChar]);
|
||||
aLen[nChar] = (unsigned)(z - azChar[nChar]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1362,7 +1396,7 @@ static void trimFunc(
|
|||
flags = SQLITE_PTR_TO_INT(sqlite3_user_data(context));
|
||||
if( flags & 1 ){
|
||||
while( nIn>0 ){
|
||||
int len = 0;
|
||||
unsigned int len = 0;
|
||||
for(i=0; i<nChar; i++){
|
||||
len = aLen[i];
|
||||
if( len<=nIn && memcmp(zIn, azChar[i], len)==0 ) break;
|
||||
|
@ -1374,7 +1408,7 @@ static void trimFunc(
|
|||
}
|
||||
if( flags & 2 ){
|
||||
while( nIn>0 ){
|
||||
int len = 0;
|
||||
unsigned int len = 0;
|
||||
for(i=0; i<nChar; i++){
|
||||
len = aLen[i];
|
||||
if( len<=nIn && memcmp(&zIn[nIn-len],azChar[i],len)==0 ) break;
|
||||
|
@ -1715,97 +1749,167 @@ static void minMaxFinalize(sqlite3_context *context){
|
|||
|
||||
/*
|
||||
** group_concat(EXPR, ?SEPARATOR?)
|
||||
**
|
||||
** The SEPARATOR goes before the EXPR string. This is tragic. The
|
||||
** groupConcatInverse() implementation would have been easier if the
|
||||
** SEPARATOR were appended after EXPR. And the order is undocumented,
|
||||
** so we could change it, in theory. But the old behavior has been
|
||||
** around for so long that we dare not, for fear of breaking something.
|
||||
*/
|
||||
typedef struct {
|
||||
StrAccum str; /* The accumulated concatenation */
|
||||
#ifndef SQLITE_OMIT_WINDOWFUNC
|
||||
int nAccum; /* Number of strings presently concatenated */
|
||||
int nFirstSepLength; /* Used to detect separator length change */
|
||||
/* If pnSepLengths!=0, refs an array of inter-string separator lengths,
|
||||
** stored as actually incorporated into presently accumulated result.
|
||||
** (Hence, its slots in use number nAccum-1 between method calls.)
|
||||
** If pnSepLengths==0, nFirstSepLength is the length used throughout.
|
||||
*/
|
||||
int *pnSepLengths;
|
||||
#endif
|
||||
} GroupConcatCtx;
|
||||
|
||||
static void groupConcatStep(
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
const char *zVal;
|
||||
StrAccum *pAccum;
|
||||
GroupConcatCtx *pGCC;
|
||||
const char *zSep;
|
||||
int nVal, nSep;
|
||||
assert( argc==1 || argc==2 );
|
||||
if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
|
||||
pAccum = (StrAccum*)sqlite3_aggregate_context(context, sizeof(*pAccum));
|
||||
|
||||
if( pAccum ){
|
||||
pGCC = (GroupConcatCtx*)sqlite3_aggregate_context(context, sizeof(*pGCC));
|
||||
if( pGCC ){
|
||||
sqlite3 *db = sqlite3_context_db_handle(context);
|
||||
int firstTerm = pAccum->mxAlloc==0;
|
||||
pAccum->mxAlloc = db->aLimit[SQLITE_LIMIT_LENGTH];
|
||||
if( !firstTerm ){
|
||||
if( argc==2 ){
|
||||
zSep = (char*)sqlite3_value_text(argv[1]);
|
||||
nSep = sqlite3_value_bytes(argv[1]);
|
||||
}else{
|
||||
zSep = ",";
|
||||
nSep = 1;
|
||||
int firstTerm = pGCC->str.mxAlloc==0;
|
||||
pGCC->str.mxAlloc = db->aLimit[SQLITE_LIMIT_LENGTH];
|
||||
if( argc==1 ){
|
||||
if( !firstTerm ){
|
||||
sqlite3_str_appendchar(&pGCC->str, 1, ',');
|
||||
}
|
||||
if( zSep ) sqlite3_str_append(pAccum, zSep, nSep);
|
||||
#ifndef SQLITE_OMIT_WINDOWFUNC
|
||||
else{
|
||||
pGCC->nFirstSepLength = 1;
|
||||
}
|
||||
#endif
|
||||
}else if( !firstTerm ){
|
||||
zSep = (char*)sqlite3_value_text(argv[1]);
|
||||
nSep = sqlite3_value_bytes(argv[1]);
|
||||
if( zSep ){
|
||||
sqlite3_str_append(&pGCC->str, zSep, nSep);
|
||||
}
|
||||
#ifndef SQLITE_OMIT_WINDOWFUNC
|
||||
else{
|
||||
nSep = 0;
|
||||
}
|
||||
if( nSep != pGCC->nFirstSepLength || pGCC->pnSepLengths != 0 ){
|
||||
int *pnsl = pGCC->pnSepLengths;
|
||||
if( pnsl == 0 ){
|
||||
/* First separator length variation seen, start tracking them. */
|
||||
pnsl = (int*)sqlite3_malloc64((pGCC->nAccum+1) * sizeof(int));
|
||||
if( pnsl!=0 ){
|
||||
int i = 0, nA = pGCC->nAccum-1;
|
||||
while( i<nA ) pnsl[i++] = pGCC->nFirstSepLength;
|
||||
}
|
||||
}else{
|
||||
pnsl = (int*)sqlite3_realloc64(pnsl, pGCC->nAccum * sizeof(int));
|
||||
}
|
||||
if( pnsl!=0 ){
|
||||
if( ALWAYS(pGCC->nAccum>0) ){
|
||||
pnsl[pGCC->nAccum-1] = nSep;
|
||||
}
|
||||
pGCC->pnSepLengths = pnsl;
|
||||
}else{
|
||||
sqlite3StrAccumSetError(&pGCC->str, SQLITE_NOMEM);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#ifndef SQLITE_OMIT_WINDOWFUNC
|
||||
else{
|
||||
pGCC->nFirstSepLength = sqlite3_value_bytes(argv[1]);
|
||||
}
|
||||
pGCC->nAccum += 1;
|
||||
#endif
|
||||
zVal = (char*)sqlite3_value_text(argv[0]);
|
||||
nVal = sqlite3_value_bytes(argv[0]);
|
||||
if( zVal ) sqlite3_str_append(pAccum, zVal, nVal);
|
||||
if( zVal ) sqlite3_str_append(&pGCC->str, zVal, nVal);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_WINDOWFUNC
|
||||
static void groupConcatInverse(
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
int n;
|
||||
StrAccum *pAccum;
|
||||
GroupConcatCtx *pGCC;
|
||||
assert( argc==1 || argc==2 );
|
||||
(void)argc; /* Suppress unused parameter warning */
|
||||
if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
|
||||
pAccum = (StrAccum*)sqlite3_aggregate_context(context, sizeof(*pAccum));
|
||||
/* pAccum is always non-NULL since groupConcatStep() will have always
|
||||
pGCC = (GroupConcatCtx*)sqlite3_aggregate_context(context, sizeof(*pGCC));
|
||||
/* pGCC is always non-NULL since groupConcatStep() will have always
|
||||
** run frist to initialize it */
|
||||
if( ALWAYS(pAccum) ){
|
||||
n = sqlite3_value_bytes(argv[0]);
|
||||
if( argc==2 ){
|
||||
n += sqlite3_value_bytes(argv[1]);
|
||||
if( ALWAYS(pGCC) ){
|
||||
int nVS;
|
||||
/* Must call sqlite3_value_text() to convert the argument into text prior
|
||||
** to invoking sqlite3_value_bytes(), in case the text encoding is UTF16 */
|
||||
(void)sqlite3_value_text(argv[0]);
|
||||
nVS = sqlite3_value_bytes(argv[0]);
|
||||
pGCC->nAccum -= 1;
|
||||
if( pGCC->pnSepLengths!=0 ){
|
||||
assert(pGCC->nAccum >= 0);
|
||||
if( pGCC->nAccum>0 ){
|
||||
nVS += *pGCC->pnSepLengths;
|
||||
memmove(pGCC->pnSepLengths, pGCC->pnSepLengths+1,
|
||||
(pGCC->nAccum-1)*sizeof(int));
|
||||
}
|
||||
}else{
|
||||
n++;
|
||||
/* If removing single accumulated string, harmlessly over-do. */
|
||||
nVS += pGCC->nFirstSepLength;
|
||||
}
|
||||
if( n>=(int)pAccum->nChar ){
|
||||
pAccum->nChar = 0;
|
||||
if( nVS>=(int)pGCC->str.nChar ){
|
||||
pGCC->str.nChar = 0;
|
||||
}else{
|
||||
pAccum->nChar -= n;
|
||||
memmove(pAccum->zText, &pAccum->zText[n], pAccum->nChar);
|
||||
pGCC->str.nChar -= nVS;
|
||||
memmove(pGCC->str.zText, &pGCC->str.zText[nVS], pGCC->str.nChar);
|
||||
}
|
||||
if( pGCC->str.nChar==0 ){
|
||||
pGCC->str.mxAlloc = 0;
|
||||
sqlite3_free(pGCC->pnSepLengths);
|
||||
pGCC->pnSepLengths = 0;
|
||||
}
|
||||
if( pAccum->nChar==0 ) pAccum->mxAlloc = 0;
|
||||
}
|
||||
}
|
||||
#else
|
||||
# define groupConcatInverse 0
|
||||
#endif /* SQLITE_OMIT_WINDOWFUNC */
|
||||
static void groupConcatFinalize(sqlite3_context *context){
|
||||
StrAccum *pAccum;
|
||||
pAccum = sqlite3_aggregate_context(context, 0);
|
||||
if( pAccum ){
|
||||
if( pAccum->accError==SQLITE_TOOBIG ){
|
||||
sqlite3_result_error_toobig(context);
|
||||
}else if( pAccum->accError==SQLITE_NOMEM ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
}else{
|
||||
sqlite3_result_text(context, sqlite3StrAccumFinish(pAccum), -1,
|
||||
sqlite3_free);
|
||||
}
|
||||
GroupConcatCtx *pGCC
|
||||
= (GroupConcatCtx*)sqlite3_aggregate_context(context, 0);
|
||||
if( pGCC ){
|
||||
sqlite3ResultStrAccum(context, &pGCC->str);
|
||||
#ifndef SQLITE_OMIT_WINDOWFUNC
|
||||
sqlite3_free(pGCC->pnSepLengths);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#ifndef SQLITE_OMIT_WINDOWFUNC
|
||||
static void groupConcatValue(sqlite3_context *context){
|
||||
sqlite3_str *pAccum;
|
||||
pAccum = (sqlite3_str*)sqlite3_aggregate_context(context, 0);
|
||||
if( pAccum ){
|
||||
GroupConcatCtx *pGCC
|
||||
= (GroupConcatCtx*)sqlite3_aggregate_context(context, 0);
|
||||
if( pGCC ){
|
||||
StrAccum *pAccum = &pGCC->str;
|
||||
if( pAccum->accError==SQLITE_TOOBIG ){
|
||||
sqlite3_result_error_toobig(context);
|
||||
}else if( pAccum->accError==SQLITE_NOMEM ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
}else{
|
||||
const char *zText = sqlite3_str_value(pAccum);
|
||||
sqlite3_result_text(context, zText, -1, SQLITE_TRANSIENT);
|
||||
sqlite3_result_text(context, zText, pAccum->nChar, SQLITE_TRANSIENT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1869,11 +1973,12 @@ int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){
|
|||
int nExpr;
|
||||
assert( pExpr!=0 );
|
||||
assert( pExpr->op==TK_FUNCTION );
|
||||
assert( ExprUseXList(pExpr) );
|
||||
if( !pExpr->x.pList ){
|
||||
return 0;
|
||||
}
|
||||
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
|
||||
nExpr = pExpr->x.pList->nExpr;
|
||||
assert( !ExprHasProperty(pExpr, EP_IntValue) );
|
||||
pDef = sqlite3FindFunction(db, pExpr->u.zToken, nExpr, SQLITE_UTF8, 0);
|
||||
#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
|
||||
if( pDef==0 ) return 0;
|
||||
|
@ -1897,6 +2002,7 @@ int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){
|
|||
Expr *pEscape = pExpr->x.pList->a[2].pExpr;
|
||||
char *zEscape;
|
||||
if( pEscape->op!=TK_STRING ) return 0;
|
||||
assert( !ExprHasProperty(pEscape, EP_IntValue) );
|
||||
zEscape = pEscape->u.zToken;
|
||||
if( zEscape[0]==0 || zEscape[1]!=0 ) return 0;
|
||||
if( zEscape[0]==aWc[0] ) return 0;
|
||||
|
@ -2005,11 +2111,11 @@ static void logFunc(
|
|||
switch( SQLITE_PTR_TO_INT(sqlite3_user_data(context)) ){
|
||||
case 1:
|
||||
/* Convert from natural logarithm to log base 10 */
|
||||
ans *= 1.0/M_LN10;
|
||||
ans /= M_LN10;
|
||||
break;
|
||||
case 2:
|
||||
/* Convert from natural logarithm to log base 2 */
|
||||
ans *= 1.0/M_LN2;
|
||||
ans /= M_LN2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -2072,9 +2178,7 @@ static void math2Func(
|
|||
}
|
||||
|
||||
/*
|
||||
** Implementation of 2-argument SQL math functions:
|
||||
**
|
||||
** power(X,Y) - Compute X to the Y-th power
|
||||
** Implementation of 0-argument pi() function.
|
||||
*/
|
||||
static void piFunc(
|
||||
sqlite3_context *context,
|
||||
|
@ -2125,12 +2229,12 @@ void sqlite3RegisterBuiltinFunctions(void){
|
|||
*/
|
||||
static FuncDef aBuiltinFunc[] = {
|
||||
/***** Functions only available with SQLITE_TESTCTRL_INTERNAL_FUNCTIONS *****/
|
||||
#if !defined(SQLITE_UNTESTABLE)
|
||||
TEST_FUNC(implies_nonnull_row, 2, INLINEFUNC_implies_nonnull_row, 0),
|
||||
TEST_FUNC(expr_compare, 2, INLINEFUNC_expr_compare, 0),
|
||||
TEST_FUNC(expr_implies_expr, 2, INLINEFUNC_expr_implies_expr, 0),
|
||||
#ifdef SQLITE_DEBUG
|
||||
TEST_FUNC(affinity, 1, INLINEFUNC_affinity, 0),
|
||||
#endif
|
||||
TEST_FUNC(affinity, 1, INLINEFUNC_affinity, 0),
|
||||
#endif /* !defined(SQLITE_UNTESTABLE) */
|
||||
/***** Regular functions *****/
|
||||
#ifdef SQLITE_SOUNDEX
|
||||
FUNCTION(soundex, 1, 0, 0, soundexFunc ),
|
||||
|
@ -2150,8 +2254,7 @@ void sqlite3RegisterBuiltinFunctions(void){
|
|||
INLINE_FUNC(likelihood, 2, INLINEFUNC_unlikely, SQLITE_FUNC_UNLIKELY),
|
||||
INLINE_FUNC(likely, 1, INLINEFUNC_unlikely, SQLITE_FUNC_UNLIKELY),
|
||||
#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
|
||||
FUNCTION2(sqlite_offset, 1, 0, 0, noopFunc, SQLITE_FUNC_OFFSET|
|
||||
SQLITE_FUNC_TYPEOF),
|
||||
INLINE_FUNC(sqlite_offset, 1, INLINEFUNC_sqlite_offset, 0 ),
|
||||
#endif
|
||||
FUNCTION(ltrim, 1, 1, 0, trimFunc ),
|
||||
FUNCTION(ltrim, 2, 1, 0, trimFunc ),
|
||||
|
@ -2162,15 +2265,17 @@ void sqlite3RegisterBuiltinFunctions(void){
|
|||
FUNCTION(min, -1, 0, 1, minmaxFunc ),
|
||||
FUNCTION(min, 0, 0, 1, 0 ),
|
||||
WAGGREGATE(min, 1, 0, 1, minmaxStep, minMaxFinalize, minMaxValue, 0,
|
||||
SQLITE_FUNC_MINMAX ),
|
||||
SQLITE_FUNC_MINMAX|SQLITE_FUNC_ANYORDER ),
|
||||
FUNCTION(max, -1, 1, 1, minmaxFunc ),
|
||||
FUNCTION(max, 0, 1, 1, 0 ),
|
||||
WAGGREGATE(max, 1, 1, 1, minmaxStep, minMaxFinalize, minMaxValue, 0,
|
||||
SQLITE_FUNC_MINMAX ),
|
||||
SQLITE_FUNC_MINMAX|SQLITE_FUNC_ANYORDER ),
|
||||
FUNCTION2(typeof, 1, 0, 0, typeofFunc, SQLITE_FUNC_TYPEOF),
|
||||
FUNCTION2(subtype, 1, 0, 0, subtypeFunc, SQLITE_FUNC_TYPEOF),
|
||||
FUNCTION2(length, 1, 0, 0, lengthFunc, SQLITE_FUNC_LENGTH),
|
||||
FUNCTION(instr, 2, 0, 0, instrFunc ),
|
||||
FUNCTION(printf, -1, 0, 0, printfFunc ),
|
||||
FUNCTION(format, -1, 0, 0, printfFunc ),
|
||||
FUNCTION(unicode, 1, 0, 0, unicodeFunc ),
|
||||
FUNCTION(char, -1, 0, 0, charFunc ),
|
||||
FUNCTION(abs, 1, 0, 0, absFunc ),
|
||||
|
@ -2202,9 +2307,10 @@ void sqlite3RegisterBuiltinFunctions(void){
|
|||
WAGGREGATE(total, 1,0,0, sumStep,totalFinalize,totalFinalize,sumInverse, 0),
|
||||
WAGGREGATE(avg, 1,0,0, sumStep, avgFinalize, avgFinalize, sumInverse, 0),
|
||||
WAGGREGATE(count, 0,0,0, countStep,
|
||||
countFinalize, countFinalize, countInverse, SQLITE_FUNC_COUNT ),
|
||||
countFinalize, countFinalize, countInverse,
|
||||
SQLITE_FUNC_COUNT|SQLITE_FUNC_ANYORDER ),
|
||||
WAGGREGATE(count, 1,0,0, countStep,
|
||||
countFinalize, countFinalize, countInverse, 0 ),
|
||||
countFinalize, countFinalize, countInverse, SQLITE_FUNC_ANYORDER ),
|
||||
WAGGREGATE(group_concat, 1, 0, 0, groupConcatStep,
|
||||
groupConcatFinalize, groupConcatValue, groupConcatInverse, 0),
|
||||
WAGGREGATE(group_concat, 2, 0, 0, groupConcatStep,
|
||||
|
@ -2268,6 +2374,7 @@ void sqlite3RegisterBuiltinFunctions(void){
|
|||
#endif
|
||||
sqlite3WindowFunctions();
|
||||
sqlite3RegisterDateTimeFunctions();
|
||||
sqlite3RegisterJsonFunctions();
|
||||
sqlite3InsertBuiltinFuncs(aBuiltinFunc, ArraySize(aBuiltinFunc));
|
||||
|
||||
#if 0 /* Enable to print out how the built-in functions are hashed */
|
||||
|
@ -2279,6 +2386,7 @@ void sqlite3RegisterBuiltinFunctions(void){
|
|||
for(p=sqlite3BuiltinFunctions.a[i]; p; p=p->u.pHash){
|
||||
int n = sqlite3Strlen30(p->zName);
|
||||
int h = p->zName[0] + n;
|
||||
assert( p->funcFlags & SQLITE_FUNC_BUILTIN );
|
||||
printf(" %s(%d)", p->zName, h);
|
||||
}
|
||||
printf("\n");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue