odbc_driver.c

00001 /* File: odbc_driver.c
00002 ** Author: Saikat Mukherjee
00003 ** Contact:   xsb-contact@cs.sunysb.edu
00004 ** 
00005 ** Copyright (C) The Research Foundation of SUNY, 2002-2006
00006 ** 
00007 ** XSB is free software; you can redistribute it and/or modify it under the
00008 ** terms of the GNU Library General Public License as published by the Free
00009 ** Software Foundation; either version 2 of the License, or (at your option)
00010 ** any later version.
00011 ** 
00012 ** XSB is distributed in the hope that it will be useful, but WITHOUT ANY
00013 ** WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00014 ** FOR A PARTICULAR PURPOSE.  See the GNU Library General Public License for
00015 ** more details.
00016 ** 
00017 ** You should have received a copy of the GNU Library General Public License
00018 ** along with XSB; if not, write to the Free Software Foundation,
00019 ** Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00020 **
00021 */
00022 
00023 /*
00024 ** This is the ODBC driver for connecting to a database.
00025 */
00026 
00027 #include "xsb_config.h"
00028 
00029 #ifdef WIN_NT
00030 #include <windows.h>
00031 #endif
00032 
00033 #ifdef WIN_NT
00034 #define XSB_DLL
00035 #endif
00036 
00037 #include "odbc_driver_defs.h"
00038 
00039 static int driverODBC_getXSBType(SQLSMALLINT dataType);
00040 static void driverODBC_error(SQLSMALLINT handleType, SQLHANDLE handle);
00041 static struct xsb_data** driverODBC_getNextRow(struct driverODBC_queryInfo* query, int direct);
00042 
00043 struct driverODBC_connectionInfo* odbcHandles[MAX_HANDLES];
00044 struct driverODBC_queryInfo* odbcQueries[MAX_QUERIES];
00045 int numHandles, numQueries;
00046 SQLCHAR* errorMesg;
00047 SQLHENV henv;
00048 
00049 DllExport int call_conv driverODBC_initialise()
00050 {
00051   numHandles = numQueries = 0;
00052   errorMesg = NULL;
00053 
00054   return TRUE;
00055 }
00056 
00057 
00058 int driverODBC_connect(struct xsb_connectionHandle* handle)
00059 {
00060   struct driverODBC_connectionInfo* odbcHandle;
00061   SQLRETURN val;
00062 
00063   odbcHandle = (struct driverODBC_connectionInfo *)malloc(sizeof(struct driverODBC_connectionInfo));
00064 
00065   val = SQLAllocEnv(&henv);
00066   if (val != SQL_SUCCESS && val != SQL_SUCCESS_WITH_INFO) {
00067     errorMesg = (SQLCHAR *) "HENV allocation error\n";
00068     return FAILURE;
00069   }
00070 
00071   val = SQLAllocConnect(henv, &(odbcHandle->hdbc));
00072   if (val != SQL_SUCCESS && val != SQL_SUCCESS_WITH_INFO) {
00073     driverODBC_error(SQL_HANDLE_ENV, henv);
00074     free(odbcHandle);
00075     return FAILURE;
00076   }
00077         
00078   val = (SQLRETURN) SQLConnect(odbcHandle->hdbc,
00079                                (SQLCHAR *) handle->dsn,
00080                                SQL_NTS, (SQLCHAR *) handle->user,
00081                                SQL_NTS, (SQLCHAR *) handle->password,
00082                                SQL_NTS);
00083   if (val != SQL_SUCCESS && val != SQL_SUCCESS_WITH_INFO) {
00084     driverODBC_error(SQL_HANDLE_DBC, (SQLCHAR *) odbcHandle->hdbc);
00085     val = SQLFreeHandle(SQL_HANDLE_DBC, odbcHandle->hdbc);
00086     if (val != SQL_SUCCESS && val != SQL_SUCCESS_WITH_INFO)
00087       driverODBC_error(SQL_HANDLE_DBC, odbcHandle->hdbc);
00088     free(odbcHandle);
00089     return FAILURE;
00090   }
00091         
00092   odbcHandle->handle =
00093     (char *)malloc((strlen(handle->handle) + 1) * sizeof(char));
00094   strcpy(odbcHandle->handle, handle->handle);
00095   odbcHandles[numHandles++] = odbcHandle;
00096         
00097   return SUCCESS;
00098 }
00099 
00100 
00101 int driverODBC_disconnect(struct xsb_connectionHandle* handle)
00102 {
00103   SQLRETURN val;
00104   int i, j;
00105 
00106   for (i = 0 ; i < numHandles ; i++) {
00107     if (!strcmp(odbcHandles[i]->handle, handle->handle)) {
00108       val = SQLDisconnect(odbcHandles[i]->hdbc);
00109       if (val != SQL_SUCCESS && val != SQL_SUCCESS_WITH_INFO) {
00110         driverODBC_error(SQL_HANDLE_DBC, odbcHandles[i]->hdbc);
00111         return FAILURE;
00112       }
00113         
00114       val = SQLFreeHandle(SQL_HANDLE_DBC, odbcHandles[i]->hdbc);
00115       if (val != SQL_SUCCESS && val != SQL_SUCCESS_WITH_INFO) {
00116         driverODBC_error(SQL_HANDLE_DBC, odbcHandles[i]->hdbc);
00117         return FAILURE;
00118       }
00119                         
00120       free(odbcHandles[i]->handle);                     
00121       free(odbcHandles[i]);
00122                         
00123       for (j = i + 1 ; j < numHandles ; j++)
00124         odbcHandles[j-1] = odbcHandles[j];
00125       odbcHandles[numHandles-1] = NULL;
00126       numHandles--;
00127       break;
00128     }
00129   }
00130         
00131   return SUCCESS;
00132 }
00133 
00134 
00135 struct xsb_data** driverODBC_query(struct xsb_queryHandle* handle)
00136 {
00137   struct driverODBC_queryInfo* query;
00138   SQLHDBC hdbc;
00139   SQLRETURN val;
00140   int i;
00141 
00142   query = NULL;
00143   hdbc = NULL;
00144   if (handle->state == QUERY_RETRIEVE) {
00145       for (i = 0 ; i < numQueries ; i++) {
00146         if (!strcmp(odbcQueries[i]->handle, handle->handle)) {
00147           query = odbcQueries[i];
00148           break;
00149         }
00150       }
00151   }
00152   else if (handle->state == QUERY_BEGIN) {
00153     for (i = 0 ; i < numHandles ; i++) {
00154       if (!strcmp(odbcHandles[i]->handle, handle->connHandle->handle)) {
00155         hdbc = odbcHandles[i]->hdbc;
00156         break;
00157       }
00158     }
00159         
00160     query = (struct driverODBC_queryInfo *)malloc(sizeof(struct driverODBC_queryInfo));
00161     query->handle = (char *)malloc((strlen(handle->handle) + 1) * sizeof(char));
00162     strcpy(query->handle, handle->handle);
00163     query->query = (char *)malloc((strlen(handle->query) + 1) * sizeof(char));
00164     strcpy(query->query, handle->query);
00165 
00166     val = SQLAllocStmt(hdbc, &(query->hstmt));
00167     if (val != SQL_SUCCESS && val != SQL_SUCCESS_WITH_INFO) {
00168       driverODBC_error(SQL_HANDLE_DBC, hdbc);
00169       return NULL;
00170     }
00171                 
00172     val = SQLExecDirect(query->hstmt, (SQLCHAR *) handle->query, SQL_NTS);
00173     if (val != SQL_SUCCESS && val != SQL_SUCCESS_WITH_INFO) {
00174       driverODBC_error(SQL_HANDLE_STMT, query->hstmt);
00175       return NULL;
00176     }
00177 
00178     query->resultmeta = (struct driverODBC_meta *)malloc(sizeof(struct driverODBC_meta));
00179     val = SQLNumResultCols(query->hstmt, (SQLSMALLINT *)(&(query->resultmeta->numCols)));
00180     if (val != SQL_SUCCESS && val != SQL_SUCCESS_WITH_INFO) {
00181       driverODBC_error(SQL_HANDLE_STMT, query->hstmt);
00182       return NULL;
00183     }
00184     handle->numResultCols = query->resultmeta->numCols;
00185     if (query->resultmeta->numCols == 0) {
00186       return NULL;
00187     }
00188 
00189     query->resultmeta->types = (struct driverODBC_columnmeta **)malloc(query->resultmeta->numCols * sizeof(struct driverODBC_columnmeta *));
00190     for (i = 0 ; i < query->resultmeta->numCols ; i++) {
00191       query->resultmeta->types[i] = (struct driverODBC_columnmeta *)malloc(sizeof(struct driverODBC_columnmeta));
00192       val = SQLColAttribute(query->hstmt, (SQLUSMALLINT) (i + 1), SQL_COLUMN_TYPE, NULL, 0, NULL, (SQLPOINTER) &(query->resultmeta->types[i]->type));
00193       if (val != SQL_SUCCESS && val != SQL_SUCCESS_WITH_INFO) {
00194         driverODBC_error(SQL_HANDLE_STMT, query->hstmt);
00195         return NULL;
00196       }
00197       val = SQLColAttribute(query->hstmt, (SQLUSMALLINT) (i + 1), SQL_COLUMN_LENGTH, NULL, 0, NULL, (SQLPOINTER) &(query->resultmeta->types[i]->length));
00198       if (val != SQL_SUCCESS && val != SQL_SUCCESS_WITH_INFO) {
00199         driverODBC_error(SQL_HANDLE_STMT, query->hstmt);
00200         return NULL;
00201       }
00202     }
00203         
00204     handle->state = QUERY_RETRIEVE;
00205     odbcQueries[numQueries++] = query;
00206   }
00207         
00208   return driverODBC_getNextRow(query, 1);
00209 }
00210 
00211 
00212 static struct xsb_data** driverODBC_getNextRow(struct driverODBC_queryInfo* query, int direct)
00213 {
00214   struct xsb_data** result;
00215   SQLINTEGER** pcbValues;
00216   SQLRETURN val;
00217   int i;
00218 
00219   result = (struct xsb_data **)malloc(query->resultmeta->numCols * sizeof(struct xsb_data *));
00220   pcbValues = (SQLINTEGER **)malloc(query->resultmeta->numCols * sizeof(SQLINTEGER *));
00221   for (i = 0 ; i < query->resultmeta->numCols ; i++) {
00222     result[i] = (struct xsb_data *)malloc(sizeof(struct xsb_data));
00223     result[i]->val = (union xsb_value *)malloc(sizeof(union xsb_value));
00224     pcbValues[i] = (SQLINTEGER *)malloc(sizeof(SQLINTEGER));
00225     if (driverODBC_getXSBType(query->resultmeta->types[i]->type) == STRING_TYPE) {
00226       result[i]->type = STRING_TYPE;
00227       result[i]->length = query->resultmeta->types[i]->length + 1;
00228       result[i]->val->str_val = (char *)malloc(result[i]->length * sizeof(char));
00229       val = SQLBindCol(query->hstmt, (SQLUSMALLINT) (i + 1), SQL_C_CHAR, (SQLPOINTER *)result[i]->val->str_val, (SQLINTEGER)result[i]->length, pcbValues[i]);
00230       if (val != SQL_SUCCESS && val != SQL_SUCCESS_WITH_INFO) {
00231         driverODBC_error(SQL_HANDLE_STMT, query->hstmt);
00232         return NULL;
00233       }
00234     }
00235     else if (driverODBC_getXSBType(query->resultmeta->types[i]->type) == INT_TYPE) {
00236       result[i]->type = INT_TYPE;
00237       result[i]->val->i_val = (int *)malloc(sizeof(int));
00238       val = SQLBindCol(query->hstmt, (SQLUSMALLINT) (i + 1), SQL_C_SLONG, (SQLPOINTER *)result[i]->val->i_val, 0, pcbValues[i]);
00239       if (val != SQL_SUCCESS && val != SQL_SUCCESS_WITH_INFO) {
00240         driverODBC_error(SQL_HANDLE_STMT, query->hstmt);
00241         return NULL;
00242       }
00243     }
00244     else if (driverODBC_getXSBType(query->resultmeta->types[i]->type) == FLOAT_TYPE) {
00245       result[i]->type = FLOAT_TYPE;
00246       result[i]->val->f_val = (double *)malloc(sizeof(double));
00247       val = SQLBindCol(query->hstmt, (SQLUSMALLINT) (i + 1), SQL_C_DOUBLE, (SQLPOINTER *)result[i]->val->f_val, 0, pcbValues[i]);
00248       if (val != SQL_SUCCESS && val != SQL_SUCCESS_WITH_INFO) {
00249         driverODBC_error(SQL_HANDLE_STMT, query->hstmt);
00250         return NULL;
00251       }
00252     }
00253   }
00254 
00255   val = SQLFetch(query->hstmt);
00256 
00257   if (val == SQL_SUCCESS || val == SQL_SUCCESS_WITH_INFO) {
00258       for (i = 0 ; i < query->resultmeta->numCols ; i++) {
00259         if (*(pcbValues[i]) == SQL_NULL_DATA)
00260           result[i]->val = NULL;
00261       }
00262   }
00263 
00264   if (val != SQL_SUCCESS && val != SQL_SUCCESS_WITH_INFO) {
00265     if (direct != 1) {
00266       val = SQLFreeStmt(query->hstmt, SQL_CLOSE);
00267       if (val != SQL_SUCCESS && val != SQL_SUCCESS_WITH_INFO)
00268         driverODBC_error(SQL_HANDLE_STMT, query->hstmt);
00269     }
00270     return NULL;
00271   }
00272 
00273   if (val != SQL_SUCCESS && val != SQL_NO_DATA && val != SQL_SUCCESS_WITH_INFO) {
00274     driverODBC_error(SQL_HANDLE_STMT, query->hstmt);
00275     return NULL;
00276   }     
00277         
00278   return result;
00279 }
00280 
00281 
00282 int driverODBC_prepareStatement(struct xsb_queryHandle* qHandle)
00283 {
00284   struct driverODBC_queryInfo* query;
00285   SQLRETURN val;
00286   SQLHDBC hdbc;
00287   int i;
00288         
00289   hdbc = NULL;
00290 
00291   query = (struct driverODBC_queryInfo *)malloc(sizeof(struct driverODBC_queryInfo));
00292   query->handle = (char *)malloc((strlen(qHandle->handle) + 1) * sizeof(char));
00293   strcpy(query->handle, qHandle->handle);
00294   query->query = (char *)malloc((strlen(qHandle->query) + 1) * sizeof(char));
00295   strcpy(query->query, qHandle->query);
00296 
00297   for (i = 0 ; i < numHandles ; i++) {
00298     if (!strcmp(qHandle->connHandle->handle, odbcHandles[i]->handle)) {
00299       hdbc = odbcHandles[i]->hdbc;
00300       break;
00301     }
00302   }
00303         
00304   val = SQLAllocStmt(hdbc, &(query->hstmt));
00305   if (val != SQL_SUCCESS && val != SQL_SUCCESS_WITH_INFO) {
00306     driverODBC_error(SQL_HANDLE_DBC, hdbc);
00307     return FAILURE;
00308   }
00309 
00310   val = SQLPrepare(query->hstmt, (SQLCHAR *) query->query, SQL_NTS);
00311   if (val != SQL_SUCCESS && val != SQL_SUCCESS_WITH_INFO) {
00312     driverODBC_error(SQL_HANDLE_STMT, query->hstmt);
00313     return FAILURE;
00314   }
00315 
00316   query->parammeta = (struct driverODBC_meta *)malloc(sizeof(struct driverODBC_meta));
00317   val = SQLNumParams(query->hstmt, &(query->parammeta->numCols));
00318   if (val != SQL_SUCCESS && val != SQL_SUCCESS_WITH_INFO) {
00319     driverODBC_error(SQL_HANDLE_STMT, query->hstmt);
00320     return FAILURE;
00321   }
00322 
00323   query->parammeta->types = (struct driverODBC_columnmeta **)malloc(query->parammeta->numCols * sizeof(struct driverODBC_columnmeta));
00324   for (i = 0 ; i < query->parammeta->numCols ; i++) {
00325     query->parammeta->types[i] = (struct driverODBC_columnmeta *)malloc(sizeof(struct driverODBC_columnmeta));
00326     val = SQLDescribeParam(query->hstmt, (SQLUSMALLINT) (i + 1), &(query->parammeta->types[i]->type), &(query->parammeta->types[i]->length), NULL, NULL);
00327     if (val != SQL_SUCCESS && val != SQL_SUCCESS_WITH_INFO) {
00328       driverODBC_error(SQL_HANDLE_STMT, query->hstmt);
00329       return FAILURE;
00330     }
00331   }
00332         
00333   odbcQueries[numQueries++] = query;
00334         
00335   return query->parammeta->numCols;
00336 }
00337 
00338 
00339 struct xsb_data** driverODBC_execPrepareStatement(struct xsb_data** param, struct xsb_queryHandle* handle)
00340 {
00341   struct driverODBC_queryInfo* query;
00342   SQLRETURN val;
00343   int i;
00344 
00345   val = 0;
00346   query = NULL;
00347   for (i = 0 ; i < numQueries ; i++) {
00348     if (!strcmp(odbcQueries[i]->handle, handle->handle)) {
00349       query = odbcQueries[i];
00350       break;
00351     }
00352   }
00353         
00354   if (handle->state == QUERY_RETRIEVE)
00355     return driverODBC_getNextRow(query, 0);
00356         
00357   for (i = 0 ; i < query->parammeta->numCols ; i++) {
00358     if (param[i]->type == STRING_TYPE) 
00359       val = SQLBindParameter(query->hstmt, (SQLUSMALLINT)(i + 1), SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(param[i]->val->str_val) + 1, 0, (SQLPOINTER)param[i]->val->str_val, 0, NULL);
00360     else if (param[i]->type == INT_TYPE)
00361       val = SQLBindParameter(query->hstmt, (SQLUSMALLINT)(i + 1), SQL_PARAM_INPUT, SQL_C_DEFAULT, SQL_INTEGER, 0, 0, (SQLPOINTER)param[i]->val->i_val, 0, NULL);
00362     else if (param[i]->type == FLOAT_TYPE)      
00363       val = SQLBindParameter(query->hstmt, (SQLUSMALLINT) (i + 1), SQL_PARAM_INPUT, SQL_C_DEFAULT, SQL_DOUBLE, 0, 0, (SQLPOINTER)param[i]->val->f_val, 0, NULL);
00364     if (val != SQL_SUCCESS && val != SQL_SUCCESS_WITH_INFO) {
00365       driverODBC_error(SQL_HANDLE_STMT, query->hstmt);
00366       return NULL;
00367     }
00368   }
00369         
00370   val = SQLExecute(query->hstmt);
00371   if (val != SQL_SUCCESS && val != SQL_SUCCESS_WITH_INFO) {
00372     driverODBC_error(SQL_HANDLE_STMT, query->hstmt);
00373     return NULL;
00374   }
00375 
00376   query->resultmeta = (struct driverODBC_meta *)malloc(sizeof(struct driverODBC_meta));
00377   val = SQLNumResultCols(query->hstmt, (SQLSMALLINT *)(&(query->resultmeta->numCols)));
00378   if (val != SQL_SUCCESS && val != SQL_SUCCESS_WITH_INFO) {
00379     driverODBC_error(SQL_HANDLE_STMT, query->hstmt);
00380     return NULL;
00381   }
00382   handle->numResultCols = query->resultmeta->numCols;
00383   if (query->resultmeta->numCols == 0) {
00384     return NULL;
00385   }
00386 
00387   query->resultmeta->types = (struct driverODBC_columnmeta **)malloc(query->resultmeta->numCols * sizeof(struct driverODBC_columnmeta *));
00388   for (i = 0 ; i < query->resultmeta->numCols ; i++) {
00389     query->resultmeta->types[i] = (struct driverODBC_columnmeta *)malloc(sizeof(struct driverODBC_columnmeta));
00390     val = SQLColAttribute(query->hstmt, (SQLUSMALLINT) (i + 1), SQL_COLUMN_TYPE, NULL, 0, NULL, (SQLPOINTER) &(query->resultmeta->types[i]->type));
00391     if (val != SQL_SUCCESS && val != SQL_SUCCESS_WITH_INFO) {
00392       driverODBC_error(SQL_HANDLE_STMT, query->hstmt);
00393       return NULL;
00394     }
00395     val = SQLColAttribute(query->hstmt, (SQLUSMALLINT) (i + 1), SQL_COLUMN_LENGTH, NULL, 0, NULL, (SQLPOINTER) &(query->resultmeta->types[i]->length));
00396     if (val != SQL_SUCCESS && val != SQL_SUCCESS_WITH_INFO) {
00397       driverODBC_error(SQL_HANDLE_STMT, query->hstmt);
00398       return NULL;
00399     }
00400   }
00401 
00402   handle->state = QUERY_RETRIEVE;
00403 
00404   return driverODBC_getNextRow(query, 0);
00405 }
00406 
00407 
00408 int driverODBC_closeStatement(struct xsb_queryHandle* handle)
00409 {
00410   struct driverODBC_queryInfo* query;
00411   SQLRETURN val;
00412   int i, j;
00413 
00414   for (i = 0 ; i < numQueries ; i++) {
00415     if (!strcmp(odbcQueries[i]->handle, handle->handle)) {
00416       query = odbcQueries[i];
00417       for (j = 0 ; j < query->resultmeta->numCols ; j++)
00418         free(query->resultmeta->types[j]);
00419       free(query->resultmeta->types);
00420       free(query->resultmeta);
00421       val = SQLFreeHandle(SQL_HANDLE_STMT, query->hstmt);
00422       if (val != SQL_SUCCESS && val != SQL_SUCCESS_WITH_INFO) {
00423         driverODBC_error(SQL_HANDLE_STMT, query->hstmt);
00424         return FAILURE;
00425       }
00426       for (j = i + 1 ; j < numQueries ; j++)
00427         odbcQueries[j-1] = odbcQueries[j];
00428       free(query->handle);
00429       free(query->query);
00430       free(query);
00431       numQueries--;
00432     }
00433   }
00434 
00435   return SUCCESS;
00436 }
00437 
00438 
00439 char* driverODBC_errorMesg()
00440 {
00441   char* temp;
00442   if (errorMesg != NULL) {
00443     temp = (char *)malloc(SQL_MAX_MESSAGE_LENGTH * sizeof(char));
00444     strcpy(temp, (char *)errorMesg);
00445     free(errorMesg);
00446     errorMesg = NULL;
00447     return temp;
00448   }
00449   return NULL;
00450 }
00451 
00452 
00453 static int driverODBC_getXSBType(SQLSMALLINT dataType)
00454 {
00455   int type;
00456   type = STRING_TYPE;
00457   switch (dataType) {
00458   case SQL_CHAR:
00459   case SQL_VARCHAR:
00460   case SQL_LONGVARCHAR:
00461     type = STRING_TYPE;
00462     break;
00463 
00464   case SQL_DECIMAL:
00465   case SQL_NUMERIC:
00466   case SQL_REAL:    
00467   case SQL_DOUBLE:
00468     type = FLOAT_TYPE;
00469     break;
00470 
00471   case SQL_SMALLINT:
00472   case SQL_INTEGER:
00473   case SQL_TINYINT:
00474   case SQL_BIGINT:
00475     type = INT_TYPE;
00476     break;
00477   }
00478 
00479   return type;
00480 }
00481 
00482 
00483 static void driverODBC_error(SQLSMALLINT handleType, SQLHANDLE handle)
00484 {
00485   SQLCHAR* sqlState;
00486         
00487   if (errorMesg != NULL) {
00488     free(errorMesg);
00489     errorMesg = NULL;
00490   }
00491 
00492   errorMesg = (SQLCHAR *)malloc(SQL_MAX_MESSAGE_LENGTH * sizeof(SQLCHAR));
00493   sqlState = (SQLCHAR *)malloc(6 * sizeof(SQLCHAR));
00494   SQLGetDiagRec(handleType, handle, 1, sqlState, NULL, errorMesg, SQL_MAX_MESSAGE_LENGTH - 1, NULL);
00495   free(sqlState);
00496 }
00497 
00498 
00499 DllExport int call_conv driverODBC_register(void)
00500 {
00501   union functionPtrs* funcConnect;
00502   union functionPtrs* funcDisconnect;
00503   union functionPtrs* funcQuery;
00504   union functionPtrs* funcPrepare;
00505   union functionPtrs* funcExecPrepare;
00506   union functionPtrs* funcCloseStmt;
00507   union functionPtrs* funcErrorMesg;
00508 
00509   registerXSBDriver("odbc", 7);
00510 
00511   funcConnect = (union functionPtrs *)malloc(sizeof(union functionPtrs));
00512   funcConnect->connectDriver = driverODBC_connect;
00513   registerXSBFunction("odbc", CONNECT, funcConnect);
00514 
00515   funcDisconnect = (union functionPtrs *)malloc(sizeof(union functionPtrs));
00516   funcDisconnect->disconnectDriver = driverODBC_disconnect;
00517   registerXSBFunction("odbc", DISCONNECT, funcDisconnect);
00518 
00519   funcQuery = (union functionPtrs *)malloc(sizeof(union functionPtrs));
00520   funcQuery->queryDriver = driverODBC_query;
00521   registerXSBFunction("odbc", QUERY, funcQuery);
00522 
00523   funcPrepare = (union functionPtrs *)malloc(sizeof(union functionPtrs));
00524   funcPrepare->prepareStmtDriver = driverODBC_prepareStatement;
00525   registerXSBFunction("odbc", PREPARE, funcPrepare);
00526         
00527   funcExecPrepare = (union functionPtrs *)malloc(sizeof(union functionPtrs));
00528   funcExecPrepare->executeStmtDriver = driverODBC_execPrepareStatement;
00529   registerXSBFunction("odbc", EXEC_PREPARE, funcExecPrepare);
00530 
00531   funcCloseStmt = (union functionPtrs *)malloc(sizeof(union functionPtrs));
00532   funcCloseStmt->closeStmtDriver = driverODBC_closeStatement;
00533   registerXSBFunction("odbc", CLOSE_STMT, funcCloseStmt);
00534 
00535   funcErrorMesg = (union functionPtrs *)malloc(sizeof(union functionPtrs));
00536   funcErrorMesg->errorMesgDriver = driverODBC_errorMesg;
00537   registerXSBFunction("odbc", ERROR_MESG, funcErrorMesg);
00538 
00539   return TRUE;
00540 }
00541 
00542 

Generated on Wed Jul 26 13:30:44 2006 for XSB by  doxygen 1.4.5