1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-10-21 11:13:54 +03:00

Add support for the CONCAT() and CONCAT_WS() SQL functions, modeled after

the PostgreSQL behavior.

FossilOrigin-Name: 0b434ca7aa19eff4ad134a8c6f88f6a7ccab88864faa55e93579a2462d8ac3bc
This commit is contained in:
drh
2023-08-29 15:24:41 +00:00
parent b44b802378
commit e1e67abc5c
4 changed files with 129 additions and 8 deletions

View File

@@ -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 ),