Changeset: fea48a097a74 for MonetDB URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=fea48a097a74 Modified Files: clients/ChangeLog.Dec2011 clients/odbc/driver/ODBCUtil.c clients/odbc/driver/ODBCUtil.h clients/odbc/driver/SQLColumnPrivileges.c clients/odbc/driver/SQLColumns.c clients/odbc/driver/SQLConnect.c clients/odbc/driver/SQLExecute.c clients/odbc/driver/SQLForeignKeys.c clients/odbc/driver/SQLGetInfo.c clients/odbc/driver/SQLPrepare.c clients/odbc/driver/SQLPrimaryKeys.c clients/odbc/driver/SQLProcedures.c clients/odbc/driver/SQLSetConnectAttr.c clients/odbc/driver/SQLSpecialColumns.c clients/odbc/driver/SQLStatistics.c clients/odbc/driver/SQLTablePrivileges.c clients/odbc/driver/SQLTables.c Branch: Dec2011 Log Message:
ODBC: Implemented database name as catalog, fixed catalog functions. The catalog functions (functions like SQLTables that return a result set describing the database catalog) interpret their arguments that are used for filtering the result in different ways depending on the function and on the value of the SQL_ATTR_METADATA_ID attribute. This is now also implemented. Also fixed SQLColumns and SQLSpecialColumns to return the proper values for various column types. SQLSpecialColumns was totally bogus, and SQLColumns didn't recognize 'wrd'. (One changeset because it is more work than it is worth to split this up.) diffs (truncated from 2723 to 300 lines): diff --git a/clients/ChangeLog.Dec2011 b/clients/ChangeLog.Dec2011 --- a/clients/ChangeLog.Dec2011 +++ b/clients/ChangeLog.Dec2011 @@ -1,6 +1,11 @@ # ChangeLog file for clients # This file is updated with Maddlog +* Fri Oct 28 2011 Sjoerd Mullender <[email protected]> +- ODBC: The database name is now used as the catalog name throughout. + Functions that return a catalog name return the database name, and + functions that match on catalog name match it with the database name. + * Mon Oct 24 2011 Sjoerd Mullender <[email protected]> - ODBC: Implemented an easier way to create a log file of interactions with the ODBC driver. You can now add a connection attribute diff --git a/clients/odbc/driver/ODBCUtil.c b/clients/odbc/driver/ODBCUtil.c --- a/clients/odbc/driver/ODBCUtil.c +++ b/clients/odbc/driver/ODBCUtil.c @@ -371,6 +371,98 @@ ODBCTranslateSQL(const SQLCHAR *query, s return nquery; } +char * +ODBCParseOA(const char *tab, const char *col, const char *arg, size_t len) +{ + size_t i; + char *res; + const char *s; + + /* count length, counting ' and \ double */ + for (i = 0, s = arg; s < arg + len; i++, s++) { + if (*s == '\'' || *s == '\\') + i++; + } + i += strlen(tab) + strlen(col) + 10; /* ""."" = '' */ + res = malloc(i + 1); + snprintf(res, i, "\"%s\".\"%s\" = '", tab, col); + for (i = strlen(res), s = arg; s < arg + len; s++) { + if (*s == '\'' || *s == '\\') + res[i++] = *s; + res[i++] = *s; + } + res[i++] = '\''; + res[i] = 0; + return res; +} + +char * +ODBCParsePV(const char *tab, const char *col, const char *arg, size_t len) +{ + size_t i; + char *res; + const char *s; + + /* count length, counting ' and \ double */ + for (i = 0, s = arg; s < arg + len; i++, s++) { + if (*s == '\'' || *s == '\\') + i++; + } + i += strlen(tab) + strlen(col) + 25; /* ""."" like '' escape '\\' */ + res = malloc(i + 1); + snprintf(res, i, "\"%s\".\"%s\" like '", tab, col); + for (i = strlen(res), s = arg; s < arg + len; s++) { + if (*s == '\'' || *s == '\\') + res[i++] = *s; + res[i++] = *s; + } + for (s = "' escape '\\\\'"; *s; s++) + res[i++] = *s; + res[i] = 0; + return res; +} + +char * +ODBCParseID(const char *tab, const char *col, const char *arg, size_t len) +{ + size_t i; + char *res; + const char *s; + int fold = 1; + + while (len > 0 && (arg[--len] == ' ' || arg[len] == '\t')) + ; + len++; + if (len >= 2 && *arg == '"' && arg[len - 1] == '"') { + arg++; + len -= 2; + fold = 0; + } + + for (i = 0, s = arg; s < arg + len; i++, s++) { + if (*s == '\'' || *s == '\\') + i++; + } + i += strlen(tab) + strlen(col) + 10; /* ""."" = '' */ + if (fold) + i += 14; /* 2 times upper() */ + res = malloc(i + 1); + if (fold) + snprintf(res, i, "upper(\"%s\".\"%s\") = upper('", tab, col); + else + snprintf(res, i, "\"%s\".\"%s\" = '", tab, col); + for (i = strlen(res); len != 0; len--, arg++) { + if (*arg == '\'' || *arg == '\\') + res[i++] = *arg; + res[i++] = *arg; + } + res[i++] = '\''; + if (fold) + res[i++] = ')'; + res[i] = 0; + return res; +} + struct sql_types ODBC_sql_types[] = { {SQL_CHAR, SQL_CHAR, 0, 0, UNAFFECTED, 1, UNAFFECTED, 0, SQL_FALSE}, {SQL_VARCHAR, SQL_VARCHAR, 0, 0, UNAFFECTED, 1, UNAFFECTED, 0, SQL_FALSE}, diff --git a/clients/odbc/driver/ODBCUtil.h b/clients/odbc/driver/ODBCUtil.h --- a/clients/odbc/driver/ODBCUtil.h +++ b/clients/odbc/driver/ODBCUtil.h @@ -144,6 +144,10 @@ extern char *ODBCutf82wchar(const SQLCHA } while (0) #endif /* WITH_WCHAR */ +char *ODBCParseOA(const char *tab, const char *col, const char *arg, size_t len); +char *ODBCParsePV(const char *tab, const char *col, const char *arg, size_t len); +char *ODBCParseID(const char *tab, const char *col, const char *arg, size_t len); + /* SQL_DESC_CONCISE_TYPE, SQL_DESC_DATETIME_INTERVAL_CODE, and * SQL_DESC_TYPE are interdependent and setting one affects the other. * Also, setting them affect other fields. This is all encoded in diff --git a/clients/odbc/driver/SQLColumnPrivileges.c b/clients/odbc/driver/SQLColumnPrivileges.c --- a/clients/odbc/driver/SQLColumnPrivileges.c +++ b/clients/odbc/driver/SQLColumnPrivileges.c @@ -54,6 +54,7 @@ SQLColumnPrivileges_(ODBCStmt *stmt, RETCODE rc; char *query = NULL; char *query_end = NULL; + char *cat = NULL, *sch = NULL, *tab = NULL, *col = NULL; fixODBCstring(CatalogName, NameLength1, SQLSMALLINT , addStmtError, stmt, return SQL_ERROR); @@ -72,8 +73,54 @@ SQLColumnPrivileges_(ODBCStmt *stmt, (int) NameLength4, (char *) ColumnName); #endif + if (stmt->Dbc->sql_attr_metadata_id == SQL_FALSE) { + if (NameLength1 > 0) { + cat = ODBCParseOA("e", "value", + (const char *) CatalogName, + (size_t) NameLength1); + } + if (NameLength2 > 0) { + sch = ODBCParseOA("s", "name", + (const char *) SchemaName, + (size_t) NameLength2); + } + if (NameLength3 > 0) { + tab = ODBCParseOA("t", "name", + (const char *) TableName, + (size_t) NameLength3); + } + if (NameLength4 > 0) { + col = ODBCParsePV("c", "name", + (const char *) ColumnName, + (size_t) NameLength4); + } + } else { + if (NameLength1 > 0) { + cat = ODBCParseID("e", "value", + (const char *) CatalogName, + (size_t) NameLength1); + } + if (NameLength2 > 0) { + sch = ODBCParseID("s", "name", + (const char *) SchemaName, + (size_t) NameLength2); + } + if (NameLength3 > 0) { + tab = ODBCParseID("t", "name", + (const char *) TableName, + (size_t) NameLength3); + } + if (NameLength4 > 0) { + col = ODBCParseID("c", "name", + (const char *) ColumnName, + (size_t) NameLength4); + } + } + /* construct the query now */ - query = malloc(1200 + NameLength2 + NameLength3 + NameLength4); + query = malloc(1200 + (cat ? strlen(cat) : 0) + + (sch ? strlen(sch) : 0) + (tab ? strlen(tab) : 0) + + (col ? strlen(col) : 0)); query_end = query; /* SQLColumnPrivileges returns a table with the following columns: @@ -87,139 +134,78 @@ SQLColumnPrivileges_(ODBCStmt *stmt, is_grantable VARCHAR */ - sprintf(query_end, - "select cast(null as varchar(128)) as \"table_cat\"," - " \"s\".\"name\" as \"table_schem\"," - " \"t\".\"name\" as \"table_name\"," - " \"c\".\"name\" as \"column_name\"," - " case \"a\".\"id\"" - " when \"s\".\"owner\" then '_SYSTEM'" - " else \"g\".\"name\"" - " end as \"grantor\"," - " case \"a\".\"name\"" - " when 'public' then 'PUBLIC'" - " else \"a\".\"name\"" - " end as \"grantee\"," - " case \"p\".\"privileges\"" - " when 1 then 'SELECT'" - " when 2 then 'UPDATE'" - " when 4 then 'INSERT'" - " when 8 then 'DELETE'" - " when 16 then 'EXECUTE'" - " when 32 then 'GRANT'" - " end as \"privilege\"," - " case \"p\".\"grantable\"" - " when 1 then 'YES'" - " when 0 then 'NO'" - " end as \"is_grantable\" " - "from \"sys\".\"schemas\" \"s\"," - " \"sys\".\"_tables\" \"t\"," - " \"sys\".\"_columns\" \"c\"," - " \"sys\".\"auths\" \"a\"," - " \"sys\".\"privileges\" \"p\"," - " \"sys\".\"auths\" \"g\" " - "where \"p\".\"obj_id\" = \"c\".\"id\" and" - " \"c\".\"table_id\" = \"t\".\"id\" and" - " \"p\".\"auth_id\" = \"a\".\"id\" and" - " \"t\".\"schema_id\" = \"s\".\"id\" and" - " \"t\".\"system\" = false and" - " \"p\".\"grantor\" = \"g\".\"id\""); + strcpy(query_end, + "select \"e\".\"value\" as \"table_cat\"," + " \"s\".\"name\" as \"table_schem\"," + " \"t\".\"name\" as \"table_name\"," + " \"c\".\"name\" as \"column_name\"," + " case \"a\".\"id\"" + " when \"s\".\"owner\" then '_SYSTEM'" + " else \"g\".\"name\"" + " end as \"grantor\"," + " case \"a\".\"name\"" + " when 'public' then 'PUBLIC'" + " else \"a\".\"name\"" + " end as \"grantee\"," + " case \"p\".\"privileges\"" + " when 1 then 'SELECT'" + " when 2 then 'UPDATE'" + " when 4 then 'INSERT'" + " when 8 then 'DELETE'" + " when 16 then 'EXECUTE'" + " when 32 then 'GRANT'" + " end as \"privilege\"," + " case \"p\".\"grantable\"" + " when 1 then 'YES'" + " when 0 then 'NO'" + " end as \"is_grantable\" " + "from \"sys\".\"schemas\" \"s\"," + " \"sys\".\"_tables\" \"t\"," + " \"sys\".\"_columns\" \"c\"," + " \"sys\".\"auths\" \"a\"," + " \"sys\".\"privileges\" \"p\"," + " \"sys\".\"auths\" \"g\"," + " \"sys\".\"env\"() \"e\" " + "where \"p\".\"obj_id\" = \"c\".\"id\" and" + " \"c\".\"table_id\" = \"t\".\"id\" and" + " \"p\".\"auth_id\" = \"a\".\"id\" and" + " \"t\".\"schema_id\" = \"s\".\"id\" and" + " \"t\".\"system\" = false and" + " \"p\".\"grantor\" = \"g\".\"id\" and" + " \"e\".\"name\" = 'gdk_dbname'"); + assert(strlen(query) < 1100); query_end += strlen(query_end); /* Construct the selection condition query part */ - if (stmt->Dbc->sql_attr_metadata_id == SQL_TRUE) { - /* treat arguments as identifiers */ - /* remove trailing blanks */ - while (NameLength2 > 0 && - isspace((int) SchemaName[NameLength2 - 1])) - NameLength2--; - while (NameLength3 > 0 && - isspace((int) TableName[NameLength3 - 1])) - NameLength3--; - while (NameLength4 > 0 && - isspace((int) ColumnName[NameLength4 - 1])) - NameLength4--; - if (NameLength2 > 0) { - sprintf(query_end, " and \"s\".\"name\" = '"); - query_end += strlen(query_end); - while (NameLength2-- > 0) - *query_end++ = tolower(*SchemaName++); - *query_end++ = '\''; _______________________________________________ Checkin-list mailing list [email protected] http://mail.monetdb.org/mailman/listinfo/checkin-list
