Index: src/expr.c ================================================================== --- src/expr.c +++ src/expr.c @@ -2871,10 +2871,26 @@ if( pDef->funcFlags & SQLITE_FUNC_UNLIKELY ){ assert( nFarg>=1 ); sqlite3ExprCode(pParse, pFarg->a[0].pExpr, target); break; } + + /* The AFFINITY() function returns the type affinity of its argument. + ** The type affinity is a compile-time value, so we might as well + ** code it directly. + */ + if( pDef->funcFlags & SQLITE_FUNC_AFFINITY ){ + int aff; + static const char *const azAffName[] = { + "", "BLOB", "TEXT", "NUMERIC", "INTEGER", "REAL" + }; + assert( nFarg==1 ); + aff = sqlite3ExprAffinity(pFarg->a[0].pExpr); + if( aff ) aff -= SQLITE_AFF_BLOB - 1; + sqlite3VdbeAddOp4(v, OP_String8, 0, target, 0, azAffName[aff], 0); + break; + } for(i=0; ia[i].pExpr) ){ testcase( i==31 ); constMask |= MASKBIT32(i); Index: src/func.c ================================================================== --- src/func.c +++ src/func.c @@ -1715,10 +1715,11 @@ FUNCTION(max, -1, 1, 1, minmaxFunc ), FUNCTION(max, 0, 1, 1, 0 ), AGGREGATE2(max, 1, 1, 1, minmaxStep, minMaxFinalize, SQLITE_FUNC_MINMAX ), FUNCTION2(typeof, 1, 0, 0, typeofFunc, SQLITE_FUNC_TYPEOF), + FUNCTION2(affinity, 1, 0, 0, noopFunc, SQLITE_FUNC_AFFINITY), FUNCTION2(length, 1, 0, 0, lengthFunc, SQLITE_FUNC_LENGTH), FUNCTION(instr, 2, 0, 0, instrFunc ), FUNCTION(substr, 2, 0, 0, substrFunc ), FUNCTION(substr, 3, 0, 0, substrFunc ), FUNCTION(printf, -1, 0, 0, printfFunc ), Index: src/sqliteInt.h ================================================================== --- src/sqliteInt.h +++ src/sqliteInt.h @@ -1346,22 +1346,23 @@ /* ** Possible values for FuncDef.flags. Note that the _LENGTH and _TYPEOF ** values must correspond to OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG. There ** are assert() statements in the code to verify this. */ -#define SQLITE_FUNC_ENCMASK 0x003 /* SQLITE_UTF8, SQLITE_UTF16BE or UTF16LE */ -#define SQLITE_FUNC_LIKE 0x004 /* Candidate for the LIKE optimization */ -#define SQLITE_FUNC_CASE 0x008 /* Case-sensitive LIKE-type function */ -#define SQLITE_FUNC_EPHEM 0x010 /* Ephemeral. Delete with VDBE */ -#define SQLITE_FUNC_NEEDCOLL 0x020 /* sqlite3GetFuncCollSeq() might be called */ -#define SQLITE_FUNC_LENGTH 0x040 /* Built-in length() function */ -#define SQLITE_FUNC_TYPEOF 0x080 /* Built-in typeof() function */ -#define SQLITE_FUNC_COUNT 0x100 /* Built-in count(*) aggregate */ -#define SQLITE_FUNC_COALESCE 0x200 /* Built-in coalesce() or ifnull() */ -#define SQLITE_FUNC_UNLIKELY 0x400 /* Built-in unlikely() function */ -#define SQLITE_FUNC_CONSTANT 0x800 /* Constant inputs give a constant output */ -#define SQLITE_FUNC_MINMAX 0x1000 /* True for min() and max() aggregates */ +#define SQLITE_FUNC_ENCMASK 0x0003 /* SQLITE_UTF8, SQLITE_UTF16BE or UTF16LE */ +#define SQLITE_FUNC_LIKE 0x0004 /* Candidate for the LIKE optimization */ +#define SQLITE_FUNC_CASE 0x0008 /* Case-sensitive LIKE-type function */ +#define SQLITE_FUNC_EPHEM 0x0010 /* Ephemeral. Delete with VDBE */ +#define SQLITE_FUNC_NEEDCOLL 0x0020 /* sqlite3GetFuncCollSeq might be called */ +#define SQLITE_FUNC_LENGTH 0x0040 /* Built-in length() function */ +#define SQLITE_FUNC_TYPEOF 0x0080 /* Built-in typeof() function */ +#define SQLITE_FUNC_COUNT 0x0100 /* Built-in count(*) aggregate */ +#define SQLITE_FUNC_COALESCE 0x0200 /* Built-in coalesce() or ifnull() */ +#define SQLITE_FUNC_UNLIKELY 0x0400 /* Built-in unlikely() function */ +#define SQLITE_FUNC_CONSTANT 0x0800 /* Constant inputs give a constant output */ +#define SQLITE_FUNC_MINMAX 0x1000 /* True for min() and max() aggregates */ +#define SQLITE_FUNC_AFFINITY 0x2000 /* Built-in affinity() function */ /* ** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are ** used to create the initializers for the FuncDef structures. ** ADDED test/affinity1.test Index: test/affinity1.test ================================================================== --- /dev/null +++ test/affinity1.test @@ -0,0 +1,88 @@ +# 2015-06-02 +# +# 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. The +# focus of this file is type affinity and the affinity() built-in +# function. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set ::testprefix affinity1 + +do_execsql_test 100 { + CREATE TABLE t1( + c01 INT, + c02 INTEGER, + c03 TINYINT, + c04 SMALLINT, + c05 MEDIUMINT, + c06 BIGINT, + c07 UNSIGNED BIG INT, + c08 INT2, + c09 INT4, + c10 CHARACTER(20), + c11 VARCHAR(255), + c12 VARYING CHARACTER(255), + c13 NCHAR(55), + c14 NATIVE CHARACTER(70), + c15 NVARCHAR(100), + c16 TEXT, + c17 CLOB, + c20 BLOB, + c21, + c30 REAL, + c31 DOUBLE, + c32 DOUBLE PRECISION, + c33 FLOAT, + c40 NUMERIC, + c41 DECIMAL(10,5), + c42 BOOLEAN, + c43 DATE, + c44 DATETIME, + c50 FLOATING POINT, + c60 STRING + ); + INSERT INTO t1 DEFAULT VALUES; +} {} +do_execsql_test 201 { + SELECT affinity(c01), affinity(c01+1), affinity(+c01) FROM t1; +} {INTEGER {} {}} +do_execsql_test 202 {SELECT affinity(c02) FROM t1} {INTEGER} +do_execsql_test 203 {SELECT affinity(c03) FROM t1} {INTEGER} +do_execsql_test 204 {SELECT affinity(c04) FROM t1} {INTEGER} +do_execsql_test 205 {SELECT affinity(c05) FROM t1} {INTEGER} +do_execsql_test 206 {SELECT affinity(c06) FROM t1} {INTEGER} +do_execsql_test 207 {SELECT affinity(c07) FROM t1} {INTEGER} +do_execsql_test 208 {SELECT affinity(c08) FROM t1} {INTEGER} +do_execsql_test 209 {SELECT affinity(c09) FROM t1} {INTEGER} +do_execsql_test 210 {SELECT affinity(c10) FROM t1} {TEXT} +do_execsql_test 211 {SELECT affinity(c11) FROM t1} {TEXT} +do_execsql_test 212 {SELECT affinity(c12) FROM t1} {TEXT} +do_execsql_test 213 {SELECT affinity(c13) FROM t1} {TEXT} +do_execsql_test 214 {SELECT affinity(c14) FROM t1} {TEXT} +do_execsql_test 215 {SELECT affinity(c15) FROM t1} {TEXT} +do_execsql_test 216 {SELECT affinity(c16) FROM t1} {TEXT} +do_execsql_test 220 {SELECT affinity(c20) FROM t1} {BLOB} +do_execsql_test 221 {SELECT affinity(c21) FROM t1} {BLOB} +do_execsql_test 230 {SELECT affinity(c30) FROM t1} {REAL} +do_execsql_test 231 {SELECT affinity(c31) FROM t1} {REAL} +do_execsql_test 232 {SELECT affinity(c32) FROM t1} {REAL} +do_execsql_test 233 {SELECT affinity(c33) FROM t1} {REAL} +do_execsql_test 240 {SELECT affinity(c40) FROM t1} {NUMERIC} +do_execsql_test 241 {SELECT affinity(c41) FROM t1} {NUMERIC} +do_execsql_test 242 {SELECT affinity(c42) FROM t1} {NUMERIC} +do_execsql_test 243 {SELECT affinity(c43) FROM t1} {NUMERIC} +do_execsql_test 244 {SELECT affinity(c44) FROM t1} {NUMERIC} +do_execsql_test 250 {SELECT affinity(c50) FROM t1} {INTEGER} +do_execsql_test 260 {SELECT affinity(c60) FROM t1} {NUMERIC} + + +finish_test