mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-08 14:02:16 +03:00
Merge the latest trunk enhancements into the reuse-schema branch.
FossilOrigin-Name: c2d4adabb929b6088808b05a2f031d045eb4839b44548a66006dc21e358e71f4
This commit is contained in:
@@ -819,8 +819,7 @@ has_tclsh85:
|
|||||||
touch .target_source
|
touch .target_source
|
||||||
|
|
||||||
sqlite3.c: .target_source $(TOP)/tool/mksqlite3c.tcl src-verify has_tclsh84
|
sqlite3.c: .target_source $(TOP)/tool/mksqlite3c.tcl src-verify has_tclsh84
|
||||||
$(TCLSH_CMD) $(TOP)/tool/mksqlite3c.tcl $(AMALGAMATION_LINE_MACROS) \
|
$(TCLSH_CMD) $(TOP)/tool/mksqlite3c.tcl $(AMALGAMATION_LINE_MACROS) $(EXTRA_SRC)
|
||||||
$(EXTRA_SRC)
|
|
||||||
cp tsrc/sqlite3ext.h .
|
cp tsrc/sqlite3ext.h .
|
||||||
cp $(TOP)/ext/session/sqlite3session.h .
|
cp $(TOP)/ext/session/sqlite3session.h .
|
||||||
|
|
||||||
@@ -831,8 +830,7 @@ sqlite3r.c: sqlite3.c sqlite3r.h has_tclsh84
|
|||||||
cp $(TOP)/ext/recover/sqlite3recover.c tsrc/
|
cp $(TOP)/ext/recover/sqlite3recover.c tsrc/
|
||||||
cp $(TOP)/ext/recover/sqlite3recover.h tsrc/
|
cp $(TOP)/ext/recover/sqlite3recover.h tsrc/
|
||||||
cp $(TOP)/ext/recover/dbdata.c tsrc/
|
cp $(TOP)/ext/recover/dbdata.c tsrc/
|
||||||
$(TCLSH_CMD) $(TOP)/tool/mksqlite3c.tcl --enable-recover \
|
$(TCLSH_CMD) $(TOP)/tool/mksqlite3c.tcl --enable-recover $(AMALGAMATION_LINE_MACROS) $(EXTRA_SRC)
|
||||||
$(AMALGAMATION_LINE_MACROS) $(EXTRA_SRC)
|
|
||||||
|
|
||||||
sqlite3ext.h: .target_source
|
sqlite3ext.h: .target_source
|
||||||
cp tsrc/sqlite3ext.h .
|
cp tsrc/sqlite3ext.h .
|
||||||
|
@@ -51,7 +51,7 @@
|
|||||||
*/
|
*/
|
||||||
"use strict";
|
"use strict";
|
||||||
const wPost = (type,...args)=>postMessage({type, payload:args});
|
const wPost = (type,...args)=>postMessage({type, payload:args});
|
||||||
const installAsyncProxy = function(self){
|
const installAsyncProxy = function(){
|
||||||
const toss = function(...args){throw new Error(args.join(' '))};
|
const toss = function(...args){throw new Error(args.join(' '))};
|
||||||
if(globalThis.window === globalThis){
|
if(globalThis.window === globalThis){
|
||||||
toss("This code cannot run from the main thread.",
|
toss("This code cannot run from the main thread.",
|
||||||
@@ -563,12 +563,9 @@ const installAsyncProxy = function(self){
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if( state.opfsFlags.OPFS_UNLINK_BEFORE_OPEN & opfsFlags ){
|
if( state.opfsFlags.OPFS_UNLINK_BEFORE_OPEN & opfsFlags ){
|
||||||
//log("async proxy opfsFlags =",opfsFlags);
|
|
||||||
try{
|
try{
|
||||||
await hDir.removeEntry(filenamePart);
|
await hDir.removeEntry(filenamePart);
|
||||||
//log("Unlinked",filename,hDir,filenamePart);
|
}catch(e){
|
||||||
}
|
|
||||||
catch(e){
|
|
||||||
/* ignoring */
|
/* ignoring */
|
||||||
//warn("Ignoring failed Unlink of",filename,":",e);
|
//warn("Ignoring failed Unlink of",filename,":",e);
|
||||||
}
|
}
|
||||||
@@ -922,5 +919,5 @@ if(!globalThis.SharedArrayBuffer){
|
|||||||
!navigator?.storage?.getDirectory){
|
!navigator?.storage?.getDirectory){
|
||||||
wPost('opfs-unavailable',"Missing required OPFS APIs.");
|
wPost('opfs-unavailable',"Missing required OPFS APIs.");
|
||||||
}else{
|
}else{
|
||||||
installAsyncProxy(self);
|
installAsyncProxy();
|
||||||
}
|
}
|
||||||
|
48
manifest
48
manifest
@@ -1,9 +1,9 @@
|
|||||||
C Do\snot\sautomatically\sactivate\sSQLITE_ENABLE_SHARED_SCHEMA\sin\sthe\nMakefile.\s\sInstead,\senhance\sthe\smdevtest\sand\ssdevtest\stargets\sof\ntestrunner.tcl\sto\sset\sthat\soption\ssometimes\sand\ssometimes\snot.
|
C Merge\sthe\slatest\strunk\senhancements\sinto\sthe\sreuse-schema\sbranch.
|
||||||
D 2024-03-13T16:49:36.651
|
D 2024-03-18T18:56:10.107
|
||||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||||
F Makefile.in da128eae24b56cbbf05e131d3342323846ea62a534a964d32fb7f06ae974f89f
|
F Makefile.in e4803e664ceb8ddbc3f9ead25cbe0b3d3def21a77c175124b421e6a53b105b8d
|
||||||
F Makefile.linux-gcc f3842a0b1efbfbb74ac0ef60e56b301836d05b4d867d014f714fa750048f1ab6
|
F Makefile.linux-gcc f3842a0b1efbfbb74ac0ef60e56b301836d05b4d867d014f714fa750048f1ab6
|
||||||
F Makefile.msc a6f772c667c3a967c1a65b8f7bf1502b73001052567b5c7702cde8dc80f2568b
|
F Makefile.msc a6f772c667c3a967c1a65b8f7bf1502b73001052567b5c7702cde8dc80f2568b
|
||||||
F README.md 6358805260a03ebead84e168bbf3740ddf3f683b477e478567186aa7afb490d3
|
F README.md 6358805260a03ebead84e168bbf3740ddf3f683b477e478567186aa7afb490d3
|
||||||
@@ -611,7 +611,7 @@ F ext/wasm/api/sqlite3-api-oo1.js 7f3bcf0549ac44cde4b9da0b642d771916738d3f6781fb
|
|||||||
F ext/wasm/api/sqlite3-api-prologue.js 93a72b07b2a5d964d2edc76a90b439ece49298bd7ba60a1c6ae5d4878213701e
|
F ext/wasm/api/sqlite3-api-prologue.js 93a72b07b2a5d964d2edc76a90b439ece49298bd7ba60a1c6ae5d4878213701e
|
||||||
F ext/wasm/api/sqlite3-api-worker1.js 8d9c0562831f62218170a3373468d8a0b7a6503b5985e309b69bf71187b525cf
|
F ext/wasm/api/sqlite3-api-worker1.js 8d9c0562831f62218170a3373468d8a0b7a6503b5985e309b69bf71187b525cf
|
||||||
F ext/wasm/api/sqlite3-license-version-header.js 0c807a421f0187e778dc1078f10d2994b915123c1223fe752b60afdcd1263f89
|
F ext/wasm/api/sqlite3-license-version-header.js 0c807a421f0187e778dc1078f10d2994b915123c1223fe752b60afdcd1263f89
|
||||||
F ext/wasm/api/sqlite3-opfs-async-proxy.js b4c7ce9d7f7957f243d0fbd5b6e28bac80cd3c1b738374cd0c96d89df8f2f316
|
F ext/wasm/api/sqlite3-opfs-async-proxy.js 196ad83d36ca794e564044788c9d21b964679d63cad865f604da37c4afc9a285
|
||||||
F ext/wasm/api/sqlite3-vfs-helper.c-pp.js 3f828cc66758acb40e9c5b4dcfd87fd478a14c8fb7f0630264e6c7fa0e57515d
|
F ext/wasm/api/sqlite3-vfs-helper.c-pp.js 3f828cc66758acb40e9c5b4dcfd87fd478a14c8fb7f0630264e6c7fa0e57515d
|
||||||
F ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js 5a430874906ff3f4a6ca69aadf0c2aaedc1bb45489b8365bff7e955a83a8d42a
|
F ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js 5a430874906ff3f4a6ca69aadf0c2aaedc1bb45489b8365bff7e955a83a8d42a
|
||||||
F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 3c72f1a0e6a7343c8c882d29d01bb440f10be12c844651605b486e76f3d6cc8c
|
F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 3c72f1a0e6a7343c8c882d29d01bb440f10be12c844651605b486e76f3d6cc8c
|
||||||
@@ -701,7 +701,7 @@ F src/date.c 126ba2ab10aeb2e7ba6e089b5f07b747c0625b8287f78b60da346eda8d23c875
|
|||||||
F src/dbpage.c 80e46e1df623ec40486da7a5086cb723b0275a6e2a7b01d9f9b5da0f04ba2782
|
F src/dbpage.c 80e46e1df623ec40486da7a5086cb723b0275a6e2a7b01d9f9b5da0f04ba2782
|
||||||
F src/dbstat.c 3b677254d512fcafd4d0b341bf267b38b235ccfddbef24f9154e19360fa22e43
|
F src/dbstat.c 3b677254d512fcafd4d0b341bf267b38b235ccfddbef24f9154e19360fa22e43
|
||||||
F src/delete.c cb766727c78e715f9fb7ec8a7d03658ed2a3016343ca687acfcec9083cdca500
|
F src/delete.c cb766727c78e715f9fb7ec8a7d03658ed2a3016343ca687acfcec9083cdca500
|
||||||
F src/expr.c 05516e8b7d7d22f98160a0360fde69edce3304a430600567ed33e66d588ca59b
|
F src/expr.c d7cfe9b9fe7ab47b254706589467d2e65fec3536b936d6f4eb28b84da6726ecc
|
||||||
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
|
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
|
||||||
F src/fkey.c a47610f0a5c6cb0ad79f8fcef039c01833dec0c751bb695f28dc0ec6a4c3ba00
|
F src/fkey.c a47610f0a5c6cb0ad79f8fcef039c01833dec0c751bb695f28dc0ec6a4c3ba00
|
||||||
F src/func.c 4204c56196847faefef57fa14e43b8e4d65eb8d7e65318abe463472e3fd148cb
|
F src/func.c 4204c56196847faefef57fa14e43b8e4d65eb8d7e65318abe463472e3fd148cb
|
||||||
@@ -710,7 +710,7 @@ F src/hash.c 9ee4269fb1d6632a6fecfb9479c93a1f29271bddbbaf215dd60420bcb80c7220
|
|||||||
F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51
|
F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51
|
||||||
F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6
|
F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6
|
||||||
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
|
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
|
||||||
F src/insert.c eb33ea46dcab93e90f112fced343aaf41f59cbd2e951d5066f1f9302be1c2f34
|
F src/insert.c 06ce505713e86172612f9e01febefd2d3331d1f70461b4ada0eae5a76bb6349f
|
||||||
F src/json.c e2e40760d6689134c3e2ece38c6a496b34ff5e2661a8f238444a119af666fdce
|
F src/json.c e2e40760d6689134c3e2ece38c6a496b34ff5e2661a8f238444a119af666fdce
|
||||||
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
|
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
|
||||||
F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36
|
F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36
|
||||||
@@ -740,23 +740,23 @@ F src/os_win.c 6ff43bac175bd9ed79e7c0f96840b139f2f51d01689a638fd05128becf94908a
|
|||||||
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
|
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
|
||||||
F src/pager.c ff60e98138d2499082ac6230f01ac508aba545315debccfca2fd6042f5f10fcd
|
F src/pager.c ff60e98138d2499082ac6230f01ac508aba545315debccfca2fd6042f5f10fcd
|
||||||
F src/pager.h 4b1140d691860de0be1347474c51fee07d5420bd7f802d38cbab8ea4ab9f538a
|
F src/pager.h 4b1140d691860de0be1347474c51fee07d5420bd7f802d38cbab8ea4ab9f538a
|
||||||
F src/parse.y 6209f01e8e7495379571454744fa82a5cfc2e7eeb89e46dee3f410d73ea6252d
|
F src/parse.y 5bcef16094213efcc365a9d4dc4e3131f09251dc8838dce4a9e5f9764bff5b82
|
||||||
F src/pcache.c 040b165f30622a21b7a9a77c6f2e4877a32fb7f22d4c7f0d2a6fa6833a156a75
|
F src/pcache.c 040b165f30622a21b7a9a77c6f2e4877a32fb7f22d4c7f0d2a6fa6833a156a75
|
||||||
F src/pcache.h 1497ce1b823cf00094bb0cf3bac37b345937e6f910890c626b16512316d3abf5
|
F src/pcache.h 1497ce1b823cf00094bb0cf3bac37b345937e6f910890c626b16512316d3abf5
|
||||||
F src/pcache1.c 602acb23c471bb8d557a6f0083cc2be641d6cafcafa19e481eba7ef4c9ca0f00
|
F src/pcache1.c 602acb23c471bb8d557a6f0083cc2be641d6cafcafa19e481eba7ef4c9ca0f00
|
||||||
F src/pragma.c e921676f6c29502c681b53d0c5d609a8780eaeeddbaa76459aa7607efc6a2760
|
F src/pragma.c e921676f6c29502c681b53d0c5d609a8780eaeeddbaa76459aa7607efc6a2760
|
||||||
F src/pragma.h 50f6d3b408ed56bde4f4e4aead8c0b2022030b692e8de237c1b7a0b5ce87a0c8
|
F src/pragma.h 50f6d3b408ed56bde4f4e4aead8c0b2022030b692e8de237c1b7a0b5ce87a0c8
|
||||||
F src/prepare.c 9fe59f2cf0b75554982ffe906c83ebe478354b6d981ed0c143cc9f2f58c9210a
|
F src/prepare.c 9fe59f2cf0b75554982ffe906c83ebe478354b6d981ed0c143cc9f2f58c9210a
|
||||||
F src/printf.c 10e8bad30042f8bd6114a013b4afc229ec8ad255ab27518d7d9f52e8cbc5cd0a
|
F src/printf.c 87b67bba3662a0523f39ae6b084a3907109702f717c654d6cecb838af5cd57f1
|
||||||
F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
|
F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
|
||||||
F src/resolve.c ef87e3bc7700bfe761a7bbee2ce6084f1766dc816dd82a3ae77c133eec898432
|
F src/resolve.c ef87e3bc7700bfe761a7bbee2ce6084f1766dc816dd82a3ae77c133eec898432
|
||||||
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
|
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
|
||||||
F src/select.c 43fabfc01bf87addd15e39f112f1e2ade15b19594835ab8a9e5bd50839d4e1b1
|
F src/select.c df2bf515fc36e02e97959a70e82da8a4967d6c85590646a7fda2926a734c81ce
|
||||||
F src/shell.c.in 736d540ed0704e567767c712e1c1c6a3e2f87bb8b7bc9020febb121ee2f70abe
|
F src/shell.c.in 736d540ed0704e567767c712e1c1c6a3e2f87bb8b7bc9020febb121ee2f70abe
|
||||||
F src/sqlite.h.in 1e317e1d0a17becd7ad9d1d30f2a248d78440d3ca2befead0e747043ebb1989a
|
F src/sqlite.h.in 1e317e1d0a17becd7ad9d1d30f2a248d78440d3ca2befead0e747043ebb1989a
|
||||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||||
F src/sqlite3ext.h 3f046c04ea3595d6bfda99b781926b17e672fd6d27da2ba6d8d8fc39981dcb54
|
F src/sqlite3ext.h 3f046c04ea3595d6bfda99b781926b17e672fd6d27da2ba6d8d8fc39981dcb54
|
||||||
F src/sqliteInt.h 1e23a22284150bd911b2cb5a041a7f315f5c92167db7822188f970b69f7fa224
|
F src/sqliteInt.h c472e384c0d70a352ce7239a29a799b93ee6d8bc385bbf0be7e8afcbc525b131
|
||||||
F src/sqliteLimit.h 6878ab64bdeb8c24a1d762d45635e34b96da21132179023338c93f820eee6728
|
F src/sqliteLimit.h 6878ab64bdeb8c24a1d762d45635e34b96da21132179023338c93f820eee6728
|
||||||
F src/status.c 5028a0afee355aa492f26f0b6a3ec23145caa9261a93164d96cd0b9bf1b2318f
|
F src/status.c 5028a0afee355aa492f26f0b6a3ec23145caa9261a93164d96cd0b9bf1b2318f
|
||||||
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
|
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
|
||||||
@@ -837,11 +837,11 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
|
|||||||
F src/wal.c 887fc4ca3f020ebb2e376f222069570834ac63bf50111ef0cbf3ae417048ed89
|
F src/wal.c 887fc4ca3f020ebb2e376f222069570834ac63bf50111ef0cbf3ae417048ed89
|
||||||
F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452
|
F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452
|
||||||
F src/walker.c 7c7ea0115345851c3da4e04e2e239a29983b61fb5b038b94eede6aba462640e2
|
F src/walker.c 7c7ea0115345851c3da4e04e2e239a29983b61fb5b038b94eede6aba462640e2
|
||||||
F src/where.c 6e171826508b08356a3a103a6739eb538d755578fdc1dbf5db84f574672db672
|
F src/where.c a34a0eeb04a6c5916b576752dfdca8947c46d2463a2c9805919c8d781b3bdd1f
|
||||||
F src/whereInt.h 82a13766f13d1a53b05387c2e60726289ef26404bc7b9b1f7770204d97357fb8
|
F src/whereInt.h 82a13766f13d1a53b05387c2e60726289ef26404bc7b9b1f7770204d97357fb8
|
||||||
F src/wherecode.c 5d77db30a2a3dd532492ae882de114edba2fae672622056b1c7fd61f5917a8f1
|
F src/wherecode.c 5d77db30a2a3dd532492ae882de114edba2fae672622056b1c7fd61f5917a8f1
|
||||||
F src/whereexpr.c 6ebd90b553f4bb5c7df5a4b2f39b6a7c81a67484353827cdd2048f2514ec6f30
|
F src/whereexpr.c 7b64295f1d82ad0928df435925dd7bbd5997b44a026153113eace0d9e71ff435
|
||||||
F src/window.c 5b1387d59df30d481ed14cceef5f4d1dab1f8752aa106ba72c8b62777bd139d2
|
F src/window.c 5d95122dd330bfaebd732358c8ef067c5a9394a53ac249470d611d0ce2c52be2
|
||||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||||
F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627
|
F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627
|
||||||
F test/affinity3.test f094773025eddf31135c7ad4cde722b7696f8eb07b97511f98585addf2a510a9
|
F test/affinity3.test f094773025eddf31135c7ad4cde722b7696f8eb07b97511f98585addf2a510a9
|
||||||
@@ -869,7 +869,7 @@ F test/altermalloc3.test 8040e486368403f2fdd6fc3998258b499bd4cc2f3ddbb5f8f874cd4
|
|||||||
F test/alterqf.test 8ec03d776de9c391daa0078ea8f838903bdcfb11dfae4ba3576b48436834ccba
|
F test/alterqf.test 8ec03d776de9c391daa0078ea8f838903bdcfb11dfae4ba3576b48436834ccba
|
||||||
F test/altertab.test 8a2712f9076da5012a002d0b5cc0a421398a5bf61c25bab41b77c427586a7a27
|
F test/altertab.test 8a2712f9076da5012a002d0b5cc0a421398a5bf61c25bab41b77c427586a7a27
|
||||||
F test/altertab2.test 62597b6fd08feaba1b6bfe7d31dac6117c67e06dc9ce9c478a3abe75b5926de0
|
F test/altertab2.test 62597b6fd08feaba1b6bfe7d31dac6117c67e06dc9ce9c478a3abe75b5926de0
|
||||||
F test/altertab3.test 6c432fbb9963e0bd6549bf1422f6861d744ee5a80cb3298564e81e556481df16
|
F test/altertab3.test e167ce3b8e243b52306c1e40b13eb868f402a969513c063998593862cc643b44
|
||||||
F test/altertrig.test aacc980b657354fe2d3d4d3a004f07d04ccc1a93e5ef82d68a79088c274ddc6b
|
F test/altertrig.test aacc980b657354fe2d3d4d3a004f07d04ccc1a93e5ef82d68a79088c274ddc6b
|
||||||
F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f
|
F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f
|
||||||
F test/analyze.test 2fb21d7d64748636384e6cb8998dbf83968caf644c07fcb4f76c18f2e7ede94b
|
F test/analyze.test 2fb21d7d64748636384e6cb8998dbf83968caf644c07fcb4f76c18f2e7ede94b
|
||||||
@@ -1233,7 +1233,7 @@ F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d
|
|||||||
F test/func.test 504d202650c7940b5aa98364dd68f242df87f39f829e51074a55d79fc7bc7414
|
F test/func.test 504d202650c7940b5aa98364dd68f242df87f39f829e51074a55d79fc7bc7414
|
||||||
F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f
|
F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f
|
||||||
F test/func3.test 600a632c305a88f3946d38f9a51efe145c989b2e13bd2b2a488db47fe76bab6a
|
F test/func3.test 600a632c305a88f3946d38f9a51efe145c989b2e13bd2b2a488db47fe76bab6a
|
||||||
F test/func4.test e8ef9b2bd6a192a213cbd5cf31a3b35e25cd6ff2fdaeea0b58d63be31b03d220
|
F test/func4.test a3f9062487dbd826776f54f4e0e9517fe8c3cf689af92735308965774d51fac5
|
||||||
F test/func5.test 863e6d1bd0013d09c17236f8a13ea34008dd857d87d85a13a673960e4c25d82a
|
F test/func5.test 863e6d1bd0013d09c17236f8a13ea34008dd857d87d85a13a673960e4c25d82a
|
||||||
F test/func6.test 9cc9b1f43b435af34fe1416eb1e318c8920448ea7a6962f2121972f5215cb9b0
|
F test/func6.test 9cc9b1f43b435af34fe1416eb1e318c8920448ea7a6962f2121972f5215cb9b0
|
||||||
F test/func7.test adbfc910385a6ffd15dc47be3c619ef070c542fcb7488964badb17b2d9a4d080
|
F test/func7.test adbfc910385a6ffd15dc47be3c619ef070c542fcb7488964badb17b2d9a4d080
|
||||||
@@ -1273,7 +1273,7 @@ F test/imposter1.test c3f1db2d3db2c24611a6596a3fc0ffc14f1466c8
|
|||||||
F test/in.test d1cad4ededd425568b2e39fb0c31fa9a3772311dd595801ff13ba3912b69bba6
|
F test/in.test d1cad4ededd425568b2e39fb0c31fa9a3772311dd595801ff13ba3912b69bba6
|
||||||
F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75
|
F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75
|
||||||
F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0
|
F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0
|
||||||
F test/in4.test fdd1d8134da8376985c2edba6035a2de1f6c731524d2ffa651419e8fe2cd1c5a
|
F test/in4.test bb767ec1cfd1730256f0a83219f0acda36bc251b63f8b8bb7d8c7cff17875a4f
|
||||||
F test/in5.test b32ce7f4a93f44c5dee94af16886d922cc16ebe33c8e1765c73d4049d0f4b40f
|
F test/in5.test b32ce7f4a93f44c5dee94af16886d922cc16ebe33c8e1765c73d4049d0f4b40f
|
||||||
F test/in6.test f5f40d6816a8bb7c784424b58a10ac38efb76ab29127a2c17399e0cbeeda0e4b
|
F test/in6.test f5f40d6816a8bb7c784424b58a10ac38efb76ab29127a2c17399e0cbeeda0e4b
|
||||||
F test/incrblob.test c9b96afc292aeff43d6687bcb09b0280aa599822
|
F test/incrblob.test c9b96afc292aeff43d6687bcb09b0280aa599822
|
||||||
@@ -1657,7 +1657,7 @@ F test/spellfix2.test dfc8f519a3fc204cb2dfa8b4f29821ae90f6f8c3
|
|||||||
F test/spellfix3.test 0f9efaaa502a0e0a09848028518a6fb096c8ad33
|
F test/spellfix3.test 0f9efaaa502a0e0a09848028518a6fb096c8ad33
|
||||||
F test/spellfix4.test 51c7c26514ade169855c66bcf130bd5acfb4d7fd090cc624645ab275ae6a41fb
|
F test/spellfix4.test 51c7c26514ade169855c66bcf130bd5acfb4d7fd090cc624645ab275ae6a41fb
|
||||||
F test/sqldiff1.test 1b7ab4f312442c5cc6b3a5f299fa8ca051416d1dd173cb1126fd51bf64f2c3fb
|
F test/sqldiff1.test 1b7ab4f312442c5cc6b3a5f299fa8ca051416d1dd173cb1126fd51bf64f2c3fb
|
||||||
F test/sqllimits1.test 5880a2f107185744ba4d93637f44c78d17706a9899a38b694d50f209735c81cc
|
F test/sqllimits1.test dee96a51b83ef866d06ec3c687d4c951d97b02549facc5be88c9dfcb215b98bf
|
||||||
F test/sqllog.test 6af6cb0b09f4e44e1917e06ce85be7670302517a
|
F test/sqllog.test 6af6cb0b09f4e44e1917e06ce85be7670302517a
|
||||||
F test/startup.c 1beb5ca66fcc0fce95c3444db9d1674f90fc605499a574ae2434dcfc10d22805
|
F test/startup.c 1beb5ca66fcc0fce95c3444db9d1674f90fc605499a574ae2434dcfc10d22805
|
||||||
F test/stat.test 123212a20ceb496893d5254a5f6c76442ce549fdc08d1702d8288a2bbaac8408
|
F test/stat.test 123212a20ceb496893d5254a5f6c76442ce549fdc08d1702d8288a2bbaac8408
|
||||||
@@ -1696,7 +1696,7 @@ F test/temptable2.test 76821347810ecc88203e6ef0dd6897b6036ac788e9dd3e6b04fd4d163
|
|||||||
F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637
|
F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637
|
||||||
F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc
|
F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc
|
||||||
F test/tester.tcl ad2bf61b6676442e106c147f6d8b3735a61478f7c6ee9916178139efafc39232
|
F test/tester.tcl ad2bf61b6676442e106c147f6d8b3735a61478f7c6ee9916178139efafc39232
|
||||||
F test/testrunner.tcl 841b082df19abd3d482f893c82a7795401539ba8f0df321290e5f4392cd167a6
|
F test/testrunner.tcl 125d68bba59070d73cb4b0a8a17bbff414ee1f8081eafb84fa903d274e0bdbb7
|
||||||
F test/testrunner_data.tcl 140b7201874bb2c98ed413f2c7f7beb069a6ef7b5fa619e9b458e20822f09110
|
F test/testrunner_data.tcl 140b7201874bb2c98ed413f2c7f7beb069a6ef7b5fa619e9b458e20822f09110
|
||||||
F test/thread001.test a0985c117eab62c0c65526e9fa5d1360dd1cac5b03bde223902763274ce21899
|
F test/thread001.test a0985c117eab62c0c65526e9fa5d1360dd1cac5b03bde223902763274ce21899
|
||||||
F test/thread002.test c24c83408e35ba5a952a3638b7ac03ccdf1ce4409289c54a050ac4c5f1de7502
|
F test/thread002.test c24c83408e35ba5a952a3638b7ac03ccdf1ce4409289c54a050ac4c5f1de7502
|
||||||
@@ -1931,6 +1931,8 @@ F test/vacuum4.test 7ea76b769fffeb41f925303b04cbcf5a5bbeabe55e4c60ae754ff24eeeb7
|
|||||||
F test/vacuum5.test 263b144d537e92ad8e9ca8a73cc6e1583f41cfd0dda9432b87f7806174a2f48c
|
F test/vacuum5.test 263b144d537e92ad8e9ca8a73cc6e1583f41cfd0dda9432b87f7806174a2f48c
|
||||||
F test/vacuum6.test b137b04bf3392d3f5c3b8fda0ce85a6775a70ca112f6559f74ff52dc9ce042fd
|
F test/vacuum6.test b137b04bf3392d3f5c3b8fda0ce85a6775a70ca112f6559f74ff52dc9ce042fd
|
||||||
F test/vacuummem.test 4b30f5b95a9ff86e9d5c20741e50a898b2dc10b0962a3211571eb165357003fb
|
F test/vacuummem.test 4b30f5b95a9ff86e9d5c20741e50a898b2dc10b0962a3211571eb165357003fb
|
||||||
|
F test/values.test e7c156f92d32ed645908fbad0a1144f0f31650376cdcb212fde701978c89d3b1
|
||||||
|
F test/valuesfault.test 2ef23ed965e3bd08e268cdc38a0d11653390ddbbe1e8e2e98d16f55edd30f6e8
|
||||||
F test/varint.test bbce22cda8fc4d135bcc2b589574be8410614e62
|
F test/varint.test bbce22cda8fc4d135bcc2b589574be8410614e62
|
||||||
F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661
|
F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661
|
||||||
F test/view.test d4c4281e1679245829db35597817282f60dc513fc39cc5439078f009bd118487
|
F test/view.test d4c4281e1679245829db35597817282f60dc513fc39cc5439078f009bd118487
|
||||||
@@ -2019,7 +2021,7 @@ F test/whereH.test e4b07f7a3c2f5d31195cd33710054c78667573b2
|
|||||||
F test/whereI.test c4bb7e2ca56d49bd8ab5c7bd085b8b83e353922b46904d68aefb3c7468643581
|
F test/whereI.test c4bb7e2ca56d49bd8ab5c7bd085b8b83e353922b46904d68aefb3c7468643581
|
||||||
F test/whereJ.test fc05e374cc9f2dc204148d6c06822c380ad388895fe97a6d335b94a26a08aecf
|
F test/whereJ.test fc05e374cc9f2dc204148d6c06822c380ad388895fe97a6d335b94a26a08aecf
|
||||||
F test/whereK.test 0270ab7f04ba5436fb9156d31d642a1c82727f4c4bfe5ba90d435c78cf44684a
|
F test/whereK.test 0270ab7f04ba5436fb9156d31d642a1c82727f4c4bfe5ba90d435c78cf44684a
|
||||||
F test/whereL.test f0e9585623af522ee9f382f8f945ad4b7eb7d806d18746f33f00c374acf6ab65
|
F test/whereL.test 438a397fa883b77bb6361c08a8befa41b52e9cfbe15a2a43715d122f8cfa8649
|
||||||
F test/whereM.test 0dbc9998783458ddcf3cc078ca7c2951d8b2677d472ecf0028f449ed327c0250
|
F test/whereM.test 0dbc9998783458ddcf3cc078ca7c2951d8b2677d472ecf0028f449ed327c0250
|
||||||
F test/wherefault.test 6cf2a9c5712952d463d3f45ebee7f6caf400984df51a195d884cfb7eb0e837a7
|
F test/wherefault.test 6cf2a9c5712952d463d3f45ebee7f6caf400984df51a195d884cfb7eb0e837a7
|
||||||
F test/wherelfault.test 9012e4ef5259058b771606616bd007af5d154e64cc25fa9fd4170f6411db44e3
|
F test/wherelfault.test 9012e4ef5259058b771606616bd007af5d154e64cc25fa9fd4170f6411db44e3
|
||||||
@@ -2098,7 +2100,7 @@ F tool/genfkey.test b6afd7b825d797a1e1274f519ab5695373552ecad5cd373530c63533638a
|
|||||||
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
|
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
|
||||||
F tool/index_usage.c f62a0c701b2c7ff2f3e21d206f093c123f222dbf07136a10ffd1ca15a5c706c5
|
F tool/index_usage.c f62a0c701b2c7ff2f3e21d206f093c123f222dbf07136a10ffd1ca15a5c706c5
|
||||||
F tool/kvtest-speed.sh 4761a9c4b3530907562314d7757995787f7aef8f
|
F tool/kvtest-speed.sh 4761a9c4b3530907562314d7757995787f7aef8f
|
||||||
F tool/lemon.c 7f264d5d06450f929a20fa63a1b7e8f2df47dfaa6d7f80e4afef3639157497a4
|
F tool/lemon.c 2eaee61479f9b97056950741c8f671a13281c819b94246698264a322360319a9
|
||||||
F tool/lempar.c e6b649778e5c027c8365ff01d7ef39297cd7285fa1f881cce31792689541e79f
|
F tool/lempar.c e6b649778e5c027c8365ff01d7ef39297cd7285fa1f881cce31792689541e79f
|
||||||
F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9
|
F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9
|
||||||
F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862
|
F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862
|
||||||
@@ -2187,8 +2189,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
|||||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||||
P da47151561fb7045dbfe9967b27c10bfd754bc88f537c43f5e3739b52b703f72
|
P 693b8f9307fc9d3e00f2a573329f054709ad916a570773c986d32524b4d7522e 76fb3a908f45230b956cb659c754e47603e80aa72a2aad50d479437a9c013f61
|
||||||
R f9ddc79a6ef5671bab269c8fc35a39f2
|
R aa84582729c32dbdf9ff004281703344
|
||||||
U drh
|
U drh
|
||||||
Z 28013b67504b9c056878bcc413a4fa76
|
Z 1460fe2e76c9e3a0dadc727534aebd41
|
||||||
# Remove this line to create a well-formed Fossil manifest.
|
# Remove this line to create a well-formed Fossil manifest.
|
||||||
|
@@ -1 +1 @@
|
|||||||
693b8f9307fc9d3e00f2a573329f054709ad916a570773c986d32524b4d7522e
|
c2d4adabb929b6088808b05a2f031d045eb4839b44548a66006dc21e358e71f4
|
98
src/expr.c
98
src/expr.c
@@ -218,9 +218,10 @@ Expr *sqlite3ExprSkipCollateAndLikely(Expr *pExpr){
|
|||||||
assert( pExpr->x.pList->nExpr>0 );
|
assert( pExpr->x.pList->nExpr>0 );
|
||||||
assert( pExpr->op==TK_FUNCTION );
|
assert( pExpr->op==TK_FUNCTION );
|
||||||
pExpr = pExpr->x.pList->a[0].pExpr;
|
pExpr = pExpr->x.pList->a[0].pExpr;
|
||||||
}else{
|
}else if( pExpr->op==TK_COLLATE ){
|
||||||
assert( pExpr->op==TK_COLLATE );
|
|
||||||
pExpr = pExpr->pLeft;
|
pExpr = pExpr->pLeft;
|
||||||
|
}else{
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return pExpr;
|
return pExpr;
|
||||||
@@ -1869,6 +1870,7 @@ SrcList *sqlite3SrcListDup(sqlite3 *db, const SrcList *p, int flags){
|
|||||||
pNewItem->iCursor = pOldItem->iCursor;
|
pNewItem->iCursor = pOldItem->iCursor;
|
||||||
pNewItem->addrFillSub = pOldItem->addrFillSub;
|
pNewItem->addrFillSub = pOldItem->addrFillSub;
|
||||||
pNewItem->regReturn = pOldItem->regReturn;
|
pNewItem->regReturn = pOldItem->regReturn;
|
||||||
|
pNewItem->regResult = pOldItem->regResult;
|
||||||
if( pNewItem->fg.isIndexedBy ){
|
if( pNewItem->fg.isIndexedBy ){
|
||||||
pNewItem->u1.zIndexedBy = sqlite3DbStrDup(db, pOldItem->u1.zIndexedBy);
|
pNewItem->u1.zIndexedBy = sqlite3DbStrDup(db, pOldItem->u1.zIndexedBy);
|
||||||
}
|
}
|
||||||
@@ -2345,6 +2347,54 @@ Expr *sqlite3ExprSimplifiedAndOr(Expr *pExpr){
|
|||||||
return pExpr;
|
return pExpr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** pExpr is a TK_FUNCTION node. Try to determine whether or not the
|
||||||
|
** function is a constant function. A function is constant if all of
|
||||||
|
** the following are true:
|
||||||
|
**
|
||||||
|
** (1) It is a scalar function (not an aggregate or window function)
|
||||||
|
** (2) It has either the SQLITE_FUNC_CONSTANT or SQLITE_FUNC_SLOCHNG
|
||||||
|
** property.
|
||||||
|
** (3) All of its arguments are constants
|
||||||
|
**
|
||||||
|
** This routine sets pWalker->eCode to 0 if pExpr is not a constant.
|
||||||
|
** It makes no changes to pWalker->eCode if pExpr is constant. In
|
||||||
|
** every case, it returns WRC_Abort.
|
||||||
|
**
|
||||||
|
** Called as a service subroutine from exprNodeIsConstant().
|
||||||
|
*/
|
||||||
|
static SQLITE_NOINLINE int exprNodeIsConstantFunction(
|
||||||
|
Walker *pWalker,
|
||||||
|
Expr *pExpr
|
||||||
|
){
|
||||||
|
int n; /* Number of arguments */
|
||||||
|
ExprList *pList; /* List of arguments */
|
||||||
|
FuncDef *pDef; /* The function */
|
||||||
|
sqlite3 *db; /* The database */
|
||||||
|
|
||||||
|
assert( pExpr->op==TK_FUNCTION );
|
||||||
|
if( ExprHasProperty(pExpr, EP_TokenOnly)
|
||||||
|
|| (pList = pExpr->x.pList)==0
|
||||||
|
){;
|
||||||
|
n = 0;
|
||||||
|
}else{
|
||||||
|
n = pList->nExpr;
|
||||||
|
sqlite3WalkExprList(pWalker, pList);
|
||||||
|
if( pWalker->eCode==0 ) return WRC_Abort;
|
||||||
|
}
|
||||||
|
db = pWalker->pParse->db;
|
||||||
|
pDef = sqlite3FindFunction(db, pExpr->u.zToken, n, ENC(db), 0);
|
||||||
|
if( pDef==0
|
||||||
|
|| pDef->xFinalize!=0
|
||||||
|
|| (pDef->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG))==0
|
||||||
|
|| ExprHasProperty(pExpr, EP_WinFunc)
|
||||||
|
){
|
||||||
|
pWalker->eCode = 0;
|
||||||
|
return WRC_Abort;
|
||||||
|
}
|
||||||
|
return WRC_Continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** These routines are Walker callbacks used to check expressions to
|
** These routines are Walker callbacks used to check expressions to
|
||||||
@@ -2373,6 +2423,7 @@ Expr *sqlite3ExprSimplifiedAndOr(Expr *pExpr){
|
|||||||
** malformed schema error.
|
** malformed schema error.
|
||||||
*/
|
*/
|
||||||
static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
|
static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
|
||||||
|
assert( pWalker->eCode>0 );
|
||||||
|
|
||||||
/* If pWalker->eCode is 2 then any term of the expression that comes from
|
/* If pWalker->eCode is 2 then any term of the expression that comes from
|
||||||
** the ON or USING clauses of an outer join disqualifies the expression
|
** the ON or USING clauses of an outer join disqualifies the expression
|
||||||
@@ -2392,6 +2443,8 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
|
|||||||
){
|
){
|
||||||
if( pWalker->eCode==5 ) ExprSetProperty(pExpr, EP_FromDDL);
|
if( pWalker->eCode==5 ) ExprSetProperty(pExpr, EP_FromDDL);
|
||||||
return WRC_Continue;
|
return WRC_Continue;
|
||||||
|
}else if( pWalker->pParse ){
|
||||||
|
return exprNodeIsConstantFunction(pWalker, pExpr);
|
||||||
}else{
|
}else{
|
||||||
pWalker->eCode = 0;
|
pWalker->eCode = 0;
|
||||||
return WRC_Abort;
|
return WRC_Abort;
|
||||||
@@ -2444,9 +2497,10 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
|
|||||||
return WRC_Continue;
|
return WRC_Continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static int exprIsConst(Expr *p, int initFlag, int iCur){
|
static int exprIsConst(Parse *pParse, Expr *p, int initFlag, int iCur){
|
||||||
Walker w;
|
Walker w;
|
||||||
w.eCode = initFlag;
|
w.eCode = initFlag;
|
||||||
|
w.pParse = pParse;
|
||||||
w.xExprCallback = exprNodeIsConstant;
|
w.xExprCallback = exprNodeIsConstant;
|
||||||
w.xSelectCallback = sqlite3SelectWalkFail;
|
w.xSelectCallback = sqlite3SelectWalkFail;
|
||||||
#ifdef SQLITE_DEBUG
|
#ifdef SQLITE_DEBUG
|
||||||
@@ -2464,9 +2518,15 @@ static int exprIsConst(Expr *p, int initFlag, int iCur){
|
|||||||
** For the purposes of this function, a double-quoted string (ex: "abc")
|
** For the purposes of this function, a double-quoted string (ex: "abc")
|
||||||
** is considered a variable but a single-quoted string (ex: 'abc') is
|
** is considered a variable but a single-quoted string (ex: 'abc') is
|
||||||
** a constant.
|
** a constant.
|
||||||
|
**
|
||||||
|
** The pParse parameter may be NULL. But if it is NULL, there is no way
|
||||||
|
** to determine if function calls are constant or not, and hence all
|
||||||
|
** function calls will be considered to be non-constant. If pParse is
|
||||||
|
** not NULL, then a function call might be constant, depending on the
|
||||||
|
** function and on its parameters.
|
||||||
*/
|
*/
|
||||||
int sqlite3ExprIsConstant(Expr *p){
|
int sqlite3ExprIsConstant(Parse *pParse, Expr *p){
|
||||||
return exprIsConst(p, 1, 0);
|
return exprIsConst(pParse, p, 1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -2482,8 +2542,8 @@ int sqlite3ExprIsConstant(Expr *p){
|
|||||||
** can be added to the pParse->pConstExpr list and evaluated once when
|
** can be added to the pParse->pConstExpr list and evaluated once when
|
||||||
** the prepared statement starts up. See sqlite3ExprCodeRunJustOnce().
|
** the prepared statement starts up. See sqlite3ExprCodeRunJustOnce().
|
||||||
*/
|
*/
|
||||||
int sqlite3ExprIsConstantNotJoin(Expr *p){
|
static int sqlite3ExprIsConstantNotJoin(Parse *pParse, Expr *p){
|
||||||
return exprIsConst(p, 2, 0);
|
return exprIsConst(pParse, p, 2, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -2493,7 +2553,7 @@ int sqlite3ExprIsConstantNotJoin(Expr *p){
|
|||||||
** table other than iCur.
|
** table other than iCur.
|
||||||
*/
|
*/
|
||||||
int sqlite3ExprIsTableConstant(Expr *p, int iCur){
|
int sqlite3ExprIsTableConstant(Expr *p, int iCur){
|
||||||
return exprIsConst(p, 3, iCur);
|
return exprIsConst(0, p, 3, iCur);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -2650,7 +2710,7 @@ int sqlite3ExprIsConstantOrGroupBy(Parse *pParse, Expr *p, ExprList *pGroupBy){
|
|||||||
*/
|
*/
|
||||||
int sqlite3ExprIsConstantOrFunction(Expr *p, u8 isInit){
|
int sqlite3ExprIsConstantOrFunction(Expr *p, u8 isInit){
|
||||||
assert( isInit==0 || isInit==1 );
|
assert( isInit==0 || isInit==1 );
|
||||||
return exprIsConst(p, 4+isInit, 0);
|
return exprIsConst(0, p, 4+isInit, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SQLITE_ENABLE_CURSOR_HINTS
|
#ifdef SQLITE_ENABLE_CURSOR_HINTS
|
||||||
@@ -2895,13 +2955,13 @@ static void sqlite3SetHasNullFlag(Vdbe *v, int iCur, int regHasNull){
|
|||||||
** The argument is an IN operator with a list (not a subquery) on the
|
** The argument is an IN operator with a list (not a subquery) on the
|
||||||
** right-hand side. Return TRUE if that list is constant.
|
** right-hand side. Return TRUE if that list is constant.
|
||||||
*/
|
*/
|
||||||
static int sqlite3InRhsIsConstant(Expr *pIn){
|
static int sqlite3InRhsIsConstant(Parse *pParse, Expr *pIn){
|
||||||
Expr *pLHS;
|
Expr *pLHS;
|
||||||
int res;
|
int res;
|
||||||
assert( !ExprHasProperty(pIn, EP_xIsSelect) );
|
assert( !ExprHasProperty(pIn, EP_xIsSelect) );
|
||||||
pLHS = pIn->pLeft;
|
pLHS = pIn->pLeft;
|
||||||
pIn->pLeft = 0;
|
pIn->pLeft = 0;
|
||||||
res = sqlite3ExprIsConstant(pIn);
|
res = sqlite3ExprIsConstant(pParse, pIn);
|
||||||
pIn->pLeft = pLHS;
|
pIn->pLeft = pLHS;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@@ -3170,7 +3230,7 @@ int sqlite3FindInIndex(
|
|||||||
if( eType==0
|
if( eType==0
|
||||||
&& (inFlags & IN_INDEX_NOOP_OK)
|
&& (inFlags & IN_INDEX_NOOP_OK)
|
||||||
&& ExprUseXList(pX)
|
&& ExprUseXList(pX)
|
||||||
&& (!sqlite3InRhsIsConstant(pX) || pX->x.pList->nExpr<=2)
|
&& (!sqlite3InRhsIsConstant(pParse,pX) || pX->x.pList->nExpr<=2)
|
||||||
){
|
){
|
||||||
pParse->nTab--; /* Back out the allocation of the unused cursor */
|
pParse->nTab--; /* Back out the allocation of the unused cursor */
|
||||||
iTab = -1; /* Cursor is not allocated */
|
iTab = -1; /* Cursor is not allocated */
|
||||||
@@ -3453,7 +3513,7 @@ void sqlite3CodeRhsOfIN(
|
|||||||
** this code only executes once. Because for a non-constant
|
** this code only executes once. Because for a non-constant
|
||||||
** expression we need to rerun this code each time.
|
** expression we need to rerun this code each time.
|
||||||
*/
|
*/
|
||||||
if( addrOnce && !sqlite3ExprIsConstant(pE2) ){
|
if( addrOnce && !sqlite3ExprIsConstant(pParse, pE2) ){
|
||||||
sqlite3VdbeChangeToNoop(v, addrOnce-1);
|
sqlite3VdbeChangeToNoop(v, addrOnce-1);
|
||||||
sqlite3VdbeChangeToNoop(v, addrOnce);
|
sqlite3VdbeChangeToNoop(v, addrOnce);
|
||||||
ExprClearProperty(pExpr, EP_Subrtn);
|
ExprClearProperty(pExpr, EP_Subrtn);
|
||||||
@@ -4790,7 +4850,9 @@ expr_code_doover:
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if( ConstFactorOk(pParse) && sqlite3ExprIsConstantNotJoin(pExpr) ){
|
if( ConstFactorOk(pParse)
|
||||||
|
&& sqlite3ExprIsConstantNotJoin(pParse,pExpr)
|
||||||
|
){
|
||||||
/* SQL functions can be expensive. So try to avoid running them
|
/* SQL functions can be expensive. So try to avoid running them
|
||||||
** multiple times if we know they always give the same result */
|
** multiple times if we know they always give the same result */
|
||||||
return sqlite3ExprCodeRunJustOnce(pParse, pExpr, -1);
|
return sqlite3ExprCodeRunJustOnce(pParse, pExpr, -1);
|
||||||
@@ -4821,7 +4883,7 @@ expr_code_doover:
|
|||||||
}
|
}
|
||||||
|
|
||||||
for(i=0; i<nFarg; i++){
|
for(i=0; i<nFarg; i++){
|
||||||
if( i<32 && sqlite3ExprIsConstant(pFarg->a[i].pExpr) ){
|
if( i<32 && sqlite3ExprIsConstant(pParse, pFarg->a[i].pExpr) ){
|
||||||
testcase( i==31 );
|
testcase( i==31 );
|
||||||
constMask |= MASKBIT32(i);
|
constMask |= MASKBIT32(i);
|
||||||
}
|
}
|
||||||
@@ -5288,7 +5350,7 @@ int sqlite3ExprCodeTemp(Parse *pParse, Expr *pExpr, int *pReg){
|
|||||||
if( ConstFactorOk(pParse)
|
if( ConstFactorOk(pParse)
|
||||||
&& ALWAYS(pExpr!=0)
|
&& ALWAYS(pExpr!=0)
|
||||||
&& pExpr->op!=TK_REGISTER
|
&& pExpr->op!=TK_REGISTER
|
||||||
&& sqlite3ExprIsConstantNotJoin(pExpr)
|
&& sqlite3ExprIsConstantNotJoin(pParse, pExpr)
|
||||||
){
|
){
|
||||||
*pReg = 0;
|
*pReg = 0;
|
||||||
r2 = sqlite3ExprCodeRunJustOnce(pParse, pExpr, -1);
|
r2 = sqlite3ExprCodeRunJustOnce(pParse, pExpr, -1);
|
||||||
@@ -5352,7 +5414,7 @@ void sqlite3ExprCodeCopy(Parse *pParse, Expr *pExpr, int target){
|
|||||||
** might choose to code the expression at initialization time.
|
** might choose to code the expression at initialization time.
|
||||||
*/
|
*/
|
||||||
void sqlite3ExprCodeFactorable(Parse *pParse, Expr *pExpr, int target){
|
void sqlite3ExprCodeFactorable(Parse *pParse, Expr *pExpr, int target){
|
||||||
if( pParse->okConstFactor && sqlite3ExprIsConstantNotJoin(pExpr) ){
|
if( pParse->okConstFactor && sqlite3ExprIsConstantNotJoin(pParse,pExpr) ){
|
||||||
sqlite3ExprCodeRunJustOnce(pParse, pExpr, target);
|
sqlite3ExprCodeRunJustOnce(pParse, pExpr, target);
|
||||||
}else{
|
}else{
|
||||||
sqlite3ExprCodeCopy(pParse, pExpr, target);
|
sqlite3ExprCodeCopy(pParse, pExpr, target);
|
||||||
@@ -5411,7 +5473,7 @@ int sqlite3ExprCodeExprList(
|
|||||||
sqlite3VdbeAddOp2(v, copyOp, j+srcReg-1, target+i);
|
sqlite3VdbeAddOp2(v, copyOp, j+srcReg-1, target+i);
|
||||||
}
|
}
|
||||||
}else if( (flags & SQLITE_ECEL_FACTOR)!=0
|
}else if( (flags & SQLITE_ECEL_FACTOR)!=0
|
||||||
&& sqlite3ExprIsConstantNotJoin(pExpr)
|
&& sqlite3ExprIsConstantNotJoin(pParse,pExpr)
|
||||||
){
|
){
|
||||||
sqlite3ExprCodeRunJustOnce(pParse, pExpr, target+i);
|
sqlite3ExprCodeRunJustOnce(pParse, pExpr, target+i);
|
||||||
}else{
|
}else{
|
||||||
|
208
src/insert.c
208
src/insert.c
@@ -577,6 +577,193 @@ void sqlite3AutoincrementEnd(Parse *pParse){
|
|||||||
# define autoIncStep(A,B,C)
|
# define autoIncStep(A,B,C)
|
||||||
#endif /* SQLITE_OMIT_AUTOINCREMENT */
|
#endif /* SQLITE_OMIT_AUTOINCREMENT */
|
||||||
|
|
||||||
|
/*
|
||||||
|
** If argument pVal is a Select object returned by an sqlite3MultiValues()
|
||||||
|
** that was able to use the co-routine optimization, finish coding the
|
||||||
|
** co-routine.
|
||||||
|
*/
|
||||||
|
void sqlite3MultiValuesEnd(Parse *pParse, Select *pVal){
|
||||||
|
if( ALWAYS(pVal) && pVal->pSrc->nSrc>0 ){
|
||||||
|
SrcItem *pItem = &pVal->pSrc->a[0];
|
||||||
|
sqlite3VdbeEndCoroutine(pParse->pVdbe, pItem->regReturn);
|
||||||
|
sqlite3VdbeJumpHere(pParse->pVdbe, pItem->addrFillSub - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Return true if all expressions in the expression-list passed as the
|
||||||
|
** only argument are constant.
|
||||||
|
*/
|
||||||
|
static int exprListIsConstant(Parse *pParse, ExprList *pRow){
|
||||||
|
int ii;
|
||||||
|
for(ii=0; ii<pRow->nExpr; ii++){
|
||||||
|
if( 0==sqlite3ExprIsConstant(pParse, pRow->a[ii].pExpr) ) return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Return true if all expressions in the expression-list passed as the
|
||||||
|
** only argument are both constant and have no affinity.
|
||||||
|
*/
|
||||||
|
static int exprListIsNoAffinity(Parse *pParse, ExprList *pRow){
|
||||||
|
int ii;
|
||||||
|
if( exprListIsConstant(pParse,pRow)==0 ) return 0;
|
||||||
|
for(ii=0; ii<pRow->nExpr; ii++){
|
||||||
|
assert( pRow->a[ii].pExpr->affExpr==0 );
|
||||||
|
if( 0!=sqlite3ExprAffinity(pRow->a[ii].pExpr) ) return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** This function is called by the parser for the second and subsequent
|
||||||
|
** rows of a multi-row VALUES clause. Argument pLeft is the part of
|
||||||
|
** the VALUES clause already parsed, argument pRow is the vector of values
|
||||||
|
** for the new row. The Select object returned represents the complete
|
||||||
|
** VALUES clause, including the new row.
|
||||||
|
**
|
||||||
|
** There are two ways in which this may be achieved - by incremental
|
||||||
|
** coding of a co-routine (the "co-routine" method) or by returning a
|
||||||
|
** Select object equivalent to the following (the "UNION ALL" method):
|
||||||
|
**
|
||||||
|
** "pLeft UNION ALL SELECT pRow"
|
||||||
|
**
|
||||||
|
** If the VALUES clause contains a lot of rows, this compound Select
|
||||||
|
** object may consume a lot of memory.
|
||||||
|
**
|
||||||
|
** When the co-routine method is used, each row that will be returned
|
||||||
|
** by the VALUES clause is coded into part of a co-routine as it is
|
||||||
|
** passed to this function. The returned Select object is equivalent to:
|
||||||
|
**
|
||||||
|
** SELECT * FROM (
|
||||||
|
** Select object to read co-routine
|
||||||
|
** )
|
||||||
|
**
|
||||||
|
** The co-routine method is used in most cases. Exceptions are:
|
||||||
|
**
|
||||||
|
** a) If the current statement has a WITH clause. This is to avoid
|
||||||
|
** statements like:
|
||||||
|
**
|
||||||
|
** WITH cte AS ( VALUES('x'), ('y') ... )
|
||||||
|
** SELECT * FROM cte AS a, cte AS b;
|
||||||
|
**
|
||||||
|
** This will not work, as the co-routine uses a hard-coded register
|
||||||
|
** for its OP_Yield instructions, and so it is not possible for two
|
||||||
|
** cursors to iterate through it concurrently.
|
||||||
|
**
|
||||||
|
** b) The schema is currently being parsed (i.e. the VALUES clause is part
|
||||||
|
** of a schema item like a VIEW or TRIGGER). In this case there is no VM
|
||||||
|
** being generated when parsing is taking place, and so generating
|
||||||
|
** a co-routine is not possible.
|
||||||
|
**
|
||||||
|
** c) There are non-constant expressions in the VALUES clause (e.g.
|
||||||
|
** the VALUES clause is part of a correlated sub-query).
|
||||||
|
**
|
||||||
|
** d) One or more of the values in the first row of the VALUES clause
|
||||||
|
** has an affinity (i.e. is a CAST expression). This causes problems
|
||||||
|
** because the complex rules SQLite uses (see function
|
||||||
|
** sqlite3SubqueryColumnTypes() in select.c) to determine the effective
|
||||||
|
** affinity of such a column for all rows require access to all values in
|
||||||
|
** the column simultaneously.
|
||||||
|
*/
|
||||||
|
Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList *pRow){
|
||||||
|
|
||||||
|
if( pParse->bHasWith /* condition (a) above */
|
||||||
|
|| pParse->db->init.busy /* condition (b) above */
|
||||||
|
|| exprListIsConstant(pParse,pRow)==0 /* condition (c) above */
|
||||||
|
|| (pLeft->pSrc->nSrc==0 &&
|
||||||
|
exprListIsNoAffinity(pParse,pLeft->pEList)==0) /* condition (d) above */
|
||||||
|
|| IN_SPECIAL_PARSE
|
||||||
|
){
|
||||||
|
/* The co-routine method cannot be used. Fall back to UNION ALL. */
|
||||||
|
Select *pSelect = 0;
|
||||||
|
int f = SF_Values | SF_MultiValue;
|
||||||
|
if( pLeft->pSrc->nSrc ){
|
||||||
|
sqlite3MultiValuesEnd(pParse, pLeft);
|
||||||
|
f = SF_Values;
|
||||||
|
}else if( pLeft->pPrior ){
|
||||||
|
/* In this case set the SF_MultiValue flag only if it was set on pLeft */
|
||||||
|
f = (f & pLeft->selFlags);
|
||||||
|
}
|
||||||
|
pSelect = sqlite3SelectNew(pParse, pRow, 0, 0, 0, 0, 0, f, 0);
|
||||||
|
pLeft->selFlags &= ~SF_MultiValue;
|
||||||
|
if( pSelect ){
|
||||||
|
pSelect->op = TK_ALL;
|
||||||
|
pSelect->pPrior = pLeft;
|
||||||
|
pLeft = pSelect;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
SrcItem *p = 0; /* SrcItem that reads from co-routine */
|
||||||
|
|
||||||
|
if( pLeft->pSrc->nSrc==0 ){
|
||||||
|
/* Co-routine has not yet been started and the special Select object
|
||||||
|
** that accesses the co-routine has not yet been created. This block
|
||||||
|
** does both those things. */
|
||||||
|
Vdbe *v = sqlite3GetVdbe(pParse);
|
||||||
|
Select *pRet = sqlite3SelectNew(pParse, 0, 0, 0, 0, 0, 0, 0, 0);
|
||||||
|
|
||||||
|
/* Ensure the database schema has been read. This is to ensure we have
|
||||||
|
** the correct text encoding. */
|
||||||
|
if( (pParse->db->mDbFlags & DBFLAG_SchemaKnownOk)==0 ){
|
||||||
|
sqlite3ReadSchema(pParse);
|
||||||
|
}
|
||||||
|
|
||||||
|
if( pRet ){
|
||||||
|
SelectDest dest;
|
||||||
|
pRet->pSrc->nSrc = 1;
|
||||||
|
pRet->pPrior = pLeft->pPrior;
|
||||||
|
pRet->op = pLeft->op;
|
||||||
|
pLeft->pPrior = 0;
|
||||||
|
pLeft->op = TK_SELECT;
|
||||||
|
assert( pLeft->pNext==0 );
|
||||||
|
assert( pRet->pNext==0 );
|
||||||
|
p = &pRet->pSrc->a[0];
|
||||||
|
p->pSelect = pLeft;
|
||||||
|
p->fg.viaCoroutine = 1;
|
||||||
|
p->addrFillSub = sqlite3VdbeCurrentAddr(v) + 1;
|
||||||
|
p->regReturn = ++pParse->nMem;
|
||||||
|
p->iCursor = -1;
|
||||||
|
p->u1.nRow = 2;
|
||||||
|
sqlite3VdbeAddOp3(v,OP_InitCoroutine,p->regReturn,0,p->addrFillSub);
|
||||||
|
sqlite3SelectDestInit(&dest, SRT_Coroutine, p->regReturn);
|
||||||
|
|
||||||
|
/* Allocate registers for the output of the co-routine. Do so so
|
||||||
|
** that there are two unused registers immediately before those
|
||||||
|
** used by the co-routine. This allows the code in sqlite3Insert()
|
||||||
|
** to use these registers directly, instead of copying the output
|
||||||
|
** of the co-routine to a separate array for processing. */
|
||||||
|
dest.iSdst = pParse->nMem + 3;
|
||||||
|
dest.nSdst = pLeft->pEList->nExpr;
|
||||||
|
pParse->nMem += 2 + dest.nSdst;
|
||||||
|
|
||||||
|
pLeft->selFlags |= SF_MultiValue;
|
||||||
|
sqlite3Select(pParse, pLeft, &dest);
|
||||||
|
p->regResult = dest.iSdst;
|
||||||
|
assert( pParse->nErr || dest.iSdst>0 );
|
||||||
|
pLeft = pRet;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
p = &pLeft->pSrc->a[0];
|
||||||
|
assert( !p->fg.isTabFunc && !p->fg.isIndexedBy );
|
||||||
|
p->u1.nRow++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( pParse->nErr==0 ){
|
||||||
|
assert( p!=0 );
|
||||||
|
if( p->pSelect->pEList->nExpr!=pRow->nExpr ){
|
||||||
|
sqlite3SelectWrongNumTermsError(pParse, p->pSelect);
|
||||||
|
}else{
|
||||||
|
sqlite3ExprCodeExprList(pParse, pRow, p->regResult, 0, 0);
|
||||||
|
sqlite3VdbeAddOp1(pParse->pVdbe, OP_Yield, p->regReturn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sqlite3ExprListDelete(pParse->db, pRow);
|
||||||
|
}
|
||||||
|
|
||||||
|
return pLeft;
|
||||||
|
}
|
||||||
|
|
||||||
/* Forward declaration */
|
/* Forward declaration */
|
||||||
static int xferOptimization(
|
static int xferOptimization(
|
||||||
@@ -913,11 +1100,25 @@ void sqlite3Insert(
|
|||||||
if( pSelect ){
|
if( pSelect ){
|
||||||
/* Data is coming from a SELECT or from a multi-row VALUES clause.
|
/* Data is coming from a SELECT or from a multi-row VALUES clause.
|
||||||
** Generate a co-routine to run the SELECT. */
|
** Generate a co-routine to run the SELECT. */
|
||||||
int regYield; /* Register holding co-routine entry-point */
|
|
||||||
int addrTop; /* Top of the co-routine */
|
|
||||||
int rc; /* Result code */
|
int rc; /* Result code */
|
||||||
|
|
||||||
regYield = ++pParse->nMem;
|
if( pSelect->pSrc->nSrc==1
|
||||||
|
&& pSelect->pSrc->a[0].fg.viaCoroutine
|
||||||
|
&& pSelect->pPrior==0
|
||||||
|
){
|
||||||
|
SrcItem *pItem = &pSelect->pSrc->a[0];
|
||||||
|
dest.iSDParm = pItem->regReturn;
|
||||||
|
regFromSelect = pItem->regResult;
|
||||||
|
nColumn = pItem->pSelect->pEList->nExpr;
|
||||||
|
ExplainQueryPlan((pParse, 0, "SCAN %S", pItem));
|
||||||
|
if( bIdListInOrder && nColumn==pTab->nCol ){
|
||||||
|
regData = regFromSelect;
|
||||||
|
regRowid = regData - 1;
|
||||||
|
regIns = regRowid - (IsVirtual(pTab) ? 1 : 0);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
int addrTop; /* Top of the co-routine */
|
||||||
|
int regYield = ++pParse->nMem;
|
||||||
addrTop = sqlite3VdbeCurrentAddr(v) + 1;
|
addrTop = sqlite3VdbeCurrentAddr(v) + 1;
|
||||||
sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop);
|
sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop);
|
||||||
sqlite3SelectDestInit(&dest, SRT_Coroutine, regYield);
|
sqlite3SelectDestInit(&dest, SRT_Coroutine, regYield);
|
||||||
@@ -932,6 +1133,7 @@ void sqlite3Insert(
|
|||||||
sqlite3VdbeJumpHere(v, addrTop - 1); /* label B: */
|
sqlite3VdbeJumpHere(v, addrTop - 1); /* label B: */
|
||||||
assert( pSelect->pEList );
|
assert( pSelect->pEList );
|
||||||
nColumn = pSelect->pEList->nExpr;
|
nColumn = pSelect->pEList->nExpr;
|
||||||
|
}
|
||||||
|
|
||||||
/* Set useTempTable to TRUE if the result of the SELECT statement
|
/* Set useTempTable to TRUE if the result of the SELECT statement
|
||||||
** should be written into a temporary table (template 4). Set to
|
** should be written into a temporary table (template 4). Set to
|
||||||
|
33
src/parse.y
33
src/parse.y
@@ -565,6 +565,7 @@ cmd ::= select(X). {
|
|||||||
select(A) ::= WITH wqlist(W) selectnowith(X). {A = attachWithToSelect(pParse,X,W);}
|
select(A) ::= WITH wqlist(W) selectnowith(X). {A = attachWithToSelect(pParse,X,W);}
|
||||||
select(A) ::= WITH RECURSIVE wqlist(W) selectnowith(X).
|
select(A) ::= WITH RECURSIVE wqlist(W) selectnowith(X).
|
||||||
{A = attachWithToSelect(pParse,X,W);}
|
{A = attachWithToSelect(pParse,X,W);}
|
||||||
|
|
||||||
%endif /* SQLITE_OMIT_CTE */
|
%endif /* SQLITE_OMIT_CTE */
|
||||||
select(A) ::= selectnowith(A). {
|
select(A) ::= selectnowith(A). {
|
||||||
Select *p = A;
|
Select *p = A;
|
||||||
@@ -622,24 +623,27 @@ oneselect(A) ::= SELECT distinct(D) selcollist(W) from(X) where_opt(Y)
|
|||||||
%endif
|
%endif
|
||||||
|
|
||||||
|
|
||||||
oneselect(A) ::= values(A).
|
// Single row VALUES clause.
|
||||||
|
//
|
||||||
%type values {Select*}
|
%type values {Select*}
|
||||||
|
oneselect(A) ::= values(A).
|
||||||
%destructor values {sqlite3SelectDelete(pParse->db, $$);}
|
%destructor values {sqlite3SelectDelete(pParse->db, $$);}
|
||||||
values(A) ::= VALUES LP nexprlist(X) RP. {
|
values(A) ::= VALUES LP nexprlist(X) RP. {
|
||||||
A = sqlite3SelectNew(pParse,X,0,0,0,0,0,SF_Values,0);
|
A = sqlite3SelectNew(pParse,X,0,0,0,0,0,SF_Values,0);
|
||||||
}
|
}
|
||||||
values(A) ::= values(A) COMMA LP nexprlist(Y) RP. {
|
|
||||||
Select *pRight, *pLeft = A;
|
// Multiple row VALUES clause.
|
||||||
pRight = sqlite3SelectNew(pParse,Y,0,0,0,0,0,SF_Values|SF_MultiValue,0);
|
//
|
||||||
if( ALWAYS(pLeft) ) pLeft->selFlags &= ~SF_MultiValue;
|
%type mvalues {Select*}
|
||||||
if( pRight ){
|
oneselect(A) ::= mvalues(A). {
|
||||||
pRight->op = TK_ALL;
|
sqlite3MultiValuesEnd(pParse, A);
|
||||||
pRight->pPrior = pLeft;
|
|
||||||
A = pRight;
|
|
||||||
}else{
|
|
||||||
A = pLeft;
|
|
||||||
}
|
}
|
||||||
|
%destructor mvalues {sqlite3SelectDelete(pParse->db, $$);}
|
||||||
|
mvalues(A) ::= values(A) COMMA LP nexprlist(Y) RP. {
|
||||||
|
A = sqlite3MultiValues(pParse, A, Y);
|
||||||
|
}
|
||||||
|
mvalues(A) ::= mvalues(A) COMMA LP nexprlist(Y) RP. {
|
||||||
|
A = sqlite3MultiValues(pParse, A, Y);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The "distinct" nonterminal is true (1) if the DISTINCT keyword is
|
// The "distinct" nonterminal is true (1) if the DISTINCT keyword is
|
||||||
@@ -1321,7 +1325,7 @@ expr(A) ::= expr(A) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
|
|||||||
if( A ) sqlite3ExprIdToTrueFalse(A);
|
if( A ) sqlite3ExprIdToTrueFalse(A);
|
||||||
}else{
|
}else{
|
||||||
Expr *pRHS = Y->a[0].pExpr;
|
Expr *pRHS = Y->a[0].pExpr;
|
||||||
if( Y->nExpr==1 && sqlite3ExprIsConstant(pRHS) && A->op!=TK_VECTOR ){
|
if( Y->nExpr==1 && sqlite3ExprIsConstant(pParse,pRHS) && A->op!=TK_VECTOR ){
|
||||||
Y->a[0].pExpr = 0;
|
Y->a[0].pExpr = 0;
|
||||||
sqlite3ExprListDelete(pParse->db, Y);
|
sqlite3ExprListDelete(pParse->db, Y);
|
||||||
pRHS = sqlite3PExpr(pParse, TK_UPLUS, pRHS, 0);
|
pRHS = sqlite3PExpr(pParse, TK_UPLUS, pRHS, 0);
|
||||||
@@ -1761,9 +1765,10 @@ with ::= WITH RECURSIVE wqlist(W). { sqlite3WithPush(pParse, W, 1); }
|
|||||||
wqas(A) ::= AS. {A = M10d_Any;}
|
wqas(A) ::= AS. {A = M10d_Any;}
|
||||||
wqas(A) ::= AS MATERIALIZED. {A = M10d_Yes;}
|
wqas(A) ::= AS MATERIALIZED. {A = M10d_Yes;}
|
||||||
wqas(A) ::= AS NOT MATERIALIZED. {A = M10d_No;}
|
wqas(A) ::= AS NOT MATERIALIZED. {A = M10d_No;}
|
||||||
wqitem(A) ::= nm(X) eidlist_opt(Y) wqas(M) LP select(Z) RP. {
|
wqitem(A) ::= withnm(X) eidlist_opt(Y) wqas(M) LP select(Z) RP. {
|
||||||
A = sqlite3CteNew(pParse, &X, Y, Z, M); /*A-overwrites-X*/
|
A = sqlite3CteNew(pParse, &X, Y, Z, M); /*A-overwrites-X*/
|
||||||
}
|
}
|
||||||
|
withnm(A) ::= nm(A). {pParse->bHasWith = 1;}
|
||||||
wqlist(A) ::= wqitem(X). {
|
wqlist(A) ::= wqitem(X). {
|
||||||
A = sqlite3WithAdd(pParse, 0, X); /*A-overwrites-X*/
|
A = sqlite3WithAdd(pParse, 0, X); /*A-overwrites-X*/
|
||||||
}
|
}
|
||||||
|
@@ -860,6 +860,10 @@ void sqlite3_str_vappendf(
|
|||||||
assert( pSel!=0 );
|
assert( pSel!=0 );
|
||||||
if( pSel->selFlags & SF_NestedFrom ){
|
if( pSel->selFlags & SF_NestedFrom ){
|
||||||
sqlite3_str_appendf(pAccum, "(join-%u)", pSel->selId);
|
sqlite3_str_appendf(pAccum, "(join-%u)", pSel->selId);
|
||||||
|
}else if( pSel->selFlags & SF_MultiValue ){
|
||||||
|
assert( !pItem->fg.isTabFunc && !pItem->fg.isIndexedBy );
|
||||||
|
sqlite3_str_appendf(pAccum, "%u-ROW VALUES CLAUSE",
|
||||||
|
pItem->u1.nRow);
|
||||||
}else{
|
}else{
|
||||||
sqlite3_str_appendf(pAccum, "(subquery-%u)", pSel->selId);
|
sqlite3_str_appendf(pAccum, "(subquery-%u)", pSel->selId);
|
||||||
}
|
}
|
||||||
|
@@ -4776,7 +4776,7 @@ static void constInsert(
|
|||||||
){
|
){
|
||||||
int i;
|
int i;
|
||||||
assert( pColumn->op==TK_COLUMN );
|
assert( pColumn->op==TK_COLUMN );
|
||||||
assert( sqlite3ExprIsConstant(pValue) );
|
assert( sqlite3ExprIsConstant(pConst->pParse, pValue) );
|
||||||
|
|
||||||
if( ExprHasProperty(pColumn, EP_FixedCol) ) return;
|
if( ExprHasProperty(pColumn, EP_FixedCol) ) return;
|
||||||
if( sqlite3ExprAffinity(pValue)!=0 ) return;
|
if( sqlite3ExprAffinity(pValue)!=0 ) return;
|
||||||
@@ -4834,10 +4834,10 @@ static void findConstInWhere(WhereConst *pConst, Expr *pExpr){
|
|||||||
pLeft = pExpr->pLeft;
|
pLeft = pExpr->pLeft;
|
||||||
assert( pRight!=0 );
|
assert( pRight!=0 );
|
||||||
assert( pLeft!=0 );
|
assert( pLeft!=0 );
|
||||||
if( pRight->op==TK_COLUMN && sqlite3ExprIsConstant(pLeft) ){
|
if( pRight->op==TK_COLUMN && sqlite3ExprIsConstant(pConst->pParse, pLeft) ){
|
||||||
constInsert(pConst,pRight,pLeft,pExpr);
|
constInsert(pConst,pRight,pLeft,pExpr);
|
||||||
}
|
}
|
||||||
if( pLeft->op==TK_COLUMN && sqlite3ExprIsConstant(pRight) ){
|
if( pLeft->op==TK_COLUMN && sqlite3ExprIsConstant(pConst->pParse, pRight) ){
|
||||||
constInsert(pConst,pLeft,pRight,pExpr);
|
constInsert(pConst,pLeft,pRight,pExpr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7636,7 +7636,7 @@ int sqlite3Select(
|
|||||||
/* Generate code for all sub-queries in the FROM clause
|
/* Generate code for all sub-queries in the FROM clause
|
||||||
*/
|
*/
|
||||||
pSub = pItem->pSelect;
|
pSub = pItem->pSelect;
|
||||||
if( pSub==0 ) continue;
|
if( pSub==0 || pItem->addrFillSub!=0 ) continue;
|
||||||
|
|
||||||
/* The code for a subquery should only be generated once. */
|
/* The code for a subquery should only be generated once. */
|
||||||
assert( pItem->addrFillSub==0 );
|
assert( pItem->addrFillSub==0 );
|
||||||
|
@@ -3292,6 +3292,8 @@ struct IdList {
|
|||||||
**
|
**
|
||||||
** u1.zIndexedBy fg.isIndexedBy && !fg.isTabFunc
|
** u1.zIndexedBy fg.isIndexedBy && !fg.isTabFunc
|
||||||
** u1.pFuncArg fg.isTabFunc && !fg.isIndexedBy
|
** u1.pFuncArg fg.isTabFunc && !fg.isIndexedBy
|
||||||
|
** u1.nRow !fg.isTabFunc && !fg.isIndexedBy
|
||||||
|
**
|
||||||
** u2.pIBIndex fg.isIndexedBy && !fg.isCte
|
** u2.pIBIndex fg.isIndexedBy && !fg.isCte
|
||||||
** u2.pCteUse fg.isCte && !fg.isIndexedBy
|
** u2.pCteUse fg.isCte && !fg.isIndexedBy
|
||||||
*/
|
*/
|
||||||
@@ -3331,6 +3333,7 @@ struct SrcItem {
|
|||||||
union {
|
union {
|
||||||
char *zIndexedBy; /* Identifier from "INDEXED BY <zIndex>" clause */
|
char *zIndexedBy; /* Identifier from "INDEXED BY <zIndex>" clause */
|
||||||
ExprList *pFuncArg; /* Arguments to table-valued-function */
|
ExprList *pFuncArg; /* Arguments to table-valued-function */
|
||||||
|
u32 nRow; /* Number of rows in a VALUES clause */
|
||||||
} u1;
|
} u1;
|
||||||
union {
|
union {
|
||||||
Index *pIBIndex; /* Index structure corresponding to u1.zIndexedBy */
|
Index *pIBIndex; /* Index structure corresponding to u1.zIndexedBy */
|
||||||
@@ -3832,6 +3835,7 @@ struct Parse {
|
|||||||
u8 disableLookaside; /* Number of times lookaside has been disabled */
|
u8 disableLookaside; /* Number of times lookaside has been disabled */
|
||||||
u8 prepFlags; /* SQLITE_PREPARE_* flags */
|
u8 prepFlags; /* SQLITE_PREPARE_* flags */
|
||||||
u8 withinRJSubrtn; /* Nesting level for RIGHT JOIN body subroutines */
|
u8 withinRJSubrtn; /* Nesting level for RIGHT JOIN body subroutines */
|
||||||
|
u8 bHasWith; /* True if statement contains WITH */
|
||||||
#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST)
|
#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST)
|
||||||
u8 earlyCleanup; /* OOM inside sqlite3ParserAddCleanup() */
|
u8 earlyCleanup; /* OOM inside sqlite3ParserAddCleanup() */
|
||||||
#endif
|
#endif
|
||||||
@@ -4510,6 +4514,9 @@ struct Window {
|
|||||||
** due to the SQLITE_SUBTYPE flag */
|
** due to the SQLITE_SUBTYPE flag */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList *pRow);
|
||||||
|
void sqlite3MultiValuesEnd(Parse *pParse, Select *pVal);
|
||||||
|
|
||||||
#ifndef SQLITE_OMIT_WINDOWFUNC
|
#ifndef SQLITE_OMIT_WINDOWFUNC
|
||||||
void sqlite3WindowDelete(sqlite3*, Window*);
|
void sqlite3WindowDelete(sqlite3*, Window*);
|
||||||
void sqlite3WindowUnlinkFromSelect(Window*);
|
void sqlite3WindowUnlinkFromSelect(Window*);
|
||||||
@@ -5078,8 +5085,7 @@ void sqlite3LeaveMutexAndCloseZombie(sqlite3*);
|
|||||||
u32 sqlite3IsTrueOrFalse(const char*);
|
u32 sqlite3IsTrueOrFalse(const char*);
|
||||||
int sqlite3ExprIdToTrueFalse(Expr*);
|
int sqlite3ExprIdToTrueFalse(Expr*);
|
||||||
int sqlite3ExprTruthValue(const Expr*);
|
int sqlite3ExprTruthValue(const Expr*);
|
||||||
int sqlite3ExprIsConstant(Expr*);
|
int sqlite3ExprIsConstant(Parse*,Expr*);
|
||||||
int sqlite3ExprIsConstantNotJoin(Expr*);
|
|
||||||
int sqlite3ExprIsConstantOrFunction(Expr*, u8);
|
int sqlite3ExprIsConstantOrFunction(Expr*, u8);
|
||||||
int sqlite3ExprIsConstantOrGroupBy(Parse*, Expr*, ExprList*);
|
int sqlite3ExprIsConstantOrGroupBy(Parse*, Expr*, ExprList*);
|
||||||
int sqlite3ExprIsTableConstant(Expr*,int);
|
int sqlite3ExprIsTableConstant(Expr*,int);
|
||||||
|
15
src/where.c
15
src/where.c
@@ -1329,7 +1329,7 @@ static sqlite3_index_info *allocateIndexInfo(
|
|||||||
Expr *pE2;
|
Expr *pE2;
|
||||||
|
|
||||||
/* Skip over constant terms in the ORDER BY clause */
|
/* Skip over constant terms in the ORDER BY clause */
|
||||||
if( sqlite3ExprIsConstant(pExpr) ){
|
if( sqlite3ExprIsConstant(0, pExpr) ){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1441,7 +1441,7 @@ static sqlite3_index_info *allocateIndexInfo(
|
|||||||
pIdxInfo->nConstraint = j;
|
pIdxInfo->nConstraint = j;
|
||||||
for(i=j=0; i<nOrderBy; i++){
|
for(i=j=0; i<nOrderBy; i++){
|
||||||
Expr *pExpr = pOrderBy->a[i].pExpr;
|
Expr *pExpr = pOrderBy->a[i].pExpr;
|
||||||
if( sqlite3ExprIsConstant(pExpr) ) continue;
|
if( sqlite3ExprIsConstant(0, pExpr) ) continue;
|
||||||
assert( pExpr->op==TK_COLUMN
|
assert( pExpr->op==TK_COLUMN
|
||||||
|| (pExpr->op==TK_COLLATE && pExpr->pLeft->op==TK_COLUMN
|
|| (pExpr->op==TK_COLLATE && pExpr->pLeft->op==TK_COLUMN
|
||||||
&& pExpr->iColumn==pExpr->pLeft->iColumn) );
|
&& pExpr->iColumn==pExpr->pLeft->iColumn) );
|
||||||
@@ -3623,7 +3623,7 @@ static void wherePartIdxExpr(
|
|||||||
u8 aff;
|
u8 aff;
|
||||||
|
|
||||||
if( pLeft->op!=TK_COLUMN ) return;
|
if( pLeft->op!=TK_COLUMN ) return;
|
||||||
if( !sqlite3ExprIsConstant(pRight) ) return;
|
if( !sqlite3ExprIsConstant(0, pRight) ) return;
|
||||||
if( !sqlite3IsBinary(sqlite3ExprCompareCollSeq(pParse, pPart)) ) return;
|
if( !sqlite3IsBinary(sqlite3ExprCompareCollSeq(pParse, pPart)) ) return;
|
||||||
if( pLeft->iColumn<0 ) return;
|
if( pLeft->iColumn<0 ) return;
|
||||||
aff = pIdx->pTable->aCol[pLeft->iColumn].affinity;
|
aff = pIdx->pTable->aCol[pLeft->iColumn].affinity;
|
||||||
@@ -4997,7 +4997,7 @@ static i8 wherePathSatisfiesOrderBy(
|
|||||||
if( MASKBIT(i) & obSat ) continue;
|
if( MASKBIT(i) & obSat ) continue;
|
||||||
p = pOrderBy->a[i].pExpr;
|
p = pOrderBy->a[i].pExpr;
|
||||||
mTerm = sqlite3WhereExprUsage(&pWInfo->sMaskSet,p);
|
mTerm = sqlite3WhereExprUsage(&pWInfo->sMaskSet,p);
|
||||||
if( mTerm==0 && !sqlite3ExprIsConstant(p) ) continue;
|
if( mTerm==0 && !sqlite3ExprIsConstant(0,p) ) continue;
|
||||||
if( (mTerm&~orderDistinctMask)==0 ){
|
if( (mTerm&~orderDistinctMask)==0 ){
|
||||||
obSat |= MASKBIT(i);
|
obSat |= MASKBIT(i);
|
||||||
}
|
}
|
||||||
@@ -5866,7 +5866,7 @@ static SQLITE_NOINLINE void whereAddIndexedExpr(
|
|||||||
}else{
|
}else{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if( sqlite3ExprIsConstant(pExpr) ) continue;
|
if( sqlite3ExprIsConstant(0,pExpr) ) continue;
|
||||||
if( pExpr->op==TK_FUNCTION ){
|
if( pExpr->op==TK_FUNCTION ){
|
||||||
/* Functions that might set a subtype should not be replaced by the
|
/* Functions that might set a subtype should not be replaced by the
|
||||||
** value taken from an expression index since the index omits the
|
** value taken from an expression index since the index omits the
|
||||||
@@ -6144,7 +6144,11 @@ WhereInfo *sqlite3WhereBegin(
|
|||||||
){
|
){
|
||||||
pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
|
pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
|
||||||
}
|
}
|
||||||
|
if( ALWAYS(pWInfo->pSelect)
|
||||||
|
&& (pWInfo->pSelect->selFlags & SF_MultiValue)==0
|
||||||
|
){
|
||||||
ExplainQueryPlan((pParse, 0, "SCAN CONSTANT ROW"));
|
ExplainQueryPlan((pParse, 0, "SCAN CONSTANT ROW"));
|
||||||
|
}
|
||||||
}else{
|
}else{
|
||||||
/* Assign a bit from the bitmask to every term in the FROM clause.
|
/* Assign a bit from the bitmask to every term in the FROM clause.
|
||||||
**
|
**
|
||||||
@@ -6896,6 +6900,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
|
|||||||
*/
|
*/
|
||||||
if( pTabItem->fg.viaCoroutine ){
|
if( pTabItem->fg.viaCoroutine ){
|
||||||
testcase( pParse->db->mallocFailed );
|
testcase( pParse->db->mallocFailed );
|
||||||
|
assert( pTabItem->regResult>=0 );
|
||||||
translateColumnToCopy(pParse, pLevel->addrBody, pLevel->iTabCur,
|
translateColumnToCopy(pParse, pLevel->addrBody, pLevel->iTabCur,
|
||||||
pTabItem->regResult, 0);
|
pTabItem->regResult, 0);
|
||||||
continue;
|
continue;
|
||||||
|
@@ -989,7 +989,7 @@ static SQLITE_NOINLINE int exprMightBeIndexed2(
|
|||||||
if( pIdx->aiColumn[i]!=XN_EXPR ) continue;
|
if( pIdx->aiColumn[i]!=XN_EXPR ) continue;
|
||||||
assert( pIdx->bHasExpr );
|
assert( pIdx->bHasExpr );
|
||||||
if( sqlite3ExprCompareSkip(pExpr,pIdx->aColExpr->a[i].pExpr,iCur)==0
|
if( sqlite3ExprCompareSkip(pExpr,pIdx->aColExpr->a[i].pExpr,iCur)==0
|
||||||
&& !sqlite3ExprIsConstant(pIdx->aColExpr->a[i].pExpr)
|
&& !sqlite3ExprIsConstant(0,pIdx->aColExpr->a[i].pExpr)
|
||||||
){
|
){
|
||||||
aiCurCol[0] = iCur;
|
aiCurCol[0] = iCur;
|
||||||
aiCurCol[1] = XN_EXPR;
|
aiCurCol[1] = XN_EXPR;
|
||||||
|
@@ -1164,7 +1164,7 @@ void sqlite3WindowListDelete(sqlite3 *db, Window *p){
|
|||||||
** variable values in the expression tree.
|
** variable values in the expression tree.
|
||||||
*/
|
*/
|
||||||
static Expr *sqlite3WindowOffsetExpr(Parse *pParse, Expr *pExpr){
|
static Expr *sqlite3WindowOffsetExpr(Parse *pParse, Expr *pExpr){
|
||||||
if( 0==sqlite3ExprIsConstant(pExpr) ){
|
if( 0==sqlite3ExprIsConstant(0,pExpr) ){
|
||||||
if( IN_RENAME_OBJECT ) sqlite3RenameExprUnmap(pParse, pExpr);
|
if( IN_RENAME_OBJECT ) sqlite3RenameExprUnmap(pParse, pExpr);
|
||||||
sqlite3ExprDelete(pParse->db, pExpr);
|
sqlite3ExprDelete(pParse->db, pExpr);
|
||||||
pExpr = sqlite3ExprAlloc(pParse->db, TK_NULL, 0, 0);
|
pExpr = sqlite3ExprAlloc(pParse->db, TK_NULL, 0, 0);
|
||||||
|
@@ -736,4 +736,31 @@ do_execsql_test 29.7 {
|
|||||||
END}
|
END}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------
|
||||||
|
reset_db
|
||||||
|
do_execsql_test 30.0 {
|
||||||
|
CREATE TABLE t1(a, b);
|
||||||
|
CREATE VIEW v1 AS
|
||||||
|
SELECT ( VALUES(a), (b) ) FROM (
|
||||||
|
SELECT a, b FROM t1
|
||||||
|
)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
do_execsql_test 30.1 {
|
||||||
|
SELECT * FROM v1
|
||||||
|
}
|
||||||
|
|
||||||
|
do_execsql_test 30.1 {
|
||||||
|
ALTER TABLE t1 RENAME TO t2;
|
||||||
|
}
|
||||||
|
do_execsql_test 30.2 {
|
||||||
|
SELECT sql FROM sqlite_schema WHERE type='view'
|
||||||
|
} {
|
||||||
|
{CREATE VIEW v1 AS
|
||||||
|
SELECT ( VALUES(a), (b) ) FROM (
|
||||||
|
SELECT a, b FROM "t2"
|
||||||
|
)}
|
||||||
|
}
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
# 2013 March 10
|
# 2023-03-10
|
||||||
#
|
#
|
||||||
# The author disclaims copyright to this source code. In place of
|
# The author disclaims copyright to this source code. In place of
|
||||||
# a legal notice, here is a blessing:
|
# a legal notice, here is a blessing:
|
||||||
@@ -9,7 +9,10 @@
|
|||||||
#
|
#
|
||||||
#***********************************************************************
|
#***********************************************************************
|
||||||
# This file implements regression tests for SQLite library. The focus of
|
# This file implements regression tests for SQLite library. The focus of
|
||||||
# this file is testing the tointeger() and toreal() functions.
|
# this file is testing the tointeger() and toreal() functions that are
|
||||||
|
# part of the "totype.c" extension. This file does not test the core
|
||||||
|
# SQLite library. Failures of tests in this file are related to the
|
||||||
|
# ext/misc/totype.c extension.
|
||||||
#
|
#
|
||||||
# Several of the toreal() tests are disabled on platforms where floating
|
# Several of the toreal() tests are disabled on platforms where floating
|
||||||
# point precision is not high enough to represent their constant integer
|
# point precision is not high enough to represent their constant integer
|
||||||
@@ -23,6 +26,20 @@ load_static_extension db totype
|
|||||||
|
|
||||||
set highPrecision(1) [expr \
|
set highPrecision(1) [expr \
|
||||||
{[db eval {SELECT tointeger(9223372036854775807 + 1);}] eq {{}}}]
|
{[db eval {SELECT tointeger(9223372036854775807 + 1);}] eq {{}}}]
|
||||||
|
set highPrecision(2) [expr \
|
||||||
|
{[db eval {SELECT toreal(-9223372036854775808 + 1);}] eq {{}}}]
|
||||||
|
|
||||||
|
# highPrecision(3) is only known to be false on i586 with gcc-13 and -O2.
|
||||||
|
# It is true on the exact same platform with -O0. Both results seem
|
||||||
|
# reasonable, so we'll just very the expectation accordingly.
|
||||||
|
#
|
||||||
|
set highPrecision(3) [expr \
|
||||||
|
{[db eval {SELECT toreal(9007199254740992 + 1);}] eq {{}}}]
|
||||||
|
|
||||||
|
if {!$highPrecision(1) || !$highPrecision(2) || !$highPrecision(3)} {
|
||||||
|
puts "NOTICE: use_long_double: [use_long_double] \
|
||||||
|
highPrecision: $highPrecision(1) $highPrecision(2) $highPrecision(3)"
|
||||||
|
}
|
||||||
|
|
||||||
do_execsql_test func4-1.1 {
|
do_execsql_test func4-1.1 {
|
||||||
SELECT tointeger(NULL);
|
SELECT tointeger(NULL);
|
||||||
@@ -195,8 +212,6 @@ do_execsql_test func4-1.55 {
|
|||||||
} {{}}
|
} {{}}
|
||||||
|
|
||||||
ifcapable floatingpoint {
|
ifcapable floatingpoint {
|
||||||
set highPrecision(2) [expr \
|
|
||||||
{[db eval {SELECT toreal(-9223372036854775808 + 1);}] eq {{}}}]
|
|
||||||
|
|
||||||
do_execsql_test func4-2.1 {
|
do_execsql_test func4-2.1 {
|
||||||
SELECT toreal(NULL);
|
SELECT toreal(NULL);
|
||||||
@@ -341,10 +356,14 @@ ifcapable floatingpoint {
|
|||||||
do_execsql_test func4-2.45 {
|
do_execsql_test func4-2.45 {
|
||||||
SELECT toreal(9007199254740992);
|
SELECT toreal(9007199254740992);
|
||||||
} {9007199254740992.0}
|
} {9007199254740992.0}
|
||||||
if {$highPrecision(2)} {
|
if {$highPrecision(3)} {
|
||||||
do_execsql_test func4-2.46 {
|
do_execsql_test func4-2.46 {
|
||||||
SELECT toreal(9007199254740992 + 1);
|
SELECT toreal(9007199254740992 + 1);
|
||||||
} {{}}
|
} {{}}
|
||||||
|
} else {
|
||||||
|
do_execsql_test func4-2.46 {
|
||||||
|
SELECT toreal(9007199254740992 + 1);
|
||||||
|
} {9007199254740992.0}
|
||||||
}
|
}
|
||||||
do_execsql_test func4-2.47 {
|
do_execsql_test func4-2.47 {
|
||||||
SELECT toreal(9007199254740992 + 2);
|
SELECT toreal(9007199254740992 + 2);
|
||||||
@@ -626,10 +645,14 @@ ifcapable floatingpoint {
|
|||||||
do_execsql_test func4-5.22 {
|
do_execsql_test func4-5.22 {
|
||||||
SELECT tointeger(toreal(9007199254740992));
|
SELECT tointeger(toreal(9007199254740992));
|
||||||
} {9007199254740992}
|
} {9007199254740992}
|
||||||
if {$highPrecision(2)} {
|
if {$highPrecision(3)} {
|
||||||
do_execsql_test func4-5.23 {
|
do_execsql_test func4-5.23 {
|
||||||
SELECT tointeger(toreal(9007199254740992 + 1));
|
SELECT tointeger(toreal(9007199254740992 + 1));
|
||||||
} {{}}
|
} {{}}
|
||||||
|
} else {
|
||||||
|
do_execsql_test func4-5.23 {
|
||||||
|
SELECT tointeger(toreal(9007199254740992 + 1));
|
||||||
|
} {9007199254740992}
|
||||||
}
|
}
|
||||||
do_execsql_test func4-5.24 {
|
do_execsql_test func4-5.24 {
|
||||||
SELECT tointeger(toreal(9007199254740992 + 2));
|
SELECT tointeger(toreal(9007199254740992 + 2));
|
||||||
|
@@ -458,14 +458,14 @@ do_execsql_test 11.0 {
|
|||||||
do_execsql_test 11.1 {
|
do_execsql_test 11.1 {
|
||||||
SELECT * FROM t1
|
SELECT * FROM t1
|
||||||
WHERE b IN (345, (SELECT 1 FROM t1
|
WHERE b IN (345, (SELECT 1 FROM t1
|
||||||
WHERE b IN (345 NOT GLOB 510)
|
WHERE b IN (coalesce(1,random()))
|
||||||
AND c GLOB 'abc*xyz'))
|
AND c GLOB 'abc*xyz'))
|
||||||
AND c BETWEEN 'abc' AND 'xyz';
|
AND c BETWEEN 'abc' AND 'xyz';
|
||||||
} {xyz 1 abcdefxyz 99}
|
} {xyz 1 abcdefxyz 99}
|
||||||
do_execsql_test 11.2 {
|
do_execsql_test 11.2 {
|
||||||
EXPLAIN SELECT * FROM t1
|
EXPLAIN SELECT * FROM t1
|
||||||
WHERE b IN (345, (SELECT 1 FROM t1
|
WHERE b IN (345, (SELECT 1 FROM t1
|
||||||
WHERE b IN (345 NOT GLOB 510)
|
WHERE b IN (coalesce(1,random()))
|
||||||
AND c GLOB 'abc*xyz'))
|
AND c GLOB 'abc*xyz'))
|
||||||
AND c BETWEEN 'abc' AND 'xyz';
|
AND c BETWEEN 'abc' AND 'xyz';
|
||||||
} {/ SeekScan /}
|
} {/ SeekScan /}
|
||||||
|
@@ -922,7 +922,7 @@ do_catchsql_test sqllimits1-18.1 {
|
|||||||
do_catchsql_test sqllimits1-18.2 {
|
do_catchsql_test sqllimits1-18.2 {
|
||||||
INSERT INTO b1 VALUES(1), (2), (3), (4), (5), (6), (7), (8), (9), (10)
|
INSERT INTO b1 VALUES(1), (2), (3), (4), (5), (6), (7), (8), (9), (10)
|
||||||
UNION VALUES(11);
|
UNION VALUES(11);
|
||||||
} {1 {too many terms in compound SELECT}}
|
} {0 {}}
|
||||||
|
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
|
@@ -64,6 +64,8 @@ Usage:
|
|||||||
--dryrun
|
--dryrun
|
||||||
--explain
|
--explain
|
||||||
--jobs NUMBER-OF-JOBS
|
--jobs NUMBER-OF-JOBS
|
||||||
|
--stop-on-coredump
|
||||||
|
--stop-on-error
|
||||||
--zipvfs ZIPVFS-SOURCE-DIR
|
--zipvfs ZIPVFS-SOURCE-DIR
|
||||||
|
|
||||||
Special values for PERMUTATION that work with plain tclsh:
|
Special values for PERMUTATION that work with plain tclsh:
|
||||||
@@ -172,6 +174,8 @@ set TRG(zipvfs) "" ;# -zipvfs option, if any
|
|||||||
set TRG(buildonly) 0 ;# True if --buildonly option
|
set TRG(buildonly) 0 ;# True if --buildonly option
|
||||||
set TRG(dryrun) 0 ;# True if --dryrun option
|
set TRG(dryrun) 0 ;# True if --dryrun option
|
||||||
set TRG(explain) 0 ;# True for the --explain option
|
set TRG(explain) 0 ;# True for the --explain option
|
||||||
|
set TRG(stopOnError) 0 ;# Stop running at first failure
|
||||||
|
set TRG(stopOnCore) 0 ;# Stop on a core-dump
|
||||||
|
|
||||||
switch -nocase -glob -- $tcl_platform(os) {
|
switch -nocase -glob -- $tcl_platform(os) {
|
||||||
*darwin* {
|
*darwin* {
|
||||||
@@ -468,6 +472,10 @@ for {set ii 0} {$ii < [llength $argv]} {incr ii} {
|
|||||||
set TRG(dryrun) 1
|
set TRG(dryrun) 1
|
||||||
} elseif {($n>2 && [string match "$a*" --explain]) || $a=="-e"} {
|
} elseif {($n>2 && [string match "$a*" --explain]) || $a=="-e"} {
|
||||||
set TRG(explain) 1
|
set TRG(explain) 1
|
||||||
|
} elseif {[string match "$a*" --stop-on-error]} {
|
||||||
|
set TRG(stopOnError) 1
|
||||||
|
} elseif {[string match "$a*" --stop-on-coredump]} {
|
||||||
|
set TRG(stopOnCore) 1
|
||||||
} else {
|
} else {
|
||||||
usage
|
usage
|
||||||
}
|
}
|
||||||
@@ -993,6 +1001,14 @@ proc script_input_ready {fd iJob jobid} {
|
|||||||
}
|
}
|
||||||
puts "FAILED: $job(displayname) ($iJob)"
|
puts "FAILED: $job(displayname) ($iJob)"
|
||||||
set state "failed"
|
set state "failed"
|
||||||
|
if {$TRG(stopOnError)} {
|
||||||
|
puts "OUTPUT: $O($iJob)"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
if {$TRG(stopOnCore) && [string first {core dumped} $O($iJob)]>0} {
|
||||||
|
puts "OUTPUT: $O($iJob)"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
set tm [clock_milliseconds]
|
set tm [clock_milliseconds]
|
||||||
|
583
test/values.test
Normal file
583
test/values.test
Normal file
@@ -0,0 +1,583 @@
|
|||||||
|
# 2024 March 3
|
||||||
|
#
|
||||||
|
# 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 values
|
||||||
|
|
||||||
|
|
||||||
|
do_execsql_test 1.0 {
|
||||||
|
CREATE TABLE x1(a, b, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
explain_i {
|
||||||
|
INSERT INTO x1(a, b, c) VALUES(1, 1, 1), (2, 2, 2), (3, 3, 3), (4, 4, 4);
|
||||||
|
}
|
||||||
|
do_execsql_test 1.1.1 {
|
||||||
|
INSERT INTO x1 VALUES(1, 1, 1), (2, 2, 2), (3, 3, 3), (4, 4, 4);
|
||||||
|
}
|
||||||
|
do_execsql_test 1.1.2 {
|
||||||
|
SELECT * FROM x1;
|
||||||
|
} {
|
||||||
|
1 1 1
|
||||||
|
2 2 2
|
||||||
|
3 3 3
|
||||||
|
4 4 4
|
||||||
|
}
|
||||||
|
|
||||||
|
do_execsql_test 1.2.0 {
|
||||||
|
DELETE FROM x1
|
||||||
|
}
|
||||||
|
do_execsql_test 1.2.1 {
|
||||||
|
INSERT INTO x1 VALUES(1, 1, 1), (2, 2, 2), (3, 3, 3) UNION ALL SELECT 4, 4, 4;
|
||||||
|
SELECT * FROM x1;
|
||||||
|
} {1 1 1 2 2 2 3 3 3 4 4 4}
|
||||||
|
|
||||||
|
sqlite3_limit db SQLITE_LIMIT_COMPOUND_SELECT 4
|
||||||
|
|
||||||
|
do_execsql_test 1.2.2 {
|
||||||
|
DELETE FROM x1;
|
||||||
|
INSERT INTO x1
|
||||||
|
VALUES(1, 1, 1), (2, 2, 2), (3, 3, 3), (4, 4, 4), (5, 5, 5)
|
||||||
|
UNION ALL SELECT 6, 6, 6;
|
||||||
|
SELECT * FROM x1;
|
||||||
|
} {1 1 1 2 2 2 3 3 3 4 4 4 5 5 5 6 6 6}
|
||||||
|
|
||||||
|
do_execsql_test 1.2.3 {
|
||||||
|
DELETE FROM x1;
|
||||||
|
INSERT INTO x1
|
||||||
|
VALUES(1, 1, 1), (2, 2, 2), (3, 3, 3), (4, 4, 4)
|
||||||
|
UNION ALL SELECT 6, 6, 6;
|
||||||
|
SELECT * FROM x1;
|
||||||
|
} {1 1 1 2 2 2 3 3 3 4 4 4 6 6 6}
|
||||||
|
|
||||||
|
do_execsql_test 1.2.4 {
|
||||||
|
DELETE FROM x1;
|
||||||
|
INSERT INTO x1 VALUES(1, 1, 1), (2, 2, 2), (3, 3, 3) UNION ALL SELECT 6, 6, 6;
|
||||||
|
SELECT * FROM x1;
|
||||||
|
} {
|
||||||
|
1 1 1
|
||||||
|
2 2 2
|
||||||
|
3 3 3
|
||||||
|
6 6 6
|
||||||
|
}
|
||||||
|
|
||||||
|
set a 4
|
||||||
|
set b 5
|
||||||
|
set c 6
|
||||||
|
do_execsql_test 1.2.5 {
|
||||||
|
DELETE FROM x1;
|
||||||
|
INSERT INTO x1
|
||||||
|
VALUES(1, 1, 1), (2, 2, 2), (3, 3, 3),
|
||||||
|
(4, 4, $a), (5, 5, $b), (6, 6, $c)
|
||||||
|
}
|
||||||
|
|
||||||
|
do_execsql_test 1.2.6 {
|
||||||
|
SELECT * FROM x1;
|
||||||
|
} {
|
||||||
|
1 1 1
|
||||||
|
2 2 2
|
||||||
|
3 3 3
|
||||||
|
4 4 4
|
||||||
|
5 5 5
|
||||||
|
6 6 6
|
||||||
|
}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------
|
||||||
|
# SQLITE_LIMIT_COMPOUND_SELECT set to 0.
|
||||||
|
#
|
||||||
|
reset_db
|
||||||
|
|
||||||
|
do_execsql_test 2.0 {
|
||||||
|
CREATE TABLE x1(a, b, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
sqlite3_limit db SQLITE_LIMIT_COMPOUND_SELECT 3
|
||||||
|
|
||||||
|
do_catchsql_test 2.1.1 {
|
||||||
|
INSERT INTO x1 VALUES
|
||||||
|
(1, 1, 1),
|
||||||
|
(2, 2, 2),
|
||||||
|
(3, 3, 3),
|
||||||
|
(4, 4, 4),
|
||||||
|
(5, 5, 5),
|
||||||
|
(6, 6, 6),
|
||||||
|
(7, 7, 7),
|
||||||
|
(8, 8, 8),
|
||||||
|
(9, 9, 9),
|
||||||
|
(10, 10, 10, 10)
|
||||||
|
} {1 {all VALUES must have the same number of terms}}
|
||||||
|
|
||||||
|
do_catchsql_test 2.1.2 {
|
||||||
|
INSERT INTO x1 VALUES
|
||||||
|
(1, 1, 1),
|
||||||
|
(2, 2, 2, 2),
|
||||||
|
(3, 3, 3),
|
||||||
|
(4, 4, 4),
|
||||||
|
(5, 5, 5),
|
||||||
|
(6, 6, 6),
|
||||||
|
(7, 7, 7),
|
||||||
|
(8, 8, 8),
|
||||||
|
(9, 9, 9),
|
||||||
|
(10, 10, 10)
|
||||||
|
} {1 {all VALUES must have the same number of terms}}
|
||||||
|
|
||||||
|
sqlite3_limit db SQLITE_LIMIT_COMPOUND_SELECT 0
|
||||||
|
|
||||||
|
do_execsql_test 2.2 {
|
||||||
|
INSERT INTO x1 VALUES
|
||||||
|
(1, 1, 1),
|
||||||
|
(2, 2, 2),
|
||||||
|
(3, 3, 3),
|
||||||
|
(4, 4, 4),
|
||||||
|
(5, 5, 5),
|
||||||
|
(6, 6, 6),
|
||||||
|
(7, 7, 7),
|
||||||
|
(8, 8, 8),
|
||||||
|
(9, 9, 9),
|
||||||
|
(10, 10, 10)
|
||||||
|
} {}
|
||||||
|
do_execsql_test 2.3 {
|
||||||
|
INSERT INTO x1 VALUES
|
||||||
|
(1, 1, 1),
|
||||||
|
(2, 2, 2),
|
||||||
|
(3, 3, 3),
|
||||||
|
(4, 4, 4),
|
||||||
|
(5, 5, 5),
|
||||||
|
(6, 6, 6),
|
||||||
|
(7, 7, 7),
|
||||||
|
(8, 8, 8),
|
||||||
|
(9, 9, 9),
|
||||||
|
(10, 10, 10)
|
||||||
|
UNION ALL
|
||||||
|
SELECT 5, 12, 12
|
||||||
|
ORDER BY 1
|
||||||
|
} {}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------
|
||||||
|
reset_db
|
||||||
|
|
||||||
|
do_execsql_test 3.0 {
|
||||||
|
CREATE TABLE y1(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
do_execsql_test 3.1.1 {
|
||||||
|
DELETE FROM y1;
|
||||||
|
INSERT INTO y1 VALUES(1, 2), (3, 4), (row_number() OVER (), 5);
|
||||||
|
}
|
||||||
|
do_execsql_test 3.1.2 {
|
||||||
|
SELECT * FROM y1;
|
||||||
|
} {1 2 3 4 1 5}
|
||||||
|
do_execsql_test 3.2.1 {
|
||||||
|
DELETE FROM y1;
|
||||||
|
INSERT INTO y1 VALUES(1, 2), (3, 4), (row_number() OVER (), 6)
|
||||||
|
, (row_number() OVER (), 7)
|
||||||
|
}
|
||||||
|
do_execsql_test 3.1.2 {
|
||||||
|
SELECT * FROM y1;
|
||||||
|
} {1 2 3 4 1 6 1 7}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------
|
||||||
|
reset_db
|
||||||
|
|
||||||
|
do_execsql_test 4.0 {
|
||||||
|
CREATE TABLE x1(a PRIMARY KEY, b) WITHOUT ROWID;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach {tn iLimit} {1 0 2 3} {
|
||||||
|
sqlite3_limit db SQLITE_LIMIT_COMPOUND_SELECT $iLimit
|
||||||
|
|
||||||
|
do_execsql_test 4.1.1 {
|
||||||
|
DELETE FROM x1;
|
||||||
|
INSERT INTO x1 VALUES
|
||||||
|
(1, 1),
|
||||||
|
(2, (SELECT * FROM (VALUES('a'), ('b'), ('c'), ('d')) ))
|
||||||
|
}
|
||||||
|
do_execsql_test 4.1.2 {
|
||||||
|
SELECT * FROM x1
|
||||||
|
} {1 1 2 a}
|
||||||
|
|
||||||
|
do_execsql_test 4.2.1 {
|
||||||
|
DELETE FROM x1;
|
||||||
|
INSERT INTO x1 VALUES
|
||||||
|
(1, 1),
|
||||||
|
(2, 2),
|
||||||
|
(3, 3),
|
||||||
|
(4, 4),
|
||||||
|
(5, (SELECT * FROM (VALUES('a'), ('b'), ('c'), ('d')) ))
|
||||||
|
}
|
||||||
|
do_execsql_test 4.2.2 {
|
||||||
|
SELECT * FROM x1
|
||||||
|
} {1 1 2 2 3 3 4 4 5 a}
|
||||||
|
|
||||||
|
do_execsql_test 4.3.1 {
|
||||||
|
DELETE FROM x1;
|
||||||
|
INSERT INTO x1 VALUES
|
||||||
|
(1, (SELECT * FROM (VALUES('a'), ('b'), ('c'), ('d'), ('e')) ))
|
||||||
|
}
|
||||||
|
do_execsql_test 4.3.2 {
|
||||||
|
SELECT * FROM x1
|
||||||
|
} {1 a}
|
||||||
|
}
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
reset_db
|
||||||
|
|
||||||
|
do_execsql_test 5.0 {
|
||||||
|
CREATE VIEW v1 AS VALUES(1, 2, 3), (4, 5, 6), (7, 8, 9);
|
||||||
|
}
|
||||||
|
do_execsql_test 5.1 {
|
||||||
|
SELECT * FROM v1
|
||||||
|
} {1 2 3 4 5 6 7 8 9}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------
|
||||||
|
reset_db
|
||||||
|
do_execsql_test 6.0 {
|
||||||
|
CREATE TABLE t1(x);
|
||||||
|
INSERT INTO t1 VALUES(1), (2);
|
||||||
|
}
|
||||||
|
|
||||||
|
do_execsql_test 6.1 {
|
||||||
|
SELECT ( VALUES( x ), ( x ) ) FROM t1;
|
||||||
|
} {1 2}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------
|
||||||
|
reset_db
|
||||||
|
do_execsql_test 6.0 {
|
||||||
|
CREATE TABLE t1(x);
|
||||||
|
INSERT INTO t1 VALUES('x'), ('y');
|
||||||
|
}
|
||||||
|
|
||||||
|
do_execsql_test 6.1 {
|
||||||
|
SELECT * FROM t1, (VALUES(1), (2))
|
||||||
|
} {x 1 x 2 y 1 y 2}
|
||||||
|
|
||||||
|
do_execsql_test 6.2 {
|
||||||
|
VALUES(CAST(44 AS REAL)),(55);
|
||||||
|
} {44.0 55}
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
do_execsql_test 7.1 {
|
||||||
|
WITH x1(a, b) AS (
|
||||||
|
VALUES(1, 2), ('a', 'b')
|
||||||
|
)
|
||||||
|
SELECT * FROM x1 one, x1 two
|
||||||
|
} {
|
||||||
|
1 2 1 2
|
||||||
|
1 2 a b
|
||||||
|
a b 1 2
|
||||||
|
a b a b
|
||||||
|
}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------
|
||||||
|
reset_db
|
||||||
|
|
||||||
|
set VVV {
|
||||||
|
( VALUES('a', 'b'), ('c', 'd'), (123, NULL) )
|
||||||
|
}
|
||||||
|
set VVV2 {
|
||||||
|
(
|
||||||
|
SELECT 'a' AS column1, 'b' AS column2
|
||||||
|
UNION ALL SELECT 'c', 'd' UNION ALL SELECT 123, NULL
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
do_execsql_test 8.0 {
|
||||||
|
CREATE TABLE t1(x);
|
||||||
|
INSERT INTO t1 VALUES('d'), (NULL), (123)
|
||||||
|
}
|
||||||
|
foreach {tn q res} {
|
||||||
|
1 "SELECT * FROM t1 LEFT JOIN VVV" {
|
||||||
|
d a b d c d d 123 {}
|
||||||
|
{} a b {} c d {} 123 {}
|
||||||
|
123 a b 123 c d 123 123 {}
|
||||||
|
}
|
||||||
|
|
||||||
|
2 "SELECT * FROM t1 LEFT JOIN VVV ON (column1=x)" {
|
||||||
|
d {} {}
|
||||||
|
{} {} {}
|
||||||
|
123 123 {}
|
||||||
|
}
|
||||||
|
|
||||||
|
3 "SELECT * FROM t1 RIGHT JOIN VVV" {
|
||||||
|
d a b d c d d 123 {}
|
||||||
|
{} a b {} c d {} 123 {}
|
||||||
|
123 a b 123 c d 123 123 {}
|
||||||
|
}
|
||||||
|
|
||||||
|
4 "SELECT * FROM t1 RIGHT JOIN VVV ON (column1=x)" {
|
||||||
|
123 123 {}
|
||||||
|
{} a b
|
||||||
|
{} c d
|
||||||
|
}
|
||||||
|
|
||||||
|
5 "SELECT * FROM t1 FULL OUTER JOIN VVV ON (column1=x)" {
|
||||||
|
d {} {}
|
||||||
|
{} {} {}
|
||||||
|
123 123 {}
|
||||||
|
{} a b
|
||||||
|
{} c d
|
||||||
|
}
|
||||||
|
|
||||||
|
6 "SELECT count(*) FROM VVV" { 3 }
|
||||||
|
|
||||||
|
7 "SELECT (SELECT column1 FROM VVV)" { a }
|
||||||
|
|
||||||
|
8 "SELECT * FROM VVV UNION ALL SELECT * FROM VVV" {
|
||||||
|
a b c d 123 {}
|
||||||
|
a b c d 123 {}
|
||||||
|
}
|
||||||
|
|
||||||
|
9 "SELECT * FROM VVV INTERSECT SELECT * FROM VVV" {
|
||||||
|
123 {} a b c d
|
||||||
|
}
|
||||||
|
|
||||||
|
10 "SELECT * FROM VVV eXCEPT SELECT * FROM VVV" { }
|
||||||
|
|
||||||
|
11 "SELECT * FROM VVV eXCEPT SELECT 'a', 'b'" { 123 {} c d }
|
||||||
|
|
||||||
|
} {
|
||||||
|
set q1 [string map [list VVV $VVV] $q]
|
||||||
|
set q2 [string map [list VVV $VVV2] $q]
|
||||||
|
set q3 "WITH VVV AS $VVV $q"
|
||||||
|
|
||||||
|
do_execsql_test 8.1.$tn.1 $q1 $res
|
||||||
|
do_execsql_test 8.1.$tn.2 $q2 $res
|
||||||
|
do_execsql_test 8.1.$tn.3 $q3 $res
|
||||||
|
}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------
|
||||||
|
reset_db
|
||||||
|
|
||||||
|
do_execsql_test 9.1 {
|
||||||
|
VALUES(456), (123), (NULL) UNION ALL SELECT 122 ORDER BY 1
|
||||||
|
} { {} 122 123 456 }
|
||||||
|
|
||||||
|
do_execsql_test 9.2 {
|
||||||
|
VALUES (1, 2), (3, 4), (
|
||||||
|
( SELECT column1 FROM ( VALUES (5, 6), (7, 8) ) ),
|
||||||
|
( SELECT max(column2) FROM ( VALUES (5, 1), (7, 6) ) )
|
||||||
|
)
|
||||||
|
} { 1 2 3 4 5 6 }
|
||||||
|
|
||||||
|
do_execsql_test 10.1 {
|
||||||
|
CREATE TABLE a2(a, b, c DEFAULT 'xyz');
|
||||||
|
}
|
||||||
|
do_execsql_test 10.2 {
|
||||||
|
INSERT INTO a2(a) VALUES(3),(4);
|
||||||
|
}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------
|
||||||
|
reset_db
|
||||||
|
ifcapable fts5 {
|
||||||
|
do_execsql_test 11.0 {
|
||||||
|
CREATE VIRTUAL TABLE ft USING fts3(x);
|
||||||
|
}
|
||||||
|
do_execsql_test 11.1 {
|
||||||
|
INSERT INTO ft VALUES('one'), ('two');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------
|
||||||
|
reset_db
|
||||||
|
do_execsql_test 12.0 {
|
||||||
|
CREATE TABLE t1(a, b);
|
||||||
|
}
|
||||||
|
do_execsql_test 12.1 {
|
||||||
|
INSERT INTO t1 SELECT 1, 2 UNION ALL VALUES(3, 4), (5, 6);
|
||||||
|
}
|
||||||
|
do_execsql_test 12.2 {
|
||||||
|
SELECT * FROM t1
|
||||||
|
} {1 2 3 4 5 6}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------
|
||||||
|
reset_db
|
||||||
|
do_execsql_test 13.0 {
|
||||||
|
CREATE TABLE t1(x);
|
||||||
|
INSERT INTO t1 VALUES('xyz');
|
||||||
|
|
||||||
|
SELECT (
|
||||||
|
VALUES( (max(substr('abc', 1, 1), x)) ),
|
||||||
|
(123),
|
||||||
|
(456)
|
||||||
|
)
|
||||||
|
FROM t1;
|
||||||
|
} {xyz}
|
||||||
|
|
||||||
|
do_catchsql_test 13.1 {
|
||||||
|
VALUES(300), (zeroblob(300) OVER win);
|
||||||
|
} {1 {zeroblob() may not be used as a window function}}
|
||||||
|
|
||||||
|
#--------------------------------------------------------------------------
|
||||||
|
reset_db
|
||||||
|
do_execsql_test 14.1 {
|
||||||
|
PRAGMA encoding = utf16;
|
||||||
|
CREATE TABLE t1(a, b);
|
||||||
|
} {}
|
||||||
|
|
||||||
|
db close
|
||||||
|
sqlite3 db test.db
|
||||||
|
|
||||||
|
do_execsql_test 14.2 {
|
||||||
|
INSERT INTO t1 VALUES
|
||||||
|
(17, 'craft'),
|
||||||
|
(16, 'urtlek' IN(1,2,3));
|
||||||
|
}
|
||||||
|
|
||||||
|
#--------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
reset_db
|
||||||
|
do_eqp_test 15.1 {
|
||||||
|
VALUES(1),(2),(3),(4),(5);
|
||||||
|
} {
|
||||||
|
QUERY PLAN
|
||||||
|
`--SCAN 5-ROW VALUES CLAUSE
|
||||||
|
}
|
||||||
|
do_execsql_test 15.2 {
|
||||||
|
CREATE TABLE t1(a,b);
|
||||||
|
}
|
||||||
|
do_eqp_test 15.3 {
|
||||||
|
INSERT INTO t1 VALUES
|
||||||
|
(1,2),(3,4),(7,8);
|
||||||
|
} {
|
||||||
|
QUERY PLAN
|
||||||
|
`--SCAN 3-ROW VALUES CLAUSE
|
||||||
|
}
|
||||||
|
do_eqp_test 15.4 {
|
||||||
|
INSERT INTO t1 VALUES
|
||||||
|
(1,2),(3,4),(7,8),
|
||||||
|
(5,row_number()OVER());
|
||||||
|
} {
|
||||||
|
QUERY PLAN
|
||||||
|
`--COMPOUND QUERY
|
||||||
|
|--LEFT-MOST SUBQUERY
|
||||||
|
| `--SCAN 3-ROW VALUES CLAUSE
|
||||||
|
`--UNION ALL
|
||||||
|
|--CO-ROUTINE (subquery-xxxxxx)
|
||||||
|
| `--SCAN CONSTANT ROW
|
||||||
|
`--SCAN (subquery-xxxxxx)
|
||||||
|
}
|
||||||
|
do_eqp_test 15.5 {
|
||||||
|
SELECT * FROM (VALUES(1),(2),(3),(4),(5),(6)), (VALUES('a'),('b'),('c'));
|
||||||
|
} {
|
||||||
|
QUERY PLAN
|
||||||
|
|--SCAN 6-ROW VALUES CLAUSE
|
||||||
|
`--SCAN 3-ROW VALUES CLAUSE
|
||||||
|
}
|
||||||
|
do_execsql_test 15.6 {
|
||||||
|
CREATE TABLE t2(x,y);
|
||||||
|
}
|
||||||
|
do_eqp_test 15.7 {
|
||||||
|
SELECT * FROM t2 UNION ALL VALUES(1,2),(3,4),(5,6),(7,8);
|
||||||
|
} {
|
||||||
|
QUERY PLAN
|
||||||
|
`--COMPOUND QUERY
|
||||||
|
|--LEFT-MOST SUBQUERY
|
||||||
|
| `--SCAN t2
|
||||||
|
`--UNION ALL
|
||||||
|
`--SCAN 4-ROW VALUES CLAUSE
|
||||||
|
}
|
||||||
|
|
||||||
|
#--------------------------------------------------------------------------
|
||||||
|
# The VALUES-as-coroutine optimization can be applied to later rows of
|
||||||
|
# a VALUES clause even if earlier rows do not qualify.
|
||||||
|
#
|
||||||
|
reset_db
|
||||||
|
do_execsql_test 16.1 {
|
||||||
|
CREATE TABLE t1(a,b);
|
||||||
|
}
|
||||||
|
do_execsql_test 16.2 {
|
||||||
|
BEGIN;
|
||||||
|
INSERT INTO t1 VALUES(1,2),(3,4),(5,6),
|
||||||
|
(7,row_number()OVER()),
|
||||||
|
(9,10), (11,12), (13,14), (15,16);
|
||||||
|
SELECT * FROM t1 ORDER BY a, b;
|
||||||
|
ROLLBACK;
|
||||||
|
} {1 2 3 4 5 6 7 1 9 10 11 12 13 14 15 16}
|
||||||
|
do_eqp_test 16.3 {
|
||||||
|
INSERT INTO t1 VALUES(1,2),(3,4),(5,6),
|
||||||
|
(7,row_number()OVER()),
|
||||||
|
(9,10), (11,12), (13,14), (15,16);
|
||||||
|
} {
|
||||||
|
QUERY PLAN
|
||||||
|
`--COMPOUND QUERY
|
||||||
|
|--LEFT-MOST SUBQUERY
|
||||||
|
| `--SCAN 3-ROW VALUES CLAUSE
|
||||||
|
|--UNION ALL
|
||||||
|
| |--CO-ROUTINE (subquery-xxxxxx)
|
||||||
|
| | `--SCAN CONSTANT ROW
|
||||||
|
| `--SCAN (subquery-xxxxxx)
|
||||||
|
`--UNION ALL
|
||||||
|
`--SCAN 4-ROW VALUES CLAUSE
|
||||||
|
}
|
||||||
|
do_execsql_test 16.4 {
|
||||||
|
BEGIN;
|
||||||
|
INSERT INTO t1 VALUES
|
||||||
|
(1,row_number()OVER()),
|
||||||
|
(2,3), (4,5), (6,7);
|
||||||
|
SELECT * FROM t1 ORDER BY a, b;
|
||||||
|
ROLLBACK;
|
||||||
|
} {1 1 2 3 4 5 6 7}
|
||||||
|
do_eqp_test 16.5 {
|
||||||
|
INSERT INTO t1 VALUES
|
||||||
|
(1,row_number()OVER()),
|
||||||
|
(2,3), (4,5), (6,7);
|
||||||
|
} {
|
||||||
|
QUERY PLAN
|
||||||
|
`--COMPOUND QUERY
|
||||||
|
|--LEFT-MOST SUBQUERY
|
||||||
|
| |--CO-ROUTINE (subquery-xxxxxx)
|
||||||
|
| | `--SCAN CONSTANT ROW
|
||||||
|
| `--SCAN (subquery-xxxxxx)
|
||||||
|
`--UNION ALL
|
||||||
|
`--SCAN 3-ROW VALUES CLAUSE
|
||||||
|
}
|
||||||
|
do_execsql_test 16.6 {
|
||||||
|
BEGIN;
|
||||||
|
INSERT INTO t1 VALUES
|
||||||
|
(1,2),(3,4),
|
||||||
|
(5,row_number()OVER()),
|
||||||
|
(7,8),(9,10),(11,12),
|
||||||
|
(13,row_number()OVER()),
|
||||||
|
(15,16),(17,18),(19,20),(21,22);
|
||||||
|
SELECT * FROM t1 ORDER BY a, b;
|
||||||
|
ROLLBACK;
|
||||||
|
} { 1 2 3 4 5 1 7 8 9 10 11 12 13 1 15 16 17 18 19 20 21 22}
|
||||||
|
do_eqp_test 16.7 {
|
||||||
|
INSERT INTO t1 VALUES
|
||||||
|
(1,2),(3,4),
|
||||||
|
(5,row_number()OVER()),
|
||||||
|
(7,8),(9,10),(11,12),
|
||||||
|
(13,row_number()OVER()),
|
||||||
|
(15,16),(17,18),(19,20),(21,22);
|
||||||
|
} {
|
||||||
|
QUERY PLAN
|
||||||
|
`--COMPOUND QUERY
|
||||||
|
|--LEFT-MOST SUBQUERY
|
||||||
|
| `--SCAN 2-ROW VALUES CLAUSE
|
||||||
|
|--UNION ALL
|
||||||
|
| |--CO-ROUTINE (subquery-xxxxxx)
|
||||||
|
| | `--SCAN CONSTANT ROW
|
||||||
|
| `--SCAN (subquery-xxxxxx)
|
||||||
|
|--UNION ALL
|
||||||
|
| `--SCAN 3-ROW VALUES CLAUSE
|
||||||
|
|--UNION ALL
|
||||||
|
| |--CO-ROUTINE (subquery-xxxxxx)
|
||||||
|
| | `--SCAN CONSTANT ROW
|
||||||
|
| `--SCAN (subquery-xxxxxx)
|
||||||
|
`--UNION ALL
|
||||||
|
`--SCAN 4-ROW VALUES CLAUSE
|
||||||
|
}
|
||||||
|
|
||||||
|
finish_test
|
37
test/valuesfault.test
Normal file
37
test/valuesfault.test
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
# 2024 March 3
|
||||||
|
#
|
||||||
|
# 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 valuesfault
|
||||||
|
source $testdir/malloc_common.tcl
|
||||||
|
|
||||||
|
|
||||||
|
do_execsql_test 1.0 {
|
||||||
|
CREATE TABLE x1(a, b, c);
|
||||||
|
}
|
||||||
|
faultsim_save_and_close
|
||||||
|
|
||||||
|
do_faultsim_test 1 -prep {
|
||||||
|
faultsim_restore_and_reopen
|
||||||
|
sqlite3_limit db SQLITE_LIMIT_COMPOUND_SELECT 2
|
||||||
|
} -body {
|
||||||
|
execsql {
|
||||||
|
INSERT INTO x1 VALUES(1, 1, 1), (2, 2, 2), (3, 3, 3), (4, 4, 4);
|
||||||
|
}
|
||||||
|
} -test {
|
||||||
|
faultsim_test_result {0 {}}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
finish_test
|
@@ -49,6 +49,33 @@ do_eqp_test 120 {
|
|||||||
|--SEARCH t2 USING INDEX sqlite_autoindex_t2_1 (a=?)
|
|--SEARCH t2 USING INDEX sqlite_autoindex_t2_1 (a=?)
|
||||||
`--SCAN t3
|
`--SCAN t3
|
||||||
}
|
}
|
||||||
|
do_eqp_test 121 {
|
||||||
|
SELECT * FROM t1, t2, t3
|
||||||
|
WHERE t1.a=t2.a AND t2.a=t3.j AND t3.j=abs(5)
|
||||||
|
ORDER BY t1.a;
|
||||||
|
} {
|
||||||
|
QUERY PLAN
|
||||||
|
|--SEARCH t1 USING INDEX sqlite_autoindex_t1_1 (a=?)
|
||||||
|
|--SEARCH t2 USING INDEX sqlite_autoindex_t2_1 (a=?)
|
||||||
|
`--SCAN t3
|
||||||
|
}
|
||||||
|
|
||||||
|
# The sqlite3ExprIsConstant() routine does not believe that
|
||||||
|
# the expression "coalesce(5,random())" is constant. So the
|
||||||
|
# optimization does not apply in this case.
|
||||||
|
#
|
||||||
|
sqlite3_create_function db
|
||||||
|
do_eqp_test 122 {
|
||||||
|
SELECT * FROM t1, t2, t3
|
||||||
|
WHERE t1.a=t2.a AND t2.a=t3.j AND t3.j=coalesce(5,random())
|
||||||
|
ORDER BY t1.a;
|
||||||
|
} {
|
||||||
|
QUERY PLAN
|
||||||
|
|--SCAN t3
|
||||||
|
|--SEARCH t1 USING INDEX sqlite_autoindex_t1_1 (a=?)
|
||||||
|
|--SEARCH t2 USING INDEX sqlite_autoindex_t2_1 (a=?)
|
||||||
|
`--USE TEMP B-TREE FOR ORDER BY
|
||||||
|
}
|
||||||
|
|
||||||
# Constant propagation in the face of collating sequences:
|
# Constant propagation in the face of collating sequences:
|
||||||
#
|
#
|
||||||
|
219
tool/lemon.c
219
tool/lemon.c
@@ -59,6 +59,82 @@ static char *msort(char*,char**,int(*)(const char*,const char*));
|
|||||||
*/
|
*/
|
||||||
#define lemonStrlen(X) ((int)strlen(X))
|
#define lemonStrlen(X) ((int)strlen(X))
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Header on the linked list of memory allocations.
|
||||||
|
*/
|
||||||
|
typedef struct MemChunk MemChunk;
|
||||||
|
struct MemChunk {
|
||||||
|
MemChunk *pNext;
|
||||||
|
size_t sz;
|
||||||
|
/* Actually memory follows */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Global linked list of all memory allocations.
|
||||||
|
*/
|
||||||
|
static MemChunk *memChunkList = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Wrappers around malloc(), calloc(), realloc() and free().
|
||||||
|
**
|
||||||
|
** All memory allocations are kept on a doubly-linked list. The
|
||||||
|
** lemon_free_all() function can be called prior to exit to clean
|
||||||
|
** up any memory leaks.
|
||||||
|
**
|
||||||
|
** This is not necessary. But compilers and getting increasingly
|
||||||
|
** fussy about memory leaks, even in command-line programs like Lemon
|
||||||
|
** where they do not matter. So this code is provided to hush the
|
||||||
|
** warnings.
|
||||||
|
*/
|
||||||
|
static void *lemon_malloc(size_t nByte){
|
||||||
|
MemChunk *p;
|
||||||
|
if( nByte<0 ) return 0;
|
||||||
|
p = malloc( nByte + sizeof(MemChunk) );
|
||||||
|
if( p==0 ){
|
||||||
|
fprintf(stderr, "Out of memory. Failed to allocate %lld bytes.\n",
|
||||||
|
(long long int)nByte);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
p->pNext = memChunkList;
|
||||||
|
p->sz = nByte;
|
||||||
|
memChunkList = p;
|
||||||
|
return (void*)&p[1];
|
||||||
|
}
|
||||||
|
static void *lemon_calloc(size_t nElem, size_t sz){
|
||||||
|
void *p = lemon_malloc(nElem*sz);
|
||||||
|
memset(p, 0, nElem*sz);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
static void lemon_free(void *pOld){
|
||||||
|
if( pOld ){
|
||||||
|
MemChunk *p = (MemChunk*)pOld;
|
||||||
|
p--;
|
||||||
|
memset(pOld, 0, p->sz);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static void *lemon_realloc(void *pOld, size_t nNew){
|
||||||
|
void *pNew;
|
||||||
|
MemChunk *p;
|
||||||
|
if( pOld==0 ) return lemon_malloc(nNew);
|
||||||
|
p = (MemChunk*)pOld;
|
||||||
|
p--;
|
||||||
|
if( p->sz>=nNew ) return pOld;
|
||||||
|
pNew = lemon_malloc( nNew );
|
||||||
|
memcpy(pNew, pOld, p->sz);
|
||||||
|
return pNew;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Free all outstanding memory allocations.
|
||||||
|
** Do this right before exiting.
|
||||||
|
*/
|
||||||
|
static void lemon_free_all(void){
|
||||||
|
while( memChunkList ){
|
||||||
|
MemChunk *pNext = memChunkList->pNext;
|
||||||
|
free( memChunkList );
|
||||||
|
memChunkList = pNext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Compilers are starting to complain about the use of sprintf() and strcpy(),
|
** Compilers are starting to complain about the use of sprintf() and strcpy(),
|
||||||
** saying they are unsafe. So we define our own versions of those routines too.
|
** saying they are unsafe. So we define our own versions of those routines too.
|
||||||
@@ -497,7 +573,7 @@ static struct action *Action_new(void){
|
|||||||
if( actionfreelist==0 ){
|
if( actionfreelist==0 ){
|
||||||
int i;
|
int i;
|
||||||
int amt = 100;
|
int amt = 100;
|
||||||
actionfreelist = (struct action *)calloc(amt, sizeof(struct action));
|
actionfreelist = (struct action *)lemon_calloc(amt, sizeof(struct action));
|
||||||
if( actionfreelist==0 ){
|
if( actionfreelist==0 ){
|
||||||
fprintf(stderr,"Unable to allocate memory for a new parser action.");
|
fprintf(stderr,"Unable to allocate memory for a new parser action.");
|
||||||
exit(1);
|
exit(1);
|
||||||
@@ -616,14 +692,14 @@ struct acttab {
|
|||||||
|
|
||||||
/* Free all memory associated with the given acttab */
|
/* Free all memory associated with the given acttab */
|
||||||
void acttab_free(acttab *p){
|
void acttab_free(acttab *p){
|
||||||
free( p->aAction );
|
lemon_free( p->aAction );
|
||||||
free( p->aLookahead );
|
lemon_free( p->aLookahead );
|
||||||
free( p );
|
lemon_free( p );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate a new acttab structure */
|
/* Allocate a new acttab structure */
|
||||||
acttab *acttab_alloc(int nsymbol, int nterminal){
|
acttab *acttab_alloc(int nsymbol, int nterminal){
|
||||||
acttab *p = (acttab *) calloc( 1, sizeof(*p) );
|
acttab *p = (acttab *) lemon_calloc( 1, sizeof(*p) );
|
||||||
if( p==0 ){
|
if( p==0 ){
|
||||||
fprintf(stderr,"Unable to allocate memory for a new acttab.");
|
fprintf(stderr,"Unable to allocate memory for a new acttab.");
|
||||||
exit(1);
|
exit(1);
|
||||||
@@ -642,7 +718,7 @@ acttab *acttab_alloc(int nsymbol, int nterminal){
|
|||||||
void acttab_action(acttab *p, int lookahead, int action){
|
void acttab_action(acttab *p, int lookahead, int action){
|
||||||
if( p->nLookahead>=p->nLookaheadAlloc ){
|
if( p->nLookahead>=p->nLookaheadAlloc ){
|
||||||
p->nLookaheadAlloc += 25;
|
p->nLookaheadAlloc += 25;
|
||||||
p->aLookahead = (struct lookahead_action *) realloc( p->aLookahead,
|
p->aLookahead = (struct lookahead_action *) lemon_realloc( p->aLookahead,
|
||||||
sizeof(p->aLookahead[0])*p->nLookaheadAlloc );
|
sizeof(p->aLookahead[0])*p->nLookaheadAlloc );
|
||||||
if( p->aLookahead==0 ){
|
if( p->aLookahead==0 ){
|
||||||
fprintf(stderr,"malloc failed\n");
|
fprintf(stderr,"malloc failed\n");
|
||||||
@@ -692,7 +768,7 @@ int acttab_insert(acttab *p, int makeItSafe){
|
|||||||
if( p->nAction + n >= p->nActionAlloc ){
|
if( p->nAction + n >= p->nActionAlloc ){
|
||||||
int oldAlloc = p->nActionAlloc;
|
int oldAlloc = p->nActionAlloc;
|
||||||
p->nActionAlloc = p->nAction + n + p->nActionAlloc + 20;
|
p->nActionAlloc = p->nAction + n + p->nActionAlloc + 20;
|
||||||
p->aAction = (struct lookahead_action *) realloc( p->aAction,
|
p->aAction = (struct lookahead_action *) lemon_realloc( p->aAction,
|
||||||
sizeof(p->aAction[0])*p->nActionAlloc);
|
sizeof(p->aAction[0])*p->nActionAlloc);
|
||||||
if( p->aAction==0 ){
|
if( p->aAction==0 ){
|
||||||
fprintf(stderr,"malloc failed\n");
|
fprintf(stderr,"malloc failed\n");
|
||||||
@@ -1314,7 +1390,7 @@ static struct config **basisend = 0; /* End of list of basis configs */
|
|||||||
|
|
||||||
/* Return a pointer to a new configuration */
|
/* Return a pointer to a new configuration */
|
||||||
PRIVATE struct config *newconfig(void){
|
PRIVATE struct config *newconfig(void){
|
||||||
return (struct config*)calloc(1, sizeof(struct config));
|
return (struct config*)lemon_calloc(1, sizeof(struct config));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The configuration "old" is no longer used */
|
/* The configuration "old" is no longer used */
|
||||||
@@ -1530,19 +1606,19 @@ static char *bDefineUsed = 0; /* True for every -D macro actually used */
|
|||||||
static void handle_D_option(char *z){
|
static void handle_D_option(char *z){
|
||||||
char **paz;
|
char **paz;
|
||||||
nDefine++;
|
nDefine++;
|
||||||
azDefine = (char **) realloc(azDefine, sizeof(azDefine[0])*nDefine);
|
azDefine = (char **) lemon_realloc(azDefine, sizeof(azDefine[0])*nDefine);
|
||||||
if( azDefine==0 ){
|
if( azDefine==0 ){
|
||||||
fprintf(stderr,"out of memory\n");
|
fprintf(stderr,"out of memory\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
bDefineUsed = (char*)realloc(bDefineUsed, nDefine);
|
bDefineUsed = (char*)lemon_realloc(bDefineUsed, nDefine);
|
||||||
if( bDefineUsed==0 ){
|
if( bDefineUsed==0 ){
|
||||||
fprintf(stderr,"out of memory\n");
|
fprintf(stderr,"out of memory\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
bDefineUsed[nDefine-1] = 0;
|
bDefineUsed[nDefine-1] = 0;
|
||||||
paz = &azDefine[nDefine-1];
|
paz = &azDefine[nDefine-1];
|
||||||
*paz = (char *) malloc( lemonStrlen(z)+1 );
|
*paz = (char *) lemon_malloc( lemonStrlen(z)+1 );
|
||||||
if( *paz==0 ){
|
if( *paz==0 ){
|
||||||
fprintf(stderr,"out of memory\n");
|
fprintf(stderr,"out of memory\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
@@ -1556,7 +1632,7 @@ static void handle_D_option(char *z){
|
|||||||
*/
|
*/
|
||||||
static char *outputDir = NULL;
|
static char *outputDir = NULL;
|
||||||
static void handle_d_option(char *z){
|
static void handle_d_option(char *z){
|
||||||
outputDir = (char *) malloc( lemonStrlen(z)+1 );
|
outputDir = (char *) lemon_malloc( lemonStrlen(z)+1 );
|
||||||
if( outputDir==0 ){
|
if( outputDir==0 ){
|
||||||
fprintf(stderr,"out of memory\n");
|
fprintf(stderr,"out of memory\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
@@ -1566,7 +1642,7 @@ static void handle_d_option(char *z){
|
|||||||
|
|
||||||
static char *user_templatename = NULL;
|
static char *user_templatename = NULL;
|
||||||
static void handle_T_option(char *z){
|
static void handle_T_option(char *z){
|
||||||
user_templatename = (char *) malloc( lemonStrlen(z)+1 );
|
user_templatename = (char *) lemon_malloc( lemonStrlen(z)+1 );
|
||||||
if( user_templatename==0 ){
|
if( user_templatename==0 ){
|
||||||
memory_error();
|
memory_error();
|
||||||
}
|
}
|
||||||
@@ -1803,6 +1879,7 @@ int main(int argc, char **argv){
|
|||||||
|
|
||||||
/* return 0 on success, 1 on failure. */
|
/* return 0 on success, 1 on failure. */
|
||||||
exitcode = ((lem.errorcnt > 0) || (lem.nconflict > 0)) ? 1 : 0;
|
exitcode = ((lem.errorcnt > 0) || (lem.nconflict > 0)) ? 1 : 0;
|
||||||
|
lemon_free_all();
|
||||||
exit(exitcode);
|
exit(exitcode);
|
||||||
return (exitcode);
|
return (exitcode);
|
||||||
}
|
}
|
||||||
@@ -2391,7 +2468,7 @@ static void parseonetoken(struct pstate *psp)
|
|||||||
case IN_RHS:
|
case IN_RHS:
|
||||||
if( x[0]=='.' ){
|
if( x[0]=='.' ){
|
||||||
struct rule *rp;
|
struct rule *rp;
|
||||||
rp = (struct rule *)calloc( sizeof(struct rule) +
|
rp = (struct rule *)lemon_calloc( sizeof(struct rule) +
|
||||||
sizeof(struct symbol*)*psp->nrhs + sizeof(char*)*psp->nrhs, 1);
|
sizeof(struct symbol*)*psp->nrhs + sizeof(char*)*psp->nrhs, 1);
|
||||||
if( rp==0 ){
|
if( rp==0 ){
|
||||||
ErrorMsg(psp->filename,psp->tokenlineno,
|
ErrorMsg(psp->filename,psp->tokenlineno,
|
||||||
@@ -2443,17 +2520,17 @@ static void parseonetoken(struct pstate *psp)
|
|||||||
struct symbol *msp = psp->rhs[psp->nrhs-1];
|
struct symbol *msp = psp->rhs[psp->nrhs-1];
|
||||||
if( msp->type!=MULTITERMINAL ){
|
if( msp->type!=MULTITERMINAL ){
|
||||||
struct symbol *origsp = msp;
|
struct symbol *origsp = msp;
|
||||||
msp = (struct symbol *) calloc(1,sizeof(*msp));
|
msp = (struct symbol *) lemon_calloc(1,sizeof(*msp));
|
||||||
memset(msp, 0, sizeof(*msp));
|
memset(msp, 0, sizeof(*msp));
|
||||||
msp->type = MULTITERMINAL;
|
msp->type = MULTITERMINAL;
|
||||||
msp->nsubsym = 1;
|
msp->nsubsym = 1;
|
||||||
msp->subsym = (struct symbol **) calloc(1,sizeof(struct symbol*));
|
msp->subsym = (struct symbol**)lemon_calloc(1,sizeof(struct symbol*));
|
||||||
msp->subsym[0] = origsp;
|
msp->subsym[0] = origsp;
|
||||||
msp->name = origsp->name;
|
msp->name = origsp->name;
|
||||||
psp->rhs[psp->nrhs-1] = msp;
|
psp->rhs[psp->nrhs-1] = msp;
|
||||||
}
|
}
|
||||||
msp->nsubsym++;
|
msp->nsubsym++;
|
||||||
msp->subsym = (struct symbol **) realloc(msp->subsym,
|
msp->subsym = (struct symbol **) lemon_realloc(msp->subsym,
|
||||||
sizeof(struct symbol*)*msp->nsubsym);
|
sizeof(struct symbol*)*msp->nsubsym);
|
||||||
msp->subsym[msp->nsubsym-1] = Symbol_new(&x[1]);
|
msp->subsym[msp->nsubsym-1] = Symbol_new(&x[1]);
|
||||||
if( ISLOWER(x[1]) || ISLOWER(msp->subsym[0]->name[0]) ){
|
if( ISLOWER(x[1]) || ISLOWER(msp->subsym[0]->name[0]) ){
|
||||||
@@ -2669,7 +2746,7 @@ static void parseonetoken(struct pstate *psp)
|
|||||||
nLine = lemonStrlen(zLine);
|
nLine = lemonStrlen(zLine);
|
||||||
n += nLine + lemonStrlen(psp->filename) + nBack;
|
n += nLine + lemonStrlen(psp->filename) + nBack;
|
||||||
}
|
}
|
||||||
*psp->declargslot = (char *) realloc(*psp->declargslot, n);
|
*psp->declargslot = (char *) lemon_realloc(*psp->declargslot, n);
|
||||||
zBuf = *psp->declargslot + nOld;
|
zBuf = *psp->declargslot + nOld;
|
||||||
if( addLineMacro ){
|
if( addLineMacro ){
|
||||||
if( nOld && zBuf[-1]!='\n' ){
|
if( nOld && zBuf[-1]!='\n' ){
|
||||||
@@ -2783,7 +2860,7 @@ static void parseonetoken(struct pstate *psp)
|
|||||||
}else if( ISUPPER(x[0]) || ((x[0]=='|' || x[0]=='/') && ISUPPER(x[1])) ){
|
}else if( ISUPPER(x[0]) || ((x[0]=='|' || x[0]=='/') && ISUPPER(x[1])) ){
|
||||||
struct symbol *msp = psp->tkclass;
|
struct symbol *msp = psp->tkclass;
|
||||||
msp->nsubsym++;
|
msp->nsubsym++;
|
||||||
msp->subsym = (struct symbol **) realloc(msp->subsym,
|
msp->subsym = (struct symbol **) lemon_realloc(msp->subsym,
|
||||||
sizeof(struct symbol*)*msp->nsubsym);
|
sizeof(struct symbol*)*msp->nsubsym);
|
||||||
if( !ISUPPER(x[0]) ) x++;
|
if( !ISUPPER(x[0]) ) x++;
|
||||||
msp->subsym[msp->nsubsym-1] = Symbol_new(x);
|
msp->subsym[msp->nsubsym-1] = Symbol_new(x);
|
||||||
@@ -2998,10 +3075,10 @@ void Parse(struct lemon *gp)
|
|||||||
fseek(fp,0,2);
|
fseek(fp,0,2);
|
||||||
filesize = ftell(fp);
|
filesize = ftell(fp);
|
||||||
rewind(fp);
|
rewind(fp);
|
||||||
filebuf = (char *)malloc( filesize+1 );
|
filebuf = (char *)lemon_malloc( filesize+1 );
|
||||||
if( filesize>100000000 || filebuf==0 ){
|
if( filesize>100000000 || filebuf==0 ){
|
||||||
ErrorMsg(ps.filename,0,"Input file too large.");
|
ErrorMsg(ps.filename,0,"Input file too large.");
|
||||||
free(filebuf);
|
lemon_free(filebuf);
|
||||||
gp->errorcnt++;
|
gp->errorcnt++;
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return;
|
return;
|
||||||
@@ -3009,7 +3086,7 @@ void Parse(struct lemon *gp)
|
|||||||
if( fread(filebuf,1,filesize,fp)!=filesize ){
|
if( fread(filebuf,1,filesize,fp)!=filesize ){
|
||||||
ErrorMsg(ps.filename,0,"Can't read in all %d bytes of this file.",
|
ErrorMsg(ps.filename,0,"Can't read in all %d bytes of this file.",
|
||||||
filesize);
|
filesize);
|
||||||
free(filebuf);
|
lemon_free(filebuf);
|
||||||
gp->errorcnt++;
|
gp->errorcnt++;
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return;
|
return;
|
||||||
@@ -3121,7 +3198,7 @@ void Parse(struct lemon *gp)
|
|||||||
*cp = (char)c; /* Restore the buffer */
|
*cp = (char)c; /* Restore the buffer */
|
||||||
cp = nextcp;
|
cp = nextcp;
|
||||||
}
|
}
|
||||||
free(filebuf); /* Release the buffer after parsing */
|
lemon_free(filebuf); /* Release the buffer after parsing */
|
||||||
gp->rule = ps.firstrule;
|
gp->rule = ps.firstrule;
|
||||||
gp->errorcnt = ps.errorcnt;
|
gp->errorcnt = ps.errorcnt;
|
||||||
}
|
}
|
||||||
@@ -3139,7 +3216,7 @@ struct plink *Plink_new(void){
|
|||||||
if( plink_freelist==0 ){
|
if( plink_freelist==0 ){
|
||||||
int i;
|
int i;
|
||||||
int amt = 100;
|
int amt = 100;
|
||||||
plink_freelist = (struct plink *)calloc( amt, sizeof(struct plink) );
|
plink_freelist = (struct plink *)lemon_calloc( amt, sizeof(struct plink) );
|
||||||
if( plink_freelist==0 ){
|
if( plink_freelist==0 ){
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Unable to allocate memory for a new follow-set propagation link.\n");
|
"Unable to allocate memory for a new follow-set propagation link.\n");
|
||||||
@@ -3192,9 +3269,7 @@ void Plink_delete(struct plink *plp)
|
|||||||
** Procedures for generating reports and tables in the LEMON parser generator.
|
** Procedures for generating reports and tables in the LEMON parser generator.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Generate a filename with the given suffix. Space to hold the
|
/* Generate a filename with the given suffix.
|
||||||
** name comes from malloc() and must be freed by the calling
|
|
||||||
** function.
|
|
||||||
*/
|
*/
|
||||||
PRIVATE char *file_makename(struct lemon *lemp, const char *suffix)
|
PRIVATE char *file_makename(struct lemon *lemp, const char *suffix)
|
||||||
{
|
{
|
||||||
@@ -3211,7 +3286,7 @@ PRIVATE char *file_makename(struct lemon *lemp, const char *suffix)
|
|||||||
sz += lemonStrlen(suffix);
|
sz += lemonStrlen(suffix);
|
||||||
if( outputDir ) sz += lemonStrlen(outputDir) + 1;
|
if( outputDir ) sz += lemonStrlen(outputDir) + 1;
|
||||||
sz += 5;
|
sz += 5;
|
||||||
name = (char*)malloc( sz );
|
name = (char*)lemon_malloc( sz );
|
||||||
if( name==0 ){
|
if( name==0 ){
|
||||||
fprintf(stderr,"Can't allocate space for a filename.\n");
|
fprintf(stderr,"Can't allocate space for a filename.\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
@@ -3238,7 +3313,7 @@ PRIVATE FILE *file_open(
|
|||||||
){
|
){
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
|
||||||
if( lemp->outname ) free(lemp->outname);
|
if( lemp->outname ) lemon_free(lemp->outname);
|
||||||
lemp->outname = file_makename(lemp, suffix);
|
lemp->outname = file_makename(lemp, suffix);
|
||||||
fp = fopen(lemp->outname,mode);
|
fp = fopen(lemp->outname,mode);
|
||||||
if( fp==0 && *mode=='w' ){
|
if( fp==0 && *mode=='w' ){
|
||||||
@@ -3554,14 +3629,14 @@ PRIVATE char *pathsearch(char *argv0, char *name, int modemask)
|
|||||||
if( cp ){
|
if( cp ){
|
||||||
c = *cp;
|
c = *cp;
|
||||||
*cp = 0;
|
*cp = 0;
|
||||||
path = (char *)malloc( lemonStrlen(argv0) + lemonStrlen(name) + 2 );
|
path = (char *)lemon_malloc( lemonStrlen(argv0) + lemonStrlen(name) + 2 );
|
||||||
if( path ) lemon_sprintf(path,"%s/%s",argv0,name);
|
if( path ) lemon_sprintf(path,"%s/%s",argv0,name);
|
||||||
*cp = c;
|
*cp = c;
|
||||||
}else{
|
}else{
|
||||||
pathlist = getenv("PATH");
|
pathlist = getenv("PATH");
|
||||||
if( pathlist==0 ) pathlist = ".:/bin:/usr/bin";
|
if( pathlist==0 ) pathlist = ".:/bin:/usr/bin";
|
||||||
pathbuf = (char *) malloc( lemonStrlen(pathlist) + 1 );
|
pathbuf = (char *) lemon_malloc( lemonStrlen(pathlist) + 1 );
|
||||||
path = (char *)malloc( lemonStrlen(pathlist)+lemonStrlen(name)+2 );
|
path = (char *)lemon_malloc( lemonStrlen(pathlist)+lemonStrlen(name)+2 );
|
||||||
if( (pathbuf != 0) && (path!=0) ){
|
if( (pathbuf != 0) && (path!=0) ){
|
||||||
pathbufptr = pathbuf;
|
pathbufptr = pathbuf;
|
||||||
lemon_strcpy(pathbuf, pathlist);
|
lemon_strcpy(pathbuf, pathlist);
|
||||||
@@ -3577,7 +3652,7 @@ PRIVATE char *pathsearch(char *argv0, char *name, int modemask)
|
|||||||
if( access(path,modemask)==0 ) break;
|
if( access(path,modemask)==0 ) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(pathbufptr);
|
lemon_free(pathbufptr);
|
||||||
}
|
}
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
@@ -3708,7 +3783,7 @@ PRIVATE FILE *tplt_open(struct lemon *lemp)
|
|||||||
fprintf(stderr,"Can't open the template file \"%s\".\n",tpltname);
|
fprintf(stderr,"Can't open the template file \"%s\".\n",tpltname);
|
||||||
lemp->errorcnt++;
|
lemp->errorcnt++;
|
||||||
}
|
}
|
||||||
free(toFree);
|
lemon_free(toFree);
|
||||||
return in;
|
return in;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3837,7 +3912,7 @@ PRIVATE char *append_str(const char *zText, int n, int p1, int p2){
|
|||||||
}
|
}
|
||||||
if( (int) (n+sizeof(zInt)*2+used) >= alloced ){
|
if( (int) (n+sizeof(zInt)*2+used) >= alloced ){
|
||||||
alloced = n + sizeof(zInt)*2 + used + 200;
|
alloced = n + sizeof(zInt)*2 + used + 200;
|
||||||
z = (char *) realloc(z, alloced);
|
z = (char *) lemon_realloc(z, alloced);
|
||||||
}
|
}
|
||||||
if( z==0 ) return empty;
|
if( z==0 ) return empty;
|
||||||
while( n-- > 0 ){
|
while( n-- > 0 ){
|
||||||
@@ -4127,7 +4202,7 @@ void print_stack_union(
|
|||||||
|
|
||||||
/* Allocate and initialize types[] and allocate stddt[] */
|
/* Allocate and initialize types[] and allocate stddt[] */
|
||||||
arraysize = lemp->nsymbol * 2;
|
arraysize = lemp->nsymbol * 2;
|
||||||
types = (char**)calloc( arraysize, sizeof(char*) );
|
types = (char**)lemon_calloc( arraysize, sizeof(char*) );
|
||||||
if( types==0 ){
|
if( types==0 ){
|
||||||
fprintf(stderr,"Out of memory.\n");
|
fprintf(stderr,"Out of memory.\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
@@ -4144,7 +4219,7 @@ void print_stack_union(
|
|||||||
len = lemonStrlen(sp->datatype);
|
len = lemonStrlen(sp->datatype);
|
||||||
if( len>maxdtlength ) maxdtlength = len;
|
if( len>maxdtlength ) maxdtlength = len;
|
||||||
}
|
}
|
||||||
stddt = (char*)malloc( maxdtlength*2 + 1 );
|
stddt = (char*)lemon_malloc( maxdtlength*2 + 1 );
|
||||||
if( stddt==0 ){
|
if( stddt==0 ){
|
||||||
fprintf(stderr,"Out of memory.\n");
|
fprintf(stderr,"Out of memory.\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
@@ -4193,7 +4268,7 @@ void print_stack_union(
|
|||||||
}
|
}
|
||||||
if( types[hash]==0 ){
|
if( types[hash]==0 ){
|
||||||
sp->dtnum = hash + 1;
|
sp->dtnum = hash + 1;
|
||||||
types[hash] = (char*)malloc( lemonStrlen(stddt)+1 );
|
types[hash] = (char*)lemon_malloc( lemonStrlen(stddt)+1 );
|
||||||
if( types[hash]==0 ){
|
if( types[hash]==0 ){
|
||||||
fprintf(stderr,"Out of memory.\n");
|
fprintf(stderr,"Out of memory.\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
@@ -4215,13 +4290,13 @@ void print_stack_union(
|
|||||||
for(i=0; i<arraysize; i++){
|
for(i=0; i<arraysize; i++){
|
||||||
if( types[i]==0 ) continue;
|
if( types[i]==0 ) continue;
|
||||||
fprintf(out," %s yy%d;\n",types[i],i+1); lineno++;
|
fprintf(out," %s yy%d;\n",types[i],i+1); lineno++;
|
||||||
free(types[i]);
|
lemon_free(types[i]);
|
||||||
}
|
}
|
||||||
if( lemp->errsym && lemp->errsym->useCnt ){
|
if( lemp->errsym && lemp->errsym->useCnt ){
|
||||||
fprintf(out," int yy%d;\n",lemp->errsym->dtnum); lineno++;
|
fprintf(out," int yy%d;\n",lemp->errsym->dtnum); lineno++;
|
||||||
}
|
}
|
||||||
free(stddt);
|
lemon_free(stddt);
|
||||||
free(types);
|
lemon_free(types);
|
||||||
fprintf(out,"} YYMINORTYPE;\n"); lineno++;
|
fprintf(out,"} YYMINORTYPE;\n"); lineno++;
|
||||||
*plineno = lineno;
|
*plineno = lineno;
|
||||||
}
|
}
|
||||||
@@ -4450,7 +4525,7 @@ void ReportTable(
|
|||||||
if( mhflag ){
|
if( mhflag ){
|
||||||
char *incName = file_makename(lemp, ".h");
|
char *incName = file_makename(lemp, ".h");
|
||||||
fprintf(out,"#include \"%s\"\n", incName); lineno++;
|
fprintf(out,"#include \"%s\"\n", incName); lineno++;
|
||||||
free(incName);
|
lemon_free(incName);
|
||||||
}
|
}
|
||||||
tplt_xfer(lemp->name,in,out,&lineno);
|
tplt_xfer(lemp->name,in,out,&lineno);
|
||||||
|
|
||||||
@@ -4557,7 +4632,7 @@ void ReportTable(
|
|||||||
** table must be computed before generating the YYNSTATE macro because
|
** table must be computed before generating the YYNSTATE macro because
|
||||||
** we need to know how many states can be eliminated.
|
** we need to know how many states can be eliminated.
|
||||||
*/
|
*/
|
||||||
ax = (struct axset *) calloc(lemp->nxstate*2, sizeof(ax[0]));
|
ax = (struct axset *) lemon_calloc(lemp->nxstate*2, sizeof(ax[0]));
|
||||||
if( ax==0 ){
|
if( ax==0 ){
|
||||||
fprintf(stderr,"malloc failed\n");
|
fprintf(stderr,"malloc failed\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
@@ -4615,7 +4690,7 @@ void ReportTable(
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
free(ax);
|
lemon_free(ax);
|
||||||
|
|
||||||
/* Mark rules that are actually used for reduce actions after all
|
/* Mark rules that are actually used for reduce actions after all
|
||||||
** optimizations have been applied
|
** optimizations have been applied
|
||||||
@@ -5241,7 +5316,7 @@ void SetSize(int n)
|
|||||||
/* Allocate a new set */
|
/* Allocate a new set */
|
||||||
char *SetNew(void){
|
char *SetNew(void){
|
||||||
char *s;
|
char *s;
|
||||||
s = (char*)calloc( size, 1);
|
s = (char*)lemon_calloc( size, 1);
|
||||||
if( s==0 ){
|
if( s==0 ){
|
||||||
memory_error();
|
memory_error();
|
||||||
}
|
}
|
||||||
@@ -5251,7 +5326,7 @@ char *SetNew(void){
|
|||||||
/* Deallocate a set */
|
/* Deallocate a set */
|
||||||
void SetFree(char *s)
|
void SetFree(char *s)
|
||||||
{
|
{
|
||||||
free(s);
|
lemon_free(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add a new element to the set. Return TRUE if the element was added
|
/* Add a new element to the set. Return TRUE if the element was added
|
||||||
@@ -5310,7 +5385,7 @@ const char *Strsafe(const char *y)
|
|||||||
|
|
||||||
if( y==0 ) return 0;
|
if( y==0 ) return 0;
|
||||||
z = Strsafe_find(y);
|
z = Strsafe_find(y);
|
||||||
if( z==0 && (cpy=(char *)malloc( lemonStrlen(y)+1 ))!=0 ){
|
if( z==0 && (cpy=(char *)lemon_malloc( lemonStrlen(y)+1 ))!=0 ){
|
||||||
lemon_strcpy(cpy,y);
|
lemon_strcpy(cpy,y);
|
||||||
z = cpy;
|
z = cpy;
|
||||||
Strsafe_insert(z);
|
Strsafe_insert(z);
|
||||||
@@ -5346,13 +5421,13 @@ static struct s_x1 *x1a;
|
|||||||
/* Allocate a new associative array */
|
/* Allocate a new associative array */
|
||||||
void Strsafe_init(void){
|
void Strsafe_init(void){
|
||||||
if( x1a ) return;
|
if( x1a ) return;
|
||||||
x1a = (struct s_x1*)malloc( sizeof(struct s_x1) );
|
x1a = (struct s_x1*)lemon_malloc( sizeof(struct s_x1) );
|
||||||
if( x1a ){
|
if( x1a ){
|
||||||
x1a->size = 1024;
|
x1a->size = 1024;
|
||||||
x1a->count = 0;
|
x1a->count = 0;
|
||||||
x1a->tbl = (x1node*)calloc(1024, sizeof(x1node) + sizeof(x1node*));
|
x1a->tbl = (x1node*)lemon_calloc(1024, sizeof(x1node) + sizeof(x1node*));
|
||||||
if( x1a->tbl==0 ){
|
if( x1a->tbl==0 ){
|
||||||
free(x1a);
|
lemon_free(x1a);
|
||||||
x1a = 0;
|
x1a = 0;
|
||||||
}else{
|
}else{
|
||||||
int i;
|
int i;
|
||||||
@@ -5387,7 +5462,7 @@ int Strsafe_insert(const char *data)
|
|||||||
struct s_x1 array;
|
struct s_x1 array;
|
||||||
array.size = arrSize = x1a->size*2;
|
array.size = arrSize = x1a->size*2;
|
||||||
array.count = x1a->count;
|
array.count = x1a->count;
|
||||||
array.tbl = (x1node*)calloc(arrSize, sizeof(x1node) + sizeof(x1node*));
|
array.tbl = (x1node*)lemon_calloc(arrSize, sizeof(x1node)+sizeof(x1node*));
|
||||||
if( array.tbl==0 ) return 0; /* Fail due to malloc failure */
|
if( array.tbl==0 ) return 0; /* Fail due to malloc failure */
|
||||||
array.ht = (x1node**)&(array.tbl[arrSize]);
|
array.ht = (x1node**)&(array.tbl[arrSize]);
|
||||||
for(i=0; i<arrSize; i++) array.ht[i] = 0;
|
for(i=0; i<arrSize; i++) array.ht[i] = 0;
|
||||||
@@ -5402,7 +5477,7 @@ int Strsafe_insert(const char *data)
|
|||||||
newnp->from = &(array.ht[h]);
|
newnp->from = &(array.ht[h]);
|
||||||
array.ht[h] = newnp;
|
array.ht[h] = newnp;
|
||||||
}
|
}
|
||||||
/* free(x1a->tbl); // This program was originally for 16-bit machines.
|
/* lemon_free(x1a->tbl); // This program was originally for 16-bit machines.
|
||||||
** Don't worry about freeing memory on modern platforms. */
|
** Don't worry about freeing memory on modern platforms. */
|
||||||
*x1a = array;
|
*x1a = array;
|
||||||
}
|
}
|
||||||
@@ -5443,7 +5518,7 @@ struct symbol *Symbol_new(const char *x)
|
|||||||
|
|
||||||
sp = Symbol_find(x);
|
sp = Symbol_find(x);
|
||||||
if( sp==0 ){
|
if( sp==0 ){
|
||||||
sp = (struct symbol *)calloc(1, sizeof(struct symbol) );
|
sp = (struct symbol *)lemon_calloc(1, sizeof(struct symbol) );
|
||||||
MemoryCheck(sp);
|
MemoryCheck(sp);
|
||||||
sp->name = Strsafe(x);
|
sp->name = Strsafe(x);
|
||||||
sp->type = ISUPPER(*x) ? TERMINAL : NONTERMINAL;
|
sp->type = ISUPPER(*x) ? TERMINAL : NONTERMINAL;
|
||||||
@@ -5514,13 +5589,13 @@ static struct s_x2 *x2a;
|
|||||||
/* Allocate a new associative array */
|
/* Allocate a new associative array */
|
||||||
void Symbol_init(void){
|
void Symbol_init(void){
|
||||||
if( x2a ) return;
|
if( x2a ) return;
|
||||||
x2a = (struct s_x2*)malloc( sizeof(struct s_x2) );
|
x2a = (struct s_x2*)lemon_malloc( sizeof(struct s_x2) );
|
||||||
if( x2a ){
|
if( x2a ){
|
||||||
x2a->size = 128;
|
x2a->size = 128;
|
||||||
x2a->count = 0;
|
x2a->count = 0;
|
||||||
x2a->tbl = (x2node*)calloc(128, sizeof(x2node) + sizeof(x2node*));
|
x2a->tbl = (x2node*)lemon_calloc(128, sizeof(x2node) + sizeof(x2node*));
|
||||||
if( x2a->tbl==0 ){
|
if( x2a->tbl==0 ){
|
||||||
free(x2a);
|
lemon_free(x2a);
|
||||||
x2a = 0;
|
x2a = 0;
|
||||||
}else{
|
}else{
|
||||||
int i;
|
int i;
|
||||||
@@ -5555,7 +5630,7 @@ int Symbol_insert(struct symbol *data, const char *key)
|
|||||||
struct s_x2 array;
|
struct s_x2 array;
|
||||||
array.size = arrSize = x2a->size*2;
|
array.size = arrSize = x2a->size*2;
|
||||||
array.count = x2a->count;
|
array.count = x2a->count;
|
||||||
array.tbl = (x2node*)calloc(arrSize, sizeof(x2node) + sizeof(x2node*));
|
array.tbl = (x2node*)lemon_calloc(arrSize, sizeof(x2node)+sizeof(x2node*));
|
||||||
if( array.tbl==0 ) return 0; /* Fail due to malloc failure */
|
if( array.tbl==0 ) return 0; /* Fail due to malloc failure */
|
||||||
array.ht = (x2node**)&(array.tbl[arrSize]);
|
array.ht = (x2node**)&(array.tbl[arrSize]);
|
||||||
for(i=0; i<arrSize; i++) array.ht[i] = 0;
|
for(i=0; i<arrSize; i++) array.ht[i] = 0;
|
||||||
@@ -5571,7 +5646,7 @@ int Symbol_insert(struct symbol *data, const char *key)
|
|||||||
newnp->from = &(array.ht[h]);
|
newnp->from = &(array.ht[h]);
|
||||||
array.ht[h] = newnp;
|
array.ht[h] = newnp;
|
||||||
}
|
}
|
||||||
/* free(x2a->tbl); // This program was originally written for 16-bit
|
/* lemon_free(x2a->tbl); // This program was originally written for 16-bit
|
||||||
** machines. Don't worry about freeing this trivial amount of memory
|
** machines. Don't worry about freeing this trivial amount of memory
|
||||||
** on modern platforms. Just leak it. */
|
** on modern platforms. Just leak it. */
|
||||||
*x2a = array;
|
*x2a = array;
|
||||||
@@ -5632,7 +5707,7 @@ struct symbol **Symbol_arrayof()
|
|||||||
int i,arrSize;
|
int i,arrSize;
|
||||||
if( x2a==0 ) return 0;
|
if( x2a==0 ) return 0;
|
||||||
arrSize = x2a->count;
|
arrSize = x2a->count;
|
||||||
array = (struct symbol **)calloc(arrSize, sizeof(struct symbol *));
|
array = (struct symbol **)lemon_calloc(arrSize, sizeof(struct symbol *));
|
||||||
if( array ){
|
if( array ){
|
||||||
for(i=0; i<arrSize; i++) array[i] = x2a->tbl[i].data;
|
for(i=0; i<arrSize; i++) array[i] = x2a->tbl[i].data;
|
||||||
}
|
}
|
||||||
@@ -5680,7 +5755,7 @@ PRIVATE unsigned statehash(struct config *a)
|
|||||||
struct state *State_new()
|
struct state *State_new()
|
||||||
{
|
{
|
||||||
struct state *newstate;
|
struct state *newstate;
|
||||||
newstate = (struct state *)calloc(1, sizeof(struct state) );
|
newstate = (struct state *)lemon_calloc(1, sizeof(struct state) );
|
||||||
MemoryCheck(newstate);
|
MemoryCheck(newstate);
|
||||||
return newstate;
|
return newstate;
|
||||||
}
|
}
|
||||||
@@ -5713,13 +5788,13 @@ static struct s_x3 *x3a;
|
|||||||
/* Allocate a new associative array */
|
/* Allocate a new associative array */
|
||||||
void State_init(void){
|
void State_init(void){
|
||||||
if( x3a ) return;
|
if( x3a ) return;
|
||||||
x3a = (struct s_x3*)malloc( sizeof(struct s_x3) );
|
x3a = (struct s_x3*)lemon_malloc( sizeof(struct s_x3) );
|
||||||
if( x3a ){
|
if( x3a ){
|
||||||
x3a->size = 128;
|
x3a->size = 128;
|
||||||
x3a->count = 0;
|
x3a->count = 0;
|
||||||
x3a->tbl = (x3node*)calloc(128, sizeof(x3node) + sizeof(x3node*));
|
x3a->tbl = (x3node*)lemon_calloc(128, sizeof(x3node) + sizeof(x3node*));
|
||||||
if( x3a->tbl==0 ){
|
if( x3a->tbl==0 ){
|
||||||
free(x3a);
|
lemon_free(x3a);
|
||||||
x3a = 0;
|
x3a = 0;
|
||||||
}else{
|
}else{
|
||||||
int i;
|
int i;
|
||||||
@@ -5754,7 +5829,7 @@ int State_insert(struct state *data, struct config *key)
|
|||||||
struct s_x3 array;
|
struct s_x3 array;
|
||||||
array.size = arrSize = x3a->size*2;
|
array.size = arrSize = x3a->size*2;
|
||||||
array.count = x3a->count;
|
array.count = x3a->count;
|
||||||
array.tbl = (x3node*)calloc(arrSize, sizeof(x3node) + sizeof(x3node*));
|
array.tbl = (x3node*)lemon_calloc(arrSize, sizeof(x3node)+sizeof(x3node*));
|
||||||
if( array.tbl==0 ) return 0; /* Fail due to malloc failure */
|
if( array.tbl==0 ) return 0; /* Fail due to malloc failure */
|
||||||
array.ht = (x3node**)&(array.tbl[arrSize]);
|
array.ht = (x3node**)&(array.tbl[arrSize]);
|
||||||
for(i=0; i<arrSize; i++) array.ht[i] = 0;
|
for(i=0; i<arrSize; i++) array.ht[i] = 0;
|
||||||
@@ -5770,7 +5845,7 @@ int State_insert(struct state *data, struct config *key)
|
|||||||
newnp->from = &(array.ht[h]);
|
newnp->from = &(array.ht[h]);
|
||||||
array.ht[h] = newnp;
|
array.ht[h] = newnp;
|
||||||
}
|
}
|
||||||
free(x3a->tbl);
|
lemon_free(x3a->tbl);
|
||||||
*x3a = array;
|
*x3a = array;
|
||||||
}
|
}
|
||||||
/* Insert the new data */
|
/* Insert the new data */
|
||||||
@@ -5811,7 +5886,7 @@ struct state **State_arrayof(void)
|
|||||||
int i,arrSize;
|
int i,arrSize;
|
||||||
if( x3a==0 ) return 0;
|
if( x3a==0 ) return 0;
|
||||||
arrSize = x3a->count;
|
arrSize = x3a->count;
|
||||||
array = (struct state **)calloc(arrSize, sizeof(struct state *));
|
array = (struct state **)lemon_calloc(arrSize, sizeof(struct state *));
|
||||||
if( array ){
|
if( array ){
|
||||||
for(i=0; i<arrSize; i++) array[i] = x3a->tbl[i].data;
|
for(i=0; i<arrSize; i++) array[i] = x3a->tbl[i].data;
|
||||||
}
|
}
|
||||||
@@ -5853,13 +5928,13 @@ static struct s_x4 *x4a;
|
|||||||
/* Allocate a new associative array */
|
/* Allocate a new associative array */
|
||||||
void Configtable_init(void){
|
void Configtable_init(void){
|
||||||
if( x4a ) return;
|
if( x4a ) return;
|
||||||
x4a = (struct s_x4*)malloc( sizeof(struct s_x4) );
|
x4a = (struct s_x4*)lemon_malloc( sizeof(struct s_x4) );
|
||||||
if( x4a ){
|
if( x4a ){
|
||||||
x4a->size = 64;
|
x4a->size = 64;
|
||||||
x4a->count = 0;
|
x4a->count = 0;
|
||||||
x4a->tbl = (x4node*)calloc(64, sizeof(x4node) + sizeof(x4node*));
|
x4a->tbl = (x4node*)lemon_calloc(64, sizeof(x4node) + sizeof(x4node*));
|
||||||
if( x4a->tbl==0 ){
|
if( x4a->tbl==0 ){
|
||||||
free(x4a);
|
lemon_free(x4a);
|
||||||
x4a = 0;
|
x4a = 0;
|
||||||
}else{
|
}else{
|
||||||
int i;
|
int i;
|
||||||
@@ -5894,7 +5969,8 @@ int Configtable_insert(struct config *data)
|
|||||||
struct s_x4 array;
|
struct s_x4 array;
|
||||||
array.size = arrSize = x4a->size*2;
|
array.size = arrSize = x4a->size*2;
|
||||||
array.count = x4a->count;
|
array.count = x4a->count;
|
||||||
array.tbl = (x4node*)calloc(arrSize, sizeof(x4node) + sizeof(x4node*));
|
array.tbl = (x4node*)lemon_calloc(arrSize,
|
||||||
|
sizeof(x4node) + sizeof(x4node*));
|
||||||
if( array.tbl==0 ) return 0; /* Fail due to malloc failure */
|
if( array.tbl==0 ) return 0; /* Fail due to malloc failure */
|
||||||
array.ht = (x4node**)&(array.tbl[arrSize]);
|
array.ht = (x4node**)&(array.tbl[arrSize]);
|
||||||
for(i=0; i<arrSize; i++) array.ht[i] = 0;
|
for(i=0; i<arrSize; i++) array.ht[i] = 0;
|
||||||
@@ -5909,9 +5985,6 @@ int Configtable_insert(struct config *data)
|
|||||||
newnp->from = &(array.ht[h]);
|
newnp->from = &(array.ht[h]);
|
||||||
array.ht[h] = newnp;
|
array.ht[h] = newnp;
|
||||||
}
|
}
|
||||||
/* free(x4a->tbl); // This code was originall written for 16-bit machines.
|
|
||||||
** on modern machines, don't worry about freeing this trival amount of
|
|
||||||
** memory. */
|
|
||||||
*x4a = array;
|
*x4a = array;
|
||||||
}
|
}
|
||||||
/* Insert the new data */
|
/* Insert the new data */
|
||||||
|
Reference in New Issue
Block a user