00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "xsb_config.h"
00026 #include "cell_xsb.h"
00027
00028 #ifdef CYGWIN
00029 #define FAR
00030 #include "sql.h"
00031 #include "sqlext.h"
00032 #include "odbc_string.h"
00033 #else
00034 #ifdef WIN_NT
00035 #include <windows.h>
00036 #endif
00037 #include <sql.h>
00038 #include <sqlext.h>
00039 #include <string.h>
00040 #endif
00041
00042 #include <stdio.h>
00043
00044 #include <stdlib.h>
00045 #include <assert.h>
00046
00047 #include "cinterf.h"
00048 #include "deref.h"
00049
00050 #include "error_xsb.h"
00051 #include "export.h"
00052 #include "register.h"
00053 #include "ptoc_tag_xsb_i.h"
00054 #include "io_builtins_xsb.h"
00055 #include "flags_xsb.h"
00056 #include "auxlry.h"
00057 #include "flag_defs_xsb.h"
00058 #include "loader_xsb.h"
00059 #include "memory_xsb.h"
00060 #include "heap_xsb.h"
00061
00062 #include "context.h"
00063 #include "varstring_xsb.h"
00064 #include "thread_xsb.h"
00065
00066 #define MAXCURSORNUM 200
00067 #define MAXVARSTRLEN 65000
00068 #define MAXI(a,b) ((a)>(b)?(a):(b))
00069
00070 static Psc nullFctPsc = NULL;
00071
00072 static long SQL_NTSval = SQL_NTS;
00073 static long SQL_NULL_DATAval = SQL_NULL_DATA;
00074
00075 static HENV henv = NULL;
00076
00077
00078 struct Cursor {
00079 struct Cursor *NCursor;
00080 struct Cursor *PCursor;
00081 HDBC hdbc;
00082 int driver_code;
00083
00084 int Status;
00085 UCHAR *Sql;
00086 HSTMT hstmt;
00087 int NumBindVars;
00088 UCHAR **BindList;
00089 int *BindTypes;
00090 SQLINTEGER *BindLens;
00091 SWORD NumCols;
00092 SWORD *ColTypes;
00093 UDWORD *ColLen;
00094 UDWORD *OutLen;
00095 UCHAR **Data;
00096 };
00097
00098
00099 struct NumberofCursors{
00100 HDBC hdbc;
00101 int CursorCount;
00102 struct NumberofCursors *NCurNum;
00103 };
00104
00105
00106
00107 #ifndef MULTI_THREAD
00108 struct NumberofCursors *FCurNum;
00109
00110 struct Cursor *FCursor;
00111 struct Cursor *LCursor;
00112
00113 #endif
00114
00115
00116 void print_hdbc(char *msg, HDBC hdbc) {
00117 int *ptr;
00118 int wds = 48;
00119
00120 printf("\n%s\nhdbc: %p",msg,hdbc);
00121 for(ptr = (int *)(((int)hdbc / 32) * 32); ptr < (int *)hdbc+wds ; ptr++) {
00122 if (((int)ptr % 32) == 0) printf("\n%p: ",ptr);
00123 printf(" %08x",*ptr);
00124 }
00125 printf("\n\n");
00126 }
00127
00128 SWORD ODBCToXSBType(SWORD odbcType)
00129 {
00130 switch (odbcType) {
00131 case SQL_TINYINT:
00132 case SQL_SMALLINT:
00133 case SQL_INTEGER:
00134 return SQL_C_SLONG;
00135 case SQL_DECIMAL:
00136 case SQL_NUMERIC:
00137 case SQL_REAL:
00138 case SQL_FLOAT:
00139 case SQL_DOUBLE:
00140 return SQL_C_FLOAT;
00141 case SQL_BINARY:
00142 case SQL_VARBINARY:
00143 case SQL_LONGVARBINARY:
00144 return SQL_C_BINARY;
00145 case SQL_DATE:
00146 case SQL_TIME:
00147 case SQL_TIMESTAMP:
00148 case SQL_CHAR:
00149 case SQL_VARCHAR:
00150 default:
00151 return SQL_C_CHAR;
00152 }
00153 }
00154
00155 int GetInfoTypeType(int SQL_INFO_TYPE)
00156 {
00157
00158
00159
00160
00161
00162
00163 int type;
00164 switch(SQL_INFO_TYPE) {
00165 case SQL_ACCESSIBLE_PROCEDURES:
00166 case SQL_ACCESSIBLE_TABLES:
00167 #if (ODBCVER >= 0x0300)
00168 case SQL_CATALOG_NAME:
00169 case SQL_COLLATION_SEQ:
00170 #endif
00171 case SQL_CATALOG_NAME_SEPARATOR:
00172 case SQL_CATALOG_TERM:
00173 case SQL_COLUMN_ALIAS:
00174 case SQL_DATA_SOURCE_NAME:
00175 case SQL_DATA_SOURCE_READ_ONLY:
00176 case SQL_DATABASE_NAME:
00177 case SQL_DBMS_NAME:
00178 case SQL_DBMS_VER:
00179 case SQL_DESCRIBE_PARAMETER:
00180 case SQL_DM_VER:
00181 case SQL_DRIVER_NAME:
00182 case SQL_DRIVER_ODBC_VER:
00183 case SQL_DRIVER_VER:
00184 case SQL_EXPRESSIONS_IN_ORDERBY:
00185 case SQL_IDENTIFIER_QUOTE_CHAR:
00186 case SQL_INTEGRITY:
00187 case SQL_KEYWORDS:
00188 case SQL_LIKE_ESCAPE_CLAUSE:
00189 case SQL_MAX_ROW_SIZE_INCLUDES_LONG:
00190 case SQL_MULT_RESULT_SETS:
00191 case SQL_MULTIPLE_ACTIVE_TXN:
00192 case SQL_NEED_LONG_DATA_LEN:
00193 case SQL_ODBC_VER:
00194 case SQL_ORDER_BY_COLUMNS_IN_SELECT:
00195 case SQL_PROCEDURE_TERM:
00196 case SQL_PROCEDURES:
00197 case SQL_ROW_UPDATES:
00198 case SQL_SCHEMA_TERM:
00199 case SQL_SEARCH_PATTERN_ESCAPE:
00200 case SQL_SERVER_NAME:
00201 case SQL_SPECIAL_CHARACTERS:
00202 case SQL_TABLE_TERM:
00203 case SQL_USER_NAME:
00204 case SQL_XOPEN_CLI_YEAR:
00205 type = 0;
00206 break;
00207 #if (ODBCVER >= 0x0300)
00208 case SQL_ACTIVE_ENVIRONMENTS:
00209 #endif
00210 case SQL_CATALOG_LOCATION:
00211 case SQL_CONCAT_NULL_BEHAVIOR:
00212 case SQL_CORRELATION_NAME:
00213 case SQL_CURSOR_COMMIT_BEHAVIOR:
00214 case SQL_CURSOR_ROLLBACK_BEHAVIOR:
00215 case SQL_FILE_USAGE:
00216 case SQL_GROUP_BY:
00217 case SQL_IDENTIFIER_CASE:
00218 case SQL_MAX_CATALOG_NAME_LEN:
00219 case SQL_MAX_COLUMN_NAME_LEN:
00220 case SQL_MAX_COLUMNS_IN_GROUP_BY:
00221 case SQL_MAX_COLUMNS_IN_INDEX:
00222 case SQL_MAX_COLUMNS_IN_ORDER_BY:
00223 case SQL_MAX_COLUMNS_IN_SELECT:
00224 case SQL_MAX_COLUMNS_IN_TABLE:
00225 case SQL_MAX_CONCURRENT_ACTIVITIES:
00226 case SQL_MAX_CURSOR_NAME_LEN:
00227 case SQL_MAX_DRIVER_CONNECTIONS:
00228 case SQL_MAX_IDENTIFIER_LEN:
00229 case SQL_MAX_PROCEDURE_NAME_LEN:
00230 case SQL_MAX_SCHEMA_NAME_LEN:
00231 case SQL_MAX_TABLE_NAME_LEN:
00232 case SQL_MAX_TABLES_IN_SELECT:
00233 case SQL_MAX_USER_NAME_LEN:
00234 case SQL_NON_NULLABLE_COLUMNS:
00235 case SQL_NULL_COLLATION:
00236 case SQL_QUOTED_IDENTIFIER_CASE:
00237 case SQL_TXN_CAPABLE:
00238 type = 1;
00239 break;
00240 #if (ODBCVER >= 0x0300)
00241 case SQL_ASYNC_MODE:
00242
00243 case SQL_DDL_INDEX:
00244 #endif
00245 case SQL_DEFAULT_TXN_ISOLATION:
00246 case SQL_DRIVER_HDBC:
00247 case SQL_DRIVER_HENV:
00248 case SQL_DRIVER_HDESC:
00249 case SQL_DRIVER_HLIB:
00250 case SQL_DRIVER_HSTMT:
00251 case SQL_MAX_ASYNC_CONCURRENT_STATEMENTS:
00252 case SQL_MAX_BINARY_LITERAL_LEN:
00253 case SQL_MAX_CHAR_LITERAL_LEN:
00254 case SQL_MAX_INDEX_SIZE:
00255 case SQL_MAX_ROW_SIZE:
00256 case SQL_MAX_STATEMENT_LEN:
00257 case SQL_ODBC_INTERFACE_CONFORMANCE:
00258 case SQL_SQL_CONFORMANCE:
00259 type = 2;
00260 break;
00261
00262 case SQL_ALTER_TABLE:
00263 case SQL_BOOKMARK_PERSISTENCE:
00264 case SQL_CATALOG_USAGE:
00265 case SQL_CONVERT_BIGINT:
00266 case SQL_CONVERT_BINARY:
00267 case SQL_CONVERT_BIT:
00268 case SQL_CONVERT_CHAR:
00269 #ifdef SQL_CONVERT_GUID
00270 case SQL_CONVERT_GUID:
00271 #endif
00272 case SQL_CONVERT_DATE:
00273 case SQL_CONVERT_DECIMAL:
00274 case SQL_CONVERT_DOUBLE:
00275 case SQL_CONVERT_FLOAT:
00276 case SQL_CONVERT_INTEGER:
00277 #if (ODBCVER >= 0x0300)
00278 case SQL_AGGREGATE_FUNCTIONS:
00279 case SQL_ALTER_DOMAIN:
00280 case SQL_BATCH_ROW_COUNT:
00281 case SQL_BATCH_SUPPORT:
00282 case SQL_CONVERT_INTERVAL_YEAR_MONTH:
00283 case SQL_CONVERT_INTERVAL_DAY_TIME:
00284 case SQL_CREATE_ASSERTION:
00285 case SQL_CREATE_CHARACTER_SET:
00286 case SQL_CREATE_COLLATION:
00287 case SQL_CREATE_DOMAIN:
00288 case SQL_CREATE_SCHEMA:
00289 case SQL_CREATE_TABLE:
00290 case SQL_CREATE_TRANSLATION:
00291 case SQL_CREATE_VIEW:
00292 case SQL_DATETIME_LITERALS:
00293 #endif
00294 case SQL_CONVERT_LONGVARBINARY:
00295 case SQL_CONVERT_LONGVARCHAR:
00296 case SQL_CONVERT_NUMERIC:
00297 case SQL_CONVERT_REAL:
00298 case SQL_CONVERT_SMALLINT:
00299 case SQL_CONVERT_TIME:
00300 case SQL_CONVERT_TIMESTAMP:
00301 case SQL_CONVERT_TINYINT:
00302 case SQL_CONVERT_VARBINARY:
00303 case SQL_CONVERT_VARCHAR:
00304 case SQL_CONVERT_FUNCTIONS:
00305 case SQL_DROP_ASSERTION:
00306 case SQL_DROP_CHARACTER_SET:
00307 case SQL_DROP_COLLATION:
00308 case SQL_DROP_DOMAIN:
00309 case SQL_DROP_SCHEMA:
00310 case SQL_DROP_TABLE:
00311 case SQL_DROP_TRANSLATION:
00312 case SQL_DROP_VIEW:
00313 case SQL_DYNAMIC_CURSOR_ATTRIBUTES1:
00314 case SQL_DYNAMIC_CURSOR_ATTRIBUTES2:
00315 case SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1:
00316 case SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES2:
00317 case SQL_GETDATA_EXTENSIONS:
00318 case SQL_INDEX_KEYWORDS:
00319 case SQL_INFO_SCHEMA_VIEWS:
00320 case SQL_INSERT_STATEMENT:
00321 case SQL_KEYSET_CURSOR_ATTRIBUTES1:
00322 case SQL_KEYSET_CURSOR_ATTRIBUTES2:
00323 case SQL_NUMERIC_FUNCTIONS:
00324 case SQL_OJ_CAPABILITIES:
00325 case SQL_PARAM_ARRAY_ROW_COUNTS:
00326 case SQL_PARAM_ARRAY_SELECTS:
00327 case SQL_POS_OPERATIONS:
00328 case SQL_SCHEMA_USAGE:
00329 case SQL_SCROLL_OPTIONS:
00330 case SQL_SQL92_DATETIME_FUNCTIONS:
00331 case SQL_SQL92_FOREIGN_KEY_DELETE_RULE:
00332 case SQL_SQL92_FOREIGN_KEY_UPDATE_RULE:
00333 case SQL_SQL92_GRANT:
00334 case SQL_SQL92_NUMERIC_VALUE_FUNCTIONS:
00335 case SQL_SQL92_PREDICATES:
00336 case SQL_SQL92_RELATIONAL_JOIN_OPERATORS:
00337 case SQL_SQL92_REVOKE:
00338 case SQL_SQL92_ROW_VALUE_CONSTRUCTOR:
00339 case SQL_SQL92_STRING_FUNCTIONS:
00340 case SQL_SQL92_VALUE_EXPRESSIONS:
00341 case SQL_STANDARD_CLI_CONFORMANCE:
00342 case SQL_STATIC_CURSOR_ATTRIBUTES1:
00343 case SQL_STATIC_CURSOR_ATTRIBUTES2:
00344 case SQL_STRING_FUNCTIONS:
00345 case SQL_SUBQUERIES:
00346 case SQL_SYSTEM_FUNCTIONS:
00347 case SQL_TIMEDATE_ADD_INTERVALS:
00348 case SQL_TIMEDATE_DIFF_INTERVALS:
00349 case SQL_TIMEDATE_FUNCTIONS:
00350 case SQL_TXN_ISOLATION_OPTION:
00351 case SQL_UNION:
00352 type = 3;
00353 break;
00354 default:
00355 type= -1;
00356 }
00357 return type;
00358 }
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369 int PrintErrorMsg(struct Cursor *cur)
00370 {
00371 UCHAR FAR *szsqlstate;
00372 SDWORD FAR *pfnativeerror;
00373 UCHAR FAR *szerrormsg;
00374 SWORD cberrormsgmax;
00375 SWORD FAR *pcberrormsg;
00376 RETCODE rc;
00377
00378 szsqlstate=(UCHAR FAR *)malloc(sizeof(UCHAR FAR)*10);
00379 pfnativeerror=(SDWORD FAR *)malloc(sizeof(SDWORD FAR));
00380 szerrormsg=(UCHAR FAR *)malloc(sizeof(UCHAR FAR)*SQL_MAX_MESSAGE_LENGTH);
00381 pcberrormsg=(SWORD FAR *)malloc(sizeof(SWORD FAR));
00382 cberrormsgmax=SQL_MAX_MESSAGE_LENGTH-1;
00383 if (cur != NULL)
00384 rc = SQLError(SQL_NULL_HENV, cur->hdbc, cur->hstmt, szsqlstate,
00385 pfnativeerror, szerrormsg,cberrormsgmax,pcberrormsg);
00386 else
00387 rc = SQLError(SQL_NULL_HENV, NULL, SQL_NULL_HSTMT, szsqlstate,
00388 pfnativeerror, szerrormsg,cberrormsgmax,pcberrormsg);
00389 if ((rc == SQL_SUCCESS) || (rc == SQL_SUCCESS_WITH_INFO)) {
00390 printf("ODBC SYSCALL ERROR (CODE %s): %s\n", szsqlstate, szerrormsg);
00391 }
00392 free(szsqlstate);
00393 free(pfnativeerror);
00394 free(szerrormsg);
00395 free(pcberrormsg);
00396 return 1;
00397 }
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407 void SetCursorClose(struct Cursor *cur)
00408 {
00409 int j;
00410
00411 SQLFreeStmt(cur->hstmt, SQL_CLOSE);
00412
00413 if (cur->NumBindVars) {
00414 for (j = 0; j < cur->NumBindVars; j++)
00415 if (cur->BindTypes[j] < 2) free((void *)cur->BindList[j]);
00416 free(cur->BindList);
00417 free(cur->BindTypes);
00418 free(cur->BindLens);
00419 }
00420
00421 if (cur->NumCols) {
00422 for (j = 0; j < cur->NumCols; j++)
00423 free(cur->Data[j]);
00424 free(cur->ColTypes);
00425 free(cur->ColLen);
00426 free(cur->OutLen);
00427 free(cur->Data);
00428 }
00429
00430
00431 if (cur->Sql) free(cur->Sql);
00432
00433 cur->Sql = 0;
00434 cur->NumCols =
00435 cur->Status =
00436 cur->NumBindVars = 0;
00437 }
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460 void ODBCConnect(CTXTdecl)
00461 {
00462 UCHAR uid[128];
00463 UCHAR *server;
00464 UCHAR *pwd;
00465 UCHAR *connectIn;
00466 HDBC hdbc = NULL;
00467 RETCODE rc;
00468 int new;
00469
00470
00471 if (!henv) {
00472
00473 SYS_MUTEX_LOCK( MUTEX_ODBC) ;
00474
00475 rc = SQLAllocEnv(&henv);
00476 if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
00477 xsb_error("Environment allocation failed");
00478 ctop_int(CTXTc 6, 0);
00479 return;
00480 }
00481
00482
00483
00484
00485 LCursor = FCursor = NULL;
00486 FCurNum = NULL;
00487 if (nullFctPsc == NULL)
00488 nullFctPsc = pair_psc(insert("NULL",1,global_mod,&new));
00489 SYS_MUTEX_UNLOCK( MUTEX_ODBC) ;
00490 }
00491
00492
00493 rc = SQLAllocConnect(henv, &hdbc);
00494 if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
00495 xsb_error("Connection Resources Allocation Failed");
00496 ctop_int(CTXTc 6, 0);
00497 return;
00498 }
00499
00500 if (!ptoc_int(CTXTc 2)) {
00501
00502 server = (UCHAR *)ptoc_string(CTXTc 3);
00503 strcpy(uid, (UCHAR *)ptoc_string(CTXTc 4));
00504 pwd = (UCHAR *)ptoc_string(CTXTc 5);
00505
00506
00507 rc = SQLConnect(hdbc, server, SQL_NTS, uid, SQL_NTS, pwd, SQL_NTS);
00508 if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
00509 SQLFreeConnect(hdbc);
00510 xsb_error("Connection to server %s failed", server);
00511 ctop_int(CTXTc 6, 0);
00512 return;
00513 }
00514 } else {
00515
00516 connectIn = (UCHAR *)ptoc_longstring(CTXTc 3);
00517 rc = SQLDriverConnect(hdbc, NULL, connectIn, SQL_NTS, NULL, 0, NULL,SQL_DRIVER_NOPROMPT);
00518 if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
00519 SQLFreeConnect(hdbc);
00520 xsb_error("Connection to driver failed: %s", connectIn);
00521 ctop_int(CTXTc 6, 0);
00522 return;
00523 }
00524 }
00525
00526 ctop_int(CTXTc 6, (long)hdbc);
00527 return;
00528 }
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542 void ODBCDisconnect(CTXTdecl)
00543 {
00544 struct Cursor *cur = FCursor;
00545 struct Cursor *tcur;
00546 struct NumberofCursors *numi = FCurNum, *numj = FCurNum;
00547 HDBC hdbc = (HDBC)ptoc_int(CTXTc 2);
00548 RETCODE rc;
00549
00550 rc = SQLTransact(henv,hdbc,SQL_COMMIT);
00551 if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
00552 xsb_abort("[ODBC] Error committing transactions");
00553 }
00554
00555 if (hdbc == NULL) {
00556 if (FCursor != NULL)
00557 xsb_abort("[ODBC] Must close all connections before shutting down");
00558 SQLFreeEnv(henv);
00559 return;
00560 }
00561
00562
00563 while((numj != NULL) && (numj->hdbc != hdbc)){
00564 if(numj != FCurNum) numi=numi->NCurNum;
00565 numj=numj->NCurNum;
00566 }
00567
00568 if(numj != NULL){
00569 if(numj == FCurNum) FCurNum=numj->NCurNum;
00570 else numi->NCurNum=numj->NCurNum;
00571 free(numj);
00572 }
00573
00574 while (cur != NULL) {
00575 if (cur->hdbc == hdbc) {
00576 tcur = cur->NCursor;
00577 if (cur->Status != 0) {
00578 SetCursorClose(cur);
00579 }
00580 SQLFreeStmt(cur->hstmt,SQL_DROP);
00581 if (cur->PCursor) (cur->PCursor)->NCursor = cur->NCursor;
00582 else FCursor = cur->NCursor;
00583 if (cur->NCursor) (cur->NCursor)->PCursor = cur->PCursor;
00584 else LCursor = cur->PCursor;
00585 free(cur);
00586
00587 cur = tcur;
00588 }
00589 else cur = cur->NCursor;
00590 }
00591
00592 SQLDisconnect(hdbc);
00593 SQLFreeConnect(hdbc);
00594
00595 }
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616 void FindFreeCursor(CTXTdecl)
00617 {
00618 struct Cursor *curi = FCursor, *curj = NULL, *curk = NULL;
00619 struct NumberofCursors *num = FCurNum;
00620 HDBC hdbc = (HDBC)ptoc_int(CTXTc 2);
00621 char *Sql_stmt = ptoc_longstring(CTXTc 3);
00622 RETCODE rc;
00623 char drname[25]; SQLSMALLINT drnamelen;
00624
00625
00626 while (curi != NULL) {
00627 if (curi->hdbc == hdbc) {
00628 if (curi->Status == 0) curj = curi;
00629 else {
00630 if (curi->Status == 1) {
00631
00632 if (!strcmp(curi->Sql,Sql_stmt)) {
00633 if (curi != FCursor) {
00634 (curi->PCursor)->NCursor = curi->NCursor;
00635 if (curi == LCursor) LCursor = curi->PCursor;
00636 else (curi->NCursor)->PCursor = curi->PCursor;
00637 FCursor->PCursor = curi;
00638 curi->PCursor = NULL;
00639 curi->NCursor = FCursor;
00640 FCursor = curi;
00641 }
00642 curi->Status = 2;
00643 ctop_int(CTXTc 4, (long)curi);
00644
00645 return;
00646 } else {
00647 curk = curi;
00648 }
00649 }
00650 }
00651 }
00652 curi = curi->NCursor;
00653 }
00654
00655
00656 if (curj != NULL) {
00657 curi = curj;
00658
00659 }
00660 else {
00661 while((num != NULL) && (num->hdbc != hdbc)){
00662 num=num->NCurNum;
00663 }
00664 if(num == NULL){
00665 num = (struct NumberofCursors *)malloc(sizeof(struct NumberofCursors));
00666 num->hdbc = hdbc;
00667 num->NCurNum=FCurNum;
00668 FCurNum=num;
00669 num->CursorCount=0;
00670 }
00671
00672 if (num->CursorCount < MAXCURSORNUM) {
00673
00674 curi = (struct Cursor *)calloc(sizeof(struct Cursor),1);
00675 curi->PCursor = NULL;
00676 curi->NCursor = FCursor;
00677 if (FCursor == NULL) LCursor = curi;
00678 else FCursor->PCursor = curi;
00679 FCursor = curi;
00680
00681 rc = SQLAllocStmt(hdbc,&(curi->hstmt));
00682 if (!((rc==SQL_SUCCESS) ||
00683 (rc==SQL_SUCCESS_WITH_INFO))) {
00684 free(curi);
00685
00686 xsb_abort("[ODBC] ERROR while trying to allocate ODBC statement\n");
00687 }
00688
00689 num->CursorCount++;
00690
00691
00692 }
00693 else if (curk == NULL) {
00694 ctop_int(CTXTc 4, 0);
00695 return;
00696 }
00697 else {
00698 curi = curk;
00699 SetCursorClose(curi);
00700
00701 }
00702 }
00703
00704
00705 if (curi != FCursor) {
00706 (curi->PCursor)->NCursor = curi->NCursor;
00707 if (curi == LCursor) LCursor = curi->PCursor;
00708 else (curi->NCursor)->PCursor = curi->PCursor;
00709 FCursor->PCursor = curi;
00710 curi->PCursor = NULL;
00711 curi->NCursor = FCursor;
00712 FCursor = curi;
00713 }
00714
00715 rc = SQLGetInfo(hdbc,SQL_DRIVER_NAME,drname,(SQLSMALLINT)25,&drnamelen);
00716 if (rc != SQL_SUCCESS) curi->driver_code = 0;
00717 else if (!strcmp(drname,"odbcjt32.dll")) curi->driver_code = 1;
00718 else curi->driver_code = 0;
00719
00720 curi->hdbc = hdbc;
00721 curi->Sql = (UCHAR *)strdup(Sql_stmt);
00722 if (!curi->Sql)
00723 xsb_abort("[ODBC] Not enough memory for SQL stmt in FindFreeCursor!\n");
00724 curi->Status = 3;
00725 ctop_int(CTXTc 4, (long)curi);
00726 return;
00727 }
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745 void SetBindVarNum(CTXTdecl)
00746 {
00747 struct Cursor *cur = (struct Cursor *)ptoc_int(CTXTc 2);
00748 int NumBindVars = ptoc_int(CTXTc 3);
00749
00750 if (cur->Status == 2) {
00751 if (cur->NumBindVars != NumBindVars)
00752 xsb_abort("[ODBC] Number of Bind values provided does not agree with query\n");
00753 return;
00754 }
00755
00756 cur->NumBindVars = NumBindVars;
00757 cur->BindList = malloc(sizeof(UCHAR *) * NumBindVars);
00758 if (!cur->BindList)
00759 xsb_abort("[ODBC] Not enough memory for cur->BindList!");
00760 cur->BindTypes = malloc(sizeof(int) * NumBindVars);
00761 if (!cur->BindTypes)
00762 xsb_abort("[ODBC] Not enough memory for cur->BindTypes!");
00763 cur->BindLens = malloc(sizeof(SQLINTEGER) * NumBindVars);
00764 if (!cur->BindLens)
00765 xsb_abort("[ODBC] Not enough memory for cur->BindLens!");
00766
00767 }
00768
00769 DllExport void call_conv write_canonical_term(CTXTdeclc Cell prologterm, int letterflag);
00770 #define wcan_string tsgLBuff1
00771
00772 #define MAX_BIND_VALS 30
00773 char *term_string[MAX_BIND_VALS] = {0};
00774
00775 void string_to_char(Cell list, char **term_string) {
00776 Cell tlist, car;
00777 char *charptr;
00778 int len = 0;
00779
00780 if (*term_string) free(*term_string);
00781 XSB_Deref(list);
00782 tlist = list;
00783 while (islist(tlist)) {
00784 len++;
00785 tlist = p2p_cdr(tlist);
00786 XSB_Deref(tlist);
00787 }
00788 *term_string = charptr = malloc(len+1);
00789 while (islist(list)) {
00790 car = p2p_car(list);
00791 XSB_Deref(car);
00792 *(charptr++) = int_val(car);
00793 list = p2p_cdr(list);
00794 XSB_Deref(list);
00795 }
00796 *charptr = '\0';
00797 }
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812 void SetBindVal(CTXTdecl)
00813 {
00814 RETCODE rc;
00815 struct Cursor *cur = (struct Cursor *)ptoc_int(CTXTc 2);
00816 int j = ptoc_int(CTXTc 3);
00817 Cell BindVal = ptoc_tag(CTXTc 4);
00818
00819 if (!((j >= 0) && (j < cur->NumBindVars)))
00820 xsb_abort("[ODBC] Abnormal argument in SetBindVal!");
00821
00822
00823
00824 if (cur->Status == 2) {
00825 if (isinteger(BindVal)) {
00826 if (cur->BindTypes[j] != 0) {
00827 if (cur->BindTypes[j] < 2) free((void *)cur->BindList[j]);
00828 cur->BindList[j] = (UCHAR *)malloc(sizeof(int));
00829 cur->BindTypes[j] = 0;
00830 rc = SQLBindParameter(cur->hstmt, (short)(j+1), SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, (int *)(cur->BindList[j]), 0, NULL);
00831 if (rc != SQL_SUCCESS) {
00832 ctop_int(CTXTc 5,PrintErrorMsg(cur));
00833 SetCursorClose(cur);
00834 return;
00835 }
00836 }
00837 *((int *)cur->BindList[j]) = oint_val(BindVal);
00838 } else if (isofloat(BindVal)) {
00839 if (cur->BindTypes[j] != 1) {
00840
00841 if (cur->BindTypes[j] < 2) free((void *)cur->BindList[j]);
00842 cur->BindList[j] = (UCHAR *)malloc(sizeof(float));
00843 cur->BindTypes[j] = 1;
00844 rc = SQLBindParameter(cur->hstmt, (short)(j+1), SQL_PARAM_INPUT, SQL_C_FLOAT, SQL_FLOAT, 0, 0, (float *)(cur->BindList[j]), 0, NULL);
00845 if (rc != SQL_SUCCESS) {
00846 ctop_int(CTXTc 5,PrintErrorMsg(cur));
00847 SetCursorClose(cur);
00848 return;
00849 }
00850 }
00851 *((float *)cur->BindList[j]) = (float)ofloat_val(BindVal);
00852 } else if (isstring(BindVal)) {
00853 if (cur->BindTypes[j] != 2) {
00854
00855 if (cur->BindTypes[j] < 2) free((void *)cur->BindList[j]);
00856 cur->BindTypes[j] = 2;
00857
00858 }
00859 cur->BindList[j] = string_val(BindVal);
00860 } else if (isconstr(BindVal) && get_str_psc(BindVal) == nullFctPsc) {
00861 if (cur->BindTypes[j] < 2) free((void *)cur->BindList[j]);
00862 cur->BindTypes[j] = 3;
00863 cur->BindList[j] = NULL;
00864 } else if (isconstr(BindVal) && get_arity(get_str_psc(BindVal))==1) {
00865 if (!strcmp(get_name(get_str_psc(BindVal)),"string")) {
00866 if (cur->BindTypes[j] < 2) free((void *)cur->BindList[j]);
00867 string_to_char(p2p_arg(BindVal,1),&(term_string[j]));
00868 cur->BindTypes[j] = 2;
00869 cur->BindList[j] = term_string[j];
00870 } else {
00871 if (cur->BindTypes[j] < 2) free((void *)cur->BindList[j]);
00872 write_canonical_term(CTXTc p2p_arg(BindVal,1),1);
00873 if (term_string[j]) free(term_string[j]);
00874 term_string[j] = malloc(wcan_string->length+1);
00875 strcpy(term_string[j],wcan_string->string);
00876 cur->BindTypes[j] = 2;
00877 cur->BindList[j] = term_string[j];
00878 }
00879 } else {
00880 xsb_abort("[ODBC] Unknown bind variable type, %d", cur->BindTypes[j]);
00881 }
00882 ctop_int(CTXTc 5,0);
00883 return;
00884 }
00885
00886
00887 if (isinteger(BindVal)) {
00888 cur->BindTypes[j] = 0;
00889 cur->BindList[j] = (UCHAR *)malloc(sizeof(int));
00890 if (!cur->BindList[j])
00891 xsb_abort("[ODBC] Not enough memory for an int in SetBindVal!");
00892 *((int *)cur->BindList[j]) = oint_val(BindVal);
00893 } else if (isofloat(BindVal)) {
00894 cur->BindTypes[j] = 1;
00895 cur->BindList[j] = (UCHAR *)malloc(sizeof(float));
00896 if (!cur->BindList[j])
00897 xsb_abort("[ODBC] Not enough memory for a float in SetBindVal!");
00898 *((float *)cur->BindList[j]) = (float)ofloat_val(BindVal);
00899 } else if (isstring(BindVal)) {
00900 cur->BindTypes[j] = 2;
00901 cur->BindList[j] = string_val(BindVal);
00902 } else if (isconstr(BindVal) && get_str_psc(BindVal) == nullFctPsc) {
00903 cur->BindTypes[j] = 3;
00904 cur->BindList[j] = NULL;
00905 } else if (isconstr(BindVal) && get_arity(get_str_psc(BindVal))==1) {
00906 if (!strcmp(get_name(get_str_psc(BindVal)),"string")) {
00907 string_to_char(p2p_arg(BindVal,1),&(term_string[j]));
00908 cur->BindTypes[j] = 2;
00909 cur->BindList[j] = term_string[j];
00910 } else {
00911 write_canonical_term(CTXTc p2p_arg(BindVal,1),1);
00912 if (term_string[j]) free(term_string[j]);
00913 term_string[j] = malloc(wcan_string->length+1);
00914 strcpy(term_string[j],wcan_string->string);
00915 cur->BindTypes[j] = 2;
00916 cur->BindList[j] = term_string[j];
00917 }
00918 } else {
00919 xsb_abort("[ODBC] Unknown bind variable type, %d", cur->BindTypes[j]);
00920 }
00921 ctop_int(CTXTc 5,0);
00922 return;
00923 }
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939 void Parse(CTXTdecl)
00940 {
00941 int j;
00942 struct Cursor *cur = (struct Cursor *)ptoc_int(CTXTc 2);
00943 RETCODE rc;
00944 if (cur->Status == 2) {
00945 rc = SQLFreeStmt(cur->hstmt,SQL_CLOSE);
00946 if ((rc != SQL_SUCCESS) && (rc != SQL_SUCCESS_WITH_INFO)) {
00947 ctop_int(CTXTc 3, PrintErrorMsg(cur));
00948 SetCursorClose(cur);
00949 return;
00950 }
00951
00952 for (j = 0; j < cur->NumBindVars; j++) {
00953 cur->BindLens[j] = 0;
00954 switch (cur->BindTypes[j])
00955 {
00956 case 2:
00957 cur->BindLens[j] = strlen((char *)cur->BindList[j]);
00958 if (cur->driver_code == 1)
00959 rc = SQLBindParameter(cur->hstmt, (short)(j+1), SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 0, 0,(char *)cur->BindList[j], 0, &SQL_NTSval);
00960 else rc = SQLBindParameter(cur->hstmt, (short)(j+1), SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 0, 0,(char *)cur->BindList[j], cur->BindLens[j], &cur->BindLens[j]);
00961 break;
00962 case 3:
00963 rc = SQLBindParameter(cur->hstmt, (short)(j+1), SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 0, 0,NULL, 0, &SQL_NULL_DATAval);
00964 break;
00965 }
00966 }
00967 } else {
00968 if (SQL_SUCCESS != (rc = SQLPrepare(cur->hstmt, cur->Sql, SQL_NTS)))
00969 {
00970 ctop_int(CTXTc 3,PrintErrorMsg(cur));
00971 SetCursorClose(cur);
00972 return;
00973 }
00974
00975
00976
00977 for (j = 0; j < cur->NumBindVars; j++) {
00978 switch (cur->BindTypes[j])
00979 {
00980 case 0:
00981 rc = SQLBindParameter(cur->hstmt, (short)(j+1), SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, (int *)(cur->BindList[j]), 0, NULL);
00982 break;
00983 case 1:
00984 rc = SQLBindParameter(cur->hstmt, (short)(j+1), SQL_PARAM_INPUT, SQL_C_FLOAT, SQL_FLOAT, 0, 0, (float *)cur->BindList[j], 0, NULL);
00985 break;
00986 case 2:
00987
00988 cur->BindLens[j] = strlen((char *)cur->BindList[j]);
00989 if (cur->driver_code == 1)
00990 rc = SQLBindParameter(cur->hstmt, (short)(j+1), SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 0, 0,(char *)cur->BindList[j], 0, &SQL_NTSval);
00991 else rc = SQLBindParameter(cur->hstmt, (short)(j+1), SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 0, 0,(char *)cur->BindList[j], cur->BindLens[j], &cur->BindLens[j]);
00992 break;
00993 case 3:
00994 rc = SQLBindParameter(cur->hstmt, (short)(j+1), SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 0, 0,NULL, 0, &SQL_NULL_DATAval);
00995 break;
00996 default:
00997 xsb_abort("[ODBC] illegal BindVal");
00998 rc = 0;
00999 }
01000 if (rc != SQL_SUCCESS)
01001 {
01002 ctop_int(CTXTc 3,PrintErrorMsg(cur));
01003 SetCursorClose(cur);
01004 return;
01005 }
01006 }
01007 }
01008
01009 if (SQLExecute(cur->hstmt) != SQL_SUCCESS) {
01010 ctop_int(CTXTc 3,PrintErrorMsg(cur));
01011 SetCursorClose(cur);
01012 return;
01013 }
01014 ctop_int(CTXTc 3,0);
01015 return;
01016 }
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026 void ODBCCommit(CTXTdecl)
01027 {
01028 struct Cursor *cur = FCursor;
01029 HDBC hdbc = (HDBC)ptoc_int(CTXTc 2);
01030 RETCODE rc;
01031
01032 if (((rc=SQLTransact(henv,hdbc,SQL_COMMIT)) == SQL_SUCCESS) ||
01033 (rc == SQL_SUCCESS_WITH_INFO)) {
01034
01035 while (cur != NULL) {
01036 if (cur->hdbc == hdbc && cur->Status != 0) SetCursorClose(cur);
01037 cur = cur->NCursor;
01038 }
01039 ctop_int(CTXTc 3,0);
01040 } else
01041 ctop_int(CTXTc 3,PrintErrorMsg(NULL));
01042 return;
01043 }
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053 void ODBCRollback(CTXTdecl)
01054 {
01055 struct Cursor *cur = FCursor;
01056 HDBC hdbc = (HDBC)ptoc_int(CTXTc 2);
01057 RETCODE rc;
01058
01059 if (((rc=SQLTransact(henv,hdbc,SQL_ROLLBACK)) == SQL_SUCCESS) ||
01060 (rc == SQL_SUCCESS_WITH_INFO)) {
01061
01062 while (cur != NULL) {
01063 if (cur->hdbc == hdbc && cur->Status != 0) SetCursorClose(cur);
01064 cur = cur->NCursor;
01065 }
01066 ctop_int(CTXTc 3,0);
01067 } else
01068 ctop_int(CTXTc 3, PrintErrorMsg(NULL));
01069 return;
01070 }
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081 void ODBCColumns(CTXTdecl)
01082 {
01083 struct Cursor *cur = (struct Cursor *)ptoc_int(CTXTc 2);
01084 char tmpstr[255];
01085 char *str1, *str2, *str3;
01086 RETCODE rc;
01087
01088 strcpy(tmpstr,ptoc_string(CTXTc 3));
01089 str1 = strtok(tmpstr,".");
01090 str2 = str3 = NULL;
01091 if (str1) str2 = strtok(NULL,".");
01092 if (str2) str3 = strtok(NULL,".");
01093 if (!str3 && !str2) {str3 = str1; str1 = NULL;}
01094 else if (!str3) {str3 = str2; str2 = NULL;}
01095
01096 if (((rc=SQLColumns(cur->hstmt,
01097 str1, SQL_NTS,
01098 str2, SQL_NTS,
01099 str3, SQL_NTS,
01100 NULL,0)) == SQL_SUCCESS) ||
01101 (rc == SQL_SUCCESS_WITH_INFO)) {
01102 ctop_int(CTXTc 4,0);
01103 } else {
01104 ctop_int(CTXTc 4,PrintErrorMsg(cur));
01105 SetCursorClose(cur);
01106 }
01107 return;
01108 }
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118 void ODBCTables(CTXTdecl)
01119 {
01120 struct Cursor *cur = (struct Cursor *)ptoc_int(CTXTc 2);
01121 RETCODE rc;
01122
01123 if (cur->Status == 2) {
01124 rc = SQLFreeStmt(cur->hstmt,SQL_CLOSE);
01125 if ((rc != SQL_SUCCESS) && (rc != SQL_SUCCESS_WITH_INFO)) {
01126 ctop_int(CTXTc 3, PrintErrorMsg(cur));
01127 SetCursorClose(cur);
01128 return;
01129 }
01130 }
01131
01132 if (((rc=SQLTables(cur->hstmt,
01133 NULL, 0,
01134 NULL, 0,
01135 NULL, 0,
01136 NULL, 0)) == SQL_SUCCESS) ||
01137 (rc == SQL_SUCCESS_WITH_INFO)) {
01138 ctop_int(CTXTc 3,0);
01139 } else {
01140 ctop_int(CTXTc 3,PrintErrorMsg(cur));
01141 SetCursorClose(cur);
01142 }
01143 return;
01144 }
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154 void ODBCUserTables(CTXTdecl)
01155 {
01156 struct Cursor *cur = (struct Cursor *)ptoc_int(CTXTc 2);
01157 UWORD TablePrivilegeExists;
01158 RETCODE rc;
01159
01160
01161
01162 SQLGetFunctions(cur->hdbc,SQL_API_SQLTABLEPRIVILEGES,&TablePrivilegeExists);
01163 if (!TablePrivilegeExists) {
01164 printf("Privilege concept does not exist in this DVMS: you probably can access any of the existing tables\n");
01165 ctop_int(CTXTc 3, 2);
01166 return;
01167 }
01168 if (((rc=SQLTablePrivileges(cur->hstmt,
01169 NULL, 0,
01170 NULL, 0,
01171 NULL, 0)) == SQL_SUCCESS) ||
01172 (rc == SQL_SUCCESS_WITH_INFO))
01173 ctop_int(CTXTc 3,0);
01174 else {
01175 ctop_int(CTXTc 3,PrintErrorMsg(cur));
01176 SetCursorClose(cur);
01177 }
01178 return;
01179 }
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193 UDWORD DisplayColSize(SWORD coltype, UDWORD collen, UCHAR *colname)
01194 {
01195 switch (ODBCToXSBType(coltype)) {
01196 case SQL_C_SLONG:
01197 return sizeof(long *);
01198 case SQL_C_CHAR: {
01199 UDWORD tmp = MAXI(collen+1, strlen((char *) colname));
01200 if (tmp < MAXVARSTRLEN) return tmp;
01201 else return MAXVARSTRLEN;
01202 }
01203 case SQL_C_BINARY: {
01204 return MAXVARSTRLEN;
01205 }
01206 case SQL_C_FLOAT:
01207 return sizeof(float *);
01208 default:
01209 printf("Illegal ODBC Type: %d\n",coltype);
01210 return 0;
01211 }
01212 }
01213 extern xsbBool unify(CTXTdecltypec Cell, Cell);
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225 void ODBCDataSources(CTXTdecl)
01226 {
01227 SQLCHAR DSN[SQL_MAX_DSN_LENGTH+1];
01228 SQLCHAR Description[SQL_MAX_DSN_LENGTH+1];
01229 RETCODE rc;
01230 int seq, new;
01231 SWORD dsn_size, descr_size;
01232 Cell op2 = ptoc_tag(CTXTc 3);
01233 Cell op3 = ptoc_tag(CTXTc 4);
01234
01235 if (!henv) {
01236
01237 SYS_MUTEX_LOCK( MUTEX_ODBC) ;
01238
01239 rc = SQLAllocEnv(&henv);
01240 if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
01241 xsb_error("Environment allocation failed");
01242 ctop_int(CTXTc 5,1);
01243 return;
01244 }
01245 LCursor = FCursor = NULL;
01246 FCurNum = NULL;
01247 if (nullFctPsc == NULL)
01248 nullFctPsc = pair_psc(insert("NULL",1,global_mod,&new));
01249 SYS_MUTEX_UNLOCK( MUTEX_ODBC) ;
01250 }
01251
01252 seq = ptoc_int(CTXTc 2);
01253 if (seq == 1) {
01254 rc = SQLDataSources(henv,SQL_FETCH_FIRST,DSN,
01255 SQL_MAX_DSN_LENGTH,&dsn_size,
01256 Description,SQL_MAX_DSN_LENGTH,
01257 &descr_size);
01258 if (rc == SQL_NO_DATA_FOUND) {
01259 ctop_int(CTXTc 5,2);
01260 return;
01261 }
01262 if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
01263 xsb_error("Environment allocation failed");
01264 ctop_int(CTXTc 5,1);
01265 return;
01266 }
01267 } else {
01268 rc = SQLDataSources(henv,SQL_FETCH_NEXT,DSN,
01269 SQL_MAX_DSN_LENGTH,&dsn_size,
01270 Description,SQL_MAX_DSN_LENGTH,
01271 &descr_size);
01272 if (rc == SQL_NO_DATA_FOUND) {
01273 ctop_int(CTXTc 5,2);
01274 return;
01275 }
01276 if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
01277 xsb_error("Environment allocation failed");
01278 ctop_int(CTXTc 5,1);
01279 return;
01280 }
01281 }
01282 XSB_Deref(op2);
01283 if (isref(op2))
01284 {
01285 char * tempDSNstring= string_find(DSN,1);
01286 Cell cellStr = makestring(tempDSNstring);
01287 unify(CTXTc op2, cellStr);
01288 }
01289 else {
01290 xsb_error("[ODBCDataSources] Param 2 should be a free variable.");
01291 ctop_int(CTXTc 5,1);
01292 return;
01293 }
01294 XSB_Deref(op3);
01295 if (isref(op3))
01296 {
01297 unify(CTXTc op3, makestring(string_find(Description,1)));
01298 }
01299 else {
01300 xsb_error("[ODBCDataSources] Param 3 should be a free variable.");
01301 ctop_int(CTXTc 5,1);
01302 return;
01303 }
01304 ctop_int(CTXTc 5,0);
01305 return;
01306 }
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322 void ODBCDescribeSelect(CTXTdecl)
01323 {
01324 int j;
01325 UCHAR colname[50];
01326 SWORD colnamelen;
01327 SWORD scale;
01328 SWORD nullable;
01329 UDWORD collen;
01330 struct Cursor *cur = (struct Cursor *)ptoc_int(CTXTc 2);
01331
01332 cur->NumCols = 0;
01333 SQLNumResultCols(cur->hstmt, (SQLSMALLINT*)&(cur->NumCols));
01334 if (!(cur->NumCols)) {
01335
01336 cur->Status = 1;
01337 ctop_int(CTXTc 3,2);
01338 return;
01339 }
01340
01341
01342 if (cur->Status != 2) {
01343 cur->ColTypes =
01344 (SWORD *)malloc(sizeof(SWORD) * cur->NumCols);
01345 if (!cur->ColTypes)
01346 xsb_abort("[ODBC] Not enough memory for ColTypes!");
01347
01348 cur->Data =
01349 (UCHAR **)malloc(sizeof(char *) * cur->NumCols);
01350 if (!cur->Data)
01351 xsb_abort("[ODBC] Not enough memory for Data!");
01352
01353 cur->OutLen =
01354 (UDWORD *)malloc(sizeof(UDWORD) * cur->NumCols);
01355 if (!cur->OutLen)
01356 xsb_abort("[ODBC] Not enough memory for OutLen!");
01357
01358 cur->ColLen =
01359 (UDWORD *)malloc(sizeof(UDWORD) * cur->NumCols);
01360 if (!cur->ColLen)
01361 xsb_abort("[ODBC] Not enough memory for ColLen!");
01362
01363 for (j = 0; j < cur->NumCols; j++) {
01364 SQLDescribeCol(cur->hstmt, (short)(j+1), (UCHAR FAR*)colname,
01365 sizeof(colname), &colnamelen,
01366 &(cur->ColTypes[j]),
01367 &collen, &scale, &nullable);
01368
01369 if (cur->ColTypes[j] == -9) cur->ColTypes[j] = SQL_VARCHAR;
01370 colnamelen = (colnamelen > 49) ? 49 : colnamelen;
01371 colname[colnamelen] = '\0';
01372 cur->ColLen[j] = DisplayColSize(cur->ColTypes[j],collen,colname);
01373 if (!(cur->ColLen[j])) {
01374
01375
01376 cur->NumCols = j;
01377 SetCursorClose(cur);
01378
01379 ctop_int(CTXTc 3,1);
01380 return;
01381 }
01382 cur->Data[j] =
01383 (UCHAR *) malloc(((unsigned) cur->ColLen[j]+1)*sizeof(UCHAR));
01384 if (!cur->Data[j])
01385 xsb_abort("[ODBC] Not enough memory for Data[j]!");
01386 }
01387 }
01388
01389 for (j = 0; j < cur->NumCols; j++) {
01390 SQLBindCol(cur->hstmt, (short)(j+1),
01391 ODBCToXSBType(cur->ColTypes[j]), cur->Data[j],
01392 cur->ColLen[j], (SDWORD FAR *)(&(cur->OutLen[j])));
01393 }
01394
01395 ctop_int(CTXTc 3,0);
01396 return;
01397 }
01398
01399
01400
01401
01402
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412 void FetchNextRow(CTXTdecl)
01413 {
01414 struct Cursor *cur = (struct Cursor *)ptoc_int(CTXTc 2);
01415 RETCODE rc;
01416
01417 if (cur->Status == 0) {
01418 ctop_int(CTXTc 3,2);
01419 return;
01420 }
01421
01422 rc = SQLFetch(cur->hstmt);
01423
01424 if ((rc == SQL_SUCCESS) || (rc == SQL_SUCCESS_WITH_INFO))
01425 ctop_int(CTXTc 3,0);
01426 else if (rc == SQL_NO_DATA_FOUND){
01427 cur->Status = 1;
01428 ctop_int(CTXTc 3,1);
01429 }
01430 else {
01431 SetCursorClose(cur);
01432 ctop_int(CTXTc 3,2);
01433 }
01434 return;
01435 }
01436
01437
01438
01439
01440
01441
01442
01443
01444
01445
01446
01447
01448
01449
01450
01451 void ODBCConnectOption(CTXTdecl)
01452 {
01453 HDBC hdbc = (HDBC)ptoc_int(CTXTc 2);
01454 int set = ptoc_int(CTXTc 3);
01455 long value = 0;
01456 RETCODE rc;
01457
01458 if (set) {
01459 rc = SQLSetConnectOption(hdbc,(UWORD)ptoc_int(CTXTc 4),(UDWORD)ptoc_int(CTXTc 5));
01460 } else {
01461 rc = SQLGetConnectOption(hdbc,(UWORD)ptoc_int(CTXTc 4),(PTR)&value);
01462 ctop_int(CTXTc 5,value);
01463 }
01464 if ((rc == SQL_SUCCESS) || (rc == SQL_SUCCESS_WITH_INFO))
01465 ctop_int(CTXTc 6,0);
01466 else ctop_int(CTXTc 6,PrintErrorMsg(NULL));
01467 }
01468
01469
01470
01471 Cell build_codes_list(CTXTdeclc char *charptr) {
01472 int len = strlen(charptr);
01473
01474 if (len == 0) {
01475 return makenil;
01476 } else {
01477 CPtr this_term, prev_tail;
01478 check_glstack_overflow(4,pcreg,2*sizeof(Cell)*len);
01479 this_term = hreg;
01480 cell(hreg++) = makeint((int)*charptr); charptr++;
01481 prev_tail = hreg++;
01482 while (*charptr != 0) {
01483 cell(prev_tail) = makelist(hreg);
01484 cell(hreg++) = makeint((int)*charptr); charptr++;
01485 prev_tail = hreg++;
01486 }
01487 cell(prev_tail) = makenil;
01488 return makelist(this_term);
01489 }
01490 }
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502
01503 int GetColumn(CTXTdecl)
01504 {
01505 struct Cursor *cur = (struct Cursor *)ptoc_int(CTXTc 2);
01506 int ColCurNum = ptoc_int(CTXTc 3);
01507 Cell op = ptoc_tag(CTXTc 4);
01508 UDWORD len;
01509 if (ColCurNum < 0 || ColCurNum >= cur->NumCols) {
01510
01511 ctop_int(CTXTc 5,1);
01512 return TRUE;
01513 }
01514 ctop_int(CTXTc 5,0);
01515
01516
01517 if (cur->OutLen[ColCurNum] == SQL_NULL_DATA) {
01518
01519 Cell nullterm = makecs(hreg);
01520 new_heap_functor(hreg,nullFctPsc);
01521 new_heap_free(hreg);
01522 if (isconstr(op) && get_arity(get_str_psc(op)) == 1)
01523
01524 return unify(CTXTc cell(clref_val(op)+1),nullterm);
01525 else return unify(CTXTc op,nullterm);
01526 }
01527
01528
01529
01530 switch (ODBCToXSBType(cur->ColTypes[ColCurNum])) {
01531 case SQL_C_CHAR:
01532
01533 len = ((cur->ColLen[ColCurNum] < cur->OutLen[ColCurNum])?
01534 cur->ColLen[ColCurNum]:cur->OutLen[ColCurNum]);
01535 *(cur->Data[ColCurNum]+len) = '\0';
01536
01537
01538 XSB_Deref(op);
01539 if (isref(op))
01540 return unify(CTXTc op, makestring(string_find(cur->Data[ColCurNum],1)));
01541 if (isconstr(op) && get_arity(get_str_psc(op)) == 1) {
01542 if (!strcmp(get_name(get_str_psc(op)),"string")) {
01543 return unify(CTXTc cell(clref_val(ptoc_tag(CTXTc 4))+1),
01544 build_codes_list(CTXTc cur->Data[ColCurNum]));
01545 } else {
01546 STRFILE strfile;
01547
01548 strfile.strcnt = strlen(cur->Data[ColCurNum]);
01549 if (strfile.strcnt >= MAXVARSTRLEN-1)
01550 xsb_warn("[ODBC] Likely overflow of data in column of PROLOG_TERM type\n");
01551 strfile.strptr = strfile.strbase = cur->Data[ColCurNum];
01552 read_canonical_term(CTXTc NULL,&strfile,2);
01553 return TRUE;
01554 }
01555 }
01556 if (!isstring(op)) return FALSE;
01557 if (strcmp(string_val(op),cur->Data[ColCurNum])) return FALSE;
01558 return TRUE;
01559 case SQL_C_BINARY:
01560
01561 len = ((cur->ColLen[ColCurNum] < cur->OutLen[ColCurNum])?
01562 cur->ColLen[ColCurNum]:cur->OutLen[ColCurNum]);
01563 *(cur->Data[ColCurNum]+len) = '\0';
01564
01565
01566 XSB_Deref(op);
01567 if (isref(op))
01568 return unify(CTXTc op, makestring(string_find(cur->Data[ColCurNum],1)));
01569 if (isconstr(op) && get_arity(get_str_psc(op)) == 1) {
01570 if (!strcmp(get_name(get_str_psc(op)),"string")) {
01571 return unify(CTXTc cell(clref_val(ptoc_tag(CTXTc 4))+1),
01572 build_codes_list(CTXTc cur->Data[ColCurNum]));
01573 } else {
01574 STRFILE strfile;
01575
01576 strfile.strcnt = strlen(cur->Data[ColCurNum]);
01577 strfile.strptr = strfile.strbase = cur->Data[ColCurNum];
01578 read_canonical_term(CTXTc NULL,&strfile,2);
01579 return TRUE;
01580 }
01581 }
01582 if (!isstring(op)) return FALSE;
01583 if (strcmp(string_val(op),cur->Data[ColCurNum])) return FALSE;
01584 return TRUE;
01585 case SQL_C_SLONG:
01586 return unify(CTXTc op,makeint(*(long *)(cur->Data[ColCurNum])));
01587 case SQL_C_FLOAT:
01588 return unify(CTXTc op,makefloat(*(float *)(cur->Data[ColCurNum])));
01589 }
01590 return FALSE;
01591 }
01592
01593
01594
01595
01596
01597
01598
01599
01600
01601
01602
01603
01604
01605
01606
01607
01608
01609 void ODBCGetInfo(CTXTdecl)
01610 {
01611 HDBC hdbc = (HDBC) ptoc_int(CTXTc 2);
01612 SQLRETURN sqlrc = SQL_SUCCESS;
01613
01614 SQLCHAR strValue[50];
01615 SQLUSMALLINT supported;
01616 SQLRETURN retcode;
01617 SQLINTEGER nValue;
01618 SQLSMALLINT pcbValue;
01619
01620 short int InfoType = ptoc_int(CTXTc 3);
01621 short int InfoTypeType = GetInfoTypeType(InfoType);
01622
01623
01624 sqlrc = SQLGetFunctions(hdbc, SQL_API_SQLGETINFO, &supported);
01625
01626 if (supported == SQL_TRUE)
01627 {
01628 switch(InfoTypeType) {
01629 case 0:
01630 retcode = SQLGetInfo(hdbc, InfoType, strValue, 50, &pcbValue);
01631 if(retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO)
01632 {
01633
01634 ctop_string(CTXTc 4,string_find(strValue,1));
01635 ctop_int(CTXTc 5,0);
01636 } else {
01637 ctop_int(CTXTc 5,1);
01638 }
01639 break;
01640 case 1:
01641 case 2:
01642 case 3:
01643 case 4:
01644 retcode = SQLGetInfo(hdbc, InfoType, &nValue, 0, &pcbValue);
01645 if(retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO)
01646 {
01647
01648 ctop_int(CTXTc 4,nValue);
01649 ctop_int(CTXTc 5,0);
01650 } else {
01651 ctop_int(CTXTc 5,1);
01652 }
01653 break;
01654 case -1:
01655 default:
01656 ctop_int(CTXTc 5, -1);
01657 break;
01658 }
01659 } else {
01660 ctop_int(CTXTc 5,-2);
01661 }
01662 }
01663
01664
01665
01666
01667
01668
01669
01670
01671
01672
01673
01674
01675
01676
01677 void ODBCRowCount(CTXTdecl) {
01678 struct Cursor *cur = (struct Cursor *)ptoc_int(CTXTc 2);
01679 SQLINTEGER count;
01680 RETCODE rc;
01681
01682 rc = SQLRowCount(cur->hstmt, &count);
01683 if ((rc != SQL_SUCCESS) && (rc != SQL_SUCCESS_WITH_INFO)) {
01684 ctop_int(CTXTc 3, 0);
01685 ctop_int(CTXTc 4, PrintErrorMsg(cur));
01686 return;
01687 }
01688
01689 ctop_int(CTXTc 3,count);
01690 ctop_int(CTXTc 4,0);
01691 return;
01692 }