summaryrefslogtreecommitdiff
path: root/src/interfaces/odbc/info.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/interfaces/odbc/info.c')
-rw-r--r--src/interfaces/odbc/info.c644
1 files changed, 452 insertions, 192 deletions
diff --git a/src/interfaces/odbc/info.c b/src/interfaces/odbc/info.c
index d4fda3670b..fc5dcef341 100644
--- a/src/interfaces/odbc/info.c
+++ b/src/interfaces/odbc/info.c
@@ -10,7 +10,7 @@
* SQLTables, SQLColumns, SQLStatistics, SQLSpecialColumns,
* SQLPrimaryKeys, SQLForeignKeys,
* SQLProcedureColumns(NI), SQLProcedures,
- * SQLTablePrivileges(NI), SQLColumnPrivileges(NI)
+ * SQLTablePrivileges, SQLColumnPrivileges(NI)
*
* Comments: See "notice.txt" for copyright and license information.
*--------
@@ -231,13 +231,14 @@ PGAPI_GetInfo(
case SQL_FETCH_DIRECTION: /* ODBC 1.0 */
len = 4;
- value = ci->drivers.use_declarefetch ? (SQL_FD_FETCH_NEXT) : (SQL_FD_FETCH_NEXT |
- SQL_FD_FETCH_FIRST |
- SQL_FD_FETCH_LAST |
- SQL_FD_FETCH_PRIOR |
- SQL_FD_FETCH_ABSOLUTE |
- SQL_FD_FETCH_RELATIVE |
- SQL_FD_FETCH_BOOKMARK);
+ value = ci->drivers.use_declarefetch ? (SQL_FD_FETCH_NEXT) :
+ (SQL_FD_FETCH_NEXT |
+ SQL_FD_FETCH_FIRST |
+ SQL_FD_FETCH_LAST |
+ SQL_FD_FETCH_PRIOR |
+ SQL_FD_FETCH_ABSOLUTE |
+ SQL_FD_FETCH_RELATIVE |
+ SQL_FD_FETCH_BOOKMARK);
break;
case SQL_FILE_USAGE: /* ODBC 2.0 */
@@ -665,7 +666,6 @@ PGAPI_GetInfo(
/* unrecognized key */
conn->errormsg = "Unrecognized key passed to PGAPI_GetInfo.";
conn->errornumber = CONN_NOT_IMPLEMENTED_ERROR;
- CC_log_error(func, "", conn);
return SQL_ERROR;
}
@@ -685,12 +685,20 @@ PGAPI_GetInfo(
if (rgbInfoValue)
{
+#ifdef UNICODE_SUPPORT
+ if (conn->unicode)
+ {
+ len = utf8_to_ucs2(p, len, (SQLWCHAR *) rgbInfoValue, cbInfoValueMax / 2);
+ len *= 2;
+ }
+ else
+#endif /* UNICODE_SUPPORT */
strncpy_null((char *) rgbInfoValue, p, (size_t) cbInfoValueMax);
if (len >= cbInfoValueMax)
{
result = SQL_SUCCESS_WITH_INFO;
- conn->errornumber = STMT_TRUNCATED;
+ conn->errornumber = CONN_TRUNCATED;
conn->errormsg = "The buffer was too small for tthe InfoValue.";
}
}
@@ -721,6 +729,7 @@ PGAPI_GetTypeInfo(
{
static char *func = "PGAPI_GetTypeInfo";
StatementClass *stmt = (StatementClass *) hstmt;
+ QResultClass *res;
TupleNode *row;
int i;
@@ -737,31 +746,31 @@ PGAPI_GetTypeInfo(
}
stmt->manual_result = TRUE;
- stmt->result = QR_Constructor();
- if (!stmt->result)
+ if (res = QR_Constructor(), !res)
{
SC_log_error(func, "Error creating result.", stmt);
return SQL_ERROR;
}
+ SC_set_Result(stmt, res);
extend_bindings(stmt, 15);
- QR_set_num_fields(stmt->result, 15);
- QR_set_field_info(stmt->result, 0, "TYPE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 1, "DATA_TYPE", PG_TYPE_INT2, 2);
- QR_set_field_info(stmt->result, 2, "PRECISION", PG_TYPE_INT4, 4);
- QR_set_field_info(stmt->result, 3, "LITERAL_PREFIX", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 4, "LITERAL_SUFFIX", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 5, "CREATE_PARAMS", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 6, "NULLABLE", PG_TYPE_INT2, 2);
- QR_set_field_info(stmt->result, 7, "CASE_SENSITIVE", PG_TYPE_INT2, 2);
- QR_set_field_info(stmt->result, 8, "SEARCHABLE", PG_TYPE_INT2, 2);
- QR_set_field_info(stmt->result, 9, "UNSIGNED_ATTRIBUTE", PG_TYPE_INT2, 2);
- QR_set_field_info(stmt->result, 10, "MONEY", PG_TYPE_INT2, 2);
- QR_set_field_info(stmt->result, 11, "AUTO_INCREMENT", PG_TYPE_INT2, 2);
- QR_set_field_info(stmt->result, 12, "LOCAL_TYPE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 13, "MINIMUM_SCALE", PG_TYPE_INT2, 2);
- QR_set_field_info(stmt->result, 14, "MAXIMUM_SCALE", PG_TYPE_INT2, 2);
+ QR_set_num_fields(res, 15);
+ QR_set_field_info(res, 0, "TYPE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 1, "DATA_TYPE", PG_TYPE_INT2, 2);
+ QR_set_field_info(res, 2, "PRECISION", PG_TYPE_INT4, 4);
+ QR_set_field_info(res, 3, "LITERAL_PREFIX", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 4, "LITERAL_SUFFIX", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 5, "CREATE_PARAMS", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 6, "NULLABLE", PG_TYPE_INT2, 2);
+ QR_set_field_info(res, 7, "CASE_SENSITIVE", PG_TYPE_INT2, 2);
+ QR_set_field_info(res, 8, "SEARCHABLE", PG_TYPE_INT2, 2);
+ QR_set_field_info(res, 9, "UNSIGNED_ATTRIBUTE", PG_TYPE_INT2, 2);
+ QR_set_field_info(res, 10, "MONEY", PG_TYPE_INT2, 2);
+ QR_set_field_info(res, 11, "AUTO_INCREMENT", PG_TYPE_INT2, 2);
+ QR_set_field_info(res, 12, "LOCAL_TYPE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 13, "MINIMUM_SCALE", PG_TYPE_INT2, 2);
+ QR_set_field_info(res, 14, "MAXIMUM_SCALE", PG_TYPE_INT2, 2);
for (i = 0, sqlType = sqlTypes[0]; sqlType; sqlType = sqlTypes[++i])
{
@@ -795,7 +804,7 @@ PGAPI_GetTypeInfo(
set_nullfield_int2(&row->tuple[13], pgtype_scale(stmt, pgType, PG_STATIC));
set_nullfield_int2(&row->tuple[14], pgtype_scale(stmt, pgType, PG_STATIC));
- QR_add_tuple(stmt->result, row);
+ QR_add_tuple(res, row);
}
}
@@ -898,7 +907,7 @@ PGAPI_GetFunctions(
pfExists[SQL_API_SQLMORERESULTS] = TRUE;
pfExists[SQL_API_SQLNATIVESQL] = TRUE;
pfExists[SQL_API_SQLNUMPARAMS] = TRUE;
- pfExists[SQL_API_SQLPARAMOPTIONS] = FALSE;
+ pfExists[SQL_API_SQLPARAMOPTIONS] = TRUE;
pfExists[SQL_API_SQLPRIMARYKEYS] = TRUE;
pfExists[SQL_API_SQLPROCEDURECOLUMNS] = FALSE;
if (PG_VERSION_LT(conn, 6.5))
@@ -907,7 +916,7 @@ PGAPI_GetFunctions(
pfExists[SQL_API_SQLPROCEDURES] = TRUE;
pfExists[SQL_API_SQLSETPOS] = TRUE;
pfExists[SQL_API_SQLSETSCROLLOPTIONS] = TRUE; /* odbc 1.0 */
- pfExists[SQL_API_SQLTABLEPRIVILEGES] = FALSE;
+ pfExists[SQL_API_SQLTABLEPRIVILEGES] = TRUE;
}
}
else
@@ -1070,7 +1079,7 @@ PGAPI_GetFunctions(
*pfExists = TRUE;
break;
case SQL_API_SQLPARAMOPTIONS:
- *pfExists = FALSE;
+ *pfExists = TRUE;
break;
case SQL_API_SQLPRIMARYKEYS:
*pfExists = TRUE;
@@ -1091,7 +1100,7 @@ PGAPI_GetFunctions(
*pfExists = TRUE;
break; /* odbc 1.0 */
case SQL_API_SQLTABLEPRIVILEGES:
- *pfExists = FALSE;
+ *pfExists = TRUE;
break;
}
}
@@ -1115,6 +1124,7 @@ PGAPI_Tables(
static char *func = "PGAPI_Tables";
StatementClass *stmt = (StatementClass *) hstmt;
StatementClass *tbl_stmt;
+ QResultClass *res;
TupleNode *row;
HSTMT htbl_stmt;
RETCODE result;
@@ -1291,8 +1301,7 @@ PGAPI_Tables(
return SQL_ERROR;
}
- stmt->result = QR_Constructor();
- if (!stmt->result)
+ if (res = QR_Constructor(), !res)
{
stmt->errormsg = "Couldn't allocate memory for PGAPI_Tables result.";
stmt->errornumber = STMT_NO_MEMORY_ERROR;
@@ -1300,6 +1309,7 @@ PGAPI_Tables(
PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
return SQL_ERROR;
}
+ SC_set_Result(stmt, res);
/* the binding structure for a statement is not set up until */
@@ -1310,12 +1320,12 @@ PGAPI_Tables(
extend_bindings(stmt, 5);
/* set the field names */
- QR_set_num_fields(stmt->result, 5);
- QR_set_field_info(stmt->result, 0, "TABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 1, "TABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 2, "TABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 3, "TABLE_TYPE", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 4, "REMARKS", PG_TYPE_TEXT, 254);
+ QR_set_num_fields(res, 5);
+ QR_set_field_info(res, 0, "TABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 1, "TABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 2, "TABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 3, "TABLE_TYPE", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 4, "REMARKS", PG_TYPE_TEXT, 254);
/* add the tuples */
result = PGAPI_Fetch(htbl_stmt);
@@ -1372,6 +1382,7 @@ PGAPI_Tables(
row = (TupleNode *) malloc(sizeof(TupleNode) + (5 - 1) *sizeof(TupleField));
/*set_tuplefield_string(&row->tuple[0], "");*/
+ /*set_tuplefield_string(&row->tuple[0], "cat0");*/
set_tuplefield_null(&row->tuple[0]);
/*
@@ -1389,9 +1400,10 @@ PGAPI_Tables(
set_tuplefield_null(&row->tuple[1]);
set_tuplefield_string(&row->tuple[2], table_name);
set_tuplefield_string(&row->tuple[3], systable ? "SYSTEM TABLE" : (view ? "VIEW" : "TABLE"));
- set_tuplefield_string(&row->tuple[4], "");
+ /*set_tuplefield_string(&row->tuple[4], "");*/
+ set_tuplefield_string(&row->tuple[4], "TABLE");
- QR_add_tuple(stmt->result, row);
+ QR_add_tuple(res, row);
}
result = PGAPI_Fetch(htbl_stmt);
}
@@ -1425,11 +1437,14 @@ PGAPI_Tables(
* PostgreSQL needs 2 '\\' to escape '_' and '%'.
*/
static int
-reallyEscapeCatalogEscapes(const char *src, int srclen, char *dest, int dst_len)
+reallyEscapeCatalogEscapes(const char *src, int srclen, char *dest, int dst_len, int ccsc)
{
int i, outlen;
const char *in;
BOOL escape_in = FALSE;
+#ifdef MULTIBYTE
+ encoded_str encstr;
+#endif
if (srclen == SQL_NULL_DATA)
{
@@ -1441,12 +1456,13 @@ reallyEscapeCatalogEscapes(const char *src, int srclen, char *dest, int dst_len)
if (srclen <= 0)
return STRCPY_FAIL;
#ifdef MULTIBYTE
- multibyte_init();
+ encoded_str_constr(&encstr, ccsc, src);
#endif
for (i = 0, in = src, outlen = 0; i < srclen && outlen < dst_len; i++, in++)
{
#ifdef MULTIBYTE
- if (multibyte_char_check(*in) != 0)
+ encoded_nextchar(&encstr);
+ if (ENCODE_STATUS(encstr) != 0)
{
dest[outlen++] = *in;
continue;
@@ -1496,6 +1512,7 @@ PGAPI_Columns(
{
static char *func = "PGAPI_Columns";
StatementClass *stmt = (StatementClass *) hstmt;
+ QResultClass *res;
TupleNode *row;
HSTMT hcol_stmt;
StatementClass *col_stmt;
@@ -1505,7 +1522,7 @@ PGAPI_Columns(
table_name[MAX_INFO_STRING],
field_name[MAX_INFO_STRING],
field_type_name[MAX_INFO_STRING];
- Int2 field_number,
+ Int2 field_number, sqltype,
result_cols,
scale;
Int4 field_type,
@@ -1556,7 +1573,7 @@ PGAPI_Columns(
char esc_table_name[MAX_TABLE_LEN * 2];
int escTbnamelen;
- escTbnamelen = reallyEscapeCatalogEscapes(szTableName, cbTableName, esc_table_name, sizeof(esc_table_name));
+ escTbnamelen = reallyEscapeCatalogEscapes(szTableName, cbTableName, esc_table_name, sizeof(esc_table_name), conn->ccsc);
my_strcat(columns_query, " and c.relname like '%.*s'", esc_table_name, escTbnamelen);
my_strcat(columns_query, " and u.usename like '%.*s'", szTableOwner, cbTableOwner);
my_strcat(columns_query, " and a.attname like '%.*s'", szColumnName, cbColumnName);
@@ -1701,8 +1718,7 @@ PGAPI_Columns(
return SQL_ERROR;
}
- stmt->result = QR_Constructor();
- if (!stmt->result)
+ if (res = QR_Constructor(), !res)
{
stmt->errormsg = "Couldn't allocate memory for PGAPI_Columns result.";
stmt->errornumber = STMT_NO_MEMORY_ERROR;
@@ -1710,6 +1726,7 @@ PGAPI_Columns(
PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
return SQL_ERROR;
}
+ SC_set_Result(stmt, res);
/* the binding structure for a statement is not set up until */
@@ -1721,23 +1738,32 @@ PGAPI_Columns(
extend_bindings(stmt, result_cols);
/* set the field names */
- QR_set_num_fields(stmt->result, result_cols);
- QR_set_field_info(stmt->result, 0, "TABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 1, "TABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 2, "TABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 3, "COLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 4, "DATA_TYPE", PG_TYPE_INT2, 2);
- QR_set_field_info(stmt->result, 5, "TYPE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 6, "PRECISION", PG_TYPE_INT4, 4);
- QR_set_field_info(stmt->result, 7, "LENGTH", PG_TYPE_INT4, 4);
- QR_set_field_info(stmt->result, 8, "SCALE", PG_TYPE_INT2, 2);
- QR_set_field_info(stmt->result, 9, "RADIX", PG_TYPE_INT2, 2);
- QR_set_field_info(stmt->result, 10, "NULLABLE", PG_TYPE_INT2, 2);
- QR_set_field_info(stmt->result, 11, "REMARKS", PG_TYPE_TEXT, 254);
+ QR_set_num_fields(res, result_cols);
+ QR_set_field_info(res, 0, "TABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 1, "TABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 2, "TABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 3, "COLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 4, "DATA_TYPE", PG_TYPE_INT2, 2);
+ QR_set_field_info(res, 5, "TYPE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 6, "PRECISION", PG_TYPE_INT4, 4);
+ QR_set_field_info(res, 7, "LENGTH", PG_TYPE_INT4, 4);
+ QR_set_field_info(res, 8, "SCALE", PG_TYPE_INT2, 2);
+ QR_set_field_info(res, 9, "RADIX", PG_TYPE_INT2, 2);
+ QR_set_field_info(res, 10, "NULLABLE", PG_TYPE_INT2, 2);
+ QR_set_field_info(res, 11, "REMARKS", PG_TYPE_TEXT, 254);
/* User defined fields */
- QR_set_field_info(stmt->result, 12, "DISPLAY_SIZE", PG_TYPE_INT4, 4);
- QR_set_field_info(stmt->result, 13, "FIELD_TYPE", PG_TYPE_INT4, 4);
+#if (ODBCVER >= 0x0300)
+ QR_set_field_info(res, 12, "COLUMN_DEF", PG_TYPE_INT4, 254);
+ QR_set_field_info(res, 13, "SQL_DATA_TYPE", PG_TYPE_INT2, 2);
+ QR_set_field_info(res, 14, "SQL_DATETIME_SUB", PG_TYPE_INT2, 2);
+ QR_set_field_info(res, 15, "CHAR_OCTET_LENGTH", PG_TYPE_INT4, 4);
+ QR_set_field_info(res, 16, "ORDINAL_POSITION", PG_TYPE_INT4, 4);
+ QR_set_field_info(res, 17, "IS_NULLABLE", PG_TYPE_TEXT, 254);
+#else
+ QR_set_field_info(res, 12, "DISPLAY_SIZE", PG_TYPE_INT4, 4);
+ QR_set_field_info(res, 13, "FIELD_TYPE", PG_TYPE_INT4, 4);
+#endif /* ODBCVER */
result = PGAPI_Fetch(hcol_stmt);
@@ -1764,7 +1790,8 @@ PGAPI_Columns(
set_tuplefield_string(&row->tuple[1], "");
set_tuplefield_string(&row->tuple[2], table_name);
set_tuplefield_string(&row->tuple[3], "oid");
- set_tuplefield_int2(&row->tuple[4], pgtype_to_sqltype(stmt, the_type));
+ sqltype = pgtype_to_sqltype(stmt, the_type);
+ set_tuplefield_int2(&row->tuple[4], sqltype);
set_tuplefield_string(&row->tuple[5], "OID");
set_tuplefield_int4(&row->tuple[7], pgtype_length(stmt, the_type, PG_STATIC, PG_STATIC));
@@ -1775,10 +1802,14 @@ PGAPI_Columns(
set_tuplefield_int2(&row->tuple[10], SQL_NO_NULLS);
set_tuplefield_string(&row->tuple[11], "");
+#if (ODBCVER >= 0x0300)
+ set_tuplefield_int2(&row->tuple[13], sqltype);
+#else
set_tuplefield_int4(&row->tuple[12], pgtype_display_size(stmt, the_type, PG_STATIC, PG_STATIC));
set_tuplefield_int4(&row->tuple[13], the_type);
+#endif /* ODBCVER */
- QR_add_tuple(stmt->result, row);
+ QR_add_tuple(res, row);
}
}
@@ -1794,7 +1825,8 @@ PGAPI_Columns(
set_tuplefield_string(&row->tuple[1], "");
set_tuplefield_string(&row->tuple[2], table_name);
set_tuplefield_string(&row->tuple[3], field_name);
- set_tuplefield_int2(&row->tuple[4], pgtype_to_sqltype(stmt, field_type));
+ sqltype = pgtype_to_sqltype(stmt, field_type);
+ set_tuplefield_int2(&row->tuple[4], sqltype);
set_tuplefield_string(&row->tuple[5], field_type_name);
@@ -1812,7 +1844,7 @@ PGAPI_Columns(
*----------
*/
qlog("PGAPI_Columns: table='%s',field_name='%s',type=%d,sqltype=%d,name='%s'\n",
- table_name, field_name, field_type, pgtype_to_sqltype(stmt,field_type), field_type_name);
+ table_name, field_name, field_type, pgtype_to_sqltype, field_type_name);
useStaticPrecision = TRUE;
@@ -1869,9 +1901,31 @@ PGAPI_Columns(
set_nullfield_int2(&row->tuple[9], pgtype_radix(stmt, field_type));
set_tuplefield_int2(&row->tuple[10], (Int2) (not_null[0] == '1' ? SQL_NO_NULLS : pgtype_nullable(stmt, field_type)));
set_tuplefield_string(&row->tuple[11], "");
+#if (ODBCVER >= 0x0300)
+ switch (sqltype)
+ {
+ case SQL_TYPE_DATE:
+ set_tuplefield_int2(&row->tuple[13], SQL_DATETIME);
+ set_tuplefield_int2(&row->tuple[14], SQL_CODE_DATE);
+ break;
+ case SQL_TYPE_TIME:
+ set_tuplefield_int2(&row->tuple[13], SQL_DATETIME);
+ set_tuplefield_int2(&row->tuple[14], SQL_CODE_TIME);
+ break;
+ case SQL_TYPE_TIMESTAMP:
+ set_tuplefield_int2(&row->tuple[13], SQL_DATETIME);
+ set_tuplefield_int2(&row->tuple[14], SQL_CODE_TIMESTAMP);
+ break;
+ default:
+ set_tuplefield_int2(&row->tuple[13], sqltype);
+ break;
+ }
+ set_tuplefield_int4(&row->tuple[16], field_number);
+#else
set_tuplefield_int4(&row->tuple[13], field_type);
+#endif /* ODBCVER */
- QR_add_tuple(stmt->result, row);
+ QR_add_tuple(res, row);
result = PGAPI_Fetch(hcol_stmt);
@@ -1913,7 +1967,7 @@ PGAPI_Columns(
set_tuplefield_int4(&row->tuple[12], pgtype_display_size(stmt, the_type, PG_STATIC, PG_STATIC));
set_tuplefield_int4(&row->tuple[13], the_type);
- QR_add_tuple(stmt->result, row);
+ QR_add_tuple(res, row);
}
/*
@@ -1949,6 +2003,7 @@ PGAPI_SpecialColumns(
static char *func = "PGAPI_SpecialColumns";
TupleNode *row;
StatementClass *stmt = (StatementClass *) hstmt;
+ QResultClass *res;
ConnInfo *ci;
HSTMT hcol_stmt;
StatementClass *col_stmt;
@@ -2017,18 +2072,19 @@ PGAPI_SpecialColumns(
result = PGAPI_Fetch(hcol_stmt);
PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
- stmt->result = QR_Constructor();
+ res = QR_Constructor();
+ SC_set_Result(stmt, res);
extend_bindings(stmt, 8);
- QR_set_num_fields(stmt->result, 8);
- QR_set_field_info(stmt->result, 0, "SCOPE", PG_TYPE_INT2, 2);
- QR_set_field_info(stmt->result, 1, "COLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 2, "DATA_TYPE", PG_TYPE_INT2, 2);
- QR_set_field_info(stmt->result, 3, "TYPE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 4, "PRECISION", PG_TYPE_INT4, 4);
- QR_set_field_info(stmt->result, 5, "LENGTH", PG_TYPE_INT4, 4);
- QR_set_field_info(stmt->result, 6, "SCALE", PG_TYPE_INT2, 2);
- QR_set_field_info(stmt->result, 7, "PSEUDO_COLUMN", PG_TYPE_INT2, 2);
+ QR_set_num_fields(res, 8);
+ QR_set_field_info(res, 0, "SCOPE", PG_TYPE_INT2, 2);
+ QR_set_field_info(res, 1, "COLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 2, "DATA_TYPE", PG_TYPE_INT2, 2);
+ QR_set_field_info(res, 3, "TYPE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 4, "PRECISION", PG_TYPE_INT4, 4);
+ QR_set_field_info(res, 5, "LENGTH", PG_TYPE_INT4, 4);
+ QR_set_field_info(res, 6, "SCALE", PG_TYPE_INT2, 2);
+ QR_set_field_info(res, 7, "PSEUDO_COLUMN", PG_TYPE_INT2, 2);
if (relhasrules[0] != '1')
{
@@ -2046,7 +2102,7 @@ PGAPI_SpecialColumns(
set_tuplefield_int2(&row->tuple[6], pgtype_scale(stmt, PG_TYPE_OID, PG_STATIC));
set_tuplefield_int2(&row->tuple[7], SQL_PC_PSEUDO);
- QR_add_tuple(stmt->result, row);
+ QR_add_tuple(res, row);
}
else if (fColType == SQL_ROWVER)
@@ -2066,7 +2122,7 @@ PGAPI_SpecialColumns(
set_tuplefield_int2(&row->tuple[6], pgtype_scale(stmt, the_type, PG_STATIC));
set_tuplefield_int2(&row->tuple[7], SQL_PC_PSEUDO);
- QR_add_tuple(stmt->result, row);
+ QR_add_tuple(res, row);
}
}
}
@@ -2095,6 +2151,7 @@ PGAPI_Statistics(
{
static char *func = "PGAPI_Statistics";
StatementClass *stmt = (StatementClass *) hstmt;
+ QResultClass *res;
char index_query[INFO_INQUIRY_LEN];
HSTMT hindx_stmt;
RETCODE result;
@@ -2133,14 +2190,14 @@ PGAPI_Statistics(
ci = &(SC_get_conn(stmt)->connInfo);
- stmt->result = QR_Constructor();
- if (!stmt->result)
+ if (res = QR_Constructor(), !res)
{
stmt->errormsg = "Couldn't allocate memory for PGAPI_Statistics result.";
stmt->errornumber = STMT_NO_MEMORY_ERROR;
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
+ SC_set_Result(stmt, res);
/* the binding structure for a statement is not set up until */
@@ -2151,20 +2208,20 @@ PGAPI_Statistics(
extend_bindings(stmt, 13);
/* set the field names */
- QR_set_num_fields(stmt->result, 13);
- QR_set_field_info(stmt->result, 0, "TABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 1, "TABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 2, "TABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 3, "NON_UNIQUE", PG_TYPE_INT2, 2);
- QR_set_field_info(stmt->result, 4, "INDEX_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 5, "INDEX_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 6, "TYPE", PG_TYPE_INT2, 2);
- QR_set_field_info(stmt->result, 7, "SEQ_IN_INDEX", PG_TYPE_INT2, 2);
- QR_set_field_info(stmt->result, 8, "COLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 9, "COLLATION", PG_TYPE_CHAR, 1);
- QR_set_field_info(stmt->result, 10, "CARDINALITY", PG_TYPE_INT4, 4);
- QR_set_field_info(stmt->result, 11, "PAGES", PG_TYPE_INT4, 4);
- QR_set_field_info(stmt->result, 12, "FILTER_CONDITION", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_num_fields(res, 13);
+ QR_set_field_info(res, 0, "TABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 1, "TABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 2, "TABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 3, "NON_UNIQUE", PG_TYPE_INT2, 2);
+ QR_set_field_info(res, 4, "INDEX_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 5, "INDEX_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 6, "TYPE", PG_TYPE_INT2, 2);
+ QR_set_field_info(res, 7, "SEQ_IN_INDEX", PG_TYPE_INT2, 2);
+ QR_set_field_info(res, 8, "COLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 9, "COLLATION", PG_TYPE_CHAR, 1);
+ QR_set_field_info(res, 10, "CARDINALITY", PG_TYPE_INT4, 4);
+ QR_set_field_info(res, 11, "PAGES", PG_TYPE_INT4, 4);
+ QR_set_field_info(res, 12, "FILTER_CONDITION", PG_TYPE_TEXT, MAX_INFO_STRING);
/*
* only use the table name... the owner should be redundant, and we
@@ -2395,7 +2452,7 @@ PGAPI_Statistics(
set_tuplefield_null(&row->tuple[11]);
set_tuplefield_null(&row->tuple[12]);
- QR_add_tuple(stmt->result, row);
+ QR_add_tuple(res, row);
}
result = PGAPI_Fetch(hindx_stmt);
@@ -2457,7 +2514,7 @@ PGAPI_Statistics(
set_tuplefield_null(&row->tuple[11]);
set_tuplefield_null(&row->tuple[12]);
- QR_add_tuple(stmt->result, row);
+ QR_add_tuple(res, row);
i++;
}
}
@@ -2520,12 +2577,15 @@ PGAPI_ColumnPrivileges(
SWORD cbColumnName)
{
static char *func = "PGAPI_ColumnPrivileges";
+ StatementClass *stmt = (StatementClass *) hstmt;
mylog("%s: entering...\n", func);
/* Neither Access or Borland care about this. */
- SC_log_error(func, "Function not implemented", (StatementClass *) hstmt);
+ stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
+ stmt->errormsg = "not implemented";
+ SC_log_error(func, "Function not implemented", stmt);
return SQL_ERROR;
}
@@ -2547,6 +2607,7 @@ PGAPI_PrimaryKeys(
{
static char *func = "PGAPI_PrimaryKeys";
StatementClass *stmt = (StatementClass *) hstmt;
+ QResultClass *res;
ConnectionClass *conn;
TupleNode *row;
RETCODE result;
@@ -2572,14 +2633,14 @@ PGAPI_PrimaryKeys(
stmt->manual_result = TRUE;
stmt->errormsg_created = TRUE;
- stmt->result = QR_Constructor();
- if (!stmt->result)
+ if (res = QR_Constructor(), !res)
{
stmt->errormsg = "Couldn't allocate memory for PGAPI_PrimaryKeys result.";
stmt->errornumber = STMT_NO_MEMORY_ERROR;
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
+ SC_set_Result(stmt, res);
/* the binding structure for a statement is not set up until */
@@ -2591,13 +2652,13 @@ PGAPI_PrimaryKeys(
extend_bindings(stmt, result_cols);
/* set the field names */
- QR_set_num_fields(stmt->result, result_cols);
- QR_set_field_info(stmt->result, 0, "TABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 1, "TABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 2, "TABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 3, "COLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 4, "KEY_SEQ", PG_TYPE_INT2, 2);
- QR_set_field_info(stmt->result, 5, "PK_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_num_fields(res, result_cols);
+ QR_set_field_info(res, 0, "TABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 1, "TABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 2, "TABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 3, "COLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 4, "KEY_SEQ", PG_TYPE_INT2, 2);
+ QR_set_field_info(res, 5, "PK_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
result = PGAPI_AllocStmt(stmt->hdbc, &htbl_stmt);
@@ -2709,7 +2770,7 @@ PGAPI_PrimaryKeys(
set_tuplefield_int2(&row->tuple[4], (Int2) (++seq));
set_tuplefield_null(&row->tuple[5]);
- QR_add_tuple(stmt->result, row);
+ QR_add_tuple(res, row);
mylog(">> primaryKeys: pktab = '%s', attname = '%s', seq = %d\n", pktab, attname, seq);
@@ -2775,7 +2836,7 @@ getClientTableName(ConnectionClass *conn, char *serverTableName, BOOL *nameAlloc
return ret;
if (!conn->server_encoding)
{
- if (res = CC_send_query(conn, "select getdatabaseencoding()", NULL), res)
+ if (res = CC_send_query(conn, "select getdatabaseencoding()", NULL, TRUE), res)
{
if (QR_get_num_tuples(res) > 0)
conn->server_encoding = strdup(QR_get_value_backend_row(res, 0, 0));
@@ -2785,25 +2846,16 @@ getClientTableName(ConnectionClass *conn, char *serverTableName, BOOL *nameAlloc
if (!conn->server_encoding)
return ret;
sprintf(query, "SET CLIENT_ENCODING TO '%s'", conn->server_encoding);
- if (res = CC_send_query(conn, query, NULL), res)
- {
- bError = QR_get_aborted(res);
- QR_Destructor(res);
- }
- else
- bError = TRUE;
+ bError = (CC_send_query(conn, query, NULL, TRUE) == NULL);
if (!bError && continueExec)
{
sprintf(query, "select OID from pg_class where relname = '%s'", serverTableName);
- if (res = CC_send_query(conn, query, NULL), res)
+ if (res = CC_send_query(conn, query, NULL, TRUE), res)
{
if (QR_get_num_tuples(res) > 0)
strcpy(saveoid, QR_get_value_backend_row(res, 0, 0));
else
- {
continueExec = FALSE;
- bError = QR_get_aborted(res);
- }
QR_Destructor(res);
}
else
@@ -2817,17 +2869,11 @@ getClientTableName(ConnectionClass *conn, char *serverTableName, BOOL *nameAlloc
}
/* restore the client encoding */
sprintf(query, "SET CLIENT_ENCODING TO '%s'", conn->client_encoding);
- if (res = CC_send_query(conn, query, NULL), res)
- {
- bError = QR_get_aborted(res);
- QR_Destructor(res);
- }
- else
- bError = TRUE;
+ bError = (CC_send_query(conn, query, NULL, TRUE) == NULL);
if (bError || !continueExec)
return ret;
sprintf(query, "select relname from pg_class where OID = %s", saveoid);
- if (res = CC_send_query(conn, query, NULL), res)
+ if (res = CC_send_query(conn, query, NULL, TRUE), res)
{
if (QR_get_num_tuples(res) > 0)
{
@@ -2854,7 +2900,7 @@ getClientColumnName(ConnectionClass *conn, const char *serverTableName, char *se
return ret;
if (!conn->server_encoding)
{
- if (res = CC_send_query(conn, "select getdatabaseencoding()", NULL), res)
+ if (res = CC_send_query(conn, "select getdatabaseencoding()", NULL, TRUE), res)
{
if (QR_get_num_tuples(res) > 0)
conn->server_encoding = strdup(QR_get_value_backend_row(res, 0, 0));
@@ -2864,19 +2910,13 @@ getClientColumnName(ConnectionClass *conn, const char *serverTableName, char *se
if (!conn->server_encoding)
return ret;
sprintf(query, "SET CLIENT_ENCODING TO '%s'", conn->server_encoding);
- if (res = CC_send_query(conn, query, NULL), res)
- {
- bError = QR_get_aborted(res);
- QR_Destructor(res);
- }
- else
- bError = TRUE;
+ bError = (CC_send_query(conn, query, NULL, TRUE) == NULL);
if (!bError && continueExec)
{
sprintf(query, "select attrelid, attnum from pg_class, pg_attribute "
"where relname = '%s' and attrelid = pg_class.oid "
"and attname = '%s'", serverTableName, serverColumnName);
- if (res = CC_send_query(conn, query, NULL), res)
+ if (res = CC_send_query(conn, query, NULL, TRUE), res)
{
if (QR_get_num_tuples(res) > 0)
{
@@ -2884,10 +2924,7 @@ getClientColumnName(ConnectionClass *conn, const char *serverTableName, char *se
strcpy(saveattnum, QR_get_value_backend_row(res, 0, 1));
}
else
- {
continueExec = FALSE;
- bError = QR_get_aborted(res);
- }
QR_Destructor(res);
}
else
@@ -2901,17 +2938,11 @@ getClientColumnName(ConnectionClass *conn, const char *serverTableName, char *se
}
/* restore the cleint encoding */
sprintf(query, "SET CLIENT_ENCODING TO '%s'", conn->client_encoding);
- if (res = CC_send_query(conn, query, NULL), res)
- {
- bError = QR_get_aborted(res);
- QR_Destructor(res);
- }
- else
- bError = TRUE;
+ bError = (CC_send_query(conn, query, NULL, TRUE) == NULL);
if (bError || !continueExec)
return ret;
sprintf(query, "select attname from pg_attribute where attrelid = %s and attnum = %s", saveattrelid, saveattnum);
- if (res = CC_send_query(conn, query, NULL), res)
+ if (res = CC_send_query(conn, query, NULL, TRUE), res)
{
if (QR_get_num_tuples(res) > 0)
{
@@ -2942,6 +2973,7 @@ PGAPI_ForeignKeys(
{
static char *func = "PGAPI_ForeignKeys";
StatementClass *stmt = (StatementClass *) hstmt;
+ QResultClass *res;
TupleNode *row;
HSTMT htbl_stmt,
hpkey_stmt;
@@ -2997,14 +3029,14 @@ PGAPI_ForeignKeys(
stmt->manual_result = TRUE;
stmt->errormsg_created = TRUE;
- stmt->result = QR_Constructor();
- if (!stmt->result)
+ if (res = QR_Constructor(), !res)
{
stmt->errormsg = "Couldn't allocate memory for PGAPI_ForeignKeys result.";
stmt->errornumber = STMT_NO_MEMORY_ERROR;
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
+ SC_set_Result(stmt, res);
/* the binding structure for a statement is not set up until */
@@ -3016,23 +3048,23 @@ PGAPI_ForeignKeys(
extend_bindings(stmt, result_cols);
/* set the field names */
- QR_set_num_fields(stmt->result, result_cols);
- QR_set_field_info(stmt->result, 0, "PKTABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 1, "PKTABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 2, "PKTABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 3, "PKCOLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 4, "FKTABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 5, "FKTABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 6, "FKTABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 7, "FKCOLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 8, "KEY_SEQ", PG_TYPE_INT2, 2);
- QR_set_field_info(stmt->result, 9, "UPDATE_RULE", PG_TYPE_INT2, 2);
- QR_set_field_info(stmt->result, 10, "DELETE_RULE", PG_TYPE_INT2, 2);
- QR_set_field_info(stmt->result, 11, "FK_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 12, "PK_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 13, "TRIGGER_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_num_fields(res, result_cols);
+ QR_set_field_info(res, 0, "PKTABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 1, "PKTABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 2, "PKTABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 3, "PKCOLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 4, "FKTABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 5, "FKTABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 6, "FKTABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 7, "FKCOLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 8, "KEY_SEQ", PG_TYPE_INT2, 2);
+ QR_set_field_info(res, 9, "UPDATE_RULE", PG_TYPE_INT2, 2);
+ QR_set_field_info(res, 10, "DELETE_RULE", PG_TYPE_INT2, 2);
+ QR_set_field_info(res, 11, "FK_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 12, "PK_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 13, "TRIGGER_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
#if (ODBCVER >= 0x0300)
- QR_set_field_info(stmt->result, 14, "DEFERRABILITY", PG_TYPE_INT2, 2);
+ QR_set_field_info(res, 14, "DEFERRABILITY", PG_TYPE_INT2, 2);
#endif /* ODBCVER >= 0x0300 */
/*
@@ -3369,7 +3401,7 @@ PGAPI_ForeignKeys(
set_tuplefield_int2(&row->tuple[14], defer_type);
#endif /* ODBCVER >= 0x0300 */
- QR_add_tuple(stmt->result, row);
+ QR_add_tuple(res, row);
#ifdef MULTIBYTE
if (fkey_alloced)
free(fkey_text);
@@ -3623,7 +3655,7 @@ PGAPI_ForeignKeys(
set_tuplefield_int2(&row->tuple[14], defer_type);
#endif /* ODBCVER >= 0x0300 */
- QR_add_tuple(stmt->result, row);
+ QR_add_tuple(res, row);
#ifdef MULTIBYTE
if (pkey_alloced)
free(pkey_text);
@@ -3687,10 +3719,13 @@ PGAPI_ProcedureColumns(
SWORD cbColumnName)
{
static char *func = "PGAPI_ProcedureColumns";
+ StatementClass *stmt = (StatementClass *) hstmt;
mylog("%s: entering...\n", func);
- SC_log_error(func, "Function not implemented", (StatementClass *) hstmt);
+ stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
+ stmt->errormsg = "not implemented";
+ SC_log_error(func, "Function not implemented", stmt);
return SQL_ERROR;
}
@@ -3717,7 +3752,7 @@ PGAPI_Procedures(
{
stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
stmt->errormsg = "Version is too old";
- SC_log_error(func, "Function not implemented", (StatementClass *) hstmt);
+ SC_log_error(func, "Function not implemented", stmt);
return SQL_ERROR;
}
if (!SC_recycle_statement(stmt))
@@ -3733,16 +3768,13 @@ PGAPI_Procedures(
" case when prorettype = 0 then 1::int2 else 2::int2 end as " "PROCEDURE_TYPE" " from pg_proc");
my_strcat(proc_query, " where proname like '%.*s'", szProcName, cbProcName);
- res = CC_send_query(conn, proc_query, NULL);
- if (!res || QR_aborted(res))
+ if (res = CC_send_query(conn, proc_query, NULL, TRUE), !res)
{
- if (res)
- QR_Destructor(res);
stmt->errornumber = STMT_EXEC_ERROR;
stmt->errormsg = "PGAPI_Procedures query error";
return SQL_ERROR;
}
- stmt->result = res;
+ SC_set_Result(stmt, res);
/*
* also, things need to think that this statement is finished so the
@@ -3759,6 +3791,52 @@ PGAPI_Procedures(
}
+#define ACLMAX 8
+#define ALL_PRIVILIGES "arwdRxt"
+static int
+usracl_auth(char *usracl, const char *auth)
+{
+ int i, j, addcnt = 0;
+
+ for (i = 0; auth[i]; i++)
+ {
+ for (j = 0; j < ACLMAX; j++)
+ {
+ if (usracl[j] == auth[i])
+ break;
+ else if (!usracl[j])
+ {
+ usracl[j]= auth[i];
+ addcnt++;
+ break;
+ }
+ }
+ }
+ return addcnt;
+}
+static void
+useracl_upd(char (*useracl)[ACLMAX], QResultClass *allures, const char *user, const char *auth)
+{
+ int usercount = QR_get_num_tuples(allures), i, addcnt = 0;
+
+mylog("user=%s auth=%s\n", user, auth);
+ if (user[0])
+ for (i = 0; i < usercount; i++)
+ {
+ if (strcmp(QR_get_value_backend_row(allures, i, 0), user) == 0)
+ {
+ addcnt += usracl_auth(useracl[i], auth);
+ break;
+ }
+ }
+ else
+ for (i = 0; i < usercount; i++)
+ {
+ addcnt += usracl_auth(useracl[i], auth);
+ }
+ mylog("addcnt=%d\n", addcnt);
+}
+
RETCODE SQL_API
PGAPI_TablePrivileges(
HSTMT hstmt,
@@ -3767,13 +3845,24 @@ PGAPI_TablePrivileges(
UCHAR FAR * szTableOwner,
SWORD cbTableOwner,
UCHAR FAR * szTableName,
- SWORD cbTableName)
+ SWORD cbTableName,
+ UWORD flag)
{
StatementClass *stmt = (StatementClass *) hstmt;
static char *func = "PGAPI_TablePrivileges";
+ ConnectionClass *conn = SC_get_conn(stmt);
Int2 result_cols;
+ char proc_query[INFO_INQUIRY_LEN];
+ QResultClass *res, *allures = NULL;
+ TupleNode *row;
+ int tablecount, usercount, i, j, k;
+ BOOL grpauth, sys, su;
+ char (*useracl)[ACLMAX], *acl, *user, *delim, *auth;
+ char *reln, *owner, *priv;
mylog("%s: entering...\n", func);
+ if (!SC_recycle_statement(stmt))
+ return SQL_ERROR;
/*
* a statement is actually executed, so we'll have to do this
@@ -3784,16 +3873,187 @@ PGAPI_TablePrivileges(
/* set the field names */
stmt->manual_result = TRUE;
- stmt->result = QR_Constructor();
- QR_set_num_fields(stmt->result, result_cols);
- QR_set_field_info(stmt->result, 0, "TABLE_CAT", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 1, "TABLE_SCHEM", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 2, "TABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 3, "GRANTOR", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 4, "GRANTEE", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 5, "PRIVILEGE", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 6, "IS_GRANTABLE", PG_TYPE_TEXT, MAX_INFO_STRING);
-
- SC_log_error(func, "Function not implemented", (StatementClass *) hstmt);
- return SQL_ERROR;
+ res = QR_Constructor();
+ SC_set_Result(stmt, res);
+ QR_set_num_fields(res, result_cols);
+ QR_set_field_info(res, 0, "TABLE_CAT", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 1, "TABLE_SCHEM", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 2, "TABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 3, "GRANTOR", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 4, "GRANTEE", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 5, "PRIVILEGE", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 6, "IS_GRANTABLE", PG_TYPE_TEXT, MAX_INFO_STRING);
+
+ /*
+ * also, things need to think that this statement is finished so the
+ * results can be retrieved.
+ */
+ stmt->status = STMT_FINISHED;
+ /* set up the current tuple pointer for SQLFetch */
+ stmt->currTuple = -1;
+ stmt->rowset_start = -1;
+ stmt->current_col = -1;
+ strncpy_null(proc_query, "select relname, usename, relacl from pg_class , pg_user where", sizeof(proc_query));
+ if ((flag & PODBC_NOT_SEARCH_PATTERN) != 0)
+ my_strcat(proc_query, " relname = '%.*s' and", szTableName, cbTableName);
+ else
+ {
+ char esc_table_name[MAX_TABLE_LEN * 2];
+ int escTbnamelen;
+
+ escTbnamelen = reallyEscapeCatalogEscapes(szTableName, cbTableName, esc_table_name, sizeof(esc_table_name), conn->ccsc);
+ my_strcat(proc_query, " relname like '%.*s' and", esc_table_name, escTbnamelen);
+ }
+ strcat(proc_query, " pg_user.usesysid = relowner");
+ if (res = CC_send_query(conn, proc_query, NULL, TRUE), !res)
+ {
+ stmt->errornumber = STMT_EXEC_ERROR;
+ stmt->errormsg = "PGAPI_TablePrivileges query error";
+ return SQL_ERROR;
+ }
+ strncpy_null(proc_query, "select usename, usesysid, usesuper from pg_user", sizeof(proc_query));
+ tablecount = QR_get_num_tuples(res);
+ if (allures = CC_send_query(conn, proc_query, NULL, TRUE), !allures)
+ {
+ QR_Destructor(res);
+ stmt->errornumber = STMT_EXEC_ERROR;
+ stmt->errormsg = "PGAPI_TablePrivileges query error";
+ return SQL_ERROR;
+ }
+ usercount = QR_get_num_tuples(allures);
+ useracl = (char (*)[ACLMAX]) malloc(usercount * sizeof(char [ACLMAX]));
+ for (i = 0; i < tablecount; i++)
+ {
+ memset(useracl, 0, usercount * sizeof(char[ACLMAX]));
+ acl = (char *) QR_get_value_backend_row(res, i, 2);
+ if (acl && acl[0] == '{')
+ user = acl + 1;
+ else
+ user = NULL;
+ for (; user && *user;)
+ {
+ grpauth = FALSE;
+ if (user[0] == '"' && strncmp(user + 1, "group ", 6) == 0)
+ {
+ user += 7;
+ grpauth = TRUE;
+ }
+ if (delim = strchr(user, '='), !delim)
+ break;
+ *delim = '\0';
+ auth = delim + 1;
+ if (grpauth)
+ {
+ if (delim = strchr(auth, '"'), delim)
+ {
+ *delim = '\0';
+ delim++;
+ }
+ }
+ else if (delim = strchr(auth, ','), delim)
+ *delim = '\0';
+ else if (delim = strchr(auth, '}'), delim)
+ *delim = '\0';
+ if (grpauth) /* handle group privilege */
+ {
+ QResultClass *gres;
+ int i;
+ char *grolist, *uid, *delm;
+
+ snprintf(proc_query, sizeof(proc_query) - 1, "select grolist from pg_group where groname = '%s'", user);
+ if (gres = CC_send_query(conn, proc_query, NULL, TRUE))
+ {
+ grolist = QR_get_value_backend_row(gres, 0, 0);
+ if (grolist && grolist[0] == '{')
+ {
+ for (uid = grolist + 1; *uid;)
+ {
+ if (delm = strchr(uid, ','), delm)
+ *delm = '\0';
+ else if (delm = strchr(uid, '}'), delm)
+ *delm = '\0';
+mylog("guid=%s\n", uid);
+ for (i = 0; i < usercount; i++)
+ {
+ if (strcmp(QR_get_value_backend_row(allures, i, 1), uid) == 0)
+ useracl_upd(useracl, allures, QR_get_value_backend_row(allures, i, 0), auth);
+ }
+ uid = delm + 1;
+ }
+ }
+ QR_Destructor(gres);
+ }
+ }
+ else
+ useracl_upd(useracl, allures, user, auth);
+ if (!delim)
+ break;
+ user = delim + 1;
+ }
+ reln = QR_get_value_backend_row(res, i, 0);
+ owner = QR_get_value_backend_row(res, i, 1);
+ /* The owner has all privileges */
+ useracl_upd(useracl, allures, owner, ALL_PRIVILIGES);
+ for (j = 0; j < usercount; j++)
+ {
+ user = QR_get_value_backend_row(allures, j, 0);
+ su = (strcmp(QR_get_value_backend_row(allures, j, 2), "t") == 0);
+ sys = (strcmp(user, owner) == 0);
+ /* Super user has all privileges */
+ if (su)
+ useracl_upd(useracl, allures, user, ALL_PRIVILIGES);
+ for (k = 0; k < ACLMAX; k++)
+ {
+ if (!useracl[j][k])
+ break;
+ switch (useracl[j][k])
+ {
+ case 'R': /* rule */
+ case 't': /* trigger */
+ continue;
+ }
+ row = (TupleNode *) malloc(sizeof(TupleNode) + (7 - 1) *sizeof(TupleField));
+ set_tuplefield_string(&row->tuple[0], "");
+ set_tuplefield_string(&row->tuple[1], "");
+ set_tuplefield_string(&row->tuple[2], reln);
+ if (su || sys)
+ set_tuplefield_string(&row->tuple[3], "_SYSTEM");
+ else
+ set_tuplefield_string(&row->tuple[3], owner);
+ mylog("user=%s\n", user);
+ set_tuplefield_string(&row->tuple[4], user);
+ switch (useracl[j][k])
+ {
+ case 'a':
+ priv = "INSERT";
+ break;
+ case 'r':
+ priv = "SELECT";
+ break;
+ case 'w':
+ priv = "UPDATE";
+ break;
+ case 'd':
+ priv = "DELETE";
+ break;
+ case 'x':
+ priv = "REFERENCES";
+ break;
+ default:
+ priv = "";
+ }
+ set_tuplefield_string(&row->tuple[5], priv);
+ /* The owner and the super user are grantable */
+ if (sys || su)
+ set_tuplefield_string(&row->tuple[6], "YES");
+ else
+ set_tuplefield_string(&row->tuple[6], "NO");
+ QR_add_tuple(SC_get_Result(stmt), row);
+ }
+ }
+ }
+ free(useracl);
+ QR_Destructor(res);
+ QR_Destructor(allures);
+ return SQL_SUCCESS;
}