Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions sqlite/src/tokenize.c
Original file line number Diff line number Diff line change
Expand Up @@ -877,6 +877,7 @@ char *sqlite3Normalize_alternate(
int j; /* Bytes of normalized SQL generated so far */
sqlite3_str *pStr; /* The normalized SQL string under construction */
int useStrId = 0; /* Treat string token as identifier */
int isProcedure = 0; /* Non-zero if SQL is an EXEC PROCEDURE statement */

db = pVdbe ? sqlite3VdbeDb(pVdbe) : 0;
tokenType = -1;
Expand All @@ -889,6 +890,14 @@ char *sqlite3Normalize_alternate(
}
n = sqlite3GetToken((unsigned char*)zSql+i, &tokenType);
if( NEVER(n<=0) ) break;

/* If the SQL string is an EXEC PROCEDURE statement and the first "("
** is encountered, append "()" and stop parsing */
if (isProcedure && tokenType == TK_LP && nParen == 0) {
sqlite3_str_append(pStr, "()", 2);
break;
}

switch( tokenType ){
case TK_SPACE: {
break;
Expand Down Expand Up @@ -995,6 +1004,12 @@ char *sqlite3Normalize_alternate(
iStartIN = 0;
/* fall through */
}
case TK_PROCEDURE: {
if (prevType == TK_EXECUTE || prevType == TK_EXEC) {
isProcedure = 1;
}
/* fall through */
}
default: {
if( sqlite3IsIdChar(zSql[i]) ) addSpaceSeparator(pStr);
j = pStr->nChar;
Expand Down Expand Up @@ -1037,6 +1052,9 @@ char *sqlite3Normalize(
int nParenAtIN; /* Value of nParent at start of RHS of IN operator */
int j; /* Bytes of normalized SQL generated so far */
sqlite3_str *pStr; /* The normalized SQL string under construction */
#if defined(SQLITE_BUILDING_FOR_COMDB2)
int isProcedure = 0; /* Non-zero if SQL is an EXEC PROCEDURE statement */
#endif /* defined(SQLITE_BUILDING_FOR_COMDB2) */

#if defined(SQLITE_BUILDING_FOR_COMDB2)
db = pVdbe ? sqlite3VdbeDb(pVdbe) : 0;
Expand All @@ -1053,6 +1071,14 @@ char *sqlite3Normalize(
}
n = sqlite3GetToken((unsigned char*)zSql+i, &tokenType);
if( NEVER(n<=0) ) break;
#if defined(SQLITE_BUILDING_FOR_COMDB2)
/* If the SQL string is executing a procedure and the first "("
is encountered, append "()" and stop parsing */
if (isProcedure && tokenType == TK_LP && nParen == 0) {
sqlite3_str_append(pStr, "()", 2);
break;
}
#endif /* defined(SQLITE_BUILDING_FOR_COMDB2) */
switch( tokenType ){
case TK_SPACE: {
break;
Expand Down Expand Up @@ -1143,6 +1169,14 @@ char *sqlite3Normalize(
iStartIN = 0;
/* fall through */
}
#if defined(SQLITE_BUILDING_FOR_COMDB2)
case TK_PROCEDURE: {
if (prevType == TK_EXECUTE || prevType == TK_EXEC) {
isProcedure = 1;
}
/* fall through */
}
#endif /* defined(SQLITE_BUILDING_FOR_COMDB2) */
default: {
if( sqlite3IsIdChar(zSql[i]) ) addSpaceSeparator(pStr);
j = pStr->nChar;
Expand Down
2 changes: 1 addition & 1 deletion tests/fingerprints.test/README
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ result set (i.e. via the WHERE clause):

4f16a8ec9db90f803e406659938b2602: "SELECT 1" ==> "SELECT?;"
69d1558c950bbb908f4b8df0d63e2cf4: "SELECT comdb2_host();"
812bdde365a22a61bcd52bf005990c37: "EXEC PROCEDURE sys.cmd.send(?);"
ba65a98635122c91120d37676cbfc1ef: "EXEC PROCEDURE sys.cmd.send();"

The corresponding SQL statements are excluded because these are (sometimes?)
used by the test suite itself at various stages. Since the exact quantity
Expand Down
2 changes: 1 addition & 1 deletion tests/fingerprints.test/t03.req
Original file line number Diff line number Diff line change
@@ -1 +1 @@
SELECT fingerprint, count, total_cost, total_rows, normalized_sql FROM comdb2_fingerprints WHERE fingerprint NOT IN ('4f16a8ec9db90f803e406659938b2602', '69d1558c950bbb908f4b8df0d63e2cf4', '812bdde365a22a61bcd52bf005990c37') ORDER BY fingerprint;
SELECT fingerprint, count, total_cost, total_rows, normalized_sql FROM comdb2_fingerprints WHERE fingerprint NOT IN ('4f16a8ec9db90f803e406659938b2602', '69d1558c950bbb908f4b8df0d63e2cf4', 'ba65a98635122c91120d37676cbfc1ef') ORDER BY fingerprint;
33 changes: 33 additions & 0 deletions tests/fingerprints.test/t09.req
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
-- Create a dummy procedure
CREATE PROCEDURE fp_proc VERSION 'test' {local function main() end}$$

-- Call it with different argument counts
EXEC PROCEDURE fp_proc()
EXEC PROCEDURE fp_proc(1)
EXEC PROCEDURE fp_proc(1,2,3)
EXEC PROCEDURE fp_proc(1, 'hello', x'DEADBEEF', 3.14, NULL)
EXECUTE PROCEDURE fp_proc('a','b','c',4,5,6)
EXECUTE PROCEDURE fp_proc('()','fun()')
EXECUTE PROCEDURE fp_proc('-47', '1', x'DEADBEEF')

-- Call with bound parameters
@bind CDB2_INTEGER myint 42
EXEC PROCEDURE fp_proc(@myint)
@bind CDB2_CSTRING mystr hello
@bind CDB2_INTEGER myint 99
EXEC PROCEDURE fp_proc(@myint, @mystr)
@bind CDB2_REAL myreal 2.718
@bind CDB2_INTEGER myint 1
@bind CDB2_CSTRING mystr world
EXEC PROCEDURE fp_proc(@myint, @mystr, @myreal)

-- Mix bound parameters with literals
@bind CDB2_INTEGER myint 7
EXEC PROCEDURE fp_proc(@myint, 'literal', 3.14, NULL)

-- Syntax error but still has the same fingerprint
EXEC PROCEDURE fp_proc(fun())

-- All should produce the same fingerprint
SELECT COUNT(DISTINCT fingerprint) as 'unique_fps' FROM comdb2_fingerprints WHERE normalized_sql LIKE 'EXEC PROCEDURE fp_proc%'
SELECT normalized_sql FROM comdb2_fingerprints WHERE normalized_sql LIKE 'EXEC PROCEDURE fp_proc%'
4 changes: 4 additions & 0 deletions tests/fingerprints.test/t09.req.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
(version='test')
[EXEC PROCEDURE fp_proc(fun())] failed with rc -3 bad argument -> fun())
(unique_fps=1)
(normalized_sql='EXEC PROCEDURE fp_proc();')