Commit f8abefe4 authored by Bruce Momjian's avatar Bruce Momjian

Here is a diff to info.c in interfaces/odbc that updates SQLForeignKeys to

return foreign key information based on the pg_trigger system table.  I
have tested the patch with (what I believe) is all possible
primary/foreign key combinations -- however I may have missed some, so if
anyone feels like taking the patch for a test drive, here are some useful
links:

Michael Fork
parent e19c8acc
...@@ -2252,11 +2252,15 @@ HSTMT htbl_stmt, hpkey_stmt; ...@@ -2252,11 +2252,15 @@ HSTMT htbl_stmt, hpkey_stmt;
StatementClass *tbl_stmt; StatementClass *tbl_stmt;
RETCODE result, keyresult; RETCODE result, keyresult;
char tables_query[MAX_STATEMENT_LEN]; char tables_query[MAX_STATEMENT_LEN];
char args[1024], tgname[MAX_INFO_STRING]; char trig_deferrable[2];
char pktab[MAX_TABLE_LEN + 1], fktab[MAX_TABLE_LEN + 1]; char trig_initdeferred[2];
char *ptr, *pkey_ptr, *pkptr, *fkptr, *frel, *prel; char trig_args[1024];
int i, k, pkeys, seq, ntabs; char upd_rule[MAX_NAME_LEN], del_rule[MAX_NAME_LEN];
SWORD nargs, rule_type, action; char pk_table_needed[MAX_TABLE_LEN + 1];
char fk_table_needed[MAX_TABLE_LEN + 1];
char *pkey_ptr, *fkey_ptr, *pk_table, *fk_table;
int i, j, k, num_keys;
SWORD trig_nargs, upd_rule_type, del_rule_type, defer_type;
char pkey[MAX_INFO_STRING]; char pkey[MAX_INFO_STRING];
Int2 result_cols; Int2 result_cols;
...@@ -2268,6 +2272,7 @@ Int2 result_cols; ...@@ -2268,6 +2272,7 @@ Int2 result_cols;
SC_log_error(func, "", NULL); SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE; return SQL_INVALID_HANDLE;
} }
stmt->manual_result = TRUE; stmt->manual_result = TRUE;
stmt->errormsg_created = TRUE; stmt->errormsg_created = TRUE;
...@@ -2301,6 +2306,9 @@ Int2 result_cols; ...@@ -2301,6 +2306,9 @@ Int2 result_cols;
QR_set_field_info(stmt->result, 11, "FK_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); 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, 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_field_info(stmt->result, 13, "TRIGGER_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
#if (ODBCVER >= 0x0300)
QR_set_field_info(stmt->result, 14, "DEFERRABILITY", PG_TYPE_INT2, 2);
#endif /* ODBCVER >= 0x0300 */
/* also, things need to think that this statement is finished so */ /* also, things need to think that this statement is finished so */
/* the results can be retrieved. */ /* the results can be retrieved. */
...@@ -2322,25 +2330,46 @@ Int2 result_cols; ...@@ -2322,25 +2330,46 @@ Int2 result_cols;
tbl_stmt = (StatementClass *) htbl_stmt; tbl_stmt = (StatementClass *) htbl_stmt;
pktab[0] = '\0'; pk_table_needed[0] = '\0';
fktab[0] = '\0'; fk_table_needed[0] = '\0';
make_string(szPkTableName, cbPkTableName, pktab);
make_string(szFkTableName, cbFkTableName, fktab);
make_string(szPkTableName, cbPkTableName, pk_table_needed);
make_string(szFkTableName, cbFkTableName, fk_table_needed);
/* Case #2 -- Get the foreign keys in the specified table (fktab) that /* Case #2 -- Get the foreign keys in the specified table (fktab) that
refer to the primary keys of other table(s). refer to the primary keys of other table(s).
*/ */
if (fktab[0] != '\0') { if (fk_table_needed[0] != '\0') {
mylog("%s: entering Foreign Key Case #2", func);
sprintf(tables_query, "select pg_trigger.tgargs, pg_trigger.tgnargs, pg_trigger.tgname" sprintf(tables_query, "SELECT pt.tgargs, "
" from pg_proc, pg_trigger, pg_class" " pt.tgnargs, "
" where pg_proc.oid = pg_trigger.tgfoid and pg_trigger.tgrelid = pg_class.oid" " pt.tgdeferrable, "
" AND pg_proc.proname = 'check_primary_key' AND pg_class.relname = '%s'", " pt.tginitdeferred, "
fktab); " pg_proc.proname, "
" pg_proc_1.proname "
"FROM pg_class pc, "
" pg_proc pg_proc, "
" pg_proc pg_proc_1, "
" pg_trigger pg_trigger, "
" pg_trigger pg_trigger_1, "
" pg_proc pp, "
" pg_trigger pt "
"WHERE pt.tgrelid = pc.oid "
"AND pp.oid = pt.tgfoid "
"AND pg_trigger.tgconstrrelid = pc.oid "
"AND pg_proc.oid = pg_trigger.tgfoid "
"AND pg_trigger_1.tgfoid = pg_proc_1.oid "
"AND pg_trigger_1.tgconstrrelid = pc.oid "
"AND ((pc.relname='%s') "
"AND (pp.proname LIKE '%%ins') "
"AND (pg_proc.proname LIKE '%%upd') "
"AND (pg_proc_1.proname LIKE '%%del') "
"AND (pg_trigger.tgrelid=pt.tgconstrrelid) "
"AND (pg_trigger_1.tgrelid = pt.tgconstrrelid))",
fk_table_needed);
result = SQLExecDirect(htbl_stmt, tables_query, strlen(tables_query)); result = SQLExecDirect(htbl_stmt, tables_query, strlen(tables_query));
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
stmt->errormsg = SC_create_errormsg(htbl_stmt); stmt->errormsg = SC_create_errormsg(htbl_stmt);
stmt->errornumber = tbl_stmt->errornumber; stmt->errornumber = tbl_stmt->errornumber;
...@@ -2350,7 +2379,7 @@ Int2 result_cols; ...@@ -2350,7 +2379,7 @@ Int2 result_cols;
} }
result = SQLBindCol(htbl_stmt, 1, SQL_C_BINARY, result = SQLBindCol(htbl_stmt, 1, SQL_C_BINARY,
args, MAX_INFO_STRING, NULL); trig_args, sizeof(trig_args), NULL);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
stmt->errormsg = tbl_stmt->errormsg; stmt->errormsg = tbl_stmt->errormsg;
stmt->errornumber = tbl_stmt->errornumber; stmt->errornumber = tbl_stmt->errornumber;
...@@ -2360,7 +2389,7 @@ Int2 result_cols; ...@@ -2360,7 +2389,7 @@ Int2 result_cols;
} }
result = SQLBindCol(htbl_stmt, 2, SQL_C_SHORT, result = SQLBindCol(htbl_stmt, 2, SQL_C_SHORT,
&nargs, 0, NULL); &trig_nargs, 0, NULL);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
stmt->errormsg = tbl_stmt->errormsg; stmt->errormsg = tbl_stmt->errormsg;
stmt->errornumber = tbl_stmt->errornumber; stmt->errornumber = tbl_stmt->errornumber;
...@@ -2370,7 +2399,37 @@ Int2 result_cols; ...@@ -2370,7 +2399,37 @@ Int2 result_cols;
} }
result = SQLBindCol(htbl_stmt, 3, SQL_C_CHAR, result = SQLBindCol(htbl_stmt, 3, SQL_C_CHAR,
tgname, sizeof(tgname), NULL); trig_deferrable, sizeof(trig_deferrable), NULL);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
stmt->errormsg = tbl_stmt->errormsg;
stmt->errornumber = tbl_stmt->errornumber;
SC_log_error(func, "", stmt);
SQLFreeStmt(htbl_stmt, SQL_DROP);
return SQL_ERROR;
}
result = SQLBindCol(htbl_stmt, 4, SQL_C_CHAR,
trig_initdeferred, sizeof(trig_initdeferred), NULL);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
stmt->errormsg = tbl_stmt->errormsg;
stmt->errornumber = tbl_stmt->errornumber;
SC_log_error(func, "", stmt);
SQLFreeStmt(htbl_stmt, SQL_DROP);
return SQL_ERROR;
}
result = SQLBindCol(htbl_stmt, 5, SQL_C_CHAR,
upd_rule, sizeof(upd_rule), NULL);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
stmt->errormsg = tbl_stmt->errormsg;
stmt->errornumber = tbl_stmt->errornumber;
SC_log_error(func, "", stmt);
SQLFreeStmt(htbl_stmt, SQL_DROP);
return SQL_ERROR;
}
result = SQLBindCol(htbl_stmt, 6, SQL_C_CHAR,
del_rule, sizeof(del_rule), NULL);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
stmt->errormsg = tbl_stmt->errormsg; stmt->errormsg = tbl_stmt->errormsg;
stmt->errornumber = tbl_stmt->errornumber; stmt->errornumber = tbl_stmt->errornumber;
...@@ -2412,31 +2471,27 @@ Int2 result_cols; ...@@ -2412,31 +2471,27 @@ Int2 result_cols;
while (result == SQL_SUCCESS) { while (result == SQL_SUCCESS) {
/* Compute the number of keyparts. */ /* Compute the number of keyparts. */
pkeys = nargs / 2; num_keys = (trig_nargs - 4) / 2;
mylog("Foreign Key Case#2: nargs = %d, pkeys = %d\n", nargs, pkeys); mylog("Foreign Key Case#2: trig_nargs = %d, num_keys = %d\n", trig_nargs, num_keys);
ptr = args; pk_table = trig_args;
/* Get to the PK Table Name */ /* Get to the PK Table Name */
for (k = 0; k < pkeys; k++) for (k = 0; k < 2; k++)
ptr += strlen(ptr) + 1; pk_table += strlen(pk_table) + 1;
prel = ptr;
mylog("prel = '%s'\n", prel);
/* If there is a pk table specified, then check it. */ /* If there is a pk table specified, then check it. */
if (pktab[0] != '\0') { if (pk_table_needed[0] != '\0') {
/* If it doesn't match, then continue */ /* If it doesn't match, then continue */
if ( strcmp(prel, pktab)) { if ( strcmp(pk_table, pk_table_needed)) {
result = SQLFetch(htbl_stmt); result = SQLFetch(htbl_stmt);
continue; continue;
} }
} }
keyresult = SQLPrimaryKeys(hpkey_stmt, NULL, 0, NULL, 0, prel, SQL_NTS); keyresult = SQLPrimaryKeys(hpkey_stmt, NULL, 0, NULL, 0, pk_table, SQL_NTS);
if (keyresult != SQL_SUCCESS) { if (keyresult != SQL_SUCCESS) {
stmt->errornumber = STMT_NO_MEMORY_ERROR; stmt->errornumber = STMT_NO_MEMORY_ERROR;
stmt->errormsg = "Couldn't get primary keys for SQLForeignKeys result."; stmt->errormsg = "Couldn't get primary keys for SQLForeignKeys result.";
...@@ -2448,76 +2503,147 @@ Int2 result_cols; ...@@ -2448,76 +2503,147 @@ Int2 result_cols;
/* Check that the key listed is the primary key */ /* Check that the key listed is the primary key */
keyresult = SQLFetch(hpkey_stmt); keyresult = SQLFetch(hpkey_stmt);
for (k = 0; k < pkeys; k++) {
ptr += strlen(ptr) + 1; /* Get to first primary key */
if ( keyresult != SQL_SUCCESS || strcmp(ptr, pkey)) { pkey_ptr = trig_args;
pkeys = 0; for (i = 0; i < 5; i++)
pkey_ptr += strlen(pkey_ptr) + 1;
for (k = 0; k < num_keys; k++) {
mylog("%s: pkey_ptr='%s', pkey='%s'\n", func, pkey_ptr, pkey);
if ( keyresult != SQL_SUCCESS || strcmp(pkey_ptr, pkey)) {
num_keys = 0;
break; break;
} }
/* Get to next primary key */
for (k = 0; k < 2; k++)
pkey_ptr += strlen(pkey_ptr) + 1;
keyresult = SQLFetch(hpkey_stmt); keyresult = SQLFetch(hpkey_stmt);
} }
ptr = prel;
/* Set to first fk column */
fkey_ptr = trig_args;
for (k = 0; k < 4; k++)
fkey_ptr += strlen(fkey_ptr) + 1;
/* Set update and delete actions for foreign keys */
if (!strcmp(upd_rule, "RI_FKey_cascade_upd")) {
upd_rule_type = SQL_CASCADE;
} else if (!strcmp(upd_rule, "RI_FKey_noaction_upd")) {
upd_rule_type = SQL_NO_ACTION;
} else if (!strcmp(upd_rule, "RI_FKey_restrict_upd")) {
upd_rule_type = SQL_NO_ACTION;
} else if (!strcmp(upd_rule, "RI_FKey_setdefault_upd")) {
upd_rule_type = SQL_SET_DEFAULT;
} else if (!strcmp(upd_rule, "RI_FKey_setnull_upd")) {
upd_rule_type = SQL_SET_NULL;
}
if (!strcmp(upd_rule, "RI_FKey_cascade_del")) {
del_rule_type = SQL_CASCADE;
} else if (!strcmp(upd_rule, "RI_FKey_noaction_del")) {
del_rule_type = SQL_NO_ACTION;
} else if (!strcmp(upd_rule, "RI_FKey_restrict_del")) {
del_rule_type = SQL_NO_ACTION;
} else if (!strcmp(upd_rule, "RI_FKey_setdefault_del")) {
del_rule_type = SQL_SET_DEFAULT;
} else if (!strcmp(upd_rule, "RI_FKey_setnull_del")) {
del_rule_type = SQL_SET_NULL;
}
#if (ODBCVER >= 0x0300)
/* Set deferrability type */
if (!strcmp(trig_initdeferred, "y")) {
defer_type = SQL_INITIALLY_DEFERRED;
} else if (!strcmp(trig_deferrable, "y")) {
defer_type = SQL_INITIALLY_IMMEDIATE;
} else {
defer_type = SQL_NOT_DEFERRABLE;
}
#endif /* ODBCVER >= 0x0300 */
/* Set to first fk column */ /* Get to first primary key */
fkptr = args; pkey_ptr = trig_args;
seq = 0; for (i = 0; i < 5; i++)
pkey_ptr += strlen(pkey_ptr) + 1;
for (k = 0; k < pkeys; k++) { for (k = 0; k < num_keys; k++) {
row = (TupleNode *)malloc(sizeof(TupleNode) + (result_cols - 1) * sizeof(TupleField)); row = (TupleNode *)malloc(sizeof(TupleNode) + (result_cols - 1) * sizeof(TupleField));
mylog("%s: pk_table = '%s', pkey_ptr = '%s'\n", func, pk_table, pkey_ptr);
set_tuplefield_null(&row->tuple[0]); set_tuplefield_null(&row->tuple[0]);
set_tuplefield_string(&row->tuple[1], ""); set_tuplefield_string(&row->tuple[1], "");
set_tuplefield_string(&row->tuple[2], pk_table);
set_tuplefield_string(&row->tuple[3], pkey_ptr);
set_tuplefield_string(&row->tuple[2], prel); mylog("%s: fk_table_needed = '%s', fkey_ptr = '%s'\n", func, fk_table_needed, fkey_ptr);
/* Get to the primary key */
ptr += strlen(ptr) + 1;
mylog("prel = '%s', ptr = '%s'\n", prel, ptr);
set_tuplefield_string(&row->tuple[3], ptr);
set_tuplefield_null(&row->tuple[4]); set_tuplefield_null(&row->tuple[4]);
set_tuplefield_string(&row->tuple[5], ""); set_tuplefield_string(&row->tuple[5], "");
set_tuplefield_string(&row->tuple[6], fk_table_needed);
set_tuplefield_string(&row->tuple[7], fkey_ptr);
set_tuplefield_string(&row->tuple[6], fktab); mylog("%s: upd_rule_type = '%i', del_rule_type = '%i'\n, trig_name = '%s'", func, upd_rule_type, del_rule_type, trig_args);
set_tuplefield_string(&row->tuple[7], fkptr); set_tuplefield_int2(&row->tuple[8], (Int2) (k + 1));
set_tuplefield_int2(&row->tuple[9], (Int2) upd_rule_type);
mylog("fktab = '%s', fkptr = '%s'\n", fktab, fkptr); set_tuplefield_int2(&row->tuple[10], (Int2) del_rule_type);
set_tuplefield_int2(&row->tuple[8], (Int2) (++seq));
set_tuplefield_null(&row->tuple[9]);
set_tuplefield_null(&row->tuple[10]);
set_tuplefield_null(&row->tuple[11]); set_tuplefield_null(&row->tuple[11]);
set_tuplefield_null(&row->tuple[12]); set_tuplefield_null(&row->tuple[12]);
set_tuplefield_string(&row->tuple[13], trig_args);
set_tuplefield_string(&row->tuple[13], tgname); #if (ODBCVER >= 0x0300)
set_tuplefield_int2(&row->tuple[14], defer_type);
#endif /* ODBCVER >= 0x0300 */
QR_add_tuple(stmt->result, row); QR_add_tuple(stmt->result, row);
/* next foreign key */ /* next primary/foreign key */
fkptr += strlen(fkptr) + 1; for (i = 0; i < 2; i++) {
fkey_ptr += strlen(fkey_ptr) + 1;
pkey_ptr += strlen(pkey_ptr) + 1;
}
} }
result = SQLFetch(htbl_stmt); result = SQLFetch(htbl_stmt);
} }
SQLFreeStmt(hpkey_stmt, SQL_DROP);
} }
/* Case #1 -- Get the foreign keys in other tables that refer to the primary key /* Case #1 -- Get the foreign keys in other tables that refer to the primary key
in the specified table (pktab). i.e., Who points to me? in the specified table (pktab). i.e., Who points to me?
*/ */
else if (pktab[0] != '\0') { else if (pk_table_needed[0] != '\0') {
sprintf(tables_query, "select pg_trigger.tgargs, pg_trigger.tgnargs" sprintf(tables_query, "SELECT pg_trigger.tgargs, "
", pg_trigger.tgtype, pg_trigger.tgname" " pg_trigger.tgnargs, "
" from pg_proc, pg_trigger, pg_class" " pg_trigger.tgdeferrable, "
" where pg_proc.oid = pg_trigger.tgfoid and pg_trigger.tgrelid = pg_class.oid" " pg_trigger.tginitdeferred, "
" AND pg_proc.proname = 'check_foreign_key' AND pg_class.relname = '%s'", " pg_proc.proname, "
pktab); " pg_proc_1.proname "
"FROM pg_class pg_class, "
" pg_class pg_class_1, "
" pg_class pg_class_2, "
" pg_proc pg_proc, "
" pg_proc pg_proc_1, "
" pg_trigger pg_trigger, "
" pg_trigger pg_trigger_1, "
" pg_trigger pg_trigger_2 "
"WHERE pg_trigger.tgconstrrelid = pg_class.oid "
" AND pg_trigger.tgrelid = pg_class_1.oid "
" AND pg_trigger_1.tgfoid = pg_proc_1.oid "
" AND pg_trigger_1.tgconstrrelid = pg_class_1.oid "
" AND pg_trigger_2.tgconstrrelid = pg_class_2.oid "
" AND pg_trigger_2.tgfoid = pg_proc.oid "
" AND pg_class_2.oid = pg_trigger.tgrelid "
" AND ("
" (pg_class.relname='%s') "
" AND (pg_proc.proname Like '%%upd') "
" AND (pg_proc_1.proname Like '%%del')"
" AND (pg_trigger_1.tgrelid = pg_trigger.tgconstrrelid) "
" AND (pg_trigger_2.tgrelid = pg_trigger.tgconstrrelid) "
" )",
pk_table_needed);
result = SQLExecDirect(htbl_stmt, tables_query, strlen(tables_query)); result = SQLExecDirect(htbl_stmt, tables_query, strlen(tables_query));
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
...@@ -2529,7 +2655,7 @@ Int2 result_cols; ...@@ -2529,7 +2655,7 @@ Int2 result_cols;
} }
result = SQLBindCol(htbl_stmt, 1, SQL_C_BINARY, result = SQLBindCol(htbl_stmt, 1, SQL_C_BINARY,
args, sizeof(args), NULL); trig_args, sizeof(trig_args), NULL);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
stmt->errormsg = tbl_stmt->errormsg; stmt->errormsg = tbl_stmt->errormsg;
stmt->errornumber = tbl_stmt->errornumber; stmt->errornumber = tbl_stmt->errornumber;
...@@ -2539,7 +2665,7 @@ Int2 result_cols; ...@@ -2539,7 +2665,7 @@ Int2 result_cols;
} }
result = SQLBindCol(htbl_stmt, 2, SQL_C_SHORT, result = SQLBindCol(htbl_stmt, 2, SQL_C_SHORT,
&nargs, 0, NULL); &trig_nargs, 0, NULL);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
stmt->errormsg = tbl_stmt->errormsg; stmt->errormsg = tbl_stmt->errormsg;
stmt->errornumber = tbl_stmt->errornumber; stmt->errornumber = tbl_stmt->errornumber;
...@@ -2548,8 +2674,8 @@ Int2 result_cols; ...@@ -2548,8 +2674,8 @@ Int2 result_cols;
return SQL_ERROR; return SQL_ERROR;
} }
result = SQLBindCol(htbl_stmt, 3, SQL_C_SHORT, result = SQLBindCol(htbl_stmt, 3, SQL_C_CHAR,
&rule_type, 0, NULL); trig_deferrable, sizeof(trig_deferrable), NULL);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
stmt->errormsg = tbl_stmt->errormsg; stmt->errormsg = tbl_stmt->errormsg;
stmt->errornumber = tbl_stmt->errornumber; stmt->errornumber = tbl_stmt->errornumber;
...@@ -2559,7 +2685,7 @@ Int2 result_cols; ...@@ -2559,7 +2685,7 @@ Int2 result_cols;
} }
result = SQLBindCol(htbl_stmt, 4, SQL_C_CHAR, result = SQLBindCol(htbl_stmt, 4, SQL_C_CHAR,
tgname, sizeof(tgname), NULL); trig_initdeferred, sizeof(trig_initdeferred), NULL);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
stmt->errormsg = tbl_stmt->errormsg; stmt->errormsg = tbl_stmt->errormsg;
stmt->errornumber = tbl_stmt->errornumber; stmt->errornumber = tbl_stmt->errornumber;
...@@ -2568,147 +2694,137 @@ Int2 result_cols; ...@@ -2568,147 +2694,137 @@ Int2 result_cols;
return SQL_ERROR; return SQL_ERROR;
} }
result = SQLFetch(htbl_stmt); result = SQLBindCol(htbl_stmt, 5, SQL_C_CHAR,
if (result == SQL_NO_DATA_FOUND) upd_rule, sizeof(upd_rule), NULL);
return SQL_SUCCESS; if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
stmt->errormsg = tbl_stmt->errormsg;
if(result != SQL_SUCCESS) {
stmt->errormsg = SC_create_errormsg(htbl_stmt);
stmt->errornumber = tbl_stmt->errornumber; stmt->errornumber = tbl_stmt->errornumber;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
SQLFreeStmt(htbl_stmt, SQL_DROP); SQLFreeStmt(htbl_stmt, SQL_DROP);
return SQL_ERROR; return SQL_ERROR;
} }
keyresult = SQLAllocStmt( stmt->hdbc, &hpkey_stmt); result = SQLBindCol(htbl_stmt, 6, SQL_C_CHAR,
if((keyresult != SQL_SUCCESS) && (keyresult != SQL_SUCCESS_WITH_INFO)) { del_rule, sizeof(del_rule), NULL);
stmt->errornumber = STMT_NO_MEMORY_ERROR; if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
stmt->errormsg = "Couldn't allocate statement for SQLForeignKeys (pkeys) result."; stmt->errormsg = tbl_stmt->errormsg;
stmt->errornumber = tbl_stmt->errornumber;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
SQLFreeStmt(htbl_stmt, SQL_DROP);
return SQL_ERROR; return SQL_ERROR;
} }
keyresult = SQLPrimaryKeys(hpkey_stmt, NULL, 0, NULL, 0, pktab, SQL_NTS); result = SQLFetch(htbl_stmt);
if (keyresult != SQL_SUCCESS) { if (result == SQL_NO_DATA_FOUND)
stmt->errornumber = STMT_NO_MEMORY_ERROR; return SQL_SUCCESS;
stmt->errormsg = "Couldn't get primary keys for SQLForeignKeys result.";
SC_log_error(func, "", stmt);
SQLFreeStmt(hpkey_stmt, SQL_DROP);
return SQL_ERROR;
}
keyresult = SQLBindCol(hpkey_stmt, 4, SQL_C_CHAR, if(result != SQL_SUCCESS) {
pkey, sizeof(pkey), NULL); stmt->errormsg = SC_create_errormsg(htbl_stmt);
if (keyresult != SQL_SUCCESS) { stmt->errornumber = tbl_stmt->errornumber;
stmt->errornumber = STMT_NO_MEMORY_ERROR;
stmt->errormsg = "Couldn't bindcol for primary keys for SQLForeignKeys result.";
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
SQLFreeStmt(hpkey_stmt, SQL_DROP); SQLFreeStmt(htbl_stmt, SQL_DROP);
return SQL_ERROR; return SQL_ERROR;
} }
while (result == SQL_SUCCESS) { while (result == SQL_SUCCESS) {
/* Get the number of tables */
ptr = args;
ntabs = atoi(args);
ptr += strlen(ptr) + 1;
/* Handle action (i.e., 'cascade', 'restrict', 'setnull') */
switch(tolower((unsigned char) ptr[0])) {
case 'c':
action = SQL_CASCADE;
break;
case 'r':
action = SQL_RESTRICT;
break;
case 's':
action = SQL_SET_NULL;
break;
default:
action = -1;
break;
}
rule_type >>= TRIGGER_SHIFT;
ptr += strlen(ptr) + 1;
/* Calculate the number of key parts */ /* Calculate the number of key parts */
pkeys = (nargs - ( 2 + ntabs)) / (ntabs + 1); num_keys = (trig_nargs - 4) / 2;;
pkey_ptr = ptr;
keyresult = SQLExtendedFetch(hpkey_stmt, SQL_FETCH_FIRST, -1, NULL, NULL);
if ( keyresult != SQL_SUCCESS || strcmp(pkey, ptr)) {
ntabs = 0;
}
/* Get to the last primary keypart */
for (i = 1; i < pkeys; i++) {
/* If keypart doesnt match, skip this entry */
if ( keyresult != SQL_SUCCESS || strcmp(pkey, ptr)) {
ntabs = 0;
break;
}
ptr += strlen(ptr) + 1;
keyresult = SQLExtendedFetch(hpkey_stmt, SQL_FETCH_NEXT, -1, NULL, NULL);
}
mylog("Foreign Key Case#1: nargs = %d, ntabs = %d, pkeys = %d\n", nargs, ntabs, pkeys);
/* Handle action (i.e., 'cascade', 'restrict', 'setnull') */
/* Get Foreign Key Tables */ if (!strcmp(upd_rule, "RI_FKey_cascade_upd")) {
for (i = 0; i < ntabs; i++) { upd_rule_type = SQL_CASCADE;
} else if (!strcmp(upd_rule, "RI_FKey_noaction_upd")) {
seq = 0; upd_rule_type = SQL_NO_ACTION;
pkptr = pkey_ptr; } else if (!strcmp(upd_rule, "RI_FKey_restrict_upd")) {
upd_rule_type = SQL_NO_ACTION;
ptr += strlen(ptr) + 1; } else if (!strcmp(upd_rule, "RI_FKey_setdefault_upd")) {
frel = ptr; upd_rule_type = SQL_SET_DEFAULT;
} else if (!strcmp(upd_rule, "RI_FKey_setnull_upd")) {
for (k = 0; k < pkeys; k++) { upd_rule_type = SQL_SET_NULL;
}
if (!strcmp(upd_rule, "RI_FKey_cascade_del")) {
del_rule_type = SQL_CASCADE;
} else if (!strcmp(upd_rule, "RI_FKey_noaction_del")) {
del_rule_type = SQL_NO_ACTION;
} else if (!strcmp(upd_rule, "RI_FKey_restrict_del")) {
del_rule_type = SQL_NO_ACTION;
} else if (!strcmp(upd_rule, "RI_FKey_setdefault_del")) {
del_rule_type = SQL_SET_DEFAULT;
} else if (!strcmp(upd_rule, "RI_FKey_setnull_del")) {
del_rule_type = SQL_SET_NULL;
}
#if (ODBCVER >= 0x0300)
/* Set deferrability type */
if (!strcmp(trig_initdeferred, "y")) {
defer_type = SQL_INITIALLY_DEFERRED;
} else if (!strcmp(trig_deferrable, "y")) {
defer_type = SQL_INITIALLY_IMMEDIATE;
} else {
defer_type = SQL_NOT_DEFERRABLE;
}
#endif /* ODBCVER >= 0x0300 */
mylog("Foreign Key Case#1: trig_nargs = %d, num_keys = %d\n", trig_nargs, num_keys);
/* Get to first primary key */
pkey_ptr = trig_args;
for (i = 0; i < 5; i++)
pkey_ptr += strlen(pkey_ptr) + 1;
/* Get to first foreign table */
fk_table = trig_args;
fk_table += strlen(fk_table) + 1;
/* Get to first foreign key */
fkey_ptr = trig_args;
for (k = 0; k < 4; k++)
fkey_ptr += strlen(fkey_ptr) + 1;
for (k = 0; k < num_keys; k++) {
mylog("pkey_ptr = '%s', fk_table = '%s', fkey_ptr = '%s'\n", pkey_ptr, fk_table, fkey_ptr);
row = (TupleNode *)malloc(sizeof(TupleNode) + (result_cols - 1) * sizeof(TupleField)); row = (TupleNode *)malloc(sizeof(TupleNode) + (result_cols - 1) * sizeof(TupleField));
mylog("pk_table_needed = '%s', pkey_ptr = '%s'\n", pk_table_needed, pkey_ptr);
set_tuplefield_null(&row->tuple[0]); set_tuplefield_null(&row->tuple[0]);
set_tuplefield_string(&row->tuple[1], ""); set_tuplefield_string(&row->tuple[1], "");
set_tuplefield_string(&row->tuple[2], pk_table_needed);
set_tuplefield_string(&row->tuple[3], pkey_ptr);
set_tuplefield_string(&row->tuple[2], pktab); mylog("fk_table = '%s', fkey_ptr = '%s'\n", fk_table, fkey_ptr);
set_tuplefield_string(&row->tuple[3], pkptr);
mylog("pktab = '%s', pkptr = '%s'\n", pktab, pkptr);
set_tuplefield_null(&row->tuple[4]); set_tuplefield_null(&row->tuple[4]);
set_tuplefield_string(&row->tuple[5], ""); set_tuplefield_string(&row->tuple[5], "");
set_tuplefield_string(&row->tuple[6], frel); set_tuplefield_string(&row->tuple[6], fk_table);
set_tuplefield_string(&row->tuple[7], fkey_ptr);
/* Get to the foreign key */
ptr += strlen(ptr) + 1;
set_tuplefield_string(&row->tuple[7], ptr);
mylog("frel = '%s', ptr = '%s'\n", frel, ptr); set_tuplefield_int2(&row->tuple[8], (Int2) (k + 1));
mylog("rule_type = %d, action = %d\n", rule_type, action);
set_tuplefield_int2(&row->tuple[8], (Int2) (++seq)); mylog("upd_rule = %d, del_rule= %d", upd_rule_type, del_rule_type);
set_nullfield_int2(&row->tuple[9], (Int2) upd_rule_type);
set_nullfield_int2(&row->tuple[9], (Int2) ((rule_type & TRIGGER_UPDATE) ? action : -1)); set_nullfield_int2(&row->tuple[10], (Int2) del_rule_type);
set_nullfield_int2(&row->tuple[10], (Int2) ((rule_type & TRIGGER_DELETE) ? action : -1));
set_tuplefield_null(&row->tuple[11]); set_tuplefield_null(&row->tuple[11]);
set_tuplefield_null(&row->tuple[12]); set_tuplefield_null(&row->tuple[12]);
set_tuplefield_string(&row->tuple[13], tgname); set_tuplefield_string(&row->tuple[13], trig_args);
QR_add_tuple(stmt->result, row); #if (ODBCVER >= 0x0300)
mylog("defer_type = '%s', defer_type);
set_tuplefield_int2(&row->tuple[14], defer_type);
#endif /* ODBCVER >= 0x0300 */
/* next primary key */ QR_add_tuple(stmt->result, row);
pkptr += strlen(pkptr) + 1;
/* next primary/foreign key */
for (j = 0; j < 2; j++) {
pkey_ptr += strlen(pkey_ptr) + 1;
fkey_ptr += strlen(fkey_ptr) + 1;
} }
} }
result = SQLFetch(htbl_stmt); result = SQLFetch(htbl_stmt);
...@@ -2723,7 +2839,6 @@ Int2 result_cols; ...@@ -2723,7 +2839,6 @@ Int2 result_cols;
} }
SQLFreeStmt(htbl_stmt, SQL_DROP); SQLFreeStmt(htbl_stmt, SQL_DROP);
SQLFreeStmt(hpkey_stmt, SQL_DROP);
mylog("SQLForeignKeys(): EXIT, stmt=%u\n", stmt); mylog("SQLForeignKeys(): EXIT, stmt=%u\n", stmt);
return SQL_SUCCESS; return SQL_SUCCESS;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment