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:
80
src/func.c
80
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 ),
|
||||
|
Reference in New Issue
Block a user