diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/btree.c | 2 | ||||
-rw-r--r-- | src/ctime.c | 3 | ||||
-rw-r--r-- | src/func.c | 8 | ||||
-rw-r--r-- | src/main.c | 3 | ||||
-rw-r--r-- | src/parse.y | 72 | ||||
-rw-r--r-- | src/sqlite.h.in | 10 | ||||
-rw-r--r-- | src/sqliteInt.h | 2 | ||||
-rw-r--r-- | src/test_config.c | 16 | ||||
-rw-r--r-- | src/vdbeblob.c | 5 |
9 files changed, 116 insertions, 5 deletions
diff --git a/src/btree.c b/src/btree.c index c752b0771..f985ce340 100644 --- a/src/btree.c +++ b/src/btree.c @@ -5989,7 +5989,7 @@ int sqlite3BtreeIndexMoveto( && indexCellCompare(pCur, 0, pIdxKey, xRecordCompare)<=0 && pIdxKey->errCode==SQLITE_OK ){ - pCur->curFlags &= ~BTCF_ValidOvfl; + pCur->curFlags &= ~(BTCF_ValidOvfl|BTCF_AtLast); if( !pCur->pPage->isInit ){ return SQLITE_CORRUPT_BKPT; } diff --git a/src/ctime.c b/src/ctime.c index 0ffe2a5bd..fe7849fec 100644 --- a/src/ctime.c +++ b/src/ctime.c @@ -295,6 +295,9 @@ static const char * const sqlite3azCompileOpt[] = { #ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC "ENABLE_OFFSET_SQL_FUNC", #endif +#ifdef SQLITE_ENABLE_ORDERED_SET_AGGREGATES + "ENABLE_ORDERED_SET_AGGREGATES", +#endif #ifdef SQLITE_ENABLE_OVERSIZE_CELL_CHECK "ENABLE_OVERSIZE_CELL_CHECK", #endif diff --git a/src/func.c b/src/func.c index 8fcda11dc..a634a7fbe 100644 --- a/src/func.c +++ b/src/func.c @@ -2049,7 +2049,11 @@ static void minMaxFinalize(sqlite3_context *context){ ** group_concat(EXPR, ?SEPARATOR?) ** string_agg(EXPR, SEPARATOR) ** -** The SEPARATOR goes before the EXPR string. This is tragic. The +** Content is accumulated in GroupConcatCtx.str with the SEPARATOR +** coming before the EXPR value, except for the first entry which +** omits the SEPARATOR. +** +** It is tragic that the SEPARATOR goes before the EXPR string. 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 @@ -2153,7 +2157,7 @@ static void groupConcatInverse( /* pGCC is always non-NULL since groupConcatStep() will have always ** run first to initialize it */ if( ALWAYS(pGCC) ){ - int nVS; + int nVS; /* Number of characters to remove */ /* 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]); diff --git a/src/main.c b/src/main.c index 5d6212208..ac08eea04 100644 --- a/src/main.c +++ b/src/main.c @@ -1926,7 +1926,8 @@ int sqlite3CreateFunc( assert( SQLITE_FUNC_CONSTANT==SQLITE_DETERMINISTIC ); assert( SQLITE_FUNC_DIRECT==SQLITE_DIRECTONLY ); extraFlags = enc & (SQLITE_DETERMINISTIC|SQLITE_DIRECTONLY| - SQLITE_SUBTYPE|SQLITE_INNOCUOUS|SQLITE_RESULT_SUBTYPE); + SQLITE_SUBTYPE|SQLITE_INNOCUOUS| + SQLITE_RESULT_SUBTYPE|SQLITE_SELFORDER1); enc &= (SQLITE_FUNC_ENCMASK|SQLITE_ANY); /* The SQLITE_INNOCUOUS flag is the same bit as SQLITE_FUNC_UNSAFE. But diff --git a/src/parse.y b/src/parse.y index 926dd6e7d..a6a5e046d 100644 --- a/src/parse.y +++ b/src/parse.y @@ -264,6 +264,9 @@ columnname(A) ::= nm(A) typetoken(Y). {sqlite3AddColumn(pParse,A,Y);} CURRENT FOLLOWING PARTITION PRECEDING RANGE UNBOUNDED EXCLUDE GROUPS OTHERS TIES %endif SQLITE_OMIT_WINDOWFUNC +%ifdef SQLITE_ENABLE_ORDERED_SET_AGGREGATES + WITHIN +%endif SQLITE_ENABLE_ORDERED_SET_AGGREGATES %ifndef SQLITE_OMIT_GENERATED_COLUMNS GENERATED ALWAYS %endif @@ -1179,6 +1182,65 @@ expr(A) ::= idj(X) LP STAR RP. { A = sqlite3ExprFunction(pParse, 0, &X, 0); } +%ifdef SQLITE_ENABLE_ORDERED_SET_AGGREGATES +%include { + /* Generate an expression node that represents an ordered-set aggregate function. + ** + ** SQLite does not do anything special to evaluate ordered-set aggregates. The + ** aggregate function itself is expected to do any required ordering on its own. + ** This is just syntactic sugar. + ** + ** This syntax: percentile(f) WITHIN GROUP ( ORDER BY y ) + ** + ** Is equivalent to: percentile(y,f) + ** + ** The purpose of this function is to generate an Expr node from the first syntax + ** into a TK_FUNCTION node that looks like it came from the second syntax. + ** + ** Only functions that have the SQLITE_SELFORDER1 perperty are allowed to do this + ** transformation. Because DISTINCT is not allowed in the ordered-set aggregate + ** syntax, an error is raised if DISTINCT is used. + */ + static Expr *sqlite3ExprAddOrderedsetFunction( + Parse *pParse, /* Parsing context */ + Token *pFuncname, /* Name of the function */ + int isDistinct, /* DISTINCT or ALL qualifier */ + ExprList *pOrig, /* Arguments to the function */ + Expr *pOrderby /* Expression in the ORDER BY clause */ + ){ + ExprList *p; /* Modified argument list */ + Expr *pExpr; /* Final result */ + p = sqlite3ExprListAppend(pParse, 0, pOrderby); + if( pOrig ){ + int i; + for(i=0; i<pOrig->nExpr; i++){ + p = sqlite3ExprListAppend(pParse, p, pOrig->a[i].pExpr); + pOrig->a[i].pExpr = 0; + } + sqlite3ExprListDelete(pParse->db, pOrig); + } + pExpr = sqlite3ExprFunction(pParse, p, pFuncname, 0); + if( pParse->nErr==0 ){ + FuncDef *pDef; + u8 enc = ENC(pParse->db); + assert( pExpr!=0 ); /* Because otherwise pParse->nErr would not be zero */ + assert( p!=0 ); /* Because otherwise pParse->nErr would not be zero */ + pDef = sqlite3FindFunction(pParse->db, pExpr->u.zToken, -2, enc, 0); + if( pDef==0 || (pDef->funcFlags & SQLITE_SELFORDER1)==0 ){ + sqlite3ErrorMsg(pParse, "%#T() is not an ordered-set aggregate", pExpr); + }else if( isDistinct==SF_Distinct ){ + sqlite3ErrorMsg(pParse, "DISTINCT not allowed on ordered-set aggregate %T()", + pFuncname); + } + } + return pExpr; + } +} +expr(A) ::= idj(X) LP distinct(D) exprlist(Y) RP WITHIN GROUP LP ORDER BY expr(E) RP. { + A = sqlite3ExprAddOrderedsetFunction(pParse, &X, D, Y, E); +} +%endif SQLITE_ENABLE_ORDERED_SET_AGGREGATES + %ifndef SQLITE_OMIT_WINDOWFUNC expr(A) ::= idj(X) LP distinct(D) exprlist(Y) RP filter_over(Z). { A = sqlite3ExprFunction(pParse, Y, &X, D); @@ -1193,7 +1255,15 @@ expr(A) ::= idj(X) LP STAR RP filter_over(Z). { A = sqlite3ExprFunction(pParse, 0, &X, 0); sqlite3WindowAttach(pParse, A, Z); } -%endif +%ifdef SQLITE_ENABLE_ORDERED_SET_AGGREGATES +expr(A) ::= idj(X) LP distinct(D) exprlist(Y) RP WITHIN GROUP LP ORDER BY expr(E) RP + filter_over(Z). { + A = sqlite3ExprAddOrderedsetFunction(pParse, &X, D, Y, E); + sqlite3WindowAttach(pParse, A, Z); +} +%endif SQLITE_ENABLE_ORDERED_SET_AGGREGATES + +%endif SQLITE_OMIT_WINDOWFUNC term(A) ::= CTIME_KW(OP). { A = sqlite3ExprFunction(pParse, 0, &OP, 0); diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 810ccecc9..5546793c9 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -5615,6 +5615,15 @@ int sqlite3_create_window_function( ** [sqlite3_result_subtype()] should avoid setting this property, as the ** purpose of this property is to disable certain optimizations that are ** incompatible with subtypes. +** +** [[SQLITE_SELFORDER1]] <dt>SQLITE_SELFORDER1</dt><dd> +** The SQLITE_SELFORDER1 flag indicates that the function is an aggregate +** that internally orders the values provided to the first argument. The +** ordered-set aggregate SQL notation with a single ORDER BY term can be +** used to invoke this function. If the ordered-set aggregate notation is +** used on a function that lacks this flag, then an error is raised. Note +** that the ordered-set aggregate syntax is only available if SQLite is +** built using the -DSQLITE_ENABLE_ORDERED_SET_AGGREGATES compile-time option. ** </dd> ** </dl> */ @@ -5623,6 +5632,7 @@ int sqlite3_create_window_function( #define SQLITE_SUBTYPE 0x000100000 #define SQLITE_INNOCUOUS 0x000200000 #define SQLITE_RESULT_SUBTYPE 0x001000000 +#define SQLITE_SELFORDER1 0x002000000 /* ** CAPI3REF: Deprecated Functions diff --git a/src/sqliteInt.h b/src/sqliteInt.h index d1ffce6d8..0dab59f7a 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -658,6 +658,8 @@ #ifdef SQLITE_OMIT_FLOATING_POINT # define double sqlite_int64 # define float sqlite_int64 +# define fabs(X) ((X)<0?-(X):(X)) +# define sqlite3IsOverflow(X) 0 # define LONGDOUBLE_TYPE sqlite_int64 # ifndef SQLITE_BIG_DBL # define SQLITE_BIG_DBL (((sqlite3_int64)1)<<50) diff --git a/src/test_config.c b/src/test_config.c index 58de5a462..49527861a 100644 --- a/src/test_config.c +++ b/src/test_config.c @@ -189,6 +189,14 @@ static void set_options(Tcl_Interp *interp){ Tcl_SetVar2(interp, "sqlite_options", "offset_sql_func","0",TCL_GLOBAL_ONLY); #endif +#ifdef SQLITE_ENABLE_ORDERED_SET_AGGREGATES + Tcl_SetVar2(interp, "sqlite_options", + "ordered_set_aggregates","1",TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", + "ordered_set_aggregates","0",TCL_GLOBAL_ONLY); +#endif + #ifdef SQLITE_ENABLE_PREUPDATE_HOOK Tcl_SetVar2(interp, "sqlite_options", "preupdate", "1", TCL_GLOBAL_ONLY); #else @@ -341,6 +349,14 @@ static void set_options(Tcl_Interp *interp){ Tcl_SetVar2(interp, "sqlite_options", "columnmetadata", "0", TCL_GLOBAL_ONLY); #endif +#ifdef SQLITE_ENABLE_ORDEREDSETFUNC + Tcl_SetVar2(interp, "sqlite_options", "ordered_set_funcs", "1", + TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "ordered_set_funcs", "0", + TCL_GLOBAL_ONLY); +#endif + #ifdef SQLITE_ENABLE_OVERSIZE_CELL_CHECK Tcl_SetVar2(interp, "sqlite_options", "oversize_cell_check", "1", TCL_GLOBAL_ONLY); diff --git a/src/vdbeblob.c b/src/vdbeblob.c index 522447dbc..6cb36da37 100644 --- a/src/vdbeblob.c +++ b/src/vdbeblob.c @@ -167,6 +167,11 @@ int sqlite3_blob_open( pTab = 0; sqlite3ErrorMsg(&sParse, "cannot open table without rowid: %s", zTable); } + if( pTab && (pTab->tabFlags&TF_HasGenerated)!=0 ){ + pTab = 0; + sqlite3ErrorMsg(&sParse, "cannot open table with generated columns: %s", + zTable); + } #ifndef SQLITE_OMIT_VIEW if( pTab && IsView(pTab) ){ pTab = 0; |