Upgrade SQLite to 3.40 (#699)

This commit is contained in:
Paul Kulchenko 2022-11-28 12:54:48 -08:00 committed by GitHub
parent bcae817215
commit 0dc0758574
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
151 changed files with 27917 additions and 22169 deletions

View file

@ -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");