Modified:
trunk/ChangeLog
trunk/driver/catalog.c
trunk/driver/myutil.h
trunk/driver/utility.c
trunk/test/my_catalog.c
Log:
MyODBC Crystal Reports can't connect to a tbl if a field name has a single quote (Bug
#32989)
Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog 2008-03-11 13:17:54 UTC (rev 1056)
+++ trunk/ChangeLog 2008-03-11 13:59:45 UTC (rev 1057)
@@ -23,6 +23,8 @@
* An SQLSTATE of HY000 was returned when a stored procedure was not found,
instead of 42000. This caused problems with ADO's adCmdUnknown option.
(Bug #27158)
+ * MyODBC Crystal Reports can't connect to a tbl if a field name has a
+ single quote. (Bug #32989)
----
Modified: trunk/driver/catalog.c
===================================================================
--- trunk/driver/catalog.c 2008-03-11 13:17:54 UTC (rev 1056)
+++ trunk/driver/catalog.c 2008-03-11 13:59:45 UTC (rev 1057)
@@ -280,7 +280,8 @@
if (catalog && *catalog)
{
to= strmov(to, "FROM `");
- to+= mysql_real_escape_string(mysql, to, (char *)catalog, catalog_length);
+ to+= myodbc_escape_string(mysql, to, sizeof(buff) - (to - buff),
+ (char *)catalog, catalog_length, 1);
to= strmov(to, "` ");
}
@@ -298,8 +299,8 @@
if (wildcard)
to+= mysql_real_escape_string(mysql, to, (char *)table, table_length);
else
- to+= myodbc_escape_wildcard(mysql, to, sizeof(buff) - (to - buff),
- (char *)table, table_length);
+ to+= myodbc_escape_string(mysql, to, sizeof(buff) - (to - buff),
+ (char *)table, table_length, 0);
to= strmov(to, "'");
}
@@ -611,17 +612,20 @@
{
char buff[255];
char *select, *to;
+ size_t select_len;
unsigned long *lengths;
/* Get a list of column names that match our criteria. */
to= strmov(buff, "SHOW COLUMNS FROM `");
if (cbCatalog)
{
- to+= mysql_real_escape_string(mysql, to, (char *)szCatalog, cbCatalog);
+ to+= myodbc_escape_string(mysql, to, sizeof(buff) - (to - buff),
+ (char *)szCatalog, cbCatalog, 1);
to= strmov(to, "`.`");
}
- to+= mysql_real_escape_string(mysql, to, (char *)szTable, cbTable);
+ to+= myodbc_escape_string(mysql, to, sizeof(buff) - (to - buff),
+ (char *)szTable, cbTable, 1);
to= strmov(to, "`");
if (cbColumn)
@@ -643,9 +647,8 @@
pthread_mutex_unlock(&dbc->lock);
/* Build a SELECT ... LIMIT 0 to get the field metadata. */
- if (!(select= (char *)my_malloc(sizeof(char) * (ulong)result->row_count *
- (NAME_LEN + 1) + NAME_LEN * 2,
- MYF(0))))
+ select_len = (ulong)result->row_count * (NAME_LEN + 1) + NAME_LEN * 2;
+ if (!(select= (char *)my_malloc(select_len, MYF(0))))
{
set_mem_error(mysql);
return NULL;
@@ -656,7 +659,8 @@
{
to= strmov(to, "`");
lengths= mysql_fetch_lengths(result);
- to+= mysql_real_escape_string(mysql, to, row[0], lengths[0]);
+ to+= myodbc_escape_string(mysql, to, select_len - (to - select),
+ (char *)row[0], lengths[0], 1);
to= strmov(to, "`,");
}
*(--to)= '\0';
@@ -664,11 +668,13 @@
to= strmov(to, " FROM `");
if (cbCatalog)
{
- to+= mysql_real_escape_string(mysql, to, (char *)szCatalog, cbCatalog);
+ to+= myodbc_escape_string(mysql, to, select_len - (to - select),
+ (char *)szCatalog, cbCatalog, 1);
to= strmov(to, "`.`");
}
- to+= mysql_real_escape_string(mysql, to, (char *)szTable, cbTable);
+ to+= myodbc_escape_string(mysql, to, select_len - (to - select),
+ (char *)szTable, cbTable, 1);
to= strmov(to, "` LIMIT 0");
mysql_free_result(result);
Modified: trunk/driver/myutil.h
===================================================================
--- trunk/driver/myutil.h 2008-03-11 13:17:54 UTC (rev 1056)
+++ trunk/driver/myutil.h 2008-03-11 13:59:45 UTC (rev 1057)
@@ -216,8 +216,8 @@
int myodbc_casecmp(const char *s, const char *t, uint len);
my_bool reget_current_catalog(DBC FAR *dbc);
-ulong myodbc_escape_wildcard(MYSQL *mysql, char *to, ulong to_length,
- const char *from, ulong length);
+ulong myodbc_escape_string(MYSQL *mysql, char *to, ulong to_length,
+ const char *from, ulong length, int escape_id);
/* Functions used when debugging */
void query_print(FILE *log_file,char *query);
Modified: trunk/driver/utility.c
===================================================================
--- trunk/driver/utility.c 2008-03-11 13:17:54 UTC (rev 1056)
+++ trunk/driver/utility.c 2008-03-11 13:59:45 UTC (rev 1057)
@@ -1428,18 +1428,19 @@
/**
Escapes a string that may contain wildcard characters (%, _) and other
problematic characters (", ', \n, etc). Like mysql_real_escape_string() but
- also including % and _.
+ also including % and _. Can be used with an identified by passing escape_id.
@param[in] mysql Pointer to MYSQL structure
@param[out] to Buffer for escaped string
@param[in] to_length Length of destination buffer, or 0 for "big enough"
@param[in] from The string to escape
@param[in] length The length of the string to escape
+ @param[in] escape_id Escaping an identified that will be quoted
*/
-ulong myodbc_escape_wildcard(MYSQL *mysql __attribute__((unused)),
- char *to, ulong to_length,
- const char *from, ulong length)
+ulong myodbc_escape_string(MYSQL *mysql __attribute__((unused)),
+ char *to, ulong to_length,
+ const char *from, ulong length, int escape_id)
{
const char *to_start= to;
const char *end, *to_end=to_start + (to_length ? to_length-1 : 2*length);
@@ -1461,7 +1462,7 @@
break;
}
while (tmp_length--)
- *to++= *from++;
+ *to++= *from++;
from--;
continue;
}
@@ -1481,34 +1482,34 @@
else
#endif
switch (*from) {
- case 0: /* Must be escaped for 'mysql' */
+ case 0: /* Must be escaped for 'mysql' */
escape= '0';
break;
- case '\n': /* Must be escaped for logs */
+ case '\n': /* Must be escaped for logs */
escape= 'n';
break;
case '\r':
escape= 'r';
break;
case '\\':
- escape= '\\';
- break;
case '\'':
- escape= '\'';
- break;
- case '"': /* Better safe than sorry */
- escape= '"';
- break;
+ case '"': /* Better safe than sorry */
case '_':
- escape= '_';
- break;
case '%':
- escape= '%';
+ escape= *from;
break;
- case '\032': /* This gives problems on Win32 */
+ case '\032': /* This gives problems on Win32 */
escape= 'Z';
break;
}
+ /* if escaping an id, only handle back-tick */
+ if (escape_id)
+ {
+ if (*from == '`')
+ escape= *from;
+ else
+ escape= 0;
+ }
if (escape)
{
if (to + 2 > to_end)
Modified: trunk/test/my_catalog.c
===================================================================
--- trunk/test/my_catalog.c 2008-03-11 13:17:54 UTC (rev 1056)
+++ trunk/test/my_catalog.c 2008-03-11 13:59:45 UTC (rev 1057)
@@ -1153,6 +1153,31 @@
}
+/*
+ Bug #32989 - Crystal Reports fails if a field has a single quote
+*/
+DECLARE_TEST(t_bug32989)
+{
+ SQLCHAR name[20];
+ SQLLEN len;
+
+ ok_sql(hstmt, "drop table if exists t_bug32989");
+ ok_sql(hstmt, "create table t_bug32989 (`doesn't work` int)");
+
+ ok_stmt(hstmt, SQLColumns(hstmt, "test", SQL_NTS, NULL, 0,
+ "t_bug32989", SQL_NTS, NULL, 0));
+ ok_stmt(hstmt, SQLFetch(hstmt));
+
+ ok_stmt(hstmt, SQLGetData(hstmt, 4, SQL_C_CHAR, name, 20, &len));
+ is_num(len, 12);
+ is_str(name, "doesn't work", 13);
+ ok_stmt(hstmt, SQLFreeStmt(hstmt, SQL_CLOSE));
+
+ ok_sql(hstmt, "drop table if exists t_bug32989");
+ return OK;
+}
+
+
BEGIN_TESTS
ADD_TEST(my_columns_null)
ADD_TEST(my_drop_table)
@@ -1176,6 +1201,7 @@
ADD_TEST(t_bug29888)
ADD_TEST(t_bug14407)
ADD_TEST(t_bug32864)
+ ADD_TEST(t_bug32989)
END_TESTS
| Thread |
|---|
| • Connector/ODBC 3.51 commit: r1057 - in trunk: . driver test | jbalint | 11 Mar |