CC: | prewittm [...] ms.com |
Subject: | dbd_preparse not ignoring placeholders in comments |
We encountered the 'DBD::ODBC does not yet support binding a named
parameter more than once' error when something that looked like a
placeholder was found in the SQL comments part of a query like this:
/* $Date: 2010/05/01 12:00:00 */
select * from tb
The :00 and :00 were interpreted as placeholders. I looked at
dbd_preparse in dbdimp.c and see why it is happening. It looks like
there is no detection as to whether you are in or outside of a comment.
If you look at the recent versions of dbdimp.c in DBD::Sybase, you'll
see they've added code to detect this this situation and ignore anything
inside line or block comments:
while (*src) {
next_state = state; /* default situation */
while (*src) {
next_state = state; /* default situation */
switch (state) {
case DEFAULT:
if (*src == '\'' || *src == '"') {
last_literal = *src;
next_state = LITERAL;
} else if (*src == '/' && *(src+1) == '*') {
next_state = COMMENT;
} else if (*src == '-' && *(src+1) == '-') {
next_state = LINE_COMMENT;
} else if (*src == '@') {
varname[0] = '@';
pos = 1;
next_state = VARIABLE;
}
break;
case LITERAL:
if (*src == last_literal) {
next_state = DEFAULT;
}
break;
case COMMENT:
if (*(src-1) == '*' && *src == '/') {
next_state = DEFAULT;
}
break;
case LINE_COMMENT:
if (*src == '\n') {
next_state = DEFAULT;
}
break;
case VARIABLE:
if (!isalnum(*src) && *src != '_') {
varname[pos] = 0;
next_state = DEFAULT;
} else if (pos < VARNAME_LEN) {
varname[pos++] = *src;
}
}
It would be great to add this to the ODBC version of dbdimp.c (looks
like it was originally copied from the DBD::Sybase implementation (or a
common base)).