aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--VERSION2
-rwxr-xr-xconfigure18
-rw-r--r--ext/fts5/fts5_index.c2
-rw-r--r--ext/wasm/api/sqlite3-api-prologue.js6
-rw-r--r--manifest29
-rw-r--r--manifest.uuid2
-rw-r--r--src/date.c51
-rw-r--r--src/func.c80
-rw-r--r--src/test1.c36
-rw-r--r--test/date.test24
-rw-r--r--test/date4.test38
-rw-r--r--test/func9.test40
12 files changed, 289 insertions, 39 deletions
diff --git a/VERSION b/VERSION
index a9184766b..faf0dcbb0 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-3.43.0
+3.44.0
diff --git a/configure b/configure
index 6b0c584a4..e5aa01944 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for sqlite 3.43.0.
+# Generated by GNU Autoconf 2.69 for sqlite 3.44.0.
#
#
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@ -726,8 +726,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='sqlite'
PACKAGE_TARNAME='sqlite'
-PACKAGE_VERSION='3.43.0'
-PACKAGE_STRING='sqlite 3.43.0'
+PACKAGE_VERSION='3.44.0'
+PACKAGE_STRING='sqlite 3.44.0'
PACKAGE_BUGREPORT=''
PACKAGE_URL=''
@@ -1470,7 +1470,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures sqlite 3.43.0 to adapt to many kinds of systems.
+\`configure' configures sqlite 3.44.0 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1535,7 +1535,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of sqlite 3.43.0:";;
+ short | recursive ) echo "Configuration of sqlite 3.44.0:";;
esac
cat <<\_ACEOF
@@ -1665,7 +1665,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-sqlite configure 3.43.0
+sqlite configure 3.44.0
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2084,7 +2084,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by sqlite $as_me 3.43.0, which was
+It was created by sqlite $as_me 3.44.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -12457,7 +12457,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by sqlite $as_me 3.43.0, which was
+This file was extended by sqlite $as_me 3.44.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -12523,7 +12523,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-sqlite config.status 3.43.0
+sqlite config.status 3.44.0
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c
index 267489a7e..1b3f0fef9 100644
--- a/ext/fts5/fts5_index.c
+++ b/ext/fts5/fts5_index.c
@@ -3272,7 +3272,7 @@ static Fts5Iter *fts5MultiIterAlloc(
int nSeg
){
Fts5Iter *pNew;
- int nSlot; /* Power of two >= nSeg */
+ i64 nSlot; /* Power of two >= nSeg */
for(nSlot=2; nSlot<nSeg; nSlot=nSlot*2);
pNew = fts5IdxMalloc(p,
diff --git a/ext/wasm/api/sqlite3-api-prologue.js b/ext/wasm/api/sqlite3-api-prologue.js
index 996f23298..ef1154f6b 100644
--- a/ext/wasm/api/sqlite3-api-prologue.js
+++ b/ext/wasm/api/sqlite3-api-prologue.js
@@ -1560,15 +1560,15 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
};
/**
+ Converts SQL input from a variety of convenient formats
+ to plain strings.
+
If v is a string, it is returned as-is. If it is-a Array, its
join("") result is returned. If is is a Uint8Array, Int8Array,
or ArrayBuffer, it is assumed to hold UTF-8-encoded text and is
decoded to a string. If it looks like a WASM pointer,
wasm.cstrToJs(sql) is returned. Else undefined is returned.
- The intent of this function is to convert SQL input text from a
- variety of common forms to plain strings.
-
Added in 3.44
*/
capi.sqlite3_js_sql_to_string = (sql)=>{
diff --git a/manifest b/manifest
index 15a2c4be2..9dffaa660 100644
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Add\sa\sUI,\sof\ssorts,\sto\sthe\sJS\sSQLTester.
-D 2023-08-30T11:54:43.323
+C Add\sa\sJS\simplementation\sof\sJava's\sSQLTester.
+D 2023-08-30T13:07:35.058
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -7,7 +7,7 @@ F Makefile.in 345a8599cf8ff015db534cedad7af70a1a6c36e295b85d720966c18af836ed30
F Makefile.linux-gcc f3842a0b1efbfbb74ac0ef60e56b301836d05b4d867d014f714fa750048f1ab6
F Makefile.msc 26c2d196391a285c279adb10fd6001774d9b243af94b700b681e4a49cd476684
F README.md 963d30019abf0cc06b263cd2824bce022893f3f93a531758f6f04ff2194a16a8
-F VERSION c6366dc72582d3144ce87b013cc35fe48d62f6d07d5be0c9716ea33c862144aa
+F VERSION 4c09b629c03b8ae32317cb336a32f3aa3252841d6dcd51184cecc4278d08f21e
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90
@@ -33,7 +33,7 @@ F autoconf/tea/win/nmakehlp.c b01f822eabbe1ed2b64e70882d97d48402b42d2689a1ea0034
F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63
F config.guess 883205ddf25b46f10c181818bf42c09da9888884af96f79e1719264345053bd6
F config.sub c2d0260f17f3e4bc0b6808fccf1b291cb5e9126c14fc5890efc77b9fd0175559
-F configure 9dc3300339f4d6b3c3b108de60cc6ae6b3c547e25c7e6df280b4775db4de3a1b x
+F configure 550c90a234b3d4ae80919e3c0a0bf0e6f34e4288eb613d7c71375714162a5038 x
F configure.ac 4654d32ac0a0d0b48f1e1e79bdc3d777b723cf2f63c33eb1d7c4ed8b435938e8
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
F doc/F2FS.txt c1d4a0ae9711cfe0e1d8b019d154f1c29e0d3abfe820787ba1e9ed7691160fcd
@@ -94,7 +94,7 @@ F ext/fts5/fts5_buffer.c 3001fbabb585d6de52947b44b455235072b741038391f830d6b7292
F ext/fts5/fts5_config.c 054359543566cbff1ba65a188330660a5457299513ac71c53b3a07d934c7b081
F ext/fts5/fts5_expr.c bd3b81ce669c4104e34ffe66570af1999a317b142c15fccb112de9fb0caa57a6
F ext/fts5/fts5_hash.c 65e7707bc8774706574346d18c20218facf87de3599b995963c3e6d6809f203d
-F ext/fts5/fts5_index.c b484322421cbb421d22bb2cd304001b80596d671cd626367c8c806b889de4b42
+F ext/fts5/fts5_index.c 77bd70d50cb8397f3d8465cc4894dcdac75aa5e1fb3bbc5a4a5bc15e12fced97
F ext/fts5/fts5_main.c 7070031993ba5b5d89b13206ec4ef624895f2f7c0ec72725913d301e4d382445
F ext/fts5/fts5_storage.c 3c9b41fce41b6410f2e8f82eb035c6a29b2560483f773e6dc98cf3cb2e4ddbb5
F ext/fts5/fts5_tcl.c b1445cbe69908c411df8084a10b2485500ac70a9c747cdc8cda175a3da59d8ae
@@ -565,7 +565,7 @@ F ext/wasm/api/pre-js.c-pp.js ad906703f7429590f2fbf5e6498513bf727a1a4f0ebfa057af
F ext/wasm/api/sqlite3-api-cleanup.js d235ad237df6954145404305040991c72ef8b1881715d2a650dda7b3c2576d0e
F ext/wasm/api/sqlite3-api-glue.js b65e546568f1dfb35205b9792feb5146a6323d71b55cda58e2ed30def6dd52f3
F ext/wasm/api/sqlite3-api-oo1.js 9678dc4d9a5d39632b6ffe6ea94a023119260815bf32f265bf5f6c36c9516db8
-F ext/wasm/api/sqlite3-api-prologue.js 723908946bd624d367e4df7093e9a6c9725606dc526953ea601cad8d7ce88538
+F ext/wasm/api/sqlite3-api-prologue.js 9aeba7b45cf41b3a26d34d7fb2525633cd1adfc544888c1ea8dbb077496f4ce9
F ext/wasm/api/sqlite3-api-worker1.js 9f32af64df1a031071912eea7a201557fe39b1738645c0134562bb84e88e2fec
F ext/wasm/api/sqlite3-license-version-header.js 0c807a421f0187e778dc1078f10d2994b915123c1223fe752b60afdcd1263f89
F ext/wasm/api/sqlite3-opfs-async-proxy.js 8cf8a897726f14071fae6be6648125162b256dfb4f96555b865dbb7a6b65e379
@@ -651,14 +651,14 @@ F src/build.c a8ae3b32d9aa9bbd2c0e97d7c0dd80def9fbca408425de1608f57ee6f47f45f4
F src/callback.c db3a45e376deff6a16c0058163fe0ae2b73a2945f3f408ca32cf74960b28d490
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/ctime.c db847fac81837ff5e5028a5f7505147ac645ae676104adc5bc08e356f243de40
-F src/date.c f73f203b3877cef866c60ab402aec2bf89597219b60635cf50cbe3c5e4533e94
+F src/date.c eebc54a00e888d3c56147779e9f361b77d62fd69ff2008c5373946aa1ba1d574
F src/dbpage.c f3eea5f7ec47e09ee7da40f42b25092ecbe961fc59566b8e5f705f34335b2387
F src/dbstat.c ec92074baa61d883de58c945162d9e666c13cd7cf3a23bc38b4d1c4d0b2c2bef
F src/delete.c cb766727c78e715f9fb7ec8a7d03658ed2a3016343ca687acfcec9083cdca500
F src/expr.c 1affe0cc049683ef0ef3545d9b6901508556b0ef7e2892a344c3df6d7288d79d
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c a7fcbf7e66d14dbb73cf49f31489ebf66d0e6006c62b95246924a3bae9f37b36
-F src/func.c f480d46974ecc84fefdd429377158981b974e0e33d656f1b0e919ba7c4bdd390
+F src/func.c c96c7f55b97493ce278937e6ab6578a866b7e5d6dd486d58b220e9d17e88a750
F src/global.c 29f56a330ed9d1b5cd9b79ac0ca36f97ac3afc730ff8bfa987b0db9e559d684d
F src/hash.c 9ee4269fb1d6632a6fecfb9479c93a1f29271bddbbaf215dd60420bcb80c7220
F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51
@@ -715,7 +715,7 @@ F src/sqliteLimit.h 33b1c9baba578d34efe7dfdb43193b366111cdf41476b1e82699e14c11ee
F src/status.c 160c445d7d28c984a0eae38c144f6419311ed3eace59b44ac6dafc20db4af749
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
F src/tclsqlite.c ecbc3c99c0d0c3ed122a913f143026c26d38d57f33e06bb71185dd5c1efe37cd
-F src/test1.c ebba2473874a23add4a10881b90bd445cfa7f59f90749434938aec14239c6486
+F src/test1.c 57bd144d022ed1356ae5238110beb251e79b0db5cc1ec44ef5b2f44306adb75f
F src/test2.c 54520d0565ef2b9bf0f8f1dcac43dc4d06baf4ffe13d10905f8d8c3ad3e4b9ab
F src/test3.c e5178558c41ff53236ae0271e9acb3d6885a94981d2eb939536ee6474598840e
F src/test4.c 4533b76419e7feb41b40582554663ed3cd77aaa54e135cf76b3205098cd6e664
@@ -995,9 +995,10 @@ F test/ctime.test 340f362f41f92972bbd71f44e10569a5cc694062b692231bd08aa6fe6c1c47
F test/cursorhint.test 05cf0febe5c5f8a31f199401fd1c9322249e753950d55f26f9d5aca61408a270
F test/cursorhint2.test 6f3aa9cb19e7418967a10ec6905209bcbb5968054da855fc36c8beee9ae9c42f
F test/dataversion1.test 6e5e86ac681f0782e766ebcb56c019ae001522d114e0e111e5ebf68ccf2a7bb8
-F test/date.test 1d44557f668298b10d3335b22ab8feb133267b67ec4d85538908fe4dfebd2611
+F test/date.test c0d17cdfd89395bc78087b131e3538d96f864b5029c335318011accc7c0d0934
F test/date2.test 7e12ec14aaf4d5e6294b4ba140445b0eca06ea50062a9c3a69c4ee13d0b6f8b1
F test/date3.test a1b77abf05c6772fe5ca2337cac1398892f2a41e62bce7e6be0f4a08a0e64ae5
+F test/date4.test db9e5760cf6f480fcf36bb7ca8e215880ff44354a31be6fb3d7e58f9d2e057e9
F test/dbdata.test 042f49acff3438f940eeba5868d3af080ae64ddf26ae78f80c92bec3ca7d8603
F test/dbfuzz.c 73047c920d6210e5912c87cdffd9a1c281d4252e
F test/dbfuzz001.test 55e1a3504f8dea84155e09912fe3b1c3ad77e0b1a938ec42ca03b8e51b321e30
@@ -1185,6 +1186,7 @@ F test/func5.test 863e6d1bd0013d09c17236f8a13ea34008dd857d87d85a13a673960e4c25d8
F test/func6.test 9cc9b1f43b435af34fe1416eb1e318c8920448ea7a6962f2121972f5215cb9b0
F test/func7.test adbfc910385a6ffd15dc47be3c619ef070c542fcb7488964badb17b2d9a4d080
F test/func8.test c4e2ecacf9f16e47a245e7a25fbabcc7e78f9c7c41a80f158527cdfdc6dd299d
+F test/func9.test b32d313f679aa9698d52f39519d301c3941823cb72b4e23406c210eadd82c824
F test/fuzz-oss1.test 514dcabb24687818ea949fa6760229eaacad74ca70157743ef36d35bbe01ffb0
F test/fuzz.test 4608c1310cff4c3014a84bcced6278139743e080046e5f6784b0de7b069371d8
F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1
@@ -2113,8 +2115,9 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P bb08ba020ce1d86ca6aa92f43d5ae915f67d08fa73120e1f603d150e76166624
-R 8240e3c6439a4fca46c74a72b36ea777
+P 058722b2d0b995195a8ce3effe9722ae1c18cb1e7a520b481030da0bd579fe41 249e82b9917ea47c56ee1cbd3345a977d335fd3fc0d67a1ef157813ef4571c7c
+R 1d37ca9b2e6614cb5d02f3816f204e9d
+T +closed 249e82b9917ea47c56ee1cbd3345a977d335fd3fc0d67a1ef157813ef4571c7c Closed\sby\sintegrate-merge.
U stephan
-Z cef4bceac8cb673301c00562148f0e5f
+Z 4d7d0ed957593edddd1409081f78edf6
# Remove this line to create a well-formed Fossil manifest.
diff --git a/manifest.uuid b/manifest.uuid
index a0ecd6b9d..0edb46a86 100644
--- a/manifest.uuid
+++ b/manifest.uuid
@@ -1 +1 @@
-249e82b9917ea47c56ee1cbd3345a977d335fd3fc0d67a1ef157813ef4571c7c \ No newline at end of file
+b530792a514d95c4e8f93cf2170d9fc4de367055fa1704fc171551c946024fa9 \ No newline at end of file
diff --git a/src/date.c b/src/date.c
index 648cdeb88..f16308544 100644
--- a/src/date.c
+++ b/src/date.c
@@ -1270,13 +1270,16 @@ static void strftimeFunc(
computeJD(&x);
computeYMD_HMS(&x);
for(i=j=0; zFmt[i]; i++){
+ char cf;
if( zFmt[i]!='%' ) continue;
if( j<i ) sqlite3_str_append(&sRes, zFmt+j, (int)(i-j));
i++;
j = i + 1;
- switch( zFmt[i] ){
- case 'd': {
- sqlite3_str_appendf(&sRes, "%02d", x.D);
+ cf = zFmt[i];
+ switch( cf ){
+ case 'd': /* Fall thru */
+ case 'e': {
+ sqlite3_str_appendf(&sRes, cf=='d' ? "%02d" : "%2d", x.D);
break;
}
case 'f': {
@@ -1285,8 +1288,21 @@ static void strftimeFunc(
sqlite3_str_appendf(&sRes, "%06.3f", s);
break;
}
- case 'H': {
- sqlite3_str_appendf(&sRes, "%02d", x.h);
+ case 'F': {
+ sqlite3_str_appendf(&sRes, "%04d-%02d-%02d", x.Y, x.M, x.D);
+ break;
+ }
+ case 'H':
+ case 'k': {
+ sqlite3_str_appendf(&sRes, cf=='H' ? "%02d" : "%2d", x.h);
+ break;
+ }
+ case 'I': /* Fall thru */
+ case 'l': {
+ int h = x.h;
+ if( h>12 ) h -= 12;
+ if( h==0 ) h = 12;
+ sqlite3_str_appendf(&sRes, cf=='I' ? "%02d" : "%2d", h);
break;
}
case 'W': /* Fall thru */
@@ -1298,7 +1314,7 @@ static void strftimeFunc(
y.D = 1;
computeJD(&y);
nDay = (int)((x.iJD-y.iJD+43200000)/86400000);
- if( zFmt[i]=='W' ){
+ if( cf=='W' ){
int wd; /* 0=Monday, 1=Tuesday, ... 6=Sunday */
wd = (int)(((x.iJD+43200000)/86400000)%7);
sqlite3_str_appendf(&sRes,"%02d",(nDay+7-wd)/7);
@@ -1319,6 +1335,19 @@ static void strftimeFunc(
sqlite3_str_appendf(&sRes,"%02d",x.m);
break;
}
+ case 'p': /* Fall thru */
+ case 'P': {
+ if( x.h>=12 ){
+ sqlite3_str_append(&sRes, cf=='p' ? "PM" : "pm", 2);
+ }else{
+ sqlite3_str_append(&sRes, cf=='p' ? "AM" : "am", 2);
+ }
+ break;
+ }
+ case 'R': {
+ sqlite3_str_appendf(&sRes, "%02d:%02d", x.h, x.m);
+ break;
+ }
case 's': {
if( x.useSubsec ){
sqlite3_str_appendf(&sRes,"%.3f",
@@ -1333,9 +1362,15 @@ static void strftimeFunc(
sqlite3_str_appendf(&sRes,"%02d",(int)x.s);
break;
}
+ case 'T': {
+ sqlite3_str_appendf(&sRes,"%02d:%02d:%02d", x.h, x.m, (int)x.s);
+ break;
+ }
+ case 'u': /* Fall thru */
case 'w': {
- sqlite3_str_appendchar(&sRes, 1,
- (char)(((x.iJD+129600000)/86400000) % 7) + '0');
+ char c = (char)(((x.iJD+129600000)/86400000) % 7) + '0';
+ if( c=='0' && cf=='u' ) c = '7';
+ sqlite3_str_appendchar(&sRes, 1, c);
break;
}
case 'Y': {
diff --git a/src/func.c b/src/func.c
index 70fda8592..333252348 100644
--- a/src/func.c
+++ b/src/func.c
@@ -1550,6 +1550,81 @@ static void trimFunc(
sqlite3_result_text(context, (char*)zIn, nIn, SQLITE_TRANSIENT);
}
+/* The core implementation of the CONCAT(...) and CONCAT_WS(SEP,...)
+** functions.
+**
+** Return a string value that is the concatenation of all non-null
+** entries in argv[]. Use zSep as the separator.
+*/
+static void concatFuncCore(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv,
+ int nSep,
+ const char *zSep
+){
+ i64 j, k, n = 0;
+ int i;
+ char *z;
+ for(i=0; i<argc; i++){
+ n += sqlite3_value_bytes(argv[i]);
+ }
+ n += (argc-1)*nSep;
+ z = sqlite3_malloc64(n+1);
+ if( z==0 ){
+ sqlite3_result_error_nomem(context);
+ return;
+ }
+ j = 0;
+ for(i=0; i<argc; i++){
+ k = sqlite3_value_bytes(argv[i]);
+ if( k>0 ){
+ const char *v = (const char*)sqlite3_value_text(argv[i]);
+ if( ALWAYS(v!=0) ){
+ if( j>0 && nSep>0 ){
+ memcpy(&z[j], zSep, nSep);
+ j += nSep;
+ }
+ memcpy(&z[j], v, k);
+ j += k;
+ }
+ }
+ }
+ z[j] = 0;
+ assert( j<=n );
+ sqlite3_result_text64(context, z, n, sqlite3_free, SQLITE_UTF8);
+}
+
+/*
+** The CONCAT(...) function. Generate a string result that is the
+** concatentation of all non-null arguments.
+*/
+static void concatFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ concatFuncCore(context, argc, argv, 0, "");
+}
+
+/*
+** The CONCAT_WS(separator, ...) function.
+**
+** Generate a string that is the concatenation of 2nd through the Nth
+** argument. Use the first argument (which must be non-NULL) as the
+** separator.
+*/
+static void concatwsFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ int nSep = sqlite3_value_bytes(argv[0]);
+ const char *zSep = (const char*)sqlite3_value_text(argv[0]);
+ if( zSep==0 ) return;
+ concatFuncCore(context, argc-1, argv+1, nSep, zSep);
+}
+
#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
/*
@@ -2559,6 +2634,11 @@ void sqlite3RegisterBuiltinFunctions(void){
FUNCTION(hex, 1, 0, 0, hexFunc ),
FUNCTION(unhex, 1, 0, 0, unhexFunc ),
FUNCTION(unhex, 2, 0, 0, unhexFunc ),
+ FUNCTION(concat, -1, 0, 0, concatFunc ),
+ FUNCTION(concat, 0, 0, 0, 0 ),
+ FUNCTION(concat_ws, -1, 0, 0, concatwsFunc ),
+ FUNCTION(concat_ws, 0, 0, 0, 0 ),
+ FUNCTION(concat_ws, 1, 0, 0, 0 ),
INLINE_FUNC(ifnull, 2, INLINEFUNC_coalesce, 0 ),
VFUNCTION(random, 0, 0, 0, randomFunc ),
VFUNCTION(randomblob, 1, 0, 0, randomBlob ),
diff --git a/src/test1.c b/src/test1.c
index 4dcf7bc11..145882f08 100644
--- a/src/test1.c
+++ b/src/test1.c
@@ -7580,6 +7580,41 @@ static int testLocaltime(const void *aliasT, void *aliasTM){
}
/*
+** TCLCMD: strftime FORMAT UNIXTIMESTAMP
+**
+** Access to the C-library strftime() routine, so that its results
+** can be compared against SQLite's internal strftime() SQL function
+** implementation.
+*/
+static int SQLITE_TCLAPI strftime_cmd(
+ void * clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *CONST objv[]
+){
+ Tcl_WideInt ts;
+ time_t t;
+ struct tm *pTm;
+ const char *zFmt;
+ size_t n;
+ char zBuf[1000];
+ if( objc!=3 ){
+ Tcl_WrongNumArgs(interp, 1, objv, "FORMAT UNIXTIMESTAMP");
+ return TCL_ERROR;
+ }
+ if( Tcl_GetWideIntFromObj(interp, objv[2], &ts) ) return TCL_ERROR;
+ zFmt = Tcl_GetString(objv[1]);
+ t = (time_t)ts;
+ pTm = gmtime(&t);
+ n = strftime(zBuf, sizeof(zBuf)-1, zFmt, pTm);
+ if( n>=0 && n<sizeof(zBuf) ){
+ zBuf[n] = 0;
+ Tcl_SetResult(interp, zBuf, TCL_VOLATILE);
+ }
+ return TCL_OK;
+}
+
+/*
** .treetrace N
*/
static int SQLITE_TCLAPI test_treetrace(
@@ -9152,6 +9187,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
#ifndef SQLITE_OMIT_EXPLAIN
{ "print_explain_query_plan", test_print_eqp, 0 },
#endif
+ { "strftime", strftime_cmd },
{ "sqlite3_test_control", test_test_control },
{ ".treetrace", test_treetrace },
#if SQLITE_OS_UNIX
diff --git a/test/date.test b/test/date.test
index 3e9318189..fb76dac8a 100644
--- a/test/date.test
+++ b/test/date.test
@@ -207,15 +207,33 @@ datetest 3.16 "strftime('[repeat 200 %Y]','2003-10-31')" [repeat 200 2003]
datetest 3.17 "strftime('[repeat 200 abc%m123]','2003-10-31')" \
[repeat 200 abc10123]
-foreach c {a b c e g h i k l n o p q r t v x y z
- A B C D E F G I K L N O P Q R T U V Z
+foreach c {a b c g h i n o q r t v x y z
+ A B C D E G K L N O Q V Z
0 1 2 3 4 5 6 6 7 9 _} {
datetest 3.18.$c "strftime('%$c','2003-10-31')" NULL
}
+datetest 3.20 {strftime('%e','2023-08-09')} { 9}
+datetest 3.21 {strftime('%F %T','2023-08-09 01:23')} {2023-08-09 01:23:00}
+datetest 3.22 {strftime('%k','2023-08-09 04:59:59')} { 4}
+datetest 3.23 {strftime('%I%P','2023-08-09 11:59:59')} {11am}
+datetest 3.24 {strftime('%I%p','2023-08-09 12:00:00')} {12PM}
+datetest 3.25 {strftime('%I%P','2023-08-09 12:59:59.9')} {12pm}
+datetest 3.26 {strftime('%I%p','2023-08-09 13:00:00')} {01PM}
+datetest 3.27 {strftime('%I%P','2023-08-09 23:59:59')} {11pm}
+datetest 3.28 {strftime('%I%p','2023-08-09 00:00:00')} {12AM}
+datetest 3.29 {strftime('%l:%M%P','2023-08-09 13:00:00')} { 1:00pm}
+datetest 3.30 {strftime('%F %R','2023-08-09 12:34:56')} {2023-08-09 12:34}
+datetest 3.31 {strftime('%w %u','2023-01-01')} {0 7}
+datetest 3.32 {strftime('%w %u','2023-01-02')} {1 1}
+datetest 3.33 {strftime('%w %u','2023-01-03')} {2 2}
+datetest 3.34 {strftime('%w %u','2023-01-04')} {3 3}
+datetest 3.35 {strftime('%w %u','2023-01-05')} {4 4}
+datetest 3.36 {strftime('%w %u','2023-01-06')} {5 5}
+datetest 3.37 {strftime('%w %u','2023-01-07')} {6 6}
# Ticket #2276. Make sure leading zeros are inserted where appropriate.
#
-datetest 3.20 \
+datetest 3.40 \
{strftime('%d/%f/%H/%W/%j/%m/%M/%S/%Y','0421-01-02 03:04:05.006')} \
02/05.006/03/00/002/01/04/05/0421
diff --git a/test/date4.test b/test/date4.test
new file mode 100644
index 000000000..5da9906bf
--- /dev/null
+++ b/test/date4.test
@@ -0,0 +1,38 @@
+# 2023-08-29
+#
+# 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.
+#
+#***********************************************************************
+#
+# Test cases for the strftime() SQL function. Comparisons against the
+# C-library strftime() function.
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# Skip this whole file if date and time functions are omitted
+# at compile-time
+#
+ifcapable {!datetime} {
+ finish_test
+ return
+}
+
+if {$tcl_platform(os)=="Linux"} {
+ set FMT {%d,%e,%F,%H,%k,%I,%l,%j,%m,%M,%u,%w,%W,%Y,%%,%P,%p}
+} else {
+ set FMT {%d,%e,%F,%H,%I,%j,%p,%R,%u,%w,%W,%%}
+}
+for {set i 0} {$i<=86400} {incr i} {
+ set TS [expr {$i*86401}]
+ do_execsql_test date4-$i {
+ SELECT strftime($::FMT,$::TS,'unixepoch');
+ } [list [strftime $FMT $TS]]
+}
+
+finish_test
diff --git a/test/func9.test b/test/func9.test
new file mode 100644
index 000000000..6cf9fc31e
--- /dev/null
+++ b/test/func9.test
@@ -0,0 +1,40 @@
+# 2023-08-29
+#
+# 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.
+#
+#*************************************************************************
+#
+# Test cases for SQL newer functions
+#
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+do_execsql_test func9-100 {
+ SELECT concat('abc',123,null,'xyz');
+} {abc123xyz}
+do_execsql_test func9-110 {
+ SELECT typeof(concat(null));
+} {text}
+do_catchsql_test func9-120 {
+ SELECT concat();
+} {1 {wrong number of arguments to function concat()}}
+do_execsql_test func9-130 {
+ SELECT concat_ws(',',1,2,3,4,5,6,7,8,NULL,9,10,11,12);
+} {1,2,3,4,5,6,7,8,9,10,11,12}
+do_execsql_test func9-140 {
+ SELECT concat_ws(NULL,1,2,3,4,5,6,7,8,NULL,9,10,11,12);
+} {{}}
+do_catchsql_test func9-150 {
+ SELECT concat_ws();
+} {1 {wrong number of arguments to function concat_ws()}}
+do_catchsql_test func9-160 {
+ SELECT concat_ws(',');
+} {1 {wrong number of arguments to function concat_ws()}}
+
+
+finish_test