Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch exp-window-functions Excluding Merge-Ins
This is equivalent to a diff from fea7ade6 to 763e6c9e
2018-06-30
| ||
20:15 | Merge implementation of SQL window functions from the exp-window-functions into trunk. (check-in: 17198a12 user: dan tags: trunk) | |
20:00 | Fix a minor problem in the code for determining whether or not an SQL statement is SQLITE_TOOBIG. (Closed-Leaf check-in: 763e6c9e user: dan tags: exp-window-functions) | |
19:12 | Merge all changes from the weak-fallback branch except those related to the weak-fallback feature itself. (check-in: aad718fb user: dan tags: exp-window-functions) | |
2018-06-26
| ||
20:19 | Merge latest trunk changes. (check-in: d9f814b4 user: dan tags: exp-window-functions) | |
2018-06-21
| ||
23:53 | Improved context for error_log message coming from sqlite3_prepare(). (check-in: fea7ade6 user: drh tags: trunk) | |
23:43 | Improved context for error_log message coming from sqlite3_prepare(). (Leaf check-in: 64df1189 user: drh tags: ieee754) | |
2018-06-19
| ||
11:15 | Minor change to the input grammar to make the parser tables slightly smaller. (check-in: 320fa69e user: drh tags: trunk) | |
Changes to Makefile.in.
︙ | ︙ | |||
186 187 188 189 190 191 192 | pager.lo parse.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \ random.lo resolve.lo rowset.lo rtree.lo \ sqlite3session.lo select.lo sqlite3rbu.lo status.lo stmt.lo \ table.lo threads.lo tokenize.lo treeview.lo trigger.lo \ update.lo upsert.lo util.lo vacuum.lo \ vdbe.lo vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo vdbesort.lo \ vdbetrace.lo wal.lo walker.lo where.lo wherecode.lo whereexpr.lo \ | | | 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 | pager.lo parse.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \ random.lo resolve.lo rowset.lo rtree.lo \ sqlite3session.lo select.lo sqlite3rbu.lo status.lo stmt.lo \ table.lo threads.lo tokenize.lo treeview.lo trigger.lo \ update.lo upsert.lo util.lo vacuum.lo \ vdbe.lo vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo vdbesort.lo \ vdbetrace.lo wal.lo walker.lo where.lo wherecode.lo whereexpr.lo \ window.lo utf.lo vtab.lo # Object files for the amalgamation. # LIBOBJS1 = sqlite3.lo # Determine the real value of LIBOBJ based on the 'configure' script # |
︙ | ︙ | |||
300 301 302 303 304 305 306 | $(TOP)/src/vxworks.h \ $(TOP)/src/wal.c \ $(TOP)/src/wal.h \ $(TOP)/src/walker.c \ $(TOP)/src/where.c \ $(TOP)/src/wherecode.c \ $(TOP)/src/whereexpr.c \ | | > | 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 | $(TOP)/src/vxworks.h \ $(TOP)/src/wal.c \ $(TOP)/src/wal.h \ $(TOP)/src/walker.c \ $(TOP)/src/where.c \ $(TOP)/src/wherecode.c \ $(TOP)/src/whereexpr.c \ $(TOP)/src/whereInt.h \ $(TOP)/src/window.c # Source code for extensions # SRC += \ $(TOP)/ext/fts1/fts1.c \ $(TOP)/ext/fts1/fts1.h \ $(TOP)/ext/fts1/fts1_hash.c \ |
︙ | ︙ | |||
414 415 416 417 418 419 420 421 422 423 424 425 426 427 | $(TOP)/src/test_superlock.c \ $(TOP)/src/test_syscall.c \ $(TOP)/src/test_tclsh.c \ $(TOP)/src/test_tclvar.c \ $(TOP)/src/test_thread.c \ $(TOP)/src/test_vfs.c \ $(TOP)/src/test_windirent.c \ $(TOP)/src/test_wsd.c \ $(TOP)/ext/fts3/fts3_term.c \ $(TOP)/ext/fts3/fts3_test.c \ $(TOP)/ext/session/test_session.c \ $(TOP)/ext/rbu/test_rbu.c # Statically linked extensions | > | 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 | $(TOP)/src/test_superlock.c \ $(TOP)/src/test_syscall.c \ $(TOP)/src/test_tclsh.c \ $(TOP)/src/test_tclvar.c \ $(TOP)/src/test_thread.c \ $(TOP)/src/test_vfs.c \ $(TOP)/src/test_windirent.c \ $(TOP)/src/test_window.c \ $(TOP)/src/test_wsd.c \ $(TOP)/ext/fts3/fts3_term.c \ $(TOP)/ext/fts3/fts3_test.c \ $(TOP)/ext/session/test_session.c \ $(TOP)/ext/rbu/test_rbu.c # Statically linked extensions |
︙ | ︙ | |||
489 490 491 492 493 494 495 496 497 498 499 500 501 502 | $(TOP)/src/vdbeaux.c \ $(TOP)/src/vdbe.c \ $(TOP)/src/vdbemem.c \ $(TOP)/src/vdbetrace.c \ $(TOP)/src/where.c \ $(TOP)/src/wherecode.c \ $(TOP)/src/whereexpr.c \ parse.c \ $(TOP)/ext/fts3/fts3.c \ $(TOP)/ext/fts3/fts3_aux.c \ $(TOP)/ext/fts3/fts3_expr.c \ $(TOP)/ext/fts3/fts3_term.c \ $(TOP)/ext/fts3/fts3_tokenizer.c \ $(TOP)/ext/fts3/fts3_write.c \ | > | 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 | $(TOP)/src/vdbeaux.c \ $(TOP)/src/vdbe.c \ $(TOP)/src/vdbemem.c \ $(TOP)/src/vdbetrace.c \ $(TOP)/src/where.c \ $(TOP)/src/wherecode.c \ $(TOP)/src/whereexpr.c \ $(TOP)/src/window.c \ parse.c \ $(TOP)/ext/fts3/fts3.c \ $(TOP)/ext/fts3/fts3_aux.c \ $(TOP)/ext/fts3/fts3_expr.c \ $(TOP)/ext/fts3/fts3_term.c \ $(TOP)/ext/fts3/fts3_tokenizer.c \ $(TOP)/ext/fts3/fts3_write.c \ |
︙ | ︙ | |||
963 964 965 966 967 968 969 970 971 972 973 974 975 976 | wherecode.lo: $(TOP)/src/wherecode.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/wherecode.c whereexpr.lo: $(TOP)/src/whereexpr.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/whereexpr.c tclsqlite.lo: $(TOP)/src/tclsqlite.c $(HDR) $(LTCOMPILE) -DUSE_TCL_STUBS=1 -c $(TOP)/src/tclsqlite.c tclsqlite-shell.lo: $(TOP)/src/tclsqlite.c $(HDR) $(LTCOMPILE) -DTCLSH -o $@ -c $(TOP)/src/tclsqlite.c tclsqlite-stubs.lo: $(TOP)/src/tclsqlite.c $(HDR) | > > > | 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 | wherecode.lo: $(TOP)/src/wherecode.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/wherecode.c whereexpr.lo: $(TOP)/src/whereexpr.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/whereexpr.c window.lo: $(TOP)/src/window.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/window.c tclsqlite.lo: $(TOP)/src/tclsqlite.c $(HDR) $(LTCOMPILE) -DUSE_TCL_STUBS=1 -c $(TOP)/src/tclsqlite.c tclsqlite-shell.lo: $(TOP)/src/tclsqlite.c $(HDR) $(LTCOMPILE) -DTCLSH -o $@ -c $(TOP)/src/tclsqlite.c tclsqlite-stubs.lo: $(TOP)/src/tclsqlite.c $(HDR) |
︙ | ︙ |
Changes to Makefile.msc.
︙ | ︙ | |||
1192 1193 1194 1195 1196 1197 1198 | pager.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \ random.lo resolve.lo rowset.lo rtree.lo \ sqlite3session.lo select.lo sqlite3rbu.lo status.lo \ table.lo threads.lo tokenize.lo treeview.lo trigger.lo \ update.lo upsert.lo util.lo vacuum.lo \ vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo vdbesort.lo \ vdbetrace.lo wal.lo walker.lo where.lo wherecode.lo whereexpr.lo \ | | | 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 | pager.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \ random.lo resolve.lo rowset.lo rtree.lo \ sqlite3session.lo select.lo sqlite3rbu.lo status.lo \ table.lo threads.lo tokenize.lo treeview.lo trigger.lo \ update.lo upsert.lo util.lo vacuum.lo \ vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo vdbesort.lo \ vdbetrace.lo wal.lo walker.lo where.lo wherecode.lo whereexpr.lo \ window.lo utf.lo vtab.lo # <</mark>> # Object files for the amalgamation. # LIBOBJS1 = sqlite3.lo # Determine the real value of LIBOBJ based on the 'configure' script |
︙ | ︙ | |||
1303 1304 1305 1306 1307 1308 1309 | $(TOP)\src\vdbesort.c \ $(TOP)\src\vdbetrace.c \ $(TOP)\src\vtab.c \ $(TOP)\src\wal.c \ $(TOP)\src\walker.c \ $(TOP)\src\where.c \ $(TOP)\src\wherecode.c \ | | > | 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 | $(TOP)\src\vdbesort.c \ $(TOP)\src\vdbetrace.c \ $(TOP)\src\vtab.c \ $(TOP)\src\wal.c \ $(TOP)\src\walker.c \ $(TOP)\src\where.c \ $(TOP)\src\wherecode.c \ $(TOP)\src\whereexpr.c \ $(TOP)\src\window.c # Core miscellaneous files. # SRC03 = \ $(TOP)\src\parse.y # Core header files, part 1. |
︙ | ︙ | |||
1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 | $(TOP)\src\test_superlock.c \ $(TOP)\src\test_syscall.c \ $(TOP)\src\test_tclsh.c \ $(TOP)\src\test_tclvar.c \ $(TOP)\src\test_thread.c \ $(TOP)\src\test_vfs.c \ $(TOP)\src\test_windirent.c \ $(TOP)\src\test_wsd.c \ $(TOP)\ext\fts3\fts3_term.c \ $(TOP)\ext\fts3\fts3_test.c \ $(TOP)\ext\rbu\test_rbu.c \ $(TOP)\ext\session\test_session.c # Statically linked extensions. | > | 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 | $(TOP)\src\test_superlock.c \ $(TOP)\src\test_syscall.c \ $(TOP)\src\test_tclsh.c \ $(TOP)\src\test_tclvar.c \ $(TOP)\src\test_thread.c \ $(TOP)\src\test_vfs.c \ $(TOP)\src\test_windirent.c \ $(TOP)\src\test_window.c \ $(TOP)\src\test_wsd.c \ $(TOP)\ext\fts3\fts3_term.c \ $(TOP)\ext\fts3\fts3_test.c \ $(TOP)\ext\rbu\test_rbu.c \ $(TOP)\ext\session\test_session.c # Statically linked extensions. |
︙ | ︙ | |||
2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 | wherecode.lo: $(TOP)\src\wherecode.c $(HDR) $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\wherecode.c whereexpr.lo: $(TOP)\src\whereexpr.c $(HDR) $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\whereexpr.c tclsqlite.lo: $(TOP)\src\tclsqlite.c $(HDR) $(SQLITE_TCL_DEP) $(LTCOMPILE) $(NO_WARN) -DUSE_TCL_STUBS=1 -DBUILD_sqlite -I$(TCLINCDIR) -c $(TOP)\src\tclsqlite.c tclsqlite-shell.lo: $(TOP)\src\tclsqlite.c $(HDR) $(SQLITE_TCL_DEP) $(LTCOMPILE) $(NO_WARN) -DTCLSH -DBUILD_sqlite -I$(TCLINCDIR) -c $(TOP)\src\tclsqlite.c tclsqlite3.exe: tclsqlite-shell.lo $(SQLITE3C) $(SQLITE3H) $(LIBRESOBJS) | > > > | 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 | wherecode.lo: $(TOP)\src\wherecode.c $(HDR) $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\wherecode.c whereexpr.lo: $(TOP)\src\whereexpr.c $(HDR) $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\whereexpr.c window.lo: $(TOP)\src\window.c $(HDR) $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\window.c tclsqlite.lo: $(TOP)\src\tclsqlite.c $(HDR) $(SQLITE_TCL_DEP) $(LTCOMPILE) $(NO_WARN) -DUSE_TCL_STUBS=1 -DBUILD_sqlite -I$(TCLINCDIR) -c $(TOP)\src\tclsqlite.c tclsqlite-shell.lo: $(TOP)\src\tclsqlite.c $(HDR) $(SQLITE_TCL_DEP) $(LTCOMPILE) $(NO_WARN) -DTCLSH -DBUILD_sqlite -I$(TCLINCDIR) -c $(TOP)\src\tclsqlite.c tclsqlite3.exe: tclsqlite-shell.lo $(SQLITE3C) $(SQLITE3H) $(LIBRESOBJS) |
︙ | ︙ |
Changes to main.mk.
︙ | ︙ | |||
71 72 73 74 75 76 77 | pager.o pcache.o pcache1.o pragma.o prepare.o printf.o \ random.o resolve.o rowset.o rtree.o \ select.o sqlite3rbu.o status.o stmt.o \ table.o threads.o tokenize.o treeview.o trigger.o \ update.o upsert.o userauth.o util.o vacuum.o \ vdbeapi.o vdbeaux.o vdbeblob.o vdbemem.o vdbesort.o \ vdbetrace.o wal.o walker.o where.o wherecode.o whereexpr.o \ | | | 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | pager.o pcache.o pcache1.o pragma.o prepare.o printf.o \ random.o resolve.o rowset.o rtree.o \ select.o sqlite3rbu.o status.o stmt.o \ table.o threads.o tokenize.o treeview.o trigger.o \ update.o upsert.o userauth.o util.o vacuum.o \ vdbeapi.o vdbeaux.o vdbeblob.o vdbemem.o vdbesort.o \ vdbetrace.o wal.o walker.o where.o wherecode.o whereexpr.o \ utf.o vtab.o window.o LIBOBJ += sqlite3session.o # All of the source code files. # SRC = \ $(TOP)/src/alter.c \ |
︙ | ︙ | |||
178 179 180 181 182 183 184 | $(TOP)/src/vxworks.h \ $(TOP)/src/wal.c \ $(TOP)/src/wal.h \ $(TOP)/src/walker.c \ $(TOP)/src/where.c \ $(TOP)/src/wherecode.c \ $(TOP)/src/whereexpr.c \ | | > | 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 | $(TOP)/src/vxworks.h \ $(TOP)/src/wal.c \ $(TOP)/src/wal.h \ $(TOP)/src/walker.c \ $(TOP)/src/where.c \ $(TOP)/src/wherecode.c \ $(TOP)/src/whereexpr.c \ $(TOP)/src/whereInt.h \ $(TOP)/src/window.c # Source code for extensions # SRC += \ $(TOP)/ext/fts1/fts1.c \ $(TOP)/ext/fts1/fts1.h \ $(TOP)/ext/fts1/fts1_hash.c \ |
︙ | ︙ | |||
344 345 346 347 348 349 350 351 352 353 354 355 356 357 | $(TOP)/src/test_superlock.c \ $(TOP)/src/test_syscall.c \ $(TOP)/src/test_tclsh.c \ $(TOP)/src/test_tclvar.c \ $(TOP)/src/test_thread.c \ $(TOP)/src/test_vfs.c \ $(TOP)/src/test_windirent.c \ $(TOP)/src/test_wsd.c # Extensions to be statically loaded. # TESTSRC += \ $(TOP)/ext/misc/amatch.c \ $(TOP)/ext/misc/carray.c \ | > | 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 | $(TOP)/src/test_superlock.c \ $(TOP)/src/test_syscall.c \ $(TOP)/src/test_tclsh.c \ $(TOP)/src/test_tclvar.c \ $(TOP)/src/test_thread.c \ $(TOP)/src/test_vfs.c \ $(TOP)/src/test_windirent.c \ $(TOP)/src/test_window.c \ $(TOP)/src/test_wsd.c # Extensions to be statically loaded. # TESTSRC += \ $(TOP)/ext/misc/amatch.c \ $(TOP)/ext/misc/carray.c \ |
︙ | ︙ |
Changes to src/alter.c.
︙ | ︙ | |||
70 71 72 73 74 75 76 | /* Advance zCsr to the next token. Store that token type in 'token', ** and its length in 'len' (to be used next iteration of this loop). */ do { zCsr += len; len = sqlite3GetToken(zCsr, &token); } while( token==TK_SPACE ); | | | 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | /* Advance zCsr to the next token. Store that token type in 'token', ** and its length in 'len' (to be used next iteration of this loop). */ do { zCsr += len; len = sqlite3GetToken(zCsr, &token); } while( token==TK_SPACE ); assert( len>0 || !*zCsr ); } while( token!=TK_LP && token!=TK_USING ); zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", (int)(((u8*)tname.z) - zSql), zSql, zTableName, tname.z+tname.n); sqlite3_result_text(context, zRet, -1, SQLITE_DYNAMIC); } } |
︙ | ︙ | |||
194 195 196 197 198 199 200 | /* Advance zCsr to the next token. Store that token type in 'token', ** and its length in 'len' (to be used next iteration of this loop). */ do { zCsr += len; len = sqlite3GetToken(zCsr, &token); }while( token==TK_SPACE ); | | | 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 | /* Advance zCsr to the next token. Store that token type in 'token', ** and its length in 'len' (to be used next iteration of this loop). */ do { zCsr += len; len = sqlite3GetToken(zCsr, &token); }while( token==TK_SPACE ); assert( len>0 || !*zCsr ); /* Variable 'dist' stores the number of tokens read since the most ** recent TK_DOT or TK_ON. This means that when a WHEN, FOR or BEGIN ** token is read and 'dist' equals 2, the condition stated above ** to be met. ** ** Note that ON cannot be a database, table or column name, so |
︙ | ︙ |
Changes to src/analyze.c.
︙ | ︙ | |||
481 482 483 484 485 486 487 488 489 490 491 492 493 494 | static const FuncDef statInitFuncdef = { 2+IsStat34, /* nArg */ SQLITE_UTF8, /* funcFlags */ 0, /* pUserData */ 0, /* pNext */ statInit, /* xSFunc */ 0, /* xFinalize */ "stat_init", /* zName */ {0} }; #ifdef SQLITE_ENABLE_STAT4 /* ** pNew and pOld are both candidate non-periodic samples selected for | > | 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 | static const FuncDef statInitFuncdef = { 2+IsStat34, /* nArg */ SQLITE_UTF8, /* funcFlags */ 0, /* pUserData */ 0, /* pNext */ statInit, /* xSFunc */ 0, /* xFinalize */ 0, 0, /* xValue, xInverse */ "stat_init", /* zName */ {0} }; #ifdef SQLITE_ENABLE_STAT4 /* ** pNew and pOld are both candidate non-periodic samples selected for |
︙ | ︙ | |||
797 798 799 800 801 802 803 804 805 806 807 808 809 810 | static const FuncDef statPushFuncdef = { 2+IsStat34, /* nArg */ SQLITE_UTF8, /* funcFlags */ 0, /* pUserData */ 0, /* pNext */ statPush, /* xSFunc */ 0, /* xFinalize */ "stat_push", /* zName */ {0} }; #define STAT_GET_STAT1 0 /* "stat" column of stat1 table */ #define STAT_GET_ROWID 1 /* "rowid" column of stat[34] entry */ #define STAT_GET_NEQ 2 /* "neq" column of stat[34] entry */ | > | 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 | static const FuncDef statPushFuncdef = { 2+IsStat34, /* nArg */ SQLITE_UTF8, /* funcFlags */ 0, /* pUserData */ 0, /* pNext */ statPush, /* xSFunc */ 0, /* xFinalize */ 0, 0, /* xValue, xInverse */ "stat_push", /* zName */ {0} }; #define STAT_GET_STAT1 0 /* "stat" column of stat1 table */ #define STAT_GET_ROWID 1 /* "rowid" column of stat[34] entry */ #define STAT_GET_NEQ 2 /* "neq" column of stat[34] entry */ |
︙ | ︙ | |||
948 949 950 951 952 953 954 955 956 957 958 959 960 961 | static const FuncDef statGetFuncdef = { 1+IsStat34, /* nArg */ SQLITE_UTF8, /* funcFlags */ 0, /* pUserData */ 0, /* pNext */ statGet, /* xSFunc */ 0, /* xFinalize */ "stat_get", /* zName */ {0} }; static void callStatGet(Vdbe *v, int regStat4, int iParam, int regOut){ assert( regOut!=regStat4 && regOut!=regStat4+1 ); #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 | > | 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 | static const FuncDef statGetFuncdef = { 1+IsStat34, /* nArg */ SQLITE_UTF8, /* funcFlags */ 0, /* pUserData */ 0, /* pNext */ statGet, /* xSFunc */ 0, /* xFinalize */ 0, 0, /* xValue, xInverse */ "stat_get", /* zName */ {0} }; static void callStatGet(Vdbe *v, int regStat4, int iParam, int regOut){ assert( regOut!=regStat4 && regOut!=regStat4+1 ); #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 |
︙ | ︙ |
Changes to src/attach.c.
︙ | ︙ | |||
410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 | static const FuncDef detach_func = { 1, /* nArg */ SQLITE_UTF8, /* funcFlags */ 0, /* pUserData */ 0, /* pNext */ detachFunc, /* xSFunc */ 0, /* xFinalize */ "sqlite_detach", /* zName */ {0} }; codeAttach(pParse, SQLITE_DETACH, &detach_func, pDbname, 0, 0, pDbname); } /* ** Called by the parser to compile an ATTACH statement. ** ** ATTACH p AS pDbname KEY pKey */ void sqlite3Attach(Parse *pParse, Expr *p, Expr *pDbname, Expr *pKey){ static const FuncDef attach_func = { 3, /* nArg */ SQLITE_UTF8, /* funcFlags */ 0, /* pUserData */ 0, /* pNext */ attachFunc, /* xSFunc */ 0, /* xFinalize */ "sqlite_attach", /* zName */ {0} }; codeAttach(pParse, SQLITE_ATTACH, &attach_func, p, p, pDbname, pKey); } #endif /* SQLITE_OMIT_ATTACH */ | > > | 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 | static const FuncDef detach_func = { 1, /* nArg */ SQLITE_UTF8, /* funcFlags */ 0, /* pUserData */ 0, /* pNext */ detachFunc, /* xSFunc */ 0, /* xFinalize */ 0, 0, /* xValue, xInverse */ "sqlite_detach", /* zName */ {0} }; codeAttach(pParse, SQLITE_DETACH, &detach_func, pDbname, 0, 0, pDbname); } /* ** Called by the parser to compile an ATTACH statement. ** ** ATTACH p AS pDbname KEY pKey */ void sqlite3Attach(Parse *pParse, Expr *p, Expr *pDbname, Expr *pKey){ static const FuncDef attach_func = { 3, /* nArg */ SQLITE_UTF8, /* funcFlags */ 0, /* pUserData */ 0, /* pNext */ attachFunc, /* xSFunc */ 0, /* xFinalize */ 0, 0, /* xValue, xInverse */ "sqlite_attach", /* zName */ {0} }; codeAttach(pParse, SQLITE_ATTACH, &attach_func, p, p, pDbname, pKey); } #endif /* SQLITE_OMIT_ATTACH */ |
︙ | ︙ |
Changes to src/btree.c.
︙ | ︙ | |||
5181 5182 5183 5184 5185 5186 5187 5188 5189 5190 5191 5192 5193 5194 | assert( pCur->pgnoRoot==0 || pCur->pPage->nCell==0 ); *pRes = 1; rc = SQLITE_OK; } return rc; } /* Move the cursor to the last entry in the table. Return SQLITE_OK ** on success. Set *pRes to 0 if the cursor actually points to something ** or set *pRes to 1 if the table is empty. */ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){ int rc; | > > > > > > > > > > > > > > | 5181 5182 5183 5184 5185 5186 5187 5188 5189 5190 5191 5192 5193 5194 5195 5196 5197 5198 5199 5200 5201 5202 5203 5204 5205 5206 5207 5208 | assert( pCur->pgnoRoot==0 || pCur->pPage->nCell==0 ); *pRes = 1; rc = SQLITE_OK; } return rc; } /* ** This function is a no-op if cursor pCur does not point to a valid row. ** Otherwise, if pCur is valid, configure it so that the next call to ** sqlite3BtreeNext() is a no-op. */ #ifndef SQLITE_OMIT_WINDOWFUNC void sqlite3BtreeSkipNext(BtCursor *pCur){ if( pCur->eState==CURSOR_VALID ){ pCur->eState = CURSOR_SKIPNEXT; pCur->skipNext = 1; } } #endif /* SQLITE_OMIT_WINDOWFUNC */ /* Move the cursor to the last entry in the table. Return SQLITE_OK ** on success. Set *pRes to 0 if the cursor actually points to something ** or set *pRes to 1 if the table is empty. */ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){ int rc; |
︙ | ︙ |
Changes to src/btree.h.
︙ | ︙ | |||
297 298 299 300 301 302 303 304 305 306 307 308 309 310 | int nData; /* Size of pData. 0 if none. */ int nZero; /* Extra zero data appended after pData,nData */ }; int sqlite3BtreeInsert(BtCursor*, const BtreePayload *pPayload, int flags, int seekResult); int sqlite3BtreeFirst(BtCursor*, int *pRes); int sqlite3BtreeLast(BtCursor*, int *pRes); int sqlite3BtreeNext(BtCursor*, int flags); int sqlite3BtreeEof(BtCursor*); int sqlite3BtreePrevious(BtCursor*, int flags); i64 sqlite3BtreeIntegerKey(BtCursor*); #ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC i64 sqlite3BtreeOffset(BtCursor*); | > > > | 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 | int nData; /* Size of pData. 0 if none. */ int nZero; /* Extra zero data appended after pData,nData */ }; int sqlite3BtreeInsert(BtCursor*, const BtreePayload *pPayload, int flags, int seekResult); int sqlite3BtreeFirst(BtCursor*, int *pRes); #ifndef SQLITE_OMIT_WINDOWFUNC void sqlite3BtreeSkipNext(BtCursor*); #endif int sqlite3BtreeLast(BtCursor*, int *pRes); int sqlite3BtreeNext(BtCursor*, int flags); int sqlite3BtreeEof(BtCursor*); int sqlite3BtreePrevious(BtCursor*, int flags); i64 sqlite3BtreeIntegerKey(BtCursor*); #ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC i64 sqlite3BtreeOffset(BtCursor*); |
︙ | ︙ |
Changes to src/expr.c.
︙ | ︙ | |||
1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 | if( p->pRight ){ sqlite3ExprDeleteNN(db, p->pRight); }else if( ExprHasProperty(p, EP_xIsSelect) ){ sqlite3SelectDelete(db, p->x.pSelect); }else{ sqlite3ExprListDelete(db, p->x.pList); } } if( ExprHasProperty(p, EP_MemToken) ) sqlite3DbFree(db, p->u.zToken); if( !ExprHasProperty(p, EP_Static) ){ sqlite3DbFreeNN(db, p); } } void sqlite3ExprDelete(sqlite3 *db, Expr *p){ | > > > | 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 | if( p->pRight ){ sqlite3ExprDeleteNN(db, p->pRight); }else if( ExprHasProperty(p, EP_xIsSelect) ){ sqlite3SelectDelete(db, p->x.pSelect); }else{ sqlite3ExprListDelete(db, p->x.pList); } if( !ExprHasProperty(p, EP_Reduced) ){ sqlite3WindowDelete(db, p->pWin); } } if( ExprHasProperty(p, EP_MemToken) ) sqlite3DbFree(db, p->u.zToken); if( !ExprHasProperty(p, EP_Static) ){ sqlite3DbFreeNN(db, p); } } void sqlite3ExprDelete(sqlite3 *db, Expr *p){ |
︙ | ︙ | |||
1107 1108 1109 1110 1111 1112 1113 | ** The size of the structure can be found by masking the return value ** of this routine with 0xfff. The flags can be found by masking the ** return value with EP_Reduced|EP_TokenOnly. ** ** Note that with flags==EXPRDUP_REDUCE, this routines works on full-size ** (unreduced) Expr objects as they or originally constructed by the parser. ** During expression analysis, extra information is computed and moved into | | | > > > > | 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 | ** The size of the structure can be found by masking the return value ** of this routine with 0xfff. The flags can be found by masking the ** return value with EP_Reduced|EP_TokenOnly. ** ** Note that with flags==EXPRDUP_REDUCE, this routines works on full-size ** (unreduced) Expr objects as they or originally constructed by the parser. ** During expression analysis, extra information is computed and moved into ** later parts of the Expr object and that extra information might get chopped ** off if the expression is reduced. Note also that it does not work to ** make an EXPRDUP_REDUCE copy of a reduced expression. It is only legal ** to reduce a pristine expression tree from the parser. The implementation ** of dupedExprStructSize() contain multiple assert() statements that attempt ** to enforce this constraint. */ static int dupedExprStructSize(Expr *p, int flags){ int nSize; assert( flags==EXPRDUP_REDUCE || flags==0 ); /* Only one flag value allowed */ assert( EXPR_FULLSIZE<=0xfff ); assert( (0xfff & (EP_Reduced|EP_TokenOnly))==0 ); if( 0==flags || p->op==TK_SELECT_COLUMN #ifndef SQLITE_OMIT_WINDOWFUNC || p->pWin #endif ){ nSize = EXPR_FULLSIZE; }else{ assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) ); assert( !ExprHasProperty(p, EP_FromJoin) ); assert( !ExprHasProperty(p, EP_MemToken) ); assert( !ExprHasProperty(p, EP_NoReduce) ); if( p->pLeft || p->x.pList ){ |
︙ | ︙ | |||
1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 | pNew->pRight = p->pRight ? exprDup(db, p->pRight, EXPRDUP_REDUCE, &zAlloc) : 0; } if( pzBuffer ){ *pzBuffer = zAlloc; } }else{ if( !ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){ if( pNew->op==TK_SELECT_COLUMN ){ pNew->pLeft = p->pLeft; assert( p->iColumn==0 || p->pRight==0 ); assert( p->pRight==0 || p->pRight==p->pLeft ); }else{ pNew->pLeft = sqlite3ExprDup(db, p->pLeft, 0); | > > > > > > > | 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 | pNew->pRight = p->pRight ? exprDup(db, p->pRight, EXPRDUP_REDUCE, &zAlloc) : 0; } if( pzBuffer ){ *pzBuffer = zAlloc; } }else{ #ifndef SQLITE_OMIT_WINDOWFUNC if( ExprHasProperty(p, EP_Reduced|EP_TokenOnly) ){ pNew->pWin = 0; }else{ pNew->pWin = sqlite3WindowDup(db, pNew, p->pWin); } #endif /* SQLITE_OMIT_WINDOWFUNC */ if( !ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){ if( pNew->op==TK_SELECT_COLUMN ){ pNew->pLeft = p->pLeft; assert( p->iColumn==0 || p->pRight==0 ); assert( p->pRight==0 || p->pRight==p->pLeft ); }else{ pNew->pLeft = sqlite3ExprDup(db, p->pLeft, 0); |
︙ | ︙ | |||
1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 | pNew->iLimit = 0; pNew->iOffset = 0; pNew->selFlags = p->selFlags & ~SF_UsesEphemeral; pNew->addrOpenEphm[0] = -1; pNew->addrOpenEphm[1] = -1; pNew->nSelectRow = p->nSelectRow; pNew->pWith = withDup(db, p->pWith); sqlite3SelectSetName(pNew, p->zSelName); *pp = pNew; pp = &pNew->pPrior; pNext = pNew; } return pRet; | > > > > | 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 | pNew->iLimit = 0; pNew->iOffset = 0; pNew->selFlags = p->selFlags & ~SF_UsesEphemeral; pNew->addrOpenEphm[0] = -1; pNew->addrOpenEphm[1] = -1; pNew->nSelectRow = p->nSelectRow; pNew->pWith = withDup(db, p->pWith); #ifndef SQLITE_OMIT_WINDOWFUNC pNew->pWin = 0; pNew->pWinDefn = sqlite3WindowListDup(db, p->pWinDefn); #endif sqlite3SelectSetName(pNew, p->zSelName); *pp = pNew; pp = &pNew->pPrior; pNext = pNew; } return pRet; |
︙ | ︙ | |||
3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 | FuncDef *pDef; /* The function definition object */ const char *zId; /* The function name */ u32 constMask = 0; /* Mask of function arguments that are constant */ int i; /* Loop counter */ sqlite3 *db = pParse->db; /* The database connection */ u8 enc = ENC(db); /* The text encoding used by this database */ CollSeq *pColl = 0; /* A collating sequence */ if( ConstFactorOk(pParse) && sqlite3ExprIsConstantNotJoin(pExpr) ){ /* SQL functions can be expensive. So try to move constant functions ** out of the inner loop, even if that means an extra OP_Copy. */ return sqlite3ExprCodeAtInit(pParse, pExpr, -1); } assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); | > > > > > > | 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 | FuncDef *pDef; /* The function definition object */ const char *zId; /* The function name */ u32 constMask = 0; /* Mask of function arguments that are constant */ int i; /* Loop counter */ sqlite3 *db = pParse->db; /* The database connection */ u8 enc = ENC(db); /* The text encoding used by this database */ CollSeq *pColl = 0; /* A collating sequence */ #ifndef SQLITE_OMIT_WINDOWFUNC if( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) && pExpr->pWin ){ return pExpr->pWin->regResult; } #endif if( ConstFactorOk(pParse) && sqlite3ExprIsConstantNotJoin(pExpr) ){ /* SQL functions can be expensive. So try to move constant functions ** out of the inner loop, even if that means an extra OP_Copy. */ return sqlite3ExprCodeAtInit(pParse, pExpr, -1); } assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); |
︙ | ︙ |
Changes to src/func.c.
︙ | ︙ | |||
1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 | } }else{ p->rSum += sqlite3_value_double(argv[0]); p->approx = 1; } } } static void sumFinalize(sqlite3_context *context){ SumCtx *p; p = sqlite3_aggregate_context(context, 0); if( p && p->cnt>0 ){ if( p->overflow ){ sqlite3_result_error(context,"integer overflow",-1); }else if( p->approx ){ | > > > > > > > > > > > > > > > > > > > > > > > > > | 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 | } }else{ p->rSum += sqlite3_value_double(argv[0]); p->approx = 1; } } } #ifndef SQLITE_OMIT_WINDOWFUNC static void sumInverse(sqlite3_context *context, int argc, sqlite3_value**argv){ SumCtx *p; int type; assert( argc==1 ); UNUSED_PARAMETER(argc); p = sqlite3_aggregate_context(context, sizeof(*p)); type = sqlite3_value_numeric_type(argv[0]); if( p && type!=SQLITE_NULL ){ p->cnt--; if( type==SQLITE_INTEGER ){ i64 v = sqlite3_value_int64(argv[0]); p->rSum -= v; if( (p->approx|p->overflow)==0 && sqlite3AddInt64(&p->iSum, -1*v) ){ p->overflow = 1; } }else{ p->rSum += sqlite3_value_double(argv[0]); p->approx = 1; } } } #else # define sumInverse 0 #endif /* SQLITE_OMIT_WINDOWFUNC */ static void sumFinalize(sqlite3_context *context){ SumCtx *p; p = sqlite3_aggregate_context(context, 0); if( p && p->cnt>0 ){ if( p->overflow ){ sqlite3_result_error(context,"integer overflow",-1); }else if( p->approx ){ |
︙ | ︙ | |||
1585 1586 1587 1588 1589 1590 1591 | Mem *pArg = (Mem *)argv[0]; Mem *pBest; UNUSED_PARAMETER(NotUsed); pBest = (Mem *)sqlite3_aggregate_context(context, sizeof(*pBest)); if( !pBest ) return; | | | 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 | Mem *pArg = (Mem *)argv[0]; Mem *pBest; UNUSED_PARAMETER(NotUsed); pBest = (Mem *)sqlite3_aggregate_context(context, sizeof(*pBest)); if( !pBest ) return; if( sqlite3_value_type(pArg)==SQLITE_NULL ){ if( pBest->flags ) sqlite3SkipAccumulatorLoad(context); }else if( pBest->flags ){ int max; int cmp; CollSeq *pColl = sqlite3GetFuncCollSeq(context); /* This step function is used for both the min() and max() aggregates, ** the only difference between the two being that the sense of the |
︙ | ︙ | |||
1611 1612 1613 1614 1615 1616 1617 | sqlite3SkipAccumulatorLoad(context); } }else{ pBest->db = sqlite3_context_db_handle(context); sqlite3VdbeMemCopy(pBest, pArg); } } | | | > > > > > > > > > > | 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 | sqlite3SkipAccumulatorLoad(context); } }else{ pBest->db = sqlite3_context_db_handle(context); sqlite3VdbeMemCopy(pBest, pArg); } } static void minMaxValueFinalize(sqlite3_context *context, int bValue){ sqlite3_value *pRes; pRes = (sqlite3_value *)sqlite3_aggregate_context(context, 0); if( pRes ){ if( pRes->flags ){ sqlite3_result_value(context, pRes); } if( bValue==0 ) sqlite3VdbeMemRelease(pRes); } } #ifndef SQLITE_OMIT_WINDOWFUNC static void minMaxValue(sqlite3_context *context){ return minMaxValueFinalize(context, 1); } #else # define minMaxValue 0 #endif /* SQLITE_OMIT_WINDOWFUNC */ static void minMaxFinalize(sqlite3_context *context){ return minMaxValueFinalize(context, 0); } /* ** group_concat(EXPR, ?SEPARATOR?) */ static void groupConcatStep( sqlite3_context *context, int argc, |
︙ | ︙ | |||
1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 | if( zSep ) sqlite3_str_append(pAccum, zSep, nSep); } zVal = (char*)sqlite3_value_text(argv[0]); nVal = sqlite3_value_bytes(argv[0]); if( zVal ) sqlite3_str_append(pAccum, zVal, nVal); } } 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); } } } /* ** This routine does per-connection function registration. Most ** of the built-in functions above are part of the global function set. ** This routine only deals with those that are not global. */ void sqlite3RegisterPerConnectionBuiltinFunctions(sqlite3 *db){ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 | if( zSep ) sqlite3_str_append(pAccum, zSep, nSep); } zVal = (char*)sqlite3_value_text(argv[0]); nVal = sqlite3_value_bytes(argv[0]); if( zVal ) sqlite3_str_append(pAccum, zVal, nVal); } } #ifndef SQLITE_OMIT_WINDOWFUNC static void groupConcatInverse( sqlite3_context *context, int argc, sqlite3_value **argv ){ int n; assert( argc==1 || argc==2 ); StrAccum *pAccum; if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; pAccum = (StrAccum*)sqlite3_aggregate_context(context, sizeof(*pAccum)); if( pAccum ){ n = sqlite3_value_bytes(argv[0]); if( argc==2 ){ n += sqlite3_value_bytes(argv[1]); } if( n>=pAccum->nChar ){ pAccum->nChar = 0; }else{ pAccum->nChar -= n; memmove(pAccum->zText, &pAccum->zText[n], pAccum->nChar); } 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); } } } #ifndef SQLITE_OMIT_WINDOWFUNC static void groupConcatValue(sqlite3_context *context){ sqlite3_str *pAccum; pAccum = (sqlite3_str*)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{ const char *zText = sqlite3_str_value(pAccum); sqlite3_result_text(context, zText, -1, SQLITE_TRANSIENT); } } } #else # define groupConcatValue 0 #endif /* SQLITE_OMIT_WINDOWFUNC */ /* ** This routine does per-connection function registration. Most ** of the built-in functions above are part of the global function set. ** This routine only deals with those that are not global. */ void sqlite3RegisterPerConnectionBuiltinFunctions(sqlite3 *db){ |
︙ | ︙ | |||
1708 1709 1710 1711 1712 1713 1714 | void sqlite3RegisterLikeFunctions(sqlite3 *db, int caseSensitive){ struct compareInfo *pInfo; if( caseSensitive ){ pInfo = (struct compareInfo*)&likeInfoAlt; }else{ pInfo = (struct compareInfo*)&likeInfoNorm; } | | | | | 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 | void sqlite3RegisterLikeFunctions(sqlite3 *db, int caseSensitive){ struct compareInfo *pInfo; if( caseSensitive ){ pInfo = (struct compareInfo*)&likeInfoAlt; }else{ pInfo = (struct compareInfo*)&likeInfoNorm; } sqlite3CreateFunc(db, "like", 2, SQLITE_UTF8, pInfo, likeFunc, 0, 0, 0, 0, 0); sqlite3CreateFunc(db, "like", 3, SQLITE_UTF8, pInfo, likeFunc, 0, 0, 0, 0, 0); sqlite3CreateFunc(db, "glob", 2, SQLITE_UTF8, (struct compareInfo*)&globInfo, likeFunc, 0, 0, 0, 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 |
︙ | ︙ | |||
1820 1821 1822 1823 1824 1825 1826 | FUNCTION(ltrim, 2, 1, 0, trimFunc ), FUNCTION(rtrim, 1, 2, 0, trimFunc ), FUNCTION(rtrim, 2, 2, 0, trimFunc ), FUNCTION(trim, 1, 3, 0, trimFunc ), FUNCTION(trim, 2, 3, 0, trimFunc ), FUNCTION(min, -1, 0, 1, minmaxFunc ), FUNCTION(min, 0, 0, 1, 0 ), | | | | 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 | FUNCTION(ltrim, 2, 1, 0, trimFunc ), FUNCTION(rtrim, 1, 2, 0, trimFunc ), FUNCTION(rtrim, 2, 2, 0, trimFunc ), FUNCTION(trim, 1, 3, 0, trimFunc ), FUNCTION(trim, 2, 3, 0, trimFunc ), FUNCTION(min, -1, 0, 1, minmaxFunc ), FUNCTION(min, 0, 0, 1, 0 ), WAGGREGATE(min, 1, 0, 1, minmaxStep, minMaxFinalize, minMaxValue, 0, SQLITE_FUNC_MINMAX ), FUNCTION(max, -1, 1, 1, minmaxFunc ), FUNCTION(max, 0, 1, 1, 0 ), WAGGREGATE(max, 1, 1, 1, minmaxStep, minMaxFinalize, minMaxValue, 0, SQLITE_FUNC_MINMAX ), FUNCTION2(typeof, 1, 0, 0, typeofFunc, 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(unicode, 1, 0, 0, unicodeFunc ), FUNCTION(char, -1, 0, 0, charFunc ), |
︙ | ︙ | |||
1855 1856 1857 1858 1859 1860 1861 | VFUNCTION(last_insert_rowid, 0, 0, 0, last_insert_rowid), VFUNCTION(changes, 0, 0, 0, changes ), VFUNCTION(total_changes, 0, 0, 0, total_changes ), FUNCTION(replace, 3, 0, 0, replaceFunc ), FUNCTION(zeroblob, 1, 0, 0, zeroblobFunc ), FUNCTION(substr, 2, 0, 0, substrFunc ), FUNCTION(substr, 3, 0, 0, substrFunc ), | | | | < | | | > | > > | 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 | VFUNCTION(last_insert_rowid, 0, 0, 0, last_insert_rowid), VFUNCTION(changes, 0, 0, 0, changes ), VFUNCTION(total_changes, 0, 0, 0, total_changes ), FUNCTION(replace, 3, 0, 0, replaceFunc ), FUNCTION(zeroblob, 1, 0, 0, zeroblobFunc ), FUNCTION(substr, 2, 0, 0, substrFunc ), FUNCTION(substr, 3, 0, 0, substrFunc ), WAGGREGATE(sum, 1,0,0, sumStep, sumFinalize, sumFinalize, sumInverse, 0), WAGGREGATE(total, 1,0,0, sumStep,totalFinalize,totalFinalize,sumInverse, 0), WAGGREGATE(avg, 1,0,0, sumStep, avgFinalize, avgFinalize, sumInverse, 0), AGGREGATE2(count, 0,0,0, countStep, countFinalize, SQLITE_FUNC_COUNT ), WAGGREGATE(count, 1,0,0, countStep, countFinalize, 0, 0, 0 ), WAGGREGATE(group_concat, 1, 0, 0, groupConcatStep, groupConcatFinalize, groupConcatValue, groupConcatInverse, 0), WAGGREGATE(group_concat, 2, 0, 0, groupConcatStep, groupConcatFinalize, groupConcatValue, groupConcatInverse, 0), LIKEFUNC(glob, 2, &globInfo, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE), #ifdef SQLITE_CASE_SENSITIVE_LIKE LIKEFUNC(like, 2, &likeInfoAlt, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE), LIKEFUNC(like, 3, &likeInfoAlt, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE), #else LIKEFUNC(like, 2, &likeInfoNorm, SQLITE_FUNC_LIKE), LIKEFUNC(like, 3, &likeInfoNorm, SQLITE_FUNC_LIKE), #endif #ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION FUNCTION(unknown, -1, 0, 0, unknownFunc ), #endif FUNCTION(coalesce, 1, 0, 0, 0 ), FUNCTION(coalesce, 0, 0, 0, 0 ), FUNCTION2(coalesce, -1, 0, 0, noopFunc, SQLITE_FUNC_COALESCE), }; #ifndef SQLITE_OMIT_ALTERTABLE sqlite3AlterFunctions(); #endif sqlite3WindowFunctions(); #if defined(SQLITE_ENABLE_STAT3) || defined(SQLITE_ENABLE_STAT4) sqlite3AnalyzeFunctions(); #endif sqlite3RegisterDateTimeFunctions(); sqlite3InsertBuiltinFuncs(aBuiltinFunc, ArraySize(aBuiltinFunc)); #if 0 /* Enable to print out how the built-in functions are hashed */ |
︙ | ︙ |
Changes to src/main.c.
︙ | ︙ | |||
1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 | const char *zFunctionName, int nArg, int enc, void *pUserData, void (*xSFunc)(sqlite3_context*,int,sqlite3_value **), void (*xStep)(sqlite3_context*,int,sqlite3_value **), void (*xFinal)(sqlite3_context*), FuncDestructor *pDestructor ){ FuncDef *p; int nName; int extraFlags; assert( sqlite3_mutex_held(db->mutex) ); if( zFunctionName==0 || (xSFunc && (xFinal || xStep)) || (!xSFunc && (xFinal && !xStep)) || (!xSFunc && (!xFinal && xStep)) || (nArg<-1 || nArg>SQLITE_MAX_FUNCTION_ARG) || (255<(nName = sqlite3Strlen30( zFunctionName))) ){ return SQLITE_MISUSE_BKPT; } assert( SQLITE_FUNC_CONSTANT==SQLITE_DETERMINISTIC ); extraFlags = enc & SQLITE_DETERMINISTIC; | > > > | 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 | const char *zFunctionName, int nArg, int enc, void *pUserData, void (*xSFunc)(sqlite3_context*,int,sqlite3_value **), void (*xStep)(sqlite3_context*,int,sqlite3_value **), void (*xFinal)(sqlite3_context*), void (*xValue)(sqlite3_context*), void (*xInverse)(sqlite3_context*,int,sqlite3_value **), FuncDestructor *pDestructor ){ FuncDef *p; int nName; int extraFlags; assert( sqlite3_mutex_held(db->mutex) ); if( zFunctionName==0 || (xSFunc && (xFinal || xStep)) || (!xSFunc && (xFinal && !xStep)) || (!xSFunc && (!xFinal && xStep)) || ((xValue || xInverse) && (!xStep || !xFinal || !xValue || !xInverse)) || (nArg<-1 || nArg>SQLITE_MAX_FUNCTION_ARG) || (255<(nName = sqlite3Strlen30( zFunctionName))) ){ return SQLITE_MISUSE_BKPT; } assert( SQLITE_FUNC_CONSTANT==SQLITE_DETERMINISTIC ); extraFlags = enc & SQLITE_DETERMINISTIC; |
︙ | ︙ | |||
1712 1713 1714 1715 1716 1717 1718 | ** to the hash table. */ if( enc==SQLITE_UTF16 ){ enc = SQLITE_UTF16NATIVE; }else if( enc==SQLITE_ANY ){ int rc; rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF8|extraFlags, | | | | 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 | ** to the hash table. */ if( enc==SQLITE_UTF16 ){ enc = SQLITE_UTF16NATIVE; }else if( enc==SQLITE_ANY ){ int rc; rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF8|extraFlags, pUserData, xSFunc, xStep, xFinal, xValue, xInverse, pDestructor); if( rc==SQLITE_OK ){ rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF16LE|extraFlags, pUserData, xSFunc, xStep, xFinal, xValue, xInverse, pDestructor); } if( rc!=SQLITE_OK ){ return rc; } enc = SQLITE_UTF16BE; } #else |
︙ | ︙ | |||
1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 | pDestructor->nRef++; } p->u.pDestructor = pDestructor; p->funcFlags = (p->funcFlags & SQLITE_FUNC_ENCMASK) | extraFlags; testcase( p->funcFlags & SQLITE_DETERMINISTIC ); p->xSFunc = xSFunc ? xSFunc : xStep; p->xFinalize = xFinal; p->pUserData = pUserData; p->nArg = (u16)nArg; return SQLITE_OK; } /* | > > | | | > > > > | | | < < < < < < < < < < < | | < | | 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 | pDestructor->nRef++; } p->u.pDestructor = pDestructor; p->funcFlags = (p->funcFlags & SQLITE_FUNC_ENCMASK) | extraFlags; testcase( p->funcFlags & SQLITE_DETERMINISTIC ); p->xSFunc = xSFunc ? xSFunc : xStep; p->xFinalize = xFinal; p->xValue = xValue; p->xInverse = xInverse; p->pUserData = pUserData; p->nArg = (u16)nArg; return SQLITE_OK; } /* ** Worker function used by utf-8 APIs that create new functions: ** ** sqlite3_create_function() ** sqlite3_create_function_v2() ** sqlite3_create_window_function() */ static int createFunctionApi( sqlite3 *db, const char *zFunc, int nArg, int enc, void *p, void (*xSFunc)(sqlite3_context*,int,sqlite3_value**), void (*xStep)(sqlite3_context*,int,sqlite3_value**), void (*xFinal)(sqlite3_context*), void (*xValue)(sqlite3_context*), void (*xInverse)(sqlite3_context*,int,sqlite3_value**), void(*xDestroy)(void*) ){ int rc = SQLITE_ERROR; FuncDestructor *pArg = 0; #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) ){ return SQLITE_MISUSE_BKPT; |
︙ | ︙ | |||
1814 1815 1816 1817 1818 1819 1820 | xDestroy(p); goto out; } pArg->nRef = 0; pArg->xDestroy = xDestroy; pArg->pUserData = p; } | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 | xDestroy(p); goto out; } pArg->nRef = 0; pArg->xDestroy = xDestroy; pArg->pUserData = p; } rc = sqlite3CreateFunc(db, zFunc, nArg, enc, p, xSFunc, xStep, xFinal, xValue, xInverse, pArg ); if( pArg && pArg->nRef==0 ){ assert( rc!=SQLITE_OK ); xDestroy(p); sqlite3_free(pArg); } out: rc = sqlite3ApiExit(db, rc); sqlite3_mutex_leave(db->mutex); return rc; } /* ** Create new user functions. */ int sqlite3_create_function( sqlite3 *db, const char *zFunc, int nArg, int enc, void *p, void (*xSFunc)(sqlite3_context*,int,sqlite3_value **), void (*xStep)(sqlite3_context*,int,sqlite3_value **), void (*xFinal)(sqlite3_context*) ){ return createFunctionApi(db, zFunc, nArg, enc, p, xSFunc, xStep, xFinal, 0, 0, 0); } int sqlite3_create_function_v2( sqlite3 *db, const char *zFunc, int nArg, int enc, void *p, void (*xSFunc)(sqlite3_context*,int,sqlite3_value **), void (*xStep)(sqlite3_context*,int,sqlite3_value **), void (*xFinal)(sqlite3_context*), void (*xDestroy)(void *) ){ return createFunctionApi(db, zFunc, nArg, enc, p, xSFunc, xStep, xFinal, 0, 0, xDestroy); } int sqlite3_create_window_function( sqlite3 *db, const char *zFunc, int nArg, int enc, void *p, void (*xStep)(sqlite3_context*,int,sqlite3_value **), void (*xFinal)(sqlite3_context*), void (*xValue)(sqlite3_context*), void (*xInverse)(sqlite3_context*,int,sqlite3_value **), void (*xDestroy)(void *) ){ return createFunctionApi(db, zFunc, nArg, enc, p, 0, xStep, xFinal, xValue, xInverse, xDestroy); } #ifndef SQLITE_OMIT_UTF16 int sqlite3_create_function16( sqlite3 *db, const void *zFunctionName, int nArg, int eTextRep, |
︙ | ︙ | |||
1847 1848 1849 1850 1851 1852 1853 | #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) || zFunctionName==0 ) return SQLITE_MISUSE_BKPT; #endif sqlite3_mutex_enter(db->mutex); assert( !db->mallocFailed ); zFunc8 = sqlite3Utf16to8(db, zFunctionName, -1, SQLITE_UTF16NATIVE); | | | 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 | #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) || zFunctionName==0 ) return SQLITE_MISUSE_BKPT; #endif sqlite3_mutex_enter(db->mutex); assert( !db->mallocFailed ); zFunc8 = sqlite3Utf16to8(db, zFunctionName, -1, SQLITE_UTF16NATIVE); rc = sqlite3CreateFunc(db, zFunc8, nArg, eTextRep, p, xSFunc,xStep,xFinal,0,0,0); sqlite3DbFree(db, zFunc8); rc = sqlite3ApiExit(db, rc); sqlite3_mutex_leave(db->mutex); return rc; } #endif |
︙ | ︙ |
Changes to src/parse.y.
︙ | ︙ | |||
95 96 97 98 99 100 101 102 103 104 105 106 107 108 | ** ** UPDATE ON (a,b,c) ** ** Then the "b" IdList records the list "a,b,c". */ struct TrigEvent { int a; IdList * b; }; /* ** Disable lookaside memory allocation for objects that might be ** shared across database connections. */ static void disableLookaside(Parse *pParse){ pParse->disableLookaside++; pParse->db->lookaside.bDisable++; | > > | 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | ** ** UPDATE ON (a,b,c) ** ** Then the "b" IdList records the list "a,b,c". */ struct TrigEvent { int a; IdList * b; }; struct FrameBound { int eType; Expr *pExpr; }; /* ** Disable lookaside memory allocation for objects that might be ** shared across database connections. */ static void disableLookaside(Parse *pParse){ pParse->disableLookaside++; pParse->db->lookaside.bDisable++; |
︙ | ︙ | |||
205 206 207 208 209 210 211 | // This obviates the need for the "id" nonterminal. // %fallback ID ABORT ACTION AFTER ANALYZE ASC ATTACH BEFORE BEGIN BY CASCADE CAST COLUMNKW CONFLICT DATABASE DEFERRED DESC DETACH DO EACH END EXCLUSIVE EXPLAIN FAIL FOR IGNORE IMMEDIATE INITIALLY INSTEAD LIKE_KW MATCH NO PLAN | | > > > | 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 | // This obviates the need for the "id" nonterminal. // %fallback ID ABORT ACTION AFTER ANALYZE ASC ATTACH BEFORE BEGIN BY CASCADE CAST COLUMNKW CONFLICT DATABASE DEFERRED DESC DETACH DO EACH END EXCLUSIVE EXPLAIN FAIL FOR IGNORE IMMEDIATE INITIALLY INSTEAD LIKE_KW MATCH NO PLAN QUERY KEY OF OFFSET PRAGMA RAISE RECURSIVE RELEASE REPLACE RESTRICT ROW ROWS ROLLBACK SAVEPOINT TEMP TRIGGER VACUUM VIEW VIRTUAL WITH WITHOUT %ifdef SQLITE_OMIT_COMPOUND_SELECT EXCEPT INTERSECT UNION %endif SQLITE_OMIT_COMPOUND_SELECT %ifndef SQLITE_OMIT_WINDOWFUNC CURRENT FOLLOWING PARTITION PRECEDING RANGE UNBOUNDED %endif SQLITE_OMIT_WINDOWFUNC REINDEX RENAME CTIME_KW IF . %wildcard ANY. // Define operator precedence early so that this is the first occurrence // of the operator tokens in the grammer. Keeping the operators together // causes them to be assigned integer values that are close together, |
︙ | ︙ | |||
523 524 525 526 527 528 529 | } %type multiselect_op {int} multiselect_op(A) ::= UNION(OP). {A = @OP; /*A-overwrites-OP*/} multiselect_op(A) ::= UNION ALL. {A = TK_ALL;} multiselect_op(A) ::= EXCEPT|INTERSECT(OP). {A = @OP; /*A-overwrites-OP*/} %endif SQLITE_OMIT_COMPOUND_SELECT oneselect(A) ::= SELECT(S) distinct(D) selcollist(W) from(X) where_opt(Y) | | > > > > > > > > > > > | 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 | } %type multiselect_op {int} multiselect_op(A) ::= UNION(OP). {A = @OP; /*A-overwrites-OP*/} multiselect_op(A) ::= UNION ALL. {A = TK_ALL;} multiselect_op(A) ::= EXCEPT|INTERSECT(OP). {A = @OP; /*A-overwrites-OP*/} %endif SQLITE_OMIT_COMPOUND_SELECT oneselect(A) ::= SELECT(S) distinct(D) selcollist(W) from(X) where_opt(Y) groupby_opt(P) having_opt(Q) %ifndef SQLITE_OMIT_WINDOWFUNC windowdefn_opt(R) %endif orderby_opt(Z) limit_opt(L). { #if SELECTTRACE_ENABLED Token s = S; /*A-overwrites-S*/ #endif A = sqlite3SelectNew(pParse,W,X,Y,P,Q,Z,D,L); #ifndef SQLITE_OMIT_WINDOWFUNC if( A ){ A->pWinDefn = R; }else{ sqlite3WindowListDelete(pParse->db, R); } #endif // SQLITE_OMIT_WINDOWFUNC #if SELECTTRACE_ENABLED /* Populate the Select.zSelName[] string that is used to help with ** query planner debugging, to differentiate between multiple Select ** objects in a complex query. ** ** If the SELECT keyword is immediately followed by a C-style comment ** then extract the first few alphanumeric characters from within that |
︙ | ︙ | |||
999 1000 1001 1002 1003 1004 1005 | } %ifndef SQLITE_OMIT_CAST expr(A) ::= CAST LP expr(E) AS typetoken(T) RP. { A = sqlite3ExprAlloc(pParse->db, TK_CAST, &T, 1); sqlite3ExprAttachSubtrees(pParse->db, A, E, 0); } %endif SQLITE_OMIT_CAST | | > > > > > | > > > > > | 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 | } %ifndef SQLITE_OMIT_CAST expr(A) ::= CAST LP expr(E) AS typetoken(T) RP. { A = sqlite3ExprAlloc(pParse->db, TK_CAST, &T, 1); sqlite3ExprAttachSubtrees(pParse->db, A, E, 0); } %endif SQLITE_OMIT_CAST expr(A) ::= id(X) LP distinct(D) exprlist(Y) RP %ifndef SQLITE_OMIT_WINDOWFUNC over_opt(Z) %endif . { if( Y && Y->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){ sqlite3ErrorMsg(pParse, "too many arguments on function %T", &X); } A = sqlite3ExprFunction(pParse, Y, &X); sqlite3WindowAttach(pParse, A, Z); if( D==SF_Distinct && A ){ A->flags |= EP_Distinct; } } expr(A) ::= id(X) LP STAR RP %ifndef SQLITE_OMIT_WINDOWFUNC over_opt(Z) %endif . { A = sqlite3ExprFunction(pParse, 0, &X); sqlite3WindowAttach(pParse, A, Z); } term(A) ::= CTIME_KW(OP). { A = sqlite3ExprFunction(pParse, 0, &OP); } expr(A) ::= LP nexprlist(X) COMMA expr(Y) RP. { ExprList *pList = sqlite3ExprListAppend(pParse, X, Y); |
︙ | ︙ | |||
1566 1567 1568 1569 1570 1571 1572 | wqlist(A) ::= nm(X) eidlist_opt(Y) AS LP select(Z) RP. { A = sqlite3WithAdd(pParse, 0, &X, Y, Z); /*A-overwrites-X*/ } wqlist(A) ::= wqlist(A) COMMA nm(X) eidlist_opt(Y) AS LP select(Z) RP. { A = sqlite3WithAdd(pParse, A, &X, Y, Z); } %endif SQLITE_OMIT_CTE | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 | wqlist(A) ::= nm(X) eidlist_opt(Y) AS LP select(Z) RP. { A = sqlite3WithAdd(pParse, 0, &X, Y, Z); /*A-overwrites-X*/ } wqlist(A) ::= wqlist(A) COMMA nm(X) eidlist_opt(Y) AS LP select(Z) RP. { A = sqlite3WithAdd(pParse, A, &X, Y, Z); } %endif SQLITE_OMIT_CTE //////////////////////// WINDOW FUNCTION EXPRESSIONS ///////////////////////// // These must be at the end of this file. Specifically, the rules that // introduce tokens WINDOW, OVER and FILTER must appear last. This causes // the integer values assigned to these tokens to be larger than all other // tokens that may be output by the tokenizer except TK_SPACE and TK_ILLEGAL. // %ifndef SQLITE_OMIT_WINDOWFUNC %type windowdefn_list {Window*} %destructor windowdefn_list {sqlite3WindowDelete(pParse->db, $$);} windowdefn_list(A) ::= windowdefn(Z). { A = Z; } windowdefn_list(A) ::= windowdefn_list(Y) COMMA windowdefn(Z). { if( Z ) Z->pNextWin = Y; A = Z; } %type windowdefn {Window*} %destructor windowdefn {sqlite3WindowDelete(pParse->db, $$);} windowdefn(A) ::= nm(X) AS window(Y). { if( Y ){ Y->zName = sqlite3DbStrNDup(pParse->db, X.z, X.n); } A = Y; } %type window {Window*} %destructor window {sqlite3WindowDelete(pParse->db, $$);} %type frame_opt {Window*} %destructor frame_opt {sqlite3WindowDelete(pParse->db, $$);} %type window_or_nm {Window*} %destructor window_or_nm { sqlite3WindowDelete(pParse->db, $$);} %type part_opt {ExprList*} %destructor part_opt {sqlite3ExprListDelete(pParse->db, $$);} %type filter_opt {Expr*} %destructor filter_opt {sqlite3ExprDelete(pParse->db, $$);} %type range_or_rows {int} %type frame_bound {struct FrameBound} %destructor frame_bound {sqlite3ExprDelete(pParse->db, $$.pExpr);} window_or_nm(A) ::= window(Z). {A = Z;} window_or_nm(A) ::= nm(Z). { A = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window)); if( A ){ A->zName = sqlite3DbStrNDup(pParse->db, Z.z, Z.n); } } window(A) ::= LP part_opt(X) orderby_opt(Y) frame_opt(Z) RP. { A = Z; if( A ){ A->pPartition = X; A->pOrderBy = Y; } } part_opt(A) ::= PARTITION BY exprlist(X). { A = X; } part_opt(A) ::= . { A = 0; } frame_opt(A) ::= . { A = sqlite3WindowAlloc(pParse, TK_RANGE, TK_UNBOUNDED, 0, TK_CURRENT, 0); } frame_opt(A) ::= range_or_rows(X) frame_bound(Y). { A = sqlite3WindowAlloc(pParse, X, Y.eType, Y.pExpr, TK_CURRENT, 0); } frame_opt(A) ::= range_or_rows(X) BETWEEN frame_bound(Y) AND frame_bound(Z). { A = sqlite3WindowAlloc(pParse, X, Y.eType, Y.pExpr, Z.eType, Z.pExpr); } range_or_rows(A) ::= RANGE. { A = TK_RANGE; } range_or_rows(A) ::= ROWS. { A = TK_ROWS; } frame_bound(A) ::= UNBOUNDED PRECEDING. { A.eType = TK_UNBOUNDED; A.pExpr = 0; } frame_bound(A) ::= expr(X) PRECEDING. { A.eType = TK_PRECEDING; A.pExpr = X; } frame_bound(A) ::= CURRENT ROW. { A.eType = TK_CURRENT ; A.pExpr = 0; } frame_bound(A) ::= expr(X) FOLLOWING. { A.eType = TK_FOLLOWING; A.pExpr = X; } frame_bound(A) ::= UNBOUNDED FOLLOWING. { A.eType = TK_UNBOUNDED; A.pExpr = 0; } %type windowdefn_opt {Window*} %destructor windowdefn_opt {sqlite3WindowDelete(pParse->db, $$);} windowdefn_opt(A) ::= . { A = 0; } windowdefn_opt(A) ::= WINDOW windowdefn_list(B). { A = B; } %type over_opt {Window*} %destructor over_opt {sqlite3WindowDelete(pParse->db, $$);} over_opt(A) ::= . { A = 0; } over_opt(A) ::= filter_opt(W) OVER window_or_nm(Z). { A = Z; if( A ) A->pFilter = W; } filter_opt(A) ::= . { A = 0; } filter_opt(A) ::= FILTER LP WHERE expr(X) RP. { A = X; } %endif // SQLITE_OMIT_WINDOWFUNC |
Changes to src/resolve.c.
︙ | ︙ | |||
752 753 754 755 756 757 758 | /* Date/time functions that use 'now', and other functions like ** sqlite_version() that might change over time cannot be used ** in an index. */ notValid(pParse, pNC, "non-deterministic functions", NC_IdxExpr|NC_PartIdx); } } | > > > > > > > > | > > > > > > > > > > > > > > > > > | > > > > | > > > > > > > > > > > > > > > > > > > | | | | | | | | | | | | | | > | 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 | /* Date/time functions that use 'now', and other functions like ** sqlite_version() that might change over time cannot be used ** in an index. */ notValid(pParse, pNC, "non-deterministic functions", NC_IdxExpr|NC_PartIdx); } } #ifndef SQLITE_OMIT_WINDOWFUNC if( is_agg==0 && pExpr->pWin ){ sqlite3ErrorMsg(pParse, "%.*s() may not be used as a window function", nId, zId ); pNC->nErr++; }else if( (is_agg && (pNC->ncFlags & NC_AllowAgg)==0) || (is_agg && (pDef->funcFlags & SQLITE_FUNC_WINDOW) && !pExpr->pWin) || (is_agg && pExpr->pWin && (pNC->ncFlags & NC_AllowWin)==0) ){ const char *zType; if( (pDef->funcFlags & SQLITE_FUNC_WINDOW) || pExpr->pWin ){ zType = "window"; }else{ zType = "aggregate"; } sqlite3ErrorMsg(pParse, "misuse of %s function %.*s()", zType, nId,zId); pNC->nErr++; is_agg = 0; } #else if( (is_agg && (pNC->ncFlags & NC_AllowAgg)==0) ){ sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId); pNC->nErr++; is_agg = 0; } #endif else if( no_such_func && pParse->db->init.busy==0 #ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION && pParse->explain==0 #endif ){ sqlite3ErrorMsg(pParse, "no such function: %.*s", nId, zId); pNC->nErr++; }else if( wrong_num_args ){ sqlite3ErrorMsg(pParse,"wrong number of arguments to function %.*s()", nId, zId); pNC->nErr++; } if( is_agg ){ #ifndef SQLITE_OMIT_WINDOWFUNC pNC->ncFlags &= ~(pExpr->pWin ? NC_AllowWin : NC_AllowAgg); #else pNC->ncFlags &= ~NC_AllowAgg; #endif } sqlite3WalkExprList(pWalker, pList); if( is_agg ){ #ifndef SQLITE_OMIT_WINDOWFUNC if( pExpr->pWin ){ Select *pSel = pNC->pWinSelect; sqlite3WalkExprList(pWalker, pExpr->pWin->pPartition); sqlite3WalkExprList(pWalker, pExpr->pWin->pOrderBy); sqlite3WalkExpr(pWalker, pExpr->pWin->pFilter); sqlite3WindowUpdate(pParse, pSel->pWinDefn, pExpr->pWin, pDef); if( 0==pSel->pWin || 0==sqlite3WindowCompare(pParse, pSel->pWin, pExpr->pWin) ){ pExpr->pWin->pNextWin = pSel->pWin; pSel->pWin = pExpr->pWin; } pNC->ncFlags |= NC_AllowWin; }else #endif /* SQLITE_OMIT_WINDOWFUNC */ { NameContext *pNC2 = pNC; pExpr->op = TK_AGG_FUNCTION; pExpr->op2 = 0; while( pNC2 && !sqlite3FunctionUsesThisSrc(pExpr, pNC2->pSrcList) ){ pExpr->op2++; pNC2 = pNC2->pNext; } assert( pDef!=0 ); if( pNC2 ){ assert( SQLITE_FUNC_MINMAX==NC_MinMaxAgg ); testcase( (pDef->funcFlags & SQLITE_FUNC_MINMAX)!=0 ); pNC2->ncFlags |= NC_HasAgg | (pDef->funcFlags & SQLITE_FUNC_MINMAX); } pNC->ncFlags |= NC_AllowAgg; } } /* FIX ME: Compute pExpr->affinity based on the expected return ** type of the function */ return WRC_Prune; } #ifndef SQLITE_OMIT_SUBQUERY |
︙ | ︙ | |||
1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 | p->selFlags |= SF_Resolved; /* Resolve the expressions in the LIMIT and OFFSET clauses. These ** are not allowed to refer to any names, so pass an empty NameContext. */ memset(&sNC, 0, sizeof(sNC)); sNC.pParse = pParse; if( sqlite3ResolveExprNames(&sNC, p->pLimit) ){ return WRC_Abort; } /* If the SF_Converted flags is set, then this Select object was ** was created by the convertCompoundSelectToSubquery() function. ** In this case the ORDER BY clause (p->pOrderBy) should be resolved | > | 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 | p->selFlags |= SF_Resolved; /* Resolve the expressions in the LIMIT and OFFSET clauses. These ** are not allowed to refer to any names, so pass an empty NameContext. */ memset(&sNC, 0, sizeof(sNC)); sNC.pParse = pParse; sNC.pWinSelect = p; if( sqlite3ResolveExprNames(&sNC, p->pLimit) ){ return WRC_Abort; } /* If the SF_Converted flags is set, then this Select object was ** was created by the convertCompoundSelectToSubquery() function. ** In this case the ORDER BY clause (p->pOrderBy) should be resolved |
︙ | ︙ | |||
1290 1291 1292 1293 1294 1295 1296 | pItem->fg.isCorrelated = (nRef!=0); } } /* Set up the local name-context to pass to sqlite3ResolveExprNames() to ** resolve the result-set expression list. */ | | > | 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 | pItem->fg.isCorrelated = (nRef!=0); } } /* Set up the local name-context to pass to sqlite3ResolveExprNames() to ** resolve the result-set expression list. */ sNC.ncFlags = NC_AllowAgg|NC_AllowWin; sNC.pSrcList = p->pSrc; sNC.pNext = pOuterNC; /* Resolve names in the result set. */ if( sqlite3ResolveExprListNames(&sNC, p->pEList) ) return WRC_Abort; sNC.ncFlags &= ~NC_AllowWin; /* If there are no aggregate functions in the result-set, and no GROUP BY ** expression, do not allow aggregates in any of the other expressions. */ assert( (p->selFlags & SF_Aggregate)==0 ); pGroupBy = p->pGroupBy; if( pGroupBy || (sNC.ncFlags & NC_HasAgg)!=0 ){ |
︙ | ︙ | |||
1344 1345 1346 1347 1348 1349 1350 | } } /* The ORDER BY and GROUP BY clauses may not refer to terms in ** outer queries */ sNC.pNext = 0; | | | 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 | } } /* The ORDER BY and GROUP BY clauses may not refer to terms in ** outer queries */ sNC.pNext = 0; sNC.ncFlags |= NC_AllowAgg|NC_AllowWin; /* If this is a converted compound query, move the ORDER BY clause from ** the sub-query back to the parent query. At this point each term ** within the ORDER BY clause has been transformed to an integer value. ** These integers will be replaced by copies of the corresponding result ** set expressions by the call to resolveOrderGroupBy() below. */ if( p->selFlags & SF_Converted ){ |
︙ | ︙ | |||
1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 | && resolveOrderGroupBy(&sNC, p, p->pOrderBy, "ORDER") ){ return WRC_Abort; } if( db->mallocFailed ){ return WRC_Abort; } /* Resolve the GROUP BY clause. At the same time, make sure ** the GROUP BY clause does not contain aggregate functions. */ if( pGroupBy ){ struct ExprList_item *pItem; | > | 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 | && resolveOrderGroupBy(&sNC, p, p->pOrderBy, "ORDER") ){ return WRC_Abort; } if( db->mallocFailed ){ return WRC_Abort; } sNC.ncFlags &= ~NC_AllowWin; /* Resolve the GROUP BY clause. At the same time, make sure ** the GROUP BY clause does not contain aggregate functions. */ if( pGroupBy ){ struct ExprList_item *pItem; |
︙ | ︙ |
Changes to src/select.c.
︙ | ︙ | |||
92 93 94 95 96 97 98 99 100 101 102 103 104 105 | sqlite3ExprListDelete(db, p->pEList); sqlite3SrcListDelete(db, p->pSrc); sqlite3ExprDelete(db, p->pWhere); sqlite3ExprListDelete(db, p->pGroupBy); sqlite3ExprDelete(db, p->pHaving); sqlite3ExprListDelete(db, p->pOrderBy); sqlite3ExprDelete(db, p->pLimit); if( OK_IF_ALWAYS_TRUE(p->pWith) ) sqlite3WithDelete(db, p->pWith); if( bFree ) sqlite3DbFreeNN(db, p); p = pPrior; bFree = 1; } } | > > > > > | 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | sqlite3ExprListDelete(db, p->pEList); sqlite3SrcListDelete(db, p->pSrc); sqlite3ExprDelete(db, p->pWhere); sqlite3ExprListDelete(db, p->pGroupBy); sqlite3ExprDelete(db, p->pHaving); sqlite3ExprListDelete(db, p->pOrderBy); sqlite3ExprDelete(db, p->pLimit); #ifndef SQLITE_OMIT_WINDOWFUNC if( OK_IF_ALWAYS_TRUE(p->pWinDefn) ){ sqlite3WindowListDelete(db, p->pWinDefn); } #endif if( OK_IF_ALWAYS_TRUE(p->pWith) ) sqlite3WithDelete(db, p->pWith); if( bFree ) sqlite3DbFreeNN(db, p); p = pPrior; bFree = 1; } } |
︙ | ︙ | |||
158 159 160 161 162 163 164 165 166 167 168 169 170 171 | pNew->pGroupBy = pGroupBy; pNew->pHaving = pHaving; pNew->pOrderBy = pOrderBy; pNew->pPrior = 0; pNew->pNext = 0; pNew->pLimit = pLimit; pNew->pWith = 0; if( pParse->db->mallocFailed ) { clearSelect(pParse->db, pNew, pNew!=&standin); pNew = 0; }else{ assert( pNew->pSrc!=0 || pParse->nErr>0 ); } assert( pNew!=&standin ); | > > > > | 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 | pNew->pGroupBy = pGroupBy; pNew->pHaving = pHaving; pNew->pOrderBy = pOrderBy; pNew->pPrior = 0; pNew->pNext = 0; pNew->pLimit = pLimit; pNew->pWith = 0; #ifndef SQLITE_OMIT_WINDOWFUNC pNew->pWin = 0; pNew->pWinDefn = 0; #endif if( pParse->db->mallocFailed ) { clearSelect(pParse->db, pNew, pNew!=&standin); pNew = 0; }else{ assert( pNew->pSrc!=0 || pParse->nErr>0 ); } assert( pNew!=&standin ); |
︙ | ︙ | |||
525 526 527 528 529 530 531 | isOuter, &p->pWhere); } } } return 0; } | < < < < < < < < | 534 535 536 537 538 539 540 541 542 543 544 545 546 547 | isOuter, &p->pWhere); } } } return 0; } /* ** An instance of this object holds information (beyond pParse and pSelect) ** needed to load the next result row that is to be added to the sorter. */ typedef struct RowLoadInfo RowLoadInfo; struct RowLoadInfo { int regResult; /* Store results in array of registers here */ |
︙ | ︙ | |||
674 675 676 677 678 679 680 | pOp = sqlite3VdbeGetOp(v, pSort->addrSortIndex); if( pParse->db->mallocFailed ) return; pOp->p2 = nKey + nData; pKI = pOp->p4.pKeyInfo; memset(pKI->aSortOrder, 0, pKI->nKeyField); /* Makes OP_Jump testable */ sqlite3VdbeChangeP4(v, -1, (char*)pKI, P4_KEYINFO); testcase( pKI->nAllField > pKI->nKeyField+2 ); | | | 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 | pOp = sqlite3VdbeGetOp(v, pSort->addrSortIndex); if( pParse->db->mallocFailed ) return; pOp->p2 = nKey + nData; pKI = pOp->p4.pKeyInfo; memset(pKI->aSortOrder, 0, pKI->nKeyField); /* Makes OP_Jump testable */ sqlite3VdbeChangeP4(v, -1, (char*)pKI, P4_KEYINFO); testcase( pKI->nAllField > pKI->nKeyField+2 ); pOp->p4.pKeyInfo = sqlite3KeyInfoFromExprList(pParse,pSort->pOrderBy,nOBSat, pKI->nAllField-pKI->nKeyField-1); addrJmp = sqlite3VdbeCurrentAddr(v); sqlite3VdbeAddOp3(v, OP_Jump, addrJmp+1, 0, addrJmp+1); VdbeCoverage(v); pSort->labelBkOut = sqlite3VdbeMakeLabel(v); pSort->regReturn = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Gosub, pSort->regReturn, pSort->labelBkOut); sqlite3VdbeAddOp1(v, OP_ResetSorter, pSort->iECursor); |
︙ | ︙ | |||
1344 1345 1346 1347 1348 1349 1350 | ** then the KeyInfo structure is appropriate for initializing a virtual ** index to implement a DISTINCT test. ** ** Space to hold the KeyInfo structure is obtained from malloc. The calling ** function is responsible for seeing that this structure is eventually ** freed. */ | | | 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 | ** then the KeyInfo structure is appropriate for initializing a virtual ** index to implement a DISTINCT test. ** ** Space to hold the KeyInfo structure is obtained from malloc. The calling ** function is responsible for seeing that this structure is eventually ** freed. */ KeyInfo *sqlite3KeyInfoFromExprList( Parse *pParse, /* Parsing context */ ExprList *pList, /* Form the KeyInfo object from this ExprList */ int iStart, /* Begin with this column of pList */ int nExtra /* Add this many extra columns to the end */ ){ int nExpr; KeyInfo *pInfo; |
︙ | ︙ | |||
3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 | ** ** (**) We no longer attempt to flatten aggregate subqueries. Was: ** The subquery may not be an aggregate that uses the built-in min() or ** or max() functions. (Without this restriction, a query like: ** "SELECT x FROM (SELECT max(y), x FROM t1)" would not necessarily ** return the value X for which Y was maximal.) ** ** ** In this routine, the "p" parameter is a pointer to the outer query. ** The subquery is p->pSrc->a[iFrom]. isAgg is true if the outer query ** uses aggregates. ** ** If flattening is not attempted, this routine is a no-op and returns 0. ** If flattening is attempted this routine returns 1. | > > > > | 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 | ** ** (**) We no longer attempt to flatten aggregate subqueries. Was: ** The subquery may not be an aggregate that uses the built-in min() or ** or max() functions. (Without this restriction, a query like: ** "SELECT x FROM (SELECT max(y), x FROM t1)" would not necessarily ** return the value X for which Y was maximal.) ** ** (25) If either the subquery or the parent query contains a window ** function in the select list or ORDER BY clause, flattening ** is not attempted. ** ** ** In this routine, the "p" parameter is a pointer to the outer query. ** The subquery is p->pSrc->a[iFrom]. isAgg is true if the outer query ** uses aggregates. ** ** If flattening is not attempted, this routine is a no-op and returns 0. ** If flattening is attempted this routine returns 1. |
︙ | ︙ | |||
3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 | if( OptimizationDisabled(db, SQLITE_QueryFlattener) ) return 0; pSrc = p->pSrc; assert( pSrc && iFrom>=0 && iFrom<pSrc->nSrc ); pSubitem = &pSrc->a[iFrom]; iParent = pSubitem->iCursor; pSub = pSubitem->pSelect; assert( pSub!=0 ); pSubSrc = pSub->pSrc; assert( pSubSrc ); /* Prior to version 3.1.2, when LIMIT and OFFSET had to be simple constants, ** not arbitrary expressions, we allowed some combining of LIMIT and OFFSET ** because they could be computed at compile-time. But when LIMIT and OFFSET ** became arbitrary expressions, we were forced to add restrictions (13) | > > > > | 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 | if( OptimizationDisabled(db, SQLITE_QueryFlattener) ) return 0; pSrc = p->pSrc; assert( pSrc && iFrom>=0 && iFrom<pSrc->nSrc ); pSubitem = &pSrc->a[iFrom]; iParent = pSubitem->iCursor; pSub = pSubitem->pSelect; assert( pSub!=0 ); #ifndef SQLITE_OMIT_WINDOWFUNC if( p->pWin || pSub->pWin ) return 0; /* Restriction (25) */ #endif pSubSrc = pSub->pSrc; assert( pSubSrc ); /* Prior to version 3.1.2, when LIMIT and OFFSET had to be simple constants, ** not arbitrary expressions, we allowed some combining of LIMIT and OFFSET ** because they could be computed at compile-time. But when LIMIT and OFFSET ** became arbitrary expressions, we were forced to add restrictions (13) |
︙ | ︙ | |||
4105 4106 4107 4108 4109 4110 4111 | ** a GROUP BY clause. But such a HAVING clause is also harmless ** so there does not appear to be any reason to add extra logic ** to suppress it. **) ** ** (2) The inner query is the recursive part of a common table expression. ** ** (3) The inner query has a LIMIT clause (since the changes to the WHERE | | > > > > > > > > | 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 | ** a GROUP BY clause. But such a HAVING clause is also harmless ** so there does not appear to be any reason to add extra logic ** to suppress it. **) ** ** (2) The inner query is the recursive part of a common table expression. ** ** (3) The inner query has a LIMIT clause (since the changes to the WHERE ** clause would change the meaning of the LIMIT). ** ** (4) The inner query is the right operand of a LEFT JOIN and the ** expression to be pushed down does not come from the ON clause ** on that LEFT JOIN. ** ** (5) The WHERE clause expression originates in the ON or USING clause ** of a LEFT JOIN where iCursor is not the right-hand table of that ** left join. An example: ** ** SELECT * ** FROM (SELECT 1 AS a1 UNION ALL SELECT 2) AS aa ** JOIN (SELECT 1 AS b2 UNION ALL SELECT 2) AS bb ON (a1=b2) ** LEFT JOIN (SELECT 8 AS c3 UNION ALL SELECT 9) AS cc ON (b2=2); ** ** The correct answer is three rows: (1,1,NULL),(2,2,8),(2,2,9). ** But if the (b2=2) term were to be pushed down into the bb subquery, ** then the (1,1,NULL) row would be suppressed. ** ** (6) The inner query features one or more window-functions (since ** changes to the WHERE clause of the inner query could change the ** window over which window functions are calculated). ** ** Return 0 if no changes are made and non-zero if one or more WHERE clause ** terms are duplicated into the subquery. */ static int pushDownWhereTerms( Parse *pParse, /* Parse context (for malloc() and error reporting) */ Select *pSubq, /* The subquery whose WHERE clause is to be augmented */ Expr *pWhere, /* The WHERE clause of the outer query */ int iCursor, /* Cursor number of the subquery */ int isLeftJoin /* True if pSubq is the right term of a LEFT JOIN */ ){ Expr *pNew; int nChng = 0; if( pWhere==0 ) return 0; if( pSubq->selFlags & SF_Recursive ) return 0; /* restriction (2) */ #ifndef SQLITE_OMIT_WINDOWFUNC if( pSubq->pWin ) return 0; #endif #ifdef SQLITE_DEBUG /* Only the first term of a compound can have a WITH clause. But make ** sure no other terms are marked SF_Recursive in case something changes ** in the future. */ { |
︙ | ︙ | |||
4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 | pParse->pWith = pWith->pOuter; } } } #else #define selectPopWith 0 #endif /* ** This routine is a Walker callback for "expanding" a SELECT statement. ** "Expanding" means to do the following: ** ** (1) Make sure VDBE cursor numbers have been assigned to every ** element of the FROM clause. | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623 4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641 4642 | pParse->pWith = pWith->pOuter; } } } #else #define selectPopWith 0 #endif /* ** The SrcList_item structure passed as the second argument represents a ** sub-query in the FROM clause of a SELECT statement. This function ** allocates and populates the SrcList_item.pTab object. If successful, ** SQLITE_OK is returned. Otherwise, if an OOM error is encountered, ** SQLITE_NOMEM. */ int sqlite3ExpandSubquery(Parse *pParse, struct SrcList_item *pFrom){ Select *pSel = pFrom->pSelect; Table *pTab; assert( pSel ); pFrom->pTab = pTab = sqlite3DbMallocZero(pParse->db, sizeof(Table)); if( pTab==0 ) return SQLITE_NOMEM; pTab->nTabRef = 1; if( pFrom->zAlias ){ pTab->zName = sqlite3DbStrDup(pParse->db, pFrom->zAlias); }else{ pTab->zName = sqlite3MPrintf(pParse->db, "subquery_%p", (void*)pTab); } while( pSel->pPrior ){ pSel = pSel->pPrior; } sqlite3ColumnsFromExprList(pParse, pSel->pEList,&pTab->nCol,&pTab->aCol); pTab->iPKey = -1; pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); pTab->tabFlags |= TF_Ephemeral; return SQLITE_OK; } /* ** This routine is a Walker callback for "expanding" a SELECT statement. ** "Expanding" means to do the following: ** ** (1) Make sure VDBE cursor numbers have been assigned to every ** element of the FROM clause. |
︙ | ︙ | |||
4656 4657 4658 4659 4660 4661 4662 | if( pFrom->zName==0 ){ #ifndef SQLITE_OMIT_SUBQUERY Select *pSel = pFrom->pSelect; /* A sub-query in the FROM clause of a SELECT */ assert( pSel!=0 ); assert( pFrom->pTab==0 ); if( sqlite3WalkSelect(pWalker, pSel) ) return WRC_Abort; | < | < < < < < < < < < < < | 4702 4703 4704 4705 4706 4707 4708 4709 4710 4711 4712 4713 4714 4715 4716 | if( pFrom->zName==0 ){ #ifndef SQLITE_OMIT_SUBQUERY Select *pSel = pFrom->pSelect; /* A sub-query in the FROM clause of a SELECT */ assert( pSel!=0 ); assert( pFrom->pTab==0 ); if( sqlite3WalkSelect(pWalker, pSel) ) return WRC_Abort; if( sqlite3ExpandSubquery(pParse, pFrom) ) return WRC_Abort; #endif }else{ /* An ordinary table or view name in the FROM clause */ assert( pFrom->pTab==0 ); pFrom->pTab = pTab = sqlite3LocateTableItem(pParse, 0, pFrom); if( pTab==0 ) return WRC_Abort; if( pTab->nTabRef>=0xffff ){ |
︙ | ︙ | |||
4969 4970 4971 4972 4973 4974 4975 | static void selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){ Parse *pParse; int i; SrcList *pTabList; struct SrcList_item *pFrom; assert( p->selFlags & SF_Resolved ); | | | 5003 5004 5005 5006 5007 5008 5009 5010 5011 5012 5013 5014 5015 5016 5017 | static void selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){ Parse *pParse; int i; SrcList *pTabList; struct SrcList_item *pFrom; assert( p->selFlags & SF_Resolved ); if( p->selFlags & SF_HasTypeInfo ) return; p->selFlags |= SF_HasTypeInfo; pParse = pWalker->pParse; pTabList = p->pSrc; for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){ Table *pTab = pFrom->pTab; assert( pTab!=0 ); if( (pTab->tabFlags & TF_Ephemeral)!=0 ){ |
︙ | ︙ | |||
5072 5073 5074 5075 5076 5077 5078 | Expr *pE = pFunc->pExpr; assert( !ExprHasProperty(pE, EP_xIsSelect) ); if( pE->x.pList==0 || pE->x.pList->nExpr!=1 ){ sqlite3ErrorMsg(pParse, "DISTINCT aggregates must have exactly one " "argument"); pFunc->iDistinct = -1; }else{ | | | 5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116 5117 5118 5119 5120 | Expr *pE = pFunc->pExpr; assert( !ExprHasProperty(pE, EP_xIsSelect) ); if( pE->x.pList==0 || pE->x.pList->nExpr!=1 ){ sqlite3ErrorMsg(pParse, "DISTINCT aggregates must have exactly one " "argument"); pFunc->iDistinct = -1; }else{ KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pE->x.pList,0,0); sqlite3VdbeAddOp4(v, OP_OpenEphemeral, pFunc->iDistinct, 0, 0, (char*)pKeyInfo, P4_KEYINFO); } } } } |
︙ | ︙ | |||
5446 5447 5448 5449 5450 5451 5452 | /* If ORDER BY makes no difference in the output then neither does ** DISTINCT so it can be removed too. */ sqlite3ExprListDelete(db, p->pOrderBy); p->pOrderBy = 0; p->selFlags &= ~SF_Distinct; } sqlite3SelectPrep(pParse, p, 0); | < < < < > > > > > > > > > > > > > > > > | 5480 5481 5482 5483 5484 5485 5486 5487 5488 5489 5490 5491 5492 5493 5494 5495 5496 5497 5498 5499 5500 5501 5502 5503 5504 5505 5506 5507 5508 5509 5510 5511 5512 5513 5514 5515 5516 5517 5518 5519 5520 5521 5522 5523 5524 | /* If ORDER BY makes no difference in the output then neither does ** DISTINCT so it can be removed too. */ sqlite3ExprListDelete(db, p->pOrderBy); p->pOrderBy = 0; p->selFlags &= ~SF_Distinct; } sqlite3SelectPrep(pParse, p, 0); if( pParse->nErr || db->mallocFailed ){ goto select_end; } assert( p->pEList!=0 ); #if SELECTTRACE_ENABLED if( sqlite3SelectTrace & 0x104 ){ SELECTTRACE(0x104,pParse,p, ("after name resolution:\n")); sqlite3TreeViewSelect(0, p, 0); } #endif if( pDest->eDest==SRT_Output ){ generateColumnNames(pParse, p); } #ifndef SQLITE_OMIT_WINDOWFUNC if( sqlite3WindowRewrite(pParse, p) ){ goto select_end; } #if SELECTTRACE_ENABLED if( sqlite3SelectTrace & 0x108 ){ SELECTTRACE(0x104,pParse,p, ("after window rewrite:\n")); sqlite3TreeViewSelect(0, p, 0); } #endif #endif /* SQLITE_OMIT_WINDOWFUNC */ pTabList = p->pSrc; isAgg = (p->selFlags & SF_Aggregate)!=0; memset(&sSort, 0, sizeof(sSort)); sSort.pOrderBy = p->pOrderBy; /* Try to various optimizations (flattening subqueries, and strength ** reduction of join operators) in the FROM clause up into the main query */ #if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) for(i=0; !p->pPrior && i<pTabList->nSrc; i++){ struct SrcList_item *pItem = &pTabList->a[i]; Select *pSub = pItem->pSelect; |
︙ | ︙ | |||
5794 5795 5796 5797 5798 5799 5800 | ** If that is the case, then the OP_OpenEphemeral instruction will be ** changed to an OP_Noop once we figure out that the sorting index is ** not needed. The sSort.addrSortIndex variable is used to facilitate ** that change. */ if( sSort.pOrderBy ){ KeyInfo *pKeyInfo; | > | | 5840 5841 5842 5843 5844 5845 5846 5847 5848 5849 5850 5851 5852 5853 5854 5855 | ** If that is the case, then the OP_OpenEphemeral instruction will be ** changed to an OP_Noop once we figure out that the sorting index is ** not needed. The sSort.addrSortIndex variable is used to facilitate ** that change. */ if( sSort.pOrderBy ){ KeyInfo *pKeyInfo; pKeyInfo = sqlite3KeyInfoFromExprList( pParse, sSort.pOrderBy, 0, pEList->nExpr); sSort.iECursor = pParse->nTab++; sSort.addrSortIndex = sqlite3VdbeAddOp4(v, OP_OpenEphemeral, sSort.iECursor, sSort.pOrderBy->nExpr+1+pEList->nExpr, 0, (char*)pKeyInfo, P4_KEYINFO ); }else{ |
︙ | ︙ | |||
5828 5829 5830 5831 5832 5833 5834 | } /* Open an ephemeral index to use for the distinct set. */ if( p->selFlags & SF_Distinct ){ sDistinct.tabTnct = pParse->nTab++; sDistinct.addrTnct = sqlite3VdbeAddOp4(v, OP_OpenEphemeral, | | | | | > > > > > > > | | 5875 5876 5877 5878 5879 5880 5881 5882 5883 5884 5885 5886 5887 5888 5889 5890 5891 5892 5893 5894 5895 5896 5897 5898 5899 5900 5901 5902 5903 5904 5905 5906 5907 5908 5909 | } /* Open an ephemeral index to use for the distinct set. */ if( p->selFlags & SF_Distinct ){ sDistinct.tabTnct = pParse->nTab++; sDistinct.addrTnct = sqlite3VdbeAddOp4(v, OP_OpenEphemeral, sDistinct.tabTnct, 0, 0, (char*)sqlite3KeyInfoFromExprList(pParse, p->pEList,0,0), P4_KEYINFO); sqlite3VdbeChangeP5(v, BTREE_UNORDERED); sDistinct.eTnctType = WHERE_DISTINCT_UNORDERED; }else{ sDistinct.eTnctType = WHERE_DISTINCT_NOOP; } if( !isAgg && pGroupBy==0 ){ /* No aggregate functions and no GROUP BY clause */ u16 wctrlFlags = (sDistinct.isTnct ? WHERE_WANT_DISTINCT : 0) | (p->selFlags & SF_FixedLimit); #ifndef SQLITE_OMIT_WINDOWFUNC Window *pWin = p->pWin; /* Master window object (or NULL) */ if( pWin ){ sqlite3WindowCodeInit(pParse, pWin); } #endif assert( WHERE_USE_LIMIT==SF_FixedLimit ); /* Begin the database scan. */ SELECTTRACE(1,pParse,p,("WhereBegin\n")); pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, sSort.pOrderBy, p->pEList, wctrlFlags, p->nSelectRow); if( pWInfo==0 ) goto select_end; if( sqlite3WhereOutputRowCount(pWInfo) < p->nSelectRow ){ |
︙ | ︙ | |||
5870 5871 5872 5873 5874 5875 5876 | ** instruction ended up not being needed, then change the OP_OpenEphemeral ** into an OP_Noop. */ if( sSort.addrSortIndex>=0 && sSort.pOrderBy==0 ){ sqlite3VdbeChangeToNoop(v, sSort.addrSortIndex); } | < > > > > > > > > > > > > > > > > > > > | | | | | | > | 5924 5925 5926 5927 5928 5929 5930 5931 5932 5933 5934 5935 5936 5937 5938 5939 5940 5941 5942 5943 5944 5945 5946 5947 5948 5949 5950 5951 5952 5953 5954 5955 5956 5957 5958 5959 5960 5961 5962 5963 5964 5965 | ** instruction ended up not being needed, then change the OP_OpenEphemeral ** into an OP_Noop. */ if( sSort.addrSortIndex>=0 && sSort.pOrderBy==0 ){ sqlite3VdbeChangeToNoop(v, sSort.addrSortIndex); } assert( p->pEList==pEList ); #ifndef SQLITE_OMIT_WINDOWFUNC if( pWin ){ int addrGosub = sqlite3VdbeMakeLabel(v); int iCont = sqlite3VdbeMakeLabel(v); int iBreak = sqlite3VdbeMakeLabel(v); int regGosub = ++pParse->nMem; sqlite3WindowCodeStep(pParse, p, pWInfo, regGosub, addrGosub); sqlite3VdbeAddOp2(v, OP_Goto, 0, iBreak); sqlite3VdbeResolveLabel(v, addrGosub); selectInnerLoop(pParse, p, -1, &sSort, &sDistinct, pDest, iCont, iBreak); sqlite3VdbeResolveLabel(v, iCont); sqlite3VdbeAddOp1(v, OP_Return, regGosub); sqlite3VdbeResolveLabel(v, iBreak); }else #endif /* SQLITE_OMIT_WINDOWFUNC */ { /* Use the standard inner loop. */ selectInnerLoop(pParse, p, -1, &sSort, &sDistinct, pDest, sqlite3WhereContinueLabel(pWInfo), sqlite3WhereBreakLabel(pWInfo)); /* End the database scan loop. */ sqlite3WhereEnd(pWInfo); } }else{ /* This case when there exist aggregate functions or a GROUP BY clause ** or both */ NameContext sNC; /* Name context for processing aggregate information */ int iAMem; /* First Mem address for storing current GROUP BY */ int iBMem; /* First Mem address for previous GROUP BY */ int iUseFlag; /* Mem address holding flag indicating that at least |
︙ | ︙ | |||
6007 6008 6009 6010 6011 6012 6013 | /* If there is a GROUP BY clause we might need a sorting index to ** implement it. Allocate that sorting index now. If it turns out ** that we do not need it after all, the OP_SorterOpen instruction ** will be converted into a Noop. */ sAggInfo.sortingIdx = pParse->nTab++; | | | 6080 6081 6082 6083 6084 6085 6086 6087 6088 6089 6090 6091 6092 6093 6094 | /* If there is a GROUP BY clause we might need a sorting index to ** implement it. Allocate that sorting index now. If it turns out ** that we do not need it after all, the OP_SorterOpen instruction ** will be converted into a Noop. */ sAggInfo.sortingIdx = pParse->nTab++; pKeyInfo = sqlite3KeyInfoFromExprList(pParse,pGroupBy,0,sAggInfo.nColumn); addrSortingIdx = sqlite3VdbeAddOp4(v, OP_SorterOpen, sAggInfo.sortingIdx, sAggInfo.nSortingColumn, 0, (char*)pKeyInfo, P4_KEYINFO); /* Initialize memory locations used by GROUP BY aggregate processing */ iUseFlag = ++pParse->nMem; |
︙ | ︙ |
Changes to src/sqlite.h.in.
︙ | ︙ | |||
4617 4618 4619 4620 4621 4622 4623 | ** KEYWORDS: {function creation routines} ** KEYWORDS: {application-defined SQL function} ** KEYWORDS: {application-defined SQL functions} ** METHOD: sqlite3 ** ** ^These functions (collectively known as "function creation routines") ** are used to add SQL functions or aggregates or to redefine the behavior | | | | | | > > | 4617 4618 4619 4620 4621 4622 4623 4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 4635 4636 4637 | ** KEYWORDS: {function creation routines} ** KEYWORDS: {application-defined SQL function} ** KEYWORDS: {application-defined SQL functions} ** METHOD: sqlite3 ** ** ^These functions (collectively known as "function creation routines") ** are used to add SQL functions or aggregates or to redefine the behavior ** of existing SQL functions or aggregates. The only differences between ** the three "sqlite3_create_function*" routines are the text encoding ** expected for the second parameter (the name of the function being ** created) and the presence or absence of a destructor callback for ** the application data pointer. Function sqlite3_create_window_function() ** is similar, but allows the user to supply the extra callback functions ** needed by [aggregate window functions]. ** ** ^The first parameter is the [database connection] to which the SQL ** function is to be added. ^If an application uses more than one database ** connection then application-defined SQL functions must be added ** to each database connection separately. ** ** ^The second parameter is the name of the SQL function to be created or |
︙ | ︙ | |||
4667 4668 4669 4670 4671 4672 4673 | ** function that is not deterministic. The SQLite query planner is able to ** perform additional optimizations on deterministic functions, so use ** of the [SQLITE_DETERMINISTIC] flag is recommended where possible. ** ** ^(The fifth parameter is an arbitrary pointer. The implementation of the ** function can gain access to this pointer using [sqlite3_user_data()].)^ ** | | > > > > > > > > > > > | | | | | | < | | | 4669 4670 4671 4672 4673 4674 4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 4688 4689 4690 4691 4692 4693 4694 4695 4696 4697 4698 4699 4700 4701 4702 4703 4704 4705 4706 4707 4708 4709 4710 | ** function that is not deterministic. The SQLite query planner is able to ** perform additional optimizations on deterministic functions, so use ** of the [SQLITE_DETERMINISTIC] flag is recommended where possible. ** ** ^(The fifth parameter is an arbitrary pointer. The implementation of the ** function can gain access to this pointer using [sqlite3_user_data()].)^ ** ** ^The sixth, seventh and eighth parameters passed to the three ** "sqlite3_create_function*" functions, xFunc, xStep and xFinal, are ** pointers to C-language functions that implement the SQL function or ** aggregate. ^A scalar SQL function requires an implementation of the xFunc ** callback only; NULL pointers must be passed as the xStep and xFinal ** parameters. ^An aggregate SQL function requires an implementation of xStep ** and xFinal and NULL pointer must be passed for xFunc. ^To delete an existing ** SQL function or aggregate, pass NULL pointers for all three function ** callbacks. ** ** ^The sixth, seventh, eighth and ninth parameters (xStep, xFinal, xValue ** and xInverse) passed to sqlite3_create_window_function are pointers to ** C-lanugage callbacks that implement the new function. xStep and xFinal ** must both be non-NULL. xValue and xInverse may either both be NULL, in ** which case a regular aggregate function is created, or must both be ** non-NULL, in which case the new function may be used as either an aggregate ** or aggregate window function. More details regarding the implementation ** of aggregate window functions are ** [user-defined window functions|available here]. ** ** ^(If the final parameter to sqlite3_create_function_v2() or ** sqlite3_create_window_function() is not NULL, then it is destructor for ** the application data pointer. The destructor is invoked when the function ** is deleted, either by being overloaded or when the database connection ** closes.)^ ^The destructor is also invoked if the call to ** sqlite3_create_function_v2() fails. ^When the destructor callback is ** invoked, it is passed a single argument which is a copy of the application ** data pointer which was the fifth parameter to sqlite3_create_function_v2(). ** ** ^It is permitted to register multiple implementations of the same ** functions with the same name but with either differing numbers of ** arguments or differing preferred text encodings. ^SQLite will use ** the implementation that most closely matches the way in which the ** SQL function is used. ^A function implementation with a non-negative ** nArg parameter is a better match than a function implementation with |
︙ | ︙ | |||
4736 4737 4738 4739 4740 4741 4742 4743 4744 4745 4746 4747 4748 4749 | int nArg, int eTextRep, void *pApp, void (*xFunc)(sqlite3_context*,int,sqlite3_value**), void (*xStep)(sqlite3_context*,int,sqlite3_value**), void (*xFinal)(sqlite3_context*), void(*xDestroy)(void*) ); /* ** CAPI3REF: Text Encodings ** ** These constant define integer codes that represent the various ** text encodings supported by SQLite. | > > > > > > > > > > > > | 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 | int nArg, int eTextRep, void *pApp, void (*xFunc)(sqlite3_context*,int,sqlite3_value**), void (*xStep)(sqlite3_context*,int,sqlite3_value**), void (*xFinal)(sqlite3_context*), void(*xDestroy)(void*) ); int sqlite3_create_window_function( sqlite3 *db, const char *zFunctionName, int nArg, int eTextRep, void *pApp, void (*xStep)(sqlite3_context*,int,sqlite3_value**), void (*xFinal)(sqlite3_context*), void (*xValue)(sqlite3_context*), void (*xInverse)(sqlite3_context*,int,sqlite3_value**), void(*xDestroy)(void*) ); /* ** CAPI3REF: Text Encodings ** ** These constant define integer codes that represent the various ** text encodings supported by SQLite. |
︙ | ︙ |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 | typedef struct TriggerStep TriggerStep; typedef struct UnpackedRecord UnpackedRecord; typedef struct Upsert Upsert; typedef struct VTable VTable; typedef struct VtabCtx VtabCtx; typedef struct Walker Walker; typedef struct WhereInfo WhereInfo; typedef struct With With; /* ** The bitmask datatype defined below is used for various optimizations. ** ** Changing this from a 64-bit to a 32-bit type limits the number of | > | 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 | typedef struct TriggerStep TriggerStep; typedef struct UnpackedRecord UnpackedRecord; typedef struct Upsert Upsert; typedef struct VTable VTable; typedef struct VtabCtx VtabCtx; typedef struct Walker Walker; typedef struct WhereInfo WhereInfo; typedef struct Window Window; typedef struct With With; /* ** The bitmask datatype defined below is used for various optimizations. ** ** Changing this from a 64-bit to a 32-bit type limits the number of |
︙ | ︙ | |||
1616 1617 1618 1619 1620 1621 1622 | ** structure is held in the db->aHash hash table. ** ** The u.pHash field is used by the global built-ins. The u.pDestructor ** field is used by per-connection app-def functions. */ struct FuncDef { i8 nArg; /* Number of arguments. -1 means unlimited */ | | > > | 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 | ** structure is held in the db->aHash hash table. ** ** The u.pHash field is used by the global built-ins. The u.pDestructor ** field is used by per-connection app-def functions. */ struct FuncDef { i8 nArg; /* Number of arguments. -1 means unlimited */ u32 funcFlags; /* Some combination of SQLITE_FUNC_* */ void *pUserData; /* User data parameter */ FuncDef *pNext; /* Next function with same name */ void (*xSFunc)(sqlite3_context*,int,sqlite3_value**); /* func or agg-step */ void (*xFinalize)(sqlite3_context*); /* Agg finalizer */ void (*xValue)(sqlite3_context*); /* Current agg value */ void (*xInverse)(sqlite3_context*,int,sqlite3_value**); /* inverse agg-step */ const char *zName; /* SQL name of the function. */ union { FuncDef *pHash; /* Next with a different name but the same hash */ FuncDestructor *pDestructor; /* Reference counted destructor function */ } u; }; |
︙ | ︙ | |||
1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 | #define SQLITE_FUNC_UNLIKELY 0x0400 /* Built-in unlikely() function */ #define SQLITE_FUNC_CONSTANT 0x0800 /* Constant inputs give a constant output */ #define SQLITE_FUNC_MINMAX 0x1000 /* True for min() and max() aggregates */ #define SQLITE_FUNC_SLOCHNG 0x2000 /* "Slow Change". Value constant during a ** single query - might change over time */ #define SQLITE_FUNC_AFFINITY 0x4000 /* Built-in affinity() function */ #define SQLITE_FUNC_OFFSET 0x8000 /* Built-in sqlite_offset() function */ /* ** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are ** used to create the initializers for the FuncDef structures. ** ** FUNCTION(zName, nArg, iArg, bNC, xFunc) ** Used to create a scalar function definition of a function zName | > > | 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 | #define SQLITE_FUNC_UNLIKELY 0x0400 /* Built-in unlikely() function */ #define SQLITE_FUNC_CONSTANT 0x0800 /* Constant inputs give a constant output */ #define SQLITE_FUNC_MINMAX 0x1000 /* True for min() and max() aggregates */ #define SQLITE_FUNC_SLOCHNG 0x2000 /* "Slow Change". Value constant during a ** single query - might change over time */ #define SQLITE_FUNC_AFFINITY 0x4000 /* Built-in affinity() function */ #define SQLITE_FUNC_OFFSET 0x8000 /* Built-in sqlite_offset() function */ #define SQLITE_FUNC_WINDOW 0x10000 /* Built-in window-only function */ #define SQLITE_FUNC_WINDOW_SIZE 0x20000 /* Requires partition size as arg. */ /* ** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are ** used to create the initializers for the FuncDef structures. ** ** FUNCTION(zName, nArg, iArg, bNC, xFunc) ** Used to create a scalar function definition of a function zName |
︙ | ︙ | |||
1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 | ** arbitrary non-NULL pointer. The bNC parameter is not used. ** ** AGGREGATE(zName, nArg, iArg, bNC, xStep, xFinal) ** Used to create an aggregate function definition implemented by ** the C functions xStep and xFinal. The first four parameters ** are interpreted in the same way as the first 4 parameters to ** FUNCTION(). ** ** LIKEFUNC(zName, nArg, pArg, flags) ** Used to create a scalar function definition of a function zName ** that accepts nArg arguments and is implemented by a call to C ** function likeFunc. Argument pArg is cast to a (void *) and made ** available as the function user-data (sqlite3_user_data()). The ** FuncDef.flags variable is set to the value passed as the flags ** parameter. */ #define FUNCTION(zName, nArg, iArg, bNC, xFunc) \ {nArg, SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \ | > > > > > > | | | | | | | | | | > > > > | 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 | ** arbitrary non-NULL pointer. The bNC parameter is not used. ** ** AGGREGATE(zName, nArg, iArg, bNC, xStep, xFinal) ** Used to create an aggregate function definition implemented by ** the C functions xStep and xFinal. The first four parameters ** are interpreted in the same way as the first 4 parameters to ** FUNCTION(). ** ** WFUNCTION(zName, nArg, iArg, xStep, xFinal, xValue, xInverse) ** Used to create an aggregate function definition implemented by ** the C functions xStep and xFinal. The first four parameters ** are interpreted in the same way as the first 4 parameters to ** FUNCTION(). ** ** LIKEFUNC(zName, nArg, pArg, flags) ** Used to create a scalar function definition of a function zName ** that accepts nArg arguments and is implemented by a call to C ** function likeFunc. Argument pArg is cast to a (void *) and made ** available as the function user-data (sqlite3_user_data()). The ** FuncDef.flags variable is set to the value passed as the flags ** parameter. */ #define FUNCTION(zName, nArg, iArg, bNC, xFunc) \ {nArg, SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \ SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} } #define VFUNCTION(zName, nArg, iArg, bNC, xFunc) \ {nArg, SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \ SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} } #define DFUNCTION(zName, nArg, iArg, bNC, xFunc) \ {nArg, SQLITE_FUNC_SLOCHNG|SQLITE_UTF8, \ 0, 0, xFunc, 0, 0, 0, #zName, {0} } #define PURE_DATE(zName, nArg, iArg, bNC, xFunc) \ {nArg, SQLITE_FUNC_SLOCHNG|SQLITE_UTF8|SQLITE_FUNC_CONSTANT, \ (void*)&sqlite3Config, 0, xFunc, 0, 0, 0, #zName, {0} } #define FUNCTION2(zName, nArg, iArg, bNC, xFunc, extraFlags) \ {nArg,SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL)|extraFlags,\ SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} } #define STR_FUNCTION(zName, nArg, pArg, bNC, xFunc) \ {nArg, SQLITE_FUNC_SLOCHNG|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \ pArg, 0, xFunc, 0, 0, 0, #zName, } #define LIKEFUNC(zName, nArg, arg, flags) \ {nArg, SQLITE_FUNC_CONSTANT|SQLITE_UTF8|flags, \ (void *)arg, 0, likeFunc, 0, 0, 0, #zName, {0} } #define AGGREGATE(zName, nArg, arg, nc, xStep, xFinal, xValue) \ {nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL), \ SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,xValue,0,#zName, {0}} #define AGGREGATE2(zName, nArg, arg, nc, xStep, xFinal, extraFlags) \ {nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL)|extraFlags, \ SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,xFinal,0,#zName, {0}} #define WAGGREGATE(zName, nArg, arg, nc, xStep, xFinal, xValue, xInverse, f) \ {nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL)|f, \ SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,xValue,xInverse,#zName, {0}} /* ** All current savepoints are stored in a linked list starting at ** sqlite3.pSavepoint. The first element in the list is the most recently ** opened savepoint. Savepoints are added to the list by the vdbe ** OP_Savepoint instruction. */ |
︙ | ︙ | |||
2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 | i16 iRightJoinTable; /* If EP_FromJoin, the right table of the join */ u8 op2; /* TK_REGISTER: original value of Expr.op ** TK_COLUMN: the value of p5 for OP_Column ** TK_AGG_FUNCTION: nesting depth */ AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */ Table *pTab; /* Table for TK_COLUMN expressions. Can be NULL ** for a column of an index on an expression */ }; /* ** The following are the meanings of bits in the Expr.flags field. */ #define EP_FromJoin 0x000001 /* Originates in ON/USING clause of outer join */ #define EP_Agg 0x000002 /* Contains one or more aggregate functions */ | > > > | 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 | i16 iRightJoinTable; /* If EP_FromJoin, the right table of the join */ u8 op2; /* TK_REGISTER: original value of Expr.op ** TK_COLUMN: the value of p5 for OP_Column ** TK_AGG_FUNCTION: nesting depth */ AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */ Table *pTab; /* Table for TK_COLUMN expressions. Can be NULL ** for a column of an index on an expression */ #ifndef SQLITE_OMIT_WINDOWFUNC Window *pWin; /* Window definition for window functions */ #endif }; /* ** The following are the meanings of bits in the Expr.flags field. */ #define EP_FromJoin 0x000001 /* Originates in ON/USING clause of outer join */ #define EP_Agg 0x000002 /* Contains one or more aggregate functions */ |
︙ | ︙ | |||
2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 | AggInfo *pAggInfo; /* Information about aggregates at this level */ Upsert *pUpsert; /* ON CONFLICT clause information from an upsert */ } uNC; NameContext *pNext; /* Next outer name context. NULL for outermost */ int nRef; /* Number of names resolved by this context */ int nErr; /* Number of errors encountered while resolving names */ u16 ncFlags; /* Zero or more NC_* flags defined below */ }; /* ** Allowed values for the NameContext, ncFlags field. ** ** Value constraints (all checked via assert()): ** NC_HasAgg == SF_HasAgg | > | 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 | AggInfo *pAggInfo; /* Information about aggregates at this level */ Upsert *pUpsert; /* ON CONFLICT clause information from an upsert */ } uNC; NameContext *pNext; /* Next outer name context. NULL for outermost */ int nRef; /* Number of names resolved by this context */ int nErr; /* Number of errors encountered while resolving names */ u16 ncFlags; /* Zero or more NC_* flags defined below */ Select *pWinSelect; /* SELECT statement for any window functions */ }; /* ** Allowed values for the NameContext, ncFlags field. ** ** Value constraints (all checked via assert()): ** NC_HasAgg == SF_HasAgg |
︙ | ︙ | |||
2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 | #define NC_IdxExpr 0x0020 /* True if resolving columns of CREATE INDEX */ #define NC_VarSelect 0x0040 /* A correlated subquery has been seen */ #define NC_UEList 0x0080 /* True if uNC.pEList is used */ #define NC_UAggInfo 0x0100 /* True if uNC.pAggInfo is used */ #define NC_UUpsert 0x0200 /* True if uNC.pUpsert is used */ #define NC_MinMaxAgg 0x1000 /* min/max aggregates seen. See note above */ #define NC_Complex 0x2000 /* True if a function or subquery seen */ /* ** An instance of the following object describes a single ON CONFLICT ** clause in an upsert. ** ** The pUpsertTarget field is only set if the ON CONFLICT clause includes ** conflict-target clause. (In "ON CONFLICT(a,b)" the "(a,b)" is the | > | 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 | #define NC_IdxExpr 0x0020 /* True if resolving columns of CREATE INDEX */ #define NC_VarSelect 0x0040 /* A correlated subquery has been seen */ #define NC_UEList 0x0080 /* True if uNC.pEList is used */ #define NC_UAggInfo 0x0100 /* True if uNC.pAggInfo is used */ #define NC_UUpsert 0x0200 /* True if uNC.pUpsert is used */ #define NC_MinMaxAgg 0x1000 /* min/max aggregates seen. See note above */ #define NC_Complex 0x2000 /* True if a function or subquery seen */ #define NC_AllowWin 0x4000 /* Window functions are allowed here */ /* ** An instance of the following object describes a single ON CONFLICT ** clause in an upsert. ** ** The pUpsertTarget field is only set if the ON CONFLICT clause includes ** conflict-target clause. (In "ON CONFLICT(a,b)" the "(a,b)" is the |
︙ | ︙ | |||
2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 | ExprList *pGroupBy; /* The GROUP BY clause */ Expr *pHaving; /* The HAVING clause */ ExprList *pOrderBy; /* The ORDER BY clause */ Select *pPrior; /* Prior select in a compound select statement */ Select *pNext; /* Next select to the left in a compound */ Expr *pLimit; /* LIMIT expression. NULL means not used. */ With *pWith; /* WITH clause attached to this select. Or NULL. */ }; /* ** Allowed values for Select.selFlags. The "SF" prefix stands for ** "Select Flag". ** ** Value constraints (all checked via assert()) | > > > > | 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 | ExprList *pGroupBy; /* The GROUP BY clause */ Expr *pHaving; /* The HAVING clause */ ExprList *pOrderBy; /* The ORDER BY clause */ Select *pPrior; /* Prior select in a compound select statement */ Select *pNext; /* Next select to the left in a compound */ Expr *pLimit; /* LIMIT expression. NULL means not used. */ With *pWith; /* WITH clause attached to this select. Or NULL. */ #ifndef SQLITE_OMIT_WINDOWFUNC Window *pWin; /* List of window functions */ Window *pWinDefn; /* List of named window definitions */ #endif }; /* ** Allowed values for Select.selFlags. The "SF" prefix stands for ** "Select Flag". ** ** Value constraints (all checked via assert()) |
︙ | ︙ | |||
3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 | struct SrcCount *pSrcCount; /* Counting column references */ struct CCurHint *pCCurHint; /* Used by codeCursorHint() */ int *aiCol; /* array of column indexes */ struct IdxCover *pIdxCover; /* Check for index coverage */ struct IdxExprTrans *pIdxTrans; /* Convert idxed expr to column */ ExprList *pGroupBy; /* GROUP BY clause */ Select *pSelect; /* HAVING to WHERE clause ctx */ } u; }; /* Forward declarations */ int sqlite3WalkExpr(Walker*, Expr*); int sqlite3WalkExprList(Walker*, ExprList*); int sqlite3WalkSelect(Walker*, Select*); | > | 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 | struct SrcCount *pSrcCount; /* Counting column references */ struct CCurHint *pCCurHint; /* Used by codeCursorHint() */ int *aiCol; /* array of column indexes */ struct IdxCover *pIdxCover; /* Check for index coverage */ struct IdxExprTrans *pIdxTrans; /* Convert idxed expr to column */ ExprList *pGroupBy; /* GROUP BY clause */ Select *pSelect; /* HAVING to WHERE clause ctx */ struct WindowRewrite *pRewrite; /* Window rewrite context */ } u; }; /* Forward declarations */ int sqlite3WalkExpr(Walker*, Expr*); int sqlite3WalkExprList(Walker*, ExprList*); int sqlite3WalkSelect(Walker*, Select*); |
︙ | ︙ | |||
3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 | */ struct TreeView { int iLevel; /* Which level of the tree we are on */ u8 bLine[100]; /* Draw vertical in column i if bLine[i] is true */ }; #endif /* SQLITE_DEBUG */ /* ** Assuming zIn points to the first byte of a UTF-8 character, ** advance zIn to point to the first byte of the next UTF-8 character. */ #define SQLITE_SKIP_UTF8(zIn) { \ if( (*(zIn++))>=0xc0 ){ \ while( (*zIn & 0xc0)==0x80 ){ zIn++; } \ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 | */ struct TreeView { int iLevel; /* Which level of the tree we are on */ u8 bLine[100]; /* Draw vertical in column i if bLine[i] is true */ }; #endif /* SQLITE_DEBUG */ /* ** Object used to encode the OVER() clause attached to a window-function ** invocation. And some fields used while generating VM code for the same. */ struct Window { char *zName; /* Name of window (may be NULL) */ ExprList *pPartition; /* PARTITION BY clause */ ExprList *pOrderBy; /* ORDER BY clause */ u8 eType; /* TK_RANGE or TK_ROWS */ u8 eStart; /* UNBOUNDED, CURRENT, PRECEDING or FOLLOWING */ u8 eEnd; /* UNBOUNDED, CURRENT, PRECEDING or FOLLOWING */ Expr *pStart; /* Expression for "<expr> PRECEDING" */ Expr *pEnd; /* Expression for "<expr> FOLLOWING" */ Window *pNextWin; /* Next window function belonging to this SELECT */ Expr *pFilter; FuncDef *pFunc; int iEphCsr; /* Temp table used by this window */ int regAccum; int regResult; int csrApp; /* Function cursor (used by min/max) */ int regApp; /* Function register (also used by min/max) */ int regPart; Expr *pOwner; /* Expression object this window is attached to */ int nBufferCol; /* Number of columns in buffer table */ int iArgCol; /* Offset of first argument for this function */ }; #ifndef SQLITE_OMIT_WINDOWFUNC void sqlite3WindowDelete(sqlite3*, Window*); void sqlite3WindowListDelete(sqlite3 *db, Window *p); Window *sqlite3WindowAlloc(Parse*, int, int, Expr*, int , Expr*); void sqlite3WindowAttach(Parse*, Expr*, Window*); int sqlite3WindowCompare(Parse*, Window*, Window*); void sqlite3WindowCodeInit(Parse*, Window*); void sqlite3WindowCodeStep(Parse*, Select*, WhereInfo*, int, int); int sqlite3WindowRewrite(Parse*, Select*); int sqlite3ExpandSubquery(Parse*, struct SrcList_item*); void sqlite3WindowUpdate(Parse*, Window*, Window*, FuncDef*); Window *sqlite3WindowDup(sqlite3 *db, Expr *pOwner, Window *p); Window *sqlite3WindowListDup(sqlite3 *db, Window *p); void sqlite3WindowFunctions(void); #else # define sqlite3WindowDelete(a,b) # define sqlite3WindowFunctions() # define sqlite3WindowAttach(a,b,c) #endif /* ** Assuming zIn points to the first byte of a UTF-8 character, ** advance zIn to point to the first byte of the next UTF-8 character. */ #define SQLITE_SKIP_UTF8(zIn) { \ if( (*(zIn++))>=0xc0 ){ \ while( (*zIn & 0xc0)==0x80 ){ zIn++; } \ |
︙ | ︙ | |||
4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177 4178 | void sqlite3SchemaClear(void *); Schema *sqlite3SchemaGet(sqlite3 *, Btree *); int sqlite3SchemaToIndex(sqlite3 *db, Schema *); KeyInfo *sqlite3KeyInfoAlloc(sqlite3*,int,int); void sqlite3KeyInfoUnref(KeyInfo*); KeyInfo *sqlite3KeyInfoRef(KeyInfo*); KeyInfo *sqlite3KeyInfoOfIndex(Parse*, Index*); #ifdef SQLITE_DEBUG int sqlite3KeyInfoIsWriteable(KeyInfo*); #endif int sqlite3CreateFunc(sqlite3 *, const char *, int, int, void *, void (*)(sqlite3_context*,int,sqlite3_value **), | > > | > > > | 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 | void sqlite3SchemaClear(void *); Schema *sqlite3SchemaGet(sqlite3 *, Btree *); int sqlite3SchemaToIndex(sqlite3 *db, Schema *); KeyInfo *sqlite3KeyInfoAlloc(sqlite3*,int,int); void sqlite3KeyInfoUnref(KeyInfo*); KeyInfo *sqlite3KeyInfoRef(KeyInfo*); KeyInfo *sqlite3KeyInfoOfIndex(Parse*, Index*); KeyInfo *sqlite3KeyInfoFromExprList(Parse*, ExprList*, int, int); #ifdef SQLITE_DEBUG int sqlite3KeyInfoIsWriteable(KeyInfo*); #endif int sqlite3CreateFunc(sqlite3 *, const char *, int, int, void *, void (*)(sqlite3_context*,int,sqlite3_value **), void (*)(sqlite3_context*,int,sqlite3_value **), void (*)(sqlite3_context*), void (*)(sqlite3_context*), void (*)(sqlite3_context*,int,sqlite3_value **), FuncDestructor *pDestructor ); void sqlite3NoopDestructor(void*); void sqlite3OomFault(sqlite3*); void sqlite3OomClear(sqlite3*); int sqlite3ApiExit(sqlite3 *db, int); int sqlite3OpenTempDatabase(Parse *); |
︙ | ︙ | |||
4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 | ** The interface to the LEMON-generated parser */ #ifndef SQLITE_AMALGAMATION void *sqlite3ParserAlloc(void*(*)(u64), Parse*); void sqlite3ParserFree(void*, void(*)(void*)); #endif void sqlite3Parser(void*, int, Token); #ifdef YYTRACKMAXSTACKDEPTH int sqlite3ParserStackPeak(void*); #endif void sqlite3AutoLoadExtensions(sqlite3*); #ifndef SQLITE_OMIT_LOAD_EXTENSION void sqlite3CloseExtensions(sqlite3*); | > | 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 | ** The interface to the LEMON-generated parser */ #ifndef SQLITE_AMALGAMATION void *sqlite3ParserAlloc(void*(*)(u64), Parse*); void sqlite3ParserFree(void*, void(*)(void*)); #endif void sqlite3Parser(void*, int, Token); int sqlite3ParserFallback(int); #ifdef YYTRACKMAXSTACKDEPTH int sqlite3ParserStackPeak(void*); #endif void sqlite3AutoLoadExtensions(sqlite3*); #ifndef SQLITE_OMIT_LOAD_EXTENSION void sqlite3CloseExtensions(sqlite3*); |
︙ | ︙ |
Changes to src/test1.c.
︙ | ︙ | |||
7795 7796 7797 7798 7799 7800 7801 7802 7803 7804 7805 7806 7807 7808 | extern int sqlite3WalTrace; #endif #ifdef SQLITE_TEST #ifdef SQLITE_ENABLE_FTS3 extern int sqlite3_fts3_enable_parentheses; #endif #endif for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){ Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0); } for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, aObjCmd[i].clientData, 0); | > > > | 7795 7796 7797 7798 7799 7800 7801 7802 7803 7804 7805 7806 7807 7808 7809 7810 7811 | extern int sqlite3WalTrace; #endif #ifdef SQLITE_TEST #ifdef SQLITE_ENABLE_FTS3 extern int sqlite3_fts3_enable_parentheses; #endif #endif #if defined(SQLITE_ENABLE_SELECTTRACE) extern int sqlite3SelectTrace; #endif for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){ Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0); } for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, aObjCmd[i].clientData, 0); |
︙ | ︙ | |||
7880 7881 7882 7883 7884 7885 7886 7887 7888 7889 7890 7891 7892 | (char*)&bitmask_size, TCL_LINK_INT|TCL_LINK_READ_ONLY); Tcl_LinkVar(interp, "longdouble_size", (char*)&longdouble_size, TCL_LINK_INT|TCL_LINK_READ_ONLY); Tcl_LinkVar(interp, "sqlite_sync_count", (char*)&sqlite3_sync_count, TCL_LINK_INT); Tcl_LinkVar(interp, "sqlite_fullsync_count", (char*)&sqlite3_fullsync_count, TCL_LINK_INT); #if defined(SQLITE_ENABLE_FTS3) && defined(SQLITE_TEST) Tcl_LinkVar(interp, "sqlite_fts3_enable_parentheses", (char*)&sqlite3_fts3_enable_parentheses, TCL_LINK_INT); #endif return TCL_OK; } | > > > > | 7883 7884 7885 7886 7887 7888 7889 7890 7891 7892 7893 7894 7895 7896 7897 7898 7899 | (char*)&bitmask_size, TCL_LINK_INT|TCL_LINK_READ_ONLY); Tcl_LinkVar(interp, "longdouble_size", (char*)&longdouble_size, TCL_LINK_INT|TCL_LINK_READ_ONLY); Tcl_LinkVar(interp, "sqlite_sync_count", (char*)&sqlite3_sync_count, TCL_LINK_INT); Tcl_LinkVar(interp, "sqlite_fullsync_count", (char*)&sqlite3_fullsync_count, TCL_LINK_INT); #if defined(SQLITE_ENABLE_SELECTTRACE) Tcl_LinkVar(interp, "sqlite3SelectTrace", (char*)&sqlite3SelectTrace, TCL_LINK_INT); #endif #if defined(SQLITE_ENABLE_FTS3) && defined(SQLITE_TEST) Tcl_LinkVar(interp, "sqlite_fts3_enable_parentheses", (char*)&sqlite3_fts3_enable_parentheses, TCL_LINK_INT); #endif return TCL_OK; } |
Changes to src/test_config.c.
︙ | ︙ | |||
757 758 759 760 761 762 763 764 765 766 767 768 769 770 | #endif #ifdef SQLITE_ENABLE_URI_00_ERROR Tcl_SetVar2(interp, "sqlite_options", "uri_00_error", "1", TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp, "sqlite_options", "uri_00_error", "0", TCL_GLOBAL_ONLY); #endif #define LINKVAR(x) { \ static const int cv_ ## x = SQLITE_ ## x; \ Tcl_LinkVar(interp, "SQLITE_" #x, (char *)&(cv_ ## x), \ TCL_LINK_INT | TCL_LINK_READ_ONLY); } LINKVAR( MAX_LENGTH ); | > > > > > > | 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 | #endif #ifdef SQLITE_ENABLE_URI_00_ERROR Tcl_SetVar2(interp, "sqlite_options", "uri_00_error", "1", TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp, "sqlite_options", "uri_00_error", "0", TCL_GLOBAL_ONLY); #endif #ifdef SQLITE_OMIT_WINDOWFUNC Tcl_SetVar2(interp, "sqlite_options", "windowfunc", "0", TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp, "sqlite_options", "windowfunc", "1", TCL_GLOBAL_ONLY); #endif #define LINKVAR(x) { \ static const int cv_ ## x = SQLITE_ ## x; \ Tcl_LinkVar(interp, "SQLITE_" #x, (char *)&(cv_ ## x), \ TCL_LINK_INT | TCL_LINK_READ_ONLY); } LINKVAR( MAX_LENGTH ); |
︙ | ︙ |
Changes to src/test_tclsh.c.
︙ | ︙ | |||
101 102 103 104 105 106 107 108 109 110 111 112 113 114 | #if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) extern int Sqlitetestfts3_Init(Tcl_Interp *interp); #endif #ifdef SQLITE_ENABLE_ZIPVFS extern int Zipvfs_Init(Tcl_Interp*); #endif extern int TestExpert_Init(Tcl_Interp*); Tcl_CmdInfo cmdInfo; /* Since the primary use case for this binary is testing of SQLite, ** be sure to generate core files if we crash */ #if defined(unix) { struct rlimit x; | > | 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | #if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) extern int Sqlitetestfts3_Init(Tcl_Interp *interp); #endif #ifdef SQLITE_ENABLE_ZIPVFS extern int Zipvfs_Init(Tcl_Interp*); #endif extern int TestExpert_Init(Tcl_Interp*); extern int Sqlitetest_window_Init(Tcl_Interp *); Tcl_CmdInfo cmdInfo; /* Since the primary use case for this binary is testing of SQLite, ** be sure to generate core files if we crash */ #if defined(unix) { struct rlimit x; |
︙ | ︙ | |||
165 166 167 168 169 170 171 172 173 174 175 176 177 178 | SqliteRbu_Init(interp); Sqlitetesttcl_Init(interp); #if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) Sqlitetestfts3_Init(interp); #endif TestExpert_Init(interp); Tcl_CreateObjCommand( interp, "load_testfixture_extensions", load_testfixture_extensions,0,0 ); return 0; } | > | 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 | SqliteRbu_Init(interp); Sqlitetesttcl_Init(interp); #if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) Sqlitetestfts3_Init(interp); #endif TestExpert_Init(interp); Sqlitetest_window_Init(interp); Tcl_CreateObjCommand( interp, "load_testfixture_extensions", load_testfixture_extensions,0,0 ); return 0; } |
︙ | ︙ |
Added src/test_window.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 | /* ** 2018 June 17 ** ** 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. ** ************************************************************************* */ #include "sqlite3.h" #ifdef SQLITE_TEST #include "sqliteInt.h" #include <tcl.h> extern int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb); extern const char *sqlite3ErrName(int); typedef struct TestWindow TestWindow; struct TestWindow { Tcl_Obj *xStep; Tcl_Obj *xFinal; Tcl_Obj *xValue; Tcl_Obj *xInverse; Tcl_Interp *interp; }; typedef struct TestWindowCtx TestWindowCtx; struct TestWindowCtx { Tcl_Obj *pVal; }; static void doTestWindowStep( int bInverse, sqlite3_context *ctx, int nArg, sqlite3_value **apArg ){ int i; TestWindow *p = (TestWindow*)sqlite3_user_data(ctx); Tcl_Obj *pEval = Tcl_DuplicateObj(bInverse ? p->xInverse : p->xStep); TestWindowCtx *pCtx = sqlite3_aggregate_context(ctx, sizeof(TestWindowCtx)); Tcl_IncrRefCount(pEval); if( pCtx ){ const char *zResult; int rc; if( pCtx->pVal ){ Tcl_ListObjAppendElement(p->interp, pEval, Tcl_DuplicateObj(pCtx->pVal)); }else{ Tcl_ListObjAppendElement(p->interp, pEval, Tcl_NewStringObj("", -1)); } for(i=0; i<nArg; i++){ Tcl_Obj *pArg; pArg = Tcl_NewStringObj((const char*)sqlite3_value_text(apArg[i]), -1); Tcl_ListObjAppendElement(p->interp, pEval, pArg); } rc = Tcl_EvalObjEx(p->interp, pEval, TCL_EVAL_GLOBAL); if( rc!=TCL_OK ){ zResult = Tcl_GetStringResult(p->interp); sqlite3_result_error(ctx, zResult, -1); }else{ if( pCtx->pVal ) Tcl_DecrRefCount(pCtx->pVal); pCtx->pVal = Tcl_DuplicateObj(Tcl_GetObjResult(p->interp)); Tcl_IncrRefCount(pCtx->pVal); } } Tcl_DecrRefCount(pEval); } static void doTestWindowFinalize(int bValue, sqlite3_context *ctx){ TestWindow *p = (TestWindow*)sqlite3_user_data(ctx); Tcl_Obj *pEval = Tcl_DuplicateObj(bValue ? p->xValue : p->xFinal); TestWindowCtx *pCtx = sqlite3_aggregate_context(ctx, sizeof(TestWindowCtx)); Tcl_IncrRefCount(pEval); if( pCtx ){ const char *zResult; int rc; if( pCtx->pVal ){ Tcl_ListObjAppendElement(p->interp, pEval, Tcl_DuplicateObj(pCtx->pVal)); }else{ Tcl_ListObjAppendElement(p->interp, pEval, Tcl_NewStringObj("", -1)); } rc = Tcl_EvalObjEx(p->interp, pEval, TCL_EVAL_GLOBAL); zResult = Tcl_GetStringResult(p->interp); if( rc!=TCL_OK ){ sqlite3_result_error(ctx, zResult, -1); }else{ sqlite3_result_text(ctx, zResult, -1, SQLITE_TRANSIENT); } if( bValue==0 ){ if( pCtx->pVal ) Tcl_DecrRefCount(pCtx->pVal); pCtx->pVal = 0; } } Tcl_DecrRefCount(pEval); } static void testWindowStep( sqlite3_context *ctx, int nArg, sqlite3_value **apArg ){ doTestWindowStep(0, ctx, nArg, apArg); } static void testWindowInverse( sqlite3_context *ctx, int nArg, sqlite3_value **apArg ){ doTestWindowStep(1, ctx, nArg, apArg); } static void testWindowFinal(sqlite3_context *ctx){ doTestWindowFinalize(0, ctx); } static void testWindowValue(sqlite3_context *ctx){ doTestWindowFinalize(1, ctx); } static void testWindowDestroy(void *pCtx){ ckfree(pCtx); } /* ** Usage: sqlite3_create_window_function DB NAME XSTEP XFINAL XVALUE XINVERSE */ static int SQLITE_TCLAPI test_create_window( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ TestWindow *pNew; sqlite3 *db; const char *zName; int rc; if( objc!=7 ){ Tcl_WrongNumArgs(interp, 1, objv, "DB NAME XSTEP XFINAL XVALUE XINVERSE"); return TCL_ERROR; } if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; zName = Tcl_GetString(objv[2]); pNew = ckalloc(sizeof(TestWindow)); memset(pNew, 0, sizeof(TestWindow)); pNew->xStep = Tcl_DuplicateObj(objv[3]); pNew->xFinal = Tcl_DuplicateObj(objv[4]); pNew->xValue = Tcl_DuplicateObj(objv[5]); pNew->xInverse = Tcl_DuplicateObj(objv[6]); pNew->interp = interp; Tcl_IncrRefCount(pNew->xStep); Tcl_IncrRefCount(pNew->xFinal); Tcl_IncrRefCount(pNew->xValue); Tcl_IncrRefCount(pNew->xInverse); rc = sqlite3_create_window_function(db, zName, -1, SQLITE_UTF8, (void*)pNew, testWindowStep, testWindowFinal, testWindowValue, testWindowInverse, testWindowDestroy ); if( rc!=SQLITE_OK ){ Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1)); return TCL_ERROR; } return TCL_OK; } static int SQLITE_TCLAPI test_create_window_misuse( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ sqlite3 *db; int rc; if( objc!=2 ){ Tcl_WrongNumArgs(interp, 1, objv, "DB"); return TCL_ERROR; } if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; rc = sqlite3_create_window_function(db, "fff", -1, SQLITE_UTF8, 0, 0, testWindowFinal, testWindowValue, testWindowInverse, 0 ); if( rc!=SQLITE_MISUSE ) goto error; rc = sqlite3_create_window_function(db, "fff", -1, SQLITE_UTF8, 0, testWindowStep, 0, testWindowValue, testWindowInverse, 0 ); if( rc!=SQLITE_MISUSE ) goto error; rc = sqlite3_create_window_function(db, "fff", -1, SQLITE_UTF8, 0, testWindowStep, testWindowFinal, 0, testWindowInverse, 0 ); if( rc!=SQLITE_MISUSE ) goto error; rc = sqlite3_create_window_function(db, "fff", -1, SQLITE_UTF8, 0, testWindowStep, testWindowFinal, testWindowValue, 0, 0 ); if( rc!=SQLITE_MISUSE ) goto error; return TCL_OK; error: Tcl_SetObjResult(interp, Tcl_NewStringObj("misuse test error", -1)); return TCL_ERROR; } /* ** xStep for sumint(). */ static void sumintStep( sqlite3_context *ctx, int nArg, sqlite3_value *apArg[] ){ sqlite3_int64 *pInt; assert( nArg==1 ); if( sqlite3_value_type(apArg[0])!=SQLITE_INTEGER ){ sqlite3_result_error(ctx, "invalid argument", -1); return; } pInt = (sqlite3_int64*)sqlite3_aggregate_context(ctx, sizeof(sqlite3_int64)); if( pInt ){ *pInt += sqlite3_value_int64(apArg[0]); } } /* ** xInverse for sumint(). */ static void sumintInverse( sqlite3_context *ctx, int nArg, sqlite3_value *apArg[] ){ sqlite3_int64 *pInt; pInt = (sqlite3_int64*)sqlite3_aggregate_context(ctx, sizeof(sqlite3_int64)); *pInt -= sqlite3_value_int64(apArg[0]); } /* ** xFinal for sumint(). */ static void sumintFinal(sqlite3_context *ctx){ sqlite3_int64 res = 0; sqlite3_int64 *pInt; pInt = (sqlite3_int64*)sqlite3_aggregate_context(ctx, 0); if( pInt ) res = *pInt; sqlite3_result_int64(ctx, res); } /* ** xValue for sumint(). */ static void sumintValue(sqlite3_context *ctx){ sqlite3_int64 res = 0; sqlite3_int64 *pInt; pInt = (sqlite3_int64*)sqlite3_aggregate_context(ctx, 0); if( pInt ) res = *pInt; sqlite3_result_int64(ctx, res); } static int SQLITE_TCLAPI test_create_sumint( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ sqlite3 *db; int rc; if( objc!=2 ){ Tcl_WrongNumArgs(interp, 1, objv, "DB"); return TCL_ERROR; } if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; rc = sqlite3_create_window_function(db, "sumint", 1, SQLITE_UTF8, 0, sumintStep, sumintFinal, sumintValue, sumintInverse, 0 ); if( rc!=SQLITE_OK ){ Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1)); return TCL_ERROR; } return TCL_OK; } int Sqlitetest_window_Init(Tcl_Interp *interp){ static struct { char *zName; Tcl_ObjCmdProc *xProc; int clientData; } aObjCmd[] = { { "sqlite3_create_window_function", test_create_window, 0 }, { "test_create_window_function_misuse", test_create_window_misuse, 0 }, { "test_create_sumint", test_create_sumint, 0 }, }; int i; for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ ClientData c = (ClientData)SQLITE_INT_TO_PTR(aObjCmd[i].clientData); Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, c, 0); } return TCL_OK; } #endif |
Changes to src/tokenize.c.
︙ | ︙ | |||
50 51 52 53 54 55 56 57 58 59 60 | #define CC_STAR 21 /* '*' */ #define CC_PERCENT 22 /* '%' */ #define CC_COMMA 23 /* ',' */ #define CC_AND 24 /* '&' */ #define CC_TILDA 25 /* '~' */ #define CC_DOT 26 /* '.' */ #define CC_ILLEGAL 27 /* Illegal character */ static const unsigned char aiClass[] = { #ifdef SQLITE_ASCII /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf */ | > | | 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | #define CC_STAR 21 /* '*' */ #define CC_PERCENT 22 /* '%' */ #define CC_COMMA 23 /* ',' */ #define CC_AND 24 /* '&' */ #define CC_TILDA 25 /* '~' */ #define CC_DOT 26 /* '.' */ #define CC_ILLEGAL 27 /* Illegal character */ #define CC_NUL 28 /* 0x00 */ static const unsigned char aiClass[] = { #ifdef SQLITE_ASCII /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf */ /* 0x */ 28, 27, 27, 27, 27, 27, 27, 27, 27, 7, 7, 27, 7, 7, 27, 27, /* 1x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, /* 2x */ 7, 15, 8, 5, 4, 22, 24, 8, 17, 18, 21, 20, 23, 11, 26, 16, /* 3x */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 19, 12, 14, 13, 6, /* 4x */ 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 5x */ 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 9, 27, 27, 27, 1, /* 6x */ 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 7x */ 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 27, 10, 27, 25, 27, |
︙ | ︙ | |||
184 185 186 187 188 189 190 191 192 193 194 195 196 197 | #endif /* Make the IdChar function accessible from ctime.c */ #ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS int sqlite3IsIdChar(u8 c){ return IdChar(c); } #endif /* ** Return the length (in bytes) of the token that begins at z[0]. ** Store the token type in *tokenType before returning. */ int sqlite3GetToken(const unsigned char *z, int *tokenType){ int i, c; | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 | #endif /* Make the IdChar function accessible from ctime.c */ #ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS int sqlite3IsIdChar(u8 c){ return IdChar(c); } #endif #ifndef SQLITE_OMIT_WINDOWFUNC /* ** Return the id of the next token in string (*pz). Before returning, set ** (*pz) to point to the byte following the parsed token. */ static int getToken(const unsigned char **pz){ const unsigned char *z = *pz; int t; /* Token type to return */ do { z += sqlite3GetToken(z, &t); }while( t==TK_SPACE ); if( t==TK_ID || t==TK_STRING || t==TK_JOIN_KW || t==TK_WINDOW || t==TK_OVER || sqlite3ParserFallback(t)==TK_ID ){ t = TK_ID; } *pz = z; return t; } /* ** The following three functions are called immediately after the tokenizer ** reads the keywords WINDOW, OVER and FILTER, respectively, to determine ** whether the token should be treated as a keyword or an SQL identifier. ** This cannot be handled by the usual lemon %fallback method, due to ** the ambiguity in some constructions. e.g. ** ** SELECT sum(x) OVER ... ** ** In the above, "OVER" might be a keyword, or it might be an alias for the ** sum(x) expression. If a "%fallback ID OVER" directive were added to ** grammar, then SQLite would always treat "OVER" as an alias, making it ** impossible to call a window-function without a FILTER clause. ** ** WINDOW is treated as a keyword if: ** ** * the following token is an identifier, or a keyword that can fallback ** to being an identifier, and ** * the token after than one is TK_AS. ** ** OVER is a keyword if: ** ** * the previous token was TK_RP, and ** * the next token is either TK_LP or an identifier. ** ** FILTER is a keyword if: ** ** * the previous token was TK_RP, and ** * the next token is TK_LP. */ static int analyzeWindowKeyword(const unsigned char *z){ int t; t = getToken(&z); if( t!=TK_ID ) return TK_ID; t = getToken(&z); if( t!=TK_AS ) return TK_ID; return TK_WINDOW; } static int analyzeOverKeyword(const unsigned char *z, int lastToken){ if( lastToken==TK_RP ){ int t = getToken(&z); if( t==TK_LP || t==TK_ID ) return TK_OVER; } return TK_ID; } static int analyzeFilterKeyword(const unsigned char *z, int lastToken){ if( lastToken==TK_RP && getToken(&z)==TK_LP ){ return TK_FILTER; } return TK_ID; } #endif // SQLITE_OMIT_WINDOWFUNC /* ** Return the length (in bytes) of the token that begins at z[0]. ** Store the token type in *tokenType before returning. */ int sqlite3GetToken(const unsigned char *z, int *tokenType){ int i, c; |
︙ | ︙ | |||
452 453 454 455 456 457 458 459 460 461 462 463 464 465 | /* If it is not a BLOB literal, then it must be an ID, since no ** SQL keywords start with the letter 'x'. Fall through */ } case CC_ID: { i = 1; break; } default: { *tokenType = TK_ILLEGAL; return 1; } } while( IdChar(z[i]) ){ i++; } *tokenType = TK_ID; | > > > > | 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 | /* If it is not a BLOB literal, then it must be an ID, since no ** SQL keywords start with the letter 'x'. Fall through */ } case CC_ID: { i = 1; break; } case CC_NUL: { *tokenType = TK_ILLEGAL; return 0; } default: { *tokenType = TK_ILLEGAL; return 1; } } while( IdChar(z[i]) ){ i++; } *tokenType = TK_ID; |
︙ | ︙ | |||
505 506 507 508 509 510 511 | } #endif assert( pParse->pNewTable==0 ); assert( pParse->pNewTrigger==0 ); assert( pParse->nVar==0 ); assert( pParse->pVList==0 ); while( 1 ){ | < | | | | | | < < > | | | < < > | < < < < > | > > > > > > > | > | > > | | > > > > > > > > > > > | > > > > | | | | | | < | 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 | } #endif assert( pParse->pNewTable==0 ); assert( pParse->pNewTrigger==0 ); assert( pParse->nVar==0 ); assert( pParse->pVList==0 ); while( 1 ){ n = sqlite3GetToken((u8*)zSql, &tokenType); mxSqlLen -= n; if( mxSqlLen<0 ){ pParse->rc = SQLITE_TOOBIG; break; } #ifndef SQLITE_OMIT_WINDOWFUNC if( tokenType>=TK_WINDOW ){ assert( tokenType==TK_SPACE || tokenType==TK_OVER || tokenType==TK_FILTER || tokenType==TK_ILLEGAL || tokenType==TK_WINDOW ); #else if( tokenType>=TK_SPACE ){ assert( tokenType==TK_SPACE || tokenType==TK_ILLEGAL ); #endif // SQLITE_OMIT_WINDOWFUNC if( db->u1.isInterrupted ){ pParse->rc = SQLITE_INTERRUPT; break; } if( tokenType==TK_SPACE ){ zSql += n; continue; } if( zSql[0]==0 ){ /* Upon reaching the end of input, call the parser two more times ** with tokens TK_SEMI and 0, in that order. */ if( lastTokenParsed==TK_SEMI ){ tokenType = 0; }else if( lastTokenParsed==0 ){ break; }else{ tokenType = TK_SEMI; } n = 0; #ifndef SQLITE_OMIT_WINDOWFUNC }else if( tokenType==TK_WINDOW ){ assert( n==6 ); tokenType = analyzeWindowKeyword((const u8*)&zSql[6]); }else if( tokenType==TK_OVER ){ assert( n==4 ); tokenType = analyzeOverKeyword((const u8*)&zSql[4], lastTokenParsed); }else if( tokenType==TK_FILTER ){ assert( n==6 ); tokenType = analyzeFilterKeyword((const u8*)&zSql[6], lastTokenParsed); #endif // SQLITE_OMIT_WINDOWFUNC }else{ sqlite3ErrorMsg(pParse, "unrecognized token: \"%.*s\"", n, zSql); break; } } pParse->sLastToken.z = zSql; pParse->sLastToken.n = n; sqlite3Parser(pEngine, tokenType, pParse->sLastToken); lastTokenParsed = tokenType; zSql += n; if( pParse->rc!=SQLITE_OK || db->mallocFailed ) break; } assert( nErr==0 ); #ifdef YYTRACKMAXSTACKDEPTH sqlite3_mutex_enter(sqlite3MallocMutex()); sqlite3StatusHighwater(SQLITE_STATUS_PARSER_STACK, sqlite3ParserStackPeak(pEngine) ); |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
5078 5079 5080 5081 5082 5083 5084 | #ifdef SQLITE_TEST sqlite3_sort_count++; sqlite3_search_count--; #endif p->aCounter[SQLITE_STMTSTATUS_SORT]++; /* Fall through into OP_Rewind */ } | | > > > > | 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 5089 5090 5091 5092 5093 5094 5095 5096 5097 5098 5099 5100 5101 5102 | #ifdef SQLITE_TEST sqlite3_sort_count++; sqlite3_search_count--; #endif p->aCounter[SQLITE_STMTSTATUS_SORT]++; /* Fall through into OP_Rewind */ } /* Opcode: Rewind P1 P2 * * P5 ** ** The next use of the Rowid or Column or Next instruction for P1 ** will refer to the first entry in the database table or index. ** If the table or index is empty, jump immediately to P2. ** If the table or index is not empty, fall through to the following ** instruction. ** ** If P5 is non-zero and the table is not empty, then the "skip-next" ** flag is set on the cursor so that the next OP_Next instruction ** executed on it is a no-op. ** ** This opcode leaves the cursor configured to move in forward order, ** from the beginning toward the end. In other words, the cursor is ** configured to use Next, not Prev. */ case OP_Rewind: { /* jump */ VdbeCursor *pC; |
︙ | ︙ | |||
5110 5111 5112 5113 5114 5115 5116 5117 5118 5119 5120 5121 5122 5123 | if( isSorter(pC) ){ rc = sqlite3VdbeSorterRewind(pC, &res); }else{ assert( pC->eCurType==CURTYPE_BTREE ); pCrsr = pC->uc.pCursor; assert( pCrsr ); rc = sqlite3BtreeFirst(pCrsr, &res); pC->deferredMoveto = 0; pC->cacheStatus = CACHE_STALE; } if( rc ) goto abort_due_to_error; pC->nullRow = (u8)res; assert( pOp->p2>0 && pOp->p2<p->nOp ); VdbeBranchTaken(res!=0,2); | > > > | 5114 5115 5116 5117 5118 5119 5120 5121 5122 5123 5124 5125 5126 5127 5128 5129 5130 | if( isSorter(pC) ){ rc = sqlite3VdbeSorterRewind(pC, &res); }else{ assert( pC->eCurType==CURTYPE_BTREE ); pCrsr = pC->uc.pCursor; assert( pCrsr ); rc = sqlite3BtreeFirst(pCrsr, &res); #ifndef SQLITE_OMIT_WINDOWFUNC if( pOp->p5 ) sqlite3BtreeSkipNext(pCrsr); #endif pC->deferredMoveto = 0; pC->cacheStatus = CACHE_STALE; } if( rc ) goto abort_due_to_error; pC->nullRow = (u8)res; assert( pOp->p2>0 && pOp->p2<p->nOp ); VdbeBranchTaken(res!=0,2); |
︙ | ︙ | |||
6277 6278 6279 6280 6281 6282 6283 | if( pIn1->u.i>SMALLEST_INT64 ) pIn1->u.i--; VdbeBranchTaken(pIn1->u.i==0, 2); if( pIn1->u.i==0 ) goto jump_to_p2; break; } | | | | | | | | | | | 6284 6285 6286 6287 6288 6289 6290 6291 6292 6293 6294 6295 6296 6297 6298 6299 6300 6301 6302 6303 6304 6305 6306 6307 6308 6309 6310 6311 6312 6313 6314 6315 | if( pIn1->u.i>SMALLEST_INT64 ) pIn1->u.i--; VdbeBranchTaken(pIn1->u.i==0, 2); if( pIn1->u.i==0 ) goto jump_to_p2; break; } /* Opcode: AggStep0 P1 P2 P3 P4 P5 ** Synopsis: accum=r[P3] step(r[P2@P5]) ** ** Execute the xStep (if P1==0) or xInverse (if P1!=0) function for an ** aggregate. The function has P5 arguments. P4 is a pointer to the ** FuncDef structure that specifies the function. Register P3 is the ** accumulator. ** ** The P5 arguments are taken from register P2 and its ** successors. */ /* Opcode: AggStep P1 P2 P3 P4 P5 ** Synopsis: accum=r[P3] step(r[P2@P5]) ** ** Execute the xStep (if P1==0) or xInverse (if P1!=0) function for an ** aggregate. The function has P5 arguments. P4 is a pointer to the ** FuncDef structure that specifies the function. Register P3 is the ** accumulator. ** ** The P5 arguments are taken from register P2 and its ** successors. ** ** This opcode is initially coded as OP_AggStep0. On first evaluation, ** the FuncDef stored in P4 is converted into an sqlite3_context and ** the opcode is changed. In this way, the initialization of the |
︙ | ︙ | |||
6360 6361 6362 6363 6364 6365 6366 6367 6368 6369 6370 6371 6372 6373 6374 | } #endif pMem->n++; assert( pCtx->pOut->flags==MEM_Null ); assert( pCtx->isError==0 ); assert( pCtx->skipFlag==0 ); (pCtx->pFunc->xSFunc)(pCtx,pCtx->argc,pCtx->argv); /* IMP: R-24505-23230 */ if( pCtx->isError ){ if( pCtx->isError>0 ){ sqlite3VdbeError(p, "%s", sqlite3_value_text(pCtx->pOut)); rc = pCtx->isError; } if( pCtx->skipFlag ){ assert( pOp[-1].opcode==OP_CollSeq ); | > > > > > > | 6367 6368 6369 6370 6371 6372 6373 6374 6375 6376 6377 6378 6379 6380 6381 6382 6383 6384 6385 6386 6387 | } #endif pMem->n++; assert( pCtx->pOut->flags==MEM_Null ); assert( pCtx->isError==0 ); assert( pCtx->skipFlag==0 ); #ifndef SQLITE_OMIT_WINDOWFUNC if( pOp->p1 ){ (pCtx->pFunc->xInverse)(pCtx,pCtx->argc,pCtx->argv); }else #endif (pCtx->pFunc->xSFunc)(pCtx,pCtx->argc,pCtx->argv); /* IMP: R-24505-23230 */ if( pCtx->isError ){ if( pCtx->isError>0 ){ sqlite3VdbeError(p, "%s", sqlite3_value_text(pCtx->pOut)); rc = pCtx->isError; } if( pCtx->skipFlag ){ assert( pOp[-1].opcode==OP_CollSeq ); |
︙ | ︙ | |||
6382 6383 6384 6385 6386 6387 6388 | if( rc ) goto abort_due_to_error; } assert( pCtx->pOut->flags==MEM_Null ); assert( pCtx->skipFlag==0 ); break; } | | < | > > > > > > > > > > | 6395 6396 6397 6398 6399 6400 6401 6402 6403 6404 6405 6406 6407 6408 6409 6410 6411 6412 6413 6414 6415 6416 6417 6418 6419 6420 6421 6422 6423 6424 6425 6426 6427 6428 6429 6430 6431 6432 6433 6434 6435 6436 | if( rc ) goto abort_due_to_error; } assert( pCtx->pOut->flags==MEM_Null ); assert( pCtx->skipFlag==0 ); break; } /* Opcode: AggFinal P1 P2 P3 P4 * ** Synopsis: accum=r[P1] N=P2 ** ** P1 is the memory location that is the accumulator for an aggregate ** or window function. If P3 is zero, then execute the finalizer function ** for an aggregate and store the result in P1. Or, if P3 is non-zero, ** invoke the xValue() function and store the result in register P3. ** ** P2 is the number of arguments that the step function takes and ** P4 is a pointer to the FuncDef for this function. The P2 ** argument is not used by this opcode. It is only there to disambiguate ** functions that can take varying numbers of arguments. The ** P4 argument is only needed for the degenerate case where ** the step function was not previously called. */ case OP_AggFinal: { Mem *pMem; assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) ); pMem = &aMem[pOp->p1]; assert( (pMem->flags & ~(MEM_Null|MEM_Agg))==0 ); #ifndef SQLITE_OMIT_WINDOWFUNC if( pOp->p3 ){ rc = sqlite3VdbeMemAggValue(pMem, &aMem[pOp->p3], pOp->p4.pFunc); pMem = &aMem[pOp->p3]; }else #endif rc = sqlite3VdbeMemFinalize(pMem, pOp->p4.pFunc); if( rc ){ sqlite3VdbeError(p, "%s", sqlite3_value_text(pMem)); goto abort_due_to_error; } sqlite3VdbeChangeEncoding(pMem, encoding); UPDATE_MAX_BLOBSIZE(pMem); if( sqlite3VdbeMemTooBig(pMem) ){ |
︙ | ︙ |
Changes to src/vdbe.h.
︙ | ︙ | |||
239 240 241 242 243 244 245 246 247 248 249 250 251 252 | void sqlite3VdbeResolveLabel(Vdbe*, int); #ifdef SQLITE_COVERAGE_TEST int sqlite3VdbeLabelHasBeenResolved(Vdbe*,int); #endif int sqlite3VdbeCurrentAddr(Vdbe*); #ifdef SQLITE_DEBUG int sqlite3VdbeAssertMayAbort(Vdbe *, int); #endif void sqlite3VdbeResetStepResult(Vdbe*); void sqlite3VdbeRewind(Vdbe*); int sqlite3VdbeReset(Vdbe*); void sqlite3VdbeSetNumCols(Vdbe*,int); int sqlite3VdbeSetColName(Vdbe*, int, int, const char *, void(*)(void*)); void sqlite3VdbeCountChanges(Vdbe*); | > | 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 | void sqlite3VdbeResolveLabel(Vdbe*, int); #ifdef SQLITE_COVERAGE_TEST int sqlite3VdbeLabelHasBeenResolved(Vdbe*,int); #endif int sqlite3VdbeCurrentAddr(Vdbe*); #ifdef SQLITE_DEBUG int sqlite3VdbeAssertMayAbort(Vdbe *, int); int sqlite3VdbeAssertAggContext(sqlite3_context*); #endif void sqlite3VdbeResetStepResult(Vdbe*); void sqlite3VdbeRewind(Vdbe*); int sqlite3VdbeReset(Vdbe*); void sqlite3VdbeSetNumCols(Vdbe*,int); int sqlite3VdbeSetColName(Vdbe*, int, int, const char *, void(*)(void*)); void sqlite3VdbeCountChanges(Vdbe*); |
︙ | ︙ |
Changes to src/vdbeInt.h.
︙ | ︙ | |||
493 494 495 496 497 498 499 500 501 502 503 504 505 506 | void sqlite3VdbeIntegerAffinity(Mem*); int sqlite3VdbeMemRealify(Mem*); int sqlite3VdbeMemNumerify(Mem*); void sqlite3VdbeMemCast(Mem*,u8,u8); int sqlite3VdbeMemFromBtree(BtCursor*,u32,u32,Mem*); void sqlite3VdbeMemRelease(Mem *p); int sqlite3VdbeMemFinalize(Mem*, FuncDef*); const char *sqlite3OpcodeName(int); int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve); int sqlite3VdbeMemClearAndResize(Mem *pMem, int n); int sqlite3VdbeCloseStatement(Vdbe *, int); void sqlite3VdbeFrameDelete(VdbeFrame*); int sqlite3VdbeFrameRestore(VdbeFrame *); #ifdef SQLITE_ENABLE_PREUPDATE_HOOK | > > > | 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 | void sqlite3VdbeIntegerAffinity(Mem*); int sqlite3VdbeMemRealify(Mem*); int sqlite3VdbeMemNumerify(Mem*); void sqlite3VdbeMemCast(Mem*,u8,u8); int sqlite3VdbeMemFromBtree(BtCursor*,u32,u32,Mem*); void sqlite3VdbeMemRelease(Mem *p); int sqlite3VdbeMemFinalize(Mem*, FuncDef*); #ifndef SQLITE_OMIT_WINDOWFUNC int sqlite3VdbeMemAggValue(Mem*, Mem*, FuncDef*); #endif const char *sqlite3OpcodeName(int); int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve); int sqlite3VdbeMemClearAndResize(Mem *pMem, int n); int sqlite3VdbeCloseStatement(Vdbe *, int); void sqlite3VdbeFrameDelete(VdbeFrame*); int sqlite3VdbeFrameRestore(VdbeFrame *); #ifdef SQLITE_ENABLE_PREUPDATE_HOOK |
︙ | ︙ |
Changes to src/vdbeapi.c.
︙ | ︙ | |||
820 821 822 823 824 825 826 827 828 829 830 831 832 833 | if( (p->pMem->flags & MEM_Agg)==0 ){ return createAggContext(p, nByte); }else{ return (void*)p->pMem->z; } } /* ** Return the auxiliary data pointer, if any, for the iArg'th argument to ** the user-function defined by pCtx. ** ** The left-most argument is 0. ** ** Undocumented behavior: If iArg is negative then access a cache of | > > > > > > > > > > > > | 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 | if( (p->pMem->flags & MEM_Agg)==0 ){ return createAggContext(p, nByte); }else{ return (void*)p->pMem->z; } } /* ** This function is only used within assert() statements to check that the ** aggregate context has already been allocated. i.e.: ** ** assert( sqlite3VdbeAssertAggContext(p) ); */ #ifdef SQLITE_DEBUG int sqlite3VdbeAssertAggContext(sqlite3_context *p){ return ((p->pMem->flags & MEM_Agg)!=0); } #endif /* SQLITE_DEBUG */ /* ** Return the auxiliary data pointer, if any, for the iArg'th argument to ** the user-function defined by pCtx. ** ** The left-most argument is 0. ** ** Undocumented behavior: If iArg is negative then access a cache of |
︙ | ︙ |
Changes to src/vdbemem.c.
︙ | ︙ | |||
411 412 413 414 415 416 417 418 419 420 421 422 423 424 | pFunc->xFinalize(&ctx); /* IMP: R-24505-23230 */ assert( (pMem->flags & MEM_Dyn)==0 ); if( pMem->szMalloc>0 ) sqlite3DbFreeNN(pMem->db, pMem->zMalloc); memcpy(pMem, &t, sizeof(t)); return ctx.isError; } /* ** If the memory cell contains a value that must be freed by ** invoking the external callback in Mem.xDel, then this routine ** will free that value. It also sets Mem.flags to MEM_Null. ** ** This is a helper routine for sqlite3VdbeMemSetNull() and ** for sqlite3VdbeMemRelease(). Use those other routines as the | > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 | pFunc->xFinalize(&ctx); /* IMP: R-24505-23230 */ assert( (pMem->flags & MEM_Dyn)==0 ); if( pMem->szMalloc>0 ) sqlite3DbFreeNN(pMem->db, pMem->zMalloc); memcpy(pMem, &t, sizeof(t)); return ctx.isError; } /* ** Memory cell pAccum contains the context of an aggregate function. ** This routine calls the xValue method for that function and stores ** the results in memory cell pMem. ** ** SQLITE_ERROR is returned if xValue() reports an error. SQLITE_OK ** otherwise. */ #ifndef SQLITE_OMIT_WINDOWFUNC int sqlite3VdbeMemAggValue(Mem *pAccum, Mem *pOut, FuncDef *pFunc){ sqlite3_context ctx; Mem t; assert( pFunc!=0 ); assert( pFunc->xValue!=0 ); assert( (pAccum->flags & MEM_Null)!=0 || pFunc==pAccum->u.pDef ); assert( pAccum->db==0 || sqlite3_mutex_held(pAccum->db->mutex) ); memset(&ctx, 0, sizeof(ctx)); memset(&t, 0, sizeof(t)); t.flags = MEM_Null; t.db = pAccum->db; ctx.pOut = pOut; ctx.pMem = pAccum; ctx.pFunc = pFunc; pFunc->xValue(&ctx); return ctx.isError; } #endif /* SQLITE_OMIT_WINDOWFUNC */ /* ** If the memory cell contains a value that must be freed by ** invoking the external callback in Mem.xDel, then this routine ** will free that value. It also sets Mem.flags to MEM_Null. ** ** This is a helper routine for sqlite3VdbeMemSetNull() and ** for sqlite3VdbeMemRelease(). Use those other routines as the |
︙ | ︙ |
Changes to src/walker.c.
︙ | ︙ | |||
50 51 52 53 54 55 56 57 58 59 60 61 62 63 | pExpr = pExpr->pRight; continue; }else if( ExprHasProperty(pExpr, EP_xIsSelect) ){ if( sqlite3WalkSelect(pWalker, pExpr->x.pSelect) ) return WRC_Abort; }else if( pExpr->x.pList ){ if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort; } } break; } return WRC_Continue; } int sqlite3WalkExpr(Walker *pWalker, Expr *pExpr){ return pExpr ? walkExpr(pWalker,pExpr) : WRC_Continue; | > > > > > > > > | 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | pExpr = pExpr->pRight; continue; }else if( ExprHasProperty(pExpr, EP_xIsSelect) ){ if( sqlite3WalkSelect(pWalker, pExpr->x.pSelect) ) return WRC_Abort; }else if( pExpr->x.pList ){ if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort; } #ifndef SQLITE_OMIT_WINDOWFUNC if( !ExprHasProperty(pExpr, EP_Reduced) && pExpr->pWin ){ Window *pWin = pExpr->pWin; if( sqlite3WalkExprList(pWalker, pWin->pPartition) ) return WRC_Abort; if( sqlite3WalkExprList(pWalker, pWin->pOrderBy) ) return WRC_Abort; if( sqlite3WalkExpr(pWalker, pWin->pFilter) ) return WRC_Abort; } #endif } break; } return WRC_Continue; } int sqlite3WalkExpr(Walker *pWalker, Expr *pExpr){ return pExpr ? walkExpr(pWalker,pExpr) : WRC_Continue; |
︙ | ︙ |
Added src/window.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 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 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 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 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 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 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 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 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 | /* ** 2018 May 08 ** ** 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. ** ************************************************************************* */ #include "sqliteInt.h" #ifndef SQLITE_OMIT_WINDOWFUNC /* ** SELECT REWRITING ** ** Any SELECT statement that contains one or more window functions in ** either the select list or ORDER BY clause (the only two places window ** functions may be used) is transformed by function sqlite3WindowRewrite() ** in order to support window function processing. For example, with the ** schema: ** ** CREATE TABLE t1(a, b, c, d, e, f, g); ** ** the statement: ** ** SELECT a+1, max(b) OVER (PARTITION BY c ORDER BY d) FROM t1 ORDER BY e; ** ** is transformed to: ** ** SELECT a+1, max(b) OVER (PARTITION BY c ORDER BY d) FROM ( ** SELECT a, e, c, d, b FROM t1 ORDER BY c, d ** ) ORDER BY e; ** ** The flattening optimization is disabled when processing this transformed ** SELECT statement. This allows the implementation of the window function ** (in this case max()) to process rows sorted in order of (c, d), which ** makes things easier for obvious reasons. More generally: ** ** * FROM, WHERE, GROUP BY and HAVING clauses are all moved to ** the sub-query. ** ** * ORDER BY, LIMIT and OFFSET remain part of the parent query. ** ** * Terminals from each of the expression trees that make up the ** select-list and ORDER BY expressions in the parent query are ** selected by the sub-query. For the purposes of the transformation, ** terminals are column references and aggregate functions. ** ** If there is more than one window function in the SELECT that uses ** the same window declaration (the OVER bit), then a single scan may ** be used to process more than one window function. For example: ** ** SELECT max(b) OVER (PARTITION BY c ORDER BY d), ** min(e) OVER (PARTITION BY c ORDER BY d) ** FROM t1; ** ** is transformed in the same way as the example above. However: ** ** SELECT max(b) OVER (PARTITION BY c ORDER BY d), ** min(e) OVER (PARTITION BY a ORDER BY b) ** FROM t1; ** ** Must be transformed to: ** ** SELECT max(b) OVER (PARTITION BY c ORDER BY d) FROM ( ** SELECT e, min(e) OVER (PARTITION BY a ORDER BY b), c, d, b FROM ** SELECT a, e, c, d, b FROM t1 ORDER BY a, b ** ) ORDER BY c, d ** ) ORDER BY e; ** ** so that both min() and max() may process rows in the order defined by ** their respective window declarations. ** ** INTERFACE WITH SELECT.C ** ** When processing the rewritten SELECT statement, code in select.c calls ** sqlite3WhereBegin() to begin iterating through the results of the ** sub-query, which is always implemented as a co-routine. It then calls ** sqlite3WindowCodeStep() to process rows and finish the scan by calling ** sqlite3WhereEnd(). ** ** sqlite3WindowCodeStep() generates VM code so that, for each row returned ** by the sub-query a sub-routine (OP_Gosub) coded by select.c is invoked. ** When the sub-routine is invoked: ** ** * The results of all window-functions for the row are stored ** in the associated Window.regResult registers. ** ** * The required terminal values are stored in the current row of ** temp table Window.iEphCsr. ** ** In some cases, depending on the window frame and the specific window ** functions invoked, sqlite3WindowCodeStep() caches each entire partition ** in a temp table before returning any rows. In other cases it does not. ** This detail is encapsulated within this file, the code generated by ** select.c is the same in either case. ** ** BUILT-IN WINDOW FUNCTIONS ** ** This implementation features the following built-in window functions: ** ** row_number() ** rank() ** dense_rank() ** percent_rank() ** cume_dist() ** ntile(N) ** lead(expr [, offset [, default]]) ** lag(expr [, offset [, default]]) ** first_value(expr) ** last_value(expr) ** nth_value(expr, N) ** ** These are the same built-in window functions supported by Postgres. ** Although the behaviour of aggregate window functions (functions that ** can be used as either aggregates or window funtions) allows them to ** be implemented using an API, built-in window functions are much more ** esoteric. Additionally, some window functions (e.g. nth_value()) ** may only be implemented by caching the entire partition in memory. ** As such, some built-in window functions use the same API as aggregate ** window functions and some are implemented directly using VDBE ** instructions. Additionally, for those functions that use the API, the ** window frame is sometimes modified before the SELECT statement is ** rewritten. For example, regardless of the specified window frame, the ** row_number() function always uses: ** ** ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ** ** See sqlite3WindowUpdate() for details. ** ** As well as some of the built-in window functions, aggregate window ** functions min() and max() are implemented using VDBE instructions if ** the start of the window frame is declared as anything other than ** UNBOUNDED PRECEDING. */ /* ** Implementation of built-in window function row_number(). Assumes that the ** window frame has been coerced to: ** ** ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW */ static void row_numberStepFunc( sqlite3_context *pCtx, int nArg, sqlite3_value **apArg ){ i64 *p = (i64*)sqlite3_aggregate_context(pCtx, sizeof(*p)); if( p ) (*p)++; } static void row_numberInvFunc( sqlite3_context *pCtx, int nArg, sqlite3_value **apArg ){ } static void row_numberValueFunc(sqlite3_context *pCtx){ i64 *p = (i64*)sqlite3_aggregate_context(pCtx, sizeof(*p)); sqlite3_result_int64(pCtx, (p ? *p : 0)); } /* ** Context object type used by rank(), dense_rank(), percent_rank() and ** cume_dist(). */ struct CallCount { i64 nValue; i64 nStep; i64 nTotal; }; /* ** Implementation of built-in window function dense_rank(). Assumes that ** the window frame has been set to: ** ** RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW */ static void dense_rankStepFunc( sqlite3_context *pCtx, int nArg, sqlite3_value **apArg ){ struct CallCount *p; p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p)); if( p ) p->nStep = 1; } static void dense_rankInvFunc( sqlite3_context *pCtx, int nArg, sqlite3_value **apArg ){ } static void dense_rankValueFunc(sqlite3_context *pCtx){ struct CallCount *p; p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p)); if( p ){ if( p->nStep ){ p->nValue++; p->nStep = 0; } sqlite3_result_int64(pCtx, p->nValue); } } /* ** Implementation of built-in window function rank(). Assumes that ** the window frame has been set to: ** ** RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW */ static void rankStepFunc( sqlite3_context *pCtx, int nArg, sqlite3_value **apArg ){ struct CallCount *p; p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p)); if( p ){ p->nStep++; if( p->nValue==0 ){ p->nValue = p->nStep; } } } static void rankInvFunc( sqlite3_context *pCtx, int nArg, sqlite3_value **apArg ){ } static void rankValueFunc(sqlite3_context *pCtx){ struct CallCount *p; p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p)); if( p ){ sqlite3_result_int64(pCtx, p->nValue); p->nValue = 0; } } /* ** Implementation of built-in window function percent_rank(). Assumes that ** the window frame has been set to: ** ** RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW */ static void percent_rankStepFunc( sqlite3_context *pCtx, int nArg, sqlite3_value **apArg ){ struct CallCount *p; assert( nArg==1 ); assert( sqlite3VdbeAssertAggContext(pCtx) ); p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p)); if( ALWAYS(p) ){ if( p->nTotal==0 ){ p->nTotal = sqlite3_value_int64(apArg[0]); } p->nStep++; if( p->nValue==0 ){ p->nValue = p->nStep; } } } static void percent_rankInvFunc( sqlite3_context *pCtx, int nArg, sqlite3_value **apArg ){ } static void percent_rankValueFunc(sqlite3_context *pCtx){ struct CallCount *p; p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p)); if( p ){ if( p->nTotal>1 ){ double r = (double)(p->nValue-1) / (double)(p->nTotal-1); sqlite3_result_double(pCtx, r); }else{ sqlite3_result_double(pCtx, 0.0); } p->nValue = 0; } } /* ** Implementation of built-in window function cume_dist(). Assumes that ** the window frame has been set to: ** ** RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW */ static void cume_distStepFunc( sqlite3_context *pCtx, int nArg, sqlite3_value **apArg ){ struct CallCount *p; assert( nArg==1 ); assert( sqlite3VdbeAssertAggContext(pCtx) ); p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p)); if( ALWAYS(p) ){ if( p->nTotal==0 ){ p->nTotal = sqlite3_value_int64(apArg[0]); } p->nStep++; } } static void cume_distInvFunc( sqlite3_context *pCtx, int nArg, sqlite3_value **apArg ){ } static void cume_distValueFunc(sqlite3_context *pCtx){ struct CallCount *p; p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p)); if( p && p->nTotal ){ double r = (double)(p->nStep) / (double)(p->nTotal); sqlite3_result_double(pCtx, r); } } /* ** Context object for ntile() window function. */ struct NtileCtx { i64 nTotal; /* Total rows in partition */ i64 nParam; /* Parameter passed to ntile(N) */ i64 iRow; /* Current row */ }; /* ** Implementation of ntile(). This assumes that the window frame has ** been coerced to: ** ** ROWS UNBOUNDED PRECEDING AND CURRENT ROW */ static void ntileStepFunc( sqlite3_context *pCtx, int nArg, sqlite3_value **apArg ){ struct NtileCtx *p; assert( nArg==2 ); p = (struct NtileCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p)); if( p ){ if( p->nTotal==0 ){ p->nParam = sqlite3_value_int64(apArg[0]); p->nTotal = sqlite3_value_int64(apArg[1]); if( p->nParam<=0 ){ sqlite3_result_error( pCtx, "argument of ntile must be a positive integer", -1 ); } } p->iRow++; } } static void ntileInvFunc( sqlite3_context *pCtx, int nArg, sqlite3_value **apArg ){ } static void ntileValueFunc(sqlite3_context *pCtx){ struct NtileCtx *p; p = (struct NtileCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p)); if( p && p->nParam>0 ){ int nSize = (p->nTotal / p->nParam); if( nSize==0 ){ sqlite3_result_int64(pCtx, p->iRow); }else{ i64 nLarge = p->nTotal - p->nParam*nSize; i64 iSmall = nLarge*(nSize+1); i64 iRow = p->iRow-1; assert( (nLarge*(nSize+1) + (p->nParam-nLarge)*nSize)==p->nTotal ); if( iRow<iSmall ){ sqlite3_result_int64(pCtx, 1 + iRow/(nSize+1)); }else{ sqlite3_result_int64(pCtx, 1 + nLarge + (iRow-iSmall)/nSize); } } } } /* ** Context object for last_value() window function. */ struct LastValueCtx { sqlite3_value *pVal; int nVal; }; /* ** Implementation of last_value(). */ static void last_valueStepFunc( sqlite3_context *pCtx, int nArg, sqlite3_value **apArg ){ struct LastValueCtx *p; p = (struct LastValueCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p)); if( p ){ sqlite3_value_free(p->pVal); p->pVal = sqlite3_value_dup(apArg[0]); if( p->pVal==0 ){ sqlite3_result_error_nomem(pCtx); }else{ p->nVal++; } } } static void last_valueInvFunc( sqlite3_context *pCtx, int nArg, sqlite3_value **apArg ){ struct LastValueCtx *p; p = (struct LastValueCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p)); if( ALWAYS(p) ){ p->nVal--; if( p->nVal==0 ){ sqlite3_value_free(p->pVal); p->pVal = 0; } } } static void last_valueValueFunc(sqlite3_context *pCtx){ struct LastValueCtx *p; p = (struct LastValueCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p)); if( p && p->pVal ){ sqlite3_result_value(pCtx, p->pVal); } } static void last_valueFinalizeFunc(sqlite3_context *pCtx){ struct LastValueCtx *p; p = (struct LastValueCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p)); if( p && p->pVal ){ sqlite3_result_value(pCtx, p->pVal); sqlite3_value_free(p->pVal); p->pVal = 0; } } /* ** No-op implementations of nth_value(), first_value(), lead() and lag(). ** These are all implemented inline using VDBE instructions. */ static void nth_valueStepFunc(sqlite3_context *pCtx, int n, sqlite3_value **a){} static void nth_valueInvFunc(sqlite3_context *pCtx, int n, sqlite3_value **ap){} static void nth_valueValueFunc(sqlite3_context *pCtx){} static void first_valueStepFunc(sqlite3_context *p, int n, sqlite3_value **ap){} static void first_valueInvFunc(sqlite3_context *p, int n, sqlite3_value **ap){} static void first_valueValueFunc(sqlite3_context *pCtx){} static void leadStepFunc(sqlite3_context *pCtx, int n, sqlite3_value **ap){} static void leadInvFunc(sqlite3_context *pCtx, int n, sqlite3_value **ap){} static void leadValueFunc(sqlite3_context *pCtx){} static void lagStepFunc(sqlite3_context *pCtx, int n, sqlite3_value **ap){} static void lagInvFunc(sqlite3_context *pCtx, int n, sqlite3_value **ap){} static void lagValueFunc(sqlite3_context *pCtx){} #define WINDOWFUNC(name,nArg,extra) { \ nArg, (SQLITE_UTF8|SQLITE_FUNC_WINDOW|extra), 0, 0, \ name ## StepFunc, name ## ValueFunc, name ## ValueFunc, \ name ## InvFunc, #name \ } #define WINDOWFUNCF(name,nArg,extra) { \ nArg, (SQLITE_UTF8|SQLITE_FUNC_WINDOW|extra), 0, 0, \ name ## StepFunc, name ## FinalizeFunc, name ## ValueFunc, \ name ## InvFunc, #name \ } /* ** Register those built-in window functions that are not also aggregates. */ void sqlite3WindowFunctions(void){ static FuncDef aWindowFuncs[] = { WINDOWFUNC(row_number, 0, 0), WINDOWFUNC(dense_rank, 0, 0), WINDOWFUNC(rank, 0, 0), WINDOWFUNC(percent_rank, 0, SQLITE_FUNC_WINDOW_SIZE), WINDOWFUNC(cume_dist, 0, SQLITE_FUNC_WINDOW_SIZE), WINDOWFUNC(ntile, 1, SQLITE_FUNC_WINDOW_SIZE), WINDOWFUNCF(last_value, 1, 0), WINDOWFUNC(nth_value, 2, 0), WINDOWFUNC(first_value, 1, 0), WINDOWFUNC(lead, 1, 0), WINDOWFUNC(lead, 2, 0), WINDOWFUNC(lead, 3, 0), WINDOWFUNC(lag, 1, 0), WINDOWFUNC(lag, 2, 0), WINDOWFUNC(lag, 3, 0), }; sqlite3InsertBuiltinFuncs(aWindowFuncs, ArraySize(aWindowFuncs)); } /* ** This function is called immediately after resolving the function name ** for a window function within a SELECT statement. Argument pList is a ** linked list of WINDOW definitions for the current SELECT statement. ** Argument pFunc is the function definition just resolved and pWin ** is the Window object representing the associated OVER clause. This ** function updates the contents of pWin as follows: ** ** * If the OVER clause refered to a named window (as in "max(x) OVER win"), ** search list pList for a matching WINDOW definition, and update pWin ** accordingly. If no such WINDOW clause can be found, leave an error ** in pParse. ** ** * If the function is a built-in window function that requires the ** window to be coerced (see "BUILT-IN WINDOW FUNCTIONS" at the top ** of this file), pWin is updated here. */ void sqlite3WindowUpdate( Parse *pParse, Window *pList, /* List of named windows for this SELECT */ Window *pWin, /* Window frame to update */ FuncDef *pFunc /* Window function definition */ ){ if( pWin->zName && pWin->eType==0 ){ Window *p; for(p=pList; p; p=p->pNextWin){ if( sqlite3StrICmp(p->zName, pWin->zName)==0 ) break; } if( p==0 ){ sqlite3ErrorMsg(pParse, "no such window: %s", pWin->zName); return; } pWin->pPartition = sqlite3ExprListDup(pParse->db, p->pPartition, 0); pWin->pOrderBy = sqlite3ExprListDup(pParse->db, p->pOrderBy, 0); pWin->pStart = sqlite3ExprDup(pParse->db, p->pStart, 0); pWin->pEnd = sqlite3ExprDup(pParse->db, p->pEnd, 0); pWin->eStart = p->eStart; pWin->eEnd = p->eEnd; pWin->eType = p->eType; } if( pFunc->funcFlags & SQLITE_FUNC_WINDOW ){ sqlite3 *db = pParse->db; if( pWin->pFilter ){ sqlite3ErrorMsg(pParse, "FILTER clause may only be used with aggregate window functions" ); }else if( pFunc->xSFunc==row_numberStepFunc || pFunc->xSFunc==ntileStepFunc ){ sqlite3ExprDelete(db, pWin->pStart); sqlite3ExprDelete(db, pWin->pEnd); pWin->pStart = pWin->pEnd = 0; pWin->eType = TK_ROWS; pWin->eStart = TK_UNBOUNDED; pWin->eEnd = TK_CURRENT; }else if( pFunc->xSFunc==dense_rankStepFunc || pFunc->xSFunc==rankStepFunc || pFunc->xSFunc==percent_rankStepFunc || pFunc->xSFunc==cume_distStepFunc ){ sqlite3ExprDelete(db, pWin->pStart); sqlite3ExprDelete(db, pWin->pEnd); pWin->pStart = pWin->pEnd = 0; pWin->eType = TK_RANGE; pWin->eStart = TK_UNBOUNDED; pWin->eEnd = TK_CURRENT; } } pWin->pFunc = pFunc; } /* ** Context object passed through sqlite3WalkExprList() to ** selectWindowRewriteExprCb() by selectWindowRewriteEList(). */ typedef struct WindowRewrite WindowRewrite; struct WindowRewrite { Window *pWin; ExprList *pSub; }; /* ** Callback function used by selectWindowRewriteEList(). If necessary, ** this function appends to the output expression-list and updates ** expression (*ppExpr) in place. */ static int selectWindowRewriteExprCb(Walker *pWalker, Expr *pExpr){ struct WindowRewrite *p = pWalker->u.pRewrite; Parse *pParse = pWalker->pParse; switch( pExpr->op ){ case TK_FUNCTION: if( pExpr->pWin==0 ){ break; }else{ Window *pWin; for(pWin=p->pWin; pWin; pWin=pWin->pNextWin){ if( pExpr->pWin==pWin ){ assert( pWin->pOwner==pExpr ); return WRC_Prune; } } } /* Fall through. */ case TK_AGG_FUNCTION: case TK_COLUMN: { Expr *pDup = sqlite3ExprDup(pParse->db, pExpr, 0); p->pSub = sqlite3ExprListAppend(pParse, p->pSub, pDup); if( p->pSub ){ assert( ExprHasProperty(pExpr, EP_Static)==0 ); ExprSetProperty(pExpr, EP_Static); sqlite3ExprDelete(pParse->db, pExpr); ExprClearProperty(pExpr, EP_Static); memset(pExpr, 0, sizeof(Expr)); pExpr->op = TK_COLUMN; pExpr->iColumn = p->pSub->nExpr-1; pExpr->iTable = p->pWin->iEphCsr; } break; } default: /* no-op */ break; } return WRC_Continue; } static int selectWindowRewriteSelectCb(Walker *pWalker, Select *pSelect){ return WRC_Prune; } /* ** Iterate through each expression in expression-list pEList. For each: ** ** * TK_COLUMN, ** * aggregate function, or ** * window function with a Window object that is not a member of the ** linked list passed as the second argument (pWin) ** ** Append the node to output expression-list (*ppSub). And replace it ** with a TK_COLUMN that reads the (N-1)th element of table ** pWin->iEphCsr, where N is the number of elements in (*ppSub) after ** appending the new one. */ static void selectWindowRewriteEList( Parse *pParse, Window *pWin, ExprList *pEList, /* Rewrite expressions in this list */ ExprList **ppSub /* IN/OUT: Sub-select expression-list */ ){ Walker sWalker; WindowRewrite sRewrite; memset(&sWalker, 0, sizeof(Walker)); memset(&sRewrite, 0, sizeof(WindowRewrite)); sRewrite.pSub = *ppSub; sRewrite.pWin = pWin; sWalker.pParse = pParse; sWalker.xExprCallback = selectWindowRewriteExprCb; sWalker.xSelectCallback = selectWindowRewriteSelectCb; sWalker.u.pRewrite = &sRewrite; (void)sqlite3WalkExprList(&sWalker, pEList); *ppSub = sRewrite.pSub; } /* ** Append a copy of each expression in expression-list pAppend to ** expression list pList. Return a pointer to the result list. */ static ExprList *exprListAppendList( Parse *pParse, /* Parsing context */ ExprList *pList, /* List to which to append. Might be NULL */ ExprList *pAppend /* List of values to append. Might be NULL */ ){ if( pAppend ){ int i; int nInit = pList ? pList->nExpr : 0; for(i=0; i<pAppend->nExpr; i++){ Expr *pDup = sqlite3ExprDup(pParse->db, pAppend->a[i].pExpr, 0); pList = sqlite3ExprListAppend(pParse, pList, pDup); if( pList ) pList->a[nInit+i].sortOrder = pAppend->a[i].sortOrder; } } return pList; } /* ** If the SELECT statement passed as the second argument does not invoke ** any SQL window functions, this function is a no-op. Otherwise, it ** rewrites the SELECT statement so that window function xStep functions ** are invoked in the correct order as described under "SELECT REWRITING" ** at the top of this file. */ int sqlite3WindowRewrite(Parse *pParse, Select *p){ int rc = SQLITE_OK; if( p->pWin ){ Vdbe *v = sqlite3GetVdbe(pParse); sqlite3 *db = pParse->db; Select *pSub = 0; /* The subquery */ SrcList *pSrc = p->pSrc; Expr *pWhere = p->pWhere; ExprList *pGroupBy = p->pGroupBy; Expr *pHaving = p->pHaving; ExprList *pSort = 0; ExprList *pSublist = 0; /* Expression list for sub-query */ Window *pMWin = p->pWin; /* Master window object */ Window *pWin; /* Window object iterator */ p->pSrc = 0; p->pWhere = 0; p->pGroupBy = 0; p->pHaving = 0; /* Create the ORDER BY clause for the sub-select. This is the concatenation ** of the window PARTITION and ORDER BY clauses. Then, if this makes it ** redundant, remove the ORDER BY from the parent SELECT. */ pSort = sqlite3ExprListDup(db, pMWin->pPartition, 0); pSort = exprListAppendList(pParse, pSort, pMWin->pOrderBy); if( pSort && p->pOrderBy ){ if( sqlite3ExprListCompare(pSort, p->pOrderBy, -1)==0 ){ sqlite3ExprListDelete(db, p->pOrderBy); p->pOrderBy = 0; } } /* Assign a cursor number for the ephemeral table used to buffer rows. ** The OpenEphemeral instruction is coded later, after it is known how ** many columns the table will have. */ pMWin->iEphCsr = pParse->nTab++; selectWindowRewriteEList(pParse, pMWin, p->pEList, &pSublist); selectWindowRewriteEList(pParse, pMWin, p->pOrderBy, &pSublist); pMWin->nBufferCol = (pSublist ? pSublist->nExpr : 0); /* Append the PARTITION BY and ORDER BY expressions to the to the ** sub-select expression list. They are required to figure out where ** boundaries for partitions and sets of peer rows lie. */ pSublist = exprListAppendList(pParse, pSublist, pMWin->pPartition); pSublist = exprListAppendList(pParse, pSublist, pMWin->pOrderBy); /* Append the arguments passed to each window function to the ** sub-select expression list. Also allocate two registers for each ** window function - one for the accumulator, another for interim ** results. */ for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ pWin->iArgCol = (pSublist ? pSublist->nExpr : 0); pSublist = exprListAppendList(pParse, pSublist, pWin->pOwner->x.pList); if( pWin->pFilter ){ Expr *pFilter = sqlite3ExprDup(db, pWin->pFilter, 0); pSublist = sqlite3ExprListAppend(pParse, pSublist, pFilter); } pWin->regAccum = ++pParse->nMem; pWin->regResult = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regAccum); } /* If there is no ORDER BY or PARTITION BY clause, and the window ** function accepts zero arguments, and there are no other columns ** selected (e.g. "SELECT row_number() OVER () FROM t1"), it is possible ** that pSublist is still NULL here. Add a constant expression here to ** keep everything legal in this case. */ if( pSublist==0 ){ pSublist = sqlite3ExprListAppend(pParse, 0, sqlite3ExprAlloc(db, TK_INTEGER, &sqlite3IntTokens[0], 0) ); } pSub = sqlite3SelectNew( pParse, pSublist, pSrc, pWhere, pGroupBy, pHaving, pSort, 0, 0 ); p->pSrc = sqlite3SrcListAppend(db, 0, 0, 0); assert( p->pSrc || db->mallocFailed ); if( p->pSrc ){ p->pSrc->a[0].pSelect = pSub; sqlite3SrcListAssignCursors(pParse, p->pSrc); if( sqlite3ExpandSubquery(pParse, &p->pSrc->a[0]) ){ rc = SQLITE_NOMEM; }else{ pSub->selFlags |= SF_Expanded; p->selFlags &= ~SF_Aggregate; sqlite3SelectPrep(pParse, pSub, 0); } sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pMWin->iEphCsr, pSublist->nExpr); }else{ sqlite3SelectDelete(db, pSub); } if( db->mallocFailed ) rc = SQLITE_NOMEM; } return rc; } /* ** Free the Window object passed as the second argument. */ void sqlite3WindowDelete(sqlite3 *db, Window *p){ if( p ){ sqlite3ExprDelete(db, p->pFilter); sqlite3ExprListDelete(db, p->pPartition); sqlite3ExprListDelete(db, p->pOrderBy); sqlite3ExprDelete(db, p->pEnd); sqlite3ExprDelete(db, p->pStart); sqlite3DbFree(db, p->zName); sqlite3DbFree(db, p); } } /* ** Free the linked list of Window objects starting at the second argument. */ void sqlite3WindowListDelete(sqlite3 *db, Window *p){ while( p ){ Window *pNext = p->pNextWin; sqlite3WindowDelete(db, p); p = pNext; } } /* ** Allocate and return a new Window object. */ Window *sqlite3WindowAlloc( Parse *pParse, int eType, int eStart, Expr *pStart, int eEnd, Expr *pEnd ){ Window *pWin = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window)); if( pWin ){ assert( eType ); pWin->eType = eType; pWin->eStart = eStart; pWin->eEnd = eEnd; pWin->pEnd = pEnd; pWin->pStart = pStart; }else{ sqlite3ExprDelete(pParse->db, pEnd); sqlite3ExprDelete(pParse->db, pStart); } return pWin; } /* ** Attach window object pWin to expression p. */ void sqlite3WindowAttach(Parse *pParse, Expr *p, Window *pWin){ if( p ){ p->pWin = pWin; if( pWin ) pWin->pOwner = p; }else{ sqlite3WindowDelete(pParse->db, pWin); } } /* ** Return 0 if the two window objects are identical, or non-zero otherwise. ** Identical window objects can be processed in a single scan. */ int sqlite3WindowCompare(Parse *pParse, Window *p1, Window *p2){ if( p1->eType!=p2->eType ) return 1; if( p1->eStart!=p2->eStart ) return 1; if( p1->eEnd!=p2->eEnd ) return 1; if( sqlite3ExprCompare(pParse, p1->pStart, p2->pStart, -1) ) return 1; if( sqlite3ExprCompare(pParse, p1->pEnd, p2->pEnd, -1) ) return 1; if( sqlite3ExprListCompare(p1->pPartition, p2->pPartition, -1) ) return 1; if( sqlite3ExprListCompare(p1->pOrderBy, p2->pOrderBy, -1) ) return 1; return 0; } /* ** This is called by code in select.c before it calls sqlite3WhereBegin() ** to begin iterating through the sub-query results. It is used to allocate ** and initialize registers and cursors used by sqlite3WindowCodeStep(). */ void sqlite3WindowCodeInit(Parse *pParse, Window *pMWin){ Window *pWin; Vdbe *v = sqlite3GetVdbe(pParse); int nPart = (pMWin->pPartition ? pMWin->pPartition->nExpr : 0); nPart += (pMWin->pOrderBy ? pMWin->pOrderBy->nExpr : 0); if( nPart ){ pMWin->regPart = pParse->nMem+1; pParse->nMem += nPart; sqlite3VdbeAddOp3(v, OP_Null, 0, pMWin->regPart, pMWin->regPart+nPart-1); } for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ FuncDef *p = pWin->pFunc; if( (p->funcFlags & SQLITE_FUNC_MINMAX) && pWin->eStart!=TK_UNBOUNDED ){ /* The inline versions of min() and max() require a single ephemeral ** table and 3 registers. The registers are used as follows: ** ** regApp+0: slot to copy min()/max() argument to for MakeRecord ** regApp+1: integer value used to ensure keys are unique ** regApp+2: output of MakeRecord */ ExprList *pList = pWin->pOwner->x.pList; KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pList, 0, 0); pWin->csrApp = pParse->nTab++; pWin->regApp = pParse->nMem+1; pParse->nMem += 3; if( pKeyInfo && pWin->pFunc->zName[1]=='i' ){ assert( pKeyInfo->aSortOrder[0]==0 ); pKeyInfo->aSortOrder[0] = 1; } sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pWin->csrApp, 2); sqlite3VdbeAppendP4(v, pKeyInfo, P4_KEYINFO); sqlite3VdbeAddOp2(v, OP_Integer, 0, pWin->regApp+1); } else if( p->xSFunc==nth_valueStepFunc || p->xSFunc==first_valueStepFunc ){ /* Allocate two registers at pWin->regApp. These will be used to ** store the start and end index of the current frame. */ assert( pMWin->iEphCsr ); pWin->regApp = pParse->nMem+1; pWin->csrApp = pParse->nTab++; pParse->nMem += 2; sqlite3VdbeAddOp2(v, OP_OpenDup, pWin->csrApp, pMWin->iEphCsr); } else if( p->xSFunc==leadStepFunc || p->xSFunc==lagStepFunc ){ assert( pMWin->iEphCsr ); pWin->csrApp = pParse->nTab++; sqlite3VdbeAddOp2(v, OP_OpenDup, pWin->csrApp, pMWin->iEphCsr); } } } /* ** A "PRECEDING <expr>" (bEnd==0) or "FOLLOWING <expr>" (bEnd==1) has just ** been evaluated and the result left in register reg. This function generates ** VM code to check that the value is a non-negative integer and throws ** an exception if it is not. */ static void windowCheckFrameValue(Parse *pParse, int reg, int bEnd){ static const char *azErr[] = { "frame starting offset must be a non-negative integer", "frame ending offset must be a non-negative integer" }; Vdbe *v = sqlite3GetVdbe(pParse); int regZero = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp2(v, OP_Integer, 0, regZero); sqlite3VdbeAddOp2(v, OP_MustBeInt, reg, sqlite3VdbeCurrentAddr(v)+2); sqlite3VdbeAddOp3(v, OP_Ge, regZero, sqlite3VdbeCurrentAddr(v)+2, reg); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_ERROR, OE_Abort); sqlite3VdbeAppendP4(v, (void*)azErr[bEnd], P4_STATIC); sqlite3ReleaseTempReg(pParse, regZero); } /* ** Return the number of arguments passed to the window-function associated ** with the object passed as the only argument to this function. */ static int windowArgCount(Window *pWin){ ExprList *pList = pWin->pOwner->x.pList; return (pList ? pList->nExpr : 0); } /* ** Generate VM code to invoke either xStep() (if bInverse is 0) or ** xInverse (if bInverse is non-zero) for each window function in the ** linked list starting at pMWin. Or, for built-in window functions ** that do not use the standard function API, generate the required ** inline VM code. ** ** If argument csr is greater than or equal to 0, then argument reg is ** the first register in an array of registers guaranteed to be large ** enough to hold the array of arguments for each function. In this case ** the arguments are extracted from the current row of csr into the ** array of registers before invoking OP_AggStep. ** ** Or, if csr is less than zero, then the array of registers at reg is ** already populated with all columns from the current row of the sub-query. ** ** If argument regPartSize is non-zero, then it is a register containing the ** number of rows in the current partition. */ static void windowAggStep( Parse *pParse, Window *pMWin, /* Linked list of window functions */ int csr, /* Read arguments from this cursor */ int bInverse, /* True to invoke xInverse instead of xStep */ int reg, /* Array of registers */ int regPartSize /* Register containing size of partition */ ){ Vdbe *v = sqlite3GetVdbe(pParse); Window *pWin; for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ int flags = pWin->pFunc->funcFlags; int regArg; int nArg = windowArgCount(pWin); if( csr>=0 ){ int i; for(i=0; i<nArg; i++){ sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol+i, reg+i); } regArg = reg; if( flags & SQLITE_FUNC_WINDOW_SIZE ){ if( nArg==0 ){ regArg = regPartSize; }else{ sqlite3VdbeAddOp2(v, OP_SCopy, regPartSize, reg+nArg); } nArg++; } }else{ assert( !(flags & SQLITE_FUNC_WINDOW_SIZE) ); regArg = reg + pWin->iArgCol; } if( (pWin->pFunc->funcFlags & SQLITE_FUNC_MINMAX) && pWin->eStart!=TK_UNBOUNDED ){ if( bInverse==0 ){ sqlite3VdbeAddOp2(v, OP_AddImm, pWin->regApp+1, 1); sqlite3VdbeAddOp2(v, OP_SCopy, regArg, pWin->regApp); sqlite3VdbeAddOp3(v, OP_MakeRecord, pWin->regApp, 2, pWin->regApp+2); sqlite3VdbeAddOp2(v, OP_IdxInsert, pWin->csrApp, pWin->regApp+2); }else{ sqlite3VdbeAddOp4Int(v, OP_SeekGE, pWin->csrApp, 0, regArg, 1); VdbeCoverage(v); sqlite3VdbeAddOp1(v, OP_Delete, pWin->csrApp); sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2); } }else if( pWin->regApp ){ assert( pWin->pFunc->xSFunc==nth_valueStepFunc || pWin->pFunc->xSFunc==first_valueStepFunc ); assert( bInverse==0 || bInverse==1 ); sqlite3VdbeAddOp2(v, OP_AddImm, pWin->regApp+1-bInverse, 1); }else if( pWin->pFunc->xSFunc==leadStepFunc || pWin->pFunc->xSFunc==lagStepFunc ){ /* no-op */ }else{ int addrIf = 0; if( pWin->pFilter ){ int regTmp; assert( nArg==pWin->pOwner->x.pList->nExpr ); if( csr>0 ){ regTmp = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol+nArg,regTmp); }else{ regTmp = regArg + nArg; } addrIf = sqlite3VdbeAddOp3(v, OP_IfNot, regTmp, 0, 1); VdbeCoverage(v); if( csr>0 ){ sqlite3ReleaseTempReg(pParse, regTmp); } } if( pWin->pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){ CollSeq *pColl; pColl = sqlite3ExprNNCollSeq(pParse, pWin->pOwner->x.pList->a[0].pExpr); sqlite3VdbeAddOp4(v, OP_CollSeq, 0,0,0, (const char*)pColl, P4_COLLSEQ); } sqlite3VdbeAddOp3(v, OP_AggStep0, bInverse, regArg, pWin->regAccum); sqlite3VdbeAppendP4(v, pWin->pFunc, P4_FUNCDEF); sqlite3VdbeChangeP5(v, (u8)nArg); if( addrIf ) sqlite3VdbeJumpHere(v, addrIf); } } } /* ** Generate VM code to invoke either xValue() (bFinal==0) or xFinalize() ** (bFinal==1) for each window function in the linked list starting at ** pMWin. Or, for built-in window-functions that do not use the standard ** API, generate the equivalent VM code. */ static void windowAggFinal(Parse *pParse, Window *pMWin, int bFinal){ Vdbe *v = sqlite3GetVdbe(pParse); Window *pWin; for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ if( (pWin->pFunc->funcFlags & SQLITE_FUNC_MINMAX) && pWin->eStart!=TK_UNBOUNDED ){ sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regResult); sqlite3VdbeAddOp1(v, OP_Last, pWin->csrApp); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_Column, pWin->csrApp, 0, pWin->regResult); sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2); if( bFinal ){ sqlite3VdbeAddOp1(v, OP_ResetSorter, pWin->csrApp); } }else if( pWin->regApp ){ }else{ if( bFinal==0 ){ sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regResult); } sqlite3VdbeAddOp2(v, OP_AggFinal, pWin->regAccum, windowArgCount(pWin)); sqlite3VdbeAppendP4(v, pWin->pFunc, P4_FUNCDEF); if( bFinal ){ sqlite3VdbeAddOp2(v, OP_Copy, pWin->regAccum, pWin->regResult); sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regAccum); }else{ sqlite3VdbeChangeP3(v, -1, pWin->regResult); } } } } /* ** This function generates VM code to invoke the sub-routine at address ** lblFlushPart once for each partition with the entire partition cached in ** the Window.iEphCsr temp table. */ static void windowPartitionCache( Parse *pParse, Select *p, /* The rewritten SELECT statement */ WhereInfo *pWInfo, /* WhereInfo to call WhereEnd() on */ int regFlushPart, /* Register to use with Gosub lblFlushPart */ int lblFlushPart, /* Subroutine to Gosub to */ int *pRegSize /* OUT: Register containing partition size */ ){ Window *pMWin = p->pWin; Vdbe *v = sqlite3GetVdbe(pParse); int iSubCsr = p->pSrc->a[0].iCursor; int nSub = p->pSrc->a[0].pTab->nCol; int k; int reg = pParse->nMem+1; int regRecord = reg+nSub; int regRowid = regRecord+1; *pRegSize = regRowid; pParse->nMem += nSub + 2; /* Martial the row returned by the sub-select into an array of ** registers. */ for(k=0; k<nSub; k++){ sqlite3VdbeAddOp3(v, OP_Column, iSubCsr, k, reg+k); } sqlite3VdbeAddOp3(v, OP_MakeRecord, reg, nSub, regRecord); /* Check if this is the start of a new partition. If so, call the ** flush_partition sub-routine. */ if( pMWin->pPartition ){ int addr; ExprList *pPart = pMWin->pPartition; int nPart = pPart->nExpr; int regNewPart = reg + pMWin->nBufferCol; KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pPart, 0, 0); addr = sqlite3VdbeAddOp3(v, OP_Compare, regNewPart, pMWin->regPart,nPart); sqlite3VdbeAppendP4(v, (void*)pKeyInfo, P4_KEYINFO); sqlite3VdbeAddOp3(v, OP_Jump, addr+2, addr+4, addr+2); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_Copy, regNewPart, pMWin->regPart, nPart-1); sqlite3VdbeAddOp2(v, OP_Gosub, regFlushPart, lblFlushPart); } /* Buffer the current row in the ephemeral table. */ sqlite3VdbeAddOp2(v, OP_NewRowid, pMWin->iEphCsr, regRowid); sqlite3VdbeAddOp3(v, OP_Insert, pMWin->iEphCsr, regRecord, regRowid); /* End of the input loop */ sqlite3WhereEnd(pWInfo); /* Invoke "flush_partition" to deal with the final (or only) partition */ sqlite3VdbeAddOp2(v, OP_Gosub, regFlushPart, lblFlushPart); } /* ** Invoke the sub-routine at regGosub (generated by code in select.c) to ** return the current row of Window.iEphCsr. If all window functions are ** aggregate window functions that use the standard API, a single ** OP_Gosub instruction is all that this routine generates. Extra VM code ** for per-row processing is only generated for the following built-in window ** functions: ** ** nth_value() ** first_value() ** lag() ** lead() */ static void windowReturnOneRow( Parse *pParse, Window *pMWin, int regGosub, int addrGosub ){ Vdbe *v = sqlite3GetVdbe(pParse); Window *pWin; for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ FuncDef *pFunc = pWin->pFunc; if( pFunc->xSFunc==nth_valueStepFunc || pFunc->xSFunc==first_valueStepFunc ){ int csr = pWin->csrApp; int lbl = sqlite3VdbeMakeLabel(v); int tmpReg = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regResult); if( pFunc->xSFunc==nth_valueStepFunc ){ sqlite3VdbeAddOp3(v, OP_Column, pMWin->iEphCsr, pWin->iArgCol+1,tmpReg); }else{ sqlite3VdbeAddOp2(v, OP_Integer, 1, tmpReg); } sqlite3VdbeAddOp3(v, OP_Add, tmpReg, pWin->regApp, tmpReg); sqlite3VdbeAddOp3(v, OP_Gt, pWin->regApp+1, lbl, tmpReg); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_SeekRowid, csr, lbl, tmpReg); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol, pWin->regResult); sqlite3VdbeResolveLabel(v, lbl); sqlite3ReleaseTempReg(pParse, tmpReg); } else if( pFunc->xSFunc==leadStepFunc || pFunc->xSFunc==lagStepFunc ){ int nArg = pWin->pOwner->x.pList->nExpr; int iEph = pMWin->iEphCsr; int csr = pWin->csrApp; int lbl = sqlite3VdbeMakeLabel(v); int tmpReg = sqlite3GetTempReg(pParse); if( nArg<3 ){ sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regResult); }else{ sqlite3VdbeAddOp3(v, OP_Column, iEph, pWin->iArgCol+2, pWin->regResult); } sqlite3VdbeAddOp2(v, OP_Rowid, iEph, tmpReg); if( nArg<2 ){ int val = (pFunc->xSFunc==leadStepFunc ? 1 : -1); sqlite3VdbeAddOp2(v, OP_AddImm, tmpReg, val); }else{ int op = (pFunc->xSFunc==leadStepFunc ? OP_Add : OP_Subtract); int tmpReg2 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_Column, iEph, pWin->iArgCol+1, tmpReg2); sqlite3VdbeAddOp3(v, op, tmpReg2, tmpReg, tmpReg); sqlite3ReleaseTempReg(pParse, tmpReg2); } sqlite3VdbeAddOp3(v, OP_SeekRowid, csr, lbl, tmpReg); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol, pWin->regResult); sqlite3VdbeResolveLabel(v, lbl); sqlite3ReleaseTempReg(pParse, tmpReg); } } sqlite3VdbeAddOp2(v, OP_Gosub, regGosub, addrGosub); } /* ** Invoke the code generated by windowReturnOneRow() and, optionally, the ** xInverse() function for each window function, for one or more rows ** from the Window.iEphCsr temp table. This routine generates VM code ** similar to: ** ** while( regCtr>0 ){ ** regCtr--; ** windowReturnOneRow() ** if( bInverse ){ ** AggStep (xInverse) ** } ** Next (Window.iEphCsr) ** } */ static void windowReturnRows( Parse *pParse, Window *pMWin, /* List of window functions */ int regCtr, /* Register containing number of rows */ int regGosub, /* Register for Gosub addrGosub */ int addrGosub, /* Address of sub-routine for ReturnOneRow */ int regInvArg, /* Array of registers for xInverse args */ int regInvSize /* Register containing size of partition */ ){ int addr; Vdbe *v = sqlite3GetVdbe(pParse); windowAggFinal(pParse, pMWin, 0); addr = sqlite3VdbeAddOp3(v, OP_IfPos, regCtr, sqlite3VdbeCurrentAddr(v)+2 ,1); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Goto, 0, 0); windowReturnOneRow(pParse, pMWin, regGosub, addrGosub); if( regInvArg ){ windowAggStep(pParse, pMWin, pMWin->iEphCsr, 1, regInvArg, regInvSize); } sqlite3VdbeAddOp2(v, OP_Next, pMWin->iEphCsr, addr); VdbeCoverage(v); sqlite3VdbeJumpHere(v, addr+1); /* The OP_Goto */ } /* ** Generate code to set the accumulator register for each window function ** in the linked list passed as the second argument to NULL. And perform ** any equivalent initialization required by any built-in window functions ** in the list. */ static int windowInitAccum(Parse *pParse, Window *pMWin){ Vdbe *v = sqlite3GetVdbe(pParse); int regArg; int nArg = 0; Window *pWin; for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ FuncDef *pFunc = pWin->pFunc; sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regAccum); nArg = MAX(nArg, windowArgCount(pWin)); if( pFunc->xSFunc==nth_valueStepFunc || pFunc->xSFunc==first_valueStepFunc ){ sqlite3VdbeAddOp2(v, OP_Integer, 0, pWin->regApp); sqlite3VdbeAddOp2(v, OP_Integer, 0, pWin->regApp+1); } if( (pFunc->funcFlags & SQLITE_FUNC_MINMAX) && pWin->csrApp ){ assert( pWin->eStart!=TK_UNBOUNDED ); sqlite3VdbeAddOp1(v, OP_ResetSorter, pWin->csrApp); sqlite3VdbeAddOp2(v, OP_Integer, 0, pWin->regApp+1); } } regArg = pParse->nMem+1; pParse->nMem += nArg; return regArg; } /* ** This function does the work of sqlite3WindowCodeStep() for all "ROWS" ** window frame types except for "BETWEEN UNBOUNDED PRECEDING AND CURRENT ** ROW". Pseudo-code for each follows. ** ** ROWS BETWEEN <expr1> PRECEDING AND <expr2> FOLLOWING ** ** ... ** if( new partition ){ ** Gosub flush_partition ** } ** Insert (record in eph-table) ** sqlite3WhereEnd() ** Gosub flush_partition ** ** flush_partition: ** Once { ** OpenDup (iEphCsr -> csrStart) ** OpenDup (iEphCsr -> csrEnd) ** } ** regStart = <expr1> // PRECEDING expression ** regEnd = <expr2> // FOLLOWING expression ** if( regStart<0 || regEnd<0 ){ error! } ** Rewind (csr,csrStart,csrEnd) // if EOF goto flush_partition_done ** Next(csrEnd) // if EOF skip Aggstep ** Aggstep (csrEnd) ** if( (regEnd--)<=0 ){ ** AggFinal (xValue) ** Gosub addrGosub ** Next(csr) // if EOF goto flush_partition_done ** if( (regStart--)<=0 ){ ** AggStep (csrStart, xInverse) ** Next(csrStart) ** } ** } ** flush_partition_done: ** ResetSorter (csr) ** Return ** ** ROWS BETWEEN <expr> PRECEDING AND CURRENT ROW ** ROWS BETWEEN CURRENT ROW AND <expr> FOLLOWING ** ROWS BETWEEN UNBOUNDED PRECEDING AND <expr> FOLLOWING ** ** These are similar to the above. For "CURRENT ROW", intialize the ** register to 0. For "UNBOUNDED PRECEDING" to infinity. ** ** ROWS BETWEEN <expr> PRECEDING AND UNBOUNDED FOLLOWING ** ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING ** ** Rewind (csr,csrStart,csrEnd) // if EOF goto flush_partition_done ** while( 1 ){ ** Next(csrEnd) // Exit while(1) at EOF ** Aggstep (csrEnd) ** } ** while( 1 ){ ** AggFinal (xValue) ** Gosub addrGosub ** Next(csr) // if EOF goto flush_partition_done ** if( (regStart--)<=0 ){ ** AggStep (csrStart, xInverse) ** Next(csrStart) ** } ** } ** ** For the "CURRENT ROW AND UNBOUNDED FOLLOWING" case, the final if() ** condition is always true (as if regStart were initialized to 0). ** ** RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING ** ** This is the only RANGE case handled by this routine. It modifies the ** second while( 1 ) loop in "ROWS BETWEEN CURRENT ... UNBOUNDED..." to ** be: ** ** while( 1 ){ ** AggFinal (xValue) ** while( 1 ){ ** regPeer++ ** Gosub addrGosub ** Next(csr) // if EOF goto flush_partition_done ** if( new peer ) break; ** } ** while( (regPeer--)>0 ){ ** AggStep (csrStart, xInverse) ** Next(csrStart) ** } ** } ** ** ROWS BETWEEN <expr> FOLLOWING AND <expr> FOLLOWING ** ** regEnd = regEnd - regStart ** Rewind (csr,csrStart,csrEnd) // if EOF goto flush_partition_done ** Aggstep (csrEnd) ** Next(csrEnd) // if EOF fall-through ** if( (regEnd--)<=0 ){ ** if( (regStart--)<=0 ){ ** AggFinal (xValue) ** Gosub addrGosub ** Next(csr) // if EOF goto flush_partition_done ** } ** AggStep (csrStart, xInverse) ** Next (csrStart) ** } ** ** ROWS BETWEEN <expr> PRECEDING AND <expr> PRECEDING ** ** Replace the bit after "Rewind" in the above with: ** ** if( (regEnd--)<=0 ){ ** AggStep (csrEnd) ** Next (csrEnd) ** } ** AggFinal (xValue) ** Gosub addrGosub ** Next(csr) // if EOF goto flush_partition_done ** if( (regStart--)<=0 ){ ** AggStep (csr2, xInverse) ** Next (csr2) ** } ** */ static void windowCodeRowExprStep( Parse *pParse, Select *p, WhereInfo *pWInfo, int regGosub, int addrGosub ){ Window *pMWin = p->pWin; Vdbe *v = sqlite3GetVdbe(pParse); int regFlushPart; /* Register for "Gosub flush_partition" */ int lblFlushPart; /* Label for "Gosub flush_partition" */ int lblFlushDone; /* Label for "Gosub flush_partition_done" */ int regArg; int addr; int csrStart = pParse->nTab++; int csrEnd = pParse->nTab++; int regStart; /* Value of <expr> PRECEDING */ int regEnd; /* Value of <expr> FOLLOWING */ int addrGoto; int addrTop; int addrIfPos1; int addrIfPos2; int regSize = 0; assert( pMWin->eStart==TK_PRECEDING || pMWin->eStart==TK_CURRENT || pMWin->eStart==TK_FOLLOWING || pMWin->eStart==TK_UNBOUNDED ); assert( pMWin->eEnd==TK_FOLLOWING || pMWin->eEnd==TK_CURRENT || pMWin->eEnd==TK_UNBOUNDED || pMWin->eEnd==TK_PRECEDING ); /* Allocate register and label for the "flush_partition" sub-routine. */ regFlushPart = ++pParse->nMem; lblFlushPart = sqlite3VdbeMakeLabel(v); lblFlushDone = sqlite3VdbeMakeLabel(v); regStart = ++pParse->nMem; regEnd = ++pParse->nMem; windowPartitionCache(pParse, p, pWInfo, regFlushPart, lblFlushPart, ®Size); addrGoto = sqlite3VdbeAddOp0(v, OP_Goto); /* Start of "flush_partition" */ sqlite3VdbeResolveLabel(v, lblFlushPart); sqlite3VdbeAddOp2(v, OP_Once, 0, sqlite3VdbeCurrentAddr(v)+3); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_OpenDup, csrStart, pMWin->iEphCsr); sqlite3VdbeAddOp2(v, OP_OpenDup, csrEnd, pMWin->iEphCsr); /* If either regStart or regEnd are not non-negative integers, throw ** an exception. */ if( pMWin->pStart ){ sqlite3ExprCode(pParse, pMWin->pStart, regStart); windowCheckFrameValue(pParse, regStart, 0); } if( pMWin->pEnd ){ sqlite3ExprCode(pParse, pMWin->pEnd, regEnd); windowCheckFrameValue(pParse, regEnd, 1); } /* If this is "ROWS <expr1> FOLLOWING AND ROWS <expr2> FOLLOWING", do: ** ** if( regEnd<regStart ){ ** // The frame always consists of 0 rows ** regStart = regSize; ** } ** regEnd = regEnd - regStart; */ if( pMWin->pEnd && pMWin->pStart && pMWin->eStart==TK_FOLLOWING ){ assert( pMWin->eEnd==TK_FOLLOWING ); sqlite3VdbeAddOp3(v, OP_Ge, regStart, sqlite3VdbeCurrentAddr(v)+2, regEnd); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Copy, regSize, regStart); sqlite3VdbeAddOp3(v, OP_Subtract, regStart, regEnd, regEnd); } if( pMWin->pEnd && pMWin->pStart && pMWin->eEnd==TK_PRECEDING ){ assert( pMWin->eStart==TK_PRECEDING ); sqlite3VdbeAddOp3(v, OP_Le, regStart, sqlite3VdbeCurrentAddr(v)+3, regEnd); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Copy, regSize, regStart); sqlite3VdbeAddOp2(v, OP_Copy, regSize, regEnd); } /* Initialize the accumulator register for each window function to NULL */ regArg = windowInitAccum(pParse, pMWin); sqlite3VdbeAddOp2(v, OP_Rewind, pMWin->iEphCsr, lblFlushDone); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Rewind, csrStart, lblFlushDone); VdbeCoverageNeverTaken(v); sqlite3VdbeChangeP5(v, 1); sqlite3VdbeAddOp2(v, OP_Rewind, csrEnd, lblFlushDone); VdbeCoverageNeverTaken(v); sqlite3VdbeChangeP5(v, 1); /* Invoke AggStep function for each window function using the row that ** csrEnd currently points to. Or, if csrEnd is already at EOF, ** do nothing. */ addrTop = sqlite3VdbeCurrentAddr(v); if( pMWin->eEnd==TK_PRECEDING ){ addrIfPos1 = sqlite3VdbeAddOp3(v, OP_IfPos, regEnd, 0 , 1); VdbeCoverage(v); } sqlite3VdbeAddOp2(v, OP_Next, csrEnd, sqlite3VdbeCurrentAddr(v)+2); VdbeCoverage(v); addr = sqlite3VdbeAddOp0(v, OP_Goto); windowAggStep(pParse, pMWin, csrEnd, 0, regArg, regSize); if( pMWin->eEnd==TK_UNBOUNDED ){ sqlite3VdbeAddOp2(v, OP_Goto, 0, addrTop); sqlite3VdbeJumpHere(v, addr); addrTop = sqlite3VdbeCurrentAddr(v); }else{ sqlite3VdbeJumpHere(v, addr); if( pMWin->eEnd==TK_PRECEDING ){ sqlite3VdbeJumpHere(v, addrIfPos1); } } if( pMWin->eEnd==TK_FOLLOWING ){ addrIfPos1 = sqlite3VdbeAddOp3(v, OP_IfPos, regEnd, 0 , 1); VdbeCoverage(v); } if( pMWin->eStart==TK_FOLLOWING ){ addrIfPos2 = sqlite3VdbeAddOp3(v, OP_IfPos, regStart, 0 , 1); VdbeCoverage(v); } windowAggFinal(pParse, pMWin, 0); windowReturnOneRow(pParse, pMWin, regGosub, addrGosub); sqlite3VdbeAddOp2(v, OP_Next, pMWin->iEphCsr, sqlite3VdbeCurrentAddr(v)+2); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Goto, 0, lblFlushDone); if( pMWin->eStart==TK_FOLLOWING ){ sqlite3VdbeJumpHere(v, addrIfPos2); } if( pMWin->eStart==TK_CURRENT || pMWin->eStart==TK_PRECEDING || pMWin->eStart==TK_FOLLOWING ){ int addrJumpHere = 0; if( pMWin->eStart==TK_PRECEDING ){ addrJumpHere = sqlite3VdbeAddOp3(v, OP_IfPos, regStart, 0 , 1); VdbeCoverage(v); } sqlite3VdbeAddOp2(v, OP_Next, csrStart, sqlite3VdbeCurrentAddr(v)+1); VdbeCoverage(v); windowAggStep(pParse, pMWin, csrStart, 1, regArg, regSize); if( addrJumpHere ){ sqlite3VdbeJumpHere(v, addrJumpHere); } } if( pMWin->eEnd==TK_FOLLOWING ){ sqlite3VdbeJumpHere(v, addrIfPos1); } sqlite3VdbeAddOp2(v, OP_Goto, 0, addrTop); /* flush_partition_done: */ sqlite3VdbeResolveLabel(v, lblFlushDone); sqlite3VdbeAddOp1(v, OP_ResetSorter, pMWin->iEphCsr); sqlite3VdbeAddOp1(v, OP_Return, regFlushPart); /* Jump to here to skip over flush_partition */ sqlite3VdbeJumpHere(v, addrGoto); } /* ** This function does the work of sqlite3WindowCodeStep() for cases that ** would normally be handled by windowCodeDefaultStep() when there are ** one or more built-in window-functions that require the entire partition ** to be cached in a temp table before any rows can be returned. Additionally. ** "RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING" is always handled by ** this function. ** ** Pseudo-code corresponding to the VM code generated by this function ** for each type of window follows. ** ** RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ** ** flush_partition: ** Once { ** OpenDup (iEphCsr -> csrLead) ** } ** Integer ctr 0 ** foreach row (csrLead){ ** if( new peer ){ ** AggFinal (xValue) ** for(i=0; i<ctr; i++){ ** Gosub addrGosub ** Next iEphCsr ** } ** Integer ctr 0 ** } ** AggStep (csrLead) ** Incr ctr ** } ** ** AggFinal (xFinalize) ** for(i=0; i<ctr; i++){ ** Gosub addrGosub ** Next iEphCsr ** } ** ** ResetSorter (csr) ** Return ** ** ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ** ** As above, except that the "if( new peer )" branch is always taken. ** ** RANGE BETWEEN CURRENT ROW AND CURRENT ROW ** ** As above, except that each of the for() loops becomes: ** ** for(i=0; i<ctr; i++){ ** Gosub addrGosub ** AggStep (xInverse, iEphCsr) ** Next iEphCsr ** } ** ** RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ** ** flush_partition: ** Once { ** OpenDup (iEphCsr -> csrLead) ** } ** foreach row (csrLead) { ** AggStep (csrLead) ** } ** foreach row (iEphCsr) { ** Gosub addrGosub ** } ** ** RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING ** ** flush_partition: ** Once { ** OpenDup (iEphCsr -> csrLead) ** } ** foreach row (csrLead){ ** AggStep (csrLead) ** } ** Rewind (csrLead) ** Integer ctr 0 ** foreach row (csrLead){ ** if( new peer ){ ** AggFinal (xValue) ** for(i=0; i<ctr; i++){ ** Gosub addrGosub ** AggStep (xInverse, iEphCsr) ** Next iEphCsr ** } ** Integer ctr 0 ** } ** Incr ctr ** } ** ** AggFinal (xFinalize) ** for(i=0; i<ctr; i++){ ** Gosub addrGosub ** Next iEphCsr ** } ** ** ResetSorter (csr) ** Return */ static void windowCodeCacheStep( Parse *pParse, Select *p, WhereInfo *pWInfo, int regGosub, int addrGosub ){ Window *pMWin = p->pWin; Vdbe *v = sqlite3GetVdbe(pParse); int k; int addr; ExprList *pPart = pMWin->pPartition; ExprList *pOrderBy = pMWin->pOrderBy; int nPeer = pOrderBy ? pOrderBy->nExpr : 0; int regNewPeer; int addrGoto; /* Address of Goto used to jump flush_par.. */ int addrNext; /* Jump here for next iteration of loop */ int regFlushPart; int lblFlushPart; int csrLead; int regCtr; int regArg; /* Register array to martial function args */ int regSize; int lblEmpty; int bReverse = pMWin->pOrderBy && pMWin->eStart==TK_CURRENT && pMWin->eEnd==TK_UNBOUNDED; assert( (pMWin->eStart==TK_UNBOUNDED && pMWin->eEnd==TK_CURRENT) || (pMWin->eStart==TK_UNBOUNDED && pMWin->eEnd==TK_UNBOUNDED) || (pMWin->eStart==TK_CURRENT && pMWin->eEnd==TK_CURRENT) || (pMWin->eStart==TK_CURRENT && pMWin->eEnd==TK_UNBOUNDED) ); lblEmpty = sqlite3VdbeMakeLabel(v); regNewPeer = pParse->nMem+1; pParse->nMem += nPeer; /* Allocate register and label for the "flush_partition" sub-routine. */ regFlushPart = ++pParse->nMem; lblFlushPart = sqlite3VdbeMakeLabel(v); csrLead = pParse->nTab++; regCtr = ++pParse->nMem; windowPartitionCache(pParse, p, pWInfo, regFlushPart, lblFlushPart, ®Size); addrGoto = sqlite3VdbeAddOp0(v, OP_Goto); /* Start of "flush_partition" */ sqlite3VdbeResolveLabel(v, lblFlushPart); sqlite3VdbeAddOp2(v, OP_Once, 0, sqlite3VdbeCurrentAddr(v)+2); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_OpenDup, csrLead, pMWin->iEphCsr); /* Initialize the accumulator register for each window function to NULL */ regArg = windowInitAccum(pParse, pMWin); sqlite3VdbeAddOp2(v, OP_Integer, 0, regCtr); sqlite3VdbeAddOp2(v, OP_Rewind, csrLead, lblEmpty); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Rewind, pMWin->iEphCsr, lblEmpty); VdbeCoverageNeverTaken(v); if( bReverse ){ int addr = sqlite3VdbeCurrentAddr(v); windowAggStep(pParse, pMWin, csrLead, 0, regArg, regSize); sqlite3VdbeAddOp2(v, OP_Next, csrLead, addr); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Rewind, csrLead, lblEmpty); VdbeCoverageNeverTaken(v); } addrNext = sqlite3VdbeCurrentAddr(v); if( pOrderBy && (pMWin->eEnd==TK_CURRENT || pMWin->eStart==TK_CURRENT) ){ int bCurrent = (pMWin->eStart==TK_CURRENT); int addrJump = 0; /* Address of OP_Jump below */ if( pMWin->eType==TK_RANGE ){ int iOff = pMWin->nBufferCol + (pPart ? pPart->nExpr : 0); int regPeer = pMWin->regPart + (pPart ? pPart->nExpr : 0); KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pOrderBy, 0, 0); for(k=0; k<nPeer; k++){ sqlite3VdbeAddOp3(v, OP_Column, csrLead, iOff+k, regNewPeer+k); } addr = sqlite3VdbeAddOp3(v, OP_Compare, regNewPeer, regPeer, nPeer); sqlite3VdbeAppendP4(v, (void*)pKeyInfo, P4_KEYINFO); addrJump = sqlite3VdbeAddOp3(v, OP_Jump, addr+2, 0, addr+2); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_Copy, regNewPeer, regPeer, nPeer-1); } windowReturnRows(pParse, pMWin, regCtr, regGosub, addrGosub, (bCurrent ? regArg : 0), (bCurrent ? regSize : 0) ); if( addrJump ) sqlite3VdbeJumpHere(v, addrJump); } if( bReverse==0 ){ windowAggStep(pParse, pMWin, csrLead, 0, regArg, regSize); } sqlite3VdbeAddOp2(v, OP_AddImm, regCtr, 1); sqlite3VdbeAddOp2(v, OP_Next, csrLead, addrNext); VdbeCoverage(v); windowReturnRows(pParse, pMWin, regCtr, regGosub, addrGosub, 0, 0); sqlite3VdbeResolveLabel(v, lblEmpty); sqlite3VdbeAddOp1(v, OP_ResetSorter, pMWin->iEphCsr); sqlite3VdbeAddOp1(v, OP_Return, regFlushPart); /* Jump to here to skip over flush_partition */ sqlite3VdbeJumpHere(v, addrGoto); } /* ** RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ** ** ... ** if( new partition ){ ** AggFinal (xFinalize) ** Gosub addrGosub ** ResetSorter eph-table ** } ** else if( new peer ){ ** AggFinal (xValue) ** Gosub addrGosub ** ResetSorter eph-table ** } ** AggStep ** Insert (record into eph-table) ** sqlite3WhereEnd() ** AggFinal (xFinalize) ** Gosub addrGosub ** ** RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ** ** As above, except take no action for a "new peer". Invoke ** the sub-routine once only for each partition. ** ** RANGE BETWEEN CURRENT ROW AND CURRENT ROW ** ** As above, except that the "new peer" condition is handled in the ** same way as "new partition" (so there is no "else if" block). ** ** ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ** ** As above, except assume every row is a "new peer". */ static void windowCodeDefaultStep( Parse *pParse, Select *p, WhereInfo *pWInfo, int regGosub, int addrGosub ){ Window *pMWin = p->pWin; Vdbe *v = sqlite3GetVdbe(pParse); int k; int iSubCsr = p->pSrc->a[0].iCursor; int nSub = p->pSrc->a[0].pTab->nCol; int reg = pParse->nMem+1; int regRecord = reg+nSub; int regRowid = regRecord+1; int addr; ExprList *pPart = pMWin->pPartition; ExprList *pOrderBy = pMWin->pOrderBy; assert( pMWin->eType==TK_RANGE || (pMWin->eStart==TK_UNBOUNDED && pMWin->eEnd==TK_CURRENT) ); assert( (pMWin->eStart==TK_UNBOUNDED && pMWin->eEnd==TK_CURRENT) || (pMWin->eStart==TK_UNBOUNDED && pMWin->eEnd==TK_UNBOUNDED) || (pMWin->eStart==TK_CURRENT && pMWin->eEnd==TK_CURRENT) || (pMWin->eStart==TK_CURRENT && pMWin->eEnd==TK_UNBOUNDED && !pOrderBy) ); if( pMWin->eEnd==TK_UNBOUNDED ){ pOrderBy = 0; } pParse->nMem += nSub + 2; /* Martial the row returned by the sub-select into an array of ** registers. */ for(k=0; k<nSub; k++){ sqlite3VdbeAddOp3(v, OP_Column, iSubCsr, k, reg+k); } /* Check if this is the start of a new partition or peer group. */ if( pPart || pOrderBy ){ int nPart = (pPart ? pPart->nExpr : 0); int addrGoto = 0; int addrJump = 0; int nPeer = (pOrderBy ? pOrderBy->nExpr : 0); if( pPart ){ int regNewPart = reg + pMWin->nBufferCol; KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pPart, 0, 0); addr = sqlite3VdbeAddOp3(v, OP_Compare, regNewPart, pMWin->regPart,nPart); sqlite3VdbeAppendP4(v, (void*)pKeyInfo, P4_KEYINFO); addrJump = sqlite3VdbeAddOp3(v, OP_Jump, addr+2, 0, addr+2); VdbeCoverage(v); windowAggFinal(pParse, pMWin, 1); if( pOrderBy ){ addrGoto = sqlite3VdbeAddOp0(v, OP_Goto); } } if( pOrderBy ){ int regNewPeer = reg + pMWin->nBufferCol + nPart; int regPeer = pMWin->regPart + nPart; if( addrJump ) sqlite3VdbeJumpHere(v, addrJump); if( pMWin->eType==TK_RANGE ){ KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pOrderBy, 0, 0); addr = sqlite3VdbeAddOp3(v, OP_Compare, regNewPeer, regPeer, nPeer); sqlite3VdbeAppendP4(v, (void*)pKeyInfo, P4_KEYINFO); addrJump = sqlite3VdbeAddOp3(v, OP_Jump, addr+2, 0, addr+2); VdbeCoverage(v); }else{ addrJump = 0; } windowAggFinal(pParse, pMWin, pMWin->eStart==TK_CURRENT); if( addrGoto ) sqlite3VdbeJumpHere(v, addrGoto); } sqlite3VdbeAddOp2(v, OP_Rewind, pMWin->iEphCsr,sqlite3VdbeCurrentAddr(v)+3); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Gosub, regGosub, addrGosub); sqlite3VdbeAddOp2(v, OP_Next, pMWin->iEphCsr, sqlite3VdbeCurrentAddr(v)-1); VdbeCoverage(v); sqlite3VdbeAddOp1(v, OP_ResetSorter, pMWin->iEphCsr); sqlite3VdbeAddOp3( v, OP_Copy, reg+pMWin->nBufferCol, pMWin->regPart, nPart+nPeer-1 ); if( addrJump ) sqlite3VdbeJumpHere(v, addrJump); } /* Invoke step function for window functions */ windowAggStep(pParse, pMWin, -1, 0, reg, 0); /* Buffer the current row in the ephemeral table. */ if( pMWin->nBufferCol>0 ){ sqlite3VdbeAddOp3(v, OP_MakeRecord, reg, pMWin->nBufferCol, regRecord); }else{ sqlite3VdbeAddOp2(v, OP_Blob, 0, regRecord); sqlite3VdbeAppendP4(v, (void*)"", 0); } sqlite3VdbeAddOp2(v, OP_NewRowid, pMWin->iEphCsr, regRowid); sqlite3VdbeAddOp3(v, OP_Insert, pMWin->iEphCsr, regRecord, regRowid); /* End the database scan loop. */ sqlite3WhereEnd(pWInfo); windowAggFinal(pParse, pMWin, 1); sqlite3VdbeAddOp2(v, OP_Rewind, pMWin->iEphCsr,sqlite3VdbeCurrentAddr(v)+3); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Gosub, regGosub, addrGosub); sqlite3VdbeAddOp2(v, OP_Next, pMWin->iEphCsr, sqlite3VdbeCurrentAddr(v)-1); VdbeCoverage(v); } /* ** Allocate and return a duplicate of the Window object indicated by the ** third argument. Set the Window.pOwner field of the new object to ** pOwner. */ Window *sqlite3WindowDup(sqlite3 *db, Expr *pOwner, Window *p){ Window *pNew = 0; if( p ){ pNew = sqlite3DbMallocZero(db, sizeof(Window)); if( pNew ){ pNew->zName = sqlite3DbStrDup(db, p->zName); pNew->pFilter = sqlite3ExprDup(db, p->pFilter, 0); pNew->pPartition = sqlite3ExprListDup(db, p->pPartition, 0); pNew->pOrderBy = sqlite3ExprListDup(db, p->pOrderBy, 0); pNew->eType = p->eType; pNew->eEnd = p->eEnd; pNew->eStart = p->eStart; pNew->pStart = sqlite3ExprDup(db, p->pStart, 0); pNew->pEnd = sqlite3ExprDup(db, p->pEnd, 0); pNew->pOwner = pOwner; } } return pNew; } /* ** Return a copy of the linked list of Window objects passed as the ** second argument. */ Window *sqlite3WindowListDup(sqlite3 *db, Window *p){ Window *pWin; Window *pRet = 0; Window **pp = &pRet; for(pWin=p; pWin; pWin=pWin->pNextWin){ *pp = sqlite3WindowDup(db, 0, pWin); if( *pp==0 ) break; pp = &((*pp)->pNextWin); } return pRet; } /* ** sqlite3WhereBegin() has already been called for the SELECT statement ** passed as the second argument when this function is invoked. It generates ** code to populate the Window.regResult register for each window function and ** invoke the sub-routine at instruction addrGosub once for each row. ** This function calls sqlite3WhereEnd() before returning. */ void sqlite3WindowCodeStep( Parse *pParse, /* Parse context */ Select *p, /* Rewritten SELECT statement */ WhereInfo *pWInfo, /* Context returned by sqlite3WhereBegin() */ int regGosub, /* Register for OP_Gosub */ int addrGosub /* OP_Gosub here to return each row */ ){ Window *pMWin = p->pWin; /* There are three different functions that may be used to do the work ** of this one, depending on the window frame and the specific built-in ** window functions used (if any). ** ** windowCodeRowExprStep() handles all "ROWS" window frames, except for: ** ** ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ** ** The exception is because windowCodeRowExprStep() implements all window ** frame types by caching the entire partition in a temp table, and ** "ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW" is easy enough to ** implement without such a cache. ** ** windowCodeCacheStep() is used for: ** ** RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING ** ** It is also used for anything not handled by windowCodeRowExprStep() ** that invokes a built-in window function that requires the entire ** partition to be cached in a temp table before any rows are returned ** (e.g. nth_value() or percent_rank()). ** ** Finally, assuming there is no built-in window function that requires ** the partition to be cached, windowCodeDefaultStep() is used for: ** ** RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ** RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ** RANGE BETWEEN CURRENT ROW AND CURRENT ROW ** ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ** ** windowCodeDefaultStep() is the only one of the three functions that ** does not cache each partition in a temp table before beginning to ** return rows. */ if( pMWin->eType==TK_ROWS && (pMWin->eStart!=TK_UNBOUNDED||pMWin->eEnd!=TK_CURRENT||!pMWin->pOrderBy) ){ windowCodeRowExprStep(pParse, p, pWInfo, regGosub, addrGosub); }else{ Window *pWin; int bCache = 0; /* True to use CacheStep() */ if( pMWin->eStart==TK_CURRENT && pMWin->eEnd==TK_UNBOUNDED ){ bCache = 1; }else{ for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ FuncDef *pFunc = pWin->pFunc; if( (pFunc->funcFlags & SQLITE_FUNC_WINDOW_SIZE) || (pFunc->xSFunc==nth_valueStepFunc) || (pFunc->xSFunc==first_valueStepFunc) || (pFunc->xSFunc==leadStepFunc) || (pFunc->xSFunc==lagStepFunc) ){ bCache = 1; break; } } } /* Otherwise, call windowCodeDefaultStep(). */ if( bCache ){ windowCodeCacheStep(pParse, p, pWInfo, regGosub, addrGosub); }else{ windowCodeDefaultStep(pParse, p, pWInfo, regGosub, addrGosub); } } } #endif /* SQLITE_OMIT_WINDOWFUNC */ |
Changes to test/permutations.test.
︙ | ︙ | |||
278 279 280 281 282 283 284 285 286 287 288 289 290 291 | test_suite "fts5-light" -prefix "" -description { All FTS5 tests. } -files [ test_set \ [glob -nocomplain $::testdir/../ext/fts5/test/*.test] \ -exclude *corrupt* *fault* *big* *fts5aj* ] test_suite "lsm1" -prefix "" -description { All LSM1 tests. } -files [glob -nocomplain $::testdir/../ext/lsm1/test/*.test] test_suite "nofaultsim" -prefix "" -description { "Very" quick test suite. Runs in less than 5 minutes on a workstation. | > > > > > > | 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 | test_suite "fts5-light" -prefix "" -description { All FTS5 tests. } -files [ test_set \ [glob -nocomplain $::testdir/../ext/fts5/test/*.test] \ -exclude *corrupt* *fault* *big* *fts5aj* ] test_suite "window" -prefix "" -description { All window function related tests . } -files [ test_set [glob -nocomplain $::testdir/window*.test] ] test_suite "lsm1" -prefix "" -description { All LSM1 tests. } -files [glob -nocomplain $::testdir/../ext/lsm1/test/*.test] test_suite "nofaultsim" -prefix "" -description { "Very" quick test suite. Runs in less than 5 minutes on a workstation. |
︙ | ︙ |
Added test/pg_common.tcl.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 | # 2018 May 19 # # 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. # #*********************************************************************** # package require sqlite3 package require Pgtcl set db [pg_connect -conninfo "dbname=postgres user=postgres password=postgres"] sqlite3 sqlite "" proc execsql {sql} { set lSql [list] set frag "" while {[string length $sql]>0} { set i [string first ";" $sql] if {$i>=0} { append frag [string range $sql 0 $i] set sql [string range $sql $i+1 end] if {[sqlite complete $frag]} { lappend lSql $frag set frag "" } } else { set frag $sql set sql "" } } if {$frag != ""} { lappend lSql $frag } #puts $lSql set ret "" foreach stmt $lSql { set res [pg_exec $::db $stmt] set err [pg_result $res -error] if {$err!=""} { error $err } for {set i 0} {$i < [pg_result $res -numTuples]} {incr i} { if {$i==0} { set ret [pg_result $res -getTuple 0] } else { append ret " [pg_result $res -getTuple $i]" } # lappend ret {*}[pg_result $res -getTuple $i] } pg_result $res -clear } set ret } proc execsql_test {tn sql} { set res [execsql $sql] set sql [string map {string_agg group_concat} $sql] puts $::fd "do_execsql_test $tn {" puts $::fd " [string trim $sql]" puts $::fd "} {$res}" puts $::fd "" } # Same as [execsql_test], except coerce all results to floating point values # with two decimal points. # proc execsql_float_test {tn sql} { set F "%.2f" set res [execsql $sql] set res2 [list] foreach r $res { if {$r != ""} { set r [format $F $r] } lappend res2 $r } puts $::fd "do_test $tn {" puts $::fd " set myres {}" puts $::fd " foreach r \[db eval {[string trim $sql]}\] {" puts $::fd " lappend myres \[format $F \[set r\]\]" puts $::fd " }" puts $::fd " set myres" puts $::fd "} {$res2}" puts $::fd "" } proc start_test {name date} { set dir [file dirname $::argv0] set output [file join $dir $name.test] set ::fd [open $output w] puts $::fd [string trimleft " # $date # # 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. # #*********************************************************************** # This file implements regression tests for SQLite library. # #################################################### # DO NOT EDIT! THIS FILE IS AUTOMATICALLY GENERATED! #################################################### "] puts $::fd {set testdir [file dirname $argv0]} puts $::fd {source $testdir/tester.tcl} puts $::fd "set testprefix $name" puts $::fd "" } proc -- {args} { puts $::fd "# $args" } proc ========== {args} { puts $::fd "#[string repeat = 74]" puts $::fd "" } proc finish_test {} { puts $::fd finish_test close $::fd } proc ifcapable {arg} { puts $::fd "ifcapable $arg { finish_test ; return }" } |
Added test/window1.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 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 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 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 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 | # 2018 May 8 # # 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. # #*********************************************************************** # This file implements regression tests for SQLite library. # set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix window1 ifcapable !windowfunc { finish_test return } do_execsql_test 1.0 { CREATE TABLE t1(a, b, c, d); INSERT INTO t1 VALUES(1, 2, 3, 4); INSERT INTO t1 VALUES(5, 6, 7, 8); INSERT INTO t1 VALUES(9, 10, 11, 12); } do_execsql_test 1.1 { SELECT sum(b) OVER () FROM t1 } {18 18 18} do_execsql_test 1.2 { SELECT a, sum(b) OVER () FROM t1 } {1 18 5 18 9 18} do_execsql_test 1.3 { SELECT a, 4 + sum(b) OVER () FROM t1 } {1 22 5 22 9 22} do_execsql_test 1.4 { SELECT a + 4 + sum(b) OVER () FROM t1 } {23 27 31} do_execsql_test 1.5 { SELECT a, sum(b) OVER (PARTITION BY c) FROM t1 } {1 2 5 6 9 10} foreach {tn sql} { 1 "SELECT sum(b) OVER () FROM t1" 2 "SELECT sum(b) OVER (PARTITION BY c) FROM t1" 3 "SELECT sum(b) OVER (ORDER BY c) FROM t1" 4 "SELECT sum(b) OVER (PARTITION BY d ORDER BY c) FROM t1" 5 "SELECT sum(b) FILTER (WHERE a>0) OVER (PARTITION BY d ORDER BY c) FROM t1" 6 "SELECT sum(b) OVER (ORDER BY c RANGE UNBOUNDED PRECEDING) FROM t1" 7 "SELECT sum(b) OVER (ORDER BY c ROWS 45 PRECEDING) FROM t1" 8 "SELECT sum(b) OVER (ORDER BY c RANGE CURRENT ROW) FROM t1" 9 "SELECT sum(b) OVER (ORDER BY c RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM t1" 10 "SELECT sum(b) OVER (ORDER BY c ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) FROM t1" } { do_test 2.$tn { lindex [catchsql $sql] 0 } 0 } foreach {tn sql} { 1 "SELECT * FROM t1 WHERE sum(b) OVER ()" 2 "SELECT * FROM t1 GROUP BY sum(b) OVER ()" 3 "SELECT * FROM t1 GROUP BY a HAVING sum(b) OVER ()" } { do_catchsql_test 3.$tn $sql {1 {misuse of window function sum()}} } do_execsql_test 4.0 { CREATE TABLE t2(a, b, c); INSERT INTO t2 VALUES(0, 0, 0); INSERT INTO t2 VALUES(1, 1, 1); INSERT INTO t2 VALUES(2, 0, 2); INSERT INTO t2 VALUES(3, 1, 0); INSERT INTO t2 VALUES(4, 0, 1); INSERT INTO t2 VALUES(5, 1, 2); INSERT INTO t2 VALUES(6, 0, 0); } do_execsql_test 4.1 { SELECT a, sum(a) OVER (PARTITION BY b) FROM t2; } { 0 12 2 12 4 12 6 12 1 9 3 9 5 9 } do_execsql_test 4.2 { SELECT a, sum(a) OVER (PARTITION BY b) FROM t2 ORDER BY a; } { 0 12 1 9 2 12 3 9 4 12 5 9 6 12 } do_execsql_test 4.3 { SELECT a, sum(a) OVER () FROM t2 ORDER BY a; } { 0 21 1 21 2 21 3 21 4 21 5 21 6 21 } do_execsql_test 4.4 { SELECT a, sum(a) OVER (ORDER BY a) FROM t2; } { 0 0 1 1 2 3 3 6 4 10 5 15 6 21 } do_execsql_test 4.5 { SELECT a, sum(a) OVER (PARTITION BY b ORDER BY a) FROM t2 ORDER BY a } { 0 0 1 1 2 2 3 4 4 6 5 9 6 12 } do_execsql_test 4.6 { SELECT a, sum(a) OVER (PARTITION BY c ORDER BY a) FROM t2 ORDER BY a } { 0 0 1 1 2 2 3 3 4 5 5 7 6 9 } do_execsql_test 4.7 { SELECT a, sum(a) OVER (PARTITION BY b ORDER BY a DESC) FROM t2 ORDER BY a } { 0 12 1 9 2 12 3 8 4 10 5 5 6 6 } do_execsql_test 4.8 { SELECT a, sum(a) OVER (PARTITION BY b ORDER BY a DESC), sum(a) OVER (PARTITION BY c ORDER BY a) FROM t2 ORDER BY a } { 0 12 0 1 9 1 2 12 2 3 8 3 4 10 5 5 5 7 6 6 9 } do_execsql_test 4.9 { SELECT a, sum(a) OVER (ORDER BY a), avg(a) OVER (ORDER BY a) FROM t2 ORDER BY a } { 0 0 0.0 1 1 0.5 2 3 1.0 3 6 1.5 4 10 2.0 5 15 2.5 6 21 3.0 } do_execsql_test 4.10.1 { SELECT a, count() OVER (ORDER BY a DESC), group_concat(a, '.') OVER (ORDER BY a DESC) FROM t2 ORDER BY a DESC } { 6 1 6 5 2 6.5 4 3 6.5.4 3 4 6.5.4.3 2 5 6.5.4.3.2 1 6 6.5.4.3.2.1 0 7 6.5.4.3.2.1.0 } do_execsql_test 4.10.2 { SELECT a, count(*) OVER (ORDER BY a DESC), group_concat(a, '.') OVER (ORDER BY a DESC) FROM t2 ORDER BY a DESC } { 6 1 6 5 2 6.5 4 3 6.5.4 3 4 6.5.4.3 2 5 6.5.4.3.2 1 6 6.5.4.3.2.1 0 7 6.5.4.3.2.1.0 } do_catchsql_test 5.1 { SELECT ntile(0) OVER (ORDER BY a) FROM t2; } {1 {argument of ntile must be a positive integer}} do_catchsql_test 5.2 { SELECT ntile(-1) OVER (ORDER BY a) FROM t2; } {1 {argument of ntile must be a positive integer}} do_catchsql_test 5.3 { SELECT ntile('zbc') OVER (ORDER BY a) FROM t2; } {1 {argument of ntile must be a positive integer}} do_execsql_test 5.4 { CREATE TABLE t4(a, b); SELECT ntile(1) OVER (ORDER BY a) FROM t4; } {} #------------------------------------------------------------------------- reset_db do_execsql_test 6.1 { CREATE TABLE t1(x); INSERT INTO t1 VALUES(7), (6), (5), (4), (3), (2), (1); CREATE TABLE t2(x); INSERT INTO t2 VALUES('b'), ('a'); SELECT x, count(*) OVER (ORDER BY x) FROM t1; } {1 1 2 2 3 3 4 4 5 5 6 6 7 7} do_execsql_test 6.2 { SELECT * FROM t2, (SELECT x, count(*) OVER (ORDER BY x) FROM t1); } { b 1 1 b 2 2 b 3 3 b 4 4 b 5 5 b 6 6 b 7 7 a 1 1 a 2 2 a 3 3 a 4 4 a 5 5 a 6 6 a 7 7 } do_catchsql_test 6.3 { SELECT x, lag(x) FILTER (WHERE (x%2)=0) OVER w FROM t1 WINDOW w AS (ORDER BY x) } {1 {FILTER clause may only be used with aggregate window functions}} #------------------------------------------------------------------------- # Attempt to use a window function as an aggregate. And other errors. # reset_db do_execsql_test 7.0 { CREATE TABLE t1(x, y); INSERT INTO t1 VALUES(1, 2); INSERT INTO t1 VALUES(3, 4); INSERT INTO t1 VALUES(5, 6); INSERT INTO t1 VALUES(7, 8); INSERT INTO t1 VALUES(9, 10); } do_catchsql_test 7.1.1 { SELECT nth_value(x, 1) FROM t1; } {1 {misuse of window function nth_value()}} do_catchsql_test 7.1.2 { SELECT * FROM t1 WHERE nth_value(x, 1) OVER (ORDER BY y); } {1 {misuse of window function nth_value()}} do_catchsql_test 7.1.3 { SELECT count(*) FROM t1 GROUP BY y HAVING nth_value(x, 1) OVER (ORDER BY y); } {1 {misuse of window function nth_value()}} do_catchsql_test 7.1.4 { SELECT count(*) FROM t1 GROUP BY nth_value(x, 1) OVER (ORDER BY y); } {1 {misuse of window function nth_value()}} do_catchsql_test 7.1.5 { SELECT count(*) FROM t1 LIMIT nth_value(x, 1) OVER (); } {1 {no such column: x}} do_catchsql_test 7.1.6 { SELECT trim(x) OVER (ORDER BY y) FROM t1; } {1 {trim() may not be used as a window function}} do_catchsql_test 7.1.7 { SELECT max(x) OVER abc FROM t1 WINDOW def AS (ORDER BY y); } {1 {no such window: abc}} do_execsql_test 7.2 { SELECT lead(y) OVER win, lead(y, 2) OVER win, lead(y, 3, 'default') OVER win FROM t1 WINDOW win AS (ORDER BY x) } { 4 6 8 6 8 10 8 10 default 10 {} default {} {} default } do_execsql_test 7.3 { SELECT row_number() OVER (ORDER BY x) FROM t1 } {1 2 3 4 5} do_execsql_test 7.4 { SELECT row_number() OVER win, lead(x) OVER win FROM t1 WINDOW win AS (ORDER BY x ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) } {1 3 2 5 3 7 4 9 5 {}} #------------------------------------------------------------------------- # Attempt to use a window function in a view. # do_execsql_test 8.0 { CREATE TABLE t3(a, b, c); WITH s(i) AS ( VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<6 ) INSERT INTO t3 SELECT i, i, i FROM s; CREATE VIEW v1 AS SELECT sum(b) OVER (ORDER BY c), min(b) OVER (ORDER BY c), max(b) OVER (ORDER BY c) FROM t3; CREATE VIEW v2 AS SELECT sum(b) OVER win, min(b) OVER win, max(b) OVER win FROM t3 WINDOW win AS (ORDER BY c); } do_execsql_test 8.1.1 { SELECT * FROM v1 } {1 1 1 3 1 2 6 1 3 10 1 4 15 1 5 21 1 6} do_execsql_test 8.1.2 { SELECT * FROM v2 } {1 1 1 3 1 2 6 1 3 10 1 4 15 1 5 21 1 6} db close sqlite3 db test.db do_execsql_test 8.2.1 { SELECT * FROM v1 } {1 1 1 3 1 2 6 1 3 10 1 4 15 1 5 21 1 6} do_execsql_test 8.2.2 { SELECT * FROM v2 } {1 1 1 3 1 2 6 1 3 10 1 4 15 1 5 21 1 6} #------------------------------------------------------------------------- # Attempt to use a window function in a trigger. # do_execsql_test 9.0 { CREATE TABLE t4(x, y); INSERT INTO t4 VALUES(1, 'g'); INSERT INTO t4 VALUES(2, 'i'); INSERT INTO t4 VALUES(3, 'l'); INSERT INTO t4 VALUES(4, 'g'); INSERT INTO t4 VALUES(5, 'a'); CREATE TABLE t5(x, y, m); CREATE TRIGGER t4i AFTER INSERT ON t4 BEGIN DELETE FROM t5; INSERT INTO t5 SELECT x, y, max(y) OVER xyz FROM t4 WINDOW xyz AS (PARTITION BY (x%2) ORDER BY x); END; } do_execsql_test 9.1.1 { SELECT x, y, max(y) OVER xyz FROM t4 WINDOW xyz AS (PARTITION BY (x%2) ORDER BY x) ORDER BY 1 } {1 g g 2 i i 3 l l 4 g i 5 a l} do_execsql_test 9.1.2 { INSERT INTO t4 VALUES(6, 'm'); SELECT x, y, max(y) OVER xyz FROM t4 WINDOW xyz AS (PARTITION BY (x%2) ORDER BY x) ORDER BY 1 } {1 g g 2 i i 3 l l 4 g i 5 a l 6 m m} do_execsql_test 9.1.3 { SELECT * FROM t5 ORDER BY 1 } {1 g g 2 i i 3 l l 4 g i 5 a l 6 m m} do_execsql_test 9.2 { WITH aaa(x, y, z) AS ( SELECT x, y, max(y) OVER xyz FROM t4 WINDOW xyz AS (PARTITION BY (x%2) ORDER BY x) ) SELECT * FROM aaa ORDER BY 1; } {1 g g 2 i i 3 l l 4 g i 5 a l 6 m m} do_execsql_test 9.3 { WITH aaa(x, y, z) AS ( SELECT x, y, max(y) OVER xyz FROM t4 WINDOW xyz AS (ORDER BY x) ) SELECT *, min(z) OVER (ORDER BY x) FROM aaa ORDER BY 1; } {1 g g g 2 i i g 3 l l g 4 g l g 5 a l g 6 m m g} #------------------------------------------------------------------------- # do_execsql_test 10.0 { CREATE TABLE sales(emp TEXT PRIMARY KEY, region, total); INSERT INTO sales VALUES ('Alice', 'North', 34), ('Frank', 'South', 22), ('Charles', 'North', 45), ('Darrell', 'South', 8), ('Grant', 'South', 23), ('Brad' , 'North', 22), ('Elizabeth', 'South', 99), ('Horace', 'East', 1); } # Best two salespeople from each region # do_execsql_test 10.1 { SELECT emp, region, total FROM ( SELECT emp, region, total, row_number() OVER (PARTITION BY region ORDER BY total DESC) AS rank FROM sales ) WHERE rank<=2 ORDER BY region, total DESC } { Horace East 1 Charles North 45 Alice North 34 Elizabeth South 99 Grant South 23 } do_execsql_test 10.2 { SELECT emp, region, sum(total) OVER win FROM sales WINDOW win AS (PARTITION BY region ORDER BY total) } { Horace East 1 Brad North 22 Alice North 56 Charles North 101 Darrell South 8 Frank South 30 Grant South 53 Elizabeth South 152 } do_execsql_test 10.3 { SELECT emp, region, sum(total) OVER win FROM sales WINDOW win AS (PARTITION BY region ORDER BY total) LIMIT 5 } { Horace East 1 Brad North 22 Alice North 56 Charles North 101 Darrell South 8 } do_execsql_test 10.4 { SELECT emp, region, sum(total) OVER win FROM sales WINDOW win AS (PARTITION BY region ORDER BY total) LIMIT 5 OFFSET 2 } { Alice North 56 Charles North 101 Darrell South 8 Frank South 30 Grant South 53 } do_execsql_test 10.5 { SELECT emp, region, sum(total) OVER win FROM sales WINDOW win AS ( PARTITION BY region ORDER BY total ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING ) } { Horace East 1 Brad North 101 Alice North 79 Charles North 45 Darrell South 152 Frank South 144 Grant South 122 Elizabeth South 99 } do_execsql_test 10.6 { SELECT emp, region, sum(total) OVER win FROM sales WINDOW win AS ( PARTITION BY region ORDER BY total ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING ) LIMIT 5 OFFSET 2 } { Alice North 79 Charles North 45 Darrell South 152 Frank South 144 Grant South 122 } do_execsql_test 10.7 { SELECT emp, region, ( SELECT sum(total) OVER ( ORDER BY total RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) || outer.emp FROM sales ) FROM sales AS outer; } { Alice North 254Alice Frank South 254Frank Charles North 254Charles Darrell South 254Darrell Grant South 254Grant Brad North 254Brad Elizabeth South 254Elizabeth Horace East 254Horace } do_execsql_test 10.8 { SELECT emp, region, ( SELECT sum(total) FILTER (WHERE sales.emp!=outer.emp) OVER ( ORDER BY total RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) FROM sales ) FROM sales AS outer; } { Alice North 220 Frank South 232 Charles North 209 Darrell South 246 Grant South 231 Brad North 232 Elizabeth South 155 Horace East 253 } #------------------------------------------------------------------------- # Check that it is not possible to use a window function in a CREATE INDEX # statement. # do_execsql_test 11.0 { CREATE TABLE t6(a, b, c); } do_catchsql_test 11.1 { CREATE INDEX t6i ON t6(a) WHERE sum(b) OVER (); } {1 {misuse of window function sum()}} do_catchsql_test 11.2 { CREATE INDEX t6i ON t6(a) WHERE lead(b) OVER (); } {1 {misuse of window function lead()}} do_catchsql_test 11.3 { CREATE INDEX t6i ON t6(sum(b) OVER ()); } {1 {misuse of window function sum()}} do_catchsql_test 11.4 { CREATE INDEX t6i ON t6(lead(b) OVER ()); } {1 {misuse of window function lead()}} finish_test |
Added test/window2.tcl.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 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 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 | # 2018 May 19 # # 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. # #*********************************************************************** # source [file join [file dirname $argv0] pg_common.tcl] #========================================================================= start_test window2 "2018 May 19" ifcapable !windowfunc execsql_test 1.0 { DROP TABLE IF EXISTS t1; CREATE TABLE t1(a INTEGER PRIMARY KEY, b TEXT, c TEXT, d INTEGER); INSERT INTO t1 VALUES(1, 'odd', 'one', 1); INSERT INTO t1 VALUES(2, 'even', 'two', 2); INSERT INTO t1 VALUES(3, 'odd', 'three', 3); INSERT INTO t1 VALUES(4, 'even', 'four', 4); INSERT INTO t1 VALUES(5, 'odd', 'five', 5); INSERT INTO t1 VALUES(6, 'even', 'six', 6); } execsql_test 1.1 { SELECT c, sum(d) OVER (PARTITION BY b ORDER BY c) FROM t1; } execsql_test 1.2 { SELECT sum(d) OVER () FROM t1; } execsql_test 1.3 { SELECT sum(d) OVER (PARTITION BY b) FROM t1; } ========== execsql_test 2.1 { SELECT a, sum(d) OVER ( ORDER BY d ROWS BETWEEN 1000 PRECEDING AND 1 FOLLOWING ) FROM t1 } execsql_test 2.2 { SELECT a, sum(d) OVER ( ORDER BY d ROWS BETWEEN 1000 PRECEDING AND 1000 FOLLOWING ) FROM t1 } execsql_test 2.3 { SELECT a, sum(d) OVER ( ORDER BY d ROWS BETWEEN 1 PRECEDING AND 1000 FOLLOWING ) FROM t1 } execsql_test 2.4 { SELECT a, sum(d) OVER ( ORDER BY d ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING ) FROM t1 } execsql_test 2.5 { SELECT a, sum(d) OVER ( ORDER BY d ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING ) FROM t1 } execsql_test 2.6 { SELECT a, sum(d) OVER ( PARTITION BY b ORDER BY d ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING ) FROM t1 } execsql_test 2.7 { SELECT a, sum(d) OVER ( PARTITION BY b ORDER BY d ROWS BETWEEN 0 PRECEDING AND 0 FOLLOWING ) FROM t1 } execsql_test 2.8 { SELECT a, sum(d) OVER ( ORDER BY d ROWS BETWEEN CURRENT ROW AND 2 FOLLOWING ) FROM t1 } execsql_test 2.9 { SELECT a, sum(d) OVER ( ORDER BY d ROWS BETWEEN UNBOUNDED PRECEDING AND 2 FOLLOWING ) FROM t1 } execsql_test 2.10 { SELECT a, sum(d) OVER ( ORDER BY d ROWS BETWEEN CURRENT ROW AND 2 FOLLOWING ) FROM t1 } execsql_test 2.11 { SELECT a, sum(d) OVER ( ORDER BY d ROWS BETWEEN 2 PRECEDING AND CURRENT ROW ) FROM t1 } execsql_test 2.13 { SELECT a, sum(d) OVER ( ORDER BY d ROWS BETWEEN 2 PRECEDING AND UNBOUNDED FOLLOWING ) FROM t1 } execsql_test 2.14 { SELECT a, sum(d) OVER ( ORDER BY d ROWS BETWEEN 3 PRECEDING AND 1 PRECEDING ) FROM t1 } execsql_test 2.15 { SELECT a, sum(d) OVER ( PARTITION BY b ORDER BY d ROWS BETWEEN 1 PRECEDING AND 0 PRECEDING ) FROM t1 } execsql_test 2.16 { SELECT a, sum(d) OVER ( PARTITION BY b ORDER BY d ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING ) FROM t1 } execsql_test 2.17 { SELECT a, sum(d) OVER ( PARTITION BY b ORDER BY d ROWS BETWEEN 1 PRECEDING AND 2 PRECEDING ) FROM t1 } execsql_test 2.18 { SELECT a, sum(d) OVER ( PARTITION BY b ORDER BY d ROWS BETWEEN UNBOUNDED PRECEDING AND 2 PRECEDING ) FROM t1 } execsql_test 2.19 { SELECT a, sum(d) OVER ( PARTITION BY b ORDER BY d ROWS BETWEEN 1 FOLLOWING AND 3 FOLLOWING ) FROM t1 } execsql_test 2.20 { SELECT a, sum(d) OVER ( ORDER BY d ROWS BETWEEN 1 FOLLOWING AND 2 FOLLOWING ) FROM t1 } execsql_test 2.21 { SELECT a, sum(d) OVER ( ORDER BY d ROWS BETWEEN 1 FOLLOWING AND UNBOUNDED FOLLOWING ) FROM t1 } execsql_test 2.22 { SELECT a, sum(d) OVER ( PARTITION BY b ORDER BY d ROWS BETWEEN 1 FOLLOWING AND UNBOUNDED FOLLOWING ) FROM t1 } execsql_test 2.23 { SELECT a, sum(d) OVER ( ORDER BY d ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING ) FROM t1 } execsql_test 2.24 { SELECT a, sum(d) OVER ( PARTITION BY a%2 ORDER BY d ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING ) FROM t1 } execsql_test 2.25 { SELECT a, sum(d) OVER ( ORDER BY d ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) FROM t1 } execsql_test 2.26 { SELECT a, sum(d) OVER ( PARTITION BY b ORDER BY d ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) FROM t1 } execsql_test 2.27 { SELECT a, sum(d) OVER ( ORDER BY d ROWS BETWEEN CURRENT ROW AND CURRENT ROW ) FROM t1 } execsql_test 2.28 { SELECT a, sum(d) OVER ( PARTITION BY b ORDER BY d ROWS BETWEEN CURRENT ROW AND CURRENT ROW ) FROM t1 } execsql_test 2.29 { SELECT a, sum(d) OVER ( ORDER BY d RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING ) FROM t1 } execsql_test 2.30 { SELECT a, sum(d) OVER ( ORDER BY b RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING ) FROM t1 } execsql_test 3.1 { SELECT a, sum(d) OVER ( PARTITION BY b ORDER BY d RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING ) FROM t1 } execsql_test 3.2 { SELECT a, sum(d) OVER ( ORDER BY b RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING ) FROM t1 } execsql_test 3.3 { SELECT a, sum(d) OVER ( ORDER BY d ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) FROM t1 } execsql_test 3.4 { SELECT a, sum(d) OVER ( ORDER BY d/2 ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) FROM t1 } #puts $::fd finish_test ========== execsql_test 4.0 { DROP TABLE IF EXISTS t2; CREATE TABLE t2(a INTEGER PRIMARY KEY, b INTEGER); INSERT INTO t2(a, b) VALUES (1,0), (2,74), (3,41), (4,74), (5,23), (6,99), (7,26), (8,33), (9,2), (10,89), (11,81), (12,96), (13,59), (14,38), (15,68), (16,39), (17,62), (18,91), (19,46), (20,6), (21,99), (22,97), (23,27), (24,46), (25,78), (26,54), (27,97), (28,8), (29,67), (30,29), (31,93), (32,84), (33,77), (34,23), (35,16), (36,16), (37,93), (38,65), (39,35), (40,47), (41,7), (42,86), (43,74), (44,61), (45,91), (46,85), (47,24), (48,85), (49,43), (50,59), (51,12), (52,32), (53,56), (54,3), (55,91), (56,22), (57,90), (58,55), (59,15), (60,28), (61,89), (62,25), (63,47), (64,1), (65,56), (66,40), (67,43), (68,56), (69,16), (70,75), (71,36), (72,89), (73,98), (74,76), (75,81), (76,4), (77,94), (78,42), (79,30), (80,78), (81,33), (82,29), (83,53), (84,63), (85,2), (86,87), (87,37), (88,80), (89,84), (90,72), (91,41), (92,9), (93,61), (94,73), (95,95), (96,65), (97,13), (98,58), (99,96), (100,98), (101,1), (102,21), (103,74), (104,65), (105,35), (106,5), (107,73), (108,11), (109,51), (110,87), (111,41), (112,12), (113,8), (114,20), (115,31), (116,31), (117,15), (118,95), (119,22), (120,73), (121,79), (122,88), (123,34), (124,8), (125,11), (126,49), (127,34), (128,90), (129,59), (130,96), (131,60), (132,55), (133,75), (134,77), (135,44), (136,2), (137,7), (138,85), (139,57), (140,74), (141,29), (142,70), (143,59), (144,19), (145,39), (146,26), (147,26), (148,47), (149,80), (150,90), (151,36), (152,58), (153,47), (154,9), (155,72), (156,72), (157,66), (158,33), (159,93), (160,75), (161,64), (162,81), (163,9), (164,23), (165,37), (166,13), (167,12), (168,14), (169,62), (170,91), (171,36), (172,91), (173,33), (174,15), (175,34), (176,36), (177,99), (178,3), (179,95), (180,69), (181,58), (182,52), (183,30), (184,50), (185,84), (186,10), (187,84), (188,33), (189,21), (190,39), (191,44), (192,58), (193,30), (194,38), (195,34), (196,83), (197,27), (198,82), (199,17), (200,7); } execsql_test 4.1 { SELECT a, sum(b) OVER ( PARTITION BY (b%10) ORDER BY b ) FROM t2 ORDER BY a; } execsql_test 4.2 { SELECT a, sum(b) OVER ( PARTITION BY (b%10) ORDER BY b RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) FROM t2 ORDER BY a; } execsql_test 4.3 { SELECT b, sum(b) OVER ( ORDER BY b ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) FROM t2 ORDER BY b; } execsql_test 4.4 { SELECT b, sum(b) OVER ( ORDER BY b RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) FROM t2 ORDER BY b; } execsql_test 4.5 { SELECT b, sum(b) OVER ( ORDER BY b RANGE BETWEEN CURRENT ROW AND CURRENT ROW ) FROM t2 ORDER BY b; } execsql_test 4.6.1 { SELECT b, sum(b) OVER ( RANGE BETWEEN CURRENT ROW AND CURRENT ROW ) FROM t2 ORDER BY b; } execsql_test 4.6.2 { SELECT b, sum(b) OVER () FROM t2 ORDER BY b; } execsql_test 4.6.3 { SELECT b, sum(b) OVER ( RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) FROM t2 ORDER BY b; } execsql_test 4.6.4 { SELECT b, sum(b) OVER ( RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING ) FROM t2 ORDER BY b; } execsql_test 4.7.1 { SELECT b, sum(b) OVER ( ROWS BETWEEN CURRENT ROW AND CURRENT ROW ) FROM t2 ORDER BY 1, 2; } execsql_test 4.7.2 { SELECT b, sum(b) OVER ( ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) FROM t2 ORDER BY 1, 2; } execsql_test 4.7.3 { SELECT b, sum(b) OVER ( ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) FROM t2 ORDER BY 1, 2; } execsql_test 4.7.4 { SELECT b, sum(b) OVER ( ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING ) FROM t2 ORDER BY 1, 2; } execsql_test 4.8.1 { SELECT b, sum(b) OVER ( ORDER BY a ROWS BETWEEN CURRENT ROW AND CURRENT ROW ) FROM t2 ORDER BY 1, 2; } execsql_test 4.8.2 { SELECT b, sum(b) OVER ( ORDER BY a ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) FROM t2 ORDER BY 1, 2; } execsql_test 4.8.3 { SELECT b, sum(b) OVER ( ORDER BY a ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) FROM t2 ORDER BY 1, 2; } execsql_test 4.8.4 { SELECT b, sum(b) OVER ( ORDER BY a ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING ) FROM t2 ORDER BY 1, 2; } finish_test |
Added test/window2.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 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 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 | # 2018 May 19 # # 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. # #*********************************************************************** # This file implements regression tests for SQLite library. # #################################################### # DO NOT EDIT! THIS FILE IS AUTOMATICALLY GENERATED! #################################################### set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix window2 ifcapable !windowfunc { finish_test ; return } do_execsql_test 1.0 { DROP TABLE IF EXISTS t1; CREATE TABLE t1(a INTEGER PRIMARY KEY, b TEXT, c TEXT, d INTEGER); INSERT INTO t1 VALUES(1, 'odd', 'one', 1); INSERT INTO t1 VALUES(2, 'even', 'two', 2); INSERT INTO t1 VALUES(3, 'odd', 'three', 3); INSERT INTO t1 VALUES(4, 'even', 'four', 4); INSERT INTO t1 VALUES(5, 'odd', 'five', 5); INSERT INTO t1 VALUES(6, 'even', 'six', 6); } {} do_execsql_test 1.1 { SELECT c, sum(d) OVER (PARTITION BY b ORDER BY c) FROM t1; } {four 4 six 10 two 12 five 5 one 6 three 9} do_execsql_test 1.2 { SELECT sum(d) OVER () FROM t1; } {21 21 21 21 21 21} do_execsql_test 1.3 { SELECT sum(d) OVER (PARTITION BY b) FROM t1; } {12 12 12 9 9 9} #========================================================================== do_execsql_test 2.1 { SELECT a, sum(d) OVER ( ORDER BY d ROWS BETWEEN 1000 PRECEDING AND 1 FOLLOWING ) FROM t1 } {1 3 2 6 3 10 4 15 5 21 6 21} do_execsql_test 2.2 { SELECT a, sum(d) OVER ( ORDER BY d ROWS BETWEEN 1000 PRECEDING AND 1000 FOLLOWING ) FROM t1 } {1 21 2 21 3 21 4 21 5 21 6 21} do_execsql_test 2.3 { SELECT a, sum(d) OVER ( ORDER BY d ROWS BETWEEN 1 PRECEDING AND 1000 FOLLOWING ) FROM t1 } {1 21 2 21 3 20 4 18 5 15 6 11} do_execsql_test 2.4 { SELECT a, sum(d) OVER ( ORDER BY d ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING ) FROM t1 } {1 3 2 6 3 9 4 12 5 15 6 11} do_execsql_test 2.5 { SELECT a, sum(d) OVER ( ORDER BY d ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING ) FROM t1 } {1 1 2 3 3 5 4 7 5 9 6 11} do_execsql_test 2.6 { SELECT a, sum(d) OVER ( PARTITION BY b ORDER BY d ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING ) FROM t1 } {2 6 4 12 6 10 1 4 3 9 5 8} do_execsql_test 2.7 { SELECT a, sum(d) OVER ( PARTITION BY b ORDER BY d ROWS BETWEEN 0 PRECEDING AND 0 FOLLOWING ) FROM t1 } {2 2 4 4 6 6 1 1 3 3 5 5} do_execsql_test 2.8 { SELECT a, sum(d) OVER ( ORDER BY d ROWS BETWEEN CURRENT ROW AND 2 FOLLOWING ) FROM t1 } {1 6 2 9 3 12 4 15 5 11 6 6} do_execsql_test 2.9 { SELECT a, sum(d) OVER ( ORDER BY d ROWS BETWEEN UNBOUNDED PRECEDING AND 2 FOLLOWING ) FROM t1 } {1 6 2 10 3 15 4 21 5 21 6 21} do_execsql_test 2.10 { SELECT a, sum(d) OVER ( ORDER BY d ROWS BETWEEN CURRENT ROW AND 2 FOLLOWING ) FROM t1 } {1 6 2 9 3 12 4 15 5 11 6 6} do_execsql_test 2.11 { SELECT a, sum(d) OVER ( ORDER BY d ROWS BETWEEN 2 PRECEDING AND CURRENT ROW ) FROM t1 } {1 1 2 3 3 6 4 9 5 12 6 15} do_execsql_test 2.13 { SELECT a, sum(d) OVER ( ORDER BY d ROWS BETWEEN 2 PRECEDING AND UNBOUNDED FOLLOWING ) FROM t1 } {1 21 2 21 3 21 4 20 5 18 6 15} do_execsql_test 2.14 { SELECT a, sum(d) OVER ( ORDER BY d ROWS BETWEEN 3 PRECEDING AND 1 PRECEDING ) FROM t1 } {1 {} 2 1 3 3 4 6 5 9 6 12} do_execsql_test 2.15 { SELECT a, sum(d) OVER ( PARTITION BY b ORDER BY d ROWS BETWEEN 1 PRECEDING AND 0 PRECEDING ) FROM t1 } {2 2 4 6 6 10 1 1 3 4 5 8} do_execsql_test 2.16 { SELECT a, sum(d) OVER ( PARTITION BY b ORDER BY d ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING ) FROM t1 } {2 {} 4 2 6 4 1 {} 3 1 5 3} do_execsql_test 2.17 { SELECT a, sum(d) OVER ( PARTITION BY b ORDER BY d ROWS BETWEEN 1 PRECEDING AND 2 PRECEDING ) FROM t1 } {2 {} 4 {} 6 {} 1 {} 3 {} 5 {}} do_execsql_test 2.18 { SELECT a, sum(d) OVER ( PARTITION BY b ORDER BY d ROWS BETWEEN UNBOUNDED PRECEDING AND 2 PRECEDING ) FROM t1 } {2 {} 4 {} 6 2 1 {} 3 {} 5 1} do_execsql_test 2.19 { SELECT a, sum(d) OVER ( PARTITION BY b ORDER BY d ROWS BETWEEN 1 FOLLOWING AND 3 FOLLOWING ) FROM t1 } {2 10 4 6 6 {} 1 8 3 5 5 {}} do_execsql_test 2.20 { SELECT a, sum(d) OVER ( ORDER BY d ROWS BETWEEN 1 FOLLOWING AND 2 FOLLOWING ) FROM t1 } {1 5 2 7 3 9 4 11 5 6 6 {}} do_execsql_test 2.21 { SELECT a, sum(d) OVER ( ORDER BY d ROWS BETWEEN 1 FOLLOWING AND UNBOUNDED FOLLOWING ) FROM t1 } {1 20 2 18 3 15 4 11 5 6 6 {}} do_execsql_test 2.22 { SELECT a, sum(d) OVER ( PARTITION BY b ORDER BY d ROWS BETWEEN 1 FOLLOWING AND UNBOUNDED FOLLOWING ) FROM t1 } {2 10 4 6 6 {} 1 8 3 5 5 {}} do_execsql_test 2.23 { SELECT a, sum(d) OVER ( ORDER BY d ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING ) FROM t1 } {1 21 2 20 3 18 4 15 5 11 6 6} do_execsql_test 2.24 { SELECT a, sum(d) OVER ( PARTITION BY a%2 ORDER BY d ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING ) FROM t1 } {2 12 4 10 6 6 1 9 3 8 5 5} do_execsql_test 2.25 { SELECT a, sum(d) OVER ( ORDER BY d ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) FROM t1 } {1 21 2 21 3 21 4 21 5 21 6 21} do_execsql_test 2.26 { SELECT a, sum(d) OVER ( PARTITION BY b ORDER BY d ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) FROM t1 } {2 12 4 12 6 12 1 9 3 9 5 9} do_execsql_test 2.27 { SELECT a, sum(d) OVER ( ORDER BY d ROWS BETWEEN CURRENT ROW AND CURRENT ROW ) FROM t1 } {1 1 2 2 3 3 4 4 5 5 6 6} do_execsql_test 2.28 { SELECT a, sum(d) OVER ( PARTITION BY b ORDER BY d ROWS BETWEEN CURRENT ROW AND CURRENT ROW ) FROM t1 } {2 2 4 4 6 6 1 1 3 3 5 5} do_execsql_test 2.29 { SELECT a, sum(d) OVER ( ORDER BY d RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING ) FROM t1 } {1 21 2 20 3 18 4 15 5 11 6 6} do_execsql_test 2.30 { SELECT a, sum(d) OVER ( ORDER BY b RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING ) FROM t1 } {2 21 4 21 6 21 1 9 3 9 5 9} do_execsql_test 3.1 { SELECT a, sum(d) OVER ( PARTITION BY b ORDER BY d RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING ) FROM t1 } {2 12 4 10 6 6 1 9 3 8 5 5} do_execsql_test 3.2 { SELECT a, sum(d) OVER ( ORDER BY b RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING ) FROM t1 } {2 21 4 21 6 21 1 9 3 9 5 9} do_execsql_test 3.3 { SELECT a, sum(d) OVER ( ORDER BY d ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) FROM t1 } {1 21 2 21 3 21 4 21 5 21 6 21} do_execsql_test 3.4 { SELECT a, sum(d) OVER ( ORDER BY d/2 ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) FROM t1 } {1 1 2 3 3 6 4 10 5 15 6 21} #========================================================================== do_execsql_test 4.0 { DROP TABLE IF EXISTS t2; CREATE TABLE t2(a INTEGER PRIMARY KEY, b INTEGER); INSERT INTO t2(a, b) VALUES (1,0), (2,74), (3,41), (4,74), (5,23), (6,99), (7,26), (8,33), (9,2), (10,89), (11,81), (12,96), (13,59), (14,38), (15,68), (16,39), (17,62), (18,91), (19,46), (20,6), (21,99), (22,97), (23,27), (24,46), (25,78), (26,54), (27,97), (28,8), (29,67), (30,29), (31,93), (32,84), (33,77), (34,23), (35,16), (36,16), (37,93), (38,65), (39,35), (40,47), (41,7), (42,86), (43,74), (44,61), (45,91), (46,85), (47,24), (48,85), (49,43), (50,59), (51,12), (52,32), (53,56), (54,3), (55,91), (56,22), (57,90), (58,55), (59,15), (60,28), (61,89), (62,25), (63,47), (64,1), (65,56), (66,40), (67,43), (68,56), (69,16), (70,75), (71,36), (72,89), (73,98), (74,76), (75,81), (76,4), (77,94), (78,42), (79,30), (80,78), (81,33), (82,29), (83,53), (84,63), (85,2), (86,87), (87,37), (88,80), (89,84), (90,72), (91,41), (92,9), (93,61), (94,73), (95,95), (96,65), (97,13), (98,58), (99,96), (100,98), (101,1), (102,21), (103,74), (104,65), (105,35), (106,5), (107,73), (108,11), (109,51), (110,87), (111,41), (112,12), (113,8), (114,20), (115,31), (116,31), (117,15), (118,95), (119,22), (120,73), (121,79), (122,88), (123,34), (124,8), (125,11), (126,49), (127,34), (128,90), (129,59), (130,96), (131,60), (132,55), (133,75), (134,77), (135,44), (136,2), (137,7), (138,85), (139,57), (140,74), (141,29), (142,70), (143,59), (144,19), (145,39), (146,26), (147,26), (148,47), (149,80), (150,90), (151,36), (152,58), (153,47), (154,9), (155,72), (156,72), (157,66), (158,33), (159,93), (160,75), (161,64), (162,81), (163,9), (164,23), (165,37), (166,13), (167,12), (168,14), (169,62), (170,91), (171,36), (172,91), (173,33), (174,15), (175,34), (176,36), (177,99), (178,3), (179,95), (180,69), (181,58), (182,52), (183,30), (184,50), (185,84), (186,10), (187,84), (188,33), (189,21), (190,39), (191,44), (192,58), (193,30), (194,38), (195,34), (196,83), (197,27), (198,82), (199,17), (200,7); } {} do_execsql_test 4.1 { SELECT a, sum(b) OVER ( PARTITION BY (b%10) ORDER BY b ) FROM t2 ORDER BY a; } {1 0 2 754 3 251 4 754 5 101 6 1247 7 132 8 266 9 6 10 950 11 667 12 1052 13 535 14 128 15 428 16 250 17 336 18 1122 19 368 20 6 21 1247 22 1000 23 92 24 368 25 584 26 320 27 1000 28 24 29 478 30 133 31 1049 32 1090 33 632 34 101 35 54 36 54 37 1049 38 450 39 145 40 354 41 21 42 764 43 754 44 424 45 1122 46 930 47 42 48 930 49 352 50 535 51 42 52 118 53 536 54 6 55 1122 56 86 57 770 58 255 59 50 60 52 61 950 62 75 63 354 64 2 65 536 66 160 67 352 68 536 69 54 70 675 71 276 72 950 73 868 74 678 75 667 76 4 77 1184 78 160 79 120 80 584 81 266 82 133 83 405 84 468 85 6 86 806 87 166 88 500 89 1090 90 552 91 251 92 27 93 424 94 687 95 1215 96 450 97 32 98 360 99 1052 100 868 101 2 102 66 103 754 104 450 105 145 106 5 107 687 108 24 109 302 110 806 111 251 112 42 113 24 114 30 115 128 116 128 117 50 118 1215 119 86 120 687 121 683 122 672 123 178 124 24 125 24 126 299 127 178 128 770 129 535 130 1052 131 270 132 255 133 675 134 632 135 266 136 6 137 21 138 930 139 411 140 754 141 133 142 340 143 535 144 46 145 250 146 132 147 132 148 354 149 500 150 770 151 276 152 360 153 354 154 27 155 552 156 552 157 602 158 266 159 1049 160 675 161 384 162 667 163 27 164 101 165 166 166 32 167 42 168 18 169 336 170 1122 171 276 172 1122 173 266 174 50 175 178 176 276 177 1247 178 6 179 1215 180 604 181 360 182 212 183 120 184 210 185 1090 186 10 187 1090 188 266 189 66 190 250 191 266 192 360 193 120 194 128 195 178 196 770 197 92 198 634 199 38 200 21} do_execsql_test 4.2 { SELECT a, sum(b) OVER ( PARTITION BY (b%10) ORDER BY b RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) FROM t2 ORDER BY a; } {1 0 2 754 3 251 4 754 5 101 6 1247 7 132 8 266 9 6 10 950 11 667 12 1052 13 535 14 128 15 428 16 250 17 336 18 1122 19 368 20 6 21 1247 22 1000 23 92 24 368 25 584 26 320 27 1000 28 24 29 478 30 133 31 1049 32 1090 33 632 34 101 35 54 36 54 37 1049 38 450 39 145 40 354 41 21 42 764 43 754 44 424 45 1122 46 930 47 42 48 930 49 352 50 535 51 42 52 118 53 536 54 6 55 1122 56 86 57 770 58 255 59 50 60 52 61 950 62 75 63 354 64 2 65 536 66 160 67 352 68 536 69 54 70 675 71 276 72 950 73 868 74 678 75 667 76 4 77 1184 78 160 79 120 80 584 81 266 82 133 83 405 84 468 85 6 86 806 87 166 88 500 89 1090 90 552 91 251 92 27 93 424 94 687 95 1215 96 450 97 32 98 360 99 1052 100 868 101 2 102 66 103 754 104 450 105 145 106 5 107 687 108 24 109 302 110 806 111 251 112 42 113 24 114 30 115 128 116 128 117 50 118 1215 119 86 120 687 121 683 122 672 123 178 124 24 125 24 126 299 127 178 128 770 129 535 130 1052 131 270 132 255 133 675 134 632 135 266 136 6 137 21 138 930 139 411 140 754 141 133 142 340 143 535 144 46 145 250 146 132 147 132 148 354 149 500 150 770 151 276 152 360 153 354 154 27 155 552 156 552 157 602 158 266 159 1049 160 675 161 384 162 667 163 27 164 101 165 166 166 32 167 42 168 18 169 336 170 1122 171 276 172 1122 173 266 174 50 175 178 176 276 177 1247 178 6 179 1215 180 604 181 360 182 212 183 120 184 210 185 1090 186 10 187 1090 188 266 189 66 190 250 191 266 192 360 193 120 194 128 195 178 196 770 197 92 198 634 199 38 200 21} do_execsql_test 4.3 { SELECT b, sum(b) OVER ( ORDER BY b ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) FROM t2 ORDER BY b; } {0 0 1 1 1 2 2 4 2 6 2 8 3 11 3 14 4 18 5 23 6 29 7 36 7 43 7 50 8 58 8 66 8 74 9 83 9 92 9 101 10 111 11 122 11 133 12 145 12 157 12 169 13 182 13 195 14 209 15 224 15 239 15 254 16 270 16 286 16 302 17 319 19 338 20 358 21 379 21 400 22 422 22 444 23 467 23 490 23 513 24 537 25 562 26 588 26 614 26 640 27 667 27 694 28 722 29 751 29 780 29 809 30 839 30 869 30 899 31 930 31 961 32 993 33 1026 33 1059 33 1092 33 1125 33 1158 34 1192 34 1226 34 1260 34 1294 35 1329 35 1364 36 1400 36 1436 36 1472 36 1508 37 1545 37 1582 38 1620 38 1658 39 1697 39 1736 39 1775 40 1815 41 1856 41 1897 41 1938 42 1980 43 2023 43 2066 44 2110 44 2154 46 2200 46 2246 47 2293 47 2340 47 2387 47 2434 49 2483 50 2533 51 2584 52 2636 53 2689 54 2743 55 2798 55 2853 56 2909 56 2965 56 3021 57 3078 58 3136 58 3194 58 3252 58 3310 59 3369 59 3428 59 3487 59 3546 60 3606 61 3667 61 3728 62 3790 62 3852 63 3915 64 3979 65 4044 65 4109 65 4174 66 4240 67 4307 68 4375 69 4444 70 4514 72 4586 72 4658 72 4730 73 4803 73 4876 73 4949 74 5023 74 5097 74 5171 74 5245 74 5319 75 5394 75 5469 75 5544 76 5620 77 5697 77 5774 78 5852 78 5930 79 6009 80 6089 80 6169 81 6250 81 6331 81 6412 82 6494 83 6577 84 6661 84 6745 84 6829 84 6913 85 6998 85 7083 85 7168 86 7254 87 7341 87 7428 88 7516 89 7605 89 7694 89 7783 90 7873 90 7963 90 8053 91 8144 91 8235 91 8326 91 8417 91 8508 93 8601 93 8694 93 8787 94 8881 95 8976 95 9071 95 9166 96 9262 96 9358 96 9454 97 9551 97 9648 98 9746 98 9844 99 9943 99 10042 99 10141} do_execsql_test 4.4 { SELECT b, sum(b) OVER ( ORDER BY b RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) FROM t2 ORDER BY b; } {0 10141 1 10141 1 10141 2 10141 2 10141 2 10141 3 10141 3 10141 4 10141 5 10141 6 10141 7 10141 7 10141 7 10141 8 10141 8 10141 8 10141 9 10141 9 10141 9 10141 10 10141 11 10141 11 10141 12 10141 12 10141 12 10141 13 10141 13 10141 14 10141 15 10141 15 10141 15 10141 16 10141 16 10141 16 10141 17 10141 19 10141 20 10141 21 10141 21 10141 22 10141 22 10141 23 10141 23 10141 23 10141 24 10141 25 10141 26 10141 26 10141 26 10141 27 10141 27 10141 28 10141 29 10141 29 10141 29 10141 30 10141 30 10141 30 10141 31 10141 31 10141 32 10141 33 10141 33 10141 33 10141 33 10141 33 10141 34 10141 34 10141 34 10141 34 10141 35 10141 35 10141 36 10141 36 10141 36 10141 36 10141 37 10141 37 10141 38 10141 38 10141 39 10141 39 10141 39 10141 40 10141 41 10141 41 10141 41 10141 42 10141 43 10141 43 10141 44 10141 44 10141 46 10141 46 10141 47 10141 47 10141 47 10141 47 10141 49 10141 50 10141 51 10141 52 10141 53 10141 54 10141 55 10141 55 10141 56 10141 56 10141 56 10141 57 10141 58 10141 58 10141 58 10141 58 10141 59 10141 59 10141 59 10141 59 10141 60 10141 61 10141 61 10141 62 10141 62 10141 63 10141 64 10141 65 10141 65 10141 65 10141 66 10141 67 10141 68 10141 69 10141 70 10141 72 10141 72 10141 72 10141 73 10141 73 10141 73 10141 74 10141 74 10141 74 10141 74 10141 74 10141 75 10141 75 10141 75 10141 76 10141 77 10141 77 10141 78 10141 78 10141 79 10141 80 10141 80 10141 81 10141 81 10141 81 10141 82 10141 83 10141 84 10141 84 10141 84 10141 84 10141 85 10141 85 10141 85 10141 86 10141 87 10141 87 10141 88 10141 89 10141 89 10141 89 10141 90 10141 90 10141 90 10141 91 10141 91 10141 91 10141 91 10141 91 10141 93 10141 93 10141 93 10141 94 10141 95 10141 95 10141 95 10141 96 10141 96 10141 96 10141 97 10141 97 10141 98 10141 98 10141 99 10141 99 10141 99 10141} do_execsql_test 4.5 { SELECT b, sum(b) OVER ( ORDER BY b RANGE BETWEEN CURRENT ROW AND CURRENT ROW ) FROM t2 ORDER BY b; } {0 0 1 2 1 2 2 6 2 6 2 6 3 6 3 6 4 4 5 5 6 6 7 21 7 21 7 21 8 24 8 24 8 24 9 27 9 27 9 27 10 10 11 22 11 22 12 36 12 36 12 36 13 26 13 26 14 14 15 45 15 45 15 45 16 48 16 48 16 48 17 17 19 19 20 20 21 42 21 42 22 44 22 44 23 69 23 69 23 69 24 24 25 25 26 78 26 78 26 78 27 54 27 54 28 28 29 87 29 87 29 87 30 90 30 90 30 90 31 62 31 62 32 32 33 165 33 165 33 165 33 165 33 165 34 136 34 136 34 136 34 136 35 70 35 70 36 144 36 144 36 144 36 144 37 74 37 74 38 76 38 76 39 117 39 117 39 117 40 40 41 123 41 123 41 123 42 42 43 86 43 86 44 88 44 88 46 92 46 92 47 188 47 188 47 188 47 188 49 49 50 50 51 51 52 52 53 53 54 54 55 110 55 110 56 168 56 168 56 168 57 57 58 232 58 232 58 232 58 232 59 236 59 236 59 236 59 236 60 60 61 122 61 122 62 124 62 124 63 63 64 64 65 195 65 195 65 195 66 66 67 67 68 68 69 69 70 70 72 216 72 216 72 216 73 219 73 219 73 219 74 370 74 370 74 370 74 370 74 370 75 225 75 225 75 225 76 76 77 154 77 154 78 156 78 156 79 79 80 160 80 160 81 243 81 243 81 243 82 82 83 83 84 336 84 336 84 336 84 336 85 255 85 255 85 255 86 86 87 174 87 174 88 88 89 267 89 267 89 267 90 270 90 270 90 270 91 455 91 455 91 455 91 455 91 455 93 279 93 279 93 279 94 94 95 285 95 285 95 285 96 288 96 288 96 288 97 194 97 194 98 196 98 196 99 297 99 297 99 297} do_execsql_test 4.6.1 { SELECT b, sum(b) OVER ( RANGE BETWEEN CURRENT ROW AND CURRENT ROW ) FROM t2 ORDER BY b; } {0 10141 1 10141 1 10141 2 10141 2 10141 2 10141 3 10141 3 10141 4 10141 5 10141 6 10141 7 10141 7 10141 7 10141 8 10141 8 10141 8 10141 9 10141 9 10141 9 10141 10 10141 11 10141 11 10141 12 10141 12 10141 12 10141 13 10141 13 10141 14 10141 15 10141 15 10141 15 10141 16 10141 16 10141 16 10141 17 10141 19 10141 20 10141 21 10141 21 10141 22 10141 22 10141 23 10141 23 10141 23 10141 24 10141 25 10141 26 10141 26 10141 26 10141 27 10141 27 10141 28 10141 29 10141 29 10141 29 10141 30 10141 30 10141 30 10141 31 10141 31 10141 32 10141 33 10141 33 10141 33 10141 33 10141 33 10141 34 10141 34 10141 34 10141 34 10141 35 10141 35 10141 36 10141 36 10141 36 10141 36 10141 37 10141 37 10141 38 10141 38 10141 39 10141 39 10141 39 10141 40 10141 41 10141 41 10141 41 10141 42 10141 43 10141 43 10141 44 10141 44 10141 46 10141 46 10141 47 10141 47 10141 47 10141 47 10141 49 10141 50 10141 51 10141 52 10141 53 10141 54 10141 55 10141 55 10141 56 10141 56 10141 56 10141 57 10141 58 10141 58 10141 58 10141 58 10141 59 10141 59 10141 59 10141 59 10141 60 10141 61 10141 61 10141 62 10141 62 10141 63 10141 64 10141 65 10141 65 10141 65 10141 66 10141 67 10141 68 10141 69 10141 70 10141 72 10141 72 10141 72 10141 73 10141 73 10141 73 10141 74 10141 74 10141 74 10141 74 10141 74 10141 75 10141 75 10141 75 10141 76 10141 77 10141 77 10141 78 10141 78 10141 79 10141 80 10141 80 10141 81 10141 81 10141 81 10141 82 10141 83 10141 84 10141 84 10141 84 10141 84 10141 85 10141 85 10141 85 10141 86 10141 87 10141 87 10141 88 10141 89 10141 89 10141 89 10141 90 10141 90 10141 90 10141 91 10141 91 10141 91 10141 91 10141 91 10141 93 10141 93 10141 93 10141 94 10141 95 10141 95 10141 95 10141 96 10141 96 10141 96 10141 97 10141 97 10141 98 10141 98 10141 99 10141 99 10141 99 10141} do_execsql_test 4.6.2 { SELECT b, sum(b) OVER () FROM t2 ORDER BY b; } {0 10141 1 10141 1 10141 2 10141 2 10141 2 10141 3 10141 3 10141 4 10141 5 10141 6 10141 7 10141 7 10141 7 10141 8 10141 8 10141 8 10141 9 10141 9 10141 9 10141 10 10141 11 10141 11 10141 12 10141 12 10141 12 10141 13 10141 13 10141 14 10141 15 10141 15 10141 15 10141 16 10141 16 10141 16 10141 17 10141 19 10141 20 10141 21 10141 21 10141 22 10141 22 10141 23 10141 23 10141 23 10141 24 10141 25 10141 26 10141 26 10141 26 10141 27 10141 27 10141 28 10141 29 10141 29 10141 29 10141 30 10141 30 10141 30 10141 31 10141 31 10141 32 10141 33 10141 33 10141 33 10141 33 10141 33 10141 34 10141 34 10141 34 10141 34 10141 35 10141 35 10141 36 10141 36 10141 36 10141 36 10141 37 10141 37 10141 38 10141 38 10141 39 10141 39 10141 39 10141 40 10141 41 10141 41 10141 41 10141 42 10141 43 10141 43 10141 44 10141 44 10141 46 10141 46 10141 47 10141 47 10141 47 10141 47 10141 49 10141 50 10141 51 10141 52 10141 53 10141 54 10141 55 10141 55 10141 56 10141 56 10141 56 10141 57 10141 58 10141 58 10141 58 10141 58 10141 59 10141 59 10141 59 10141 59 10141 60 10141 61 10141 61 10141 62 10141 62 10141 63 10141 64 10141 65 10141 65 10141 65 10141 66 10141 67 10141 68 10141 69 10141 70 10141 72 10141 72 10141 72 10141 73 10141 73 10141 73 10141 74 10141 74 10141 74 10141 74 10141 74 10141 75 10141 75 10141 75 10141 76 10141 77 10141 77 10141 78 10141 78 10141 79 10141 80 10141 80 10141 81 10141 81 10141 81 10141 82 10141 83 10141 84 10141 84 10141 84 10141 84 10141 85 10141 85 10141 85 10141 86 10141 87 10141 87 10141 88 10141 89 10141 89 10141 89 10141 90 10141 90 10141 90 10141 91 10141 91 10141 91 10141 91 10141 91 10141 93 10141 93 10141 93 10141 94 10141 95 10141 95 10141 95 10141 96 10141 96 10141 96 10141 97 10141 97 10141 98 10141 98 10141 99 10141 99 10141 99 10141} do_execsql_test 4.6.3 { SELECT b, sum(b) OVER ( RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) FROM t2 ORDER BY b; } {0 10141 1 10141 1 10141 2 10141 2 10141 2 10141 3 10141 3 10141 4 10141 5 10141 6 10141 7 10141 7 10141 7 10141 8 10141 8 10141 8 10141 9 10141 9 10141 9 10141 10 10141 11 10141 11 10141 12 10141 12 10141 12 10141 13 10141 13 10141 14 10141 15 10141 15 10141 15 10141 16 10141 16 10141 16 10141 17 10141 19 10141 20 10141 21 10141 21 10141 22 10141 22 10141 23 10141 23 10141 23 10141 24 10141 25 10141 26 10141 26 10141 26 10141 27 10141 27 10141 28 10141 29 10141 29 10141 29 10141 30 10141 30 10141 30 10141 31 10141 31 10141 32 10141 33 10141 33 10141 33 10141 33 10141 33 10141 34 10141 34 10141 34 10141 34 10141 35 10141 35 10141 36 10141 36 10141 36 10141 36 10141 37 10141 37 10141 38 10141 38 10141 39 10141 39 10141 39 10141 40 10141 41 10141 41 10141 41 10141 42 10141 43 10141 43 10141 44 10141 44 10141 46 10141 46 10141 47 10141 47 10141 47 10141 47 10141 49 10141 50 10141 51 10141 52 10141 53 10141 54 10141 55 10141 55 10141 56 10141 56 10141 56 10141 57 10141 58 10141 58 10141 58 10141 58 10141 59 10141 59 10141 59 10141 59 10141 60 10141 61 10141 61 10141 62 10141 62 10141 63 10141 64 10141 65 10141 65 10141 65 10141 66 10141 67 10141 68 10141 69 10141 70 10141 72 10141 72 10141 72 10141 73 10141 73 10141 73 10141 74 10141 74 10141 74 10141 74 10141 74 10141 75 10141 75 10141 75 10141 76 10141 77 10141 77 10141 78 10141 78 10141 79 10141 80 10141 80 10141 81 10141 81 10141 81 10141 82 10141 83 10141 84 10141 84 10141 84 10141 84 10141 85 10141 85 10141 85 10141 86 10141 87 10141 87 10141 88 10141 89 10141 89 10141 89 10141 90 10141 90 10141 90 10141 91 10141 91 10141 91 10141 91 10141 91 10141 93 10141 93 10141 93 10141 94 10141 95 10141 95 10141 95 10141 96 10141 96 10141 96 10141 97 10141 97 10141 98 10141 98 10141 99 10141 99 10141 99 10141} do_execsql_test 4.6.4 { SELECT b, sum(b) OVER ( RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING ) FROM t2 ORDER BY b; } {0 10141 1 10141 1 10141 2 10141 2 10141 2 10141 3 10141 3 10141 4 10141 5 10141 6 10141 7 10141 7 10141 7 10141 8 10141 8 10141 8 10141 9 10141 9 10141 9 10141 10 10141 11 10141 11 10141 12 10141 12 10141 12 10141 13 10141 13 10141 14 10141 15 10141 15 10141 15 10141 16 10141 16 10141 16 10141 17 10141 19 10141 20 10141 21 10141 21 10141 22 10141 22 10141 23 10141 23 10141 23 10141 24 10141 25 10141 26 10141 26 10141 26 10141 27 10141 27 10141 28 10141 29 10141 29 10141 29 10141 30 10141 30 10141 30 10141 31 10141 31 10141 32 10141 33 10141 33 10141 33 10141 33 10141 33 10141 34 10141 34 10141 34 10141 34 10141 35 10141 35 10141 36 10141 36 10141 36 10141 36 10141 37 10141 37 10141 38 10141 38 10141 39 10141 39 10141 39 10141 40 10141 41 10141 41 10141 41 10141 42 10141 43 10141 43 10141 44 10141 44 10141 46 10141 46 10141 47 10141 47 10141 47 10141 47 10141 49 10141 50 10141 51 10141 52 10141 53 10141 54 10141 55 10141 55 10141 56 10141 56 10141 56 10141 57 10141 58 10141 58 10141 58 10141 58 10141 59 10141 59 10141 59 10141 59 10141 60 10141 61 10141 61 10141 62 10141 62 10141 63 10141 64 10141 65 10141 65 10141 65 10141 66 10141 67 10141 68 10141 69 10141 70 10141 72 10141 72 10141 72 10141 73 10141 73 10141 73 10141 74 10141 74 10141 74 10141 74 10141 74 10141 75 10141 75 10141 75 10141 76 10141 77 10141 77 10141 78 10141 78 10141 79 10141 80 10141 80 10141 81 10141 81 10141 81 10141 82 10141 83 10141 84 10141 84 10141 84 10141 84 10141 85 10141 85 10141 85 10141 86 10141 87 10141 87 10141 88 10141 89 10141 89 10141 89 10141 90 10141 90 10141 90 10141 91 10141 91 10141 91 10141 91 10141 91 10141 93 10141 93 10141 93 10141 94 10141 95 10141 95 10141 95 10141 96 10141 96 10141 96 10141 97 10141 97 10141 98 10141 98 10141 99 10141 99 10141 99 10141} do_execsql_test 4.7.1 { SELECT b, sum(b) OVER ( ROWS BETWEEN CURRENT ROW AND CURRENT ROW ) FROM t2 ORDER BY 1, 2; } {0 0 1 1 1 1 2 2 2 2 2 2 3 3 3 3 4 4 5 5 6 6 7 7 7 7 7 7 8 8 8 8 8 8 9 9 9 9 9 9 10 10 11 11 11 11 12 12 12 12 12 12 13 13 13 13 14 14 15 15 15 15 15 15 16 16 16 16 16 16 17 17 19 19 20 20 21 21 21 21 22 22 22 22 23 23 23 23 23 23 24 24 25 25 26 26 26 26 26 26 27 27 27 27 28 28 29 29 29 29 29 29 30 30 30 30 30 30 31 31 31 31 32 32 33 33 33 33 33 33 33 33 33 33 34 34 34 34 34 34 34 34 35 35 35 35 36 36 36 36 36 36 36 36 37 37 37 37 38 38 38 38 39 39 39 39 39 39 40 40 41 41 41 41 41 41 42 42 43 43 43 43 44 44 44 44 46 46 46 46 47 47 47 47 47 47 47 47 49 49 50 50 51 51 52 52 53 53 54 54 55 55 55 55 56 56 56 56 56 56 57 57 58 58 58 58 58 58 58 58 59 59 59 59 59 59 59 59 60 60 61 61 61 61 62 62 62 62 63 63 64 64 65 65 65 65 65 65 66 66 67 67 68 68 69 69 70 70 72 72 72 72 72 72 73 73 73 73 73 73 74 74 74 74 74 74 74 74 74 74 75 75 75 75 75 75 76 76 77 77 77 77 78 78 78 78 79 79 80 80 80 80 81 81 81 81 81 81 82 82 83 83 84 84 84 84 84 84 84 84 85 85 85 85 85 85 86 86 87 87 87 87 88 88 89 89 89 89 89 89 90 90 90 90 90 90 91 91 91 91 91 91 91 91 91 91 93 93 93 93 93 93 94 94 95 95 95 95 95 95 96 96 96 96 96 96 97 97 97 97 98 98 98 98 99 99 99 99 99 99} do_execsql_test 4.7.2 { SELECT b, sum(b) OVER ( ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) FROM t2 ORDER BY 1, 2; } {0 0 1 3379 1 5443 2 372 2 4473 2 7074 3 2916 3 9096 4 4049 5 5643 6 1047 7 2205 7 7081 7 10141 8 1553 8 5926 8 6422 9 4883 9 7932 9 8497 10 9544 11 5727 11 6433 12 2825 12 5918 12 8582 13 5190 13 8570 14 8596 15 3189 15 6023 15 8924 16 1942 16 1958 16 3590 17 10134 19 7474 20 5946 21 5464 21 9682 22 3029 22 6140 23 212 23 1926 23 8520 24 2626 25 3331 26 337 26 7539 26 7565 27 1270 27 10035 28 3217 29 1649 29 4355 29 7326 30 4215 30 9400 30 9853 31 5977 31 6008 32 2857 33 370 33 4326 33 8175 33 8909 33 9661 34 6414 34 6516 34 8958 34 9925 35 2151 35 5638 36 3701 36 7818 36 8785 36 8994 37 4597 37 8557 38 735 38 9891 39 842 39 7513 39 9721 40 3475 41 115 41 4874 41 5906 42 4185 43 2754 43 3518 44 7072 44 9765 46 1041 46 1316 47 2198 47 3378 47 7612 47 7923 49 6482 50 9450 51 5778 52 9370 53 4408 54 1448 55 3174 55 6876 56 2913 56 3435 56 3574 57 7223 58 5248 58 7876 58 9318 58 9823 59 697 59 2813 59 6665 59 7455 60 6821 61 2426 61 4944 62 904 62 8658 63 4471 64 8407 65 2116 65 5177 65 5603 66 8142 67 1620 68 803 69 9260 70 7396 72 4833 72 8004 72 8076 73 5017 73 5716 73 6213 74 74 74 189 74 2365 74 5538 74 7297 75 3665 75 6951 75 8343 76 3964 77 1903 77 7028 78 1394 78 4293 79 6292 80 4677 80 7692 81 542 81 4045 81 8488 82 10117 83 10008 84 1826 84 4761 84 9534 84 9628 85 2602 85 2711 85 7166 86 2291 87 4560 87 5865 88 6380 89 461 89 3306 89 3790 90 3119 90 6606 90 7782 91 995 91 2517 91 3007 91 8749 91 8876 93 1742 93 2051 93 8268 94 4143 95 5112 95 6118 95 9191 96 638 96 5344 96 6761 97 1243 97 1545 98 3888 98 5442 99 311 99 1146 99 9093} do_execsql_test 4.7.3 { SELECT b, sum(b) OVER ( ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) FROM t2 ORDER BY 1, 2; } {0 10141 1 10141 1 10141 2 10141 2 10141 2 10141 3 10141 3 10141 4 10141 5 10141 6 10141 7 10141 7 10141 7 10141 8 10141 8 10141 8 10141 9 10141 9 10141 9 10141 10 10141 11 10141 11 10141 12 10141 12 10141 12 10141 13 10141 13 10141 14 10141 15 10141 15 10141 15 10141 16 10141 16 10141 16 10141 17 10141 19 10141 20 10141 21 10141 21 10141 22 10141 22 10141 23 10141 23 10141 23 10141 24 10141 25 10141 26 10141 26 10141 26 10141 27 10141 27 10141 28 10141 29 10141 29 10141 29 10141 30 10141 30 10141 30 10141 31 10141 31 10141 32 10141 33 10141 33 10141 33 10141 33 10141 33 10141 34 10141 34 10141 34 10141 34 10141 35 10141 35 10141 36 10141 36 10141 36 10141 36 10141 37 10141 37 10141 38 10141 38 10141 39 10141 39 10141 39 10141 40 10141 41 10141 41 10141 41 10141 42 10141 43 10141 43 10141 44 10141 44 10141 46 10141 46 10141 47 10141 47 10141 47 10141 47 10141 49 10141 50 10141 51 10141 52 10141 53 10141 54 10141 55 10141 55 10141 56 10141 56 10141 56 10141 57 10141 58 10141 58 10141 58 10141 58 10141 59 10141 59 10141 59 10141 59 10141 60 10141 61 10141 61 10141 62 10141 62 10141 63 10141 64 10141 65 10141 65 10141 65 10141 66 10141 67 10141 68 10141 69 10141 70 10141 72 10141 72 10141 72 10141 73 10141 73 10141 73 10141 74 10141 74 10141 74 10141 74 10141 74 10141 75 10141 75 10141 75 10141 76 10141 77 10141 77 10141 78 10141 78 10141 79 10141 80 10141 80 10141 81 10141 81 10141 81 10141 82 10141 83 10141 84 10141 84 10141 84 10141 84 10141 85 10141 85 10141 85 10141 86 10141 87 10141 87 10141 88 10141 89 10141 89 10141 89 10141 90 10141 90 10141 90 10141 91 10141 91 10141 91 10141 91 10141 91 10141 93 10141 93 10141 93 10141 94 10141 95 10141 95 10141 95 10141 96 10141 96 10141 96 10141 97 10141 97 10141 98 10141 98 10141 99 10141 99 10141 99 10141} do_execsql_test 4.7.4 { SELECT b, sum(b) OVER ( ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING ) FROM t2 ORDER BY 1, 2; } {0 10141 1 4699 1 6763 2 3069 2 5670 2 9771 3 1048 3 7228 4 6096 5 4503 6 9100 7 7 7 3067 7 7943 8 3727 8 4223 8 8596 9 1653 9 2218 9 5267 10 607 11 3719 11 4425 12 1571 12 4235 12 7328 13 1584 13 4964 14 1559 15 1232 15 4133 15 6967 16 6567 16 8199 16 8215 17 24 19 2686 20 4215 21 480 21 4698 22 4023 22 7134 23 1644 23 8238 23 9952 24 7539 25 6835 26 2602 26 2628 26 9830 27 133 27 8898 28 6952 29 2844 29 5815 29 8521 30 318 30 771 30 5956 31 4164 31 4195 32 7316 33 513 33 1265 33 1999 33 5848 33 9804 34 250 34 1217 34 3659 34 3761 35 4538 35 8025 36 1183 36 1392 36 2359 36 6476 37 1621 37 5581 38 288 38 9444 39 459 39 2667 39 9338 40 6706 41 4276 41 5308 41 10067 42 5998 43 6666 43 7430 44 420 44 3113 46 8871 46 9146 47 2265 47 2576 47 6810 47 7990 49 3708 50 741 51 4414 52 823 53 5786 54 8747 55 3320 55 7022 56 6623 56 6762 56 7284 57 2975 58 376 58 881 58 2323 58 4951 59 2745 59 3535 59 7387 59 9503 60 3380 61 5258 61 7776 62 1545 62 9299 63 5733 64 1798 65 4603 65 5029 65 8090 66 2065 67 8588 68 9406 69 950 70 2815 72 2137 72 2209 72 5380 73 4001 73 4498 73 5197 74 2918 74 4677 74 7850 74 10026 74 10141 75 1873 75 3265 75 6551 76 6253 77 3190 77 8315 78 5926 78 8825 79 3928 80 2529 80 5544 81 1734 81 6177 81 9680 82 106 83 216 84 597 84 691 84 5464 84 8399 85 3060 85 7515 85 7624 86 7936 87 4363 87 5668 88 3849 89 6440 89 6924 89 9769 90 2449 90 3625 90 7112 91 1356 91 1483 91 7225 91 7715 91 9237 93 1966 93 8183 93 8492 94 6092 95 1045 95 4118 95 5124 96 3476 96 4893 96 9599 97 8693 97 8995 98 4797 98 6351 99 1147 99 9094 99 9929} do_execsql_test 4.8.1 { SELECT b, sum(b) OVER ( ORDER BY a ROWS BETWEEN CURRENT ROW AND CURRENT ROW ) FROM t2 ORDER BY 1, 2; } {0 0 1 1 1 1 2 2 2 2 2 2 3 3 3 3 4 4 5 5 6 6 7 7 7 7 7 7 8 8 8 8 8 8 9 9 9 9 9 9 10 10 11 11 11 11 12 12 12 12 12 12 13 13 13 13 14 14 15 15 15 15 15 15 16 16 16 16 16 16 17 17 19 19 20 20 21 21 21 21 22 22 22 22 23 23 23 23 23 23 24 24 25 25 26 26 26 26 26 26 27 27 27 27 28 28 29 29 29 29 29 29 30 30 30 30 30 30 31 31 31 31 32 32 33 33 33 33 33 33 33 33 33 33 34 34 34 34 34 34 34 34 35 35 35 35 36 36 36 36 36 36 36 36 37 37 37 37 38 38 38 38 39 39 39 39 39 39 40 40 41 41 41 41 41 41 42 42 43 43 43 43 44 44 44 44 46 46 46 46 47 47 47 47 47 47 47 47 49 49 50 50 51 51 52 52 53 53 54 54 55 55 55 55 56 56 56 56 56 56 57 57 58 58 58 58 58 58 58 58 59 59 59 59 59 59 59 59 60 60 61 61 61 61 62 62 62 62 63 63 64 64 65 65 65 65 65 65 66 66 67 67 68 68 69 69 70 70 72 72 72 72 72 72 73 73 73 73 73 73 74 74 74 74 74 74 74 74 74 74 75 75 75 75 75 75 76 76 77 77 77 77 78 78 78 78 79 79 80 80 80 80 81 81 81 81 81 81 82 82 83 83 84 84 84 84 84 84 84 84 85 85 85 85 85 85 86 86 87 87 87 87 88 88 89 89 89 89 89 89 90 90 90 90 90 90 91 91 91 91 91 91 91 91 91 91 93 93 93 93 93 93 94 94 95 95 95 95 95 95 96 96 96 96 96 96 97 97 97 97 98 98 98 98 99 99 99 99 99 99} do_execsql_test 4.8.2 { SELECT b, sum(b) OVER ( ORDER BY a ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) FROM t2 ORDER BY 1, 2; } {0 0 1 3379 1 5443 2 372 2 4473 2 7074 3 2916 3 9096 4 4049 5 5643 6 1047 7 2205 7 7081 7 10141 8 1553 8 5926 8 6422 9 4883 9 7932 9 8497 10 9544 11 5727 11 6433 12 2825 12 5918 12 8582 13 5190 13 8570 14 8596 15 3189 15 6023 15 8924 16 1942 16 1958 16 3590 17 10134 19 7474 20 5946 21 5464 21 9682 22 3029 22 6140 23 212 23 1926 23 8520 24 2626 25 3331 26 337 26 7539 26 7565 27 1270 27 10035 28 3217 29 1649 29 4355 29 7326 30 4215 30 9400 30 9853 31 5977 31 6008 32 2857 33 370 33 4326 33 8175 33 8909 33 9661 34 6414 34 6516 34 8958 34 9925 35 2151 35 5638 36 3701 36 7818 36 8785 36 8994 37 4597 37 8557 38 735 38 9891 39 842 39 7513 39 9721 40 3475 41 115 41 4874 41 5906 42 4185 43 2754 43 3518 44 7072 44 9765 46 1041 46 1316 47 2198 47 3378 47 7612 47 7923 49 6482 50 9450 51 5778 52 9370 53 4408 54 1448 55 3174 55 6876 56 2913 56 3435 56 3574 57 7223 58 5248 58 7876 58 9318 58 9823 59 697 59 2813 59 6665 59 7455 60 6821 61 2426 61 4944 62 904 62 8658 63 4471 64 8407 65 2116 65 5177 65 5603 66 8142 67 1620 68 803 69 9260 70 7396 72 4833 72 8004 72 8076 73 5017 73 5716 73 6213 74 74 74 189 74 2365 74 5538 74 7297 75 3665 75 6951 75 8343 76 3964 77 1903 77 7028 78 1394 78 4293 79 6292 80 4677 80 7692 81 542 81 4045 81 8488 82 10117 83 10008 84 1826 84 4761 84 9534 84 9628 85 2602 85 2711 85 7166 86 2291 87 4560 87 5865 88 6380 89 461 89 3306 89 3790 90 3119 90 6606 90 7782 91 995 91 2517 91 3007 91 8749 91 8876 93 1742 93 2051 93 8268 94 4143 95 5112 95 6118 95 9191 96 638 96 5344 96 6761 97 1243 97 1545 98 3888 98 5442 99 311 99 1146 99 9093} do_execsql_test 4.8.3 { SELECT b, sum(b) OVER ( ORDER BY a ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) FROM t2 ORDER BY 1, 2; } {0 10141 1 10141 1 10141 2 10141 2 10141 2 10141 3 10141 3 10141 4 10141 5 10141 6 10141 7 10141 7 10141 7 10141 8 10141 8 10141 8 10141 9 10141 9 10141 9 10141 10 10141 11 10141 11 10141 12 10141 12 10141 12 10141 13 10141 13 10141 14 10141 15 10141 15 10141 15 10141 16 10141 16 10141 16 10141 17 10141 19 10141 20 10141 21 10141 21 10141 22 10141 22 10141 23 10141 23 10141 23 10141 24 10141 25 10141 26 10141 26 10141 26 10141 27 10141 27 10141 28 10141 29 10141 29 10141 29 10141 30 10141 30 10141 30 10141 31 10141 31 10141 32 10141 33 10141 33 10141 33 10141 33 10141 33 10141 34 10141 34 10141 34 10141 34 10141 35 10141 35 10141 36 10141 36 10141 36 10141 36 10141 37 10141 37 10141 38 10141 38 10141 39 10141 39 10141 39 10141 40 10141 41 10141 41 10141 41 10141 42 10141 43 10141 43 10141 44 10141 44 10141 46 10141 46 10141 47 10141 47 10141 47 10141 47 10141 49 10141 50 10141 51 10141 52 10141 53 10141 54 10141 55 10141 55 10141 56 10141 56 10141 56 10141 57 10141 58 10141 58 10141 58 10141 58 10141 59 10141 59 10141 59 10141 59 10141 60 10141 61 10141 61 10141 62 10141 62 10141 63 10141 64 10141 65 10141 65 10141 65 10141 66 10141 67 10141 68 10141 69 10141 70 10141 72 10141 72 10141 72 10141 73 10141 73 10141 73 10141 74 10141 74 10141 74 10141 74 10141 74 10141 75 10141 75 10141 75 10141 76 10141 77 10141 77 10141 78 10141 78 10141 79 10141 80 10141 80 10141 81 10141 81 10141 81 10141 82 10141 83 10141 84 10141 84 10141 84 10141 84 10141 85 10141 85 10141 85 10141 86 10141 87 10141 87 10141 88 10141 89 10141 89 10141 89 10141 90 10141 90 10141 90 10141 91 10141 91 10141 91 10141 91 10141 91 10141 93 10141 93 10141 93 10141 94 10141 95 10141 95 10141 95 10141 96 10141 96 10141 96 10141 97 10141 97 10141 98 10141 98 10141 99 10141 99 10141 99 10141} do_execsql_test 4.8.4 { SELECT b, sum(b) OVER ( ORDER BY a ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING ) FROM t2 ORDER BY 1, 2; } {0 10141 1 4699 1 6763 2 3069 2 5670 2 9771 3 1048 3 7228 4 6096 5 4503 6 9100 7 7 7 3067 7 7943 8 3727 8 4223 8 8596 9 1653 9 2218 9 5267 10 607 11 3719 11 4425 12 1571 12 4235 12 7328 13 1584 13 4964 14 1559 15 1232 15 4133 15 6967 16 6567 16 8199 16 8215 17 24 19 2686 20 4215 21 480 21 4698 22 4023 22 7134 23 1644 23 8238 23 9952 24 7539 25 6835 26 2602 26 2628 26 9830 27 133 27 8898 28 6952 29 2844 29 5815 29 8521 30 318 30 771 30 5956 31 4164 31 4195 32 7316 33 513 33 1265 33 1999 33 5848 33 9804 34 250 34 1217 34 3659 34 3761 35 4538 35 8025 36 1183 36 1392 36 2359 36 6476 37 1621 37 5581 38 288 38 9444 39 459 39 2667 39 9338 40 6706 41 4276 41 5308 41 10067 42 5998 43 6666 43 7430 44 420 44 3113 46 8871 46 9146 47 2265 47 2576 47 6810 47 7990 49 3708 50 741 51 4414 52 823 53 5786 54 8747 55 3320 55 7022 56 6623 56 6762 56 7284 57 2975 58 376 58 881 58 2323 58 4951 59 2745 59 3535 59 7387 59 9503 60 3380 61 5258 61 7776 62 1545 62 9299 63 5733 64 1798 65 4603 65 5029 65 8090 66 2065 67 8588 68 9406 69 950 70 2815 72 2137 72 2209 72 5380 73 4001 73 4498 73 5197 74 2918 74 4677 74 7850 74 10026 74 10141 75 1873 75 3265 75 6551 76 6253 77 3190 77 8315 78 5926 78 8825 79 3928 80 2529 80 5544 81 1734 81 6177 81 9680 82 106 83 216 84 597 84 691 84 5464 84 8399 85 3060 85 7515 85 7624 86 7936 87 4363 87 5668 88 3849 89 6440 89 6924 89 9769 90 2449 90 3625 90 7112 91 1356 91 1483 91 7225 91 7715 91 9237 93 1966 93 8183 93 8492 94 6092 95 1045 95 4118 95 5124 96 3476 96 4893 96 9599 97 8693 97 8995 98 4797 98 6351 99 1147 99 9094 99 9929} finish_test |
Added test/window3.tcl.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 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 | # 2018 May 19 # # 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. # #*********************************************************************** # source [file join [file dirname $argv0] pg_common.tcl] #========================================================================= start_test window3 "2018 May 31" ifcapable !windowfunc execsql_test 1.0 { DROP TABLE IF EXISTS t2; CREATE TABLE t2(a INTEGER PRIMARY KEY, b INTEGER); INSERT INTO t2(a, b) VALUES (1,0), (2,74), (3,41), (4,74), (5,23), (6,99), (7,26), (8,33), (9,2), (10,89), (11,81), (12,96), (13,59), (14,38), (15,68), (16,39), (17,62), (18,91), (19,46), (20,6), (21,99), (22,97), (23,27), (24,46), (25,78), (26,54), (27,97), (28,8), (29,67), (30,29), (31,93), (32,84), (33,77), (34,23), (35,16), (36,16), (37,93), (38,65), (39,35), (40,47), (41,7), (42,86), (43,74), (44,61), (45,91), (46,85), (47,24), (48,85), (49,43), (50,59), (51,12), (52,32), (53,56), (54,3), (55,91), (56,22), (57,90), (58,55), (59,15), (60,28), (61,89), (62,25), (63,47), (64,1), (65,56), (66,40), (67,43), (68,56), (69,16), (70,75), (71,36), (72,89), (73,98), (74,76), (75,81), (76,4), (77,94), (78,42), (79,30), (80,78), (81,33), (82,29), (83,53), (84,63), (85,2), (86,87), (87,37), (88,80), (89,84), (90,72), (91,41), (92,9), (93,61), (94,73), (95,95), (96,65), (97,13), (98,58), (99,96), (100,98), (101,1), (102,21), (103,74), (104,65), (105,35), (106,5), (107,73), (108,11), (109,51), (110,87), (111,41), (112,12), (113,8), (114,20), (115,31), (116,31), (117,15), (118,95), (119,22), (120,73), (121,79), (122,88), (123,34), (124,8), (125,11), (126,49), (127,34), (128,90), (129,59), (130,96), (131,60), (132,55), (133,75), (134,77), (135,44), (136,2), (137,7), (138,85), (139,57), (140,74), (141,29), (142,70), (143,59), (144,19), (145,39), (146,26), (147,26), (148,47), (149,80), (150,90), (151,36), (152,58), (153,47), (154,9), (155,72), (156,72), (157,66), (158,33), (159,93), (160,75), (161,64), (162,81), (163,9), (164,23), (165,37), (166,13), (167,12), (168,14), (169,62), (170,91), (171,36), (172,91), (173,33), (174,15), (175,34), (176,36), (177,99), (178,3), (179,95), (180,69), (181,58), (182,52), (183,30), (184,50), (185,84), (186,10), (187,84), (188,33), (189,21), (190,39), (191,44), (192,58), (193,30), (194,38), (195,34), (196,83), (197,27), (198,82), (199,17), (200,7); } execsql_test 1.1 { SELECT max(b) OVER ( ORDER BY a ) FROM t2 } foreach {tn window} { 1 "RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW" 2 "RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING" 3 "RANGE BETWEEN CURRENT ROW AND CURRENT ROW" 4 "RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING" 5 "ROWS BETWEEN UNBOUNDED PRECEDING AND 4 PRECEDING" 6 "ROWS BETWEEN 4 PRECEDING AND 2 PRECEDING" 7 "ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW" 8 "ROWS BETWEEN 4 PRECEDING AND CURRENT ROW" 9 "ROWS BETWEEN CURRENT ROW AND CURRENT ROW" 10 "ROWS BETWEEN UNBOUNDED PRECEDING AND 4 FOLLOWING" 11 "ROWS BETWEEN 4 PRECEDING AND 2 FOLLOWING" 12 "ROWS BETWEEN CURRENT ROW AND 4 FOLLOWING" 13 "ROWS BETWEEN 2 FOLLOWING AND 4 FOLLOWING" 14 "ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING" 15 "ROWS BETWEEN 4 PRECEDING AND UNBOUNDED FOLLOWING" 16 "ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING" 17 "ROWS BETWEEN 4 FOLLOWING AND UNBOUNDED FOLLOWING" } { execsql_test 1.$tn.2.1 "SELECT max(b) OVER ( ORDER BY a $window ) FROM t2" execsql_test 1.$tn.2.2 "SELECT min(b) OVER ( ORDER BY a $window ) FROM t2" execsql_test 1.$tn.3.1 " SELECT row_number() OVER ( ORDER BY a $window ) FROM t2 " execsql_test 1.$tn.3.2 " SELECT row_number() OVER ( PARTITION BY b%10 ORDER BY a $window ) FROM t2 " execsql_test 1.$tn.3.3 " SELECT row_number() OVER ( $window ) FROM t2 " execsql_test 1.$tn.4.1 " SELECT dense_rank() OVER ( ORDER BY a $window ) FROM t2 " execsql_test 1.$tn.4.2 " SELECT dense_rank() OVER ( PARTITION BY b%10 ORDER BY a $window ) FROM t2 " execsql_test 1.$tn.4.3 " SELECT dense_rank() OVER ( ORDER BY b $window ) FROM t2 " execsql_test 1.$tn.4.4 " SELECT dense_rank() OVER ( PARTITION BY b%10 ORDER BY b $window ) FROM t2 " execsql_test 1.$tn.4.5 " SELECT dense_rank() OVER ( ORDER BY b%10 $window ) FROM t2 " execsql_test 1.$tn.4.6 " SELECT dense_rank() OVER ( PARTITION BY b%2 ORDER BY b%10 $window ) FROM t2 " execsql_test 1.$tn.5.1 " SELECT rank() OVER ( ORDER BY a $window ) FROM t2 " execsql_test 1.$tn.5.2 " SELECT rank() OVER ( PARTITION BY b%10 ORDER BY a $window ) FROM t2 " execsql_test 1.$tn.5.3 " SELECT rank() OVER ( ORDER BY b $window ) FROM t2 " execsql_test 1.$tn.5.4 " SELECT rank() OVER ( PARTITION BY b%10 ORDER BY b $window ) FROM t2 " execsql_test 1.$tn.5.5 " SELECT rank() OVER ( ORDER BY b%10 $window ) FROM t2 " execsql_test 1.$tn.5.6 " SELECT rank() OVER ( PARTITION BY b%2 ORDER BY b%10 $window ) FROM t2 " execsql_test 1.$tn.6.1 " SELECT row_number() OVER ( PARTITION BY b%2 ORDER BY b%10 $window ), rank() OVER ( PARTITION BY b%2 ORDER BY b%10 $window ), dense_rank() OVER ( PARTITION BY b%2 ORDER BY b%10 $window ) FROM t2 " execsql_float_test 1.$tn.7.1 " SELECT percent_rank() OVER ( ORDER BY a $window ) FROM t2 " execsql_float_test 1.$tn.7.2 " SELECT percent_rank() OVER ( PARTITION BY b%10 ORDER BY a $window ) FROM t2 " execsql_float_test 1.$tn.7.3 " SELECT percent_rank() OVER ( ORDER BY b $window ) FROM t2 " execsql_float_test 1.$tn.7.4 " SELECT percent_rank() OVER ( PARTITION BY b%10 ORDER BY b $window ) FROM t2 " execsql_float_test 1.$tn.7.5 " SELECT percent_rank() OVER ( ORDER BY b%10 $window ) FROM t2 " execsql_float_test 1.$tn.7.6 " SELECT percent_rank() OVER (PARTITION BY b%2 ORDER BY b%10 $window) FROM t2 " execsql_float_test 1.$tn.8.1 " SELECT cume_dist() OVER ( ORDER BY a $window ) FROM t2 " execsql_float_test 1.$tn.8.2 " SELECT cume_dist() OVER ( PARTITION BY b%10 ORDER BY a $window ) FROM t2 " execsql_float_test 1.$tn.8.3 " SELECT cume_dist() OVER ( ORDER BY b $window ) FROM t2 " execsql_float_test 1.$tn.8.4 " SELECT cume_dist() OVER ( PARTITION BY b%10 ORDER BY b $window ) FROM t2 " execsql_float_test 1.$tn.8.5 " SELECT cume_dist() OVER ( ORDER BY b%10 $window ) FROM t2 " execsql_float_test 1.$tn.8.6 " SELECT cume_dist() OVER ( PARTITION BY b%2 ORDER BY b%10 $window ) FROM t2 " execsql_float_test 1.$tn.8.1 " SELECT ntile(100) OVER ( ORDER BY a $window ) FROM t2 " execsql_float_test 1.$tn.8.2 " SELECT ntile(101) OVER ( PARTITION BY b%10 ORDER BY a $window ) FROM t2 " execsql_float_test 1.$tn.8.3 " SELECT ntile(102) OVER ( ORDER BY b,a $window ) FROM t2 " execsql_float_test 1.$tn.8.4 " SELECT ntile(103) OVER ( PARTITION BY b%10 ORDER BY b,a $window ) FROM t2 " execsql_float_test 1.$tn.8.5 " SELECT ntile(104) OVER ( ORDER BY b%10,a $window ) FROM t2 " execsql_float_test 1.$tn.8.6 " SELECT ntile(105) OVER (PARTITION BY b%2,a ORDER BY b%10 $window) FROM t2 " execsql_float_test 1.$tn.8.7 " SELECT ntile(105) OVER ( $window ) FROM t2 " execsql_test 1.$tn.9.1 " SELECT last_value(a+b) OVER ( ORDER BY a $window ) FROM t2 " execsql_test 1.$tn.9.2 " SELECT last_value(a+b) OVER ( PARTITION BY b%10 ORDER BY a $window ) FROM t2 " execsql_test 1.$tn.9.3 " SELECT last_value(a+b) OVER ( ORDER BY b,a $window ) FROM t2 " execsql_test 1.$tn.9.4 " SELECT last_value(a+b) OVER ( PARTITION BY b%10 ORDER BY b,a $window ) FROM t2 " execsql_test 1.$tn.9.5 " SELECT last_value(a+b) OVER ( ORDER BY b%10,a $window ) FROM t2 " execsql_test 1.$tn.9.6 " SELECT last_value(a+b) OVER (PARTITION BY b%2,a ORDER BY b%10 $window) FROM t2 " execsql_test 1.$tn.10.1 " SELECT nth_value(b,b+1) OVER (ORDER BY a $window) FROM t2 " execsql_test 1.$tn.10.2 " SELECT nth_value(b,b+1) OVER (PARTITION BY b%10 ORDER BY a $window) FROM t2 " execsql_test 1.$tn.10.3 " SELECT nth_value(b,b+1) OVER ( ORDER BY b,a $window ) FROM t2 " execsql_test 1.$tn.10.4 " SELECT nth_value(b,b+1) OVER ( PARTITION BY b%10 ORDER BY b,a $window ) FROM t2 " execsql_test 1.$tn.10.5 " SELECT nth_value(b,b+1) OVER ( ORDER BY b%10,a $window ) FROM t2 " execsql_test 1.$tn.10.6 " SELECT nth_value(b,b+1) OVER (PARTITION BY b%2,a ORDER BY b%10 $window) FROM t2 " execsql_test 1.$tn.11.1 " SELECT first_value(b) OVER (ORDER BY a $window) FROM t2 " execsql_test 1.$tn.11.2 " SELECT first_value(b) OVER (PARTITION BY b%10 ORDER BY a $window) FROM t2 " execsql_test 1.$tn.11.3 " SELECT first_value(b) OVER ( ORDER BY b,a $window ) FROM t2 " execsql_test 1.$tn.11.4 " SELECT first_value(b) OVER ( PARTITION BY b%10 ORDER BY b,a $window ) FROM t2 " execsql_test 1.$tn.11.5 " SELECT first_value(b) OVER ( ORDER BY b%10,a $window ) FROM t2 " execsql_test 1.$tn.11.6 " SELECT first_value(b) OVER (PARTITION BY b%2,a ORDER BY b%10 $window) FROM t2 " execsql_test 1.$tn.12.1 " SELECT lead(b,b) OVER (ORDER BY a $window) FROM t2 " execsql_test 1.$tn.12.2 " SELECT lead(b,b) OVER (PARTITION BY b%10 ORDER BY a $window) FROM t2 " execsql_test 1.$tn.12.3 " SELECT lead(b,b) OVER ( ORDER BY b,a $window ) FROM t2 " execsql_test 1.$tn.12.4 " SELECT lead(b,b) OVER ( PARTITION BY b%10 ORDER BY b,a $window ) FROM t2 " execsql_test 1.$tn.12.5 " SELECT lead(b,b) OVER ( ORDER BY b%10,a $window ) FROM t2 " execsql_test 1.$tn.12.6 " SELECT lead(b,b) OVER (PARTITION BY b%2,a ORDER BY b%10 $window) FROM t2 " execsql_test 1.$tn.13.1 " SELECT lag(b,b) OVER (ORDER BY a $window) FROM t2 " execsql_test 1.$tn.13.2 " SELECT lag(b,b) OVER (PARTITION BY b%10 ORDER BY a $window) FROM t2 " execsql_test 1.$tn.13.3 " SELECT lag(b,b) OVER ( ORDER BY b,a $window ) FROM t2 " execsql_test 1.$tn.13.4 " SELECT lag(b,b) OVER ( PARTITION BY b%10 ORDER BY b,a $window ) FROM t2 " execsql_test 1.$tn.13.5 " SELECT lag(b,b) OVER ( ORDER BY b%10,a $window ) FROM t2 " execsql_test 1.$tn.13.6 " SELECT lag(b,b) OVER (PARTITION BY b%2,a ORDER BY b%10 $window) FROM t2 " execsql_test 1.$tn.14.1 " SELECT string_agg(CAST(b AS TEXT), '.') OVER (ORDER BY a $window) FROM t2 " execsql_test 1.$tn.14.2 " SELECT string_agg(CAST(b AS TEXT), '.') OVER (PARTITION BY b%10 ORDER BY a $window) FROM t2 " execsql_test 1.$tn.14.3 " SELECT string_agg(CAST(b AS TEXT), '.') OVER ( ORDER BY b,a $window ) FROM t2 " execsql_test 1.$tn.14.4 " SELECT string_agg(CAST(b AS TEXT), '.') OVER ( PARTITION BY b%10 ORDER BY b,a $window ) FROM t2 " execsql_test 1.$tn.14.5 " SELECT string_agg(CAST(b AS TEXT), '.') OVER ( ORDER BY b%10,a $window ) FROM t2 " execsql_test 1.$tn.14.6 " SELECT string_agg(CAST(b AS TEXT), '.') OVER (PARTITION BY b%2,a ORDER BY b%10 $window) FROM t2 " execsql_test 1.$tn.15.1 " SELECT string_agg(CAST(b AS TEXT), '.') FILTER (WHERE a%2=0) OVER (ORDER BY a $window) FROM t2 " execsql_test 1.$tn.15.2 " SELECT string_agg(CAST(b AS TEXT), '.') FILTER (WHERE 0=1) OVER (ORDER BY a $window) FROM t2 " execsql_test 1.$tn.15.3 " SELECT string_agg(CAST(b AS TEXT), '.') FILTER (WHERE 1=0) OVER (PARTITION BY (a%10) ORDER BY a $window) FROM t2 " execsql_test 1.$tn.15.4 " SELECT string_agg(CAST(b AS TEXT), '.') FILTER (WHERE a%2=0) OVER (PARTITION BY (a%10) ORDER BY a $window) FROM t2 " } finish_test |
Added test/window3.test.
cannot compute difference between binary files
Added test/window4.tcl.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 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 | # 2018 May 19 # # 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. # #*********************************************************************** # source [file join [file dirname $argv0] pg_common.tcl] #========================================================================= start_test window4 "2018 June 04" ifcapable !windowfunc execsql_test 1.0 { DROP TABLE IF EXISTS t3; CREATE TABLE t3(a TEXT PRIMARY KEY); INSERT INTO t3 VALUES('a'), ('b'), ('c'), ('d'), ('e'); INSERT INTO t3 VALUES('f'), ('g'), ('h'), ('i'), ('j'); } for {set i 1} {$i < 20} {incr i} { execsql_test 1.$i "SELECT a, ntile($i) OVER (ORDER BY a) FROM t3" } execsql_test 2.0 { DROP TABLE IF EXISTS t4; CREATE TABLE t4(a INTEGER PRIMARY KEY, b TEXT, c INTEGER); INSERT INTO t4 VALUES(1, 'A', 9); INSERT INTO t4 VALUES(2, 'B', 3); INSERT INTO t4 VALUES(3, 'C', 2); INSERT INTO t4 VALUES(4, 'D', 10); INSERT INTO t4 VALUES(5, 'E', 5); INSERT INTO t4 VALUES(6, 'F', 1); INSERT INTO t4 VALUES(7, 'G', 1); INSERT INTO t4 VALUES(8, 'H', 2); INSERT INTO t4 VALUES(9, 'I', 10); INSERT INTO t4 VALUES(10, 'J', 4); } execsql_test 2.1 { SELECT a, nth_value(b, c) OVER (ORDER BY a) FROM t4 } execsql_test 2.2.1 { SELECT a, lead(b) OVER (ORDER BY a) FROM t4 } execsql_test 2.2.2 { SELECT a, lead(b, 2) OVER (ORDER BY a) FROM t4 } execsql_test 2.2.3 { SELECT a, lead(b, 3, 'abc') OVER (ORDER BY a) FROM t4 } execsql_test 2.3.1 { SELECT a, lag(b) OVER (ORDER BY a) FROM t4 } execsql_test 2.3.2 { SELECT a, lag(b, 2) OVER (ORDER BY a) FROM t4 } execsql_test 2.3.3 { SELECT a, lag(b, 3, 'abc') OVER (ORDER BY a) FROM t4 } execsql_test 2.4.1 { SELECT string_agg(b, '.') OVER ( ORDER BY a ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING ) FROM t4 } execsql_test 3.0 { DROP TABLE IF EXISTS t5; CREATE TABLE t5(a INTEGER PRIMARY KEY, b TEXT, c TEXT, d INTEGER); INSERT INTO t5 VALUES(1, 'A', 'one', 5); INSERT INTO t5 VALUES(2, 'B', 'two', 4); INSERT INTO t5 VALUES(3, 'A', 'three', 3); INSERT INTO t5 VALUES(4, 'B', 'four', 2); INSERT INTO t5 VALUES(5, 'A', 'five', 1); } execsql_test 3.1 { SELECT a, nth_value(c, d) OVER (ORDER BY b) FROM t5 } execsql_test 3.2 { SELECT a, nth_value(c, d) OVER (PARTITION BY b ORDER BY a) FROM t5 } execsql_test 3.3 { SELECT a, count(*) OVER abc, count(*) OVER def FROM t5 WINDOW abc AS (ORDER BY a), def AS (ORDER BY a DESC) ORDER BY a; } execsql_test 3.4 { SELECT a, max(a) FILTER (WHERE (a%2)=0) OVER w FROM t5 WINDOW w AS (ORDER BY a) } execsql_test 3.5.1 { SELECT a, max(c) OVER (ORDER BY a ROWS BETWEEN 1 PRECEDING AND 2 PRECEDING) FROM t5 } execsql_test 3.5.2 { SELECT a, max(c) OVER (ORDER BY a ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) FROM t5 } execsql_test 3.5.3 { SELECT a, max(c) OVER (ORDER BY a ROWS BETWEEN 0 PRECEDING AND 0 PRECEDING) FROM t5 } execsql_test 3.6.1 { SELECT a, max(c) OVER (ORDER BY a ROWS BETWEEN 2 FOLLOWING AND 1 FOLLOWING) FROM t5 } execsql_test 3.6.2 { SELECT a, max(c) OVER (ORDER BY a ROWS BETWEEN 1 FOLLOWING AND 1 FOLLOWING) FROM t5 } execsql_test 3.6.3 { SELECT a, max(c) OVER (ORDER BY a ROWS BETWEEN 0 FOLLOWING AND 0 FOLLOWING) FROM t5 } ========== execsql_test 4.0 { DROP TABLE IF EXISTS ttt; CREATE TABLE ttt(a INTEGER PRIMARY KEY, b INTEGER, c INTEGER); INSERT INTO ttt VALUES(1, 1, 1); INSERT INTO ttt VALUES(2, 2, 2); INSERT INTO ttt VALUES(3, 3, 3); INSERT INTO ttt VALUES(4, 1, 2); INSERT INTO ttt VALUES(5, 2, 3); INSERT INTO ttt VALUES(6, 3, 4); INSERT INTO ttt VALUES(7, 1, 3); INSERT INTO ttt VALUES(8, 2, 4); INSERT INTO ttt VALUES(9, 3, 5); } execsql_test 4.1 { SELECT max(c), max(b) OVER (ORDER BY b) FROM ttt GROUP BY b; } execsql_test 4.2 { SELECT max(b) OVER (ORDER BY max(c)) FROM ttt GROUP BY b; } execsql_test 4.3 { SELECT abs(max(b) OVER (ORDER BY b)) FROM ttt GROUP BY b; } execsql_test 4.4 { SELECT sum(b) OVER ( ORDER BY a RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING ) FROM ttt; } set lPart [list "PARTITION BY b" "PARTITION BY b, a" "" "PARTITION BY a"] set lOrder [list "ORDER BY a" "ORDER BY a DESC" "" "ORDER BY b, a"] set lRange { "RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW" "RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING" "RANGE BETWEEN CURRENT ROW AND CURRENT ROW" "RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING" } set lRows { "ROWS BETWEEN 3 PRECEDING AND 1 FOLLOWING" "ROWS BETWEEN 3 PRECEDING AND 2 FOLLOWING" "ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING" "ROWS BETWEEN 0 PRECEDING AND 1 PRECEDING" "ROWS BETWEEN 1 FOLLOWING AND 500 FOLLOWING" } set tn 1 set SQL { SELECT max(c) OVER ($p1 $o1 $r1), min(c) OVER ($p2 $o2 $r2) FROM ttt ORDER BY a } set SQL2 { SELECT sum(c) OVER ($p1 $o1 $r1), sum(c) OVER ($p2 $o2 $r2) FROM ttt ORDER BY a } set o1 [lindex $lOrder 0] set o2 [lindex $lOrder 0] set r1 [lindex $lRange 0] set r2 [lindex $lRange 0] foreach p1 $lPart { foreach p2 $lPart { execsql_test 4.5.$tn.1 [subst $SQL] execsql_test 4.5.$tn.2 [subst $SQL2] incr tn }} set o1 [lindex $lOrder 0] set o2 [lindex $lOrder 0] set p1 [lindex $lPart 0] set p2 [lindex $lPart 0] foreach r1 $lRange { foreach r2 $lRange { execsql_test 4.5.$tn.1 [subst $SQL] execsql_test 4.5.$tn.2 [subst $SQL2] incr tn }} foreach r1 $lRows { foreach r2 $lRows { execsql_test 4.5.$tn.1 [subst $SQL] execsql_test 4.5.$tn.2 [subst $SQL2] incr tn }} set r1 [lindex $lRange 0] set r2 [lindex $lRange 0] set p1 [lindex $lPart 0] set p2 [lindex $lPart 0] foreach o1 $lOrder { foreach o2 $lOrder { execsql_test 4.5.$tn.1 [subst $SQL] execsql_test 4.5.$tn.2 [subst $SQL2] incr tn }} ========== execsql_test 7.0 { DROP TABLE IF EXISTS t1; CREATE TABLE t1(x INTEGER, y INTEGER); INSERT INTO t1 VALUES(1, 2); INSERT INTO t1 VALUES(3, 4); INSERT INTO t1 VALUES(5, 6); INSERT INTO t1 VALUES(7, 8); INSERT INTO t1 VALUES(9, 10); } execsql_test 7.1 { SELECT lead(y) OVER win FROM t1 WINDOW win AS (ORDER BY x) } execsql_test 7.2 { SELECT lead(y, 2) OVER win FROM t1 WINDOW win AS (ORDER BY x) } execsql_test 7.3 { SELECT lead(y, 3, -1) OVER win FROM t1 WINDOW win AS (ORDER BY x) } execsql_test 7.4 { SELECT lead(y) OVER win, lead(y) OVER win FROM t1 WINDOW win AS (ORDER BY x) } execsql_test 7.5 { SELECT lead(y) OVER win, lead(y, 2) OVER win, lead(y, 3, -1) OVER win FROM t1 WINDOW win AS (ORDER BY x) } ========== execsql_test 8.0 { DROP TABLE IF EXISTS t1; CREATE TABLE t1(a INTEGER, b INTEGER, c INTEGER, d INTEGER); INSERT INTO t1 VALUES(1, 2, 3, 4); INSERT INTO t1 VALUES(5, 6, 7, 8); INSERT INTO t1 VALUES(9, 10, 11, 12); } execsql_test 8.1 { SELECT row_number() OVER win, nth_value(d,2) OVER win, lead(d) OVER win FROM t1 WINDOW win AS (ORDER BY a) } execsql_test 8.2 { SELECT row_number() OVER win, rank() OVER win, dense_rank() OVER win, ntile(2) OVER win, first_value(d) OVER win, last_value(d) OVER win, nth_value(d,2) OVER win, lead(d) OVER win, lag(d) OVER win, max(d) OVER win, min(d) OVER win FROM t1 WINDOW win AS (ORDER BY a) } ========== execsql_test 9.0 { DROP TABLE IF EXISTS t2; CREATE TABLE t2(x INTEGER); INSERT INTO t2 VALUES(1), (1), (1), (4), (4), (6), (7); } execsql_test 9.1 { SELECT rank() OVER () FROM t2 } execsql_test 9.2 { SELECT dense_rank() OVER (PARTITION BY x) FROM t2 } execsql_float_test 9.3 { SELECT x, percent_rank() OVER (PARTITION BY x ORDER BY x) FROM t2 } execsql_test 9.4 { SELECT x, rank() OVER (ORDER BY x) FROM t2 ORDER BY 1,2 } execsql_test 9.5 { SELECT DISTINCT x, rank() OVER (ORDER BY x) FROM t2 ORDER BY 1,2 } finish_test |
Added test/window4.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 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 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 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 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 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 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 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 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 | # 2018 June 04 # # 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. # #*********************************************************************** # This file implements regression tests for SQLite library. # #################################################### # DO NOT EDIT! THIS FILE IS AUTOMATICALLY GENERATED! #################################################### set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix window4 ifcapable !windowfunc { finish_test ; return } do_execsql_test 1.0 { DROP TABLE IF EXISTS t3; CREATE TABLE t3(a TEXT PRIMARY KEY); INSERT INTO t3 VALUES('a'), ('b'), ('c'), ('d'), ('e'); INSERT INTO t3 VALUES('f'), ('g'), ('h'), ('i'), ('j'); } {} do_execsql_test 1.1 { SELECT a, ntile(1) OVER (ORDER BY a) FROM t3 } {a 1 b 1 c 1 d 1 e 1 f 1 g 1 h 1 i 1 j 1} do_execsql_test 1.2 { SELECT a, ntile(2) OVER (ORDER BY a) FROM t3 } {a 1 b 1 c 1 d 1 e 1 f 2 g 2 h 2 i 2 j 2} do_execsql_test 1.3 { SELECT a, ntile(3) OVER (ORDER BY a) FROM t3 } {a 1 b 1 c 1 d 1 e 2 f 2 g 2 h 3 i 3 j 3} do_execsql_test 1.4 { SELECT a, ntile(4) OVER (ORDER BY a) FROM t3 } {a 1 b 1 c 1 d 2 e 2 f 2 g 3 h 3 i 4 j 4} do_execsql_test 1.5 { SELECT a, ntile(5) OVER (ORDER BY a) FROM t3 } {a 1 b 1 c 2 d 2 e 3 f 3 g 4 h 4 i 5 j 5} do_execsql_test 1.6 { SELECT a, ntile(6) OVER (ORDER BY a) FROM t3 } {a 1 b 1 c 2 d 2 e 3 f 3 g 4 h 4 i 5 j 6} do_execsql_test 1.7 { SELECT a, ntile(7) OVER (ORDER BY a) FROM t3 } {a 1 b 1 c 2 d 2 e 3 f 3 g 4 h 5 i 6 j 7} do_execsql_test 1.8 { SELECT a, ntile(8) OVER (ORDER BY a) FROM t3 } {a 1 b 1 c 2 d 2 e 3 f 4 g 5 h 6 i 7 j 8} do_execsql_test 1.9 { SELECT a, ntile(9) OVER (ORDER BY a) FROM t3 } {a 1 b 1 c 2 d 3 e 4 f 5 g 6 h 7 i 8 j 9} do_execsql_test 1.10 { SELECT a, ntile(10) OVER (ORDER BY a) FROM t3 } {a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10} do_execsql_test 1.11 { SELECT a, ntile(11) OVER (ORDER BY a) FROM t3 } {a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10} do_execsql_test 1.12 { SELECT a, ntile(12) OVER (ORDER BY a) FROM t3 } {a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10} do_execsql_test 1.13 { SELECT a, ntile(13) OVER (ORDER BY a) FROM t3 } {a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10} do_execsql_test 1.14 { SELECT a, ntile(14) OVER (ORDER BY a) FROM t3 } {a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10} do_execsql_test 1.15 { SELECT a, ntile(15) OVER (ORDER BY a) FROM t3 } {a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10} do_execsql_test 1.16 { SELECT a, ntile(16) OVER (ORDER BY a) FROM t3 } {a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10} do_execsql_test 1.17 { SELECT a, ntile(17) OVER (ORDER BY a) FROM t3 } {a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10} do_execsql_test 1.18 { SELECT a, ntile(18) OVER (ORDER BY a) FROM t3 } {a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10} do_execsql_test 1.19 { SELECT a, ntile(19) OVER (ORDER BY a) FROM t3 } {a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10} do_execsql_test 2.0 { DROP TABLE IF EXISTS t4; CREATE TABLE t4(a INTEGER PRIMARY KEY, b TEXT, c INTEGER); INSERT INTO t4 VALUES(1, 'A', 9); INSERT INTO t4 VALUES(2, 'B', 3); INSERT INTO t4 VALUES(3, 'C', 2); INSERT INTO t4 VALUES(4, 'D', 10); INSERT INTO t4 VALUES(5, 'E', 5); INSERT INTO t4 VALUES(6, 'F', 1); INSERT INTO t4 VALUES(7, 'G', 1); INSERT INTO t4 VALUES(8, 'H', 2); INSERT INTO t4 VALUES(9, 'I', 10); INSERT INTO t4 VALUES(10, 'J', 4); } {} do_execsql_test 2.1 { SELECT a, nth_value(b, c) OVER (ORDER BY a) FROM t4 } {1 {} 2 {} 3 B 4 {} 5 E 6 A 7 A 8 B 9 {} 10 D} do_execsql_test 2.2.1 { SELECT a, lead(b) OVER (ORDER BY a) FROM t4 } {1 B 2 C 3 D 4 E 5 F 6 G 7 H 8 I 9 J 10 {}} do_execsql_test 2.2.2 { SELECT a, lead(b, 2) OVER (ORDER BY a) FROM t4 } {1 C 2 D 3 E 4 F 5 G 6 H 7 I 8 J 9 {} 10 {}} do_execsql_test 2.2.3 { SELECT a, lead(b, 3, 'abc') OVER (ORDER BY a) FROM t4 } {1 D 2 E 3 F 4 G 5 H 6 I 7 J 8 abc 9 abc 10 abc} do_execsql_test 2.3.1 { SELECT a, lag(b) OVER (ORDER BY a) FROM t4 } {1 {} 2 A 3 B 4 C 5 D 6 E 7 F 8 G 9 H 10 I} do_execsql_test 2.3.2 { SELECT a, lag(b, 2) OVER (ORDER BY a) FROM t4 } {1 {} 2 {} 3 A 4 B 5 C 6 D 7 E 8 F 9 G 10 H} do_execsql_test 2.3.3 { SELECT a, lag(b, 3, 'abc') OVER (ORDER BY a) FROM t4 } {1 abc 2 abc 3 abc 4 A 5 B 6 C 7 D 8 E 9 F 10 G} do_execsql_test 2.4.1 { SELECT group_concat(b, '.') OVER ( ORDER BY a ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING ) FROM t4 } {A.B.C.D.E.F.G.H.I.J B.C.D.E.F.G.H.I.J C.D.E.F.G.H.I.J D.E.F.G.H.I.J E.F.G.H.I.J F.G.H.I.J G.H.I.J H.I.J I.J J} do_execsql_test 3.0 { DROP TABLE IF EXISTS t5; CREATE TABLE t5(a INTEGER PRIMARY KEY, b TEXT, c TEXT, d INTEGER); INSERT INTO t5 VALUES(1, 'A', 'one', 5); INSERT INTO t5 VALUES(2, 'B', 'two', 4); INSERT INTO t5 VALUES(3, 'A', 'three', 3); INSERT INTO t5 VALUES(4, 'B', 'four', 2); INSERT INTO t5 VALUES(5, 'A', 'five', 1); } {} do_execsql_test 3.1 { SELECT a, nth_value(c, d) OVER (ORDER BY b) FROM t5 } {1 {} 3 five 5 one 2 two 4 three} do_execsql_test 3.2 { SELECT a, nth_value(c, d) OVER (PARTITION BY b ORDER BY a) FROM t5 } {1 {} 3 {} 5 one 2 {} 4 four} do_execsql_test 3.3 { SELECT a, count(*) OVER abc, count(*) OVER def FROM t5 WINDOW abc AS (ORDER BY a), def AS (ORDER BY a DESC) ORDER BY a; } {1 1 5 2 2 4 3 3 3 4 4 2 5 5 1} do_execsql_test 3.4 { SELECT a, max(a) FILTER (WHERE (a%2)=0) OVER w FROM t5 WINDOW w AS (ORDER BY a) } {1 {} 2 2 3 2 4 4 5 4} do_execsql_test 3.5.1 { SELECT a, max(c) OVER (ORDER BY a ROWS BETWEEN 1 PRECEDING AND 2 PRECEDING) FROM t5 } {1 {} 2 {} 3 {} 4 {} 5 {}} do_execsql_test 3.5.2 { SELECT a, max(c) OVER (ORDER BY a ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) FROM t5 } {1 {} 2 one 3 two 4 three 5 four} do_execsql_test 3.5.3 { SELECT a, max(c) OVER (ORDER BY a ROWS BETWEEN 0 PRECEDING AND 0 PRECEDING) FROM t5 } {1 one 2 two 3 three 4 four 5 five} do_execsql_test 3.6.1 { SELECT a, max(c) OVER (ORDER BY a ROWS BETWEEN 2 FOLLOWING AND 1 FOLLOWING) FROM t5 } {1 {} 2 {} 3 {} 4 {} 5 {}} do_execsql_test 3.6.2 { SELECT a, max(c) OVER (ORDER BY a ROWS BETWEEN 1 FOLLOWING AND 1 FOLLOWING) FROM t5 } {1 two 2 three 3 four 4 five 5 {}} do_execsql_test 3.6.3 { SELECT a, max(c) OVER (ORDER BY a ROWS BETWEEN 0 FOLLOWING AND 0 FOLLOWING) FROM t5 } {1 one 2 two 3 three 4 four 5 five} #========================================================================== do_execsql_test 4.0 { DROP TABLE IF EXISTS ttt; CREATE TABLE ttt(a INTEGER PRIMARY KEY, b INTEGER, c INTEGER); INSERT INTO ttt VALUES(1, 1, 1); INSERT INTO ttt VALUES(2, 2, 2); INSERT INTO ttt VALUES(3, 3, 3); INSERT INTO ttt VALUES(4, 1, 2); INSERT INTO ttt VALUES(5, 2, 3); INSERT INTO ttt VALUES(6, 3, 4); INSERT INTO ttt VALUES(7, 1, 3); INSERT INTO ttt VALUES(8, 2, 4); INSERT INTO ttt VALUES(9, 3, 5); } {} do_execsql_test 4.1 { SELECT max(c), max(b) OVER (ORDER BY b) FROM ttt GROUP BY b; } {3 1 4 2 5 3} do_execsql_test 4.2 { SELECT max(b) OVER (ORDER BY max(c)) FROM ttt GROUP BY b; } {1 2 3} do_execsql_test 4.3 { SELECT abs(max(b) OVER (ORDER BY b)) FROM ttt GROUP BY b; } {1 2 3} do_execsql_test 4.4 { SELECT sum(b) OVER ( ORDER BY a RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING ) FROM ttt; } {18 17 15 12 11 9 6 5 3} do_execsql_test 4.5.1.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), min(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {1 1 2 2 3 3 2 1 3 2 4 3 3 1 4 2 5 3} do_execsql_test 4.5.1.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), sum(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {1 1 2 2 3 3 3 3 5 5 7 7 6 6 9 9 12 12} do_execsql_test 4.5.2.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), min(c) OVER (PARTITION BY b, a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {1 1 2 2 3 3 2 2 3 3 4 4 3 3 4 4 5 5} do_execsql_test 4.5.2.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), sum(c) OVER (PARTITION BY b, a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {1 1 2 2 3 3 3 2 5 3 7 4 6 3 9 4 12 5} do_execsql_test 4.5.3.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), min(c) OVER ( ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {1 1 2 1 3 1 2 1 3 1 4 1 3 1 4 1 5 1} do_execsql_test 4.5.3.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), sum(c) OVER ( ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {1 1 2 3 3 6 3 8 5 11 7 15 6 18 9 22 12 27} do_execsql_test 4.5.4.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), min(c) OVER (PARTITION BY a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {1 1 2 2 3 3 2 2 3 3 4 4 3 3 4 4 5 5} do_execsql_test 4.5.4.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), sum(c) OVER (PARTITION BY a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {1 1 2 2 3 3 3 2 5 3 7 4 6 3 9 4 12 5} do_execsql_test 4.5.5.1 { SELECT max(c) OVER (PARTITION BY b, a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), min(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {1 1 2 2 3 3 2 1 3 2 4 3 3 1 4 2 5 3} do_execsql_test 4.5.5.2 { SELECT sum(c) OVER (PARTITION BY b, a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), sum(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {1 1 2 2 3 3 2 3 3 5 4 7 3 6 4 9 5 12} do_execsql_test 4.5.6.1 { SELECT max(c) OVER (PARTITION BY b, a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), min(c) OVER (PARTITION BY b, a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {1 1 2 2 3 3 2 2 3 3 4 4 3 3 4 4 5 5} do_execsql_test 4.5.6.2 { SELECT sum(c) OVER (PARTITION BY b, a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), sum(c) OVER (PARTITION BY b, a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {1 1 2 2 3 3 2 2 3 3 4 4 3 3 4 4 5 5} do_execsql_test 4.5.7.1 { SELECT max(c) OVER (PARTITION BY b, a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), min(c) OVER ( ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {1 1 2 1 3 1 2 1 3 1 4 1 3 1 4 1 5 1} do_execsql_test 4.5.7.2 { SELECT sum(c) OVER (PARTITION BY b, a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), sum(c) OVER ( ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {1 1 2 3 3 6 2 8 3 11 4 15 3 18 4 22 5 27} do_execsql_test 4.5.8.1 { SELECT max(c) OVER (PARTITION BY b, a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), min(c) OVER (PARTITION BY a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {1 1 2 2 3 3 2 2 3 3 4 4 3 3 4 4 5 5} do_execsql_test 4.5.8.2 { SELECT sum(c) OVER (PARTITION BY b, a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), sum(c) OVER (PARTITION BY a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {1 1 2 2 3 3 2 2 3 3 4 4 3 3 4 4 5 5} do_execsql_test 4.5.9.1 { SELECT max(c) OVER ( ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), min(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {1 1 2 2 3 3 3 1 3 2 4 3 4 1 4 2 5 3} do_execsql_test 4.5.9.2 { SELECT sum(c) OVER ( ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), sum(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {1 1 3 2 6 3 8 3 11 5 15 7 18 6 22 9 27 12} do_execsql_test 4.5.10.1 { SELECT max(c) OVER ( ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), min(c) OVER (PARTITION BY b, a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {1 1 2 2 3 3 3 2 3 3 4 4 4 3 4 4 5 5} do_execsql_test 4.5.10.2 { SELECT sum(c) OVER ( ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), sum(c) OVER (PARTITION BY b, a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {1 1 3 2 6 3 8 2 11 3 15 4 18 3 22 4 27 5} do_execsql_test 4.5.11.1 { SELECT max(c) OVER ( ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), min(c) OVER ( ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {1 1 2 1 3 1 3 1 3 1 4 1 4 1 4 1 5 1} do_execsql_test 4.5.11.2 { SELECT sum(c) OVER ( ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), sum(c) OVER ( ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {1 1 3 3 6 6 8 8 11 11 15 15 18 18 22 22 27 27} do_execsql_test 4.5.12.1 { SELECT max(c) OVER ( ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), min(c) OVER (PARTITION BY a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {1 1 2 2 3 3 3 2 3 3 4 4 4 3 4 4 5 5} do_execsql_test 4.5.12.2 { SELECT sum(c) OVER ( ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), sum(c) OVER (PARTITION BY a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {1 1 3 2 6 3 8 2 11 3 15 4 18 3 22 4 27 5} do_execsql_test 4.5.13.1 { SELECT max(c) OVER (PARTITION BY a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), min(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {1 1 2 2 3 3 2 1 3 2 4 3 3 1 4 2 5 3} do_execsql_test 4.5.13.2 { SELECT sum(c) OVER (PARTITION BY a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), sum(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {1 1 2 2 3 3 2 3 3 5 4 7 3 6 4 9 5 12} do_execsql_test 4.5.14.1 { SELECT max(c) OVER (PARTITION BY a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), min(c) OVER (PARTITION BY b, a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {1 1 2 2 3 3 2 2 3 3 4 4 3 3 4 4 5 5} do_execsql_test 4.5.14.2 { SELECT sum(c) OVER (PARTITION BY a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), sum(c) OVER (PARTITION BY b, a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {1 1 2 2 3 3 2 2 3 3 4 4 3 3 4 4 5 5} do_execsql_test 4.5.15.1 { SELECT max(c) OVER (PARTITION BY a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), min(c) OVER ( ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {1 1 2 1 3 1 2 1 3 1 4 1 3 1 4 1 5 1} do_execsql_test 4.5.15.2 { SELECT sum(c) OVER (PARTITION BY a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), sum(c) OVER ( ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {1 1 2 3 3 6 2 8 3 11 4 15 3 18 4 22 5 27} do_execsql_test 4.5.16.1 { SELECT max(c) OVER (PARTITION BY a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), min(c) OVER (PARTITION BY a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {1 1 2 2 3 3 2 2 3 3 4 4 3 3 4 4 5 5} do_execsql_test 4.5.16.2 { SELECT sum(c) OVER (PARTITION BY a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), sum(c) OVER (PARTITION BY a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {1 1 2 2 3 3 2 2 3 3 4 4 3 3 4 4 5 5} do_execsql_test 4.5.17.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), min(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {1 1 2 2 3 3 2 1 3 2 4 3 3 1 4 2 5 3} do_execsql_test 4.5.17.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), sum(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {1 1 2 2 3 3 3 3 5 5 7 7 6 6 9 9 12 12} do_execsql_test 4.5.18.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), min(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) FROM ttt ORDER BY a } {1 1 2 2 3 3 2 1 3 2 4 3 3 1 4 2 5 3} do_execsql_test 4.5.18.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), sum(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) FROM ttt ORDER BY a } {1 6 2 9 3 12 3 6 5 9 7 12 6 6 9 9 12 12} do_execsql_test 4.5.19.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), min(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND CURRENT ROW) FROM ttt ORDER BY a } {1 1 2 2 3 3 2 2 3 3 4 4 3 3 4 4 5 5} do_execsql_test 4.5.19.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), sum(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND CURRENT ROW) FROM ttt ORDER BY a } {1 1 2 2 3 3 3 2 5 3 7 4 6 3 9 4 12 5} do_execsql_test 4.5.20.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), min(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) FROM ttt ORDER BY a } {1 1 2 2 3 3 2 2 3 3 4 4 3 3 4 4 5 5} do_execsql_test 4.5.20.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), sum(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) FROM ttt ORDER BY a } {1 6 2 9 3 12 3 5 5 7 7 9 6 3 9 4 12 5} do_execsql_test 4.5.21.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING), min(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {3 1 4 2 5 3 3 1 4 2 5 3 3 1 4 2 5 3} do_execsql_test 4.5.21.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING), sum(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {6 1 9 2 12 3 6 3 9 5 12 7 6 6 9 9 12 12} do_execsql_test 4.5.22.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING), min(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) FROM ttt ORDER BY a } {3 1 4 2 5 3 3 1 4 2 5 3 3 1 4 2 5 3} do_execsql_test 4.5.22.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING), sum(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) FROM ttt ORDER BY a } {6 6 9 9 12 12 6 6 9 9 12 12 6 6 9 9 12 12} do_execsql_test 4.5.23.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING), min(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND CURRENT ROW) FROM ttt ORDER BY a } {3 1 4 2 5 3 3 2 4 3 5 4 3 3 4 4 5 5} do_execsql_test 4.5.23.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING), sum(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND CURRENT ROW) FROM ttt ORDER BY a } {6 1 9 2 12 3 6 2 9 3 12 4 6 3 9 4 12 5} do_execsql_test 4.5.24.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING), min(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) FROM ttt ORDER BY a } {3 1 4 2 5 3 3 2 4 3 5 4 3 3 4 4 5 5} do_execsql_test 4.5.24.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING), sum(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) FROM ttt ORDER BY a } {6 6 9 9 12 12 6 5 9 7 12 9 6 3 9 4 12 5} do_execsql_test 4.5.25.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND CURRENT ROW), min(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {1 1 2 2 3 3 2 1 3 2 4 3 3 1 4 2 5 3} do_execsql_test 4.5.25.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND CURRENT ROW), sum(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {1 1 2 2 3 3 2 3 3 5 4 7 3 6 4 9 5 12} do_execsql_test 4.5.26.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND CURRENT ROW), min(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) FROM ttt ORDER BY a } {1 1 2 2 3 3 2 1 3 2 4 3 3 1 4 2 5 3} do_execsql_test 4.5.26.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND CURRENT ROW), sum(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) FROM ttt ORDER BY a } {1 6 2 9 3 12 2 6 3 9 4 12 3 6 4 9 5 12} do_execsql_test 4.5.27.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND CURRENT ROW), min(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND CURRENT ROW) FROM ttt ORDER BY a } {1 1 2 2 3 3 2 2 3 3 4 4 3 3 4 4 5 5} do_execsql_test 4.5.27.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND CURRENT ROW), sum(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND CURRENT ROW) FROM ttt ORDER BY a } {1 1 2 2 3 3 2 2 3 3 4 4 3 3 4 4 5 5} do_execsql_test 4.5.28.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND CURRENT ROW), min(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) FROM ttt ORDER BY a } {1 1 2 2 3 3 2 2 3 3 4 4 3 3 4 4 5 5} do_execsql_test 4.5.28.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND CURRENT ROW), sum(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) FROM ttt ORDER BY a } {1 6 2 9 3 12 2 5 3 7 4 9 3 3 4 4 5 5} do_execsql_test 4.5.29.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING), min(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {3 1 4 2 5 3 3 1 4 2 5 3 3 1 4 2 5 3} do_execsql_test 4.5.29.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING), sum(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {6 1 9 2 12 3 5 3 7 5 9 7 3 6 4 9 5 12} do_execsql_test 4.5.30.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING), min(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) FROM ttt ORDER BY a } {3 1 4 2 5 3 3 1 4 2 5 3 3 1 4 2 5 3} do_execsql_test 4.5.30.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING), sum(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) FROM ttt ORDER BY a } {6 6 9 9 12 12 5 6 7 9 9 12 3 6 4 9 5 12} do_execsql_test 4.5.31.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING), min(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND CURRENT ROW) FROM ttt ORDER BY a } {3 1 4 2 5 3 3 2 4 3 5 4 3 3 4 4 5 5} do_execsql_test 4.5.31.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING), sum(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND CURRENT ROW) FROM ttt ORDER BY a } {6 1 9 2 12 3 5 2 7 3 9 4 3 3 4 4 5 5} do_execsql_test 4.5.32.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING), min(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) FROM ttt ORDER BY a } {3 1 4 2 5 3 3 2 4 3 5 4 3 3 4 4 5 5} do_execsql_test 4.5.32.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING), sum(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) FROM ttt ORDER BY a } {6 6 9 9 12 12 5 5 7 7 9 9 3 3 4 4 5 5} do_execsql_test 4.5.33.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 3 PRECEDING AND 1 FOLLOWING), min(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 3 PRECEDING AND 1 FOLLOWING) FROM ttt ORDER BY a } {2 1 3 2 4 3 3 1 4 2 5 3 3 1 4 2 5 3} do_execsql_test 4.5.33.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 3 PRECEDING AND 1 FOLLOWING), sum(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 3 PRECEDING AND 1 FOLLOWING) FROM ttt ORDER BY a } {3 3 5 5 7 7 6 6 9 9 12 12 6 6 9 9 12 12} do_execsql_test 4.5.34.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 3 PRECEDING AND 1 FOLLOWING), min(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 3 PRECEDING AND 2 FOLLOWING) FROM ttt ORDER BY a } {2 1 3 2 4 3 3 1 4 2 5 3 3 1 4 2 5 3} do_execsql_test 4.5.34.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 3 PRECEDING AND 1 FOLLOWING), sum(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 3 PRECEDING AND 2 FOLLOWING) FROM ttt ORDER BY a } {3 6 5 9 7 12 6 6 9 9 12 12 6 6 9 9 12 12} do_execsql_test 4.5.35.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 3 PRECEDING AND 1 FOLLOWING), min(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) FROM ttt ORDER BY a } {2 {} 3 {} 4 {} 3 1 4 2 5 3 3 2 4 3 5 4} do_execsql_test 4.5.35.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 3 PRECEDING AND 1 FOLLOWING), sum(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) FROM ttt ORDER BY a } {3 {} 5 {} 7 {} 6 1 9 2 12 3 6 2 9 3 12 4} do_execsql_test 4.5.36.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 3 PRECEDING AND 1 FOLLOWING), min(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 0 PRECEDING AND 1 PRECEDING) FROM ttt ORDER BY a } {2 {} 3 {} 4 {} 3 {} 4 {} 5 {} 3 {} 4 {} 5 {}} do_execsql_test 4.5.36.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 3 PRECEDING AND 1 FOLLOWING), sum(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 0 PRECEDING AND 1 PRECEDING) FROM ttt ORDER BY a } {3 {} 5 {} 7 {} 6 {} 9 {} 12 {} 6 {} 9 {} 12 {}} do_execsql_test 4.5.37.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 3 PRECEDING AND 1 FOLLOWING), min(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 1 FOLLOWING AND 500 FOLLOWING) FROM ttt ORDER BY a } {2 2 3 3 4 4 3 3 4 4 5 5 3 {} 4 {} 5 {}} do_execsql_test 4.5.37.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 3 PRECEDING AND 1 FOLLOWING), sum(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 1 FOLLOWING AND 500 FOLLOWING) FROM ttt ORDER BY a } {3 5 5 7 7 9 6 3 9 4 12 5 6 {} 9 {} 12 {}} do_execsql_test 4.5.38.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 3 PRECEDING AND 2 FOLLOWING), min(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 3 PRECEDING AND 1 FOLLOWING) FROM ttt ORDER BY a } {3 1 4 2 5 3 3 1 4 2 5 3 3 1 4 2 5 3} do_execsql_test 4.5.38.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 3 PRECEDING AND 2 FOLLOWING), sum(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 3 PRECEDING AND 1 FOLLOWING) FROM ttt ORDER BY a } {6 3 9 5 12 7 6 6 9 9 12 12 6 6 9 9 12 12} do_execsql_test 4.5.39.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 3 PRECEDING AND 2 FOLLOWING), min(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 3 PRECEDING AND 2 FOLLOWING) FROM ttt ORDER BY a } {3 1 4 2 5 3 3 1 4 2 5 3 3 1 4 2 5 3} do_execsql_test 4.5.39.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 3 PRECEDING AND 2 FOLLOWING), sum(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 3 PRECEDING AND 2 FOLLOWING) FROM ttt ORDER BY a } {6 6 9 9 12 12 6 6 9 9 12 12 6 6 9 9 12 12} do_execsql_test 4.5.40.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 3 PRECEDING AND 2 FOLLOWING), min(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) FROM ttt ORDER BY a } {3 {} 4 {} 5 {} 3 1 4 2 5 3 3 2 4 3 5 4} do_execsql_test 4.5.40.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 3 PRECEDING AND 2 FOLLOWING), sum(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) FROM ttt ORDER BY a } {6 {} 9 {} 12 {} 6 1 9 2 12 3 6 2 9 3 12 4} do_execsql_test 4.5.41.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 3 PRECEDING AND 2 FOLLOWING), min(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 0 PRECEDING AND 1 PRECEDING) FROM ttt ORDER BY a } {3 {} 4 {} 5 {} 3 {} 4 {} 5 {} 3 {} 4 {} 5 {}} do_execsql_test 4.5.41.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 3 PRECEDING AND 2 FOLLOWING), sum(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 0 PRECEDING AND 1 PRECEDING) FROM ttt ORDER BY a } {6 {} 9 {} 12 {} 6 {} 9 {} 12 {} 6 {} 9 {} 12 {}} do_execsql_test 4.5.42.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 3 PRECEDING AND 2 FOLLOWING), min(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 1 FOLLOWING AND 500 FOLLOWING) FROM ttt ORDER BY a } {3 2 4 3 5 4 3 3 4 4 5 5 3 {} 4 {} 5 {}} do_execsql_test 4.5.42.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 3 PRECEDING AND 2 FOLLOWING), sum(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 1 FOLLOWING AND 500 FOLLOWING) FROM ttt ORDER BY a } {6 5 9 7 12 9 6 3 9 4 12 5 6 {} 9 {} 12 {}} do_execsql_test 4.5.43.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING), min(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 3 PRECEDING AND 1 FOLLOWING) FROM ttt ORDER BY a } {{} 1 {} 2 {} 3 1 1 2 2 3 3 2 1 3 2 4 3} do_execsql_test 4.5.43.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING), sum(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 3 PRECEDING AND 1 FOLLOWING) FROM ttt ORDER BY a } {{} 3 {} 5 {} 7 1 6 2 9 3 12 2 6 3 9 4 12} do_execsql_test 4.5.44.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING), min(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 3 PRECEDING AND 2 FOLLOWING) FROM ttt ORDER BY a } {{} 1 {} 2 {} 3 1 1 2 2 3 3 2 1 3 2 4 3} do_execsql_test 4.5.44.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING), sum(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 3 PRECEDING AND 2 FOLLOWING) FROM ttt ORDER BY a } {{} 6 {} 9 {} 12 1 6 2 9 3 12 2 6 3 9 4 12} do_execsql_test 4.5.45.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING), min(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) FROM ttt ORDER BY a } {{} {} {} {} {} {} 1 1 2 2 3 3 2 2 3 3 4 4} do_execsql_test 4.5.45.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING), sum(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) FROM ttt ORDER BY a } {{} {} {} {} {} {} 1 1 2 2 3 3 2 2 3 3 4 4} do_execsql_test 4.5.46.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING), min(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 0 PRECEDING AND 1 PRECEDING) FROM ttt ORDER BY a } {{} {} {} {} {} {} 1 {} 2 {} 3 {} 2 {} 3 {} 4 {}} do_execsql_test 4.5.46.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING), sum(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 0 PRECEDING AND 1 PRECEDING) FROM ttt ORDER BY a } {{} {} {} {} {} {} 1 {} 2 {} 3 {} 2 {} 3 {} 4 {}} do_execsql_test 4.5.47.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING), min(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 1 FOLLOWING AND 500 FOLLOWING) FROM ttt ORDER BY a } {{} 2 {} 3 {} 4 1 3 2 4 3 5 2 {} 3 {} 4 {}} do_execsql_test 4.5.47.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING), sum(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 1 FOLLOWING AND 500 FOLLOWING) FROM ttt ORDER BY a } {{} 5 {} 7 {} 9 1 3 2 4 3 5 2 {} 3 {} 4 {}} do_execsql_test 4.5.48.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 0 PRECEDING AND 1 PRECEDING), min(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 3 PRECEDING AND 1 FOLLOWING) FROM ttt ORDER BY a } {{} 1 {} 2 {} 3 {} 1 {} 2 {} 3 {} 1 {} 2 {} 3} do_execsql_test 4.5.48.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 0 PRECEDING AND 1 PRECEDING), sum(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 3 PRECEDING AND 1 FOLLOWING) FROM ttt ORDER BY a } {{} 3 {} 5 {} 7 {} 6 {} 9 {} 12 {} 6 {} 9 {} 12} do_execsql_test 4.5.49.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 0 PRECEDING AND 1 PRECEDING), min(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 3 PRECEDING AND 2 FOLLOWING) FROM ttt ORDER BY a } {{} 1 {} 2 {} 3 {} 1 {} 2 {} 3 {} 1 {} 2 {} 3} do_execsql_test 4.5.49.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 0 PRECEDING AND 1 PRECEDING), sum(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 3 PRECEDING AND 2 FOLLOWING) FROM ttt ORDER BY a } {{} 6 {} 9 {} 12 {} 6 {} 9 {} 12 {} 6 {} 9 {} 12} do_execsql_test 4.5.50.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 0 PRECEDING AND 1 PRECEDING), min(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) FROM ttt ORDER BY a } {{} {} {} {} {} {} {} 1 {} 2 {} 3 {} 2 {} 3 {} 4} do_execsql_test 4.5.50.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 0 PRECEDING AND 1 PRECEDING), sum(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) FROM ttt ORDER BY a } {{} {} {} {} {} {} {} 1 {} 2 {} 3 {} 2 {} 3 {} 4} do_execsql_test 4.5.51.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 0 PRECEDING AND 1 PRECEDING), min(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 0 PRECEDING AND 1 PRECEDING) FROM ttt ORDER BY a } {{} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {}} do_execsql_test 4.5.51.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 0 PRECEDING AND 1 PRECEDING), sum(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 0 PRECEDING AND 1 PRECEDING) FROM ttt ORDER BY a } {{} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {}} do_execsql_test 4.5.52.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 0 PRECEDING AND 1 PRECEDING), min(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 1 FOLLOWING AND 500 FOLLOWING) FROM ttt ORDER BY a } {{} 2 {} 3 {} 4 {} 3 {} 4 {} 5 {} {} {} {} {} {}} do_execsql_test 4.5.52.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 0 PRECEDING AND 1 PRECEDING), sum(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 1 FOLLOWING AND 500 FOLLOWING) FROM ttt ORDER BY a } {{} 5 {} 7 {} 9 {} 3 {} 4 {} 5 {} {} {} {} {} {}} do_execsql_test 4.5.53.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 1 FOLLOWING AND 500 FOLLOWING), min(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 3 PRECEDING AND 1 FOLLOWING) FROM ttt ORDER BY a } {3 1 4 2 5 3 3 1 4 2 5 3 {} 1 {} 2 {} 3} do_execsql_test 4.5.53.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 1 FOLLOWING AND 500 FOLLOWING), sum(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 3 PRECEDING AND 1 FOLLOWING) FROM ttt ORDER BY a } {5 3 7 5 9 7 3 6 4 9 5 12 {} 6 {} 9 {} 12} do_execsql_test 4.5.54.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 1 FOLLOWING AND 500 FOLLOWING), min(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 3 PRECEDING AND 2 FOLLOWING) FROM ttt ORDER BY a } {3 1 4 2 5 3 3 1 4 2 5 3 {} 1 {} 2 {} 3} do_execsql_test 4.5.54.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 1 FOLLOWING AND 500 FOLLOWING), sum(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 3 PRECEDING AND 2 FOLLOWING) FROM ttt ORDER BY a } {5 6 7 9 9 12 3 6 4 9 5 12 {} 6 {} 9 {} 12} do_execsql_test 4.5.55.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 1 FOLLOWING AND 500 FOLLOWING), min(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) FROM ttt ORDER BY a } {3 {} 4 {} 5 {} 3 1 4 2 5 3 {} 2 {} 3 {} 4} do_execsql_test 4.5.55.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 1 FOLLOWING AND 500 FOLLOWING), sum(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) FROM ttt ORDER BY a } {5 {} 7 {} 9 {} 3 1 4 2 5 3 {} 2 {} 3 {} 4} do_execsql_test 4.5.56.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 1 FOLLOWING AND 500 FOLLOWING), min(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 0 PRECEDING AND 1 PRECEDING) FROM ttt ORDER BY a } {3 {} 4 {} 5 {} 3 {} 4 {} 5 {} {} {} {} {} {} {}} do_execsql_test 4.5.56.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 1 FOLLOWING AND 500 FOLLOWING), sum(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 0 PRECEDING AND 1 PRECEDING) FROM ttt ORDER BY a } {5 {} 7 {} 9 {} 3 {} 4 {} 5 {} {} {} {} {} {} {}} do_execsql_test 4.5.57.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 1 FOLLOWING AND 500 FOLLOWING), min(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 1 FOLLOWING AND 500 FOLLOWING) FROM ttt ORDER BY a } {3 2 4 3 5 4 3 3 4 4 5 5 {} {} {} {} {} {}} do_execsql_test 4.5.57.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 1 FOLLOWING AND 500 FOLLOWING), sum(c) OVER (PARTITION BY b ORDER BY a ROWS BETWEEN 1 FOLLOWING AND 500 FOLLOWING) FROM ttt ORDER BY a } {5 5 7 7 9 9 3 3 4 4 5 5 {} {} {} {} {} {}} do_execsql_test 4.5.58.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), min(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {1 1 2 2 3 3 2 1 3 2 4 3 3 1 4 2 5 3} do_execsql_test 4.5.58.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), sum(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {1 1 2 2 3 3 3 3 5 5 7 7 6 6 9 9 12 12} do_execsql_test 4.5.59.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), min(c) OVER (PARTITION BY b ORDER BY a DESC RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {1 1 2 2 3 3 2 2 3 3 4 4 3 3 4 4 5 5} do_execsql_test 4.5.59.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), sum(c) OVER (PARTITION BY b ORDER BY a DESC RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {1 6 2 9 3 12 3 5 5 7 7 9 6 3 9 4 12 5} do_execsql_test 4.5.60.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), min(c) OVER (PARTITION BY b RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {1 1 2 2 3 3 2 1 3 2 4 3 3 1 4 2 5 3} do_execsql_test 4.5.60.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), sum(c) OVER (PARTITION BY b RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {1 6 2 9 3 12 3 6 5 9 7 12 6 6 9 9 12 12} do_execsql_test 4.5.61.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), min(c) OVER (PARTITION BY b ORDER BY b, a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {1 1 2 2 3 3 2 1 3 2 4 3 3 1 4 2 5 3} do_execsql_test 4.5.61.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), sum(c) OVER (PARTITION BY b ORDER BY b, a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {1 1 2 2 3 3 3 3 5 5 7 7 6 6 9 9 12 12} do_execsql_test 4.5.62.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY a DESC RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), min(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {3 1 4 2 5 3 3 1 4 2 5 3 3 1 4 2 5 3} do_execsql_test 4.5.62.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY a DESC RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), sum(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {6 1 9 2 12 3 5 3 7 5 9 7 3 6 4 9 5 12} do_execsql_test 4.5.63.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY a DESC RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), min(c) OVER (PARTITION BY b ORDER BY a DESC RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {3 1 4 2 5 3 3 2 4 3 5 4 3 3 4 4 5 5} do_execsql_test 4.5.63.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY a DESC RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), sum(c) OVER (PARTITION BY b ORDER BY a DESC RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {6 6 9 9 12 12 5 5 7 7 9 9 3 3 4 4 5 5} do_execsql_test 4.5.64.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY a DESC RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), min(c) OVER (PARTITION BY b RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {3 1 4 2 5 3 3 1 4 2 5 3 3 1 4 2 5 3} do_execsql_test 4.5.64.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY a DESC RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), sum(c) OVER (PARTITION BY b RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {6 6 9 9 12 12 5 6 7 9 9 12 3 6 4 9 5 12} do_execsql_test 4.5.65.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY a DESC RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), min(c) OVER (PARTITION BY b ORDER BY b, a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {3 1 4 2 5 3 3 1 4 2 5 3 3 1 4 2 5 3} do_execsql_test 4.5.65.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY a DESC RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), sum(c) OVER (PARTITION BY b ORDER BY b, a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {6 1 9 2 12 3 5 3 7 5 9 7 3 6 4 9 5 12} do_execsql_test 4.5.66.1 { SELECT max(c) OVER (PARTITION BY b RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), min(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {3 1 4 2 5 3 3 1 4 2 5 3 3 1 4 2 5 3} do_execsql_test 4.5.66.2 { SELECT sum(c) OVER (PARTITION BY b RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), sum(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {6 1 9 2 12 3 6 3 9 5 12 7 6 6 9 9 12 12} do_execsql_test 4.5.67.1 { SELECT max(c) OVER (PARTITION BY b RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), min(c) OVER (PARTITION BY b ORDER BY a DESC RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {3 1 4 2 5 3 3 2 4 3 5 4 3 3 4 4 5 5} do_execsql_test 4.5.67.2 { SELECT sum(c) OVER (PARTITION BY b RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), sum(c) OVER (PARTITION BY b ORDER BY a DESC RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {6 6 9 9 12 12 6 5 9 7 12 9 6 3 9 4 12 5} do_execsql_test 4.5.68.1 { SELECT max(c) OVER (PARTITION BY b RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), min(c) OVER (PARTITION BY b RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {3 1 4 2 5 3 3 1 4 2 5 3 3 1 4 2 5 3} do_execsql_test 4.5.68.2 { SELECT sum(c) OVER (PARTITION BY b RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), sum(c) OVER (PARTITION BY b RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {6 6 9 9 12 12 6 6 9 9 12 12 6 6 9 9 12 12} do_execsql_test 4.5.69.1 { SELECT max(c) OVER (PARTITION BY b RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), min(c) OVER (PARTITION BY b ORDER BY b, a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {3 1 4 2 5 3 3 1 4 2 5 3 3 1 4 2 5 3} do_execsql_test 4.5.69.2 { SELECT sum(c) OVER (PARTITION BY b RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), sum(c) OVER (PARTITION BY b ORDER BY b, a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {6 1 9 2 12 3 6 3 9 5 12 7 6 6 9 9 12 12} do_execsql_test 4.5.70.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY b, a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), min(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {1 1 2 2 3 3 2 1 3 2 4 3 3 1 4 2 5 3} do_execsql_test 4.5.70.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY b, a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), sum(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {1 1 2 2 3 3 3 3 5 5 7 7 6 6 9 9 12 12} do_execsql_test 4.5.71.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY b, a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), min(c) OVER (PARTITION BY b ORDER BY a DESC RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {1 1 2 2 3 3 2 2 3 3 4 4 3 3 4 4 5 5} do_execsql_test 4.5.71.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY b, a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), sum(c) OVER (PARTITION BY b ORDER BY a DESC RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {1 6 2 9 3 12 3 5 5 7 7 9 6 3 9 4 12 5} do_execsql_test 4.5.72.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY b, a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), min(c) OVER (PARTITION BY b RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {1 1 2 2 3 3 2 1 3 2 4 3 3 1 4 2 5 3} do_execsql_test 4.5.72.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY b, a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), sum(c) OVER (PARTITION BY b RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {1 6 2 9 3 12 3 6 5 9 7 12 6 6 9 9 12 12} do_execsql_test 4.5.73.1 { SELECT max(c) OVER (PARTITION BY b ORDER BY b, a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), min(c) OVER (PARTITION BY b ORDER BY b, a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {1 1 2 2 3 3 2 1 3 2 4 3 3 1 4 2 5 3} do_execsql_test 4.5.73.2 { SELECT sum(c) OVER (PARTITION BY b ORDER BY b, a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), sum(c) OVER (PARTITION BY b ORDER BY b, a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM ttt ORDER BY a } {1 1 2 2 3 3 3 3 5 5 7 7 6 6 9 9 12 12} #========================================================================== do_execsql_test 7.0 { DROP TABLE IF EXISTS t1; CREATE TABLE t1(x INTEGER, y INTEGER); INSERT INTO t1 VALUES(1, 2); INSERT INTO t1 VALUES(3, 4); INSERT INTO t1 VALUES(5, 6); INSERT INTO t1 VALUES(7, 8); INSERT INTO t1 VALUES(9, 10); } {} do_execsql_test 7.1 { SELECT lead(y) OVER win FROM t1 WINDOW win AS (ORDER BY x) } {4 6 8 10 {}} do_execsql_test 7.2 { SELECT lead(y, 2) OVER win FROM t1 WINDOW win AS (ORDER BY x) } {6 8 10 {} {}} do_execsql_test 7.3 { SELECT lead(y, 3, -1) OVER win FROM t1 WINDOW win AS (ORDER BY x) } {8 10 -1 -1 -1} do_execsql_test 7.4 { SELECT lead(y) OVER win, lead(y) OVER win FROM t1 WINDOW win AS (ORDER BY x) } {4 4 6 6 8 8 10 10 {} {}} do_execsql_test 7.5 { SELECT lead(y) OVER win, lead(y, 2) OVER win, lead(y, 3, -1) OVER win FROM t1 WINDOW win AS (ORDER BY x) } {4 6 8 6 8 10 8 10 -1 10 {} -1 {} {} -1} #========================================================================== do_execsql_test 8.0 { DROP TABLE IF EXISTS t1; CREATE TABLE t1(a INTEGER, b INTEGER, c INTEGER, d INTEGER); INSERT INTO t1 VALUES(1, 2, 3, 4); INSERT INTO t1 VALUES(5, 6, 7, 8); INSERT INTO t1 VALUES(9, 10, 11, 12); } {} do_execsql_test 8.1 { SELECT row_number() OVER win, nth_value(d,2) OVER win, lead(d) OVER win FROM t1 WINDOW win AS (ORDER BY a) } {1 {} 8 2 8 12 3 8 {}} do_execsql_test 8.2 { SELECT row_number() OVER win, rank() OVER win, dense_rank() OVER win, ntile(2) OVER win, first_value(d) OVER win, last_value(d) OVER win, nth_value(d,2) OVER win, lead(d) OVER win, lag(d) OVER win, max(d) OVER win, min(d) OVER win FROM t1 WINDOW win AS (ORDER BY a) } {1 1 1 1 4 4 {} 8 {} 4 4 2 2 2 1 4 8 8 12 4 8 4 3 3 3 2 4 12 8 {} 8 12 4} #========================================================================== do_execsql_test 9.0 { DROP TABLE IF EXISTS t2; CREATE TABLE t2(x INTEGER); INSERT INTO t2 VALUES(1), (1), (1), (4), (4), (6), (7); } {} do_execsql_test 9.1 { SELECT rank() OVER () FROM t2 } {1 1 1 1 1 1 1} do_execsql_test 9.2 { SELECT dense_rank() OVER (PARTITION BY x) FROM t2 } {1 1 1 1 1 1 1} do_test 9.3 { set myres {} foreach r [db eval {SELECT x, percent_rank() OVER (PARTITION BY x ORDER BY x) FROM t2}] { lappend myres [format %.2f [set r]] } set myres } {1.00 0.00 1.00 0.00 1.00 0.00 4.00 0.00 4.00 0.00 6.00 0.00 7.00 0.00} do_execsql_test 9.4 { SELECT x, rank() OVER (ORDER BY x) FROM t2 ORDER BY 1,2 } {1 1 1 1 1 1 4 4 4 4 6 6 7 7} do_execsql_test 9.5 { SELECT DISTINCT x, rank() OVER (ORDER BY x) FROM t2 ORDER BY 1,2 } {1 1 4 4 6 6 7 7} finish_test |
Added test/window5.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | # 2018 May 8 # # 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. # #*********************************************************************** # This file implements regression tests for SQLite library. Specifically, # it tests the sqlite3_create_window_function() API. # set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix window5 ifcapable !windowfunc { finish_test return } proc m_step {ctx val} { lappend ctx $val return $ctx } proc m_value {ctx} { set lSort [lsort $ctx] set nVal [llength $lSort] set n [expr $nVal/2] if {($nVal % 2)==0 && $nVal>0} { set a [lindex $lSort $n] set b [lindex $lSort $n-1] if {($a+$b) % 2} { set ret [expr ($a+$b)/2.0] } else { set ret [expr ($a+$b)/2] } } else { set ret [lindex $lSort $n] } return $ret } proc m_inverse {ctx val} { set ctx [lrange $ctx 1 end] return $ctx } proc w_value {ctx} { lsort $ctx } sqlite3_create_window_function db median m_step m_value m_value m_inverse sqlite3_create_window_function db win m_step w_value w_value m_inverse do_test 0.0 { test_create_window_function_misuse db } {} do_execsql_test 1.0 { CREATE TABLE t1(a, b); INSERT INTO t1 VALUES(4, 'a'); INSERT INTO t1 VALUES(6, 'b'); INSERT INTO t1 VALUES(1, 'c'); INSERT INTO t1 VALUES(5, 'd'); INSERT INTO t1 VALUES(2, 'e'); INSERT INTO t1 VALUES(3, 'f'); } do_execsql_test 1.1 { SELECT win(a) OVER (ORDER BY b), median(a) OVER (ORDER BY b) FROM t1; } {4 4 {4 6} 5 {1 4 6} 4 {1 4 5 6} 4.5 {1 2 4 5 6} 4 {1 2 3 4 5 6} 3.5} test_create_sumint db do_execsql_test 2.0 { SELECT sumint(a) OVER (ORDER BY rowid) FROM t1 ORDER BY rowid; } {4 10 11 16 18 21} do_execsql_test 2.1 { SELECT sumint(a) OVER (ORDER BY rowid ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) FROM t1 ORDER BY rowid; } {10 11 12 8 10 5} finish_test |
Added test/window6.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 | # 2018 May 8 # # 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. # #*********************************************************************** # This file implements regression tests for SQLite library. Specifically, # it tests the sqlite3_create_window_function() API. # set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix window6 ifcapable !windowfunc { finish_test return } set setup { CREATE TABLE %t1(%x, %y %typename); INSERT INTO %t1 VALUES(1, 'a'); INSERT INTO %t1 VALUES(2, 'b'); INSERT INTO %t1 VALUES(3, 'c'); INSERT INTO %t1 VALUES(4, 'd'); INSERT INTO %t1 VALUES(5, 'e'); } foreach {tn vars} { 1 {} 2 { set A(%t1) over } 3 { set A(%x) over } 4 { set A(%alias) over set A(%x) following set A(%y) over } 5 { set A(%t1) over set A(%x) following set A(%y) preceding set A(%w) current set A(%alias) filter set A(%typename) window } 6 { set A(%x) window } } { set A(%t1) t1 set A(%x) x set A(%y) y set A(%w) w set A(%alias) alias set A(%typename) integer eval $vars set MAP [array get A] set setup_sql [string map $MAP $setup] reset_db execsql $setup_sql do_execsql_test 1.$tn.1 [string map $MAP { SELECT group_concat(%x, '.') OVER (ORDER BY %y) FROM %t1 }] {1 1.2 1.2.3 1.2.3.4 1.2.3.4.5} do_execsql_test 1.$tn.2 [string map $MAP { SELECT sum(%x) OVER %w FROM %t1 WINDOW %w AS (ORDER BY %y) }] {1 3 6 10 15} do_execsql_test 1.$tn.3 [string map $MAP { SELECT sum(%alias.%x) OVER %w FROM %t1 %alias WINDOW %w AS (ORDER BY %y) }] {1 3 6 10 15} do_execsql_test 1.$tn.4 [string map $MAP { SELECT sum(%x) %alias FROM %t1 }] {15} } proc winproc {args} { return "window: $args" } db func window winproc do_execsql_test 2.0 { SELECT window('hello world'); } {{window: {hello world}}} proc wincmp {a b} { string compare $b $a } db collate window wincmp do_execsql_test 3.0 { CREATE TABLE window(x COLLATE window); INSERT INTO window VALUES('bob'), ('alice'), ('cate'); SELECT * FROM window ORDER BY x COLLATE window; } {cate bob alice} do_execsql_test 3.1 { DROP TABLE window; CREATE TABLE x1(x); INSERT INTO x1 VALUES('bob'), ('alice'), ('cate'); CREATE INDEX window ON x1(x COLLATE window); SELECT * FROM x1 ORDER BY x COLLATE window; } {cate bob alice} do_execsql_test 4.0 { CREATE TABLE t4(x, y); } # do_execsql_test 4.1 { PRAGMA parser_trace = 1 } do_execsql_test 4.1 { SELECT * FROM t4 window, t4; } #------------------------------------------------------------------------- reset_db do_execsql_test 5.0 { CREATE TABLE over(x, over); CREATE TABLE window(x, window); INSERT INTO over VALUES(1, 2), (3, 4), (5, 6); INSERT INTO window VALUES(1, 2), (3, 4), (5, 6); SELECT sum(x) over FROM over } {9} do_execsql_test 5.1 { SELECT sum(x) over over FROM over WINDOW over AS () } {9 9 9} do_execsql_test 5.2 { SELECT sum(over) over over over FROM over over WINDOW over AS (ORDER BY over) } {2 6 12} do_execsql_test 5.3 { SELECT sum(over) over over over FROM over over WINDOW over AS (ORDER BY over); } {2 6 12} do_execsql_test 5.4 { SELECT sum(window) OVER window window FROM window window window window AS (ORDER BY window); } {2 6 12} finish_test |
Added test/windowfault.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | # 2018 May 8 # # 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. # #*********************************************************************** # This file implements regression tests for SQLite library. # set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix windowfault ifcapable !windowfunc { finish_test return } do_execsql_test 1.0 { CREATE TABLE t1(a, b, c, d); INSERT INTO t1 VALUES(1, 2, 3, 4); INSERT INTO t1 VALUES(5, 6, 7, 8); INSERT INTO t1 VALUES(9, 10, 11, 12); } faultsim_save_and_close do_faultsim_test 1 -start 1 -faults oom-* -prep { faultsim_restore_and_reopen } -body { execsql { SELECT row_number() OVER win, rank() OVER win, dense_rank() OVER win, ntile(2) OVER win, first_value(d) OVER win, last_value(d) OVER win, nth_value(d,2) OVER win, lead(d) OVER win, lag(d) OVER win, max(d) OVER win, min(d) OVER win FROM t1 WINDOW win AS (ORDER BY a) } } -test { faultsim_test_result {0 {1 1 1 1 4 4 {} 8 {} 4 4 2 2 2 1 4 8 8 12 4 8 4 3 3 3 2 4 12 8 {} 8 12 4}} } do_faultsim_test 1.1 -faults oom-t* -prep { faultsim_restore_and_reopen } -body { execsql { SELECT row_number() OVER win, rank() OVER win, dense_rank() OVER win FROM t1 WINDOW win AS (PARTITION BY c<7 ORDER BY a) } } -test { faultsim_test_result {0 {1 1 1 2 2 2 1 1 1}} } do_faultsim_test 1.2 -faults oom-t* -prep { faultsim_restore_and_reopen } -body { execsql { SELECT ntile(105) OVER ( RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) FROM t1 } } -test { faultsim_test_result {0 {1 2 3}} } do_faultsim_test 2 -start 1 -faults oom-* -prep { faultsim_restore_and_reopen } -body { execsql { SELECT round(percent_rank() OVER win, 2), round(cume_dist() OVER win, 2) FROM t1 WINDOW win AS (ORDER BY a) } } -test { faultsim_test_result {0 {0.0 0.33 0.5 0.67 1.0 1.0}} } do_faultsim_test 3 -faults oom-* -prep { faultsim_restore_and_reopen } -body { execsql { SELECT min(d) OVER win, max(d) OVER win FROM t1 WINDOW win AS (ORDER BY a RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) } } -test { faultsim_test_result {0 {4 12 8 12 12 12}} } do_faultsim_test 4 -faults oom-* -prep { faultsim_restore_and_reopen } -body { execsql { CREATE VIEW aaa AS SELECT min(d) OVER w, max(d) OVER w FROM t1 WINDOW w AS (ORDER BY a RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING); SELECT * FROM aaa; } } -test { faultsim_test_result {0 {4 12 8 12 12 12}} } do_faultsim_test 5 -start 1 -faults oom-* -prep { faultsim_restore_and_reopen } -body { execsql { SELECT last_value(a) OVER win1, last_value(a) OVER win2 FROM t1 WINDOW win1 AS (ORDER BY a ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING), win2 AS (ORDER BY a) } } -test { faultsim_test_result {0 {5 1 9 5 9 9}} } finish_test |
Changes to tool/lempar.c.
︙ | ︙ | |||
86 87 88 89 90 91 92 93 94 95 96 97 98 99 | */ #ifndef INTERFACE # define INTERFACE 1 #endif /************* Begin control #defines *****************************************/ %% /************* End control #defines *******************************************/ /* Define the yytestcase() macro to be a no-op if is not already defined ** otherwise. ** ** Applications can choose to define yytestcase() in the %include section ** to a macro that can assist in verifying code coverage. For production ** code the yytestcase() macro should be turned off. But it is useful | > | 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | */ #ifndef INTERFACE # define INTERFACE 1 #endif /************* Begin control #defines *****************************************/ %% /************* End control #defines *******************************************/ #define YY_NLOOKAHEAD ((int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0]))) /* Define the yytestcase() macro to be a no-op if is not already defined ** otherwise. ** ** Applications can choose to define yytestcase() in the %include section ** to a macro that can assist in verifying code coverage. For production ** code the yytestcase() macro should be turned off. But it is useful |
︙ | ︙ | |||
515 516 517 518 519 520 521 | assert( stateno <= YY_SHIFT_COUNT ); #if defined(YYCOVERAGE) yycoverage[stateno][iLookAhead] = 1; #endif do{ i = yy_shift_ofst[stateno]; assert( i>=0 ); | | | | 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 | assert( stateno <= YY_SHIFT_COUNT ); #if defined(YYCOVERAGE) yycoverage[stateno][iLookAhead] = 1; #endif do{ i = yy_shift_ofst[stateno]; assert( i>=0 ); /* assert( i+YYNTOKEN<=(int)YY_NLOOKAHEAD ); */ assert( iLookAhead!=YYNOCODE ); assert( iLookAhead < YYNTOKEN ); i += iLookAhead; if( i>=YY_NLOOKAHEAD || yy_lookahead[i]!=iLookAhead ){ #ifdef YYFALLBACK YYCODETYPE iFallback; /* Fallback token */ if( iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0]) && (iFallback = yyFallback[iLookAhead])!=0 ){ #ifndef NDEBUG if( yyTraceFILE ){ fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n", |
︙ | ︙ | |||
1053 1054 1055 1056 1057 1058 1059 | cDiv = ' '; } fprintf(yyTraceFILE,"]\n"); } #endif return; } | > > > > > > > > > > > > > | 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 | cDiv = ' '; } fprintf(yyTraceFILE,"]\n"); } #endif return; } /* ** Return the fallback token corresponding to canonical token iToken, or ** 0 if iToken has no fallback. */ int ParseFallback(int iToken){ #ifdef YYFALLBACK if( iToken<sizeof(yyFallback)/sizeof(yyFallback[0]) ){ return yyFallback[iToken]; } #endif return 0; } |
Changes to tool/mkkeywordhash.c.
︙ | ︙ | |||
144 145 146 147 148 149 150 151 152 153 154 155 156 157 | # define CTE 0x00040000 #endif #ifdef SQLITE_OMIT_UPSERT # define UPSERT 0 #else # define UPSERT 0x00080000 #endif /* ** These are the keywords */ static Keyword aKeywordTable[] = { { "ABORT", "TK_ABORT", CONFLICT|TRIGGER }, { "ACTION", "TK_ACTION", FKEY }, | > > > > > | 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 | # define CTE 0x00040000 #endif #ifdef SQLITE_OMIT_UPSERT # define UPSERT 0 #else # define UPSERT 0x00080000 #endif #ifdef SQLITE_OMIT_WINDOWFUNC # define WINDOWFUNC 0 #else # define WINDOWFUNC 0x00100000 #endif /* ** These are the keywords */ static Keyword aKeywordTable[] = { { "ABORT", "TK_ABORT", CONFLICT|TRIGGER }, { "ACTION", "TK_ACTION", FKEY }, |
︙ | ︙ | |||
176 177 178 179 180 181 182 183 184 185 186 187 188 189 | { "COLLATE", "TK_COLLATE", ALWAYS }, { "COLUMN", "TK_COLUMNKW", ALTER }, { "COMMIT", "TK_COMMIT", ALWAYS }, { "CONFLICT", "TK_CONFLICT", CONFLICT }, { "CONSTRAINT", "TK_CONSTRAINT", ALWAYS }, { "CREATE", "TK_CREATE", ALWAYS }, { "CROSS", "TK_JOIN_KW", ALWAYS }, { "CURRENT_DATE", "TK_CTIME_KW", ALWAYS }, { "CURRENT_TIME", "TK_CTIME_KW", ALWAYS }, { "CURRENT_TIMESTAMP","TK_CTIME_KW", ALWAYS }, { "DATABASE", "TK_DATABASE", ATTACH }, { "DEFAULT", "TK_DEFAULT", ALWAYS }, { "DEFERRED", "TK_DEFERRED", ALWAYS }, { "DEFERRABLE", "TK_DEFERRABLE", FKEY }, | > | 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 | { "COLLATE", "TK_COLLATE", ALWAYS }, { "COLUMN", "TK_COLUMNKW", ALTER }, { "COMMIT", "TK_COMMIT", ALWAYS }, { "CONFLICT", "TK_CONFLICT", CONFLICT }, { "CONSTRAINT", "TK_CONSTRAINT", ALWAYS }, { "CREATE", "TK_CREATE", ALWAYS }, { "CROSS", "TK_JOIN_KW", ALWAYS }, { "CURRENT", "TK_CURRENT", WINDOWFUNC }, { "CURRENT_DATE", "TK_CTIME_KW", ALWAYS }, { "CURRENT_TIME", "TK_CTIME_KW", ALWAYS }, { "CURRENT_TIMESTAMP","TK_CTIME_KW", ALWAYS }, { "DATABASE", "TK_DATABASE", ATTACH }, { "DEFAULT", "TK_DEFAULT", ALWAYS }, { "DEFERRED", "TK_DEFERRED", ALWAYS }, { "DEFERRABLE", "TK_DEFERRABLE", FKEY }, |
︙ | ︙ | |||
198 199 200 201 202 203 204 205 206 207 208 209 210 211 | { "ELSE", "TK_ELSE", ALWAYS }, { "ESCAPE", "TK_ESCAPE", ALWAYS }, { "EXCEPT", "TK_EXCEPT", COMPOUND }, { "EXCLUSIVE", "TK_EXCLUSIVE", ALWAYS }, { "EXISTS", "TK_EXISTS", ALWAYS }, { "EXPLAIN", "TK_EXPLAIN", EXPLAIN }, { "FAIL", "TK_FAIL", CONFLICT|TRIGGER }, { "FOR", "TK_FOR", TRIGGER }, { "FOREIGN", "TK_FOREIGN", FKEY }, { "FROM", "TK_FROM", ALWAYS }, { "FULL", "TK_JOIN_KW", ALWAYS }, { "GLOB", "TK_LIKE_KW", ALWAYS }, { "GROUP", "TK_GROUP", ALWAYS }, { "HAVING", "TK_HAVING", ALWAYS }, | > > | 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 | { "ELSE", "TK_ELSE", ALWAYS }, { "ESCAPE", "TK_ESCAPE", ALWAYS }, { "EXCEPT", "TK_EXCEPT", COMPOUND }, { "EXCLUSIVE", "TK_EXCLUSIVE", ALWAYS }, { "EXISTS", "TK_EXISTS", ALWAYS }, { "EXPLAIN", "TK_EXPLAIN", EXPLAIN }, { "FAIL", "TK_FAIL", CONFLICT|TRIGGER }, { "FILTER", "TK_FILTER", WINDOWFUNC }, { "FOLLOWING", "TK_FOLLOWING", WINDOWFUNC }, { "FOR", "TK_FOR", TRIGGER }, { "FOREIGN", "TK_FOREIGN", FKEY }, { "FROM", "TK_FROM", ALWAYS }, { "FULL", "TK_JOIN_KW", ALWAYS }, { "GLOB", "TK_LIKE_KW", ALWAYS }, { "GROUP", "TK_GROUP", ALWAYS }, { "HAVING", "TK_HAVING", ALWAYS }, |
︙ | ︙ | |||
237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 | { "NULL", "TK_NULL", ALWAYS }, { "OF", "TK_OF", ALWAYS }, { "OFFSET", "TK_OFFSET", ALWAYS }, { "ON", "TK_ON", ALWAYS }, { "OR", "TK_OR", ALWAYS }, { "ORDER", "TK_ORDER", ALWAYS }, { "OUTER", "TK_JOIN_KW", ALWAYS }, { "PLAN", "TK_PLAN", EXPLAIN }, { "PRAGMA", "TK_PRAGMA", PRAGMA }, { "PRIMARY", "TK_PRIMARY", ALWAYS }, { "QUERY", "TK_QUERY", EXPLAIN }, { "RAISE", "TK_RAISE", TRIGGER }, { "RECURSIVE", "TK_RECURSIVE", CTE }, { "REFERENCES", "TK_REFERENCES", FKEY }, { "REGEXP", "TK_LIKE_KW", ALWAYS }, { "REINDEX", "TK_REINDEX", REINDEX }, { "RELEASE", "TK_RELEASE", ALWAYS }, { "RENAME", "TK_RENAME", ALTER }, { "REPLACE", "TK_REPLACE", CONFLICT }, { "RESTRICT", "TK_RESTRICT", FKEY }, { "RIGHT", "TK_JOIN_KW", ALWAYS }, { "ROLLBACK", "TK_ROLLBACK", ALWAYS }, { "ROW", "TK_ROW", TRIGGER }, { "SAVEPOINT", "TK_SAVEPOINT", ALWAYS }, { "SELECT", "TK_SELECT", ALWAYS }, { "SET", "TK_SET", ALWAYS }, { "TABLE", "TK_TABLE", ALWAYS }, { "TEMP", "TK_TEMP", ALWAYS }, { "TEMPORARY", "TK_TEMP", ALWAYS }, { "THEN", "TK_THEN", ALWAYS }, { "TO", "TK_TO", ALWAYS }, { "TRANSACTION", "TK_TRANSACTION", ALWAYS }, { "TRIGGER", "TK_TRIGGER", TRIGGER }, { "UNION", "TK_UNION", COMPOUND }, { "UNIQUE", "TK_UNIQUE", ALWAYS }, { "UPDATE", "TK_UPDATE", ALWAYS }, { "USING", "TK_USING", ALWAYS }, { "VACUUM", "TK_VACUUM", VACUUM }, { "VALUES", "TK_VALUES", ALWAYS }, { "VIEW", "TK_VIEW", VIEW }, { "VIRTUAL", "TK_VIRTUAL", VTAB }, { "WITH", "TK_WITH", CTE }, { "WITHOUT", "TK_WITHOUT", ALWAYS }, { "WHEN", "TK_WHEN", ALWAYS }, { "WHERE", "TK_WHERE", ALWAYS }, }; /* Number of keywords */ | > > > > > > > | 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 | { "NULL", "TK_NULL", ALWAYS }, { "OF", "TK_OF", ALWAYS }, { "OFFSET", "TK_OFFSET", ALWAYS }, { "ON", "TK_ON", ALWAYS }, { "OR", "TK_OR", ALWAYS }, { "ORDER", "TK_ORDER", ALWAYS }, { "OUTER", "TK_JOIN_KW", ALWAYS }, { "OVER", "TK_OVER", WINDOWFUNC }, { "PARTITION", "TK_PARTITION", WINDOWFUNC }, { "PLAN", "TK_PLAN", EXPLAIN }, { "PRAGMA", "TK_PRAGMA", PRAGMA }, { "PRECEDING", "TK_PRECEDING", WINDOWFUNC }, { "PRIMARY", "TK_PRIMARY", ALWAYS }, { "QUERY", "TK_QUERY", EXPLAIN }, { "RAISE", "TK_RAISE", TRIGGER }, { "RANGE", "TK_RANGE", WINDOWFUNC }, { "RECURSIVE", "TK_RECURSIVE", CTE }, { "REFERENCES", "TK_REFERENCES", FKEY }, { "REGEXP", "TK_LIKE_KW", ALWAYS }, { "REINDEX", "TK_REINDEX", REINDEX }, { "RELEASE", "TK_RELEASE", ALWAYS }, { "RENAME", "TK_RENAME", ALTER }, { "REPLACE", "TK_REPLACE", CONFLICT }, { "RESTRICT", "TK_RESTRICT", FKEY }, { "RIGHT", "TK_JOIN_KW", ALWAYS }, { "ROLLBACK", "TK_ROLLBACK", ALWAYS }, { "ROW", "TK_ROW", TRIGGER }, { "ROWS", "TK_ROWS", ALWAYS }, { "SAVEPOINT", "TK_SAVEPOINT", ALWAYS }, { "SELECT", "TK_SELECT", ALWAYS }, { "SET", "TK_SET", ALWAYS }, { "TABLE", "TK_TABLE", ALWAYS }, { "TEMP", "TK_TEMP", ALWAYS }, { "TEMPORARY", "TK_TEMP", ALWAYS }, { "THEN", "TK_THEN", ALWAYS }, { "TO", "TK_TO", ALWAYS }, { "TRANSACTION", "TK_TRANSACTION", ALWAYS }, { "TRIGGER", "TK_TRIGGER", TRIGGER }, { "UNBOUNDED", "TK_UNBOUNDED", WINDOWFUNC }, { "UNION", "TK_UNION", COMPOUND }, { "UNIQUE", "TK_UNIQUE", ALWAYS }, { "UPDATE", "TK_UPDATE", ALWAYS }, { "USING", "TK_USING", ALWAYS }, { "VACUUM", "TK_VACUUM", VACUUM }, { "VALUES", "TK_VALUES", ALWAYS }, { "VIEW", "TK_VIEW", VIEW }, { "VIRTUAL", "TK_VIRTUAL", VTAB }, { "WINDOW", "TK_WINDOW", WINDOWFUNC }, { "WITH", "TK_WITH", CTE }, { "WITHOUT", "TK_WITHOUT", ALWAYS }, { "WHEN", "TK_WHEN", ALWAYS }, { "WHERE", "TK_WHERE", ALWAYS }, }; /* Number of keywords */ |
︙ | ︙ |
Changes to tool/mksqlite3c-noext.tcl.
︙ | ︙ | |||
347 348 349 350 351 352 353 354 355 356 357 358 359 360 | trigger.c update.c vacuum.c vtab.c wherecode.c whereexpr.c where.c parse.c tokenize.c complete.c main.c | > | 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 | trigger.c update.c vacuum.c vtab.c wherecode.c whereexpr.c where.c window.c parse.c tokenize.c complete.c main.c |
︙ | ︙ |
Changes to tool/mksqlite3c.tcl.
︙ | ︙ | |||
365 366 367 368 369 370 371 372 373 374 375 376 377 378 | update.c upsert.c vacuum.c vtab.c wherecode.c whereexpr.c where.c parse.c tokenize.c complete.c main.c | > | 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 | update.c upsert.c vacuum.c vtab.c wherecode.c whereexpr.c where.c window.c parse.c tokenize.c complete.c main.c |
︙ | ︙ |