· 8 years ago · Mar 02, 2018, 07:50 PM
1/* $Id: dbdimp.c 12185 2008-12-19 19:39:22Z mjevans $
2 *
3 * portions Copyright (c) 1994,1995,1996,1997 Tim Bunce
4 * portions Copyright (c) 1997 Thomas K. Wenrich
5 * portions Copyright (c) 1997-2001 Jeff Urlwin
6 * portions Copyright (c) 2007-2008 Martin J. Evans
7 *
8 * You may distribute under the terms of either the GNU General Public
9 * License or the Artistic License, as specified in the Perl README file.
10 *
11 */
12
13/*
14 * NOTES:
15 *
16 * o Trace levels 1 and 2 are reserved for DBI (see DBI::DBD) so don't
17 * use them here in DBIc_TRACE_LEVEL tests.
18 * "Trace Levels" in DBI defines trace levels as:
19 * 0 - Trace disabled.
20 * 1 - Trace DBI method calls returning with results or errors.
21 * 2 - Trace method entry with parameters and returning with results.
22 * 3 - As above, adding some high-level information from the driver
23 * and some internal information from the DBI.
24 * 4 - As above, adding more detailed information from the driver.
25 * 5 to 15 - As above but with more and more obscure information.
26 */
27
28#include "ODBC.h"
29#if defined(WITH_UNICODE)
30# include "unicode_helper.h"
31#endif
32
33#if defined(WITH_UNICODE) && (defined(_IODBCUNIX_H) || defined(_IODBCEXT_H))
34#error DBD::ODBC will not run properly with iODBC in unicode mode as iODBC defines wide characters as being 4 bytes in size
35#endif
36
37/* Can't find a constant in DBI for SQL tracing but it is 256 */
38#define SQL_TRACE_FLAG 0x100
39#define TRACE0(a,b) PerlIO_printf(DBIc_LOGPIO(a), (b))
40#define TRACE1(a,b,c) PerlIO_printf(DBIc_LOGPIO(a), (b), (c))
41#define TRACE2(a,b,c,d) PerlIO_printf(DBIc_LOGPIO(a), (b), (c), (d))
42#define TRACE3(a,b,c,d,e) PerlIO_printf(DBIc_LOGPIO(a), (b), (c), (d), (e))
43
44static SQLSMALLINT default_parameter_type(imp_sth_t *imp_sth);
45static int post_connect(SV *dbh, imp_dbh_t *imp_dbh, SV *attr);
46static int set_odbc_version(SV *dbh, imp_dbh_t *imp_dbh, SV* attr);
47static const char *S_SqlTypeToString (SWORD sqltype);
48static const char *S_SqlCTypeToString (SWORD sqltype);
49static const char *cSqlTables = "SQLTables(%s,%s,%s,%s)";
50static const char *cSqlPrimaryKeys = "SQLPrimaryKeys(%s,%s,%s)";
51static const char *cSqlStatistics = "SQLStatistics(%s,%s,%s,%d,%d)";
52static const char *cSqlForeignKeys = "SQLForeignKeys(%s,%s,%s,%s,%s,%s)";
53static const char *cSqlColumns = "SQLColumns(%s,%s,%s,%s)";
54static const char *cSqlGetTypeInfo = "SQLGetTypeInfo(%d)";
55static void AllODBCErrors(HENV henv, HDBC hdbc, HSTMT hstmt, int output, PerlIO *logfp);
56static int check_connection_active(SV *h);
57static int build_results(SV *sth, SV *dbh, RETCODE orc);
58
59/* AV *dbd_st_fetch(SV * sth, imp_sth_t *imp_sth); */
60int dbd_describe(SV *h, imp_sth_t *imp_sth, int more);
61int dbd_db_login6_sv(SV *dbh, imp_dbh_t *imp_dbh, SV *dbname, SV *uid, SV *pwd, SV *attr);
62int dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, SV *attr);
63int dbd_st_finish(SV *sth, imp_sth_t *imp_sth);
64
65#define av_sz(av) (av_len(av) + 1)
66
67/* for sanity/ease of use with potentially null strings */
68#define XXSAFECHAR(p) ((p) ? (p) : "(null)")
69
70/* unique value for db attrib that won't conflict with SQL types, just
71 * increment by one if you are adding! */
72#define ODBC_IGNORE_NAMED_PLACEHOLDERS 0x8332
73#define ODBC_DEFAULT_BIND_TYPE 0x8333
74#define ODBC_ASYNC_EXEC 0x8334
75#define ODBC_ERR_HANDLER 0x8335
76#define ODBC_ROWCACHESIZE 0x8336
77#define ODBC_ROWSINCACHE 0x8337
78#define ODBC_FORCE_REBIND 0x8338
79#define ODBC_EXEC_DIRECT 0x8339
80#define ODBC_VERSION 0x833A
81#define ODBC_CURSORTYPE 0x833B
82#define ODBC_QUERY_TIMEOUT 0x833C
83#define ODBC_HAS_UNICODE 0x833D
84#define ODBC_PUTDATA_START 0x833E
85#define ODBC_OUTCON_STR 0x833F
86#define ODBC_COLUMN_DISPLAY_SIZE 0x8340
87
88/* This is the bind type for parameters we fall back to if the bind_param
89 method was not given a parameter type and SQLDescribeParam is not supported
90 or failed */
91#ifdef WITH_UNICODE
92# define ODBC_BACKUP_BIND_TYPE_VALUE SQL_WVARCHAR
93#else
94# define ODBC_BACKUP_BIND_TYPE_VALUE SQL_VARCHAR
95#endif
96
97SV *dbd_param_err(SQLHANDLE h, int recno);
98static int rebind_param(SV *sth, imp_sth_t *imp_sth, phs_t *phs);
99static void get_param_type(SV *sth, imp_sth_t *imp_sth, phs_t *phs);
100
101
102DBISTATE_DECLARE;
103
104void dbd_init(dbistate_t *dbistate)
105{
106 DBIS = dbistate;
107}
108
109
110
111static RETCODE odbc_set_query_timeout(SV *h, HSTMT hstmt, UV odbc_timeout)
112{
113 RETCODE rc;
114 D_imp_xxh(h);
115 if (DBIc_TRACE(imp_xxh, 0, 0, 3)) {
116 TRACE1(imp_xxh, " Set timeout to: %d\n", odbc_timeout);
117 }
118 rc = SQLSetStmtAttr(hstmt,(SQLINTEGER)SQL_ATTR_QUERY_TIMEOUT,
119 (SQLPOINTER)odbc_timeout,(SQLINTEGER)SQL_IS_INTEGER);
120 if (!SQL_SUCCEEDED(rc)) {
121 /* raise warnings if setting fails, but don't die? */
122 if (DBIc_TRACE(imp_xxh, 0, 0, 3))
123 TRACE1(imp_xxh,
124 " !!Failed to set Statement ATTR Query Timeout to %d\n",
125 (int)odbc_timeout);
126 }
127 return rc;
128}
129#if 0
130static UV odbc_get_query_timeout(imp_dbh_t *imp_dbh) {
131 RETCODE rc;
132 UV timeout;
133 rc = SQLGetConnectAttr(imp_dbh->hdbc,
134 (SQLINTEGER)SQL_ATTR_QUERY_TIMEOUT,
135 (SQLPOINTER)&timeout,sizeof(timeout), 0);
136 if (!SQL_SUCCEEDED(rc)) {
137 if (DBIc_TRACE(imp_dbh, 0, 0, 3))
138 TRACE1(imp_dbh, " !!Failed to get ATTR query Timeout %d\n", rc);
139 }
140 return timeout;
141}
142#endif /* 0 */
143
144
145
146static void odbc_clear_result_set(SV *sth, imp_sth_t *imp_sth)
147{
148 SV *value;
149 char *key;
150 I32 keylen;
151
152 Safefree(imp_sth->fbh);
153 Safefree(imp_sth->ColNames);
154 Safefree(imp_sth->RowBuffer);
155
156 /* dgood - Yikes! I don't want to go down to this level, */
157 /* but if I don't, it won't figure out that the */
158 /* number of columns have changed... */
159 if (DBIc_FIELDS_AV(imp_sth)) {
160 sv_free((SV*)DBIc_FIELDS_AV(imp_sth));
161 DBIc_FIELDS_AV(imp_sth) = Nullav;
162 }
163
164 while ( (value = hv_iternextsv((HV*)SvRV(sth), &key, &keylen)) ) {
165 if (strncmp(key, "NAME_", 5) == 0 ||
166 strncmp(key, "TYPE", 4) == 0 ||
167 strncmp(key, "PRECISION", 9) == 0 ||
168 strncmp(key, "SCALE", 5) == 0 ||
169 strncmp(key, "NULLABLE", 8) == 0
170 ) {
171 hv_delete((HV*)SvRV(sth), key, keylen, G_DISCARD);
172 if (DBIc_TRACE(imp_sth, 0, 0, 4)) {
173 TRACE2(imp_sth, " ODBC_CLEAR_RESULTS '%s' => %s\n",
174 key, neatsvpv(value,0));
175 }
176 }
177 }
178 /*
179 PerlIO_printf(DBILOGFP,"CLEAR RESULTS cached attributes:\n");
180 while ( (value = hv_iternextsv((HV*)SvRV(inner), &key, &keylen)) ) {
181 PerlIO_printf(DBILOGFP,"CLEARRESULTS '%s' => %s\n", key, neatsvpv(value,0));
182 }
183*/
184
185 imp_sth->fbh = NULL;
186 imp_sth->ColNames = NULL;
187 imp_sth->RowBuffer = NULL;
188 imp_sth->done_desc = 0;
189
190}
191
192
193
194static void odbc_handle_outparams(imp_sth_t *imp_sth, int debug)
195{
196 int i = (imp_sth->out_params_av) ? AvFILL(imp_sth->out_params_av)+1 : 0;
197 if (debug >= 3)
198 TRACE1(imp_sth, " processing %d output parameters\n", i);
199
200 while (--i >= 0) {
201 phs_t *phs = (phs_t*)(void*)SvPVX(AvARRAY(imp_sth->out_params_av)[i]);
202 SV *sv = phs->sv;
203 if (debug >= 8) {
204 TRACE2(imp_sth, " outparam %s, length:%d\n",
205 phs->name, phs->strlen_or_ind);
206 }
207
208 /* phs->strlen_or_ind has been updated by ODBC to hold the length
209 * of the result */
210 if (phs->strlen_or_ind != SQL_NULL_DATA) {
211 /*
212 * When ODBC fills an output parameter buffer, the size of the
213 * data that were available is written into the memory location
214 * provided by strlen_or_ind pointer argument during the
215 * SQLBindParameter() call.
216 *
217 * If the number of bytes available exceeds the size of the output
218 * buffer, ODBC will truncate the data such that it fits in the
219 * available buffer. However, the strlen_or_ind will still reflect
220 * the size of the data before it was truncated.
221 *
222 * This fact provides us a way to detect truncation on this particular
223 * output parameter. Otherwise, the only way to detect truncation is
224 * through a follow-up to a SQL_SUCCESS_WITH_INFO result. Such a call
225 * cannot return enough information to state exactly where the
226 * truncation occurred.
227 */
228 SvPOK_only(sv); /* string, disable other OK bits */
229 if (phs->strlen_or_ind > phs->maxlen) { /* out param truncated */
230 SvCUR_set(sv, phs->maxlen);
231 *SvEND(sv) = '\0'; /* null terminate */
232
233 if (debug >= 2) {
234 PerlIO_printf(
235 DBIc_LOGPIO(imp_sth),
236 " outparam %s = '%s'\t(TRUNCATED from %ld to %ld)\n",
237 phs->name, SvPV_nolen(sv), (long)phs->strlen_or_ind,
238 (long)phs->maxlen);
239 }
240 } else { /* no truncation occurred */
241 SvCUR_set(sv, phs->strlen_or_ind); /* new length */
242 *SvEND(sv) = '\0'; /* null terminate */
243 if (phs->strlen_or_ind == phs->maxlen &&
244 (phs->sql_type == SQL_NUMERIC ||
245 phs->sql_type == SQL_DECIMAL ||
246 phs->sql_type == SQL_INTEGER ||
247 phs->sql_type == SQL_SMALLINT ||
248 phs->sql_type == SQL_FLOAT ||
249 phs->sql_type == SQL_REAL ||
250 phs->sql_type == SQL_DOUBLE)) {
251 /*
252 * fix up for oracle, which leaves the buffer at the size
253 * requested, but only returns a few characters. The
254 * intent is to truncate down to the actual number of
255 * characters necessary. Need to find the first null
256 * byte and set the length there.
257 */
258 char *pstart = SvPV_nolen(sv);
259 char *p = pstart;
260 while (*p != '\0') {
261 p++;
262 }
263
264 if (debug >= 2) {
265 PerlIO_printf(
266 DBIc_LOGPIO(imp_sth),
267 " outparam %s = '%s'\t(len %ld), is numeric end"
268 " of buffer = %d\n",
269 phs->name, SvPV(sv,na), (long)phs->strlen_or_ind,
270 phs->sql_type, p - pstart);
271 }
272 SvCUR_set(sv, p - pstart);
273 }
274 }
275 } else { /* is NULL */
276 if (debug >= 2)
277 TRACE1(imp_sth, " outparam %s = undef (NULL)\n", phs->name);
278 (void)SvOK_off(phs->sv);
279 }
280 }
281}
282
283
284
285static int build_results(SV *sth, SV *dbh, RETCODE orc)
286{
287 RETCODE rc;
288 D_imp_dbh(dbh);
289 D_imp_sth(sth);
290 dTHR;
291
292 if (DBIc_TRACE(imp_sth, 0, 0, 3))
293 TRACE2(imp_sth, " build_results sql f%d\n\t%s\n",
294 imp_sth->hstmt, imp_sth->statement);
295
296 /* init sth pointers */
297 imp_sth->fbh = NULL;
298 imp_sth->ColNames = NULL;
299 imp_sth->RowBuffer = NULL;
300 imp_sth->RowCount = -1;
301 imp_sth->eod = -1;
302
303 imp_sth->odbc_column_display_size = imp_dbh->odbc_column_display_size;
304
305 if (!dbd_describe(sth, imp_sth, 0)) {
306 /* SQLFreeStmt(imp_sth->hstmt, SQL_DROP); */ /* TBD: 3.0 update */
307 if (DBIc_TRACE(imp_sth, 0, 0, 3)) {
308 TRACE0(imp_sth, " !!dbd_describe failed, build_results...!\n");
309 }
310 SQLFreeHandle(SQL_HANDLE_STMT, imp_sth->hstmt);
311 imp_sth->hstmt = SQL_NULL_HSTMT;
312 return 0; /* dbd_describe already called dbd_error() */
313 }
314
315 if (DBIc_TRACE(imp_sth, 0, 0, 3)) {
316 TRACE0(imp_sth, " dbd_describe build_results #2...!\n");
317 }
318 if (dbd_describe(sth, imp_sth, 0) <= 0) {
319 if (DBIc_TRACE(imp_sth, 0, 0, 3)) {
320 TRACE0(imp_sth, " dbd_describe build_results #3...!\n");
321 }
322 return 0;
323 }
324
325 DBIc_IMPSET_on(imp_sth);
326
327 if (orc != SQL_NO_DATA) {
328 imp_sth->RowCount = -1;
329 rc = SQLRowCount(imp_sth->hstmt, &imp_sth->RowCount);
330 dbd_error(sth, rc, "build_results/SQLRowCount");
331 if (rc != SQL_SUCCESS) {
332 return -1;
333 }
334 } else {
335 imp_sth->RowCount = 0;
336 }
337
338 DBIc_ACTIVE_on(imp_sth); /* XXX should only set for select ? */
339 imp_sth->eod = SQL_SUCCESS;
340 return 1;
341}
342
343
344
345int odbc_discon_all(SV *drh, imp_drh_t *imp_drh)
346{
347 dTHR;
348 /* The disconnect_all concept is flawed and needs more work */
349 if (!dirty && !SvTRUE(perl_get_sv("DBI::PERL_ENDING",0))) {
350 DBIh_SET_ERR_CHAR(drh, (imp_xxh_t*)imp_drh, Nullch, 1,
351 "disconnect_all not implemented", Nullch, Nullch);
352 return FALSE;
353 }
354 return FALSE;
355}
356
357
358
359
360/* error : <=(-2), ok row count : >=0, unknown count : (-1) */
361int dbd_db_execdirect( SV *dbh,
362 SV *statement )
363{
364 D_imp_dbh(dbh);
365 SQLRETURN ret;
366 SQLLEN rows;
367 SQLHSTMT stmt;
368 int dbh_active;
369 char *sql;
370 STRLEN sql_len;
371
372 sql = SvPV(statement, sql_len);
373
374 if ((dbh_active = check_connection_active(dbh)) == 0) return 0;
375
376 ret = SQLAllocHandle(SQL_HANDLE_STMT, imp_dbh->hdbc, &stmt );
377 if (!SQL_SUCCEEDED(ret)) {
378 dbd_error( dbh, ret, "Statement allocation error" );
379 return(-2);
380 }
381
382 /* if odbc_query_timeout has been set, set it in the driver */
383 if (imp_dbh->odbc_query_timeout != -1) {
384 ret = odbc_set_query_timeout(dbh, stmt, imp_dbh->odbc_query_timeout);
385 if (!SQL_SUCCEEDED(ret)) {
386 dbd_error(dbh, ret, "execdirect set_query_timeout");
387 }
388 /* don't fail if the query timeout can't be set. */
389 }
390
391 if (DBIc_TRACE(imp_dbh, SQL_TRACE_FLAG, 0, 3)) {
392 TRACE1(imp_dbh, " SQLExecDirect %s\n", SvPV_nolen(statement));
393 }
394
395#ifdef WITH_UNICODE
396 if (SvOK(statement) && DO_UTF8(statement)) {
397 SQLWCHAR *wsql;
398 STRLEN wsql_len;
399 SV *sql_copy;
400
401 if (DBIc_TRACE(imp_dbh, 0x02000000, 0, 0))
402 TRACE0(imp_dbh, " Processing utf8 sql in unicode mode\n");
403
404 sql_copy = sv_mortalcopy(statement);
405
406 SV_toWCHAR(sql_copy);
407
408 wsql = (SQLWCHAR *)SvPV(sql_copy, wsql_len);
409
410 ret = SQLExecDirectW(stmt, wsql, wsql_len / sizeof(SQLWCHAR));
411 } else {
412 if (DBIc_TRACE(imp_dbh, 0x02000000, 0, 0))
413 TRACE0(imp_dbh, " Processing utf8 sql in non-unicode mode\n");
414
415 ret = SQLExecDirect(stmt, (SQLCHAR *)sql, SQL_NTS);
416 }
417#else
418 if (DBIc_TRACE(imp_dbh, 0x02000000, 0, 0))
419 TRACE0(imp_dbh, " Processing utf8 sql in non-unicode mode\n");
420 ret = SQLExecDirect(stmt, (SQLCHAR *)sql, SQL_NTS);
421#endif
422 if (DBIc_TRACE(imp_dbh, 0, 0, 3))
423 TRACE1(imp_dbh, " SQLExecDirect = %d\n", ret);
424 if (!SQL_SUCCEEDED(ret) && ret != SQL_NO_DATA) {
425 dbd_error2(dbh, ret, "Execute immediate failed",
426 imp_dbh->henv, imp_dbh->hdbc, stmt );
427 if (ret < 0) {
428 rows = -2;
429 }
430 else {
431 rows = -3; /* ?? */
432 }
433 }
434 else {
435 if (ret == SQL_NO_DATA) {
436 rows = 0;
437 } else {
438 ret = SQLRowCount(stmt, &rows);
439 if (!SQL_SUCCEEDED(ret)) {
440 dbd_error( dbh, ret, "SQLRowCount failed" );
441 if (ret < 0)
442 rows = -1;
443 }
444 }
445 }
446 ret = SQLFreeHandle(SQL_HANDLE_STMT,stmt);
447 if (!SQL_SUCCEEDED(ret)) {
448 dbd_error2(dbh, ret, "Statement destruction error",
449 imp_dbh->henv, imp_dbh->hdbc, stmt);
450 }
451
452 return (int)rows;
453}
454
455
456
457void dbd_db_destroy(SV *dbh, imp_dbh_t *imp_dbh)
458{
459 if (DBIc_ACTIVE(imp_dbh))
460 dbd_db_disconnect(dbh, imp_dbh);
461 /* Nothing in imp_dbh to be freed */
462
463 DBIc_IMPSET_off(imp_dbh);
464 if (DBIc_TRACE(imp_dbh, 0, 0, 8))
465 TRACE0(imp_dbh, " DBD::ODBC Disconnected!\n");
466}
467
468
469
470
471/*
472 * quick dumb function to handle case insensitivity for DSN= or DRIVER=
473 * in DSN...note this is becuase strncmpi is not available on all
474 * platforms using that name (VC++, Debian, etc most notably).
475 * Note, also, strupr doesn't seem to have a standard name, either...
476 */
477
478int dsnHasDriverOrDSN(char *dsn) {
479
480 char upper_dsn[512];
481 char *cp = upper_dsn;
482 strncpy(upper_dsn, dsn, sizeof(upper_dsn)-1);
483 upper_dsn[sizeof(upper_dsn)-1] = '\0';
484 while (*cp != '\0') {
485 *cp = toupper(*cp);
486 cp++;
487 }
488 return (strncmp(upper_dsn, "DSN=", 4) == 0 ||
489 strncmp(upper_dsn, "DRIVER=", 7) == 0);
490}
491
492
493
494int dsnHasUIDorPWD(char *dsn) {
495
496 char upper_dsn[512];
497 char *cp = upper_dsn;
498 strncpy(upper_dsn, dsn, sizeof(upper_dsn)-1);
499 upper_dsn[sizeof(upper_dsn)-1] = '\0';
500 while (*cp != '\0') {
501 *cp = toupper(*cp);
502 cp++;
503 }
504 return (strstr(upper_dsn, "UID=") != 0 || strstr(upper_dsn, "PWD=") != 0);
505}
506
507
508
509/*------------------------------------------------------------
510connecting to a data source.
511Allocates henv and hdbc.
512NOTE: This is the old 5 argument version
513------------------------------------------------------------*/
514int
515 dbd_db_login(dbh, imp_dbh, dbname, uid, pwd)
516 SV *dbh; imp_dbh_t *imp_dbh; char *dbname; char *uid; char *pwd;
517{
518 return dbd_db_login6(dbh, imp_dbh, dbname, uid, pwd, Nullsv);
519}
520
521
522
523/************************************************************************/
524/* */
525/* dbd_db_login6_sv */
526/* ================ */
527/* */
528/* This API was introduced to DBI after 1.607 (subversion revision */
529/* 11723) and is the same as dbd_db_login6 except the connection */
530/* strings are SVs so we can detect unicode strings and call */
531/* SQLDriverConnectW. */
532/* */
533/************************************************************************/
534int dbd_db_login6_sv(
535 SV *dbh,
536 imp_dbh_t *imp_dbh,
537 SV *dbname,
538 SV *uid,
539 SV *pwd,
540 SV *attr)
541{
542#ifndef WITH_UNICODE
543 if (DBIc_TRACE(imp_dbh, 0x04000000, 0, 0))
544 TRACE0(imp_dbh, "non-Unicode login6\n");
545 return dbd_db_login6(dbh, imp_dbh, SvPV_nolen(dbname), SvPV_nolen(uid),
546 SvPV_nolen(pwd), attr);
547#else
548
549 D_imp_drh_from_dbh;
550 dTHR;
551 RETCODE rc;
552 SV *wconstr;
553 SQLWCHAR dc_constr[512];
554 STRLEN dc_constr_len;
555
556 if (DBIc_TRACE(imp_dbh, 0x04000000, 0, 0)) {
557 TRACE0(imp_dbh, "Unicode login6 \n");
558 TRACE2(imp_dbh, "dbname=%s, uid=%s, pwd=xxxxx\n",
559 SvPV_nolen(dbname), SvPV_nolen(uid));
560 }
561
562 imp_dbh->out_connect_string = NULL;
563
564 if (!imp_drh->connects) {
565 rc = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &imp_drh->henv);
566 dbd_error(dbh, rc, "db_login/SQLAllocHandle(env)");
567 if (!SQL_SUCCEEDED(rc)) return 0;
568
569 if (set_odbc_version(dbh, imp_dbh, attr) != 1) return 0;
570 }
571
572 imp_dbh->henv = imp_drh->henv; /* needed for dbd_error */
573
574 rc = SQLAllocHandle(SQL_HANDLE_DBC, imp_drh->henv, &imp_dbh->hdbc);
575 if (!SQL_SUCCEEDED(rc)) {
576 dbd_error(dbh, rc, "db_login/SQLAllocHandle(dbc)");
577 if (imp_drh->connects == 0) {
578 SQLFreeHandle(SQL_HANDLE_ENV, imp_drh->henv);
579 imp_drh->henv = SQL_NULL_HENV;
580 imp_dbh->henv = SQL_NULL_HENV; /* needed for dbd_error */
581 }
582 return 0;
583 }
584
585 /* If the connection string is too long to pass to SQLConnect or it
586 contains DSN or DRIVER, we've little choice to but to call
587 SQLDriverConnect and need to tag the uid/pwd on the end of the
588 connection string (unless they already exist). */
589
590 if ((SvCUR(dbname) > SQL_MAX_DSN_LENGTH ||
591 dsnHasDriverOrDSN(SvPV_nolen(dbname))) &&
592 !dsnHasUIDorPWD(SvPV_nolen(dbname))) {
593 sv_catpvf(dbname, ";UID=%s;PWD=%s;",
594 SvPV_nolen(uid), SvPV_nolen(pwd));
595 if (DBIc_TRACE(imp_dbh, 0x04000000, 0, 0))
596 TRACE1(imp_dbh, "Now using dbname = %s\n", SvPV_nolen(dbname));
597 }
598
599 if (DBIc_TRACE(imp_dbh, 0x04000000, 0, 0))
600 TRACE2(imp_dbh, " SQLDriverConnect '%s', '%s', 'xxxx'\n",
601 SvPV_nolen(dbname), SvPV_nolen(uid));
602
603 wconstr = sv_mortalcopy(dbname);
604#ifdef sv_utf8_decode
605 sv_utf8_decode(wconstr);
606#else
607 SvUTF8_on(wconstr);
608#endif
609 SV_toWCHAR(wconstr);
610
611 /* The following is to work around a bug in SQLDriverConnectW in unixODBC
612 which in at least 2.2.11 (and probably up to 2.2.13 official release
613 [not pre-release]) core dumps if the wide connection string does not end
614 in a 0. */
615 {
616 char *p;
617
618 memset(dc_constr, '\0', sizeof(dc_constr));
619 p = SvPV(wconstr, dc_constr_len);
620 if (dc_constr_len > (sizeof(dc_constr) - 2)) {
621 croak("Cannot process connection string - too long");
622 }
623 memcpy(dc_constr, p, dc_constr_len);
624 }
625
626 {
627 SQLWCHAR wout_str[512];
628 SQLSMALLINT wout_str_len;
629
630 rc = SQLDriverConnectW(imp_dbh->hdbc,
631 0, /* no hwnd */
632 dc_constr,
633 (SQLSMALLINT)(dc_constr_len / sizeof(SQLWCHAR)),
634 wout_str, sizeof(wout_str) / sizeof(wout_str[0]),
635 &wout_str_len,
636 SQL_DRIVER_NOPROMPT);
637 if (SQL_SUCCEEDED(rc)) {
638 imp_dbh->out_connect_string = sv_newwvn(wout_str, wout_str_len);
639 if (DBIc_TRACE(imp_dbh, 0x04000000, 0, 0))
640 TRACE1(imp_dbh, "Out connection string: %s\n",
641 SvPV_nolen(imp_dbh->out_connect_string));
642 }
643 }
644
645 if (!SQL_SUCCEEDED(rc)) {
646 SV *wuid, *wpwd;
647 if (DBIc_TRACE(imp_dbh, 0x04000000, 0, 0))
648 TRACE0(imp_dbh, " SQLDriverConnect failed:\n");
649 /*
650 * Added code for DBD::ODBC 0.39 to help return a better
651 * error code in the case where the user is using a
652 * DSN-less connection and the dbname doesn't look like a
653 * true DSN.
654 */
655 /* wanted to use strncmpi, but couldn't find one on all
656 * platforms. Sigh. */
657 if (SvCUR(dbname) > SQL_MAX_DSN_LENGTH ||
658 dsnHasDriverOrDSN(SvPV_nolen(dbname))) {
659
660 /* must be DSN= or some "direct" connection attributes,
661 * probably best to error here and give the user a real
662 * error code because the SQLConnect call could hide the
663 * real problem.
664 */
665 dbd_error(dbh, rc, "db_login/SQLConnect");
666 SQLFreeHandle(SQL_HANDLE_DBC, imp_dbh->hdbc);
667 if (imp_drh->connects == 0) {
668 SQLFreeHandle(SQL_HANDLE_ENV, imp_drh->henv);
669 imp_drh->henv = SQL_NULL_HENV;
670 imp_dbh->henv = SQL_NULL_HENV; /* needed for dbd_error */
671 }
672 return 0;
673 }
674
675 /* ok, the DSN is short, so let's try to use it to connect
676 * and quietly take all error messages */
677 AllODBCErrors(imp_dbh->henv, imp_dbh->hdbc, 0, 0, DBIc_LOGPIO(imp_dbh));
678
679 if (DBIc_TRACE(imp_dbh, 0x04000000, 0, 0))
680 TRACE2(imp_dbh, " SQLConnect '%s', '%s'\n",
681 neatsvpv(dbname, 0), neatsvpv(uid, 0));
682
683 wconstr = sv_mortalcopy(dbname);
684#ifdef sv_utf8_decode
685 sv_utf8_decode(wconstr);
686#else
687 SvUTF8_on(wconstr);
688#endif
689 SV_toWCHAR(wconstr);
690
691 wuid = sv_mortalcopy(uid);
692#ifdef sv_utf8_decode
693 sv_utf8_decode(wuid);
694#else
695 SvUTF8_on(wuid);
696#endif
697 SV_toWCHAR(wuid);
698
699 wpwd = sv_mortalcopy(pwd);
700#ifdef sv_utf8_decode
701 sv_utf8_decode(wpwd);
702#else
703 SvUTF8_on(wpwd);
704#endif
705 SV_toWCHAR(wpwd);
706
707 rc = SQLConnectW(imp_dbh->hdbc,
708 (SQLWCHAR *)SvPV_nolen(wconstr),
709 (SQLSMALLINT)(SvCUR(wconstr) / sizeof(SQLWCHAR)),
710 (SQLWCHAR *)SvPV_nolen(wuid),
711 (SQLSMALLINT)(SvCUR(wuid) / sizeof(SQLWCHAR)),
712 (SQLWCHAR *)SvPV_nolen(wpwd),
713 (SQLSMALLINT)(SvCUR(wpwd) / sizeof(SQLWCHAR)));
714 }
715 if (!SQL_SUCCEEDED(rc)) {
716 dbd_error(dbh, rc, "db_login/SQLConnect");
717 SQLFreeHandle(SQL_HANDLE_DBC, imp_dbh->hdbc);/* TBD: 3.0 update */
718 if (imp_drh->connects == 0) {
719 SQLFreeHandle(SQL_HANDLE_ENV, imp_drh->henv);
720 imp_drh->henv = SQL_NULL_HENV;
721 imp_dbh->henv = SQL_NULL_HENV; /* needed for dbd_error */
722 }
723 return 0;
724 } else if (rc == SQL_SUCCESS_WITH_INFO) {
725 dbd_error(dbh, rc, "db_login/SQLConnect");
726 }
727
728 if (post_connect(dbh, imp_dbh, attr) != 1) return 0;
729
730
731 imp_drh->connects++;
732 DBIc_IMPSET_on(imp_dbh); /* imp_dbh set up now */
733 DBIc_ACTIVE_on(imp_dbh); /* call disconnect before freeing */
734 return 1;
735#endif /* WITH_UNICODE */
736
737}
738
739
740
741/************************************************************************/
742/* */
743/* dbd_db_login6 */
744/* ============= */
745/* */
746/* A newer version of the dbd_db_login API with the additional attr as */
747/* the sixth argument. Once everyone upgrades to at least */
748/* DBI 1.60X (where X > 7) this API won't get called anymore since */
749/* dbd_db_login6_sv will be favoured. */
750/* */
751/* NOTE: I had hoped to make dbd_db_login6_sv support Unicode and */
752/* dbd_db_login6 to not support Unicode but as no one (except me) has */
753/* a DBI which supports dbd_db_login6_sv and unixODBC REQUIRES us to */
754/* call SQLDriverConnectW if we are going to call other SQLXXXW */
755/* functions later I've got no choice but to convert the ASCII strings */
756/* passed to dbd_db_login6 to wide characters when DBD::ODBC is built */
757/* for Unicode. */
758/* */
759/************************************************************************/
760int dbd_db_login6(
761 SV *dbh,
762 imp_dbh_t *imp_dbh,
763 char *dbname,
764 char *uid,
765 char *pwd,
766 SV *attr)
767{
768 D_imp_drh_from_dbh;
769 dTHR;
770
771 RETCODE rc;
772 char dbname_local[512];
773#ifdef WITH_UNICODE
774 SQLWCHAR wconstr[512];
775 STRLEN wconstr_len;
776 unsigned int i;
777#endif
778
779 if (DBIc_TRACE(imp_dbh, 0x04000000, 0, 0))
780 TRACE0(imp_dbh, "dbd_db_login6\n");
781 if (!imp_drh->connects) {
782 rc = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &imp_drh->henv);
783 dbd_error(dbh, rc, "db_login/SQLAllocHandle(env)");
784 if (!SQL_SUCCEEDED(rc)) return 0;
785
786 if (set_odbc_version(dbh, imp_dbh, attr) != 1) return 0;
787 }
788
789 imp_dbh->henv = imp_drh->henv; /* needed for dbd_error */
790
791 imp_dbh->out_connect_string = NULL;
792
793 rc = SQLAllocHandle(SQL_HANDLE_DBC, imp_drh->henv, &imp_dbh->hdbc);
794 if (!SQL_SUCCEEDED(rc)) {
795 dbd_error(dbh, rc, "db_login/SQLAllocHandle(dbc)");
796 if (imp_drh->connects == 0) {
797 SQLFreeHandle(SQL_HANDLE_ENV, imp_drh->henv);
798 imp_drh->henv = SQL_NULL_HENV;
799 imp_dbh->henv = SQL_NULL_HENV; /* needed for dbd_error */
800 }
801 return 0;
802 }
803
804#ifndef DBD_ODBC_NO_SQLDRIVERCONNECT
805 /* If the connection string is too long to pass to SQLConnect or it
806 contains DSN or DRIVER, we've little choice to but to call
807 SQLDriverConnect and need to tag the uid/pwd on the end of the
808 connection string (unless they already exist). */
809
810 if ((strlen(dbname) > SQL_MAX_DSN_LENGTH ||
811 dsnHasDriverOrDSN(dbname)) && !dsnHasUIDorPWD(dbname)) {
812 if ((strlen(dbname) + strlen(uid) + strlen(pwd) + 12) >
813 sizeof(dbname_local)) {
814 croak("Connection string too long");
815 }
816 sprintf(dbname_local, "%s;UID=%s;PWD=%s;", dbname, uid, pwd);
817 dbname = dbname_local;
818 }
819
820 if (DBIc_TRACE(imp_dbh, 0x04000000, 0, 0))
821 TRACE2(imp_dbh, " SQLDriverConnect '%s', '%s', 'xxxx'\n", dbname, uid);
822
823# ifdef WITH_UNICODE
824 if (strlen(dbname) > (sizeof(wconstr) / sizeof(wconstr[0]))) {
825 croak("Connection string too big to convert to wide characters");
826 }
827
828 for (i = 0; i < strlen(dbname); i++) {
829 wconstr[i] = dbname[i];
830 }
831 wconstr[i] = 0;
832 wconstr_len = i;
833
834 {
835 SQLWCHAR wout_str[512];
836 SQLSMALLINT wout_str_len;
837
838 rc = SQLDriverConnectW(imp_dbh->hdbc,
839 0, /* no hwnd */
840 wconstr, (SQLSMALLINT)wconstr_len,
841 wout_str, sizeof(wout_str) / sizeof(wout_str[0]),
842 &wout_str_len,
843 SQL_DRIVER_NOPROMPT);
844 if (SQL_SUCCEEDED(rc)) {
845 imp_dbh->out_connect_string = sv_newwvn(wout_str, wout_str_len);
846 if (DBIc_TRACE(imp_dbh, 0x04000000, 0, 0))
847 TRACE1(imp_dbh, "Out connection string: %s\n",
848 SvPV_nolen(imp_dbh->out_connect_string));
849 }
850 }
851
852# else /* WITH_UNICODE */
853
854 {
855 char out_str[512];
856 SQLSMALLINT out_str_len;
857
858 rc = SQLDriverConnect(imp_dbh->hdbc,
859 0, /* no hwnd */
860 dbname,
861 (SQLSMALLINT)strlen(dbname),
862 out_str, sizeof(out_str), &out_str_len,
863 SQL_DRIVER_NOPROMPT);
864 if (SQL_SUCCEEDED(rc)) {
865 imp_dbh->out_connect_string = newSVpv(out_str, out_str_len);
866 if (DBIc_TRACE(imp_dbh, 0x04000000, 0, 0))
867 TRACE1(imp_dbh, "Out connection string: %s\n",
868 SvPV_nolen(imp_dbh->out_connect_string));
869 }
870 }
871
872# endif /* WITH_UNICODE */
873#else
874 /* if we are using something that can not handle SQLDriverconnect,
875 * then set rc to a not OK state and we'll fall back on SQLConnect
876 */
877 rc = SQL_ERROR;
878#endif
879
880 if (!SQL_SUCCEEDED(rc)) {
881 if (DBIc_TRACE(imp_dbh, 0, 0, 4)) {
882#ifdef DBD_ODBC_NO_SQLDRIVERCONNECT
883 TRACE0(imp_dbh, " !SQLDriverConnect unsupported.\n");
884#else
885 TRACE0(imp_dbh, " SQLDriverConnect failed:\n");
886#endif
887 }
888
889#ifndef DBD_ODBC_NO_SQLDRIVERCONNECT
890 /*
891 * Added code for DBD::ODBC 0.39 to help return a better
892 * error code in the case where the user is using a
893 * DSN-less connection and the dbname doesn't look like a
894 * true DSN.
895 */
896 /* wanted to use strncmpi, but couldn't find one on all
897 * platforms. Sigh. */
898 if (strlen(dbname) > SQL_MAX_DSN_LENGTH || dsnHasDriverOrDSN(dbname)) {
899
900 /* must be DSN= or some "direct" connection attributes,
901 * probably best to error here and give the user a real
902 * error code because the SQLConnect call could hide the
903 * real problem.
904 */
905 dbd_error(dbh, rc, "db_login/SQLConnect");
906 SQLFreeHandle(SQL_HANDLE_DBC, imp_dbh->hdbc);
907 if (imp_drh->connects == 0) {
908 SQLFreeHandle(SQL_HANDLE_ENV, imp_drh->henv);
909 imp_drh->henv = SQL_NULL_HENV;
910 imp_dbh->henv = SQL_NULL_HENV; /* needed for dbd_error */
911 }
912 return 0;
913 }
914
915 /* ok, the DSN is short, so let's try to use it to connect
916 * and quietly take all error messages */
917 AllODBCErrors(imp_dbh->henv, imp_dbh->hdbc, 0, 0, DBIc_LOGPIO(imp_dbh));
918#endif /* DriverConnect supported */
919
920 if (DBIc_TRACE(imp_dbh, 0x04000000, 0, 0))
921 TRACE2(imp_dbh, " SQLConnect '%s', '%s'\n", dbname, uid);
922#ifdef WITH_UNICODE
923 {
924 SQLWCHAR wuid[100], wpwd[100];
925 for (i = 0; i < strlen(uid); i++) {
926 wuid[i] = uid[i];
927 }
928 wuid[i] = 0;
929 for (i = 0; i < strlen(pwd); i++) {
930 wpwd[i] = pwd[i];
931 }
932 wpwd[i] = 0;
933 for (i = 0; i < strlen(dbname); i++) {
934 wconstr[i] = dbname[i];
935 }
936 wconstr[i] = 0;
937 wconstr_len = i;
938
939 rc = SQLConnectW(imp_dbh->hdbc,
940 wconstr, wconstr_len,
941 wuid, (SQLSMALLINT)strlen(uid),
942 wpwd, (SQLSMALLINT)strlen(pwd));
943 }
944#else
945 rc = SQLConnect(imp_dbh->hdbc,
946 dbname, (SQLSMALLINT)strlen(dbname),
947 uid, (SQLSMALLINT)strlen(uid),
948 pwd, (SQLSMALLINT)strlen(pwd));
949#endif
950 }
951
952 if (!SQL_SUCCEEDED(rc)) {
953 dbd_error(dbh, rc, "db_login/SQLConnect");
954 SQLFreeHandle(SQL_HANDLE_DBC, imp_dbh->hdbc);/* TBD: 3.0 update */
955 if (imp_drh->connects == 0) {
956 SQLFreeHandle(SQL_HANDLE_ENV, imp_drh->henv);
957 imp_drh->henv = SQL_NULL_HENV;
958 imp_dbh->henv = SQL_NULL_HENV; /* needed for dbd_error */
959 }
960 return 0;
961 } else if (rc == SQL_SUCCESS_WITH_INFO) {
962 dbd_error(dbh, rc, "db_login/SQLConnect");
963 }
964
965 if (post_connect(dbh, imp_dbh, attr) != 1) return 0;
966
967
968 imp_drh->connects++;
969 DBIc_IMPSET_on(imp_dbh); /* imp_dbh set up now */
970 DBIc_ACTIVE_on(imp_dbh); /* call disconnect before freeing */
971 return 1;
972}
973
974
975
976int dbd_db_disconnect(SV *dbh, imp_dbh_t *imp_dbh)
977{
978 RETCODE rc;
979 D_imp_drh_from_dbh;
980 UDWORD autoCommit = 0;
981 dTHR;
982
983 /* We assume that disconnect will always work */
984 /* since most errors imply already disconnected. */
985 DBIc_ACTIVE_off(imp_dbh);
986
987 if (imp_dbh->out_connect_string) {
988 SvREFCNT_dec(imp_dbh->out_connect_string);
989 }
990
991 /* If not autocommit, should we rollback? I don't think that's
992 * appropriate. -- TBD: Need to check this, maybe we should
993 * rollback?
994 */
995
996 /* TBD: 3.0 update */
997 rc = SQLGetConnectOption(imp_dbh->hdbc, SQL_AUTOCOMMIT, &autoCommit);
998 /* quietly handle a problem with SQLGetConnectOption() */
999 if (!SQL_SUCCEEDED(rc)) {
1000 AllODBCErrors(imp_dbh->henv, imp_dbh->hdbc, 0,
1001 DBIc_TRACE(imp_dbh, 0, 0, 4), DBIc_LOGPIO(imp_dbh));
1002 }
1003 else {
1004 if (!autoCommit) {
1005 rc = dbd_db_rollback(dbh, imp_dbh);
1006 if (DBIc_TRACE(imp_dbh, 0, 0, 3)) {
1007 TRACE1(imp_dbh,
1008 "** auto-rollback due to disconnect without commit"
1009 " returned %d\n", rc);
1010 }
1011 }
1012 }
1013 rc = SQLDisconnect(imp_dbh->hdbc);
1014 if (!SQL_SUCCEEDED(rc)) {
1015 dbd_error(dbh, rc, "db_disconnect/SQLDisconnect");
1016 /* return 0; XXX if disconnect fails, fall through... */
1017 }
1018 if (DBIc_TRACE(imp_dbh, 0x04000000, 0, 0))
1019 TRACE1(imp_dbh, "SQLDisconnect=%d\n", rc);
1020
1021 SQLFreeHandle(SQL_HANDLE_DBC, imp_dbh->hdbc);
1022 imp_dbh->hdbc = SQL_NULL_HDBC;
1023 imp_drh->connects--;
1024 strcpy(imp_dbh->odbc_dbname, "disconnect");
1025 if (imp_drh->connects == 0) {
1026 SQLFreeHandle(SQL_HANDLE_ENV, imp_drh->henv);
1027 imp_drh->henv = SQL_NULL_HENV;
1028 imp_dbh->henv = SQL_NULL_HENV; /* needed for dbd_error */
1029 }
1030 /* We don't free imp_dbh since a reference still exists */
1031 /* The DESTROY method is the only one to 'free' memory. */
1032 /* Note that statement objects may still exists for this dbh! */
1033
1034 return 1;
1035}
1036
1037
1038
1039
1040int dbd_db_commit(SV *dbh, imp_dbh_t *imp_dbh)
1041{
1042 RETCODE rc;
1043 dTHR;
1044
1045 /* TBD: 3.0 update */
1046 rc = SQLTransact(imp_dbh->henv, imp_dbh->hdbc, SQL_COMMIT);
1047 if (!SQL_SUCCEEDED(rc)) {
1048 dbd_error(dbh, rc, "db_commit/SQLTransact");
1049 return 0;
1050 }
1051 /* support for DBI 1.20 begin_work */
1052 if (DBIc_has(imp_dbh, DBIcf_BegunWork)) {
1053 /* reset autocommit */
1054 rc = SQLSetConnectOption(imp_dbh->hdbc, SQL_AUTOCOMMIT,
1055 SQL_AUTOCOMMIT_ON);
1056 DBIc_off(imp_dbh,DBIcf_BegunWork);
1057 }
1058 return 1;
1059}
1060
1061
1062
1063int dbd_db_rollback(SV *dbh, imp_dbh_t *imp_dbh)
1064{
1065 RETCODE rc;
1066 dTHR;
1067
1068 /* TBD: 3.0 update */
1069 rc = SQLTransact(imp_dbh->henv, imp_dbh->hdbc, SQL_ROLLBACK);
1070 if (!SQL_SUCCEEDED(rc)) {
1071 dbd_error(dbh, rc, "db_rollback/SQLTransact");
1072 return 0;
1073 }
1074 /* support for DBI 1.20 begin_work */
1075 if (DBIc_has(imp_dbh, DBIcf_BegunWork)) {
1076 /* reset autocommit */
1077 rc = SQLSetConnectOption(imp_dbh->hdbc, SQL_AUTOCOMMIT,
1078 SQL_AUTOCOMMIT_ON);
1079 DBIc_off(imp_dbh,DBIcf_BegunWork);
1080 }
1081 return 1;
1082}
1083
1084
1085
1086void dbd_error2(
1087 SV *h,
1088 RETCODE err_rc,
1089 char *what,
1090 HENV henv,
1091 HDBC hdbc,
1092 HSTMT hstmt)
1093{
1094 D_imp_xxh(h);
1095 dTHR;
1096
1097 /*
1098 * It's a shame to have to add all this stuff with imp_dbh and
1099 * imp_sth, but imp_dbh is needed to get the odbc_err_handler
1100 * and imp_sth is needed to get imp_dbh.
1101 */
1102 struct imp_dbh_st *imp_dbh = NULL;
1103 struct imp_sth_st *imp_sth = NULL;
1104
1105 if (DBIc_TRACE(imp_xxh, 0, 0, 4)) {
1106 PerlIO_printf(DBIc_LOGPIO(imp_xxh),
1107 " !!dbd_error2(err_rc=%d, what=%s, handles=(%p,%p,%p)\n",
1108 err_rc, (what ? what : "null"), henv, hdbc, hstmt);
1109 }
1110
1111 switch(DBIc_TYPE(imp_xxh)) {
1112 case DBIt_ST:
1113 imp_sth = (struct imp_sth_st *)(imp_xxh);
1114 imp_dbh = (struct imp_dbh_st *)(DBIc_PARENT_COM(imp_sth));
1115 break;
1116 case DBIt_DB:
1117 imp_dbh = (struct imp_dbh_st *)(imp_xxh);
1118 break;
1119 default:
1120 croak("panic: dbd_error2 on bad handle type");
1121 }
1122
1123 while(henv != SQL_NULL_HENV) {
1124 UCHAR sqlstate[SQL_SQLSTATE_SIZE+1];
1125 /*
1126 * ODBC spec says ErrorMsg must not be greater than
1127 * SQL_MAX_MESSAGE_LENGTH (says spec) but we concatenate a little
1128 * on the end later (e.g. sql state) so make room for more.
1129 */
1130 UCHAR ErrorMsg[SQL_MAX_MESSAGE_LENGTH+512];
1131 SWORD ErrorMsgLen;
1132 SDWORD NativeError;
1133 RETCODE rc = 0;
1134
1135 /* TBD: 3.0 update */
1136 while(SQL_SUCCEEDED(rc=SQLError(
1137 henv, hdbc, hstmt,
1138 sqlstate, &NativeError,
1139 ErrorMsg, sizeof(ErrorMsg)-1, &ErrorMsgLen))) {
1140
1141 ErrorMsg[ErrorMsgLen] = '\0';
1142 sqlstate[SQL_SQLSTATE_SIZE] = '\0';
1143
1144 if (DBIc_TRACE(imp_dbh, 0, 0, 3)) {
1145 PerlIO_printf(DBIc_LOGPIO(imp_dbh),
1146 " !SQLError(%p,%p,%p) = "
1147 "(%s, %ld, %s)\n",
1148 henv, hdbc, hstmt, sqlstate, NativeError, ErrorMsg);
1149 }
1150
1151 /*
1152 * If there's an error handler, run it and see what it returns...
1153 * (lifted from DBD:Sybase 0.21)
1154 */
1155 if(imp_dbh->odbc_err_handler) {
1156 dSP;
1157 /* SV *sv, **svp; */
1158 /* HV *hv; */
1159 int retval, count;
1160
1161 ENTER;
1162 SAVETMPS;
1163 PUSHMARK(sp);
1164
1165 if (DBIc_TRACE(imp_dbh, 0, 0, 3))
1166 TRACE0(imp_dbh, " Calling error handler\n");
1167
1168 /*
1169 * Here are the args to the error handler routine:
1170 * 1. sqlstate (string)
1171 * 2. ErrorMsg (string)
1172 * 3. NativeError (integer)
1173 * That's it for now...
1174 */
1175 XPUSHs(sv_2mortal(newSVpv(sqlstate, 0)));
1176 XPUSHs(sv_2mortal(newSVpv(ErrorMsg, 0)));
1177 XPUSHs(sv_2mortal(newSViv(NativeError)));
1178
1179 PUTBACK;
1180 if((count = perl_call_sv(imp_dbh->odbc_err_handler, G_SCALAR)) != 1)
1181 croak("An error handler can't return a LIST.");
1182 SPAGAIN;
1183 retval = POPi;
1184
1185 PUTBACK;
1186 FREETMPS;
1187 LEAVE;
1188
1189 /* If the called sub returns 0 then ignore this error */
1190 if(retval == 0) {
1191 if (DBIc_TRACE(imp_dbh, 0, 0, 3))
1192 TRACE0(imp_dbh,
1193 " Handler caused error to be ignored\n");
1194 continue;
1195 }
1196 }
1197 strcat(ErrorMsg, " (SQL-");
1198 strcat(ErrorMsg, sqlstate);
1199 strcat(ErrorMsg, ")");
1200 /* maybe bad way to add hint about invalid transaction
1201 * state upon disconnect...
1202 */
1203 if (what && !strcmp(sqlstate, "25000") &&
1204 !strcmp(what, "db_disconnect/SQLDisconnect")) {
1205 strcat(ErrorMsg, " You need to commit before disconnecting! ");
1206 }
1207
1208 if (SQL_SUCCEEDED(err_rc)) {
1209 DBIh_SET_ERR_CHAR(h, imp_xxh, "", 1, ErrorMsg, sqlstate, Nullch);
1210 } else {
1211 DBIh_SET_ERR_CHAR(h, imp_xxh, Nullch, 1, ErrorMsg,
1212 sqlstate, Nullch);
1213 }
1214 continue;
1215 }
1216 if (rc != SQL_NO_DATA_FOUND) { /* should never happen */
1217 if (DBIc_TRACE(imp_xxh, 0, 0, 3))
1218 TRACE1(imp_dbh,
1219 " !!SQLError returned %d unexpectedly.\n", rc);
1220 DBIh_SET_ERR_CHAR(
1221 h, imp_xxh, Nullch, 1,
1222 "Unable to fetch information about the error", "IM008", Nullch);
1223 }
1224 /* climb up the tree each time round the loop */
1225 if (hstmt != SQL_NULL_HSTMT) hstmt = SQL_NULL_HSTMT;
1226 else if (hdbc != SQL_NULL_HDBC) hdbc = SQL_NULL_HDBC;
1227 else henv = SQL_NULL_HENV; /* done the top */
1228 }
1229}
1230
1231
1232
1233/*------------------------------------------------------------
1234empties entire ODBC error queue.
1235------------------------------------------------------------*/
1236void dbd_error(SV *h, RETCODE err_rc, char *what)
1237{
1238 D_imp_xxh(h);
1239 dTHR;
1240
1241 struct imp_dbh_st *imp_dbh = NULL;
1242 struct imp_sth_st *imp_sth = NULL;
1243 HSTMT hstmt = SQL_NULL_HSTMT;
1244
1245 switch(DBIc_TYPE(imp_xxh)) {
1246 case DBIt_ST:
1247 imp_sth = (struct imp_sth_st *)(imp_xxh);
1248 imp_dbh = (struct imp_dbh_st *)(DBIc_PARENT_COM(imp_sth));
1249 hstmt = imp_sth->hstmt;
1250 break;
1251 case DBIt_DB:
1252 imp_dbh = (struct imp_dbh_st *)(imp_xxh);
1253 break;
1254 default:
1255 croak("panic: dbd_error on bad handle type");
1256 }
1257 /*
1258 * If status is SQL_SUCCESS, there's no error, so we can just return.
1259 * There may be status or other non-error messsages though.
1260 * We want those messages if the debug level is set to at least 3.
1261 * If an error handler is installed, let it decide what messages
1262 * should or shouldn't be reported.
1263 */
1264 if ((err_rc == SQL_SUCCESS) && DBIc_TRACE(imp_dbh, 0, 0, 3) &&
1265 !imp_dbh->odbc_err_handler)
1266 return;
1267
1268 dbd_error2(h, err_rc, what, imp_dbh->henv, imp_dbh->hdbc, hstmt);
1269}
1270
1271
1272
1273
1274void dbd_caution(SV *h, char *what)
1275{
1276 D_imp_xxh(h);
1277 dTHR;
1278
1279 SV *errstr;
1280 errstr = DBIc_ERRSTR(imp_xxh);
1281 sv_setpvn(errstr, "", 0);
1282 sv_setiv(DBIc_ERR(imp_xxh), (IV)-1);
1283 /* sqlstate isn't set for SQL_NO_DATA returns */
1284 sv_setpvn(DBIc_STATE(imp_xxh), "00000", 5);
1285
1286 if (what) {
1287 sv_catpv(errstr, "(DBD: ");
1288 sv_catpv(errstr, what);
1289 sv_catpv(errstr, " err=-1)");
1290 }
1291
1292 if (DBIc_TRACE(imp_xxh, 0, 0, 3))
1293 PerlIO_printf(DBIc_LOGPIO(imp_xxh), " !!%s error %d recorded: %s\n",
1294 what, -1, SvPV(errstr,na));
1295}
1296
1297
1298
1299/*-------------------------------------------------------------------------
1300dbd_preparse:
1301- scan for placeholders (? and :xx style) and convert them to ?.
1302- builds translation table to convert positional parameters of the
1303execute() call to :nn type placeholders.
1304We need two data structures to translate this stuff:
1305- a hash to convert positional parameters to placeholders
1306- an array, representing the actual '?' query parameters.
1307%param = (name1=>plh1, name2=>plh2, ..., name_n=>plh_n) #
1308@qm_param = (\$param{'name1'}, \$param{'name2'}, ...)
1309-------------------------------------------------------------------------*/
1310void dbd_preparse(imp_sth_t *imp_sth, char *statement)
1311{
1312 dTHR;
1313 bool in_literal = FALSE;
1314 char *src, *start, *dest;
1315 phs_t phs_tpl, *phs;
1316 SV *phs_sv;
1317 int idx=0, style=0, laststyle=0;
1318 int param = 0;
1319 STRLEN namelen;
1320 char name[256];
1321 SV **svpp;
1322 char ch;
1323 char literal_ch = '\0';
1324
1325 /* allocate room for copy of statement with spare capacity */
1326 imp_sth->statement = (char*)safemalloc(strlen(statement)+1);
1327
1328 /* initialize phs ready to be cloned per placeholder */
1329 memset(&phs_tpl, 0, sizeof(phs_tpl));
1330 phs_tpl.value_type = SQL_C_CHAR;
1331 phs_tpl.sv = &sv_undef;
1332
1333 src = statement;
1334 dest = imp_sth->statement;
1335 if (DBIc_TRACE(imp_sth, 0, 0, 5))
1336 TRACE1(imp_sth, " ignore named placeholders = %d\n",
1337 imp_sth->odbc_ignore_named_placeholders);
1338 while(*src) {
1339 /*
1340 * JLU 10/6/2000 fixed to make the literal a " instead of '
1341 * JLU 1/28/2001 fixed to make literals either " or ', but deal
1342 * with ' "foo" ' or " foo's " correctly (just to be safe).
1343 *
1344 */
1345 if (*src == '"' || *src == '\'') {
1346 if (!in_literal) {
1347 literal_ch = *src;
1348 in_literal = 1;
1349 } else {
1350 if (*src == literal_ch) {
1351 in_literal = 0;
1352 }
1353 }
1354 }
1355 if ((*src != ':' && *src != '?') || in_literal) {
1356 *dest++ = *src++;
1357 continue;
1358 }
1359 start = dest; /* save name inc colon */
1360 ch = *src++;
1361 if (ch == '?') { /* X/Open standard */
1362 idx++;
1363 sprintf(name, "%d", idx);
1364 *dest++ = ch;
1365 style = 3;
1366 }
1367 else if (isDIGIT(*src)) { /* ':1' */
1368 char *p = name;
1369 *dest++ = '?';
1370 idx = atoi(src);
1371 while(isDIGIT(*src))
1372 *p++ = *src++;
1373 *p = 0;
1374 style = 1;
1375 if (DBIc_TRACE(imp_sth, 0, 0, 5))
1376 TRACE1(imp_sth, " found numbered parameter = %s\n", name);
1377 }
1378 else if (!imp_sth->odbc_ignore_named_placeholders && isALNUM(*src)) {
1379 /* ':foo' is valid, only if we are ignoring named
1380 * parameters
1381 */
1382 char *p = name;
1383 idx++;
1384 *dest++ = '?';
1385
1386 while(isALNUM(*src)) /* includes '_' */
1387 *p++ = *src++;
1388 *p = 0;
1389 style = 2;
1390 if (DBIc_TRACE(imp_sth, 0, 0, 5))
1391 TRACE1(imp_sth, " found named parameter = %s\n", name);
1392 }
1393 else { /* perhaps ':=' PL/SQL construct */
1394 *dest++ = ch;
1395 continue;
1396 }
1397 *dest = '\0'; /* handy for debugging */
1398 if (laststyle && style != laststyle)
1399 croak("Can't mix placeholder styles (%d/%d)",style,laststyle);
1400 laststyle = style;
1401
1402 if (imp_sth->all_params_hv == NULL)
1403 imp_sth->all_params_hv = newHV();
1404 namelen = strlen(name);
1405
1406 svpp = hv_fetch(imp_sth->all_params_hv, name, (I32)namelen, 0);
1407 if (svpp == NULL) {
1408 if (DBIc_TRACE(imp_sth, 0, 0, 5))
1409 TRACE1(imp_sth, " creating new parameter key %s\n", name);
1410 /* create SV holding the placeholder */
1411 phs_sv = newSVpv((char*)&phs_tpl, sizeof(phs_tpl)+namelen+1);
1412 phs = (phs_t*)SvPVX(phs_sv);
1413 strcpy(phs->name, name);
1414 phs->idx = idx;
1415
1416 /* store placeholder to all_params_hv */
1417 svpp = hv_store(imp_sth->all_params_hv, name, (I32)namelen, phs_sv, 0);
1418 } else {
1419 if (DBIc_TRACE(imp_sth, 0, 0, 5))
1420 TRACE1(imp_sth, " parameter key %s already exists\n", name);
1421 croak("DBD::ODBC does not yet support binding a named parameter more than once\n");
1422 }
1423 }
1424 *dest = '\0';
1425 if (imp_sth->all_params_hv) {
1426 DBIc_NUM_PARAMS(imp_sth) = (int)HvKEYS(imp_sth->all_params_hv);
1427 if (DBIc_TRACE(imp_sth, 0, 0, 4))
1428 TRACE1(imp_sth,
1429 " dbd_preparse scanned %d distinct placeholders\n",
1430 (int)DBIc_NUM_PARAMS(imp_sth));
1431 }
1432}
1433
1434
1435
1436int dbd_st_tables(
1437 SV *dbh,
1438 SV *sth,
1439 char *catalog,
1440 char *schema,
1441 char *table,
1442 char *table_type)
1443{
1444 D_imp_dbh(dbh);
1445 D_imp_sth(sth);
1446 RETCODE rc;
1447 int dbh_active;
1448 /* SV **svp; */
1449 /* char cname[128]; */ /* cursorname */
1450 dTHR;
1451
1452 imp_sth->henv = imp_dbh->henv; /* needed for dbd_error */
1453 imp_sth->hdbc = imp_dbh->hdbc;
1454
1455 imp_sth->done_desc = 0;
1456
1457 if ((dbh_active = check_connection_active(dbh)) == 0) return 0;
1458
1459 rc = SQLAllocHandle(SQL_HANDLE_STMT, imp_dbh->hdbc, &imp_sth->hstmt);
1460 if (rc != SQL_SUCCESS) {
1461 dbd_error(sth, rc, "st_tables/SQLAllocHandle(stmt)");
1462 return 0;
1463 }
1464
1465 /* just for sanity, later. Any internals that may rely on this (including */
1466 /* debugging) will have valid data */
1467 imp_sth->statement = (char *)safemalloc(strlen(cSqlTables)+
1468 strlen(XXSAFECHAR(catalog)) +
1469 strlen(XXSAFECHAR(schema)) +
1470 strlen(XXSAFECHAR(table)) +
1471 strlen(XXSAFECHAR(table_type))+1);
1472 sprintf(imp_sth->statement, cSqlTables, XXSAFECHAR(catalog),
1473 XXSAFECHAR(schema), XXSAFECHAR(table), XXSAFECHAR(table_type));
1474
1475 rc = SQLTables(imp_sth->hstmt,
1476 (catalog && *catalog) ? catalog : 0, SQL_NTS,
1477 (schema && *schema) ? schema : 0, SQL_NTS,
1478 (table && *table) ? table : 0, SQL_NTS,
1479 table_type && *table_type ? table_type : 0,
1480 SQL_NTS /* type (view, table, etc) */
1481 );
1482
1483 if (DBIc_TRACE(imp_sth, 0, 0, 4))
1484 TRACE2(imp_dbh, " Tables result %d (%s)\n",
1485 rc, table_type ? table_type : "(null)");
1486
1487 dbd_error(sth, rc, "st_tables/SQLTables");
1488 if (!SQL_SUCCEEDED(rc)) {
1489 SQLFreeHandle(SQL_HANDLE_STMT,imp_sth->hstmt);
1490 /* SQLFreeStmt(imp_sth->hstmt, SQL_DROP);*/ /* TBD: 3.0 update */
1491 imp_sth->hstmt = SQL_NULL_HSTMT;
1492 return 0;
1493 }
1494 return build_results(sth, dbh, rc);
1495}
1496
1497
1498
1499int dbd_st_primary_keys(
1500 SV *dbh,
1501 SV *sth,
1502 char *catalog,
1503 char *schema,
1504 char *table)
1505{
1506 dTHR;
1507 D_imp_dbh(dbh);
1508 D_imp_sth(sth);
1509 RETCODE rc;
1510 int dbh_active;
1511
1512 imp_sth->henv = imp_dbh->henv; /* needed for dbd_error */
1513 imp_sth->hdbc = imp_dbh->hdbc;
1514
1515 imp_sth->done_desc = 0;
1516
1517 if ((dbh_active = check_connection_active(dbh)) == 0) return 0;
1518
1519 rc = SQLAllocHandle(SQL_HANDLE_STMT, imp_dbh->hdbc, &imp_sth->hstmt);
1520 if (rc != SQL_SUCCESS) {
1521 dbd_error(sth, rc, "odbc_db_primary_key_info/SQLAllocHandle(stmt)");
1522 return 0;
1523 }
1524
1525 /* just for sanity, later. Any internals that may rely on this (including */
1526 /* debugging) will have valid data */
1527 imp_sth->statement = (char *)safemalloc(strlen(cSqlPrimaryKeys)+
1528 strlen(XXSAFECHAR(catalog))+
1529 strlen(XXSAFECHAR(schema))+
1530 strlen(XXSAFECHAR(table))+1);
1531
1532 sprintf(imp_sth->statement,
1533 cSqlPrimaryKeys, XXSAFECHAR(catalog), XXSAFECHAR(schema),
1534 XXSAFECHAR(table));
1535
1536 rc = SQLPrimaryKeys(imp_sth->hstmt,
1537 (catalog && *catalog) ? catalog : 0, SQL_NTS,
1538 (schema && *schema) ? schema : 0, SQL_NTS,
1539 (table && *table) ? table : 0, SQL_NTS);
1540
1541 if (DBIc_TRACE(imp_sth, 0, 0, 4))
1542 PerlIO_printf(
1543 DBIc_LOGPIO(imp_dbh),
1544 "SQLPrimaryKeys call: cat = %s, schema = %s, table = %s\n",
1545 XXSAFECHAR(catalog), XXSAFECHAR(schema), XXSAFECHAR(table));
1546
1547 dbd_error(sth, rc, "st_primary_key_info/SQLPrimaryKeys");
1548
1549 if (!SQL_SUCCEEDED(rc)) {
1550 SQLFreeHandle(SQL_HANDLE_STMT,imp_sth->hstmt);
1551 /* SQLFreeStmt(imp_sth->hstmt, SQL_DROP);*/ /* TBD: 3.0 update */
1552 imp_sth->hstmt = SQL_NULL_HSTMT;
1553 return 0;
1554 }
1555
1556 return build_results(sth, dbh, rc);
1557}
1558
1559
1560
1561int dbd_st_statistics(
1562 SV *dbh,
1563 SV *sth,
1564 char *catalog,
1565 char *schema,
1566 char *table,
1567 int unique,
1568 int quick)
1569{
1570 dTHR;
1571 D_imp_dbh(dbh);
1572 D_imp_sth(sth);
1573 RETCODE rc;
1574 int dbh_active;
1575 SQLUSMALLINT odbc_unique;
1576 SQLUSMALLINT odbc_quick;
1577
1578 imp_sth->henv = imp_dbh->henv; /* needed for dbd_error */
1579 imp_sth->hdbc = imp_dbh->hdbc;
1580
1581 imp_sth->done_desc = 0;
1582
1583 if ((dbh_active = check_connection_active(dbh)) == 0) return 0;
1584
1585 rc = SQLAllocHandle(SQL_HANDLE_STMT, imp_dbh->hdbc, &imp_sth->hstmt);
1586 if (rc != SQL_SUCCESS) {
1587 dbd_error(sth, rc, "odbc_db_primary_key_info/SQLAllocHandle(stmt)");
1588 return 0;
1589 }
1590
1591 odbc_unique = (unique ? SQL_INDEX_UNIQUE : SQL_INDEX_ALL);
1592 odbc_quick = (quick ? SQL_QUICK : SQL_ENSURE);
1593
1594 /* just for sanity, later. Any internals that may rely on this (including */
1595 /* debugging) will have valid data */
1596 imp_sth->statement = (char *)safemalloc(strlen(cSqlStatistics)+
1597 strlen(XXSAFECHAR(catalog))+
1598 strlen(XXSAFECHAR(schema))+
1599 strlen(XXSAFECHAR(table))+1);
1600
1601 sprintf(imp_sth->statement,
1602 cSqlStatistics, XXSAFECHAR(catalog), XXSAFECHAR(schema),
1603 XXSAFECHAR(table), unique, quick);
1604
1605 rc = SQLStatistics(imp_sth->hstmt,
1606 (catalog && *catalog) ? catalog : 0, SQL_NTS,
1607 (schema && *schema) ? schema : 0, SQL_NTS,
1608 (table && *table) ? table : 0, SQL_NTS,
1609 odbc_unique, odbc_quick);
1610
1611 if (DBIc_TRACE(imp_sth, 0, 0, 4))
1612 PerlIO_printf(
1613 DBIc_LOGPIO(imp_dbh),
1614 "SQLStatistics call: cat = %s, schema = %s, table = %s"
1615 ", unique=%d, quick = %d\n",
1616 XXSAFECHAR(catalog), XXSAFECHAR(schema), XXSAFECHAR(table),
1617 odbc_unique, odbc_quick);
1618
1619 dbd_error(sth, rc, "st_statistics/SQLStatistics");
1620
1621 if (!SQL_SUCCEEDED(rc)) {
1622 SQLFreeHandle(SQL_HANDLE_STMT,imp_sth->hstmt);
1623 /* SQLFreeStmt(imp_sth->hstmt, SQL_DROP);*/ /* TBD: 3.0 update */
1624 imp_sth->hstmt = SQL_NULL_HSTMT;
1625 return 0;
1626 }
1627
1628 return build_results(sth, dbh, rc);
1629}
1630
1631
1632
1633/************************************************************************/
1634/* */
1635/* odbc_st_prepare */
1636/* =============== */
1637/* */
1638/* dbd_st_prepare is the old API which is now replaced with */
1639/* dbd_st_prepare_sv (taking a perl scalar) so this is now: */
1640/* */
1641/* a) just a wrapper around dbd_st_prepare_sv and */
1642/* b) not used - see ODBC.c */
1643/* */
1644/************************************************************************/
1645int odbc_st_prepare(
1646 SV *sth,
1647 imp_sth_t *imp_sth,
1648 char *statement,
1649 SV *attribs)
1650{
1651 dTHR;
1652 SV *sql;
1653
1654 sql = sv_newmortal();
1655
1656 sv_setpvn(sql, statement, strlen(statement));
1657
1658 return dbd_st_prepare_sv(sth, imp_sth, sql, attribs);
1659
1660}
1661
1662
1663
1664/************************************************************************/
1665/* */
1666/* odbc_st_prepare_sv */
1667/* ================== */
1668/* */
1669/* dbd_st_prepare_sv is the newer version of dbd_st_prepare taking a */
1670/* a perl scalar for the sql statement instead of a char*. */
1671/* */
1672/************************************************************************/
1673int odbc_st_prepare_sv(
1674 SV *sth,
1675 imp_sth_t *imp_sth,
1676 SV *statement,
1677 SV *attribs)
1678{
1679 dTHR;
1680 D_imp_dbh_from_sth;
1681 RETCODE rc;
1682 int dbh_active;
1683 char *sql;
1684 STRLEN sql_len;
1685
1686 sql = SvPV(statement, sql_len);
1687
1688 imp_sth->done_desc = 0;
1689 imp_sth->henv = imp_dbh->henv; /* needed for dbd_error */
1690 imp_sth->hdbc = imp_dbh->hdbc;
1691 imp_sth->odbc_ignore_named_placeholders =
1692 imp_dbh->odbc_ignore_named_placeholders;
1693 imp_sth->odbc_default_bind_type = imp_dbh->odbc_default_bind_type;
1694 imp_sth->odbc_force_rebind = imp_dbh->odbc_force_rebind;
1695 imp_sth->odbc_query_timeout = imp_dbh->odbc_query_timeout;
1696 imp_sth->odbc_putdata_start = imp_dbh->odbc_putdata_start;
1697 imp_sth->odbc_column_display_size = imp_dbh->odbc_column_display_size;
1698 if (DBIc_TRACE(imp_dbh, 0, 0, 5))
1699 TRACE1(imp_dbh, " initializing sth query timeout to %d\n",
1700 (int)imp_dbh->odbc_query_timeout);
1701
1702 if ((dbh_active = check_connection_active(sth)) == 0) return 0;
1703
1704 rc = SQLAllocHandle(SQL_HANDLE_STMT, imp_dbh->hdbc, &imp_sth->hstmt);
1705 if (!SQL_SUCCEEDED(rc)) {
1706 dbd_error(sth, rc, "st_prepare/SQLAllocHandle(stmt)");
1707 return 0;
1708 }
1709
1710 imp_sth->odbc_exec_direct = imp_dbh->odbc_exec_direct;
1711
1712 {
1713 /*
1714 * allow setting of odbc_execdirect in prepare() or overriding
1715 */
1716 SV **odbc_exec_direct_sv;
1717 /* if the attribute is there, let it override what the default
1718 * value from the dbh is (set above).
1719 * NOTE:
1720 * There are unfortunately two possible attributes because of an early
1721 * typo in DBD::ODBC which we keep for backwards compatibility.
1722 */
1723 if ((odbc_exec_direct_sv =
1724 DBD_ATTRIB_GET_SVP(attribs, "odbc_execdirect",
1725 (I32)strlen("odbc_execdirect"))) != NULL) {
1726 imp_sth->odbc_exec_direct = SvIV(*odbc_exec_direct_sv) != 0;
1727 }
1728 if ((odbc_exec_direct_sv =
1729 DBD_ATTRIB_GET_SVP(attribs, "odbc_exec_direct",
1730 (I32)strlen("odbc_exec_direct"))) != NULL) {
1731 imp_sth->odbc_exec_direct = SvIV(*odbc_exec_direct_sv) != 0;
1732 }
1733 }
1734 /* scan statement for '?', ':1' and/or ':foo' style placeholders */
1735 dbd_preparse(imp_sth, sql);
1736
1737 /* Hold this statement for subsequent call of dbd_execute */
1738 if (!imp_sth->odbc_exec_direct) {
1739 /* parse the (possibly edited) SQL statement */
1740 if (DBIc_TRACE(imp_dbh, SQL_TRACE_FLAG, 0, 3)) {
1741 TRACE1(imp_dbh, " SQLPrepare %s\n", imp_sth->statement);
1742 }
1743#ifdef WITH_UNICODE
1744 if (SvOK(statement) && DO_UTF8(statement)) {
1745 SQLWCHAR *wsql;
1746 STRLEN wsql_len;
1747 SV *sql_copy;
1748
1749 if (DBIc_TRACE(imp_dbh, 0x02000000, 0, 0))
1750 TRACE0(imp_dbh, " Processing utf8 sql in unicode mode\n");
1751
1752 sql_copy = sv_newmortal();
1753 sv_setpv(sql_copy, imp_sth->statement);
1754#ifdef sv_utf8_decode
1755 sv_utf8_decode(sql_copy);
1756#else
1757 SvUTF8_on(sql_copy);
1758#endif
1759 SV_toWCHAR(sql_copy);
1760
1761 wsql = (SQLWCHAR *)SvPV(sql_copy, wsql_len);
1762
1763 rc = SQLPrepareW(imp_sth->hstmt,
1764 wsql, wsql_len / sizeof(SQLWCHAR));
1765 } else {
1766 if (DBIc_TRACE(imp_dbh, 0x02000000, 0, 0))
1767 TRACE0(imp_dbh, " Processing non-utf8 sql in unicode mode\n");
1768
1769 rc = SQLPrepare(imp_sth->hstmt, imp_sth->statement,
1770 strlen(imp_sth->statement));
1771 }
1772
1773#else
1774 if (DBIc_TRACE(imp_dbh, 0x02000000, 0, 0))
1775 TRACE0(imp_dbh, " Processing sql in non-unicode mode\n");
1776
1777 rc = SQLPrepare(imp_sth->hstmt, imp_sth->statement,
1778 strlen(imp_sth->statement));
1779#endif
1780 if (DBIc_TRACE(imp_dbh, 0, 0, 3))
1781 TRACE1(imp_dbh, " SQLPrepare = %d\n", rc);
1782
1783 if (!SQL_SUCCEEDED(rc)) {
1784 dbd_error(sth, rc, "st_prepare/SQLPrepare");
1785 SQLFreeHandle(SQL_HANDLE_STMT,imp_sth->hstmt);
1786 /* SQLFreeStmt(imp_sth->hstmt, SQL_DROP);*/ /* TBD: 3.0 update */
1787 imp_sth->hstmt = SQL_NULL_HSTMT;
1788 return 0;
1789 }
1790 } else if (DBIc_TRACE(imp_dbh, 0, 0, 3)) {
1791 TRACE1(imp_dbh, " odbc_exec_direct=1, statement (%s) "
1792 "held for later exec\n", imp_sth->statement);
1793 }
1794
1795
1796 /* init sth pointers */
1797 imp_sth->henv = imp_dbh->henv;
1798 imp_sth->hdbc = imp_dbh->hdbc;
1799 imp_sth->fbh = NULL;
1800 imp_sth->ColNames = NULL;
1801 imp_sth->RowBuffer = NULL;
1802 imp_sth->RowCount = -1;
1803 imp_sth->eod = -1;
1804
1805 /*
1806 * If odbc_async_exec is set and odbc_async_type is SQL_AM_STATEMENT,
1807 * we need to set the SQL_ATTR_ASYNC_ENABLE attribute.
1808 */
1809 if (imp_dbh->odbc_async_exec &&
1810 imp_dbh->odbc_async_type == SQL_AM_STATEMENT){
1811 rc = SQLSetStmtAttr(imp_sth->hstmt,
1812 SQL_ATTR_ASYNC_ENABLE,
1813 (SQLPOINTER) SQL_ASYNC_ENABLE_ON,
1814 SQL_IS_UINTEGER
1815 );
1816 if (!SQL_SUCCEEDED(rc)) {
1817 dbd_error(sth, rc, "st_prepare/SQLSetStmtAttr");
1818 SQLFreeStmt(imp_sth->hstmt, SQL_DROP);
1819 imp_sth->hstmt = SQL_NULL_HSTMT;
1820 return 0;
1821 }
1822 }
1823
1824 /*
1825 * If odbc_query_timeout is set (not -1)
1826 * we need to set the SQL_ATTR_QUERY_TIMEOUT
1827 */
1828 if (imp_sth->odbc_query_timeout != -1){
1829 odbc_set_query_timeout(sth, imp_sth->hstmt, imp_sth->odbc_query_timeout);
1830 if (!SQL_SUCCEEDED(rc)) {
1831 dbd_error(sth, rc, "set_query_timeout");
1832 }
1833 /* don't fail if the query timeout can't be set. */
1834 }
1835
1836 DBIc_IMPSET_on(imp_sth);
1837 return 1;
1838}
1839
1840
1841
1842/* Given SQL type return string description - only used in debug output */
1843static const char *S_SqlTypeToString (SWORD sqltype)
1844{
1845 switch(sqltype) {
1846 case SQL_CHAR: return "CHAR";
1847 case SQL_NUMERIC: return "NUMERIC";
1848 case SQL_DECIMAL: return "DECIMAL";
1849 case SQL_INTEGER: return "INTEGER";
1850 case SQL_SMALLINT: return "SMALLINT";
1851 case SQL_FLOAT: return "FLOAT";
1852 case SQL_REAL: return "REAL";
1853 case SQL_DOUBLE: return "DOUBLE";
1854 case SQL_VARCHAR: return "VARCHAR";
1855#ifdef SQL_WCHAR
1856 case SQL_WCHAR: return "UNICODE CHAR";
1857#endif
1858#ifdef SQL_WVARCHAR
1859 /* added for SQLServer 7 ntext type 2/24/2000 */
1860 case SQL_WVARCHAR: return "UNICODE VARCHAR";
1861#endif
1862#ifdef SQL_WLONGVARCHAR
1863 case SQL_WLONGVARCHAR: return "UNICODE LONG VARCHAR";
1864#endif
1865 case SQL_DATE: return "DATE";
1866 case SQL_TYPE_DATE: return "DATE";
1867 case SQL_TIME: return "TIME";
1868 case SQL_TYPE_TIME: return "TIME";
1869 case SQL_TIMESTAMP: return "TIMESTAMP";
1870 case SQL_TYPE_TIMESTAMP: return "TIMESTAMP";
1871 case SQL_LONGVARCHAR: return "LONG VARCHAR";
1872 case SQL_BINARY: return "BINARY";
1873 case SQL_VARBINARY: return "VARBINARY";
1874 case SQL_LONGVARBINARY: return "LONG VARBINARY";
1875 case SQL_BIGINT: return "BIGINT";
1876 case SQL_TINYINT: return "TINYINT";
1877 case SQL_BIT: return "BIT";
1878 }
1879 return "unknown";
1880}
1881
1882
1883
1884static const char *S_SqlCTypeToString (SWORD sqltype)
1885{
1886 static char s_buf[100];
1887#define s_c(x) case x: return #x
1888 switch(sqltype) {
1889 s_c(SQL_C_CHAR);
1890 s_c(SQL_C_WCHAR);
1891 s_c(SQL_C_BIT);
1892 s_c(SQL_C_STINYINT);
1893 s_c(SQL_C_UTINYINT);
1894 s_c(SQL_C_SSHORT);
1895 s_c(SQL_C_USHORT);
1896 s_c(SQL_C_FLOAT);
1897 s_c(SQL_C_DOUBLE);
1898 s_c(SQL_C_BINARY);
1899 s_c(SQL_C_DATE);
1900 s_c(SQL_C_TIME);
1901 s_c(SQL_C_TIMESTAMP);
1902 s_c(SQL_C_TYPE_DATE);
1903 s_c(SQL_C_TYPE_TIME);
1904 s_c(SQL_C_TYPE_TIMESTAMP);
1905 }
1906#undef s_c
1907 sprintf(s_buf, "(CType %d)", sqltype);
1908 return s_buf;
1909}
1910
1911
1912
1913
1914/*
1915 * describes the output variables of a query,
1916 * allocates buffers for result rows,
1917 * and binds this buffers to the statement.
1918 */
1919int dbd_describe(SV *h, imp_sth_t *imp_sth, int more)
1920{
1921 dTHR;
1922 SQLRETURN rc; /* ODBC fn return value */
1923 UCHAR *rbuf_ptr;
1924 SQLSMALLINT i;
1925 imp_fbh_t *fbh;
1926 SQLLEN t_dbsize = 0; /* size of native type */
1927 SQLSMALLINT num_fields;
1928 SQLCHAR *cur_col_name;
1929 struct imp_dbh_st *imp_dbh = NULL;
1930 imp_dbh = (struct imp_dbh_st *)(DBIc_PARENT_COM(imp_sth));
1931
1932 if (DBIc_TRACE(imp_sth, 0, 0, 4))
1933 TRACE1(imp_sth, " dbd_describe done_desc=%d\n", imp_sth->done_desc);
1934
1935 if (imp_sth->done_desc)
1936 return 1; /* success, already done it */
1937
1938 rc = SQLNumResultCols(imp_sth->hstmt, &num_fields);
1939 if (!SQL_SUCCEEDED(rc)) {
1940 dbd_error(h, rc, "dbd_describe/SQLNumResultCols");
1941 return 0;
1942 } else if (DBIc_TRACE(imp_sth, 0, 0, 4))
1943 TRACE1(imp_sth, " dbd_describe SQLNumResultCols=0 (rows=%d)\n",
1944 num_fields);
1945
1946 /*
1947 * A little extra check to see if SQLMoreResults is supported
1948 * before trying to call it. This is to work around some strange
1949 * behavior with SQLServer's driver and stored procedures which
1950 * insert data.
1951 */
1952 imp_sth->done_desc = 1; /* assume ok from here on */
1953 if (!more) {
1954 while (num_fields == 0 &&
1955 imp_dbh->odbc_sqlmoreresults_supported == 1) {
1956 rc = SQLMoreResults(imp_sth->hstmt);
1957 if (DBIc_TRACE(imp_sth, 0, 0, 8))
1958 TRACE1(imp_sth,
1959 " Numfields = 0, SQLMoreResults = %d\n", rc);
1960 if (rc == SQL_SUCCESS_WITH_INFO) {
1961 AllODBCErrors(imp_sth->henv, imp_sth->hdbc, imp_sth->hstmt,
1962 DBIc_TRACE(imp_sth, 0, 0, 4),
1963 DBIc_LOGPIO(imp_dbh));
1964 }
1965 if (rc == SQL_NO_DATA) {
1966 imp_sth->moreResults = 0;
1967 break;
1968 } else if (!SQL_SUCCEEDED(rc)) {
1969 break;
1970 }
1971 /* reset describe flags, so that we re-describe */
1972 imp_sth->done_desc = 0;
1973
1974 /* force future executes to rebind automatically */
1975 imp_sth->odbc_force_rebind = 1;
1976
1977 rc = SQLNumResultCols(imp_sth->hstmt, &num_fields);
1978 if (!SQL_SUCCEEDED(rc)) {
1979 dbd_error(h, rc, "dbd_describe/SQLNumResultCols");
1980 return 0;
1981 } else if (DBIc_TRACE(imp_sth, 0, 0, 8)) {
1982 TRACE1(imp_dbh, " num fields after MoreResults = %d\n",
1983 num_fields);
1984 }
1985 } /* end of SQLMoreResults */
1986 } /* end of more */
1987
1988 DBIc_NUM_FIELDS(imp_sth) = num_fields;
1989
1990 if (num_fields == 0) {
1991 if (DBIc_TRACE(imp_sth, 0, 0, 4))
1992 TRACE0(imp_dbh, " dbd_describe skipped (no result cols)\n");
1993 return 1;
1994 }
1995
1996 /* allocate field buffers */
1997 Newz(42, imp_sth->fbh, num_fields, imp_fbh_t);
1998 /* the +255 below instead is due to an old comment in this code before
1999 this change claiming foxpro wrote off end of memory
2000 (and so 255 bytes were added - kept here without evidence) */
2001 Newz(42, imp_sth->ColNames,
2002 (num_fields + 1) * imp_dbh->max_column_name_len + 255, UCHAR);
2003
2004 cur_col_name = imp_sth->ColNames;
2005 /* Pass 1: Get space needed for field names, display buffer and dbuf */
2006 for (fbh=imp_sth->fbh, i=0; i < num_fields; i++, fbh++) {
2007 fbh->imp_sth = imp_sth;
2008#ifdef WITH_UNICODE
2009 rc = SQLDescribeColW(imp_sth->hstmt,
2010 (SQLSMALLINT)(i+1),
2011 (SQLWCHAR *) cur_col_name,
2012 (SQLSMALLINT)imp_dbh->max_column_name_len,
2013 &fbh->ColNameLen,
2014 &fbh->ColSqlType,
2015 &fbh->ColDef,
2016 &fbh->ColScale,
2017 &fbh->ColNullable);
2018 /*
2019 printf("strlen=%d, collen=%d\n", strlen(cur_col_name), fbh->ColNameLen);
2020
2021 {
2022
2023 int i;
2024
2025 SQLWCHAR *wp = (SQLWCHAR *)cur_col_name;
2026
2027 printf("SQLDescribeCol = ");
2028
2029 for (i = 0; i < fbh->ColNameLen; i++) {
2030 printf("%ld, ", wp[i]);
2031 }
2032 printf("\n");
2033 }
2034 */
2035
2036#else /* WITH_UNICODE */
2037 rc = SQLDescribeCol(imp_sth->hstmt,
2038 (SQLSMALLINT)(i+1),
2039 cur_col_name,
2040 (SQLSMALLINT)imp_dbh->max_column_name_len,
2041 &fbh->ColNameLen,
2042 &fbh->ColSqlType,
2043 &fbh->ColDef,
2044 &fbh->ColScale,
2045 &fbh->ColNullable);
2046#endif /* WITH_UNICODE */
2047 if (!SQL_SUCCEEDED(rc)) { /* should never fail */
2048 dbd_error(h, rc, "describe/SQLDescribeCol");
2049 break;
2050 }
2051 fbh->ColName = cur_col_name;
2052#ifdef WITH_UNICODE
2053 cur_col_name += fbh->ColNameLen * sizeof(SQLWCHAR);
2054#else
2055 cur_col_name += fbh->ColNameLen + 1;
2056 cur_col_name[fbh->ColNameLen] = '\0';
2057#endif
2058#ifdef SQL_COLUMN_DISPLAY_SIZE
2059 if (DBIc_TRACE(imp_sth, 0, 0, 8))
2060 PerlIO_printf(DBIc_LOGPIO(imp_dbh),
2061 " DescribeCol column = %d, name = %s, "
2062 "len = %d, type = %s(%d), "
2063 "precision = %ld, scale = %d, nullable = %d\n",
2064 i+1, fbh->ColName,
2065 fbh->ColNameLen,
2066 S_SqlTypeToString(fbh->ColSqlType),
2067 fbh->ColSqlType,
2068 fbh->ColDef, fbh->ColScale, fbh->ColNullable);
2069 rc = SQLColAttributes(imp_sth->hstmt,
2070 (SQLSMALLINT)(i+1),SQL_COLUMN_DISPLAY_SIZE,
2071 NULL, 0, NULL ,
2072 &fbh->ColDisplaySize);/* TBD: 3.0 update */
2073 if (!SQL_SUCCEEDED(rc)) {
2074 /* Some ODBC drivers don't support SQL_COLUMN_DISPLAY_SIZE on
2075 some result-sets. e.g., The "Infor Integration ODBC driver"
2076 cannot handle SQL_COLUMN_DISPLAY_SIZE and SQL_COLUMN_LENGTH
2077 for SQLTables and SQLColumns calls. We used to fail here but
2078 there is a prescident not to as this code is already in an
2079 ifdef for drivers that do not define SQL_COLUMN_DISPLAY_SIZE.
2080 Since just about everyone will be using an ODBC driver manager
2081 now it is unlikely these attributes will not be defined so we
2082 default if the call fails now */
2083 if( DBIc_TRACE(imp_sth, 0, 0, 8) ) {
2084 TRACE0(imp_sth,
2085 " describe/SQLColAttributes/SQL_COLUMN_DISPLAY_SIZE "
2086 "not supported, will be equal to SQL_COLUMN_LENGTH\n");
2087 }
2088 /* ColDisplaySize will be made equal to ColLength */
2089 fbh->ColDisplaySize = 0;
2090 rc = SQL_SUCCESS;
2091 } else if (DBIc_TRACE(imp_sth, 0, 0, 8)) {
2092 TRACE1(imp_sth, " display size = %ld\n", fbh->ColDisplaySize);
2093 }
2094
2095 /* TBD: should we only add a terminator if it's a char??? */
2096 fbh->ColDisplaySize += 1; /* add terminator */
2097#else
2098 fbh->ColDisplaySize = imp_sth->odbc_column_display_size;
2099#endif
2100
2101#ifdef SQL_COLUMN_LENGTH
2102 rc = SQLColAttributes(imp_sth->hstmt,(SQLSMALLINT)(i+1),
2103 SQL_COLUMN_LENGTH,
2104 NULL, 0, NULL ,&fbh->ColLength);
2105 if (!SQL_SUCCEEDED(rc)) {
2106 /* See comment above under SQL_COLUMN_DISPLAY_SIZE */
2107 fbh->ColLength = imp_sth->odbc_column_display_size;
2108 if( DBIc_TRACE(imp_sth, 0, 0, 8) ) {
2109 TRACE1(imp_sth,
2110 " describe/SQLColAttributes/SQL_COLUMN_LENGTH not "
2111 "supported, fallback on %d\n", fbh->ColLength);
2112 }
2113 rc = SQL_SUCCESS;
2114 } else if (DBIc_TRACE(imp_sth, 0, 0, 8)) {
2115 TRACE1(imp_sth, " column length = %ld\n", fbh->ColLength);
2116 }
2117# if defined(WITH_UNICODE)
2118 fbh->ColLength += 1; /* add extra byte for double nul terminator */
2119# endif
2120#else
2121 fbh->ColLength = imp_sth->odbc_column_display_size;
2122#endif
2123
2124 /* may want to ensure Display Size at least as large as column
2125 * length -- workaround for some drivers which report a shorter
2126 * display length
2127 * */
2128 fbh->ColDisplaySize =
2129 fbh->ColDisplaySize > fbh->ColLength ?
2130 fbh->ColDisplaySize : fbh->ColLength;
2131
2132 /*
2133 * change fetched size, decimal digits etc for some types,
2134 * The tests for ColDef = 0 are for when the driver does not give
2135 * us a length for the column e.g., "max" column types in SQL Server
2136 * like varbinary(max).
2137 */
2138 fbh->ftype = SQL_C_CHAR;
2139 switch(fbh->ColSqlType)
2140 {
2141 case SQL_VARBINARY:
2142 case SQL_BINARY:
2143 fbh->ftype = SQL_C_BINARY;
2144 if (fbh->ColDef == 0) { /* cope with varbinary(max) */
2145 fbh->ColDisplaySize = DBIc_LongReadLen(imp_sth);
2146 }
2147 break;
2148#if defined(WITH_UNICODE)
2149 case SQL_WCHAR:
2150 case SQL_WVARCHAR:
2151 fbh->ftype = SQL_C_WCHAR;
2152 /* MS SQL returns bytes, Oracle returns characters ... */
2153
2154 if (fbh->ColDef == 0) { /* cope with nvarchar(max) */
2155 fbh->ColDisplaySize = DBIc_LongReadLen(imp_sth);
2156 fbh->ColLength = DBIc_LongReadLen(imp_sth);
2157 }
2158
2159 fbh->ColDisplaySize*=sizeof(SQLWCHAR);
2160 fbh->ColLength*=sizeof(SQLWCHAR);
2161 break;
2162#else
2163# if defined(SQL_WCHAR)
2164 case SQL_WCHAR:
2165 if (fbh->ColDef == 0) {
2166 fbh->ColDisplaySize = DBIc_LongReadLen(imp_sth);
2167 }
2168 break;
2169# endif
2170# if defined(SQL_WVARCHAR)
2171 case SQL_WVARCHAR:
2172 if (fbh->ColDef == 0) {
2173 fbh->ColDisplaySize = DBIc_LongReadLen(imp_sth);
2174 }
2175 break;
2176# endif
2177#endif /* WITH_UNICODE */
2178 case SQL_LONGVARBINARY:
2179 fbh->ftype = SQL_C_BINARY;
2180 fbh->ColDisplaySize = DBIc_LongReadLen(imp_sth);
2181 break;
2182#ifdef SQL_WLONGVARCHAR
2183 case SQL_WLONGVARCHAR: /* added for SQLServer 7 ntext type */
2184# if defined(WITH_UNICODE)
2185 fbh->ftype = SQL_C_WCHAR;
2186 /* MS SQL returns bytes, Oracle returns characters ... */
2187 fbh->ColLength*=sizeof(SQLWCHAR);
2188 fbh->ColDisplaySize = DBIc_LongReadLen(imp_sth)+1;
2189 break;
2190# endif /* WITH_UNICODE */
2191#endif
2192 case SQL_VARCHAR:
2193 if (fbh->ColDef == 0) {
2194 fbh->ColDisplaySize = DBIc_LongReadLen(imp_sth)+1;
2195 }
2196 break;
2197 case SQL_LONGVARCHAR:
2198 fbh->ColDisplaySize = DBIc_LongReadLen(imp_sth)+1;
2199 break;
2200#ifdef TIMESTAMP_STRUCT /* XXX! */
2201 case SQL_TIMESTAMP:
2202 case SQL_TYPE_TIMESTAMP:
2203 fbh->ftype = SQL_C_TIMESTAMP;
2204 fbh->ColDisplaySize = sizeof(TIMESTAMP_STRUCT);
2205 break;
2206#endif
2207 }
2208
2209 /* make sure alignment is accounted for on all types, including
2210 * chars */
2211#if 0
2212 if (fbh->ftype != SQL_C_CHAR) {
2213 t_dbsize += t_dbsize % sizeof(int); /* alignment (JLU incorrect!) */
2214 }
2215#endif
2216 t_dbsize += fbh->ColDisplaySize;
2217 /* alignment -- always pad so the next column is aligned on a
2218 word boundary */
2219 t_dbsize += (sizeof(int) - (t_dbsize % sizeof(int))) % sizeof(int);
2220
2221 if (DBIc_TRACE(imp_sth, 0, 0, 4))
2222 PerlIO_printf(DBIc_LOGPIO(imp_dbh),
2223 " now using col %d: type = %s (%d), len = %d, "
2224 "display size = %d, prec = %d, scale = %d\n",
2225 i+1, S_SqlTypeToString(fbh->ColSqlType),
2226 fbh->ColSqlType,
2227 fbh->ColLength, fbh->ColDisplaySize,
2228 fbh->ColDef, fbh->ColScale);
2229 }
2230 if (!SQL_SUCCEEDED(rc)) {
2231 /* dbd_error called above */
2232 Safefree(imp_sth->fbh);
2233 return 0;
2234 }
2235
2236 /* allocate Row memory */
2237 Newz(42, imp_sth->RowBuffer, t_dbsize + num_fields, UCHAR);
2238
2239 /* Second pass:
2240 - get column names
2241 - bind column output
2242 */
2243
2244 rbuf_ptr = imp_sth->RowBuffer;
2245
2246 for(i=0, fbh = imp_sth->fbh;
2247 i < num_fields && SQL_SUCCEEDED(rc); i++, fbh++)
2248 {
2249 /* not sure I need this anymore, since we are trying to align
2250 * the columns anyway
2251 * */
2252 switch(fbh->ftype)
2253 {
2254 case SQL_C_BINARY:
2255 case SQL_C_TIMESTAMP:
2256 case SQL_C_TYPE_TIMESTAMP:
2257 /* make sure pointer is on word boundary for Solaris */
2258 rbuf_ptr += (sizeof(int) -
2259 ((rbuf_ptr - imp_sth->RowBuffer) % sizeof(int))) %
2260 sizeof(int);
2261
2262 break;
2263 }
2264
2265 fbh->data = rbuf_ptr;
2266 rbuf_ptr += fbh->ColDisplaySize;
2267 /* alignment -- always pad so the next column is aligned on a word
2268 boundary */
2269 rbuf_ptr += (sizeof(int) - ((rbuf_ptr - imp_sth->RowBuffer) %
2270 sizeof(int))) % sizeof(int);
2271
2272 /* Bind output column variables */
2273 rc = SQLBindCol(imp_sth->hstmt,
2274 (SQLSMALLINT)(i+1),
2275 fbh->ftype, fbh->data,
2276 fbh->ColDisplaySize, &fbh->datalen);
2277 if (!SQL_SUCCEEDED(rc)) {
2278 dbd_error(h, rc, "describe/SQLBindCol");
2279 break;
2280 }
2281 } /* end pass 2 */
2282
2283 if (!SQL_SUCCEEDED(rc)) {
2284 /* dbd_error called above */
2285 Safefree(imp_sth->fbh);
2286 return 0;
2287 }
2288 return 1;
2289}
2290
2291
2292
2293/*======================================================================*/
2294/* */
2295/* dbd_st_execute */
2296/* ============== */
2297/* */
2298/* returns: */
2299/* -2 - error */
2300/* >=0 - ok, row count */
2301/* -1 - unknown count */
2302/* */
2303/*======================================================================*/
2304int dbd_st_execute(
2305 SV *sth, imp_sth_t *imp_sth)
2306{
2307 dTHR;
2308 RETCODE rc;
2309 D_imp_dbh_from_sth;
2310 int outparams = 0;
2311 int ret;
2312
2313 if (DBIc_TRACE(imp_sth, 0, 0, 3))
2314 TRACE1(imp_dbh, "+dbd_st_execute(%p)\n", sth);
2315
2316 /*
2317 * if the handle is active, we need to finish it here.
2318 * Note that dbd_st_finish already checks to see if it's active.
2319 */
2320 dbd_st_finish(sth, imp_sth);;
2321
2322 /*
2323 * bind_param_inout support
2324 */
2325 outparams = (imp_sth->out_params_av) ? AvFILL(imp_sth->out_params_av)+1 : 0;
2326 if (DBIc_TRACE(imp_sth, 0, 0, 4)) {
2327 TRACE1(imp_dbh, " outparams = %d\n", outparams);
2328 }
2329
2330 if (imp_dbh->odbc_defer_binding) {
2331 rc = SQLFreeStmt(imp_sth->hstmt, SQL_RESET_PARAMS);
2332 /* check bind input parameters */
2333 if (imp_sth->all_params_hv) {
2334 HV *hv = imp_sth->all_params_hv;
2335 SV *sv;
2336 char *key;
2337 I32 retlen;
2338 hv_iterinit(hv);
2339 while( (sv = hv_iternextsv(hv, &key, &retlen)) != NULL ) {
2340 if (sv != &sv_undef) {
2341 phs_t *phs = (phs_t*)(void*)SvPVX(sv);
2342 if (!rebind_param(sth, imp_sth, phs)) return -2;
2343 if (DBIc_TRACE(imp_sth, 0, 0, 8)) {
2344 if (SvOK(phs->sv) && (phs->value_type == SQL_C_CHAR)) {
2345 char sbuf[256];
2346 unsigned int i = 0;
2347
2348 while((phs->sv_buf[i] != 0) && (i < (sizeof(sbuf) - 6))) {
2349 sbuf[i] = phs->sv_buf[i];
2350 i++;
2351 }
2352 strcpy(&sbuf[i], "...");
2353
2354 TRACE2(imp_dbh,
2355 " rebind check char Param %d (%s)\n",
2356 phs->idx, sbuf);
2357 }
2358 }
2359 }
2360 }
2361 }
2362 }
2363
2364 if (outparams) { /* check validity of bind_param_inout SV's */
2365 int i = outparams;
2366 while(--i >= 0) {
2367 phs_t *phs = (phs_t*)(void*)SvPVX(AvARRAY(imp_sth->out_params_av)[i]);
2368 /* Make sure we have the value in string format. Typically a number */
2369 /* will be converted back into a string using the same bound buffer */
2370 /* so the sv_buf test below will not trip. */
2371
2372 /* mutation check */
2373 if (SvTYPE(phs->sv) != phs->sv_type /* has the type changed? */
2374 || (SvOK(phs->sv) && !SvPOK(phs->sv)) /* is there still a string? */
2375 || SvPVX(phs->sv) != phs->sv_buf /* has the string buffer moved? */
2376 ) {
2377 if (!rebind_param(sth, imp_sth, phs))
2378 croak("Can't rebind placeholder %s", phs->name);
2379 } else {
2380 /* no mutation found */
2381 }
2382 }
2383 }
2384
2385
2386 if (imp_sth->odbc_exec_direct) {
2387 /* statement ready for SQLExecDirect */
2388 if (DBIc_TRACE(imp_sth, 0, 0, 5)) {
2389 TRACE0(imp_dbh,
2390 " odbc_exec_direct=1, using SQLExecDirect\n");
2391 }
2392 rc = SQLExecDirect(imp_sth->hstmt, imp_sth->statement, SQL_NTS);
2393 } else {
2394 rc = SQLExecute(imp_sth->hstmt);
2395 }
2396 if (DBIc_TRACE(imp_sth, 0, 0, 8))
2397 TRACE2(imp_dbh, " SQLExecute/SQLExecDirect(%p)=%d\n",
2398 imp_sth->hstmt, rc);
2399 /*
2400 * If asynchronous execution has been enabled, SQLExecute will
2401 * return SQL_STILL_EXECUTING until it has finished.
2402 * Grab whatever messages occur during execution...
2403 */
2404 while (rc == SQL_STILL_EXECUTING){
2405 dbd_error(sth, rc, "st_execute/SQLExecute");
2406
2407 /*
2408 * Wait a second so we don't loop too fast and bring the machine
2409 * to its knees
2410 */
2411 if (DBIc_TRACE(imp_sth, 0, 0, 5))
2412 TRACE1(imp_dbh, " SQLExecute(%p) still executing", imp_sth->hstmt);
2413 sleep(1);
2414 rc = SQLExecute(imp_sth->hstmt);
2415 }
2416 /* patches to handle blobs better, via Jochen Wiedmann */
2417 while (rc == SQL_NEED_DATA) {
2418 phs_t* phs;
2419 STRLEN len;
2420 UCHAR* ptr;
2421
2422 if (DBIc_TRACE(imp_sth, 0, 0, 5))
2423 TRACE1(imp_dbh, " NEED DATA\n", imp_sth->hstmt);
2424
2425 while ((rc = SQLParamData(imp_sth->hstmt, (PTR*) &phs)) ==
2426 SQL_STILL_EXECUTING) {
2427 if (DBIc_TRACE(imp_sth, 0, 0, 5))
2428 TRACE1(imp_dbh, " SQLParamData(%p) still executing",
2429 imp_sth->hstmt);
2430 /*
2431 * wait a while to avoid looping too fast waiting for SQLParamData
2432 * to complete.
2433 */
2434 sleep(1);
2435 }
2436 if (rc != SQL_NEED_DATA) {
2437 break;
2438 }
2439
2440 /* phs->sv is already upgraded to a PV in rebind_param.
2441 * It is not NULL, because we otherwise won't be called here
2442 * (value_len = 0).
2443 */
2444 ptr = SvPV(phs->sv, len);
2445 rc = SQLPutData(imp_sth->hstmt, ptr, len);
2446 if (!SQL_SUCCEEDED(rc)) {
2447 break;
2448 }
2449 rc = SQL_NEED_DATA; /* So the loop continues ... */
2450 }
2451
2452 /*
2453 * Call dbd_error regardless of the value of rc so we can
2454 * get any status messages that are desired.
2455 */
2456 dbd_error(sth, rc, "st_execute/SQLExecute");
2457 if (!SQL_SUCCEEDED(rc) && rc != SQL_NO_DATA) {
2458 /* dbd_error(sth, rc, "st_execute/SQLExecute"); */
2459 if (DBIc_TRACE(imp_sth, 0, 0, 3))
2460 TRACE1(imp_dbh, "-dbd_st_execute(%p)=-2\n", sth);
2461 return -2;
2462 }
2463
2464 if (rc != SQL_NO_DATA) {
2465
2466 /* SWORD num_fields; */
2467 RETCODE rc2;
2468 rc2 = SQLRowCount(imp_sth->hstmt, &imp_sth->RowCount);
2469 if (DBIc_TRACE(imp_sth, 0, 0, 7))
2470 TRACE2(imp_dbh, " SQLRowCount=%d (rows=%d)\n",
2471 rc2, (SQL_SUCCEEDED(rc2) ? imp_sth->RowCount : -1));
2472 if (!SQL_SUCCEEDED(rc2)) {
2473 dbd_error(sth, rc2, "st_execute/SQLRowCount"); /* XXX ? */
2474 imp_sth->RowCount = -1;
2475 }
2476
2477 /* sanity check for strange circumstances and multiple types of
2478 * result sets. Crazy that it can happen, but it can with
2479 * multiple result sets and stored procedures which return
2480 * result sets.
2481 * This seems to slow things down a bit and is rarely needed.
2482 *
2483 * This can happen in Sql Server in strange cases where stored
2484 * procs have multiple result sets. Sometimes, if there is an
2485 * select then an insert, etc. Maybe this should be a special
2486 * attribute to force a re-describe after every execute? */
2487 if (imp_sth->odbc_force_rebind) {
2488 /* force calling dbd_describe after each execute */
2489 odbc_clear_result_set(sth, imp_sth);
2490 }
2491 } else {
2492 /* SQL_NO_DATA returned, must have no rows :) */
2493 /* seem to need to reset the done_desc, but not sure if this is
2494 * what we want yet */
2495 if (DBIc_TRACE(imp_sth, 0, 0, 7))
2496 TRACE0(imp_dbh,
2497 " SQL_NO_DATA...resetting done_desc!\n");
2498 imp_sth->done_desc = 0;
2499 imp_sth->RowCount = 0;
2500 }
2501
2502 /*
2503 * MS SQL Server is very picky wrt to completing a procedure i.e.,
2504 * it says the output bound parameters are not available until the procedure
2505 * is complete and the procedure is not complete until you have called
2506 * SQLMoreResults and it has returned SQL_NO_DATA. So, if you call a
2507 * procedure multiple times in the same statement (e.g., by just calling
2508 * execute) DBD::ODBC will call dbd_describe to describe the first
2509 * execute, discover there is no result-set and call SQLMoreResults - ok,
2510 * but after that, the dbd_describe is done and SQLMoreResults will not
2511 * get called. The following is a klude to get around this until
2512 * a) DBD::ODBC can be changed to stop skipping over non-result-set
2513 * generating statements and b) the SQLMoreResults calls move out of
2514 * dbd_describe.
2515 */
2516 {
2517 SQLSMALLINT flds = 0;
2518 SQLRETURN sts;
2519
2520 sts = SQLNumResultCols(imp_sth->hstmt, &flds);
2521 if (flds == 0) { /* not a result-set */
2522 if (DBIc_TRACE(imp_sth, 0, 0, 4))
2523 TRACE2(imp_dbh, " nflds=(%d,%d), resetting done_desc\n",
2524 flds, DBIc_NUM_FIELDS(imp_sth));
2525 imp_sth->done_desc = 0;
2526 }
2527 }
2528
2529 if (!imp_sth->done_desc) {
2530 /* This needs to be done after SQLExecute for some drivers! */
2531 /* Especially for order by and join queries. */
2532 /* See Microsoft Knowledge Base article (#Q124899) */
2533 /* describe and allocate storage for results (if any needed) */
2534 if (!dbd_describe(sth, imp_sth, 0)) {
2535 if (DBIc_TRACE(imp_sth, 0, 0, 3)) {
2536 TRACE0(imp_sth,
2537 " !!dbd_describe failed, dbd_st_execute #1...!\n");
2538 }
2539 if (DBIc_TRACE(imp_sth, 0, 0, 3))
2540 TRACE1(imp_dbh, "-dbd_st_execute(%p)=-2\n", sth);
2541 return -2; /* dbd_describe already called dbd_error() */
2542 }
2543 }
2544
2545 if (DBIc_NUM_FIELDS(imp_sth) > 0) {
2546 DBIc_ACTIVE_on(imp_sth); /* only set for select (?) */
2547 if (DBIc_TRACE(imp_sth, 0, 0, 4)) {
2548 TRACE1(imp_sth, " have %d fields\n",
2549 DBIc_NUM_FIELDS(imp_sth));
2550 }
2551
2552 } else {
2553 if (DBIc_TRACE(imp_sth, 0, 0, 4)) {
2554 TRACE0(imp_dbh, " got no rows: resetting ACTIVE, moreResults\n");
2555 }
2556 imp_sth->moreResults = 0;
2557 /* flag that we've done the describe to avoid a problem
2558 * where calling describe after execute returned no rows
2559 * caused SQLServer to provide a description of a query
2560 * that didn't quite apply. */
2561
2562 /* imp_sth->done_desc = 1; */
2563 DBIc_ACTIVE_off(imp_sth);
2564 }
2565 imp_sth->eod = SQL_SUCCESS;
2566
2567 if (outparams) { /* check validity of bound output SV's */
2568 odbc_handle_outparams(imp_sth, DBIc_TRACE_LEVEL(imp_sth));
2569 }
2570
2571 /*
2572 * JLU: Jon Smirl had:
2573 * return (imp_sth->RowCount == -1 ? -1 : abs(imp_sth->RowCount));
2574 * why? Why do you need the abs() of the rowcount? Special reason?
2575 * The e-mail that accompanied the change indicated that Sybase would return
2576 * a negative value for an estimate. Wouldn't you WANT that to stay
2577 * negative?
2578 *
2579 * dgood: JLU had:
2580 * return imp_sth->RowCount;
2581 * Because you return -2 on errors so if you don't abs() it, a perfectly
2582 * valid return value will get flagged as an error...
2583 */
2584 ret = (imp_sth->RowCount == -1 ? -1 : abs(imp_sth->RowCount));
2585
2586 if (DBIc_TRACE(imp_sth, 0, 0, 3))
2587 TRACE2(imp_dbh, "-dbd_st_execute(%p)=%d\n", sth, ret);
2588 return ret;
2589 /* return imp_sth->RowCount; */
2590}
2591
2592
2593
2594
2595/*----------------------------------------
2596 * running $sth->fetch()
2597 *----------------------------------------
2598 */
2599AV *dbd_st_fetch(SV *sth, imp_sth_t *imp_sth)
2600{
2601 dTHR;
2602 D_imp_dbh_from_sth;
2603 int i;
2604 AV *av;
2605 RETCODE rc;
2606 int num_fields;
2607#ifdef TIMESTAMP_STRUCT /* iODBC doesn't define this */
2608 char cvbuf[512];
2609#endif
2610 int ChopBlanks;
2611
2612 /* Check that execute() was executed sucessfully. This also implies */
2613 /* that dbd_describe() executed sucessfuly so the memory buffers */
2614 /* are allocated and bound. */
2615 if ( !DBIc_ACTIVE(imp_sth) ) {
2616 dbd_error(sth, SQL_ERROR, "no select statement currently executing");
2617 return Nullav;
2618 }
2619
2620 rc = SQLFetch(imp_sth->hstmt);
2621 if (DBIc_TRACE(imp_sth, 0, 0, 4))
2622 TRACE1(imp_dbh, " SQLFetch rc %d\n", rc);
2623 imp_sth->eod = rc;
2624 if (!SQL_SUCCEEDED(rc)) {
2625 if (SQL_NO_DATA_FOUND == rc) {
2626
2627 if (imp_dbh->odbc_sqlmoreresults_supported == 1) {
2628 rc = SQLMoreResults(imp_sth->hstmt);
2629 /* Check for multiple results */
2630 if (DBIc_TRACE(imp_sth, 0, 0, 6))
2631 TRACE1(imp_dbh, " Getting more results: %d\n", rc);
2632
2633 if (rc == SQL_SUCCESS_WITH_INFO) {
2634 dbd_error(sth, rc, "st_fetch/SQLMoreResults");
2635 /* imp_sth->moreResults = 0; */
2636 }
2637 if (SQL_SUCCEEDED(rc)){
2638 /* More results detected. Clear out the old result */
2639 /* stuff and re-describe the fields. */
2640 if (DBIc_TRACE(imp_sth, 0, 0, 3)) {
2641 TRACE0(imp_dbh, " MORE Results!\n");
2642 }
2643 odbc_clear_result_set(sth, imp_sth);
2644
2645 /* force future executes to rebind automatically */
2646 imp_sth->odbc_force_rebind = 1;
2647
2648 /* tell the odbc driver that we need to unbind the
2649 * bound columns. Fix bug for 0.35 (2/8/02) */
2650 rc = SQLFreeStmt(imp_sth->hstmt, SQL_UNBIND);
2651 if (!SQL_SUCCEEDED(rc)) {
2652 AllODBCErrors(imp_dbh->henv, imp_dbh->hdbc, 0,
2653 DBIc_TRACE(imp_sth, 0, 0, 3),
2654 DBIc_LOGPIO(imp_dbh));
2655 }
2656
2657 if (!dbd_describe(sth, imp_sth, 1)) {
2658 if (DBIc_TRACE(imp_sth, 0, 0, 3))
2659 TRACE0(imp_dbh,
2660 " !!MORE Results dbd_describe failed...!\n");
2661 return Nullav; /* dbd_describe already called dbd_error() */
2662 }
2663
2664
2665 if (DBIc_TRACE(imp_sth, 0, 0, 4)) {
2666 TRACE0(imp_dbh,
2667 " MORE Results dbd_describe success...!\n");
2668 }
2669 /* set moreResults so we'll know we can keep fetching */
2670 imp_sth->moreResults = 1;
2671 imp_sth->done_desc = 0;
2672 return Nullav;
2673 }
2674 else if (rc == SQL_NO_DATA_FOUND || rc == SQL_NO_DATA ||
2675 rc == SQL_SUCCESS_WITH_INFO){
2676 /* No more results */
2677 /* need to check output params here... */
2678 int outparams = (imp_sth->out_params_av) ?
2679 AvFILL(imp_sth->out_params_av)+1 : 0;
2680
2681 if (DBIc_TRACE(imp_sth, 0, 0, 6)) {
2682 TRACE1(imp_sth, " No more results -- outparams = %d\n",
2683 outparams);
2684 }
2685 imp_sth->moreResults = 0;
2686 imp_sth->done_desc = 1;
2687 if (outparams) {
2688 odbc_handle_outparams(imp_sth, DBIc_TRACE_LEVEL(imp_sth));
2689 }
2690 /* XXX need to 'finish' here */
2691 dbd_st_finish(sth, imp_sth);
2692 return Nullav;
2693 }
2694 else {
2695 dbd_error(sth, rc, "st_fetch/SQLMoreResults");
2696 }
2697 }
2698 else {
2699 /*
2700 * SQLMoreResults not supported, just finish.
2701 * per bug found by Jarkko Hyöty [hyoty@medialab.sonera.fi]
2702 * No more results
2703 */
2704 imp_sth->moreResults = 0;
2705 /* XXX need to 'finish' here */
2706 dbd_st_finish(sth, imp_sth);
2707 return Nullav;
2708 }
2709 } else {
2710 dbd_error(sth, rc, "st_fetch/SQLFetch");
2711 /* XXX need to 'finish' here */
2712 dbd_st_finish(sth, imp_sth);
2713 return Nullav;
2714 }
2715 }
2716
2717
2718 if (imp_sth->RowCount == -1)
2719 imp_sth->RowCount = 0;
2720 imp_sth->RowCount++;
2721
2722 av = DBIc_DBISTATE(imp_sth)->get_fbav(imp_sth);
2723 num_fields = AvFILL(av)+1;
2724
2725 if (DBIc_TRACE(imp_sth, 0, 0, 4))
2726 TRACE1(imp_dbh, " fetch num_fields=%d\n", num_fields);
2727
2728 ChopBlanks = DBIc_has(imp_sth, DBIcf_ChopBlanks);
2729
2730 for(i=0; i < num_fields; ++i) {
2731 imp_fbh_t *fbh = &imp_sth->fbh[i];
2732 SV *sv = AvARRAY(av)[i]; /* Note: we (re)use the SV in the AV */
2733
2734 if (DBIc_TRACE(imp_sth, 0, 0, 4))
2735 PerlIO_printf(
2736 DBIc_LOGPIO(imp_dbh), " fetch col#%d %s datalen=%d displ=%d\n",
2737 i, fbh->ColName, fbh->datalen, fbh->ColDisplaySize);
2738
2739 if (fbh->datalen == SQL_NULL_DATA) { /* NULL value */
2740 SvOK_off(sv);
2741 continue;
2742 }
2743
2744 if (fbh->datalen > fbh->ColDisplaySize || fbh->datalen < 0) {
2745 /* truncated LONG ??? DBIcf_LongTruncOk() */
2746 /* DBIcf_LongTruncOk this should only apply to LONG type fields */
2747 /* truncation of other fields should always be an error since it's */
2748 /* a sign of an internal error */
2749 if (!DBIc_has(imp_sth, DBIcf_LongTruncOk)
2750 /* && rc == SQL_SUCCESS_WITH_INFO */) {
2751
2752 /*
2753 * Since we've detected the problem locally via the datalen,
2754 * we don't need to worry about the value of rc.
2755 *
2756 * This used to make sure rc was set to SQL_SUCCESS_WITH_INFO
2757 * but since it's an error and not SUCCESS, call dbd_error()
2758 * with SQL_ERROR explicitly instead.
2759 */
2760
2761 dbd_error(
2762 sth, SQL_ERROR,
2763 "st_fetch/SQLFetch (long truncated DBI attribute LongTruncOk "
2764 "not set and/or LongReadLen too small)");
2765 return Nullav;
2766 }
2767 /* LongTruncOk true, just ensure perl has the right length
2768 * for the truncated data.
2769 */
2770 sv_setpvn(sv, (char*)fbh->data, fbh->ColDisplaySize);
2771 }
2772 else switch(fbh->ftype) {
2773#ifdef TIMESTAMP_STRUCT /* iODBC doesn't define this */
2774 TIMESTAMP_STRUCT *ts;
2775 case SQL_C_TIMESTAMP:
2776 case SQL_C_TYPE_TIMESTAMP:
2777 ts = (TIMESTAMP_STRUCT *)fbh->data;
2778 sprintf(cvbuf, "%04d-%02d-%02d %02d:%02d:%02d",
2779 ts->year, ts->month, ts->day,
2780 ts->hour, ts->minute, ts->second, ts->fraction);
2781 sv_setpv(sv, cvbuf);
2782 break;
2783#endif
2784#if defined(WITH_UNICODE)
2785 case SQL_C_WCHAR:
2786 if (ChopBlanks && fbh->ColSqlType == SQL_WCHAR && fbh->datalen > 0)
2787 {
2788 SQLWCHAR *p = (SQLWCHAR*)fbh->data;
2789 while(fbh->datalen && p[fbh->datalen-1]==L' ') {
2790 --fbh->datalen;
2791 }
2792 }
2793 sv_setwvn(sv,(SQLWCHAR*)fbh->data,fbh->datalen/sizeof(SQLWCHAR));
2794 break;
2795#endif /* WITH_UNICODE */
2796 default:
2797 if (ChopBlanks && fbh->ColSqlType == SQL_CHAR && fbh->datalen > 0)
2798 {
2799 char *p = (char*)fbh->data;
2800 while(fbh->datalen && p[fbh->datalen - 1]==' ')
2801 --fbh->datalen;
2802 }
2803 sv_setpvn(sv, (char*)fbh->data, fbh->datalen);
2804 }
2805 }
2806 return av;
2807}
2808
2809
2810
2811
2812int dbd_st_rows(SV *sth, imp_sth_t *imp_sth)
2813{
2814 return (int)imp_sth->RowCount;
2815}
2816
2817
2818
2819
2820int dbd_st_finish(SV *sth, imp_sth_t *imp_sth)
2821{
2822 dTHR;
2823 D_imp_dbh_from_sth;
2824 RETCODE rc;
2825
2826 if (DBIc_TRACE(imp_sth, 0, 0, 3))
2827 TRACE1(imp_sth, " dbd_st_finish(%p)\n", sth);
2828
2829 /* Cancel further fetches from this cursor. */
2830 /* We don't close the cursor till DESTROY (dbd_st_destroy). */
2831 /* The application may re execute(...) it. */
2832
2833 /* XXX semantics of finish (eg oracle vs odbc) need lots more thought */
2834 /* re-read latest DBI specs and ODBC manuals */
2835 if (DBIc_ACTIVE(imp_sth) && imp_dbh->hdbc != SQL_NULL_HDBC) {
2836
2837 rc = SQLFreeStmt(imp_sth->hstmt, SQL_CLOSE);/* TBD: 3.0 update */
2838 if (!SQL_SUCCEEDED(rc)) {
2839 dbd_error(sth, rc, "finish/SQLFreeStmt(SQL_CLOSE)");
2840 return 0;
2841 }
2842 if (DBIc_TRACE(imp_sth, 0, 0, 6)) {
2843 TRACE0(imp_dbh, " dbd_st_finish closed query:\n");
2844 }
2845 }
2846 DBIc_ACTIVE_off(imp_sth);
2847 return 1;
2848}
2849
2850
2851
2852void dbd_st_destroy(SV *sth, imp_sth_t *imp_sth)
2853{
2854 dTHR;
2855 D_imp_dbh_from_sth;
2856 RETCODE rc;
2857
2858 /* Free contents of imp_sth */
2859
2860 /* PerlIO_printf(DBIc_LOGPIO(imp_dbh), " dbd_st_destroy\n"); */
2861 Safefree(imp_sth->fbh);
2862 Safefree(imp_sth->RowBuffer);
2863 Safefree(imp_sth->ColNames);
2864 Safefree(imp_sth->statement);
2865
2866 if (imp_sth->out_params_av)
2867 sv_free((SV*)imp_sth->out_params_av);
2868
2869 if (imp_sth->all_params_hv) {
2870 HV *hv = imp_sth->all_params_hv;
2871 SV *sv;
2872 char *key;
2873 I32 retlen;
2874 hv_iterinit(hv);
2875 while( (sv = hv_iternextsv(hv, &key, &retlen)) != NULL ) {
2876 if (sv != &sv_undef) {
2877 phs_t *phs_tpl = (phs_t*)(void*)SvPVX(sv);
2878 sv_free(phs_tpl->sv);
2879 }
2880 }
2881 sv_free((SV*)imp_sth->all_params_hv);
2882 }
2883
2884 /* SQLxxx functions dump core when no connection exists. This happens
2885 * when the db was disconnected before perl ending. Hence,
2886 * checking for the dirty flag.
2887 */
2888 if (imp_dbh->hdbc != SQL_NULL_HDBC && !dirty) {
2889
2890 rc = SQLFreeHandle(SQL_HANDLE_STMT,imp_sth->hstmt);
2891 /* rc = SQLFreeStmt(imp_sth->hstmt, SQL_DROP);*/ /* TBD: 3.0 update */
2892
2893 if (DBIc_TRACE(imp_sth, 0, 0, 5))
2894 TRACE1(imp_dbh, " SQLFreeStmt=%d.\n", rc);
2895
2896 if (!SQL_SUCCEEDED(rc)) {
2897 dbd_error(sth, rc, "st_destroy/SQLFreeStmt(SQL_DROP)");
2898 /* return 0; */
2899 }
2900 }
2901
2902 DBIc_IMPSET_off(imp_sth); /* let DBI know we've done it */
2903}
2904
2905
2906/************************************************************************/
2907/* */
2908/* get_param_type */
2909/* ============== */
2910/* */
2911/* Sets the following fields for a parameter in the phs_st: */
2912/* */
2913/* sql_type - the SQL type to use when binding this parameter */
2914/* describe_param_called - set to 1 if we called SQLDescribeParam */
2915/* describe_param_status - set to result of SQLDescribeParam if */
2916/* SQLDescribeParam called */
2917/* described_sql_type - the sql type returned by SQLDescribeParam */
2918/* param_size - the parameter size returned by SQLDescribeParam */
2919/* */
2920/* The sql_type field is set to one of the following: */
2921/* value passed in bind method call if specified */
2922/* if SQLDescribeParam not supported: */
2923/* value of odbc_default_bind_type attribute if set else */
2924/* SQL_VARCHAR */
2925/* if SQLDescribeParam supported: */
2926/* if SQLDescribeParam succeeds: */
2927/* parameter type returned by SQLDescribeParam */
2928/* else if SQLDescribeParam fails: */
2929/* value of odbc_default_bind_type attribute if set else */
2930/* SQL_VARCHAR */
2931/* */
2932/* NOTE: Just because an ODBC driver says it supports SQLDescribeParam */
2933/* does not mean you can call it successfully e.g., MS SQL Server */
2934/* implements SQLDescribeParam by examining your SQL and rewriting it */
2935/* to be a select statement so it can find the column types etc. This */
2936/* fails horribly when the statement does not contain a table */
2937/* e.g., "select ?, LEN(?)" and so do most other SQL Server drivers. */
2938/* */
2939/************************************************************************/
2940static void get_param_type(SV *sth, imp_sth_t *imp_sth, phs_t *phs)
2941{
2942 SWORD fNullable;
2943 SWORD ibScale;
2944 D_imp_dbh_from_sth;
2945 RETCODE rc;
2946
2947 if (DBIc_TRACE(imp_sth, 0, 0, 4))
2948 TRACE2(imp_sth, " +get_param_type(%p,%s)\n", sth, phs->name);
2949
2950 if (imp_dbh->odbc_sqldescribeparam_supported != 1) {
2951 /* As SQLDescribeParam is not supported by the ODBC driver we need to
2952 default a SQL type to bind the parameter as. The default is either
2953 the value set with odbc_default_bind_type or a fallback of
2954 SQL_VARCHAR. */
2955 phs->sql_type = default_parameter_type(imp_sth);
2956 if (DBIc_TRACE(imp_sth, 0, 0, 4))
2957 TRACE1(imp_dbh, " defaulted param type to %d\n", phs->sql_type);
2958 } else if (!phs->describe_param_called) {
2959 /* If we haven't had a go at calling SQLDescribeParam before for this
2960 parameter, have a go now. If it fails we'll default the sql type
2961 as above when driver does not have SQLDescribeParam */
2962
2963 rc = SQLDescribeParam(imp_sth->hstmt,
2964 phs->idx, &phs->described_sql_type,
2965 &phs->param_size, &ibScale,
2966 &fNullable);
2967 phs->describe_param_called = 1;
2968 phs->describe_param_status = rc;
2969 if (!SQL_SUCCEEDED(rc)) {
2970 phs->sql_type = default_parameter_type(imp_sth);
2971 if (DBIc_TRACE(imp_sth, 0, 0, 3))
2972 TRACE1(imp_dbh, " SQLDescribeParam failed reverting to "
2973 "default SQL bind type %d\n", phs->sql_type);
2974 /* show any odbc errors in log */
2975 AllODBCErrors(imp_sth->henv, imp_sth->hdbc, imp_sth->hstmt,
2976 DBIc_TRACE(imp_sth, 0, 0, 3),
2977 DBIc_LOGPIO(imp_sth));
2978 } else {
2979 if (DBIc_TRACE(imp_sth, 0, 0, 5))
2980 PerlIO_printf(DBIc_LOGPIO(imp_dbh),
2981 " SQLDescribeParam %s: SqlType=%s(%d) "
2982 "param_size=%d Scale=%d Nullable=%d\n",
2983 phs->name,
2984 S_SqlTypeToString(phs->described_sql_type),
2985 phs->described_sql_type,
2986 phs->param_size, ibScale, fNullable);
2987
2988 /*
2989 * for non-integral numeric types, let the driver/database handle
2990 * the conversion for us
2991 */
2992 switch(phs->described_sql_type) {
2993 case SQL_NUMERIC:
2994 case SQL_DECIMAL:
2995 case SQL_FLOAT:
2996 case SQL_REAL:
2997 case SQL_DOUBLE:
2998 if (DBIc_TRACE(imp_sth, 0, 0, 5))
2999 TRACE3(imp_dbh,
3000 " Param %s is numeric SQL type %s "
3001 "(param size:%d) changed to SQL_VARCHAR",
3002 phs->name,
3003 S_SqlTypeToString(phs->described_sql_type),
3004 phs->param_size);
3005 phs->sql_type = SQL_VARCHAR;
3006 break;
3007 default:
3008 phs->sql_type = phs->described_sql_type;
3009 }
3010 }
3011 } else if (phs->describe_param_called) {
3012 if (DBIc_TRACE(imp_sth, 0, 0, 5))
3013 TRACE1(imp_dbh,
3014 " SQLDescribeParam already run and returned rc=%d\n",
3015 phs->describe_param_status);
3016 }
3017
3018 if (phs->requested_type != 0) {
3019 phs->sql_type = phs->requested_type;
3020 if (DBIc_TRACE(imp_sth, 0, 0, 5))
3021 TRACE1(imp_dbh, " Overriding sql type with requested type %d\n",
3022 phs->requested_type);
3023 }
3024
3025#if defined(WITH_UNICODE)
3026 /* for Unicode string types, change value_type to SQL_C_WCHAR*/
3027 switch (phs->sql_type) {
3028 case SQL_WCHAR:
3029 case SQL_WVARCHAR:
3030 case SQL_WLONGVARCHAR:
3031 phs->value_type = SQL_C_WCHAR;
3032 if (DBIc_TRACE(imp_sth, 0, 0, 8)) {
3033 TRACE0(imp_dbh,
3034 " get_param_type: modified value type to SQL_C_WCHAR\n");
3035 }
3036 break;
3037 }
3038#endif /* WITH_UNICODE */
3039 if (DBIc_TRACE(imp_sth, 0, 0, 8)) TRACE0(imp_dbh, " -get_param_type\n");
3040}
3041
3042
3043
3044/*======================================================================*/
3045/* */
3046/* rebind_param */
3047/* ============ */
3048/* */
3049/*======================================================================*/
3050static int rebind_param(
3051 SV *sth,
3052 imp_sth_t *imp_sth,
3053 phs_t *phs)
3054{
3055 dTHR;
3056 D_imp_dbh_from_sth;
3057 SQLRETURN rc;
3058 /* args of SQLBindParameter() call */
3059 SQLSMALLINT param_type;
3060 SQLSMALLINT value_type;
3061 UCHAR *value_ptr;
3062 SQLULEN column_size;
3063 SQLSMALLINT d_digits;
3064 SQLLEN buffer_length;
3065 SQLULEN default_column_size;
3066 STRLEN value_len = 0;
3067
3068 if (DBIc_TRACE(imp_sth, 0, 0, 4)) {
3069 char *text = neatsvpv(phs->sv,value_len);
3070 PerlIO_printf(
3071 DBIc_LOGPIO(imp_dbh),
3072 " +rebind_param %s '%.100s' (size svCUR=%d/SvLEN=%d/max=%ld) "
3073 "svtype %ld, value type:%d sql type:%d\n",
3074 phs->name, text, SvOK(phs->sv) ? SvCUR(phs->sv) : -1,
3075 SvOK(phs->sv) ? SvLEN(phs->sv) : -1 ,phs->maxlen,
3076 SvTYPE(phs->sv), phs->value_type, phs->sql_type);
3077 }
3078
3079 if (phs->is_inout) {
3080 /*
3081 * At the moment we always do sv_setsv() and rebind.
3082 * Later we may optimise this so that more often we can
3083 * just copy the value & length over and not rebind.
3084 */
3085 if (SvREADONLY(phs->sv))
3086 croak(no_modify);
3087 /* phs->sv _is_ the real live variable, it may 'mutate' later */
3088 /* pre-upgrade high to reduce risk of SvPVX realloc/move */
3089 (void)SvUPGRADE(phs->sv, SVt_PVNV);
3090 /* ensure room for result, 28 is magic number (see sv_2pv) */
3091#if defined(WITH_UNICODE)
3092 SvGROW(phs->sv,
3093 (phs->maxlen+sizeof(SQLWCHAR) < 28) ?
3094 28 : phs->maxlen+sizeof(SQLWCHAR));
3095#else
3096 SvGROW(phs->sv, (phs->maxlen < 28) ? 28 : phs->maxlen+1);
3097#endif /* WITH_UNICODE */
3098 }
3099 else {
3100 /* phs->sv is copy of real variable, upgrade to at least string */
3101 (void)SvUPGRADE(phs->sv, SVt_PV);
3102 }
3103
3104 /*
3105 * At this point phs->sv must be at least a PV with a valid buffer,
3106 * even if it's undef (null)
3107 * Here we set phs->sv_buf, and value_len.
3108 */
3109 if (SvOK(phs->sv)) {
3110 phs->sv_buf = SvPV(phs->sv, value_len);
3111 } else {
3112 /* it's undef but if it was inout param it would point to a
3113 * valid buffer, at least */
3114 phs->sv_buf = SvPVX(phs->sv);
3115 value_len = 0;
3116 }
3117
3118 get_param_type(sth, imp_sth, phs);
3119
3120#if defined(WITH_UNICODE)
3121 if (phs->value_type == SQL_C_WCHAR) {
3122 if (DBIc_TRACE(imp_sth, 0, 0, 8)) {
3123 TRACE1(imp_dbh,
3124 " Need to modify phs->sv in place: old length = %i\n",
3125 value_len);
3126 }
3127 SV_toWCHAR(phs->sv); /* may modify SvPV(phs->sv), ... */
3128 /* ... so phs->sv_buf must be updated */
3129 phs->sv_buf=SvPV(phs->sv,value_len);
3130 if (DBIc_TRACE(imp_sth, 0, 0, 8)) {
3131 TRACE1(imp_dbh,
3132 " Need to modify phs->sv in place: new length = %i\n",
3133 value_len);
3134 }
3135 }
3136
3137 /* value_len has current value length now */
3138 phs->sv_type = SvTYPE(phs->sv); /* part of mutation check */
3139 phs->maxlen = SvLEN(phs->sv) - sizeof(SQLWCHAR); /* avail buffer space */
3140
3141#else /* !WITH_UNICODE */
3142 /* value_len has current value length now */
3143 phs->sv_type = SvTYPE(phs->sv); /* part of mutation check */
3144 phs->maxlen = SvLEN(phs->sv) - 1; /* avail buffer space */
3145#endif /* WITH_UNICODE */
3146
3147 if (DBIc_TRACE(imp_sth, 0, 0, 4)) {
3148 PerlIO_printf(DBIc_LOGPIO(imp_dbh),
3149 " bind %s '%.100s' value_len=%d maxlen=%ld null=%d)\n",
3150 phs->name, SvOK(phs->sv) ? phs->sv_buf : "(null)",
3151 value_len,(long)phs->maxlen, SvOK(phs->sv) ? 0 : 1);
3152 }
3153
3154 /*
3155 * JLU: was SQL_PARAM_OUTPUT only, but that caused a problem with
3156 * Oracle's drivers and in/out parameters. Can't be output only
3157 * with Oracle. Need to test on other platforms to ensure this
3158 * does not cause a problem.
3159 */
3160 param_type = phs->is_inout ? SQL_PARAM_INPUT_OUTPUT : SQL_PARAM_INPUT;
3161 value_type = phs->value_type;
3162 d_digits = value_len;
3163 column_size = phs->is_inout ? phs->maxlen : value_len;
3164
3165 /* per patch from Paul G. Weiss, who was experiencing re-preparing
3166 * of queries when the size of the bound string's were increasing
3167 * for example select * from tabtest where name = ?
3168 * then executing with 'paul' and then 'thomas' would cause
3169 * SQLServer to prepare the query twice, but if we ran 'thomas'
3170 * then 'paul', it would not re-prepare the query. The key seems
3171 * to be allocating enough space for the largest parameter.
3172 * TBD: the default for this should be a DBD::ODBC specific option
3173 * or attribute.
3174 */
3175 if (phs->sql_type == SQL_VARCHAR && !phs->is_inout) {
3176 d_digits = 0;
3177 /* default to at least 80 if this is the first time through */
3178 if (phs->biggestparam == 0) {
3179 phs->biggestparam = (value_len > 80) ? value_len : 80;
3180 } else {
3181 /* bump up max, if needed */
3182 if (value_len > phs->biggestparam) {
3183 phs->biggestparam = value_len;
3184 }
3185 }
3186 }
3187
3188 if ((phs->describe_param_called == 1) &&
3189 (SQL_SUCCEEDED(phs->describe_param_status))) {
3190 default_column_size = phs->param_size;
3191 } else {
3192 if ((phs->sql_type == SQL_VARCHAR) && !phs->is_inout) {
3193 default_column_size = phs->biggestparam;
3194 } else {
3195 default_column_size = value_len;
3196 }
3197 }
3198
3199 /* JLU
3200 * need to look at this.
3201 * was buffer_length = value_len for some binding purposes
3202 */
3203 buffer_length = phs->is_inout ? phs->maxlen : value_len;
3204
3205 /* When we fill a LONGVARBINARY, the CTYPE must be set to SQL_C_BINARY */
3206 if (value_type == SQL_C_CHAR) { /* could be changed by bind_plh */
3207 switch(phs->sql_type) {
3208 case SQL_LONGVARBINARY:
3209 case SQL_BINARY:
3210 case SQL_VARBINARY:
3211 value_type = SQL_C_BINARY;
3212 d_digits = 0;
3213 column_size = default_column_size;
3214 break;
3215#ifdef SQL_WLONGVARCHAR
3216 case SQL_WLONGVARCHAR: /* added for SQLServer 7 ntext type */
3217#endif
3218 case SQL_CHAR:
3219 case SQL_VARCHAR:
3220 case SQL_LONGVARCHAR:
3221 d_digits = 0;
3222 column_size = default_column_size;
3223 break;
3224 case SQL_DATE:
3225 case SQL_TYPE_DATE:
3226 case SQL_TIME:
3227 case SQL_TYPE_TIME:
3228 break;
3229 case SQL_TIMESTAMP:
3230 case SQL_TYPE_TIMESTAMP:
3231 d_digits = 0; /* tbd: millisecondS?) */
3232 /* bug fix! if phs->sv is not OK, then there's a chance
3233 * we go through garbage data to determine the length */
3234 if (SvOK(phs->sv)) {
3235 char *cp;
3236 if (phs->sv_buf && *phs->sv_buf) {
3237 cp = strchr(phs->sv_buf, '.');
3238 if (cp) {
3239 ++cp;
3240 while (*cp != '\0' && isdigit(*cp)) {
3241 cp++;
3242 d_digits++;
3243 }
3244 }
3245 } else {
3246 /* hard code for SQL Server when passing Undef to
3247 bound parameters */
3248 column_size = 23;
3249 }
3250 }
3251 break;
3252 default:
3253 break;
3254 }
3255 }
3256
3257 if (!SvOK(phs->sv)) {
3258 phs->strlen_or_ind = SQL_NULL_DATA;
3259 /* if is_inout, shouldn't we null terminate the buffer and send
3260 * it, instead?? */
3261 if (!phs->is_inout) {
3262 column_size = 1;
3263 }
3264 if (phs->is_inout) {
3265 if (!phs->sv_buf) {
3266 croak("panic: DBD::ODBC binding undef with bad buffer!!!!");
3267 }
3268 /* just in case, we *know* we called SvGROW above */
3269 phs->sv_buf[0] = '\0';
3270 /* patch for binding undef inout params on sql server */
3271 d_digits = 1;
3272 value_ptr = phs->sv_buf;
3273 } else {
3274 value_ptr = NULL;
3275 }
3276 }
3277 else {
3278 value_ptr = phs->sv_buf;
3279 phs->strlen_or_ind = value_len;
3280 /* not undef, may be a blank string or something */
3281 if (!phs->is_inout && phs->strlen_or_ind == 0) {
3282 column_size = 1;
3283 }
3284 }
3285 if (DBIc_TRACE(imp_sth, 0, 0, 4)) {
3286 PerlIO_printf(DBIc_LOGPIO(imp_dbh),
3287 " bind %s value_type:%d %s cs=%d dd=%d bl=%ld\n",
3288 phs->name, value_type, S_SqlTypeToString(phs->sql_type),
3289 column_size, d_digits, buffer_length);
3290 }
3291
3292 if (value_len < imp_sth->odbc_putdata_start) {
3293 /* already set and should be left alone JLU */
3294 /* d_digits = value_len; */
3295 } else {
3296 SQLLEN vl = value_len;
3297
3298 if (DBIc_TRACE(imp_sth, 0, 0, 4))
3299 TRACE1(imp_dbh, " using data_at_exec for size %ld\n", value_len);
3300
3301 d_digits = 0; /* not relevant to lobs */
3302 phs->strlen_or_ind = SQL_LEN_DATA_AT_EXEC(vl);
3303 value_ptr = (UCHAR*) phs;
3304 }
3305
3306 if (DBIc_TRACE(imp_sth, 0, 0, 5)) {
3307 PerlIO_printf(
3308 DBIc_LOGPIO(imp_dbh),
3309 " SQLBindParameter: idx=%d: param_type=%d, name=%s, "
3310 "value_type=%d, SQL_Type=%d, column_size=%d, d_digits=%d, "
3311 "value_ptr=%p, buffer_length=%d, cbValue=%d, param_size=%d\n",
3312 phs->idx, param_type, phs->name, value_type, phs->sql_type,
3313 column_size, d_digits, value_ptr, buffer_length, phs->strlen_or_ind,
3314 phs->param_size);
3315 /* avoid tracing data_at_exec as value_ptr will point to phs */
3316 if ((value_type == SQL_C_CHAR) && (phs->strlen_or_ind > 0)) {
3317 TRACE1(imp_sth, " Param value = %s\n", value_ptr);
3318 }
3319#if THE_FOLLOWING_CODE_IS_FLAWED_AND_BROKEN
3320 /*
3321 * value_ptr is not null terminated - it is a byte array so PVallocW
3322 * won't work as it works on null terminated strings
3323 */
3324#if defined(WITH_UNICODE)
3325 if (value_type==SQL_C_WCHAR) {
3326 char * c1;
3327 c1 = PVallocW((SQLWCHAR *)value_ptr);
3328 TRACE1(imp_dbh, " Param value = L'%s'\n", c1);
3329 PVfreeW(c1);
3330 }
3331#endif /* WITH_UNICODE */
3332#endif
3333 }
3334
3335 /*
3336 * The following code is a workaround for a problem in SQL Server
3337 * when inserting more than 400K into varbinary(max) or varchar(max)
3338 * columns. The older SQL Server driver (not the native client driver):
3339 *
3340 * o reports the size of xxx(max) columns as 2147483647 bytes in size
3341 * when in reality they can be a lot bigger than that.
3342 * o if you bind more than 400K you get the following errors:
3343 * (HY000, 0, [Microsoft][ODBC SQL Server Driver]
3344 * Warning: Partial insert/update. The insert/update of a text or
3345 * image column(s) did not succeed.)
3346 * (42000, 7125, [Microsoft][ODBC SQL Server Driver][SQL Server]
3347 * The text, ntext, or image pointer value conflicts with the column
3348 * name specified.)
3349 *
3350 * There appear to be 2 workarounds but I was not prepared to do the first.
3351 * The first is simply to set the indicator to SQL_LEN_DATA_AT_EXEC(409600)
3352 * if the parameter was larger than 409600 - miraculously it works but
3353 * shouldn't according to MSDN.
3354 * The second workaround (used here) is to set the indicator to
3355 * SQL_LEN_DATA_AT_EXEC(0) and the buffer_length to 0.
3356 *
3357 */
3358 if ((strcmp(imp_dbh->odbc_driver_name, "SQLSRV32.DLL") == 0) &&
3359 ((phs->sql_type == SQL_LONGVARCHAR) || (phs->sql_type == SQL_LONGVARBINARY)) &&
3360 (column_size == 2147483647) && (phs->strlen_or_ind < 0) &&
3361 ((-phs->strlen_or_ind + SQL_LEN_DATA_AT_EXEC_OFFSET) >= 409600)) {
3362 phs->strlen_or_ind = SQL_LEN_DATA_AT_EXEC(0);
3363 buffer_length = 0;
3364 }
3365 /*
3366 * workaround bug in SQL Server ODBC driver where it can describe some
3367 * parameters (especially in SQL using sub selects) the wrong way.
3368 * If this is a varchar then the column_size must be at least as big
3369 * as the buffer size but if SQL Server associated the wrong column with
3370 * our parameter it could get a totally different size. Without this
3371 * a varchar(10) column can be desribed as a varchar(n) where n is less
3372 * than 10 and this leads to data truncation errors - see rt 39841.
3373 */
3374 if ((phs->sql_type == SQL_VARCHAR) && (column_size < buffer_length)) {
3375 column_size = buffer_length;
3376 }
3377 rc = SQLBindParameter(imp_sth->hstmt,
3378 phs->idx, param_type, value_type, phs->sql_type,
3379 column_size, d_digits,
3380 value_ptr, buffer_length, &phs->strlen_or_ind);
3381
3382 if (!SQL_SUCCEEDED(rc)) {
3383 dbd_error(sth, rc, "rebind_param/SQLBindParameter");
3384 return 0;
3385 }
3386
3387 if (DBIc_TRACE(imp_sth, 0, 0, 4)) TRACE0(imp_dbh, " -rebind_param\n");
3388
3389 return 1;
3390}
3391
3392
3393
3394/*------------------------------------------------------------
3395 * bind placeholder.
3396 * Is called from ODBC.xs execute()
3397 * AND from ODBC.xs bind_param()
3398 */
3399int dbd_bind_ph(
3400 SV *sth,
3401 imp_sth_t *imp_sth,
3402 SV *ph_namesv,
3403 SV *newvalue,
3404 IV sql_type,
3405 SV *attribs,
3406 int is_inout,
3407 IV maxlen)
3408{
3409 dTHR;
3410 SV **phs_svp;
3411 STRLEN name_len;
3412 char *name;
3413 char namebuf[30];
3414 phs_t *phs;
3415 D_imp_dbh_from_sth;
3416
3417 if (SvNIOK(ph_namesv) ) { /* passed as a number */
3418 name = namebuf;
3419 sprintf(name, "%d", (int)SvIV(ph_namesv));
3420 name_len = strlen(name);
3421 }
3422 else {
3423 name = SvPV(ph_namesv, name_len);
3424 }
3425 if (DBIc_TRACE(imp_sth, 0, 0, 4)) {
3426 PerlIO_printf(
3427 DBIc_LOGPIO(imp_dbh),
3428 "+dbd_bind_ph(%p, %s, value='%.200s', attribs=%s, sql_type=%ld, is_inout=%d, maxlen=%ld\n",
3429 sth, name, SvOK(newvalue) ? SvPV_nolen(newvalue) : "undef",
3430 attribs ? SvPV_nolen(attribs) : "", sql_type, is_inout, maxlen);
3431 }
3432
3433 /* the problem with the code below is we are getting SVt_PVLV when
3434 * an "undef" value from a hash lookup that doesn't exist. It's an
3435 * "undef" value, but it doesn't come in as a scalar.
3436 * from a hash is arriving. Let's leave this out until we are
3437 * handling arrays. JLU 7/12/02
3438 */
3439#if 0
3440 if (SvTYPE(newvalue) > SVt_PVMG) { /* hook for later array logic */
3441 if (DBIc_TRACE(imp_sth, 0, 0, 3))
3442 TRACE2(imp_dbh, " !!bind %s perl type = %d -- croaking!\n",
3443 name, SvTYPE(newvalue));
3444 croak("Can't bind non-scalar value (currently)");
3445 }
3446#endif
3447
3448 /*
3449 * all_params_hv created during dbd_preparse.
3450 */
3451 phs_svp = hv_fetch(imp_sth->all_params_hv, name, (I32)name_len, 0);
3452 if (phs_svp == NULL)
3453 croak("Can't bind unknown placeholder '%s'", name);
3454 phs = (phs_t*)SvPVX(*phs_svp); /* placeholder struct */
3455
3456 phs->requested_type = sql_type; /* save type requested */
3457
3458 if (phs->sv == &sv_undef) { /* first bind for this placeholder */
3459 phs->value_type = SQL_C_CHAR; /* default */
3460
3461 phs->maxlen = maxlen; /* 0 if not inout */
3462 phs->is_inout = is_inout;
3463 if (is_inout) {
3464 phs->sv = SvREFCNT_inc(newvalue); /* point to live var */
3465 ++imp_sth->has_inout_params;
3466 /* build array of phs's so we can deal with out vars fast */
3467 if (!imp_sth->out_params_av)
3468 imp_sth->out_params_av = newAV();
3469 av_push(imp_sth->out_params_av, SvREFCNT_inc(*phs_svp));
3470 }
3471 }
3472 /* check later rebinds for any changes */
3473 /*
3474 * else if (is_inout || phs->is_inout) {
3475 * croak("Can't rebind or change param %s in/out mode after first bind", phs->name);
3476 * }
3477 * */
3478 else if (is_inout != phs->is_inout) {
3479 croak("Can't rebind or change param %s in/out mode after first bind "
3480 "(%d => %d)", phs->name, phs->is_inout, is_inout);
3481 }
3482 else if (maxlen && maxlen > phs->maxlen) {
3483 if (DBIc_TRACE(imp_sth, 0, 0, 4))
3484 PerlIO_printf(DBIc_LOGPIO(imp_dbh),
3485 "!attempt to change param %s maxlen (%ld->$ld)\n",
3486 phs->name, phs->maxlen, maxlen);
3487 croak("Can't change param %s maxlen (%ld->%ld) after first bind",
3488 phs->name, phs->maxlen, maxlen);
3489 }
3490
3491 if (!is_inout) { /* normal bind to take a (new) copy of current value */
3492 if (phs->sv == &sv_undef) /* (first time bind) */
3493 phs->sv = newSV(0);
3494 sv_setsv(phs->sv, newvalue);
3495 } else if (newvalue != phs->sv) {
3496 if (phs->sv)
3497 SvREFCNT_dec(phs->sv);
3498 phs->sv = SvREFCNT_inc(newvalue); /* point to live var */
3499 }
3500
3501 if (imp_dbh->odbc_defer_binding) {
3502 get_param_type(sth, imp_sth, phs);
3503
3504 if (DBIc_TRACE(imp_sth, 0, 0, 4)) TRACE0(imp_dbh, "-dbd_bind_ph=1\n");
3505 return 1;
3506 }
3507 /* fall through for "immediate" binding */
3508
3509 if (DBIc_TRACE(imp_sth, 0, 0, 4))
3510 TRACE0(imp_dbh, "-dbd_bind_ph=rebind_param\n");
3511 return rebind_param(sth, imp_sth, phs);
3512}
3513
3514
3515/*------------------------------------------------------------
3516 * blob_read:
3517 * read part of a BLOB from a table.
3518 * XXX needs more thought
3519 */
3520int dbd_st_blob_read(sth, imp_sth, field, offset, len, destrv, destoffset)
3521SV *sth;
3522imp_sth_t *imp_sth;
3523int field;
3524long offset;
3525long len;
3526SV *destrv;
3527long destoffset;
3528{
3529 dTHR;
3530 SQLLEN retl;
3531 SV *bufsv;
3532 RETCODE rc;
3533
3534 bufsv = SvRV(destrv);
3535 sv_setpvn(bufsv,"",0); /* ensure it's writable string */
3536 SvGROW(bufsv, len+destoffset+1); /* SvGROW doesn't do +1 */
3537
3538 /* XXX for this to work be probably need to avoid calling SQLGetData in
3539 * fetch. The definition of SQLGetData doesn't work well with the DBI's
3540 * notion of how LongReadLen would work. Needs more thought. */
3541
3542 rc = SQLGetData(imp_sth->hstmt, (SQLSMALLINT)(field+1),
3543 SQL_C_BINARY,
3544 ((UCHAR *)SvPVX(bufsv)) + destoffset, len, &retl
3545 );
3546 if (DBIc_TRACE(imp_sth, 0, 0, 4))
3547 PerlIO_printf(DBIc_LOGPIO(imp_sth),
3548 "SQLGetData(...,off=%d, len=%d)->rc=%d,len=%d SvCUR=%d\n",
3549 destoffset, len, rc, retl, SvCUR(bufsv));
3550
3551 if (!SQL_SUCCEEDED(rc)) {
3552 dbd_error(sth, rc, "dbd_st_blob_read/SQLGetData");
3553 return 0;
3554 }
3555 if (rc == SQL_SUCCESS_WITH_INFO) { /* XXX should check for 01004 */
3556 retl = len;
3557 }
3558
3559 if (retl == SQL_NULL_DATA) { /* field is null */
3560 (void)SvOK_off(bufsv);
3561 return 1;
3562 }
3563#ifdef SQL_NO_TOTAL
3564 if (retl == SQL_NO_TOTAL) { /* unknown length! */
3565 (void)SvOK_off(bufsv);
3566 return 0;
3567 }
3568#endif
3569
3570 SvCUR_set(bufsv, destoffset+retl);
3571 *SvEND(bufsv) = '\0'; /* consistent with perl sv_setpvn etc */
3572
3573 if (DBIc_TRACE(imp_sth, 0, 0, 4))
3574 TRACE1(imp_sth, " blob_read: SvCUR=%d\n", SvCUR(bufsv));
3575
3576 return 1;
3577}
3578
3579
3580
3581/*======================================================================*/
3582/* */
3583/* S_db_storeOptions */
3584/* ================= */
3585/* S_db_fetchOptions */
3586/* ================= */
3587/* */
3588/* An array of options/attributes we support on database handles for */
3589/* storing and fetching. */
3590/* */
3591/*======================================================================*/
3592typedef struct {
3593 const char *str;
3594 UWORD fOption;
3595 UDWORD atrue;
3596 UDWORD afalse;
3597} db_params;
3598
3599static db_params S_db_storeOptions[] = {
3600 { "AutoCommit", SQL_AUTOCOMMIT, SQL_AUTOCOMMIT_ON, SQL_AUTOCOMMIT_OFF },
3601 { "ReadOnly", SQL_ATTR_ACCESS_MODE, SQL_MODE_READ_ONLY, SQL_MODE_READ_WRITE},
3602#if 0 /* not defined by DBI/DBD specification */
3603 { "TRANSACTION",
3604 SQL_ACCESS_MODE, SQL_MODE_READ_ONLY, SQL_MODE_READ_WRITE },
3605 { "solid_trace", SQL_OPT_TRACE, SQL_OPT_TRACE_ON, SQL_OPT_TRACE_OFF },
3606 { "solid_timeout", SQL_LOGIN_TIMEOUT },
3607 { "ISOLATION", SQL_TXN_ISOLATION },
3608 { "solid_tracefile", SQL_OPT_TRACEFILE },
3609#endif
3610 { "odbc_SQL_ROWSET_SIZE", SQL_ROWSET_SIZE },
3611 { "odbc_ignore_named_placeholders", ODBC_IGNORE_NAMED_PLACEHOLDERS },
3612 { "odbc_default_bind_type", ODBC_DEFAULT_BIND_TYPE },
3613 { "odbc_force_rebind", ODBC_FORCE_REBIND },
3614 { "odbc_async_exec", ODBC_ASYNC_EXEC },
3615 { "odbc_err_handler", ODBC_ERR_HANDLER },
3616 { "odbc_exec_direct", ODBC_EXEC_DIRECT },
3617 { "odbc_version", ODBC_VERSION },
3618 { "odbc_cursortype", ODBC_CURSORTYPE },
3619 { "odbc_query_timeout", ODBC_QUERY_TIMEOUT },
3620 { "odbc_putdata_start", ODBC_PUTDATA_START },
3621 { "odbc_column_display_size", ODBC_COLUMN_DISPLAY_SIZE },
3622 { NULL },
3623};
3624
3625static db_params S_db_fetchOptions[] = {
3626 { "AutoCommit", SQL_AUTOCOMMIT, SQL_AUTOCOMMIT_ON, SQL_AUTOCOMMIT_OFF },
3627 { "ReadOnly", SQL_ATTR_ACCESS_MODE, SQL_MODE_READ_ONLY, SQL_MODE_READ_WRITE}, { "RowCacheSize", ODBC_ROWCACHESIZE },
3628 { "odbc_SQL_ROWSET_SIZE", SQL_ROWSET_SIZE },
3629 { "odbc_SQL_DRIVER_ODBC_VER", SQL_DRIVER_ODBC_VER },
3630 { "odbc_ignore_named_placeholders", ODBC_IGNORE_NAMED_PLACEHOLDERS },
3631 { "odbc_default_bind_type", ODBC_DEFAULT_BIND_TYPE },
3632 { "odbc_force_rebind", ODBC_FORCE_REBIND },
3633 { "odbc_async_exec", ODBC_ASYNC_EXEC },
3634 { "odbc_err_handler", ODBC_ERR_HANDLER },
3635 { "odbc_SQL_DBMS_NAME", SQL_DBMS_NAME },
3636 { "odbc_exec_direct", ODBC_EXEC_DIRECT },
3637 { "odbc_query_timeout", ODBC_QUERY_TIMEOUT},
3638 { "odbc_putdata_start", ODBC_PUTDATA_START},
3639 { "odbc_column_display_size", ODBC_COLUMN_DISPLAY_SIZE},
3640 { "odbc_has_unicode", ODBC_HAS_UNICODE},
3641 { "odbc_out_connect_string", ODBC_OUTCON_STR},
3642 { NULL }
3643};
3644
3645/*======================================================================*/
3646/* */
3647/* S_dbOption */
3648/* ========== */
3649/* */
3650/* Given a string and a length, locate this option in the specified */
3651/* array of valid options. Typically used by STORE and FETCH methods */
3652/* to decide if this option/attribute is supported by us. */
3653/* */
3654/*======================================================================*/
3655static const db_params *
3656 S_dbOption(const db_params *pars, char *key, STRLEN len)
3657{
3658 /* search option to set */
3659 while (pars->str != NULL) {
3660 if (strncmp(pars->str, key, len) == 0
3661 && len == strlen(pars->str))
3662 break;
3663 pars++;
3664 }
3665 if (pars->str == NULL) {
3666 return NULL;
3667 }
3668 return pars;
3669}
3670
3671
3672
3673/*======================================================================*/
3674/* */
3675/* dbd_db_STORE_attrib */
3676/* =================== */
3677/* */
3678/* This function handles: */
3679/* */
3680/* $dbh->{$key} = $value */
3681/* */
3682/* Method to handle the setting of driver specific attributes and DBI */
3683/* attributes AutoCommit and ChopBlanks (no other DBI attributes). */
3684/* */
3685/* Return TRUE if the attribute was handled, else FALSE. */
3686/* */
3687/*======================================================================*/
3688int dbd_db_STORE_attrib(SV *dbh, imp_dbh_t *imp_dbh, SV *keysv, SV *valuesv)
3689{
3690 dTHR;
3691 D_imp_drh_from_dbh;
3692 RETCODE rc;
3693 STRLEN kl;
3694 STRLEN plen;
3695 char *key = SvPV(keysv,kl);
3696 int on;
3697 UDWORD vParam;
3698 const db_params *pars;
3699 int bSetSQLConnectionOption;
3700
3701 if ((pars = S_dbOption(S_db_storeOptions, key, kl)) == NULL) {
3702 if (DBIc_TRACE(imp_dbh, 0, 0, 3))
3703 TRACE1(imp_dbh,
3704 " !!DBD::ODBC unsupported attribute passed (%s)\n", key);
3705
3706 return FALSE;
3707 }
3708
3709 bSetSQLConnectionOption = TRUE;
3710 switch(pars->fOption)
3711 {
3712 case SQL_LOGIN_TIMEOUT:
3713 case SQL_TXN_ISOLATION:
3714 case SQL_ROWSET_SIZE:
3715 vParam = SvIV(valuesv);
3716 break;
3717 case SQL_OPT_TRACEFILE:
3718 vParam = (UDWORD) SvPV(valuesv, plen);
3719 break;
3720
3721 case ODBC_IGNORE_NAMED_PLACEHOLDERS:
3722 bSetSQLConnectionOption = FALSE;
3723 /*
3724 * set value to ignore placeholders. Will affect all
3725 * statements from here on.
3726 */
3727 imp_dbh->odbc_ignore_named_placeholders = SvTRUE(valuesv);
3728 break;
3729
3730 case ODBC_DEFAULT_BIND_TYPE:
3731 bSetSQLConnectionOption = FALSE;
3732 /*
3733 * set value of default bind type. Default is SQL_VARCHAR,
3734 * but setting to 0 will cause SQLDescribeParam to be used.
3735 */
3736 imp_dbh->odbc_default_bind_type = (SQLSMALLINT)SvIV(valuesv);
3737
3738 break;
3739
3740 case ODBC_FORCE_REBIND:
3741 bSetSQLConnectionOption = FALSE;
3742 /*
3743 * set value to force rebind
3744 */
3745 imp_dbh->odbc_force_rebind = SvTRUE(valuesv);
3746 break;
3747
3748 case ODBC_QUERY_TIMEOUT:
3749 bSetSQLConnectionOption = FALSE;
3750 imp_dbh->odbc_query_timeout = (SQLINTEGER)SvIV(valuesv);
3751 break;
3752
3753 case ODBC_PUTDATA_START:
3754 bSetSQLConnectionOption = FALSE;
3755 imp_dbh->odbc_putdata_start = SvIV(valuesv);
3756 break;
3757
3758 case ODBC_COLUMN_DISPLAY_SIZE:
3759 bSetSQLConnectionOption = FALSE;
3760 imp_dbh->odbc_column_display_size = SvIV(valuesv);
3761 break;
3762
3763 case ODBC_EXEC_DIRECT:
3764 bSetSQLConnectionOption = FALSE;
3765 /*
3766 * set value of odbc_exec_direct. Non-zero will
3767 * make prepare, essentially a noop and make execute
3768 * use SQLExecDirect. This is to support drivers that
3769 * _only_ support SQLExecDirect.
3770 */
3771 imp_dbh->odbc_exec_direct = SvTRUE(valuesv);
3772 break;
3773
3774 case ODBC_ASYNC_EXEC:
3775 bSetSQLConnectionOption = FALSE;
3776 /*
3777 * set asynchronous execution. It can only be turned on if
3778 * the driver supports it, but will fail silently.
3779 */
3780 if (SvTRUE(valuesv)) {
3781 /* Only bother setting the attribute if it's not already set! */
3782 if (imp_dbh->odbc_async_exec)
3783 break;
3784
3785 /*
3786 * Determine which method of async execution this
3787 * driver allows -- per-connection or per-statement
3788 */
3789 rc = SQLGetInfo(imp_dbh->hdbc,
3790 SQL_ASYNC_MODE,
3791 &imp_dbh->odbc_async_type,
3792 sizeof(imp_dbh->odbc_async_type),
3793 NULL
3794 );
3795 /*
3796 * Normally, we'd do a if (!SQL_ok(rc)) ... here.
3797 * Unfortunately, if the driver doesn't support async
3798 * mode, it may return an error here. There doesn't
3799 * seem to be any other way to check (other than doing
3800 * a special check for the SQLSTATE). We'll just default
3801 * to doing nothing and not bother checking errors.
3802 */
3803
3804 if (imp_dbh->odbc_async_type == SQL_AM_CONNECTION){
3805 /*
3806 * Driver has per-connection async option. Set it
3807 * now in the dbh.
3808 */
3809 if (DBIc_TRACE(imp_dbh, 0, 0, 4))
3810 TRACE0(imp_dbh,
3811 " Supported AsyncType is SQL_AM_CONNECTION\n");
3812 rc = SQLSetConnectOption(imp_dbh->hdbc,
3813 SQL_ATTR_ASYNC_ENABLE,
3814 SQL_ASYNC_ENABLE_ON
3815 );
3816 if (!SQL_SUCCEEDED(rc)) {
3817 dbd_error(dbh, rc, "db_STORE/SQLSetConnectOption");
3818 return FALSE;
3819 }
3820 imp_dbh->odbc_async_exec = 1;
3821 }
3822 else if (imp_dbh->odbc_async_type == SQL_AM_STATEMENT){
3823 /*
3824 * Driver has per-statement async option. Just set
3825 * odbc_async_exec and the rest will be handled by
3826 * dbd_st_prepare.
3827 */
3828 if (DBIc_TRACE(imp_dbh, 0, 0, 4))
3829 TRACE0(imp_dbh,
3830 " Supported AsyncType is SQL_AM_STATEMENT\n");
3831 imp_dbh->odbc_async_exec = 1;
3832 }
3833 else { /* (imp_dbh->odbc_async_type == SQL_AM_NONE) */
3834 /*
3835 * We're out of luck.
3836 */
3837 if (DBIc_TRACE(imp_dbh, 0, 0, 4))
3838 TRACE0(imp_dbh, " Supported AsyncType is SQL_AM_NONE\n");
3839 imp_dbh->odbc_async_exec = 0;
3840 return FALSE;
3841 }
3842 } else {
3843 /* Only bother turning it off if it was previously set... */
3844 if (imp_dbh->odbc_async_exec == 1) {
3845
3846 /* We only need to do anything here if odbc_async_type is
3847 * SQL_AM_CONNECTION since the per-statement async type
3848 * is turned on only when the statement handle is created.
3849 */
3850 if (imp_dbh->odbc_async_type == SQL_AM_CONNECTION){
3851 rc = SQLSetConnectOption(imp_dbh->hdbc,
3852 SQL_ATTR_ASYNC_ENABLE,
3853 SQL_ASYNC_ENABLE_OFF
3854 );
3855 if (!SQL_SUCCEEDED(rc)) {
3856 dbd_error(dbh, rc, "db_STORE/SQLSetConnectOption");
3857 return FALSE;
3858 }
3859 }
3860 }
3861 imp_dbh->odbc_async_exec = 0;
3862 }
3863 break;
3864
3865 case ODBC_ERR_HANDLER:
3866 bSetSQLConnectionOption = FALSE;
3867
3868 /* This was taken from DBD::Sybase 0.21 */
3869 /* I believe the following if test which has been in DBD::ODBC
3870 * for ages is wrong and should (at least now) use SvOK or
3871 * it is impossible to reset the error handler
3872 *
3873 * if(valuesv == &PL_sv_undef) {
3874 * imp_dbh->odbc_err_handler = NULL;
3875 */
3876 if (!SvOK(valuesv)) {
3877 imp_dbh->odbc_err_handler = NULL;
3878 } else if(imp_dbh->odbc_err_handler == (SV*)NULL) {
3879 imp_dbh->odbc_err_handler = newSVsv(valuesv);
3880 } else {
3881 sv_setsv(imp_dbh->odbc_err_handler, valuesv);
3882 }
3883 break;
3884 case ODBC_VERSION:
3885 /* set only in connect, nothing to store */
3886 bSetSQLConnectionOption = FALSE;
3887 break;
3888
3889 case ODBC_CURSORTYPE:
3890 /* set only in connect, nothing to store */
3891 bSetSQLConnectionOption = FALSE;
3892 break;
3893
3894 case SQL_ATTR_ACCESS_MODE:
3895 on = SvTRUE(valuesv);
3896 vParam = on ? pars->atrue : pars->afalse;
3897 break;
3898
3899 default:
3900 on = SvTRUE(valuesv);
3901 vParam = on ? pars->atrue : pars->afalse;
3902 break;
3903 }
3904
3905 if (bSetSQLConnectionOption) {
3906 /* TBD: 3.0 update */
3907
3908 rc = SQLSetConnectOption(imp_dbh->hdbc, pars->fOption, vParam);
3909
3910 if (!SQL_SUCCEEDED(rc)) {
3911 dbd_error(dbh, rc, "db_STORE/SQLSetConnectOption");
3912 return FALSE;
3913 }
3914 /* keep our flags in sync */
3915 if (kl == 10 && strEQ(key, "AutoCommit"))
3916 DBIc_set(imp_dbh, DBIcf_AutoCommit, SvTRUE(valuesv));
3917 }
3918 return TRUE;
3919}
3920
3921
3922
3923/*======================================================================*/
3924/* */
3925/* dbd_db_FETCH_attrib */
3926/* =================== */
3927/* */
3928/* Counterpart of dbd_db_STORE_attrib handing: */
3929/* */
3930/* $value = $dbh->{$key}; */
3931/* */
3932/* returns an "SV" with the value */
3933/* */
3934/*======================================================================*/
3935SV *dbd_db_FETCH_attrib(SV *dbh, imp_dbh_t *imp_dbh, SV *keysv)
3936{
3937 dTHR;
3938 D_imp_drh_from_dbh;
3939 RETCODE rc;
3940 STRLEN kl;
3941 char *key = SvPV(keysv,kl);
3942 UDWORD vParam = 0;
3943 const db_params *pars;
3944 SV *retsv = Nullsv;
3945
3946 /* checking pars we need FAST */
3947
3948 if (DBIc_TRACE(imp_dbh, 0, 0, 8))
3949 TRACE1(imp_dbh, " FETCH %s\n", key);
3950
3951
3952 if ((pars = S_dbOption(S_db_fetchOptions, key, kl)) == NULL)
3953 return Nullsv;
3954
3955 switch (pars->fOption) {
3956 case ODBC_OUTCON_STR:
3957 if (!imp_dbh->out_connect_string) {
3958 retsv = &PL_sv_undef;
3959 } else {
3960 retsv = newSVsv(imp_dbh->out_connect_string);
3961 }
3962 break;
3963
3964 case SQL_DRIVER_ODBC_VER:
3965 retsv = newSVpv(imp_dbh->odbc_ver, 0);
3966 break;
3967
3968 case SQL_DBMS_NAME:
3969 retsv = newSVpv(imp_dbh->odbc_dbname, 0);
3970 break;
3971
3972 case ODBC_IGNORE_NAMED_PLACEHOLDERS:
3973 retsv = newSViv(imp_dbh->odbc_ignore_named_placeholders);
3974 break;
3975
3976 case ODBC_QUERY_TIMEOUT:
3977 /*
3978 * fetch current value of query timeout
3979 *
3980 * -1 is our internal flag saying odbc_query_timeout has never been
3981 * set so we map it back to the default for ODBC which is 0
3982 */
3983 if (imp_dbh->odbc_query_timeout == -1) {
3984 retsv = newSViv(0);
3985 } else {
3986 retsv = newSViv(imp_dbh->odbc_query_timeout);
3987 }
3988 break;
3989
3990 case ODBC_PUTDATA_START:
3991 retsv = newSViv(imp_dbh->odbc_putdata_start);
3992 break;
3993
3994 case ODBC_COLUMN_DISPLAY_SIZE:
3995 retsv = newSViv(imp_dbh->odbc_column_display_size);
3996 break;
3997
3998 case ODBC_HAS_UNICODE:
3999 retsv = newSViv(imp_dbh->odbc_has_unicode);
4000 break;
4001
4002 case ODBC_DEFAULT_BIND_TYPE:
4003 retsv = newSViv(imp_dbh->odbc_default_bind_type);
4004 break;
4005
4006 case ODBC_FORCE_REBIND:
4007 retsv = newSViv(imp_dbh->odbc_force_rebind);
4008 break;
4009
4010 case ODBC_EXEC_DIRECT:
4011 retsv = newSViv(imp_dbh->odbc_exec_direct);
4012 break;
4013
4014 case ODBC_ASYNC_EXEC:
4015 /*
4016 * fetch current value of asynchronous execution (should be
4017 * either 0 or 1).
4018 */
4019 retsv = newSViv(imp_dbh->odbc_async_exec);
4020 break;
4021
4022 case ODBC_ERR_HANDLER:
4023 /* fetch current value of the error handler (a coderef). */
4024 if(imp_dbh->odbc_err_handler) {
4025 retsv = newSVsv(imp_dbh->odbc_err_handler);
4026 } else {
4027 retsv = &sv_undef;
4028 }
4029 break;
4030
4031 case ODBC_ROWCACHESIZE:
4032 retsv = newSViv(imp_dbh->RowCacheSize);
4033 break;
4034 default:
4035 /*
4036 * The remainders we support are ODBC attributes like
4037 * AutoCommit (SQL_AUTOCOMMIT)
4038 * odbc_SQL_ROWSET_SIZE (SQL_ROWSET_SIZE)
4039 *
4040 * Nothing else should get here for now unless any item is added
4041 * to S_db_fetchOptions.
4042 */
4043
4044 rc = SQLGetConnectOption(imp_dbh->hdbc, pars->fOption, &vParam);/* TBD: 3.0 update */
4045 dbd_error(dbh, rc, "db_FETCH/SQLGetConnectOption");
4046 if (!SQL_SUCCEEDED(rc)) {
4047 if (DBIc_TRACE(imp_dbh, 0, 0, 3))
4048 TRACE1(imp_dbh,
4049 " !!SQLGetConnectOption=%d in dbd_db_FETCH\n", rc);
4050 return Nullsv;
4051 }
4052
4053 switch(pars->fOption) {
4054 case SQL_ROWSET_SIZE:
4055 retsv = newSViv(vParam);
4056 break;
4057 default:
4058 if (vParam == pars->atrue)
4059 retsv = newSViv(1);
4060 else
4061 retsv = newSViv(0);
4062 break;
4063 } /* inner switch */
4064 } /* outer switch */
4065
4066 return sv_2mortal(retsv);
4067}
4068
4069
4070
4071/*======================================================================*/
4072/* */
4073/* S_st_fetch_params */
4074/* ================= */
4075/* S_st_store_params */
4076/* ================= */
4077/* */
4078/* An array of options/attributes we support on statement handles for */
4079/* storing and fetching. */
4080/* */
4081/*======================================================================*/
4082
4083/*
4084 * added "need_describe" flag to handle the situation where you don't
4085 * have a result set yet to describe. Certain attributes don't need
4086 * the result set to operate, hence don't do a describe unless you need
4087 * to do one.
4088 * DBD::ODBC 0.45_15
4089 * */
4090typedef struct {
4091 const char *str;
4092 unsigned len:8;
4093 unsigned array:1;
4094 unsigned need_describe:1;
4095 unsigned filler:22;
4096} T_st_params;
4097
4098#define s_A(str,need_describe) { str, sizeof(str)-1,0,need_describe }
4099static T_st_params S_st_fetch_params[] =
4100{
4101 s_A("NUM_OF_PARAMS",1), /* 0 */
4102 s_A("NUM_OF_FIELDS",1), /* 1 */
4103 s_A("NAME",1), /* 2 */
4104 s_A("NULLABLE",1), /* 3 */
4105 s_A("TYPE",1), /* 4 */
4106 s_A("PRECISION",1), /* 5 */
4107 s_A("SCALE",1), /* 6 */
4108 s_A("sol_type",1), /* 7 */
4109 s_A("sol_length",1), /* 8 */
4110 s_A("CursorName",1), /* 9 */
4111 s_A("odbc_more_results",1), /* 10 */
4112 s_A("ParamValues",0), /* 11 */
4113
4114 s_A("LongReadLen",0), /* 12 */
4115 s_A("odbc_ignore_named_placeholders",0), /* 13 */
4116 s_A("odbc_default_bind_type",0), /* 14 */
4117 s_A("odbc_force_rebind",0), /* 15 */
4118 s_A("odbc_query_timeout",0), /* 16 */
4119 s_A("odbc_putdata_start",0), /* 17 */
4120 s_A("ParamTypes",0), /* 18 */
4121 s_A("odbc_column_display_size",0), /* 19 */
4122 s_A("",0), /* END */
4123};
4124
4125static T_st_params S_st_store_params[] =
4126{
4127 s_A("odbc_ignore_named_placeholders",0), /* 0 */
4128 s_A("odbc_default_bind_type",0), /* 1 */
4129 s_A("odbc_force_rebind",0), /* 2 */
4130 s_A("odbc_query_timeout",0), /* 3 */
4131 s_A("odbc_putdata_start",0), /* 4 */
4132 s_A("odbc_column_display_size",0), /* 5 */
4133 s_A("",0), /* END */
4134};
4135#undef s_A
4136
4137
4138
4139/*======================================================================*/
4140/* */
4141/* dbd_st_FETCH_attrib */
4142/* =================== */
4143/* */
4144/*======================================================================*/
4145SV *dbd_st_FETCH_attrib(SV *sth, imp_sth_t *imp_sth, SV *keysv)
4146{
4147 dTHR;
4148 STRLEN kl;
4149 char *key = SvPV(keysv,kl);
4150 int i;
4151 SV *retsv = NULL;
4152 T_st_params *par;
4153 char cursor_name[256];
4154 SWORD cursor_name_len;
4155 RETCODE rc;
4156
4157 for (par = S_st_fetch_params; par->len > 0; par++)
4158 if (par->len == kl && strEQ(key, par->str))
4159 break;
4160
4161
4162 if (par->len <= 0)
4163 return Nullsv;
4164
4165 if (par->need_describe && !imp_sth->done_desc && !dbd_describe(sth, imp_sth,0))
4166 {
4167 /* dbd_describe has already called dbd_error() */
4168 /* we can't return Nullsv here because the xs code will */
4169 /* then just pass the attribute name to DBI for FETCH. */
4170 if (DBIc_TRACE(imp_sth, 0, 0, 4)) {
4171 TRACE1(imp_sth,
4172 " !!!dbd_st_FETCH_attrib (%s) needed query description, "
4173 "but failed\n", par->str);
4174 }
4175 if (DBIc_WARN(imp_sth)) {
4176 warn("Describe failed during %s->FETCH(%s,%d)",
4177 SvPV(sth,na), key,imp_sth->done_desc);
4178 }
4179 return &sv_undef;
4180 }
4181
4182 i = DBIc_NUM_FIELDS(imp_sth);
4183
4184
4185 switch(par - S_st_fetch_params)
4186 {
4187 AV *av;
4188
4189 case 0: /* NUM_OF_PARAMS */
4190 return Nullsv; /* handled by DBI */
4191 case 1: /* NUM_OF_FIELDS */
4192 if (DBIc_TRACE(imp_sth, 0, 0, 9)) {
4193 TRACE1(imp_sth, " dbd_st_FETCH_attrib NUM_OF_FIELDS %d\n", i);
4194 }
4195 retsv = newSViv(i);
4196 break;
4197 case 2: /* NAME */
4198 av = newAV();
4199 retsv = newRV(sv_2mortal((SV*)av));
4200 if (DBIc_TRACE(imp_sth, 0, 0, 9)) {
4201 int j;
4202 TRACE1(imp_sth, " dbd_st_FETCH_attrib NAMES %d\n", i);
4203
4204 for (j = 0; j < i; j++)
4205 TRACE1(imp_sth, "\t%s\n", imp_sth->fbh[j].ColName);
4206 }
4207 while(--i >= 0) {
4208 if (DBIc_TRACE(imp_sth, 0, 0, 9)) {
4209 TRACE2(imp_sth, " Colname %d => %s\n",
4210 i, imp_sth->fbh[i].ColName);
4211 }
4212#ifdef WITH_UNICODE
4213 av_store(av, i,
4214 sv_newwvn((SQLWCHAR *)imp_sth->fbh[i].ColName,
4215 imp_sth->fbh[i].ColNameLen));
4216#else
4217 av_store(av, i, newSVpv(imp_sth->fbh[i].ColName, 0));
4218#endif
4219 }
4220 break;
4221 case 3: /* NULLABLE */
4222 av = newAV();
4223 retsv = newRV(sv_2mortal((SV*)av));
4224 while(--i >= 0)
4225 av_store(av, i,
4226 (imp_sth->fbh[i].ColNullable == SQL_NO_NULLS)
4227 ? &sv_no : &sv_yes);
4228 break;
4229 case 4: /* TYPE */
4230 av = newAV();
4231 retsv = newRV(sv_2mortal((SV*)av));
4232 while(--i >= 0)
4233 av_store(av, i, newSViv(imp_sth->fbh[i].ColSqlType));
4234 break;
4235 case 5: /* PRECISION */
4236 av = newAV();
4237 retsv = newRV(sv_2mortal((SV*)av));
4238 while(--i >= 0)
4239 av_store(av, i, newSViv(imp_sth->fbh[i].ColDef));
4240 break;
4241 case 6: /* SCALE */
4242 av = newAV();
4243 retsv = newRV(sv_2mortal((SV*)av));
4244 while(--i >= 0)
4245 av_store(av, i, newSViv(imp_sth->fbh[i].ColScale));
4246 break;
4247 case 7: /* sol_type */
4248 av = newAV();
4249 retsv = newRV(sv_2mortal((SV*)av));
4250 while(--i >= 0)
4251 av_store(av, i, newSViv(imp_sth->fbh[i].ColSqlType));
4252 break;
4253 case 8: /* sol_length */
4254 av = newAV();
4255 retsv = newRV(sv_2mortal((SV*)av));
4256 while(--i >= 0)
4257 av_store(av, i, newSViv(imp_sth->fbh[i].ColLength));
4258 break;
4259 case 9: /* CursorName */
4260 rc = SQLGetCursorName(imp_sth->hstmt, cursor_name,
4261 sizeof(cursor_name), &cursor_name_len);
4262 if (!SQL_SUCCEEDED(rc)) {
4263 dbd_error(sth, rc, "st_FETCH/SQLGetCursorName");
4264 return Nullsv;
4265 }
4266 retsv = newSVpv(cursor_name, cursor_name_len);
4267 break;
4268 case 10: /* odbc_more_results */
4269 retsv = newSViv(imp_sth->moreResults);
4270 if (i == 0 && imp_sth->moreResults == 0) {
4271 int outparams = (imp_sth->out_params_av) ?
4272 AvFILL(imp_sth->out_params_av)+1 : 0;
4273 if (DBIc_TRACE(imp_sth, 0, 0, 4)) {
4274 TRACE0(imp_sth,
4275 " numfields == 0 && moreResults = 0 finish\n");
4276 }
4277 if (outparams) {
4278 odbc_handle_outparams(imp_sth, DBIc_TRACE_LEVEL(imp_sth));
4279 }
4280 /* XXX need to 'finish' here */
4281 dbd_st_finish(sth, imp_sth);
4282 }
4283 break;
4284 case 11: /* ParamValues */
4285 {
4286 /* not sure if there's a memory leak here. */
4287 HV *paramvalues = newHV();
4288 if (imp_sth->all_params_hv) {
4289 HV *hv = imp_sth->all_params_hv;
4290 SV *sv;
4291 char *key;
4292 I32 retlen;
4293 hv_iterinit(hv);
4294 while( (sv = hv_iternextsv(hv, &key, &retlen)) != NULL ) {
4295 if (sv != &sv_undef) {
4296 phs_t *phs = (phs_t*)(void*)SvPVX(sv);
4297 hv_store(paramvalues, phs->name, (I32)strlen(phs->name),
4298 newSVsv(phs->sv), 0);
4299 }
4300 }
4301 }
4302 /* ensure HV is freed when the ref is freed */
4303 retsv = newRV_noinc((SV *)paramvalues);
4304 break;
4305 }
4306 case 12: /* LongReadLen */
4307 retsv = newSViv(DBIc_LongReadLen(imp_sth));
4308 break;
4309 case 13: /* odbc_ignore_named_placeholders */
4310 retsv = newSViv(imp_sth->odbc_ignore_named_placeholders);
4311 break;
4312 case 14: /* odbc_default_bind_type */
4313 retsv = newSViv(imp_sth->odbc_default_bind_type);
4314 break;
4315 case 15: /* odbc_force_rebind */
4316 retsv = newSViv(imp_sth->odbc_force_rebind);
4317 break;
4318 case 16: /* odbc_query_timeout */
4319 /*
4320 * -1 is our internal flag saying odbc_query_timeout has never been
4321 * set so we map it back to the default for ODBC which is 0
4322 */
4323 if (imp_sth->odbc_query_timeout == -1) {
4324 retsv = newSViv(0);
4325 } else {
4326 retsv = newSViv(imp_sth->odbc_query_timeout);
4327 }
4328 break;
4329 case 17: /* odbc_putdata_start */
4330 retsv = newSViv(imp_sth->odbc_putdata_start);
4331 break;
4332 case 18: /* ParamTypes */
4333 {
4334 /* not sure if there's a memory leak here. */
4335 HV *paramtypes = newHV();
4336 if (imp_sth->all_params_hv) {
4337 HV *hv = imp_sth->all_params_hv;
4338 SV *sv;
4339 char *key;
4340 I32 retlen;
4341 hv_iterinit(hv);
4342 while( (sv = hv_iternextsv(hv, &key, &retlen)) != NULL ) {
4343 if (sv != &sv_undef) {
4344 HV *subh = newHV();
4345
4346 phs_t *phs = (phs_t*)(void*)SvPVX(sv);
4347 hv_store(subh, "TYPE", 4, newSViv(phs->sql_type), 0);
4348 hv_store(paramtypes, phs->name, (I32)strlen(phs->name),
4349 newRV_noinc((SV *)subh), 0);
4350 }
4351 }
4352 }
4353 /* ensure HV is freed when the ref is freed */
4354 retsv = newRV_noinc((SV *)paramtypes);
4355 break;
4356 }
4357 case 19: /* odbc_column_display_size */
4358 retsv = newSViv(imp_sth->odbc_column_display_size);
4359 break;
4360 default:
4361 return Nullsv;
4362 }
4363 return sv_2mortal(retsv);
4364}
4365
4366
4367
4368/*======================================================================*/
4369/* */
4370/* dbd_st_STORE_attrib */
4371/* =================== */
4372/* */
4373/*======================================================================*/
4374int dbd_st_STORE_attrib(SV *sth, imp_sth_t *imp_sth, SV *keysv, SV *valuesv)
4375{
4376 dTHR;
4377 D_imp_dbh_from_sth;
4378 STRLEN kl;
4379 STRLEN vl;
4380 char *key = SvPV(keysv,kl);
4381 char *value = SvPV(valuesv, vl);
4382 T_st_params *par;
4383
4384 for (par = S_st_store_params; par->len > 0; par++)
4385 if (par->len == kl && strEQ(key, par->str))
4386 break;
4387
4388 if (par->len <= 0)
4389 return FALSE;
4390
4391 switch(par - S_st_store_params)
4392 {
4393 case 0:
4394 imp_sth->odbc_ignore_named_placeholders = SvTRUE(valuesv);
4395 return TRUE;
4396
4397 case 1:
4398 imp_sth->odbc_default_bind_type = SvIV(valuesv);
4399 return TRUE;
4400 break;
4401
4402 case 2:
4403 imp_sth->odbc_force_rebind = (int)SvIV(valuesv);
4404 return TRUE;
4405 break;
4406
4407 case 3:
4408 imp_sth->odbc_query_timeout = SvIV(valuesv);
4409 return TRUE;
4410 break;
4411
4412 case 4:
4413 imp_sth->odbc_putdata_start = SvIV(valuesv);
4414 return TRUE;
4415 break;
4416
4417 case 5:
4418 imp_sth->odbc_column_display_size = SvIV(valuesv);
4419 return TRUE;
4420 break;
4421 }
4422 return FALSE;
4423}
4424
4425
4426
4427SV *
4428 odbc_get_info(dbh, ftype)
4429 SV *dbh;
4430int ftype;
4431{
4432 dTHR;
4433 D_imp_dbh(dbh);
4434 RETCODE rc;
4435 SV *retsv = NULL;
4436 int i;
4437 int size = 256;
4438 char *rgbInfoValue;
4439 SWORD cbInfoValue = -2;
4440
4441 New(0, rgbInfoValue, size, char);
4442
4443 /* See fancy logic below */
4444 for (i = 0; i < 6; i++)
4445 rgbInfoValue[i] = (char)0xFF;
4446
4447 rc = SQLGetInfo(imp_dbh->hdbc, (SQLUSMALLINT)ftype,
4448 rgbInfoValue, (SQLSMALLINT)(size-1), &cbInfoValue);
4449 if (cbInfoValue > size-1) {
4450 Renew(rgbInfoValue, cbInfoValue+1, char);
4451 rc = SQLGetInfo(imp_dbh->hdbc, (SQLUSMALLINT)ftype,
4452 rgbInfoValue, cbInfoValue, &cbInfoValue);
4453 }
4454 if (!SQL_SUCCEEDED(rc)) {
4455 dbd_error(dbh, rc, "odbc_get_info/SQLGetInfo");
4456 Safefree(rgbInfoValue);
4457 /* patched 2/12/02, thanks to Steffen Goldner */
4458 return &sv_undef;
4459 /* return Nullsv; */
4460 }
4461
4462 /* Fancy logic here to determine if result is a string or int */
4463 if (cbInfoValue == -2) /* is int */
4464 retsv = newSViv(*(int *)rgbInfoValue); /* XXX cast */
4465 else if (cbInfoValue != 2 && cbInfoValue != 4) /* must be string */
4466 retsv = newSVpv(rgbInfoValue, 0);
4467 else if (rgbInfoValue[cbInfoValue] == '\0') /* must be string */ /* patch from Steffen Goldner 0.37 2/12/02 */
4468 retsv = newSVpv(rgbInfoValue, 0);
4469 else if (cbInfoValue == 2) /* short */
4470 retsv = newSViv(*(short *)rgbInfoValue); /* XXX cast */
4471 else if (cbInfoValue == 4) /* int */
4472 retsv = newSViv(*(int *)rgbInfoValue); /* XXX cast */
4473 else
4474 croak("panic: SQLGetInfo cbInfoValue == %d", cbInfoValue);
4475
4476 if (DBIc_TRACE(imp_dbh, 0, 0, 4))
4477 PerlIO_printf(
4478 DBIc_LOGPIO(imp_dbh),
4479 " SQLGetInfo: ftype %d, cbInfoValue %d: %s\n",
4480 ftype, cbInfoValue, neatsvpv(retsv,0));
4481
4482 Safefree(rgbInfoValue);
4483 return sv_2mortal(retsv);
4484}
4485
4486#ifdef THE_FOLLOWING_NO_LONGER_USED_REPLACE_BY_dbd_st_primary_keys
4487int
4488 odbc_get_statistics(dbh, sth, CatalogName, SchemaName, TableName, Unique)
4489 SV * dbh;
4490SV * sth;
4491char * CatalogName;
4492char * SchemaName;
4493char * TableName;
4494int Unique;
4495{
4496 dTHR;
4497 D_imp_dbh(dbh);
4498 D_imp_sth(sth);
4499 RETCODE rc;
4500 int dbh_active;
4501
4502 imp_sth->henv = imp_dbh->henv; /* needed for dbd_error */
4503 imp_sth->hdbc = imp_dbh->hdbc;
4504
4505 imp_sth->done_desc = 0;
4506
4507 if ((dbh_active = check_connection_active(dbh)) == 0) return 0;
4508
4509 rc = SQLAllocHandle(SQL_HANDLE_STMT, imp_dbh->hdbc, &imp_sth->hstmt);
4510 if (rc != SQL_SUCCESS) {
4511 dbd_error(sth, rc, "odbc_get_statistics/SQLAllocHandle(stmt)");
4512 return 0;
4513 }
4514
4515 rc = SQLStatistics(imp_sth->hstmt,
4516 CatalogName, (SQLSMALLINT)strlen(CatalogName),
4517 SchemaName, (SQLSMALLINT)strlen(SchemaName),
4518 TableName, (SQLSMALLINT)strlen(TableName),
4519 (SQLUSMALLINT)Unique, (SQLUSMALLINT)0);
4520 if (!SQL_SUCCEEDED(rc)) {
4521 dbd_error(sth, rc, "odbc_get_statistics/SQLGetStatistics");
4522 return 0;
4523 }
4524 return build_results(sth, dbh, rc);
4525}
4526#endif /* THE_FOLLOWING_NO_LONGER_USED_REPLACE_BY_dbd_st_primary_keys */
4527
4528#ifdef THE_FOLLOWING_NO_LONGER_USED_REPLACE_BY_dbd_st_primary_keys
4529int
4530 odbc_get_primary_keys(dbh, sth, CatalogName, SchemaName, TableName)
4531 SV * dbh;
4532SV * sth;
4533char * CatalogName;
4534char * SchemaName;
4535char * TableName;
4536{
4537 dTHR;
4538 D_imp_dbh(dbh);
4539 D_imp_sth(sth);
4540 RETCODE rc;
4541 int dbh_active;
4542
4543 imp_sth->henv = imp_dbh->henv; /* needed for dbd_error */
4544 imp_sth->hdbc = imp_dbh->hdbc;
4545
4546 imp_sth->done_desc = 0;
4547
4548 if ((dbh_active = check_connection_active(dbh)) == 0) return 0;
4549
4550 rc = SQLAllocHandle(SQL_HANDLE_STMT, imp_dbh->hdbc, &imp_sth->hstmt);
4551 if (rc != SQL_SUCCESS) {
4552 dbd_error(sth, rc, "odbc_get_primary_keys/SQLAllocHandle(stmt)");
4553 return 0;
4554 }
4555
4556 rc = SQLPrimaryKeys(imp_sth->hstmt,
4557 CatalogName, (SQLSMALLINT)strlen(CatalogName),
4558 SchemaName, (SQLSMALLINT)strlen(SchemaName),
4559 TableName, (SQLSMALLINT)strlen(TableName));
4560 if (DBIc_TRACE(imp_sth, 0, 0, 3))
4561 TRACE1(imp_dbh, " SQLPrimaryKeys rc = %d\n", rc);
4562 if (!SQL_SUCCEEDED(rc)) {
4563 dbd_error(sth, rc, "odbc_get_primary_keys/SQLPrimaryKeys");
4564 return 0;
4565 }
4566 return build_results(sth, dbh, rc);
4567}
4568#endif /* THE_FOLLOWING_NO_LONGER_USED_REPLACE_BY_dbd_st_primary_keys */
4569
4570
4571
4572int
4573 odbc_get_special_columns(dbh, sth, Identifier, CatalogName, SchemaName, TableName, Scope, Nullable)
4574 SV * dbh;
4575SV * sth;
4576int Identifier;
4577char * CatalogName;
4578char * SchemaName;
4579char * TableName;
4580int Scope;
4581int Nullable;
4582{
4583 dTHR;
4584 D_imp_dbh(dbh);
4585 D_imp_sth(sth);
4586 RETCODE rc;
4587 int dbh_active;
4588
4589 imp_sth->henv = imp_dbh->henv; /* needed for dbd_error */
4590 imp_sth->hdbc = imp_dbh->hdbc;
4591
4592 imp_sth->done_desc = 0;
4593
4594 if ((dbh_active = check_connection_active(dbh)) == 0) return 0;
4595
4596 rc = SQLAllocHandle(SQL_HANDLE_STMT, imp_dbh->hdbc, &imp_sth->hstmt);
4597 if (rc != SQL_SUCCESS) {
4598 dbd_error(sth, rc, "odbc_get_special_columns/SQLAllocHandle(stmt)");
4599 return 0;
4600 }
4601
4602 rc = SQLSpecialColumns(imp_sth->hstmt,
4603 (SQLSMALLINT)Identifier,
4604 CatalogName, (SQLSMALLINT)strlen(CatalogName),
4605 SchemaName, (SQLSMALLINT)strlen(SchemaName),
4606 TableName, (SQLSMALLINT)strlen(TableName),
4607 (SQLSMALLINT)Scope, (SQLSMALLINT)Nullable);
4608 if (!SQL_SUCCEEDED(rc)) {
4609 dbd_error(sth, rc, "odbc_get_special_columns/SQLSpecialClumns");
4610 return 0;
4611 }
4612 return build_results(sth, dbh, rc);
4613}
4614
4615
4616
4617int
4618 odbc_get_foreign_keys(dbh, sth, PK_CatalogName, PK_SchemaName, PK_TableName, FK_CatalogName, FK_SchemaName, FK_TableName)
4619 SV * dbh;
4620SV * sth;
4621char * PK_CatalogName;
4622char * PK_SchemaName;
4623char * PK_TableName;
4624char * FK_CatalogName;
4625char * FK_SchemaName;
4626char * FK_TableName;
4627{
4628 dTHR;
4629 D_imp_dbh(dbh);
4630 D_imp_sth(sth);
4631 RETCODE rc;
4632 int dbh_active;
4633
4634 imp_sth->henv = imp_dbh->henv; /* needed for dbd_error */
4635 imp_sth->hdbc = imp_dbh->hdbc;
4636
4637 imp_sth->done_desc = 0;
4638
4639 if ((dbh_active = check_connection_active(dbh)) == 0) return 0;
4640
4641 rc = SQLAllocHandle(SQL_HANDLE_STMT, imp_dbh->hdbc, &imp_sth->hstmt);
4642 if (rc != SQL_SUCCESS) {
4643 dbd_error(sth, rc, "odbc_get_foreign_keys/SQLAllocHandle(stmt)");
4644 return 0;
4645 }
4646
4647
4648 /* just for sanity, later. Any internals that may rely on this (including */
4649 /* debugging) will have valid data */
4650 imp_sth->statement = (char *)safemalloc(strlen(cSqlForeignKeys)+
4651 strlen(XXSAFECHAR(PK_CatalogName))+
4652 strlen(XXSAFECHAR(PK_SchemaName))+
4653 strlen(XXSAFECHAR(PK_TableName))+
4654 strlen(XXSAFECHAR(FK_CatalogName))+
4655 strlen(XXSAFECHAR(FK_SchemaName))+
4656 strlen(XXSAFECHAR(FK_TableName))+
4657 1);
4658
4659 sprintf(imp_sth->statement,
4660 cSqlForeignKeys,
4661 XXSAFECHAR(PK_CatalogName), XXSAFECHAR(PK_SchemaName),XXSAFECHAR(PK_TableName),
4662 XXSAFECHAR(FK_CatalogName), XXSAFECHAR(FK_SchemaName),XXSAFECHAR(FK_TableName)
4663 );
4664 /* fix to handle "" (undef) calls -- thanks to Kevin Shepherd */
4665 rc = SQLForeignKeys(
4666 imp_sth->hstmt,
4667 (PK_CatalogName && *PK_CatalogName) ? PK_CatalogName : 0, SQL_NTS,
4668 (PK_SchemaName && *PK_SchemaName) ? PK_SchemaName : 0, SQL_NTS,
4669 (PK_TableName && *PK_TableName) ? PK_TableName : 0, SQL_NTS,
4670 (FK_CatalogName && *FK_CatalogName) ? FK_CatalogName : 0, SQL_NTS,
4671 (FK_SchemaName && *FK_SchemaName) ? FK_SchemaName : 0, SQL_NTS,
4672 (FK_TableName && *FK_TableName) ? FK_TableName : 0, SQL_NTS);
4673 if (!SQL_SUCCEEDED(rc)) {
4674 dbd_error(sth, rc, "odbc_get_foreign_keys/SQLForeignKeys");
4675 return 0;
4676 }
4677 return build_results(sth, dbh, rc);
4678}
4679
4680
4681
4682int
4683 odbc_describe_col(sth, colno, ColumnName, BufferLength, NameLength, DataType, ColumnSize, DecimalDigits, Nullable)
4684 SV *sth;
4685int colno;
4686char *ColumnName;
4687I16 BufferLength;
4688I16 *NameLength;
4689I16 *DataType;
4690U32 *ColumnSize;
4691I16 *DecimalDigits;
4692I16 *Nullable;
4693{
4694 D_imp_sth(sth);
4695 SQLULEN ColSize;
4696 RETCODE rc;
4697 rc = SQLDescribeCol(imp_sth->hstmt, (SQLSMALLINT)colno,
4698 ColumnName, BufferLength, NameLength,
4699 DataType, &ColSize, DecimalDigits, Nullable);
4700 if (!SQL_SUCCEEDED(rc)) {
4701 dbd_error(sth, rc, "DescribeCol/SQLDescribeCol");
4702 return 0;
4703 }
4704 *ColumnSize = (U32)ColSize;
4705 return 1;
4706}
4707
4708
4709
4710
4711int
4712 odbc_get_type_info(dbh, sth, ftype)
4713 SV *dbh;
4714SV *sth;
4715int ftype;
4716{
4717 dTHR;
4718 D_imp_dbh(dbh);
4719 D_imp_sth(sth);
4720 RETCODE rc;
4721 int dbh_active;
4722
4723#if 0
4724 /* TBD: cursorname? */
4725 char cname[128]; /* cursorname */
4726#endif
4727
4728 imp_sth->henv = imp_dbh->henv; /* needed for dbd_error */
4729 imp_sth->hdbc = imp_dbh->hdbc;
4730
4731 imp_sth->done_desc = 0;
4732
4733 if ((dbh_active = check_connection_active(dbh)) == 0) return 0;
4734
4735 rc = SQLAllocHandle(SQL_HANDLE_STMT, imp_dbh->hdbc, &imp_sth->hstmt);
4736 if (rc != SQL_SUCCESS) {
4737 dbd_error(sth, rc, "odbc_get_type_info/SQLAllocHandle(stmt)");
4738 return 0;
4739 }
4740
4741 /* just for sanity, later. Any internals that may rely on this (including */
4742 /* debugging) will have valid data */
4743 imp_sth->statement = (char *)safemalloc(strlen(cSqlGetTypeInfo)+ftype/10+1);
4744 sprintf(imp_sth->statement, cSqlGetTypeInfo, ftype);
4745
4746 rc = SQLGetTypeInfo(imp_sth->hstmt, (SQLSMALLINT)ftype);
4747
4748 dbd_error(sth, rc, "odbc_get_type_info/SQLGetTypeInfo");
4749 if (!SQL_SUCCEEDED(rc)) {
4750 SQLFreeHandle(SQL_HANDLE_STMT,imp_sth->hstmt);
4751 /* SQLFreeStmt(imp_sth->hstmt, SQL_DROP);*/ /* TBD: 3.0 update */
4752 imp_sth->hstmt = SQL_NULL_HSTMT;
4753 return 0;
4754 }
4755
4756 return build_results(sth, dbh, rc);
4757}
4758
4759
4760
4761SV *
4762 odbc_cancel(sth)
4763 SV *sth;
4764{
4765 dTHR;
4766 D_imp_sth(sth);
4767 RETCODE rc;
4768
4769 rc = SQLCancel(imp_sth->hstmt);
4770 if (!SQL_SUCCEEDED(rc)) {
4771 dbd_error(sth, rc, "odbc_cancel/SQLCancel");
4772 return Nullsv;
4773 }
4774 return newSViv(1);
4775}
4776
4777
4778
4779/************************************************************************/
4780/* */
4781/* odbc_col_attributes */
4782/* =================== */
4783/* */
4784/************************************************************************/
4785SV *odbc_col_attributes(SV *sth, int colno, int desctype)
4786{
4787 dTHR;
4788 D_imp_sth(sth);
4789 RETCODE rc;
4790 SV *retsv = NULL;
4791 char str_attr[256];
4792 SWORD str_attr_len = 0;
4793 SQLLEN num_attr = 0;
4794
4795 memset(str_attr, '\0', sizeof(str_attr));
4796
4797 if ( !DBIc_ACTIVE(imp_sth) ) {
4798 dbd_error(sth, SQL_ERROR, "no statement executing");
4799 return Nullsv;
4800 }
4801
4802 /*
4803 * At least on Win95, calling this with colno==0 would "core" dump/GPF.
4804 * protect, even though it's valid for some values of desctype
4805 * (e.g. SQL_COLUMN_COUNT, since it doesn't depend on the colcount)
4806 */
4807 if (colno == 0) {
4808 dbd_error(sth, SQL_ERROR,
4809 "cannot obtain SQLColAttributes for column 0");
4810 return Nullsv;
4811 }
4812
4813 rc = SQLColAttributes(imp_sth->hstmt, (SQLUSMALLINT)colno,
4814 (SQLUSMALLINT)desctype,
4815 str_attr, sizeof(str_attr),
4816 &str_attr_len, &num_attr);
4817
4818 if (!SQL_SUCCEEDED(rc)) {
4819 dbd_error(sth, rc, "odbc_col_attributes/SQLColAttributes");
4820 return Nullsv;
4821 } else if (SQL_SUCCESS_WITH_INFO == rc) {
4822 warn("SQLColAttributes has truncated returned data");
4823 }
4824
4825
4826 if (DBIc_TRACE(imp_sth, 0, 0, 3)) {
4827 PerlIO_printf(
4828 DBIc_LOGPIO(imp_sth),
4829 " SQLColAttributes: colno=%d, desctype=%d, str_attr=%s, "
4830 "str_attr_len=%d, num_attr=%ld",
4831 colno, desctype, str_attr, str_attr_len, (long)num_attr);
4832 }
4833
4834 switch (desctype) {
4835 case SQL_COLUMN_AUTO_INCREMENT:
4836 case SQL_COLUMN_CASE_SENSITIVE:
4837 case SQL_COLUMN_COUNT:
4838 case SQL_COLUMN_DISPLAY_SIZE:
4839 case SQL_COLUMN_LENGTH:
4840 case SQL_COLUMN_MONEY:
4841 case SQL_COLUMN_NULLABLE:
4842 case SQL_COLUMN_PRECISION:
4843 case SQL_COLUMN_SCALE:
4844 case SQL_COLUMN_SEARCHABLE:
4845 case SQL_COLUMN_TYPE:
4846 case SQL_COLUMN_UNSIGNED:
4847 case SQL_COLUMN_UPDATABLE:
4848 {
4849 retsv = newSViv(num_attr);
4850 break;
4851 }
4852 case SQL_COLUMN_LABEL:
4853 case SQL_COLUMN_NAME:
4854 case SQL_COLUMN_OWNER_NAME:
4855 case SQL_COLUMN_QUALIFIER_NAME:
4856 case SQL_COLUMN_TABLE_NAME:
4857 case SQL_COLUMN_TYPE_NAME:
4858 {
4859 /*
4860 * NOTE: in unixODBC 2.2.11, if you called SQLDriverConnectW and
4861 * then called SQLColAttributes for a string type it would often
4862 * return half the number of characters it had written to
4863 * str_attr in str_attr_len.
4864 */
4865 retsv = newSVpv(str_attr, strlen(str_attr));
4866 break;
4867 }
4868 default:
4869 {
4870 dbd_error(sth, SQL_ERROR,
4871 "driver-specific column attributes not supported");
4872 return Nullsv;
4873 break;
4874 }
4875 }
4876
4877
4878#ifdef OLD_STUFF_THAT_SEEMS_FLAWED
4879 /*
4880 * sigh...Oracle's ODBC driver version 8.0.4 resets str_attr_len to 0, when
4881 * putting a value in num_attr. This is a change!
4882 *
4883 * double sigh. SQL Server (and MySql under Unix) set str_attr_len
4884 * but use num_attr, not str_attr. This change may be problematic
4885 * for other drivers. (the additional || num_attr != -2...)
4886 */
4887 if (str_attr_len == -2 || str_attr_len == 0 || num_attr != -2)
4888 retsv = newSViv(num_attr);
4889 else if (str_attr_len != 2 && str_attr_len != 4)
4890 retsv = newSVpv(str_attr, 0);
4891 else if (str_attr[str_attr_len] == '\0') /* fix for DBD::ODBC 0.39 thanks to Nicolas DeRico */
4892 retsv = newSVpv(str_attr, 0);
4893 else {
4894 if (str_attr_len == 2)
4895 retsv = newSViv(*(short *)str_attr);
4896 else
4897 retsv = newSViv(*(int *)str_attr);
4898 }
4899#endif
4900
4901 return sv_2mortal(retsv);
4902}
4903
4904
4905
4906int
4907 odbc_db_columns(dbh, sth, catalog, schema, table, column)
4908 SV *dbh;
4909SV *sth;
4910char *catalog;
4911char *schema;
4912char *table;
4913char *column;
4914{
4915 dTHR;
4916 D_imp_dbh(dbh);
4917 D_imp_sth(sth);
4918 RETCODE rc;
4919 int dbh_active;
4920 imp_sth->henv = imp_dbh->henv; /* needed for dbd_error */
4921 imp_sth->hdbc = imp_dbh->hdbc;
4922
4923 imp_sth->done_desc = 0;
4924
4925 if ((dbh_active = check_connection_active(dbh)) == 0) return 0;
4926
4927 rc = SQLAllocHandle(SQL_HANDLE_STMT, imp_dbh->hdbc, &imp_sth->hstmt);
4928 if (rc != SQL_SUCCESS) {
4929 dbd_error(sth, rc, "odbc_db_columns/SQLAllocHandle(stmt)");
4930 return 0;
4931 }
4932
4933 /* just for sanity, later. Any internals that may rely on this (including */
4934 /* debugging) will have valid data */
4935 imp_sth->statement = (char *)safemalloc(strlen(cSqlColumns)+
4936 strlen(XXSAFECHAR(catalog))+
4937 strlen(XXSAFECHAR(schema))+
4938 strlen(XXSAFECHAR(table))+
4939 strlen(XXSAFECHAR(column))+1);
4940
4941 sprintf(imp_sth->statement,
4942 cSqlColumns, XXSAFECHAR(catalog), XXSAFECHAR(schema),
4943 XXSAFECHAR(table), XXSAFECHAR(column));
4944
4945 rc = SQLColumns(imp_sth->hstmt,
4946 (catalog && *catalog) ? catalog : 0, SQL_NTS,
4947 (schema && *schema) ? schema : 0, SQL_NTS,
4948 (table && *table) ? table : 0, SQL_NTS,
4949 (column && *column) ? column : 0, SQL_NTS);
4950
4951 if (DBIc_TRACE(imp_sth, 0, 0, 3))
4952 PerlIO_printf(
4953 DBIc_LOGPIO(imp_dbh),
4954 " SQLColumns call: cat = %s, schema = %s, table = %s, "
4955 "column = %s\n",
4956 XXSAFECHAR(catalog), XXSAFECHAR(schema), XXSAFECHAR(table),
4957 XXSAFECHAR(column));
4958 dbd_error(sth, rc, "odbc_columns/SQLColumns");
4959
4960 if (!SQL_SUCCEEDED(rc)) {
4961 SQLFreeHandle(SQL_HANDLE_STMT,imp_sth->hstmt);
4962 /* SQLFreeStmt(imp_sth->hstmt, SQL_DROP);*/ /* TBD: 3.0 update */
4963 imp_sth->hstmt = SQL_NULL_HSTMT;
4964 return 0;
4965 }
4966 return build_results(sth, dbh, rc);
4967}
4968
4969
4970
4971/*
4972 * AllODBCErrors
4973 * =============
4974 *
4975 * Given ODBC environment, connection and statement handles (any of which may
4976 * be null) this function will retrieve all ODBC errors recorded and
4977 * optionally (if output is not 0) output then to the specified log handle.
4978 *
4979 */
4980static void AllODBCErrors(
4981 HENV henv, HDBC hdbc, HSTMT hstmt, int output, PerlIO *logfp)
4982{
4983 SQLRETURN rc;
4984
4985 do {
4986 UCHAR sqlstate[SQL_SQLSTATE_SIZE+1];
4987 /* ErrorMsg must not be greater than SQL_MAX_MESSAGE_LENGTH */
4988 UCHAR ErrorMsg[SQL_MAX_MESSAGE_LENGTH];
4989 SWORD ErrorMsgLen;
4990 SDWORD NativeError;
4991
4992 /* TBD: 3.0 update */
4993 rc=SQLError(henv, hdbc, hstmt,
4994 sqlstate, &NativeError,
4995 ErrorMsg, sizeof(ErrorMsg)-1, &ErrorMsgLen);
4996
4997 if (output && SQL_SUCCEEDED(rc))
4998 PerlIO_printf(logfp, "%s %s\n", sqlstate, ErrorMsg);
4999
5000 } while(SQL_SUCCEEDED(rc));
5001 return;
5002}
5003
5004
5005
5006/************************************************************************/
5007/* */
5008/* check_connection_active */
5009/* ======================= */
5010/* */
5011/************************************************************************/
5012static int check_connection_active(SV *h)
5013{
5014 D_imp_xxh(h);
5015 struct imp_dbh_st *imp_dbh = NULL;
5016 struct imp_sth_st *imp_sth = NULL;
5017
5018 switch(DBIc_TYPE(imp_xxh)) {
5019 case DBIt_ST:
5020 imp_sth = (struct imp_sth_st *)imp_xxh;
5021 imp_dbh = (struct imp_dbh_st *)(DBIc_PARENT_COM(imp_sth));
5022 break;
5023 case DBIt_DB:
5024 imp_dbh = (struct imp_dbh_st *)imp_xxh;
5025 break;
5026 default:
5027 croak("panic: check_connection_active bad handle type");
5028 }
5029
5030 if (!DBIc_ACTIVE(imp_dbh)) {
5031 DBIh_SET_ERR_CHAR(
5032 h, imp_xxh, Nullch, 1,
5033 "Cannot allocate statement when disconnected from the database",
5034 "08003", Nullch);
5035 return 0;
5036 }
5037 return 1;
5038
5039}
5040
5041
5042
5043/************************************************************************/
5044/* */
5045/* set_odbc_version */
5046/* ================ */
5047/* */
5048/* Set the ODBC version we require. This defaults to ODBC 3 but if */
5049/* attr contains the odbc_version atttribute this overrides it. If we */
5050/* fail for any reason the env handle is freed, the error reported and */
5051/* 0 is returned. If all ok, 1 is returned. */
5052/* */
5053/************************************************************************/
5054static int set_odbc_version(
5055 SV *dbh,
5056 imp_dbh_t *imp_dbh,
5057 SV* attr)
5058{
5059 D_imp_drh_from_dbh;
5060 SV **svp;
5061 UV odbc_version = 0;
5062 SQLRETURN rc;
5063
5064
5065 DBD_ATTRIB_GET_IV(
5066 attr, "odbc_version", 12, svp, odbc_version);
5067 if (svp && odbc_version) {
5068 rc = SQLSetEnvAttr(imp_drh->henv, SQL_ATTR_ODBC_VERSION,
5069 (SQLPOINTER)odbc_version, SQL_IS_INTEGER);
5070 } else {
5071 /* make sure we request a 3.0 version */
5072 rc = SQLSetEnvAttr(imp_drh->henv, SQL_ATTR_ODBC_VERSION,
5073 (SQLPOINTER)SQL_OV_ODBC3, SQL_IS_INTEGER);
5074 }
5075 if (!SQL_SUCCEEDED(rc)) {
5076 dbd_error2(
5077 dbh, rc, "db_login/SQLSetEnvAttr", imp_drh->henv, 0, 0);
5078 if (imp_drh->connects == 0) {
5079 SQLFreeHandle(SQL_HANDLE_ENV, imp_drh->henv);
5080 imp_drh->henv = SQL_NULL_HENV;
5081 }
5082 return 0;
5083 }
5084 return 1;
5085}
5086
5087
5088
5089/************************************************************************/
5090/* */
5091/* post_connect */
5092/* ============ */
5093/* */
5094/* Operations to perform immediately after we have connected. */
5095/* */
5096/* NOTE: prior to DBI subversion version 11605 (fixed post 1.607) */
5097/* DBD_ATTRIB_DELETE segfaulted so instead of calling: */
5098/* DBD_ATTRIB_DELETE(attr, "odbc_cursortype", */
5099/* strlen("odbc_cursortype")); */
5100/* we do the following: */
5101/* hv_delete((HV*)SvRV(attr), "odbc_cursortype", */
5102/* strlen("odbc_cursortype"), G_DISCARD); */
5103/* */
5104/************************************************************************/
5105static int post_connect(
5106 SV *dbh,
5107 imp_dbh_t *imp_dbh,
5108 SV *attr)
5109{
5110 D_imp_drh_from_dbh;
5111 SQLRETURN rc;
5112 SWORD dbvlen;
5113 UWORD supported;
5114
5115 if (DBIc_TRACE(imp_dbh, 0x04000000, 0, 0))
5116 TRACE0(imp_dbh, "Turning autocommit on\n");
5117
5118 /* DBI spec requires AutoCommit on */
5119 rc = SQLSetConnectAttr(imp_dbh->hdbc, SQL_AUTOCOMMIT,
5120 (SQLPOINTER)SQL_AUTOCOMMIT_ON, 0);
5121 if (!SQL_SUCCEEDED(rc)) {
5122 dbd_error(dbh, rc, "post_connect/SQLSetConnectAttr(SQL_AUTOCOMMIT)");
5123 SQLFreeHandle(SQL_HANDLE_DBC, imp_dbh->hdbc);
5124 if (imp_drh->connects == 0) {
5125 SQLFreeHandle(SQL_HANDLE_ENV, imp_drh->henv);
5126 imp_drh->henv = SQL_NULL_HENV;
5127 imp_dbh->henv = SQL_NULL_HENV; /* needed for dbd_error */
5128 }
5129 return 0;
5130 }
5131 DBIc_set(imp_dbh,DBIcf_AutoCommit, 1);
5132
5133 /* get the ODBC compatibility level for this driver */
5134 rc = SQLGetInfo(imp_dbh->hdbc, SQL_DRIVER_ODBC_VER, &imp_dbh->odbc_ver,
5135 (SWORD)sizeof(imp_dbh->odbc_ver), &dbvlen);
5136 if (!SQL_SUCCEEDED(rc)) {
5137 dbd_error(dbh, rc, "post_connect/SQLGetInfo(DRIVER_ODBC_VER)");
5138 strcpy(imp_dbh->odbc_ver, "01.00");
5139 }
5140 if (DBIc_TRACE(imp_dbh, 0x04000000, 0, 0))
5141 TRACE1(imp_dbh, "DRIVER_ODBC_VER = %s\n", imp_dbh->odbc_ver);
5142
5143 /* get ODBC driver name and version */
5144 rc = SQLGetInfo(imp_dbh->hdbc, SQL_DRIVER_NAME, &imp_dbh->odbc_driver_name,
5145 (SQLSMALLINT)sizeof(imp_dbh->odbc_driver_name), &dbvlen);
5146 if (!SQL_SUCCEEDED(rc)) {
5147 dbd_error(dbh, rc, "post_connect/SQLGetInfo(DRIVER_NAME)");
5148 strcpy(imp_dbh->odbc_driver_name, "unknown");
5149 }
5150 if (DBIc_TRACE(imp_dbh, 0x04000000, 0, 0))
5151 TRACE1(imp_dbh, "DRIVER_NAME = %s\n", imp_dbh->odbc_driver_name);
5152
5153 rc = SQLGetInfo(imp_dbh->hdbc, SQL_DRIVER_VER,
5154 &imp_dbh->odbc_driver_version,
5155 (SQLSMALLINT)sizeof(imp_dbh->odbc_driver_version), &dbvlen);
5156 if (!SQL_SUCCEEDED(rc)) {
5157 dbd_error(dbh, rc, "post_connect/SQLGetInfo(DRIVER_VERSION)");
5158 strcpy(imp_dbh->odbc_driver_name, "unknown");
5159 }
5160 if (DBIc_TRACE(imp_dbh, 0x04000000, 0, 0))
5161 TRACE1(imp_dbh, "DRIVER_VERSION = %s\n", imp_dbh->odbc_driver_version);
5162
5163 /* find maximum column name length */
5164 rc = SQLGetInfo(imp_dbh->hdbc, SQL_MAX_COLUMN_NAME_LEN,
5165 &imp_dbh->max_column_name_len,
5166 (SWORD) sizeof(imp_dbh->max_column_name_len), &dbvlen);
5167 if (!SQL_SUCCEEDED(rc)) {
5168 dbd_error(dbh, rc, "post_connect/SQLGetInfo(MAX_COLUMN_NAME_LEN)");
5169 imp_dbh->max_column_name_len = 256;
5170 } else {
5171 if (DBIc_TRACE(imp_dbh, 0x04000000, 0, 0))
5172 TRACE1(imp_dbh, "MAX_COLUMN_NAME_LEN = %d\n",
5173 imp_dbh->max_column_name_len);
5174 }
5175 if (imp_dbh->max_column_name_len > 256) {
5176 imp_dbh->max_column_name_len = 256;
5177 DBIh_SET_ERR_CHAR(
5178 dbh, (imp_xxh_t*)imp_drh, "0", 1,
5179 "Max column name length pegged at 256", Nullch, Nullch);
5180 }
5181
5182 /* default ignoring named parameters to false */
5183 imp_dbh->odbc_ignore_named_placeholders = 0;
5184
5185#ifdef WITH_UNICODE
5186 imp_dbh->odbc_has_unicode = 1;
5187#else
5188 imp_dbh->odbc_has_unicode = 0;
5189#endif
5190
5191 if (DBIc_TRACE(imp_dbh, 0x04000000, 0, 0))
5192 TRACE1(imp_dbh, "DBD::ODBC is unicode built : %s\n",
5193 imp_dbh->odbc_has_unicode ? "YES" : "NO");
5194
5195 imp_dbh->odbc_default_bind_type = 0;
5196 /* flag to see if SQLDescribeParam is supported */
5197 imp_dbh->odbc_sqldescribeparam_supported = -1;
5198 /* flag to see if SQLDescribeParam is supported */
5199 imp_dbh->odbc_sqlmoreresults_supported = -1;
5200 imp_dbh->odbc_defer_binding = 0;
5201 imp_dbh->odbc_force_rebind = 0;
5202 /* default value for query timeout is -1 which means do not set the
5203 query timeout at all. */
5204 imp_dbh->odbc_query_timeout = -1;
5205 imp_dbh->odbc_putdata_start = 32768;
5206 imp_dbh->odbc_column_display_size = 2001;
5207 imp_dbh->odbc_exec_direct = 0; /* default to not having SQLExecDirect used */
5208 imp_dbh->RowCacheSize = 1; /* default value for now */
5209
5210 /* see if we're connected to MS SQL Server */
5211 memset(imp_dbh->odbc_dbname, 'z', sizeof(imp_dbh->odbc_dbname));
5212 rc = SQLGetInfo(imp_dbh->hdbc, SQL_DBMS_NAME, imp_dbh->odbc_dbname,
5213 (SWORD)sizeof(imp_dbh->odbc_dbname), &dbvlen);
5214 if (SQL_SUCCEEDED(rc)) {
5215 /* can't find stricmp on my Linux, nor strcmpi. must be a
5216 * portable way to do this*/
5217 if (!strcmp(imp_dbh->odbc_dbname, "Microsoft SQL Server")) {
5218 imp_dbh->odbc_defer_binding = 1;
5219 }
5220 } else {
5221 strcpy(imp_dbh->odbc_dbname, "Unknown/Unsupported");
5222 }
5223 if (DBIc_TRACE(imp_dbh, 0x04000000, 0, 0))
5224 TRACE1(imp_dbh, "SQL_DBMS_NAME = %s\n", imp_dbh->odbc_dbname);
5225
5226 /* check to see if SQLMoreResults is supported */
5227 rc = SQLGetFunctions(imp_dbh->hdbc, SQL_API_SQLMORERESULTS, &supported);
5228 if (SQL_SUCCEEDED(rc)) {
5229 if (DBIc_TRACE(imp_dbh, 0x04000000, 0, 0))
5230 TRACE1(imp_dbh, "SQLMoreResults supported: %d\n", supported);
5231 imp_dbh->odbc_sqlmoreresults_supported = supported ? 1 : 0;
5232 } else {
5233 imp_dbh->odbc_sqlmoreresults_supported = 0;
5234 if (DBIc_TRACE(imp_dbh, 0x04000000, 0, 0))
5235 TRACE0(imp_dbh,
5236 " !!SQLGetFunctions(SQL_API_SQLMORERESULTS) failed:\n");
5237 AllODBCErrors(imp_dbh->henv, imp_dbh->hdbc, 0,
5238 DBIc_TRACE(imp_dbh, 0, 0, 3), DBIc_LOGPIO(imp_dbh));
5239 }
5240
5241 /* call only once per connection / DBH -- may want to do
5242 * this during the connect to avoid potential threading
5243 * issues */
5244 /* check to see if SQLDescribeParam is supported */
5245 rc = SQLGetFunctions(imp_dbh->hdbc, SQL_API_SQLDESCRIBEPARAM, &supported);
5246 if (SQL_SUCCEEDED(rc)) {
5247 imp_dbh->odbc_sqldescribeparam_supported = supported ? 1 : 0;
5248 } else {
5249 imp_dbh->odbc_sqldescribeparam_supported = 0;
5250 if (DBIc_TRACE(imp_dbh, 0x04000000, 0, 0))
5251 TRACE0(imp_dbh,
5252 " !!SQLGetFunctions(SQL_API_SQLDESCRIBEPARAM) failed:\n");
5253 AllODBCErrors(imp_dbh->henv, imp_dbh->hdbc, 0,
5254 DBIc_TRACE(imp_dbh, 0, 0, 3), DBIc_LOGPIO(imp_dbh));
5255 }
5256 if (DBIc_TRACE(imp_dbh, 0x04000000, 0, 0))
5257 TRACE1(imp_dbh, "SQLDescribeParam supported: %d\n",
5258 imp_dbh->odbc_sqldescribeparam_supported);
5259
5260 /* odbc_cursortype */
5261 {
5262 SV **svp;
5263 UV odbc_cursortype = 0;
5264
5265 DBD_ATTRIB_GET_IV(attr, "odbc_cursortype", 15,
5266 svp, odbc_cursortype);
5267 if (svp && odbc_cursortype) {
5268 if (DBIc_TRACE(imp_dbh, 0x04000000, 0, 0))
5269 TRACE1(imp_dbh,
5270 " Setting cursor type to: %d", odbc_cursortype);
5271 /* delete odbc_cursortype so we don't see it again via STORE */
5272 hv_delete((HV*)SvRV(attr), "odbc_cursortype",
5273 strlen("odbc_cursortype"), G_DISCARD);
5274
5275 rc = SQLSetConnectAttr(imp_dbh->hdbc,(SQLINTEGER)SQL_CURSOR_TYPE,
5276 (SQLPOINTER)odbc_cursortype,
5277 (SQLINTEGER)SQL_IS_INTEGER);
5278 if (!SQL_SUCCEEDED(rc) && (DBIc_TRACE(imp_dbh, 0x04000000, 0, 0)))
5279 TRACE1(imp_dbh, " !!Failed to set SQL_CURSORTYPE to %d\n",
5280 (int)odbc_cursortype);
5281 }
5282 }
5283
5284 /* odbc_query_timeout */
5285 {
5286 SV **svp;
5287 UV odbc_timeout = 0;
5288
5289 DBD_ATTRIB_GET_IV(
5290 attr, "odbc_query_timeout", strlen("odbc_query_timeout"),
5291 svp, odbc_timeout);
5292 if (svp && odbc_timeout) {
5293 imp_dbh->odbc_query_timeout = odbc_timeout;
5294 if (DBIc_TRACE(imp_dbh, 0x04000000, 0, 0))
5295 TRACE1(imp_dbh, " Setting DBH query timeout to %d\n",
5296 (int)odbc_timeout);
5297 /* delete odbc_cursortype so we don't see it again via STORE */
5298 hv_delete((HV*)SvRV(attr), "odbc_query_timeout",
5299 strlen("odbc_query_timeout"), G_DISCARD);
5300 }
5301 }
5302
5303 /* odbc_putdata_start */
5304 {
5305 SV **svp;
5306 IV putdata_start_value;
5307
5308 DBD_ATTRIB_GET_IV(
5309 attr, "odbc_putdata_start", strlen("odbc_putdata_start"),
5310 svp, putdata_start_value);
5311 if (svp) {
5312 imp_dbh->odbc_putdata_start = putdata_start_value;
5313 if (DBIc_TRACE(imp_dbh, 0x04000000, 0, 0))
5314 TRACE1(imp_dbh, " Setting DBH putdata_start to %d\n",
5315 (int)putdata_start_value);
5316 /* delete odbc_putdata_start so we don't see it again via STORE */
5317 hv_delete((HV*)SvRV(attr), "odbc_putdata_start",
5318 strlen("odbc_putdata_start"), G_DISCARD);
5319 }
5320 }
5321
5322 /* odbc_column_display_size */
5323 {
5324 SV **svp;
5325 IV column_display_size_value;
5326
5327 DBD_ATTRIB_GET_IV(
5328 attr, "odbc_column_display_size",
5329 strlen("odbc_column_display_size"),
5330 svp, column_display_size_value);
5331 if (svp) {
5332 imp_dbh->odbc_column_display_size = column_display_size_value;
5333 if (DBIc_TRACE(imp_dbh, 0x04000000, 0, 0))
5334 TRACE1(imp_dbh,
5335 " Setting DBH default column display size to %d\n",
5336 (int)column_display_size_value);
5337 /* delete odbc_column_display_size so we don't see it again via STORE */
5338 hv_delete((HV*)SvRV(attr), "odbc_column_display_size",
5339 strlen("odbc_column_display_size"), G_DISCARD);
5340 }
5341 }
5342
5343 return 1;
5344
5345}
5346
5347
5348
5349static SQLSMALLINT default_parameter_type(imp_sth_t *imp_sth)
5350{
5351 if (imp_sth->odbc_default_bind_type != 0) {
5352 return imp_sth->odbc_default_bind_type;
5353 } else {
5354 return ODBC_BACKUP_BIND_TYPE_VALUE;
5355 }
5356}
5357
5358/* end */