rpm  5.4.15
rpmodbc.c
Go to the documentation of this file.
1 
5 #include "system.h"
6 
7 #if defined(HAVE_SQLEXT_H)
8 #include <sqlext.h>
9 #endif
10 
11 #include <rpmiotypes.h>
12 #include <rpmio.h> /* for *Pool methods */
13 #include <rpmlog.h>
14 #include <rpmmacro.h>
15 #include <rpmurl.h>
16 #include <argv.h>
17 
18 #define _RPMODBC_INTERNAL
19 #include <rpmodbc.h>
20 
21 #include "debug.h"
22 
23 /*@unchecked@*/
24 int _odbc_debug = 0;
25 
26 #define DBG(_t, _l) \
27  if ((_t) || _odbc_debug) fprintf _l
28 
29 #define SPEW(_t, _rc, _odbc) \
30  { if ((_t) || _odbc_debug) \
31  fprintf(stderr, "<-- %s(%p) rc %d\n", __FUNCTION__, (_odbc), \
32  (_rc)); \
33  }
34 
35 #if !defined(WITH_UNIXODBC) /* XXX retrofit */
36 #define SQL_SUCCEEDED(rc) (((rc)&(~1))==0)
37 #define SQL_NO_DATA 100
38 #define SQL_FETCH_NEXT 1
39 #define SQL_FETCH_FIRST 2
40 #define SQL_FETCH_LAST 3
41 #define SQL_FETCH_PRIOR 4
42 #define SQL_FETCH_ABSOLUTE 5
43 #define SQL_FETCH_RELATIVE 6
44 
45 #define SQL_C_CHAR 1
46 #define SQL_C_SHORT 5
47 #define SQL_C_LONG 4
48 #define SQL_C_FLOAT 6
49 #define SQL_C_DOUBLE 8
50 #define SQL_C_DATE 9
51 #define SQL_C_TIME 10
52 #define SQL_C_TIMESTAMP 11
53 
54 #define SQL_COLUMN_NAME 1
55 #define SQL_COLUMN_TABLE_NAME 15
56 #define SQL_COLUMN_LABEL 18
57 
58 #define SQL_COMMIT 0
59 #define SQL_ROLLBACK 1
60 
61 #endif
62 
63 /*==============================================================*/
64 #if defined(WITH_UNIXODBC)
65 static int Xchkodbc(/*@unused@*/ ODBC_t odbc, int ht, const char * msg,
66  int error, int printit,
67  const char * func, const char * fn, unsigned ln)
68 {
69  int rc = error;
70 
71  /* XXX filter SQL_NO_DATA(100) return. */
72  if (printit && !SQL_SUCCEEDED(rc) && rc != SQL_NO_DATA) {
73  HNDL_t H;
74  short ret;
75  int i;
76 
77  fprintf(stderr, "error: %s:%s:%u: %s(%d):\n",
78  func, fn, ln, msg, rc);
79 
80  switch (ht) {
81  case SQL_HANDLE_ENV: H = odbc->env; break;
82  case SQL_HANDLE_DBC: H = odbc->dbc; break;
83  case SQL_HANDLE_STMT: H = odbc->stmt; break;
84  case SQL_HANDLE_DESC: H = odbc->desc; break;
85  default: H = NULL; break;
86  }
87 
88 assert(H);
89  i = 0;
90  do {
91  int native;
92  unsigned char state[7];
93  unsigned char text[256];
94  short len;
95  ret = SQLGetDiagRec(H->ht, H->hp, ++i, state, &native, text,
96  sizeof(text), &len);
97  if (SQL_SUCCEEDED(ret))
98  fprintf(stderr, "\t%s:%ld:%ld:%s\n",
99  state, (long)i, (long)native, text);
100  } while (ret == SQL_SUCCESS);
101  }
102 
103  return rc;
104 }
105 
106 /* XXF FIXME: add logic to set printit */
107 #define CHECK(_o, _t, _m, _rc) \
108  Xchkodbc(_o, _t, _m, _rc, 1, __FUNCTION__, __FILE__, __LINE__)
109 #else
110 #define CHECK(_o, _t, _m, _rc) (-1)
111 #endif /* WITH_UNIXODBC */
112 
113 static void * hFree(ODBC_t odbc, HNDL_t H)
114 {
115  int xx;
116 
117  if (H) {
118  if (H->hp)
119  xx = CHECK(odbc, H->ht, "SQLFreeHandle",
120  SQLFreeHandle(H->ht, H->hp));
121  H->ht = 0;
122  H->hp = NULL;
123  H = _free(H);
124  }
125  return NULL;
126 };
127 
128 static void * hAlloc(ODBC_t odbc, int ht)
129 {
130  HNDL_t PH;
131  HNDL_t H = xmalloc(sizeof(*H));
132  SQLHANDLE * parent;
133  int xx;
134 
135  H->ht = ht;
136  H->hp = NULL;
137 
138  switch (ht) {
139  case SQL_HANDLE_ENV: PH = NULL; break;
140  case SQL_HANDLE_DBC: PH = odbc->env; break;
141  case SQL_HANDLE_STMT: PH = odbc->dbc; break;
142  case SQL_HANDLE_DESC: PH = odbc->dbc; break;
143  default: PH = NULL; break;
144  }
145  parent = (PH ? PH->hp : NULL);
146 
147  xx = CHECK(odbc, H->ht, "SQLAllocHandle",
148  SQLAllocHandle(H->ht, parent, &H->hp));
149 assert(H->hp);
150 
151  return H;
152 };
153 
154 /*==============================================================*/
155 typedef struct key_s {
156  int32_t t;
157  uint32_t v;
158  const char *n;
159 } KEY;
160 
161 #define _ENTRY(_t, _v) { _t, SQL_ATTR_##_v, #_v, }
162 static KEY SQL_ATTRS[] = {
163 #if defined(WITH_UNIXODBC)
164  /* sql.h */
165  _ENTRY(8+1, APP_PARAM_DESC), /* ptr */
166  _ENTRY(8+1, APP_ROW_DESC), /* ptr */
167  _ENTRY(8+1, IMP_PARAM_DESC), /* RO ptr */
168  _ENTRY(8+1, IMP_ROW_DESC), /* RO ptr */
169  /* sqlext.h */
170  _ENTRY( 8, ASYNC_ENABLE), /* ul */
171  /* SQL_ATTR_ASYNC_STMT_EVENT ptr */
172  /* SQL_ATTR_ASYNC_STMT_PCALLBACK ptr */
173  /* SQL_ATTR_ASYNC_STMT_PCONTEXT ptr */
174  _ENTRY( 8, CONCURRENCY), /* ul */
175  /* SQL_ATTR_CURSOR_SCROLLABLE ul */
176  /* SQL_ATTR_CURSOR_SENSITIVITY ul */
177  _ENTRY( 8, CURSOR_TYPE), /* ul */
178  _ENTRY( 8, ENABLE_AUTO_IPD), /* ul */
179  _ENTRY(8+8, FETCH_BOOKMARK_PTR), /* *l */
180  _ENTRY( 8, KEYSET_SIZE), /* ul */
181  _ENTRY( 8, MAX_LENGTH), /* ul */
182  _ENTRY( 8, MAX_ROWS), /* ul */
183  /* SQL_ATTR_METADATA_ID ul */
184  _ENTRY( 8, NOSCAN), /* ul */
185  _ENTRY(8+8, PARAM_BIND_OFFSET_PTR), /* *ul */
186  _ENTRY( 8, PARAM_BIND_TYPE), /* ul */
187  _ENTRY(8+2, PARAM_OPERATION_PTR), /* *uh */
188  _ENTRY(8+2, PARAM_STATUS_PTR), /* *uh */
189  _ENTRY(8+8, PARAMS_PROCESSED_PTR), /* *ul */
190  _ENTRY( 8, PARAMSET_SIZE), /* ul */
191  _ENTRY( 8, QUERY_TIMEOUT), /* ul */
192  _ENTRY( 8, RETRIEVE_DATA), /* ul */
193  _ENTRY( 8, ROW_ARRAY_SIZE), /* ul */
194  _ENTRY(8+8, ROW_BIND_OFFSET_PTR), /* *ul */
195  _ENTRY( 8, ROW_BIND_TYPE), /* ul */
196  _ENTRY( 8, ROW_NUMBER), /* RO ul */
197  _ENTRY(8+2, ROW_OPERATION_PTR), /* *uh */
198  _ENTRY(8+2, ROW_STATUS_PTR), /* *uh */
199  _ENTRY(8+8, ROWS_FETCHED_PTR), /* *ul */
200  _ENTRY( 8, SIMULATE_CURSOR), /* ul */
201  _ENTRY( 8, USE_BOOKMARKS), /* ul */
202 #else
203  { 0, 0, "UNKNOWN" },
204 #endif /* WITH_UNIXODBC */
205 };
206 #undef _ENTRY
207 static size_t nSQL_ATTRS = sizeof(SQL_ATTRS) / sizeof(SQL_ATTRS[0]);
208 
209 static int odbcDumpStmt(ODBC_t odbc, void * _fp)
210 {
211  FILE * fp = (_fp ? _fp : stderr);
212  int rc = 0;
213  size_t i;
214 
215  for (i = 0; i < nSQL_ATTRS; i++) {
216  int _attr = SQL_ATTRS[i].v;
217  unsigned long _ul;
218  void * _p;
219  unsigned short * _uhp;
220  unsigned long * _ulp;
221  int ns;
222 
223  _ul = 0;
224  _p = NULL;
225  _uhp = NULL;
226  _ulp = NULL;
227  ns = 0;
228  switch (SQL_ATTRS[i].t) {
229  default:
230  continue;
231  break;
232  case 8:
233  rc = odbcGetStmtAttr(odbc, _attr, &_ul, sizeof(_ul), &ns);
234  if (_ul != 0)
235 fprintf(fp, "\t%s:\t0x%lx\n", SQL_ATTRS[i].n, _ul);
236  break;
237  case 8+1:
238  rc = odbcGetStmtAttr(odbc, _attr, &_p, sizeof(_p), &ns);
239  if (_p != NULL)
240 fprintf(fp, "\t%s:\t%p\n", SQL_ATTRS[i].n, _p);
241  break;
242  case 8+2:
243  rc = odbcGetStmtAttr(odbc, _attr, &_uhp, sizeof(_uhp), &ns);
244  if (_uhp != NULL)
245 fprintf(fp, "\t%s:\t*(%p) = 0x%hx\n", SQL_ATTRS[i].n, _uhp, *_uhp);
246  break;
247  case 8+8:
248  rc = odbcGetStmtAttr(odbc, _attr, &_ulp, sizeof(_ulp), &ns);
249  if (_uhp != NULL)
250 fprintf(fp, "\t%s:\t*(%p) = 0x%lx\n", SQL_ATTRS[i].n, _ulp, *_ulp);
251  break;
252  }
253  }
254 
255  return rc;
256 }
257 
258 int odbcGetStmtAttr(ODBC_t odbc, int _attr, void * _bp, int _nb, int * nsp)
259 {
260  SQLHANDLE * stmt = odbc->stmt->hp;
261  int rc = -1;
262  if (stmt)
263  rc = CHECK(odbc, SQL_HANDLE_STMT, "SQLGetStmtAttr",
264  SQLGetStmtAttr(stmt, _attr, _bp, _nb, nsp));
265 
266  return rc;
267 }
268 
269 int odbcSetStmtAttr(ODBC_t odbc, int _attr, void * _bp, int ns)
270 {
271  SQLHANDLE * stmt = odbc->stmt->hp;
272  int rc = -1;
273  if (stmt)
274  rc = CHECK(odbc, SQL_HANDLE_STMT, "SQLSetStmtAttr",
275  SQLSetStmtAttr(stmt, _attr, _bp, ns));
276  return rc;
277 }
278 
279 /*==============================================================*/
280 #define _ENTRY(_t, _v) { _t, SQL_##_v, #_v, }
281 static KEY SQL_INFOS[] = {
282 #if defined(WITH_UNIXODBC)
283  /* sql.h */
284  _ENTRY( 0, FETCH_DIRECTION), /* ul? (unixODBC) */
285 
286  _ENTRY( 1, ACCESSIBLE_PROCEDURES), /* c: Y/N */
287  _ENTRY( 1, ACCESSIBLE_TABLES), /* c: Y/N */
288  /* SQL_ACTIVE_ENVIRONMENTS uh */
289  /* SQL_AGGREGATE_FUNCTIONS ui */
290  /* SQL_ALTER_DOMAIN ui */
291  _ENTRY( 4, ALTER_TABLE), /* ui */
292  /* SQL_ASYNC_DBC_FUNCTIONS ui */
293  /* SQL_ASYNC_MODE ui */
294  /* SQL_ASYNC_NOTIFICATION ui */
295  /* SQL_BATCH_ROW_COUNT ui */
296  /* SQL_BATCH_SUPPORT ui */
297  /* SQL_BOOKMARK_PERSISTENCE ui */
298  /* SQL_CATALOG_LOCATION uh */
299  _ENTRY( 1, CATALOG_NAME), /* c: Y/N */
300  /* SQL_CATALOG_NAME_SEPARATOR s */
301  /* SQL_CATALOG_TERM s */
302  /* SQL_CATALOG_USAGE ui */
303  _ENTRY(256, COLLATION_SEQ), /* s */
304  /* SQL_COLUMN_ALIAS c: Y/N */
305  /* SQL_CONCAT_NULL_BEHAVIOR uh */
306  /* SQL_CONVERT_type ui */
307  /* SQL_CONVERT_FINCTIONS ui */
308  /* SQL_CORRELATION_NAME uh */
309  /* SQL_CREATE_ASSERTION ui */
310  /* SQL_CREATE_CHARACTER_SET ui */
311  /* SQL_CREATE_COLLATION ui */
312  /* SQL_CREATE_DOMAIN ui */
313  /* SQL_CREATE_SCHEMA ui */
314  /* SQL_CREATE_TABLE ui */
315  /* SQL_CREATE_TRANSLATION ui */
316  /* SQL_CREATE_VIEW ui */
317  _ENTRY( 2, CURSOR_COMMIT_BEHAVIOR), /* uh */
318  _ENTRY( 2, CURSOR_ROLLBACK_BEHAVIOR), /* uh */
319  _ENTRY( 4, CURSOR_SENSITIVITY), /* ui */
320  _ENTRY(256, DATA_SOURCE_NAME), /* s */
321  _ENTRY( 1, DATA_SOURCE_READ_ONLY), /* c: Y/N */
322  /* SQL_DATABASE_NAME s */
323  /* SQL_DATETIME_LITERALS ui */
324  _ENTRY(256, DBMS_NAME), /* s */
325  _ENTRY(256, DBMS_VER), /* s */
326  /* SQL_DDL_INDEX ui */
327  _ENTRY( 4, DEFAULT_TXN_ISOLATION), /* ui */
328  _ENTRY( 1, DESCRIBE_PARAMETER), /* c: Y/N */
329  /* SQL_DM_VER s */
330  /* SQL_DRIVER_AWARE_POOLING_SUPPORT ui */
331  /* SQL_DRIVER_HDBCSQL_DRIVER_HENV ul */
332  /* SQL_DRIVER_HDESC ul */
333  /* SQL_DRIVER_HLIB ul */
334  /* SQL_DRIVER_HSTMT ul */
335  /* SQL_DRIVER_NAME s */
336  /* SQL_DRIVER_ODBC_VER s */
337  /* SQL_DRIVER_VER s */
338  /* SQL_DROP_ASSERTION ui */
339  /* SQL_DROP_CHARACTER_SET ui */
340  /* SQL_DROP_COLLATION ui */
341  /* SQL_DROP_DOMAIN ui */
342  /* SQL_DROP_SCHEMA ui */
343  /* SQL_DROP_TABLE ui */
344  /* SQL_DROP_TRANSLATION ui */
345  /* SQL_DROP_VIEW ui */
346  /* SQL_DYNAMIC_CURSOR_ATTRIBUTES ui */
347  /* SQL_DYNAMIC_CURSOR_ATTRIBUTES2 ui */
348  /* SQL_EXPRESSIONS_IN_ORDERBY c: Y/N */
349  /* SQL_FILE_USAGE uh */
350  /* SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES2 ui */
351  _ENTRY( 4, GETDATA_EXTENSIONS), /* ui */
352  /* SQL_GROUP_BY uh */
353  _ENTRY( 2, IDENTIFIER_CASE), /* uh */
354  _ENTRY( 2, IDENTIFIER_QUOTE_CHAR), /* uh */
355  /* SQL_IDENTIFIER_CASE uh */
356  /* SQL_INDEX_KEYWORDS ui */
357  /* SQL_INFO_SCHEMA_VIEWS ui */
358  /* SQL_INSERT_STATEMENT ui */
359  _ENTRY( 1, INTEGRITY), /* c: Y/N */
360  /* SQL_KEYSET_CURSOR_ATTRIBUTES ui */
361  /* SQL_KEYSET_CURSOR_ATTRIBUTES2 ui */
362  /* SQL_KEYWORDS s */
363  /* SQL_LIKE_ESCAPE_CLAUSE c: Y/N */
364  /* SQL_MAX_ASYNC_CONCURRENT_STATEMENTS ui */
365  /* SQL_MAX_BINARY_LITERAL_LEN ui */
366  _ENTRY( 2, MAX_CATALOG_NAME_LEN), /* uh */
367  _ENTRY( 2, MAXIMUM_CATALOG_NAME_LENGTH), /* uh */
368  /* SQL_MAX_CHAR_LITERAL_LEN ui */
369  _ENTRY( 2, MAX_COLUMN_NAME_LEN), /* uh */
370  _ENTRY( -2, MAXIMUM_COLUMN_NAME_LENGTH), /* uh */
371  _ENTRY( 2, MAX_COLUMNS_IN_GROUP_BY), /* uh */
372  _ENTRY( -2, MAXIMUM_COLUMNS_IN_GROUP_BY), /* uh */
373  _ENTRY( 2, MAX_COLUMNS_IN_INDEX), /* uh */
374  _ENTRY( -2, MAXIMUM_COLUMNS_IN_INDEX), /* uh */
375  _ENTRY( 2, MAX_COLUMNS_IN_ORDER_BY), /* uh */
376  _ENTRY( -2, MAXIMUM_COLUMNS_IN_ORDER_BY), /* uh */
377  _ENTRY( 2, MAX_COLUMNS_IN_SELECT), /* uh */
378  _ENTRY( -2, MAXIMUM_COLUMNS_IN_SELECT), /* uh */
379  _ENTRY( 2, MAX_COLUMNS_IN_TABLE), /* uh */
380  _ENTRY( 2, MAX_CONCURRENT_ACTIVITIES), /* uh */
381  _ENTRY( -2, MAXIMUM_CONCURRENT_ACTIVITIES), /* uh */
382  _ENTRY( 2, MAX_CURSOR_NAME_LEN), /* uh */
383  _ENTRY( -2, MAXIMUM_CURSOR_NAME_LENGTH), /* uh */
384  _ENTRY( 2, MAX_DRIVER_CONNECTIONS), /* uh */
385  _ENTRY( -2, MAXIMUM_DRIVER_CONNECTIONS), /* uh */
386  _ENTRY( 2, MAX_IDENTIFIER_LEN), /* uh */
387  _ENTRY( -2, MAXIMUM_IDENTIFIER_LENGTH), /* uh */
388  _ENTRY( 2, MAX_INDEX_SIZE), /* uh */
389  _ENTRY( -2, MAXIMUM_INDEX_SIZE), /* uh */
390  /* SQL_MAX_PROCEDURE_NAME_LEN uh */
391  _ENTRY( 4, MAX_ROW_SIZE), /* ui */
392  _ENTRY( -4, MAXIMUM_ROW_SIZE), /* ui */
393  /* SQL_MAX_ROW_SIZE_INCLUDES_LONG c: Y/N */
394  _ENTRY( 2, MAX_SCHEMA_NAME_LEN), /* uh */
395  _ENTRY( -2, MAXIMUM_SCHEMA_NAME_LENGTH), /* uh */
396  _ENTRY( 4, MAX_STATEMENT_LEN), /* ui */
397  _ENTRY( -4, MAXIMUM_STATEMENT_LENGTH), /* ui */
398  _ENTRY( 2, MAX_TABLE_NAME_LEN), /* uh */
399  _ENTRY( 2, MAX_TABLES_IN_SELECT), /* uh */
400  _ENTRY( -2, MAXIMUM_TABLES_IN_SELECT), /* uh */
401  _ENTRY( 2, MAX_USER_NAME_LEN), /* uh */
402  _ENTRY( -2, MAXIMUM_USER_NAME_LENGTH), /* uh */
403  /* SQL_MULT_RESULT_SETS c: Y/N */
404  /* SQL_MULT_ACTIVE_TXN c: Y/N */
405  /* SQL_NEED_LONG_DATA_LEN c: Y/N */
406  /* SQL_NON_NULLABLE_COLUMNS uh */
407  _ENTRY( 2, NULL_COLLATION), /* uh */
408  /* SQL_NUMERIC_FUNCTIONS ui */
409  /* SQL_ODBC_INTERFACE_CONFORMANCE ui */
410  /* SQL_ODBC_VER s */
411  _ENTRY( 4, OJ_CAPABILITIES), /* ui */
412  _ENTRY( -4, OUTER_JOIN_CAPABILITIES), /* ui */
413  _ENTRY( 1, ORDER_BY_COLUMNS_IN_SELECT), /* c: Y/N */
414  /* SQL_PARAM_ARRAY_ROW_COUNTS ui */
415  /* SQL_PARAM_ARRAY_SELECTS ui */
416  /* SQL_PROCEDURE_TERM s */
417  /* SQL_PROCEDURES c: Y/N */
418  /* SQL_POS_OPERATIONS ui */
419  /* SQL_QUOTED_IDENTIFIER_CASE uh */
420  /* SQL_ROW_UPDATES c: Y/N */
421  /* SQL_SCHEMA_TERM s */
422  /* SQL_SCHEMA_USAGE ui */
423  /* SQL_SCROLL_OPTIONS ui */
424  _ENTRY( 4, SCROLL_CONCURRENCY), /* FIXME: ??? */
425  _ENTRY(256, SEARCH_PATTERN_ESCAPE), /* s */
426  _ENTRY(256, SERVER_NAME), /* s */
427  _ENTRY(256, SPECIAL_CHARACTERS), /* s */
428  /* SQL_SQL_CONFORMANCE ui */
429  /* SQL_SQL92_DATETIME_FUNCTIONS ui */
430  /* SQL_SQL92_FOREIGN_KEY_DELETE_RULE ui */
431  /* SQL_SQL92_FOREIGN_KEY_UPDATE_RULE ui */
432  /* SQL_SQL92_GRANT ui */
433  /* SQL_SQL92_NUMERIC_VALUE_FUNCTIONS ui */
434  /* SQL_SQL92_PREDICATES ui */
435  /* SQL_SQL92_RELATIONAL_JOIN_OPERATORS ui */
436  /* SQL_SQL92_REVOKE ui */
437  /* SQL_SQL92_ROW_VALUE_CONSTRUCTOR ui */
438  /* SQL_SQL92_STRING_FUNCTIONS ui */
439  /* SQL_SQL92_VALUE_EXPRESSIONS ui */
440  /* SQL_STANDARD_CLI_CONFORMANCE ui */
441  /* SQL_STATIC_CURSOR_ATTRIBUTES1 ui */
442  /* SQL_STATIC_CURSOR_ATTRIBUTES2 ui */
443  /* SQL_STRING_FUNCTIONS ui */
444  /* SQL_SUBQUERIES ui */
445  /* SQL_SYSTEM_FUNCTIONS ui */
446  /* SQL_TABLE_TERM s */
447  /* SQL_TIMEDATE_ADD_INTERVALS ui */
448  /* SQL_TIMEDATE_DIFF_INTERVALS ui */
449  /* SQL_TIMEDATE_FUNCTIONS ui */
450  _ENTRY( 2, TXN_CAPABLE), /* uh */
451  _ENTRY( -2, TRANSACTION_CAPABLE), /* uh */
452  _ENTRY( 4, TXN_ISOLATION_OPTION), /* ui */
453  _ENTRY( -4, TRANSACTION_ISOLATION_OPTION), /* ui */
454  /* SQL_UNION ui */
455  _ENTRY(256, USER_NAME), /* s */
456  _ENTRY(256, XOPEN_CLI_YEAR), /* s */
457 #else
458  { 0, 0, "UNKNOWN" },
459 #endif /* WITH_UNIXODBC */
460 };
461 #undef _ENTRY
462 static size_t nSQL_INFOS = sizeof(SQL_INFOS) / sizeof(SQL_INFOS[0]);
463 
464 static int odbcDumpInfo(ODBC_t odbc, void * _fp)
465 {
466  FILE * fp = (_fp ? _fp : stderr);
467  int rc = 0;
468  size_t i;
469 
470  for (i = 0; i < nSQL_INFOS; i++) {
471  int _type = SQL_INFOS[i].v;
472  char _c;
473  unsigned short _uh;
474  unsigned int _ui;
475  char _s[256];
476  short ns;
477 
478  _c = '\0';
479  _uh = 0;
480  _ui = 0;
481  _s[0] = '\0';
482  ns = 0;
483  switch (SQL_INFOS[i].t) {
484  default:
485  continue;
486  break;
487  case 1:
488  rc = odbcGetInfo(odbc, _type, &_c, sizeof(_c), &ns);
489  if (_c != '\0')
490 fprintf(fp, "\t%s:\t%c\n", SQL_INFOS[i].n, _c);
491  break;
492  case 2:
493  rc = odbcGetInfo(odbc, _type, &_uh, sizeof(_uh), &ns);
494  if (_uh != 0)
495 fprintf(fp, "\t%s:\t0x%hx\n", SQL_INFOS[i].n, _uh);
496  break;
497  case 4:
498  rc = odbcGetInfo(odbc, _type, &_ui, sizeof(_ui), &ns);
499  if (_ui != 0)
500 fprintf(fp, "\t%s:\t0x%x\n", SQL_INFOS[i].n, _ui);
501  break;
502  case 256:
503  rc = odbcGetInfo(odbc, _type, &_s, sizeof(_s), &ns);
504  if (_s[0] != '\0')
505 fprintf(fp, "\t%s:\t%s\n", SQL_INFOS[i].n, _s);
506  break;
507  }
508  }
509 
510  return rc;
511 }
512 
513 int odbcGetInfo(ODBC_t odbc, int _type, void * _bp, int _nb, short * nsp)
514 {
515  SQLHANDLE * dbc = odbc->dbc->hp;
516  int rc = -1;
517  if (dbc)
518  rc = CHECK(odbc, SQL_HANDLE_DBC, "SQLGetInfo",
519  SQLGetInfo(dbc, _type, _bp, _nb, nsp));
520  return rc;
521 }
522 
523 /*==============================================================*/
524 #define _ENTRY(_t, _v) { _t, SQL_ATTR_##_v, #_v, }
525 static KEY SQL_EATTRS[] = {
526 #if defined(WITH_UNIXODBC)
527  /* sqlext.h */
528  _ENTRY( 4, CONNECTION_POOLING), /* ui */
529  _ENTRY( 4, CP_MATCH), /* ui */
530  _ENTRY( 4, ODBC_VERSION), /* ui */
531  /* SQL_ATTR_OUTPUT_NTS ui */
532 
533  _ENTRY( 0, UNIXODBC_SYSPATH), /* */
534  _ENTRY( 0, UNIXODBC_VERSION), /* */
535  _ENTRY( 0, UNIXODBC_ENVATTR), /* */
536 #endif /* WITH_UNIXODBC */
537 };
538 #undef _ENTRY
539 static size_t nSQL_EATTRS = sizeof(SQL_EATTRS) / sizeof(SQL_EATTRS[0]);
540 
541 static int odbcDumpEnvAttr(ODBC_t odbc, void * _fp)
542 {
543  FILE * fp = (_fp ? _fp : stderr);
544  int rc = 0;
545  size_t i;
546 
547  for (i = 0; i < nSQL_EATTRS; i++) {
548  int _type = SQL_EATTRS[i].v;
549  unsigned int _ui;
550  int ns;
551 
552  _ui = 0;
553  ns = 0;
554  switch (SQL_EATTRS[i].t) {
555  default:
556  continue;
557  break;
558  case 4:
559  rc = odbcGetEnvAttr(odbc, _type, &_ui, sizeof(_ui), &ns);
560  if (_ui != 0)
561 fprintf(fp, "\t%s:\t0x%x\n", SQL_EATTRS[i].n, _ui);
562  break;
563  }
564  }
565 
566  return rc;
567 }
568 
569 int odbcGetEnvAttr(ODBC_t odbc, int _type, void * _bp, int _nb, int * nsp)
570 {
571  SQLHANDLE * env = odbc->env->hp;
572  int rc = -1;
573  if (env)
574  rc = CHECK(odbc, SQL_HANDLE_ENV, "SQLGetEnvAttr",
575  SQLGetEnvAttr(env, _type, _bp, _nb, nsp));
576  return rc;
577 }
578 
579 int odbcSetEnvAttr(ODBC_t odbc, int _type, void * _bp, int ns)
580 {
581  SQLHANDLE * env = odbc->env->hp;
582  int rc = -1;
583  if (env)
584  rc = CHECK(odbc, SQL_HANDLE_ENV, "SQLSetEnvAttr",
585  SQLSetEnvAttr(env, _type, _bp, ns));
586  return rc;
587 }
588 
589 /*==============================================================*/
590 #define _ENTRY(_t, _v) { _t, SQL_COLUMN_##_v, #_v, }
591 static KEY SQL_CATTRS[] = {
592 #if defined(WITH_UNIXODBC)
593  /* sqlext.h */
594  _ENTRY( 0, COUNT), /* */
595  _ENTRY( 0, NAME), /* */
596  _ENTRY( 4, TYPE), /* */
597  _ENTRY( 4, LENGTH), /* */
598  _ENTRY( 4, PRECISION), /* */
599  _ENTRY( 4, SCALE), /* */
600  _ENTRY( 4, DISPLAY_SIZE), /* */
601  _ENTRY( 0, NULLABLE), /* */
602  _ENTRY( 4, UNSIGNED), /* */
603  _ENTRY( 4, MONEY), /* */
604  _ENTRY( 4, UPDATABLE), /* */
605  _ENTRY( 4, AUTO_INCREMENT), /* */
606  _ENTRY( 4, CASE_SENSITIVE), /* */
607  _ENTRY( 4, SEARCHABLE), /* */
608  _ENTRY(256, TYPE_NAME), /* */
609  _ENTRY(256, TABLE_NAME), /* */
610  _ENTRY(256, OWNER_NAME), /* */
611  _ENTRY(256, QUALIFIER_NAME), /* */
612  _ENTRY(256, LABEL), /* */
613 #else
614  { 0, 0, "UNKNOWN" },
615 #endif /* WITH_UNIXODBC */
616 };
617 #undef _ENTRY
618 static size_t nSQL_CATTRS = sizeof(SQL_CATTRS) / sizeof(SQL_CATTRS[0]);
619 
620 static int odbcDumpColAttrs(ODBC_t odbc, int colx, void * _fp)
621 {
622  FILE * fp = (_fp ? _fp : stderr);
623  int rc = 0;
624  size_t i;
625 
626  for (i = 0; i < nSQL_CATTRS; i++) {
627  int _type = SQL_CATTRS[i].v;
628  char b[BUFSIZ];
629  size_t nb = sizeof(b);;
630  short ns;
631  long got;
632 
633  b[0] = '\0';
634  ns = 0xb00b;
635  got = 0xdeadbeef;
636  switch (SQL_CATTRS[i].t) {
637  default:
638  continue;
639  break;
640 #ifdef NOTYET /* XXX unimplemented in unixODBC=>postgres */
641  case 0:
642  rc = odbcColAttribute(odbc, colx, _type, b, nb, &ns, &got);
643 fprintf(fp, "\t%s:\tgot %lx %p[%hu] = \"%s\"\n", SQL_CATTRS[i].n, got, b, ns, b);
644  break;
645 #endif
646  case 4:
647  rc = odbcColAttribute(odbc, colx, _type, b, nb, &ns, &got);
648 fprintf(fp, "\t%s:\t0x%lx\n", SQL_CATTRS[i].n, got);
649  break;
650  case 256:
651  rc = odbcColAttribute(odbc, colx, _type, b, nb, &ns, &got);
652 fprintf(fp, "\t%s:\t%s\n", SQL_CATTRS[i].n, b);
653  break;
654  }
655  }
656 
657  return rc;
658 }
659 
661  unsigned short ColumnNumber,
662  unsigned short FieldIdentifier,
663  void * CharacterAttributePtr,
664  short BufferLength,
665  short * StringLengthPtr,
666  long * NumericAttributePtr)
667 {
668  SQLHANDLE * stmt = odbc->stmt->hp;
669  int rc = -1;
670  (void)stmt;
671 
672  rc = CHECK(odbc, SQL_HANDLE_STMT, "SQLColAttribute",
673  SQLColAttribute(stmt,
674  ColumnNumber,
675  FieldIdentifier,
676  CharacterAttributePtr,
677  BufferLength,
678  StringLengthPtr,
679  NumericAttributePtr));
680 
681 SPEW(0, rc, odbc);
682  return rc;
683 }
684 
685 /*==============================================================*/
686 
688 {
689  SQLHANDLE * stmt = odbc->stmt->hp;
690  int rc = SQL_NO_DATA;
691  (void)stmt;
692 
693  rc = CHECK(odbc, SQL_HANDLE_STMT, "SQLCloseCursor",
694  SQLCloseCursor(stmt));
695 
696 SPEW(0, rc, odbc);
697  return rc;
698 }
699 
700 const char * odbcGetCursorName(ODBC_t odbc)
701 {
702  SQLHANDLE * stmt = odbc->stmt->hp;
703  int rc = SQL_NO_DATA;
704  char b[BUFSIZ];
705  short nb = sizeof(b);
706  char * t = NULL;
707  short ns;
708  (void)stmt;
709  (void)nb;
710  (void)ns;
711 
712  rc = CHECK(odbc, SQL_HANDLE_STMT, "SQLGetCursorName",
713  SQLGetCursorName(stmt, (SQLCHAR *)b, nb, &ns));
714 
715 SPEW(0, rc, odbc);
716  if (rc == 0)
717  t = xstrdup(b);
718  return t;
719 }
720 
721 int odbcSetCursorName(ODBC_t odbc, const char * s, size_t ns)
722 {
723  SQLHANDLE * stmt = odbc->stmt->hp;
724  int rc = SQL_NO_DATA;
725  (void)stmt;
726 
727  if (ns == 0)
728  ns = strlen(s);
729  rc = CHECK(odbc, SQL_HANDLE_STMT, "SQLSetCursorName",
730  SQLSetCursorName(stmt, (SQLCHAR *)s, (SQLSMALLINT)ns));
731 
732 SPEW(0, rc, odbc);
733  return rc;
734 }
735 
736 /*==============================================================*/
737 
738 int odbcEndTran(ODBC_t odbc, int _rollback)
739 {
740  SQLHANDLE * dbc = odbc->dbc->hp; /* XXX env? */
741  short _completion = (_rollback ? SQL_ROLLBACK : SQL_COMMIT);
742  int rc = 0;
743  (void)dbc;
744 
745  rc = CHECK(odbc, SQL_HANDLE_DBC, "SQLEndTran",
746  SQLEndTran(SQL_HANDLE_DBC, dbc, _completion));
747 
748 SPEW(0, rc, odbc);
749  return rc;
750 }
751 
753 {
754  return odbcEndTran(odbc, SQL_COMMIT);
755 }
756 
758 {
759  return odbcEndTran(odbc, SQL_ROLLBACK);
760 }
761 
762 /*==============================================================*/
763 
764 int odbcConnect(ODBC_t odbc, const char * uri)
765 {
766  const char * db = NULL;
767  SQLHANDLE * dbc;
768  urlinfo u = NULL;
769  int rc = -1;
770 int xx;
771 
772 DBG(0, (stderr, "--> %s(%p,%s)\n", __FUNCTION__, odbc, uri));
773 
774  /*XXX FIXME: SQLConnect by DSN should be done here. */
775 
776  if (uri) {
777  const char * dbpath = NULL;
778  int ut = urlPath(uri, &dbpath);
779 assert(ut == URL_IS_MYSQL || ut == URL_IS_POSTGRES || ut == URL_IS_SQLSERVER);
780  rc = urlSplit(uri, &u);
781  db = rpmExpand(u->scheme, "_", basename((char *)dbpath), NULL);
782  } else {
783  u = odbc->u;
784  db = xstrdup(odbc->db);
785  }
786 assert(u);
787 assert(db);
788 
789 DBG(0, (stderr, "\tdb: %s\n", db));
790 DBG(0, (stderr, "\t u: %s\n", u->user));
791 DBG(0, (stderr, "\tpw: %s\n", u->password));
792 
793  if (odbc->dbc == NULL) /* XXX lazy? */
794  odbc->dbc = hAlloc(odbc, SQL_HANDLE_DBC);
795  dbc = odbc->dbc->hp;
796 
797  rc = CHECK(odbc, SQL_HANDLE_DBC, "SQLConnect",
798  SQLConnect(dbc,
799  (SQLCHAR *) db, SQL_NTS,
800  (SQLCHAR *) u->user, SQL_NTS,
801  (SQLCHAR *) u->password, SQL_NTS));
802 
803  /* XXX FIXME: SQLDriverConnect should print once?. */
804 
805  if (rc == 0) {
806  xx = odbcDumpInfo(odbc, NULL);
807  }
808 
809 SPEW(0, rc, odbc);
810  db = _free(db);
811  return rc;
812 }
813 
815 {
816  SQLHANDLE * dbc = odbc->dbc->hp;
817  int rc = 0;
818  (void)dbc;
819 
820  rc = CHECK(odbc, SQL_HANDLE_DBC, "SQLDisconnect",
821  SQLDisconnect(dbc));
822 
823  odbc->desc = hFree(odbc, odbc->desc); /* XXX needed? */
824  odbc->stmt = hFree(odbc, odbc->stmt); /* XXX needed? */
825  odbc->dbc = hFree(odbc, odbc->dbc); /* XXX lazy? */
826 
827 SPEW(0, rc, odbc);
828  return rc;
829 }
830 
831 int odbcListDataSources(ODBC_t odbc, void *_fp)
832 {
833  FILE * fp = (_fp ? _fp : stderr);
834  SQLHANDLE * env = odbc->env->hp;
835  int rc = 0;
836  (void)fp;
837 
838  unsigned char dsn[256];
839  unsigned char desc[256];
840  short dsn_ret;
841  short desc_ret;
842  unsigned short direction = SQL_FETCH_FIRST;
843 int xx;
844  (void)env;
845  (void)dsn_ret;
846  (void)desc_ret;
847 
848  while (SQL_SUCCEEDED((xx = CHECK(odbc, SQL_HANDLE_ENV, "SQLDataSources",
849  SQLDataSources(env, direction,
850  dsn, sizeof(dsn), &dsn_ret,
851  desc, sizeof(desc), &desc_ret)))))
852  {
853  direction = SQL_FETCH_NEXT;
854  fprintf(fp, "\t%s - %s\n", dsn, desc);
855 #ifdef NOTYET
856  if (ret == SQL_SUCCESS_WITH_INFO) fprintf(fp, "\tdata truncation\n");
857 #endif
858  }
859 
860 SPEW(0, rc, odbc);
861  return rc;
862 }
863 
864 int odbcListDrivers(ODBC_t odbc, void *_fp)
865 {
866  FILE * fp = (_fp ? _fp : stderr);
867  int rc = 0;
868  (void)fp;
869 
870  SQLHANDLE * env = odbc->env->hp;
871  unsigned char driver[256];
872  unsigned char attr[256];
873  short driver_ret;
874  short attr_ret;
875  unsigned short direction = SQL_FETCH_FIRST;
876 int xx;
877  (void)env;
878  (void)driver_ret;
879  (void)attr_ret;
880 
881  while (SQL_SUCCEEDED((xx = CHECK(odbc, SQL_HANDLE_ENV, "SQLDrivers",
882  SQLDrivers(env, direction,
883  driver, sizeof(driver), &driver_ret,
884  attr, sizeof(attr), &attr_ret)))))
885  {
886  direction = SQL_FETCH_NEXT;
887  fprintf(fp, "\t%s - %s\n", driver, attr);
888 #ifdef NOTYET
889  if (xx == SQL_SUCCESS_WITH_INFO) fprintf(fp, "\tdata truncation\n");
890 #endif
891  }
892 
893 SPEW(0, rc, odbc);
894  return rc;
895 }
896 
897 int odbcNRows(ODBC_t odbc)
898 {
899  SQLHANDLE * stmt = odbc->stmt->hp;
900  long rows = 0;
901  int rc = 0;
902  (void)stmt;
903 
904  rc = CHECK(odbc, SQL_HANDLE_STMT, "SQLRowCount",
905  SQLRowCount(stmt, &rows));
906  rc = rows;
907 
908 SPEW(0, rc, odbc);
909  return rc;
910 }
911 
912 int odbcNCols(ODBC_t odbc)
913 {
914  SQLHANDLE * stmt = odbc->stmt->hp;
915  short columns = 0;
916  int rc = 0;
917  (void)stmt;
918 
919  rc = CHECK(odbc, SQL_HANDLE_STMT, "SQLNumResultCols",
920  SQLNumResultCols(stmt, &columns));
921  rc = columns;
922 
923 SPEW(0, rc, odbc);
924  return rc;
925 }
926 
928 {
929  SQLHANDLE * stmt = odbc->stmt->hp;
930  int rc = SQL_NO_DATA;
931  (void)stmt;
932 
933  rc = CHECK(odbc, SQL_HANDLE_STMT, "SQLCancel",
934  SQLCancel(stmt));
935  odbc->stmt = hFree(odbc, odbc->stmt); /* XXX lazy? */
936 
937 SPEW(0, rc, odbc);
938  return rc;
939 }
940 
941 int odbcFetch(ODBC_t odbc)
942 {
943  SQLHANDLE * stmt = odbc->stmt->hp;
944  int rc = SQL_NO_DATA;
945  (void)stmt;
946 
947  rc = CHECK(odbc, SQL_HANDLE_STMT, "SQLFetch",
948  SQLFetch(stmt));
949 
950 SPEW(0, rc, odbc);
951  return rc;
952 }
953 
954 int odbcFetchScroll(ODBC_t odbc, short FetchOrientation, long FetchOffset)
955 {
956  SQLHANDLE * stmt = odbc->stmt->hp;
957  int rc = SQL_NO_DATA;
958  (void)stmt;
959 
960  rc = CHECK(odbc, SQL_HANDLE_STMT, "SQLFetch",
961  SQLFetchScroll(stmt, FetchOrientation, FetchOffset));
962 
963 SPEW(0, rc, odbc);
964  return rc;
965 }
966 
968  unsigned short Col_or_Param_Num,
969  short TargetType,
970  void * TargetValuePtr,
971  long BufferLength,
972  long * StrLen_or_IndPtr)
973 {
974  SQLHANDLE * stmt = odbc->stmt->hp;
975  int rc = -1;
976  (void)stmt;
977 
978  rc = CHECK(odbc, SQL_HANDLE_STMT, "SQLGetData",
979  SQLGetData(stmt,
980  Col_or_Param_Num,
981  TargetType,
982  TargetValuePtr,
983  BufferLength,
984  StrLen_or_IndPtr));
985 
986 SPEW(0, rc, odbc);
987  return rc;
988 }
989 
990 int odbcPrint(ODBC_t odbc, void * _fp)
991 {
992  FILE * fp = (_fp ? _fp : stderr);
993  SQLHANDLE * stmt = odbc->stmt->hp;
994  int rc = 0;
995  char b[BUFSIZ];
996  size_t nb = sizeof(b);
997  long got;
998  ARGV_t av = NULL;
999  int i;
1000 int xx;
1001  (void)stmt;
1002 
1003 DBG(0, (stderr, "--> %s(%p,%p)\n", __FUNCTION__, odbc, fp));
1004 
1005 if (_odbc_debug < 0)
1006 xx = odbcDumpStmt(odbc, fp);
1007 
1008  odbc->ncols = odbcNCols(odbc);
1009  odbc->nrows = 0;
1010 
1011  if (odbc->ncols)
1012  for (i = 0; i < odbc->ncols; i++) {
1013  size_t nw;
1014  short ns;
1015 if (_odbc_debug < 0)
1016 xx = odbcDumpColAttrs(odbc, i+1, NULL);
1017  ns = 0;
1018  xx = odbcColAttribute(odbc, i+1, SQL_COLUMN_LABEL,
1019  b, nb, &ns, &got);
1020  if (xx)
1021  nw = snprintf(b, nb, " Column %d", i+1);
1022  xx = argvAdd(&av, b);
1023  }
1024 
1025  /* XXX filter SQL_NO_DATA(100) return. */
1026  if (odbc->ncols)
1027  while (SQL_SUCCEEDED((xx = odbcFetch(odbc))))
1028  {
1029 
1030  fprintf(fp, "Row %d\n", ++odbc->nrows);
1031  for (i = 0; i < odbc->ncols; i++) {
1032 
1033  /* XXX filter -1 return (columns start with 1 not 0). */
1034  xx = odbcGetData(odbc, i+1, SQL_C_CHAR, b, nb, &got);
1035  if (SQL_SUCCEEDED(xx)) {
1036  if (got == 0) strcpy(b, "NULL");
1037  fprintf(fp, " %20s : %s\n", av[i], b);
1038  }
1039  }
1040  }
1041 
1042  odbc->nrows = 0;
1043  odbc->ncols = 0;
1044 
1045  odbc->stmt = hFree(odbc, odbc->stmt); /* XXX lazy? */
1046 
1047  av = argvFree(av);
1048 
1049 SPEW(0, rc, odbc);
1050 
1051  return rc;
1052 }
1053 
1054 int odbcTables(ODBC_t odbc, const char * tblname)
1055 {
1056  SQLHANDLE * stmt;
1057  int rc = 0;
1058 
1059  if (odbc->stmt == NULL)
1060  odbc->stmt = hAlloc(odbc, SQL_HANDLE_STMT);
1061  stmt = odbc->stmt->hp;
1062 
1063  rc = CHECK(odbc, SQL_HANDLE_STMT, "SQLTables",
1064  SQLTables(stmt,
1065  NULL, 0,
1066  NULL, 0,
1067  (SQLCHAR *) tblname, SQL_NTS,
1068  NULL, 0));
1069 
1070 SPEW(0, rc, odbc);
1071  return rc;
1072 }
1073 
1074 int odbcColumns(ODBC_t odbc, const char * tblname, const char * colname)
1075 {
1076  SQLHANDLE * stmt;
1077  int rc = 0;
1078 
1079  if (odbc->stmt == NULL)
1080  odbc->stmt = hAlloc(odbc, SQL_HANDLE_STMT);
1081  stmt = odbc->stmt->hp;
1082 
1083  rc = CHECK(odbc, SQL_HANDLE_STMT, "SQLColumns",
1084  SQLColumns(stmt,
1085  NULL, 0,
1086  NULL, 0,
1087  (SQLCHAR *) tblname, SQL_NTS,
1088  (SQLCHAR *) colname, SQL_NTS));
1089 
1090 SPEW(0, rc, odbc);
1091  return rc;
1092 }
1093 
1094 int odbcStatistics(ODBC_t odbc, const char * tblname)
1095 {
1096  SQLHANDLE * stmt;
1097  int rc = 0;
1098 
1099  if (odbc->stmt == NULL)
1100  odbc->stmt = hAlloc(odbc, SQL_HANDLE_STMT);
1101  stmt = odbc->stmt->hp;
1102 
1103  rc = CHECK(odbc, SQL_HANDLE_STMT, "SQLStatistics",
1104  SQLStatistics(stmt,
1105  NULL, 0,
1106  NULL, 0,
1107  (SQLCHAR *) tblname, SQL_NTS,
1108  0, 0));
1109 
1110 SPEW(0, rc, odbc);
1111  return rc;
1112 }
1113 
1114 int odbcExecDirect(ODBC_t odbc, const char * s, size_t ns)
1115 {
1116  SQLHANDLE * stmt;
1117  int rc = 0;
1118 
1119 DBG(0, (stderr, "--> %s(%p,%s,%u)\n", __FUNCTION__, odbc, s, (unsigned)ns));
1120 
1121  if (ns == 0)
1122  ns = strlen(s);
1123 
1124  if (odbc->stmt == NULL)
1125  odbc->stmt = hAlloc(odbc, SQL_HANDLE_STMT);
1126  stmt = odbc->stmt->hp;
1127 
1128  rc = CHECK(odbc, SQL_HANDLE_STMT, "SQLExecDirect",
1129  SQLExecDirect(stmt, (SQLCHAR *) s, (SQLINTEGER) ns));
1130 
1131 SPEW(0, rc, odbc);
1132  return rc;
1133 }
1134 
1135 int odbcPrepare(ODBC_t odbc, const char * s, size_t ns)
1136 {
1137  SQLHANDLE * stmt;
1138  int rc = 0;
1139 
1140 DBG(0, (stderr, "--> %s(%p,%s,%u)\n", __FUNCTION__, odbc, s, (unsigned)ns));
1141 
1142  if (ns == 0)
1143  ns = strlen(s);
1144 
1145  /* XXX FIXME: programmer error */
1146  odbc->stmt = hFree(odbc, odbc->stmt);
1147 
1148  if (odbc->stmt == NULL)
1149  odbc->stmt = hAlloc(odbc, SQL_HANDLE_STMT);
1150  stmt = odbc->stmt->hp;
1151 
1152  rc = CHECK(odbc, SQL_HANDLE_STMT, "SQLPrepare",
1153  SQLPrepare(stmt, (SQLCHAR *) s, (SQLINTEGER) ns));
1154 
1155 SPEW(0, rc, odbc);
1156  return rc;
1157 }
1158 
1159 int odbcBindCol(ODBC_t odbc, unsigned short ColumnNumber, short TargetType,
1160  void * TargetValuePtr, long BufferLength, long * StrLen_or_Ind)
1161 {
1162  SQLHANDLE * stmt = odbc->stmt->hp;
1163  int rc = CHECK(odbc, SQL_HANDLE_STMT, "SQLBindCol",
1164  SQLBindCol(stmt,
1165  ColumnNumber,
1166  TargetType,
1167  TargetValuePtr,
1168  BufferLength,
1169  StrLen_or_Ind));
1170  (void)stmt;
1171 
1172 SPEW(0, rc, odbc);
1173  return rc;
1174 }
1175 
1177 {
1178  SQLHANDLE * stmt = odbc->stmt->hp;
1179  int rc = CHECK(odbc, SQL_HANDLE_STMT, "SQLBindParameter",
1180  SQLBindParameter(stmt,
1181  param->ParameterNumber,
1182  param->InputOutputType,
1183  param->ValueType,
1184  param->ParameterType,
1185  param->ColumnSize,
1186  param->DecimalDigits,
1187  param->ParameterValuePtr,
1188  param->BufferLength,
1189  param->StrLen_or_IndPtr));
1190  (void)stmt;
1191 
1192 SPEW(0, rc, odbc);
1193  return rc;
1194 }
1195 
1197 {
1198  SQLHANDLE * stmt = odbc->stmt->hp;
1199  int rc = CHECK(odbc, SQL_HANDLE_STMT, "SQLExecute",
1200  SQLExecute(stmt));
1201  (void)stmt;
1202 
1203 SPEW(0, rc, odbc);
1204  return rc;
1205 }
1206 
1207 /*==============================================================*/
1208 
1209 static void odbcFini(void * _odbc)
1210  /*@globals fileSystem @*/
1211  /*@modifies *_odbc, fileSystem @*/
1212 {
1213  ODBC_t odbc = _odbc;
1214 
1215  odbc->desc = hFree(odbc, odbc->desc);
1216  odbc->stmt = hFree(odbc, odbc->stmt);
1217  odbc->dbc = hFree(odbc, odbc->dbc);
1218  odbc->env = hFree(odbc, odbc->env);
1219 
1220  odbc->db = _free(odbc->db);
1221  odbc->u = urlFree(odbc->u, __FUNCTION__);
1222  odbc->fn = _free(odbc->fn);
1223 }
1224 
1225 /*@unchecked@*/ /*@only@*/ /*@null@*/
1227 
1228 static ODBC_t odbcGetPool(/*@null@*/ rpmioPool pool)
1229  /*@globals _odbcPool, fileSystem @*/
1230  /*@modifies pool, _odbcPool, fileSystem @*/
1231 {
1232  ODBC_t odbc;
1233 
1234  if (_odbcPool == NULL) {
1235  _odbcPool = rpmioNewPool("odbc", sizeof(*odbc), -1, _odbc_debug,
1236  NULL, NULL, odbcFini);
1237  pool = _odbcPool;
1238  }
1239  odbc = (ODBC_t) rpmioGetPool(pool, sizeof(*odbc));
1240  memset(((char *)odbc)+sizeof(odbc->_item), 0, sizeof(*odbc)-sizeof(odbc->_item));
1241  return odbc;
1242 }
1243 
1244 static char * _odbc_uri = "mysql://luser:jasnl@localhost/test";
1245 
1246 ODBC_t odbcNew(const char * fn, int flags)
1247 {
1248  ODBC_t odbc = odbcGetPool(_odbcPool);
1249 int xx;
1250 
1251  if (fn == NULL)
1252  fn = _odbc_uri;
1253  odbc->fn = xstrdup(fn);
1254  odbc->flags = flags;
1255 
1256  { const char * dbpath = NULL;
1257  int ut = urlPath(fn, &dbpath);
1258  urlinfo u = NULL;
1259 
1260  xx = urlSplit(fn, &u);
1261 assert(ut == URL_IS_MYSQL || ut == URL_IS_POSTGRES || URL_IS_SQLSERVER);
1262  odbc->db = rpmExpand(u->scheme, "_", basename((char *)dbpath), NULL);
1263  odbc->u = urlLink(u, __FUNCTION__);
1264  }
1265 
1266  odbc->env = hAlloc(odbc, SQL_HANDLE_ENV);
1267 #if defined(WITH_UNIXODBC)
1268  xx = odbcSetEnvAttr(odbc, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);
1269 #endif
1270 
1271 if (_odbc_debug < 0)
1272 xx = odbcDumpEnvAttr(odbc, NULL);
1273 
1274  /* XXX FIXME: SQLDriverConnect should be done here. */
1275 
1276  return odbcLink(odbc);
1277 }
const bson * b
Definition: bson.h:280
int odbcColAttribute(ODBC_t odbc, unsigned short ColumnNumber, unsigned short FieldIdentifier, void *CharacterAttributePtr, short BufferLength, short *StringLengthPtr, long *NumericAttributePtr)
Definition: rpmodbc.c:660
int odbcStatistics(ODBC_t odbc, const char *tblname)
Definition: rpmodbc.c:1094
const char * scheme
Definition: rpmurl.h:57
#define SQL_ROLLBACK
Definition: rpmodbc.c:59
static size_t nSQL_INFOS
Definition: rpmodbc.c:462
ODBC_t odbcLink(ODBC_t odbc)
Reference a odbc wrapper instance.
int odbcGetStmtAttr(ODBC_t odbc, int _attr, void *_bp, int _nb, int *nsp)
Definition: rpmodbc.c:258
#define SQL_C_CHAR
Definition: rpmodbc.c:45
const char const char size_t len
Definition: bson.h:823
static KEY SQL_CATTRS[]
Definition: rpmodbc.c:591
const char * password
Definition: rpmurl.h:61
const char * user
Definition: rpmurl.h:59
#define SQL_COMMIT
Definition: rpmodbc.c:58
char * xstrdup(const char *str)
Definition: rpmmalloc.c:321
URL control structure.
Definition: rpmurl.h:52
int odbcExecute(ODBC_t odbc)
Definition: rpmodbc.c:1196
Definition: libsql.c:29
int odbcSetEnvAttr(ODBC_t odbc, int _type, void *_bp, int ns)
Definition: rpmodbc.c:579
static KEY SQL_INFOS[]
Definition: rpmodbc.c:281
ODBC_t odbcNew(const char *fn, int flags)
Create and load a odbc wrapper.
Definition: rpmodbc.c:1246
#define SQL_SUCCEEDED(rc)
Definition: rpmodbc.c:36
int odbcCancel(ODBC_t odbc)
Definition: rpmodbc.c:927
int odbcCloseCursor(ODBC_t odbc)
Definition: rpmodbc.c:687
static size_t nSQL_EATTRS
Definition: rpmodbc.c:539
static int odbcDumpInfo(ODBC_t odbc, void *_fp)
Definition: rpmodbc.c:464
#define _ENTRY(_t, _v)
Definition: rpmodbc.c:590
int odbcPrepare(ODBC_t odbc, const char *s, size_t ns)
Definition: rpmodbc.c:1135
int odbcNCols(ODBC_t odbc)
Definition: rpmodbc.c:912
int odbcGetData(ODBC_t odbc, unsigned short Col_or_Param_Num, short TargetType, void *TargetValuePtr, long BufferLength, long *StrLen_or_IndPtr)
Definition: rpmodbc.c:967
static KEY SQL_ATTRS[]
Definition: rpmodbc.c:162
int odbcListDrivers(ODBC_t odbc, void *_fp)
Definition: rpmodbc.c:864
static void * hAlloc(ODBC_t odbc, int ht)
Definition: rpmodbc.c:128
struct ODBC_s * ODBC_t
Definition: rpmodbc.h:15
static KEY SQL_EATTRS[]
Definition: rpmodbc.c:525
static void odbcFini(void *_odbc)
Definition: rpmodbc.c:1209
int odbcRollback(ODBC_t odbc)
Definition: rpmodbc.c:757
static int odbcDumpEnvAttr(ODBC_t odbc, void *_fp)
Definition: rpmodbc.c:541
rpmioPool _odbcPool
Definition: rpmodbc.c:1226
Yet Another syslog(3) API clone.
rpmioItem rpmioGetPool(rpmioPool pool, size_t size)
Get unused item from pool, or alloc a new item.
Definition: rpmmalloc.c:220
#define DBG(_t, _l)
Definition: rpmodbc.c:26
struct HNDL_s * HNDL_t
Definition: rpmodbc.h:16
int odbcNRows(ODBC_t odbc)
Definition: rpmodbc.c:897
ARGV_t argvFree(ARGV_t argv)
Destroy an argv array.
Definition: argv.c:44
int odbcGetInfo(ODBC_t odbc, int _type, void *_bp, int _nb, short *nsp)
Definition: rpmodbc.c:513
uint32_t v
Definition: libsql.c:31
int32_t t
Definition: rpmodbc.c:156
int odbcPrint(ODBC_t odbc, void *_fp)
Definition: rpmodbc.c:990
static ODBC_t odbcGetPool(rpmioPool pool)
Definition: rpmodbc.c:1228
#define SQL_FETCH_FIRST
Definition: rpmodbc.c:39
int argvAdd(ARGV_t *argvp, ARGstr_t val)
Add a string to an argv array.
Definition: argv.c:199
int odbcFetch(ODBC_t odbc)
Definition: rpmodbc.c:941
#define CHECK(_o, _t, _m, _rc)
Definition: rpmodbc.c:110
char * rpmExpand(const char *arg,...)
Return (malloc'ed) concatenated macro expansion(s).
Definition: macro.c:3252
#define URL_IS_SQLSERVER
Definition: rpmurl.h:30
const char const bson int mongo_write_concern int flags
Definition: mongo.h:485
int odbcBindParameter(ODBC_t odbc, _PARAM_t param)
Definition: rpmodbc.c:1176
int odbcSetStmtAttr(ODBC_t odbc, int _attr, void *_bp, int ns)
Definition: rpmodbc.c:269
#define SQL_NO_DATA
Definition: rpmodbc.c:37
#define SQL_COLUMN_LABEL
Definition: rpmodbc.c:56
int odbcTables(ODBC_t odbc, const char *tblname)
Definition: rpmodbc.c:1054
int odbcBindCol(ODBC_t odbc, unsigned short ColumnNumber, short TargetType, void *TargetValuePtr, long BufferLength, long *StrLen_or_Ind)
Definition: rpmodbc.c:1159
int urlSplit(const char *url, urlinfo *uret)
Parse URL string into a control structure.
Definition: url.c:476
int _odbc_debug
Definition: rpmodbc.c:24
const char const int i
Definition: bson.h:778
int odbcFetchScroll(ODBC_t odbc, short FetchOrientation, long FetchOffset)
Definition: rpmodbc.c:954
urltype urlPath(const char *url, const char **pathp)
Return path component of URL.
Definition: url.c:430
static int snprintf(char *buf, int nb, const char *fmt,...)
Definition: rpmps.c:220
#define LABEL
Definition: rpmmtree.c:2039
rpmioPool rpmioNewPool(const char *name, size_t size, int limit, int flags, char *(*dbg)(void *item), void(*init)(void *item), void(*fini)(void *item))
Create a memory pool.
Definition: rpmmalloc.c:109
#define SPEW(_t, _rc, _odbc)
Definition: rpmodbc.c:29
const char * odbcGetCursorName(ODBC_t odbc)
Definition: rpmodbc.c:700
int odbcEndTran(ODBC_t odbc, int _rollback)
Definition: rpmodbc.c:738
static void * _free(const void *p)
Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
Definition: rpmiotypes.h:756
#define URL_IS_POSTGRES
Definition: rpmurl.h:29
const char * db
Definition: mongo.h:697
int odbcCommit(ODBC_t odbc)
Definition: rpmodbc.c:752
static size_t nSQL_ATTRS
Definition: rpmodbc.c:207
static size_t nSQL_CATTRS
Definition: rpmodbc.c:618
int odbcGetEnvAttr(ODBC_t odbc, int _type, void *_bp, int _nb, int *nsp)
Definition: rpmodbc.c:569
int odbcDisconnect(ODBC_t odbc)
Definition: rpmodbc.c:814
int odbcListDataSources(ODBC_t odbc, void *_fp)
Definition: rpmodbc.c:831
#define SQL_FETCH_NEXT
Definition: rpmodbc.c:38
int odbcConnect(ODBC_t odbc, const char *uri)
Definition: rpmodbc.c:764
static int odbcDumpColAttrs(ODBC_t odbc, int colx, void *_fp)
Definition: rpmodbc.c:620
#define xmalloc
Definition: system.h:32
static char * columns[30]
Definition: rpmrpc.c:451
ARGstr_t * ARGV_t
Definition: argv.h:12
int odbcExecDirect(ODBC_t odbc, const char *s, size_t ns)
Definition: rpmodbc.c:1114
static int odbcDumpStmt(ODBC_t odbc, void *_fp)
Definition: rpmodbc.c:209
const char * n
Definition: db3.c:184
struct key_s KEY
urlinfo urlFree(urlinfo u, const char *msg)
Dereference a URL control structure instance.
#define URL_IS_MYSQL
Definition: rpmurl.h:28
static char * _odbc_uri
Definition: rpmodbc.c:1244
static void * hFree(ODBC_t odbc, HNDL_t H)
Definition: rpmodbc.c:113
int odbcColumns(ODBC_t odbc, const char *tblname, const char *colname)
Definition: rpmodbc.c:1074
int odbcSetCursorName(ODBC_t odbc, const char *s, size_t ns)
Definition: rpmodbc.c:721
const char * ns
Definition: mongo.h:326
struct _PARAM_s * _PARAM_t
Definition: rpmodbc.h:19
urlinfo urlLink(urlinfo u, const char *msg)
Reference a URL control structure instance.