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, 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
49
#define NULL_IF_NULL(a) ((a) ? ((const char *) a) : "(NULL)")
51
/* extern GLOBAL_VALUES globals; */
53
CSTR pubstr = "public";
60
SQLUSMALLINT fInfoType,
62
SQLSMALLINT cbInfoValueMax,
63
SQLSMALLINT FAR * pcbInfoValue)
65
CSTR func = "PGAPI_GetInfo";
66
ConnectionClass *conn = (ConnectionClass *) hdbc;
69
char tmp[MAX_INFO_STRING];
72
RETCODE result = SQL_ERROR;
76
mylog("%s: entering...fInfoType=%d\n", func, fInfoType);
80
CC_log_error(func, NULL_STRING, NULL);
81
return SQL_INVALID_HANDLE;
84
ci = &(conn->connInfo);
88
case SQL_ACCESSIBLE_PROCEDURES: /* ODBC 1.0 */
92
case SQL_ACCESSIBLE_TABLES: /* ODBC 1.0 */
93
p = CC_accessible_only(conn) ? "Y" : "N";
96
case SQL_ACTIVE_CONNECTIONS: /* ODBC 1.0 */
101
case SQL_ACTIVE_STATEMENTS: /* ODBC 1.0 */
106
case SQL_ALTER_TABLE: /* ODBC 2.0 */
108
value = SQL_AT_ADD_COLUMN;
109
if (PG_VERSION_GE(conn, 7.3))
110
value |= SQL_AT_DROP_COLUMN;
111
#if (ODBCVER >= 0x0300)
112
value |= SQL_AT_ADD_COLUMN_SINGLE;
113
if (PG_VERSION_GE(conn, 7.1))
114
value |= SQL_AT_ADD_CONSTRAINT
115
| SQL_AT_ADD_TABLE_CONSTRAINT
116
| SQL_AT_CONSTRAINT_INITIALLY_DEFERRED
117
| SQL_AT_CONSTRAINT_INITIALLY_IMMEDIATE
118
| SQL_AT_CONSTRAINT_DEFERRABLE;
119
if (PG_VERSION_GE(conn, 7.3))
120
value |= SQL_AT_DROP_TABLE_CONSTRAINT_RESTRICT
121
| SQL_AT_DROP_TABLE_CONSTRAINT_CASCADE
122
| SQL_AT_DROP_COLUMN_RESTRICT
123
| SQL_AT_DROP_COLUMN_CASCADE;
127
case SQL_BOOKMARK_PERSISTENCE: /* ODBC 2.0 */
128
/* very simple bookmark support */
130
value = ci->drivers.use_declarefetch && PG_VERSION_LT(conn, 7.4) ? 0 : (SQL_BP_SCROLL | SQL_BP_DELETE | SQL_BP_UPDATE | SQL_BP_TRANSACTION);
133
case SQL_COLUMN_ALIAS: /* ODBC 2.0 */
137
case SQL_CONCAT_NULL_BEHAVIOR: /* ODBC 1.0 */
139
value = SQL_CB_NON_NULL;
142
case SQL_CONVERT_INTEGER:
143
case SQL_CONVERT_SMALLINT:
144
case SQL_CONVERT_TINYINT:
145
case SQL_CONVERT_BIT:
146
case SQL_CONVERT_VARCHAR: /* ODBC 1.0 */
147
len = sizeof(SQLUINTEGER);
148
value = SQL_CVT_BIT | SQL_CVT_INTEGER;
149
mylog("SQL_CONVERT_ mask=" FORMAT_ULEN "\n", value);
151
case SQL_CONVERT_BIGINT:
152
case SQL_CONVERT_DECIMAL:
153
case SQL_CONVERT_DOUBLE:
154
case SQL_CONVERT_FLOAT:
155
case SQL_CONVERT_NUMERIC:
156
case SQL_CONVERT_REAL:
157
case SQL_CONVERT_DATE:
158
case SQL_CONVERT_TIME:
159
case SQL_CONVERT_TIMESTAMP:
160
case SQL_CONVERT_BINARY:
161
case SQL_CONVERT_LONGVARBINARY:
162
case SQL_CONVERT_VARBINARY: /* ODBC 1.0 */
163
case SQL_CONVERT_CHAR:
164
case SQL_CONVERT_LONGVARCHAR:
165
#if defined(UNICODE_SUPPORT) && (ODBCVER >= 0x0300)
166
case SQL_CONVERT_WCHAR:
167
case SQL_CONVERT_WLONGVARCHAR:
168
case SQL_CONVERT_WVARCHAR:
169
#endif /* UNICODE_SUPPORT */
170
len = sizeof(SQLUINTEGER);
171
value = 0; /* CONVERT is unavailable */
174
case SQL_CONVERT_FUNCTIONS: /* ODBC 1.0 */
175
len = sizeof(SQLUINTEGER);
176
value = SQL_FN_CVT_CONVERT;
177
mylog("CONVERT_FUNCTIONS=" FORMAT_ULEN "\n", value);
180
case SQL_CORRELATION_NAME: /* ODBC 1.0 */
183
* Saying no correlation name makes Query not work right.
184
* value = SQL_CN_NONE;
190
case SQL_CURSOR_COMMIT_BEHAVIOR: /* ODBC 1.0 */
192
value = SQL_CB_CLOSE;
193
if (!ci->drivers.use_declarefetch || PG_VERSION_GE(conn, 7.4))
194
value = SQL_CB_PRESERVE;
197
case SQL_CURSOR_ROLLBACK_BEHAVIOR: /* ODBC 1.0 */
199
value = SQL_CB_CLOSE;
200
if (!ci->drivers.use_declarefetch)
201
value = SQL_CB_PRESERVE;
204
case SQL_DATA_SOURCE_NAME: /* ODBC 1.0 */
205
p = CC_get_DSN(conn);
208
case SQL_DATA_SOURCE_READ_ONLY: /* ODBC 1.0 */
209
p = CC_is_onlyread(conn) ? "Y" : "N";
212
case SQL_DATABASE_NAME: /* Support for old ODBC 1.0 Apps */
215
* Returning the database name causes problems in MS Query. It
216
* generates query like: "SELECT DISTINCT a FROM byronnbad3
219
* p = CC_get_database(conn);
221
p = CurrCatString(conn);
224
case SQL_DBMS_NAME: /* ODBC 1.0 */
225
if (CC_fake_mss(conn))
226
p = "Microsoft SQL Server";
231
case SQL_DBMS_VER: /* ODBC 1.0 */
234
* The ODBC spec wants ##.##.#### ...whatever... so prepend
237
/* version number to the dbms version string */
239
snprintf(tmp, sizeof(tmp) - 1, "%s %s", POSTGRESDRIVERVERSION, conn->pg_version);
240
tmp[sizeof(tmp) - 1] = '\0'; */
241
if (CC_fake_mss(conn))
245
strncpy_null(tmp, conn->pg_version, sizeof(tmp));
250
case SQL_DEFAULT_TXN_ISOLATION: /* ODBC 1.0 */
252
if (PG_VERSION_LT(conn, 6.5))
253
value = SQL_TXN_SERIALIZABLE;
255
value = SQL_TXN_READ_COMMITTED;
258
case SQL_DRIVER_NAME: /* ODBC 1.0 */
259
p = DRIVER_FILE_NAME;
262
case SQL_DRIVER_ODBC_VER:
263
i_odbcver = conn->driver_version;
264
snprintf(odbcver, sizeof(odbcver), "%02x.%02x", i_odbcver / 256, i_odbcver % 256);
265
/* p = DRIVER_ODBC_VER; */
269
case SQL_DRIVER_VER: /* ODBC 1.0 */
270
p = POSTGRESDRIVERVERSION;
273
case SQL_EXPRESSIONS_IN_ORDERBY: /* ODBC 1.0 */
274
p = PG_VERSION_GE(conn, 6.5) ? "Y" : "N";
277
case SQL_FETCH_DIRECTION: /* ODBC 1.0 */
279
value = (SQL_FD_FETCH_NEXT |
284
SQL_FD_FETCH_ABSOLUTE |
285
SQL_FD_FETCH_RELATIVE |
286
SQL_FD_FETCH_BOOKMARK);
289
case SQL_FILE_USAGE: /* ODBC 2.0 */
291
value = SQL_FILE_NOT_SUPPORTED;
294
case SQL_GETDATA_EXTENSIONS: /* ODBC 2.0 */
296
value = (SQL_GD_ANY_COLUMN | SQL_GD_ANY_ORDER | SQL_GD_BOUND | SQL_GD_BLOCK);
299
case SQL_GROUP_BY: /* ODBC 2.0 */
301
value = SQL_GB_GROUP_BY_EQUALS_SELECT;
304
case SQL_IDENTIFIER_CASE: /* ODBC 1.0 */
307
* are identifiers case-sensitive (yes, but only when quoted.
308
* If not quoted, they default to lowercase)
311
value = SQL_IC_LOWER;
314
case SQL_IDENTIFIER_QUOTE_CHAR: /* ODBC 1.0 */
315
/* the character used to quote "identifiers" */
316
p = PG_VERSION_LE(conn, 6.2) ? " " : "\"";
319
case SQL_KEYWORDS: /* ODBC 2.0 */
323
case SQL_LIKE_ESCAPE_CLAUSE: /* ODBC 2.0 */
326
* is there a character that escapes '%' and '_' in a LIKE
327
* clause? not as far as I can tell
332
case SQL_LOCK_TYPES: /* ODBC 2.0 */
334
value = ci->drivers.lie ? (SQL_LCK_NO_CHANGE | SQL_LCK_EXCLUSIVE | SQL_LCK_UNLOCK) : SQL_LCK_NO_CHANGE;
337
case SQL_MAX_BINARY_LITERAL_LEN: /* ODBC 2.0 */
342
case SQL_MAX_CHAR_LITERAL_LEN: /* ODBC 2.0 */
347
case SQL_MAX_COLUMN_NAME_LEN: /* ODBC 1.0 */
349
if (PG_VERSION_GT(conn, 7.4))
350
value = CC_get_max_idlen(conn);
351
#ifdef MAX_COLUMN_LEN
353
value = MAX_COLUMN_LEN;
354
#endif /* MAX_COLUMN_LEN */
357
if (PG_VERSION_GE(conn, 7.3))
358
value = NAMEDATALEN_V73;
360
value = NAMEDATALEN_V72;
364
case SQL_MAX_COLUMNS_IN_GROUP_BY: /* ODBC 2.0 */
369
case SQL_MAX_COLUMNS_IN_INDEX: /* ODBC 2.0 */
374
case SQL_MAX_COLUMNS_IN_ORDER_BY: /* ODBC 2.0 */
379
case SQL_MAX_COLUMNS_IN_SELECT: /* ODBC 2.0 */
384
case SQL_MAX_COLUMNS_IN_TABLE: /* ODBC 2.0 */
389
case SQL_MAX_CURSOR_NAME_LEN: /* ODBC 1.0 */
391
value = MAX_CURSOR_LEN;
394
case SQL_MAX_INDEX_SIZE: /* ODBC 2.0 */
399
case SQL_MAX_OWNER_NAME_LEN: /* ODBC 1.0 */
402
if (PG_VERSION_GT(conn, 7.4))
403
value = CC_get_max_idlen(conn);
404
#ifdef MAX_SCHEMA_LEN
405
else if (conn->schema_support)
406
value = MAX_SCHEMA_LEN;
407
#endif /* MAX_SCHEMA_LEN */
410
if (PG_VERSION_GE(conn, 7.3))
411
value = NAMEDATALEN_V73;
415
case SQL_MAX_PROCEDURE_NAME_LEN: /* ODBC 1.0 */
420
case SQL_MAX_QUALIFIER_NAME_LEN: /* ODBC 1.0 */
425
case SQL_MAX_ROW_SIZE: /* ODBC 2.0 */
427
if (PG_VERSION_GE(conn, 7.1))
429
/* Large Rowa in 7.1+ */
430
value = MAX_ROW_SIZE;
434
/* Without the Toaster we're limited to the blocksize */
439
case SQL_MAX_ROW_SIZE_INCLUDES_LONG: /* ODBC 2.0 */
442
* does the preceding value include LONGVARCHAR and
443
* LONGVARBINARY fields? Well, it does include longvarchar,
444
* but not longvarbinary.
449
case SQL_MAX_STATEMENT_LEN: /* ODBC 2.0 */
450
/* maybe this should be 0? */
452
value = CC_get_max_query_len(conn);
455
case SQL_MAX_TABLE_NAME_LEN: /* ODBC 1.0 */
457
if (PG_VERSION_GT(conn, 7.4))
458
value = CC_get_max_idlen(conn);
461
value = MAX_TABLE_LEN;
462
#endif /* MAX_TABLE_LEN */
465
if (PG_VERSION_GE(conn, 7.3))
466
value = NAMEDATALEN_V73;
468
value = NAMEDATALEN_V72;
472
case SQL_MAX_TABLES_IN_SELECT: /* ODBC 2.0 */
477
case SQL_MAX_USER_NAME_LEN:
482
case SQL_MULT_RESULT_SETS: /* ODBC 1.0 */
483
/* Don't support multiple result sets but say yes anyway? */
487
case SQL_MULTIPLE_ACTIVE_TXN: /* ODBC 1.0 */
491
case SQL_NEED_LONG_DATA_LEN: /* ODBC 2.0 */
494
* Don't need the length, SQLPutData can handle any size and
500
case SQL_NON_NULLABLE_COLUMNS: /* ODBC 1.0 */
502
value = SQL_NNC_NON_NULL;
505
case SQL_NULL_COLLATION: /* ODBC 2.0 */
506
/* where are nulls sorted? */
508
if (PG_VERSION_GE(conn, 7.2))
514
case SQL_NUMERIC_FUNCTIONS: /* ODBC 1.0 */
519
case SQL_ODBC_API_CONFORMANCE: /* ODBC 1.0 */
521
value = SQL_OAC_LEVEL1;
524
case SQL_ODBC_SAG_CLI_CONFORMANCE: /* ODBC 1.0 */
526
value = SQL_OSCC_NOT_COMPLIANT;
529
case SQL_ODBC_SQL_CONFORMANCE: /* ODBC 1.0 */
531
value = SQL_OSC_CORE;
534
case SQL_ODBC_SQL_OPT_IEF: /* ODBC 1.0 */
538
case SQL_OJ_CAPABILITIES: /* ODBC 2.01 */
540
if (PG_VERSION_GE(conn, 7.1))
543
value = (SQL_OJ_LEFT |
549
SQL_OJ_ALL_COMPARISON_OPS);
552
/* OJs not in <7.1 */
556
case SQL_ORDER_BY_COLUMNS_IN_SELECT: /* ODBC 2.0 */
557
p = (PG_VERSION_LE(conn, 6.3)) ? "Y" : "N";
560
case SQL_OUTER_JOINS: /* ODBC 1.0 */
561
if (PG_VERSION_GE(conn, 7.1))
565
/* OJs not in <7.1 */
569
case SQL_OWNER_TERM: /* ODBC 1.0 */
570
if (conn->schema_support)
576
case SQL_OWNER_USAGE: /* ODBC 2.0 */
579
if (conn->schema_support)
580
value = SQL_OU_DML_STATEMENTS
581
| SQL_OU_TABLE_DEFINITION
582
| SQL_OU_INDEX_DEFINITION
583
| SQL_OU_PRIVILEGE_DEFINITION
587
case SQL_POS_OPERATIONS: /* ODBC 2.0 */
589
value = (SQL_POS_POSITION | SQL_POS_REFRESH);
590
if (0 != ci->updatable_cursors)
591
value |= (SQL_POS_UPDATE | SQL_POS_DELETE | SQL_POS_ADD);
594
case SQL_POSITIONED_STATEMENTS: /* ODBC 2.0 */
596
value = ci->drivers.lie ? (SQL_PS_POSITIONED_DELETE |
597
SQL_PS_POSITIONED_UPDATE |
598
SQL_PS_SELECT_FOR_UPDATE) : 0;
601
case SQL_PROCEDURE_TERM: /* ODBC 1.0 */
605
case SQL_PROCEDURES: /* ODBC 1.0 */
609
case SQL_QUALIFIER_LOCATION: /* ODBC 2.0 */
612
value = SQL_QL_START;
617
case SQL_QUALIFIER_NAME_SEPARATOR: /* ODBC 1.0 */
624
case SQL_QUALIFIER_TERM: /* ODBC 1.0 */
631
case SQL_QUALIFIER_USAGE: /* ODBC 2.0 */
633
#if (ODBCVER >= 0x0300)
635
value = SQL_CU_DML_STATEMENTS;
641
case SQL_QUOTED_IDENTIFIER_CASE: /* ODBC 2.0 */
642
/* are "quoted" identifiers case-sensitive? YES! */
644
value = SQL_IC_SENSITIVE;
647
case SQL_ROW_UPDATES: /* ODBC 1.0 */
650
* Driver doesn't support keyset-driven or mixed cursors, so
651
* not much point in saying row updates are supported
653
p = (0 != ci->updatable_cursors) ? "Y" : "N";
656
case SQL_SCROLL_CONCURRENCY: /* ODBC 1.0 */
658
value = SQL_SCCO_READ_ONLY;
659
if (0 != ci->updatable_cursors)
660
value |= SQL_SCCO_OPT_ROWVER;
662
value |= (SQL_SCCO_LOCK | SQL_SCCO_OPT_VALUES);
665
case SQL_SCROLL_OPTIONS: /* ODBC 1.0 */
667
value = SQL_SO_FORWARD_ONLY | SQL_SO_STATIC;
668
if (0 != (ci->updatable_cursors & ALLOW_KEYSET_DRIVEN_CURSORS))
669
value |= SQL_SO_KEYSET_DRIVEN;
671
value |= (SQL_SO_DYNAMIC | SQL_SO_MIXED);
674
case SQL_SEARCH_PATTERN_ESCAPE: /* ODBC 1.0 */
675
if (PG_VERSION_GE(conn, 6.5))
681
case SQL_SERVER_NAME: /* ODBC 1.0 */
682
p = CC_get_server(conn);
685
case SQL_SPECIAL_CHARACTERS: /* ODBC 2.0 */
689
case SQL_STATIC_SENSITIVITY: /* ODBC 2.0 */
692
if (0 != ci->updatable_cursors)
693
value |= (SQL_SS_ADDITIONS | SQL_SS_DELETIONS | SQL_SS_UPDATES);
696
case SQL_STRING_FUNCTIONS: /* ODBC 1.0 */
698
value = (SQL_FN_STR_CONCAT |
704
SQL_FN_STR_SUBSTRING |
708
case SQL_SUBQUERIES: /* ODBC 2.0 */
709
/* postgres 6.3 supports subqueries */
711
value = (SQL_SQ_QUANTIFIED |
717
case SQL_SYSTEM_FUNCTIONS: /* ODBC 1.0 */
722
case SQL_TABLE_TERM: /* ODBC 1.0 */
726
case SQL_TIMEDATE_ADD_INTERVALS: /* ODBC 2.0 */
731
case SQL_TIMEDATE_DIFF_INTERVALS: /* ODBC 2.0 */
736
case SQL_TIMEDATE_FUNCTIONS: /* ODBC 1.0 */
738
value = (SQL_FN_TD_NOW);
741
case SQL_TXN_CAPABLE: /* ODBC 1.0 */
744
* Postgres can deal with create or drop table statements in a
751
case SQL_TXN_ISOLATION_OPTION: /* ODBC 1.0 */
753
if (PG_VERSION_LT(conn, 6.5))
754
value = SQL_TXN_SERIALIZABLE;
755
else if (PG_VERSION_GE(conn, 7.1))
756
value = SQL_TXN_READ_COMMITTED | SQL_TXN_SERIALIZABLE;
758
value = SQL_TXN_READ_COMMITTED;
761
case SQL_UNION: /* ODBC 2.0 */
762
/* unions with all supported in postgres 6.3 */
764
value = (SQL_U_UNION | SQL_U_UNION_ALL);
767
case SQL_USER_NAME: /* ODBC 1.0 */
768
p = CC_get_username(conn);
772
/* unrecognized key */
773
CC_set_error(conn, CONN_NOT_IMPLEMENTED_ERROR, "Unrecognized key passed to PGAPI_GetInfo.", NULL);
777
result = SQL_SUCCESS;
779
mylog("%s: p='%s', len=%d, value=%d, cbMax=%d\n", func, p ? p : "<NULL>", len, value, cbInfoValueMax);
782
* NOTE, that if rgbInfoValue is NULL, then no warnings or errors
783
* should result and just pcbInfoValue is returned, which indicates
784
* what length would be required if a real buffer had been passed in.
788
/* char/binary data */
793
#ifdef UNICODE_SUPPORT
794
if (CC_is_in_unicode_driver(conn))
796
len = utf8_to_ucs2(p, len, (SQLWCHAR *) rgbInfoValue, cbInfoValueMax / WCLEN);
800
#endif /* UNICODE_SUPPORT */
801
strncpy_null((char *) rgbInfoValue, p, (size_t) cbInfoValueMax);
803
if (len >= cbInfoValueMax)
805
result = SQL_SUCCESS_WITH_INFO;
806
CC_set_error(conn, CONN_TRUNCATED, "The buffer was too small for the InfoValue.", func);
809
#ifdef UNICODE_SUPPORT
810
else if (CC_is_in_unicode_driver(conn))
812
#endif /* UNICODE_SUPPORT */
819
if (len == sizeof(SQLSMALLINT))
820
*((SQLUSMALLINT *) rgbInfoValue) = (SQLUSMALLINT) value;
821
else if (len == sizeof(SQLINTEGER))
822
*((SQLUINTEGER *) rgbInfoValue) = (SQLUINTEGER) value;
827
*pcbInfoValue = (SQLSMALLINT) len;
837
SQLSMALLINT fSqlType)
839
CSTR func = "PGAPI_GetTypeInfo";
840
StatementClass *stmt = (StatementClass *) hstmt;
841
ConnectionClass *conn;
842
QResultClass *res = NULL;
849
RETCODE result = SQL_SUCCESS;
851
mylog("%s: entering...fSqlType = %d\n", func, fSqlType);
853
if (result = SC_initialize_and_recycle(stmt), SQL_SUCCESS != result)
856
conn = SC_get_conn(stmt);
857
if (res = QR_Constructor(), !res)
859
SC_set_error(stmt, STMT_INTERNAL_ERROR, "Error creating result.", func);
862
SC_set_Result(stmt, res);
864
#define return DONT_CALL_RETURN_FROM_HERE???
865
#if (ODBCVER >= 0x0300)
870
extend_column_bindings(SC_get_ARDF(stmt), result_cols);
872
stmt->catalog_result = TRUE;
873
QR_set_num_fields(res, result_cols);
874
QR_set_field_info_v(res, 0, "TYPE_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
875
QR_set_field_info_v(res, 1, "DATA_TYPE", PG_TYPE_INT2, 2);
876
QR_set_field_info_v(res, 2, "PRECISION", PG_TYPE_INT4, 4);
877
QR_set_field_info_v(res, 3, "LITERAL_PREFIX", PG_TYPE_VARCHAR, MAX_INFO_STRING);
878
QR_set_field_info_v(res, 4, "LITERAL_SUFFIX", PG_TYPE_VARCHAR, MAX_INFO_STRING);
879
QR_set_field_info_v(res, 5, "CREATE_PARAMS", PG_TYPE_VARCHAR, MAX_INFO_STRING);
880
QR_set_field_info_v(res, 6, "NULLABLE", PG_TYPE_INT2, 2);
881
QR_set_field_info_v(res, 7, "CASE_SENSITIVE", PG_TYPE_INT2, 2);
882
QR_set_field_info_v(res, 8, "SEARCHABLE", PG_TYPE_INT2, 2);
883
QR_set_field_info_v(res, 9, "UNSIGNED_ATTRIBUTE", PG_TYPE_INT2, 2);
884
QR_set_field_info_v(res, 10, "MONEY", PG_TYPE_INT2, 2);
885
QR_set_field_info_v(res, 11, "AUTO_INCREMENT", PG_TYPE_INT2, 2);
886
QR_set_field_info_v(res, 12, "LOCAL_TYPE_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
887
QR_set_field_info_v(res, 13, "MINIMUM_SCALE", PG_TYPE_INT2, 2);
888
QR_set_field_info_v(res, 14, "MAXIMUM_SCALE", PG_TYPE_INT2, 2);
889
#if (ODBCVER >=0x0300)
890
QR_set_field_info_v(res, 15, "SQL_DATA_TYPE", PG_TYPE_INT2, 2);
891
QR_set_field_info_v(res, 16, "SQL_DATETIME_SUB", PG_TYPE_INT2, 2);
892
QR_set_field_info_v(res, 17, "NUM_PREC_RADIX", PG_TYPE_INT4, 4);
893
QR_set_field_info_v(res, 18, "INTERVAL_PRECISION", PG_TYPE_INT2, 2);
896
for (i = 0, sqlType = sqlTypes[0]; sqlType; sqlType = sqlTypes[++i])
898
pgType = sqltype_to_pgtype(conn, sqlType);
900
if (sqlType == SQL_LONGVARBINARY)
902
ConnInfo *ci = &(conn->connInfo);
903
inolog("%d sqltype=%d -> pgtype=%d\n", ci->bytea_as_longvarbinary, sqlType, pgType);
906
if (fSqlType == SQL_ALL_TYPES || fSqlType == sqlType)
908
int pgtcount = 1, aunq_match = -1, cnt;
910
/*if (SQL_INTEGER == sqlType || SQL_TINYINT == sqlType)*/
911
if (SQL_INTEGER == sqlType)
913
mylog("sqlType=%d ms_jet=%d\n", sqlType, conn->ms_jet);
914
if (conn->ms_jet && PG_VERSION_GE(conn, 6.4))
919
mylog("aunq_match=%d pgtcount=%d\n", aunq_match, pgtcount);
921
for (cnt = 0; cnt < pgtcount; cnt ++)
923
if (tuple = QR_AddNew(res), NULL == tuple)
926
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't QR_AddNew.", func);
930
/* These values can't be NULL */
931
if (aunq_match == cnt)
933
set_tuplefield_string(&tuple[0], pgtype_to_name(stmt, pgType, PG_UNSPECIFIED, TRUE));
934
set_tuplefield_int2(&tuple[6], SQL_NO_NULLS);
935
inolog("serial in\n");
939
set_tuplefield_string(&tuple[0], pgtype_to_name(stmt, pgType, PG_UNSPECIFIED, FALSE));
940
set_tuplefield_int2(&tuple[6], pgtype_nullable(conn, pgType));
942
set_tuplefield_int2(&tuple[1], (Int2) sqlType);
943
set_tuplefield_int2(&tuple[7], pgtype_case_sensitive(conn, pgType));
944
set_tuplefield_int2(&tuple[8], pgtype_searchable(conn, pgType));
945
set_tuplefield_int2(&tuple[10], pgtype_money(conn, pgType));
948
* Localized data-source dependent data type name (always
951
set_tuplefield_null(&tuple[12]);
953
/* These values can be NULL */
954
set_nullfield_int4(&tuple[2], pgtype_column_size(stmt, pgType, PG_STATIC, UNKNOWNS_AS_DEFAULT));
955
set_nullfield_string(&tuple[3], pgtype_literal_prefix(conn, pgType));
956
set_nullfield_string(&tuple[4], pgtype_literal_suffix(conn, pgType));
957
set_nullfield_string(&tuple[5], pgtype_create_params(conn, pgType));
959
set_tuplefield_int2(&tuple[9], SQL_TRUE);
961
set_nullfield_int2(&tuple[9], pgtype_unsigned(conn, pgType));
962
if (aunq_match == cnt)
963
set_tuplefield_int2(&tuple[11], SQL_TRUE);
965
set_nullfield_int2(&tuple[11], pgtype_auto_increment(conn, pgType));
966
set_nullfield_int2(&tuple[13], pgtype_min_decimal_digits(conn, pgType));
967
set_nullfield_int2(&tuple[14], pgtype_max_decimal_digits(conn, pgType));
968
#if (ODBCVER >=0x0300)
969
set_nullfield_int2(&tuple[15], pgtype_to_sqldesctype(stmt, pgType, PG_STATIC));
970
set_nullfield_int2(&tuple[16], pgtype_to_datetime_sub(stmt, pgType, PG_UNSPECIFIED));
971
set_nullfield_int4(&tuple[17], pgtype_radix(conn, pgType));
972
set_nullfield_int4(&tuple[18], 0);
981
* also, things need to think that this statement is finished so the
982
* results can be retrieved.
984
stmt->status = STMT_FINISHED;
985
stmt->currTuple = -1;
986
if (SQL_SUCCEEDED(result))
987
SC_set_rowset_start(stmt, -1, FALSE);
989
SC_set_Result(stmt, NULL);
990
SC_set_current_col(stmt, -1);
993
result = DiscardStatementSvp(stmt, result, FALSE);
1001
SQLUSMALLINT fFunction,
1002
SQLUSMALLINT FAR * pfExists)
1004
CSTR func = "PGAPI_GetFunctions";
1005
ConnectionClass *conn = (ConnectionClass *) hdbc;
1006
ConnInfo *ci = &(conn->connInfo);
1008
mylog("%s: entering...%u\n", func, fFunction);
1010
if (fFunction == SQL_API_ALL_FUNCTIONS)
1012
#if (ODBCVER < 0x0300)
1013
if (ci->drivers.lie)
1017
memset(pfExists, 0, sizeof(pfExists[0]) * 100);
1019
pfExists[SQL_API_SQLALLOCENV] = TRUE;
1020
pfExists[SQL_API_SQLFREEENV] = TRUE;
1021
for (i = SQL_API_SQLALLOCCONNECT; i <= SQL_NUM_FUNCTIONS; i++)
1023
for (i = SQL_EXT_API_START; i <= SQL_EXT_API_LAST; i++)
1029
memset(pfExists, 0, sizeof(pfExists[0]) * 100);
1031
/* ODBC core functions */
1032
pfExists[SQL_API_SQLALLOCCONNECT] = TRUE;
1033
pfExists[SQL_API_SQLALLOCENV] = TRUE;
1034
pfExists[SQL_API_SQLALLOCSTMT] = TRUE;
1035
pfExists[SQL_API_SQLBINDCOL] = TRUE;
1036
pfExists[SQL_API_SQLCANCEL] = TRUE;
1037
pfExists[SQL_API_SQLCOLATTRIBUTES] = TRUE;
1038
pfExists[SQL_API_SQLCONNECT] = TRUE;
1039
pfExists[SQL_API_SQLDESCRIBECOL] = TRUE; /* partial */
1040
pfExists[SQL_API_SQLDISCONNECT] = TRUE;
1041
pfExists[SQL_API_SQLERROR] = TRUE;
1042
pfExists[SQL_API_SQLEXECDIRECT] = TRUE;
1043
pfExists[SQL_API_SQLEXECUTE] = TRUE;
1044
pfExists[SQL_API_SQLFETCH] = TRUE;
1045
pfExists[SQL_API_SQLFREECONNECT] = TRUE;
1046
pfExists[SQL_API_SQLFREEENV] = TRUE;
1047
pfExists[SQL_API_SQLFREESTMT] = TRUE;
1048
pfExists[SQL_API_SQLGETCURSORNAME] = TRUE;
1049
pfExists[SQL_API_SQLNUMRESULTCOLS] = TRUE;
1050
pfExists[SQL_API_SQLPREPARE] = TRUE; /* complete? */
1051
pfExists[SQL_API_SQLROWCOUNT] = TRUE;
1052
pfExists[SQL_API_SQLSETCURSORNAME] = TRUE;
1053
pfExists[SQL_API_SQLSETPARAM] = FALSE; /* odbc 1.0 */
1054
pfExists[SQL_API_SQLTRANSACT] = TRUE;
1056
/* ODBC level 1 functions */
1057
pfExists[SQL_API_SQLBINDPARAMETER] = TRUE;
1058
pfExists[SQL_API_SQLCOLUMNS] = TRUE;
1059
pfExists[SQL_API_SQLDRIVERCONNECT] = TRUE;
1060
pfExists[SQL_API_SQLGETCONNECTOPTION] = TRUE; /* partial */
1061
pfExists[SQL_API_SQLGETDATA] = TRUE;
1062
pfExists[SQL_API_SQLGETFUNCTIONS] = TRUE;
1063
pfExists[SQL_API_SQLGETINFO] = TRUE;
1064
pfExists[SQL_API_SQLGETSTMTOPTION] = TRUE; /* partial */
1065
pfExists[SQL_API_SQLGETTYPEINFO] = TRUE;
1066
pfExists[SQL_API_SQLPARAMDATA] = TRUE;
1067
pfExists[SQL_API_SQLPUTDATA] = TRUE;
1068
pfExists[SQL_API_SQLSETCONNECTOPTION] = TRUE; /* partial */
1069
pfExists[SQL_API_SQLSETSTMTOPTION] = TRUE;
1070
pfExists[SQL_API_SQLSPECIALCOLUMNS] = TRUE;
1071
pfExists[SQL_API_SQLSTATISTICS] = TRUE;
1072
pfExists[SQL_API_SQLTABLES] = TRUE;
1074
/* ODBC level 2 functions */
1075
pfExists[SQL_API_SQLBROWSECONNECT] = FALSE;
1076
if (PG_VERSION_GE(conn, 7.4))
1077
pfExists[SQL_API_SQLCOLUMNPRIVILEGES] = FALSE;
1079
pfExists[SQL_API_SQLCOLUMNPRIVILEGES] = FALSE;
1080
pfExists[SQL_API_SQLDATASOURCES] = FALSE; /* only implemented by
1082
if (SUPPORT_DESCRIBE_PARAM(ci))
1083
pfExists[SQL_API_SQLDESCRIBEPARAM] = TRUE;
1085
pfExists[SQL_API_SQLDESCRIBEPARAM] = FALSE; /* not properly
1087
pfExists[SQL_API_SQLDRIVERS] = FALSE; /* only implemented by
1089
pfExists[SQL_API_SQLEXTENDEDFETCH] = TRUE;
1090
pfExists[SQL_API_SQLFOREIGNKEYS] = TRUE;
1091
pfExists[SQL_API_SQLMORERESULTS] = TRUE;
1092
pfExists[SQL_API_SQLNATIVESQL] = TRUE;
1093
pfExists[SQL_API_SQLNUMPARAMS] = TRUE;
1094
pfExists[SQL_API_SQLPARAMOPTIONS] = TRUE;
1095
pfExists[SQL_API_SQLPRIMARYKEYS] = TRUE;
1096
if (PG_VERSION_LT(conn, 6.5))
1097
pfExists[SQL_API_SQLPROCEDURECOLUMNS] = FALSE;
1099
pfExists[SQL_API_SQLPROCEDURECOLUMNS] = TRUE;
1100
if (PG_VERSION_LT(conn, 6.5))
1101
pfExists[SQL_API_SQLPROCEDURES] = FALSE;
1103
pfExists[SQL_API_SQLPROCEDURES] = TRUE;
1104
pfExists[SQL_API_SQLSETPOS] = TRUE;
1105
pfExists[SQL_API_SQLSETSCROLLOPTIONS] = TRUE; /* odbc 1.0 */
1106
pfExists[SQL_API_SQLTABLEPRIVILEGES] = TRUE;
1107
#if (ODBCVER >= 0x0300)
1108
if (0 == ci->updatable_cursors)
1109
pfExists[SQL_API_SQLBULKOPERATIONS] = FALSE;
1111
pfExists[SQL_API_SQLBULKOPERATIONS] = TRUE;
1112
#endif /* ODBCVER */
1117
if (ci->drivers.lie)
1123
#if (ODBCVER < 0x0300)
1124
case SQL_API_SQLALLOCCONNECT:
1127
case SQL_API_SQLALLOCENV:
1130
case SQL_API_SQLALLOCSTMT:
1133
#endif /* ODBCVER */
1134
case SQL_API_SQLBINDCOL:
1137
case SQL_API_SQLCANCEL:
1140
#if (ODBCVER >= 0x0300)
1141
case SQL_API_SQLCOLATTRIBUTE:
1143
case SQL_API_SQLCOLATTRIBUTES:
1144
#endif /* ODBCVER */
1147
case SQL_API_SQLCONNECT:
1150
case SQL_API_SQLDESCRIBECOL:
1152
break; /* partial */
1153
case SQL_API_SQLDISCONNECT:
1156
#if (ODBCVER < 0x0300)
1157
case SQL_API_SQLERROR:
1160
#endif /* ODBCVER */
1161
case SQL_API_SQLEXECDIRECT:
1164
case SQL_API_SQLEXECUTE:
1167
case SQL_API_SQLFETCH:
1170
#if (ODBCVER < 0x0300)
1171
case SQL_API_SQLFREECONNECT:
1174
case SQL_API_SQLFREEENV:
1177
#endif /* ODBCVER */
1178
case SQL_API_SQLFREESTMT:
1181
case SQL_API_SQLGETCURSORNAME:
1184
case SQL_API_SQLNUMRESULTCOLS:
1187
case SQL_API_SQLPREPARE:
1190
case SQL_API_SQLROWCOUNT:
1193
case SQL_API_SQLSETCURSORNAME:
1196
#if (ODBCVER < 0x0300)
1197
case SQL_API_SQLSETPARAM:
1199
break; /* odbc 1.0 */
1200
case SQL_API_SQLTRANSACT:
1203
#endif /* ODBCVER */
1205
/* ODBC level 1 functions */
1206
case SQL_API_SQLBINDPARAMETER:
1209
case SQL_API_SQLCOLUMNS:
1212
case SQL_API_SQLDRIVERCONNECT:
1215
#if (ODBCVER < 0x0300)
1216
case SQL_API_SQLGETCONNECTOPTION:
1218
break; /* partial */
1219
#endif /* ODBCVER */
1220
case SQL_API_SQLGETDATA:
1223
case SQL_API_SQLGETFUNCTIONS:
1226
case SQL_API_SQLGETINFO:
1229
#if (ODBCVER < 0x0300)
1230
case SQL_API_SQLGETSTMTOPTION:
1232
break; /* partial */
1233
#endif /* ODBCVER */
1234
case SQL_API_SQLGETTYPEINFO:
1237
case SQL_API_SQLPARAMDATA:
1240
case SQL_API_SQLPUTDATA:
1243
#if (ODBCVER < 0x0300)
1244
case SQL_API_SQLSETCONNECTOPTION:
1246
break; /* partial */
1247
case SQL_API_SQLSETSTMTOPTION:
1250
#endif /* ODBCVER */
1251
case SQL_API_SQLSPECIALCOLUMNS:
1254
case SQL_API_SQLSTATISTICS:
1257
case SQL_API_SQLTABLES:
1261
/* ODBC level 2 functions */
1262
case SQL_API_SQLBROWSECONNECT:
1265
case SQL_API_SQLCOLUMNPRIVILEGES:
1268
case SQL_API_SQLDATASOURCES:
1270
break; /* only implemented by DM */
1271
case SQL_API_SQLDESCRIBEPARAM:
1272
if (SUPPORT_DESCRIBE_PARAM(ci))
1276
break; /* not properly implemented */
1277
case SQL_API_SQLDRIVERS:
1279
break; /* only implemented by DM */
1280
case SQL_API_SQLEXTENDEDFETCH:
1283
case SQL_API_SQLFOREIGNKEYS:
1286
case SQL_API_SQLMORERESULTS:
1289
case SQL_API_SQLNATIVESQL:
1292
case SQL_API_SQLNUMPARAMS:
1295
#if (ODBCVER < 0x0300)
1296
case SQL_API_SQLPARAMOPTIONS:
1299
#endif /* ODBCVER */
1300
case SQL_API_SQLPRIMARYKEYS:
1303
case SQL_API_SQLPROCEDURECOLUMNS:
1304
if (PG_VERSION_LT(conn, 6.5))
1309
case SQL_API_SQLPROCEDURES:
1310
if (PG_VERSION_LT(conn, 6.5))
1315
case SQL_API_SQLSETPOS:
1318
#if (ODBCVER < 0x0300)
1319
case SQL_API_SQLSETSCROLLOPTIONS:
1321
break; /* odbc 1.0 */
1322
#endif /* ODBCVER */
1323
case SQL_API_SQLTABLEPRIVILEGES:
1326
#if (ODBCVER >= 0x0300)
1327
case SQL_API_SQLBULKOPERATIONS: /* 24 */
1328
case SQL_API_SQLALLOCHANDLE: /* 1001 */
1329
case SQL_API_SQLBINDPARAM: /* 1002 */
1330
case SQL_API_SQLCLOSECURSOR: /* 1003 */
1331
case SQL_API_SQLENDTRAN: /* 1005 */
1332
case SQL_API_SQLFETCHSCROLL: /* 1021 */
1333
case SQL_API_SQLFREEHANDLE: /* 1006 */
1334
case SQL_API_SQLGETCONNECTATTR: /* 1007 */
1335
case SQL_API_SQLGETDESCFIELD: /* 1008 */
1336
case SQL_API_SQLGETDIAGFIELD: /* 1010 */
1337
case SQL_API_SQLGETDIAGREC: /* 1011 */
1338
case SQL_API_SQLGETENVATTR: /* 1012 */
1339
case SQL_API_SQLGETSTMTATTR: /* 1014 */
1340
case SQL_API_SQLSETCONNECTATTR: /* 1016 */
1341
case SQL_API_SQLSETDESCFIELD: /* 1017 */
1342
case SQL_API_SQLSETENVATTR: /* 1019 */
1343
case SQL_API_SQLSETSTMTATTR: /* 1020 */
1346
case SQL_API_SQLGETDESCREC: /* 1009 */
1347
case SQL_API_SQLSETDESCREC: /* 1018 */
1348
case SQL_API_SQLCOPYDESC: /* 1004 */
1351
#endif /* ODBCVER */
1363
simpleCatalogEscape(const char *src, int srclen, int *result_len, const ConnectionClass *conn)
1367
char *dest = NULL, escape_ch = CC_get_escape(conn);
1372
if (!src || srclen == SQL_NULL_DATA)
1374
else if (srclen == SQL_NTS)
1375
srclen = (int) strlen(src);
1378
mylog("simple in=%s(%d)\n", src, srclen);
1379
encoded_str_constr(&encstr, conn->ccsc, src);
1380
dest = malloc(2 * srclen + 1);
1381
for (i = 0, in = src, outlen = 0; i < srclen; i++, in++)
1383
encoded_nextchar(&encstr);
1384
if (ENCODE_STATUS(encstr) != 0)
1386
dest[outlen++] = *in;
1389
if (LITERAL_QUOTE == *in ||
1391
dest[outlen++] = *in;
1392
dest[outlen++] = *in;
1394
dest[outlen] = '\0';
1396
*result_len = outlen;
1397
mylog("simple output=%s(%d)\n", dest, outlen);
1402
* PostgreSQL needs 2 '\\' to escape '_' and '%'.
1405
adjustLikePattern(const char *src, int srclen, char escape_ch, int *result_len, const ConnectionClass *conn)
1409
char *dest = NULL, escape_in_literal = CC_get_escape(conn);
1410
BOOL escape_in = FALSE;
1415
if (!src || srclen == SQL_NULL_DATA)
1417
else if (srclen == SQL_NTS)
1418
srclen = (int) strlen(src);
1419
/* if (srclen <= 0) */
1422
mylog("adjust in=%.*s(%d)\n", srclen, src, srclen);
1423
encoded_str_constr(&encstr, conn->ccsc, src);
1424
dest = malloc(2 * srclen + 1);
1425
for (i = 0, in = src, outlen = 0; i < srclen; i++, in++)
1427
encoded_nextchar(&encstr);
1428
if (ENCODE_STATUS(encstr) != 0)
1430
dest[outlen++] = *in;
1441
if (escape_ch == escape_in_literal)
1442
dest[outlen++] = escape_in_literal;
1443
dest[outlen++] = escape_ch;
1447
if (*in == escape_ch)
1450
if (escape_ch == escape_in_literal)
1451
dest[outlen++] = escape_in_literal; /* insert 1 more LEXER escape */
1456
if (LITERAL_QUOTE == *in)
1457
dest[outlen++] = *in;
1459
dest[outlen++] = *in;
1463
if (escape_ch == escape_in_literal)
1464
dest[outlen++] = escape_in_literal;
1465
dest[outlen++] = escape_ch;
1467
dest[outlen] = '\0';
1469
*result_len = outlen;
1470
mylog("adjust output=%s(%d)\n", dest, outlen);
1474
#define CSTR_SYS_TABLE "SYSTEM TABLE"
1475
#define CSTR_TABLE "TABLE"
1476
#define CSTR_VIEW "VIEW"
1478
CSTR like_op_sp = "like ";
1479
CSTR like_op_ext = "like E";
1480
CSTR eq_op_sp = "= ";
1481
CSTR eq_op_ext = "= E";
1482
static const char *gen_opestr(const char *orig_opestr, const ConnectionClass * conn)
1484
BOOL addE = (0 != CC_get_escape(conn) && PG_VERSION_GE(conn, 8.1));
1486
if (0 == strcmp(orig_opestr, eqop))
1487
return (addE ? eq_op_ext : eq_op_sp);
1488
return (addE ? like_op_ext : like_op_sp);
1492
* If specified schema name == user_name and the current schema is
1493
* 'public', allowed to use the 'public' schema.
1496
allow_public_schema(ConnectionClass *conn, const char *szSchemaName, SQLSMALLINT cbSchemaName)
1498
const char *user = CC_get_username(conn);
1499
size_t userlen = strlen(user);
1501
if (NULL == szSchemaName)
1504
if (SQL_NTS == cbSchemaName)
1505
cbSchemaName = strlen(szSchemaName);
1507
return (cbSchemaName == (SQLSMALLINT) userlen &&
1508
strnicmp(szSchemaName, user, userlen) == 0 &&
1509
stricmp(CC_get_current_schema(conn), pubstr) == 0);
1515
const SQLCHAR FAR * szTableQualifier, /* PV X*/
1516
SQLSMALLINT cbTableQualifier,
1517
const SQLCHAR FAR * szTableOwner, /* PV E*/
1518
SQLSMALLINT cbTableOwner,
1519
const SQLCHAR FAR * szTableName, /* PV E*/
1520
SQLSMALLINT cbTableName,
1521
const SQLCHAR FAR * szTableType,
1522
SQLSMALLINT cbTableType,
1525
CSTR func = "PGAPI_Tables";
1526
StatementClass *stmt = (StatementClass *) hstmt;
1527
StatementClass *tbl_stmt;
1530
HSTMT htbl_stmt = NULL;
1531
RETCODE ret = SQL_ERROR, result;
1533
char *tableType = NULL;
1534
char tables_query[INFO_INQUIRY_LEN];
1535
char table_name[MAX_INFO_STRING],
1536
table_owner[MAX_INFO_STRING],
1537
relkind_or_hasrules[MAX_INFO_STRING];
1538
#ifdef HAVE_STRTOK_R
1540
#endif /* HAVE_STRTOK_R */
1541
ConnectionClass *conn;
1543
char *escCatName = NULL, *escSchemaName = NULL, *escTableName = NULL;
1545
prefixes[MEDIUM_REGISTRY_LEN];
1546
char *table_type[32],
1547
table_types[MAX_INFO_STRING];
1548
char show_system_tables,
1549
show_regular_tables,
1555
SQLSMALLINT internal_asis_type = SQL_C_CHAR, cbSchemaName;
1556
const char *like_or_eq, *op_string;
1557
const char *szSchemaName;
1558
BOOL search_pattern;
1559
BOOL list_cat = FALSE, list_schemas = FALSE, list_table_types = FALSE, list_some = FALSE;
1560
SQLLEN cbRelname, cbRelkind, cbSchName;
1562
mylog("%s: entering...stmt=%p scnm=%p len=%d\n", func, stmt, szTableOwner, cbTableOwner);
1564
if (result = SC_initialize_and_recycle(stmt), SQL_SUCCESS != result)
1567
conn = SC_get_conn(stmt);
1568
ci = &(conn->connInfo);
1570
result = PGAPI_AllocStmt(conn, &htbl_stmt, 0);
1571
if (!SQL_SUCCEEDED(result))
1573
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate statement for PGAPI_Tables result.", func);
1576
tbl_stmt = (StatementClass *) htbl_stmt;
1577
szSchemaName = szTableOwner;
1578
cbSchemaName = cbTableOwner;
1580
#define return DONT_CALL_RETURN_FROM_HERE???
1581
search_pattern = (0 == (flag & PODBC_NOT_SEARCH_PATTERN));
1584
like_or_eq = likeop;
1585
escCatName = adjustLikePattern(szTableQualifier, cbTableQualifier, SEARCH_PATTERN_ESCAPE, NULL, conn);
1586
escTableName = adjustLikePattern(szTableName, cbTableName, SEARCH_PATTERN_ESCAPE, NULL, conn);
1591
escCatName = simpleCatalogEscape(szTableQualifier, cbTableQualifier, NULL, conn);
1592
escTableName = simpleCatalogEscape(szTableName, cbTableName, NULL, conn);
1594
retry_public_schema:
1596
free(escSchemaName);
1598
escSchemaName = adjustLikePattern(szSchemaName, cbSchemaName, SEARCH_PATTERN_ESCAPE, NULL, conn);
1600
escSchemaName = simpleCatalogEscape(szSchemaName, cbSchemaName, NULL, conn);
1602
* Create the query to find out the tables
1604
/* make_string mallocs memory */
1605
tableType = make_string(szTableType, cbTableType, NULL, 0);
1606
#if (ODBCVER >= 0x0300)
1607
if (search_pattern &&
1608
escTableName && '\0' == escTableName[0] &&
1609
escCatName && escSchemaName)
1611
if ('\0' == escSchemaName[0])
1613
if (stricmp(escCatName, SQL_ALL_CATALOGS) == 0)
1615
else if ('\0' == escCatName[0] &&
1616
stricmp(tableType, SQL_ALL_TABLE_TYPES) == 0)
1617
list_table_types = TRUE;
1619
else if ('\0' == escCatName[0] &&
1620
stricmp(escSchemaName, SQL_ALL_SCHEMAS) == 0)
1621
list_schemas = TRUE;
1623
#endif /* ODBCVER */
1624
list_some = (list_cat || list_schemas || list_table_types);
1626
tables_query[0] = '\0';
1628
strncpy_null(tables_query, "select NULL, NULL, NULL", sizeof(tables_query));
1629
else if (list_table_types)
1630
strncpy_null(tables_query, "select NULL, NULL, relkind from (select 'r' as relkind union select 'v') as a", sizeof(tables_query));
1631
else if (list_schemas)
1633
if (conn->schema_support)
1634
strncpy_null(tables_query, "select NULL, nspname, NULL"
1635
" from pg_catalog.pg_namespace n where true", sizeof(tables_query));
1637
strncpy_null(tables_query, "select NULL, NULL as nspname, NULL", sizeof(tables_query));
1639
else if (conn->schema_support)
1641
/* view is represented by its relkind since 7.1 */
1642
strcpy(tables_query, "select relname, nspname, relkind"
1643
" from pg_catalog.pg_class c, pg_catalog.pg_namespace n");
1644
strcat(tables_query, " where relkind in ('r', 'v')");
1646
else if (PG_VERSION_GE(conn, 7.1))
1648
/* view is represented by its relkind since 7.1 */
1649
strcpy(tables_query, "select relname, usename, relkind"
1650
" from pg_class c, pg_user u");
1651
strcat(tables_query, " where relkind in ('r', 'v')");
1655
strcpy(tables_query, "select relname, usename, relhasrules from pg_class c, pg_user u");
1656
strcat(tables_query, " where relkind = 'r'");
1659
op_string = gen_opestr(like_or_eq, conn);
1662
if (conn->schema_support)
1664
schema_strcat1(tables_query, " and nspname %s'%.*s'", op_string, escSchemaName, SQL_NTS, szTableName, cbTableName, conn);
1665
/* strcat(tables_query, " and pg_catalog.pg_table_is_visible(c.oid)"); */
1668
my_strcat1(tables_query, " and usename %s'%.*s'", op_string, escSchemaName, SQL_NTS);
1669
my_strcat1(tables_query, " and relname %s'%.*s'", op_string, escTableName, SQL_NTS);
1672
/* Parse the extra systable prefix */
1673
strcpy(prefixes, ci->drivers.extra_systable_prefixes);
1675
#ifdef HAVE_STRTOK_R
1676
prefix[i] = strtok_r(prefixes, ";", &last);
1678
prefix[i] = strtok(prefixes, ";");
1679
#endif /* HAVE_STRTOK_R */
1680
while (i < sizeof(prefix) && prefix[i])
1681
#ifdef HAVE_STRTOK_R
1682
prefix[++i] = strtok_r(NULL, ";", &last);
1684
prefix[++i] = strtok(NULL, ";");
1685
#endif /* HAVE_STRTOK_R */
1687
/* Parse the desired table types to return */
1688
show_system_tables = FALSE;
1689
show_regular_tables = FALSE;
1695
show_regular_tables = TRUE;
1698
#if (ODBCVER >= 0x0300)
1699
else if (list_some || stricmp(tableType, SQL_ALL_TABLE_TYPES) == 0)
1701
show_regular_tables = TRUE;
1704
#endif /* ODBCVER */
1707
strcpy(table_types, tableType);
1709
#ifdef HAVE_STRTOK_R
1710
table_type[i] = strtok_r(table_types, ",", &last);
1712
table_type[i] = strtok(table_types, ",");
1713
#endif /* HAVE_STRTOK_R */
1714
while (i < sizeof(table_type) && table_type[i])
1715
#ifdef HAVE_STRTOK_R
1716
table_type[++i] = strtok_r(NULL, ",", &last);
1718
table_type[++i] = strtok(NULL, ",");
1719
#endif /* HAVE_STRTOK_R */
1721
/* Check for desired table types to return */
1723
while (table_type[i])
1725
char *typestr = table_type[i];
1727
while (isspace(*typestr))
1729
if (*typestr == '\'')
1731
if (strnicmp(typestr, CSTR_SYS_TABLE, strlen(CSTR_SYS_TABLE)) == 0)
1732
show_system_tables = TRUE;
1733
else if (strnicmp(typestr, CSTR_TABLE, strlen(CSTR_TABLE)) == 0)
1734
show_regular_tables = TRUE;
1735
else if (strnicmp(typestr, CSTR_VIEW, strlen(CSTR_VIEW)) == 0)
1742
* If not interested in SYSTEM TABLES then filter them out to save
1743
* some time on the query. If treating system tables as regular
1744
* tables, then dont filter either.
1746
if ((list_schemas || !list_some) && !atoi(ci->show_system_tables) && !show_system_tables)
1748
if (conn->schema_support)
1749
strcat(tables_query, " and nspname not in ('pg_catalog', 'information_schema', 'pg_toast', 'pg_temp_1')");
1750
else if (!list_schemas)
1752
strcat(tables_query, " and relname !~ '^" POSTGRES_SYS_PREFIX);
1754
/* Also filter out user-defined system table types */
1755
for (i = 0; prefix[i]; i++)
1757
strcat(tables_query, "|^");
1758
strcat(tables_query, prefix[i]);
1760
strcat(tables_query, "'");
1766
if (CC_accessible_only(conn))
1767
strcat(tables_query, " and has_table_privilege(c.oid, 'select')");
1770
strcat(tables_query, " order by nspname");
1773
else if (conn->schema_support)
1774
strcat(tables_query, " and n.oid = relnamespace order by nspname, relname");
1778
if (PG_VERSION_LT(conn, 7.1))
1779
/* filter out large objects in older versions */
1780
strcat(tables_query, " and relname !~ '^xinv[0-9]+'");
1781
strcat(tables_query, " and usesysid = relowner order by relname");
1784
result = PGAPI_ExecDirect(htbl_stmt, tables_query, SQL_NTS, 0);
1785
if (!SQL_SUCCEEDED(result))
1787
SC_full_error_copy(stmt, htbl_stmt, FALSE);
1792
if (conn->schema_support &&
1793
(res = SC_get_Result(tbl_stmt)) &&
1794
0 == QR_get_num_total_tuples(res))
1796
if (allow_public_schema(conn, szSchemaName, cbSchemaName))
1798
szSchemaName = pubstr;
1799
cbSchemaName = SQL_NTS;
1800
goto retry_public_schema;
1803
#ifdef UNICODE_SUPPORT
1804
if (CC_is_in_unicode_driver(conn))
1805
internal_asis_type = INTERNAL_ASIS_TYPE;
1806
#endif /* UNICODE_SUPPORT */
1807
result = PGAPI_BindCol(htbl_stmt, 1, internal_asis_type,
1808
table_name, MAX_INFO_STRING, &cbRelname);
1809
if (!SQL_SUCCEEDED(result))
1811
SC_error_copy(stmt, tbl_stmt, TRUE);
1815
result = PGAPI_BindCol(htbl_stmt, 2, internal_asis_type,
1816
table_owner, MAX_INFO_STRING, &cbSchName);
1817
if (!SQL_SUCCEEDED(result))
1819
SC_error_copy(stmt, tbl_stmt, TRUE);
1822
result = PGAPI_BindCol(htbl_stmt, 3, internal_asis_type,
1823
relkind_or_hasrules, MAX_INFO_STRING, &cbRelkind);
1824
if (!SQL_SUCCEEDED(result))
1826
SC_error_copy(stmt, tbl_stmt, TRUE);
1830
if (res = QR_Constructor(), !res)
1832
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate memory for PGAPI_Tables result.", func);
1835
SC_set_Result(stmt, res);
1837
/* the binding structure for a statement is not set up until */
1840
* a statement is actually executed, so we'll have to do this
1843
result_cols = NUM_OF_TABLES_FIELDS;
1844
extend_column_bindings(SC_get_ARDF(stmt), result_cols);
1846
stmt->catalog_result = TRUE;
1847
/* set the field names */
1848
QR_set_num_fields(res, result_cols);
1849
QR_set_field_info_v(res, TABLES_CATALOG_NAME, "TABLE_QUALIFIER", PG_TYPE_VARCHAR, MAX_INFO_STRING);
1850
QR_set_field_info_v(res, TABLES_SCHEMA_NAME, "TABLE_OWNER", PG_TYPE_VARCHAR, MAX_INFO_STRING);
1851
QR_set_field_info_v(res, TABLES_TABLE_NAME, "TABLE_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
1852
QR_set_field_info_v(res, TABLES_TABLE_TYPE, "TABLE_TYPE", PG_TYPE_VARCHAR, MAX_INFO_STRING);
1853
QR_set_field_info_v(res, TABLES_REMARKS, "REMARKS", PG_TYPE_VARCHAR, INFO_VARCHAR_SIZE);
1855
/* add the tuples */
1856
table_name[0] = '\0';
1857
table_owner[0] = '\0';
1858
result = PGAPI_Fetch(htbl_stmt);
1859
while (SQL_SUCCEEDED(result))
1862
* Determine if this table name is a system table. If treating
1863
* system tables as regular tables, then no need to do this test.
1866
if (!atoi(ci->show_system_tables))
1868
if (conn->schema_support)
1870
if (stricmp(table_owner, "pg_catalog") == 0 ||
1871
stricmp(table_owner, "pg_toast") == 0 ||
1872
strnicmp(table_owner, "pg_temp_", 8) == 0 ||
1873
stricmp(table_owner, "information_schema") == 0)
1876
else if (strncmp(table_name, POSTGRES_SYS_PREFIX, strlen(POSTGRES_SYS_PREFIX)) == 0)
1881
/* Check extra system table prefixes */
1885
mylog("table_name='%s', prefix[%d]='%s'\n", table_name, i, prefix[i]);
1886
if (strncmp(table_name, prefix[i], strlen(prefix[i])) == 0)
1896
/* Determine if the table name is a view */
1897
if (PG_VERSION_GE(conn, 7.1))
1898
/* view is represented by its relkind since 7.1 */
1899
view = (relkind_or_hasrules[0] == 'v');
1901
view = (relkind_or_hasrules[0] == '1');
1903
/* It must be a regular table */
1904
regular_table = (!systable && !view);
1907
/* Include the row in the result set if meets all criteria */
1910
* NOTE: Unsupported table types (i.e., LOCAL TEMPORARY, ALIAS,
1911
* etc) will return nothing
1913
if ((systable && show_system_tables) ||
1914
(view && show_views) ||
1915
(regular_table && show_regular_tables))
1917
tuple = QR_AddNew(res);
1919
if (list_cat || !list_some)
1920
set_tuplefield_string(&tuple[TABLES_CATALOG_NAME], CurrCat(conn));
1922
set_tuplefield_null(&tuple[TABLES_CATALOG_NAME]);
1925
* I have to hide the table owner from Access, otherwise it
1926
* insists on referring to the table as 'owner.table'. (this
1927
* is valid according to the ODBC SQL grammar, but Postgres
1928
* won't support it.)
1930
* set_tuplefield_string(&tuple[TABLES_SCHEMA_NAME], table_owner);
1933
mylog("%s: table_name = '%s'\n", func, table_name);
1935
if (list_schemas || (conn->schema_support && !list_some))
1936
set_tuplefield_string(&tuple[TABLES_SCHEMA_NAME], GET_SCHEMA_NAME(table_owner));
1938
set_tuplefield_null(&tuple[TABLES_SCHEMA_NAME]);
1940
set_tuplefield_null(&tuple[TABLES_TABLE_NAME]);
1942
set_tuplefield_string(&tuple[TABLES_TABLE_NAME], table_name);
1943
if (list_table_types || !list_some)
1944
set_tuplefield_string(&tuple[TABLES_TABLE_TYPE], systable ? "SYSTEM TABLE" : (view ? "VIEW" : "TABLE"));
1946
set_tuplefield_null(&tuple[TABLES_TABLE_TYPE]);
1947
set_tuplefield_string(&tuple[TABLES_REMARKS], NULL_STRING);
1948
/*** set_tuplefield_string(&tuple[TABLES_REMARKS], "TABLE"); ***/
1950
result = PGAPI_Fetch(htbl_stmt);
1952
if (result != SQL_NO_DATA_FOUND)
1954
SC_full_error_copy(stmt, htbl_stmt, FALSE);
1962
* also, things need to think that this statement is finished so the
1963
* results can be retrieved.
1965
stmt->status = STMT_FINISHED;
1970
free(escSchemaName);
1975
/* set up the current tuple pointer for SQLFetch */
1976
stmt->currTuple = -1;
1977
SC_set_rowset_start(stmt, -1, FALSE);
1978
SC_set_current_col(stmt, -1);
1981
PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
1984
ret = DiscardStatementSvp(stmt, ret, FALSE);
1985
mylog("%s: EXIT, stmt=%p, ret=%d\n", func, stmt, ret);
1992
const SQLCHAR FAR * szTableQualifier, /* OA X*/
1993
SQLSMALLINT cbTableQualifier,
1994
const SQLCHAR FAR * szTableOwner, /* PV E*/
1995
SQLSMALLINT cbTableOwner,
1996
const SQLCHAR FAR * szTableName, /* PV E*/
1997
SQLSMALLINT cbTableName,
1998
const SQLCHAR FAR * szColumnName, /* PV E*/
1999
SQLSMALLINT cbColumnName,
2004
CSTR func = "PGAPI_Columns";
2005
StatementClass *stmt = (StatementClass *) hstmt;
2008
HSTMT hcol_stmt = NULL;
2009
StatementClass *col_stmt;
2010
char columns_query[INFO_INQUIRY_LEN];
2012
char table_owner[MAX_INFO_STRING],
2013
table_name[MAX_INFO_STRING],
2014
field_name[MAX_INFO_STRING],
2015
field_type_name[MAX_INFO_STRING];
2016
Int2 field_number, sqltype, concise_type,
2021
OID field_type, the_type, greloid, basetype;
2023
Int2 decimal_digits;
2024
Int4 field_length, column_size;
2025
char useStaticPrecision, useStaticScale;
2026
#endif /* USE_OLD_IMPL */
2027
char not_null[MAX_INFO_STRING],
2028
relhasrules[MAX_INFO_STRING], relkind[8];
2029
char *escSchemaName = NULL, *escTableName = NULL, *escColumnName = NULL;
2030
BOOL search_pattern = TRUE, search_by_ids, relisaview;
2032
ConnectionClass *conn;
2033
SQLSMALLINT internal_asis_type = SQL_C_CHAR, cbSchemaName;
2034
const char *like_or_eq = likeop, *op_string;
2035
const char *szSchemaName;
2036
BOOL setIdentity = FALSE;
2038
mylog("%s: entering...stmt=%p scnm=%p len=%d\n", func, stmt, szTableOwner, cbTableOwner);
2040
if (result = SC_initialize_and_recycle(stmt), SQL_SUCCESS != result)
2043
conn = SC_get_conn(stmt);
2044
ci = &(conn->connInfo);
2045
#ifdef UNICODE_SUPPORT
2046
if (CC_is_in_unicode_driver(conn))
2047
internal_asis_type = INTERNAL_ASIS_TYPE;
2048
#endif /* UNICODE_SUPPORT */
2050
#define return DONT_CALL_RETURN_FROM_HERE???
2051
search_by_ids = ((flag & PODBC_SEARCH_BY_IDS) != 0);
2054
szSchemaName = NULL;
2055
cbSchemaName = SQL_NULL_DATA;
2059
szSchemaName = szTableOwner;
2060
cbSchemaName = cbTableOwner;
2064
* TableName or ColumnName is ordinarily an pattern value,
2066
search_pattern = ((flag & PODBC_NOT_SEARCH_PATTERN) == 0);
2069
like_or_eq = likeop;
2070
escTableName = adjustLikePattern(szTableName, cbTableName, SEARCH_PATTERN_ESCAPE, NULL, conn);
2071
escColumnName = adjustLikePattern(szColumnName, cbColumnName, SEARCH_PATTERN_ESCAPE, NULL, conn);
2076
escTableName = simpleCatalogEscape(szTableName, cbTableName, NULL, conn);
2077
escColumnName = simpleCatalogEscape(szColumnName, cbColumnName, NULL, conn);
2080
retry_public_schema:
2084
free(escSchemaName);
2086
escSchemaName = adjustLikePattern(szSchemaName, cbSchemaName, SEARCH_PATTERN_ESCAPE, NULL, conn);
2088
escSchemaName = simpleCatalogEscape(szSchemaName, cbSchemaName, NULL, conn);
2091
* Create the query to find out the columns (Note: pre 6.3 did not
2092
* have the atttypmod field)
2094
op_string = gen_opestr(like_or_eq, conn);
2095
if (conn->schema_support)
2097
snprintf(columns_query, sizeof(columns_query),
2098
"select n.nspname, c.relname, a.attname, a.atttypid"
2099
", t.typname, a.attnum, a.attlen, a.atttypmod, a.attnotnull"
2100
", c.relhasrules, c.relkind, c.oid, %s, %s, %s"
2101
" from (((pg_catalog.pg_class c"
2102
" inner join pg_catalog.pg_namespace n on n.oid = c.relnamespace",
2103
PG_VERSION_GE(conn, 7.4) ?
2104
"pg_get_expr(d.adbin, d.adrelid)" : "d.adsrc",
2105
PG_VERSION_GE(conn, 7.4) ?
2106
"case t.typtype when 'd' then t.typbasetype else 0 end, t.typtypmod"
2108
PG_VERSION_GE(conn, 7.2) ? "c.relhasoids" : "1"
2111
snprintf_add(columns_query, sizeof(columns_query), " and c.oid = %u", reloid);
2115
snprintf_add(columns_query, sizeof(columns_query), " and c.relname %s'%s'", op_string, escTableName);
2116
schema_strcat1(columns_query, " and n.nspname %s'%.*s'", op_string, escSchemaName, SQL_NTS, szTableName, cbTableName, conn);
2118
strcat(columns_query, ") inner join pg_catalog.pg_attribute a"
2119
" on (not a.attisdropped)");
2120
if (0 == attnum && (NULL == escColumnName || like_or_eq != eqop))
2121
strcat(columns_query, " and a.attnum > 0");
2125
snprintf_add(columns_query, sizeof(columns_query), " and a.attnum = %d", attnum);
2127
else if (escColumnName)
2128
snprintf_add(columns_query, sizeof(columns_query), " and a.attname %s'%s'", op_string, escColumnName);
2129
strcat(columns_query,
2130
" and a.attrelid = c.oid) inner join pg_catalog.pg_type t"
2131
" on t.oid = a.atttypid) left outer join pg_attrdef d"
2132
" on a.atthasdef and d.adrelid = a.attrelid and d.adnum = a.attnum");
2133
strcat(columns_query, " order by n.nspname, c.relname, attnum");
2137
snprintf(columns_query, sizeof(columns_query),
2138
"select u.usename, c.relname, a.attname, a.atttypid"
2139
", t.typname, a.attnum, a.attlen, %s, a.attnotnull"
2140
", c.relhasrules, c.relkind, c.oid, NULL, 0, -1 from"
2141
" pg_user u, pg_class c, pg_attribute a, pg_type t where"
2142
" u.usesysid = c.relowner and c.oid= a.attrelid"
2143
" and a.atttypid = t.oid and (a.attnum > 0)",
2144
PG_VERSION_LE(conn, 6.2) ? "a.attlen" : "a.atttypmod");
2146
snprintf_add(columns_query, sizeof(columns_query), " and c.relname %s'%s'", op_string, escTableName);
2147
my_strcat1(columns_query, " and u.usename %s'%.*s'", op_string, escSchemaName, SQL_NTS);
2149
snprintf_add(columns_query, sizeof(columns_query), " and a.attname %s'%s'", op_string, escColumnName);
2150
strcat(columns_query, " order by c.relname, attnum");
2153
result = PGAPI_AllocStmt(conn, &hcol_stmt, 0);
2154
if (!SQL_SUCCEEDED(result))
2156
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate statement for PGAPI_Columns result.", func);
2160
col_stmt = (StatementClass *) hcol_stmt;
2162
mylog("%s: hcol_stmt = %p, col_stmt = %p\n", func, hcol_stmt, col_stmt);
2164
col_stmt->internal = TRUE;
2165
result = PGAPI_ExecDirect(hcol_stmt, columns_query, SQL_NTS, 0);
2166
if (!SQL_SUCCEEDED(result))
2168
SC_full_error_copy(stmt, col_stmt, FALSE);
2173
if (conn->schema_support &&
2174
(flag & PODBC_SEARCH_PUBLIC_SCHEMA) != 0 &&
2175
(res = SC_get_Result(col_stmt)) &&
2176
0 == QR_get_num_total_tuples(res))
2178
if (!search_by_ids &&
2179
allow_public_schema(conn, szSchemaName, cbSchemaName))
2181
PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
2183
szSchemaName = pubstr;
2184
cbSchemaName = SQL_NTS;
2185
goto retry_public_schema;
2189
result = PGAPI_BindCol(hcol_stmt, 1, internal_asis_type,
2190
table_owner, MAX_INFO_STRING, NULL);
2191
if (!SQL_SUCCEEDED(result))
2193
SC_error_copy(stmt, col_stmt, TRUE);
2197
result = PGAPI_BindCol(hcol_stmt, 2, internal_asis_type,
2198
table_name, MAX_INFO_STRING, NULL);
2199
if (!SQL_SUCCEEDED(result))
2201
SC_error_copy(stmt, col_stmt, TRUE);
2205
result = PGAPI_BindCol(hcol_stmt, 3, internal_asis_type,
2206
field_name, MAX_INFO_STRING, NULL);
2207
if (!SQL_SUCCEEDED(result))
2209
SC_error_copy(stmt, col_stmt, TRUE);
2213
result = PGAPI_BindCol(hcol_stmt, 4, SQL_C_ULONG,
2214
&field_type, 4, NULL);
2215
if (!SQL_SUCCEEDED(result))
2217
SC_error_copy(stmt, col_stmt, TRUE);
2221
result = PGAPI_BindCol(hcol_stmt, 5, internal_asis_type,
2222
field_type_name, MAX_INFO_STRING, NULL);
2223
if (!SQL_SUCCEEDED(result))
2225
SC_error_copy(stmt, col_stmt, TRUE);
2229
result = PGAPI_BindCol(hcol_stmt, 6, SQL_C_SHORT,
2230
&field_number, MAX_INFO_STRING, NULL);
2231
if (!SQL_SUCCEEDED(result))
2233
SC_error_copy(stmt, col_stmt, TRUE);
2238
result = PGAPI_BindCol(hcol_stmt, 7, SQL_C_LONG,
2239
&field_length, MAX_INFO_STRING, NULL);
2240
if (!SQL_SUCCEEDED(result))
2242
SC_error_copy(stmt, col_stmt, TRUE);
2245
#endif /* NOT_USED */
2247
result = PGAPI_BindCol(hcol_stmt, 8, SQL_C_LONG,
2248
&mod_length, MAX_INFO_STRING, NULL);
2249
if (!SQL_SUCCEEDED(result))
2251
SC_error_copy(stmt, col_stmt, TRUE);
2255
result = PGAPI_BindCol(hcol_stmt, 9, internal_asis_type,
2256
not_null, MAX_INFO_STRING, NULL);
2257
if (!SQL_SUCCEEDED(result))
2259
SC_error_copy(stmt, col_stmt, TRUE);
2263
result = PGAPI_BindCol(hcol_stmt, 10, internal_asis_type,
2264
relhasrules, MAX_INFO_STRING, NULL);
2265
if (!SQL_SUCCEEDED(result))
2267
SC_error_copy(stmt, col_stmt, TRUE);
2271
result = PGAPI_BindCol(hcol_stmt, 11, internal_asis_type,
2272
relkind, sizeof(relkind), NULL);
2273
if (!SQL_SUCCEEDED(result))
2275
SC_error_copy(stmt, col_stmt, TRUE);
2279
result = PGAPI_BindCol(hcol_stmt, 12, SQL_C_LONG,
2280
&greloid, sizeof(greloid), NULL);
2281
if (!SQL_SUCCEEDED(result))
2283
SC_error_copy(stmt, col_stmt, TRUE);
2287
result = PGAPI_BindCol(hcol_stmt, 14, SQL_C_ULONG,
2288
&basetype, sizeof(basetype), NULL);
2289
if (!SQL_SUCCEEDED(result))
2291
SC_error_copy(stmt, col_stmt, TRUE);
2295
result = PGAPI_BindCol(hcol_stmt, 15, SQL_C_LONG,
2296
&typmod, sizeof(typmod), NULL);
2297
if (!SQL_SUCCEEDED(result))
2299
SC_error_copy(stmt, col_stmt, TRUE);
2303
result = PGAPI_BindCol(hcol_stmt, 16, SQL_C_LONG,
2304
&relhasoids, sizeof(relhasoids), NULL);
2305
if (!SQL_SUCCEEDED(result))
2307
SC_error_copy(stmt, col_stmt, TRUE);
2311
if (res = QR_Constructor(), !res)
2313
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate memory for PGAPI_Columns result.", func);
2316
SC_set_Result(stmt, res);
2318
/* the binding structure for a statement is not set up until */
2321
* a statement is actually executed, so we'll have to do this
2324
result_cols = NUM_OF_COLUMNS_FIELDS;
2325
extend_column_bindings(SC_get_ARDF(stmt), result_cols);
2328
* Setting catalog_result here affects the behavior of
2329
* pgtype_xxx() functions. So set it later.
2330
* stmt->catalog_result = TRUE;
2332
/* set the field names */
2333
QR_set_num_fields(res, result_cols);
2334
QR_set_field_info_v(res, COLUMNS_CATALOG_NAME, "TABLE_QUALIFIER", PG_TYPE_VARCHAR, MAX_INFO_STRING);
2335
QR_set_field_info_v(res, COLUMNS_SCHEMA_NAME, "TABLE_OWNER", PG_TYPE_VARCHAR, MAX_INFO_STRING);
2336
QR_set_field_info_v(res, COLUMNS_TABLE_NAME, "TABLE_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
2337
QR_set_field_info_v(res, COLUMNS_COLUMN_NAME, "COLUMN_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
2338
QR_set_field_info_v(res, COLUMNS_DATA_TYPE, "DATA_TYPE", PG_TYPE_INT2, 2);
2339
QR_set_field_info_v(res, COLUMNS_TYPE_NAME, "TYPE_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
2340
QR_set_field_info_v(res, COLUMNS_PRECISION, "PRECISION", PG_TYPE_INT4, 4); /* COLUMN_SIZE */
2341
QR_set_field_info_v(res, COLUMNS_LENGTH, "LENGTH", PG_TYPE_INT4, 4); /* BUFFER_LENGTH */
2342
QR_set_field_info_v(res, COLUMNS_SCALE, "SCALE", PG_TYPE_INT2, 2); /* DECIMAL_DIGITS ***/
2343
QR_set_field_info_v(res, COLUMNS_RADIX, "RADIX", PG_TYPE_INT2, 2);
2344
QR_set_field_info_v(res, COLUMNS_NULLABLE, "NULLABLE", PG_TYPE_INT2, 2);
2345
QR_set_field_info_v(res, COLUMNS_REMARKS, "REMARKS", PG_TYPE_VARCHAR, INFO_VARCHAR_SIZE);
2347
#if (ODBCVER >= 0x0300)
2348
QR_set_field_info_v(res, COLUMNS_COLUMN_DEF, "COLUMN_DEF", PG_TYPE_VARCHAR, INFO_VARCHAR_SIZE);
2349
QR_set_field_info_v(res, COLUMNS_SQL_DATA_TYPE, "SQL_DATA_TYPE", PG_TYPE_INT2, 2);
2350
QR_set_field_info_v(res, COLUMNS_SQL_DATETIME_SUB, "SQL_DATETIME_SUB", PG_TYPE_INT2, 2);
2351
QR_set_field_info_v(res, COLUMNS_CHAR_OCTET_LENGTH, "CHAR_OCTET_LENGTH", PG_TYPE_INT4, 4);
2352
QR_set_field_info_v(res, COLUMNS_ORDINAL_POSITION, "ORDINAL_POSITION", PG_TYPE_INT4, 4);
2353
QR_set_field_info_v(res, COLUMNS_IS_NULLABLE, "IS_NULLABLE", PG_TYPE_VARCHAR, INFO_VARCHAR_SIZE);
2354
#endif /* ODBCVER */
2355
/* User defined fields */
2356
QR_set_field_info_v(res, COLUMNS_DISPLAY_SIZE, "DISPLAY_SIZE", PG_TYPE_INT4, 4);
2357
QR_set_field_info_v(res, COLUMNS_FIELD_TYPE, "FIELD_TYPE", PG_TYPE_INT4, 4);
2358
QR_set_field_info_v(res, COLUMNS_AUTO_INCREMENT, "AUTO_INCREMENT", PG_TYPE_INT4, 4);
2359
QR_set_field_info_v(res, COLUMNS_PHYSICAL_NUMBER, "PHYSICAL NUMBER", PG_TYPE_INT2, 2);
2360
QR_set_field_info_v(res, COLUMNS_TABLE_OID, "TABLE OID", PG_TYPE_OID, 4);
2361
QR_set_field_info_v(res, COLUMNS_BASE_TYPEID, "BASE TYPEID", PG_TYPE_OID, 4);
2362
QR_set_field_info_v(res, COLUMNS_ATTTYPMOD, "TYPMOD", PG_TYPE_INT4, 4);
2365
result = PGAPI_Fetch(hcol_stmt);
2368
* Only show oid if option AND there are other columns AND it's not
2369
* being called by SQLStatistics . Always show OID if it's a system
2373
if (PG_VERSION_GE(conn, 7.1))
2374
relisaview = (relkind[0] == 'v');
2376
relisaview = (relhasrules[0] == '1');
2377
if (result != SQL_ERROR && !stmt->internal)
2381
(atoi(ci->show_oid_column) ||
2382
strncmp(table_name, POSTGRES_SYS_PREFIX, strlen(POSTGRES_SYS_PREFIX)) == 0) &&
2383
(NULL == escColumnName ||
2384
0 == strcmp(escColumnName, OID_NAME)))
2386
/* For OID fields */
2387
the_type = PG_TYPE_OID;
2388
tuple = QR_AddNew(res);
2389
set_tuplefield_string(&tuple[COLUMNS_CATALOG_NAME], CurrCat(conn));
2390
/* see note in SQLTables() */
2391
if (conn->schema_support)
2392
set_tuplefield_string(&tuple[COLUMNS_SCHEMA_NAME], GET_SCHEMA_NAME(table_owner));
2394
set_tuplefield_string(&tuple[COLUMNS_SCHEMA_NAME], NULL_STRING);
2395
set_tuplefield_string(&tuple[COLUMNS_TABLE_NAME], table_name);
2396
set_tuplefield_string(&tuple[COLUMNS_COLUMN_NAME], OID_NAME);
2397
sqltype = pgtype_to_concise_type(stmt, the_type, PG_STATIC);
2398
set_tuplefield_int2(&tuple[COLUMNS_DATA_TYPE], sqltype);
2399
if (CC_fake_mss(conn))
2401
set_tuplefield_string(&tuple[COLUMNS_TYPE_NAME], "OID identity");
2405
set_tuplefield_string(&tuple[COLUMNS_TYPE_NAME], "OID");
2407
set_tuplefield_int4(&tuple[COLUMNS_PRECISION], pgtype_column_size(stmt, the_type, PG_STATIC, UNKNOWNS_AS_DEFAULT));
2408
set_tuplefield_int4(&tuple[COLUMNS_LENGTH], pgtype_buffer_length(stmt, the_type, PG_STATIC, UNKNOWNS_AS_DEFAULT));
2409
set_nullfield_int2(&tuple[COLUMNS_SCALE], pgtype_decimal_digits(stmt, the_type, PG_STATIC));
2410
set_nullfield_int2(&tuple[COLUMNS_RADIX], pgtype_radix(conn, the_type));
2411
set_tuplefield_int2(&tuple[COLUMNS_NULLABLE], SQL_NO_NULLS);
2412
set_tuplefield_string(&tuple[COLUMNS_REMARKS], NULL_STRING);
2414
#if (ODBCVER >= 0x0300)
2415
set_tuplefield_null(&tuple[COLUMNS_COLUMN_DEF]);
2416
set_tuplefield_int2(&tuple[COLUMNS_SQL_DATA_TYPE], sqltype);
2417
set_tuplefield_null(&tuple[COLUMNS_SQL_DATETIME_SUB]);
2418
set_tuplefield_null(&tuple[COLUMNS_CHAR_OCTET_LENGTH]);
2419
set_tuplefield_int4(&tuple[COLUMNS_ORDINAL_POSITION], ordinal);
2420
set_tuplefield_string(&tuple[COLUMNS_IS_NULLABLE], "No");
2421
#endif /* ODBCVER */
2422
set_tuplefield_int4(&tuple[COLUMNS_DISPLAY_SIZE], pgtype_display_size(stmt, the_type, PG_STATIC, UNKNOWNS_AS_DEFAULT));
2423
set_tuplefield_int4(&tuple[COLUMNS_FIELD_TYPE], the_type);
2424
set_tuplefield_int4(&tuple[COLUMNS_AUTO_INCREMENT], TRUE);
2425
set_tuplefield_int2(&tuple[COLUMNS_PHYSICAL_NUMBER], OID_ATTNUM);
2426
set_tuplefield_int4(&tuple[COLUMNS_TABLE_OID], greloid);
2427
set_tuplefield_int4(&tuple[COLUMNS_BASE_TYPEID], 0);
2428
set_tuplefield_int4(&tuple[COLUMNS_ATTTYPMOD], -1);
2433
while (SQL_SUCCEEDED(result))
2440
PGAPI_SetPos(hcol_stmt, 1, SQL_POSITION, 0);
2441
PGAPI_GetData(hcol_stmt, 13, internal_asis_type, NULL, 0, &len_needed);
2444
mylog("len_needed=%d\n", len_needed);
2445
attdef = malloc(len_needed + 1);
2446
PGAPI_GetData(hcol_stmt, 13, internal_asis_type, attdef, len_needed + 1, &len_needed);
2447
mylog(" and the data=%s\n", attdef);
2449
tuple = QR_AddNew(res);
2451
sqltype = SQL_TYPE_NULL; /* unspecified */
2452
set_tuplefield_string(&tuple[COLUMNS_CATALOG_NAME], CurrCat(conn));
2453
/* see note in SQLTables() */
2454
if (conn->schema_support)
2455
set_tuplefield_string(&tuple[COLUMNS_SCHEMA_NAME], GET_SCHEMA_NAME(table_owner));
2457
set_tuplefield_string(&tuple[COLUMNS_SCHEMA_NAME], NULL_STRING);
2458
set_tuplefield_string(&tuple[COLUMNS_TABLE_NAME], table_name);
2459
set_tuplefield_string(&tuple[COLUMNS_COLUMN_NAME], field_name);
2460
auto_unique = SQL_FALSE;
2461
if (field_type = pg_true_type(conn, field_type, basetype), field_type == basetype)
2462
mod_length = typmod;
2466
if (0 != atoi(ci->fake_oid_index))
2468
auto_unique = SQL_TRUE;
2469
set_tuplefield_string(&tuple[COLUMNS_TYPE_NAME], "identity");
2474
if (attdef && strnicmp(attdef, "nextval(", 8) == 0 &&
2477
auto_unique = SQL_TRUE;
2483
snprintf(tmp, sizeof(tmp), "%s identity", field_type_name);
2484
set_tuplefield_string(&tuple[COLUMNS_TYPE_NAME], tmp);
2489
set_tuplefield_string(&tuple[COLUMNS_TYPE_NAME], field_type_name);
2494
* Some Notes about Postgres Data Types:
2496
* VARCHAR - the length is stored in the pg_attribute.atttypmod field
2497
* BPCHAR - the length is also stored as varchar is
2499
* NUMERIC - the decimal_digits is stored in atttypmod as follows:
2501
* column_size =((atttypmod - VARHDRSZ) >> 16) & 0xffff
2502
* decimal_digits = (atttypmod - VARHDRSZ) & 0xffff
2506
qlog("%s: table='%s',field_name='%s',type=%d,name='%s'\n",
2507
func, table_name, field_name, field_type, field_type_name);
2510
useStaticPrecision = TRUE;
2511
useStaticScale = TRUE;
2513
if (field_type == PG_TYPE_NUMERIC)
2515
if (mod_length >= 4)
2516
mod_length -= 4; /* the length is in atttypmod - 4 */
2518
if (mod_length >= 0)
2520
useStaticPrecision = FALSE;
2521
useStaticScale = FALSE;
2523
column_size = (mod_length >> 16) & 0xffff;
2524
decimal_digits = mod_length & 0xffff;
2526
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);
2528
set_tuplefield_int4(&tuple[COLUMNS_PRECISION], column_size);
2529
set_tuplefield_int4(&tuple[COLUMNS_LENGTH], column_size + 2); /* sign+dec.point */
2530
set_nullfield_int2(&tuple[COLUMNS_SCALE], decimal_digits);
2531
#if (ODBCVER >= 0x0300)
2532
set_tuplefield_null(&tuple[COLUMNS_CHAR_OCTET_LENGTH]);
2533
#endif /* ODBCVER */
2534
set_tuplefield_int4(&tuple[COLUMNS_DISPLAY_SIZE], column_size + 2); /* sign+dec.point */
2537
else if ((field_type == PG_TYPE_DATETIME) ||
2538
(field_type == PG_TYPE_TIMESTAMP_NO_TMZONE))
2540
if (PG_VERSION_GE(conn, 7.2))
2542
useStaticScale = FALSE;
2544
set_nullfield_int2(&tuple[COLUMNS_SCALE], (Int2) mod_length);
2548
if ((field_type == PG_TYPE_VARCHAR) ||
2549
(field_type == PG_TYPE_BPCHAR))
2551
useStaticPrecision = FALSE;
2553
if (mod_length >= 4)
2554
mod_length -= 4; /* the length is in atttypmod - 4 */
2556
/* if (mod_length > ci->drivers.max_varchar_size || mod_length <= 0) */
2557
if (mod_length <= 0)
2558
mod_length = ci->drivers.max_varchar_size;
2559
#ifdef __MS_REPORTS_ANSI_CHAR__
2560
if (mod_length > ci->drivers.max_varchar_size)
2561
sqltype = SQL_LONGVARCHAR;
2563
sqltype = (field_type == PG_TYPE_BPCHAR) ? SQL_CHAR : SQL_VARCHAR;
2565
if (mod_length > ci->drivers.max_varchar_size)
2566
sqltype = (ALLOW_WCHAR(conn) ? SQL_WLONGVARCHAR : SQL_LONGVARCHAR);
2568
sqltype = (field_type == PG_TYPE_BPCHAR) ? (ALLOW_WCHAR(conn) ? SQL_WCHAR : SQL_CHAR) : (ALLOW_WCHAR(conn) ? SQL_WVARCHAR : SQL_VARCHAR);
2569
#endif /* __MS_LOVES_REPORTS_CHAR__ */
2571
mylog("%s: field type is VARCHAR,BPCHAR: field_type = %d, mod_length = %d\n", func, field_type, mod_length);
2573
set_tuplefield_int4(&tuple[COLUMNS_PRECISION], mod_length);
2574
field_length = mod_length;
2575
#ifdef UNICODE_SUPPORT
2576
if (0 < field_length && ALLOW_WCHAR(conn))
2577
field_length *= WCLEN;
2578
#endif /* UNICODE_SUPPORT */
2579
set_tuplefield_int4(&tuple[COLUMNS_LENGTH], field_length);
2580
#if (ODBCVER >= 0x0300)
2581
set_tuplefield_int4(&tuple[COLUMNS_CHAR_OCTET_LENGTH], pgtype_transfer_octet_length(conn, field_type, mod_length));
2582
#endif /* ODBCVER */
2583
set_tuplefield_int4(&tuple[COLUMNS_DISPLAY_SIZE], mod_length);
2586
if (useStaticPrecision)
2588
mylog("%s: field type is OTHER: field_type = %d, pgtype_length = %d\n", func, field_type, pgtype_buffer_length(stmt, field_type, PG_STATIC, UNKNOWNS_AS_DEFAULT));
2590
set_tuplefield_int4(&tuple[COLUMNS_PRECISION], pgtype_column_size(stmt, field_type, PG_STATIC, UNKNOWNS_AS_DEFAULT));
2591
set_tuplefield_int4(&tuple[COLUMNS_LENGTH], pgtype_buffer_length(stmt, field_type, PG_STATIC, UNKNOWNS_AS_DEFAULT));
2592
#if (ODBCVER >= 0x0300)
2593
set_tuplefield_null(&tuple[COLUMNS_CHAR_OCTET_LENGTH]);
2594
#endif /* ODBCVER */
2595
set_tuplefield_int4(&tuple[COLUMNS_DISPLAY_SIZE], pgtype_display_size(stmt, field_type, PG_STATIC, UNKNOWNS_AS_DEFAULT));
2599
set_nullfield_int2(&tuple[COLUMNS_SCALE], pgtype_decimal_digits(stmt, field_type, PG_STATIC));
2602
if (SQL_TYPE_NULL == sqltype)
2604
sqltype = pgtype_attr_to_concise_type(conn, field_type, mod_length, -1);
2605
concise_type = pgtype_attr_to_sqldesctype(conn, field_type, mod_length);
2608
concise_type = sqltype;
2609
#else /* USE_OLD_IMPL */
2610
/* Subtract the header length */
2613
case PG_TYPE_DATETIME:
2614
case PG_TYPE_TIMESTAMP_NO_TMZONE:
2616
case PG_TYPE_TIME_WITH_TMZONE:
2620
if (mod_length >= 4)
2623
set_tuplefield_int4(&tuple[COLUMNS_PRECISION], pgtype_attr_column_size(conn, field_type, mod_length, PG_UNSPECIFIED, UNKNOWNS_AS_DEFAULT));
2624
set_tuplefield_int4(&tuple[COLUMNS_LENGTH], pgtype_attr_buffer_length(conn, field_type, mod_length, PG_UNSPECIFIED, UNKNOWNS_AS_DEFAULT));
2625
set_tuplefield_int4(&tuple[COLUMNS_DISPLAY_SIZE], pgtype_attr_display_size(conn, field_type, mod_length, PG_UNSPECIFIED, UNKNOWNS_AS_DEFAULT));
2626
set_nullfield_int2(&tuple[COLUMNS_SCALE], pgtype_attr_decimal_digits(conn, field_type, mod_length, PG_UNSPECIFIED, UNKNOWNS_AS_DEFAULT));
2628
sqltype = pgtype_attr_to_concise_type(conn, field_type, mod_length, PG_UNSPECIFIED);
2629
concise_type = pgtype_attr_to_sqldesctype(conn, field_type, mod_length);
2630
#endif /* USE_OLD_IMPL */
2632
set_tuplefield_int2(&tuple[COLUMNS_DATA_TYPE], sqltype);
2634
set_nullfield_int2(&tuple[COLUMNS_RADIX], pgtype_radix(conn, field_type));
2635
set_tuplefield_int2(&tuple[COLUMNS_NULLABLE], (Int2) (not_null[0] != '0' ? SQL_NO_NULLS : pgtype_nullable(conn, field_type)));
2636
set_tuplefield_string(&tuple[COLUMNS_REMARKS], NULL_STRING);
2637
#if (ODBCVER >= 0x0300)
2638
if (attdef && strlen(attdef) > INFO_VARCHAR_SIZE)
2639
set_tuplefield_string(&tuple[COLUMNS_COLUMN_DEF], "TRUNCATE");
2641
set_tuplefield_string(&tuple[COLUMNS_COLUMN_DEF], attdef);
2642
set_tuplefield_int2(&tuple[COLUMNS_SQL_DATA_TYPE], concise_type);
2643
set_nullfield_int2(&tuple[COLUMNS_SQL_DATETIME_SUB], pgtype_attr_to_datetime_sub(conn, field_type, mod_length));
2644
set_tuplefield_int4(&tuple[COLUMNS_CHAR_OCTET_LENGTH], pgtype_attr_transfer_octet_length(conn, field_type, mod_length, UNKNOWNS_AS_DEFAULT));
2645
set_tuplefield_int4(&tuple[COLUMNS_ORDINAL_POSITION], ordinal);
2646
set_tuplefield_null(&tuple[COLUMNS_IS_NULLABLE]);
2647
#endif /* ODBCVER */
2648
set_tuplefield_int4(&tuple[COLUMNS_FIELD_TYPE], field_type);
2649
set_tuplefield_int4(&tuple[COLUMNS_AUTO_INCREMENT], auto_unique);
2650
set_tuplefield_int2(&tuple[COLUMNS_PHYSICAL_NUMBER], field_number);
2651
set_tuplefield_int4(&tuple[COLUMNS_TABLE_OID], greloid);
2652
set_tuplefield_int4(&tuple[COLUMNS_BASE_TYPEID], basetype);
2653
set_tuplefield_int4(&tuple[COLUMNS_ATTTYPMOD], mod_length);
2656
result = PGAPI_Fetch(hcol_stmt);
2660
if (result != SQL_NO_DATA_FOUND)
2662
SC_full_error_copy(stmt, col_stmt, FALSE);
2667
* Put the row version column at the end so it might not be mistaken
2670
if (!relisaview && !stmt->internal && atoi(ci->row_versioning))
2672
/* For Row Versioning fields */
2673
the_type = PG_TYPE_INT4;
2675
tuple = QR_AddNew(res);
2677
set_tuplefield_string(&tuple[COLUMNS_CATALOG_NAME], CurrCat(conn));
2678
if (conn->schema_support)
2679
set_tuplefield_string(&tuple[COLUMNS_SCHEMA_NAME], GET_SCHEMA_NAME(table_owner));
2681
set_tuplefield_string(&tuple[COLUMNS_SCHEMA_NAME], NULL_STRING);
2682
set_tuplefield_string(&tuple[COLUMNS_TABLE_NAME], table_name);
2683
set_tuplefield_string(&tuple[COLUMNS_COLUMN_NAME], "xmin");
2684
sqltype = pgtype_to_concise_type(stmt, the_type, PG_STATIC);
2685
set_tuplefield_int2(&tuple[COLUMNS_DATA_TYPE], sqltype);
2686
set_tuplefield_string(&tuple[COLUMNS_TYPE_NAME], pgtype_to_name(stmt, the_type, PG_UNSPECIFIED, FALSE));
2687
set_tuplefield_int4(&tuple[COLUMNS_PRECISION], pgtype_column_size(stmt, the_type, PG_STATIC, UNKNOWNS_AS_DEFAULT));
2688
set_tuplefield_int4(&tuple[COLUMNS_LENGTH], pgtype_buffer_length(stmt, the_type, PG_STATIC, UNKNOWNS_AS_DEFAULT));
2689
set_nullfield_int2(&tuple[COLUMNS_SCALE], pgtype_decimal_digits(stmt, the_type, PG_STATIC));
2690
set_nullfield_int2(&tuple[COLUMNS_RADIX], pgtype_radix(conn, the_type));
2691
set_tuplefield_int2(&tuple[COLUMNS_NULLABLE], SQL_NO_NULLS);
2692
set_tuplefield_string(&tuple[COLUMNS_REMARKS], NULL_STRING);
2693
#if (ODBCVER >= 0x0300)
2694
set_tuplefield_null(&tuple[COLUMNS_COLUMN_DEF]);
2695
set_tuplefield_int2(&tuple[COLUMNS_SQL_DATA_TYPE], sqltype);
2696
set_tuplefield_null(&tuple[COLUMNS_SQL_DATETIME_SUB]);
2697
set_tuplefield_null(&tuple[COLUMNS_CHAR_OCTET_LENGTH]);
2698
set_tuplefield_int4(&tuple[COLUMNS_ORDINAL_POSITION], ordinal);
2699
set_tuplefield_string(&tuple[COLUMNS_IS_NULLABLE], "No");
2700
#endif /* ODBCVER */
2701
set_tuplefield_int4(&tuple[COLUMNS_DISPLAY_SIZE], pgtype_display_size(stmt, the_type, PG_STATIC, UNKNOWNS_AS_DEFAULT));
2702
set_tuplefield_int4(&tuple[COLUMNS_FIELD_TYPE], the_type);
2703
set_tuplefield_int4(&tuple[COLUMNS_AUTO_INCREMENT], FALSE);
2704
set_tuplefield_int2(&tuple[COLUMNS_PHYSICAL_NUMBER], XMIN_ATTNUM);
2705
set_tuplefield_int4(&tuple[COLUMNS_TABLE_OID], greloid);
2706
set_tuplefield_int4(&tuple[COLUMNS_BASE_TYPEID], 0);
2707
set_tuplefield_int4(&tuple[COLUMNS_ATTTYPMOD], -1);
2710
result = SQL_SUCCESS;
2715
* also, things need to think that this statement is finished so the
2716
* results can be retrieved.
2718
stmt->status = STMT_FINISHED;
2719
stmt->catalog_result = TRUE;
2721
/* set up the current tuple pointer for SQLFetch */
2722
stmt->currTuple = -1;
2723
SC_set_rowset_start(stmt, -1, FALSE);
2724
SC_set_current_col(stmt, -1);
2727
free(escSchemaName);
2731
free(escColumnName);
2733
PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
2735
result = DiscardStatementSvp(stmt, result, FALSE);
2736
mylog("%s: EXIT, stmt=%p\n", func, stmt);
2742
PGAPI_SpecialColumns(
2744
SQLUSMALLINT fColType,
2745
const SQLCHAR FAR * szTableQualifier,
2746
SQLSMALLINT cbTableQualifier,
2747
const SQLCHAR FAR * szTableOwner, /* OA E*/
2748
SQLSMALLINT cbTableOwner,
2749
const SQLCHAR FAR * szTableName, /* OA(R) E*/
2750
SQLSMALLINT cbTableName,
2751
SQLUSMALLINT fScope,
2752
SQLUSMALLINT fNullable)
2754
CSTR func = "PGAPI_SpecialColumns";
2756
StatementClass *stmt = (StatementClass *) hstmt;
2757
ConnectionClass *conn;
2760
HSTMT hcol_stmt = NULL;
2761
StatementClass *col_stmt;
2762
char columns_query[INFO_INQUIRY_LEN];
2763
char *escSchemaName = NULL, *escTableName = NULL;
2764
RETCODE result = SQL_SUCCESS;
2765
char relhasrules[MAX_INFO_STRING], relkind[8], relhasoids[8];
2767
SQLSMALLINT internal_asis_type = SQL_C_CHAR, cbSchemaName;
2768
const char *szSchemaName, *eq_string;
2770
mylog("%s: entering...stmt=%p scnm=%p len=%d colType=%d scope=%d\n", func, stmt, szTableOwner, cbTableOwner, fColType, fScope);
2772
if (result = SC_initialize_and_recycle(stmt), SQL_SUCCESS != result)
2774
conn = SC_get_conn(stmt);
2775
ci = &(conn->connInfo);
2776
#ifdef UNICODE_SUPPORT
2777
if (CC_is_in_unicode_driver(conn))
2778
internal_asis_type = INTERNAL_ASIS_TYPE;
2779
#endif /* UNICODE_SUPPORT */
2781
szSchemaName = szTableOwner;
2782
cbSchemaName = cbTableOwner;
2784
escTableName = simpleCatalogEscape(szTableName, cbTableName, NULL, conn);
2787
SC_set_error(stmt, STMT_INVALID_NULL_ARG, "The table name is required", func);
2790
#define return DONT_CALL_RETURN_FROM_HERE???
2792
retry_public_schema:
2794
free(escSchemaName);
2795
escSchemaName = simpleCatalogEscape(szSchemaName, cbSchemaName, NULL, conn);
2796
eq_string = gen_opestr(eqop, conn);
2798
* Create the query to find out if this is a view or not...
2800
strcpy(columns_query, "select c.relhasrules, c.relkind");
2801
if (PG_VERSION_GE(conn, 7.2))
2802
strcat(columns_query, ", c.relhasoids");
2803
if (conn->schema_support)
2804
strcat(columns_query, " from pg_catalog.pg_namespace u,"
2805
" pg_catalog.pg_class c where "
2806
"u.oid = c.relnamespace");
2808
strcat(columns_query, " from pg_user u, pg_class c where "
2809
"u.usesysid = c.relowner");
2811
/* TableName cannot contain a string search pattern */
2812
/* my_strcat(columns_query, " and c.relname = '%.*s'", szTableName, cbTableName); */
2814
snprintf_add(columns_query, sizeof(columns_query), " and c.relname %s'%s'", eq_string, escTableName);
2815
/* SchemaName cannot contain a string search pattern */
2816
if (conn->schema_support)
2817
schema_strcat1(columns_query, " and u.nspname %s'%.*s'", eq_string, escSchemaName, SQL_NTS, szTableName, cbTableName, conn);
2819
my_strcat1(columns_query, " and u.usename %s'%.*s'", eq_string, escSchemaName, SQL_NTS);
2822
result = PGAPI_AllocStmt(conn, &hcol_stmt, 0);
2823
if (!SQL_SUCCEEDED(result))
2825
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate statement for SQLSpecialColumns result.", func);
2829
col_stmt = (StatementClass *) hcol_stmt;
2831
mylog("%s: hcol_stmt = %p, col_stmt = %p\n", func, hcol_stmt, col_stmt);
2833
result = PGAPI_ExecDirect(hcol_stmt, columns_query, SQL_NTS, 0);
2834
if (!SQL_SUCCEEDED(result))
2836
SC_full_error_copy(stmt, col_stmt, FALSE);
2842
if (conn->schema_support &&
2843
(res = SC_get_Result(col_stmt)) &&
2844
0 == QR_get_num_total_tuples(res))
2846
if (allow_public_schema(conn, szSchemaName, cbSchemaName))
2848
PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
2850
szSchemaName = pubstr;
2851
cbSchemaName = SQL_NTS;
2852
goto retry_public_schema;
2856
result = PGAPI_BindCol(hcol_stmt, 1, internal_asis_type,
2857
relhasrules, sizeof(relhasrules), NULL);
2858
if (!SQL_SUCCEEDED(result))
2860
SC_error_copy(stmt, col_stmt, TRUE);
2865
result = PGAPI_BindCol(hcol_stmt, 2, internal_asis_type,
2866
relkind, sizeof(relkind), NULL);
2867
if (!SQL_SUCCEEDED(result))
2869
SC_error_copy(stmt, col_stmt, TRUE);
2873
relhasoids[0] = '1';
2874
if (PG_VERSION_GE(conn, 7.2))
2876
result = PGAPI_BindCol(hcol_stmt, 3, internal_asis_type,
2877
relhasoids, sizeof(relhasoids), NULL);
2878
if (!SQL_SUCCEEDED(result))
2880
SC_error_copy(stmt, col_stmt, TRUE);
2886
result = PGAPI_Fetch(hcol_stmt);
2887
if (PG_VERSION_GE(conn, 7.1))
2888
relisaview = (relkind[0] == 'v');
2890
relisaview = (relhasrules[0] == '1');
2891
PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
2894
res = QR_Constructor();
2895
SC_set_Result(stmt, res);
2896
extend_column_bindings(SC_get_ARDF(stmt), 8);
2898
stmt->catalog_result = TRUE;
2899
QR_set_num_fields(res, 8);
2900
QR_set_field_info_v(res, 0, "SCOPE", PG_TYPE_INT2, 2);
2901
QR_set_field_info_v(res, 1, "COLUMN_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
2902
QR_set_field_info_v(res, 2, "DATA_TYPE", PG_TYPE_INT2, 2);
2903
QR_set_field_info_v(res, 3, "TYPE_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
2904
QR_set_field_info_v(res, 4, "PRECISION", PG_TYPE_INT4, 4);
2905
QR_set_field_info_v(res, 5, "LENGTH", PG_TYPE_INT4, 4);
2906
QR_set_field_info_v(res, 6, "SCALE", PG_TYPE_INT2, 2);
2907
QR_set_field_info_v(res, 7, "PSEUDO_COLUMN", PG_TYPE_INT2, 2);
2911
/* there's no oid for views */
2912
if (fColType == SQL_BEST_ROWID)
2916
else if (fColType == SQL_ROWVER)
2918
Int2 the_type = PG_TYPE_TID;
2920
tuple = QR_AddNew(res);
2922
set_tuplefield_null(&tuple[0]);
2923
set_tuplefield_string(&tuple[1], "ctid");
2924
set_tuplefield_int2(&tuple[2], pgtype_to_concise_type(stmt, the_type, PG_STATIC));
2925
set_tuplefield_string(&tuple[3], pgtype_to_name(stmt, the_type, PG_UNSPECIFIED, FALSE));
2926
set_tuplefield_int4(&tuple[4], pgtype_column_size(stmt, the_type, PG_STATIC, UNKNOWNS_AS_DEFAULT));
2927
set_tuplefield_int4(&tuple[5], pgtype_buffer_length(stmt, the_type, PG_STATIC, UNKNOWNS_AS_DEFAULT));
2928
set_tuplefield_int2(&tuple[6], pgtype_decimal_digits(stmt, the_type, PG_STATIC));
2929
set_tuplefield_int2(&tuple[7], SQL_PC_NOT_PSEUDO);
2930
inolog("Add ctid\n");
2935
/* use the oid value for the rowid */
2936
if (fColType == SQL_BEST_ROWID)
2938
Int2 the_type = PG_TYPE_OID;
2940
if (relhasoids[0] != '1')
2944
tuple = QR_AddNew(res);
2946
set_tuplefield_int2(&tuple[0], SQL_SCOPE_SESSION);
2947
set_tuplefield_string(&tuple[1], OID_NAME);
2948
set_tuplefield_int2(&tuple[2], pgtype_to_concise_type(stmt, the_type, PG_STATIC));
2949
set_tuplefield_string(&tuple[3], pgtype_to_name(stmt, the_type, PG_UNSPECIFIED, TRUE));
2950
set_tuplefield_int4(&tuple[4], pgtype_column_size(stmt, the_type, PG_STATIC, UNKNOWNS_AS_DEFAULT));
2951
set_tuplefield_int4(&tuple[5], pgtype_buffer_length(stmt, the_type, PG_STATIC, UNKNOWNS_AS_DEFAULT));
2952
set_tuplefield_int2(&tuple[6], pgtype_decimal_digits(stmt, the_type, PG_STATIC));
2953
set_tuplefield_int2(&tuple[7], SQL_PC_PSEUDO);
2955
else if (fColType == SQL_ROWVER)
2957
Int2 the_type = PG_TYPE_XID;
2959
/* if (atoi(ci->row_versioning)) */
2961
tuple = QR_AddNew(res);
2963
set_tuplefield_null(&tuple[0]);
2964
set_tuplefield_string(&tuple[1], "xmin");
2965
set_tuplefield_int2(&tuple[2], pgtype_to_concise_type(stmt, the_type, PG_STATIC));
2966
set_tuplefield_string(&tuple[3], pgtype_to_name(stmt, the_type, PG_UNSPECIFIED, FALSE));
2967
set_tuplefield_int4(&tuple[4], pgtype_column_size(stmt, the_type, PG_STATIC, UNKNOWNS_AS_DEFAULT));
2968
set_tuplefield_int4(&tuple[5], pgtype_buffer_length(stmt, the_type, PG_STATIC, UNKNOWNS_AS_DEFAULT));
2969
set_tuplefield_int2(&tuple[6], pgtype_decimal_digits(stmt, the_type, PG_STATIC));
2970
set_tuplefield_int2(&tuple[7], SQL_PC_PSEUDO);
2978
free(escSchemaName);
2981
stmt->status = STMT_FINISHED;
2982
stmt->currTuple = -1;
2983
SC_set_rowset_start(stmt, -1, FALSE);
2984
SC_set_current_col(stmt, -1);
2986
PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
2988
result = DiscardStatementSvp(stmt, result, FALSE);
2989
mylog("%s: EXIT, stmt=%p\n", func, stmt);
2994
#define INDOPTION_DESC 0x0001 /* values are in reverse order */
2998
const SQLCHAR FAR * szTableQualifier, /* OA X*/
2999
SQLSMALLINT cbTableQualifier,
3000
const SQLCHAR FAR * szTableOwner, /* OA E*/
3001
SQLSMALLINT cbTableOwner,
3002
const SQLCHAR FAR * szTableName, /* OA(R) E*/
3003
SQLSMALLINT cbTableName,
3004
SQLUSMALLINT fUnique,
3005
SQLUSMALLINT fAccuracy)
3007
CSTR func = "PGAPI_Statistics";
3008
StatementClass *stmt = (StatementClass *) hstmt;
3009
ConnectionClass *conn;
3011
char index_query[INFO_INQUIRY_LEN];
3012
HSTMT hcol_stmt = NULL, hindx_stmt = NULL;
3013
RETCODE ret = SQL_ERROR, result;
3014
char *escSchemaName = NULL, *table_name = NULL, *escTableName = NULL;
3015
char index_name[MAX_INFO_STRING];
3016
short fields_vector[INDEX_KEYS_STORAGE_COUNT + 1];
3017
short indopt_vector[INDEX_KEYS_STORAGE_COUNT + 1];
3020
ishash[MAX_INFO_STRING];
3021
SQLLEN index_name_len, fields_vector_len;
3024
StatementClass *col_stmt,
3026
char column_name[MAX_INFO_STRING],
3027
table_schemaname[MAX_INFO_STRING],
3029
struct columns_idx {
3032
} *column_names = NULL;
3033
/* char **column_names = NULL; */
3034
SQLLEN column_name_len;
3035
int total_columns = 0, alcount;
3038
SQLSMALLINT internal_asis_type = SQL_C_CHAR, cbSchemaName, field_number;
3039
const char *szSchemaName, *eq_string;
3043
mylog("%s: entering...stmt=%p scnm=%p len=%d\n", func, stmt, szTableOwner, cbTableOwner);
3045
if (result = SC_initialize_and_recycle(stmt), SQL_SUCCESS != result)
3048
table_name = make_string(szTableName, cbTableName, NULL, 0);
3051
SC_set_error(stmt, STMT_INVALID_NULL_ARG, "The table name is required", func);
3054
conn = SC_get_conn(stmt);
3055
ci = &(conn->connInfo);
3056
#ifdef UNICODE_SUPPORT
3057
if (CC_is_in_unicode_driver(conn))
3058
internal_asis_type = INTERNAL_ASIS_TYPE;
3059
#endif /* UNICODE_SUPPORT */
3061
if (res = QR_Constructor(), !res)
3063
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate memory for PGAPI_Statistics result.", func);
3066
SC_set_Result(stmt, res);
3068
/* the binding structure for a statement is not set up until */
3071
* a statement is actually executed, so we'll have to do this
3074
extend_column_bindings(SC_get_ARDF(stmt), 13);
3076
stmt->catalog_result = TRUE;
3077
/* set the field names */
3078
QR_set_num_fields(res, NUM_OF_STATS_FIELDS);
3079
QR_set_field_info_v(res, STATS_CATALOG_NAME, "TABLE_QUALIFIER", PG_TYPE_VARCHAR, MAX_INFO_STRING);
3080
QR_set_field_info_v(res, STATS_SCHEMA_NAME, "TABLE_OWNER", PG_TYPE_VARCHAR, MAX_INFO_STRING);
3081
QR_set_field_info_v(res, STATS_TABLE_NAME, "TABLE_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
3082
QR_set_field_info_v(res, STATS_NON_UNIQUE, "NON_UNIQUE", PG_TYPE_INT2, 2);
3083
QR_set_field_info_v(res, STATS_INDEX_QUALIFIER, "INDEX_QUALIFIER", PG_TYPE_VARCHAR, MAX_INFO_STRING);
3084
QR_set_field_info_v(res, STATS_INDEX_NAME, "INDEX_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
3085
QR_set_field_info_v(res, STATS_TYPE, "TYPE", PG_TYPE_INT2, 2);
3086
QR_set_field_info_v(res, STATS_SEQ_IN_INDEX, "SEQ_IN_INDEX", PG_TYPE_INT2, 2);
3087
QR_set_field_info_v(res, STATS_COLUMN_NAME, "COLUMN_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
3088
QR_set_field_info_v(res, STATS_COLLATION, "COLLATION", PG_TYPE_CHAR, 1);
3089
QR_set_field_info_v(res, STATS_CARDINALITY, "CARDINALITY", PG_TYPE_INT4, 4);
3090
QR_set_field_info_v(res, STATS_PAGES, "PAGES", PG_TYPE_INT4, 4);
3091
QR_set_field_info_v(res, STATS_FILTER_CONDITION, "FILTER_CONDITION", PG_TYPE_VARCHAR, MAX_INFO_STRING);
3093
#define return DONT_CALL_RETURN_FROM_HERE???
3094
szSchemaName = szTableOwner;
3095
cbSchemaName = cbTableOwner;
3097
table_schemaname[0] = '\0';
3098
if (conn->schema_support)
3099
schema_strcat(table_schemaname, "%.*s", szSchemaName, cbSchemaName, szTableName, cbTableName, conn);
3102
* we need to get a list of the field names first, so we can return
3105
result = PGAPI_AllocStmt(conn, &hcol_stmt, 0);
3106
if (!SQL_SUCCEEDED(result))
3108
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "PGAPI_AllocStmt failed in PGAPI_Statistics for columns.", func);
3112
col_stmt = (StatementClass *) hcol_stmt;
3115
* "internal" prevents SQLColumns from returning the oid if it is
3116
* being shown. This would throw everything off.
3118
col_stmt->internal = TRUE;
3120
* table_name parameter cannot contain a string search pattern.
3122
result = PGAPI_Columns(hcol_stmt, NULL, 0, table_schemaname, SQL_NTS,
3123
table_name, SQL_NTS, NULL, 0, PODBC_NOT_SEARCH_PATTERN | PODBC_SEARCH_PUBLIC_SCHEMA, 0, 0);
3124
col_stmt->internal = FALSE;
3126
if (!SQL_SUCCEEDED(result))
3128
SC_error_copy(stmt, col_stmt, TRUE);
3131
result = PGAPI_BindCol(hcol_stmt, COLUMNS_COLUMN_NAME + 1, internal_asis_type,
3132
column_name, sizeof(column_name), &column_name_len);
3133
if (!SQL_SUCCEEDED(result))
3135
SC_error_copy(stmt, col_stmt, TRUE);
3138
result = PGAPI_BindCol(hcol_stmt, COLUMNS_PHYSICAL_NUMBER + 1, SQL_C_SHORT,
3139
&field_number, sizeof(field_number), NULL);
3140
if (!SQL_SUCCEEDED(result))
3142
SC_error_copy(stmt, col_stmt, TRUE);
3147
result = PGAPI_Fetch(hcol_stmt);
3148
while (SQL_SUCCEEDED(result))
3150
if (0 == total_columns)
3151
PGAPI_GetData(hcol_stmt, 2, internal_asis_type, table_schemaname, sizeof(table_schemaname), NULL);
3153
if (total_columns >= alcount)
3160
(struct columns_idx *) realloc(column_names,
3161
alcount * sizeof(struct columns_idx));
3163
column_names[total_columns].col_name =
3164
(char *) malloc(strlen(column_name) + 1);
3165
strcpy(column_names[total_columns].col_name, column_name);
3166
column_names[total_columns].pnum = field_number;
3169
mylog("%s: column_name = '%s'\n", func, column_name);
3171
result = PGAPI_Fetch(hcol_stmt);
3174
if (result != SQL_NO_DATA_FOUND)
3176
SC_full_error_copy(stmt, col_stmt, FALSE);
3179
PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
3181
if (total_columns == 0)
3183
/* Couldn't get column names in SQLStatistics.; */
3188
/* get a list of indexes on this table */
3189
result = PGAPI_AllocStmt(conn, &hindx_stmt, 0);
3190
if (!SQL_SUCCEEDED(result))
3192
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "PGAPI_AllocStmt failed in SQLStatistics for indices.", func);
3196
indx_stmt = (StatementClass *) hindx_stmt;
3198
/* TableName cannot contain a string search pattern */
3199
escTableName = simpleCatalogEscape(table_name, SQL_NTS, NULL, conn);
3200
eq_string = gen_opestr(eqop, conn);
3201
if (conn->schema_support)
3203
escSchemaName = simpleCatalogEscape(table_schemaname, SQL_NTS, NULL, conn);
3204
snprintf(index_query, sizeof(index_query), "select c.relname, i.indkey, i.indisunique"
3205
", i.indisclustered, a.amname, c.relhasrules, n.nspname"
3207
" from pg_catalog.pg_index i, pg_catalog.pg_class c,"
3208
" pg_catalog.pg_class d, pg_catalog.pg_am a,"
3209
" pg_catalog.pg_namespace n"
3210
" where d.relname %s'%s'"
3211
" and n.nspname %s'%s'"
3212
" and n.oid = d.relnamespace"
3213
" and d.oid = i.indrelid"
3214
" and i.indexrelid = c.oid"
3215
" and c.relam = a.oid order by"
3216
, PG_VERSION_GE(conn, 7.2) ? "d.relhasoids" : "1"
3217
, PG_VERSION_GE(conn, 8.3) ? "i.indoption" : "0"
3218
, eq_string, escTableName, eq_string, escSchemaName);
3221
snprintf(index_query, sizeof(index_query), "select c.relname, i.indkey, i.indisunique"
3222
", i.indisclustered, a.amname, c.relhasrules, c.oid, %s, 0"
3223
" from pg_index i, pg_class c, pg_class d, pg_am a"
3224
" where d.relname %s'%s'"
3225
" and d.oid = i.indrelid"
3226
" and i.indexrelid = c.oid"
3227
" and c.relam = a.oid order by"
3228
, PG_VERSION_GE(conn, 7.2) ? "d.relhasoids" : "1"
3229
, eq_string, escTableName);
3230
if (PG_VERSION_GT(SC_get_conn(stmt), 6.4))
3231
strcat(index_query, " i.indisprimary desc,");
3232
if (conn->schema_support)
3233
strcat(index_query, " i.indisunique, n.nspname, c.relname");
3235
strcat(index_query, " i.indisunique, c.relname");
3237
result = PGAPI_ExecDirect(hindx_stmt, index_query, SQL_NTS, 0);
3238
if (!SQL_SUCCEEDED(result))
3241
* "Couldn't execute index query (w/SQLExecDirect) in
3244
SC_full_error_copy(stmt, indx_stmt, FALSE);
3248
/* bind the index name column */
3249
result = PGAPI_BindCol(hindx_stmt, 1, internal_asis_type,
3250
index_name, MAX_INFO_STRING, &index_name_len);
3251
if (!SQL_SUCCEEDED(result))
3253
SC_error_copy(stmt, indx_stmt, TRUE); /* "Couldn't bind column
3254
* in SQLStatistics."; */
3258
/* bind the vector column */
3259
result = PGAPI_BindCol(hindx_stmt, 2, SQL_C_DEFAULT,
3260
fields_vector, sizeof(fields_vector), &fields_vector_len);
3261
if (!SQL_SUCCEEDED(result))
3263
SC_error_copy(stmt, indx_stmt, TRUE); /* "Couldn't bind column
3264
* in SQLStatistics."; */
3268
/* bind the "is unique" column */
3269
result = PGAPI_BindCol(hindx_stmt, 3, internal_asis_type,
3270
isunique, sizeof(isunique), NULL);
3271
if (!SQL_SUCCEEDED(result))
3273
SC_error_copy(stmt, indx_stmt, TRUE); /* "Couldn't bind column
3274
* in SQLStatistics."; */
3278
/* bind the "is clustered" column */
3279
result = PGAPI_BindCol(hindx_stmt, 4, internal_asis_type,
3280
isclustered, sizeof(isclustered), NULL);
3281
if (!SQL_SUCCEEDED(result))
3283
SC_error_copy(stmt, indx_stmt, TRUE); /* "Couldn't bind column *
3284
* in SQLStatistics."; */
3289
/* bind the "is hash" column */
3290
result = PGAPI_BindCol(hindx_stmt, 5, internal_asis_type,
3291
ishash, sizeof(ishash), NULL);
3292
if (!SQL_SUCCEEDED(result))
3294
SC_error_copy(stmt, indx_stmt, TRUE); /* "Couldn't bind column *
3295
* in SQLStatistics."; */
3300
result = PGAPI_BindCol(hindx_stmt, 6, internal_asis_type,
3301
relhasrules, sizeof(relhasrules), NULL);
3302
if (!SQL_SUCCEEDED(result))
3304
SC_error_copy(stmt, indx_stmt, TRUE);
3308
result = PGAPI_BindCol(hindx_stmt, 8, SQL_C_ULONG,
3309
&ioid, sizeof(ioid), NULL);
3310
if (!SQL_SUCCEEDED(result))
3312
SC_error_copy(stmt, indx_stmt, TRUE);
3316
result = PGAPI_BindCol(hindx_stmt, 9, SQL_C_ULONG,
3317
&relhasoids, sizeof(relhasoids), NULL);
3318
if (!SQL_SUCCEEDED(result))
3320
SC_error_copy(stmt, indx_stmt, TRUE);
3324
/* bind the vector column */
3325
result = PGAPI_BindCol(hindx_stmt, 10, SQL_C_DEFAULT,
3326
indopt_vector, sizeof(fields_vector), &fields_vector_len);
3327
if (!SQL_SUCCEEDED(result))
3329
SC_error_copy(stmt, indx_stmt, TRUE); /* "Couldn't bind column
3330
* in SQLStatistics."; */
3335
relhasrules[0] = '0';
3336
result = PGAPI_Fetch(hindx_stmt);
3337
/* fake index of OID */
3338
if (relhasoids && relhasrules[0] != '1' && atoi(ci->show_oid_column) && atoi(ci->fake_oid_index))
3340
tuple = QR_AddNew(res);
3342
/* no table qualifier */
3343
set_tuplefield_string(&tuple[STATS_CATALOG_NAME], CurrCat(conn));
3344
/* don't set the table owner, else Access tries to use it */
3345
set_tuplefield_string(&tuple[STATS_SCHEMA_NAME], GET_SCHEMA_NAME(table_schemaname));
3346
set_tuplefield_string(&tuple[STATS_TABLE_NAME], table_name);
3348
/* non-unique index? */
3349
set_tuplefield_int2(&tuple[STATS_NON_UNIQUE], (Int2) (ci->drivers.unique_index ? FALSE : TRUE));
3351
/* no index qualifier */
3352
set_tuplefield_string(&tuple[STATS_INDEX_QUALIFIER], GET_SCHEMA_NAME(table_schemaname));
3354
snprintf(buf, sizeof(buf), "%s_idx_fake_oid", table_name);
3355
set_tuplefield_string(&tuple[STATS_INDEX_NAME], buf);
3358
* Clustered/HASH index?
3360
set_tuplefield_int2(&tuple[STATS_TYPE], (Int2) SQL_INDEX_OTHER);
3361
set_tuplefield_int2(&tuple[STATS_SEQ_IN_INDEX], (Int2) 1);
3363
set_tuplefield_string(&tuple[STATS_COLUMN_NAME], OID_NAME);
3364
set_tuplefield_string(&tuple[STATS_COLLATION], "A");
3365
set_tuplefield_null(&tuple[STATS_CARDINALITY]);
3366
set_tuplefield_null(&tuple[STATS_PAGES]);
3367
set_tuplefield_null(&tuple[STATS_FILTER_CONDITION]);
3370
while (SQL_SUCCEEDED(result))
3372
/* If only requesting unique indexs, then just return those. */
3373
if (fUnique == SQL_INDEX_ALL ||
3374
(fUnique == SQL_INDEX_UNIQUE && atoi(isunique)))
3378
/* add a row in this table for each field in the index */
3379
colcnt = fields_vector[0];
3380
for (i = 1; i <= colcnt; i++)
3382
tuple = QR_AddNew(res);
3384
/* no table qualifier */
3385
set_tuplefield_string(&tuple[STATS_CATALOG_NAME], CurrCat(conn));
3386
/* don't set the table owner, else Access tries to use it */
3387
set_tuplefield_string(&tuple[STATS_SCHEMA_NAME], GET_SCHEMA_NAME(table_schemaname));
3388
set_tuplefield_string(&tuple[STATS_TABLE_NAME], table_name);
3390
/* non-unique index? */
3391
if (ci->drivers.unique_index)
3392
set_tuplefield_int2(&tuple[STATS_NON_UNIQUE], (Int2) (atoi(isunique) ? FALSE : TRUE));
3394
set_tuplefield_int2(&tuple[STATS_NON_UNIQUE], TRUE);
3396
/* no index qualifier */
3397
set_tuplefield_string(&tuple[STATS_INDEX_QUALIFIER], GET_SCHEMA_NAME(table_schemaname));
3398
set_tuplefield_string(&tuple[STATS_INDEX_NAME], index_name);
3401
* Clustered/HASH index?
3403
set_tuplefield_int2(&tuple[STATS_TYPE], (Int2)
3404
(atoi(isclustered) ? SQL_INDEX_CLUSTERED :
3405
(!strncmp(ishash, "hash", 4)) ? SQL_INDEX_HASHED : SQL_INDEX_OTHER));
3406
set_tuplefield_int2(&tuple[STATS_SEQ_IN_INDEX], (Int2) i);
3408
attnum = fields_vector[i];
3409
if (OID_ATTNUM == attnum)
3411
set_tuplefield_string(&tuple[STATS_COLUMN_NAME], OID_NAME);
3412
mylog("%s: column name = oid\n", func);
3414
else if (0 == attnum)
3420
snprintf(cmd, sizeof(cmd), "select pg_get_indexdef(%u, %d, true)", ioid, i);
3421
res = CC_send_query(conn, cmd, NULL, IGNORE_ABORT_ON_CONN, stmt);
3422
if (QR_command_maybe_successful(res))
3423
set_tuplefield_string(&tuple[STATS_COLUMN_NAME], QR_get_value_backend_text(res, 0, 0));
3429
BOOL unknownf = TRUE;
3433
for (j = 0; j < total_columns; j++)
3435
if (attnum == column_names[j].pnum)
3445
set_tuplefield_string(&tuple[STATS_COLUMN_NAME], "UNKNOWN");
3446
mylog("%s: column name = UNKNOWN\n", func);
3450
set_tuplefield_string(&tuple[STATS_COLUMN_NAME], column_names[matchidx].col_name);
3451
mylog("%s: column name = '%s'\n", func, column_names[matchidx].col_name);
3455
if (i <= indopt_vector[0] &&
3456
(indopt_vector[i] & INDOPTION_DESC) != 0)
3457
set_tuplefield_string(&tuple[STATS_COLLATION], "D");
3459
set_tuplefield_string(&tuple[STATS_COLLATION], "A");
3460
set_tuplefield_null(&tuple[STATS_CARDINALITY]);
3461
set_tuplefield_null(&tuple[STATS_PAGES]);
3462
set_tuplefield_null(&tuple[STATS_FILTER_CONDITION]);
3466
result = PGAPI_Fetch(hindx_stmt);
3468
if (result != SQL_NO_DATA_FOUND)
3470
/* "SQLFetch failed in SQLStatistics."; */
3471
SC_full_error_copy(stmt, indx_stmt, FALSE);
3479
* also, things need to think that this statement is finished so the
3480
* results can be retrieved.
3482
stmt->status = STMT_FINISHED;
3485
PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
3487
PGAPI_FreeStmt(hindx_stmt, SQL_DROP);
3488
/* These things should be freed on any error ALSO! */
3494
free(escSchemaName);
3497
for (i = 0; i < total_columns; i++)
3498
free(column_names[i].col_name);
3502
/* set up the current tuple pointer for SQLFetch */
3503
stmt->currTuple = -1;
3504
SC_set_rowset_start(stmt, -1, FALSE);
3505
SC_set_current_col(stmt, -1);
3508
ret = DiscardStatementSvp(stmt, ret, FALSE);
3509
mylog("%s: EXIT, stmt=%p, ret=%d\n", func, stmt, ret);
3516
PGAPI_ColumnPrivileges(
3518
const SQLCHAR FAR * szTableQualifier, /* OA X*/
3519
SQLSMALLINT cbTableQualifier,
3520
const SQLCHAR FAR * szTableOwner, /* OA E*/
3521
SQLSMALLINT cbTableOwner,
3522
const SQLCHAR FAR * szTableName, /* OA(R) E*/
3523
SQLSMALLINT cbTableName,
3524
const SQLCHAR FAR * szColumnName, /* PV E*/
3525
SQLSMALLINT cbColumnName,
3528
CSTR func = "PGAPI_ColumnPrivileges";
3529
StatementClass *stmt = (StatementClass *) hstmt;
3530
ConnectionClass *conn = SC_get_conn(stmt);
3531
RETCODE result = SQL_ERROR;
3532
char *escSchemaName = NULL, *escTableName = NULL, *escColumnName = NULL;
3533
const char *like_or_eq, *op_string, *eq_string;
3534
char column_query[INFO_INQUIRY_LEN];
3535
size_t cq_len,cq_size;
3537
BOOL search_pattern;
3538
QResultClass *res = NULL;
3540
mylog("%s: entering...\n", func);
3542
/* Neither Access or Borland care about this. */
3544
if (result = SC_initialize_and_recycle(stmt), SQL_SUCCESS != result)
3546
if (PG_VERSION_LT(conn, 7.4))
3547
SC_set_error(stmt, STMT_NOT_IMPLEMENTED_ERROR, "Function not implementedyet", func);
3548
escSchemaName = simpleCatalogEscape(szTableOwner, cbTableOwner, NULL, conn);
3549
escTableName = simpleCatalogEscape(szTableName, cbTableName, NULL, conn);
3550
search_pattern = (0 == (flag & PODBC_NOT_SEARCH_PATTERN));
3553
like_or_eq = likeop;
3554
escColumnName = adjustLikePattern(szColumnName, cbColumnName, SEARCH_PATTERN_ESCAPE, NULL, conn);
3559
escColumnName = simpleCatalogEscape(szColumnName, cbColumnName, NULL, conn);
3561
strcpy(column_query, "select '' as TABLE_CAT, table_schema as TABLE_SCHEM,"
3562
" table_name, column_name, grantor, grantee,"
3563
" privilege_type as PRIVILEGE, is_grantable from"
3564
" information_schema.column_privileges where true");
3565
cq_len = strlen(column_query);
3566
cq_size = sizeof(column_query);
3567
col_query = column_query;
3568
op_string = gen_opestr(like_or_eq, conn);
3569
eq_string = gen_opestr(eqop, conn);
3572
col_query += cq_len;
3574
cq_len = snprintf_len(col_query, cq_size,
3575
" and table_schem %s'%s'", eq_string, escSchemaName);
3580
col_query += cq_len;
3582
cq_len += snprintf_len(col_query, cq_size,
3583
" and table_name %s'%s'", eq_string, escTableName);
3587
col_query += cq_len;
3589
cq_len += snprintf_len(col_query, cq_size,
3590
" and column_name %s'%s'", op_string, escColumnName);
3592
if (res = CC_send_query(conn, column_query, NULL, IGNORE_ABORT_ON_CONN, stmt), !QR_command_maybe_successful(res))
3594
SC_set_error(stmt, STMT_EXEC_ERROR, "PGAPI_ColumnPrivileges query error", func);
3597
SC_set_Result(stmt, res);
3600
* also, things need to think that this statement is finished so the
3601
* results can be retrieved.
3603
extend_column_bindings(SC_get_ARDF(stmt), 8);
3604
/* set up the current tuple pointer for SQLFetch */
3605
result = SQL_SUCCESS;
3607
if (!SQL_SUCCEEDED(result))
3609
/* set up the current tuple pointer for SQLFetch */
3610
stmt->status = STMT_FINISHED;
3611
stmt->currTuple = -1;
3612
SC_set_rowset_start(stmt, -1, FALSE);
3614
free(escSchemaName);
3618
free(escColumnName);
3626
* Retrieve the primary key columns for the specified table.
3631
const SQLCHAR FAR * szTableQualifier, /* OA X*/
3632
SQLSMALLINT cbTableQualifier,
3633
const SQLCHAR FAR * szTableOwner, /* OA E*/
3634
SQLSMALLINT cbTableOwner,
3635
const SQLCHAR FAR * szTableName, /* OA(R) E*/
3636
SQLSMALLINT cbTableName,
3639
CSTR func = "PGAPI_PrimaryKeys";
3640
StatementClass *stmt = (StatementClass *) hstmt;
3642
ConnectionClass *conn;
3644
RETCODE ret = SQL_SUCCESS, result;
3646
HSTMT htbl_stmt = NULL;
3647
StatementClass *tbl_stmt;
3648
char tables_query[INFO_INQUIRY_LEN];
3649
char attname[MAX_INFO_STRING];
3651
char *pktab = NULL, *pktbname;
3652
char pkscm[SCHEMA_NAME_STORAGE_LEN + 1];
3654
char tabname[TABLE_NAME_STORAGE_LEN + 1];
3656
char pkname[TABLE_NAME_STORAGE_LEN + 1];
3661
SQLSMALLINT internal_asis_type = SQL_C_CHAR, cbSchemaName;
3662
const char *szSchemaName, *eq_string;
3663
char *escSchemaName = NULL, *escTableName = NULL;
3665
mylog("%s: entering...stmt=%p scnm=%p len=%d\n", func, stmt, szTableOwner, cbTableOwner);
3667
if (result = SC_initialize_and_recycle(stmt), SQL_SUCCESS != result)
3670
if (res = QR_Constructor(), !res)
3672
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate memory for PGAPI_PrimaryKeys result.", func);
3675
SC_set_Result(stmt, res);
3677
/* the binding structure for a statement is not set up until
3679
* a statement is actually executed, so we'll have to do this
3682
result_cols = NUM_OF_PKS_FIELDS;
3683
extend_column_bindings(SC_get_ARDF(stmt), result_cols);
3685
stmt->catalog_result = TRUE;
3686
/* set the field names */
3687
QR_set_num_fields(res, result_cols);
3688
QR_set_field_info_v(res, PKS_TABLE_CAT, "TABLE_QUALIFIER", PG_TYPE_VARCHAR, MAX_INFO_STRING);
3689
QR_set_field_info_v(res, PKS_TABLE_SCHEM, "TABLE_OWNER", PG_TYPE_VARCHAR, MAX_INFO_STRING);
3690
QR_set_field_info_v(res, PKS_TABLE_NAME, "TABLE_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
3691
QR_set_field_info_v(res, PKS_COLUMN_NAME, "COLUMN_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
3692
QR_set_field_info_v(res, PKS_KEY_SQ, "KEY_SEQ", PG_TYPE_INT2, 2);
3693
QR_set_field_info_v(res, PKS_PK_NAME, "PK_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
3695
conn = SC_get_conn(stmt);
3696
result = PGAPI_AllocStmt(conn, &htbl_stmt, 0);
3697
if (!SQL_SUCCEEDED(result))
3699
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate statement for Primary Key result.", func);
3703
tbl_stmt = (StatementClass *) htbl_stmt;
3705
#ifdef UNICODE_SUPPORT
3706
if (CC_is_in_unicode_driver(conn))
3707
internal_asis_type = INTERNAL_ASIS_TYPE;
3708
#endif /* UNICODE_SUPPORT */
3710
#define return DONT_CALL_RETURN_FROM_HERE???
3713
szSchemaName = NULL;
3714
cbSchemaName = SQL_NULL_DATA;
3718
pktab = make_string(szTableName, cbTableName, NULL, 0);
3719
if (!pktab || pktab[0] == '\0')
3721
SC_set_error(stmt, STMT_INTERNAL_ERROR, "No Table specified to PGAPI_PrimaryKeys.", func);
3725
szSchemaName = szTableOwner;
3726
cbSchemaName = cbTableOwner;
3727
escTableName = simpleCatalogEscape(szTableName, cbTableName, NULL, conn);
3729
eq_string = gen_opestr(eqop, conn);
3731
retry_public_schema:
3736
free(escSchemaName);
3737
escSchemaName = simpleCatalogEscape(szSchemaName, cbSchemaName, NULL, conn);
3738
if (conn->schema_support)
3739
schema_strcat(pkscm, "%.*s", escSchemaName, SQL_NTS, szTableName, cbTableName, conn);
3742
result = PGAPI_BindCol(htbl_stmt, 1, internal_asis_type,
3743
attname, MAX_INFO_STRING, &attname_len);
3744
if (!SQL_SUCCEEDED(result))
3746
SC_error_copy(stmt, tbl_stmt, TRUE);
3750
result = PGAPI_BindCol(htbl_stmt, 3, internal_asis_type,
3751
pkname, TABLE_NAME_STORAGE_LEN, NULL);
3752
if (!SQL_SUCCEEDED(result))
3754
SC_error_copy(stmt, tbl_stmt, TRUE);
3758
result = PGAPI_BindCol(htbl_stmt, 4, internal_asis_type,
3759
pkscm, SCHEMA_NAME_STORAGE_LEN, &pkscm_len);
3760
if (!SQL_SUCCEEDED(result))
3762
SC_error_copy(stmt, tbl_stmt, TRUE);
3766
result = PGAPI_BindCol(htbl_stmt, 5, internal_asis_type,
3767
tabname, TABLE_NAME_STORAGE_LEN, &tabname_len);
3768
if (!SQL_SUCCEEDED(result))
3770
SC_error_copy(stmt, tbl_stmt, TRUE);
3775
if (PG_VERSION_LE(conn, 6.4))
3783
for (qno = qstart; qno <= qend; qno++)
3785
size_t qsize, tsize;
3793
* Simplified query to remove assumptions about number of
3794
* possible index columns. Courtesy of Tom Lane - thomas
3797
if (conn->schema_support)
3799
strncpy_null(tables_query,
3800
"select ta.attname, ia.attnum, ic.relname, n.nspname, tc.relname"
3801
" from pg_catalog.pg_attribute ta,"
3802
" pg_catalog.pg_attribute ia, pg_catalog.pg_class tc,"
3803
" pg_catalog.pg_index i, pg_catalog.pg_namespace n"
3804
", pg_catalog.pg_class ic"
3805
, sizeof(tables_query));
3806
qsize = strlen(tables_query);
3807
tsize = sizeof(tables_query) - qsize;
3808
tbqry = tables_query + qsize;
3810
snprintf(tbqry, tsize,
3811
" where tc.relname %s'%s'"
3812
" AND n.nspname %s'%s'"
3813
, eq_string, escTableName, eq_string, pkscm);
3815
snprintf(tbqry, tsize,
3816
" where tc.oid = " FORMAT_UINT4
3819
strlcat(tables_query,
3820
" AND tc.oid = i.indrelid"
3821
" AND n.oid = tc.relnamespace"
3822
" AND i.indisprimary = 't'"
3823
" AND ia.attrelid = i.indexrelid"
3824
" AND ta.attrelid = i.indrelid"
3825
" AND ta.attnum = i.indkey[ia.attnum-1]"
3826
" AND (NOT ta.attisdropped)"
3827
" AND (NOT ia.attisdropped)"
3828
" AND ic.oid = i.indexrelid"
3829
" order by ia.attnum"
3830
, sizeof(tables_query));
3834
strncpy_null(tables_query,
3835
"select ta.attname, ia.attnum, ic.relname, NULL, tc.relname"
3836
" from pg_attribute ta, pg_attribute ia, pg_class tc, pg_index i, pg_class ic"
3837
, sizeof(tables_query));
3838
qsize = strlen(tables_query);
3839
tsize = sizeof(tables_query) - qsize;
3840
tbqry = tables_query + qsize;
3842
snprintf(tbqry, tsize,
3843
" where tc.relname %s'%s'"
3844
, eq_string, escTableName);
3846
snprintf(tbqry, tsize,
3847
" where tc.oid = " FORMAT_UINT4, reloid);
3849
strlcat(tables_query,
3850
" AND tc.oid = i.indrelid"
3851
" AND i.indisprimary = 't'"
3852
" AND ia.attrelid = i.indexrelid"
3853
" AND ta.attrelid = i.indrelid"
3854
" AND ta.attnum = i.indkey[ia.attnum-1]"
3855
" AND ic.oid = i.indexrelid"
3856
" order by ia.attnum"
3857
, sizeof(tables_query));
3863
* Simplified query to search old fashoned primary key
3865
if (conn->schema_support)
3866
snprintf(tables_query, sizeof(tables_query), "select ta.attname, ia.attnum, ic.relname, n.nspname, NULL"
3867
" from pg_catalog.pg_attribute ta,"
3868
" pg_catalog.pg_attribute ia, pg_catalog.pg_class ic,"
3869
" pg_catalog.pg_index i, pg_catalog.pg_namespace n"
3870
" where ic.relname %s'%s_pkey'"
3871
" AND n.nspname %s'%s'"
3872
" AND ic.oid = i.indexrelid"
3873
" AND n.oid = ic.relnamespace"
3874
" AND ia.attrelid = i.indexrelid"
3875
" AND ta.attrelid = i.indrelid"
3876
" AND ta.attnum = i.indkey[ia.attnum-1]"
3877
" AND (NOT ta.attisdropped)"
3878
" AND (NOT ia.attisdropped)"
3879
" order by ia.attnum", eq_string, escTableName, eq_string, pkscm);
3881
snprintf(tables_query, sizeof(tables_query), "select ta.attname, ia.attnum, ic.relname, NULL, NULL"
3882
" from pg_attribute ta, pg_attribute ia, pg_class ic, pg_index i"
3883
" where ic.relname %s'%s_pkey'"
3884
" AND ic.oid = i.indexrelid"
3885
" AND ia.attrelid = i.indexrelid"
3886
" AND ta.attrelid = i.indrelid"
3887
" AND ta.attnum = i.indkey[ia.attnum-1]"
3888
" order by ia.attnum", eq_string, escTableName);
3891
mylog("%s: tables_query='%s'\n", func, tables_query);
3893
result = PGAPI_ExecDirect(htbl_stmt, tables_query, SQL_NTS, 0);
3894
if (!SQL_SUCCEEDED(result))
3896
SC_full_error_copy(stmt, tbl_stmt, FALSE);
3901
result = PGAPI_Fetch(htbl_stmt);
3902
if (result != SQL_NO_DATA_FOUND)
3907
if (conn->schema_support &&
3908
SQL_NO_DATA_FOUND == result)
3911
allow_public_schema(conn, szSchemaName, cbSchemaName))
3913
szSchemaName = pubstr;
3914
cbSchemaName = SQL_NTS;
3915
goto retry_public_schema;
3919
while (SQL_SUCCEEDED(result))
3921
tuple = QR_AddNew(res);
3923
set_tuplefield_string(&tuple[PKS_TABLE_CAT], CurrCat(conn));
3926
* I have to hide the table owner from Access, otherwise it
3927
* insists on referring to the table as 'owner.table'. (this is
3928
* valid according to the ODBC SQL grammar, but Postgres won't
3931
if (SQL_NULL_DATA == pkscm_len)
3933
set_tuplefield_string(&tuple[PKS_TABLE_SCHEM], GET_SCHEMA_NAME(pkscm));
3934
if (SQL_NULL_DATA == tabname_len)
3936
pktbname = pktab ? pktab : tabname;
3937
set_tuplefield_string(&tuple[PKS_TABLE_NAME], pktbname);
3938
set_tuplefield_string(&tuple[PKS_COLUMN_NAME], attname);
3939
set_tuplefield_int2(&tuple[PKS_KEY_SQ], (Int2) (++seq));
3940
set_tuplefield_string(&tuple[PKS_PK_NAME], pkname);
3942
mylog(">> primaryKeys: schema ='%s', pktab = '%s', attname = '%s', seq = %d\n", pkscm, pktbname, attname, seq);
3944
result = PGAPI_Fetch(htbl_stmt);
3947
if (result != SQL_NO_DATA_FOUND)
3949
SC_full_error_copy(stmt, htbl_stmt, FALSE);
3958
* also, things need to think that this statement is finished so the
3959
* results can be retrieved.
3961
stmt->status = STMT_FINISHED;
3964
PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
3969
free(escSchemaName);
3972
/* set up the current tuple pointer for SQLFetch */
3973
stmt->currTuple = -1;
3974
SC_set_rowset_start(stmt, -1, FALSE);
3975
SC_set_current_col(stmt, -1);
3978
ret = DiscardStatementSvp(stmt, ret, FALSE);
3979
mylog("%s: EXIT, stmt=%p, ret=%d\n", func, stmt, ret);
3985
* Multibyte support stuff for SQLForeignKeys().
3986
* There may be much more effective way in the
3987
* future version. The way is very forcible currently.
3990
isMultibyte(const UCHAR *str)
4000
getClientColumnName(ConnectionClass *conn, UInt4 relid, char *serverColumnName, BOOL *nameAlloced)
4002
char query[1024], saveattnum[16],
4003
*ret = serverColumnName;
4004
const char *eq_string;
4005
BOOL continueExec = TRUE,
4007
QResultClass *res = NULL;
4008
UWORD flag = IGNORE_ABORT_ON_CONN | ROLLBACK_ON_ERROR;
4010
*nameAlloced = FALSE;
4011
if (!conn->original_client_encoding || !isMultibyte(serverColumnName))
4013
if (!conn->server_encoding)
4015
if (res = CC_send_query(conn, "select getdatabaseencoding()", NULL, flag, NULL), QR_command_maybe_successful(res))
4017
if (QR_get_num_cached_tuples(res) > 0)
4018
conn->server_encoding = strdup(QR_get_value_backend_text(res, 0, 0));
4023
if (!conn->server_encoding)
4025
snprintf(query, sizeof(query), "SET CLIENT_ENCODING TO '%s'", conn->server_encoding);
4026
bError = (!QR_command_maybe_successful((res = CC_send_query(conn, query, NULL, flag, NULL))));
4028
eq_string = gen_opestr(eqop, conn);
4029
if (!bError && continueExec)
4031
snprintf(query, sizeof(query), "select attnum from pg_attribute "
4032
"where attrelid = %u and attname %s'%s'",
4033
relid, eq_string, serverColumnName);
4034
if (res = CC_send_query(conn, query, NULL, flag, NULL), QR_command_maybe_successful(res))
4036
if (QR_get_num_cached_tuples(res) > 0)
4038
strcpy(saveattnum, QR_get_value_backend_text(res, 0, 0));
4041
continueExec = FALSE;
4047
continueExec = (continueExec && !bError);
4048
/* restore the cleint encoding */
4049
snprintf(query, sizeof(query), "SET CLIENT_ENCODING TO '%s'", conn->original_client_encoding);
4050
bError = (!QR_command_maybe_successful((res = CC_send_query(conn, query, NULL, flag, NULL))));
4052
if (bError || !continueExec)
4054
snprintf(query, sizeof(query), "select attname from pg_attribute where attrelid = %u and attnum = %s", relid, saveattnum);
4055
if (res = CC_send_query(conn, query, NULL, flag, NULL), QR_command_maybe_successful(res))
4057
if (QR_get_num_cached_tuples(res) > 0)
4059
ret = strdup(QR_get_value_backend_text(res, 0, 0));
4060
*nameAlloced = TRUE;
4067
static RETCODE SQL_API
4068
PGAPI_ForeignKeys_new(
4070
const SQLCHAR FAR * szPkTableQualifier, /* OA X*/
4071
SQLSMALLINT cbPkTableQualifier,
4072
const SQLCHAR FAR * szPkTableOwner, /* OA E*/
4073
SQLSMALLINT cbPkTableOwner,
4074
const SQLCHAR FAR * szPkTableName, /* OA(R) E*/
4075
SQLSMALLINT cbPkTableName,
4076
const SQLCHAR FAR * szFkTableQualifier, /* OA X*/
4077
SQLSMALLINT cbFkTableQualifier,
4078
const SQLCHAR FAR * szFkTableOwner, /* OA E*/
4079
SQLSMALLINT cbFkTableOwner,
4080
const SQLCHAR FAR * szFkTableName, /* OA(R) E*/
4081
SQLSMALLINT cbFkTableName);
4083
static RETCODE SQL_API
4084
PGAPI_ForeignKeys_old(
4086
const SQLCHAR FAR * szPkTableQualifier, /* OA X*/
4087
SQLSMALLINT cbPkTableQualifier,
4088
const SQLCHAR FAR * szPkTableOwner, /* OA E*/
4089
SQLSMALLINT cbPkTableOwner,
4090
const SQLCHAR FAR * szPkTableName, /* OA(R) E*/
4091
SQLSMALLINT cbPkTableName,
4092
const SQLCHAR FAR * szFkTableQualifier, /* OA X*/
4093
SQLSMALLINT cbFkTableQualifier,
4094
const SQLCHAR FAR * szFkTableOwner, /* OA E*/
4095
SQLSMALLINT cbFkTableOwner,
4096
const SQLCHAR FAR * szFkTableName, /* OA(R) E*/
4097
SQLSMALLINT cbFkTableName)
4099
CSTR func = "PGAPI_ForeignKeys";
4100
StatementClass *stmt = (StatementClass *) hstmt;
4103
HSTMT htbl_stmt = NULL, hpkey_stmt = NULL;
4104
StatementClass *tbl_stmt;
4105
RETCODE ret = SQL_ERROR, result, keyresult;
4106
char tables_query[INFO_INQUIRY_LEN];
4107
char trig_deferrable[2];
4108
char trig_initdeferred[2];
4109
char trig_args[1024];
4110
char upd_rule[TABLE_NAME_STORAGE_LEN],
4111
del_rule[TABLE_NAME_STORAGE_LEN];
4112
char *pk_table_needed = NULL, *escPkTableName = NULL;
4113
char fk_table_fetched[TABLE_NAME_STORAGE_LEN + 1];
4114
char *fk_table_needed = NULL, *escFkTableName = NULL;
4115
char pk_table_fetched[TABLE_NAME_STORAGE_LEN + 1];
4116
char schema_needed[SCHEMA_NAME_STORAGE_LEN + 1];
4117
char schema_fetched[SCHEMA_NAME_STORAGE_LEN + 1];
4118
char constrname[NAMESTORAGELEN + 1], pkname[TABLE_NAME_STORAGE_LEN + 1];
4124
ConnectionClass *conn;
4126
fkey_alloced, got_pkname;
4131
SQLSMALLINT trig_nargs,
4134
SQLSMALLINT internal_asis_type = SQL_C_CHAR;
4136
#if (ODBCVER >= 0x0300)
4137
SQLSMALLINT defer_type;
4139
char pkey[MAX_INFO_STRING];
4141
UInt4 relid1, relid2;
4142
const char *eq_string;
4144
mylog("%s: entering...stmt=%p\n", func, stmt);
4146
if (result = SC_initialize_and_recycle(stmt), SQL_SUCCESS != result)
4149
if (res = QR_Constructor(), !res)
4151
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate memory for PGAPI_ForeignKeys result.", func);
4154
SC_set_Result(stmt, res);
4156
/* the binding structure for a statement is not set up until */
4159
* a statement is actually executed, so we'll have to do this
4162
result_cols = NUM_OF_FKS_FIELDS;
4163
extend_column_bindings(SC_get_ARDF(stmt), result_cols);
4165
stmt->catalog_result = TRUE;
4166
/* set the field names */
4167
QR_set_num_fields(res, result_cols);
4168
QR_set_field_info_v(res, FKS_PKTABLE_CAT, "PKTABLE_QUALIFIER", PG_TYPE_VARCHAR, MAX_INFO_STRING);
4169
QR_set_field_info_v(res, FKS_PKTABLE_SCHEM, "PKTABLE_OWNER", PG_TYPE_VARCHAR, MAX_INFO_STRING);
4170
QR_set_field_info_v(res, FKS_PKTABLE_NAME, "PKTABLE_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
4171
QR_set_field_info_v(res, FKS_PKCOLUMN_NAME, "PKCOLUMN_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
4172
QR_set_field_info_v(res, FKS_FKTABLE_CAT, "FKTABLE_QUALIFIER", PG_TYPE_VARCHAR, MAX_INFO_STRING);
4173
QR_set_field_info_v(res, FKS_FKTABLE_SCHEM, "FKTABLE_OWNER", PG_TYPE_VARCHAR, MAX_INFO_STRING);
4174
QR_set_field_info_v(res, FKS_FKTABLE_NAME, "FKTABLE_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
4175
QR_set_field_info_v(res, FKS_FKCOLUMN_NAME, "FKCOLUMN_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
4176
QR_set_field_info_v(res, FKS_KEY_SEQ, "KEY_SEQ", PG_TYPE_INT2, 2);
4177
QR_set_field_info_v(res, FKS_UPDATE_RULE, "UPDATE_RULE", PG_TYPE_INT2, 2);
4178
QR_set_field_info_v(res, FKS_DELETE_RULE, "DELETE_RULE", PG_TYPE_INT2, 2);
4179
QR_set_field_info_v(res, FKS_FK_NAME, "FK_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
4180
QR_set_field_info_v(res, FKS_PK_NAME, "PK_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
4181
#if (ODBCVER >= 0x0300)
4182
QR_set_field_info_v(res, FKS_DEFERRABILITY, "DEFERRABILITY", PG_TYPE_INT2, 2);
4183
#endif /* ODBCVER >= 0x0300 */
4184
QR_set_field_info_v(res, FKS_TRIGGER_NAME, "TRIGGER_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
4187
* also, things need to think that this statement is finished so the
4188
* results can be retrieved.
4190
stmt->status = STMT_FINISHED;
4192
/* set up the current tuple pointer for SQLFetch */
4193
stmt->currTuple = -1;
4194
SC_set_rowset_start(stmt, -1, FALSE);
4195
SC_set_current_col(stmt, -1);
4197
conn = SC_get_conn(stmt);
4198
result = PGAPI_AllocStmt(conn, &htbl_stmt, 0);
4199
if (!SQL_SUCCEEDED(result))
4201
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate statement for PGAPI_ForeignKeys result.", func);
4205
#define return DONT_CALL_RETURN_FROM_HERE???
4207
tbl_stmt = (StatementClass *) htbl_stmt;
4208
schema_needed[0] = '\0';
4209
schema_fetched[0] = '\0';
4211
pk_table_needed = make_string(szPkTableName, cbPkTableName, NULL, 0);
4212
fk_table_needed = make_string(szFkTableName, cbFkTableName, NULL, 0);
4214
#ifdef UNICODE_SUPPORT
4215
if (CC_is_in_unicode_driver(conn))
4216
internal_asis_type = INTERNAL_ASIS_TYPE;
4217
#endif /* UNICODE_SUPPORT */
4218
pkey_alloced = fkey_alloced = FALSE;
4220
eq_string = gen_opestr(eqop, conn);
4222
* Case #2 -- Get the foreign keys in the specified table (fktab) that
4223
* refer to the primary keys of other table(s).
4225
if (fk_table_needed && fk_table_needed[0] != '\0')
4227
mylog("%s: entering Foreign Key Case #2", func);
4228
escFkTableName = simpleCatalogEscape(fk_table_needed, SQL_NTS, NULL, conn);
4229
if (conn->schema_support)
4231
char *escSchemaName;
4233
schema_strcat(schema_needed, "%.*s", szFkTableOwner, cbFkTableOwner, szFkTableName, cbFkTableName, conn);
4234
escSchemaName = simpleCatalogEscape(schema_needed, SQL_NTS, NULL, conn);
4235
snprintf(tables_query, sizeof(tables_query), "SELECT pt.tgargs, "
4237
" pt.tgdeferrable, "
4238
" pt.tginitdeferred, "
4244
" pt.tgconstrname, pn.nspname "
4245
"FROM pg_catalog.pg_class pc, "
4246
" pg_catalog.pg_proc pp1, "
4247
" pg_catalog.pg_proc pp2, "
4248
" pg_catalog.pg_trigger pt1, "
4249
" pg_catalog.pg_trigger pt2, "
4250
" pg_catalog.pg_proc pp, "
4251
" pg_catalog.pg_trigger pt, "
4252
" pg_catalog.pg_class pc1, "
4253
" pg_catalog.pg_namespace pn, "
4254
" pg_catalog.pg_namespace pn1 "
4255
"WHERE pt.tgrelid = pc.oid "
4256
"AND pp.oid = pt.tgfoid "
4257
"AND pt1.tgconstrrelid = pc.oid "
4258
"AND pp1.oid = pt1.tgfoid "
4259
"AND pt2.tgfoid = pp2.oid "
4260
"AND pt2.tgconstrrelid = pc.oid "
4261
"AND ((pc.relname %s'%s') "
4262
"AND (pn1.oid = pc.relnamespace) "
4263
"AND (pn1.nspname %s'%s') "
4264
"AND (pp.proname LIKE '%%ins') "
4265
"AND (pp1.proname LIKE '%%upd') "
4266
"AND (pp1.proname not LIKE '%%check%%') "
4267
"AND (pp2.proname LIKE '%%del') "
4268
"AND (pt1.tgrelid=pt.tgconstrrelid) "
4269
"AND (pt1.tgconstrname=pt.tgconstrname) "
4270
"AND (pt2.tgrelid=pt.tgconstrrelid) "
4271
"AND (pt2.tgconstrname=pt.tgconstrname) "
4272
"AND (pt.tgconstrrelid=pc1.oid) "
4273
"AND (pc1.relnamespace=pn.oid))"
4274
" order by pt.tgconstrname",
4275
eq_string, escFkTableName, eq_string, escSchemaName);
4276
free(escSchemaName);
4279
snprintf(tables_query, sizeof(tables_query), "SELECT pt.tgargs, "
4281
" pt.tgdeferrable, "
4282
" pt.tginitdeferred, "
4287
" pc1.relname, pt.tgconstrname "
4288
"FROM pg_class pc, "
4296
"WHERE pt.tgrelid = pc.oid "
4297
"AND pp.oid = pt.tgfoid "
4298
"AND pt1.tgconstrrelid = pc.oid "
4299
"AND pp1.oid = pt1.tgfoid "
4300
"AND pt2.tgfoid = pp2.oid "
4301
"AND pt2.tgconstrrelid = pc.oid "
4302
"AND ((pc.relname %s'%s') "
4303
"AND (pp.proname LIKE '%%ins') "
4304
"AND (pp1.proname LIKE '%%upd') "
4305
"AND (pp1.proname not LIKE '%%check%%') "
4306
"AND (pp2.proname LIKE '%%del') "
4307
"AND (pt1.tgrelid=pt.tgconstrrelid) "
4308
"AND (pt1.tgconstrname=pt.tgconstrname) "
4309
"AND (pt2.tgrelid=pt.tgconstrrelid) "
4310
"AND (pt2.tgconstrname=pt.tgconstrname) "
4311
"AND (pt.tgconstrrelid=pc1.oid)) "
4312
"order by pt.tgconstrname",
4313
eq_string, escFkTableName);
4315
result = PGAPI_ExecDirect(htbl_stmt, tables_query, SQL_NTS, 0);
4317
if (!SQL_SUCCEEDED(result))
4319
SC_full_error_copy(stmt, tbl_stmt, FALSE);
4323
result = PGAPI_BindCol(htbl_stmt, 1, SQL_C_BINARY,
4324
trig_args, sizeof(trig_args), NULL);
4325
if (!SQL_SUCCEEDED(result))
4327
SC_error_copy(stmt, tbl_stmt, TRUE);
4331
result = PGAPI_BindCol(htbl_stmt, 2, SQL_C_SHORT,
4332
&trig_nargs, 0, NULL);
4333
if (!SQL_SUCCEEDED(result))
4335
SC_error_copy(stmt, tbl_stmt, TRUE);
4339
result = PGAPI_BindCol(htbl_stmt, 3, internal_asis_type,
4340
trig_deferrable, sizeof(trig_deferrable), NULL);
4341
if (!SQL_SUCCEEDED(result))
4343
SC_error_copy(stmt, tbl_stmt, TRUE);
4347
result = PGAPI_BindCol(htbl_stmt, 4, internal_asis_type,
4348
trig_initdeferred, sizeof(trig_initdeferred), NULL);
4349
if (!SQL_SUCCEEDED(result))
4351
SC_error_copy(stmt, tbl_stmt, TRUE);
4355
result = PGAPI_BindCol(htbl_stmt, 5, internal_asis_type,
4356
upd_rule, sizeof(upd_rule), NULL);
4357
if (!SQL_SUCCEEDED(result))
4359
SC_error_copy(stmt, tbl_stmt, TRUE);
4363
result = PGAPI_BindCol(htbl_stmt, 6, internal_asis_type,
4364
del_rule, sizeof(del_rule), NULL);
4365
if (!SQL_SUCCEEDED(result))
4367
SC_error_copy(stmt, tbl_stmt, TRUE);
4371
result = PGAPI_BindCol(htbl_stmt, 7, SQL_C_ULONG,
4372
&relid1, sizeof(relid1), NULL);
4373
if (!SQL_SUCCEEDED(result))
4375
SC_error_copy(stmt, tbl_stmt, TRUE);
4378
result = PGAPI_BindCol(htbl_stmt, 8, SQL_C_ULONG,
4379
&relid2, sizeof(relid2), NULL);
4380
if (!SQL_SUCCEEDED(result))
4382
SC_error_copy(stmt, tbl_stmt, TRUE);
4385
result = PGAPI_BindCol(htbl_stmt, 9, internal_asis_type,
4386
pk_table_fetched, TABLE_NAME_STORAGE_LEN, NULL);
4387
if (!SQL_SUCCEEDED(result))
4389
SC_error_copy(stmt, tbl_stmt, TRUE);
4392
result = PGAPI_BindCol(htbl_stmt, 10, internal_asis_type,
4393
constrname, NAMESTORAGELEN, NULL);
4394
if (!SQL_SUCCEEDED(result))
4396
SC_error_copy(stmt, tbl_stmt, TRUE);
4400
if (conn->schema_support)
4402
result = PGAPI_BindCol(htbl_stmt, 11, internal_asis_type,
4403
schema_fetched, SCHEMA_NAME_STORAGE_LEN, NULL);
4404
if (!SQL_SUCCEEDED(result))
4406
SC_error_copy(stmt, tbl_stmt, TRUE);
4411
result = PGAPI_Fetch(htbl_stmt);
4412
if (result == SQL_NO_DATA_FOUND)
4418
if (result != SQL_SUCCESS)
4420
SC_full_error_copy(stmt, tbl_stmt, FALSE);
4424
keyresult = PGAPI_AllocStmt(conn, &hpkey_stmt, 0);
4425
if (!SQL_SUCCEEDED(keyresult))
4427
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate statement for PGAPI_ForeignKeys (pkeys) result.", func);
4431
keyresult = PGAPI_BindCol(hpkey_stmt, 4, internal_asis_type,
4432
pkey, sizeof(pkey), NULL);
4433
if (keyresult != SQL_SUCCESS)
4435
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't bindcol for primary keys for PGAPI_ForeignKeys result.", func);
4439
while (result == SQL_SUCCESS)
4441
/* Compute the number of keyparts. */
4442
num_keys = (trig_nargs - 4) / 2;
4444
mylog("Foreign Key Case#2: trig_nargs = %d, num_keys = %d\n", trig_nargs, num_keys);
4446
/* If there is a pk table specified, then check it. */
4447
if (pk_table_needed && pk_table_needed[0] != '\0')
4449
/* If it doesn't match, then continue */
4450
if (strcmp(pk_table_fetched, pk_table_needed))
4452
result = PGAPI_Fetch(htbl_stmt);
4458
keyresult = PGAPI_PrimaryKeys(hpkey_stmt, NULL, 0, schema_fetched, SQL_NTS, pk_table_fetched, SQL_NTS, 0);
4459
if (keyresult != SQL_SUCCESS)
4461
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't get primary keys for PGAPI_ForeignKeys result.", func);
4465
/* Get to first primary key */
4466
pkey_ptr = trig_args;
4467
for (i = 0; i < 5; i++)
4468
pkey_ptr += strlen(pkey_ptr) + 1;
4470
for (k = 0; k < num_keys; k++)
4472
/* Check that the key listed is the primary key */
4473
keyresult = PGAPI_Fetch(hpkey_stmt);
4474
if (keyresult != SQL_SUCCESS)
4481
PGAPI_GetData(hpkey_stmt, 6, internal_asis_type, pkname, sizeof(pkname), NULL);
4484
pkey_text = getClientColumnName(conn, relid2, pkey_ptr, &pkey_alloced);
4485
mylog("%s: pkey_ptr='%s', pkey='%s'\n", func, pkey_text, pkey);
4486
if (strcmp(pkey_text, pkey))
4493
/* Get to next primary key */
4494
for (k = 0; k < 2; k++)
4495
pkey_ptr += strlen(pkey_ptr) + 1;
4498
PGAPI_FreeStmt(hpkey_stmt, SQL_CLOSE);
4500
/* Set to first fk column */
4501
fkey_ptr = trig_args;
4502
for (k = 0; k < 4; k++)
4503
fkey_ptr += strlen(fkey_ptr) + 1;
4505
/* Set update and delete actions for foreign keys */
4506
if (!strcmp(upd_rule, "RI_FKey_cascade_upd"))
4507
upd_rule_type = SQL_CASCADE;
4508
else if (!strcmp(upd_rule, "RI_FKey_noaction_upd"))
4509
upd_rule_type = SQL_NO_ACTION;
4510
else if (!strcmp(upd_rule, "RI_FKey_restrict_upd"))
4511
upd_rule_type = SQL_NO_ACTION;
4512
else if (!strcmp(upd_rule, "RI_FKey_setdefault_upd"))
4513
upd_rule_type = SQL_SET_DEFAULT;
4514
else if (!strcmp(upd_rule, "RI_FKey_setnull_upd"))
4515
upd_rule_type = SQL_SET_NULL;
4517
if (!strcmp(del_rule, "RI_FKey_cascade_del"))
4518
del_rule_type = SQL_CASCADE;
4519
else if (!strcmp(del_rule, "RI_FKey_noaction_del"))
4520
del_rule_type = SQL_NO_ACTION;
4521
else if (!strcmp(del_rule, "RI_FKey_restrict_del"))
4522
del_rule_type = SQL_NO_ACTION;
4523
else if (!strcmp(del_rule, "RI_FKey_setdefault_del"))
4524
del_rule_type = SQL_SET_DEFAULT;
4525
else if (!strcmp(del_rule, "RI_FKey_setnull_del"))
4526
del_rule_type = SQL_SET_NULL;
4528
#if (ODBCVER >= 0x0300)
4529
/* Set deferrability type */
4530
if (!strcmp(trig_initdeferred, "y"))
4531
defer_type = SQL_INITIALLY_DEFERRED;
4532
else if (!strcmp(trig_deferrable, "y"))
4533
defer_type = SQL_INITIALLY_IMMEDIATE;
4535
defer_type = SQL_NOT_DEFERRABLE;
4536
#endif /* ODBCVER >= 0x0300 */
4538
/* Get to first primary key */
4539
pkey_ptr = trig_args;
4540
for (i = 0; i < 5; i++)
4541
pkey_ptr += strlen(pkey_ptr) + 1;
4543
for (k = 0; k < num_keys; k++)
4545
tuple = QR_AddNew(res);
4547
pkey_text = getClientColumnName(conn, relid2, pkey_ptr, &pkey_alloced);
4548
fkey_text = getClientColumnName(conn, relid1, fkey_ptr, &fkey_alloced);
4550
mylog("%s: pk_table = '%s', pkey_ptr = '%s'\n", func, pk_table_fetched, pkey_text);
4551
set_tuplefield_string(&tuple[FKS_PKTABLE_CAT], CurrCat(conn));
4552
set_tuplefield_string(&tuple[FKS_PKTABLE_SCHEM], GET_SCHEMA_NAME(schema_fetched));
4553
set_tuplefield_string(&tuple[FKS_PKTABLE_NAME], pk_table_fetched);
4554
set_tuplefield_string(&tuple[FKS_PKCOLUMN_NAME], pkey_text);
4556
mylog("%s: fk_table_needed = '%s', fkey_ptr = '%s'\n", func, fk_table_needed, fkey_text);
4557
set_tuplefield_string(&tuple[FKS_FKTABLE_CAT], CurrCat(conn));
4558
set_tuplefield_string(&tuple[FKS_FKTABLE_SCHEM], GET_SCHEMA_NAME(schema_needed));
4559
set_tuplefield_string(&tuple[FKS_FKTABLE_NAME], fk_table_needed);
4560
set_tuplefield_string(&tuple[FKS_FKCOLUMN_NAME], fkey_text);
4562
mylog("%s: upd_rule_type = '%i', del_rule_type = '%i'\n, trig_name = '%s'", func, upd_rule_type, del_rule_type, trig_args);
4563
set_tuplefield_int2(&tuple[FKS_KEY_SEQ], (Int2) (k + 1));
4564
set_tuplefield_int2(&tuple[FKS_UPDATE_RULE], upd_rule_type);
4565
set_tuplefield_int2(&tuple[FKS_DELETE_RULE], del_rule_type);
4566
set_tuplefield_string(&tuple[FKS_FK_NAME], constrname);
4567
set_tuplefield_string(&tuple[FKS_PK_NAME], pkname);
4568
#if (ODBCVER >= 0x0300)
4569
set_tuplefield_int2(&tuple[FKS_DEFERRABILITY], defer_type);
4570
#endif /* ODBCVER >= 0x0300 */
4571
set_tuplefield_string(&tuple[FKS_TRIGGER_NAME], trig_args);
4575
fkey_alloced = FALSE;
4578
pkey_alloced = FALSE;
4579
/* next primary/foreign key */
4580
for (i = 0; i < 2; i++)
4582
fkey_ptr += strlen(fkey_ptr) + 1;
4583
pkey_ptr += strlen(pkey_ptr) + 1;
4587
result = PGAPI_Fetch(htbl_stmt);
4592
* Case #1 -- Get the foreign keys in other tables that refer to the
4593
* primary key in the specified table (pktab). i.e., Who points to
4596
else if (pk_table_needed[0] != '\0')
4598
escPkTableName = simpleCatalogEscape(pk_table_needed, SQL_NTS, NULL, conn);
4599
if (conn->schema_support)
4601
char *escSchemaName;
4603
schema_strcat(schema_needed, "%.*s", szPkTableOwner, cbPkTableOwner, szPkTableName, cbPkTableName, conn);
4604
escSchemaName = simpleCatalogEscape(schema_needed, SQL_NTS, NULL, conn);
4605
snprintf(tables_query, sizeof(tables_query), "SELECT pt.tgargs, "
4607
" pt.tgdeferrable, "
4608
" pt.tginitdeferred, "
4614
" pt.tgconstrname, pn1.nspname "
4615
"FROM pg_catalog.pg_class pc, "
4616
" pg_catalog.pg_class pc1, "
4617
" pg_catalog.pg_proc pp, "
4618
" pg_catalog.pg_proc pp1, "
4619
" pg_catalog.pg_proc pp2, "
4620
" pg_catalog.pg_trigger pt, "
4621
" pg_catalog.pg_trigger pt1, "
4622
" pg_catalog.pg_trigger pt2, "
4623
" pg_catalog.pg_namespace pn, "
4624
" pg_catalog.pg_namespace pn1 "
4625
"WHERE pc.relname %s'%s' "
4626
" AND pn.nspname %s'%s' "
4627
" AND pc.relnamespace = pn.oid "
4628
" AND pt.tgconstrrelid = pc.oid "
4629
" AND pp.oid = pt.tgfoid "
4630
" AND pp.proname Like '%%ins' "
4631
" AND pt1.tgconstrname = pt.tgconstrname "
4632
" AND pt1.tgconstrrelid = pt.tgrelid "
4633
" AND pt1.tgrelid = pc.oid "
4634
" AND pc1.oid = pt.tgrelid "
4635
" AND pp1.oid = pt1.tgfoid "
4636
" AND pp1.proname like '%%upd' "
4637
" AND (pp1.proname not like '%%check%%') "
4638
" AND pt2.tgconstrname = pt.tgconstrname "
4639
" AND pt2.tgconstrrelid = pt.tgrelid "
4640
" AND pt2.tgrelid = pc.oid "
4641
" AND pp2.oid = pt2.tgfoid "
4642
" AND pp2.proname Like '%%del' "
4643
" AND pn1.oid = pc1.relnamespace "
4644
" order by pt.tgconstrname",
4645
eq_string, escPkTableName, eq_string, escSchemaName);
4646
free(escSchemaName);
4649
snprintf(tables_query, sizeof(tables_query), "SELECT pt.tgargs, "
4651
" pt.tgdeferrable, "
4652
" pt.tginitdeferred, "
4657
" pc1.relname, pt.tgconstrname "
4658
"FROM pg_class pc, "
4666
"WHERE pc.relname %s'%s' "
4667
" AND pt.tgconstrrelid = pc.oid "
4668
" AND pp.oid = pt.tgfoid "
4669
" AND pp.proname Like '%%ins' "
4670
" AND pt1.tgconstrname = pt.tgconstrname "
4671
" AND pt1.tgconstrrelid = pt.tgrelid "
4672
" AND pt1.tgrelid = pc.oid "
4673
" AND pc1.oid = pt.tgrelid "
4674
" AND pp1.oid = pt1.tgfoid "
4675
" AND pp1.proname like '%%upd' "
4676
" AND pp1.(proname not like '%%check%%') "
4677
" AND pt2.tgconstrname = pt.tgconstrname "
4678
" AND pt2.tgconstrrelid = pt.tgrelid "
4679
" AND pt2.tgrelid = pc.oid "
4680
" AND pp2.oid = pt2.tgfoid "
4681
" AND pp2.proname Like '%%del'"
4682
" order by pt.tgconstrname",
4683
eq_string, escPkTableName);
4685
result = PGAPI_ExecDirect(htbl_stmt, tables_query, SQL_NTS, 0);
4686
if (!SQL_SUCCEEDED(result))
4688
SC_error_copy(stmt, tbl_stmt, TRUE);
4692
result = PGAPI_BindCol(htbl_stmt, 1, SQL_C_BINARY,
4693
trig_args, sizeof(trig_args), NULL);
4694
if (!SQL_SUCCEEDED(result))
4696
SC_error_copy(stmt, tbl_stmt, TRUE);
4700
result = PGAPI_BindCol(htbl_stmt, 2, SQL_C_SHORT,
4701
&trig_nargs, 0, NULL);
4702
if (!SQL_SUCCEEDED(result))
4704
SC_error_copy(stmt, tbl_stmt, TRUE);
4708
result = PGAPI_BindCol(htbl_stmt, 3, internal_asis_type,
4709
trig_deferrable, sizeof(trig_deferrable), NULL);
4710
if (!SQL_SUCCEEDED(result))
4712
SC_error_copy(stmt, tbl_stmt, TRUE);
4716
result = PGAPI_BindCol(htbl_stmt, 4, internal_asis_type,
4717
trig_initdeferred, sizeof(trig_initdeferred), NULL);
4718
if (!SQL_SUCCEEDED(result))
4720
SC_error_copy(stmt, tbl_stmt, TRUE);
4724
result = PGAPI_BindCol(htbl_stmt, 5, internal_asis_type,
4725
upd_rule, sizeof(upd_rule), NULL);
4726
if (!SQL_SUCCEEDED(result))
4728
SC_error_copy(stmt, tbl_stmt, TRUE);
4732
result = PGAPI_BindCol(htbl_stmt, 6, internal_asis_type,
4733
del_rule, sizeof(del_rule), NULL);
4734
if (!SQL_SUCCEEDED(result))
4736
SC_error_copy(stmt, tbl_stmt, TRUE);
4740
result = PGAPI_BindCol(htbl_stmt, 7, SQL_C_ULONG,
4741
&relid1, sizeof(relid1), NULL);
4742
if (!SQL_SUCCEEDED(result))
4744
SC_error_copy(stmt, tbl_stmt, TRUE);
4747
result = PGAPI_BindCol(htbl_stmt, 8, SQL_C_ULONG,
4748
&relid2, sizeof(relid2), NULL);
4749
if (!SQL_SUCCEEDED(result))
4751
SC_error_copy(stmt, tbl_stmt, TRUE);
4754
result = PGAPI_BindCol(htbl_stmt, 9, internal_asis_type,
4755
fk_table_fetched, TABLE_NAME_STORAGE_LEN, NULL);
4756
if (!SQL_SUCCEEDED(result))
4758
SC_error_copy(stmt, tbl_stmt, TRUE);
4761
result = PGAPI_BindCol(htbl_stmt, 10, internal_asis_type,
4762
constrname, NAMESTORAGELEN, NULL);
4763
if (!SQL_SUCCEEDED(result))
4765
SC_error_copy(stmt, tbl_stmt, TRUE);
4769
if (conn->schema_support)
4771
result = PGAPI_BindCol(htbl_stmt, 11, internal_asis_type,
4772
schema_fetched, SCHEMA_NAME_STORAGE_LEN, NULL);
4773
if (!SQL_SUCCEEDED(result))
4775
SC_error_copy(stmt, tbl_stmt, TRUE);
4780
result = PGAPI_Fetch(htbl_stmt);
4781
if (result == SQL_NO_DATA_FOUND)
4787
if (result != SQL_SUCCESS)
4789
SC_full_error_copy(stmt, tbl_stmt, FALSE);
4796
keyresult = PGAPI_AllocStmt(conn, &hpkey_stmt, 0);
4797
if (!SQL_SUCCEEDED(keyresult))
4799
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate statement for PGAPI_ForeignKeys (pkeys) result.", func);
4802
keyresult = PGAPI_BindCol(hpkey_stmt, 6, internal_asis_type,
4803
pkname, sizeof(pkname), NULL);
4804
if (keyresult != SQL_SUCCESS)
4806
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't bindcol for primary keys for PGAPI_ForeignKeys result.", func);
4809
keyresult = PGAPI_PrimaryKeys(hpkey_stmt, NULL, 0, schema_needed, SQL_NTS, pk_table_needed, SQL_NTS, 0);
4810
if (keyresult != SQL_SUCCESS)
4812
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't get primary keys for PGAPI_ForeignKeys result.", func);
4816
keyresult = PGAPI_Fetch(hpkey_stmt);
4817
PGAPI_FreeStmt(hpkey_stmt, SQL_CLOSE);
4818
while (result == SQL_SUCCESS)
4820
/* Calculate the number of key parts */
4821
num_keys = (trig_nargs - 4) / 2;;
4823
/* Handle action (i.e., 'cascade', 'restrict', 'setnull') */
4824
if (!strcmp(upd_rule, "RI_FKey_cascade_upd"))
4825
upd_rule_type = SQL_CASCADE;
4826
else if (!strcmp(upd_rule, "RI_FKey_noaction_upd"))
4827
upd_rule_type = SQL_NO_ACTION;
4828
else if (!strcmp(upd_rule, "RI_FKey_restrict_upd"))
4829
upd_rule_type = SQL_NO_ACTION;
4830
else if (!strcmp(upd_rule, "RI_FKey_setdefault_upd"))
4831
upd_rule_type = SQL_SET_DEFAULT;
4832
else if (!strcmp(upd_rule, "RI_FKey_setnull_upd"))
4833
upd_rule_type = SQL_SET_NULL;
4835
if (!strcmp(del_rule, "RI_FKey_cascade_del"))
4836
del_rule_type = SQL_CASCADE;
4837
else if (!strcmp(del_rule, "RI_FKey_noaction_del"))
4838
del_rule_type = SQL_NO_ACTION;
4839
else if (!strcmp(del_rule, "RI_FKey_restrict_del"))
4840
del_rule_type = SQL_NO_ACTION;
4841
else if (!strcmp(del_rule, "RI_FKey_setdefault_del"))
4842
del_rule_type = SQL_SET_DEFAULT;
4843
else if (!strcmp(del_rule, "RI_FKey_setnull_del"))
4844
del_rule_type = SQL_SET_NULL;
4846
#if (ODBCVER >= 0x0300)
4847
/* Set deferrability type */
4848
if (!strcmp(trig_initdeferred, "y"))
4849
defer_type = SQL_INITIALLY_DEFERRED;
4850
else if (!strcmp(trig_deferrable, "y"))
4851
defer_type = SQL_INITIALLY_IMMEDIATE;
4853
defer_type = SQL_NOT_DEFERRABLE;
4854
#endif /* ODBCVER >= 0x0300 */
4856
mylog("Foreign Key Case#1: trig_nargs = %d, num_keys = %d\n", trig_nargs, num_keys);
4858
/* Get to first primary key */
4859
pkey_ptr = trig_args;
4860
for (i = 0; i < 5; i++)
4861
pkey_ptr += strlen(pkey_ptr) + 1;
4863
/* Get to first foreign key */
4864
fkey_ptr = trig_args;
4865
for (k = 0; k < 4; k++)
4866
fkey_ptr += strlen(fkey_ptr) + 1;
4868
for (k = 0; k < num_keys; k++)
4870
pkey_text = getClientColumnName(conn, relid1, pkey_ptr, &pkey_alloced);
4871
fkey_text = getClientColumnName(conn, relid2, fkey_ptr, &fkey_alloced);
4873
mylog("pkey_ptr = '%s', fk_table = '%s', fkey_ptr = '%s'\n", pkey_text, fk_table_fetched, fkey_text);
4875
tuple = QR_AddNew(res);
4877
mylog("pk_table_needed = '%s', pkey_ptr = '%s'\n", pk_table_needed, pkey_text);
4878
set_tuplefield_string(&tuple[FKS_PKTABLE_CAT], CurrCat(conn));
4879
set_tuplefield_string(&tuple[FKS_PKTABLE_SCHEM], GET_SCHEMA_NAME(schema_needed));
4880
set_tuplefield_string(&tuple[FKS_PKTABLE_NAME], pk_table_needed);
4881
set_tuplefield_string(&tuple[FKS_PKCOLUMN_NAME], pkey_text);
4883
mylog("fk_table = '%s', fkey_ptr = '%s'\n", fk_table_fetched, fkey_text);
4884
set_tuplefield_string(&tuple[FKS_FKTABLE_CAT], CurrCat(conn));
4885
set_tuplefield_string(&tuple[FKS_FKTABLE_SCHEM], GET_SCHEMA_NAME(schema_fetched));
4886
set_tuplefield_string(&tuple[FKS_FKTABLE_NAME], fk_table_fetched);
4887
set_tuplefield_string(&tuple[FKS_FKCOLUMN_NAME], fkey_text);
4889
set_tuplefield_int2(&tuple[FKS_KEY_SEQ], (Int2) (k + 1));
4891
mylog("upd_rule = %d, del_rule= %d", upd_rule_type, del_rule_type);
4892
set_nullfield_int2(&tuple[FKS_UPDATE_RULE], upd_rule_type);
4893
set_nullfield_int2(&tuple[FKS_DELETE_RULE], del_rule_type);
4895
set_tuplefield_string(&tuple[FKS_FK_NAME], constrname);
4896
set_tuplefield_string(&tuple[FKS_PK_NAME], pkname);
4898
set_tuplefield_string(&tuple[FKS_TRIGGER_NAME], trig_args);
4900
#if (ODBCVER >= 0x0300)
4901
mylog(" defer_type = %d\n", defer_type);
4902
set_tuplefield_int2(&tuple[FKS_DEFERRABILITY], defer_type);
4903
#endif /* ODBCVER >= 0x0300 */
4907
pkey_alloced = FALSE;
4910
fkey_alloced = FALSE;
4912
/* next primary/foreign key */
4913
for (j = 0; j < 2; j++)
4915
pkey_ptr += strlen(pkey_ptr) + 1;
4916
fkey_ptr += strlen(fkey_ptr) + 1;
4919
result = PGAPI_Fetch(htbl_stmt);
4924
SC_set_error(stmt, STMT_INTERNAL_ERROR, "No tables specified to PGAPI_ForeignKeys.", func);
4932
* also, things need to think that this statement is finished so the
4933
* results can be retrieved.
4935
stmt->status = STMT_FINISHED;
4941
if (pk_table_needed)
4942
free(pk_table_needed);
4944
free(escPkTableName);
4945
if (fk_table_needed)
4946
free(fk_table_needed);
4948
free(escFkTableName);
4951
PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
4953
PGAPI_FreeStmt(hpkey_stmt, SQL_DROP);
4955
/* set up the current tuple pointer for SQLFetch */
4956
stmt->currTuple = -1;
4957
SC_set_rowset_start(stmt, -1, FALSE);
4958
SC_set_current_col(stmt, -1);
4961
ret = DiscardStatementSvp(stmt, ret, FALSE);
4962
mylog("%s(): EXIT, stmt=%p, ret=%d\n", func, stmt, ret);
4969
const SQLCHAR FAR * szPkTableQualifier, /* OA X*/
4970
SQLSMALLINT cbPkTableQualifier,
4971
const SQLCHAR FAR * szPkTableOwner, /* OA E*/
4972
SQLSMALLINT cbPkTableOwner,
4973
const SQLCHAR FAR * szPkTableName, /* OA(R) E*/
4974
SQLSMALLINT cbPkTableName,
4975
const SQLCHAR FAR * szFkTableQualifier, /* OA X*/
4976
SQLSMALLINT cbFkTableQualifier,
4977
const SQLCHAR FAR * szFkTableOwner, /* OA E*/
4978
SQLSMALLINT cbFkTableOwner,
4979
const SQLCHAR FAR * szFkTableName, /* OA(R) E*/
4980
SQLSMALLINT cbFkTableName)
4982
ConnectionClass *conn = SC_get_conn(((StatementClass *) hstmt));
4983
if (PG_VERSION_GE(conn, 8.1))
4984
return PGAPI_ForeignKeys_new(hstmt,
4985
szPkTableQualifier, cbPkTableQualifier,
4986
szPkTableOwner, cbPkTableOwner,
4987
szPkTableName, cbPkTableName,
4988
szFkTableQualifier, cbFkTableQualifier,
4989
szFkTableOwner, cbFkTableOwner,
4990
szFkTableName, cbFkTableName);
4992
return PGAPI_ForeignKeys_old(hstmt,
4993
szPkTableQualifier, cbPkTableQualifier,
4994
szPkTableOwner, cbPkTableOwner,
4995
szPkTableName, cbPkTableName,
4996
szFkTableQualifier, cbFkTableQualifier,
4997
szFkTableOwner, cbFkTableOwner,
4998
szFkTableName, cbFkTableName);
5002
#define PRORET_COUNT
5003
#define DISPLAY_ARGNAME
5005
PGAPI_ProcedureColumns(
5007
const SQLCHAR FAR * szProcQualifier, /* OA X*/
5008
SQLSMALLINT cbProcQualifier,
5009
const SQLCHAR FAR * szProcOwner, /* PV E*/
5010
SQLSMALLINT cbProcOwner,
5011
const SQLCHAR FAR * szProcName, /* PV E*/
5012
SQLSMALLINT cbProcName,
5013
const SQLCHAR FAR * szColumnName, /* PV X*/
5014
SQLSMALLINT cbColumnName,
5017
CSTR func = "PGAPI_ProcedureColumns";
5018
StatementClass *stmt = (StatementClass *) hstmt;
5019
ConnectionClass *conn = SC_get_conn(stmt);
5020
char proc_query[INFO_INQUIRY_LEN];
5023
char *schema_name, *procname;
5024
char *escSchemaName = NULL, *escProcName = NULL;
5025
char *params, *proargnames, *proargmodes, *delim = NULL;
5026
char *atttypid, *attname, *column_name;
5027
QResultClass *res, *tres;
5030
Int4 paramcount, column_size, i, j;
5032
BOOL search_pattern, bRetset;
5033
const char *like_or_eq, *op_string, *retset;
5034
int ret_col = -1, ext_pos = -1, poid_pos = -1, attid_pos = -1, attname_pos = -1;
5035
UInt4 poid = 0, newpoid;
5037
mylog("%s: entering...\n", func);
5039
if (PG_VERSION_LT(conn, 6.5))
5041
SC_set_error(stmt, STMT_NOT_IMPLEMENTED_ERROR, "Version is too old", func);
5044
if (result = SC_initialize_and_recycle(stmt), SQL_SUCCESS != result)
5046
search_pattern = (0 == (flag & PODBC_NOT_SEARCH_PATTERN));
5049
like_or_eq = likeop;
5050
escSchemaName = adjustLikePattern(szProcOwner, cbProcOwner, SEARCH_PATTERN_ESCAPE, NULL, conn);
5051
escProcName = adjustLikePattern(szProcName, cbProcName, SEARCH_PATTERN_ESCAPE, NULL, conn);
5056
escSchemaName = simpleCatalogEscape(szProcOwner, cbProcOwner, NULL, conn);
5057
escProcName = simpleCatalogEscape(szProcName, cbProcName, NULL, conn);
5059
op_string = gen_opestr(like_or_eq, conn);
5060
if (conn->schema_support)
5062
strcpy(proc_query, "select proname, proretset, prorettype, "
5063
"pronargs, proargtypes, nspname, p.oid");
5064
ret_col = ext_pos = 7;
5067
strcat(proc_query, ", atttypid, attname");
5068
attid_pos = ext_pos;
5069
attname_pos = ext_pos + 1;
5072
#endif /* PRORET_COUNT */
5073
if (PG_VERSION_GE(conn, 8.0))
5075
strcat(proc_query, ", proargnames");
5078
if (PG_VERSION_GE(conn, 8.1))
5080
strcat(proc_query, ", proargmodes, proallargtypes");
5084
strcat(proc_query, " from ((pg_catalog.pg_namespace n inner join"
5085
" pg_catalog.pg_proc p on p.pronamespace = n.oid)"
5086
" inner join pg_type t on t.oid = p.prorettype)"
5087
" left outer join pg_attribute a on a.attrelid = t.typrelid "
5088
" and attnum > 0 and not attisdropped where");
5090
strcat(proc_query, " from pg_catalog.pg_namespace n,"
5091
" pg_catalog.pg_proc p where");
5092
" p.pronamespace = n.oid and"
5093
" (not proretset) and");
5094
#endif /* PRORET_COUNT */
5095
strcat(proc_query, " has_function_privilege(p.oid, 'EXECUTE')");
5096
my_strcat1(proc_query, " and nspname %s'%.*s'", op_string, escSchemaName, SQL_NTS);
5098
snprintf_add(proc_query, sizeof(proc_query), " and proname %s'%s'", op_string, escProcName);
5099
strcat(proc_query, " order by nspname, proname, p.oid, attnum");
5103
strcpy(proc_query, "select proname, proretset, prorettype, "
5104
"pronargs, proargtypes from pg_proc where "
5108
snprintf_add(proc_query, sizeof(proc_query), " and proname %s'%s'", op_string, escProcName);
5109
strcat(proc_query, " order by proname, proretset");
5111
if (tres = CC_send_query(conn, proc_query, NULL, IGNORE_ABORT_ON_CONN, stmt), !QR_command_maybe_successful(tres))
5113
SC_set_error(stmt, STMT_EXEC_ERROR, "PGAPI_ProcedureColumns query error", func);
5114
QR_Destructor(tres);
5118
if (res = QR_Constructor(), !res)
5120
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate memory for PGAPI_ProcedureColumns result.", func);
5123
SC_set_Result(stmt, res);
5126
* the binding structure for a statement is not set up until
5127
* a statement is actually executed, so we'll have to do this
5130
result_cols = NUM_OF_PROCOLS_FIELDS;
5131
extend_column_bindings(SC_get_ARDF(stmt), result_cols);
5133
stmt->catalog_result = TRUE;
5134
/* set the field names */
5135
QR_set_num_fields(res, result_cols);
5136
QR_set_field_info_v(res, PROCOLS_PROCEDURE_CAT, "PROCEDURE_CAT", PG_TYPE_VARCHAR, MAX_INFO_STRING);
5137
QR_set_field_info_v(res, PROCOLS_PROCEDURE_SCHEM, "PROCEDUR_SCHEM", PG_TYPE_VARCHAR, MAX_INFO_STRING);
5138
QR_set_field_info_v(res, PROCOLS_PROCEDURE_NAME, "PROCEDURE_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
5139
QR_set_field_info_v(res, PROCOLS_COLUMN_NAME, "COLUMN_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
5140
QR_set_field_info_v(res, PROCOLS_COLUMN_TYPE, "COLUMN_TYPE", PG_TYPE_INT2, 2);
5141
QR_set_field_info_v(res, PROCOLS_DATA_TYPE, "DATA_TYPE", PG_TYPE_INT2, 2);
5142
QR_set_field_info_v(res, PROCOLS_TYPE_NAME, "TYPE_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
5143
QR_set_field_info_v(res, PROCOLS_COLUMN_SIZE, "COLUMN_SIZE", PG_TYPE_INT4, 4);
5144
QR_set_field_info_v(res, PROCOLS_BUFFER_LENGTH, "BUFFER_LENGTH", PG_TYPE_INT4, 4);
5145
QR_set_field_info_v(res, PROCOLS_DECIMAL_DIGITS, "DECIMAL_DIGITS", PG_TYPE_INT2, 2);
5146
QR_set_field_info_v(res, PROCOLS_NUM_PREC_RADIX, "NUM_PREC_RADIX", PG_TYPE_INT2, 2);
5147
QR_set_field_info_v(res, PROCOLS_NULLABLE, "NULLABLE", PG_TYPE_INT2, 2);
5148
QR_set_field_info_v(res, PROCOLS_REMARKS, "REMARKS", PG_TYPE_VARCHAR, MAX_INFO_STRING);
5149
#if (ODBCVER >= 0x0300)
5150
QR_set_field_info_v(res, PROCOLS_COLUMN_DEF, "COLUMN_DEF", PG_TYPE_VARCHAR, MAX_INFO_STRING);
5151
QR_set_field_info_v(res, PROCOLS_SQL_DATA_TYPE, "SQL_DATA_TYPE", PG_TYPE_INT2, 2);
5152
QR_set_field_info_v(res, PROCOLS_SQL_DATETIME_SUB, "SQL_DATETIME_SUB", PG_TYPE_INT2, 2);
5153
QR_set_field_info_v(res, PROCOLS_CHAR_OCTET_LENGTH, "CHAR_OCTET_LENGTH", PG_TYPE_INT4, 4);
5154
QR_set_field_info_v(res, PROCOLS_ORDINAL_POSITION, "ORDINAL_POSITION", PG_TYPE_INT4, 4);
5155
QR_set_field_info_v(res, PROCOLS_IS_NULLABLE, "IS_NULLABLE", PG_TYPE_VARCHAR, MAX_INFO_STRING);
5156
#endif /* ODBCVER >= 0x0300 */
5158
column_name = make_string(szColumnName, cbColumnName, NULL, 0);
5159
if (column_name) /* column_name is unavailable now */
5165
tcount = QR_get_num_total_tuples(tres);
5166
for (i = 0, poid = 0; i < tcount; i++)
5168
if (conn->schema_support)
5169
schema_name = GET_SCHEMA_NAME(QR_get_value_backend_text(tres, i, 5));
5172
procname = QR_get_value_backend_text(tres, i, 0);
5173
retset = QR_get_value_backend_text(tres, i, 1);
5174
pgtype = QR_get_value_backend_int(tres, i, 2, NULL);
5175
bRetset = retset && (retset[0] == 't' || retset[0] == 'y');
5178
newpoid = QR_get_value_backend_int(tres, i, poid_pos, NULL);
5179
mylog("newpoid=%d\n", newpoid);
5183
atttypid = QR_get_value_backend_text(tres, i, attid_pos);
5184
mylog("atttypid=%s\n", atttypid ? atttypid : "(null)");
5186
if (poid == 0 || newpoid != poid)
5193
#ifdef DISPLAY_ARGNAME /* !! named parameter is unavailable !! */
5194
if (PG_VERSION_GE(conn, 8.0))
5195
proargnames = QR_get_value_backend_text(tres, i, ext_pos);
5196
#endif /* DISPLAY_ARGNAME */
5197
if (PG_VERSION_GE(conn, 8.1))
5198
proargmodes = QR_get_value_backend_text(tres, i, ext_pos + 1);
5200
/* RETURN_VALUE info */
5201
if (0 != pgtype && PG_TYPE_VOID != pgtype && !bRetset && !atttypid && !proargmodes)
5203
tuple = QR_AddNew(res);
5204
set_tuplefield_string(&tuple[PROCOLS_PROCEDURE_CAT], CurrCat(conn));
5205
set_nullfield_string(&tuple[PROCOLS_PROCEDURE_SCHEM], schema_name);
5206
set_tuplefield_string(&tuple[PROCOLS_PROCEDURE_NAME], procname);
5207
set_tuplefield_string(&tuple[PROCOLS_COLUMN_NAME], NULL_STRING);
5208
set_tuplefield_int2(&tuple[PROCOLS_COLUMN_TYPE], SQL_RETURN_VALUE);
5209
set_tuplefield_int2(&tuple[PROCOLS_DATA_TYPE], pgtype_to_concise_type(stmt, pgtype, PG_STATIC));
5210
set_tuplefield_string(&tuple[PROCOLS_TYPE_NAME], pgtype_to_name(stmt, pgtype, PG_UNSPECIFIED, FALSE));
5211
column_size = pgtype_column_size(stmt, pgtype, PG_STATIC, UNKNOWNS_AS_DEFAULT);
5212
set_nullfield_int4(&tuple[PROCOLS_COLUMN_SIZE], column_size);
5213
set_tuplefield_int4(&tuple[PROCOLS_BUFFER_LENGTH], pgtype_buffer_length(stmt, pgtype, PG_STATIC, UNKNOWNS_AS_DEFAULT));
5214
set_nullfield_int2(&tuple[PROCOLS_DECIMAL_DIGITS], pgtype_decimal_digits(stmt, pgtype, PG_STATIC));
5215
set_nullfield_int2(&tuple[PROCOLS_NUM_PREC_RADIX], pgtype_radix(conn, pgtype));
5216
set_tuplefield_int2(&tuple[PROCOLS_NULLABLE], SQL_NULLABLE_UNKNOWN);
5217
set_tuplefield_null(&tuple[PROCOLS_REMARKS]);
5218
#if (ODBCVER >= 0x0300)
5219
set_tuplefield_null(&tuple[PROCOLS_COLUMN_DEF]);
5220
set_nullfield_int2(&tuple[PROCOLS_SQL_DATA_TYPE], pgtype_to_sqldesctype(stmt, pgtype, PG_STATIC));
5221
set_nullfield_int2(&tuple[PROCOLS_SQL_DATETIME_SUB], pgtype_to_datetime_sub(stmt, pgtype, PG_UNSPECIFIED));
5222
set_nullfield_int4(&tuple[PROCOLS_CHAR_OCTET_LENGTH], pgtype_attr_transfer_octet_length(conn, pgtype, PG_UNSPECIFIED, UNKNOWNS_AS_DEFAULT));
5223
set_tuplefield_int4(&tuple[PROCOLS_ORDINAL_POSITION], 0);
5224
set_tuplefield_string(&tuple[PROCOLS_IS_NULLABLE], NULL_STRING);
5225
#endif /* ODBCVER >= 0x0300 */
5232
for (p = proargmodes; *p; p++)
5238
params = QR_get_value_backend_text(tres, i, ext_pos + 2);
5239
if ('{' == *proargmodes)
5246
paramcount = QR_get_value_backend_int(tres, i, 3, NULL);
5247
params = QR_get_value_backend_text(tres, i, 4);
5251
if ('{' == *proargnames)
5254
/* PARAMETERS info */
5255
for (j = 0; j < paramcount; j++)
5257
/* PG type of parameters */
5261
while (isspace(*params) || ',' == *params)
5263
if ('\0' == *params || '}' == *params)
5267
sscanf(params, "%u", &pgtype);
5268
while (isdigit(*params))
5272
/* input/output type of parameters */
5275
while (isspace(*proargmodes) || ',' == *proargmodes)
5277
if ('\0' == *proargmodes || '}' == *proargmodes)
5280
/* name of parameters */
5283
while (isspace(*proargnames) || ',' == *proargnames)
5285
if ('\0' == *proargnames || '}' == *proargnames)
5287
else if ('"' == *proargnames)
5290
for (delim = proargnames; *delim && *delim != '"'; delim++)
5295
for (delim = proargnames; *delim && !isspace(*delim) && ',' != *delim && '}' != *delim; delim++)
5298
if (proargnames && '\0' == *delim) /* discard the incomplete name */
5302
tuple = QR_AddNew(res);
5303
set_tuplefield_string(&tuple[PROCOLS_PROCEDURE_CAT], CurrCat(conn));
5304
set_nullfield_string(&tuple[PROCOLS_PROCEDURE_SCHEM], schema_name);
5305
set_tuplefield_string(&tuple[PROCOLS_PROCEDURE_NAME], procname);
5309
set_tuplefield_string(&tuple[PROCOLS_COLUMN_NAME], proargnames);
5310
proargnames = delim + 1;
5313
set_tuplefield_string(&tuple[PROCOLS_COLUMN_NAME], NULL_STRING);
5318
switch (*proargmodes)
5321
ptype = SQL_PARAM_OUTPUT;
5324
ptype = SQL_PARAM_INPUT_OUTPUT;
5327
ptype = SQL_PARAM_INPUT;
5330
set_tuplefield_int2(&tuple[PROCOLS_COLUMN_TYPE], ptype);
5334
set_tuplefield_int2(&tuple[PROCOLS_COLUMN_TYPE], SQL_PARAM_INPUT);
5335
set_tuplefield_int2(&tuple[PROCOLS_DATA_TYPE], pgtype_to_concise_type(stmt, pgtype, PG_STATIC));
5336
set_tuplefield_string(&tuple[PROCOLS_TYPE_NAME], pgtype_to_name(stmt, pgtype, PG_UNSPECIFIED, FALSE));
5337
column_size = pgtype_column_size(stmt, pgtype, PG_STATIC, UNKNOWNS_AS_DEFAULT);
5338
set_nullfield_int4(&tuple[PROCOLS_COLUMN_SIZE], column_size);
5339
set_tuplefield_int4(&tuple[PROCOLS_BUFFER_LENGTH], pgtype_buffer_length(stmt, pgtype, PG_STATIC, UNKNOWNS_AS_DEFAULT));
5340
set_nullfield_int2(&tuple[PROCOLS_DECIMAL_DIGITS], pgtype_decimal_digits(stmt, pgtype, PG_STATIC));
5341
set_nullfield_int2(&tuple[PROCOLS_NUM_PREC_RADIX], pgtype_radix(conn, pgtype));
5342
set_tuplefield_int2(&tuple[PROCOLS_NULLABLE], SQL_NULLABLE_UNKNOWN);
5343
set_tuplefield_null(&tuple[PROCOLS_REMARKS]);
5344
#if (ODBCVER >= 0x0300)
5345
set_tuplefield_null(&tuple[PROCOLS_COLUMN_DEF]);
5346
set_nullfield_int2(&tuple[PROCOLS_SQL_DATA_TYPE], pgtype_to_sqldesctype(stmt, pgtype, PG_STATIC));
5347
set_nullfield_int2(&tuple[PROCOLS_SQL_DATETIME_SUB], pgtype_to_datetime_sub(stmt, pgtype, PG_UNSPECIFIED));
5348
set_nullfield_int4(&tuple[PROCOLS_CHAR_OCTET_LENGTH], pgtype_attr_transfer_octet_length(conn, pgtype, PG_UNSPECIFIED, UNKNOWNS_AS_DEFAULT));
5349
set_tuplefield_int4(&tuple[PROCOLS_ORDINAL_POSITION], j + 1);
5350
set_tuplefield_string(&tuple[PROCOLS_IS_NULLABLE], NULL_STRING);
5351
#endif /* ODBCVER >= 0x0300 */
5354
/* RESULT Columns info */
5355
if (NULL != atttypid || bRetset)
5366
typid = atoi(atttypid);
5367
attname = QR_get_value_backend_text(tres, i, attname_pos);
5369
tuple = QR_AddNew(res);
5370
set_tuplefield_string(&tuple[PROCOLS_PROCEDURE_CAT], CurrCat(conn));
5371
set_nullfield_string(&tuple[PROCOLS_PROCEDURE_SCHEM], schema_name);
5372
set_tuplefield_string(&tuple[PROCOLS_PROCEDURE_NAME], procname);
5373
set_tuplefield_string(&tuple[PROCOLS_COLUMN_NAME], attname);
5374
set_tuplefield_int2(&tuple[PROCOLS_COLUMN_TYPE], SQL_RESULT_COL);
5375
set_tuplefield_int2(&tuple[PROCOLS_DATA_TYPE], pgtype_to_concise_type(stmt, typid, PG_STATIC));
5376
set_tuplefield_string(&tuple[PROCOLS_TYPE_NAME], pgtype_to_name(stmt, typid, PG_UNSPECIFIED, FALSE));
5377
column_size = pgtype_column_size(stmt, typid, PG_STATIC, UNKNOWNS_AS_DEFAULT);
5378
set_nullfield_int4(&tuple[PROCOLS_COLUMN_SIZE], column_size);
5379
set_tuplefield_int4(&tuple[PROCOLS_BUFFER_LENGTH], pgtype_buffer_length(stmt, typid, PG_STATIC, UNKNOWNS_AS_DEFAULT));
5380
set_nullfield_int2(&tuple[PROCOLS_DECIMAL_DIGITS], pgtype_decimal_digits(stmt, typid, PG_STATIC));
5381
set_nullfield_int2(&tuple[PROCOLS_NUM_PREC_RADIX], pgtype_radix(conn, typid));
5382
set_tuplefield_int2(&tuple[PROCOLS_NULLABLE], SQL_NULLABLE_UNKNOWN);
5383
set_tuplefield_null(&tuple[PROCOLS_REMARKS]);
5384
#if (ODBCVER >= 0x0300)
5385
set_tuplefield_null(&tuple[PROCOLS_COLUMN_DEF]);
5386
set_nullfield_int2(&tuple[PROCOLS_SQL_DATA_TYPE], pgtype_to_sqldesctype(stmt, typid, PG_STATIC));
5387
set_nullfield_int2(&tuple[PROCOLS_SQL_DATETIME_SUB], pgtype_to_datetime_sub(stmt, typid, PG_UNSPECIFIED));
5388
set_nullfield_int4(&tuple[PROCOLS_CHAR_OCTET_LENGTH], pgtype_attr_transfer_octet_length(conn, typid, PG_UNSPECIFIED, UNKNOWNS_AS_DEFAULT));
5389
set_tuplefield_int4(&tuple[PROCOLS_ORDINAL_POSITION], 0);
5390
set_tuplefield_string(&tuple[PROCOLS_IS_NULLABLE], NULL_STRING);
5391
#endif /* ODBCVER >= 0x0300 */
5394
QR_Destructor(tres);
5396
* also, things need to think that this statement is finished so the
5397
* results can be retrieved.
5400
free(escSchemaName);
5403
stmt->status = STMT_FINISHED;
5404
/* set up the current tuple pointer for SQLFetch */
5405
stmt->currTuple = -1;
5406
SC_set_rowset_start(stmt, -1, FALSE);
5407
SC_set_current_col(stmt, -1);
5416
const SQLCHAR FAR * szProcQualifier, /* OA X*/
5417
SQLSMALLINT cbProcQualifier,
5418
const SQLCHAR FAR * szProcOwner, /* PV E*/
5419
SQLSMALLINT cbProcOwner,
5420
const SQLCHAR FAR * szProcName, /* PV E*/
5421
SQLSMALLINT cbProcName,
5424
CSTR func = "PGAPI_Procedures";
5425
StatementClass *stmt = (StatementClass *) hstmt;
5426
ConnectionClass *conn = SC_get_conn(stmt);
5427
char proc_query[INFO_INQUIRY_LEN];
5428
char *escSchemaName = NULL, *escProcName = NULL;
5431
const char *like_or_eq, *op_string;
5432
BOOL search_pattern;
5434
mylog("%s: entering... scnm=%p len=%d\n", func, szProcOwner, cbProcOwner);
5436
if (PG_VERSION_LT(conn, 6.5))
5438
SC_set_error(stmt, STMT_NOT_IMPLEMENTED_ERROR, "Version is too old", func);
5441
if (result = SC_initialize_and_recycle(stmt), SQL_SUCCESS != result)
5444
search_pattern = (0 == (flag & PODBC_NOT_SEARCH_PATTERN));
5447
like_or_eq = likeop;
5448
escSchemaName = adjustLikePattern(szProcOwner, cbProcOwner, SEARCH_PATTERN_ESCAPE, NULL, conn);
5449
escProcName = adjustLikePattern(szProcName, cbProcName, SEARCH_PATTERN_ESCAPE, NULL, conn);
5454
escSchemaName = simpleCatalogEscape(szProcOwner, cbProcOwner, NULL, conn);
5455
escProcName = simpleCatalogEscape(szProcName, cbProcName, NULL, conn);
5458
* The following seems the simplest implementation
5460
op_string = gen_opestr(like_or_eq, conn);
5461
if (conn->schema_support)
5463
strcpy(proc_query, "select '' as " "PROCEDURE_CAT" ", nspname as " "PROCEDURE_SCHEM" ","
5464
" proname as " "PROCEDURE_NAME" ", '' as " "NUM_INPUT_PARAMS" ","
5465
" '' as " "NUM_OUTPUT_PARAMS" ", '' as " "NUM_RESULT_SETS" ","
5466
" '' as " "REMARKS" ","
5467
" case when prorettype = 0 then 1::int2 else 2::int2 end"
5468
" as " "PROCEDURE_TYPE" " from pg_catalog.pg_namespace,"
5469
" pg_catalog.pg_proc"
5470
" where pg_proc.pronamespace = pg_namespace.oid");
5471
schema_strcat1(proc_query, " and nspname %s'%.*s'", op_string, escSchemaName, SQL_NTS, szProcName, cbProcName, conn);
5472
my_strcat1(proc_query, " and proname %s'%.*s'", op_string, escProcName, SQL_NTS);
5476
strcpy(proc_query, "select '' as " "PROCEDURE_CAT" ", '' as " "PROCEDURE_SCHEM" ","
5477
" proname as " "PROCEDURE_NAME" ", '' as " "NUM_INPUT_PARAMS" ","
5478
" '' as " "NUM_OUTPUT_PARAMS" ", '' as " "NUM_RESULT_SETS" ","
5479
" '' as " "REMARKS" ","
5480
" case when prorettype = 0 then 1::int2 else 2::int2 end as " "PROCEDURE_TYPE" " from pg_proc");
5481
my_strcat1(proc_query, " where proname %s'%.*s'", op_string, escSchemaName, SQL_NTS);
5484
if (res = CC_send_query(conn, proc_query, NULL, IGNORE_ABORT_ON_CONN, stmt), !QR_command_maybe_successful(res))
5486
SC_set_error(stmt, STMT_EXEC_ERROR, "PGAPI_Procedures query error", func);
5490
SC_set_Result(stmt, res);
5493
* also, things need to think that this statement is finished so the
5494
* results can be retrieved.
5496
stmt->status = STMT_FINISHED;
5497
extend_column_bindings(SC_get_ARDF(stmt), 8);
5499
free(escSchemaName);
5502
/* set up the current tuple pointer for SQLFetch */
5503
stmt->currTuple = -1;
5504
SC_set_rowset_start(stmt, -1, FALSE);
5505
SC_set_current_col(stmt, -1);
5512
#define ALL_PRIVILIGES "arwdRxt"
5514
usracl_auth(char *usracl, const char *auth)
5516
int i, j, addcnt = 0;
5518
for (i = 0; auth[i]; i++)
5520
for (j = 0; j < ACLMAX; j++)
5522
if (usracl[j] == auth[i])
5524
else if (!usracl[j])
5535
useracl_upd(char (*useracl)[ACLMAX], QResultClass *allures, const char *user, const char *auth)
5537
int usercount = (int) QR_get_num_cached_tuples(allures), i, addcnt = 0;
5539
mylog("user=%s auth=%s\n", user, auth);
5541
for (i = 0; i < usercount; i++)
5543
if (strcmp(QR_get_value_backend_text(allures, i, 0), user) == 0)
5545
addcnt += usracl_auth(useracl[i], auth);
5550
for (i = 0; i < usercount; i++)
5552
addcnt += usracl_auth(useracl[i], auth);
5554
mylog("addcnt=%d\n", addcnt);
5558
PGAPI_TablePrivileges(
5560
const SQLCHAR FAR * szTableQualifier, /* OA X*/
5561
SQLSMALLINT cbTableQualifier,
5562
const SQLCHAR FAR * szTableOwner, /* PV E*/
5563
SQLSMALLINT cbTableOwner,
5564
const SQLCHAR FAR * szTableName, /* PV E*/
5565
SQLSMALLINT cbTableName,
5568
StatementClass *stmt = (StatementClass *) hstmt;
5569
CSTR func = "PGAPI_TablePrivileges";
5570
ConnectionClass *conn = SC_get_conn(stmt);
5572
char proc_query[INFO_INQUIRY_LEN];
5573
QResultClass *res, *wres = NULL, *allures = NULL;
5575
Int4 tablecount, usercount, i, j, k;
5576
BOOL grpauth, sys, su;
5577
char (*useracl)[ACLMAX] = NULL, *acl, *user, *delim, *auth;
5578
const char *reln, *owner, *priv, *schnm = NULL;
5579
RETCODE result, ret = SQL_SUCCESS;
5580
const char *like_or_eq, *op_string;
5581
const char *szSchemaName;
5582
SQLSMALLINT cbSchemaName;
5583
char *escSchemaName = NULL, *escTableName = NULL;
5584
BOOL search_pattern;
5586
mylog("%s: entering... scnm=%p len-%d\n", func, szTableOwner, cbTableOwner);
5587
if (result = SC_initialize_and_recycle(stmt), SQL_SUCCESS != result)
5591
* a statement is actually executed, so we'll have to do this
5595
extend_column_bindings(SC_get_ARDF(stmt), result_cols);
5597
stmt->catalog_result = TRUE;
5598
/* set the field names */
5599
res = QR_Constructor();
5600
SC_set_Result(stmt, res);
5601
QR_set_num_fields(res, result_cols);
5602
QR_set_field_info_v(res, 0, "TABLE_CAT", PG_TYPE_VARCHAR, MAX_INFO_STRING);
5603
QR_set_field_info_v(res, 1, "TABLE_SCHEM", PG_TYPE_VARCHAR, MAX_INFO_STRING);
5604
QR_set_field_info_v(res, 2, "TABLE_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
5605
QR_set_field_info_v(res, 3, "GRANTOR", PG_TYPE_VARCHAR, MAX_INFO_STRING);
5606
QR_set_field_info_v(res, 4, "GRANTEE", PG_TYPE_VARCHAR, MAX_INFO_STRING);
5607
QR_set_field_info_v(res, 5, "PRIVILEGE", PG_TYPE_VARCHAR, MAX_INFO_STRING);
5608
QR_set_field_info_v(res, 6, "IS_GRANTABLE", PG_TYPE_VARCHAR, MAX_INFO_STRING);
5611
* also, things need to think that this statement is finished so the
5612
* results can be retrieved.
5614
stmt->status = STMT_FINISHED;
5615
/* set up the current tuple pointer for SQLFetch */
5616
stmt->currTuple = -1;
5617
SC_set_rowset_start(stmt, -1, FALSE);
5618
SC_set_current_col(stmt, -1);
5619
szSchemaName = szTableOwner;
5620
cbSchemaName = cbTableOwner;
5622
#define return DONT_CALL_RETURN_FROM_HERE???
5623
search_pattern = (0 == (flag & PODBC_NOT_SEARCH_PATTERN));
5626
like_or_eq = likeop;
5627
escTableName = adjustLikePattern(szTableName, cbTableName, SEARCH_PATTERN_ESCAPE, NULL, conn);
5632
escTableName = simpleCatalogEscape(szTableName, cbTableName, NULL, conn);
5635
retry_public_schema:
5637
free(escSchemaName);
5639
escSchemaName = adjustLikePattern(szSchemaName, cbSchemaName, SEARCH_PATTERN_ESCAPE, NULL, conn);
5641
escSchemaName = simpleCatalogEscape(szSchemaName, cbSchemaName, NULL, conn);
5643
op_string = gen_opestr(like_or_eq, conn);
5644
if (conn->schema_support)
5645
strncpy_null(proc_query, "select relname, usename, relacl, nspname"
5646
" from pg_catalog.pg_namespace, pg_catalog.pg_class ,"
5647
" pg_catalog.pg_user where", sizeof(proc_query));
5649
strncpy_null(proc_query, "select relname, usename, relacl"
5650
" from pg_class , pg_user where", sizeof(proc_query));
5651
if (conn->schema_support)
5654
schema_strcat1(proc_query, " nspname %s'%.*s' and", op_string, escSchemaName, SQL_NTS, szTableName, cbTableName, conn);
5657
snprintf_add(proc_query, sizeof(proc_query), " relname %s'%s' and", op_string, escTableName);
5658
if (conn->schema_support)
5660
strcat(proc_query, " pg_namespace.oid = relnamespace and relkind in ('r', 'v') and");
5661
if ((!escTableName) && (!escSchemaName))
5662
strcat(proc_query, " nspname not in ('pg_catalog', 'information_schema') and");
5664
strcat(proc_query, " pg_user.usesysid = relowner");
5665
if (wres = CC_send_query(conn, proc_query, NULL, IGNORE_ABORT_ON_CONN, stmt), !QR_command_maybe_successful(wres))
5667
SC_set_error(stmt, STMT_EXEC_ERROR, "PGAPI_TablePrivileges query error", func);
5671
tablecount = (Int4) QR_get_num_cached_tuples(wres);
5673
if (conn->schema_support &&
5674
(flag & PODBC_SEARCH_PUBLIC_SCHEMA) != 0 &&
5677
if (allow_public_schema(conn, szSchemaName, cbSchemaName))
5679
QR_Destructor(wres);
5681
szSchemaName = pubstr;
5682
cbSchemaName = SQL_NTS;
5683
goto retry_public_schema;
5687
strncpy_null(proc_query, "select usename, usesysid, usesuper from pg_user", sizeof(proc_query));
5688
if (allures = CC_send_query(conn, proc_query, NULL, IGNORE_ABORT_ON_CONN, stmt), !QR_command_maybe_successful(allures))
5690
SC_set_error(stmt, STMT_EXEC_ERROR, "PGAPI_TablePrivileges query error", func);
5694
usercount = (Int4) QR_get_num_cached_tuples(allures);
5695
useracl = (char (*)[ACLMAX]) malloc(usercount * sizeof(char [ACLMAX]));
5696
for (i = 0; i < tablecount; i++)
5698
memset(useracl, 0, usercount * sizeof(char[ACLMAX]));
5699
acl = (char *) QR_get_value_backend_text(wres, i, 2);
5700
if (acl && acl[0] == '{')
5704
for (; user && *user;)
5707
if (user[0] == '"' && strncmp(user + 1, "group ", 6) == 0)
5712
if (delim = strchr(user, '='), !delim)
5718
if (delim = strchr(auth, '"'), delim)
5724
else if (delim = strchr(auth, ','), delim)
5726
else if (delim = strchr(auth, '}'), delim)
5728
if (grpauth) /* handle group privilege */
5732
char *grolist, *uid, *delm;
5734
snprintf(proc_query, sizeof(proc_query) - 1, "select grolist from pg_group where groname = '%s'", user);
5735
if (gres = CC_send_query(conn, proc_query, NULL, IGNORE_ABORT_ON_CONN, stmt), !QR_command_maybe_successful(gres))
5737
grolist = QR_get_value_backend_text(gres, 0, 0);
5738
if (grolist && grolist[0] == '{')
5740
for (uid = grolist + 1; *uid;)
5742
if (delm = strchr(uid, ','), delm)
5744
else if (delm = strchr(uid, '}'), delm)
5746
mylog("guid=%s\n", uid);
5747
for (i = 0; i < usercount; i++)
5749
if (strcmp(QR_get_value_backend_text(allures, i, 1), uid) == 0)
5750
useracl_upd(useracl, allures, QR_get_value_backend_text(allures, i, 0), auth);
5756
QR_Destructor(gres);
5759
useracl_upd(useracl, allures, user, auth);
5764
reln = QR_get_value_backend_text(wres, i, 0);
5765
owner = QR_get_value_backend_text(wres, i, 1);
5766
if (conn->schema_support)
5767
schnm = QR_get_value_backend_text(wres, i, 3);
5768
/* The owner has all privileges */
5769
useracl_upd(useracl, allures, owner, ALL_PRIVILIGES);
5770
for (j = 0; j < usercount; j++)
5772
user = QR_get_value_backend_text(allures, j, 0);
5773
su = (strcmp(QR_get_value_backend_text(allures, j, 2), "t") == 0);
5774
sys = (strcmp(user, owner) == 0);
5775
/* Super user has all privileges */
5777
useracl_upd(useracl, allures, user, ALL_PRIVILIGES);
5778
for (k = 0; k < ACLMAX; k++)
5782
switch (useracl[j][k])
5784
case 'R': /* rule */
5785
case 't': /* trigger */
5788
tuple = QR_AddNew(res);
5789
set_tuplefield_string(&tuple[0], CurrCat(conn));
5790
if (conn->schema_support)
5791
set_tuplefield_string(&tuple[1], GET_SCHEMA_NAME(schnm));
5793
set_tuplefield_string(&tuple[1], NULL_STRING);
5794
set_tuplefield_string(&tuple[2], reln);
5796
set_tuplefield_string(&tuple[3], "_SYSTEM");
5798
set_tuplefield_string(&tuple[3], owner);
5799
mylog("user=%s\n", user);
5800
set_tuplefield_string(&tuple[4], user);
5801
switch (useracl[j][k])
5816
priv = "REFERENCES";
5821
set_tuplefield_string(&tuple[5], priv);
5822
/* The owner and the super user are grantable */
5824
set_tuplefield_string(&tuple[6], "YES");
5826
set_tuplefield_string(&tuple[6], "NO");
5833
free(escSchemaName);
5839
QR_Destructor(wres);
5841
QR_Destructor(allures);
5843
ret = DiscardStatementSvp(stmt, ret, FALSE);
5848
static RETCODE SQL_API
5849
PGAPI_ForeignKeys_new(
5851
const SQLCHAR FAR * szPkTableQualifier, /* OA X*/
5852
SQLSMALLINT cbPkTableQualifier,
5853
const SQLCHAR FAR * szPkTableOwner, /* OA E*/
5854
SQLSMALLINT cbPkTableOwner,
5855
const SQLCHAR FAR * szPkTableName, /* OA(R) E*/
5856
SQLSMALLINT cbPkTableName,
5857
const SQLCHAR FAR * szFkTableQualifier, /* OA X*/
5858
SQLSMALLINT cbFkTableQualifier,
5859
const SQLCHAR FAR * szFkTableOwner, /* OA E*/
5860
SQLSMALLINT cbFkTableOwner,
5861
const SQLCHAR FAR * szFkTableName, /* OA(R) E*/
5862
SQLSMALLINT cbFkTableName)
5864
CSTR func = "PGAPI_ForeignKeys";
5865
StatementClass *stmt = (StatementClass *) hstmt;
5866
QResultClass *res = NULL;
5867
RETCODE ret = SQL_ERROR, result;
5868
char tables_query[INFO_INQUIRY_LEN];
5869
char *pk_table_needed = NULL, *escTableName = NULL;
5870
char *fk_table_needed = NULL;
5871
char schema_needed[SCHEMA_NAME_STORAGE_LEN + 1];
5872
char catName[SCHEMA_NAME_STORAGE_LEN],
5873
scmName1[SCHEMA_NAME_STORAGE_LEN],
5874
scmName2[SCHEMA_NAME_STORAGE_LEN];
5875
const char *relqual;
5876
ConnectionClass *conn = SC_get_conn(stmt);
5878
const char *eq_string;
5880
mylog("%s: entering...stmt=%p\n", func, stmt);
5882
if (result = SC_initialize_and_recycle(stmt), SQL_SUCCESS != result)
5885
schema_needed[0] = '\0';
5886
#define return DONT_CALL_RETURN_FROM_HERE???
5888
pk_table_needed = make_string(szPkTableName, cbPkTableName, NULL, 0);
5889
fk_table_needed = make_string(szFkTableName, cbFkTableName, NULL, 0);
5891
eq_string = gen_opestr(eqop, conn);
5894
* Case #2 -- Get the foreign keys in the specified table (fktab) that
5895
* refer to the primary keys of other table(s).
5897
if (NULL != fk_table_needed)
5899
mylog("%s: entering Foreign Key Case #2", func);
5900
escTableName = simpleCatalogEscape(fk_table_needed, SQL_NTS, NULL, conn);
5901
schema_strcat(schema_needed, "%.*s", szFkTableOwner, cbFkTableOwner, szFkTableName, cbFkTableName, conn);
5902
relqual = "\n and conrelid = c.oid";
5905
* Case #1 -- Get the foreign keys in other tables that refer to the
5906
* primary key in the specified table (pktab). i.e., Who points to
5909
else if (NULL != pk_table_needed)
5911
escTableName = simpleCatalogEscape(pk_table_needed, SQL_NTS, NULL, conn);
5912
schema_strcat(schema_needed, "%.*s", szPkTableOwner, cbPkTableOwner, szPkTableName, cbPkTableName, conn);
5913
relqual = "\n and confrelid = c.oid";
5917
SC_set_error(stmt, STMT_INTERNAL_ERROR, "No tables specified to PGAPI_ForeignKeys.", func);
5921
if (conn->schema_support)
5923
char *escSchemaName;
5925
if (NULL != CurrCat(conn))
5926
snprintf(catName, sizeof(catName), "'%s'::name", CurrCat(conn));
5928
strcpy(catName, "NULL::name");
5929
strcpy(scmName1, "n2.nspname");
5930
strcpy(scmName2, "n1.nspname");
5931
escSchemaName = simpleCatalogEscape(schema_needed, SQL_NTS, NULL, conn);
5933
snprintf(tables_query, sizeof(tables_query),
5935
" %s as PKTABLE_CAT"
5936
",\n %s as PKTABLE_SCHEM"
5937
",\n c2.relname as PKTABLE_NAME"
5938
",\n a2.attname as PKCOLUMN_NAME"
5939
",\n %s as FKTABLE_CAT"
5940
",\n %s as FKTABLE_SCHEM"
5941
",\n c1.relname as FKTABLE_NAME"
5942
",\n a1.attname as FKCOLUMN_NAME"
5943
",\n i::int2 as KEY_SEQ"
5944
",\n case ref.confupdtype"
5945
"\n when 'c' then %d::int2"
5946
"\n when 'n' then %d::int2"
5947
"\n when 'd' then %d::int2"
5948
"\n when 'r' then %d::int2"
5950
"\n end as UPDATE_RULE"
5951
",\n case ref.confdeltype"
5952
"\n when 'c' then %d::int2"
5953
"\n when 'n' then %d::int2"
5954
"\n when 'd' then %d::int2"
5955
"\n when 'r' then %d::int2"
5957
"\n end as DELETE_RULE"
5958
",\n ref.conname as FK_NAME"
5959
",\n cn.conname as PK_NAME"
5960
#if (ODBCVER >= 0x0300)
5962
"\n when ref.condeferrable then"
5964
"\n when ref.condeferred then %d::int2"
5968
"\n end as DEFERRABLITY"
5969
#endif /* ODBCVER */
5972
" (select cn.oid, conrelid, conkey, confrelid, confkey"
5973
",\n generate_series(array_lower(conkey, 1), array_upper(conkey, 1)) as i"
5974
",\n confupdtype, confdeltype, conname"
5975
",\n condeferrable, condeferred"
5976
"\n from pg_catalog.pg_constraint cn"
5977
",\n pg_catalog.pg_class c"
5978
",\n pg_catalog.pg_namespace n"
5979
"\n where contype = 'f' %s"
5980
"\n and relname %s'%s'"
5981
"\n and n.oid = c.relnamespace"
5982
"\n and n.nspname %s'%s'"
5984
"\n inner join pg_catalog.pg_class c1"
5985
"\n on c1.oid = ref.conrelid)"
5986
"\n inner join pg_catalog.pg_namespace n1"
5987
"\n on n1.oid = c1.relnamespace)"
5988
"\n inner join pg_catalog.pg_attribute a1"
5989
"\n on a1.attrelid = c1.oid"
5990
"\n and a1.attnum = conkey[i])"
5991
"\n inner join pg_catalog.pg_class c2"
5992
"\n on c2.oid = ref.confrelid)"
5993
"\n inner join pg_catalog.pg_namespace n2"
5994
"\n on n2.oid = c2.relnamespace)"
5995
"\n inner join pg_catalog.pg_attribute a2"
5996
"\n on a2.attrelid = c2.oid"
5997
"\n and a2.attnum = confkey[i])"
5998
"\n left outer join pg_catalog.pg_constraint cn"
5999
"\n on cn.conrelid = ref.confrelid"
6000
"\n and cn.contype = 'p')"
6015
#if (ODBCVER >= 0x0300)
6016
, SQL_INITIALLY_DEFERRED
6017
, SQL_INITIALLY_IMMEDIATE
6018
, SQL_NOT_DEFERRABLE
6019
#endif /* ODBCVER */
6021
, eq_string, escTableName
6022
, eq_string, escSchemaName);
6024
free(escSchemaName);
6025
if (NULL != pk_table_needed &&
6026
NULL != fk_table_needed)
6029
escTableName = simpleCatalogEscape(pk_table_needed, SQL_NTS, NULL, conn);
6030
snprintf_add(tables_query, sizeof(tables_query),
6031
"\n where c2.relname %s'%s'",
6032
eq_string, escTableName);
6034
strcat(tables_query, "\n order by ref.oid, ref.i");
6038
strcpy(catName, "NULL::name");
6039
strcpy(scmName1, "NULL::name");
6040
strcpy(scmName2, "NULL::name");
6042
snprintf(tables_query, sizeof(tables_query),
6043
"select %s as PKTABLE_CAT"
6044
",\n %s as PKTABLE_SCHEM"
6045
",\n c2.relname as PKTABLE_NAME"
6046
",\n a2.attname as PKCOLUMN_NAME"
6047
",\n %s as FKTABLE_CAT"
6048
",\n %s as FKTABLE_SCHEM"
6049
",\n c1.relname as FKTABLE_NAME"
6050
",\n a1.attname as FKCOLUMN_NAME"
6051
",\n i::int2 as KEY_SEQ"
6052
",\n case confupdtype"
6053
"\n when 'c' then %d::int2"
6054
"\n when 'n' then %d::int2"
6055
"\n when 'd' then %d::int2"
6056
"\n when 'r' then %d::int2"
6058
"\n end as UPDATE_RULE"
6059
",\n case confdeltype"
6060
"\n when 'c' then %d::int2"
6061
"\n when 'n' then %d::int2"
6062
"\n when 'd' then %d::int2"
6063
"\n when 'r' then %d::int2"
6065
"\n end as DELETE_RULE"
6066
",\n conname as FK_NAME"
6067
",\n NULL::name as PK_NAME"
6068
#if (ODBCVER >= 0x0300)
6070
"\n when condeferrable then"
6072
"\n when condeferred then %d::int2"
6076
"\n end as DEFERRABLITY"
6077
#endif /* ODBCVER */
6079
"\n (select conrelid, conkey, confrelid, confkey"
6080
",\n generate_series(array_lower(conkey, 1), array_upper(conkey, 1)) as i"
6081
",\n confupdtype, confdeltype, conname"
6082
",\n condeferrable, condeferred"
6083
"\n from pg_catalog.pg_constraint cn"
6084
",\n pg_catalog.pg_class c"
6085
"\n where contype = 'f' %s"
6086
"\n and relname %s'%s'"
6088
",\n pg_catalog.pg_class c1"
6089
",\n pg_catalog.pg_attribute a1"
6090
",\n pg_catalog.pg_class c2"
6091
",\n pg_catalog.pg_attribute a2"
6092
"\n where c1.oid = ref.conrelid"
6093
"\n and c2.oid = ref.confrelid"
6094
"\n and a1.attrelid = c1.oid"
6095
"\n and a1.attnum = conkey[i]"
6096
"\n and a2.attrelid = c2.oid"
6097
"\n and a2.attnum = confkey[i]"
6098
"\n order by ref.oid, ref.i"
6113
#if (ODBCVER >= 0x0300)
6114
, SQL_INITIALLY_DEFERRED
6115
, SQL_INITIALLY_IMMEDIATE
6116
, SQL_NOT_DEFERRABLE
6117
#endif /* ODBCVER */
6118
, relqual, eq_string, escTableName);
6121
if (res = CC_send_query(conn, tables_query, NULL, IGNORE_ABORT_ON_CONN, stmt), !QR_command_maybe_successful(res))
6123
SC_set_error(stmt, STMT_EXEC_ERROR, "PGAPI_ForeignKeys query error", func);
6127
SC_set_Result(stmt, res);
6134
* also, things need to think that this statement is finished so the
6135
* results can be retrieved.
6137
if (SQL_SUCCEEDED(ret))
6139
stmt->status = STMT_FINISHED;
6140
extend_column_bindings(SC_get_ARDF(stmt), QR_NumResultCols(res));
6142
if (pk_table_needed)
6143
free(pk_table_needed);
6146
if (fk_table_needed)
6147
free(fk_table_needed);
6148
/* set up the current tuple pointer for SQLFetch */
6149
stmt->currTuple = -1;
6150
SC_set_rowset_start(stmt, -1, FALSE);
6151
SC_set_current_col(stmt, -1);
6154
ret = DiscardStatementSvp(stmt, ret, FALSE);
6155
mylog("%s(): EXIT, stmt=%p, ret=%d\n", func, stmt, ret);
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, SQLProcedures,
13
* SQLTablePrivileges, SQLColumnPrivileges(NI)
15
* Comments: See "readme.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
49
#define NULL_IF_NULL(a) ((a) ? ((const char *) a) : "(NULL)")
51
/* extern GLOBAL_VALUES globals; */
53
CSTR pubstr = "public";
60
SQLUSMALLINT fInfoType,
62
SQLSMALLINT cbInfoValueMax,
63
SQLSMALLINT FAR * pcbInfoValue)
65
CSTR func = "PGAPI_GetInfo";
66
ConnectionClass *conn = (ConnectionClass *) hdbc;
69
char tmp[MAX_INFO_STRING];
72
RETCODE result = SQL_ERROR;
76
mylog("%s: entering...fInfoType=%d\n", func, fInfoType);
80
CC_log_error(func, NULL_STRING, NULL);
81
return SQL_INVALID_HANDLE;
84
ci = &(conn->connInfo);
88
case SQL_ACCESSIBLE_PROCEDURES: /* ODBC 1.0 */
92
case SQL_ACCESSIBLE_TABLES: /* ODBC 1.0 */
93
p = CC_accessible_only(conn) ? "Y" : "N";
96
case SQL_ACTIVE_CONNECTIONS: /* ODBC 1.0 */
101
case SQL_ACTIVE_STATEMENTS: /* ODBC 1.0 */
106
case SQL_ALTER_TABLE: /* ODBC 2.0 */
108
value = SQL_AT_ADD_COLUMN;
109
if (PG_VERSION_GE(conn, 7.3))
110
value |= SQL_AT_DROP_COLUMN;
111
#if (ODBCVER >= 0x0300)
112
value |= SQL_AT_ADD_COLUMN_SINGLE;
113
if (PG_VERSION_GE(conn, 7.1))
114
value |= SQL_AT_ADD_CONSTRAINT
115
| SQL_AT_ADD_TABLE_CONSTRAINT
116
| SQL_AT_CONSTRAINT_INITIALLY_DEFERRED
117
| SQL_AT_CONSTRAINT_INITIALLY_IMMEDIATE
118
| SQL_AT_CONSTRAINT_DEFERRABLE;
119
if (PG_VERSION_GE(conn, 7.3))
120
value |= SQL_AT_DROP_TABLE_CONSTRAINT_RESTRICT
121
| SQL_AT_DROP_TABLE_CONSTRAINT_CASCADE
122
| SQL_AT_DROP_COLUMN_RESTRICT
123
| SQL_AT_DROP_COLUMN_CASCADE;
127
case SQL_BOOKMARK_PERSISTENCE: /* ODBC 2.0 */
128
/* very simple bookmark support */
130
value = ci->drivers.use_declarefetch && PG_VERSION_LT(conn, 7.4) ? 0 : (SQL_BP_SCROLL | SQL_BP_DELETE | SQL_BP_UPDATE | SQL_BP_TRANSACTION);
133
case SQL_COLUMN_ALIAS: /* ODBC 2.0 */
137
case SQL_CONCAT_NULL_BEHAVIOR: /* ODBC 1.0 */
139
value = SQL_CB_NON_NULL;
142
case SQL_CONVERT_INTEGER:
143
case SQL_CONVERT_SMALLINT:
144
case SQL_CONVERT_TINYINT:
145
case SQL_CONVERT_BIT:
146
case SQL_CONVERT_VARCHAR: /* ODBC 1.0 */
147
len = sizeof(SQLUINTEGER);
148
value = SQL_CVT_BIT | SQL_CVT_INTEGER;
149
mylog("SQL_CONVERT_ mask=" FORMAT_ULEN "\n", value);
151
case SQL_CONVERT_BIGINT:
152
case SQL_CONVERT_DECIMAL:
153
case SQL_CONVERT_DOUBLE:
154
case SQL_CONVERT_FLOAT:
155
case SQL_CONVERT_NUMERIC:
156
case SQL_CONVERT_REAL:
157
case SQL_CONVERT_DATE:
158
case SQL_CONVERT_TIME:
159
case SQL_CONVERT_TIMESTAMP:
160
case SQL_CONVERT_BINARY:
161
case SQL_CONVERT_LONGVARBINARY:
162
case SQL_CONVERT_VARBINARY: /* ODBC 1.0 */
163
case SQL_CONVERT_CHAR:
164
case SQL_CONVERT_LONGVARCHAR:
165
#if defined(UNICODE_SUPPORT) && (ODBCVER >= 0x0300)
166
case SQL_CONVERT_WCHAR:
167
case SQL_CONVERT_WLONGVARCHAR:
168
case SQL_CONVERT_WVARCHAR:
169
#endif /* UNICODE_SUPPORT */
170
len = sizeof(SQLUINTEGER);
171
value = 0; /* CONVERT is unavailable */
174
case SQL_CONVERT_FUNCTIONS: /* ODBC 1.0 */
175
len = sizeof(SQLUINTEGER);
176
value = SQL_FN_CVT_CONVERT;
177
mylog("CONVERT_FUNCTIONS=" FORMAT_ULEN "\n", value);
180
case SQL_CORRELATION_NAME: /* ODBC 1.0 */
183
* Saying no correlation name makes Query not work right.
184
* value = SQL_CN_NONE;
190
case SQL_CURSOR_COMMIT_BEHAVIOR: /* ODBC 1.0 */
192
value = SQL_CB_CLOSE;
193
if (!ci->drivers.use_declarefetch || PG_VERSION_GE(conn, 7.4))
194
value = SQL_CB_PRESERVE;
197
case SQL_CURSOR_ROLLBACK_BEHAVIOR: /* ODBC 1.0 */
199
value = SQL_CB_CLOSE;
200
if (!ci->drivers.use_declarefetch)
201
value = SQL_CB_PRESERVE;
204
case SQL_DATA_SOURCE_NAME: /* ODBC 1.0 */
205
p = CC_get_DSN(conn);
208
case SQL_DATA_SOURCE_READ_ONLY: /* ODBC 1.0 */
209
p = CC_is_onlyread(conn) ? "Y" : "N";
212
case SQL_DATABASE_NAME: /* Support for old ODBC 1.0 Apps */
215
* Returning the database name causes problems in MS Query. It
216
* generates query like: "SELECT DISTINCT a FROM byronnbad3
219
* p = CC_get_database(conn);
221
p = CurrCatString(conn);
224
case SQL_DBMS_NAME: /* ODBC 1.0 */
225
if (CC_fake_mss(conn))
226
p = "Microsoft SQL Server";
231
case SQL_DBMS_VER: /* ODBC 1.0 */
234
* The ODBC spec wants ##.##.#### ...whatever... so prepend
237
/* version number to the dbms version string */
239
snprintf(tmp, sizeof(tmp) - 1, "%s %s", POSTGRESDRIVERVERSION, conn->pg_version);
240
tmp[sizeof(tmp) - 1] = '\0'; */
241
if (CC_fake_mss(conn))
245
strncpy_null(tmp, conn->pg_version, sizeof(tmp));
250
case SQL_DEFAULT_TXN_ISOLATION: /* ODBC 1.0 */
252
if (PG_VERSION_LT(conn, 6.5))
253
value = SQL_TXN_SERIALIZABLE;
255
value = SQL_TXN_READ_COMMITTED;
258
case SQL_DRIVER_NAME: /* ODBC 1.0 */
259
p = DRIVER_FILE_NAME;
262
case SQL_DRIVER_ODBC_VER:
263
i_odbcver = conn->driver_version;
264
snprintf(odbcver, sizeof(odbcver), "%02x.%02x", i_odbcver / 256, i_odbcver % 256);
265
/* p = DRIVER_ODBC_VER; */
269
case SQL_DRIVER_VER: /* ODBC 1.0 */
270
p = POSTGRESDRIVERVERSION;
273
case SQL_EXPRESSIONS_IN_ORDERBY: /* ODBC 1.0 */
274
p = PG_VERSION_GE(conn, 6.5) ? "Y" : "N";
277
case SQL_FETCH_DIRECTION: /* ODBC 1.0 */
279
value = (SQL_FD_FETCH_NEXT |
284
SQL_FD_FETCH_ABSOLUTE |
285
SQL_FD_FETCH_RELATIVE |
286
SQL_FD_FETCH_BOOKMARK);
289
case SQL_FILE_USAGE: /* ODBC 2.0 */
291
value = SQL_FILE_NOT_SUPPORTED;
294
case SQL_GETDATA_EXTENSIONS: /* ODBC 2.0 */
296
value = (SQL_GD_ANY_COLUMN | SQL_GD_ANY_ORDER | SQL_GD_BOUND | SQL_GD_BLOCK);
299
case SQL_GROUP_BY: /* ODBC 2.0 */
301
value = SQL_GB_GROUP_BY_EQUALS_SELECT;
304
case SQL_IDENTIFIER_CASE: /* ODBC 1.0 */
307
* are identifiers case-sensitive (yes, but only when quoted.
308
* If not quoted, they default to lowercase)
311
value = SQL_IC_LOWER;
314
case SQL_IDENTIFIER_QUOTE_CHAR: /* ODBC 1.0 */
315
/* the character used to quote "identifiers" */
316
p = PG_VERSION_LE(conn, 6.2) ? " " : "\"";
319
case SQL_KEYWORDS: /* ODBC 2.0 */
323
case SQL_LIKE_ESCAPE_CLAUSE: /* ODBC 2.0 */
326
* is there a character that escapes '%' and '_' in a LIKE
327
* clause? not as far as I can tell
332
case SQL_LOCK_TYPES: /* ODBC 2.0 */
334
value = ci->drivers.lie ? (SQL_LCK_NO_CHANGE | SQL_LCK_EXCLUSIVE | SQL_LCK_UNLOCK) : SQL_LCK_NO_CHANGE;
337
case SQL_MAX_BINARY_LITERAL_LEN: /* ODBC 2.0 */
342
case SQL_MAX_CHAR_LITERAL_LEN: /* ODBC 2.0 */
347
case SQL_MAX_COLUMN_NAME_LEN: /* ODBC 1.0 */
349
if (PG_VERSION_GT(conn, 7.4))
350
value = CC_get_max_idlen(conn);
351
#ifdef MAX_COLUMN_LEN
353
value = MAX_COLUMN_LEN;
354
#endif /* MAX_COLUMN_LEN */
357
if (PG_VERSION_GE(conn, 7.3))
358
value = NAMEDATALEN_V73;
360
value = NAMEDATALEN_V72;
364
case SQL_MAX_COLUMNS_IN_GROUP_BY: /* ODBC 2.0 */
369
case SQL_MAX_COLUMNS_IN_INDEX: /* ODBC 2.0 */
374
case SQL_MAX_COLUMNS_IN_ORDER_BY: /* ODBC 2.0 */
379
case SQL_MAX_COLUMNS_IN_SELECT: /* ODBC 2.0 */
384
case SQL_MAX_COLUMNS_IN_TABLE: /* ODBC 2.0 */
389
case SQL_MAX_CURSOR_NAME_LEN: /* ODBC 1.0 */
391
value = MAX_CURSOR_LEN;
394
case SQL_MAX_INDEX_SIZE: /* ODBC 2.0 */
399
case SQL_MAX_OWNER_NAME_LEN: /* ODBC 1.0 */
402
if (PG_VERSION_GT(conn, 7.4))
403
value = CC_get_max_idlen(conn);
404
#ifdef MAX_SCHEMA_LEN
405
else if (conn->schema_support)
406
value = MAX_SCHEMA_LEN;
407
#endif /* MAX_SCHEMA_LEN */
410
if (PG_VERSION_GE(conn, 7.3))
411
value = NAMEDATALEN_V73;
415
case SQL_MAX_PROCEDURE_NAME_LEN: /* ODBC 1.0 */
420
case SQL_MAX_QUALIFIER_NAME_LEN: /* ODBC 1.0 */
425
case SQL_MAX_ROW_SIZE: /* ODBC 2.0 */
427
if (PG_VERSION_GE(conn, 7.1))
429
/* Large Rowa in 7.1+ */
430
value = MAX_ROW_SIZE;
434
/* Without the Toaster we're limited to the blocksize */
439
case SQL_MAX_ROW_SIZE_INCLUDES_LONG: /* ODBC 2.0 */
442
* does the preceding value include LONGVARCHAR and
443
* LONGVARBINARY fields? Well, it does include longvarchar,
444
* but not longvarbinary.
449
case SQL_MAX_STATEMENT_LEN: /* ODBC 2.0 */
450
/* maybe this should be 0? */
452
value = CC_get_max_query_len(conn);
455
case SQL_MAX_TABLE_NAME_LEN: /* ODBC 1.0 */
457
if (PG_VERSION_GT(conn, 7.4))
458
value = CC_get_max_idlen(conn);
461
value = MAX_TABLE_LEN;
462
#endif /* MAX_TABLE_LEN */
465
if (PG_VERSION_GE(conn, 7.3))
466
value = NAMEDATALEN_V73;
468
value = NAMEDATALEN_V72;
472
case SQL_MAX_TABLES_IN_SELECT: /* ODBC 2.0 */
477
case SQL_MAX_USER_NAME_LEN:
482
case SQL_MULT_RESULT_SETS: /* ODBC 1.0 */
483
/* Don't support multiple result sets but say yes anyway? */
487
case SQL_MULTIPLE_ACTIVE_TXN: /* ODBC 1.0 */
491
case SQL_NEED_LONG_DATA_LEN: /* ODBC 2.0 */
494
* Don't need the length, SQLPutData can handle any size and
500
case SQL_NON_NULLABLE_COLUMNS: /* ODBC 1.0 */
502
value = SQL_NNC_NON_NULL;
505
case SQL_NULL_COLLATION: /* ODBC 2.0 */
506
/* where are nulls sorted? */
508
if (PG_VERSION_GE(conn, 7.2))
514
case SQL_NUMERIC_FUNCTIONS: /* ODBC 1.0 */
519
case SQL_ODBC_API_CONFORMANCE: /* ODBC 1.0 */
521
value = SQL_OAC_LEVEL1;
524
case SQL_ODBC_SAG_CLI_CONFORMANCE: /* ODBC 1.0 */
526
value = SQL_OSCC_NOT_COMPLIANT;
529
case SQL_ODBC_SQL_CONFORMANCE: /* ODBC 1.0 */
531
value = SQL_OSC_CORE;
534
case SQL_ODBC_SQL_OPT_IEF: /* ODBC 1.0 */
538
case SQL_OJ_CAPABILITIES: /* ODBC 2.01 */
540
if (PG_VERSION_GE(conn, 7.1))
543
value = (SQL_OJ_LEFT |
549
SQL_OJ_ALL_COMPARISON_OPS);
552
/* OJs not in <7.1 */
556
case SQL_ORDER_BY_COLUMNS_IN_SELECT: /* ODBC 2.0 */
557
p = (PG_VERSION_LE(conn, 6.3)) ? "Y" : "N";
560
case SQL_OUTER_JOINS: /* ODBC 1.0 */
561
if (PG_VERSION_GE(conn, 7.1))
565
/* OJs not in <7.1 */
569
case SQL_OWNER_TERM: /* ODBC 1.0 */
570
if (conn->schema_support)
576
case SQL_OWNER_USAGE: /* ODBC 2.0 */
579
if (conn->schema_support)
580
value = SQL_OU_DML_STATEMENTS
581
| SQL_OU_TABLE_DEFINITION
582
| SQL_OU_INDEX_DEFINITION
583
| SQL_OU_PRIVILEGE_DEFINITION
587
case SQL_POS_OPERATIONS: /* ODBC 2.0 */
589
value = (SQL_POS_POSITION | SQL_POS_REFRESH);
590
if (0 != ci->updatable_cursors)
591
value |= (SQL_POS_UPDATE | SQL_POS_DELETE | SQL_POS_ADD);
594
case SQL_POSITIONED_STATEMENTS: /* ODBC 2.0 */
596
value = ci->drivers.lie ? (SQL_PS_POSITIONED_DELETE |
597
SQL_PS_POSITIONED_UPDATE |
598
SQL_PS_SELECT_FOR_UPDATE) : 0;
601
case SQL_PROCEDURE_TERM: /* ODBC 1.0 */
605
case SQL_PROCEDURES: /* ODBC 1.0 */
609
case SQL_QUALIFIER_LOCATION: /* ODBC 2.0 */
612
value = SQL_QL_START;
617
case SQL_QUALIFIER_NAME_SEPARATOR: /* ODBC 1.0 */
624
case SQL_QUALIFIER_TERM: /* ODBC 1.0 */
631
case SQL_QUALIFIER_USAGE: /* ODBC 2.0 */
633
#if (ODBCVER >= 0x0300)
635
value = SQL_CU_DML_STATEMENTS;
641
case SQL_QUOTED_IDENTIFIER_CASE: /* ODBC 2.0 */
642
/* are "quoted" identifiers case-sensitive? YES! */
644
value = SQL_IC_SENSITIVE;
647
case SQL_ROW_UPDATES: /* ODBC 1.0 */
650
* Driver doesn't support keyset-driven or mixed cursors, so
651
* not much point in saying row updates are supported
653
p = (0 != ci->updatable_cursors) ? "Y" : "N";
656
case SQL_SCROLL_CONCURRENCY: /* ODBC 1.0 */
658
value = SQL_SCCO_READ_ONLY;
659
if (0 != ci->updatable_cursors)
660
value |= SQL_SCCO_OPT_ROWVER;
662
value |= (SQL_SCCO_LOCK | SQL_SCCO_OPT_VALUES);
665
case SQL_SCROLL_OPTIONS: /* ODBC 1.0 */
667
value = SQL_SO_FORWARD_ONLY | SQL_SO_STATIC;
668
if (0 != (ci->updatable_cursors & ALLOW_KEYSET_DRIVEN_CURSORS))
669
value |= SQL_SO_KEYSET_DRIVEN;
671
value |= (SQL_SO_DYNAMIC | SQL_SO_MIXED);
674
case SQL_SEARCH_PATTERN_ESCAPE: /* ODBC 1.0 */
675
if (PG_VERSION_GE(conn, 6.5))
681
case SQL_SERVER_NAME: /* ODBC 1.0 */
682
p = CC_get_server(conn);
685
case SQL_SPECIAL_CHARACTERS: /* ODBC 2.0 */
689
case SQL_STATIC_SENSITIVITY: /* ODBC 2.0 */
692
if (0 != ci->updatable_cursors)
693
value |= (SQL_SS_ADDITIONS | SQL_SS_DELETIONS | SQL_SS_UPDATES);
696
case SQL_STRING_FUNCTIONS: /* ODBC 1.0 */
698
value = (SQL_FN_STR_CONCAT |
704
SQL_FN_STR_SUBSTRING |
708
case SQL_SUBQUERIES: /* ODBC 2.0 */
709
/* postgres 6.3 supports subqueries */
711
value = (SQL_SQ_QUANTIFIED |
717
case SQL_SYSTEM_FUNCTIONS: /* ODBC 1.0 */
722
case SQL_TABLE_TERM: /* ODBC 1.0 */
726
case SQL_TIMEDATE_ADD_INTERVALS: /* ODBC 2.0 */
731
case SQL_TIMEDATE_DIFF_INTERVALS: /* ODBC 2.0 */
736
case SQL_TIMEDATE_FUNCTIONS: /* ODBC 1.0 */
738
value = (SQL_FN_TD_NOW);
741
case SQL_TXN_CAPABLE: /* ODBC 1.0 */
744
* Postgres can deal with create or drop table statements in a
751
case SQL_TXN_ISOLATION_OPTION: /* ODBC 1.0 */
753
if (PG_VERSION_LT(conn, 6.5))
754
value = SQL_TXN_SERIALIZABLE;
755
else if (PG_VERSION_GE(conn, 7.1))
756
value = SQL_TXN_READ_COMMITTED | SQL_TXN_SERIALIZABLE;
758
value = SQL_TXN_READ_COMMITTED;
761
case SQL_UNION: /* ODBC 2.0 */
762
/* unions with all supported in postgres 6.3 */
764
value = (SQL_U_UNION | SQL_U_UNION_ALL);
767
case SQL_USER_NAME: /* ODBC 1.0 */
768
p = CC_get_username(conn);
772
/* unrecognized key */
773
CC_set_error(conn, CONN_NOT_IMPLEMENTED_ERROR, "Unrecognized key passed to PGAPI_GetInfo.", NULL);
777
result = SQL_SUCCESS;
779
mylog("%s: p='%s', len=%d, value=%d, cbMax=%d\n", func, p ? p : "<NULL>", len, value, cbInfoValueMax);
782
* NOTE, that if rgbInfoValue is NULL, then no warnings or errors
783
* should result and just pcbInfoValue is returned, which indicates
784
* what length would be required if a real buffer had been passed in.
788
/* char/binary data */
793
#ifdef UNICODE_SUPPORT
794
if (CC_is_in_unicode_driver(conn))
796
len = utf8_to_ucs2(p, len, (SQLWCHAR *) rgbInfoValue, cbInfoValueMax / WCLEN);
800
#endif /* UNICODE_SUPPORT */
801
strncpy_null((char *) rgbInfoValue, p, (size_t) cbInfoValueMax);
803
if (len >= cbInfoValueMax)
805
result = SQL_SUCCESS_WITH_INFO;
806
CC_set_error(conn, CONN_TRUNCATED, "The buffer was too small for the InfoValue.", func);
809
#ifdef UNICODE_SUPPORT
810
else if (CC_is_in_unicode_driver(conn))
812
#endif /* UNICODE_SUPPORT */
819
if (len == sizeof(SQLSMALLINT))
820
*((SQLUSMALLINT *) rgbInfoValue) = (SQLUSMALLINT) value;
821
else if (len == sizeof(SQLINTEGER))
822
*((SQLUINTEGER *) rgbInfoValue) = (SQLUINTEGER) value;
827
*pcbInfoValue = (SQLSMALLINT) len;
837
SQLSMALLINT fSqlType)
839
CSTR func = "PGAPI_GetTypeInfo";
840
StatementClass *stmt = (StatementClass *) hstmt;
841
ConnectionClass *conn;
842
QResultClass *res = NULL;
849
RETCODE result = SQL_SUCCESS;
851
mylog("%s: entering...fSqlType = %d\n", func, fSqlType);
853
if (result = SC_initialize_and_recycle(stmt), SQL_SUCCESS != result)
856
conn = SC_get_conn(stmt);
857
if (res = QR_Constructor(), !res)
859
SC_set_error(stmt, STMT_INTERNAL_ERROR, "Error creating result.", func);
862
SC_set_Result(stmt, res);
864
#define return DONT_CALL_RETURN_FROM_HERE???
865
#if (ODBCVER >= 0x0300)
870
extend_column_bindings(SC_get_ARDF(stmt), result_cols);
872
stmt->catalog_result = TRUE;
873
QR_set_num_fields(res, result_cols);
874
QR_set_field_info_v(res, 0, "TYPE_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
875
QR_set_field_info_v(res, 1, "DATA_TYPE", PG_TYPE_INT2, 2);
876
QR_set_field_info_v(res, 2, "PRECISION", PG_TYPE_INT4, 4);
877
QR_set_field_info_v(res, 3, "LITERAL_PREFIX", PG_TYPE_VARCHAR, MAX_INFO_STRING);
878
QR_set_field_info_v(res, 4, "LITERAL_SUFFIX", PG_TYPE_VARCHAR, MAX_INFO_STRING);
879
QR_set_field_info_v(res, 5, "CREATE_PARAMS", PG_TYPE_VARCHAR, MAX_INFO_STRING);
880
QR_set_field_info_v(res, 6, "NULLABLE", PG_TYPE_INT2, 2);
881
QR_set_field_info_v(res, 7, "CASE_SENSITIVE", PG_TYPE_INT2, 2);
882
QR_set_field_info_v(res, 8, "SEARCHABLE", PG_TYPE_INT2, 2);
883
QR_set_field_info_v(res, 9, "UNSIGNED_ATTRIBUTE", PG_TYPE_INT2, 2);
884
QR_set_field_info_v(res, 10, "MONEY", PG_TYPE_INT2, 2);
885
QR_set_field_info_v(res, 11, "AUTO_INCREMENT", PG_TYPE_INT2, 2);
886
QR_set_field_info_v(res, 12, "LOCAL_TYPE_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
887
QR_set_field_info_v(res, 13, "MINIMUM_SCALE", PG_TYPE_INT2, 2);
888
QR_set_field_info_v(res, 14, "MAXIMUM_SCALE", PG_TYPE_INT2, 2);
889
#if (ODBCVER >=0x0300)
890
QR_set_field_info_v(res, 15, "SQL_DATA_TYPE", PG_TYPE_INT2, 2);
891
QR_set_field_info_v(res, 16, "SQL_DATETIME_SUB", PG_TYPE_INT2, 2);
892
QR_set_field_info_v(res, 17, "NUM_PREC_RADIX", PG_TYPE_INT4, 4);
893
QR_set_field_info_v(res, 18, "INTERVAL_PRECISION", PG_TYPE_INT2, 2);
896
for (i = 0, sqlType = sqlTypes[0]; sqlType; sqlType = sqlTypes[++i])
898
pgType = sqltype_to_pgtype(conn, sqlType);
900
if (sqlType == SQL_LONGVARBINARY)
902
ConnInfo *ci = &(conn->connInfo);
903
inolog("%d sqltype=%d -> pgtype=%d\n", ci->bytea_as_longvarbinary, sqlType, pgType);
906
if (fSqlType == SQL_ALL_TYPES || fSqlType == sqlType)
908
int pgtcount = 1, aunq_match = -1, cnt;
910
/*if (SQL_INTEGER == sqlType || SQL_TINYINT == sqlType)*/
911
if (SQL_INTEGER == sqlType)
913
mylog("sqlType=%d ms_jet=%d\n", sqlType, conn->ms_jet);
914
if (conn->ms_jet && PG_VERSION_GE(conn, 6.4))
919
mylog("aunq_match=%d pgtcount=%d\n", aunq_match, pgtcount);
921
for (cnt = 0; cnt < pgtcount; cnt ++)
923
if (tuple = QR_AddNew(res), NULL == tuple)
926
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't QR_AddNew.", func);
930
/* These values can't be NULL */
931
if (aunq_match == cnt)
933
set_tuplefield_string(&tuple[0], pgtype_to_name(stmt, pgType, PG_UNSPECIFIED, TRUE));
934
set_tuplefield_int2(&tuple[6], SQL_NO_NULLS);
935
inolog("serial in\n");
939
set_tuplefield_string(&tuple[0], pgtype_to_name(stmt, pgType, PG_UNSPECIFIED, FALSE));
940
set_tuplefield_int2(&tuple[6], pgtype_nullable(conn, pgType));
942
set_tuplefield_int2(&tuple[1], (Int2) sqlType);
943
set_tuplefield_int2(&tuple[7], pgtype_case_sensitive(conn, pgType));
944
set_tuplefield_int2(&tuple[8], pgtype_searchable(conn, pgType));
945
set_tuplefield_int2(&tuple[10], pgtype_money(conn, pgType));
948
* Localized data-source dependent data type name (always
951
set_tuplefield_null(&tuple[12]);
953
/* These values can be NULL */
954
set_nullfield_int4(&tuple[2], pgtype_column_size(stmt, pgType, PG_STATIC, UNKNOWNS_AS_DEFAULT));
955
set_nullfield_string(&tuple[3], pgtype_literal_prefix(conn, pgType));
956
set_nullfield_string(&tuple[4], pgtype_literal_suffix(conn, pgType));
957
set_nullfield_string(&tuple[5], pgtype_create_params(conn, pgType));
959
set_tuplefield_int2(&tuple[9], SQL_TRUE);
961
set_nullfield_int2(&tuple[9], pgtype_unsigned(conn, pgType));
962
if (aunq_match == cnt)
963
set_tuplefield_int2(&tuple[11], SQL_TRUE);
965
set_nullfield_int2(&tuple[11], pgtype_auto_increment(conn, pgType));
966
set_nullfield_int2(&tuple[13], pgtype_min_decimal_digits(conn, pgType));
967
set_nullfield_int2(&tuple[14], pgtype_max_decimal_digits(conn, pgType));
968
#if (ODBCVER >=0x0300)
969
set_nullfield_int2(&tuple[15], pgtype_to_sqldesctype(stmt, pgType, PG_STATIC));
970
set_nullfield_int2(&tuple[16], pgtype_to_datetime_sub(stmt, pgType, PG_UNSPECIFIED));
971
set_nullfield_int4(&tuple[17], pgtype_radix(conn, pgType));
972
set_nullfield_int4(&tuple[18], 0);
981
* also, things need to think that this statement is finished so the
982
* results can be retrieved.
984
stmt->status = STMT_FINISHED;
985
stmt->currTuple = -1;
986
if (SQL_SUCCEEDED(result))
987
SC_set_rowset_start(stmt, -1, FALSE);
989
SC_set_Result(stmt, NULL);
990
SC_set_current_col(stmt, -1);
993
result = DiscardStatementSvp(stmt, result, FALSE);
1001
SQLUSMALLINT fFunction,
1002
SQLUSMALLINT FAR * pfExists)
1004
CSTR func = "PGAPI_GetFunctions";
1005
ConnectionClass *conn = (ConnectionClass *) hdbc;
1006
ConnInfo *ci = &(conn->connInfo);
1008
mylog("%s: entering...%u\n", func, fFunction);
1010
if (fFunction == SQL_API_ALL_FUNCTIONS)
1012
#if (ODBCVER < 0x0300)
1013
if (ci->drivers.lie)
1017
memset(pfExists, 0, sizeof(pfExists[0]) * 100);
1019
pfExists[SQL_API_SQLALLOCENV] = TRUE;
1020
pfExists[SQL_API_SQLFREEENV] = TRUE;
1021
for (i = SQL_API_SQLALLOCCONNECT; i <= SQL_NUM_FUNCTIONS; i++)
1023
for (i = SQL_EXT_API_START; i <= SQL_EXT_API_LAST; i++)
1029
memset(pfExists, 0, sizeof(pfExists[0]) * 100);
1031
/* ODBC core functions */
1032
pfExists[SQL_API_SQLALLOCCONNECT] = TRUE;
1033
pfExists[SQL_API_SQLALLOCENV] = TRUE;
1034
pfExists[SQL_API_SQLALLOCSTMT] = TRUE;
1035
pfExists[SQL_API_SQLBINDCOL] = TRUE;
1036
pfExists[SQL_API_SQLCANCEL] = TRUE;
1037
pfExists[SQL_API_SQLCOLATTRIBUTES] = TRUE;
1038
pfExists[SQL_API_SQLCONNECT] = TRUE;
1039
pfExists[SQL_API_SQLDESCRIBECOL] = TRUE; /* partial */
1040
pfExists[SQL_API_SQLDISCONNECT] = TRUE;
1041
pfExists[SQL_API_SQLERROR] = TRUE;
1042
pfExists[SQL_API_SQLEXECDIRECT] = TRUE;
1043
pfExists[SQL_API_SQLEXECUTE] = TRUE;
1044
pfExists[SQL_API_SQLFETCH] = TRUE;
1045
pfExists[SQL_API_SQLFREECONNECT] = TRUE;
1046
pfExists[SQL_API_SQLFREEENV] = TRUE;
1047
pfExists[SQL_API_SQLFREESTMT] = TRUE;
1048
pfExists[SQL_API_SQLGETCURSORNAME] = TRUE;
1049
pfExists[SQL_API_SQLNUMRESULTCOLS] = TRUE;
1050
pfExists[SQL_API_SQLPREPARE] = TRUE; /* complete? */
1051
pfExists[SQL_API_SQLROWCOUNT] = TRUE;
1052
pfExists[SQL_API_SQLSETCURSORNAME] = TRUE;
1053
pfExists[SQL_API_SQLSETPARAM] = FALSE; /* odbc 1.0 */
1054
pfExists[SQL_API_SQLTRANSACT] = TRUE;
1056
/* ODBC level 1 functions */
1057
pfExists[SQL_API_SQLBINDPARAMETER] = TRUE;
1058
pfExists[SQL_API_SQLCOLUMNS] = TRUE;
1059
pfExists[SQL_API_SQLDRIVERCONNECT] = TRUE;
1060
pfExists[SQL_API_SQLGETCONNECTOPTION] = TRUE; /* partial */
1061
pfExists[SQL_API_SQLGETDATA] = TRUE;
1062
pfExists[SQL_API_SQLGETFUNCTIONS] = TRUE;
1063
pfExists[SQL_API_SQLGETINFO] = TRUE;
1064
pfExists[SQL_API_SQLGETSTMTOPTION] = TRUE; /* partial */
1065
pfExists[SQL_API_SQLGETTYPEINFO] = TRUE;
1066
pfExists[SQL_API_SQLPARAMDATA] = TRUE;
1067
pfExists[SQL_API_SQLPUTDATA] = TRUE;
1068
pfExists[SQL_API_SQLSETCONNECTOPTION] = TRUE; /* partial */
1069
pfExists[SQL_API_SQLSETSTMTOPTION] = TRUE;
1070
pfExists[SQL_API_SQLSPECIALCOLUMNS] = TRUE;
1071
pfExists[SQL_API_SQLSTATISTICS] = TRUE;
1072
pfExists[SQL_API_SQLTABLES] = TRUE;
1074
/* ODBC level 2 functions */
1075
pfExists[SQL_API_SQLBROWSECONNECT] = FALSE;
1076
if (PG_VERSION_GE(conn, 7.4))
1077
pfExists[SQL_API_SQLCOLUMNPRIVILEGES] = FALSE;
1079
pfExists[SQL_API_SQLCOLUMNPRIVILEGES] = FALSE;
1080
pfExists[SQL_API_SQLDATASOURCES] = FALSE; /* only implemented by
1082
if (SUPPORT_DESCRIBE_PARAM(ci))
1083
pfExists[SQL_API_SQLDESCRIBEPARAM] = TRUE;
1085
pfExists[SQL_API_SQLDESCRIBEPARAM] = FALSE; /* not properly
1087
pfExists[SQL_API_SQLDRIVERS] = FALSE; /* only implemented by
1089
pfExists[SQL_API_SQLEXTENDEDFETCH] = TRUE;
1090
pfExists[SQL_API_SQLFOREIGNKEYS] = TRUE;
1091
pfExists[SQL_API_SQLMORERESULTS] = TRUE;
1092
pfExists[SQL_API_SQLNATIVESQL] = TRUE;
1093
pfExists[SQL_API_SQLNUMPARAMS] = TRUE;
1094
pfExists[SQL_API_SQLPARAMOPTIONS] = TRUE;
1095
pfExists[SQL_API_SQLPRIMARYKEYS] = TRUE;
1096
if (PG_VERSION_LT(conn, 6.5))
1097
pfExists[SQL_API_SQLPROCEDURECOLUMNS] = FALSE;
1099
pfExists[SQL_API_SQLPROCEDURECOLUMNS] = TRUE;
1100
if (PG_VERSION_LT(conn, 6.5))
1101
pfExists[SQL_API_SQLPROCEDURES] = FALSE;
1103
pfExists[SQL_API_SQLPROCEDURES] = TRUE;
1104
pfExists[SQL_API_SQLSETPOS] = TRUE;
1105
pfExists[SQL_API_SQLSETSCROLLOPTIONS] = TRUE; /* odbc 1.0 */
1106
pfExists[SQL_API_SQLTABLEPRIVILEGES] = TRUE;
1107
#if (ODBCVER >= 0x0300)
1108
if (0 == ci->updatable_cursors)
1109
pfExists[SQL_API_SQLBULKOPERATIONS] = FALSE;
1111
pfExists[SQL_API_SQLBULKOPERATIONS] = TRUE;
1112
#endif /* ODBCVER */
1117
if (ci->drivers.lie)
1123
#if (ODBCVER < 0x0300)
1124
case SQL_API_SQLALLOCCONNECT:
1127
case SQL_API_SQLALLOCENV:
1130
case SQL_API_SQLALLOCSTMT:
1133
#endif /* ODBCVER */
1134
case SQL_API_SQLBINDCOL:
1137
case SQL_API_SQLCANCEL:
1140
#if (ODBCVER >= 0x0300)
1141
case SQL_API_SQLCOLATTRIBUTE:
1143
case SQL_API_SQLCOLATTRIBUTES:
1144
#endif /* ODBCVER */
1147
case SQL_API_SQLCONNECT:
1150
case SQL_API_SQLDESCRIBECOL:
1152
break; /* partial */
1153
case SQL_API_SQLDISCONNECT:
1156
#if (ODBCVER < 0x0300)
1157
case SQL_API_SQLERROR:
1160
#endif /* ODBCVER */
1161
case SQL_API_SQLEXECDIRECT:
1164
case SQL_API_SQLEXECUTE:
1167
case SQL_API_SQLFETCH:
1170
#if (ODBCVER < 0x0300)
1171
case SQL_API_SQLFREECONNECT:
1174
case SQL_API_SQLFREEENV:
1177
#endif /* ODBCVER */
1178
case SQL_API_SQLFREESTMT:
1181
case SQL_API_SQLGETCURSORNAME:
1184
case SQL_API_SQLNUMRESULTCOLS:
1187
case SQL_API_SQLPREPARE:
1190
case SQL_API_SQLROWCOUNT:
1193
case SQL_API_SQLSETCURSORNAME:
1196
#if (ODBCVER < 0x0300)
1197
case SQL_API_SQLSETPARAM:
1199
break; /* odbc 1.0 */
1200
case SQL_API_SQLTRANSACT:
1203
#endif /* ODBCVER */
1205
/* ODBC level 1 functions */
1206
case SQL_API_SQLBINDPARAMETER:
1209
case SQL_API_SQLCOLUMNS:
1212
case SQL_API_SQLDRIVERCONNECT:
1215
#if (ODBCVER < 0x0300)
1216
case SQL_API_SQLGETCONNECTOPTION:
1218
break; /* partial */
1219
#endif /* ODBCVER */
1220
case SQL_API_SQLGETDATA:
1223
case SQL_API_SQLGETFUNCTIONS:
1226
case SQL_API_SQLGETINFO:
1229
#if (ODBCVER < 0x0300)
1230
case SQL_API_SQLGETSTMTOPTION:
1232
break; /* partial */
1233
#endif /* ODBCVER */
1234
case SQL_API_SQLGETTYPEINFO:
1237
case SQL_API_SQLPARAMDATA:
1240
case SQL_API_SQLPUTDATA:
1243
#if (ODBCVER < 0x0300)
1244
case SQL_API_SQLSETCONNECTOPTION:
1246
break; /* partial */
1247
case SQL_API_SQLSETSTMTOPTION:
1250
#endif /* ODBCVER */
1251
case SQL_API_SQLSPECIALCOLUMNS:
1254
case SQL_API_SQLSTATISTICS:
1257
case SQL_API_SQLTABLES:
1261
/* ODBC level 2 functions */
1262
case SQL_API_SQLBROWSECONNECT:
1265
case SQL_API_SQLCOLUMNPRIVILEGES:
1268
case SQL_API_SQLDATASOURCES:
1270
break; /* only implemented by DM */
1271
case SQL_API_SQLDESCRIBEPARAM:
1272
if (SUPPORT_DESCRIBE_PARAM(ci))
1276
break; /* not properly implemented */
1277
case SQL_API_SQLDRIVERS:
1279
break; /* only implemented by DM */
1280
case SQL_API_SQLEXTENDEDFETCH:
1283
case SQL_API_SQLFOREIGNKEYS:
1286
case SQL_API_SQLMORERESULTS:
1289
case SQL_API_SQLNATIVESQL:
1292
case SQL_API_SQLNUMPARAMS:
1295
#if (ODBCVER < 0x0300)
1296
case SQL_API_SQLPARAMOPTIONS:
1299
#endif /* ODBCVER */
1300
case SQL_API_SQLPRIMARYKEYS:
1303
case SQL_API_SQLPROCEDURECOLUMNS:
1304
if (PG_VERSION_LT(conn, 6.5))
1309
case SQL_API_SQLPROCEDURES:
1310
if (PG_VERSION_LT(conn, 6.5))
1315
case SQL_API_SQLSETPOS:
1318
#if (ODBCVER < 0x0300)
1319
case SQL_API_SQLSETSCROLLOPTIONS:
1321
break; /* odbc 1.0 */
1322
#endif /* ODBCVER */
1323
case SQL_API_SQLTABLEPRIVILEGES:
1326
#if (ODBCVER >= 0x0300)
1327
case SQL_API_SQLBULKOPERATIONS: /* 24 */
1328
case SQL_API_SQLALLOCHANDLE: /* 1001 */
1329
case SQL_API_SQLBINDPARAM: /* 1002 */
1330
case SQL_API_SQLCLOSECURSOR: /* 1003 */
1331
case SQL_API_SQLENDTRAN: /* 1005 */
1332
case SQL_API_SQLFETCHSCROLL: /* 1021 */
1333
case SQL_API_SQLFREEHANDLE: /* 1006 */
1334
case SQL_API_SQLGETCONNECTATTR: /* 1007 */
1335
case SQL_API_SQLGETDESCFIELD: /* 1008 */
1336
case SQL_API_SQLGETDIAGFIELD: /* 1010 */
1337
case SQL_API_SQLGETDIAGREC: /* 1011 */
1338
case SQL_API_SQLGETENVATTR: /* 1012 */
1339
case SQL_API_SQLGETSTMTATTR: /* 1014 */
1340
case SQL_API_SQLSETCONNECTATTR: /* 1016 */
1341
case SQL_API_SQLSETDESCFIELD: /* 1017 */
1342
case SQL_API_SQLSETENVATTR: /* 1019 */
1343
case SQL_API_SQLSETSTMTATTR: /* 1020 */
1346
case SQL_API_SQLGETDESCREC: /* 1009 */
1347
case SQL_API_SQLSETDESCREC: /* 1018 */
1348
case SQL_API_SQLCOPYDESC: /* 1004 */
1351
#endif /* ODBCVER */
1363
simpleCatalogEscape(const char *src, int srclen, int *result_len, const ConnectionClass *conn)
1367
char *dest = NULL, escape_ch = CC_get_escape(conn);
1372
if (!src || srclen == SQL_NULL_DATA)
1374
else if (srclen == SQL_NTS)
1375
srclen = (int) strlen(src);
1378
mylog("simple in=%s(%d)\n", src, srclen);
1379
encoded_str_constr(&encstr, conn->ccsc, src);
1380
dest = malloc(2 * srclen + 1);
1381
for (i = 0, in = src, outlen = 0; i < srclen; i++, in++)
1383
encoded_nextchar(&encstr);
1384
if (ENCODE_STATUS(encstr) != 0)
1386
dest[outlen++] = *in;
1389
if (LITERAL_QUOTE == *in ||
1391
dest[outlen++] = *in;
1392
dest[outlen++] = *in;
1394
dest[outlen] = '\0';
1396
*result_len = outlen;
1397
mylog("simple output=%s(%d)\n", dest, outlen);
1402
* PostgreSQL needs 2 '\\' to escape '_' and '%'.
1405
adjustLikePattern(const char *src, int srclen, char escape_ch, int *result_len, const ConnectionClass *conn)
1409
char *dest = NULL, escape_in_literal = CC_get_escape(conn);
1410
BOOL escape_in = FALSE;
1415
if (!src || srclen == SQL_NULL_DATA)
1417
else if (srclen == SQL_NTS)
1418
srclen = (int) strlen(src);
1419
/* if (srclen <= 0) */
1422
mylog("adjust in=%.*s(%d)\n", srclen, src, srclen);
1423
encoded_str_constr(&encstr, conn->ccsc, src);
1424
dest = malloc(2 * srclen + 1);
1425
for (i = 0, in = src, outlen = 0; i < srclen; i++, in++)
1427
encoded_nextchar(&encstr);
1428
if (ENCODE_STATUS(encstr) != 0)
1430
dest[outlen++] = *in;
1441
if (escape_ch == escape_in_literal)
1442
dest[outlen++] = escape_in_literal;
1443
dest[outlen++] = escape_ch;
1447
if (*in == escape_ch)
1450
if (escape_ch == escape_in_literal)
1451
dest[outlen++] = escape_in_literal; /* insert 1 more LEXER escape */
1456
if (LITERAL_QUOTE == *in)
1457
dest[outlen++] = *in;
1459
dest[outlen++] = *in;
1463
if (escape_ch == escape_in_literal)
1464
dest[outlen++] = escape_in_literal;
1465
dest[outlen++] = escape_ch;
1467
dest[outlen] = '\0';
1469
*result_len = outlen;
1470
mylog("adjust output=%s(%d)\n", dest, outlen);
1474
#define CSTR_SYS_TABLE "SYSTEM TABLE"
1475
#define CSTR_TABLE "TABLE"
1476
#define CSTR_VIEW "VIEW"
1478
CSTR like_op_sp = "like ";
1479
CSTR like_op_ext = "like E";
1480
CSTR eq_op_sp = "= ";
1481
CSTR eq_op_ext = "= E";
1482
static const char *gen_opestr(const char *orig_opestr, const ConnectionClass * conn)
1484
BOOL addE = (0 != CC_get_escape(conn) && PG_VERSION_GE(conn, 8.1));
1486
if (0 == strcmp(orig_opestr, eqop))
1487
return (addE ? eq_op_ext : eq_op_sp);
1488
return (addE ? like_op_ext : like_op_sp);
1492
* If specified schema name == user_name and the current schema is
1493
* 'public', allowed to use the 'public' schema.
1496
allow_public_schema(ConnectionClass *conn, const char *szSchemaName, SQLSMALLINT cbSchemaName)
1498
const char *user = CC_get_username(conn);
1499
size_t userlen = strlen(user);
1501
if (NULL == szSchemaName)
1504
if (SQL_NTS == cbSchemaName)
1505
cbSchemaName = strlen(szSchemaName);
1507
return (cbSchemaName == (SQLSMALLINT) userlen &&
1508
strnicmp(szSchemaName, user, userlen) == 0 &&
1509
stricmp(CC_get_current_schema(conn), pubstr) == 0);
1515
const SQLCHAR FAR * szTableQualifier, /* PV X*/
1516
SQLSMALLINT cbTableQualifier,
1517
const SQLCHAR FAR * szTableOwner, /* PV E*/
1518
SQLSMALLINT cbTableOwner,
1519
const SQLCHAR FAR * szTableName, /* PV E*/
1520
SQLSMALLINT cbTableName,
1521
const SQLCHAR FAR * szTableType,
1522
SQLSMALLINT cbTableType,
1525
CSTR func = "PGAPI_Tables";
1526
StatementClass *stmt = (StatementClass *) hstmt;
1527
StatementClass *tbl_stmt;
1530
HSTMT htbl_stmt = NULL;
1531
RETCODE ret = SQL_ERROR, result;
1533
char *tableType = NULL;
1534
char tables_query[INFO_INQUIRY_LEN];
1535
char table_name[MAX_INFO_STRING],
1536
table_owner[MAX_INFO_STRING],
1537
relkind_or_hasrules[MAX_INFO_STRING];
1538
#ifdef HAVE_STRTOK_R
1540
#endif /* HAVE_STRTOK_R */
1541
ConnectionClass *conn;
1543
char *escCatName = NULL, *escSchemaName = NULL, *escTableName = NULL;
1545
prefixes[MEDIUM_REGISTRY_LEN];
1546
char *table_type[32],
1547
table_types[MAX_INFO_STRING];
1548
char show_system_tables,
1549
show_regular_tables,
1555
SQLSMALLINT internal_asis_type = SQL_C_CHAR, cbSchemaName;
1556
const char *like_or_eq, *op_string;
1557
const char *szSchemaName;
1558
BOOL search_pattern;
1559
BOOL list_cat = FALSE, list_schemas = FALSE, list_table_types = FALSE, list_some = FALSE;
1560
SQLLEN cbRelname, cbRelkind, cbSchName;
1562
mylog("%s: entering...stmt=%p scnm=%p len=%d\n", func, stmt, szTableOwner, cbTableOwner);
1564
if (result = SC_initialize_and_recycle(stmt), SQL_SUCCESS != result)
1567
conn = SC_get_conn(stmt);
1568
ci = &(conn->connInfo);
1570
result = PGAPI_AllocStmt(conn, &htbl_stmt, 0);
1571
if (!SQL_SUCCEEDED(result))
1573
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate statement for PGAPI_Tables result.", func);
1576
tbl_stmt = (StatementClass *) htbl_stmt;
1577
szSchemaName = szTableOwner;
1578
cbSchemaName = cbTableOwner;
1580
#define return DONT_CALL_RETURN_FROM_HERE???
1581
search_pattern = (0 == (flag & PODBC_NOT_SEARCH_PATTERN));
1584
like_or_eq = likeop;
1585
escCatName = adjustLikePattern(szTableQualifier, cbTableQualifier, SEARCH_PATTERN_ESCAPE, NULL, conn);
1586
escTableName = adjustLikePattern(szTableName, cbTableName, SEARCH_PATTERN_ESCAPE, NULL, conn);
1591
escCatName = simpleCatalogEscape(szTableQualifier, cbTableQualifier, NULL, conn);
1592
escTableName = simpleCatalogEscape(szTableName, cbTableName, NULL, conn);
1594
retry_public_schema:
1596
free(escSchemaName);
1598
escSchemaName = adjustLikePattern(szSchemaName, cbSchemaName, SEARCH_PATTERN_ESCAPE, NULL, conn);
1600
escSchemaName = simpleCatalogEscape(szSchemaName, cbSchemaName, NULL, conn);
1602
* Create the query to find out the tables
1604
/* make_string mallocs memory */
1605
tableType = make_string(szTableType, cbTableType, NULL, 0);
1606
#if (ODBCVER >= 0x0300)
1607
if (search_pattern &&
1608
escTableName && '\0' == escTableName[0] &&
1609
escCatName && escSchemaName)
1611
if ('\0' == escSchemaName[0])
1613
if (stricmp(escCatName, SQL_ALL_CATALOGS) == 0)
1615
else if ('\0' == escCatName[0] &&
1616
stricmp(tableType, SQL_ALL_TABLE_TYPES) == 0)
1617
list_table_types = TRUE;
1619
else if ('\0' == escCatName[0] &&
1620
stricmp(escSchemaName, SQL_ALL_SCHEMAS) == 0)
1621
list_schemas = TRUE;
1623
#endif /* ODBCVER */
1624
list_some = (list_cat || list_schemas || list_table_types);
1626
tables_query[0] = '\0';
1628
strncpy_null(tables_query, "select NULL, NULL, NULL", sizeof(tables_query));
1629
else if (list_table_types)
1630
strncpy_null(tables_query, "select NULL, NULL, relkind from (select 'r' as relkind union select 'v') as a", sizeof(tables_query));
1631
else if (list_schemas)
1633
if (conn->schema_support)
1634
strncpy_null(tables_query, "select NULL, nspname, NULL"
1635
" from pg_catalog.pg_namespace n where true", sizeof(tables_query));
1637
strncpy_null(tables_query, "select NULL, NULL as nspname, NULL", sizeof(tables_query));
1639
else if (conn->schema_support)
1641
/* view is represented by its relkind since 7.1 */
1642
strcpy(tables_query, "select relname, nspname, relkind"
1643
" from pg_catalog.pg_class c, pg_catalog.pg_namespace n");
1644
strcat(tables_query, " where relkind in ('r', 'v')");
1646
else if (PG_VERSION_GE(conn, 7.1))
1648
/* view is represented by its relkind since 7.1 */
1649
strcpy(tables_query, "select relname, usename, relkind"
1650
" from pg_class c, pg_user u");
1651
strcat(tables_query, " where relkind in ('r', 'v')");
1655
strcpy(tables_query, "select relname, usename, relhasrules from pg_class c, pg_user u");
1656
strcat(tables_query, " where relkind = 'r'");
1659
op_string = gen_opestr(like_or_eq, conn);
1662
if (conn->schema_support)
1664
schema_strcat1(tables_query, " and nspname %s'%.*s'", op_string, escSchemaName, SQL_NTS, szTableName, cbTableName, conn);
1665
/* strcat(tables_query, " and pg_catalog.pg_table_is_visible(c.oid)"); */
1668
my_strcat1(tables_query, " and usename %s'%.*s'", op_string, escSchemaName, SQL_NTS);
1669
my_strcat1(tables_query, " and relname %s'%.*s'", op_string, escTableName, SQL_NTS);
1672
/* Parse the extra systable prefix */
1673
strcpy(prefixes, ci->drivers.extra_systable_prefixes);
1675
#ifdef HAVE_STRTOK_R
1676
prefix[i] = strtok_r(prefixes, ";", &last);
1678
prefix[i] = strtok(prefixes, ";");
1679
#endif /* HAVE_STRTOK_R */
1680
while (i < sizeof(prefix) && prefix[i])
1681
#ifdef HAVE_STRTOK_R
1682
prefix[++i] = strtok_r(NULL, ";", &last);
1684
prefix[++i] = strtok(NULL, ";");
1685
#endif /* HAVE_STRTOK_R */
1687
/* Parse the desired table types to return */
1688
show_system_tables = FALSE;
1689
show_regular_tables = FALSE;
1695
show_regular_tables = TRUE;
1698
#if (ODBCVER >= 0x0300)
1699
else if (list_some || stricmp(tableType, SQL_ALL_TABLE_TYPES) == 0)
1701
show_regular_tables = TRUE;
1704
#endif /* ODBCVER */
1707
strcpy(table_types, tableType);
1709
#ifdef HAVE_STRTOK_R
1710
table_type[i] = strtok_r(table_types, ",", &last);
1712
table_type[i] = strtok(table_types, ",");
1713
#endif /* HAVE_STRTOK_R */
1714
while (i < sizeof(table_type) && table_type[i])
1715
#ifdef HAVE_STRTOK_R
1716
table_type[++i] = strtok_r(NULL, ",", &last);
1718
table_type[++i] = strtok(NULL, ",");
1719
#endif /* HAVE_STRTOK_R */
1721
/* Check for desired table types to return */
1723
while (table_type[i])
1725
char *typestr = table_type[i];
1727
while (isspace(*typestr))
1729
if (*typestr == '\'')
1731
if (strnicmp(typestr, CSTR_SYS_TABLE, strlen(CSTR_SYS_TABLE)) == 0)
1732
show_system_tables = TRUE;
1733
else if (strnicmp(typestr, CSTR_TABLE, strlen(CSTR_TABLE)) == 0)
1734
show_regular_tables = TRUE;
1735
else if (strnicmp(typestr, CSTR_VIEW, strlen(CSTR_VIEW)) == 0)
1742
* If not interested in SYSTEM TABLES then filter them out to save
1743
* some time on the query. If treating system tables as regular
1744
* tables, then dont filter either.
1746
if ((list_schemas || !list_some) && !atoi(ci->show_system_tables) && !show_system_tables)
1748
if (conn->schema_support)
1749
strcat(tables_query, " and nspname not in ('pg_catalog', 'information_schema', 'pg_toast', 'pg_temp_1')");
1750
else if (!list_schemas)
1752
strcat(tables_query, " and relname !~ '^" POSTGRES_SYS_PREFIX);
1754
/* Also filter out user-defined system table types */
1755
for (i = 0; prefix[i]; i++)
1757
strcat(tables_query, "|^");
1758
strcat(tables_query, prefix[i]);
1760
strcat(tables_query, "'");
1766
if (CC_accessible_only(conn))
1767
strcat(tables_query, " and has_table_privilege(c.oid, 'select')");
1770
strcat(tables_query, " order by nspname");
1773
else if (conn->schema_support)
1774
strcat(tables_query, " and n.oid = relnamespace order by nspname, relname");
1778
if (PG_VERSION_LT(conn, 7.1))
1779
/* filter out large objects in older versions */
1780
strcat(tables_query, " and relname !~ '^xinv[0-9]+'");
1781
strcat(tables_query, " and usesysid = relowner order by relname");
1784
result = PGAPI_ExecDirect(htbl_stmt, tables_query, SQL_NTS, 0);
1785
if (!SQL_SUCCEEDED(result))
1787
SC_full_error_copy(stmt, htbl_stmt, FALSE);
1792
if (conn->schema_support &&
1793
(res = SC_get_Result(tbl_stmt)) &&
1794
0 == QR_get_num_total_tuples(res))
1796
if (allow_public_schema(conn, szSchemaName, cbSchemaName))
1798
szSchemaName = pubstr;
1799
cbSchemaName = SQL_NTS;
1800
goto retry_public_schema;
1803
#ifdef UNICODE_SUPPORT
1804
if (CC_is_in_unicode_driver(conn))
1805
internal_asis_type = INTERNAL_ASIS_TYPE;
1806
#endif /* UNICODE_SUPPORT */
1807
result = PGAPI_BindCol(htbl_stmt, 1, internal_asis_type,
1808
table_name, MAX_INFO_STRING, &cbRelname);
1809
if (!SQL_SUCCEEDED(result))
1811
SC_error_copy(stmt, tbl_stmt, TRUE);
1815
result = PGAPI_BindCol(htbl_stmt, 2, internal_asis_type,
1816
table_owner, MAX_INFO_STRING, &cbSchName);
1817
if (!SQL_SUCCEEDED(result))
1819
SC_error_copy(stmt, tbl_stmt, TRUE);
1822
result = PGAPI_BindCol(htbl_stmt, 3, internal_asis_type,
1823
relkind_or_hasrules, MAX_INFO_STRING, &cbRelkind);
1824
if (!SQL_SUCCEEDED(result))
1826
SC_error_copy(stmt, tbl_stmt, TRUE);
1830
if (res = QR_Constructor(), !res)
1832
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate memory for PGAPI_Tables result.", func);
1835
SC_set_Result(stmt, res);
1837
/* the binding structure for a statement is not set up until */
1840
* a statement is actually executed, so we'll have to do this
1843
result_cols = NUM_OF_TABLES_FIELDS;
1844
extend_column_bindings(SC_get_ARDF(stmt), result_cols);
1846
stmt->catalog_result = TRUE;
1847
/* set the field names */
1848
QR_set_num_fields(res, result_cols);
1849
QR_set_field_info_v(res, TABLES_CATALOG_NAME, "TABLE_QUALIFIER", PG_TYPE_VARCHAR, MAX_INFO_STRING);
1850
QR_set_field_info_v(res, TABLES_SCHEMA_NAME, "TABLE_OWNER", PG_TYPE_VARCHAR, MAX_INFO_STRING);
1851
QR_set_field_info_v(res, TABLES_TABLE_NAME, "TABLE_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
1852
QR_set_field_info_v(res, TABLES_TABLE_TYPE, "TABLE_TYPE", PG_TYPE_VARCHAR, MAX_INFO_STRING);
1853
QR_set_field_info_v(res, TABLES_REMARKS, "REMARKS", PG_TYPE_VARCHAR, INFO_VARCHAR_SIZE);
1855
/* add the tuples */
1856
table_name[0] = '\0';
1857
table_owner[0] = '\0';
1858
result = PGAPI_Fetch(htbl_stmt);
1859
while (SQL_SUCCEEDED(result))
1862
* Determine if this table name is a system table. If treating
1863
* system tables as regular tables, then no need to do this test.
1866
if (!atoi(ci->show_system_tables))
1868
if (conn->schema_support)
1870
if (stricmp(table_owner, "pg_catalog") == 0 ||
1871
stricmp(table_owner, "pg_toast") == 0 ||
1872
strnicmp(table_owner, "pg_temp_", 8) == 0 ||
1873
stricmp(table_owner, "information_schema") == 0)
1876
else if (strncmp(table_name, POSTGRES_SYS_PREFIX, strlen(POSTGRES_SYS_PREFIX)) == 0)
1881
/* Check extra system table prefixes */
1885
mylog("table_name='%s', prefix[%d]='%s'\n", table_name, i, prefix[i]);
1886
if (strncmp(table_name, prefix[i], strlen(prefix[i])) == 0)
1896
/* Determine if the table name is a view */
1897
if (PG_VERSION_GE(conn, 7.1))
1898
/* view is represented by its relkind since 7.1 */
1899
view = (relkind_or_hasrules[0] == 'v');
1901
view = (relkind_or_hasrules[0] == '1');
1903
/* It must be a regular table */
1904
regular_table = (!systable && !view);
1907
/* Include the row in the result set if meets all criteria */
1910
* NOTE: Unsupported table types (i.e., LOCAL TEMPORARY, ALIAS,
1911
* etc) will return nothing
1913
if ((systable && show_system_tables) ||
1914
(view && show_views) ||
1915
(regular_table && show_regular_tables))
1917
tuple = QR_AddNew(res);
1919
if (list_cat || !list_some)
1920
set_tuplefield_string(&tuple[TABLES_CATALOG_NAME], CurrCat(conn));
1922
set_tuplefield_null(&tuple[TABLES_CATALOG_NAME]);
1925
* I have to hide the table owner from Access, otherwise it
1926
* insists on referring to the table as 'owner.table'. (this
1927
* is valid according to the ODBC SQL grammar, but Postgres
1928
* won't support it.)
1930
* set_tuplefield_string(&tuple[TABLES_SCHEMA_NAME], table_owner);
1933
mylog("%s: table_name = '%s'\n", func, table_name);
1935
if (list_schemas || (conn->schema_support && !list_some))
1936
set_tuplefield_string(&tuple[TABLES_SCHEMA_NAME], GET_SCHEMA_NAME(table_owner));
1938
set_tuplefield_null(&tuple[TABLES_SCHEMA_NAME]);
1940
set_tuplefield_null(&tuple[TABLES_TABLE_NAME]);
1942
set_tuplefield_string(&tuple[TABLES_TABLE_NAME], table_name);
1943
if (list_table_types || !list_some)
1944
set_tuplefield_string(&tuple[TABLES_TABLE_TYPE], systable ? "SYSTEM TABLE" : (view ? "VIEW" : "TABLE"));
1946
set_tuplefield_null(&tuple[TABLES_TABLE_TYPE]);
1947
set_tuplefield_string(&tuple[TABLES_REMARKS], NULL_STRING);
1948
/*** set_tuplefield_string(&tuple[TABLES_REMARKS], "TABLE"); ***/
1950
result = PGAPI_Fetch(htbl_stmt);
1952
if (result != SQL_NO_DATA_FOUND)
1954
SC_full_error_copy(stmt, htbl_stmt, FALSE);
1962
* also, things need to think that this statement is finished so the
1963
* results can be retrieved.
1965
stmt->status = STMT_FINISHED;
1970
free(escSchemaName);
1975
/* set up the current tuple pointer for SQLFetch */
1976
stmt->currTuple = -1;
1977
SC_set_rowset_start(stmt, -1, FALSE);
1978
SC_set_current_col(stmt, -1);
1981
PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
1984
ret = DiscardStatementSvp(stmt, ret, FALSE);
1985
mylog("%s: EXIT, stmt=%p, ret=%d\n", func, stmt, ret);
1992
const SQLCHAR FAR * szTableQualifier, /* OA X*/
1993
SQLSMALLINT cbTableQualifier,
1994
const SQLCHAR FAR * szTableOwner, /* PV E*/
1995
SQLSMALLINT cbTableOwner,
1996
const SQLCHAR FAR * szTableName, /* PV E*/
1997
SQLSMALLINT cbTableName,
1998
const SQLCHAR FAR * szColumnName, /* PV E*/
1999
SQLSMALLINT cbColumnName,
2004
CSTR func = "PGAPI_Columns";
2005
StatementClass *stmt = (StatementClass *) hstmt;
2008
HSTMT hcol_stmt = NULL;
2009
StatementClass *col_stmt;
2010
char columns_query[INFO_INQUIRY_LEN];
2012
char table_owner[MAX_INFO_STRING],
2013
table_name[MAX_INFO_STRING],
2014
field_name[MAX_INFO_STRING],
2015
field_type_name[MAX_INFO_STRING];
2016
Int2 field_number, sqltype, concise_type,
2021
OID field_type, the_type, greloid, basetype;
2023
Int2 decimal_digits;
2024
Int4 field_length, column_size;
2025
char useStaticPrecision, useStaticScale;
2026
#endif /* USE_OLD_IMPL */
2027
char not_null[MAX_INFO_STRING],
2028
relhasrules[MAX_INFO_STRING], relkind[8];
2029
char *escSchemaName = NULL, *escTableName = NULL, *escColumnName = NULL;
2030
BOOL search_pattern = TRUE, search_by_ids, relisaview;
2032
ConnectionClass *conn;
2033
SQLSMALLINT internal_asis_type = SQL_C_CHAR, cbSchemaName;
2034
const char *like_or_eq = likeop, *op_string;
2035
const char *szSchemaName;
2036
BOOL setIdentity = FALSE;
2038
mylog("%s: entering...stmt=%p scnm=%p len=%d\n", func, stmt, szTableOwner, cbTableOwner);
2040
if (result = SC_initialize_and_recycle(stmt), SQL_SUCCESS != result)
2043
conn = SC_get_conn(stmt);
2044
ci = &(conn->connInfo);
2045
#ifdef UNICODE_SUPPORT
2046
if (CC_is_in_unicode_driver(conn))
2047
internal_asis_type = INTERNAL_ASIS_TYPE;
2048
#endif /* UNICODE_SUPPORT */
2050
#define return DONT_CALL_RETURN_FROM_HERE???
2051
search_by_ids = ((flag & PODBC_SEARCH_BY_IDS) != 0);
2054
szSchemaName = NULL;
2055
cbSchemaName = SQL_NULL_DATA;
2059
szSchemaName = szTableOwner;
2060
cbSchemaName = cbTableOwner;
2064
* TableName or ColumnName is ordinarily an pattern value,
2066
search_pattern = ((flag & PODBC_NOT_SEARCH_PATTERN) == 0);
2069
like_or_eq = likeop;
2070
escTableName = adjustLikePattern(szTableName, cbTableName, SEARCH_PATTERN_ESCAPE, NULL, conn);
2071
escColumnName = adjustLikePattern(szColumnName, cbColumnName, SEARCH_PATTERN_ESCAPE, NULL, conn);
2076
escTableName = simpleCatalogEscape(szTableName, cbTableName, NULL, conn);
2077
escColumnName = simpleCatalogEscape(szColumnName, cbColumnName, NULL, conn);
2080
retry_public_schema:
2084
free(escSchemaName);
2086
escSchemaName = adjustLikePattern(szSchemaName, cbSchemaName, SEARCH_PATTERN_ESCAPE, NULL, conn);
2088
escSchemaName = simpleCatalogEscape(szSchemaName, cbSchemaName, NULL, conn);
2091
* Create the query to find out the columns (Note: pre 6.3 did not
2092
* have the atttypmod field)
2094
op_string = gen_opestr(like_or_eq, conn);
2095
if (conn->schema_support)
2097
snprintf(columns_query, sizeof(columns_query),
2098
"select n.nspname, c.relname, a.attname, a.atttypid"
2099
", t.typname, a.attnum, a.attlen, a.atttypmod, a.attnotnull"
2100
", c.relhasrules, c.relkind, c.oid, %s, %s, %s"
2101
" from (((pg_catalog.pg_class c"
2102
" inner join pg_catalog.pg_namespace n on n.oid = c.relnamespace",
2103
PG_VERSION_GE(conn, 7.4) ?
2104
"pg_get_expr(d.adbin, d.adrelid)" : "d.adsrc",
2105
PG_VERSION_GE(conn, 7.4) ?
2106
"case t.typtype when 'd' then t.typbasetype else 0 end, t.typtypmod"
2108
PG_VERSION_GE(conn, 7.2) ? "c.relhasoids" : "1"
2111
snprintf_add(columns_query, sizeof(columns_query), " and c.oid = %u", reloid);
2115
snprintf_add(columns_query, sizeof(columns_query), " and c.relname %s'%s'", op_string, escTableName);
2116
schema_strcat1(columns_query, " and n.nspname %s'%.*s'", op_string, escSchemaName, SQL_NTS, szTableName, cbTableName, conn);
2118
strcat(columns_query, ") inner join pg_catalog.pg_attribute a"
2119
" on (not a.attisdropped)");
2120
if (0 == attnum && (NULL == escColumnName || like_or_eq != eqop))
2121
strcat(columns_query, " and a.attnum > 0");
2125
snprintf_add(columns_query, sizeof(columns_query), " and a.attnum = %d", attnum);
2127
else if (escColumnName)
2128
snprintf_add(columns_query, sizeof(columns_query), " and a.attname %s'%s'", op_string, escColumnName);
2129
strcat(columns_query,
2130
" and a.attrelid = c.oid) inner join pg_catalog.pg_type t"
2131
" on t.oid = a.atttypid) left outer join pg_attrdef d"
2132
" on a.atthasdef and d.adrelid = a.attrelid and d.adnum = a.attnum");
2133
strcat(columns_query, " order by n.nspname, c.relname, attnum");
2137
snprintf(columns_query, sizeof(columns_query),
2138
"select u.usename, c.relname, a.attname, a.atttypid"
2139
", t.typname, a.attnum, a.attlen, %s, a.attnotnull"
2140
", c.relhasrules, c.relkind, c.oid, NULL, 0, -1 from"
2141
" pg_user u, pg_class c, pg_attribute a, pg_type t where"
2142
" u.usesysid = c.relowner and c.oid= a.attrelid"
2143
" and a.atttypid = t.oid and (a.attnum > 0)",
2144
PG_VERSION_LE(conn, 6.2) ? "a.attlen" : "a.atttypmod");
2146
snprintf_add(columns_query, sizeof(columns_query), " and c.relname %s'%s'", op_string, escTableName);
2147
my_strcat1(columns_query, " and u.usename %s'%.*s'", op_string, escSchemaName, SQL_NTS);
2149
snprintf_add(columns_query, sizeof(columns_query), " and a.attname %s'%s'", op_string, escColumnName);
2150
strcat(columns_query, " order by c.relname, attnum");
2153
result = PGAPI_AllocStmt(conn, &hcol_stmt, 0);
2154
if (!SQL_SUCCEEDED(result))
2156
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate statement for PGAPI_Columns result.", func);
2160
col_stmt = (StatementClass *) hcol_stmt;
2162
mylog("%s: hcol_stmt = %p, col_stmt = %p\n", func, hcol_stmt, col_stmt);
2164
col_stmt->internal = TRUE;
2165
result = PGAPI_ExecDirect(hcol_stmt, columns_query, SQL_NTS, 0);
2166
if (!SQL_SUCCEEDED(result))
2168
SC_full_error_copy(stmt, col_stmt, FALSE);
2173
if (conn->schema_support &&
2174
(flag & PODBC_SEARCH_PUBLIC_SCHEMA) != 0 &&
2175
(res = SC_get_Result(col_stmt)) &&
2176
0 == QR_get_num_total_tuples(res))
2178
if (!search_by_ids &&
2179
allow_public_schema(conn, szSchemaName, cbSchemaName))
2181
PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
2183
szSchemaName = pubstr;
2184
cbSchemaName = SQL_NTS;
2185
goto retry_public_schema;
2189
result = PGAPI_BindCol(hcol_stmt, 1, internal_asis_type,
2190
table_owner, MAX_INFO_STRING, NULL);
2191
if (!SQL_SUCCEEDED(result))
2193
SC_error_copy(stmt, col_stmt, TRUE);
2197
result = PGAPI_BindCol(hcol_stmt, 2, internal_asis_type,
2198
table_name, MAX_INFO_STRING, NULL);
2199
if (!SQL_SUCCEEDED(result))
2201
SC_error_copy(stmt, col_stmt, TRUE);
2205
result = PGAPI_BindCol(hcol_stmt, 3, internal_asis_type,
2206
field_name, MAX_INFO_STRING, NULL);
2207
if (!SQL_SUCCEEDED(result))
2209
SC_error_copy(stmt, col_stmt, TRUE);
2213
result = PGAPI_BindCol(hcol_stmt, 4, SQL_C_ULONG,
2214
&field_type, 4, NULL);
2215
if (!SQL_SUCCEEDED(result))
2217
SC_error_copy(stmt, col_stmt, TRUE);
2221
result = PGAPI_BindCol(hcol_stmt, 5, internal_asis_type,
2222
field_type_name, MAX_INFO_STRING, NULL);
2223
if (!SQL_SUCCEEDED(result))
2225
SC_error_copy(stmt, col_stmt, TRUE);
2229
result = PGAPI_BindCol(hcol_stmt, 6, SQL_C_SHORT,
2230
&field_number, MAX_INFO_STRING, NULL);
2231
if (!SQL_SUCCEEDED(result))
2233
SC_error_copy(stmt, col_stmt, TRUE);
2238
result = PGAPI_BindCol(hcol_stmt, 7, SQL_C_LONG,
2239
&field_length, MAX_INFO_STRING, NULL);
2240
if (!SQL_SUCCEEDED(result))
2242
SC_error_copy(stmt, col_stmt, TRUE);
2245
#endif /* NOT_USED */
2247
result = PGAPI_BindCol(hcol_stmt, 8, SQL_C_LONG,
2248
&mod_length, MAX_INFO_STRING, NULL);
2249
if (!SQL_SUCCEEDED(result))
2251
SC_error_copy(stmt, col_stmt, TRUE);
2255
result = PGAPI_BindCol(hcol_stmt, 9, internal_asis_type,
2256
not_null, MAX_INFO_STRING, NULL);
2257
if (!SQL_SUCCEEDED(result))
2259
SC_error_copy(stmt, col_stmt, TRUE);
2263
result = PGAPI_BindCol(hcol_stmt, 10, internal_asis_type,
2264
relhasrules, MAX_INFO_STRING, NULL);
2265
if (!SQL_SUCCEEDED(result))
2267
SC_error_copy(stmt, col_stmt, TRUE);
2271
result = PGAPI_BindCol(hcol_stmt, 11, internal_asis_type,
2272
relkind, sizeof(relkind), NULL);
2273
if (!SQL_SUCCEEDED(result))
2275
SC_error_copy(stmt, col_stmt, TRUE);
2279
result = PGAPI_BindCol(hcol_stmt, 12, SQL_C_LONG,
2280
&greloid, sizeof(greloid), NULL);
2281
if (!SQL_SUCCEEDED(result))
2283
SC_error_copy(stmt, col_stmt, TRUE);
2287
result = PGAPI_BindCol(hcol_stmt, 14, SQL_C_ULONG,
2288
&basetype, sizeof(basetype), NULL);
2289
if (!SQL_SUCCEEDED(result))
2291
SC_error_copy(stmt, col_stmt, TRUE);
2295
result = PGAPI_BindCol(hcol_stmt, 15, SQL_C_LONG,
2296
&typmod, sizeof(typmod), NULL);
2297
if (!SQL_SUCCEEDED(result))
2299
SC_error_copy(stmt, col_stmt, TRUE);
2303
result = PGAPI_BindCol(hcol_stmt, 16, SQL_C_LONG,
2304
&relhasoids, sizeof(relhasoids), NULL);
2305
if (!SQL_SUCCEEDED(result))
2307
SC_error_copy(stmt, col_stmt, TRUE);
2311
if (res = QR_Constructor(), !res)
2313
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate memory for PGAPI_Columns result.", func);
2316
SC_set_Result(stmt, res);
2318
/* the binding structure for a statement is not set up until */
2321
* a statement is actually executed, so we'll have to do this
2324
result_cols = NUM_OF_COLUMNS_FIELDS;
2325
extend_column_bindings(SC_get_ARDF(stmt), result_cols);
2328
* Setting catalog_result here affects the behavior of
2329
* pgtype_xxx() functions. So set it later.
2330
* stmt->catalog_result = TRUE;
2332
/* set the field names */
2333
QR_set_num_fields(res, result_cols);
2334
QR_set_field_info_v(res, COLUMNS_CATALOG_NAME, "TABLE_QUALIFIER", PG_TYPE_VARCHAR, MAX_INFO_STRING);
2335
QR_set_field_info_v(res, COLUMNS_SCHEMA_NAME, "TABLE_OWNER", PG_TYPE_VARCHAR, MAX_INFO_STRING);
2336
QR_set_field_info_v(res, COLUMNS_TABLE_NAME, "TABLE_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
2337
QR_set_field_info_v(res, COLUMNS_COLUMN_NAME, "COLUMN_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
2338
QR_set_field_info_v(res, COLUMNS_DATA_TYPE, "DATA_TYPE", PG_TYPE_INT2, 2);
2339
QR_set_field_info_v(res, COLUMNS_TYPE_NAME, "TYPE_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
2340
QR_set_field_info_v(res, COLUMNS_PRECISION, "PRECISION", PG_TYPE_INT4, 4); /* COLUMN_SIZE */
2341
QR_set_field_info_v(res, COLUMNS_LENGTH, "LENGTH", PG_TYPE_INT4, 4); /* BUFFER_LENGTH */
2342
QR_set_field_info_v(res, COLUMNS_SCALE, "SCALE", PG_TYPE_INT2, 2); /* DECIMAL_DIGITS ***/
2343
QR_set_field_info_v(res, COLUMNS_RADIX, "RADIX", PG_TYPE_INT2, 2);
2344
QR_set_field_info_v(res, COLUMNS_NULLABLE, "NULLABLE", PG_TYPE_INT2, 2);
2345
QR_set_field_info_v(res, COLUMNS_REMARKS, "REMARKS", PG_TYPE_VARCHAR, INFO_VARCHAR_SIZE);
2347
#if (ODBCVER >= 0x0300)
2348
QR_set_field_info_v(res, COLUMNS_COLUMN_DEF, "COLUMN_DEF", PG_TYPE_VARCHAR, INFO_VARCHAR_SIZE);
2349
QR_set_field_info_v(res, COLUMNS_SQL_DATA_TYPE, "SQL_DATA_TYPE", PG_TYPE_INT2, 2);
2350
QR_set_field_info_v(res, COLUMNS_SQL_DATETIME_SUB, "SQL_DATETIME_SUB", PG_TYPE_INT2, 2);
2351
QR_set_field_info_v(res, COLUMNS_CHAR_OCTET_LENGTH, "CHAR_OCTET_LENGTH", PG_TYPE_INT4, 4);
2352
QR_set_field_info_v(res, COLUMNS_ORDINAL_POSITION, "ORDINAL_POSITION", PG_TYPE_INT4, 4);
2353
QR_set_field_info_v(res, COLUMNS_IS_NULLABLE, "IS_NULLABLE", PG_TYPE_VARCHAR, INFO_VARCHAR_SIZE);
2354
#endif /* ODBCVER */
2355
/* User defined fields */
2356
QR_set_field_info_v(res, COLUMNS_DISPLAY_SIZE, "DISPLAY_SIZE", PG_TYPE_INT4, 4);
2357
QR_set_field_info_v(res, COLUMNS_FIELD_TYPE, "FIELD_TYPE", PG_TYPE_INT4, 4);
2358
QR_set_field_info_v(res, COLUMNS_AUTO_INCREMENT, "AUTO_INCREMENT", PG_TYPE_INT4, 4);
2359
QR_set_field_info_v(res, COLUMNS_PHYSICAL_NUMBER, "PHYSICAL NUMBER", PG_TYPE_INT2, 2);
2360
QR_set_field_info_v(res, COLUMNS_TABLE_OID, "TABLE OID", PG_TYPE_OID, 4);
2361
QR_set_field_info_v(res, COLUMNS_BASE_TYPEID, "BASE TYPEID", PG_TYPE_OID, 4);
2362
QR_set_field_info_v(res, COLUMNS_ATTTYPMOD, "TYPMOD", PG_TYPE_INT4, 4);
2365
result = PGAPI_Fetch(hcol_stmt);
2368
* Only show oid if option AND there are other columns AND it's not
2369
* being called by SQLStatistics . Always show OID if it's a system
2373
if (PG_VERSION_GE(conn, 7.1))
2374
relisaview = (relkind[0] == 'v');
2376
relisaview = (relhasrules[0] == '1');
2377
if (result != SQL_ERROR && !stmt->internal)
2381
(atoi(ci->show_oid_column) ||
2382
strncmp(table_name, POSTGRES_SYS_PREFIX, strlen(POSTGRES_SYS_PREFIX)) == 0) &&
2383
(NULL == escColumnName ||
2384
0 == strcmp(escColumnName, OID_NAME)))
2386
/* For OID fields */
2387
the_type = PG_TYPE_OID;
2388
tuple = QR_AddNew(res);
2389
set_tuplefield_string(&tuple[COLUMNS_CATALOG_NAME], CurrCat(conn));
2390
/* see note in SQLTables() */
2391
if (conn->schema_support)
2392
set_tuplefield_string(&tuple[COLUMNS_SCHEMA_NAME], GET_SCHEMA_NAME(table_owner));
2394
set_tuplefield_string(&tuple[COLUMNS_SCHEMA_NAME], NULL_STRING);
2395
set_tuplefield_string(&tuple[COLUMNS_TABLE_NAME], table_name);
2396
set_tuplefield_string(&tuple[COLUMNS_COLUMN_NAME], OID_NAME);
2397
sqltype = pgtype_to_concise_type(stmt, the_type, PG_STATIC);
2398
set_tuplefield_int2(&tuple[COLUMNS_DATA_TYPE], sqltype);
2399
if (CC_fake_mss(conn))
2401
set_tuplefield_string(&tuple[COLUMNS_TYPE_NAME], "OID identity");
2405
set_tuplefield_string(&tuple[COLUMNS_TYPE_NAME], "OID");
2407
set_tuplefield_int4(&tuple[COLUMNS_PRECISION], pgtype_column_size(stmt, the_type, PG_STATIC, UNKNOWNS_AS_DEFAULT));
2408
set_tuplefield_int4(&tuple[COLUMNS_LENGTH], pgtype_buffer_length(stmt, the_type, PG_STATIC, UNKNOWNS_AS_DEFAULT));
2409
set_nullfield_int2(&tuple[COLUMNS_SCALE], pgtype_decimal_digits(stmt, the_type, PG_STATIC));
2410
set_nullfield_int2(&tuple[COLUMNS_RADIX], pgtype_radix(conn, the_type));
2411
set_tuplefield_int2(&tuple[COLUMNS_NULLABLE], SQL_NO_NULLS);
2412
set_tuplefield_string(&tuple[COLUMNS_REMARKS], NULL_STRING);
2414
#if (ODBCVER >= 0x0300)
2415
set_tuplefield_null(&tuple[COLUMNS_COLUMN_DEF]);
2416
set_tuplefield_int2(&tuple[COLUMNS_SQL_DATA_TYPE], sqltype);
2417
set_tuplefield_null(&tuple[COLUMNS_SQL_DATETIME_SUB]);
2418
set_tuplefield_null(&tuple[COLUMNS_CHAR_OCTET_LENGTH]);
2419
set_tuplefield_int4(&tuple[COLUMNS_ORDINAL_POSITION], ordinal);
2420
set_tuplefield_string(&tuple[COLUMNS_IS_NULLABLE], "No");
2421
#endif /* ODBCVER */
2422
set_tuplefield_int4(&tuple[COLUMNS_DISPLAY_SIZE], pgtype_display_size(stmt, the_type, PG_STATIC, UNKNOWNS_AS_DEFAULT));
2423
set_tuplefield_int4(&tuple[COLUMNS_FIELD_TYPE], the_type);
2424
set_tuplefield_int4(&tuple[COLUMNS_AUTO_INCREMENT], TRUE);
2425
set_tuplefield_int2(&tuple[COLUMNS_PHYSICAL_NUMBER], OID_ATTNUM);
2426
set_tuplefield_int4(&tuple[COLUMNS_TABLE_OID], greloid);
2427
set_tuplefield_int4(&tuple[COLUMNS_BASE_TYPEID], 0);
2428
set_tuplefield_int4(&tuple[COLUMNS_ATTTYPMOD], -1);
2433
while (SQL_SUCCEEDED(result))
2440
PGAPI_SetPos(hcol_stmt, 1, SQL_POSITION, 0);
2441
PGAPI_GetData(hcol_stmt, 13, internal_asis_type, NULL, 0, &len_needed);
2444
mylog("len_needed=%d\n", len_needed);
2445
attdef = malloc(len_needed + 1);
2446
PGAPI_GetData(hcol_stmt, 13, internal_asis_type, attdef, len_needed + 1, &len_needed);
2447
mylog(" and the data=%s\n", attdef);
2449
tuple = QR_AddNew(res);
2451
sqltype = SQL_TYPE_NULL; /* unspecified */
2452
set_tuplefield_string(&tuple[COLUMNS_CATALOG_NAME], CurrCat(conn));
2453
/* see note in SQLTables() */
2454
if (conn->schema_support)
2455
set_tuplefield_string(&tuple[COLUMNS_SCHEMA_NAME], GET_SCHEMA_NAME(table_owner));
2457
set_tuplefield_string(&tuple[COLUMNS_SCHEMA_NAME], NULL_STRING);
2458
set_tuplefield_string(&tuple[COLUMNS_TABLE_NAME], table_name);
2459
set_tuplefield_string(&tuple[COLUMNS_COLUMN_NAME], field_name);
2460
auto_unique = SQL_FALSE;
2461
if (field_type = pg_true_type(conn, field_type, basetype), field_type == basetype)
2462
mod_length = typmod;
2466
if (0 != atoi(ci->fake_oid_index))
2468
auto_unique = SQL_TRUE;
2469
set_tuplefield_string(&tuple[COLUMNS_TYPE_NAME], "identity");
2474
if (attdef && strnicmp(attdef, "nextval(", 8) == 0 &&
2477
auto_unique = SQL_TRUE;
2483
snprintf(tmp, sizeof(tmp), "%s identity", field_type_name);
2484
set_tuplefield_string(&tuple[COLUMNS_TYPE_NAME], tmp);
2489
set_tuplefield_string(&tuple[COLUMNS_TYPE_NAME], field_type_name);
2494
* Some Notes about Postgres Data Types:
2496
* VARCHAR - the length is stored in the pg_attribute.atttypmod field
2497
* BPCHAR - the length is also stored as varchar is
2499
* NUMERIC - the decimal_digits is stored in atttypmod as follows:
2501
* column_size =((atttypmod - VARHDRSZ) >> 16) & 0xffff
2502
* decimal_digits = (atttypmod - VARHDRSZ) & 0xffff
2506
qlog("%s: table='%s',field_name='%s',type=%d,name='%s'\n",
2507
func, table_name, field_name, field_type, field_type_name);
2510
useStaticPrecision = TRUE;
2511
useStaticScale = TRUE;
2513
if (field_type == PG_TYPE_NUMERIC)
2515
if (mod_length >= 4)
2516
mod_length -= 4; /* the length is in atttypmod - 4 */
2518
if (mod_length >= 0)
2520
useStaticPrecision = FALSE;
2521
useStaticScale = FALSE;
2523
column_size = (mod_length >> 16) & 0xffff;
2524
decimal_digits = mod_length & 0xffff;
2526
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);
2528
set_tuplefield_int4(&tuple[COLUMNS_PRECISION], column_size);
2529
set_tuplefield_int4(&tuple[COLUMNS_LENGTH], column_size + 2); /* sign+dec.point */
2530
set_nullfield_int2(&tuple[COLUMNS_SCALE], decimal_digits);
2531
#if (ODBCVER >= 0x0300)
2532
set_tuplefield_null(&tuple[COLUMNS_CHAR_OCTET_LENGTH]);
2533
#endif /* ODBCVER */
2534
set_tuplefield_int4(&tuple[COLUMNS_DISPLAY_SIZE], column_size + 2); /* sign+dec.point */
2537
else if ((field_type == PG_TYPE_DATETIME) ||
2538
(field_type == PG_TYPE_TIMESTAMP_NO_TMZONE))
2540
if (PG_VERSION_GE(conn, 7.2))
2542
useStaticScale = FALSE;
2544
set_nullfield_int2(&tuple[COLUMNS_SCALE], (Int2) mod_length);
2548
if ((field_type == PG_TYPE_VARCHAR) ||
2549
(field_type == PG_TYPE_BPCHAR))
2551
useStaticPrecision = FALSE;
2553
if (mod_length >= 4)
2554
mod_length -= 4; /* the length is in atttypmod - 4 */
2556
/* if (mod_length > ci->drivers.max_varchar_size || mod_length <= 0) */
2557
if (mod_length <= 0)
2558
mod_length = ci->drivers.max_varchar_size;
2559
#ifdef __MS_REPORTS_ANSI_CHAR__
2560
if (mod_length > ci->drivers.max_varchar_size)
2561
sqltype = SQL_LONGVARCHAR;
2563
sqltype = (field_type == PG_TYPE_BPCHAR) ? SQL_CHAR : SQL_VARCHAR;
2565
if (mod_length > ci->drivers.max_varchar_size)
2566
sqltype = (ALLOW_WCHAR(conn) ? SQL_WLONGVARCHAR : SQL_LONGVARCHAR);
2568
sqltype = (field_type == PG_TYPE_BPCHAR) ? (ALLOW_WCHAR(conn) ? SQL_WCHAR : SQL_CHAR) : (ALLOW_WCHAR(conn) ? SQL_WVARCHAR : SQL_VARCHAR);
2569
#endif /* __MS_LOVES_REPORTS_CHAR__ */
2571
mylog("%s: field type is VARCHAR,BPCHAR: field_type = %d, mod_length = %d\n", func, field_type, mod_length);
2573
set_tuplefield_int4(&tuple[COLUMNS_PRECISION], mod_length);
2574
field_length = mod_length;
2575
#ifdef UNICODE_SUPPORT
2576
if (0 < field_length && ALLOW_WCHAR(conn))
2577
field_length *= WCLEN;
2578
#endif /* UNICODE_SUPPORT */
2579
set_tuplefield_int4(&tuple[COLUMNS_LENGTH], field_length);
2580
#if (ODBCVER >= 0x0300)
2581
set_tuplefield_int4(&tuple[COLUMNS_CHAR_OCTET_LENGTH], pgtype_transfer_octet_length(conn, field_type, mod_length));
2582
#endif /* ODBCVER */
2583
set_tuplefield_int4(&tuple[COLUMNS_DISPLAY_SIZE], mod_length);
2586
if (useStaticPrecision)
2588
mylog("%s: field type is OTHER: field_type = %d, pgtype_length = %d\n", func, field_type, pgtype_buffer_length(stmt, field_type, PG_STATIC, UNKNOWNS_AS_DEFAULT));
2590
set_tuplefield_int4(&tuple[COLUMNS_PRECISION], pgtype_column_size(stmt, field_type, PG_STATIC, UNKNOWNS_AS_DEFAULT));
2591
set_tuplefield_int4(&tuple[COLUMNS_LENGTH], pgtype_buffer_length(stmt, field_type, PG_STATIC, UNKNOWNS_AS_DEFAULT));
2592
#if (ODBCVER >= 0x0300)
2593
set_tuplefield_null(&tuple[COLUMNS_CHAR_OCTET_LENGTH]);
2594
#endif /* ODBCVER */
2595
set_tuplefield_int4(&tuple[COLUMNS_DISPLAY_SIZE], pgtype_display_size(stmt, field_type, PG_STATIC, UNKNOWNS_AS_DEFAULT));
2599
set_nullfield_int2(&tuple[COLUMNS_SCALE], pgtype_decimal_digits(stmt, field_type, PG_STATIC));
2602
if (SQL_TYPE_NULL == sqltype)
2604
sqltype = pgtype_attr_to_concise_type(conn, field_type, mod_length, -1);
2605
concise_type = pgtype_attr_to_sqldesctype(conn, field_type, mod_length);
2608
concise_type = sqltype;
2609
#else /* USE_OLD_IMPL */
2610
/* Subtract the header length */
2613
case PG_TYPE_DATETIME:
2614
case PG_TYPE_TIMESTAMP_NO_TMZONE:
2616
case PG_TYPE_TIME_WITH_TMZONE:
2620
if (mod_length >= 4)
2623
set_tuplefield_int4(&tuple[COLUMNS_PRECISION], pgtype_attr_column_size(conn, field_type, mod_length, PG_UNSPECIFIED, UNKNOWNS_AS_DEFAULT));
2624
set_tuplefield_int4(&tuple[COLUMNS_LENGTH], pgtype_attr_buffer_length(conn, field_type, mod_length, PG_UNSPECIFIED, UNKNOWNS_AS_DEFAULT));
2625
set_tuplefield_int4(&tuple[COLUMNS_DISPLAY_SIZE], pgtype_attr_display_size(conn, field_type, mod_length, PG_UNSPECIFIED, UNKNOWNS_AS_DEFAULT));
2626
set_nullfield_int2(&tuple[COLUMNS_SCALE], pgtype_attr_decimal_digits(conn, field_type, mod_length, PG_UNSPECIFIED, UNKNOWNS_AS_DEFAULT));
2628
sqltype = pgtype_attr_to_concise_type(conn, field_type, mod_length, PG_UNSPECIFIED);
2629
concise_type = pgtype_attr_to_sqldesctype(conn, field_type, mod_length);
2630
#endif /* USE_OLD_IMPL */
2632
set_tuplefield_int2(&tuple[COLUMNS_DATA_TYPE], sqltype);
2634
set_nullfield_int2(&tuple[COLUMNS_RADIX], pgtype_radix(conn, field_type));
2635
set_tuplefield_int2(&tuple[COLUMNS_NULLABLE], (Int2) (not_null[0] != '0' ? SQL_NO_NULLS : pgtype_nullable(conn, field_type)));
2636
set_tuplefield_string(&tuple[COLUMNS_REMARKS], NULL_STRING);
2637
#if (ODBCVER >= 0x0300)
2638
if (attdef && strlen(attdef) > INFO_VARCHAR_SIZE)
2639
set_tuplefield_string(&tuple[COLUMNS_COLUMN_DEF], "TRUNCATE");
2641
set_tuplefield_string(&tuple[COLUMNS_COLUMN_DEF], attdef);
2642
set_tuplefield_int2(&tuple[COLUMNS_SQL_DATA_TYPE], concise_type);
2643
set_nullfield_int2(&tuple[COLUMNS_SQL_DATETIME_SUB], pgtype_attr_to_datetime_sub(conn, field_type, mod_length));
2644
set_tuplefield_int4(&tuple[COLUMNS_CHAR_OCTET_LENGTH], pgtype_attr_transfer_octet_length(conn, field_type, mod_length, UNKNOWNS_AS_DEFAULT));
2645
set_tuplefield_int4(&tuple[COLUMNS_ORDINAL_POSITION], ordinal);
2646
set_tuplefield_null(&tuple[COLUMNS_IS_NULLABLE]);
2647
#endif /* ODBCVER */
2648
set_tuplefield_int4(&tuple[COLUMNS_FIELD_TYPE], field_type);
2649
set_tuplefield_int4(&tuple[COLUMNS_AUTO_INCREMENT], auto_unique);
2650
set_tuplefield_int2(&tuple[COLUMNS_PHYSICAL_NUMBER], field_number);
2651
set_tuplefield_int4(&tuple[COLUMNS_TABLE_OID], greloid);
2652
set_tuplefield_int4(&tuple[COLUMNS_BASE_TYPEID], basetype);
2653
set_tuplefield_int4(&tuple[COLUMNS_ATTTYPMOD], mod_length);
2656
result = PGAPI_Fetch(hcol_stmt);
2660
if (result != SQL_NO_DATA_FOUND)
2662
SC_full_error_copy(stmt, col_stmt, FALSE);
2667
* Put the row version column at the end so it might not be mistaken
2670
if (!relisaview && !stmt->internal && atoi(ci->row_versioning))
2672
/* For Row Versioning fields */
2673
the_type = PG_TYPE_INT4;
2675
tuple = QR_AddNew(res);
2677
set_tuplefield_string(&tuple[COLUMNS_CATALOG_NAME], CurrCat(conn));
2678
if (conn->schema_support)
2679
set_tuplefield_string(&tuple[COLUMNS_SCHEMA_NAME], GET_SCHEMA_NAME(table_owner));
2681
set_tuplefield_string(&tuple[COLUMNS_SCHEMA_NAME], NULL_STRING);
2682
set_tuplefield_string(&tuple[COLUMNS_TABLE_NAME], table_name);
2683
set_tuplefield_string(&tuple[COLUMNS_COLUMN_NAME], "xmin");
2684
sqltype = pgtype_to_concise_type(stmt, the_type, PG_STATIC);
2685
set_tuplefield_int2(&tuple[COLUMNS_DATA_TYPE], sqltype);
2686
set_tuplefield_string(&tuple[COLUMNS_TYPE_NAME], pgtype_to_name(stmt, the_type, PG_UNSPECIFIED, FALSE));
2687
set_tuplefield_int4(&tuple[COLUMNS_PRECISION], pgtype_column_size(stmt, the_type, PG_STATIC, UNKNOWNS_AS_DEFAULT));
2688
set_tuplefield_int4(&tuple[COLUMNS_LENGTH], pgtype_buffer_length(stmt, the_type, PG_STATIC, UNKNOWNS_AS_DEFAULT));
2689
set_nullfield_int2(&tuple[COLUMNS_SCALE], pgtype_decimal_digits(stmt, the_type, PG_STATIC));
2690
set_nullfield_int2(&tuple[COLUMNS_RADIX], pgtype_radix(conn, the_type));
2691
set_tuplefield_int2(&tuple[COLUMNS_NULLABLE], SQL_NO_NULLS);
2692
set_tuplefield_string(&tuple[COLUMNS_REMARKS], NULL_STRING);
2693
#if (ODBCVER >= 0x0300)
2694
set_tuplefield_null(&tuple[COLUMNS_COLUMN_DEF]);
2695
set_tuplefield_int2(&tuple[COLUMNS_SQL_DATA_TYPE], sqltype);
2696
set_tuplefield_null(&tuple[COLUMNS_SQL_DATETIME_SUB]);
2697
set_tuplefield_null(&tuple[COLUMNS_CHAR_OCTET_LENGTH]);
2698
set_tuplefield_int4(&tuple[COLUMNS_ORDINAL_POSITION], ordinal);
2699
set_tuplefield_string(&tuple[COLUMNS_IS_NULLABLE], "No");
2700
#endif /* ODBCVER */
2701
set_tuplefield_int4(&tuple[COLUMNS_DISPLAY_SIZE], pgtype_display_size(stmt, the_type, PG_STATIC, UNKNOWNS_AS_DEFAULT));
2702
set_tuplefield_int4(&tuple[COLUMNS_FIELD_TYPE], the_type);
2703
set_tuplefield_int4(&tuple[COLUMNS_AUTO_INCREMENT], FALSE);
2704
set_tuplefield_int2(&tuple[COLUMNS_PHYSICAL_NUMBER], XMIN_ATTNUM);
2705
set_tuplefield_int4(&tuple[COLUMNS_TABLE_OID], greloid);
2706
set_tuplefield_int4(&tuple[COLUMNS_BASE_TYPEID], 0);
2707
set_tuplefield_int4(&tuple[COLUMNS_ATTTYPMOD], -1);
2710
result = SQL_SUCCESS;
2715
* also, things need to think that this statement is finished so the
2716
* results can be retrieved.
2718
stmt->status = STMT_FINISHED;
2719
stmt->catalog_result = TRUE;
2721
/* set up the current tuple pointer for SQLFetch */
2722
stmt->currTuple = -1;
2723
SC_set_rowset_start(stmt, -1, FALSE);
2724
SC_set_current_col(stmt, -1);
2727
free(escSchemaName);
2731
free(escColumnName);
2733
PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
2735
result = DiscardStatementSvp(stmt, result, FALSE);
2736
mylog("%s: EXIT, stmt=%p\n", func, stmt);
2742
PGAPI_SpecialColumns(
2744
SQLUSMALLINT fColType,
2745
const SQLCHAR FAR * szTableQualifier,
2746
SQLSMALLINT cbTableQualifier,
2747
const SQLCHAR FAR * szTableOwner, /* OA E*/
2748
SQLSMALLINT cbTableOwner,
2749
const SQLCHAR FAR * szTableName, /* OA(R) E*/
2750
SQLSMALLINT cbTableName,
2751
SQLUSMALLINT fScope,
2752
SQLUSMALLINT fNullable)
2754
CSTR func = "PGAPI_SpecialColumns";
2756
StatementClass *stmt = (StatementClass *) hstmt;
2757
ConnectionClass *conn;
2759
HSTMT hcol_stmt = NULL;
2760
StatementClass *col_stmt;
2761
char columns_query[INFO_INQUIRY_LEN];
2762
char *escSchemaName = NULL, *escTableName = NULL;
2763
RETCODE result = SQL_SUCCESS;
2764
char relhasrules[MAX_INFO_STRING], relkind[8], relhasoids[8];
2766
SQLSMALLINT internal_asis_type = SQL_C_CHAR, cbSchemaName;
2767
const char *szSchemaName, *eq_string;
2769
mylog("%s: entering...stmt=%p scnm=%p len=%d colType=%d scope=%d\n", func, stmt, szTableOwner, cbTableOwner, fColType, fScope);
2771
if (result = SC_initialize_and_recycle(stmt), SQL_SUCCESS != result)
2773
conn = SC_get_conn(stmt);
2774
#ifdef UNICODE_SUPPORT
2775
if (CC_is_in_unicode_driver(conn))
2776
internal_asis_type = INTERNAL_ASIS_TYPE;
2777
#endif /* UNICODE_SUPPORT */
2779
szSchemaName = szTableOwner;
2780
cbSchemaName = cbTableOwner;
2782
escTableName = simpleCatalogEscape(szTableName, cbTableName, NULL, conn);
2785
SC_set_error(stmt, STMT_INVALID_NULL_ARG, "The table name is required", func);
2788
#define return DONT_CALL_RETURN_FROM_HERE???
2790
retry_public_schema:
2792
free(escSchemaName);
2793
escSchemaName = simpleCatalogEscape(szSchemaName, cbSchemaName, NULL, conn);
2794
eq_string = gen_opestr(eqop, conn);
2796
* Create the query to find out if this is a view or not...
2798
strcpy(columns_query, "select c.relhasrules, c.relkind");
2799
if (PG_VERSION_GE(conn, 7.2))
2800
strcat(columns_query, ", c.relhasoids");
2801
if (conn->schema_support)
2802
strcat(columns_query, " from pg_catalog.pg_namespace u,"
2803
" pg_catalog.pg_class c where "
2804
"u.oid = c.relnamespace");
2806
strcat(columns_query, " from pg_user u, pg_class c where "
2807
"u.usesysid = c.relowner");
2809
/* TableName cannot contain a string search pattern */
2810
/* my_strcat(columns_query, " and c.relname = '%.*s'", szTableName, cbTableName); */
2812
snprintf_add(columns_query, sizeof(columns_query), " and c.relname %s'%s'", eq_string, escTableName);
2813
/* SchemaName cannot contain a string search pattern */
2814
if (conn->schema_support)
2815
schema_strcat1(columns_query, " and u.nspname %s'%.*s'", eq_string, escSchemaName, SQL_NTS, szTableName, cbTableName, conn);
2817
my_strcat1(columns_query, " and u.usename %s'%.*s'", eq_string, escSchemaName, SQL_NTS);
2820
result = PGAPI_AllocStmt(conn, &hcol_stmt, 0);
2821
if (!SQL_SUCCEEDED(result))
2823
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate statement for SQLSpecialColumns result.", func);
2827
col_stmt = (StatementClass *) hcol_stmt;
2829
mylog("%s: hcol_stmt = %p, col_stmt = %p\n", func, hcol_stmt, col_stmt);
2831
result = PGAPI_ExecDirect(hcol_stmt, columns_query, SQL_NTS, 0);
2832
if (!SQL_SUCCEEDED(result))
2834
SC_full_error_copy(stmt, col_stmt, FALSE);
2840
if (conn->schema_support &&
2841
(res = SC_get_Result(col_stmt)) &&
2842
0 == QR_get_num_total_tuples(res))
2844
if (allow_public_schema(conn, szSchemaName, cbSchemaName))
2846
PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
2848
szSchemaName = pubstr;
2849
cbSchemaName = SQL_NTS;
2850
goto retry_public_schema;
2854
result = PGAPI_BindCol(hcol_stmt, 1, internal_asis_type,
2855
relhasrules, sizeof(relhasrules), NULL);
2856
if (!SQL_SUCCEEDED(result))
2858
SC_error_copy(stmt, col_stmt, TRUE);
2863
result = PGAPI_BindCol(hcol_stmt, 2, internal_asis_type,
2864
relkind, sizeof(relkind), NULL);
2865
if (!SQL_SUCCEEDED(result))
2867
SC_error_copy(stmt, col_stmt, TRUE);
2871
relhasoids[0] = '1';
2872
if (PG_VERSION_GE(conn, 7.2))
2874
result = PGAPI_BindCol(hcol_stmt, 3, internal_asis_type,
2875
relhasoids, sizeof(relhasoids), NULL);
2876
if (!SQL_SUCCEEDED(result))
2878
SC_error_copy(stmt, col_stmt, TRUE);
2884
result = PGAPI_Fetch(hcol_stmt);
2885
if (PG_VERSION_GE(conn, 7.1))
2886
relisaview = (relkind[0] == 'v');
2888
relisaview = (relhasrules[0] == '1');
2889
PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
2892
res = QR_Constructor();
2893
SC_set_Result(stmt, res);
2894
extend_column_bindings(SC_get_ARDF(stmt), 8);
2896
stmt->catalog_result = TRUE;
2897
QR_set_num_fields(res, 8);
2898
QR_set_field_info_v(res, 0, "SCOPE", PG_TYPE_INT2, 2);
2899
QR_set_field_info_v(res, 1, "COLUMN_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
2900
QR_set_field_info_v(res, 2, "DATA_TYPE", PG_TYPE_INT2, 2);
2901
QR_set_field_info_v(res, 3, "TYPE_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
2902
QR_set_field_info_v(res, 4, "PRECISION", PG_TYPE_INT4, 4);
2903
QR_set_field_info_v(res, 5, "LENGTH", PG_TYPE_INT4, 4);
2904
QR_set_field_info_v(res, 6, "SCALE", PG_TYPE_INT2, 2);
2905
QR_set_field_info_v(res, 7, "PSEUDO_COLUMN", PG_TYPE_INT2, 2);
2909
/* there's no oid for views */
2910
if (fColType == SQL_BEST_ROWID)
2914
else if (fColType == SQL_ROWVER)
2916
Int2 the_type = PG_TYPE_TID;
2918
tuple = QR_AddNew(res);
2920
set_tuplefield_null(&tuple[0]);
2921
set_tuplefield_string(&tuple[1], "ctid");
2922
set_tuplefield_int2(&tuple[2], pgtype_to_concise_type(stmt, the_type, PG_STATIC));
2923
set_tuplefield_string(&tuple[3], pgtype_to_name(stmt, the_type, PG_UNSPECIFIED, FALSE));
2924
set_tuplefield_int4(&tuple[4], pgtype_column_size(stmt, the_type, PG_STATIC, UNKNOWNS_AS_DEFAULT));
2925
set_tuplefield_int4(&tuple[5], pgtype_buffer_length(stmt, the_type, PG_STATIC, UNKNOWNS_AS_DEFAULT));
2926
set_tuplefield_int2(&tuple[6], pgtype_decimal_digits(stmt, the_type, PG_STATIC));
2927
set_tuplefield_int2(&tuple[7], SQL_PC_NOT_PSEUDO);
2928
inolog("Add ctid\n");
2933
/* use the oid value for the rowid */
2934
if (fColType == SQL_BEST_ROWID)
2936
Int2 the_type = PG_TYPE_OID;
2938
if (relhasoids[0] != '1')
2942
tuple = QR_AddNew(res);
2944
set_tuplefield_int2(&tuple[0], SQL_SCOPE_SESSION);
2945
set_tuplefield_string(&tuple[1], OID_NAME);
2946
set_tuplefield_int2(&tuple[2], pgtype_to_concise_type(stmt, the_type, PG_STATIC));
2947
set_tuplefield_string(&tuple[3], pgtype_to_name(stmt, the_type, PG_UNSPECIFIED, TRUE));
2948
set_tuplefield_int4(&tuple[4], pgtype_column_size(stmt, the_type, PG_STATIC, UNKNOWNS_AS_DEFAULT));
2949
set_tuplefield_int4(&tuple[5], pgtype_buffer_length(stmt, the_type, PG_STATIC, UNKNOWNS_AS_DEFAULT));
2950
set_tuplefield_int2(&tuple[6], pgtype_decimal_digits(stmt, the_type, PG_STATIC));
2951
set_tuplefield_int2(&tuple[7], SQL_PC_PSEUDO);
2953
else if (fColType == SQL_ROWVER)
2955
Int2 the_type = PG_TYPE_XID;
2957
tuple = QR_AddNew(res);
2959
set_tuplefield_null(&tuple[0]);
2960
set_tuplefield_string(&tuple[1], "xmin");
2961
set_tuplefield_int2(&tuple[2], pgtype_to_concise_type(stmt, the_type, PG_STATIC));
2962
set_tuplefield_string(&tuple[3], pgtype_to_name(stmt, the_type, PG_UNSPECIFIED, FALSE));
2963
set_tuplefield_int4(&tuple[4], pgtype_column_size(stmt, the_type, PG_STATIC, UNKNOWNS_AS_DEFAULT));
2964
set_tuplefield_int4(&tuple[5], pgtype_buffer_length(stmt, the_type, PG_STATIC, UNKNOWNS_AS_DEFAULT));
2965
set_tuplefield_int2(&tuple[6], pgtype_decimal_digits(stmt, the_type, PG_STATIC));
2966
set_tuplefield_int2(&tuple[7], SQL_PC_PSEUDO);
2973
free(escSchemaName);
2976
stmt->status = STMT_FINISHED;
2977
stmt->currTuple = -1;
2978
SC_set_rowset_start(stmt, -1, FALSE);
2979
SC_set_current_col(stmt, -1);
2981
PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
2983
result = DiscardStatementSvp(stmt, result, FALSE);
2984
mylog("%s: EXIT, stmt=%p\n", func, stmt);
2989
#define INDOPTION_DESC 0x0001 /* values are in reverse order */
2993
const SQLCHAR FAR * szTableQualifier, /* OA X*/
2994
SQLSMALLINT cbTableQualifier,
2995
const SQLCHAR FAR * szTableOwner, /* OA E*/
2996
SQLSMALLINT cbTableOwner,
2997
const SQLCHAR FAR * szTableName, /* OA(R) E*/
2998
SQLSMALLINT cbTableName,
2999
SQLUSMALLINT fUnique,
3000
SQLUSMALLINT fAccuracy)
3002
CSTR func = "PGAPI_Statistics";
3003
StatementClass *stmt = (StatementClass *) hstmt;
3004
ConnectionClass *conn;
3006
char index_query[INFO_INQUIRY_LEN];
3007
HSTMT hcol_stmt = NULL, hindx_stmt = NULL;
3008
RETCODE ret = SQL_ERROR, result;
3009
char *escSchemaName = NULL, *table_name = NULL, *escTableName = NULL;
3010
char index_name[MAX_INFO_STRING];
3011
short fields_vector[INDEX_KEYS_STORAGE_COUNT + 1];
3012
short indopt_vector[INDEX_KEYS_STORAGE_COUNT + 1];
3015
ishash[MAX_INFO_STRING];
3016
SQLLEN index_name_len, fields_vector_len;
3019
StatementClass *col_stmt,
3021
char column_name[MAX_INFO_STRING],
3022
table_schemaname[MAX_INFO_STRING],
3024
struct columns_idx {
3027
} *column_names = NULL;
3028
/* char **column_names = NULL; */
3029
SQLLEN column_name_len;
3030
int total_columns = 0, alcount;
3033
SQLSMALLINT internal_asis_type = SQL_C_CHAR, cbSchemaName, field_number;
3034
const char *szSchemaName, *eq_string;
3038
mylog("%s: entering...stmt=%p scnm=%p len=%d\n", func, stmt, szTableOwner, cbTableOwner);
3040
if (result = SC_initialize_and_recycle(stmt), SQL_SUCCESS != result)
3043
table_name = make_string(szTableName, cbTableName, NULL, 0);
3046
SC_set_error(stmt, STMT_INVALID_NULL_ARG, "The table name is required", func);
3049
conn = SC_get_conn(stmt);
3050
ci = &(conn->connInfo);
3051
#ifdef UNICODE_SUPPORT
3052
if (CC_is_in_unicode_driver(conn))
3053
internal_asis_type = INTERNAL_ASIS_TYPE;
3054
#endif /* UNICODE_SUPPORT */
3056
if (res = QR_Constructor(), !res)
3058
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate memory for PGAPI_Statistics result.", func);
3061
SC_set_Result(stmt, res);
3063
/* the binding structure for a statement is not set up until */
3066
* a statement is actually executed, so we'll have to do this
3069
extend_column_bindings(SC_get_ARDF(stmt), 13);
3071
stmt->catalog_result = TRUE;
3072
/* set the field names */
3073
QR_set_num_fields(res, NUM_OF_STATS_FIELDS);
3074
QR_set_field_info_v(res, STATS_CATALOG_NAME, "TABLE_QUALIFIER", PG_TYPE_VARCHAR, MAX_INFO_STRING);
3075
QR_set_field_info_v(res, STATS_SCHEMA_NAME, "TABLE_OWNER", PG_TYPE_VARCHAR, MAX_INFO_STRING);
3076
QR_set_field_info_v(res, STATS_TABLE_NAME, "TABLE_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
3077
QR_set_field_info_v(res, STATS_NON_UNIQUE, "NON_UNIQUE", PG_TYPE_INT2, 2);
3078
QR_set_field_info_v(res, STATS_INDEX_QUALIFIER, "INDEX_QUALIFIER", PG_TYPE_VARCHAR, MAX_INFO_STRING);
3079
QR_set_field_info_v(res, STATS_INDEX_NAME, "INDEX_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
3080
QR_set_field_info_v(res, STATS_TYPE, "TYPE", PG_TYPE_INT2, 2);
3081
QR_set_field_info_v(res, STATS_SEQ_IN_INDEX, "SEQ_IN_INDEX", PG_TYPE_INT2, 2);
3082
QR_set_field_info_v(res, STATS_COLUMN_NAME, "COLUMN_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
3083
QR_set_field_info_v(res, STATS_COLLATION, "COLLATION", PG_TYPE_CHAR, 1);
3084
QR_set_field_info_v(res, STATS_CARDINALITY, "CARDINALITY", PG_TYPE_INT4, 4);
3085
QR_set_field_info_v(res, STATS_PAGES, "PAGES", PG_TYPE_INT4, 4);
3086
QR_set_field_info_v(res, STATS_FILTER_CONDITION, "FILTER_CONDITION", PG_TYPE_VARCHAR, MAX_INFO_STRING);
3088
#define return DONT_CALL_RETURN_FROM_HERE???
3089
szSchemaName = szTableOwner;
3090
cbSchemaName = cbTableOwner;
3092
table_schemaname[0] = '\0';
3093
if (conn->schema_support)
3094
schema_strcat(table_schemaname, "%.*s", szSchemaName, cbSchemaName, szTableName, cbTableName, conn);
3097
* we need to get a list of the field names first, so we can return
3100
result = PGAPI_AllocStmt(conn, &hcol_stmt, 0);
3101
if (!SQL_SUCCEEDED(result))
3103
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "PGAPI_AllocStmt failed in PGAPI_Statistics for columns.", func);
3107
col_stmt = (StatementClass *) hcol_stmt;
3110
* "internal" prevents SQLColumns from returning the oid if it is
3111
* being shown. This would throw everything off.
3113
col_stmt->internal = TRUE;
3115
* table_name parameter cannot contain a string search pattern.
3117
result = PGAPI_Columns(hcol_stmt, NULL, 0, table_schemaname, SQL_NTS,
3118
table_name, SQL_NTS, NULL, 0, PODBC_NOT_SEARCH_PATTERN | PODBC_SEARCH_PUBLIC_SCHEMA, 0, 0);
3119
col_stmt->internal = FALSE;
3121
if (!SQL_SUCCEEDED(result))
3123
SC_error_copy(stmt, col_stmt, TRUE);
3126
result = PGAPI_BindCol(hcol_stmt, COLUMNS_COLUMN_NAME + 1, internal_asis_type,
3127
column_name, sizeof(column_name), &column_name_len);
3128
if (!SQL_SUCCEEDED(result))
3130
SC_error_copy(stmt, col_stmt, TRUE);
3133
result = PGAPI_BindCol(hcol_stmt, COLUMNS_PHYSICAL_NUMBER + 1, SQL_C_SHORT,
3134
&field_number, sizeof(field_number), NULL);
3135
if (!SQL_SUCCEEDED(result))
3137
SC_error_copy(stmt, col_stmt, TRUE);
3142
result = PGAPI_Fetch(hcol_stmt);
3143
while (SQL_SUCCEEDED(result))
3145
if (0 == total_columns)
3146
PGAPI_GetData(hcol_stmt, 2, internal_asis_type, table_schemaname, sizeof(table_schemaname), NULL);
3148
if (total_columns >= alcount)
3155
(struct columns_idx *) realloc(column_names,
3156
alcount * sizeof(struct columns_idx));
3158
column_names[total_columns].col_name =
3159
(char *) malloc(strlen(column_name) + 1);
3160
strcpy(column_names[total_columns].col_name, column_name);
3161
column_names[total_columns].pnum = field_number;
3164
mylog("%s: column_name = '%s'\n", func, column_name);
3166
result = PGAPI_Fetch(hcol_stmt);
3169
if (result != SQL_NO_DATA_FOUND)
3171
SC_full_error_copy(stmt, col_stmt, FALSE);
3174
PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
3176
if (total_columns == 0)
3178
/* Couldn't get column names in SQLStatistics.; */
3183
/* get a list of indexes on this table */
3184
result = PGAPI_AllocStmt(conn, &hindx_stmt, 0);
3185
if (!SQL_SUCCEEDED(result))
3187
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "PGAPI_AllocStmt failed in SQLStatistics for indices.", func);
3191
indx_stmt = (StatementClass *) hindx_stmt;
3193
/* TableName cannot contain a string search pattern */
3194
escTableName = simpleCatalogEscape(table_name, SQL_NTS, NULL, conn);
3195
eq_string = gen_opestr(eqop, conn);
3196
if (conn->schema_support)
3198
escSchemaName = simpleCatalogEscape(table_schemaname, SQL_NTS, NULL, conn);
3199
snprintf(index_query, sizeof(index_query), "select c.relname, i.indkey, i.indisunique"
3200
", i.indisclustered, a.amname, c.relhasrules, n.nspname"
3202
" from pg_catalog.pg_index i, pg_catalog.pg_class c,"
3203
" pg_catalog.pg_class d, pg_catalog.pg_am a,"
3204
" pg_catalog.pg_namespace n"
3205
" where d.relname %s'%s'"
3206
" and n.nspname %s'%s'"
3207
" and n.oid = d.relnamespace"
3208
" and d.oid = i.indrelid"
3209
" and i.indexrelid = c.oid"
3210
" and c.relam = a.oid order by"
3211
, PG_VERSION_GE(conn, 7.2) ? "d.relhasoids" : "1"
3212
, PG_VERSION_GE(conn, 8.3) ? "i.indoption" : "0"
3213
, eq_string, escTableName, eq_string, escSchemaName);
3216
snprintf(index_query, sizeof(index_query), "select c.relname, i.indkey, i.indisunique"
3217
", i.indisclustered, a.amname, c.relhasrules, c.oid, %s, 0"
3218
" from pg_index i, pg_class c, pg_class d, pg_am a"
3219
" where d.relname %s'%s'"
3220
" and d.oid = i.indrelid"
3221
" and i.indexrelid = c.oid"
3222
" and c.relam = a.oid order by"
3223
, PG_VERSION_GE(conn, 7.2) ? "d.relhasoids" : "1"
3224
, eq_string, escTableName);
3225
if (PG_VERSION_GT(SC_get_conn(stmt), 6.4))
3226
strcat(index_query, " i.indisprimary desc,");
3227
if (conn->schema_support)
3228
strcat(index_query, " i.indisunique, n.nspname, c.relname");
3230
strcat(index_query, " i.indisunique, c.relname");
3232
result = PGAPI_ExecDirect(hindx_stmt, index_query, SQL_NTS, 0);
3233
if (!SQL_SUCCEEDED(result))
3236
* "Couldn't execute index query (w/SQLExecDirect) in
3239
SC_full_error_copy(stmt, indx_stmt, FALSE);
3243
/* bind the index name column */
3244
result = PGAPI_BindCol(hindx_stmt, 1, internal_asis_type,
3245
index_name, MAX_INFO_STRING, &index_name_len);
3246
if (!SQL_SUCCEEDED(result))
3248
SC_error_copy(stmt, indx_stmt, TRUE); /* "Couldn't bind column
3249
* in SQLStatistics."; */
3253
/* bind the vector column */
3254
result = PGAPI_BindCol(hindx_stmt, 2, SQL_C_DEFAULT,
3255
fields_vector, sizeof(fields_vector), &fields_vector_len);
3256
if (!SQL_SUCCEEDED(result))
3258
SC_error_copy(stmt, indx_stmt, TRUE); /* "Couldn't bind column
3259
* in SQLStatistics."; */
3263
/* bind the "is unique" column */
3264
result = PGAPI_BindCol(hindx_stmt, 3, internal_asis_type,
3265
isunique, sizeof(isunique), NULL);
3266
if (!SQL_SUCCEEDED(result))
3268
SC_error_copy(stmt, indx_stmt, TRUE); /* "Couldn't bind column
3269
* in SQLStatistics."; */
3273
/* bind the "is clustered" column */
3274
result = PGAPI_BindCol(hindx_stmt, 4, internal_asis_type,
3275
isclustered, sizeof(isclustered), NULL);
3276
if (!SQL_SUCCEEDED(result))
3278
SC_error_copy(stmt, indx_stmt, TRUE); /* "Couldn't bind column *
3279
* in SQLStatistics."; */
3284
/* bind the "is hash" column */
3285
result = PGAPI_BindCol(hindx_stmt, 5, internal_asis_type,
3286
ishash, sizeof(ishash), NULL);
3287
if (!SQL_SUCCEEDED(result))
3289
SC_error_copy(stmt, indx_stmt, TRUE); /* "Couldn't bind column *
3290
* in SQLStatistics."; */
3295
result = PGAPI_BindCol(hindx_stmt, 6, internal_asis_type,
3296
relhasrules, sizeof(relhasrules), NULL);
3297
if (!SQL_SUCCEEDED(result))
3299
SC_error_copy(stmt, indx_stmt, TRUE);
3303
result = PGAPI_BindCol(hindx_stmt, 8, SQL_C_ULONG,
3304
&ioid, sizeof(ioid), NULL);
3305
if (!SQL_SUCCEEDED(result))
3307
SC_error_copy(stmt, indx_stmt, TRUE);
3311
result = PGAPI_BindCol(hindx_stmt, 9, SQL_C_ULONG,
3312
&relhasoids, sizeof(relhasoids), NULL);
3313
if (!SQL_SUCCEEDED(result))
3315
SC_error_copy(stmt, indx_stmt, TRUE);
3319
/* bind the vector column */
3320
result = PGAPI_BindCol(hindx_stmt, 10, SQL_C_DEFAULT,
3321
indopt_vector, sizeof(fields_vector), &fields_vector_len);
3322
if (!SQL_SUCCEEDED(result))
3324
SC_error_copy(stmt, indx_stmt, TRUE); /* "Couldn't bind column
3325
* in SQLStatistics."; */
3330
relhasrules[0] = '0';
3331
result = PGAPI_Fetch(hindx_stmt);
3332
/* fake index of OID */
3333
if (relhasoids && relhasrules[0] != '1' && atoi(ci->show_oid_column) && atoi(ci->fake_oid_index))
3335
tuple = QR_AddNew(res);
3337
/* no table qualifier */
3338
set_tuplefield_string(&tuple[STATS_CATALOG_NAME], CurrCat(conn));
3339
/* don't set the table owner, else Access tries to use it */
3340
set_tuplefield_string(&tuple[STATS_SCHEMA_NAME], GET_SCHEMA_NAME(table_schemaname));
3341
set_tuplefield_string(&tuple[STATS_TABLE_NAME], table_name);
3343
/* non-unique index? */
3344
set_tuplefield_int2(&tuple[STATS_NON_UNIQUE], (Int2) (ci->drivers.unique_index ? FALSE : TRUE));
3346
/* no index qualifier */
3347
set_tuplefield_string(&tuple[STATS_INDEX_QUALIFIER], GET_SCHEMA_NAME(table_schemaname));
3349
snprintf(buf, sizeof(buf), "%s_idx_fake_oid", table_name);
3350
set_tuplefield_string(&tuple[STATS_INDEX_NAME], buf);
3353
* Clustered/HASH index?
3355
set_tuplefield_int2(&tuple[STATS_TYPE], (Int2) SQL_INDEX_OTHER);
3356
set_tuplefield_int2(&tuple[STATS_SEQ_IN_INDEX], (Int2) 1);
3358
set_tuplefield_string(&tuple[STATS_COLUMN_NAME], OID_NAME);
3359
set_tuplefield_string(&tuple[STATS_COLLATION], "A");
3360
set_tuplefield_null(&tuple[STATS_CARDINALITY]);
3361
set_tuplefield_null(&tuple[STATS_PAGES]);
3362
set_tuplefield_null(&tuple[STATS_FILTER_CONDITION]);
3365
while (SQL_SUCCEEDED(result))
3367
/* If only requesting unique indexs, then just return those. */
3368
if (fUnique == SQL_INDEX_ALL ||
3369
(fUnique == SQL_INDEX_UNIQUE && atoi(isunique)))
3373
/* add a row in this table for each field in the index */
3374
colcnt = fields_vector[0];
3375
for (i = 1; i <= colcnt; i++)
3377
tuple = QR_AddNew(res);
3379
/* no table qualifier */
3380
set_tuplefield_string(&tuple[STATS_CATALOG_NAME], CurrCat(conn));
3381
/* don't set the table owner, else Access tries to use it */
3382
set_tuplefield_string(&tuple[STATS_SCHEMA_NAME], GET_SCHEMA_NAME(table_schemaname));
3383
set_tuplefield_string(&tuple[STATS_TABLE_NAME], table_name);
3385
/* non-unique index? */
3386
if (ci->drivers.unique_index)
3387
set_tuplefield_int2(&tuple[STATS_NON_UNIQUE], (Int2) (atoi(isunique) ? FALSE : TRUE));
3389
set_tuplefield_int2(&tuple[STATS_NON_UNIQUE], TRUE);
3391
/* no index qualifier */
3392
set_tuplefield_string(&tuple[STATS_INDEX_QUALIFIER], GET_SCHEMA_NAME(table_schemaname));
3393
set_tuplefield_string(&tuple[STATS_INDEX_NAME], index_name);
3396
* Clustered/HASH index?
3398
set_tuplefield_int2(&tuple[STATS_TYPE], (Int2)
3399
(atoi(isclustered) ? SQL_INDEX_CLUSTERED :
3400
(!strncmp(ishash, "hash", 4)) ? SQL_INDEX_HASHED : SQL_INDEX_OTHER));
3401
set_tuplefield_int2(&tuple[STATS_SEQ_IN_INDEX], (Int2) i);
3403
attnum = fields_vector[i];
3404
if (OID_ATTNUM == attnum)
3406
set_tuplefield_string(&tuple[STATS_COLUMN_NAME], OID_NAME);
3407
mylog("%s: column name = oid\n", func);
3409
else if (0 == attnum)
3415
snprintf(cmd, sizeof(cmd), "select pg_get_indexdef(%u, %d, true)", ioid, i);
3416
res = CC_send_query(conn, cmd, NULL, IGNORE_ABORT_ON_CONN, stmt);
3417
if (QR_command_maybe_successful(res))
3418
set_tuplefield_string(&tuple[STATS_COLUMN_NAME], QR_get_value_backend_text(res, 0, 0));
3424
BOOL unknownf = TRUE;
3428
for (j = 0; j < total_columns; j++)
3430
if (attnum == column_names[j].pnum)
3440
set_tuplefield_string(&tuple[STATS_COLUMN_NAME], "UNKNOWN");
3441
mylog("%s: column name = UNKNOWN\n", func);
3445
set_tuplefield_string(&tuple[STATS_COLUMN_NAME], column_names[matchidx].col_name);
3446
mylog("%s: column name = '%s'\n", func, column_names[matchidx].col_name);
3450
if (i <= indopt_vector[0] &&
3451
(indopt_vector[i] & INDOPTION_DESC) != 0)
3452
set_tuplefield_string(&tuple[STATS_COLLATION], "D");
3454
set_tuplefield_string(&tuple[STATS_COLLATION], "A");
3455
set_tuplefield_null(&tuple[STATS_CARDINALITY]);
3456
set_tuplefield_null(&tuple[STATS_PAGES]);
3457
set_tuplefield_null(&tuple[STATS_FILTER_CONDITION]);
3461
result = PGAPI_Fetch(hindx_stmt);
3463
if (result != SQL_NO_DATA_FOUND)
3465
/* "SQLFetch failed in SQLStatistics."; */
3466
SC_full_error_copy(stmt, indx_stmt, FALSE);
3474
* also, things need to think that this statement is finished so the
3475
* results can be retrieved.
3477
stmt->status = STMT_FINISHED;
3480
PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
3482
PGAPI_FreeStmt(hindx_stmt, SQL_DROP);
3483
/* These things should be freed on any error ALSO! */
3489
free(escSchemaName);
3492
for (i = 0; i < total_columns; i++)
3493
free(column_names[i].col_name);
3497
/* set up the current tuple pointer for SQLFetch */
3498
stmt->currTuple = -1;
3499
SC_set_rowset_start(stmt, -1, FALSE);
3500
SC_set_current_col(stmt, -1);
3503
ret = DiscardStatementSvp(stmt, ret, FALSE);
3504
mylog("%s: EXIT, stmt=%p, ret=%d\n", func, stmt, ret);
3511
PGAPI_ColumnPrivileges(
3513
const SQLCHAR FAR * szTableQualifier, /* OA X*/
3514
SQLSMALLINT cbTableQualifier,
3515
const SQLCHAR FAR * szTableOwner, /* OA E*/
3516
SQLSMALLINT cbTableOwner,
3517
const SQLCHAR FAR * szTableName, /* OA(R) E*/
3518
SQLSMALLINT cbTableName,
3519
const SQLCHAR FAR * szColumnName, /* PV E*/
3520
SQLSMALLINT cbColumnName,
3523
CSTR func = "PGAPI_ColumnPrivileges";
3524
StatementClass *stmt = (StatementClass *) hstmt;
3525
ConnectionClass *conn = SC_get_conn(stmt);
3526
RETCODE result = SQL_ERROR;
3527
char *escSchemaName = NULL, *escTableName = NULL, *escColumnName = NULL;
3528
const char *like_or_eq, *op_string, *eq_string;
3529
char column_query[INFO_INQUIRY_LEN];
3530
size_t cq_len,cq_size;
3532
BOOL search_pattern;
3533
QResultClass *res = NULL;
3535
mylog("%s: entering...\n", func);
3537
/* Neither Access or Borland care about this. */
3539
if (result = SC_initialize_and_recycle(stmt), SQL_SUCCESS != result)
3541
if (PG_VERSION_LT(conn, 7.4))
3542
SC_set_error(stmt, STMT_NOT_IMPLEMENTED_ERROR, "Function not implementedyet", func);
3543
escSchemaName = simpleCatalogEscape(szTableOwner, cbTableOwner, NULL, conn);
3544
escTableName = simpleCatalogEscape(szTableName, cbTableName, NULL, conn);
3545
search_pattern = (0 == (flag & PODBC_NOT_SEARCH_PATTERN));
3548
like_or_eq = likeop;
3549
escColumnName = adjustLikePattern(szColumnName, cbColumnName, SEARCH_PATTERN_ESCAPE, NULL, conn);
3554
escColumnName = simpleCatalogEscape(szColumnName, cbColumnName, NULL, conn);
3556
strcpy(column_query, "select '' as TABLE_CAT, table_schema as TABLE_SCHEM,"
3557
" table_name, column_name, grantor, grantee,"
3558
" privilege_type as PRIVILEGE, is_grantable from"
3559
" information_schema.column_privileges where true");
3560
cq_len = strlen(column_query);
3561
cq_size = sizeof(column_query);
3562
col_query = column_query;
3563
op_string = gen_opestr(like_or_eq, conn);
3564
eq_string = gen_opestr(eqop, conn);
3567
col_query += cq_len;
3569
cq_len = snprintf_len(col_query, cq_size,
3570
" and table_schem %s'%s'", eq_string, escSchemaName);
3575
col_query += cq_len;
3577
cq_len += snprintf_len(col_query, cq_size,
3578
" and table_name %s'%s'", eq_string, escTableName);
3582
col_query += cq_len;
3584
cq_len += snprintf_len(col_query, cq_size,
3585
" and column_name %s'%s'", op_string, escColumnName);
3587
if (res = CC_send_query(conn, column_query, NULL, IGNORE_ABORT_ON_CONN, stmt), !QR_command_maybe_successful(res))
3589
SC_set_error(stmt, STMT_EXEC_ERROR, "PGAPI_ColumnPrivileges query error", func);
3592
SC_set_Result(stmt, res);
3595
* also, things need to think that this statement is finished so the
3596
* results can be retrieved.
3598
extend_column_bindings(SC_get_ARDF(stmt), 8);
3599
/* set up the current tuple pointer for SQLFetch */
3600
result = SQL_SUCCESS;
3602
if (!SQL_SUCCEEDED(result))
3604
/* set up the current tuple pointer for SQLFetch */
3605
stmt->status = STMT_FINISHED;
3606
stmt->currTuple = -1;
3607
SC_set_rowset_start(stmt, -1, FALSE);
3609
free(escSchemaName);
3613
free(escColumnName);
3621
* Retrieve the primary key columns for the specified table.
3626
const SQLCHAR FAR * szTableQualifier, /* OA X*/
3627
SQLSMALLINT cbTableQualifier,
3628
const SQLCHAR FAR * szTableOwner, /* OA E*/
3629
SQLSMALLINT cbTableOwner,
3630
const SQLCHAR FAR * szTableName, /* OA(R) E*/
3631
SQLSMALLINT cbTableName,
3634
CSTR func = "PGAPI_PrimaryKeys";
3635
StatementClass *stmt = (StatementClass *) hstmt;
3637
ConnectionClass *conn;
3639
RETCODE ret = SQL_SUCCESS, result;
3641
HSTMT htbl_stmt = NULL;
3642
StatementClass *tbl_stmt;
3643
char tables_query[INFO_INQUIRY_LEN];
3644
char attname[MAX_INFO_STRING];
3646
char *pktab = NULL, *pktbname;
3647
char pkscm[SCHEMA_NAME_STORAGE_LEN + 1];
3649
char tabname[TABLE_NAME_STORAGE_LEN + 1];
3651
char pkname[TABLE_NAME_STORAGE_LEN + 1];
3656
SQLSMALLINT internal_asis_type = SQL_C_CHAR, cbSchemaName;
3657
const char *szSchemaName, *eq_string;
3658
char *escSchemaName = NULL, *escTableName = NULL;
3660
mylog("%s: entering...stmt=%p scnm=%p len=%d\n", func, stmt, szTableOwner, cbTableOwner);
3662
if (result = SC_initialize_and_recycle(stmt), SQL_SUCCESS != result)
3665
if (res = QR_Constructor(), !res)
3667
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate memory for PGAPI_PrimaryKeys result.", func);
3670
SC_set_Result(stmt, res);
3672
/* the binding structure for a statement is not set up until
3674
* a statement is actually executed, so we'll have to do this
3677
result_cols = NUM_OF_PKS_FIELDS;
3678
extend_column_bindings(SC_get_ARDF(stmt), result_cols);
3680
stmt->catalog_result = TRUE;
3681
/* set the field names */
3682
QR_set_num_fields(res, result_cols);
3683
QR_set_field_info_v(res, PKS_TABLE_CAT, "TABLE_QUALIFIER", PG_TYPE_VARCHAR, MAX_INFO_STRING);
3684
QR_set_field_info_v(res, PKS_TABLE_SCHEM, "TABLE_OWNER", PG_TYPE_VARCHAR, MAX_INFO_STRING);
3685
QR_set_field_info_v(res, PKS_TABLE_NAME, "TABLE_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
3686
QR_set_field_info_v(res, PKS_COLUMN_NAME, "COLUMN_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
3687
QR_set_field_info_v(res, PKS_KEY_SQ, "KEY_SEQ", PG_TYPE_INT2, 2);
3688
QR_set_field_info_v(res, PKS_PK_NAME, "PK_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
3690
conn = SC_get_conn(stmt);
3691
result = PGAPI_AllocStmt(conn, &htbl_stmt, 0);
3692
if (!SQL_SUCCEEDED(result))
3694
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate statement for Primary Key result.", func);
3698
tbl_stmt = (StatementClass *) htbl_stmt;
3700
#ifdef UNICODE_SUPPORT
3701
if (CC_is_in_unicode_driver(conn))
3702
internal_asis_type = INTERNAL_ASIS_TYPE;
3703
#endif /* UNICODE_SUPPORT */
3705
#define return DONT_CALL_RETURN_FROM_HERE???
3708
szSchemaName = NULL;
3709
cbSchemaName = SQL_NULL_DATA;
3713
pktab = make_string(szTableName, cbTableName, NULL, 0);
3714
if (!pktab || pktab[0] == '\0')
3716
SC_set_error(stmt, STMT_INTERNAL_ERROR, "No Table specified to PGAPI_PrimaryKeys.", func);
3720
szSchemaName = szTableOwner;
3721
cbSchemaName = cbTableOwner;
3722
escTableName = simpleCatalogEscape(szTableName, cbTableName, NULL, conn);
3724
eq_string = gen_opestr(eqop, conn);
3726
retry_public_schema:
3731
free(escSchemaName);
3732
escSchemaName = simpleCatalogEscape(szSchemaName, cbSchemaName, NULL, conn);
3733
if (conn->schema_support)
3734
schema_strcat(pkscm, "%.*s", escSchemaName, SQL_NTS, szTableName, cbTableName, conn);
3737
result = PGAPI_BindCol(htbl_stmt, 1, internal_asis_type,
3738
attname, MAX_INFO_STRING, &attname_len);
3739
if (!SQL_SUCCEEDED(result))
3741
SC_error_copy(stmt, tbl_stmt, TRUE);
3745
result = PGAPI_BindCol(htbl_stmt, 3, internal_asis_type,
3746
pkname, TABLE_NAME_STORAGE_LEN, NULL);
3747
if (!SQL_SUCCEEDED(result))
3749
SC_error_copy(stmt, tbl_stmt, TRUE);
3753
result = PGAPI_BindCol(htbl_stmt, 4, internal_asis_type,
3754
pkscm, SCHEMA_NAME_STORAGE_LEN, &pkscm_len);
3755
if (!SQL_SUCCEEDED(result))
3757
SC_error_copy(stmt, tbl_stmt, TRUE);
3761
result = PGAPI_BindCol(htbl_stmt, 5, internal_asis_type,
3762
tabname, TABLE_NAME_STORAGE_LEN, &tabname_len);
3763
if (!SQL_SUCCEEDED(result))
3765
SC_error_copy(stmt, tbl_stmt, TRUE);
3770
if (PG_VERSION_LE(conn, 6.4))
3778
for (qno = qstart; qno <= qend; qno++)
3780
size_t qsize, tsize;
3788
* Simplified query to remove assumptions about number of
3789
* possible index columns. Courtesy of Tom Lane - thomas
3792
if (conn->schema_support)
3794
strncpy_null(tables_query,
3795
"select ta.attname, ia.attnum, ic.relname, n.nspname, tc.relname"
3796
" from pg_catalog.pg_attribute ta,"
3797
" pg_catalog.pg_attribute ia, pg_catalog.pg_class tc,"
3798
" pg_catalog.pg_index i, pg_catalog.pg_namespace n"
3799
", pg_catalog.pg_class ic"
3800
, sizeof(tables_query));
3801
qsize = strlen(tables_query);
3802
tsize = sizeof(tables_query) - qsize;
3803
tbqry = tables_query + qsize;
3805
snprintf(tbqry, tsize,
3806
" where tc.relname %s'%s'"
3807
" AND n.nspname %s'%s'"
3808
, eq_string, escTableName, eq_string, pkscm);
3810
snprintf(tbqry, tsize,
3811
" where tc.oid = " FORMAT_UINT4
3814
strlcat(tables_query,
3815
" AND tc.oid = i.indrelid"
3816
" AND n.oid = tc.relnamespace"
3817
" AND i.indisprimary = 't'"
3818
" AND ia.attrelid = i.indexrelid"
3819
" AND ta.attrelid = i.indrelid"
3820
" AND ta.attnum = i.indkey[ia.attnum-1]"
3821
" AND (NOT ta.attisdropped)"
3822
" AND (NOT ia.attisdropped)"
3823
" AND ic.oid = i.indexrelid"
3824
" order by ia.attnum"
3825
, sizeof(tables_query));
3829
strncpy_null(tables_query,
3830
"select ta.attname, ia.attnum, ic.relname, NULL, tc.relname"
3831
" from pg_attribute ta, pg_attribute ia, pg_class tc, pg_index i, pg_class ic"
3832
, sizeof(tables_query));
3833
qsize = strlen(tables_query);
3834
tsize = sizeof(tables_query) - qsize;
3835
tbqry = tables_query + qsize;
3837
snprintf(tbqry, tsize,
3838
" where tc.relname %s'%s'"
3839
, eq_string, escTableName);
3841
snprintf(tbqry, tsize,
3842
" where tc.oid = " FORMAT_UINT4, reloid);
3844
strlcat(tables_query,
3845
" AND tc.oid = i.indrelid"
3846
" AND i.indisprimary = 't'"
3847
" AND ia.attrelid = i.indexrelid"
3848
" AND ta.attrelid = i.indrelid"
3849
" AND ta.attnum = i.indkey[ia.attnum-1]"
3850
" AND ic.oid = i.indexrelid"
3851
" order by ia.attnum"
3852
, sizeof(tables_query));
3858
* Simplified query to search old fashoned primary key
3860
if (conn->schema_support)
3861
snprintf(tables_query, sizeof(tables_query), "select ta.attname, ia.attnum, ic.relname, n.nspname, NULL"
3862
" from pg_catalog.pg_attribute ta,"
3863
" pg_catalog.pg_attribute ia, pg_catalog.pg_class ic,"
3864
" pg_catalog.pg_index i, pg_catalog.pg_namespace n"
3865
" where ic.relname %s'%s_pkey'"
3866
" AND n.nspname %s'%s'"
3867
" AND ic.oid = i.indexrelid"
3868
" AND n.oid = ic.relnamespace"
3869
" AND ia.attrelid = i.indexrelid"
3870
" AND ta.attrelid = i.indrelid"
3871
" AND ta.attnum = i.indkey[ia.attnum-1]"
3872
" AND (NOT ta.attisdropped)"
3873
" AND (NOT ia.attisdropped)"
3874
" order by ia.attnum", eq_string, escTableName, eq_string, pkscm);
3876
snprintf(tables_query, sizeof(tables_query), "select ta.attname, ia.attnum, ic.relname, NULL, NULL"
3877
" from pg_attribute ta, pg_attribute ia, pg_class ic, pg_index i"
3878
" where ic.relname %s'%s_pkey'"
3879
" AND ic.oid = i.indexrelid"
3880
" AND ia.attrelid = i.indexrelid"
3881
" AND ta.attrelid = i.indrelid"
3882
" AND ta.attnum = i.indkey[ia.attnum-1]"
3883
" order by ia.attnum", eq_string, escTableName);
3886
mylog("%s: tables_query='%s'\n", func, tables_query);
3888
result = PGAPI_ExecDirect(htbl_stmt, tables_query, SQL_NTS, 0);
3889
if (!SQL_SUCCEEDED(result))
3891
SC_full_error_copy(stmt, tbl_stmt, FALSE);
3896
result = PGAPI_Fetch(htbl_stmt);
3897
if (result != SQL_NO_DATA_FOUND)
3902
if (conn->schema_support &&
3903
SQL_NO_DATA_FOUND == result)
3906
allow_public_schema(conn, szSchemaName, cbSchemaName))
3908
szSchemaName = pubstr;
3909
cbSchemaName = SQL_NTS;
3910
goto retry_public_schema;
3914
while (SQL_SUCCEEDED(result))
3916
tuple = QR_AddNew(res);
3918
set_tuplefield_string(&tuple[PKS_TABLE_CAT], CurrCat(conn));
3921
* I have to hide the table owner from Access, otherwise it
3922
* insists on referring to the table as 'owner.table'. (this is
3923
* valid according to the ODBC SQL grammar, but Postgres won't
3926
if (SQL_NULL_DATA == pkscm_len)
3928
set_tuplefield_string(&tuple[PKS_TABLE_SCHEM], GET_SCHEMA_NAME(pkscm));
3929
if (SQL_NULL_DATA == tabname_len)
3931
pktbname = pktab ? pktab : tabname;
3932
set_tuplefield_string(&tuple[PKS_TABLE_NAME], pktbname);
3933
set_tuplefield_string(&tuple[PKS_COLUMN_NAME], attname);
3934
set_tuplefield_int2(&tuple[PKS_KEY_SQ], (Int2) (++seq));
3935
set_tuplefield_string(&tuple[PKS_PK_NAME], pkname);
3937
mylog(">> primaryKeys: schema ='%s', pktab = '%s', attname = '%s', seq = %d\n", pkscm, pktbname, attname, seq);
3939
result = PGAPI_Fetch(htbl_stmt);
3942
if (result != SQL_NO_DATA_FOUND)
3944
SC_full_error_copy(stmt, htbl_stmt, FALSE);
3953
* also, things need to think that this statement is finished so the
3954
* results can be retrieved.
3956
stmt->status = STMT_FINISHED;
3959
PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
3964
free(escSchemaName);
3967
/* set up the current tuple pointer for SQLFetch */
3968
stmt->currTuple = -1;
3969
SC_set_rowset_start(stmt, -1, FALSE);
3970
SC_set_current_col(stmt, -1);
3973
ret = DiscardStatementSvp(stmt, ret, FALSE);
3974
mylog("%s: EXIT, stmt=%p, ret=%d\n", func, stmt, ret);
3980
* Multibyte support stuff for SQLForeignKeys().
3981
* There may be much more effective way in the
3982
* future version. The way is very forcible currently.
3985
isMultibyte(const UCHAR *str)
3995
getClientColumnName(ConnectionClass *conn, UInt4 relid, char *serverColumnName, BOOL *nameAlloced)
3997
char query[1024], saveattnum[16],
3998
*ret = serverColumnName;
3999
const char *eq_string;
4000
BOOL continueExec = TRUE,
4002
QResultClass *res = NULL;
4003
UWORD flag = IGNORE_ABORT_ON_CONN | ROLLBACK_ON_ERROR;
4005
*nameAlloced = FALSE;
4006
if (!conn->original_client_encoding || !isMultibyte(serverColumnName))
4008
if (!conn->server_encoding)
4010
if (res = CC_send_query(conn, "select getdatabaseencoding()", NULL, flag, NULL), QR_command_maybe_successful(res))
4012
if (QR_get_num_cached_tuples(res) > 0)
4013
conn->server_encoding = strdup(QR_get_value_backend_text(res, 0, 0));
4018
if (!conn->server_encoding)
4020
snprintf(query, sizeof(query), "SET CLIENT_ENCODING TO '%s'", conn->server_encoding);
4021
bError = (!QR_command_maybe_successful((res = CC_send_query(conn, query, NULL, flag, NULL))));
4023
eq_string = gen_opestr(eqop, conn);
4024
if (!bError && continueExec)
4026
snprintf(query, sizeof(query), "select attnum from pg_attribute "
4027
"where attrelid = %u and attname %s'%s'",
4028
relid, eq_string, serverColumnName);
4029
if (res = CC_send_query(conn, query, NULL, flag, NULL), QR_command_maybe_successful(res))
4031
if (QR_get_num_cached_tuples(res) > 0)
4033
strcpy(saveattnum, QR_get_value_backend_text(res, 0, 0));
4036
continueExec = FALSE;
4042
continueExec = (continueExec && !bError);
4043
/* restore the cleint encoding */
4044
snprintf(query, sizeof(query), "SET CLIENT_ENCODING TO '%s'", conn->original_client_encoding);
4045
bError = (!QR_command_maybe_successful((res = CC_send_query(conn, query, NULL, flag, NULL))));
4047
if (bError || !continueExec)
4049
snprintf(query, sizeof(query), "select attname from pg_attribute where attrelid = %u and attnum = %s", relid, saveattnum);
4050
if (res = CC_send_query(conn, query, NULL, flag, NULL), QR_command_maybe_successful(res))
4052
if (QR_get_num_cached_tuples(res) > 0)
4054
ret = strdup(QR_get_value_backend_text(res, 0, 0));
4055
*nameAlloced = TRUE;
4062
static RETCODE SQL_API
4063
PGAPI_ForeignKeys_new(
4065
const SQLCHAR FAR * szPkTableQualifier, /* OA X*/
4066
SQLSMALLINT cbPkTableQualifier,
4067
const SQLCHAR FAR * szPkTableOwner, /* OA E*/
4068
SQLSMALLINT cbPkTableOwner,
4069
const SQLCHAR FAR * szPkTableName, /* OA(R) E*/
4070
SQLSMALLINT cbPkTableName,
4071
const SQLCHAR FAR * szFkTableQualifier, /* OA X*/
4072
SQLSMALLINT cbFkTableQualifier,
4073
const SQLCHAR FAR * szFkTableOwner, /* OA E*/
4074
SQLSMALLINT cbFkTableOwner,
4075
const SQLCHAR FAR * szFkTableName, /* OA(R) E*/
4076
SQLSMALLINT cbFkTableName);
4078
static RETCODE SQL_API
4079
PGAPI_ForeignKeys_old(
4081
const SQLCHAR FAR * szPkTableQualifier, /* OA X*/
4082
SQLSMALLINT cbPkTableQualifier,
4083
const SQLCHAR FAR * szPkTableOwner, /* OA E*/
4084
SQLSMALLINT cbPkTableOwner,
4085
const SQLCHAR FAR * szPkTableName, /* OA(R) E*/
4086
SQLSMALLINT cbPkTableName,
4087
const SQLCHAR FAR * szFkTableQualifier, /* OA X*/
4088
SQLSMALLINT cbFkTableQualifier,
4089
const SQLCHAR FAR * szFkTableOwner, /* OA E*/
4090
SQLSMALLINT cbFkTableOwner,
4091
const SQLCHAR FAR * szFkTableName, /* OA(R) E*/
4092
SQLSMALLINT cbFkTableName)
4094
CSTR func = "PGAPI_ForeignKeys";
4095
StatementClass *stmt = (StatementClass *) hstmt;
4098
HSTMT htbl_stmt = NULL, hpkey_stmt = NULL;
4099
StatementClass *tbl_stmt;
4100
RETCODE ret = SQL_ERROR, result, keyresult;
4101
char tables_query[INFO_INQUIRY_LEN];
4102
char trig_deferrable[2];
4103
char trig_initdeferred[2];
4104
char trig_args[1024];
4105
char upd_rule[TABLE_NAME_STORAGE_LEN],
4106
del_rule[TABLE_NAME_STORAGE_LEN];
4107
char *pk_table_needed = NULL, *escPkTableName = NULL;
4108
char fk_table_fetched[TABLE_NAME_STORAGE_LEN + 1];
4109
char *fk_table_needed = NULL, *escFkTableName = NULL;
4110
char pk_table_fetched[TABLE_NAME_STORAGE_LEN + 1];
4111
char schema_needed[SCHEMA_NAME_STORAGE_LEN + 1];
4112
char schema_fetched[SCHEMA_NAME_STORAGE_LEN + 1];
4113
char constrname[NAMESTORAGELEN + 1], pkname[TABLE_NAME_STORAGE_LEN + 1];
4119
ConnectionClass *conn;
4121
fkey_alloced, got_pkname;
4126
SQLSMALLINT trig_nargs,
4129
SQLSMALLINT internal_asis_type = SQL_C_CHAR;
4131
#if (ODBCVER >= 0x0300)
4132
SQLSMALLINT defer_type;
4134
char pkey[MAX_INFO_STRING];
4136
UInt4 relid1, relid2;
4137
const char *eq_string;
4139
mylog("%s: entering...stmt=%p\n", func, stmt);
4141
if (result = SC_initialize_and_recycle(stmt), SQL_SUCCESS != result)
4144
if (res = QR_Constructor(), !res)
4146
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate memory for PGAPI_ForeignKeys result.", func);
4149
SC_set_Result(stmt, res);
4151
/* the binding structure for a statement is not set up until */
4154
* a statement is actually executed, so we'll have to do this
4157
result_cols = NUM_OF_FKS_FIELDS;
4158
extend_column_bindings(SC_get_ARDF(stmt), result_cols);
4160
stmt->catalog_result = TRUE;
4161
/* set the field names */
4162
QR_set_num_fields(res, result_cols);
4163
QR_set_field_info_v(res, FKS_PKTABLE_CAT, "PKTABLE_QUALIFIER", PG_TYPE_VARCHAR, MAX_INFO_STRING);
4164
QR_set_field_info_v(res, FKS_PKTABLE_SCHEM, "PKTABLE_OWNER", PG_TYPE_VARCHAR, MAX_INFO_STRING);
4165
QR_set_field_info_v(res, FKS_PKTABLE_NAME, "PKTABLE_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
4166
QR_set_field_info_v(res, FKS_PKCOLUMN_NAME, "PKCOLUMN_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
4167
QR_set_field_info_v(res, FKS_FKTABLE_CAT, "FKTABLE_QUALIFIER", PG_TYPE_VARCHAR, MAX_INFO_STRING);
4168
QR_set_field_info_v(res, FKS_FKTABLE_SCHEM, "FKTABLE_OWNER", PG_TYPE_VARCHAR, MAX_INFO_STRING);
4169
QR_set_field_info_v(res, FKS_FKTABLE_NAME, "FKTABLE_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
4170
QR_set_field_info_v(res, FKS_FKCOLUMN_NAME, "FKCOLUMN_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
4171
QR_set_field_info_v(res, FKS_KEY_SEQ, "KEY_SEQ", PG_TYPE_INT2, 2);
4172
QR_set_field_info_v(res, FKS_UPDATE_RULE, "UPDATE_RULE", PG_TYPE_INT2, 2);
4173
QR_set_field_info_v(res, FKS_DELETE_RULE, "DELETE_RULE", PG_TYPE_INT2, 2);
4174
QR_set_field_info_v(res, FKS_FK_NAME, "FK_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
4175
QR_set_field_info_v(res, FKS_PK_NAME, "PK_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
4176
#if (ODBCVER >= 0x0300)
4177
QR_set_field_info_v(res, FKS_DEFERRABILITY, "DEFERRABILITY", PG_TYPE_INT2, 2);
4178
#endif /* ODBCVER >= 0x0300 */
4179
QR_set_field_info_v(res, FKS_TRIGGER_NAME, "TRIGGER_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
4182
* also, things need to think that this statement is finished so the
4183
* results can be retrieved.
4185
stmt->status = STMT_FINISHED;
4187
/* set up the current tuple pointer for SQLFetch */
4188
stmt->currTuple = -1;
4189
SC_set_rowset_start(stmt, -1, FALSE);
4190
SC_set_current_col(stmt, -1);
4192
conn = SC_get_conn(stmt);
4193
result = PGAPI_AllocStmt(conn, &htbl_stmt, 0);
4194
if (!SQL_SUCCEEDED(result))
4196
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate statement for PGAPI_ForeignKeys result.", func);
4200
#define return DONT_CALL_RETURN_FROM_HERE???
4202
tbl_stmt = (StatementClass *) htbl_stmt;
4203
schema_needed[0] = '\0';
4204
schema_fetched[0] = '\0';
4206
pk_table_needed = make_string(szPkTableName, cbPkTableName, NULL, 0);
4207
fk_table_needed = make_string(szFkTableName, cbFkTableName, NULL, 0);
4209
#ifdef UNICODE_SUPPORT
4210
if (CC_is_in_unicode_driver(conn))
4211
internal_asis_type = INTERNAL_ASIS_TYPE;
4212
#endif /* UNICODE_SUPPORT */
4213
pkey_alloced = fkey_alloced = FALSE;
4215
eq_string = gen_opestr(eqop, conn);
4217
* Case #2 -- Get the foreign keys in the specified table (fktab) that
4218
* refer to the primary keys of other table(s).
4220
if (fk_table_needed && fk_table_needed[0] != '\0')
4222
mylog("%s: entering Foreign Key Case #2", func);
4223
escFkTableName = simpleCatalogEscape(fk_table_needed, SQL_NTS, NULL, conn);
4224
if (conn->schema_support)
4226
char *escSchemaName;
4228
schema_strcat(schema_needed, "%.*s", szFkTableOwner, cbFkTableOwner, szFkTableName, cbFkTableName, conn);
4229
escSchemaName = simpleCatalogEscape(schema_needed, SQL_NTS, NULL, conn);
4230
snprintf(tables_query, sizeof(tables_query), "SELECT pt.tgargs, "
4232
" pt.tgdeferrable, "
4233
" pt.tginitdeferred, "
4239
" pt.tgconstrname, pn.nspname "
4240
"FROM pg_catalog.pg_class pc, "
4241
" pg_catalog.pg_proc pp1, "
4242
" pg_catalog.pg_proc pp2, "
4243
" pg_catalog.pg_trigger pt1, "
4244
" pg_catalog.pg_trigger pt2, "
4245
" pg_catalog.pg_proc pp, "
4246
" pg_catalog.pg_trigger pt, "
4247
" pg_catalog.pg_class pc1, "
4248
" pg_catalog.pg_namespace pn, "
4249
" pg_catalog.pg_namespace pn1 "
4250
"WHERE pt.tgrelid = pc.oid "
4251
"AND pp.oid = pt.tgfoid "
4252
"AND pt1.tgconstrrelid = pc.oid "
4253
"AND pp1.oid = pt1.tgfoid "
4254
"AND pt2.tgfoid = pp2.oid "
4255
"AND pt2.tgconstrrelid = pc.oid "
4256
"AND ((pc.relname %s'%s') "
4257
"AND (pn1.oid = pc.relnamespace) "
4258
"AND (pn1.nspname %s'%s') "
4259
"AND (pp.proname LIKE '%%ins') "
4260
"AND (pp1.proname LIKE '%%upd') "
4261
"AND (pp1.proname not LIKE '%%check%%') "
4262
"AND (pp2.proname LIKE '%%del') "
4263
"AND (pt1.tgrelid=pt.tgconstrrelid) "
4264
"AND (pt1.tgconstrname=pt.tgconstrname) "
4265
"AND (pt2.tgrelid=pt.tgconstrrelid) "
4266
"AND (pt2.tgconstrname=pt.tgconstrname) "
4267
"AND (pt.tgconstrrelid=pc1.oid) "
4268
"AND (pc1.relnamespace=pn.oid))"
4269
" order by pt.tgconstrname",
4270
eq_string, escFkTableName, eq_string, escSchemaName);
4271
free(escSchemaName);
4274
snprintf(tables_query, sizeof(tables_query), "SELECT pt.tgargs, "
4276
" pt.tgdeferrable, "
4277
" pt.tginitdeferred, "
4282
" pc1.relname, pt.tgconstrname "
4283
"FROM pg_class pc, "
4291
"WHERE pt.tgrelid = pc.oid "
4292
"AND pp.oid = pt.tgfoid "
4293
"AND pt1.tgconstrrelid = pc.oid "
4294
"AND pp1.oid = pt1.tgfoid "
4295
"AND pt2.tgfoid = pp2.oid "
4296
"AND pt2.tgconstrrelid = pc.oid "
4297
"AND ((pc.relname %s'%s') "
4298
"AND (pp.proname LIKE '%%ins') "
4299
"AND (pp1.proname LIKE '%%upd') "
4300
"AND (pp1.proname not LIKE '%%check%%') "
4301
"AND (pp2.proname LIKE '%%del') "
4302
"AND (pt1.tgrelid=pt.tgconstrrelid) "
4303
"AND (pt1.tgconstrname=pt.tgconstrname) "
4304
"AND (pt2.tgrelid=pt.tgconstrrelid) "
4305
"AND (pt2.tgconstrname=pt.tgconstrname) "
4306
"AND (pt.tgconstrrelid=pc1.oid)) "
4307
"order by pt.tgconstrname",
4308
eq_string, escFkTableName);
4310
result = PGAPI_ExecDirect(htbl_stmt, tables_query, SQL_NTS, 0);
4312
if (!SQL_SUCCEEDED(result))
4314
SC_full_error_copy(stmt, tbl_stmt, FALSE);
4318
result = PGAPI_BindCol(htbl_stmt, 1, SQL_C_BINARY,
4319
trig_args, sizeof(trig_args), NULL);
4320
if (!SQL_SUCCEEDED(result))
4322
SC_error_copy(stmt, tbl_stmt, TRUE);
4326
result = PGAPI_BindCol(htbl_stmt, 2, SQL_C_SHORT,
4327
&trig_nargs, 0, NULL);
4328
if (!SQL_SUCCEEDED(result))
4330
SC_error_copy(stmt, tbl_stmt, TRUE);
4334
result = PGAPI_BindCol(htbl_stmt, 3, internal_asis_type,
4335
trig_deferrable, sizeof(trig_deferrable), NULL);
4336
if (!SQL_SUCCEEDED(result))
4338
SC_error_copy(stmt, tbl_stmt, TRUE);
4342
result = PGAPI_BindCol(htbl_stmt, 4, internal_asis_type,
4343
trig_initdeferred, sizeof(trig_initdeferred), NULL);
4344
if (!SQL_SUCCEEDED(result))
4346
SC_error_copy(stmt, tbl_stmt, TRUE);
4350
result = PGAPI_BindCol(htbl_stmt, 5, internal_asis_type,
4351
upd_rule, sizeof(upd_rule), NULL);
4352
if (!SQL_SUCCEEDED(result))
4354
SC_error_copy(stmt, tbl_stmt, TRUE);
4358
result = PGAPI_BindCol(htbl_stmt, 6, internal_asis_type,
4359
del_rule, sizeof(del_rule), NULL);
4360
if (!SQL_SUCCEEDED(result))
4362
SC_error_copy(stmt, tbl_stmt, TRUE);
4366
result = PGAPI_BindCol(htbl_stmt, 7, SQL_C_ULONG,
4367
&relid1, sizeof(relid1), NULL);
4368
if (!SQL_SUCCEEDED(result))
4370
SC_error_copy(stmt, tbl_stmt, TRUE);
4373
result = PGAPI_BindCol(htbl_stmt, 8, SQL_C_ULONG,
4374
&relid2, sizeof(relid2), NULL);
4375
if (!SQL_SUCCEEDED(result))
4377
SC_error_copy(stmt, tbl_stmt, TRUE);
4380
result = PGAPI_BindCol(htbl_stmt, 9, internal_asis_type,
4381
pk_table_fetched, TABLE_NAME_STORAGE_LEN, NULL);
4382
if (!SQL_SUCCEEDED(result))
4384
SC_error_copy(stmt, tbl_stmt, TRUE);
4387
result = PGAPI_BindCol(htbl_stmt, 10, internal_asis_type,
4388
constrname, NAMESTORAGELEN, NULL);
4389
if (!SQL_SUCCEEDED(result))
4391
SC_error_copy(stmt, tbl_stmt, TRUE);
4395
if (conn->schema_support)
4397
result = PGAPI_BindCol(htbl_stmt, 11, internal_asis_type,
4398
schema_fetched, SCHEMA_NAME_STORAGE_LEN, NULL);
4399
if (!SQL_SUCCEEDED(result))
4401
SC_error_copy(stmt, tbl_stmt, TRUE);
4406
result = PGAPI_Fetch(htbl_stmt);
4407
if (result == SQL_NO_DATA_FOUND)
4413
if (result != SQL_SUCCESS)
4415
SC_full_error_copy(stmt, tbl_stmt, FALSE);
4419
keyresult = PGAPI_AllocStmt(conn, &hpkey_stmt, 0);
4420
if (!SQL_SUCCEEDED(keyresult))
4422
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate statement for PGAPI_ForeignKeys (pkeys) result.", func);
4426
keyresult = PGAPI_BindCol(hpkey_stmt, 4, internal_asis_type,
4427
pkey, sizeof(pkey), NULL);
4428
if (keyresult != SQL_SUCCESS)
4430
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't bindcol for primary keys for PGAPI_ForeignKeys result.", func);
4434
while (result == SQL_SUCCESS)
4436
/* Compute the number of keyparts. */
4437
num_keys = (trig_nargs - 4) / 2;
4439
mylog("Foreign Key Case#2: trig_nargs = %d, num_keys = %d\n", trig_nargs, num_keys);
4441
/* If there is a pk table specified, then check it. */
4442
if (pk_table_needed && pk_table_needed[0] != '\0')
4444
/* If it doesn't match, then continue */
4445
if (strcmp(pk_table_fetched, pk_table_needed))
4447
result = PGAPI_Fetch(htbl_stmt);
4453
keyresult = PGAPI_PrimaryKeys(hpkey_stmt, NULL, 0, schema_fetched, SQL_NTS, pk_table_fetched, SQL_NTS, 0);
4454
if (keyresult != SQL_SUCCESS)
4456
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't get primary keys for PGAPI_ForeignKeys result.", func);
4460
/* Get to first primary key */
4461
pkey_ptr = trig_args;
4462
for (i = 0; i < 5; i++)
4463
pkey_ptr += strlen(pkey_ptr) + 1;
4465
for (k = 0; k < num_keys; k++)
4467
/* Check that the key listed is the primary key */
4468
keyresult = PGAPI_Fetch(hpkey_stmt);
4469
if (keyresult != SQL_SUCCESS)
4476
PGAPI_GetData(hpkey_stmt, 6, internal_asis_type, pkname, sizeof(pkname), NULL);
4479
pkey_text = getClientColumnName(conn, relid2, pkey_ptr, &pkey_alloced);
4480
mylog("%s: pkey_ptr='%s', pkey='%s'\n", func, pkey_text, pkey);
4481
if (strcmp(pkey_text, pkey))
4488
/* Get to next primary key */
4489
for (k = 0; k < 2; k++)
4490
pkey_ptr += strlen(pkey_ptr) + 1;
4493
PGAPI_FreeStmt(hpkey_stmt, SQL_CLOSE);
4495
/* Set to first fk column */
4496
fkey_ptr = trig_args;
4497
for (k = 0; k < 4; k++)
4498
fkey_ptr += strlen(fkey_ptr) + 1;
4500
/* Set update and delete actions for foreign keys */
4501
if (!strcmp(upd_rule, "RI_FKey_cascade_upd"))
4502
upd_rule_type = SQL_CASCADE;
4503
else if (!strcmp(upd_rule, "RI_FKey_noaction_upd"))
4504
upd_rule_type = SQL_NO_ACTION;
4505
else if (!strcmp(upd_rule, "RI_FKey_restrict_upd"))
4506
upd_rule_type = SQL_NO_ACTION;
4507
else if (!strcmp(upd_rule, "RI_FKey_setdefault_upd"))
4508
upd_rule_type = SQL_SET_DEFAULT;
4509
else if (!strcmp(upd_rule, "RI_FKey_setnull_upd"))
4510
upd_rule_type = SQL_SET_NULL;
4512
if (!strcmp(del_rule, "RI_FKey_cascade_del"))
4513
del_rule_type = SQL_CASCADE;
4514
else if (!strcmp(del_rule, "RI_FKey_noaction_del"))
4515
del_rule_type = SQL_NO_ACTION;
4516
else if (!strcmp(del_rule, "RI_FKey_restrict_del"))
4517
del_rule_type = SQL_NO_ACTION;
4518
else if (!strcmp(del_rule, "RI_FKey_setdefault_del"))
4519
del_rule_type = SQL_SET_DEFAULT;
4520
else if (!strcmp(del_rule, "RI_FKey_setnull_del"))
4521
del_rule_type = SQL_SET_NULL;
4523
#if (ODBCVER >= 0x0300)
4524
/* Set deferrability type */
4525
if (!strcmp(trig_initdeferred, "y"))
4526
defer_type = SQL_INITIALLY_DEFERRED;
4527
else if (!strcmp(trig_deferrable, "y"))
4528
defer_type = SQL_INITIALLY_IMMEDIATE;
4530
defer_type = SQL_NOT_DEFERRABLE;
4531
#endif /* ODBCVER >= 0x0300 */
4533
/* Get to first primary key */
4534
pkey_ptr = trig_args;
4535
for (i = 0; i < 5; i++)
4536
pkey_ptr += strlen(pkey_ptr) + 1;
4538
for (k = 0; k < num_keys; k++)
4540
tuple = QR_AddNew(res);
4542
pkey_text = getClientColumnName(conn, relid2, pkey_ptr, &pkey_alloced);
4543
fkey_text = getClientColumnName(conn, relid1, fkey_ptr, &fkey_alloced);
4545
mylog("%s: pk_table = '%s', pkey_ptr = '%s'\n", func, pk_table_fetched, pkey_text);
4546
set_tuplefield_string(&tuple[FKS_PKTABLE_CAT], CurrCat(conn));
4547
set_tuplefield_string(&tuple[FKS_PKTABLE_SCHEM], GET_SCHEMA_NAME(schema_fetched));
4548
set_tuplefield_string(&tuple[FKS_PKTABLE_NAME], pk_table_fetched);
4549
set_tuplefield_string(&tuple[FKS_PKCOLUMN_NAME], pkey_text);
4551
mylog("%s: fk_table_needed = '%s', fkey_ptr = '%s'\n", func, fk_table_needed, fkey_text);
4552
set_tuplefield_string(&tuple[FKS_FKTABLE_CAT], CurrCat(conn));
4553
set_tuplefield_string(&tuple[FKS_FKTABLE_SCHEM], GET_SCHEMA_NAME(schema_needed));
4554
set_tuplefield_string(&tuple[FKS_FKTABLE_NAME], fk_table_needed);
4555
set_tuplefield_string(&tuple[FKS_FKCOLUMN_NAME], fkey_text);
4557
mylog("%s: upd_rule_type = '%i', del_rule_type = '%i'\n, trig_name = '%s'", func, upd_rule_type, del_rule_type, trig_args);
4558
set_tuplefield_int2(&tuple[FKS_KEY_SEQ], (Int2) (k + 1));
4559
set_tuplefield_int2(&tuple[FKS_UPDATE_RULE], upd_rule_type);
4560
set_tuplefield_int2(&tuple[FKS_DELETE_RULE], del_rule_type);
4561
set_tuplefield_string(&tuple[FKS_FK_NAME], constrname);
4562
set_tuplefield_string(&tuple[FKS_PK_NAME], pkname);
4563
#if (ODBCVER >= 0x0300)
4564
set_tuplefield_int2(&tuple[FKS_DEFERRABILITY], defer_type);
4565
#endif /* ODBCVER >= 0x0300 */
4566
set_tuplefield_string(&tuple[FKS_TRIGGER_NAME], trig_args);
4570
fkey_alloced = FALSE;
4573
pkey_alloced = FALSE;
4574
/* next primary/foreign key */
4575
for (i = 0; i < 2; i++)
4577
fkey_ptr += strlen(fkey_ptr) + 1;
4578
pkey_ptr += strlen(pkey_ptr) + 1;
4582
result = PGAPI_Fetch(htbl_stmt);
4587
* Case #1 -- Get the foreign keys in other tables that refer to the
4588
* primary key in the specified table (pktab). i.e., Who points to
4591
else if (pk_table_needed[0] != '\0')
4593
escPkTableName = simpleCatalogEscape(pk_table_needed, SQL_NTS, NULL, conn);
4594
if (conn->schema_support)
4596
char *escSchemaName;
4598
schema_strcat(schema_needed, "%.*s", szPkTableOwner, cbPkTableOwner, szPkTableName, cbPkTableName, conn);
4599
escSchemaName = simpleCatalogEscape(schema_needed, SQL_NTS, NULL, conn);
4600
snprintf(tables_query, sizeof(tables_query), "SELECT pt.tgargs, "
4602
" pt.tgdeferrable, "
4603
" pt.tginitdeferred, "
4609
" pt.tgconstrname, pn1.nspname "
4610
"FROM pg_catalog.pg_class pc, "
4611
" pg_catalog.pg_class pc1, "
4612
" pg_catalog.pg_proc pp, "
4613
" pg_catalog.pg_proc pp1, "
4614
" pg_catalog.pg_proc pp2, "
4615
" pg_catalog.pg_trigger pt, "
4616
" pg_catalog.pg_trigger pt1, "
4617
" pg_catalog.pg_trigger pt2, "
4618
" pg_catalog.pg_namespace pn, "
4619
" pg_catalog.pg_namespace pn1 "
4620
"WHERE pc.relname %s'%s' "
4621
" AND pn.nspname %s'%s' "
4622
" AND pc.relnamespace = pn.oid "
4623
" AND pt.tgconstrrelid = pc.oid "
4624
" AND pp.oid = pt.tgfoid "
4625
" AND pp.proname Like '%%ins' "
4626
" AND pt1.tgconstrname = pt.tgconstrname "
4627
" AND pt1.tgconstrrelid = pt.tgrelid "
4628
" AND pt1.tgrelid = pc.oid "
4629
" AND pc1.oid = pt.tgrelid "
4630
" AND pp1.oid = pt1.tgfoid "
4631
" AND pp1.proname like '%%upd' "
4632
" AND (pp1.proname not like '%%check%%') "
4633
" AND pt2.tgconstrname = pt.tgconstrname "
4634
" AND pt2.tgconstrrelid = pt.tgrelid "
4635
" AND pt2.tgrelid = pc.oid "
4636
" AND pp2.oid = pt2.tgfoid "
4637
" AND pp2.proname Like '%%del' "
4638
" AND pn1.oid = pc1.relnamespace "
4639
" order by pt.tgconstrname",
4640
eq_string, escPkTableName, eq_string, escSchemaName);
4641
free(escSchemaName);
4644
snprintf(tables_query, sizeof(tables_query), "SELECT pt.tgargs, "
4646
" pt.tgdeferrable, "
4647
" pt.tginitdeferred, "
4652
" pc1.relname, pt.tgconstrname "
4653
"FROM pg_class pc, "
4661
"WHERE pc.relname %s'%s' "
4662
" AND pt.tgconstrrelid = pc.oid "
4663
" AND pp.oid = pt.tgfoid "
4664
" AND pp.proname Like '%%ins' "
4665
" AND pt1.tgconstrname = pt.tgconstrname "
4666
" AND pt1.tgconstrrelid = pt.tgrelid "
4667
" AND pt1.tgrelid = pc.oid "
4668
" AND pc1.oid = pt.tgrelid "
4669
" AND pp1.oid = pt1.tgfoid "
4670
" AND pp1.proname like '%%upd' "
4671
" AND pp1.(proname not like '%%check%%') "
4672
" AND pt2.tgconstrname = pt.tgconstrname "
4673
" AND pt2.tgconstrrelid = pt.tgrelid "
4674
" AND pt2.tgrelid = pc.oid "
4675
" AND pp2.oid = pt2.tgfoid "
4676
" AND pp2.proname Like '%%del'"
4677
" order by pt.tgconstrname",
4678
eq_string, escPkTableName);
4680
result = PGAPI_ExecDirect(htbl_stmt, tables_query, SQL_NTS, 0);
4681
if (!SQL_SUCCEEDED(result))
4683
SC_error_copy(stmt, tbl_stmt, TRUE);
4687
result = PGAPI_BindCol(htbl_stmt, 1, SQL_C_BINARY,
4688
trig_args, sizeof(trig_args), NULL);
4689
if (!SQL_SUCCEEDED(result))
4691
SC_error_copy(stmt, tbl_stmt, TRUE);
4695
result = PGAPI_BindCol(htbl_stmt, 2, SQL_C_SHORT,
4696
&trig_nargs, 0, NULL);
4697
if (!SQL_SUCCEEDED(result))
4699
SC_error_copy(stmt, tbl_stmt, TRUE);
4703
result = PGAPI_BindCol(htbl_stmt, 3, internal_asis_type,
4704
trig_deferrable, sizeof(trig_deferrable), NULL);
4705
if (!SQL_SUCCEEDED(result))
4707
SC_error_copy(stmt, tbl_stmt, TRUE);
4711
result = PGAPI_BindCol(htbl_stmt, 4, internal_asis_type,
4712
trig_initdeferred, sizeof(trig_initdeferred), NULL);
4713
if (!SQL_SUCCEEDED(result))
4715
SC_error_copy(stmt, tbl_stmt, TRUE);
4719
result = PGAPI_BindCol(htbl_stmt, 5, internal_asis_type,
4720
upd_rule, sizeof(upd_rule), NULL);
4721
if (!SQL_SUCCEEDED(result))
4723
SC_error_copy(stmt, tbl_stmt, TRUE);
4727
result = PGAPI_BindCol(htbl_stmt, 6, internal_asis_type,
4728
del_rule, sizeof(del_rule), NULL);
4729
if (!SQL_SUCCEEDED(result))
4731
SC_error_copy(stmt, tbl_stmt, TRUE);
4735
result = PGAPI_BindCol(htbl_stmt, 7, SQL_C_ULONG,
4736
&relid1, sizeof(relid1), NULL);
4737
if (!SQL_SUCCEEDED(result))
4739
SC_error_copy(stmt, tbl_stmt, TRUE);
4742
result = PGAPI_BindCol(htbl_stmt, 8, SQL_C_ULONG,
4743
&relid2, sizeof(relid2), NULL);
4744
if (!SQL_SUCCEEDED(result))
4746
SC_error_copy(stmt, tbl_stmt, TRUE);
4749
result = PGAPI_BindCol(htbl_stmt, 9, internal_asis_type,
4750
fk_table_fetched, TABLE_NAME_STORAGE_LEN, NULL);
4751
if (!SQL_SUCCEEDED(result))
4753
SC_error_copy(stmt, tbl_stmt, TRUE);
4756
result = PGAPI_BindCol(htbl_stmt, 10, internal_asis_type,
4757
constrname, NAMESTORAGELEN, NULL);
4758
if (!SQL_SUCCEEDED(result))
4760
SC_error_copy(stmt, tbl_stmt, TRUE);
4764
if (conn->schema_support)
4766
result = PGAPI_BindCol(htbl_stmt, 11, internal_asis_type,
4767
schema_fetched, SCHEMA_NAME_STORAGE_LEN, NULL);
4768
if (!SQL_SUCCEEDED(result))
4770
SC_error_copy(stmt, tbl_stmt, TRUE);
4775
result = PGAPI_Fetch(htbl_stmt);
4776
if (result == SQL_NO_DATA_FOUND)
4782
if (result != SQL_SUCCESS)
4784
SC_full_error_copy(stmt, tbl_stmt, FALSE);
4791
keyresult = PGAPI_AllocStmt(conn, &hpkey_stmt, 0);
4792
if (!SQL_SUCCEEDED(keyresult))
4794
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate statement for PGAPI_ForeignKeys (pkeys) result.", func);
4797
keyresult = PGAPI_BindCol(hpkey_stmt, 6, internal_asis_type,
4798
pkname, sizeof(pkname), NULL);
4799
if (keyresult != SQL_SUCCESS)
4801
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't bindcol for primary keys for PGAPI_ForeignKeys result.", func);
4804
keyresult = PGAPI_PrimaryKeys(hpkey_stmt, NULL, 0, schema_needed, SQL_NTS, pk_table_needed, SQL_NTS, 0);
4805
if (keyresult != SQL_SUCCESS)
4807
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't get primary keys for PGAPI_ForeignKeys result.", func);
4811
keyresult = PGAPI_Fetch(hpkey_stmt);
4812
PGAPI_FreeStmt(hpkey_stmt, SQL_CLOSE);
4813
while (result == SQL_SUCCESS)
4815
/* Calculate the number of key parts */
4816
num_keys = (trig_nargs - 4) / 2;;
4818
/* Handle action (i.e., 'cascade', 'restrict', 'setnull') */
4819
if (!strcmp(upd_rule, "RI_FKey_cascade_upd"))
4820
upd_rule_type = SQL_CASCADE;
4821
else if (!strcmp(upd_rule, "RI_FKey_noaction_upd"))
4822
upd_rule_type = SQL_NO_ACTION;
4823
else if (!strcmp(upd_rule, "RI_FKey_restrict_upd"))
4824
upd_rule_type = SQL_NO_ACTION;
4825
else if (!strcmp(upd_rule, "RI_FKey_setdefault_upd"))
4826
upd_rule_type = SQL_SET_DEFAULT;
4827
else if (!strcmp(upd_rule, "RI_FKey_setnull_upd"))
4828
upd_rule_type = SQL_SET_NULL;
4830
if (!strcmp(del_rule, "RI_FKey_cascade_del"))
4831
del_rule_type = SQL_CASCADE;
4832
else if (!strcmp(del_rule, "RI_FKey_noaction_del"))
4833
del_rule_type = SQL_NO_ACTION;
4834
else if (!strcmp(del_rule, "RI_FKey_restrict_del"))
4835
del_rule_type = SQL_NO_ACTION;
4836
else if (!strcmp(del_rule, "RI_FKey_setdefault_del"))
4837
del_rule_type = SQL_SET_DEFAULT;
4838
else if (!strcmp(del_rule, "RI_FKey_setnull_del"))
4839
del_rule_type = SQL_SET_NULL;
4841
#if (ODBCVER >= 0x0300)
4842
/* Set deferrability type */
4843
if (!strcmp(trig_initdeferred, "y"))
4844
defer_type = SQL_INITIALLY_DEFERRED;
4845
else if (!strcmp(trig_deferrable, "y"))
4846
defer_type = SQL_INITIALLY_IMMEDIATE;
4848
defer_type = SQL_NOT_DEFERRABLE;
4849
#endif /* ODBCVER >= 0x0300 */
4851
mylog("Foreign Key Case#1: trig_nargs = %d, num_keys = %d\n", trig_nargs, num_keys);
4853
/* Get to first primary key */
4854
pkey_ptr = trig_args;
4855
for (i = 0; i < 5; i++)
4856
pkey_ptr += strlen(pkey_ptr) + 1;
4858
/* Get to first foreign key */
4859
fkey_ptr = trig_args;
4860
for (k = 0; k < 4; k++)
4861
fkey_ptr += strlen(fkey_ptr) + 1;
4863
for (k = 0; k < num_keys; k++)
4865
pkey_text = getClientColumnName(conn, relid1, pkey_ptr, &pkey_alloced);
4866
fkey_text = getClientColumnName(conn, relid2, fkey_ptr, &fkey_alloced);
4868
mylog("pkey_ptr = '%s', fk_table = '%s', fkey_ptr = '%s'\n", pkey_text, fk_table_fetched, fkey_text);
4870
tuple = QR_AddNew(res);
4872
mylog("pk_table_needed = '%s', pkey_ptr = '%s'\n", pk_table_needed, pkey_text);
4873
set_tuplefield_string(&tuple[FKS_PKTABLE_CAT], CurrCat(conn));
4874
set_tuplefield_string(&tuple[FKS_PKTABLE_SCHEM], GET_SCHEMA_NAME(schema_needed));
4875
set_tuplefield_string(&tuple[FKS_PKTABLE_NAME], pk_table_needed);
4876
set_tuplefield_string(&tuple[FKS_PKCOLUMN_NAME], pkey_text);
4878
mylog("fk_table = '%s', fkey_ptr = '%s'\n", fk_table_fetched, fkey_text);
4879
set_tuplefield_string(&tuple[FKS_FKTABLE_CAT], CurrCat(conn));
4880
set_tuplefield_string(&tuple[FKS_FKTABLE_SCHEM], GET_SCHEMA_NAME(schema_fetched));
4881
set_tuplefield_string(&tuple[FKS_FKTABLE_NAME], fk_table_fetched);
4882
set_tuplefield_string(&tuple[FKS_FKCOLUMN_NAME], fkey_text);
4884
set_tuplefield_int2(&tuple[FKS_KEY_SEQ], (Int2) (k + 1));
4886
mylog("upd_rule = %d, del_rule= %d", upd_rule_type, del_rule_type);
4887
set_nullfield_int2(&tuple[FKS_UPDATE_RULE], upd_rule_type);
4888
set_nullfield_int2(&tuple[FKS_DELETE_RULE], del_rule_type);
4890
set_tuplefield_string(&tuple[FKS_FK_NAME], constrname);
4891
set_tuplefield_string(&tuple[FKS_PK_NAME], pkname);
4893
set_tuplefield_string(&tuple[FKS_TRIGGER_NAME], trig_args);
4895
#if (ODBCVER >= 0x0300)
4896
mylog(" defer_type = %d\n", defer_type);
4897
set_tuplefield_int2(&tuple[FKS_DEFERRABILITY], defer_type);
4898
#endif /* ODBCVER >= 0x0300 */
4902
pkey_alloced = FALSE;
4905
fkey_alloced = FALSE;
4907
/* next primary/foreign key */
4908
for (j = 0; j < 2; j++)
4910
pkey_ptr += strlen(pkey_ptr) + 1;
4911
fkey_ptr += strlen(fkey_ptr) + 1;
4914
result = PGAPI_Fetch(htbl_stmt);
4919
SC_set_error(stmt, STMT_INTERNAL_ERROR, "No tables specified to PGAPI_ForeignKeys.", func);
4927
* also, things need to think that this statement is finished so the
4928
* results can be retrieved.
4930
stmt->status = STMT_FINISHED;
4936
if (pk_table_needed)
4937
free(pk_table_needed);
4939
free(escPkTableName);
4940
if (fk_table_needed)
4941
free(fk_table_needed);
4943
free(escFkTableName);
4946
PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
4948
PGAPI_FreeStmt(hpkey_stmt, SQL_DROP);
4950
/* set up the current tuple pointer for SQLFetch */
4951
stmt->currTuple = -1;
4952
SC_set_rowset_start(stmt, -1, FALSE);
4953
SC_set_current_col(stmt, -1);
4956
ret = DiscardStatementSvp(stmt, ret, FALSE);
4957
mylog("%s(): EXIT, stmt=%p, ret=%d\n", func, stmt, ret);
4964
const SQLCHAR FAR * szPkTableQualifier, /* OA X*/
4965
SQLSMALLINT cbPkTableQualifier,
4966
const SQLCHAR FAR * szPkTableOwner, /* OA E*/
4967
SQLSMALLINT cbPkTableOwner,
4968
const SQLCHAR FAR * szPkTableName, /* OA(R) E*/
4969
SQLSMALLINT cbPkTableName,
4970
const SQLCHAR FAR * szFkTableQualifier, /* OA X*/
4971
SQLSMALLINT cbFkTableQualifier,
4972
const SQLCHAR FAR * szFkTableOwner, /* OA E*/
4973
SQLSMALLINT cbFkTableOwner,
4974
const SQLCHAR FAR * szFkTableName, /* OA(R) E*/
4975
SQLSMALLINT cbFkTableName)
4977
ConnectionClass *conn = SC_get_conn(((StatementClass *) hstmt));
4978
if (PG_VERSION_GE(conn, 8.1))
4979
return PGAPI_ForeignKeys_new(hstmt,
4980
szPkTableQualifier, cbPkTableQualifier,
4981
szPkTableOwner, cbPkTableOwner,
4982
szPkTableName, cbPkTableName,
4983
szFkTableQualifier, cbFkTableQualifier,
4984
szFkTableOwner, cbFkTableOwner,
4985
szFkTableName, cbFkTableName);
4987
return PGAPI_ForeignKeys_old(hstmt,
4988
szPkTableQualifier, cbPkTableQualifier,
4989
szPkTableOwner, cbPkTableOwner,
4990
szPkTableName, cbPkTableName,
4991
szFkTableQualifier, cbFkTableQualifier,
4992
szFkTableOwner, cbFkTableOwner,
4993
szFkTableName, cbFkTableName);
4997
#define PRORET_COUNT
4998
#define DISPLAY_ARGNAME
5000
PGAPI_ProcedureColumns(
5002
const SQLCHAR FAR * szProcQualifier, /* OA X*/
5003
SQLSMALLINT cbProcQualifier,
5004
const SQLCHAR FAR * szProcOwner, /* PV E*/
5005
SQLSMALLINT cbProcOwner,
5006
const SQLCHAR FAR * szProcName, /* PV E*/
5007
SQLSMALLINT cbProcName,
5008
const SQLCHAR FAR * szColumnName, /* PV X*/
5009
SQLSMALLINT cbColumnName,
5012
CSTR func = "PGAPI_ProcedureColumns";
5013
StatementClass *stmt = (StatementClass *) hstmt;
5014
ConnectionClass *conn = SC_get_conn(stmt);
5015
char proc_query[INFO_INQUIRY_LEN];
5018
char *schema_name, *procname;
5019
char *escSchemaName = NULL, *escProcName = NULL;
5020
char *params, *proargnames, *proargmodes, *delim = NULL;
5021
char *atttypid, *attname, *column_name;
5022
QResultClass *res, *tres;
5025
Int4 paramcount, column_size, i, j;
5027
BOOL search_pattern, bRetset;
5028
const char *like_or_eq, *op_string, *retset;
5029
int ret_col = -1, ext_pos = -1, poid_pos = -1, attid_pos = -1, attname_pos = -1;
5030
UInt4 poid = 0, newpoid;
5032
mylog("%s: entering...\n", func);
5034
if (PG_VERSION_LT(conn, 6.5))
5036
SC_set_error(stmt, STMT_NOT_IMPLEMENTED_ERROR, "Version is too old", func);
5039
if (result = SC_initialize_and_recycle(stmt), SQL_SUCCESS != result)
5041
search_pattern = (0 == (flag & PODBC_NOT_SEARCH_PATTERN));
5044
like_or_eq = likeop;
5045
escSchemaName = adjustLikePattern(szProcOwner, cbProcOwner, SEARCH_PATTERN_ESCAPE, NULL, conn);
5046
escProcName = adjustLikePattern(szProcName, cbProcName, SEARCH_PATTERN_ESCAPE, NULL, conn);
5051
escSchemaName = simpleCatalogEscape(szProcOwner, cbProcOwner, NULL, conn);
5052
escProcName = simpleCatalogEscape(szProcName, cbProcName, NULL, conn);
5054
op_string = gen_opestr(like_or_eq, conn);
5055
if (conn->schema_support)
5057
strcpy(proc_query, "select proname, proretset, prorettype, "
5058
"pronargs, proargtypes, nspname, p.oid");
5059
ret_col = ext_pos = 7;
5062
strcat(proc_query, ", atttypid, attname");
5063
attid_pos = ext_pos;
5064
attname_pos = ext_pos + 1;
5067
#endif /* PRORET_COUNT */
5068
if (PG_VERSION_GE(conn, 8.0))
5070
strcat(proc_query, ", proargnames");
5073
if (PG_VERSION_GE(conn, 8.1))
5075
strcat(proc_query, ", proargmodes, proallargtypes");
5079
strcat(proc_query, " from ((pg_catalog.pg_namespace n inner join"
5080
" pg_catalog.pg_proc p on p.pronamespace = n.oid)"
5081
" inner join pg_type t on t.oid = p.prorettype)"
5082
" left outer join pg_attribute a on a.attrelid = t.typrelid "
5083
" and attnum > 0 and not attisdropped where");
5085
strcat(proc_query, " from pg_catalog.pg_namespace n,"
5086
" pg_catalog.pg_proc p where");
5087
" p.pronamespace = n.oid and"
5088
" (not proretset) and");
5089
#endif /* PRORET_COUNT */
5090
strcat(proc_query, " has_function_privilege(p.oid, 'EXECUTE')");
5091
my_strcat1(proc_query, " and nspname %s'%.*s'", op_string, escSchemaName, SQL_NTS);
5093
snprintf_add(proc_query, sizeof(proc_query), " and proname %s'%s'", op_string, escProcName);
5094
strcat(proc_query, " order by nspname, proname, p.oid, attnum");
5098
strcpy(proc_query, "select proname, proretset, prorettype, "
5099
"pronargs, proargtypes from pg_proc where "
5103
snprintf_add(proc_query, sizeof(proc_query), " and proname %s'%s'", op_string, escProcName);
5104
strcat(proc_query, " order by proname, proretset");
5106
if (tres = CC_send_query(conn, proc_query, NULL, IGNORE_ABORT_ON_CONN, stmt), !QR_command_maybe_successful(tres))
5108
SC_set_error(stmt, STMT_EXEC_ERROR, "PGAPI_ProcedureColumns query error", func);
5109
QR_Destructor(tres);
5113
if (res = QR_Constructor(), !res)
5115
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate memory for PGAPI_ProcedureColumns result.", func);
5118
SC_set_Result(stmt, res);
5121
* the binding structure for a statement is not set up until
5122
* a statement is actually executed, so we'll have to do this
5125
result_cols = NUM_OF_PROCOLS_FIELDS;
5126
extend_column_bindings(SC_get_ARDF(stmt), result_cols);
5128
stmt->catalog_result = TRUE;
5129
/* set the field names */
5130
QR_set_num_fields(res, result_cols);
5131
QR_set_field_info_v(res, PROCOLS_PROCEDURE_CAT, "PROCEDURE_CAT", PG_TYPE_VARCHAR, MAX_INFO_STRING);
5132
QR_set_field_info_v(res, PROCOLS_PROCEDURE_SCHEM, "PROCEDUR_SCHEM", PG_TYPE_VARCHAR, MAX_INFO_STRING);
5133
QR_set_field_info_v(res, PROCOLS_PROCEDURE_NAME, "PROCEDURE_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
5134
QR_set_field_info_v(res, PROCOLS_COLUMN_NAME, "COLUMN_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
5135
QR_set_field_info_v(res, PROCOLS_COLUMN_TYPE, "COLUMN_TYPE", PG_TYPE_INT2, 2);
5136
QR_set_field_info_v(res, PROCOLS_DATA_TYPE, "DATA_TYPE", PG_TYPE_INT2, 2);
5137
QR_set_field_info_v(res, PROCOLS_TYPE_NAME, "TYPE_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
5138
QR_set_field_info_v(res, PROCOLS_COLUMN_SIZE, "COLUMN_SIZE", PG_TYPE_INT4, 4);
5139
QR_set_field_info_v(res, PROCOLS_BUFFER_LENGTH, "BUFFER_LENGTH", PG_TYPE_INT4, 4);
5140
QR_set_field_info_v(res, PROCOLS_DECIMAL_DIGITS, "DECIMAL_DIGITS", PG_TYPE_INT2, 2);
5141
QR_set_field_info_v(res, PROCOLS_NUM_PREC_RADIX, "NUM_PREC_RADIX", PG_TYPE_INT2, 2);
5142
QR_set_field_info_v(res, PROCOLS_NULLABLE, "NULLABLE", PG_TYPE_INT2, 2);
5143
QR_set_field_info_v(res, PROCOLS_REMARKS, "REMARKS", PG_TYPE_VARCHAR, MAX_INFO_STRING);
5144
#if (ODBCVER >= 0x0300)
5145
QR_set_field_info_v(res, PROCOLS_COLUMN_DEF, "COLUMN_DEF", PG_TYPE_VARCHAR, MAX_INFO_STRING);
5146
QR_set_field_info_v(res, PROCOLS_SQL_DATA_TYPE, "SQL_DATA_TYPE", PG_TYPE_INT2, 2);
5147
QR_set_field_info_v(res, PROCOLS_SQL_DATETIME_SUB, "SQL_DATETIME_SUB", PG_TYPE_INT2, 2);
5148
QR_set_field_info_v(res, PROCOLS_CHAR_OCTET_LENGTH, "CHAR_OCTET_LENGTH", PG_TYPE_INT4, 4);
5149
QR_set_field_info_v(res, PROCOLS_ORDINAL_POSITION, "ORDINAL_POSITION", PG_TYPE_INT4, 4);
5150
QR_set_field_info_v(res, PROCOLS_IS_NULLABLE, "IS_NULLABLE", PG_TYPE_VARCHAR, MAX_INFO_STRING);
5151
#endif /* ODBCVER >= 0x0300 */
5153
column_name = make_string(szColumnName, cbColumnName, NULL, 0);
5154
if (column_name) /* column_name is unavailable now */
5160
tcount = QR_get_num_total_tuples(tres);
5161
for (i = 0, poid = 0; i < tcount; i++)
5163
if (conn->schema_support)
5164
schema_name = GET_SCHEMA_NAME(QR_get_value_backend_text(tres, i, 5));
5167
procname = QR_get_value_backend_text(tres, i, 0);
5168
retset = QR_get_value_backend_text(tres, i, 1);
5169
pgtype = QR_get_value_backend_int(tres, i, 2, NULL);
5170
bRetset = retset && (retset[0] == 't' || retset[0] == 'y');
5173
newpoid = QR_get_value_backend_int(tres, i, poid_pos, NULL);
5174
mylog("newpoid=%d\n", newpoid);
5178
atttypid = QR_get_value_backend_text(tres, i, attid_pos);
5179
mylog("atttypid=%s\n", atttypid ? atttypid : "(null)");
5181
if (poid == 0 || newpoid != poid)
5188
#ifdef DISPLAY_ARGNAME /* !! named parameter is unavailable !! */
5189
if (PG_VERSION_GE(conn, 8.0))
5190
proargnames = QR_get_value_backend_text(tres, i, ext_pos);
5191
#endif /* DISPLAY_ARGNAME */
5192
if (PG_VERSION_GE(conn, 8.1))
5193
proargmodes = QR_get_value_backend_text(tres, i, ext_pos + 1);
5195
/* RETURN_VALUE info */
5196
if (0 != pgtype && PG_TYPE_VOID != pgtype && !bRetset && !atttypid && !proargmodes)
5198
tuple = QR_AddNew(res);
5199
set_tuplefield_string(&tuple[PROCOLS_PROCEDURE_CAT], CurrCat(conn));
5200
set_nullfield_string(&tuple[PROCOLS_PROCEDURE_SCHEM], schema_name);
5201
set_tuplefield_string(&tuple[PROCOLS_PROCEDURE_NAME], procname);
5202
set_tuplefield_string(&tuple[PROCOLS_COLUMN_NAME], NULL_STRING);
5203
set_tuplefield_int2(&tuple[PROCOLS_COLUMN_TYPE], SQL_RETURN_VALUE);
5204
set_tuplefield_int2(&tuple[PROCOLS_DATA_TYPE], pgtype_to_concise_type(stmt, pgtype, PG_STATIC));
5205
set_tuplefield_string(&tuple[PROCOLS_TYPE_NAME], pgtype_to_name(stmt, pgtype, PG_UNSPECIFIED, FALSE));
5206
column_size = pgtype_column_size(stmt, pgtype, PG_STATIC, UNKNOWNS_AS_DEFAULT);
5207
set_nullfield_int4(&tuple[PROCOLS_COLUMN_SIZE], column_size);
5208
set_tuplefield_int4(&tuple[PROCOLS_BUFFER_LENGTH], pgtype_buffer_length(stmt, pgtype, PG_STATIC, UNKNOWNS_AS_DEFAULT));
5209
set_nullfield_int2(&tuple[PROCOLS_DECIMAL_DIGITS], pgtype_decimal_digits(stmt, pgtype, PG_STATIC));
5210
set_nullfield_int2(&tuple[PROCOLS_NUM_PREC_RADIX], pgtype_radix(conn, pgtype));
5211
set_tuplefield_int2(&tuple[PROCOLS_NULLABLE], SQL_NULLABLE_UNKNOWN);
5212
set_tuplefield_null(&tuple[PROCOLS_REMARKS]);
5213
#if (ODBCVER >= 0x0300)
5214
set_tuplefield_null(&tuple[PROCOLS_COLUMN_DEF]);
5215
set_nullfield_int2(&tuple[PROCOLS_SQL_DATA_TYPE], pgtype_to_sqldesctype(stmt, pgtype, PG_STATIC));
5216
set_nullfield_int2(&tuple[PROCOLS_SQL_DATETIME_SUB], pgtype_to_datetime_sub(stmt, pgtype, PG_UNSPECIFIED));
5217
set_nullfield_int4(&tuple[PROCOLS_CHAR_OCTET_LENGTH], pgtype_attr_transfer_octet_length(conn, pgtype, PG_UNSPECIFIED, UNKNOWNS_AS_DEFAULT));
5218
set_tuplefield_int4(&tuple[PROCOLS_ORDINAL_POSITION], 0);
5219
set_tuplefield_string(&tuple[PROCOLS_IS_NULLABLE], NULL_STRING);
5220
#endif /* ODBCVER >= 0x0300 */
5227
for (p = proargmodes; *p; p++)
5233
params = QR_get_value_backend_text(tres, i, ext_pos + 2);
5234
if ('{' == *proargmodes)
5241
paramcount = QR_get_value_backend_int(tres, i, 3, NULL);
5242
params = QR_get_value_backend_text(tres, i, 4);
5246
if ('{' == *proargnames)
5249
/* PARAMETERS info */
5250
for (j = 0; j < paramcount; j++)
5252
/* PG type of parameters */
5256
while (isspace(*params) || ',' == *params)
5258
if ('\0' == *params || '}' == *params)
5262
sscanf(params, "%u", &pgtype);
5263
while (isdigit(*params))
5267
/* input/output type of parameters */
5270
while (isspace(*proargmodes) || ',' == *proargmodes)
5272
if ('\0' == *proargmodes || '}' == *proargmodes)
5275
/* name of parameters */
5278
while (isspace(*proargnames) || ',' == *proargnames)
5280
if ('\0' == *proargnames || '}' == *proargnames)
5282
else if ('"' == *proargnames)
5285
for (delim = proargnames; *delim && *delim != '"'; delim++)
5290
for (delim = proargnames; *delim && !isspace(*delim) && ',' != *delim && '}' != *delim; delim++)
5293
if (proargnames && '\0' == *delim) /* discard the incomplete name */
5297
tuple = QR_AddNew(res);
5298
set_tuplefield_string(&tuple[PROCOLS_PROCEDURE_CAT], CurrCat(conn));
5299
set_nullfield_string(&tuple[PROCOLS_PROCEDURE_SCHEM], schema_name);
5300
set_tuplefield_string(&tuple[PROCOLS_PROCEDURE_NAME], procname);
5304
set_tuplefield_string(&tuple[PROCOLS_COLUMN_NAME], proargnames);
5305
proargnames = delim + 1;
5308
set_tuplefield_string(&tuple[PROCOLS_COLUMN_NAME], NULL_STRING);
5313
switch (*proargmodes)
5316
ptype = SQL_PARAM_OUTPUT;
5319
ptype = SQL_PARAM_INPUT_OUTPUT;
5322
ptype = SQL_PARAM_INPUT;
5325
set_tuplefield_int2(&tuple[PROCOLS_COLUMN_TYPE], ptype);
5329
set_tuplefield_int2(&tuple[PROCOLS_COLUMN_TYPE], SQL_PARAM_INPUT);
5330
set_tuplefield_int2(&tuple[PROCOLS_DATA_TYPE], pgtype_to_concise_type(stmt, pgtype, PG_STATIC));
5331
set_tuplefield_string(&tuple[PROCOLS_TYPE_NAME], pgtype_to_name(stmt, pgtype, PG_UNSPECIFIED, FALSE));
5332
column_size = pgtype_column_size(stmt, pgtype, PG_STATIC, UNKNOWNS_AS_DEFAULT);
5333
set_nullfield_int4(&tuple[PROCOLS_COLUMN_SIZE], column_size);
5334
set_tuplefield_int4(&tuple[PROCOLS_BUFFER_LENGTH], pgtype_buffer_length(stmt, pgtype, PG_STATIC, UNKNOWNS_AS_DEFAULT));
5335
set_nullfield_int2(&tuple[PROCOLS_DECIMAL_DIGITS], pgtype_decimal_digits(stmt, pgtype, PG_STATIC));
5336
set_nullfield_int2(&tuple[PROCOLS_NUM_PREC_RADIX], pgtype_radix(conn, pgtype));
5337
set_tuplefield_int2(&tuple[PROCOLS_NULLABLE], SQL_NULLABLE_UNKNOWN);
5338
set_tuplefield_null(&tuple[PROCOLS_REMARKS]);
5339
#if (ODBCVER >= 0x0300)
5340
set_tuplefield_null(&tuple[PROCOLS_COLUMN_DEF]);
5341
set_nullfield_int2(&tuple[PROCOLS_SQL_DATA_TYPE], pgtype_to_sqldesctype(stmt, pgtype, PG_STATIC));
5342
set_nullfield_int2(&tuple[PROCOLS_SQL_DATETIME_SUB], pgtype_to_datetime_sub(stmt, pgtype, PG_UNSPECIFIED));
5343
set_nullfield_int4(&tuple[PROCOLS_CHAR_OCTET_LENGTH], pgtype_attr_transfer_octet_length(conn, pgtype, PG_UNSPECIFIED, UNKNOWNS_AS_DEFAULT));
5344
set_tuplefield_int4(&tuple[PROCOLS_ORDINAL_POSITION], j + 1);
5345
set_tuplefield_string(&tuple[PROCOLS_IS_NULLABLE], NULL_STRING);
5346
#endif /* ODBCVER >= 0x0300 */
5349
/* RESULT Columns info */
5350
if (NULL != atttypid || bRetset)
5361
typid = atoi(atttypid);
5362
attname = QR_get_value_backend_text(tres, i, attname_pos);
5364
tuple = QR_AddNew(res);
5365
set_tuplefield_string(&tuple[PROCOLS_PROCEDURE_CAT], CurrCat(conn));
5366
set_nullfield_string(&tuple[PROCOLS_PROCEDURE_SCHEM], schema_name);
5367
set_tuplefield_string(&tuple[PROCOLS_PROCEDURE_NAME], procname);
5368
set_tuplefield_string(&tuple[PROCOLS_COLUMN_NAME], attname);
5369
set_tuplefield_int2(&tuple[PROCOLS_COLUMN_TYPE], SQL_RESULT_COL);
5370
set_tuplefield_int2(&tuple[PROCOLS_DATA_TYPE], pgtype_to_concise_type(stmt, typid, PG_STATIC));
5371
set_tuplefield_string(&tuple[PROCOLS_TYPE_NAME], pgtype_to_name(stmt, typid, PG_UNSPECIFIED, FALSE));
5372
column_size = pgtype_column_size(stmt, typid, PG_STATIC, UNKNOWNS_AS_DEFAULT);
5373
set_nullfield_int4(&tuple[PROCOLS_COLUMN_SIZE], column_size);
5374
set_tuplefield_int4(&tuple[PROCOLS_BUFFER_LENGTH], pgtype_buffer_length(stmt, typid, PG_STATIC, UNKNOWNS_AS_DEFAULT));
5375
set_nullfield_int2(&tuple[PROCOLS_DECIMAL_DIGITS], pgtype_decimal_digits(stmt, typid, PG_STATIC));
5376
set_nullfield_int2(&tuple[PROCOLS_NUM_PREC_RADIX], pgtype_radix(conn, typid));
5377
set_tuplefield_int2(&tuple[PROCOLS_NULLABLE], SQL_NULLABLE_UNKNOWN);
5378
set_tuplefield_null(&tuple[PROCOLS_REMARKS]);
5379
#if (ODBCVER >= 0x0300)
5380
set_tuplefield_null(&tuple[PROCOLS_COLUMN_DEF]);
5381
set_nullfield_int2(&tuple[PROCOLS_SQL_DATA_TYPE], pgtype_to_sqldesctype(stmt, typid, PG_STATIC));
5382
set_nullfield_int2(&tuple[PROCOLS_SQL_DATETIME_SUB], pgtype_to_datetime_sub(stmt, typid, PG_UNSPECIFIED));
5383
set_nullfield_int4(&tuple[PROCOLS_CHAR_OCTET_LENGTH], pgtype_attr_transfer_octet_length(conn, typid, PG_UNSPECIFIED, UNKNOWNS_AS_DEFAULT));
5384
set_tuplefield_int4(&tuple[PROCOLS_ORDINAL_POSITION], 0);
5385
set_tuplefield_string(&tuple[PROCOLS_IS_NULLABLE], NULL_STRING);
5386
#endif /* ODBCVER >= 0x0300 */
5389
QR_Destructor(tres);
5391
* also, things need to think that this statement is finished so the
5392
* results can be retrieved.
5395
free(escSchemaName);
5398
stmt->status = STMT_FINISHED;
5399
/* set up the current tuple pointer for SQLFetch */
5400
stmt->currTuple = -1;
5401
SC_set_rowset_start(stmt, -1, FALSE);
5402
SC_set_current_col(stmt, -1);
5411
const SQLCHAR FAR * szProcQualifier, /* OA X*/
5412
SQLSMALLINT cbProcQualifier,
5413
const SQLCHAR FAR * szProcOwner, /* PV E*/
5414
SQLSMALLINT cbProcOwner,
5415
const SQLCHAR FAR * szProcName, /* PV E*/
5416
SQLSMALLINT cbProcName,
5419
CSTR func = "PGAPI_Procedures";
5420
StatementClass *stmt = (StatementClass *) hstmt;
5421
ConnectionClass *conn = SC_get_conn(stmt);
5422
char proc_query[INFO_INQUIRY_LEN];
5423
char *escSchemaName = NULL, *escProcName = NULL;
5426
const char *like_or_eq, *op_string;
5427
BOOL search_pattern;
5429
mylog("%s: entering... scnm=%p len=%d\n", func, szProcOwner, cbProcOwner);
5431
if (PG_VERSION_LT(conn, 6.5))
5433
SC_set_error(stmt, STMT_NOT_IMPLEMENTED_ERROR, "Version is too old", func);
5436
if (result = SC_initialize_and_recycle(stmt), SQL_SUCCESS != result)
5439
search_pattern = (0 == (flag & PODBC_NOT_SEARCH_PATTERN));
5442
like_or_eq = likeop;
5443
escSchemaName = adjustLikePattern(szProcOwner, cbProcOwner, SEARCH_PATTERN_ESCAPE, NULL, conn);
5444
escProcName = adjustLikePattern(szProcName, cbProcName, SEARCH_PATTERN_ESCAPE, NULL, conn);
5449
escSchemaName = simpleCatalogEscape(szProcOwner, cbProcOwner, NULL, conn);
5450
escProcName = simpleCatalogEscape(szProcName, cbProcName, NULL, conn);
5453
* The following seems the simplest implementation
5455
op_string = gen_opestr(like_or_eq, conn);
5456
if (conn->schema_support)
5458
strcpy(proc_query, "select '' as " "PROCEDURE_CAT" ", nspname as " "PROCEDURE_SCHEM" ","
5459
" proname as " "PROCEDURE_NAME" ", '' as " "NUM_INPUT_PARAMS" ","
5460
" '' as " "NUM_OUTPUT_PARAMS" ", '' as " "NUM_RESULT_SETS" ","
5461
" '' as " "REMARKS" ","
5462
" case when prorettype = 0 then 1::int2 else 2::int2 end"
5463
" as " "PROCEDURE_TYPE" " from pg_catalog.pg_namespace,"
5464
" pg_catalog.pg_proc"
5465
" where pg_proc.pronamespace = pg_namespace.oid");
5466
schema_strcat1(proc_query, " and nspname %s'%.*s'", op_string, escSchemaName, SQL_NTS, szProcName, cbProcName, conn);
5467
my_strcat1(proc_query, " and proname %s'%.*s'", op_string, escProcName, SQL_NTS);
5471
strcpy(proc_query, "select '' as " "PROCEDURE_CAT" ", '' as " "PROCEDURE_SCHEM" ","
5472
" proname as " "PROCEDURE_NAME" ", '' as " "NUM_INPUT_PARAMS" ","
5473
" '' as " "NUM_OUTPUT_PARAMS" ", '' as " "NUM_RESULT_SETS" ","
5474
" '' as " "REMARKS" ","
5475
" case when prorettype = 0 then 1::int2 else 2::int2 end as " "PROCEDURE_TYPE" " from pg_proc");
5476
my_strcat1(proc_query, " where proname %s'%.*s'", op_string, escSchemaName, SQL_NTS);
5479
if (res = CC_send_query(conn, proc_query, NULL, IGNORE_ABORT_ON_CONN, stmt), !QR_command_maybe_successful(res))
5481
SC_set_error(stmt, STMT_EXEC_ERROR, "PGAPI_Procedures query error", func);
5485
SC_set_Result(stmt, res);
5488
* also, things need to think that this statement is finished so the
5489
* results can be retrieved.
5491
stmt->status = STMT_FINISHED;
5492
extend_column_bindings(SC_get_ARDF(stmt), 8);
5494
free(escSchemaName);
5497
/* set up the current tuple pointer for SQLFetch */
5498
stmt->currTuple = -1;
5499
SC_set_rowset_start(stmt, -1, FALSE);
5500
SC_set_current_col(stmt, -1);
5507
#define ALL_PRIVILIGES "arwdRxt"
5509
usracl_auth(char *usracl, const char *auth)
5511
int i, j, addcnt = 0;
5513
for (i = 0; auth[i]; i++)
5515
for (j = 0; j < ACLMAX; j++)
5517
if (usracl[j] == auth[i])
5519
else if (!usracl[j])
5530
useracl_upd(char (*useracl)[ACLMAX], QResultClass *allures, const char *user, const char *auth)
5532
int usercount = (int) QR_get_num_cached_tuples(allures), i, addcnt = 0;
5534
mylog("user=%s auth=%s\n", user, auth);
5536
for (i = 0; i < usercount; i++)
5538
if (strcmp(QR_get_value_backend_text(allures, i, 0), user) == 0)
5540
addcnt += usracl_auth(useracl[i], auth);
5545
for (i = 0; i < usercount; i++)
5547
addcnt += usracl_auth(useracl[i], auth);
5549
mylog("addcnt=%d\n", addcnt);
5553
PGAPI_TablePrivileges(
5555
const SQLCHAR FAR * szTableQualifier, /* OA X*/
5556
SQLSMALLINT cbTableQualifier,
5557
const SQLCHAR FAR * szTableOwner, /* PV E*/
5558
SQLSMALLINT cbTableOwner,
5559
const SQLCHAR FAR * szTableName, /* PV E*/
5560
SQLSMALLINT cbTableName,
5563
StatementClass *stmt = (StatementClass *) hstmt;
5564
CSTR func = "PGAPI_TablePrivileges";
5565
ConnectionClass *conn = SC_get_conn(stmt);
5567
char proc_query[INFO_INQUIRY_LEN];
5568
QResultClass *res, *wres = NULL, *allures = NULL;
5570
Int4 tablecount, usercount, i, j, k;
5571
BOOL grpauth, sys, su;
5572
char (*useracl)[ACLMAX] = NULL, *acl, *user, *delim, *auth;
5573
const char *reln, *owner, *priv, *schnm = NULL;
5574
RETCODE result, ret = SQL_SUCCESS;
5575
const char *like_or_eq, *op_string;
5576
const char *szSchemaName;
5577
SQLSMALLINT cbSchemaName;
5578
char *escSchemaName = NULL, *escTableName = NULL;
5579
BOOL search_pattern;
5581
mylog("%s: entering... scnm=%p len-%d\n", func, szTableOwner, cbTableOwner);
5582
if (result = SC_initialize_and_recycle(stmt), SQL_SUCCESS != result)
5586
* a statement is actually executed, so we'll have to do this
5590
extend_column_bindings(SC_get_ARDF(stmt), result_cols);
5592
stmt->catalog_result = TRUE;
5593
/* set the field names */
5594
res = QR_Constructor();
5595
SC_set_Result(stmt, res);
5596
QR_set_num_fields(res, result_cols);
5597
QR_set_field_info_v(res, 0, "TABLE_CAT", PG_TYPE_VARCHAR, MAX_INFO_STRING);
5598
QR_set_field_info_v(res, 1, "TABLE_SCHEM", PG_TYPE_VARCHAR, MAX_INFO_STRING);
5599
QR_set_field_info_v(res, 2, "TABLE_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
5600
QR_set_field_info_v(res, 3, "GRANTOR", PG_TYPE_VARCHAR, MAX_INFO_STRING);
5601
QR_set_field_info_v(res, 4, "GRANTEE", PG_TYPE_VARCHAR, MAX_INFO_STRING);
5602
QR_set_field_info_v(res, 5, "PRIVILEGE", PG_TYPE_VARCHAR, MAX_INFO_STRING);
5603
QR_set_field_info_v(res, 6, "IS_GRANTABLE", PG_TYPE_VARCHAR, MAX_INFO_STRING);
5606
* also, things need to think that this statement is finished so the
5607
* results can be retrieved.
5609
stmt->status = STMT_FINISHED;
5610
/* set up the current tuple pointer for SQLFetch */
5611
stmt->currTuple = -1;
5612
SC_set_rowset_start(stmt, -1, FALSE);
5613
SC_set_current_col(stmt, -1);
5614
szSchemaName = szTableOwner;
5615
cbSchemaName = cbTableOwner;
5617
#define return DONT_CALL_RETURN_FROM_HERE???
5618
search_pattern = (0 == (flag & PODBC_NOT_SEARCH_PATTERN));
5621
like_or_eq = likeop;
5622
escTableName = adjustLikePattern(szTableName, cbTableName, SEARCH_PATTERN_ESCAPE, NULL, conn);
5627
escTableName = simpleCatalogEscape(szTableName, cbTableName, NULL, conn);
5630
retry_public_schema:
5632
free(escSchemaName);
5634
escSchemaName = adjustLikePattern(szSchemaName, cbSchemaName, SEARCH_PATTERN_ESCAPE, NULL, conn);
5636
escSchemaName = simpleCatalogEscape(szSchemaName, cbSchemaName, NULL, conn);
5638
op_string = gen_opestr(like_or_eq, conn);
5639
if (conn->schema_support)
5640
strncpy_null(proc_query, "select relname, usename, relacl, nspname"
5641
" from pg_catalog.pg_namespace, pg_catalog.pg_class ,"
5642
" pg_catalog.pg_user where", sizeof(proc_query));
5644
strncpy_null(proc_query, "select relname, usename, relacl"
5645
" from pg_class , pg_user where", sizeof(proc_query));
5646
if (conn->schema_support)
5649
schema_strcat1(proc_query, " nspname %s'%.*s' and", op_string, escSchemaName, SQL_NTS, szTableName, cbTableName, conn);
5652
snprintf_add(proc_query, sizeof(proc_query), " relname %s'%s' and", op_string, escTableName);
5653
if (conn->schema_support)
5655
strcat(proc_query, " pg_namespace.oid = relnamespace and relkind in ('r', 'v') and");
5656
if ((!escTableName) && (!escSchemaName))
5657
strcat(proc_query, " nspname not in ('pg_catalog', 'information_schema') and");
5659
strcat(proc_query, " pg_user.usesysid = relowner");
5660
if (wres = CC_send_query(conn, proc_query, NULL, IGNORE_ABORT_ON_CONN, stmt), !QR_command_maybe_successful(wres))
5662
SC_set_error(stmt, STMT_EXEC_ERROR, "PGAPI_TablePrivileges query error", func);
5666
tablecount = (Int4) QR_get_num_cached_tuples(wres);
5668
if (conn->schema_support &&
5669
(flag & PODBC_SEARCH_PUBLIC_SCHEMA) != 0 &&
5672
if (allow_public_schema(conn, szSchemaName, cbSchemaName))
5674
QR_Destructor(wres);
5676
szSchemaName = pubstr;
5677
cbSchemaName = SQL_NTS;
5678
goto retry_public_schema;
5682
strncpy_null(proc_query, "select usename, usesysid, usesuper from pg_user", sizeof(proc_query));
5683
if (allures = CC_send_query(conn, proc_query, NULL, IGNORE_ABORT_ON_CONN, stmt), !QR_command_maybe_successful(allures))
5685
SC_set_error(stmt, STMT_EXEC_ERROR, "PGAPI_TablePrivileges query error", func);
5689
usercount = (Int4) QR_get_num_cached_tuples(allures);
5690
useracl = (char (*)[ACLMAX]) malloc(usercount * sizeof(char [ACLMAX]));
5691
for (i = 0; i < tablecount; i++)
5693
memset(useracl, 0, usercount * sizeof(char[ACLMAX]));
5694
acl = (char *) QR_get_value_backend_text(wres, i, 2);
5695
if (acl && acl[0] == '{')
5699
for (; user && *user;)
5702
if (user[0] == '"' && strncmp(user + 1, "group ", 6) == 0)
5707
if (delim = strchr(user, '='), !delim)
5713
if (delim = strchr(auth, '"'), delim)
5719
else if (delim = strchr(auth, ','), delim)
5721
else if (delim = strchr(auth, '}'), delim)
5723
if (grpauth) /* handle group privilege */
5727
char *grolist, *uid, *delm;
5729
snprintf(proc_query, sizeof(proc_query) - 1, "select grolist from pg_group where groname = '%s'", user);
5730
if (gres = CC_send_query(conn, proc_query, NULL, IGNORE_ABORT_ON_CONN, stmt), !QR_command_maybe_successful(gres))
5732
grolist = QR_get_value_backend_text(gres, 0, 0);
5733
if (grolist && grolist[0] == '{')
5735
for (uid = grolist + 1; *uid;)
5737
if (delm = strchr(uid, ','), delm)
5739
else if (delm = strchr(uid, '}'), delm)
5741
mylog("guid=%s\n", uid);
5742
for (i = 0; i < usercount; i++)
5744
if (strcmp(QR_get_value_backend_text(allures, i, 1), uid) == 0)
5745
useracl_upd(useracl, allures, QR_get_value_backend_text(allures, i, 0), auth);
5751
QR_Destructor(gres);
5754
useracl_upd(useracl, allures, user, auth);
5759
reln = QR_get_value_backend_text(wres, i, 0);
5760
owner = QR_get_value_backend_text(wres, i, 1);
5761
if (conn->schema_support)
5762
schnm = QR_get_value_backend_text(wres, i, 3);
5763
/* The owner has all privileges */
5764
useracl_upd(useracl, allures, owner, ALL_PRIVILIGES);
5765
for (j = 0; j < usercount; j++)
5767
user = QR_get_value_backend_text(allures, j, 0);
5768
su = (strcmp(QR_get_value_backend_text(allures, j, 2), "t") == 0);
5769
sys = (strcmp(user, owner) == 0);
5770
/* Super user has all privileges */
5772
useracl_upd(useracl, allures, user, ALL_PRIVILIGES);
5773
for (k = 0; k < ACLMAX; k++)
5777
switch (useracl[j][k])
5779
case 'R': /* rule */
5780
case 't': /* trigger */
5783
tuple = QR_AddNew(res);
5784
set_tuplefield_string(&tuple[0], CurrCat(conn));
5785
if (conn->schema_support)
5786
set_tuplefield_string(&tuple[1], GET_SCHEMA_NAME(schnm));
5788
set_tuplefield_string(&tuple[1], NULL_STRING);
5789
set_tuplefield_string(&tuple[2], reln);
5791
set_tuplefield_string(&tuple[3], "_SYSTEM");
5793
set_tuplefield_string(&tuple[3], owner);
5794
mylog("user=%s\n", user);
5795
set_tuplefield_string(&tuple[4], user);
5796
switch (useracl[j][k])
5811
priv = "REFERENCES";
5816
set_tuplefield_string(&tuple[5], priv);
5817
/* The owner and the super user are grantable */
5819
set_tuplefield_string(&tuple[6], "YES");
5821
set_tuplefield_string(&tuple[6], "NO");
5828
free(escSchemaName);
5834
QR_Destructor(wres);
5836
QR_Destructor(allures);
5838
ret = DiscardStatementSvp(stmt, ret, FALSE);
5843
static RETCODE SQL_API
5844
PGAPI_ForeignKeys_new(
5846
const SQLCHAR FAR * szPkTableQualifier, /* OA X*/
5847
SQLSMALLINT cbPkTableQualifier,
5848
const SQLCHAR FAR * szPkTableOwner, /* OA E*/
5849
SQLSMALLINT cbPkTableOwner,
5850
const SQLCHAR FAR * szPkTableName, /* OA(R) E*/
5851
SQLSMALLINT cbPkTableName,
5852
const SQLCHAR FAR * szFkTableQualifier, /* OA X*/
5853
SQLSMALLINT cbFkTableQualifier,
5854
const SQLCHAR FAR * szFkTableOwner, /* OA E*/
5855
SQLSMALLINT cbFkTableOwner,
5856
const SQLCHAR FAR * szFkTableName, /* OA(R) E*/
5857
SQLSMALLINT cbFkTableName)
5859
CSTR func = "PGAPI_ForeignKeys";
5860
StatementClass *stmt = (StatementClass *) hstmt;
5861
QResultClass *res = NULL;
5862
RETCODE ret = SQL_ERROR, result;
5863
char tables_query[INFO_INQUIRY_LEN];
5864
char *pk_table_needed = NULL, *escTableName = NULL;
5865
char *fk_table_needed = NULL;
5866
char schema_needed[SCHEMA_NAME_STORAGE_LEN + 1];
5867
char catName[SCHEMA_NAME_STORAGE_LEN],
5868
scmName1[SCHEMA_NAME_STORAGE_LEN],
5869
scmName2[SCHEMA_NAME_STORAGE_LEN];
5870
const char *relqual;
5871
ConnectionClass *conn = SC_get_conn(stmt);
5873
const char *eq_string;
5875
mylog("%s: entering...stmt=%p\n", func, stmt);
5877
if (result = SC_initialize_and_recycle(stmt), SQL_SUCCESS != result)
5880
schema_needed[0] = '\0';
5881
#define return DONT_CALL_RETURN_FROM_HERE???
5883
pk_table_needed = make_string(szPkTableName, cbPkTableName, NULL, 0);
5884
fk_table_needed = make_string(szFkTableName, cbFkTableName, NULL, 0);
5886
eq_string = gen_opestr(eqop, conn);
5889
* Case #2 -- Get the foreign keys in the specified table (fktab) that
5890
* refer to the primary keys of other table(s).
5892
if (NULL != fk_table_needed)
5894
mylog("%s: entering Foreign Key Case #2", func);
5895
escTableName = simpleCatalogEscape(fk_table_needed, SQL_NTS, NULL, conn);
5896
schema_strcat(schema_needed, "%.*s", szFkTableOwner, cbFkTableOwner, szFkTableName, cbFkTableName, conn);
5897
relqual = "\n and conrelid = c.oid";
5900
* Case #1 -- Get the foreign keys in other tables that refer to the
5901
* primary key in the specified table (pktab). i.e., Who points to
5904
else if (NULL != pk_table_needed)
5906
escTableName = simpleCatalogEscape(pk_table_needed, SQL_NTS, NULL, conn);
5907
schema_strcat(schema_needed, "%.*s", szPkTableOwner, cbPkTableOwner, szPkTableName, cbPkTableName, conn);
5908
relqual = "\n and confrelid = c.oid";
5912
SC_set_error(stmt, STMT_INTERNAL_ERROR, "No tables specified to PGAPI_ForeignKeys.", func);
5916
if (conn->schema_support)
5918
char *escSchemaName;
5920
if (NULL != CurrCat(conn))
5921
snprintf(catName, sizeof(catName), "'%s'::name", CurrCat(conn));
5923
strcpy(catName, "NULL::name");
5924
strcpy(scmName1, "n2.nspname");
5925
strcpy(scmName2, "n1.nspname");
5926
escSchemaName = simpleCatalogEscape(schema_needed, SQL_NTS, NULL, conn);
5928
snprintf(tables_query, sizeof(tables_query),
5930
" %s as PKTABLE_CAT"
5931
",\n %s as PKTABLE_SCHEM"
5932
",\n c2.relname as PKTABLE_NAME"
5933
",\n a2.attname as PKCOLUMN_NAME"
5934
",\n %s as FKTABLE_CAT"
5935
",\n %s as FKTABLE_SCHEM"
5936
",\n c1.relname as FKTABLE_NAME"
5937
",\n a1.attname as FKCOLUMN_NAME"
5938
",\n i::int2 as KEY_SEQ"
5939
",\n case ref.confupdtype"
5940
"\n when 'c' then %d::int2"
5941
"\n when 'n' then %d::int2"
5942
"\n when 'd' then %d::int2"
5943
"\n when 'r' then %d::int2"
5945
"\n end as UPDATE_RULE"
5946
",\n case ref.confdeltype"
5947
"\n when 'c' then %d::int2"
5948
"\n when 'n' then %d::int2"
5949
"\n when 'd' then %d::int2"
5950
"\n when 'r' then %d::int2"
5952
"\n end as DELETE_RULE"
5953
",\n ref.conname as FK_NAME"
5954
",\n cn.conname as PK_NAME"
5955
#if (ODBCVER >= 0x0300)
5957
"\n when ref.condeferrable then"
5959
"\n when ref.condeferred then %d::int2"
5963
"\n end as DEFERRABLITY"
5964
#endif /* ODBCVER */
5967
" (select cn.oid, conrelid, conkey, confrelid, confkey"
5968
",\n generate_series(array_lower(conkey, 1), array_upper(conkey, 1)) as i"
5969
",\n confupdtype, confdeltype, conname"
5970
",\n condeferrable, condeferred"
5971
"\n from pg_catalog.pg_constraint cn"
5972
",\n pg_catalog.pg_class c"
5973
",\n pg_catalog.pg_namespace n"
5974
"\n where contype = 'f' %s"
5975
"\n and relname %s'%s'"
5976
"\n and n.oid = c.relnamespace"
5977
"\n and n.nspname %s'%s'"
5979
"\n inner join pg_catalog.pg_class c1"
5980
"\n on c1.oid = ref.conrelid)"
5981
"\n inner join pg_catalog.pg_namespace n1"
5982
"\n on n1.oid = c1.relnamespace)"
5983
"\n inner join pg_catalog.pg_attribute a1"
5984
"\n on a1.attrelid = c1.oid"
5985
"\n and a1.attnum = conkey[i])"
5986
"\n inner join pg_catalog.pg_class c2"
5987
"\n on c2.oid = ref.confrelid)"
5988
"\n inner join pg_catalog.pg_namespace n2"
5989
"\n on n2.oid = c2.relnamespace)"
5990
"\n inner join pg_catalog.pg_attribute a2"
5991
"\n on a2.attrelid = c2.oid"
5992
"\n and a2.attnum = confkey[i])"
5993
"\n left outer join pg_catalog.pg_constraint cn"
5994
"\n on cn.conrelid = ref.confrelid"
5995
"\n and cn.contype = 'p')"
6010
#if (ODBCVER >= 0x0300)
6011
, SQL_INITIALLY_DEFERRED
6012
, SQL_INITIALLY_IMMEDIATE
6013
, SQL_NOT_DEFERRABLE
6014
#endif /* ODBCVER */
6016
, eq_string, escTableName
6017
, eq_string, escSchemaName);
6019
free(escSchemaName);
6020
if (NULL != pk_table_needed &&
6021
NULL != fk_table_needed)
6024
escTableName = simpleCatalogEscape(pk_table_needed, SQL_NTS, NULL, conn);
6025
snprintf_add(tables_query, sizeof(tables_query),
6026
"\n where c2.relname %s'%s'",
6027
eq_string, escTableName);
6029
strcat(tables_query, "\n order by ref.oid, ref.i");
6033
strcpy(catName, "NULL::name");
6034
strcpy(scmName1, "NULL::name");
6035
strcpy(scmName2, "NULL::name");
6037
snprintf(tables_query, sizeof(tables_query),
6038
"select %s as PKTABLE_CAT"
6039
",\n %s as PKTABLE_SCHEM"
6040
",\n c2.relname as PKTABLE_NAME"
6041
",\n a2.attname as PKCOLUMN_NAME"
6042
",\n %s as FKTABLE_CAT"
6043
",\n %s as FKTABLE_SCHEM"
6044
",\n c1.relname as FKTABLE_NAME"
6045
",\n a1.attname as FKCOLUMN_NAME"
6046
",\n i::int2 as KEY_SEQ"
6047
",\n case confupdtype"
6048
"\n when 'c' then %d::int2"
6049
"\n when 'n' then %d::int2"
6050
"\n when 'd' then %d::int2"
6051
"\n when 'r' then %d::int2"
6053
"\n end as UPDATE_RULE"
6054
",\n case confdeltype"
6055
"\n when 'c' then %d::int2"
6056
"\n when 'n' then %d::int2"
6057
"\n when 'd' then %d::int2"
6058
"\n when 'r' then %d::int2"
6060
"\n end as DELETE_RULE"
6061
",\n conname as FK_NAME"
6062
",\n NULL::name as PK_NAME"
6063
#if (ODBCVER >= 0x0300)
6065
"\n when condeferrable then"
6067
"\n when condeferred then %d::int2"
6071
"\n end as DEFERRABLITY"
6072
#endif /* ODBCVER */
6074
"\n (select conrelid, conkey, confrelid, confkey"
6075
",\n generate_series(array_lower(conkey, 1), array_upper(conkey, 1)) as i"
6076
",\n confupdtype, confdeltype, conname"
6077
",\n condeferrable, condeferred"
6078
"\n from pg_catalog.pg_constraint cn"
6079
",\n pg_catalog.pg_class c"
6080
"\n where contype = 'f' %s"
6081
"\n and relname %s'%s'"
6083
",\n pg_catalog.pg_class c1"
6084
",\n pg_catalog.pg_attribute a1"
6085
",\n pg_catalog.pg_class c2"
6086
",\n pg_catalog.pg_attribute a2"
6087
"\n where c1.oid = ref.conrelid"
6088
"\n and c2.oid = ref.confrelid"
6089
"\n and a1.attrelid = c1.oid"
6090
"\n and a1.attnum = conkey[i]"
6091
"\n and a2.attrelid = c2.oid"
6092
"\n and a2.attnum = confkey[i]"
6093
"\n order by ref.oid, ref.i"
6108
#if (ODBCVER >= 0x0300)
6109
, SQL_INITIALLY_DEFERRED
6110
, SQL_INITIALLY_IMMEDIATE
6111
, SQL_NOT_DEFERRABLE
6112
#endif /* ODBCVER */
6113
, relqual, eq_string, escTableName);
6116
if (res = CC_send_query(conn, tables_query, NULL, IGNORE_ABORT_ON_CONN, stmt), !QR_command_maybe_successful(res))
6118
SC_set_error(stmt, STMT_EXEC_ERROR, "PGAPI_ForeignKeys query error", func);
6122
SC_set_Result(stmt, res);
6129
* also, things need to think that this statement is finished so the
6130
* results can be retrieved.
6132
if (SQL_SUCCEEDED(ret))
6134
stmt->status = STMT_FINISHED;
6135
extend_column_bindings(SC_get_ARDF(stmt), QR_NumResultCols(res));
6137
if (pk_table_needed)
6138
free(pk_table_needed);
6141
if (fk_table_needed)
6142
free(fk_table_needed);
6143
/* set up the current tuple pointer for SQLFetch */
6144
stmt->currTuple = -1;
6145
SC_set_rowset_start(stmt, -1, FALSE);
6146
SC_set_current_col(stmt, -1);
6149
ret = DiscardStatementSvp(stmt, ret, FALSE);
6150
mylog("%s(): EXIT, stmt=%p, ret=%d\n", func, stmt, ret);