Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Add support for the CONCAT() and CONCAT_WS() SQL functions, modeled after the PostgreSQL behavior. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
0b434ca7aa19eff4ad134a8c6f88f6a7 |
User & Date: | drh 2023-08-29 15:24:41.645 |
Context
2023-08-29
| ||
15:38 | Change the version number to 3.44.0 to begin the next development cycle. (Should have done this a few check-ins ago.) (check-in: 253fe4a45d user: drh tags: trunk) | |
15:24 | Add support for the CONCAT() and CONCAT_WS() SQL functions, modeled after the PostgreSQL behavior. (check-in: 0b434ca7aa user: drh tags: trunk) | |
10:50 | Change a variable from "int" to "i64" to make it easier to prove that it cannot overflow. (check-in: 00a8b3a263 user: dan tags: trunk) | |
Changes
Changes to src/func.c.
︙ | ︙ | |||
1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 | if( zCharSet ){ sqlite3_free(azChar); } } sqlite3_result_text(context, (char*)zIn, nIn, SQLITE_TRANSIENT); } #ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION /* ** The "unknown" function is automatically substituted in place of ** any unrecognized function name when doing an EXPLAIN or EXPLAIN QUERY PLAN ** when the SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION compile-time option is used. ** When the "sqlite3" command-line shell is built using this functionality, | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 | if( zCharSet ){ sqlite3_free(azChar); } } 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 /* ** The "unknown" function is automatically substituted in place of ** any unrecognized function name when doing an EXPLAIN or EXPLAIN QUERY PLAN ** when the SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION compile-time option is used. ** When the "sqlite3" command-line shell is built using this functionality, |
︙ | ︙ | |||
2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 | FUNCTION(round, 2, 0, 0, roundFunc ), #endif FUNCTION(upper, 1, 0, 0, upperFunc ), FUNCTION(lower, 1, 0, 0, lowerFunc ), FUNCTION(hex, 1, 0, 0, hexFunc ), FUNCTION(unhex, 1, 0, 0, unhexFunc ), FUNCTION(unhex, 2, 0, 0, unhexFunc ), INLINE_FUNC(ifnull, 2, INLINEFUNC_coalesce, 0 ), VFUNCTION(random, 0, 0, 0, randomFunc ), VFUNCTION(randomblob, 1, 0, 0, randomBlob ), FUNCTION(nullif, 2, 0, 1, nullifFunc ), DFUNCTION(sqlite_version, 0, 0, 0, versionFunc ), DFUNCTION(sqlite_source_id, 0, 0, 0, sourceidFunc ), FUNCTION(sqlite_log, 2, 0, 0, errlogFunc ), | > > > > > | 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 | FUNCTION(round, 2, 0, 0, roundFunc ), #endif FUNCTION(upper, 1, 0, 0, upperFunc ), FUNCTION(lower, 1, 0, 0, lowerFunc ), 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 ), FUNCTION(nullif, 2, 0, 1, nullifFunc ), DFUNCTION(sqlite_version, 0, 0, 0, versionFunc ), DFUNCTION(sqlite_source_id, 0, 0, 0, sourceidFunc ), FUNCTION(sqlite_log, 2, 0, 0, errlogFunc ), |
︙ | ︙ |
Added test/func9.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | # 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 |