4
* Description: This module contains routines related to
5
* ODBC informational functions.
9
* API functions: SQLGetInfo, SQLGetTypeInfo, SQLGetFunctions,
10
* SQLTables, SQLColumns, SQLStatistics, SQLSpecialColumns,
11
* SQLPrimaryKeys, SQLForeignKeys,
12
* SQLProcedureColumns(NI), SQLProcedures,
13
* SQLTablePrivileges, SQLColumnPrivileges(NI)
15
* Comments: See "notice.txt" for copyright and license information.
30
#include "dlg_specific.h"
33
#include "connection.h"
34
#include "statement.h"
39
#include "pgapifunc.h"
40
#include "multibyte.h"
43
/* Trigger related stuff for SQLForeign Keys */
44
#define TRIGGER_SHIFT 3
45
#define TRIGGER_MASK 0x03
46
#define TRIGGER_DELETE 0x01
47
#define TRIGGER_UPDATE 0x02
50
/* extern GLOBAL_VALUES globals; */
60
SWORD FAR * pcbInfoValue)
62
CSTR func = "PGAPI_GetInfo";
63
ConnectionClass *conn = (ConnectionClass *) hdbc;
71
mylog("%s: entering...fInfoType=%d\n", func, fInfoType);
75
CC_log_error(func, "", NULL);
76
return SQL_INVALID_HANDLE;
79
ci = &(conn->connInfo);
83
case SQL_ACCESSIBLE_PROCEDURES: /* ODBC 1.0 */
87
case SQL_ACCESSIBLE_TABLES: /* ODBC 1.0 */
91
case SQL_ACTIVE_CONNECTIONS: /* ODBC 1.0 */
93
value = MAX_CONNECTIONS;
96
case SQL_ACTIVE_STATEMENTS: /* ODBC 1.0 */
101
case SQL_ALTER_TABLE: /* ODBC 2.0 */
103
value = SQL_AT_ADD_COLUMN;
104
if (PG_VERSION_GE(conn, 7.3))
105
value |= SQL_AT_DROP_COLUMN;
106
#if (ODBCVER >= 0x0300)
107
value |= SQL_AT_ADD_COLUMN_SINGLE;
108
if (PG_VERSION_GE(conn, 7.1))
109
value |= SQL_AT_ADD_CONSTRAINT
110
| SQL_AT_ADD_TABLE_CONSTRAINT
111
| SQL_AT_CONSTRAINT_INITIALLY_DEFERRED
112
| SQL_AT_CONSTRAINT_INITIALLY_IMMEDIATE
113
| SQL_AT_CONSTRAINT_DEFERRABLE;
114
if (PG_VERSION_GE(conn, 7.3))
115
value |= SQL_AT_DROP_TABLE_CONSTRAINT_RESTRICT
116
| SQL_AT_DROP_TABLE_CONSTRAINT_CASCADE
117
| SQL_AT_DROP_COLUMN_RESTRICT
118
| SQL_AT_DROP_COLUMN_CASCADE;
122
case SQL_BOOKMARK_PERSISTENCE: /* ODBC 2.0 */
123
/* very simple bookmark support */
125
value = ci->drivers.use_declarefetch ? 0 : (SQL_BP_SCROLL | SQL_BP_DELETE | SQL_BP_UPDATE | SQL_BP_TRANSACTION);
128
case SQL_COLUMN_ALIAS: /* ODBC 2.0 */
132
case SQL_CONCAT_NULL_BEHAVIOR: /* ODBC 1.0 */
134
value = SQL_CB_NON_NULL;
137
case SQL_CONVERT_BIGINT:
138
case SQL_CONVERT_BINARY:
139
case SQL_CONVERT_BIT:
140
case SQL_CONVERT_CHAR:
141
case SQL_CONVERT_DATE:
142
case SQL_CONVERT_DECIMAL:
143
case SQL_CONVERT_DOUBLE:
144
case SQL_CONVERT_FLOAT:
145
case SQL_CONVERT_INTEGER:
146
case SQL_CONVERT_LONGVARBINARY:
147
case SQL_CONVERT_LONGVARCHAR:
148
case SQL_CONVERT_NUMERIC:
149
case SQL_CONVERT_REAL:
150
case SQL_CONVERT_SMALLINT:
151
case SQL_CONVERT_TIME:
152
case SQL_CONVERT_TIMESTAMP:
153
case SQL_CONVERT_TINYINT:
154
case SQL_CONVERT_VARBINARY:
155
case SQL_CONVERT_VARCHAR: /* ODBC 1.0 */
160
case SQL_CONVERT_FUNCTIONS: /* ODBC 1.0 */
165
case SQL_CORRELATION_NAME: /* ODBC 1.0 */
168
* Saying no correlation name makes Query not work right.
169
* value = SQL_CN_NONE;
175
case SQL_CURSOR_COMMIT_BEHAVIOR: /* ODBC 1.0 */
177
value = SQL_CB_CLOSE;
178
if (!ci->drivers.use_declarefetch)
179
value = SQL_CB_PRESERVE;
182
case SQL_CURSOR_ROLLBACK_BEHAVIOR: /* ODBC 1.0 */
184
value = SQL_CB_CLOSE;
185
if (!ci->drivers.use_declarefetch)
186
value = SQL_CB_PRESERVE;
189
case SQL_DATA_SOURCE_NAME: /* ODBC 1.0 */
190
p = CC_get_DSN(conn);
193
case SQL_DATA_SOURCE_READ_ONLY: /* ODBC 1.0 */
194
p = CC_is_onlyread(conn) ? "Y" : "N";
197
case SQL_DATABASE_NAME: /* Support for old ODBC 1.0 Apps */
200
* Returning the database name causes problems in MS Query. It
201
* generates query like: "SELECT DISTINCT a FROM byronnbad3
204
* p = CC_get_database(conn);
209
case SQL_DBMS_NAME: /* ODBC 1.0 */
213
case SQL_DBMS_VER: /* ODBC 1.0 */
216
* The ODBC spec wants ##.##.#### ...whatever... so prepend
219
/* version number to the dbms version string */
220
snprintf(tmp, sizeof(tmp) - 1, "%s %s", POSTGRESDRIVERVERSION, conn->pg_version);
221
tmp[sizeof(tmp) - 1] = '\0';
225
case SQL_DEFAULT_TXN_ISOLATION: /* ODBC 1.0 */
227
if (PG_VERSION_LT(conn, 6.5))
228
value = SQL_TXN_SERIALIZABLE;
230
value = SQL_TXN_READ_COMMITTED;
233
case SQL_DRIVER_NAME: /* ODBC 1.0 */
234
p = DRIVER_FILE_NAME;
237
case SQL_DRIVER_ODBC_VER:
241
case SQL_DRIVER_VER: /* ODBC 1.0 */
242
p = POSTGRESDRIVERVERSION;
245
case SQL_EXPRESSIONS_IN_ORDERBY: /* ODBC 1.0 */
249
case SQL_FETCH_DIRECTION: /* ODBC 1.0 */
251
value = ci->drivers.use_declarefetch ? (SQL_FD_FETCH_NEXT) :
256
SQL_FD_FETCH_ABSOLUTE |
257
SQL_FD_FETCH_RELATIVE |
258
SQL_FD_FETCH_BOOKMARK);
261
case SQL_FILE_USAGE: /* ODBC 2.0 */
263
value = SQL_FILE_NOT_SUPPORTED;
266
case SQL_GETDATA_EXTENSIONS: /* ODBC 2.0 */
268
value = (SQL_GD_ANY_COLUMN | SQL_GD_ANY_ORDER | SQL_GD_BOUND | SQL_GD_BLOCK);
271
case SQL_GROUP_BY: /* ODBC 2.0 */
273
value = SQL_GB_GROUP_BY_EQUALS_SELECT;
276
case SQL_IDENTIFIER_CASE: /* ODBC 1.0 */
279
* are identifiers case-sensitive (yes, but only when quoted.
280
* If not quoted, they default to lowercase)
283
value = SQL_IC_LOWER;
286
case SQL_IDENTIFIER_QUOTE_CHAR: /* ODBC 1.0 */
287
/* the character used to quote "identifiers" */
288
p = PG_VERSION_LE(conn, 6.2) ? " " : "\"";
291
case SQL_KEYWORDS: /* ODBC 2.0 */
295
case SQL_LIKE_ESCAPE_CLAUSE: /* ODBC 2.0 */
298
* is there a character that escapes '%' and '_' in a LIKE
299
* clause? not as far as I can tell
304
case SQL_LOCK_TYPES: /* ODBC 2.0 */
306
value = ci->drivers.lie ? (SQL_LCK_NO_CHANGE | SQL_LCK_EXCLUSIVE | SQL_LCK_UNLOCK) : SQL_LCK_NO_CHANGE;
309
case SQL_MAX_BINARY_LITERAL_LEN: /* ODBC 2.0 */
314
case SQL_MAX_CHAR_LITERAL_LEN: /* ODBC 2.0 */
319
case SQL_MAX_COLUMN_NAME_LEN: /* ODBC 1.0 */
321
#ifdef MAX_COLUMN_LEN
322
value = MAX_COLUMN_LEN;
323
#endif /* MAX_COLUMN_LEN */
326
if (PG_VERSION_GE(conn, 7.3))
327
value = NAMEDATALEN_V73;
329
value = NAMEDATALEN_V72;
333
case SQL_MAX_COLUMNS_IN_GROUP_BY: /* ODBC 2.0 */
338
case SQL_MAX_COLUMNS_IN_INDEX: /* ODBC 2.0 */
343
case SQL_MAX_COLUMNS_IN_ORDER_BY: /* ODBC 2.0 */
348
case SQL_MAX_COLUMNS_IN_SELECT: /* ODBC 2.0 */
353
case SQL_MAX_COLUMNS_IN_TABLE: /* ODBC 2.0 */
358
case SQL_MAX_CURSOR_NAME_LEN: /* ODBC 1.0 */
360
value = MAX_CURSOR_LEN;
363
case SQL_MAX_INDEX_SIZE: /* ODBC 2.0 */
368
case SQL_MAX_OWNER_NAME_LEN: /* ODBC 1.0 */
371
#ifdef MAX_SCHEMA_LEN
372
if (conn->schema_support)
373
value = MAX_SCHEMA_LEN;
374
#endif /* MAX_SCHEMA_LEN */
377
if (PG_VERSION_GE(conn, 7.3))
378
value = NAMEDATALEN_V73;
382
case SQL_MAX_PROCEDURE_NAME_LEN: /* ODBC 1.0 */
387
case SQL_MAX_QUALIFIER_NAME_LEN: /* ODBC 1.0 */
392
case SQL_MAX_ROW_SIZE: /* ODBC 2.0 */
394
if (PG_VERSION_GE(conn, 7.1))
396
/* Large Rowa in 7.1+ */
397
value = MAX_ROW_SIZE;
401
/* Without the Toaster we're limited to the blocksize */
406
case SQL_MAX_ROW_SIZE_INCLUDES_LONG: /* ODBC 2.0 */
409
* does the preceding value include LONGVARCHAR and
410
* LONGVARBINARY fields? Well, it does include longvarchar,
411
* but not longvarbinary.
416
case SQL_MAX_STATEMENT_LEN: /* ODBC 2.0 */
417
/* maybe this should be 0? */
419
value = CC_get_max_query_len(conn);
422
case SQL_MAX_TABLE_NAME_LEN: /* ODBC 1.0 */
425
value = MAX_TABLE_LEN;
426
#endif /* MAX_TABLE_LEN */
429
if (PG_VERSION_GE(conn, 7.3))
430
value = NAMEDATALEN_V73;
432
value = NAMEDATALEN_V72;
436
case SQL_MAX_TABLES_IN_SELECT: /* ODBC 2.0 */
441
case SQL_MAX_USER_NAME_LEN:
446
case SQL_MULT_RESULT_SETS: /* ODBC 1.0 */
447
/* Don't support multiple result sets but say yes anyway? */
451
case SQL_MULTIPLE_ACTIVE_TXN: /* ODBC 1.0 */
455
case SQL_NEED_LONG_DATA_LEN: /* ODBC 2.0 */
458
* Don't need the length, SQLPutData can handle any size and
464
case SQL_NON_NULLABLE_COLUMNS: /* ODBC 1.0 */
466
value = SQL_NNC_NON_NULL;
469
case SQL_NULL_COLLATION: /* ODBC 2.0 */
470
/* where are nulls sorted? */
475
case SQL_NUMERIC_FUNCTIONS: /* ODBC 1.0 */
480
case SQL_ODBC_API_CONFORMANCE: /* ODBC 1.0 */
482
value = SQL_OAC_LEVEL1;
485
case SQL_ODBC_SAG_CLI_CONFORMANCE: /* ODBC 1.0 */
487
value = SQL_OSCC_NOT_COMPLIANT;
490
case SQL_ODBC_SQL_CONFORMANCE: /* ODBC 1.0 */
492
value = SQL_OSC_CORE;
495
case SQL_ODBC_SQL_OPT_IEF: /* ODBC 1.0 */
499
case SQL_OJ_CAPABILITIES: /* ODBC 2.01 */
501
if (PG_VERSION_GE(conn, 7.1))
504
value = (SQL_OJ_LEFT |
510
SQL_OJ_ALL_COMPARISON_OPS);
513
/* OJs not in <7.1 */
517
case SQL_ORDER_BY_COLUMNS_IN_SELECT: /* ODBC 2.0 */
518
p = (PG_VERSION_LE(conn, 6.3)) ? "Y" : "N";
521
case SQL_OUTER_JOINS: /* ODBC 1.0 */
522
if (PG_VERSION_GE(conn, 7.1))
526
/* OJs not in <7.1 */
530
case SQL_OWNER_TERM: /* ODBC 1.0 */
531
if (conn->schema_support)
537
case SQL_OWNER_USAGE: /* ODBC 2.0 */
540
if (conn->schema_support)
541
value = SQL_OU_DML_STATEMENTS
542
| SQL_OU_TABLE_DEFINITION
543
| SQL_OU_INDEX_DEFINITION
544
| SQL_OU_PRIVILEGE_DEFINITION
548
case SQL_POS_OPERATIONS: /* ODBC 2.0 */
550
value = (SQL_POS_POSITION | SQL_POS_REFRESH);
551
#ifdef DRIVER_CURSOR_IMPLEMENT
552
if (ci->updatable_cursors)
553
value |= (SQL_POS_UPDATE | SQL_POS_DELETE | SQL_POS_ADD);
554
#endif /* DRIVER_CURSOR_IMPLEMENT */
557
case SQL_POSITIONED_STATEMENTS: /* ODBC 2.0 */
559
value = ci->drivers.lie ? (SQL_PS_POSITIONED_DELETE |
560
SQL_PS_POSITIONED_UPDATE |
561
SQL_PS_SELECT_FOR_UPDATE) : 0;
564
case SQL_PROCEDURE_TERM: /* ODBC 1.0 */
568
case SQL_PROCEDURES: /* ODBC 1.0 */
572
case SQL_QUALIFIER_LOCATION: /* ODBC 2.0 */
574
value = SQL_QL_START;
577
case SQL_QUALIFIER_NAME_SEPARATOR: /* ODBC 1.0 */
581
case SQL_QUALIFIER_TERM: /* ODBC 1.0 */
585
case SQL_QUALIFIER_USAGE: /* ODBC 2.0 */
590
case SQL_QUOTED_IDENTIFIER_CASE: /* ODBC 2.0 */
591
/* are "quoted" identifiers case-sensitive? YES! */
593
value = SQL_IC_SENSITIVE;
596
case SQL_ROW_UPDATES: /* ODBC 1.0 */
599
* Driver doesn't support keyset-driven or mixed cursors, so
600
* not much point in saying row updates are supported
602
p = (ci->updatable_cursors) ? "Y" : "N";
605
case SQL_SCROLL_CONCURRENCY: /* ODBC 1.0 */
607
value = SQL_SCCO_READ_ONLY;
608
#ifdef DRIVER_CURSOR_IMPLEMENT
609
if (ci->updatable_cursors)
610
value |= SQL_SCCO_OPT_ROWVER;
611
#endif /* DRIVER_CURSOR_IMPLEMENT */
613
value |= (SQL_SCCO_LOCK | SQL_SCCO_OPT_VALUES);
616
case SQL_SCROLL_OPTIONS: /* ODBC 1.0 */
618
value = SQL_SO_FORWARD_ONLY;
619
#ifdef DECLAREFETCH_FORWARDONLY
620
if (!ci->drivers.use_declarefetch)
621
#endif /* DECLAREFETCH_FORWARDONLY */
622
value |= SQL_SO_STATIC;
623
if (ci->updatable_cursors)
624
value |= SQL_SO_KEYSET_DRIVEN;
626
value |= (SQL_SO_DYNAMIC | SQL_SO_MIXED);
629
case SQL_SEARCH_PATTERN_ESCAPE: /* ODBC 1.0 */
630
if (PG_VERSION_GE(conn, 6.5))
636
case SQL_SERVER_NAME: /* ODBC 1.0 */
637
p = CC_get_server(conn);
640
case SQL_SPECIAL_CHARACTERS: /* ODBC 2.0 */
644
case SQL_STATIC_SENSITIVITY: /* ODBC 2.0 */
647
#ifdef DRIVER_CURSOR_IMPLEMENT
648
if (ci->updatable_cursors)
649
value |= (SQL_SS_ADDITIONS | SQL_SS_DELETIONS | SQL_SS_UPDATES);
650
#endif /* DRIVER_CURSOR_IMPLEMENT */
653
case SQL_STRING_FUNCTIONS: /* ODBC 1.0 */
655
value = (SQL_FN_STR_CONCAT |
661
SQL_FN_STR_SUBSTRING |
665
case SQL_SUBQUERIES: /* ODBC 2.0 */
666
/* postgres 6.3 supports subqueries */
668
value = (SQL_SQ_QUANTIFIED |
674
case SQL_SYSTEM_FUNCTIONS: /* ODBC 1.0 */
679
case SQL_TABLE_TERM: /* ODBC 1.0 */
683
case SQL_TIMEDATE_ADD_INTERVALS: /* ODBC 2.0 */
688
case SQL_TIMEDATE_DIFF_INTERVALS: /* ODBC 2.0 */
693
case SQL_TIMEDATE_FUNCTIONS: /* ODBC 1.0 */
695
value = (SQL_FN_TD_NOW);
698
case SQL_TXN_CAPABLE: /* ODBC 1.0 */
701
* Postgres can deal with create or drop table statements in a
708
case SQL_TXN_ISOLATION_OPTION: /* ODBC 1.0 */
710
if (PG_VERSION_LT(conn, 6.5))
711
value = SQL_TXN_SERIALIZABLE;
712
else if (PG_VERSION_GE(conn, 7.1))
713
value = SQL_TXN_READ_COMMITTED | SQL_TXN_SERIALIZABLE;
715
value = SQL_TXN_READ_COMMITTED;
718
case SQL_UNION: /* ODBC 2.0 */
719
/* unions with all supported in postgres 6.3 */
721
value = (SQL_U_UNION | SQL_U_UNION_ALL);
724
case SQL_USER_NAME: /* ODBC 1.0 */
725
p = CC_get_username(conn);
729
/* unrecognized key */
730
CC_set_error(conn, CONN_NOT_IMPLEMENTED_ERROR, "Unrecognized key passed to PGAPI_GetInfo.");
734
result = SQL_SUCCESS;
736
mylog("%s: p='%s', len=%d, value=%d, cbMax=%d\n", func, p ? p : "<NULL>", len, value, cbInfoValueMax);
739
* NOTE, that if rgbInfoValue is NULL, then no warnings or errors
740
* should result and just pcbInfoValue is returned, which indicates
741
* what length would be required if a real buffer had been passed in.
745
/* char/binary data */
750
#ifdef UNICODE_SUPPORT
753
len = utf8_to_ucs2(p, len, (SQLWCHAR *) rgbInfoValue, cbInfoValueMax / 2);
757
#endif /* UNICODE_SUPPORT */
758
strncpy_null((char *) rgbInfoValue, p, (size_t) cbInfoValueMax);
760
if (len >= cbInfoValueMax)
762
result = SQL_SUCCESS_WITH_INFO;
763
CC_set_error(conn, CONN_TRUNCATED, "The buffer was too small for tthe InfoValue.");
773
*((WORD *) rgbInfoValue) = (WORD) value;
775
*((DWORD *) rgbInfoValue) = (DWORD) value;
791
CSTR func = "PGAPI_GetTypeInfo";
792
StatementClass *stmt = (StatementClass *) hstmt;
801
mylog("%s: entering...fSqlType = %d\n", func, fSqlType);
805
SC_log_error(func, "", NULL);
806
return SQL_INVALID_HANDLE;
809
stmt->manual_result = TRUE;
810
if (res = QR_Constructor(), !res)
812
SC_log_error(func, "Error creating result.", stmt);
815
SC_set_Result(stmt, res);
817
#if (ODBCVER >= 0x0300)
822
extend_column_bindings(SC_get_ARD(stmt), result_cols);
824
QR_set_num_fields(res, result_cols);
825
QR_set_field_info(res, 0, "TYPE_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
826
QR_set_field_info(res, 1, "DATA_TYPE", PG_TYPE_INT2, 2);
827
QR_set_field_info(res, 2, "PRECISION", PG_TYPE_INT4, 4);
828
QR_set_field_info(res, 3, "LITERAL_PREFIX", PG_TYPE_VARCHAR, MAX_INFO_STRING);
829
QR_set_field_info(res, 4, "LITERAL_SUFFIX", PG_TYPE_VARCHAR, MAX_INFO_STRING);
830
QR_set_field_info(res, 5, "CREATE_PARAMS", PG_TYPE_VARCHAR, MAX_INFO_STRING);
831
QR_set_field_info(res, 6, "NULLABLE", PG_TYPE_INT2, 2);
832
QR_set_field_info(res, 7, "CASE_SENSITIVE", PG_TYPE_INT2, 2);
833
QR_set_field_info(res, 8, "SEARCHABLE", PG_TYPE_INT2, 2);
834
QR_set_field_info(res, 9, "UNSIGNED_ATTRIBUTE", PG_TYPE_INT2, 2);
835
QR_set_field_info(res, 10, "MONEY", PG_TYPE_INT2, 2);
836
QR_set_field_info(res, 11, "AUTO_INCREMENT", PG_TYPE_INT2, 2);
837
QR_set_field_info(res, 12, "LOCAL_TYPE_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
838
QR_set_field_info(res, 13, "MINIMUM_SCALE", PG_TYPE_INT2, 2);
839
QR_set_field_info(res, 14, "MAXIMUM_SCALE", PG_TYPE_INT2, 2);
840
#if (ODBCVER >=0x0300)
841
QR_set_field_info(res, 15, "SQL_DATA_TYPE", PG_TYPE_INT2, 2);
842
QR_set_field_info(res, 16, "SQL_DATATIME_SUB", PG_TYPE_INT2, 2);
843
QR_set_field_info(res, 17, "NUM_PREC_RADIX", PG_TYPE_INT4, 4);
844
QR_set_field_info(res, 18, "INTERVAL_PRECISION", PG_TYPE_INT2, 2);
847
for (i = 0, sqlType = sqlTypes[0]; sqlType; sqlType = sqlTypes[++i])
849
pgType = sqltype_to_pgtype(stmt, sqlType);
851
if (fSqlType == SQL_ALL_TYPES || fSqlType == sqlType)
853
int pgtcount = 1, cnt;
855
if (SQL_INTEGER == sqlType && PG_VERSION_GE(SC_get_conn(stmt), 6.4))
857
for (cnt = 0; cnt < pgtcount; cnt ++)
860
row = (TupleNode *) malloc(sizeof(TupleNode) + (result_cols - 1) * sizeof(TupleField));
862
/* These values can't be NULL */
865
set_tuplefield_string(&row->tuple[0], "serial");
866
set_tuplefield_int2(&row->tuple[6], SQL_NO_NULLS);
867
inolog("serial in\n");
871
set_tuplefield_string(&row->tuple[0], pgtype_to_name(stmt, pgType));
872
set_tuplefield_int2(&row->tuple[6], pgtype_nullable(stmt, pgType));
874
set_tuplefield_int2(&row->tuple[1], (Int2) sqlType);
875
set_tuplefield_int2(&row->tuple[7], pgtype_case_sensitive(stmt, pgType));
876
set_tuplefield_int2(&row->tuple[8], pgtype_searchable(stmt, pgType));
877
set_tuplefield_int2(&row->tuple[10], pgtype_money(stmt, pgType));
880
* Localized data-source dependent data type name (always
883
set_tuplefield_null(&row->tuple[12]);
885
/* These values can be NULL */
886
set_nullfield_int4(&row->tuple[2], pgtype_column_size(stmt, pgType, PG_STATIC, PG_STATIC));
887
set_nullfield_string(&row->tuple[3], pgtype_literal_prefix(stmt, pgType));
888
set_nullfield_string(&row->tuple[4], pgtype_literal_suffix(stmt, pgType));
889
set_nullfield_string(&row->tuple[5], pgtype_create_params(stmt, pgType));
892
set_nullfield_int2(&row->tuple[9], TRUE);
893
set_nullfield_int2(&row->tuple[11], TRUE);
897
set_nullfield_int2(&row->tuple[9], pgtype_unsigned(stmt, pgType));
898
set_nullfield_int2(&row->tuple[11], pgtype_auto_increment(stmt, pgType));
900
set_nullfield_int2(&row->tuple[13], pgtype_scale(stmt, pgType, PG_STATIC));
901
set_nullfield_int2(&row->tuple[14], pgtype_scale(stmt, pgType, PG_STATIC));
902
#if (ODBCVER >=0x0300)
903
set_nullfield_int2(&row->tuple[15], pgtype_to_sqldesctype(stmt, pgType));
904
set_nullfield_int2(&row->tuple[16], pgtype_to_datetime_sub(stmt, pgType));
905
set_nullfield_int4(&row->tuple[17], pgtype_radix(stmt, pgType));
906
set_nullfield_int4(&row->tuple[18], 0);
909
QR_add_tuple(res, row);
915
stmt->status = STMT_FINISHED;
916
stmt->currTuple = -1;
917
stmt->rowset_start = -1;
918
stmt->current_col = -1;
928
UWORD FAR * pfExists)
930
CSTR func = "PGAPI_GetFunctions";
931
ConnectionClass *conn = (ConnectionClass *) hdbc;
932
ConnInfo *ci = &(conn->connInfo);
934
mylog("%s: entering...%u\n", func, fFunction);
936
if (fFunction == SQL_API_ALL_FUNCTIONS)
938
#if (ODBCVER < 0x0300)
943
memset(pfExists, 0, sizeof(UWORD) * 100);
945
pfExists[SQL_API_SQLALLOCENV] = TRUE;
946
pfExists[SQL_API_SQLFREEENV] = TRUE;
947
for (i = SQL_API_SQLALLOCCONNECT; i <= SQL_NUM_FUNCTIONS; i++)
949
for (i = SQL_EXT_API_START; i <= SQL_EXT_API_LAST; i++)
955
memset(pfExists, 0, sizeof(UWORD) * 100);
957
/* ODBC core functions */
958
pfExists[SQL_API_SQLALLOCCONNECT] = TRUE;
959
pfExists[SQL_API_SQLALLOCENV] = TRUE;
960
pfExists[SQL_API_SQLALLOCSTMT] = TRUE;
961
pfExists[SQL_API_SQLBINDCOL] = TRUE;
962
pfExists[SQL_API_SQLCANCEL] = TRUE;
963
pfExists[SQL_API_SQLCOLATTRIBUTES] = TRUE;
964
pfExists[SQL_API_SQLCONNECT] = TRUE;
965
pfExists[SQL_API_SQLDESCRIBECOL] = TRUE; /* partial */
966
pfExists[SQL_API_SQLDISCONNECT] = TRUE;
967
pfExists[SQL_API_SQLERROR] = TRUE;
968
pfExists[SQL_API_SQLEXECDIRECT] = TRUE;
969
pfExists[SQL_API_SQLEXECUTE] = TRUE;
970
pfExists[SQL_API_SQLFETCH] = TRUE;
971
pfExists[SQL_API_SQLFREECONNECT] = TRUE;
972
pfExists[SQL_API_SQLFREEENV] = TRUE;
973
pfExists[SQL_API_SQLFREESTMT] = TRUE;
974
pfExists[SQL_API_SQLGETCURSORNAME] = TRUE;
975
pfExists[SQL_API_SQLNUMRESULTCOLS] = TRUE;
976
pfExists[SQL_API_SQLPREPARE] = TRUE; /* complete? */
977
pfExists[SQL_API_SQLROWCOUNT] = TRUE;
978
pfExists[SQL_API_SQLSETCURSORNAME] = TRUE;
979
pfExists[SQL_API_SQLSETPARAM] = FALSE; /* odbc 1.0 */
980
pfExists[SQL_API_SQLTRANSACT] = TRUE;
982
/* ODBC level 1 functions */
983
pfExists[SQL_API_SQLBINDPARAMETER] = TRUE;
984
pfExists[SQL_API_SQLCOLUMNS] = TRUE;
985
pfExists[SQL_API_SQLDRIVERCONNECT] = TRUE;
986
pfExists[SQL_API_SQLGETCONNECTOPTION] = TRUE; /* partial */
987
pfExists[SQL_API_SQLGETDATA] = TRUE;
988
pfExists[SQL_API_SQLGETFUNCTIONS] = TRUE;
989
pfExists[SQL_API_SQLGETINFO] = TRUE;
990
pfExists[SQL_API_SQLGETSTMTOPTION] = TRUE; /* partial */
991
pfExists[SQL_API_SQLGETTYPEINFO] = TRUE;
992
pfExists[SQL_API_SQLPARAMDATA] = TRUE;
993
pfExists[SQL_API_SQLPUTDATA] = TRUE;
994
pfExists[SQL_API_SQLSETCONNECTOPTION] = TRUE; /* partial */
995
pfExists[SQL_API_SQLSETSTMTOPTION] = TRUE;
996
pfExists[SQL_API_SQLSPECIALCOLUMNS] = TRUE;
997
pfExists[SQL_API_SQLSTATISTICS] = TRUE;
998
pfExists[SQL_API_SQLTABLES] = TRUE;
1000
/* ODBC level 2 functions */
1001
pfExists[SQL_API_SQLBROWSECONNECT] = FALSE;
1002
pfExists[SQL_API_SQLCOLUMNPRIVILEGES] = FALSE;
1003
pfExists[SQL_API_SQLDATASOURCES] = FALSE; /* only implemented by
1005
pfExists[SQL_API_SQLDESCRIBEPARAM] = FALSE; /* not properly
1007
pfExists[SQL_API_SQLDRIVERS] = FALSE; /* only implemented by
1009
pfExists[SQL_API_SQLEXTENDEDFETCH] = TRUE;
1010
pfExists[SQL_API_SQLFOREIGNKEYS] = TRUE;
1011
pfExists[SQL_API_SQLMORERESULTS] = TRUE;
1012
pfExists[SQL_API_SQLNATIVESQL] = TRUE;
1013
pfExists[SQL_API_SQLNUMPARAMS] = TRUE;
1014
pfExists[SQL_API_SQLPARAMOPTIONS] = TRUE;
1015
pfExists[SQL_API_SQLPRIMARYKEYS] = TRUE;
1016
if (PG_VERSION_LT(conn, 6.5))
1017
pfExists[SQL_API_SQLPROCEDURECOLUMNS] = FALSE;
1019
pfExists[SQL_API_SQLPROCEDURECOLUMNS] = TRUE;
1020
if (PG_VERSION_LT(conn, 6.5))
1021
pfExists[SQL_API_SQLPROCEDURES] = FALSE;
1023
pfExists[SQL_API_SQLPROCEDURES] = TRUE;
1024
pfExists[SQL_API_SQLSETPOS] = TRUE;
1025
pfExists[SQL_API_SQLSETSCROLLOPTIONS] = TRUE; /* odbc 1.0 */
1026
pfExists[SQL_API_SQLTABLEPRIVILEGES] = TRUE;
1027
#if (ODBCVER >= 0x0300)
1028
pfExists[SQL_API_SQLBULKOPERATIONS] = TRUE;
1029
#endif /* ODBCVER */
1034
if (ci->drivers.lie)
1040
#if (ODBCVER < 0x0300)
1041
case SQL_API_SQLALLOCCONNECT:
1044
case SQL_API_SQLALLOCENV:
1047
case SQL_API_SQLALLOCSTMT:
1050
#endif /* ODBCVER */
1051
case SQL_API_SQLBINDCOL:
1054
case SQL_API_SQLCANCEL:
1057
#if (ODBCVER >= 0x0300)
1058
case SQL_API_SQLCOLATTRIBUTE:
1060
case SQL_API_SQLCOLATTRIBUTES:
1061
#endif /* ODBCVER */
1064
case SQL_API_SQLCONNECT:
1067
case SQL_API_SQLDESCRIBECOL:
1069
break; /* partial */
1070
case SQL_API_SQLDISCONNECT:
1073
#if (ODBCVER < 0x0300)
1074
case SQL_API_SQLERROR:
1077
#endif /* ODBCVER */
1078
case SQL_API_SQLEXECDIRECT:
1081
case SQL_API_SQLEXECUTE:
1084
case SQL_API_SQLFETCH:
1087
#if (ODBCVER < 0x0300)
1088
case SQL_API_SQLFREECONNECT:
1091
case SQL_API_SQLFREEENV:
1094
#endif /* ODBCVER */
1095
case SQL_API_SQLFREESTMT:
1098
case SQL_API_SQLGETCURSORNAME:
1101
case SQL_API_SQLNUMRESULTCOLS:
1104
case SQL_API_SQLPREPARE:
1107
case SQL_API_SQLROWCOUNT:
1110
case SQL_API_SQLSETCURSORNAME:
1113
case SQL_API_SQLSETPARAM:
1115
break; /* odbc 1.0 */
1116
case SQL_API_SQLTRANSACT:
1120
/* ODBC level 1 functions */
1121
case SQL_API_SQLBINDPARAMETER:
1124
case SQL_API_SQLCOLUMNS:
1127
case SQL_API_SQLDRIVERCONNECT:
1130
#if (ODBCVER < 0x0300)
1131
case SQL_API_SQLGETCONNECTOPTION:
1133
break; /* partial */
1134
#endif /* ODBCVER */
1135
case SQL_API_SQLGETDATA:
1138
case SQL_API_SQLGETFUNCTIONS:
1141
case SQL_API_SQLGETINFO:
1144
#if (ODBCVER < 0x0300)
1145
case SQL_API_SQLGETSTMTOPTION:
1147
break; /* partial */
1148
#endif /* ODBCVER */
1149
case SQL_API_SQLGETTYPEINFO:
1152
case SQL_API_SQLPARAMDATA:
1155
case SQL_API_SQLPUTDATA:
1158
#if (ODBCVER < 0x0300)
1159
case SQL_API_SQLSETCONNECTOPTION:
1161
break; /* partial */
1162
case SQL_API_SQLSETSTMTOPTION:
1165
#endif /* ODBCVER */
1166
case SQL_API_SQLSPECIALCOLUMNS:
1169
case SQL_API_SQLSTATISTICS:
1172
case SQL_API_SQLTABLES:
1176
/* ODBC level 2 functions */
1177
case SQL_API_SQLBROWSECONNECT:
1180
case SQL_API_SQLCOLUMNPRIVILEGES:
1183
case SQL_API_SQLDATASOURCES:
1185
break; /* only implemented by DM */
1186
case SQL_API_SQLDESCRIBEPARAM:
1188
break; /* not properly implemented */
1189
case SQL_API_SQLDRIVERS:
1191
break; /* only implemented by DM */
1192
case SQL_API_SQLEXTENDEDFETCH:
1195
case SQL_API_SQLFOREIGNKEYS:
1198
case SQL_API_SQLMORERESULTS:
1201
case SQL_API_SQLNATIVESQL:
1204
case SQL_API_SQLNUMPARAMS:
1207
case SQL_API_SQLPARAMOPTIONS:
1210
case SQL_API_SQLPRIMARYKEYS:
1213
case SQL_API_SQLPROCEDURECOLUMNS:
1214
if (PG_VERSION_LT(conn, 6.5))
1219
case SQL_API_SQLPROCEDURES:
1220
if (PG_VERSION_LT(conn, 6.5))
1225
case SQL_API_SQLSETPOS:
1228
case SQL_API_SQLSETSCROLLOPTIONS:
1230
break; /* odbc 1.0 */
1231
case SQL_API_SQLTABLEPRIVILEGES:
1234
#if (ODBCVER >= 0x0300)
1235
case SQL_API_SQLBULKOPERATIONS: /* 24 */
1236
case SQL_API_SQLALLOCHANDLE: /* 1001 */
1237
case SQL_API_SQLBINDPARAM: /* 1002 */
1238
case SQL_API_SQLCLOSECURSOR: /* 1003 */
1239
case SQL_API_SQLENDTRAN: /* 1005 */
1240
case SQL_API_SQLFETCHSCROLL: /* 1021 */
1241
case SQL_API_SQLFREEHANDLE: /* 1006 */
1242
case SQL_API_SQLGETCONNECTATTR: /* 1007 */
1243
case SQL_API_SQLGETDESCFIELD: /* 1008 */
1244
case SQL_API_SQLGETDIAGFIELD: /* 1010 */
1245
case SQL_API_SQLGETDIAGREC: /* 1011 */
1246
case SQL_API_SQLGETENVATTR: /* 1012 */
1247
case SQL_API_SQLGETSTMTATTR: /* 1014 */
1248
case SQL_API_SQLSETCONNECTATTR: /* 1016 */
1249
case SQL_API_SQLSETDESCFIELD: /* 1017 */
1250
case SQL_API_SQLSETENVATTR: /* 1019 */
1251
case SQL_API_SQLSETSTMTATTR: /* 1020 */
1254
case SQL_API_SQLGETDESCREC: /* 1009 */
1255
case SQL_API_SQLSETDESCREC: /* 1018 */
1256
case SQL_API_SQLCOPYDESC: /* 1004 */
1259
#endif /* ODBCVER */
1270
#define CSTR_SYS_TABLE "SYSTEM TABLE"
1271
#define CSTR_TABLE "TABLE"
1272
#define CSTR_VIEW "VIEW"
1277
UCHAR FAR * szTableQualifier,
1278
SWORD cbTableQualifier,
1279
UCHAR FAR * szTableOwner,
1281
UCHAR FAR * szTableName,
1283
UCHAR FAR * szTableType,
1286
CSTR func = "PGAPI_Tables";
1287
StatementClass *stmt = (StatementClass *) hstmt;
1288
StatementClass *tbl_stmt;
1294
char tables_query[INFO_INQUIRY_LEN];
1295
char table_name[MAX_INFO_STRING],
1296
table_owner[MAX_INFO_STRING],
1297
relkind_or_hasrules[MAX_INFO_STRING];
1298
#ifdef HAVE_STRTOK_R
1300
#endif /* HAVE_STRTOK_R */
1301
ConnectionClass *conn;
1304
prefixes[MEDIUM_REGISTRY_LEN];
1305
char *table_type[32],
1306
table_types[MAX_INFO_STRING];
1307
char show_system_tables,
1308
show_regular_tables,
1314
SWORD internal_asis_type = SQL_C_CHAR;
1315
const char *likeeq = "like";
1317
mylog("%s: entering...stmt=%u scnm=%x len=%d\n", func, stmt, szTableOwner, cbTableOwner);
1321
SC_log_error(func, "", NULL);
1322
return SQL_INVALID_HANDLE;
1325
stmt->manual_result = TRUE;
1326
stmt->errormsg_created = TRUE;
1328
conn = SC_get_conn(stmt);
1329
ci = &(conn->connInfo);
1331
result = PGAPI_AllocStmt(stmt->hdbc, &htbl_stmt);
1332
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
1334
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate statement for PGAPI_Tables result.");
1335
SC_log_error(func, "", stmt);
1338
tbl_stmt = (StatementClass *) htbl_stmt;
1341
* Create the query to find out the tables
1343
if (conn->schema_support)
1345
/* view is represented by its relkind since 7.1 */
1346
strcpy(tables_query, "select relname, nspname, relkind"
1347
" from pg_catalog.pg_class, pg_catalog.pg_namespace");
1348
strcat(tables_query, " where relkind in ('r', 'v')");
1350
else if (PG_VERSION_GE(conn, 7.1))
1352
/* view is represented by its relkind since 7.1 */
1353
strcpy(tables_query, "select relname, usename, relkind"
1354
" from pg_class, pg_user");
1355
strcat(tables_query, " where relkind in ('r', 'v')");
1359
strcpy(tables_query, "select relname, usename, relhasrules from pg_class, pg_user");
1360
strcat(tables_query, " where relkind = 'r'");
1363
if (conn->schema_support)
1364
schema_strcat1(tables_query, " and nspname %s '%.*s'", likeeq, szTableOwner, cbTableOwner, szTableName, cbTableName, conn);
1366
my_strcat1(tables_query, " and usename %s '%.*s'", likeeq, szTableOwner, cbTableOwner);
1367
my_strcat1(tables_query, " and relname %s '%.*s'", likeeq, szTableName, cbTableName);
1369
/* Parse the extra systable prefix */
1370
strcpy(prefixes, ci->drivers.extra_systable_prefixes);
1372
#ifdef HAVE_STRTOK_R
1373
prefix[i] = strtok_r(prefixes, ";", &last);
1375
prefix[i] = strtok(prefixes, ";");
1376
#endif /* HAVE_STRTOK_R */
1377
while (prefix[i] && i < sizeof(prefix))
1378
#ifdef HAVE_STRTOK_R
1379
prefix[++i] = strtok_r(NULL, ";", &last);
1381
prefix[++i] = strtok(NULL, ";");
1382
#endif /* HAVE_STRTOK_R */
1384
/* Parse the desired table types to return */
1385
show_system_tables = FALSE;
1386
show_regular_tables = FALSE;
1389
/* make_string mallocs memory */
1390
tableType = make_string(szTableType, cbTableType, NULL);
1393
strcpy(table_types, tableType);
1396
#ifdef HAVE_STRTOK_R
1397
table_type[i] = strtok_r(table_types, ",", &last);
1399
table_type[i] = strtok(table_types, ",");
1400
#endif /* HAVE_STRTOK_R */
1401
while (table_type[i] && i < 32)
1402
#ifdef HAVE_STRTOK_R
1403
table_type[++i] = strtok_r(NULL, ",", &last);
1405
table_type[++i] = strtok(NULL, ",");
1406
#endif /* HAVE_STRTOK_R */
1408
/* Check for desired table types to return */
1410
while (table_type[i])
1412
char *typestr = table_type[i];
1414
while (isspace(*typestr))
1416
if (*typestr == '\'')
1418
if (strnicmp(typestr, CSTR_SYS_TABLE, strlen(CSTR_SYS_TABLE)) == 0)
1419
show_system_tables = TRUE;
1420
else if (strnicmp(typestr, CSTR_TABLE, strlen(CSTR_TABLE)) == 0)
1421
show_regular_tables = TRUE;
1422
else if (strnicmp(typestr, CSTR_VIEW, strlen(CSTR_VIEW)) == 0)
1429
show_regular_tables = TRUE;
1434
* If not interested in SYSTEM TABLES then filter them out to save
1435
* some time on the query. If treating system tables as regular
1436
* tables, then dont filter either.
1438
if (!atoi(ci->show_system_tables) && !show_system_tables)
1440
strcat(tables_query, " and relname !~ '^" POSTGRES_SYS_PREFIX);
1442
/* Also filter out user-defined system table types */
1446
strcat(tables_query, "|^");
1447
strcat(tables_query, prefix[i]);
1450
strcat(tables_query, "'");
1454
if (PG_VERSION_LT(conn, 7.1))
1455
/* filter out large objects in older versions */
1456
strcat(tables_query, " and relname !~ '^xinv[0-9]+'");
1458
if (conn->schema_support)
1459
strcat(tables_query, " and pg_namespace.oid = relnamespace order by nspname, relname");
1461
strcat(tables_query, " and usesysid = relowner order by relname");
1463
result = PGAPI_ExecDirect(htbl_stmt, tables_query, strlen(tables_query));
1464
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
1466
SC_full_error_copy(stmt, htbl_stmt);
1467
SC_log_error(func, "", stmt);
1468
PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
1472
#ifdef UNICODE_SUPPORT
1474
internal_asis_type = INTERNAL_ASIS_TYPE;
1475
#endif /* UNICODE_SUPPORT */
1476
result = PGAPI_BindCol(htbl_stmt, 1, internal_asis_type,
1477
table_name, MAX_INFO_STRING, NULL);
1478
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
1480
SC_error_copy(stmt, tbl_stmt);
1481
SC_log_error(func, "", stmt);
1482
PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
1486
result = PGAPI_BindCol(htbl_stmt, 2, internal_asis_type,
1487
table_owner, MAX_INFO_STRING, NULL);
1488
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
1490
SC_error_copy(stmt, tbl_stmt);
1491
SC_log_error(func, "", stmt);
1492
PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
1495
result = PGAPI_BindCol(htbl_stmt, 3, internal_asis_type,
1496
relkind_or_hasrules, MAX_INFO_STRING, NULL);
1497
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
1499
SC_error_copy(stmt, tbl_stmt);
1500
SC_log_error(func, "", stmt);
1501
PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
1505
if (res = QR_Constructor(), !res)
1507
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate memory for PGAPI_Tables result.");
1508
SC_log_error(func, "", stmt);
1509
PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
1512
SC_set_Result(stmt, res);
1514
/* the binding structure for a statement is not set up until */
1517
* a statement is actually executed, so we'll have to do this
1520
extend_column_bindings(SC_get_ARD(stmt), 5);
1522
/* set the field names */
1523
QR_set_num_fields(res, 5);
1524
QR_set_field_info(res, 0, "TABLE_QUALIFIER", PG_TYPE_VARCHAR, MAX_INFO_STRING);
1525
QR_set_field_info(res, 1, "TABLE_OWNER", PG_TYPE_VARCHAR, MAX_INFO_STRING);
1526
QR_set_field_info(res, 2, "TABLE_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
1527
QR_set_field_info(res, 3, "TABLE_TYPE", PG_TYPE_VARCHAR, MAX_INFO_STRING);
1528
QR_set_field_info(res, 4, "REMARKS", PG_TYPE_VARCHAR, 254);
1530
/* add the tuples */
1531
result = PGAPI_Fetch(htbl_stmt);
1532
while ((result == SQL_SUCCESS) || (result == SQL_SUCCESS_WITH_INFO))
1535
* Determine if this table name is a system table. If treating
1536
* system tables as regular tables, then no need to do this test.
1539
if (!atoi(ci->show_system_tables))
1541
if (strncmp(table_name, POSTGRES_SYS_PREFIX, strlen(POSTGRES_SYS_PREFIX)) == 0)
1546
/* Check extra system table prefixes */
1550
mylog("table_name='%s', prefix[%d]='%s'\n", table_name, i, prefix[i]);
1551
if (strncmp(table_name, prefix[i], strlen(prefix[i])) == 0)
1561
/* Determine if the table name is a view */
1562
if (PG_VERSION_GE(conn, 7.1))
1563
/* view is represented by its relkind since 7.1 */
1564
view = (relkind_or_hasrules[0] == 'v');
1566
view = (relkind_or_hasrules[0] == '1');
1568
/* It must be a regular table */
1569
regular_table = (!systable && !view);
1572
/* Include the row in the result set if meets all criteria */
1575
* NOTE: Unsupported table types (i.e., LOCAL TEMPORARY, ALIAS,
1576
* etc) will return nothing
1578
if ((systable && show_system_tables) ||
1579
(view && show_views) ||
1580
(regular_table && show_regular_tables))
1582
row = (TupleNode *) malloc(sizeof(TupleNode) + (5 - 1) *sizeof(TupleField));
1584
/*set_tuplefield_string(&row->tuple[0], "");*/
1585
set_tuplefield_null(&row->tuple[0]);
1588
* I have to hide the table owner from Access, otherwise it
1589
* insists on referring to the table as 'owner.table'. (this
1590
* is valid according to the ODBC SQL grammar, but Postgres
1591
* won't support it.)
1593
* set_tuplefield_string(&row->tuple[1], table_owner);
1596
mylog("%s: table_name = '%s'\n", func, table_name);
1598
if (conn->schema_support)
1599
set_tuplefield_string(&row->tuple[1], GET_SCHEMA_NAME(table_owner));
1601
set_tuplefield_null(&row->tuple[1]);
1602
set_tuplefield_string(&row->tuple[2], table_name);
1603
set_tuplefield_string(&row->tuple[3], systable ? "SYSTEM TABLE" : (view ? "VIEW" : "TABLE"));
1604
set_tuplefield_string(&row->tuple[4], "");
1605
/*** set_tuplefield_string(&row->tuple[4], "TABLE"); ***/
1607
QR_add_tuple(res, row);
1609
result = PGAPI_Fetch(htbl_stmt);
1611
if (result != SQL_NO_DATA_FOUND)
1613
SC_full_error_copy(stmt, htbl_stmt);
1614
SC_log_error(func, "", stmt);
1615
PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
1620
* also, things need to think that this statement is finished so the
1621
* results can be retrieved.
1623
stmt->status = STMT_FINISHED;
1625
/* set up the current tuple pointer for SQLFetch */
1626
stmt->currTuple = -1;
1627
stmt->rowset_start = -1;
1628
stmt->current_col = -1;
1630
PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
1631
mylog("%s: EXIT, stmt=%u\n", func, stmt);
1637
* PostgreSQL needs 2 '\\' to escape '_' and '%'.
1640
reallyEscapeCatalogEscapes(const char *src, int srclen, char *dest, int dst_len, int ccsc)
1644
BOOL escape_in = FALSE;
1647
if (srclen == SQL_NULL_DATA)
1652
else if (srclen == SQL_NTS)
1653
srclen = strlen(src);
1656
encoded_str_constr(&encstr, ccsc, src);
1657
for (i = 0, in = src, outlen = 0; i < srclen && outlen < dst_len; i++, in++)
1659
encoded_nextchar(&encstr);
1660
if (ENCODE_STATUS(encstr) != 0)
1662
dest[outlen++] = *in;
1671
dest[outlen++] = '\\'; /* needs 1 more */
1674
dest[outlen++] = '\\';
1675
if (outlen < dst_len)
1676
dest[outlen++] = '\\';
1677
if (outlen < dst_len)
1678
dest[outlen++] = '\\';
1686
if (outlen < dst_len)
1687
dest[outlen++] = *in;
1689
if (outlen < dst_len)
1690
dest[outlen] = '\0';
1697
UCHAR FAR * szTableQualifier,
1698
SWORD cbTableQualifier,
1699
UCHAR FAR * szTableOwner,
1701
UCHAR FAR * szTableName,
1703
UCHAR FAR * szColumnName,
1707
CSTR func = "PGAPI_Columns";
1708
StatementClass *stmt = (StatementClass *) hstmt;
1712
StatementClass *col_stmt;
1713
char columns_query[INFO_INQUIRY_LEN];
1715
char table_owner[MAX_INFO_STRING],
1716
table_name[MAX_INFO_STRING],
1717
field_name[MAX_INFO_STRING],
1718
field_type_name[MAX_INFO_STRING];
1719
Int2 field_number, sqltype,
1729
char useStaticPrecision;
1730
char not_null[MAX_INFO_STRING],
1731
relhasrules[MAX_INFO_STRING], relkind[8];
1734
ConnectionClass *conn;
1735
SWORD internal_asis_type = SQL_C_CHAR;
1736
const char *likeeq = "like";
1737
const char *mzTableOwner = szTableOwner, *mzTableName = szTableName,
1738
*mzColumnName = szColumnName;
1740
mylog("%s: entering...stmt=%u scnm=%x len=%d\n", func, stmt, szTableOwner, cbTableOwner);
1744
SC_log_error(func, "", NULL);
1745
return SQL_INVALID_HANDLE;
1748
stmt->manual_result = TRUE;
1749
stmt->errormsg_created = TRUE;
1751
conn = SC_get_conn(stmt);
1752
ci = &(conn->connInfo);
1753
#ifdef UNICODE_SUPPORT
1755
internal_asis_type = INTERNAL_ASIS_TYPE;
1756
#endif /* UNICODE_SUPPORT */
1759
* Create the query to find out the columns (Note: pre 6.3 did not
1760
* have the atttypmod field)
1762
if (conn->schema_support)
1763
sprintf(columns_query, "select u.nspname, c.relname, a.attname, a.atttypid"
1764
", t.typname, a.attnum, a.attlen, %s, a.attnotnull, c.relhasrules, c.relkind"
1765
" from pg_catalog.pg_namespace u, pg_catalog.pg_class c,"
1766
" pg_catalog.pg_attribute a, pg_catalog.pg_type t"
1767
" where u.oid = c.relnamespace"
1768
" and (not a.attisdropped)"
1769
" and c.oid= a.attrelid and a.atttypid = t.oid and (a.attnum > 0)",
1772
sprintf(columns_query, "select u.usename, c.relname, a.attname, a.atttypid"
1773
", t.typname, a.attnum, a.attlen, %s, a.attnotnull, c.relhasrules, c.relkind"
1774
" from pg_user u, pg_class c, pg_attribute a, pg_type t"
1775
" where u.usesysid = c.relowner"
1776
" and c.oid= a.attrelid and a.atttypid = t.oid and (a.attnum > 0)",
1777
PG_VERSION_LE(conn, 6.2) ? "a.attlen" : "a.atttypmod");
1779
if ((flag & PODBC_NOT_SEARCH_PATTERN) != 0)
1786
if ((flag & PODBC_NOT_SEARCH_PATTERN) != 0)
1788
my_strcat1(columns_query, " and c.relname %s '%.*s'", likeeq, mzTableName, cbTableName);
1789
if (conn->schema_support)
1790
schema_strcat1(columns_query, " and u.nspname %s '%.*s'", likeeq, mzTableOwner, cbTableOwner, mzTableName, cbTableName, conn);
1792
my_strcat1(columns_query, " and u.usename %s '%.*s'", likeeq, mzTableOwner, cbTableOwner);
1793
my_strcat1(columns_query, " and a.attname %s '%.*s'", likeeq, mzColumnName, cbColumnName);
1797
char esc_table_name[TABLE_NAME_STORAGE_LEN * 2];
1800
escTbnamelen = reallyEscapeCatalogEscapes(szTableName, cbTableName, esc_table_name, sizeof(esc_table_name), conn->ccsc);
1801
mzTableName = esc_table_name;
1802
my_strcat1(columns_query, " and c.relname %s '%.*s'", likeeq, mzTableName, escTbnamelen);
1803
if (conn->schema_support)
1804
schema_strcat1(columns_query, " and u.nspname %s '%.*s'", likeeq, szTableOwner, cbTableOwner, mzTableName, cbTableName, conn);
1806
my_strcat1(columns_query, " and u.usename %s '%.*s'", likeeq, mzTableOwner, cbTableOwner);
1807
my_strcat1(columns_query, " and a.attname %s '%.*s'", likeeq, mzColumnName, cbColumnName);
1811
* give the output in the order the columns were defined when the
1814
if (conn->schema_support)
1815
strcat(columns_query, " order by u.nspname, c.relname, attnum");
1817
strcat(columns_query, " order by c.relname, attnum");
1819
result = PGAPI_AllocStmt(stmt->hdbc, &hcol_stmt);
1820
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
1822
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate statement for PGAPI_Columns result.");
1823
SC_log_error(func, "", stmt);
1826
col_stmt = (StatementClass *) hcol_stmt;
1828
mylog("%s: hcol_stmt = %u, col_stmt = %u\n", func, hcol_stmt, col_stmt);
1830
result = PGAPI_ExecDirect(hcol_stmt, columns_query,
1831
strlen(columns_query));
1832
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
1834
SC_full_error_copy(stmt, col_stmt);
1835
SC_log_error(func, "", stmt);
1836
PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
1840
result = PGAPI_BindCol(hcol_stmt, 1, internal_asis_type,
1841
table_owner, MAX_INFO_STRING, NULL);
1842
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
1844
SC_error_copy(stmt, col_stmt);
1845
SC_log_error(func, "", stmt);
1846
PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
1850
result = PGAPI_BindCol(hcol_stmt, 2, internal_asis_type,
1851
table_name, MAX_INFO_STRING, NULL);
1852
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
1854
SC_error_copy(stmt, col_stmt);
1855
SC_log_error(func, "", stmt);
1856
PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
1860
result = PGAPI_BindCol(hcol_stmt, 3, internal_asis_type,
1861
field_name, MAX_INFO_STRING, NULL);
1862
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
1864
SC_error_copy(stmt, col_stmt);
1865
SC_log_error(func, "", stmt);
1866
PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
1870
result = PGAPI_BindCol(hcol_stmt, 4, SQL_C_LONG,
1871
&field_type, 4, NULL);
1872
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
1874
SC_error_copy(stmt, col_stmt);
1875
SC_log_error(func, "", stmt);
1876
PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
1880
result = PGAPI_BindCol(hcol_stmt, 5, internal_asis_type,
1881
field_type_name, MAX_INFO_STRING, NULL);
1882
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
1884
SC_error_copy(stmt, col_stmt);
1885
SC_log_error(func, "", stmt);
1886
PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
1890
result = PGAPI_BindCol(hcol_stmt, 6, SQL_C_SHORT,
1891
&field_number, MAX_INFO_STRING, NULL);
1892
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
1894
SC_error_copy(stmt, col_stmt);
1895
SC_log_error(func, "", stmt);
1896
PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
1900
result = PGAPI_BindCol(hcol_stmt, 7, SQL_C_LONG,
1901
&field_length, MAX_INFO_STRING, NULL);
1902
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
1904
SC_error_copy(stmt, col_stmt);
1905
SC_log_error(func, "", stmt);
1906
PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
1910
result = PGAPI_BindCol(hcol_stmt, 8, SQL_C_LONG,
1911
&mod_length, MAX_INFO_STRING, NULL);
1912
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
1914
SC_error_copy(stmt, col_stmt);
1915
SC_log_error(func, "", stmt);
1916
PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
1920
result = PGAPI_BindCol(hcol_stmt, 9, internal_asis_type,
1921
not_null, MAX_INFO_STRING, NULL);
1922
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
1924
SC_error_copy(stmt, col_stmt);
1925
SC_log_error(func, "", stmt);
1926
PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
1930
result = PGAPI_BindCol(hcol_stmt, 10, internal_asis_type,
1931
relhasrules, MAX_INFO_STRING, NULL);
1932
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
1934
SC_error_copy(stmt, col_stmt);
1935
SC_log_error(func, "", stmt);
1936
PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
1940
result = PGAPI_BindCol(hcol_stmt, 11, internal_asis_type,
1941
relkind, sizeof(relkind), NULL);
1942
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
1944
SC_error_copy(stmt, col_stmt);
1945
SC_log_error(func, "", stmt);
1946
PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
1950
if (res = QR_Constructor(), !res)
1952
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate memory for PGAPI_Columns result.");
1953
SC_log_error(func, "", stmt);
1954
PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
1957
SC_set_Result(stmt, res);
1959
/* the binding structure for a statement is not set up until */
1962
* a statement is actually executed, so we'll have to do this
1965
#if (ODBCVER >= 0x0300)
1969
#endif /* ODBCVER */
1970
result_cols = reserved_cols + 2;
1971
extend_column_bindings(SC_get_ARD(stmt), result_cols);
1973
/* set the field names */
1974
QR_set_num_fields(res, result_cols);
1975
QR_set_field_info(res, 0, "TABLE_QUALIFIER", PG_TYPE_VARCHAR, MAX_INFO_STRING);
1976
QR_set_field_info(res, 1, "TABLE_OWNER", PG_TYPE_VARCHAR, MAX_INFO_STRING);
1977
QR_set_field_info(res, 2, "TABLE_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
1978
QR_set_field_info(res, 3, "COLUMN_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
1979
QR_set_field_info(res, 4, "DATA_TYPE", PG_TYPE_INT2, 2);
1980
QR_set_field_info(res, 5, "TYPE_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
1981
QR_set_field_info(res, 6, "PRECISION", PG_TYPE_INT4, 4); /* COLUMN_SIZE */
1982
QR_set_field_info(res, 7, "LENGTH", PG_TYPE_INT4, 4); /* BUFFER_LENGTH */
1983
QR_set_field_info(res, 8, "SCALE", PG_TYPE_INT2, 2); /* DECIMAL_DIGITS ***/
1984
QR_set_field_info(res, 9, "RADIX", PG_TYPE_INT2, 2);
1985
QR_set_field_info(res, 10, "NULLABLE", PG_TYPE_INT2, 2);
1986
QR_set_field_info(res, 11, "REMARKS", PG_TYPE_VARCHAR, 254);
1988
/* User defined fields */
1989
#if (ODBCVER >= 0x0300)
1990
QR_set_field_info(res, 12, "COLUMN_DEF", PG_TYPE_INT4, 254);
1991
QR_set_field_info(res, 13, "SQL_DATA_TYPE", PG_TYPE_INT2, 2);
1992
QR_set_field_info(res, 14, "SQL_DATETIME_SUB", PG_TYPE_INT2, 2);
1993
QR_set_field_info(res, 15, "CHAR_OCTET_LENGTH", PG_TYPE_INT4, 4);
1994
QR_set_field_info(res, 16, "ORDINAL_POSITION", PG_TYPE_INT4, 4);
1995
QR_set_field_info(res, 17, "IS_NULLABLE", PG_TYPE_VARCHAR, 254);
1996
#endif /* ODBCVER */
1997
QR_set_field_info(res, reserved_cols, "DISPLAY_SIZE", PG_TYPE_INT4, 4);
1998
QR_set_field_info(res, reserved_cols + 1, "FIELD_TYPE", PG_TYPE_INT4, 4);
2001
result = PGAPI_Fetch(hcol_stmt);
2004
* Only show oid if option AND there are other columns AND it's not
2005
* being called by SQLStatistics . Always show OID if it's a system
2009
if (PG_VERSION_GE(conn, 7.1))
2010
relisaview = (relkind[0] == 'v');
2012
relisaview = (relhasrules[0] == '1');
2013
if (result != SQL_ERROR && !stmt->internal)
2016
(atoi(ci->show_oid_column) ||
2017
strncmp(table_name, POSTGRES_SYS_PREFIX, strlen(POSTGRES_SYS_PREFIX)) == 0))
2019
/* For OID fields */
2020
the_type = PG_TYPE_OID;
2021
row = (TupleNode *) malloc(sizeof(TupleNode) +
2022
(result_cols - 1) *sizeof(TupleField));
2024
set_tuplefield_string(&row->tuple[0], "");
2025
/* see note in SQLTables() */
2026
if (conn->schema_support)
2027
set_tuplefield_string(&row->tuple[1], GET_SCHEMA_NAME(table_owner));
2029
set_tuplefield_string(&row->tuple[1], "");
2030
set_tuplefield_string(&row->tuple[2], table_name);
2031
set_tuplefield_string(&row->tuple[3], "oid");
2032
sqltype = pgtype_to_concise_type(stmt, the_type);
2033
set_tuplefield_int2(&row->tuple[4], sqltype);
2034
set_tuplefield_string(&row->tuple[5], "OID");
2036
set_tuplefield_int4(&row->tuple[6], pgtype_column_size(stmt, the_type, PG_STATIC, PG_STATIC));
2037
set_tuplefield_int4(&row->tuple[7], pgtype_buffer_length(stmt, the_type, PG_STATIC, PG_STATIC));
2038
set_nullfield_int2(&row->tuple[8], pgtype_decimal_digits(stmt, the_type, PG_STATIC));
2039
set_nullfield_int2(&row->tuple[9], pgtype_radix(stmt, the_type));
2040
set_tuplefield_int2(&row->tuple[10], SQL_NO_NULLS);
2041
set_tuplefield_string(&row->tuple[11], "");
2043
#if (ODBCVER >= 0x0300)
2044
set_tuplefield_null(&row->tuple[12]);
2045
set_tuplefield_int2(&row->tuple[13], sqltype);
2046
set_tuplefield_null(&row->tuple[14]);
2047
set_tuplefield_int4(&row->tuple[15], pgtype_transfer_octet_length(stmt, the_type, PG_STATIC, PG_STATIC));
2048
set_tuplefield_int4(&row->tuple[16], ordinal);
2049
set_tuplefield_string(&row->tuple[17], "No");
2050
#endif /* ODBCVER */
2051
set_tuplefield_int4(&row->tuple[reserved_cols], pgtype_display_size(stmt, the_type, PG_STATIC, PG_STATIC));
2052
set_tuplefield_int4(&row->tuple[reserved_cols + 1], the_type);
2054
QR_add_tuple(res, row);
2059
while ((result == SQL_SUCCESS) || (result == SQL_SUCCESS_WITH_INFO))
2061
row = (TupleNode *) malloc(sizeof(TupleNode) +
2062
(result_cols - 1) *sizeof(TupleField));
2065
set_tuplefield_string(&row->tuple[0], "");
2066
/* see note in SQLTables() */
2067
if (conn->schema_support)
2068
set_tuplefield_string(&row->tuple[1], GET_SCHEMA_NAME(table_owner));
2070
set_tuplefield_string(&row->tuple[1], "");
2071
set_tuplefield_string(&row->tuple[2], table_name);
2072
set_tuplefield_string(&row->tuple[3], field_name);
2073
sqltype = pgtype_to_concise_type(stmt, field_type);
2074
set_tuplefield_int2(&row->tuple[4], sqltype);
2075
set_tuplefield_string(&row->tuple[5], field_type_name);
2079
* Some Notes about Postgres Data Types:
2081
* VARCHAR - the length is stored in the pg_attribute.atttypmod field
2082
* BPCHAR - the length is also stored as varchar is
2084
* NUMERIC - the decimal_digits is stored in atttypmod as follows:
2086
* column_size =((atttypmod - VARHDRSZ) >> 16) & 0xffff
2087
* decimal_digits = (atttypmod - VARHDRSZ) & 0xffff
2091
qlog("PGAPI_Columns: table='%s',field_name='%s',type=%d,name='%s'\n",
2092
table_name, field_name, field_type, field_type_name);
2094
useStaticPrecision = TRUE;
2096
if (field_type == PG_TYPE_NUMERIC)
2098
if (mod_length >= 4)
2099
mod_length -= 4; /* the length is in atttypmod - 4 */
2101
if (mod_length >= 0)
2103
useStaticPrecision = FALSE;
2105
column_size = (mod_length >> 16) & 0xffff;
2106
decimal_digits = mod_length & 0xffff;
2108
mylog("%s: field type is NUMERIC: field_type = %d, mod_length=%d, precision=%d, scale=%d\n", func, field_type, mod_length, column_size, decimal_digits);
2110
set_tuplefield_int4(&row->tuple[6], column_size);
2111
set_tuplefield_int4(&row->tuple[7], column_size + 2); /* sign+dec.point */
2112
set_nullfield_int2(&row->tuple[8], decimal_digits);
2113
#if (ODBCVER >= 0x0300)
2114
set_tuplefield_null(&row->tuple[15]);
2115
#endif /* ODBCVER */
2116
set_tuplefield_int4(&row->tuple[reserved_cols], column_size + 2); /* sign+dec.point */
2120
if ((field_type == PG_TYPE_VARCHAR) ||
2121
(field_type == PG_TYPE_BPCHAR))
2123
useStaticPrecision = FALSE;
2125
if (mod_length >= 4)
2126
mod_length -= 4; /* the length is in atttypmod - 4 */
2128
if (mod_length > ci->drivers.max_varchar_size || mod_length <= 0)
2129
mod_length = ci->drivers.max_varchar_size;
2131
mylog("%s: field type is VARCHAR,BPCHAR: field_type = %d, mod_length = %d\n", func, field_type, mod_length);
2133
set_tuplefield_int4(&row->tuple[6], mod_length);
2134
set_tuplefield_int4(&row->tuple[7], mod_length);
2135
set_nullfield_int2(&row->tuple[8], pgtype_decimal_digits(stmt, field_type, PG_STATIC));
2136
#if (ODBCVER >= 0x0300)
2137
set_tuplefield_int4(&row->tuple[15], pgtype_transfer_octet_length(stmt, field_type, PG_STATIC, PG_STATIC));
2138
#endif /* ODBCVER */
2139
set_tuplefield_int4(&row->tuple[reserved_cols], mod_length);
2142
if (useStaticPrecision)
2144
mylog("%s: field type is OTHER: field_type = %d, pgtype_length = %d\n", func, field_type, pgtype_buffer_length(stmt, field_type, PG_STATIC, PG_STATIC));
2146
set_tuplefield_int4(&row->tuple[6], pgtype_column_size(stmt, field_type, PG_STATIC, PG_STATIC));
2147
set_tuplefield_int4(&row->tuple[7], pgtype_buffer_length(stmt, field_type, PG_STATIC, PG_STATIC));
2148
set_nullfield_int2(&row->tuple[8], pgtype_decimal_digits(stmt, field_type, PG_STATIC));
2149
#if (ODBCVER >= 0x0300)
2150
set_tuplefield_null(&row->tuple[15]);
2151
#endif /* ODBCVER */
2152
set_tuplefield_int4(&row->tuple[reserved_cols], pgtype_display_size(stmt, field_type, PG_STATIC, PG_STATIC));
2155
set_nullfield_int2(&row->tuple[9], pgtype_radix(stmt, field_type));
2156
set_tuplefield_int2(&row->tuple[10], (Int2) (not_null[0] == '1' ? SQL_NO_NULLS : pgtype_nullable(stmt, field_type)));
2157
set_tuplefield_string(&row->tuple[11], "");
2158
#if (ODBCVER >= 0x0300)
2159
set_tuplefield_null(&row->tuple[12]);
2160
set_tuplefield_int2(&row->tuple[13], pgtype_to_sqldesctype(stmt, field_type));
2161
set_nullfield_int2(&row->tuple[14], pgtype_to_datetime_sub(stmt, field_type));
2162
set_tuplefield_int4(&row->tuple[16], ordinal);
2163
set_tuplefield_null(&row->tuple[17]);
2164
#endif /* ODBCVER */
2165
set_tuplefield_int4(&row->tuple[reserved_cols + 1], field_type);
2167
QR_add_tuple(res, row);
2170
result = PGAPI_Fetch(hcol_stmt);
2173
if (result != SQL_NO_DATA_FOUND)
2175
SC_full_error_copy(stmt, col_stmt);
2176
SC_log_error(func, "", stmt);
2177
PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
2182
* Put the row version column at the end so it might not be mistaken
2185
if (!relisaview && !stmt->internal && atoi(ci->row_versioning))
2187
/* For Row Versioning fields */
2188
the_type = PG_TYPE_INT4;
2190
row = (TupleNode *) malloc(sizeof(TupleNode) +
2191
(result_cols - 1) *sizeof(TupleField));
2193
set_tuplefield_string(&row->tuple[0], "");
2194
if (conn->schema_support)
2195
set_tuplefield_string(&row->tuple[1], GET_SCHEMA_NAME(table_owner));
2197
set_tuplefield_string(&row->tuple[1], "");
2198
set_tuplefield_string(&row->tuple[2], table_name);
2199
set_tuplefield_string(&row->tuple[3], "xmin");
2200
sqltype = pgtype_to_concise_type(stmt, the_type);
2201
set_tuplefield_int2(&row->tuple[4], sqltype);
2202
set_tuplefield_string(&row->tuple[5], pgtype_to_name(stmt, the_type));
2203
set_tuplefield_int4(&row->tuple[6], pgtype_column_size(stmt, the_type, PG_STATIC, PG_STATIC));
2204
set_tuplefield_int4(&row->tuple[7], pgtype_buffer_length(stmt, the_type, PG_STATIC, PG_STATIC));
2205
set_nullfield_int2(&row->tuple[8], pgtype_decimal_digits(stmt, the_type, PG_STATIC));
2206
set_nullfield_int2(&row->tuple[9], pgtype_radix(stmt, the_type));
2207
set_tuplefield_int2(&row->tuple[10], SQL_NO_NULLS);
2208
set_tuplefield_string(&row->tuple[11], "");
2209
#if (ODBCVER >= 0x0300)
2210
set_tuplefield_null(&row->tuple[12]);
2211
set_tuplefield_int2(&row->tuple[13], sqltype);
2212
set_tuplefield_null(&row->tuple[14]);
2213
set_tuplefield_int4(&row->tuple[15], pgtype_transfer_octet_length(stmt, the_type, PG_STATIC, PG_STATIC));
2214
set_tuplefield_int4(&row->tuple[16], ordinal);
2215
set_tuplefield_string(&row->tuple[17], "No");
2216
#endif /* ODBCVER */
2217
set_tuplefield_int4(&row->tuple[reserved_cols], pgtype_display_size(stmt, the_type, PG_STATIC, PG_STATIC));
2218
set_tuplefield_int4(&row->tuple[reserved_cols + 1], the_type);
2220
QR_add_tuple(res, row);
2225
* also, things need to think that this statement is finished so the
2226
* results can be retrieved.
2228
stmt->status = STMT_FINISHED;
2230
/* set up the current tuple pointer for SQLFetch */
2231
stmt->currTuple = -1;
2232
stmt->rowset_start = -1;
2233
stmt->current_col = -1;
2235
PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
2236
mylog("%s: EXIT, stmt=%u\n", func, stmt);
2242
PGAPI_SpecialColumns(
2245
UCHAR FAR * szTableQualifier,
2246
SWORD cbTableQualifier,
2247
UCHAR FAR * szTableOwner,
2249
UCHAR FAR * szTableName,
2254
CSTR func = "PGAPI_SpecialColumns";
2256
StatementClass *stmt = (StatementClass *) hstmt;
2257
ConnectionClass *conn;
2261
StatementClass *col_stmt;
2262
char columns_query[INFO_INQUIRY_LEN];
2264
char relhasrules[MAX_INFO_STRING], relkind[8], relhasoids[8];
2266
SWORD internal_asis_type = SQL_C_CHAR;
2268
mylog("%s: entering...stmt=%u scnm=%x len=%d colType=%d\n", func, stmt, szTableOwner, cbTableOwner, fColType);
2272
SC_log_error(func, "", NULL);
2273
return SQL_INVALID_HANDLE;
2275
conn = SC_get_conn(stmt);
2276
ci = &(conn->connInfo);
2277
#ifdef UNICODE_SUPPORT
2279
internal_asis_type = INTERNAL_ASIS_TYPE;
2280
#endif /* UNICODE_SUPPORT */
2282
stmt->manual_result = TRUE;
2285
* Create the query to find out if this is a view or not...
2287
strcpy(columns_query, "select c.relhasrules, c.relkind");
2288
if (PG_VERSION_GE(conn, 7.2))
2289
strcat(columns_query, ", c.relhasoids");
2290
if (conn->schema_support)
2291
strcat(columns_query, " from pg_catalog.pg_namespace u,"
2292
" pg_catalog.pg_class c where "
2293
"u.oid = c.relnamespace");
2295
strcat(columns_query, " from pg_user u, pg_class c where "
2296
"u.usesysid = c.relowner");
2298
/* TableName cannot contain a string search pattern */
2299
my_strcat(columns_query, " and c.relname = '%.*s'", szTableName, cbTableName);
2300
/* SchemaName cannot contain a string search pattern */
2301
if (conn->schema_support)
2302
schema_strcat(columns_query, " and u.nspname = '%.*s'", szTableOwner, cbTableOwner, szTableName, cbTableName, conn);
2304
my_strcat(columns_query, " and u.usename = '%.*s'", szTableOwner, cbTableOwner);
2307
result = PGAPI_AllocStmt(stmt->hdbc, &hcol_stmt);
2308
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
2310
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate statement for SQLSpecialColumns result.");
2311
SC_log_error(func, "", stmt);
2314
col_stmt = (StatementClass *) hcol_stmt;
2316
mylog("%s: hcol_stmt = %u, col_stmt = %u\n", func, hcol_stmt, col_stmt);
2318
result = PGAPI_ExecDirect(hcol_stmt, columns_query,
2319
strlen(columns_query));
2320
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
2322
SC_full_error_copy(stmt, col_stmt);
2323
SC_log_error(func, "", stmt);
2324
PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
2328
result = PGAPI_BindCol(hcol_stmt, 1, internal_asis_type,
2329
relhasrules, sizeof(relhasrules), NULL);
2330
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
2332
SC_error_copy(stmt, col_stmt);
2333
SC_log_error(func, "", stmt);
2334
PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
2338
result = PGAPI_BindCol(hcol_stmt, 2, internal_asis_type,
2339
relkind, sizeof(relkind), NULL);
2340
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
2342
SC_error_copy(stmt, col_stmt);
2343
SC_log_error(func, "", stmt);
2344
PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
2347
relhasoids[0] = '1';
2348
if (PG_VERSION_GE(conn, 7.2))
2350
result = PGAPI_BindCol(hcol_stmt, 3, internal_asis_type,
2351
relhasoids, sizeof(relhasoids), NULL);
2352
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
2354
SC_error_copy(stmt, col_stmt);
2355
SC_log_error(func, "", stmt);
2356
PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
2361
result = PGAPI_Fetch(hcol_stmt);
2362
if (PG_VERSION_GE(conn, 7.1))
2363
relisaview = (relkind[0] == 'v');
2365
relisaview = (relhasrules[0] == '1');
2366
PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
2368
res = QR_Constructor();
2369
SC_set_Result(stmt, res);
2370
extend_column_bindings(SC_get_ARD(stmt), 8);
2372
QR_set_num_fields(res, 8);
2373
QR_set_field_info(res, 0, "SCOPE", PG_TYPE_INT2, 2);
2374
QR_set_field_info(res, 1, "COLUMN_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
2375
QR_set_field_info(res, 2, "DATA_TYPE", PG_TYPE_INT2, 2);
2376
QR_set_field_info(res, 3, "TYPE_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
2377
QR_set_field_info(res, 4, "PRECISION", PG_TYPE_INT4, 4);
2378
QR_set_field_info(res, 5, "LENGTH", PG_TYPE_INT4, 4);
2379
QR_set_field_info(res, 6, "SCALE", PG_TYPE_INT2, 2);
2380
QR_set_field_info(res, 7, "PSEUDO_COLUMN", PG_TYPE_INT2, 2);
2384
/* there's no oid for views */
2385
if (fColType == SQL_BEST_ROWID)
2387
return SQL_NO_DATA_FOUND;
2389
else if (fColType == SQL_ROWVER)
2391
Int2 the_type = PG_TYPE_TID;
2393
row = (TupleNode *) malloc(sizeof(TupleNode) + (8 - 1) *sizeof(TupleField));
2395
set_tuplefield_null(&row->tuple[0]);
2396
set_tuplefield_string(&row->tuple[1], "ctid");
2397
set_tuplefield_int2(&row->tuple[2], pgtype_to_concise_type(stmt, the_type));
2398
set_tuplefield_string(&row->tuple[3], pgtype_to_name(stmt, the_type));
2399
set_tuplefield_int4(&row->tuple[4], pgtype_column_size(stmt, the_type, PG_STATIC, PG_STATIC));
2400
set_tuplefield_int4(&row->tuple[5], pgtype_buffer_length(stmt, the_type, PG_STATIC, PG_STATIC));
2401
set_tuplefield_int2(&row->tuple[6], pgtype_decimal_digits(stmt, the_type, PG_STATIC));
2402
set_tuplefield_int2(&row->tuple[7], SQL_PC_NOT_PSEUDO);
2404
QR_add_tuple(res, row);
2405
inolog("Add ctid\n");
2410
/* use the oid value for the rowid */
2411
if (fColType == SQL_BEST_ROWID)
2413
if (relhasoids[0] != '1')
2414
return SQL_NO_DATA_FOUND;
2415
row = (TupleNode *) malloc(sizeof(TupleNode) + (8 - 1) *sizeof(TupleField));
2417
set_tuplefield_int2(&row->tuple[0], SQL_SCOPE_SESSION);
2418
set_tuplefield_string(&row->tuple[1], "oid");
2419
set_tuplefield_int2(&row->tuple[2], pgtype_to_concise_type(stmt, PG_TYPE_OID));
2420
set_tuplefield_string(&row->tuple[3], "OID");
2421
set_tuplefield_int4(&row->tuple[4], pgtype_column_size(stmt, PG_TYPE_OID, PG_STATIC, PG_STATIC));
2422
set_tuplefield_int4(&row->tuple[5], pgtype_buffer_length(stmt, PG_TYPE_OID, PG_STATIC, PG_STATIC));
2423
set_tuplefield_int2(&row->tuple[6], pgtype_decimal_digits(stmt, PG_TYPE_OID, PG_STATIC));
2424
set_tuplefield_int2(&row->tuple[7], SQL_PC_PSEUDO);
2426
QR_add_tuple(res, row);
2429
else if (fColType == SQL_ROWVER)
2431
Int2 the_type = PG_TYPE_INT4;
2433
if (atoi(ci->row_versioning))
2435
row = (TupleNode *) malloc(sizeof(TupleNode) + (8 - 1) *sizeof(TupleField));
2437
set_tuplefield_null(&row->tuple[0]);
2438
set_tuplefield_string(&row->tuple[1], "xmin");
2439
set_tuplefield_int2(&row->tuple[2], pgtype_to_concise_type(stmt, the_type));
2440
set_tuplefield_string(&row->tuple[3], pgtype_to_name(stmt, the_type));
2441
set_tuplefield_int4(&row->tuple[4], pgtype_column_size(stmt, the_type, PG_STATIC, PG_STATIC));
2442
set_tuplefield_int4(&row->tuple[5], pgtype_buffer_length(stmt, the_type, PG_STATIC, PG_STATIC));
2443
set_tuplefield_int2(&row->tuple[6], pgtype_decimal_digits(stmt, the_type, PG_STATIC));
2444
set_tuplefield_int2(&row->tuple[7], SQL_PC_PSEUDO);
2446
QR_add_tuple(res, row);
2451
stmt->status = STMT_FINISHED;
2452
stmt->currTuple = -1;
2453
stmt->rowset_start = -1;
2454
stmt->current_col = -1;
2456
mylog("%s: EXIT, stmt=%u\n", func, stmt);
2464
UCHAR FAR * szTableQualifier,
2465
SWORD cbTableQualifier,
2466
UCHAR FAR * szTableOwner,
2468
UCHAR FAR * szTableName,
2473
CSTR func = "PGAPI_Statistics";
2474
StatementClass *stmt = (StatementClass *) hstmt;
2475
ConnectionClass *conn;
2477
char index_query[INFO_INQUIRY_LEN];
2481
char index_name[MAX_INFO_STRING];
2482
short fields_vector[INDEX_KEYS_STORAGE_COUNT];
2485
ishash[MAX_INFO_STRING];
2486
SDWORD index_name_len,
2491
StatementClass *col_stmt,
2493
char column_name[MAX_INFO_STRING],
2494
table_qualifier[MAX_INFO_STRING],
2495
relhasrules[10], relkind[8];
2496
char **column_names = 0;
2497
SQLINTEGER column_name_len;
2498
int total_columns = 0;
2502
SWORD internal_asis_type = SQL_C_CHAR;
2504
mylog("%s: entering...stmt=%u scnm=%x len=%d\n", func, stmt, szTableOwner, cbTableOwner);
2508
SC_log_error(func, "", NULL);
2509
return SQL_INVALID_HANDLE;
2512
stmt->manual_result = TRUE;
2513
stmt->errormsg_created = TRUE;
2515
conn = SC_get_conn(stmt);
2516
ci = &(conn->connInfo);
2517
#ifdef UNICODE_SUPPORT
2519
internal_asis_type = INTERNAL_ASIS_TYPE;
2520
#endif /* UNICODE_SUPPORT */
2522
if (res = QR_Constructor(), !res)
2524
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate memory for PGAPI_Statistics result.");
2525
SC_log_error(func, "", stmt);
2528
SC_set_Result(stmt, res);
2530
/* the binding structure for a statement is not set up until */
2533
* a statement is actually executed, so we'll have to do this
2536
extend_column_bindings(SC_get_ARD(stmt), 13);
2538
/* set the field names */
2539
QR_set_num_fields(res, 13);
2540
QR_set_field_info(res, 0, "TABLE_QUALIFIER", PG_TYPE_VARCHAR, MAX_INFO_STRING);
2541
QR_set_field_info(res, 1, "TABLE_OWNER", PG_TYPE_VARCHAR, MAX_INFO_STRING);
2542
QR_set_field_info(res, 2, "TABLE_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
2543
QR_set_field_info(res, 3, "NON_UNIQUE", PG_TYPE_INT2, 2);
2544
QR_set_field_info(res, 4, "INDEX_QUALIFIER", PG_TYPE_VARCHAR, MAX_INFO_STRING);
2545
QR_set_field_info(res, 5, "INDEX_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
2546
QR_set_field_info(res, 6, "TYPE", PG_TYPE_INT2, 2);
2547
QR_set_field_info(res, 7, "SEQ_IN_INDEX", PG_TYPE_INT2, 2);
2548
QR_set_field_info(res, 8, "COLUMN_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
2549
QR_set_field_info(res, 9, "COLLATION", PG_TYPE_CHAR, 1);
2550
QR_set_field_info(res, 10, "CARDINALITY", PG_TYPE_INT4, 4);
2551
QR_set_field_info(res, 11, "PAGES", PG_TYPE_INT4, 4);
2552
QR_set_field_info(res, 12, "FILTER_CONDITION", PG_TYPE_VARCHAR, MAX_INFO_STRING);
2555
* only use the table name... the owner should be redundant, and we
2556
* never use qualifiers.
2558
table_name = make_string(szTableName, cbTableName, NULL);
2561
SC_set_error(stmt, STMT_INTERNAL_ERROR, "No table name passed to PGAPI_Statistics.");
2562
SC_log_error(func, "", stmt);
2565
table_qualifier[0] = '\0';
2566
if (conn->schema_support)
2567
schema_strcat(table_qualifier, "%.*s", szTableOwner, cbTableOwner, szTableName, cbTableName, conn);
2570
* we need to get a list of the field names first, so we can return
2573
result = PGAPI_AllocStmt(stmt->hdbc, &hcol_stmt);
2574
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
2576
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "PGAPI_AllocStmt failed in PGAPI_Statistics for columns.");
2580
col_stmt = (StatementClass *) hcol_stmt;
2583
* "internal" prevents SQLColumns from returning the oid if it is
2584
* being shown. This would throw everything off.
2586
col_stmt->internal = TRUE;
2588
* table_name parameter cannot contain a string search pattern.
2590
result = PGAPI_Columns(hcol_stmt, "", 0, table_qualifier, SQL_NTS,
2591
table_name, SQL_NTS, "", 0, PODBC_NOT_SEARCH_PATTERN);
2592
col_stmt->internal = FALSE;
2594
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
2596
SC_error_copy(stmt, col_stmt);
2597
PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
2600
result = PGAPI_BindCol(hcol_stmt, 4, internal_asis_type,
2601
column_name, sizeof(column_name), &column_name_len);
2602
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
2604
SC_error_copy(stmt, col_stmt);
2605
PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
2610
result = PGAPI_Fetch(hcol_stmt);
2611
while ((result == SQL_SUCCESS) || (result == SQL_SUCCESS_WITH_INFO))
2616
(char **) realloc(column_names,
2617
total_columns * sizeof(char *));
2618
column_names[total_columns - 1] =
2619
(char *) malloc(strlen(column_name) + 1);
2620
strcpy(column_names[total_columns - 1], column_name);
2622
mylog("%s: column_name = '%s'\n", func, column_name);
2624
result = PGAPI_Fetch(hcol_stmt);
2627
if (result != SQL_NO_DATA_FOUND || total_columns == 0)
2629
SC_full_error_copy(stmt, col_stmt); /* "Couldn't get column
2631
* SQLStatistics."; */
2632
PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
2637
PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
2639
/* get a list of indexes on this table */
2640
result = PGAPI_AllocStmt(stmt->hdbc, &hindx_stmt);
2641
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
2643
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "PGAPI_AllocStmt failed in SQLStatistics for indices.");
2647
indx_stmt = (StatementClass *) hindx_stmt;
2649
if (conn->schema_support)
2650
sprintf(index_query, "select c.relname, i.indkey, i.indisunique"
2651
", i.indisclustered, a.amname, c.relhasrules, n.nspname"
2652
" from pg_catalog.pg_index i, pg_catalog.pg_class c,"
2653
" pg_catalog.pg_class d, pg_catalog.pg_am a,"
2654
" pg_catalog.pg_namespace n"
2655
" where d.relname = '%s'"
2656
" and n.nspname = '%s'"
2657
" and n.oid = d.relnamespace"
2658
" and d.oid = i.indrelid"
2659
" and i.indexrelid = c.oid"
2660
" and c.relam = a.oid order by"
2661
,table_name, table_qualifier);
2663
sprintf(index_query, "select c.relname, i.indkey, i.indisunique"
2664
", i.indisclustered, a.amname, c.relhasrules"
2665
" from pg_index i, pg_class c, pg_class d, pg_am a"
2666
" where d.relname = '%s'"
2667
" and d.oid = i.indrelid"
2668
" and i.indexrelid = c.oid"
2669
" and c.relam = a.oid order by"
2671
if (PG_VERSION_GT(SC_get_conn(stmt), 6.4))
2672
strcat(index_query, " i.indisprimary desc,");
2673
if (conn->schema_support)
2674
strcat(index_query, " i.indisunique, n.nspname, c.relname");
2676
strcat(index_query, " i.indisunique, c.relname");
2678
result = PGAPI_ExecDirect(hindx_stmt, index_query, strlen(index_query));
2679
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
2682
* "Couldn't execute index query (w/SQLExecDirect) in
2685
SC_full_error_copy(stmt, indx_stmt);
2686
PGAPI_FreeStmt(hindx_stmt, SQL_DROP);
2690
/* bind the index name column */
2691
result = PGAPI_BindCol(hindx_stmt, 1, internal_asis_type,
2692
index_name, MAX_INFO_STRING, &index_name_len);
2693
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
2695
SC_error_copy(stmt, indx_stmt); /* "Couldn't bind column
2696
* in SQLStatistics."; */
2697
PGAPI_FreeStmt(hindx_stmt, SQL_DROP);
2701
/* bind the vector column */
2702
result = PGAPI_BindCol(hindx_stmt, 2, SQL_C_DEFAULT,
2703
fields_vector, INDEX_KEYS_STORAGE_COUNT * 2, &fields_vector_len);
2704
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
2706
SC_error_copy(stmt, indx_stmt); /* "Couldn't bind column
2707
* in SQLStatistics."; */
2708
PGAPI_FreeStmt(hindx_stmt, SQL_DROP);
2712
/* bind the "is unique" column */
2713
result = PGAPI_BindCol(hindx_stmt, 3, internal_asis_type,
2714
isunique, sizeof(isunique), NULL);
2715
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
2717
SC_error_copy(stmt, indx_stmt); /* "Couldn't bind column
2718
* in SQLStatistics."; */
2719
PGAPI_FreeStmt(hindx_stmt, SQL_DROP);
2723
/* bind the "is clustered" column */
2724
result = PGAPI_BindCol(hindx_stmt, 4, internal_asis_type,
2725
isclustered, sizeof(isclustered), NULL);
2726
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
2728
SC_error_copy(stmt, indx_stmt); /* "Couldn't bind column *
2729
* in SQLStatistics."; */
2730
PGAPI_FreeStmt(hindx_stmt, SQL_DROP);
2735
/* bind the "is hash" column */
2736
result = PGAPI_BindCol(hindx_stmt, 5, internal_asis_type,
2737
ishash, sizeof(ishash), NULL);
2738
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
2740
SC_error_copy(stmt, indx_stmt); /* "Couldn't bind column *
2741
* in SQLStatistics."; */
2742
PGAPI_FreeStmt(hindx_stmt, SQL_DROP);
2747
result = PGAPI_BindCol(hindx_stmt, 6, internal_asis_type,
2748
relhasrules, sizeof(relhasrules), NULL);
2749
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
2751
SC_error_copy(stmt, indx_stmt);
2752
PGAPI_FreeStmt(hindx_stmt, SQL_DROP);
2756
relhasrules[0] = '0';
2757
result = PGAPI_Fetch(hindx_stmt);
2758
/* fake index of OID */
2759
if (relhasrules[0] != '1' && atoi(ci->show_oid_column) && atoi(ci->fake_oid_index))
2761
row = (TupleNode *) malloc(sizeof(TupleNode) +
2762
(13 - 1) *sizeof(TupleField));
2764
/* no table qualifier */
2765
set_tuplefield_string(&row->tuple[0], "");
2766
/* don't set the table owner, else Access tries to use it */
2767
set_tuplefield_string(&row->tuple[1], GET_SCHEMA_NAME(table_qualifier));
2768
set_tuplefield_string(&row->tuple[2], table_name);
2770
/* non-unique index? */
2771
set_tuplefield_int2(&row->tuple[3], (Int2) (ci->drivers.unique_index ? FALSE : TRUE));
2773
/* no index qualifier */
2774
set_tuplefield_string(&row->tuple[4], "");
2776
sprintf(buf, "%s_idx_fake_oid", table_name);
2777
set_tuplefield_string(&row->tuple[5], buf);
2780
* Clustered/HASH index?
2782
set_tuplefield_int2(&row->tuple[6], (Int2) SQL_INDEX_OTHER);
2783
set_tuplefield_int2(&row->tuple[7], (Int2) 1);
2785
set_tuplefield_string(&row->tuple[8], "oid");
2786
set_tuplefield_string(&row->tuple[9], "A");
2787
set_tuplefield_null(&row->tuple[10]);
2788
set_tuplefield_null(&row->tuple[11]);
2789
set_tuplefield_null(&row->tuple[12]);
2791
QR_add_tuple(res, row);
2794
while ((result == SQL_SUCCESS) || (result == SQL_SUCCESS_WITH_INFO))
2796
/* If only requesting unique indexs, then just return those. */
2797
if (fUnique == SQL_INDEX_ALL ||
2798
(fUnique == SQL_INDEX_UNIQUE && atoi(isunique)))
2801
/* add a row in this table for each field in the index */
2802
while (i < INDEX_KEYS_STORAGE_COUNT && fields_vector[i] != 0)
2804
row = (TupleNode *) malloc(sizeof(TupleNode) +
2805
(13 - 1) *sizeof(TupleField));
2807
/* no table qualifier */
2808
set_tuplefield_string(&row->tuple[0], "");
2809
/* don't set the table owner, else Access tries to use it */
2810
set_tuplefield_string(&row->tuple[1], GET_SCHEMA_NAME(table_qualifier));
2811
set_tuplefield_string(&row->tuple[2], table_name);
2813
/* non-unique index? */
2814
if (ci->drivers.unique_index)
2815
set_tuplefield_int2(&row->tuple[3], (Int2) (atoi(isunique) ? FALSE : TRUE));
2817
set_tuplefield_int2(&row->tuple[3], TRUE);
2819
/* no index qualifier */
2820
set_tuplefield_string(&row->tuple[4], "");
2821
set_tuplefield_string(&row->tuple[5], index_name);
2824
* Clustered/HASH index?
2826
set_tuplefield_int2(&row->tuple[6], (Int2)
2827
(atoi(isclustered) ? SQL_INDEX_CLUSTERED :
2828
(!strncmp(ishash, "hash", 4)) ? SQL_INDEX_HASHED : SQL_INDEX_OTHER));
2829
set_tuplefield_int2(&row->tuple[7], (Int2) (i + 1));
2831
if (fields_vector[i] == OID_ATTNUM)
2833
set_tuplefield_string(&row->tuple[8], "oid");
2834
mylog("%s: column name = oid\n", func);
2836
else if (fields_vector[i] < 0 || fields_vector[i] > total_columns)
2838
set_tuplefield_string(&row->tuple[8], "UNKNOWN");
2839
mylog("%s: column name = UNKNOWN\n", func);
2843
set_tuplefield_string(&row->tuple[8], column_names[fields_vector[i] - 1]);
2844
mylog("%s: column name = '%s'\n", func, column_names[fields_vector[i] - 1]);
2847
set_tuplefield_string(&row->tuple[9], "A");
2848
set_tuplefield_null(&row->tuple[10]);
2849
set_tuplefield_null(&row->tuple[11]);
2850
set_tuplefield_null(&row->tuple[12]);
2852
QR_add_tuple(res, row);
2857
result = PGAPI_Fetch(hindx_stmt);
2859
if (result != SQL_NO_DATA_FOUND)
2861
/* "SQLFetch failed in SQLStatistics."; */
2862
SC_full_error_copy(stmt, indx_stmt);
2863
PGAPI_FreeStmt(hindx_stmt, SQL_DROP);
2867
PGAPI_FreeStmt(hindx_stmt, SQL_DROP);
2870
* also, things need to think that this statement is finished so the
2871
* results can be retrieved.
2873
stmt->status = STMT_FINISHED;
2875
/* set up the current tuple pointer for SQLFetch */
2876
stmt->currTuple = -1;
2877
stmt->rowset_start = -1;
2878
stmt->current_col = -1;
2883
/* These things should be freed on any error ALSO! */
2885
for (i = 0; i < total_columns; i++)
2886
free(column_names[i]);
2889
mylog("%s: EXIT, %s, stmt=%u\n", func, error ? "error" : "success", stmt);
2893
SC_log_error(func, "", stmt);
2902
PGAPI_ColumnPrivileges(
2904
UCHAR FAR * szTableQualifier,
2905
SWORD cbTableQualifier,
2906
UCHAR FAR * szTableOwner,
2908
UCHAR FAR * szTableName,
2910
UCHAR FAR * szColumnName,
2913
CSTR func = "PGAPI_ColumnPrivileges";
2914
StatementClass *stmt = (StatementClass *) hstmt;
2916
mylog("%s: entering...\n", func);
2918
/* Neither Access or Borland care about this. */
2920
SC_set_error(stmt, STMT_NOT_IMPLEMENTED_ERROR, "not implemented");
2921
SC_log_error(func, "Function not implemented", stmt);
2929
* Retrieve the primary key columns for the specified table.
2934
UCHAR FAR * szTableQualifier,
2935
SWORD cbTableQualifier,
2936
UCHAR FAR * szTableOwner,
2938
UCHAR FAR * szTableName,
2941
CSTR func = "PGAPI_PrimaryKeys";
2942
StatementClass *stmt = (StatementClass *) hstmt;
2944
ConnectionClass *conn;
2949
StatementClass *tbl_stmt;
2950
char tables_query[INFO_INQUIRY_LEN];
2951
char attname[MAX_INFO_STRING];
2953
char pktab[TABLE_NAME_STORAGE_LEN + 1], pkscm[TABLE_NAME_STORAGE_LEN + 1];
2958
SWORD internal_asis_type = SQL_C_CHAR;
2960
mylog("%s: entering...stmt=%u scnm=%x len=%d\n", func, stmt, szTableOwner, cbTableOwner);
2964
SC_log_error(func, "", NULL);
2965
return SQL_INVALID_HANDLE;
2967
stmt->manual_result = TRUE;
2968
stmt->errormsg_created = TRUE;
2970
if (res = QR_Constructor(), !res)
2972
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate memory for PGAPI_PrimaryKeys result.");
2973
SC_log_error(func, "", stmt);
2976
SC_set_Result(stmt, res);
2978
/* the binding structure for a statement is not set up until */
2981
* a statement is actually executed, so we'll have to do this
2985
extend_column_bindings(SC_get_ARD(stmt), result_cols);
2987
/* set the field names */
2988
QR_set_num_fields(res, result_cols);
2989
QR_set_field_info(res, 0, "TABLE_QUALIFIER", PG_TYPE_VARCHAR, MAX_INFO_STRING);
2990
QR_set_field_info(res, 1, "TABLE_OWNER", PG_TYPE_VARCHAR, MAX_INFO_STRING);
2991
QR_set_field_info(res, 2, "TABLE_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
2992
QR_set_field_info(res, 3, "COLUMN_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
2993
QR_set_field_info(res, 4, "KEY_SEQ", PG_TYPE_INT2, 2);
2994
QR_set_field_info(res, 5, "PK_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
2997
result = PGAPI_AllocStmt(stmt->hdbc, &htbl_stmt);
2998
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
3000
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate statement for Primary Key result.");
3001
SC_log_error(func, "", stmt);
3004
tbl_stmt = (StatementClass *) htbl_stmt;
3006
conn = SC_get_conn(stmt);
3007
#ifdef UNICODE_SUPPORT
3009
internal_asis_type = INTERNAL_ASIS_TYPE;
3010
#endif /* UNICODE_SUPPORT */
3012
make_string(szTableName, cbTableName, pktab);
3013
if (pktab[0] == '\0')
3015
SC_set_error(stmt, STMT_INTERNAL_ERROR, "No Table specified to PGAPI_PrimaryKeys.");
3016
SC_log_error(func, "", stmt);
3017
PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
3021
if (conn->schema_support)
3022
schema_strcat(pkscm, "%.*s", szTableOwner, cbTableOwner, szTableName, cbTableName, conn);
3024
result = PGAPI_BindCol(htbl_stmt, 1, internal_asis_type,
3025
attname, MAX_INFO_STRING, &attname_len);
3026
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
3028
SC_error_copy(stmt, tbl_stmt);
3029
SC_log_error(func, "", stmt);
3030
PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
3034
if (PG_VERSION_LE(conn, 6.4))
3039
for (qno = qstart; qno <= qend; qno++)
3046
* Simplified query to remove assumptions about number of
3047
* possible index columns. Courtesy of Tom Lane - thomas
3050
if (conn->schema_support)
3051
sprintf(tables_query, "select ta.attname, ia.attnum"
3052
" from pg_catalog.pg_attribute ta,"
3053
" pg_catalog.pg_attribute ia, pg_catalog.pg_class c,"
3054
" pg_catalog.pg_index i, pg_catalog.pg_namespace n"
3055
" where c.relname = '%s'"
3056
" AND n.nspname = '%s'"
3057
" AND c.oid = i.indrelid"
3058
" AND n.oid = c.relnamespace"
3059
" AND i.indisprimary = 't'"
3060
" AND ia.attrelid = i.indexrelid"
3061
" AND ta.attrelid = i.indrelid"
3062
" AND ta.attnum = i.indkey[ia.attnum-1]"
3063
" AND (NOT ta.attisdropped)"
3064
" AND (NOT ia.attisdropped)"
3065
" order by ia.attnum", pktab, pkscm);
3067
sprintf(tables_query, "select ta.attname, ia.attnum"
3068
" from pg_attribute ta, pg_attribute ia, pg_class c, pg_index i"
3069
" where c.relname = '%s'"
3070
" AND c.oid = i.indrelid"
3071
" AND i.indisprimary = 't'"
3072
" AND ia.attrelid = i.indexrelid"
3073
" AND ta.attrelid = i.indrelid"
3074
" AND ta.attnum = i.indkey[ia.attnum-1]"
3075
" order by ia.attnum", pktab);
3080
* Simplified query to search old fashoned primary key
3082
if (conn->schema_support)
3083
sprintf(tables_query, "select ta.attname, ia.attnum"
3084
" from pg_catalog.pg_attribute ta,"
3085
" pg_catalog.pg_attribute ia, pg_catalog.pg_class c,"
3086
" pg_catalog.pg_index i, pg_catalog.pg_namespace n"
3087
" where c.relname = '%s_pkey'"
3088
" AND n.nspname = '%s'"
3089
" AND c.oid = i.indexrelid"
3090
" AND n.oid = c.relnamespace"
3091
" AND ia.attrelid = i.indexrelid"
3092
" AND ta.attrelid = i.indrelid"
3093
" AND ta.attnum = i.indkey[ia.attnum-1]"
3094
" AND (NOT ta.attisdropped)"
3095
" AND (NOT ia.attisdropped)"
3096
" order by ia.attnum", pktab, pkscm);
3098
sprintf(tables_query, "select ta.attname, ia.attnum"
3099
" from pg_attribute ta, pg_attribute ia, pg_class c, pg_index i"
3100
" where c.relname = '%s_pkey'"
3101
" AND c.oid = i.indexrelid"
3102
" AND ia.attrelid = i.indexrelid"
3103
" AND ta.attrelid = i.indrelid"
3104
" AND ta.attnum = i.indkey[ia.attnum-1]"
3105
" order by ia.attnum", pktab);
3108
mylog("%s: tables_query='%s'\n", func, tables_query);
3110
result = PGAPI_ExecDirect(htbl_stmt, tables_query, strlen(tables_query));
3111
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
3113
SC_full_error_copy(stmt, tbl_stmt);
3114
SC_log_error(func, "", stmt);
3115
PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
3119
result = PGAPI_Fetch(htbl_stmt);
3120
if (result != SQL_NO_DATA_FOUND)
3124
while ((result == SQL_SUCCESS) || (result == SQL_SUCCESS_WITH_INFO))
3126
row = (TupleNode *) malloc(sizeof(TupleNode) + (result_cols - 1) *sizeof(TupleField));
3128
set_tuplefield_null(&row->tuple[0]);
3131
* I have to hide the table owner from Access, otherwise it
3132
* insists on referring to the table as 'owner.table'. (this is
3133
* valid according to the ODBC SQL grammar, but Postgres won't
3136
set_tuplefield_string(&row->tuple[1], GET_SCHEMA_NAME(pkscm));
3137
set_tuplefield_string(&row->tuple[2], pktab);
3138
set_tuplefield_string(&row->tuple[3], attname);
3139
set_tuplefield_int2(&row->tuple[4], (Int2) (++seq));
3140
set_tuplefield_null(&row->tuple[5]);
3142
QR_add_tuple(res, row);
3144
mylog(">> primaryKeys: pktab = '%s', attname = '%s', seq = %d\n", pktab, attname, seq);
3146
result = PGAPI_Fetch(htbl_stmt);
3149
if (result != SQL_NO_DATA_FOUND)
3151
SC_full_error_copy(stmt, htbl_stmt);
3152
SC_log_error(func, "", stmt);
3153
PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
3157
PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
3161
* also, things need to think that this statement is finished so the
3162
* results can be retrieved.
3164
stmt->status = STMT_FINISHED;
3166
/* set up the current tuple pointer for SQLFetch */
3167
stmt->currTuple = -1;
3168
stmt->rowset_start = -1;
3169
stmt->current_col = -1;
3171
mylog("%s: EXIT, stmt=%u\n", func, stmt);
3177
* Multibyte support stuff for SQLForeignKeys().
3178
* There may be much more effective way in the
3179
* future version. The way is very forcible currently.
3182
isMultibyte(const unsigned char *str)
3193
getClientTableName(ConnectionClass *conn, const char *serverSchemaName, char *serverTableName, BOOL *nameAlloced)
3197
*ret = serverTableName;
3198
BOOL continueExec = TRUE,
3202
*nameAlloced = FALSE;
3203
if (!conn->client_encoding || !isMultibyte(serverTableName))
3205
if (!conn->server_encoding)
3207
if (res = CC_send_query(conn, "select getdatabaseencoding()", NULL, CLEAR_RESULT_ON_ABORT), res)
3209
if (QR_get_num_tuples(res) > 0)
3210
conn->server_encoding = strdup(QR_get_value_backend_row(res, 0, 0));
3214
if (!conn->server_encoding)
3216
sprintf(query, "SET CLIENT_ENCODING TO '%s'", conn->server_encoding);
3217
bError = (CC_send_query(conn, query, NULL, CLEAR_RESULT_ON_ABORT) == NULL);
3218
if (!bError && continueExec)
3220
if (conn->schema_support)
3221
sprintf(query, "select OID from pg_catalog.pg_class,"
3222
" pg_catalog.pg_namespace"
3223
" where relname = '%s' and pg_namespace.oid = relnamespace and"
3224
" pg_namespace.nspname = '%s'", serverTableName, serverSchemaName);
3226
sprintf(query, "select OID from pg_class where relname = '%s'", serverTableName);
3227
if (res = CC_send_query(conn, query, NULL, CLEAR_RESULT_ON_ABORT), res)
3229
if (QR_get_num_tuples(res) > 0)
3230
strcpy(saveoid, QR_get_value_backend_row(res, 0, 0));
3232
continueExec = FALSE;
3238
continueExec = (continueExec && !bError);
3239
if (bError && CC_is_in_trans(conn))
3244
/* restore the client encoding */
3245
sprintf(query, "SET CLIENT_ENCODING TO '%s'", conn->client_encoding);
3246
bError = (CC_send_query(conn, query, NULL, CLEAR_RESULT_ON_ABORT) == NULL);
3247
if (bError || !continueExec)
3249
sprintf(query, "select relname from pg_class where OID = %s", saveoid);
3250
if (res = CC_send_query(conn, query, NULL, CLEAR_RESULT_ON_ABORT), res)
3252
if (QR_get_num_tuples(res) > 0)
3254
ret = strdup(QR_get_value_backend_row(res, 0, 0));
3255
*nameAlloced = TRUE;
3262
getClientColumnName(ConnectionClass *conn, const char * serverSchemaName, const char *serverTableName, char *serverColumnName, BOOL *nameAlloced)
3267
*ret = serverColumnName;
3268
BOOL continueExec = TRUE,
3272
*nameAlloced = FALSE;
3273
if (!conn->client_encoding || !isMultibyte(serverColumnName))
3275
if (!conn->server_encoding)
3277
if (res = CC_send_query(conn, "select getdatabaseencoding()", NULL, CLEAR_RESULT_ON_ABORT), res)
3279
if (QR_get_num_tuples(res) > 0)
3280
conn->server_encoding = strdup(QR_get_value_backend_row(res, 0, 0));
3284
if (!conn->server_encoding)
3286
sprintf(query, "SET CLIENT_ENCODING TO '%s'", conn->server_encoding);
3287
bError = (CC_send_query(conn, query, NULL, CLEAR_RESULT_ON_ABORT) == NULL);
3288
if (!bError && continueExec)
3290
if (conn->schema_support)
3291
sprintf(query, "select attrelid, attnum from pg_catalog.pg_class,"
3292
" pg_catalog.pg_attribute, pg_catalog.pg_namespace "
3293
"where relname = '%s' and attrelid = pg_class.oid "
3294
"and (not attisdropped) "
3295
"and attname = '%s' and pg_namespace.oid = relnamespace and"
3296
" pg_namespace.nspname = '%s'", serverTableName, serverColumnName, serverSchemaName);
3298
sprintf(query, "select attrelid, attnum from pg_class, pg_attribute "
3299
"where relname = '%s' and attrelid = pg_class.oid "
3300
"and attname = '%s'", serverTableName, serverColumnName);
3301
if (res = CC_send_query(conn, query, NULL, CLEAR_RESULT_ON_ABORT), res)
3303
if (QR_get_num_tuples(res) > 0)
3305
strcpy(saveattrelid, QR_get_value_backend_row(res, 0, 0));
3306
strcpy(saveattnum, QR_get_value_backend_row(res, 0, 1));
3309
continueExec = FALSE;
3315
continueExec = (continueExec && !bError);
3316
if (bError && CC_is_in_trans(conn))
3321
/* restore the cleint encoding */
3322
sprintf(query, "SET CLIENT_ENCODING TO '%s'", conn->client_encoding);
3323
bError = (CC_send_query(conn, query, NULL, CLEAR_RESULT_ON_ABORT) == NULL);
3324
if (bError || !continueExec)
3326
sprintf(query, "select attname from pg_attribute where attrelid = %s and attnum = %s", saveattrelid, saveattnum);
3327
if (res = CC_send_query(conn, query, NULL, CLEAR_RESULT_ON_ABORT), res)
3329
if (QR_get_num_tuples(res) > 0)
3331
ret = strdup(QR_get_value_backend_row(res, 0, 0));
3332
*nameAlloced = TRUE;
3338
#endif /* NOT_USED */
3340
getClientColumnName(ConnectionClass *conn, UInt4 relid, char *serverColumnName, BOOL *nameAlloced)
3342
char query[1024], saveattnum[16],
3343
*ret = serverColumnName;
3344
BOOL continueExec = TRUE,
3348
*nameAlloced = FALSE;
3349
if (!conn->client_encoding || !isMultibyte(serverColumnName))
3351
if (!conn->server_encoding)
3353
if (res = CC_send_query(conn, "select getdatabaseencoding()", NULL, CLEAR_RESULT_ON_ABORT), res)
3355
if (QR_get_num_backend_tuples(res) > 0)
3356
conn->server_encoding = strdup(QR_get_value_backend_row(res, 0, 0));
3360
if (!conn->server_encoding)
3362
sprintf(query, "SET CLIENT_ENCODING TO '%s'", conn->server_encoding);
3363
bError = (CC_send_query(conn, query, NULL, CLEAR_RESULT_ON_ABORT) == NULL);
3364
if (!bError && continueExec)
3366
sprintf(query, "select attnum from pg_attribute "
3367
"where attrelid = %u and attname = '%s'",
3368
relid, serverColumnName);
3369
if (res = CC_send_query(conn, query, NULL, CLEAR_RESULT_ON_ABORT), res)
3371
if (QR_get_num_backend_tuples(res) > 0)
3373
strcpy(saveattnum, QR_get_value_backend_row(res, 0, 0));
3376
continueExec = FALSE;
3382
continueExec = (continueExec && !bError);
3383
if (bError && CC_is_in_trans(conn))
3388
/* restore the cleint encoding */
3389
sprintf(query, "SET CLIENT_ENCODING TO '%s'", conn->client_encoding);
3390
bError = (CC_send_query(conn, query, NULL, CLEAR_RESULT_ON_ABORT) == NULL);
3391
if (bError || !continueExec)
3393
sprintf(query, "select attname from pg_attribute where attrelid = %u and attnum = %s", relid, saveattnum);
3394
if (res = CC_send_query(conn, query, NULL, CLEAR_RESULT_ON_ABORT), res)
3396
if (QR_get_num_backend_tuples(res) > 0)
3398
ret = strdup(QR_get_value_backend_row(res, 0, 0));
3399
*nameAlloced = TRUE;
3409
UCHAR FAR * szPkTableQualifier,
3410
SWORD cbPkTableQualifier,
3411
UCHAR FAR * szPkTableOwner,
3412
SWORD cbPkTableOwner,
3413
UCHAR FAR * szPkTableName,
3414
SWORD cbPkTableName,
3415
UCHAR FAR * szFkTableQualifier,
3416
SWORD cbFkTableQualifier,
3417
UCHAR FAR * szFkTableOwner,
3418
SWORD cbFkTableOwner,
3419
UCHAR FAR * szFkTableName,
3420
SWORD cbFkTableName)
3422
CSTR func = "PGAPI_ForeignKeys";
3423
StatementClass *stmt = (StatementClass *) hstmt;
3428
StatementClass *tbl_stmt;
3431
char tables_query[INFO_INQUIRY_LEN];
3432
char trig_deferrable[2];
3433
char trig_initdeferred[2];
3434
char trig_args[1024];
3435
char upd_rule[TABLE_NAME_STORAGE_LEN],
3436
del_rule[TABLE_NAME_STORAGE_LEN];
3437
char pk_table_needed[TABLE_NAME_STORAGE_LEN + 1];
3438
char fk_table_fetched[TABLE_NAME_STORAGE_LEN + 1];
3439
char fk_table_needed[TABLE_NAME_STORAGE_LEN + 1];
3440
char pk_table_fetched[TABLE_NAME_STORAGE_LEN + 1];
3441
char schema_needed[SCHEMA_NAME_STORAGE_LEN + 1];
3442
char schema_fetched[SCHEMA_NAME_STORAGE_LEN + 1];
3448
ConnectionClass *conn;
3458
SWORD internal_asis_type = SQL_C_CHAR;
3460
#if (ODBCVER >= 0x0300)
3463
char pkey[MAX_INFO_STRING];
3465
UInt4 relid1, relid2;
3467
mylog("%s: entering...stmt=%u\n", func, stmt);
3471
SC_log_error(func, "", NULL);
3472
return SQL_INVALID_HANDLE;
3475
stmt->manual_result = TRUE;
3476
stmt->errormsg_created = TRUE;
3478
if (res = QR_Constructor(), !res)
3480
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate memory for PGAPI_ForeignKeys result.");
3481
SC_log_error(func, "", stmt);
3484
SC_set_Result(stmt, res);
3486
/* the binding structure for a statement is not set up until */
3489
* a statement is actually executed, so we'll have to do this
3492
#if (ODBCVER >= 0x0300)
3496
#endif /* ODBCVER */
3497
extend_column_bindings(SC_get_ARD(stmt), result_cols);
3499
/* set the field names */
3500
QR_set_num_fields(res, result_cols);
3501
QR_set_field_info(res, 0, "PKTABLE_QUALIFIER", PG_TYPE_VARCHAR, MAX_INFO_STRING);
3502
QR_set_field_info(res, 1, "PKTABLE_OWNER", PG_TYPE_VARCHAR, MAX_INFO_STRING);
3503
QR_set_field_info(res, 2, "PKTABLE_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
3504
QR_set_field_info(res, 3, "PKCOLUMN_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
3505
QR_set_field_info(res, 4, "FKTABLE_QUALIFIER", PG_TYPE_VARCHAR, MAX_INFO_STRING);
3506
QR_set_field_info(res, 5, "FKTABLE_OWNER", PG_TYPE_VARCHAR, MAX_INFO_STRING);
3507
QR_set_field_info(res, 6, "FKTABLE_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
3508
QR_set_field_info(res, 7, "FKCOLUMN_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
3509
QR_set_field_info(res, 8, "KEY_SEQ", PG_TYPE_INT2, 2);
3510
QR_set_field_info(res, 9, "UPDATE_RULE", PG_TYPE_INT2, 2);
3511
QR_set_field_info(res, 10, "DELETE_RULE", PG_TYPE_INT2, 2);
3512
QR_set_field_info(res, 11, "FK_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
3513
QR_set_field_info(res, 12, "PK_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
3514
QR_set_field_info(res, 13, "TRIGGER_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
3515
#if (ODBCVER >= 0x0300)
3516
QR_set_field_info(res, 14, "DEFERRABILITY", PG_TYPE_INT2, 2);
3517
#endif /* ODBCVER >= 0x0300 */
3520
* also, things need to think that this statement is finished so the
3521
* results can be retrieved.
3523
stmt->status = STMT_FINISHED;
3525
/* set up the current tuple pointer for SQLFetch */
3526
stmt->currTuple = -1;
3527
stmt->rowset_start = -1;
3528
stmt->current_col = -1;
3531
result = PGAPI_AllocStmt(stmt->hdbc, &htbl_stmt);
3532
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
3534
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate statement for PGAPI_ForeignKeys result.");
3535
SC_log_error(func, "", stmt);
3539
tbl_stmt = (StatementClass *) htbl_stmt;
3541
pk_table_needed[0] = '\0';
3542
fk_table_needed[0] = '\0';
3543
schema_needed[0] = '\0';
3544
schema_fetched[0] = '\0';
3546
make_string(szPkTableName, cbPkTableName, pk_table_needed);
3547
make_string(szFkTableName, cbFkTableName, fk_table_needed);
3549
conn = SC_get_conn(stmt);
3550
#ifdef UNICODE_SUPPORT
3552
internal_asis_type = INTERNAL_ASIS_TYPE;
3553
#endif /* UNICODE_SUPPORT */
3554
pkey_text = fkey_text = NULL;
3555
pkey_alloced = fkey_alloced = FALSE;
3558
* Case #2 -- Get the foreign keys in the specified table (fktab) that
3559
* refer to the primary keys of other table(s).
3561
if (fk_table_needed[0] != '\0')
3563
mylog("%s: entering Foreign Key Case #2", func);
3564
if (conn->schema_support)
3566
schema_strcat(schema_needed, "%.*s", szFkTableOwner, cbFkTableOwner, szFkTableName, cbFkTableName, conn);
3567
sprintf(tables_query, "SELECT pt.tgargs, "
3569
" pt.tgdeferrable, "
3570
" pt.tginitdeferred, "
3577
"FROM pg_catalog.pg_class pc, "
3578
" pg_catalog.pg_proc pp1, "
3579
" pg_catalog.pg_proc pp2, "
3580
" pg_catalog.pg_trigger pt1, "
3581
" pg_catalog.pg_trigger pt2, "
3582
" pg_catalog.pg_proc pp, "
3583
" pg_catalog.pg_trigger pt, "
3584
" pg_catalog.pg_class pc1, "
3585
" pg_catalog.pg_namespace pn, "
3586
" pg_catalog.pg_namespace pn1 "
3587
"WHERE pt.tgrelid = pc.oid "
3588
"AND pp.oid = pt.tgfoid "
3589
"AND pt1.tgconstrrelid = pc.oid "
3590
"AND pp1.oid = pt1.tgfoid "
3591
"AND pt2.tgfoid = pp2.oid "
3592
"AND pt2.tgconstrrelid = pc.oid "
3593
"AND ((pc.relname='%s') "
3594
"AND (pn1.oid = pc.relnamespace) "
3595
"AND (pn1.nspname = '%s') "
3596
"AND (pp.proname LIKE '%%ins') "
3597
"AND (pp1.proname LIKE '%%upd') "
3598
"AND (pp2.proname LIKE '%%del') "
3599
"AND (pt1.tgrelid=pt.tgconstrrelid) "
3600
"AND (pt1.tgconstrname=pt.tgconstrname) "
3601
"AND (pt2.tgrelid=pt.tgconstrrelid) "
3602
"AND (pt2.tgconstrname=pt.tgconstrname) "
3603
"AND (pt.tgconstrrelid=pc1.oid) "
3604
"AND (pc1.relnamespace=pn.oid))",
3605
fk_table_needed, schema_needed);
3608
sprintf(tables_query, "SELECT pt.tgargs, "
3610
" pt.tgdeferrable, "
3611
" pt.tginitdeferred, "
3617
"FROM pg_class pc, "
3625
"WHERE pt.tgrelid = pc.oid "
3626
"AND pp.oid = pt.tgfoid "
3627
"AND pt1.tgconstrrelid = pc.oid "
3628
"AND pp1.oid = pt1.tgfoid "
3629
"AND pt2.tgfoid = pp2.oid "
3630
"AND pt2.tgconstrrelid = pc.oid "
3631
"AND ((pc.relname='%s') "
3632
"AND (pp.proname LIKE '%%ins') "
3633
"AND (pp1.proname LIKE '%%upd') "
3634
"AND (pp2.proname LIKE '%%del') "
3635
"AND (pt1.tgrelid=pt.tgconstrrelid) "
3636
"AND (pt1.tgconstrname=pt.tgconstrname) "
3637
"AND (pt2.tgrelid=pt.tgconstrrelid) "
3638
"AND (pt2.tgconstrname=pt.tgconstrname) "
3639
"AND (pt.tgconstrrelid=pc1.oid)) ",
3642
result = PGAPI_ExecDirect(htbl_stmt, tables_query, strlen(tables_query));
3644
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
3646
SC_full_error_copy(stmt, tbl_stmt);
3647
SC_log_error(func, "", stmt);
3648
PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
3652
result = PGAPI_BindCol(htbl_stmt, 1, SQL_C_BINARY,
3653
trig_args, sizeof(trig_args), NULL);
3654
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
3656
SC_error_copy(stmt, tbl_stmt);
3657
SC_log_error(func, "", stmt);
3658
PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
3662
result = PGAPI_BindCol(htbl_stmt, 2, SQL_C_SHORT,
3663
&trig_nargs, 0, NULL);
3664
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
3666
SC_error_copy(stmt, tbl_stmt);
3667
SC_log_error(func, "", stmt);
3668
PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
3672
result = PGAPI_BindCol(htbl_stmt, 3, internal_asis_type,
3673
trig_deferrable, sizeof(trig_deferrable), NULL);
3674
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
3676
SC_error_copy(stmt, tbl_stmt);
3677
SC_log_error(func, "", stmt);
3678
PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
3682
result = PGAPI_BindCol(htbl_stmt, 4, internal_asis_type,
3683
trig_initdeferred, sizeof(trig_initdeferred), NULL);
3684
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
3686
SC_error_copy(stmt, tbl_stmt);
3687
SC_log_error(func, "", stmt);
3688
PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
3692
result = PGAPI_BindCol(htbl_stmt, 5, internal_asis_type,
3693
upd_rule, sizeof(upd_rule), NULL);
3694
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
3696
SC_error_copy(stmt, tbl_stmt);
3697
SC_log_error(func, "", stmt);
3698
PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
3702
result = PGAPI_BindCol(htbl_stmt, 6, internal_asis_type,
3703
del_rule, sizeof(del_rule), NULL);
3704
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
3706
SC_error_copy(stmt, tbl_stmt);
3707
SC_log_error(func, "", stmt);
3708
PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
3712
result = PGAPI_BindCol(htbl_stmt, 7, SQL_C_ULONG,
3713
&relid1, sizeof(relid1), NULL);
3714
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
3716
SC_error_copy(stmt, tbl_stmt);
3717
SC_log_error(func, "", stmt);
3718
PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
3721
result = PGAPI_BindCol(htbl_stmt, 8, SQL_C_ULONG,
3722
&relid2, sizeof(relid2), NULL);
3723
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
3725
SC_error_copy(stmt, tbl_stmt);
3726
SC_log_error(func, "", stmt);
3727
PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
3730
result = PGAPI_BindCol(htbl_stmt, 9, internal_asis_type,
3731
pk_table_fetched, TABLE_NAME_STORAGE_LEN, NULL);
3732
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
3734
SC_error_copy(stmt, tbl_stmt);
3735
SC_log_error(func, "", stmt);
3736
PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
3740
if (conn->schema_support)
3742
result = PGAPI_BindCol(htbl_stmt, 10, internal_asis_type,
3743
schema_fetched, SCHEMA_NAME_STORAGE_LEN, NULL);
3744
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
3746
SC_error_copy(stmt, tbl_stmt);
3747
SC_log_error(func, "", stmt);
3748
PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
3753
result = PGAPI_Fetch(htbl_stmt);
3754
if (result == SQL_NO_DATA_FOUND)
3757
if (result != SQL_SUCCESS)
3759
SC_full_error_copy(stmt, tbl_stmt);
3760
SC_log_error(func, "", stmt);
3761
PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
3765
keyresult = PGAPI_AllocStmt(stmt->hdbc, &hpkey_stmt);
3766
if ((keyresult != SQL_SUCCESS) && (keyresult != SQL_SUCCESS_WITH_INFO))
3768
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate statement for PGAPI_ForeignKeys (pkeys) result.");
3769
SC_log_error(func, "", stmt);
3773
keyresult = PGAPI_BindCol(hpkey_stmt, 4, internal_asis_type,
3774
pkey, sizeof(pkey), NULL);
3775
if (keyresult != SQL_SUCCESS)
3777
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't bindcol for primary keys for PGAPI_ForeignKeys result.");
3778
SC_log_error(func, "", stmt);
3779
PGAPI_FreeStmt(hpkey_stmt, SQL_DROP);
3783
while (result == SQL_SUCCESS)
3785
/* Compute the number of keyparts. */
3786
num_keys = (trig_nargs - 4) / 2;
3788
mylog("Foreign Key Case#2: trig_nargs = %d, num_keys = %d\n", trig_nargs, num_keys);
3790
/* If there is a pk table specified, then check it. */
3791
if (pk_table_needed[0] != '\0')
3793
/* If it doesn't match, then continue */
3794
if (strcmp(pk_table_fetched, pk_table_needed))
3796
result = PGAPI_Fetch(htbl_stmt);
3801
keyresult = PGAPI_PrimaryKeys(hpkey_stmt, NULL, 0, schema_fetched, SQL_NTS, pk_table_fetched, SQL_NTS);
3802
if (keyresult != SQL_SUCCESS)
3804
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't get primary keys for PGAPI_ForeignKeys result.");
3805
SC_log_error(func, "", stmt);
3806
PGAPI_FreeStmt(hpkey_stmt, SQL_DROP);
3811
/* Get to first primary key */
3812
pkey_ptr = trig_args;
3813
for (i = 0; i < 5; i++)
3814
pkey_ptr += strlen(pkey_ptr) + 1;
3816
for (k = 0; k < num_keys; k++)
3818
/* Check that the key listed is the primary key */
3819
keyresult = PGAPI_Fetch(hpkey_stmt);
3820
if (keyresult != SQL_SUCCESS)
3825
pkey_text = getClientColumnName(conn, relid2, pkey_ptr, &pkey_alloced);
3826
mylog("%s: pkey_ptr='%s', pkey='%s'\n", func, pkey_text, pkey);
3827
if (strcmp(pkey_text, pkey))
3834
/* Get to next primary key */
3835
for (k = 0; k < 2; k++)
3836
pkey_ptr += strlen(pkey_ptr) + 1;
3840
/* Set to first fk column */
3841
fkey_ptr = trig_args;
3842
for (k = 0; k < 4; k++)
3843
fkey_ptr += strlen(fkey_ptr) + 1;
3845
/* Set update and delete actions for foreign keys */
3846
if (!strcmp(upd_rule, "RI_FKey_cascade_upd"))
3847
upd_rule_type = SQL_CASCADE;
3848
else if (!strcmp(upd_rule, "RI_FKey_noaction_upd"))
3849
upd_rule_type = SQL_NO_ACTION;
3850
else if (!strcmp(upd_rule, "RI_FKey_restrict_upd"))
3851
upd_rule_type = SQL_NO_ACTION;
3852
else if (!strcmp(upd_rule, "RI_FKey_setdefault_upd"))
3853
upd_rule_type = SQL_SET_DEFAULT;
3854
else if (!strcmp(upd_rule, "RI_FKey_setnull_upd"))
3855
upd_rule_type = SQL_SET_NULL;
3857
if (!strcmp(upd_rule, "RI_FKey_cascade_del"))
3858
del_rule_type = SQL_CASCADE;
3859
else if (!strcmp(upd_rule, "RI_FKey_noaction_del"))
3860
del_rule_type = SQL_NO_ACTION;
3861
else if (!strcmp(upd_rule, "RI_FKey_restrict_del"))
3862
del_rule_type = SQL_NO_ACTION;
3863
else if (!strcmp(upd_rule, "RI_FKey_setdefault_del"))
3864
del_rule_type = SQL_SET_DEFAULT;
3865
else if (!strcmp(upd_rule, "RI_FKey_setnull_del"))
3866
del_rule_type = SQL_SET_NULL;
3868
#if (ODBCVER >= 0x0300)
3869
/* Set deferrability type */
3870
if (!strcmp(trig_initdeferred, "y"))
3871
defer_type = SQL_INITIALLY_DEFERRED;
3872
else if (!strcmp(trig_deferrable, "y"))
3873
defer_type = SQL_INITIALLY_IMMEDIATE;
3875
defer_type = SQL_NOT_DEFERRABLE;
3876
#endif /* ODBCVER >= 0x0300 */
3878
/* Get to first primary key */
3879
pkey_ptr = trig_args;
3880
for (i = 0; i < 5; i++)
3881
pkey_ptr += strlen(pkey_ptr) + 1;
3883
for (k = 0; k < num_keys; k++)
3885
row = (TupleNode *) malloc(sizeof(TupleNode) + (result_cols - 1) *sizeof(TupleField));
3887
pkey_text = getClientColumnName(conn, relid2, pkey_ptr, &pkey_alloced);
3888
fkey_text = getClientColumnName(conn, relid1, fkey_ptr, &fkey_alloced);
3890
mylog("%s: pk_table = '%s', pkey_ptr = '%s'\n", func, pk_table_fetched, pkey_text);
3891
set_tuplefield_null(&row->tuple[0]);
3892
set_tuplefield_string(&row->tuple[1], GET_SCHEMA_NAME(schema_fetched));
3893
set_tuplefield_string(&row->tuple[2], pk_table_fetched);
3894
set_tuplefield_string(&row->tuple[3], pkey_text);
3896
mylog("%s: fk_table_needed = '%s', fkey_ptr = '%s'\n", func, fk_table_needed, fkey_text);
3897
set_tuplefield_null(&row->tuple[4]);
3898
set_tuplefield_string(&row->tuple[5], GET_SCHEMA_NAME(schema_needed));
3899
set_tuplefield_string(&row->tuple[6], fk_table_needed);
3900
set_tuplefield_string(&row->tuple[7], fkey_text);
3902
mylog("%s: upd_rule_type = '%i', del_rule_type = '%i'\n, trig_name = '%s'", func, upd_rule_type, del_rule_type, trig_args);
3903
set_tuplefield_int2(&row->tuple[8], (Int2) (k + 1));
3904
set_tuplefield_int2(&row->tuple[9], (Int2) upd_rule_type);
3905
set_tuplefield_int2(&row->tuple[10], (Int2) del_rule_type);
3906
set_tuplefield_null(&row->tuple[11]);
3907
set_tuplefield_null(&row->tuple[12]);
3908
set_tuplefield_string(&row->tuple[13], trig_args);
3909
#if (ODBCVER >= 0x0300)
3910
set_tuplefield_int2(&row->tuple[14], defer_type);
3911
#endif /* ODBCVER >= 0x0300 */
3913
QR_add_tuple(res, row);
3916
fkey_alloced = FALSE;
3919
pkey_alloced = FALSE;
3920
/* next primary/foreign key */
3921
for (i = 0; i < 2; i++)
3923
fkey_ptr += strlen(fkey_ptr) + 1;
3924
pkey_ptr += strlen(pkey_ptr) + 1;
3928
result = PGAPI_Fetch(htbl_stmt);
3930
PGAPI_FreeStmt(hpkey_stmt, SQL_DROP);
3934
* Case #1 -- Get the foreign keys in other tables that refer to the
3935
* primary key in the specified table (pktab). i.e., Who points to
3938
else if (pk_table_needed[0] != '\0')
3940
if (conn->schema_support)
3942
schema_strcat(schema_needed, "%.*s", szPkTableOwner, cbPkTableOwner, szPkTableName, cbPkTableName, conn);
3943
sprintf(tables_query, "SELECT pt.tgargs, "
3945
" pt.tgdeferrable, "
3946
" pt.tginitdeferred, "
3953
"FROM pg_catalog.pg_class pc, "
3954
" pg_catalog.pg_class pc1, "
3955
" pg_catalog.pg_class pc2, "
3956
" pg_catalog.pg_proc pp, "
3957
" pg_catalog.pg_proc pp1, "
3958
" pg_catalog.pg_trigger pt, "
3959
" pg_catalog.pg_trigger pt1, "
3960
" pg_catalog.pg_trigger pt2, "
3961
" pg_catalog.pg_namespace pn, "
3962
" pg_catalog.pg_namespace pn1 "
3963
"WHERE pt.tgconstrrelid = pc.oid "
3964
" AND pt.tgrelid = pc1.oid "
3965
" AND pt1.tgfoid = pp1.oid "
3966
" AND pt1.tgconstrrelid = pc1.oid "
3967
" AND pt2.tgconstrrelid = pc2.oid "
3968
" AND pt2.tgfoid = pp.oid "
3969
" AND pc2.oid = pt.tgrelid "
3971
" (pc.relname='%s') "
3972
" AND (pn1.oid = pc.relnamespace) "
3973
" AND (pn1.nspname = '%s') "
3974
" AND (pp.proname Like '%%upd') "
3975
" AND (pp1.proname Like '%%del')"
3976
" AND (pt1.tgrelid = pt.tgconstrrelid) "
3977
" AND (pt2.tgrelid = pt.tgconstrrelid) "
3978
" AND (pn.oid = pc1.relnamespace) "
3980
pk_table_needed, schema_needed);
3983
sprintf(tables_query, "SELECT pt.tgargs, "
3985
" pt.tgdeferrable, "
3986
" pt.tginitdeferred, "
3992
"FROM pg_class pc, "
4000
"WHERE pt.tgconstrrelid = pc.oid "
4001
" AND pt.tgrelid = pc1.oid "
4002
" AND pt1.tgfoid = pp1.oid "
4003
" AND pt1.tgconstrrelid = pc1.oid "
4004
" AND pt2.tgconstrrelid = pc2.oid "
4005
" AND pt2.tgfoid = pp.oid "
4006
" AND pc2.oid = pt.tgrelid "
4008
" (pc.relname='%s') "
4009
" AND (pp.proname Like '%%upd') "
4010
" AND (pp1.proname Like '%%del')"
4011
" AND (pt1.tgrelid = pt.tgconstrrelid) "
4012
" AND (pt2.tgrelid = pt.tgconstrrelid) "
4016
result = PGAPI_ExecDirect(htbl_stmt, tables_query, strlen(tables_query));
4017
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
4019
SC_error_copy(stmt, tbl_stmt);
4020
SC_log_error(func, "", stmt);
4021
PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
4025
result = PGAPI_BindCol(htbl_stmt, 1, SQL_C_BINARY,
4026
trig_args, sizeof(trig_args), NULL);
4027
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
4029
SC_error_copy(stmt, tbl_stmt);
4030
SC_log_error(func, "", stmt);
4031
PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
4035
result = PGAPI_BindCol(htbl_stmt, 2, SQL_C_SHORT,
4036
&trig_nargs, 0, NULL);
4037
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
4039
SC_error_copy(stmt, tbl_stmt);
4040
SC_log_error(func, "", stmt);
4041
PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
4045
result = PGAPI_BindCol(htbl_stmt, 3, internal_asis_type,
4046
trig_deferrable, sizeof(trig_deferrable), NULL);
4047
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
4049
SC_error_copy(stmt, tbl_stmt);
4050
SC_log_error(func, "", stmt);
4051
PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
4055
result = PGAPI_BindCol(htbl_stmt, 4, internal_asis_type,
4056
trig_initdeferred, sizeof(trig_initdeferred), NULL);
4057
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
4059
SC_error_copy(stmt, tbl_stmt);
4060
SC_log_error(func, "", stmt);
4061
PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
4065
result = PGAPI_BindCol(htbl_stmt, 5, internal_asis_type,
4066
upd_rule, sizeof(upd_rule), NULL);
4067
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
4069
SC_error_copy(stmt, tbl_stmt);
4070
SC_log_error(func, "", stmt);
4071
PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
4075
result = PGAPI_BindCol(htbl_stmt, 6, internal_asis_type,
4076
del_rule, sizeof(del_rule), NULL);
4077
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
4079
SC_error_copy(stmt, tbl_stmt);
4080
SC_log_error(func, "", stmt);
4081
PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
4085
result = PGAPI_BindCol(htbl_stmt, 7, SQL_C_ULONG,
4086
&relid1, sizeof(relid1), NULL);
4087
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
4089
SC_error_copy(stmt, tbl_stmt);
4090
SC_log_error(func, "", stmt);
4091
PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
4094
result = PGAPI_BindCol(htbl_stmt, 8, SQL_C_ULONG,
4095
&relid2, sizeof(relid2), NULL);
4096
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
4098
SC_error_copy(stmt, tbl_stmt);
4099
SC_log_error(func, "", stmt);
4100
PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
4103
result = PGAPI_BindCol(htbl_stmt, 9, internal_asis_type,
4104
fk_table_fetched, TABLE_NAME_STORAGE_LEN, NULL);
4105
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
4107
SC_error_copy(stmt, tbl_stmt);
4108
SC_log_error(func, "", stmt);
4109
PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
4113
if (conn->schema_support)
4115
result = PGAPI_BindCol(htbl_stmt, 10, internal_asis_type,
4116
schema_fetched, SCHEMA_NAME_STORAGE_LEN, NULL);
4117
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
4119
SC_error_copy(stmt, tbl_stmt);
4120
SC_log_error(func, "", stmt);
4121
PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
4126
result = PGAPI_Fetch(htbl_stmt);
4127
if (result == SQL_NO_DATA_FOUND)
4130
if (result != SQL_SUCCESS)
4132
SC_full_error_copy(stmt, tbl_stmt);
4133
SC_log_error(func, "", stmt);
4134
PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
4138
while (result == SQL_SUCCESS)
4140
/* Calculate the number of key parts */
4141
num_keys = (trig_nargs - 4) / 2;;
4143
/* Handle action (i.e., 'cascade', 'restrict', 'setnull') */
4144
if (!strcmp(upd_rule, "RI_FKey_cascade_upd"))
4145
upd_rule_type = SQL_CASCADE;
4146
else if (!strcmp(upd_rule, "RI_FKey_noaction_upd"))
4147
upd_rule_type = SQL_NO_ACTION;
4148
else if (!strcmp(upd_rule, "RI_FKey_restrict_upd"))
4149
upd_rule_type = SQL_NO_ACTION;
4150
else if (!strcmp(upd_rule, "RI_FKey_setdefault_upd"))
4151
upd_rule_type = SQL_SET_DEFAULT;
4152
else if (!strcmp(upd_rule, "RI_FKey_setnull_upd"))
4153
upd_rule_type = SQL_SET_NULL;
4155
if (!strcmp(upd_rule, "RI_FKey_cascade_del"))
4156
del_rule_type = SQL_CASCADE;
4157
else if (!strcmp(upd_rule, "RI_FKey_noaction_del"))
4158
del_rule_type = SQL_NO_ACTION;
4159
else if (!strcmp(upd_rule, "RI_FKey_restrict_del"))
4160
del_rule_type = SQL_NO_ACTION;
4161
else if (!strcmp(upd_rule, "RI_FKey_setdefault_del"))
4162
del_rule_type = SQL_SET_DEFAULT;
4163
else if (!strcmp(upd_rule, "RI_FKey_setnull_del"))
4164
del_rule_type = SQL_SET_NULL;
4166
#if (ODBCVER >= 0x0300)
4167
/* Set deferrability type */
4168
if (!strcmp(trig_initdeferred, "y"))
4169
defer_type = SQL_INITIALLY_DEFERRED;
4170
else if (!strcmp(trig_deferrable, "y"))
4171
defer_type = SQL_INITIALLY_IMMEDIATE;
4173
defer_type = SQL_NOT_DEFERRABLE;
4174
#endif /* ODBCVER >= 0x0300 */
4176
mylog("Foreign Key Case#1: trig_nargs = %d, num_keys = %d\n", trig_nargs, num_keys);
4178
/* Get to first primary key */
4179
pkey_ptr = trig_args;
4180
for (i = 0; i < 5; i++)
4181
pkey_ptr += strlen(pkey_ptr) + 1;
4183
/* Get to first foreign key */
4184
fkey_ptr = trig_args;
4185
for (k = 0; k < 4; k++)
4186
fkey_ptr += strlen(fkey_ptr) + 1;
4188
for (k = 0; k < num_keys; k++)
4190
pkey_text = getClientColumnName(conn, relid1, pkey_ptr, &pkey_alloced);
4191
fkey_text = getClientColumnName(conn, relid2, fkey_ptr, &fkey_alloced);
4193
mylog("pkey_ptr = '%s', fk_table = '%s', fkey_ptr = '%s'\n", pkey_text, fk_table_fetched, fkey_text);
4195
row = (TupleNode *) malloc(sizeof(TupleNode) + (result_cols - 1) *sizeof(TupleField));
4197
mylog("pk_table_needed = '%s', pkey_ptr = '%s'\n", pk_table_needed, pkey_text);
4198
set_tuplefield_null(&row->tuple[0]);
4199
set_tuplefield_string(&row->tuple[1], GET_SCHEMA_NAME(schema_needed));
4200
set_tuplefield_string(&row->tuple[2], pk_table_needed);
4201
set_tuplefield_string(&row->tuple[3], pkey_text);
4203
mylog("fk_table = '%s', fkey_ptr = '%s'\n", fk_table_fetched, fkey_text);
4204
set_tuplefield_null(&row->tuple[4]);
4205
set_tuplefield_string(&row->tuple[5], GET_SCHEMA_NAME(schema_fetched));
4206
set_tuplefield_string(&row->tuple[6], fk_table_fetched);
4207
set_tuplefield_string(&row->tuple[7], fkey_text);
4209
set_tuplefield_int2(&row->tuple[8], (Int2) (k + 1));
4211
mylog("upd_rule = %d, del_rule= %d", upd_rule_type, del_rule_type);
4212
set_nullfield_int2(&row->tuple[9], (Int2) upd_rule_type);
4213
set_nullfield_int2(&row->tuple[10], (Int2) del_rule_type);
4215
set_tuplefield_null(&row->tuple[11]);
4216
set_tuplefield_null(&row->tuple[12]);
4218
set_tuplefield_string(&row->tuple[13], trig_args);
4220
#if (ODBCVER >= 0x0300)
4221
mylog(" defer_type = %d\n", defer_type);
4222
set_tuplefield_int2(&row->tuple[14], defer_type);
4223
#endif /* ODBCVER >= 0x0300 */
4225
QR_add_tuple(res, row);
4228
pkey_alloced = FALSE;
4231
fkey_alloced = FALSE;
4233
/* next primary/foreign key */
4234
for (j = 0; j < 2; j++)
4236
pkey_ptr += strlen(pkey_ptr) + 1;
4237
fkey_ptr += strlen(fkey_ptr) + 1;
4240
result = PGAPI_Fetch(htbl_stmt);
4245
SC_set_error(stmt, STMT_INTERNAL_ERROR, "No tables specified to PGAPI_ForeignKeys.");
4246
SC_log_error(func, "", stmt);
4247
PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
4255
PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
4257
mylog("PGAPI_ForeignKeys(): EXIT, stmt=%u\n", stmt);
4263
PGAPI_ProcedureColumns(
4265
UCHAR FAR * szProcQualifier,
4266
SWORD cbProcQualifier,
4267
UCHAR FAR * szProcOwner,
4269
UCHAR FAR * szProcName,
4271
UCHAR FAR * szColumnName,
4274
CSTR func = "PGAPI_ProcedureColumns";
4275
StatementClass *stmt = (StatementClass *) hstmt;
4276
ConnectionClass *conn = SC_get_conn(stmt);
4277
char proc_query[INFO_INQUIRY_LEN];
4280
char *schema_name, *procname, *params;
4281
QResultClass *res, *tres;
4282
Int4 tcount, paramcount, i, j, pgtype;
4283
const char *likeeq = "like";
4285
mylog("%s: entering...\n", func);
4287
if (PG_VERSION_LT(conn, 6.5))
4289
SC_set_error(stmt, STMT_NOT_IMPLEMENTED_ERROR, "Version is too old");
4290
SC_log_error(func, "Function not implemented", stmt);
4293
if (!SC_recycle_statement(stmt))
4295
if (conn->schema_support)
4297
strcpy(proc_query, "select proname, proretset, prorettype, "
4298
"pronargs, proargtypes, nspname from "
4299
"pg_catalog.pg_namespace, pg_catalog.pg_proc where "
4300
"pg_proc.pronamespace = pg_namespace.oid "
4301
"and (not proretset)");
4302
schema_strcat1(proc_query, " and nspname %s '%.*s'", likeeq, szProcOwner, cbProcOwner, szProcName, cbProcName, conn);
4303
my_strcat1(proc_query, " and proname %s '%.*s'", likeeq, szProcName, cbProcName);
4304
strcat(proc_query, " order by nspname, proname, proretset");
4308
strcpy(proc_query, "select proname, proretset, prorettype, "
4309
"pronargs, proargtypes from pg_proc where "
4311
my_strcat1(proc_query, " and proname %s '%.*s'", likeeq, szProcName, cbProcName);
4312
strcat(proc_query, " order by proname, proretset");
4314
if (tres = CC_send_query(conn, proc_query, NULL, CLEAR_RESULT_ON_ABORT), !tres)
4316
SC_set_error(stmt, STMT_EXEC_ERROR, "PGAPI_ProcedureColumns query error");
4320
stmt->manual_result = TRUE;
4321
stmt->errormsg_created = TRUE;
4322
if (res = QR_Constructor(), !res)
4324
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate memory for PGAPI_ProcedureColumns result.");
4325
SC_log_error(func, "", stmt);
4328
SC_set_Result(stmt, res);
4331
* the binding structure for a statement is not set up until
4332
* a statement is actually executed, so we'll have to do this
4335
#if (ODBCVER >= 0x0300)
4339
#endif /* ODBCVER */
4340
extend_column_bindings(SC_get_ARD(stmt), result_cols);
4342
/* set the field names */
4343
QR_set_num_fields(res, result_cols);
4344
QR_set_field_info(res, 0, "PROCEDURE_CAT", PG_TYPE_VARCHAR, MAX_INFO_STRING);
4345
QR_set_field_info(res, 1, "PROCEDUR_SCHEM", PG_TYPE_VARCHAR, MAX_INFO_STRING);
4346
QR_set_field_info(res, 2, "PROCEDURE_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
4347
QR_set_field_info(res, 3, "COLUMN_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
4348
QR_set_field_info(res, 4, "COLUMN_TYPE", PG_TYPE_INT2, 2);
4349
QR_set_field_info(res, 5, "DATA_TYPE", PG_TYPE_INT2, 2);
4350
QR_set_field_info(res, 6, "TYPE_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
4351
QR_set_field_info(res, 7, "COLUMN_SIZE", PG_TYPE_INT4, 4);
4352
QR_set_field_info(res, 8, "BUFFER_LENGTH", PG_TYPE_INT4, 4);
4353
QR_set_field_info(res, 9, "DECIMAL_DIGITS", PG_TYPE_INT2, 2);
4354
QR_set_field_info(res, 10, "NUM_PREC_RADIX", PG_TYPE_INT2, 2);
4355
QR_set_field_info(res, 11, "NULLABLE", PG_TYPE_INT2, 2);
4356
QR_set_field_info(res, 12, "REMARKS", PG_TYPE_VARCHAR, MAX_INFO_STRING);
4357
#if (ODBCVER >= 0x0300)
4358
QR_set_field_info(res, 13, "COLUMN_DEF", PG_TYPE_VARCHAR, MAX_INFO_STRING);
4359
QR_set_field_info(res, 14, "SQL_DATA_TYPE", PG_TYPE_INT2, 2);
4360
QR_set_field_info(res, 15, "SQL_DATATIME_SUB", PG_TYPE_INT2, 2);
4361
QR_set_field_info(res, 16, "CHAR_OCTET_LENGTH", PG_TYPE_INT4, 4);
4362
QR_set_field_info(res, 17, "ORIDINAL_POSITION", PG_TYPE_INT4, 4);
4363
QR_set_field_info(res, 18, "IS_NULLABLE", PG_TYPE_VARCHAR, MAX_INFO_STRING);
4364
#endif /* ODBCVER >= 0x0300 */
4366
if (0 == cbColumnName || !szColumnName || !szColumnName[0])
4367
tcount = QR_get_num_total_tuples(tres);
4370
for (i = 0; i < tcount; i++)
4372
if (conn->schema_support)
4373
schema_name = GET_SCHEMA_NAME(QR_get_value_backend_row(tres, i, 5));
4376
procname = QR_get_value_backend_row(tres, i, 0);
4377
pgtype = atoi(QR_get_value_backend_row(tres, i, 2));
4380
row = (TupleNode *) malloc(sizeof(TupleNode) + (result_cols - 1) *sizeof(TupleField));
4381
set_tuplefield_null(&row->tuple[0]);
4382
set_nullfield_string(&row->tuple[1], schema_name);
4383
set_tuplefield_string(&row->tuple[2], procname);
4384
set_tuplefield_string(&row->tuple[3], "");
4385
set_tuplefield_int2(&row->tuple[4], SQL_RETURN_VALUE);
4386
set_tuplefield_int2(&row->tuple[5], pgtype_to_concise_type(stmt, pgtype));
4387
set_tuplefield_string(&row->tuple[6], pgtype_to_name(stmt, pgtype));
4388
set_nullfield_int4(&row->tuple[7], pgtype_column_size(stmt, pgtype, PG_STATIC, PG_STATIC));
4389
set_tuplefield_int4(&row->tuple[8], pgtype_buffer_length(stmt, pgtype, PG_STATIC, PG_STATIC));
4390
set_nullfield_int2(&row->tuple[9], pgtype_decimal_digits(stmt, pgtype, PG_STATIC));
4391
set_nullfield_int2(&row->tuple[10], pgtype_radix(stmt, pgtype));
4392
set_tuplefield_int2(&row->tuple[11], SQL_NULLABLE_UNKNOWN);
4393
set_tuplefield_null(&row->tuple[12]);
4394
#if (ODBCVER >= 0x0300)
4395
set_tuplefield_null(&row->tuple[13]);
4396
set_nullfield_int2(&row->tuple[14], pgtype_to_sqldesctype(stmt, pgtype));
4397
set_nullfield_int2(&row->tuple[15], pgtype_to_datetime_sub(stmt, pgtype));
4398
set_nullfield_int4(&row->tuple[16], pgtype_transfer_octet_length(stmt, pgtype, PG_STATIC, PG_STATIC));
4399
set_tuplefield_int4(&row->tuple[17], 0);
4400
set_tuplefield_string(&row->tuple[18], "");
4401
#endif /* ODBCVER >= 0x0300 */
4402
QR_add_tuple(res, row);
4404
paramcount = atoi(QR_get_value_backend_row(tres, i, 3));
4405
params = QR_get_value_backend_row(tres, i, 4);
4406
for (j = 0; j < paramcount; j++)
4408
while (isspace(*params))
4410
sscanf(params, "%d", &pgtype);
4411
row = (TupleNode *) malloc(sizeof(TupleNode) + (result_cols - 1) *sizeof(TupleField));
4412
set_tuplefield_null(&row->tuple[0]);
4413
set_nullfield_string(&row->tuple[1], schema_name);
4414
set_tuplefield_string(&row->tuple[2], procname);
4415
set_tuplefield_string(&row->tuple[3], "");
4416
set_tuplefield_int2(&row->tuple[4], SQL_PARAM_INPUT);
4417
set_tuplefield_int2(&row->tuple[5], pgtype_to_concise_type(stmt, pgtype));
4418
set_tuplefield_string(&row->tuple[6], pgtype_to_name(stmt, pgtype));
4419
set_nullfield_int4(&row->tuple[7], pgtype_column_size(stmt, pgtype, PG_STATIC, PG_STATIC));
4420
set_tuplefield_int4(&row->tuple[8], pgtype_buffer_length(stmt, pgtype, PG_STATIC, PG_STATIC));
4421
set_nullfield_int2(&row->tuple[9], pgtype_decimal_digits(stmt, pgtype, PG_STATIC));
4422
set_nullfield_int2(&row->tuple[10], pgtype_radix(stmt, pgtype));
4423
set_tuplefield_int2(&row->tuple[11], SQL_NULLABLE_UNKNOWN);
4424
set_tuplefield_null(&row->tuple[12]);
4425
#if (ODBCVER >= 0x0300)
4426
set_tuplefield_null(&row->tuple[13]);
4427
set_nullfield_int2(&row->tuple[14], pgtype_to_sqldesctype(stmt, pgtype));
4428
set_nullfield_int2(&row->tuple[15], pgtype_to_datetime_sub(stmt, pgtype));
4429
set_nullfield_int4(&row->tuple[16], pgtype_transfer_octet_length(stmt, pgtype, PG_STATIC, PG_STATIC));
4430
set_tuplefield_int4(&row->tuple[17], j + 1);
4431
set_tuplefield_string(&row->tuple[18], "");
4432
#endif /* ODBCVER >= 0x0300 */
4433
QR_add_tuple(res, row);
4434
while (isdigit(*params))
4438
QR_Destructor(tres);
4440
* also, things need to think that this statement is finished so the
4441
* results can be retrieved.
4443
stmt->status = STMT_FINISHED;
4444
/* set up the current tuple pointer for SQLFetch */
4445
stmt->currTuple = -1;
4446
stmt->rowset_start = -1;
4447
stmt->current_col = -1;
4456
UCHAR FAR * szProcQualifier,
4457
SWORD cbProcQualifier,
4458
UCHAR FAR * szProcOwner,
4460
UCHAR FAR * szProcName,
4463
CSTR func = "PGAPI_Procedures";
4464
StatementClass *stmt = (StatementClass *) hstmt;
4465
ConnectionClass *conn = SC_get_conn(stmt);
4466
char proc_query[INFO_INQUIRY_LEN];
4468
const char *likeeq = "like";
4470
mylog("%s: entering... scnm=%x len=%d\n", func, szProcOwner, cbProcOwner);
4472
if (PG_VERSION_LT(conn, 6.5))
4474
SC_set_error(stmt, STMT_NOT_IMPLEMENTED_ERROR, "Version is too old");
4475
SC_log_error(func, "Function not implemented", stmt);
4478
if (!SC_recycle_statement(stmt))
4482
* The following seems the simplest implementation
4484
if (conn->schema_support)
4486
strcpy(proc_query, "select '' as " "PROCEDURE_CAT" ", nspname as " "PROCEDURE_SCHEM" ","
4487
" proname as " "PROCEDURE_NAME" ", '' as " "NUM_INPUT_PARAMS" ","
4488
" '' as " "NUM_OUTPUT_PARAMS" ", '' as " "NUM_RESULT_SETS" ","
4489
" '' as " "REMARKS" ","
4490
" case when prorettype = 0 then 1::int2 else 2::int2 end"
4491
" as " "PROCEDURE_TYPE" " from pg_catalog.pg_namespace,"
4492
" pg_catalog.pg_proc"
4493
" where pg_proc.pronamespace = pg_namespace.oid");
4494
schema_strcat1(proc_query, " and nspname %s '%.*s'", likeeq, szProcOwner, cbProcOwner, szProcName, cbProcName, conn);
4495
my_strcat1(proc_query, " and proname %s '%.*s'", likeeq, szProcName, cbProcName);
4499
strcpy(proc_query, "select '' as " "PROCEDURE_CAT" ", '' as " "PROCEDURE_SCHEM" ","
4500
" proname as " "PROCEDURE_NAME" ", '' as " "NUM_INPUT_PARAMS" ","
4501
" '' as " "NUM_OUTPUT_PARAMS" ", '' as " "NUM_RESULT_SETS" ","
4502
" '' as " "REMARKS" ","
4503
" case when prorettype = 0 then 1::int2 else 2::int2 end as " "PROCEDURE_TYPE" " from pg_proc");
4504
my_strcat1(proc_query, " where proname %s '%.*s'", likeeq, szProcName, cbProcName);
4507
if (res = CC_send_query(conn, proc_query, NULL, CLEAR_RESULT_ON_ABORT), !res)
4509
SC_set_error(stmt, STMT_EXEC_ERROR, "PGAPI_Procedures query error");
4512
SC_set_Result(stmt, res);
4515
* also, things need to think that this statement is finished so the
4516
* results can be retrieved.
4518
stmt->status = STMT_FINISHED;
4519
extend_column_bindings(SC_get_ARD(stmt), 8);
4520
/* set up the current tuple pointer for SQLFetch */
4521
stmt->currTuple = -1;
4522
stmt->rowset_start = -1;
4523
stmt->current_col = -1;
4530
#define ALL_PRIVILIGES "arwdRxt"
4532
usracl_auth(char *usracl, const char *auth)
4534
int i, j, addcnt = 0;
4536
for (i = 0; auth[i]; i++)
4538
for (j = 0; j < ACLMAX; j++)
4540
if (usracl[j] == auth[i])
4542
else if (!usracl[j])
4553
useracl_upd(char (*useracl)[ACLMAX], QResultClass *allures, const char *user, const char *auth)
4555
int usercount = QR_get_num_backend_tuples(allures), i, addcnt = 0;
4557
mylog("user=%s auth=%s\n", user, auth);
4559
for (i = 0; i < usercount; i++)
4561
if (strcmp(QR_get_value_backend_row(allures, i, 0), user) == 0)
4563
addcnt += usracl_auth(useracl[i], auth);
4568
for (i = 0; i < usercount; i++)
4570
addcnt += usracl_auth(useracl[i], auth);
4572
mylog("addcnt=%d\n", addcnt);
4576
PGAPI_TablePrivileges(
4578
UCHAR FAR * szTableQualifier,
4579
SWORD cbTableQualifier,
4580
UCHAR FAR * szTableOwner,
4582
UCHAR FAR * szTableName,
4586
StatementClass *stmt = (StatementClass *) hstmt;
4587
CSTR func = "PGAPI_TablePrivileges";
4588
ConnectionClass *conn = SC_get_conn(stmt);
4590
char proc_query[INFO_INQUIRY_LEN];
4591
QResultClass *res, *allures = NULL;
4593
int tablecount, usercount, i, j, k;
4594
BOOL grpauth, sys, su;
4595
char (*useracl)[ACLMAX], *acl, *user, *delim, *auth;
4596
char *reln, *owner, *priv, *schnm = NULL;
4597
const char *likeeq = "like";
4599
mylog("%s: entering... scnm=%x len-%d\n", func, szTableOwner, cbTableOwner);
4600
if (!SC_recycle_statement(stmt))
4604
* a statement is actually executed, so we'll have to do this
4608
extend_column_bindings(SC_get_ARD(stmt), result_cols);
4610
/* set the field names */
4611
stmt->manual_result = TRUE;
4612
res = QR_Constructor();
4613
SC_set_Result(stmt, res);
4614
QR_set_num_fields(res, result_cols);
4615
QR_set_field_info(res, 0, "TABLE_CAT", PG_TYPE_VARCHAR, MAX_INFO_STRING);
4616
QR_set_field_info(res, 1, "TABLE_SCHEM", PG_TYPE_VARCHAR, MAX_INFO_STRING);
4617
QR_set_field_info(res, 2, "TABLE_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
4618
QR_set_field_info(res, 3, "GRANTOR", PG_TYPE_VARCHAR, MAX_INFO_STRING);
4619
QR_set_field_info(res, 4, "GRANTEE", PG_TYPE_VARCHAR, MAX_INFO_STRING);
4620
QR_set_field_info(res, 5, "PRIVILEGE", PG_TYPE_VARCHAR, MAX_INFO_STRING);
4621
QR_set_field_info(res, 6, "IS_GRANTABLE", PG_TYPE_VARCHAR, MAX_INFO_STRING);
4624
* also, things need to think that this statement is finished so the
4625
* results can be retrieved.
4627
stmt->status = STMT_FINISHED;
4628
/* set up the current tuple pointer for SQLFetch */
4629
stmt->currTuple = -1;
4630
stmt->rowset_start = -1;
4631
stmt->current_col = -1;
4632
if (conn->schema_support)
4633
strncpy_null(proc_query, "select relname, usename, relacl, nspname"
4634
" from pg_catalog.pg_namespace, pg_catalog.pg_class ,"
4635
" pg_catalog.pg_user where", sizeof(proc_query));
4637
strncpy_null(proc_query, "select relname, usename, relacl"
4638
" from pg_class , pg_user where", sizeof(proc_query));
4639
if ((flag & PODBC_NOT_SEARCH_PATTERN) != 0)
4641
if (conn->schema_support)
4643
schema_strcat(proc_query, " nspname = '%.*s' and", szTableOwner, cbTableOwner, szTableName, cbTableName, conn);
4645
my_strcat(proc_query, " relname = '%.*s' and", szTableName, cbTableName);
4649
char esc_table_name[TABLE_NAME_STORAGE_LEN * 2];
4652
if (conn->schema_support)
4654
escTbnamelen = reallyEscapeCatalogEscapes(szTableOwner, cbTableOwner, esc_table_name, sizeof(esc_table_name), conn->ccsc);
4655
schema_strcat1(proc_query, " nspname %s '%.*s' and", likeeq, esc_table_name, escTbnamelen, szTableName, cbTableName, conn);
4657
escTbnamelen = reallyEscapeCatalogEscapes(szTableName, cbTableName, esc_table_name, sizeof(esc_table_name), conn->ccsc);
4658
my_strcat1(proc_query, " relname %s '%.*s' and", likeeq, esc_table_name, escTbnamelen);
4660
if (conn->schema_support)
4661
strcat(proc_query, " pg_namespace.oid = relnamespace and");
4662
strcat(proc_query, " pg_user.usesysid = relowner");
4663
if (res = CC_send_query(conn, proc_query, NULL, CLEAR_RESULT_ON_ABORT), !res)
4665
SC_set_error(stmt, STMT_EXEC_ERROR, "PGAPI_TablePrivileges query error");
4668
strncpy_null(proc_query, "select usename, usesysid, usesuper from pg_user", sizeof(proc_query));
4669
tablecount = QR_get_num_backend_tuples(res);
4670
if (allures = CC_send_query(conn, proc_query, NULL, CLEAR_RESULT_ON_ABORT), !allures)
4673
SC_set_error(stmt, STMT_EXEC_ERROR, "PGAPI_TablePrivileges query error");
4676
usercount = QR_get_num_backend_tuples(allures);
4677
useracl = (char (*)[ACLMAX]) malloc(usercount * sizeof(char [ACLMAX]));
4678
for (i = 0; i < tablecount; i++)
4680
memset(useracl, 0, usercount * sizeof(char[ACLMAX]));
4681
acl = (char *) QR_get_value_backend_row(res, i, 2);
4682
if (acl && acl[0] == '{')
4686
for (; user && *user;)
4689
if (user[0] == '"' && strncmp(user + 1, "group ", 6) == 0)
4694
if (delim = strchr(user, '='), !delim)
4700
if (delim = strchr(auth, '"'), delim)
4706
else if (delim = strchr(auth, ','), delim)
4708
else if (delim = strchr(auth, '}'), delim)
4710
if (grpauth) /* handle group privilege */
4714
char *grolist, *uid, *delm;
4716
snprintf(proc_query, sizeof(proc_query) - 1, "select grolist from pg_group where groname = '%s'", user);
4717
if (gres = CC_send_query(conn, proc_query, NULL, CLEAR_RESULT_ON_ABORT), gres != NULL)
4719
grolist = QR_get_value_backend_row(gres, 0, 0);
4720
if (grolist && grolist[0] == '{')
4722
for (uid = grolist + 1; *uid;)
4724
if (delm = strchr(uid, ','), delm)
4726
else if (delm = strchr(uid, '}'), delm)
4728
mylog("guid=%s\n", uid);
4729
for (i = 0; i < usercount; i++)
4731
if (strcmp(QR_get_value_backend_row(allures, i, 1), uid) == 0)
4732
useracl_upd(useracl, allures, QR_get_value_backend_row(allures, i, 0), auth);
4737
QR_Destructor(gres);
4741
useracl_upd(useracl, allures, user, auth);
4746
reln = QR_get_value_backend_row(res, i, 0);
4747
owner = QR_get_value_backend_row(res, i, 1);
4748
if (conn->schema_support)
4749
schnm = QR_get_value_backend_row(res, i, 3);
4750
/* The owner has all privileges */
4751
useracl_upd(useracl, allures, owner, ALL_PRIVILIGES);
4752
for (j = 0; j < usercount; j++)
4754
user = QR_get_value_backend_row(allures, j, 0);
4755
su = (strcmp(QR_get_value_backend_row(allures, j, 2), "t") == 0);
4756
sys = (strcmp(user, owner) == 0);
4757
/* Super user has all privileges */
4759
useracl_upd(useracl, allures, user, ALL_PRIVILIGES);
4760
for (k = 0; k < ACLMAX; k++)
4764
switch (useracl[j][k])
4766
case 'R': /* rule */
4767
case 't': /* trigger */
4770
row = (TupleNode *) malloc(sizeof(TupleNode) + (7 - 1) *sizeof(TupleField));
4771
set_tuplefield_string(&row->tuple[0], "");
4772
if (conn->schema_support)
4773
set_tuplefield_string(&row->tuple[1], GET_SCHEMA_NAME(schnm));
4775
set_tuplefield_string(&row->tuple[1], "");
4776
set_tuplefield_string(&row->tuple[2], reln);
4778
set_tuplefield_string(&row->tuple[3], "_SYSTEM");
4780
set_tuplefield_string(&row->tuple[3], owner);
4781
mylog("user=%s\n", user);
4782
set_tuplefield_string(&row->tuple[4], user);
4783
switch (useracl[j][k])
4798
priv = "REFERENCES";
4803
set_tuplefield_string(&row->tuple[5], priv);
4804
/* The owner and the super user are grantable */
4806
set_tuplefield_string(&row->tuple[6], "YES");
4808
set_tuplefield_string(&row->tuple[6], "NO");
4809
QR_add_tuple(SC_get_Result(stmt), row);
4815
QR_Destructor(allures);