driver_manager.c

00001 /* File: driver_manager.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 file is the  middle layer for the interface to the drivers. 
00025 ** This gets called from db_interface.P and in turn calls functions in
00026 ** driver specific C files which are in the packages/dbdrivers/xxx/cc directory.
00027 */
00028 
00029 #include <stdio.h>
00030 #include <stdlib.h>
00031 #include <string.h>
00032 
00033 #include "xsb_config.h"
00034 #include "cell_xsb.h"
00035 
00036 #ifdef WIN_NT
00037 #define XSB_DLL
00038 #endif
00039 
00040 #include "cinterf.h"
00041 #include "io_builtins_xsb.h"
00042 #include "driver_manager_defs.h"
00043 
00044 static struct xsb_connectionHandle* isConnectionHandle(char* handle);
00045 static struct xsb_queryHandle* isQueryHandle(char* handle);
00046 static char* buildSQLQuery(prolog_term sqlQueryList);
00047 static union functionPtrs* getDriverFunction(char* driver, int type);
00048 static int bindReturnList(prolog_term returnList, struct xsb_data** result, struct xsb_queryHandle*);
00049 static void freeQueryHandle(struct xsb_queryHandle* qHandle, int pos);
00050 static void freeConnectionHandle(struct xsb_connectionHandle* cHandle, int pos);
00051 static int closeQueryHandle(char* queryHandle);
00052 
00053 struct xsb_connectionHandle* CHandles[MAX_CONNECTIONS];
00054 struct xsb_queryHandle* QHandles[MAX_QUERIES];
00055 struct driver* DBdrivers[MAX_DRIVERS];
00056 int numDrivers, numCHandles, numQHandles;
00057 char* errorMesg;
00058 char* errorNumber;
00059 
00060 
00061 DllExport int call_conv initialise(void)
00062 {
00063   numDrivers = numCHandles = numQHandles = 0;
00064   errorMesg = NULL;
00065   errorNumber = NULL;
00066   return TRUE;
00067 }
00068 
00069 
00070 DllExport int call_conv openConnection(void)
00071 {
00072   int (*connectDriver)(struct xsb_connectionHandle*);
00073   char* (*errorMesgDriver)();
00074   struct xsb_connectionHandle* cHandle;
00075   char *handle, *driver, *server, *database=NULL, *user, *password, *dsn;
00076   int val;
00077 
00078   handle = ptoc_string(1);
00079   driver = ptoc_string(2);
00080   server = ptoc_string(3);
00081   if (strlen(server) == 0)
00082     dsn = ptoc_string(4);
00083   else
00084     database = ptoc_string(4);
00085   user = ptoc_string(5);
00086   password = ptoc_string(6);
00087 
00088   if (isConnectionHandle(handle) != NULL) {
00089     errorMesg = "XSB_DBI ERROR: Connection handle already exists";
00090     errorNumber = "XSB_DBI_006";
00091     return FALSE;
00092   }
00093 
00094   if (getDriverFunction(driver, CONNECT) != NULL)
00095     connectDriver = getDriverFunction(driver, CONNECT)->connectDriver;
00096   else
00097     return FALSE;
00098 
00099   cHandle = (struct xsb_connectionHandle *)malloc(sizeof(struct xsb_connectionHandle));
00100   cHandle->handle = (char *)malloc((strlen(handle) + 1) * sizeof(char));
00101   strcpy(cHandle->handle, handle);
00102   cHandle->driver = (char *)malloc((strlen(driver) + 1) * sizeof(char));
00103   strcpy(cHandle->driver, driver);
00104   if (strlen(server) == 0) {
00105     cHandle->dsn = (char *)malloc((strlen(dsn) + 1) * sizeof(char));
00106     strcpy(cHandle->dsn, dsn);
00107     cHandle->server = NULL;
00108     cHandle->database = NULL;
00109   }
00110   else {
00111     cHandle->server = (char *)malloc((strlen(server) + 1) * sizeof(char));
00112     strcpy(cHandle->server, server);
00113     cHandle->database = (char *)malloc((strlen(database) + 1) * sizeof(char));
00114     strcpy(cHandle->database, database);
00115     cHandle->dsn = NULL;
00116   }
00117   cHandle->user = (char *)malloc((strlen(user) + 1) * sizeof(char));
00118   strcpy(cHandle->user, user);
00119   cHandle->password = (char *)malloc((strlen(password) + 1) * sizeof(char));
00120   strcpy(cHandle->password, password);
00121 
00122   CHandles[numCHandles++] = cHandle;
00123   if ((val = connectDriver(cHandle)) != SUCCESS) {
00124     if (getDriverFunction(cHandle->driver, ERROR_MESG) != NULL)
00125       errorMesgDriver = getDriverFunction(cHandle->driver, ERROR_MESG)->errorMesgDriver;
00126     else
00127       return FALSE;
00128 
00129     errorMesg = errorMesgDriver();
00130     errorNumber = "XSB_DBI_000";
00131     freeConnectionHandle(cHandle, numCHandles - 1);
00132     return FALSE;
00133   }
00134 
00135   return TRUE;
00136 }  
00137 
00138 
00139 DllExport int call_conv closeConnection(void)
00140 {
00141   int (*disconnectDriver)(struct xsb_connectionHandle *);
00142   int (*closeStmtDriver)(struct xsb_queryHandle *);
00143   char* (*errorMesgDriver)();
00144   char* handle;
00145   int val, i, j;
00146 
00147   handle = ptoc_string(1);
00148 
00149   for (i = 0 ; i < numCHandles ; i++) {
00150     if (!strcmp(CHandles[i]->handle, handle)) {
00151       if (getDriverFunction(CHandles[i]->driver, DISCONNECT) != NULL)
00152         disconnectDriver = getDriverFunction(CHandles[i]->driver, DISCONNECT)->disconnectDriver;
00153       else 
00154         return FALSE;
00155 
00156       val = disconnectDriver(CHandles[i]);
00157       
00158       if (val == FAILURE) {
00159         errorMesgDriver = getDriverFunction(CHandles[i]->driver, ERROR_MESG)->errorMesgDriver;
00160         errorMesg = errorMesgDriver();
00161         return FALSE;
00162       }
00163       
00164       for (j = 0 ; j < numQHandles ; j++) {
00165         if (!strcmp(QHandles[j]->connHandle->handle, handle)) {
00166           if (getDriverFunction(CHandles[i]->driver, ERROR_MESG) != NULL)
00167             closeStmtDriver = getDriverFunction(CHandles[i]->driver, ERROR_MESG)->closeStmtDriver;
00168           else
00169             return FALSE;
00170           
00171           val = closeStmtDriver(QHandles[j]);
00172           if (val == FAILURE) {
00173             errorMesgDriver = getDriverFunction(CHandles[i]->driver, ERROR_MESG)->errorMesgDriver;
00174             errorMesg = errorMesgDriver();
00175             return FALSE;
00176           }
00177           freeQueryHandle(QHandles[j], j);
00178           break;
00179         }
00180       }
00181       freeConnectionHandle(CHandles[i], i);
00182       return TRUE;
00183     }
00184   }
00185   
00186   errorMesg = "XSB_DBI ERROR: Connection handle does not exist";
00187   errorNumber = "XSB_DBI_004";
00188   return FALSE;
00189 }
00190 
00191 
00192 DllExport int call_conv queryConnection(void)
00193 {
00194   struct xsb_data** (*queryDriver)(struct xsb_queryHandle*);
00195   char* (*errorMesgDriver)();
00196   prolog_term returnList, sqlQueryList;
00197   struct xsb_connectionHandle* cHandle;
00198   struct xsb_queryHandle* qHandle;
00199   struct xsb_data** result;
00200   char *chandle, *qhandle, *sqlQuery;
00201   int val;
00202 
00203   chandle = ptoc_string(1);
00204   qhandle = ptoc_string(2);
00205   sqlQueryList = reg_term(3);
00206   returnList = reg_term(4);
00207 
00208   result = NULL;
00209 
00210   if ((qHandle = isQueryHandle(qhandle)) != NULL) {
00211     if (strcmp(qHandle->connHandle->handle, chandle)) {
00212       errorMesg = "XSB_DBI ERROR: Query handle already exists";
00213       errorNumber = "XSB_DBI_007";;
00214       return FALSE;
00215     }
00216     
00217     if (getDriverFunction(qHandle->connHandle->driver, QUERY) != NULL) {
00218       queryDriver =
00219         getDriverFunction(qHandle->connHandle->driver, QUERY)->queryDriver;
00220     }
00221     else {
00222       return FALSE;
00223     }
00224     
00225     sqlQuery = buildSQLQuery(sqlQueryList);
00226     if (strcmp(qHandle->query, sqlQuery)) {
00227       errorMesg =
00228         "XSB DBI ERROR: Same query handle used for different queries";
00229       errorNumber = "XSB_DBI_010";
00230       return FALSE;
00231     }
00232 
00233     result = queryDriver(qHandle);
00234     if (result == NULL && qHandle->state == QUERY_RETRIEVE) {
00235       closeQueryHandle(qhandle);
00236     }
00237   }
00238   else if ((cHandle = isConnectionHandle(chandle)) != NULL) {
00239     sqlQuery = buildSQLQuery(sqlQueryList);
00240     qHandle = (struct xsb_queryHandle *)malloc(sizeof(struct xsb_queryHandle));
00241     qHandle->handle = (char *)malloc((strlen(qhandle) + 1) * sizeof(char));
00242     strcpy(qHandle->handle, qhandle);
00243     qHandle->connHandle = cHandle;
00244     qHandle->query = (char *)malloc((strlen(sqlQuery) + 1) * sizeof(char));
00245     strcpy(qHandle->query, sqlQuery);
00246     qHandle->state = QUERY_BEGIN;
00247     QHandles[numQHandles++] = qHandle;
00248 
00249     if (getDriverFunction(qHandle->connHandle->driver, QUERY) != NULL)
00250       queryDriver = getDriverFunction(qHandle->connHandle->driver, QUERY)->queryDriver;
00251     else
00252       return FALSE;
00253 
00254     result = queryDriver(qHandle);
00255   }
00256   else {
00257     errorMesg = "XSB_DBI ERROR: Connection handle does not exist";
00258     errorNumber = "XSB_DBI_004";
00259     return FALSE;               
00260   }
00261 
00262   if (result == NULL) {
00263     closeQueryHandle(qhandle);
00264   }
00265   
00266   val = bindReturnList(returnList, result, qHandle);
00267   if (val == TOO_MANY_RETURN_COLS || val == TOO_FEW_RETURN_COLS || val == INVALID_RETURN_LIST)
00268     return FALSE;
00269 
00270   if ((cHandle = isConnectionHandle(chandle)) != NULL) {
00271     if (getDriverFunction(cHandle->driver, ERROR_MESG) != NULL)
00272       errorMesgDriver =
00273         getDriverFunction(cHandle->driver, ERROR_MESG)->errorMesgDriver;
00274     else 
00275       return FALSE;
00276     
00277     errorMesg = errorMesgDriver();
00278     errorNumber = "XSB_DBI_000";
00279   }
00280 
00281   if (errorMesg == NULL && val == RESULT_NONEMPTY_OR_NOT_REQUESTED)
00282     return TRUE;
00283   else
00284     return FALSE;
00285 }
00286 
00287 DllExport int call_conv prepareStatement(void)
00288 {
00289   int (*prepareStmtDriver)(struct xsb_queryHandle*);
00290   char* (*errorMesgDriver)();
00291   prolog_term sqlQueryList;
00292   char *chandle, *qhandle, *sqlQuery;
00293   struct xsb_queryHandle* qHandle;
00294   struct xsb_connectionHandle* cHandle;
00295   int val;
00296   
00297   chandle = ptoc_string(1);
00298   qhandle = ptoc_string(2);
00299   sqlQueryList = reg_term(3);
00300   
00301   if ((cHandle = isConnectionHandle(chandle)) == NULL) {
00302     errorMesg = "XSB_DBI ERROR: Connection handle does not exist";
00303     errorNumber = "XSB_DBI_004";
00304     return FALSE;
00305   }
00306   
00307   if ((qHandle = isQueryHandle(qhandle)) != NULL) {
00308     errorMesg = "XSB_DBI ERROR: Query handle already exists";
00309     errorNumber = "XSB_DBI_007";
00310     return FALSE;
00311   }
00312 
00313   sqlQuery = buildSQLQuery(sqlQueryList);
00314 
00315   qHandle = (struct xsb_queryHandle *)malloc(sizeof(struct xsb_queryHandle));
00316   qHandle->connHandle = cHandle;
00317   qHandle->query = (char *)malloc((strlen(sqlQuery) + 1) * sizeof(char));
00318   strcpy(qHandle->query, sqlQuery);
00319   qHandle->handle = (char *)malloc((strlen(qhandle) + 1) * sizeof(char));
00320   strcpy(qHandle->handle, qhandle);
00321   qHandle->state = QUERY_BEGIN;
00322   
00323   if (getDriverFunction(cHandle->driver, PREPARE) != NULL)
00324     prepareStmtDriver = getDriverFunction(cHandle->driver, PREPARE)->prepareStmtDriver;
00325   else
00326     return FALSE;
00327   if ((val = prepareStmtDriver(qHandle)) != FAILURE) {
00328     qHandle->numParams = val;
00329     QHandles[numQHandles++] = qHandle;
00330   }
00331   else {
00332     if (getDriverFunction(cHandle->driver, ERROR_MESG) != NULL)
00333       errorMesgDriver = getDriverFunction(cHandle->driver, ERROR_MESG)->errorMesgDriver;
00334     else
00335       return FALSE;
00336     errorMesg = errorMesgDriver();
00337     errorNumber = "XSB_DBI_000";
00338     free(qHandle->query);
00339     free(qHandle);
00340     return FALSE;
00341   }
00342 
00343   return TRUE;
00344 }
00345 
00346 DllExport int call_conv executePreparedStatement(void)
00347 {
00348   struct xsb_data** (*executeStmtDriver)(struct xsb_data**, struct xsb_queryHandle*);
00349   char* (*errorMesgDriver)();
00350   struct xsb_queryHandle* qHandle;
00351   struct xsb_connectionHandle* cHandle;
00352   struct xsb_data** bindValues;
00353   struct xsb_data** result;
00354   prolog_term bindList, returnList, element;
00355   char *queryHandle, *chandle;
00356   double temp_float;
00357   int i, temp_int, val;
00358 
00359   queryHandle = ptoc_string(1);
00360   bindList = reg_term(2);
00361   returnList = reg_term(3);
00362 
00363   if ((qHandle = isQueryHandle(queryHandle)) == NULL) {
00364     errorMesg = "XSB_DBI ERROR: Query handle does not exist";
00365     errorNumber = "XSB_DBI_005";
00366     return FALSE;
00367   }
00368   
00369   if (qHandle->state == QUERY_BEGIN) {
00370     bindValues =
00371       (struct xsb_data **)malloc(qHandle->numParams * sizeof(struct xsb_data *));
00372     for (i = 0 ; i < qHandle->numParams ; i++) {
00373       bindValues[i] = (struct xsb_data *)malloc(sizeof(struct xsb_data));
00374       if (is_nil(bindList)) {
00375         errorMesg = "XSB_DBI ERROR: Not all paremeters supplied";
00376         errorNumber = "XSB_DBI_008";
00377         return FALSE;
00378       }
00379       element = p2p_car(bindList);
00380       if (is_string(element)) {
00381         bindValues[i]->type = STRING_TYPE;
00382         bindValues[i]->length = strlen(p2c_string(element));
00383         bindValues[i]->val = (union xsb_value *)malloc(sizeof(union xsb_value));
00384         bindValues[i]->val->str_val =
00385           (char *)malloc((strlen(p2c_string(element)) + 1) * sizeof(char));
00386         strcpy(bindValues[i]->val->str_val, p2c_string(element));
00387       }
00388       else if (is_int(element)) {
00389         bindValues[i]->type = INT_TYPE;
00390         bindValues[i]->val = (union xsb_value *)malloc(sizeof(union xsb_value));
00391         bindValues[i]->val->i_val = (int *)malloc(sizeof(int));
00392         temp_int = p2c_int(element);
00393         bindValues[i]->val->i_val = &temp_int;
00394       }
00395       else if (is_float(element)) {
00396         bindValues[i]->type = FLOAT_TYPE;
00397         bindValues[i]->val = (union xsb_value *)malloc(sizeof(union xsb_value));
00398         bindValues[i]->val->f_val = (double *)malloc(sizeof(double));
00399         temp_float = p2c_float(element);
00400         bindValues[i]->val->f_val = &temp_float;
00401       }
00402       else if (is_functor(element)) {
00403       }
00404       else if (is_var(element)) {
00405         errorMesg = "XSB_DBI ERROR: Unbound variable in parameter list";
00406         errorNumber = "XSB_DBI_009";
00407         return FALSE;
00408       }
00409       bindList = p2p_cdr(bindList);
00410     }
00411   }
00412         
00413   if (getDriverFunction(qHandle->connHandle->driver, EXEC_PREPARE) != NULL)
00414     executeStmtDriver =
00415       getDriverFunction(qHandle->connHandle->driver, EXEC_PREPARE)->executeStmtDriver;
00416   else
00417     return FALSE;
00418   
00419   result = executeStmtDriver(bindValues, qHandle);
00420 
00421   if (result == NULL && qHandle->state == QUERY_BEGIN) {
00422     if (getDriverFunction(qHandle->connHandle->driver, ERROR_MESG) != NULL)
00423       errorMesgDriver =
00424         getDriverFunction(qHandle->connHandle->driver, ERROR_MESG)->errorMesgDriver;
00425     else
00426       return FALSE;
00427     
00428     errorMesg = errorMesgDriver();
00429     return FALSE;
00430   }
00431   
00432   val = bindReturnList(returnList, result, qHandle);
00433 
00434   if (result == NULL) {
00435     qHandle->state = QUERY_BEGIN;
00436   }
00437   
00438   if (val == TOO_MANY_RETURN_COLS || val == TOO_FEW_RETURN_COLS || val == INVALID_RETURN_LIST)
00439     return FALSE;
00440 
00441   cHandle = qHandle->connHandle;
00442   chandle = cHandle->handle;
00443   if ((cHandle = isConnectionHandle(chandle)) != NULL) {
00444     if (getDriverFunction(cHandle->driver, ERROR_MESG) != NULL)
00445       errorMesgDriver =
00446         getDriverFunction(cHandle->driver, ERROR_MESG)->errorMesgDriver;
00447     else
00448       return FALSE;
00449           
00450     errorMesg = errorMesgDriver();
00451     errorNumber = "XSB_DBI_000";
00452   }
00453 
00454   if (errorMesg == NULL && val == RESULT_NONEMPTY_OR_NOT_REQUESTED)
00455     return TRUE;
00456   else 
00457     return FALSE;
00458 }
00459 
00460 
00461 DllExport int call_conv closeStatement(void)
00462 {
00463   char* queryHandle;
00464   
00465   queryHandle = ptoc_string(1);
00466   return closeQueryHandle(queryHandle);
00467 }
00468 
00469 
00470 DllExport int call_conv exception(void)
00471 {
00472   prolog_term number;
00473   prolog_term message;
00474         
00475   number = reg_term(1);
00476   message = reg_term(2);
00477   if (is_var(message) && errorMesg != NULL && errorNumber != NULL) {
00478     c2p_string(errorMesg, message);
00479     c2p_string(errorNumber, number);
00480     errorMesg = NULL;
00481     errorNumber = NULL;
00482     return TRUE;
00483   }
00484         
00485   return FALSE;
00486 }
00487 
00488 
00489 static char* buildSQLQuery(prolog_term sqlQueryList)
00490 {
00491   prolog_term element;
00492   char* sqlQuery;
00493   char* temp;
00494   char* t1;
00495   int i, cnt;
00496 
00497   sqlQuery = (char *)malloc(QUERY_SIZE * sizeof(char));
00498   sqlQuery[0] = '\0';
00499   while (!is_nil(sqlQueryList)) {
00500     element = p2p_car(sqlQueryList);
00501     sqlQueryList = p2p_cdr(sqlQueryList);
00502     if (is_string(element)) {
00503       t1 = (char *)malloc(ELEMENT_SIZE * sizeof(char));
00504       sprintf(t1, "%s", p2c_string(element));
00505       if (t1[0] == TERM_CHAR) {
00506         cnt = 0;
00507         temp = (char *)malloc(ELEMENT_SIZE * sizeof(char));
00508         temp[cnt++] = '\'';
00509         /* protect inner quotes in Prolog terms */
00510         for (i = 0 ; i < strlen(t1) ; i++) {
00511           if (t1[i] == '\'') {
00512             temp[cnt++] = '\\';
00513             temp[cnt++] = t1[i];
00514           }
00515           else {
00516             temp[cnt++] = t1[i];
00517           }
00518         }
00519         temp[cnt++] = '\'';
00520         strcat(sqlQuery, temp);
00521       }
00522       else {
00523         strcat(sqlQuery, t1);            
00524       }
00525     }
00526     else if (is_int(element)) {
00527       temp = (char *)malloc(ELEMENT_SIZE * sizeof(char));
00528       sprintf(temp, "%d", p2c_int(element));
00529       strcat(sqlQuery, temp);
00530     }
00531     else if (is_float(element)) {
00532       temp = (char *)malloc(ELEMENT_SIZE * sizeof(char));
00533       sprintf(temp, "%f", p2c_float(element));                  
00534       strcat(sqlQuery, temp);
00535     }
00536     else if (is_var(element)) {
00537       errorMesg = "XSB_DBI ERROR: Unbound variable in parameter list";
00538     }
00539   }
00540 
00541   return sqlQuery;  
00542 }
00543 
00544 
00545 static int bindReturnList(prolog_term returnList, struct xsb_data** result, struct xsb_queryHandle* qHandle)
00546 {
00547   prolog_term element;
00548   char* temp;
00549   char c;
00550   int i, j;
00551   int rFlag;
00552   
00553   if (is_nil(returnList) && result == NULL) {
00554     rFlag = RESULT_NONEMPTY_OR_NOT_REQUESTED;
00555   }
00556 
00557   if (!is_nil(returnList) && result == NULL && qHandle->state == QUERY_BEGIN) {
00558     errorMesg = "XSB_DBI_ERROR: Invalid return list in query";
00559     errorNumber = "XSB_DBI_012";
00560     rFlag = INVALID_RETURN_LIST;
00561   }  
00562   else if (!is_nil(returnList) && result == NULL) {
00563     while (!is_nil(returnList)) {
00564       element = p2p_car(returnList);
00565       c2p_nil(element);
00566       returnList = p2p_cdr(returnList);
00567     }
00568     rFlag = RESULT_EMPTY_BUT_REQUESTED;
00569   }
00570 
00571   i = 0;
00572   if (result != NULL) {
00573     while (!is_nil(returnList)) {
00574       if (qHandle->numResultCols <= i) {
00575         errorMesg = "XSB_DBI ERROR: Number of requested columns exceeds the number of columns in the query";
00576         errorNumber = "XSB_DBI_011";
00577         rFlag = TOO_MANY_RETURN_COLS;
00578         return rFlag;   
00579       }
00580       element = p2p_car(returnList);
00581       if (result == NULL) {
00582         c2p_nil(element);
00583       }
00584       else if (is_var(element) && result[i]->type == STRING_TYPE) {
00585         if (result[i]->val == NULL)
00586           c2p_nil(element);
00587         else {
00588           c = result[i]->val->str_val[0];
00589           if (c == TERM_CHAR) {
00590             temp = (char *)malloc(strlen(result[i]->val->str_val) * sizeof(char));
00591             for (j = 1 ; j < strlen(result[i]->val->str_val) ; j++) {
00592               temp[j-1] = result[i]->val->str_val[j];
00593             }
00594             temp[strlen(result[i]->val->str_val) - 1] = '\0';
00595             c2p_functor("term", 1, element);
00596             c2p_string(temp, p2p_arg(element, 1));
00597           }
00598           else {
00599             c2p_string(result[i]->val->str_val, element);           
00600           }
00601         }
00602       }
00603       else if (is_var(element) && result[i]->type == INT_TYPE)
00604         c2p_int(*(result[i]->val->i_val), element);
00605       else if (is_var(element) && result[i]->type == FLOAT_TYPE)
00606         c2p_float(*(result[i]->val->f_val), element);
00607       returnList = p2p_cdr(returnList);
00608       i++;
00609     }
00610     rFlag = RESULT_NONEMPTY_OR_NOT_REQUESTED;
00611   }
00612 
00613   if (result != NULL && qHandle->numResultCols > i) {
00614     errorMesg = "XSB_DBI ERROR: Number of requested columns is less than the number of returned columns";
00615     errorNumber = "XSB_DBI_013";    
00616     rFlag = TOO_FEW_RETURN_COLS;
00617     return rFlag;
00618   }
00619 
00620   return rFlag;  
00621 }
00622 
00623 
00624 static void freeConnectionHandle(struct xsb_connectionHandle* cHandle, int pos)
00625 {
00626   int j;
00627   
00628   free(cHandle->handle);
00629   free(cHandle->driver);
00630   if (cHandle->server == NULL)
00631     free(cHandle->dsn);
00632   else {
00633     free(cHandle->server);
00634     free(cHandle->database);
00635   }
00636   free(cHandle->user);
00637   free(cHandle->password);
00638   free(cHandle);
00639   for (j = pos + 1 ; j < numCHandles ; j++)
00640     CHandles[j-1] = CHandles[j];
00641   CHandles[numCHandles-1] = NULL;
00642   numCHandles--;
00643 }
00644 
00645 
00646 static int closeQueryHandle(char* queryHandle)
00647 {
00648   int (*closeStmtDriver)(struct xsb_queryHandle*);
00649   char* (*errorMesgDriver)();
00650   char* driverName;  
00651   int i, result;
00652   
00653   for (i = 0 ; i < numQHandles ; i++) {
00654     if (!strcmp(QHandles[i]->handle, queryHandle)) {
00655       driverName = QHandles[i]->connHandle->driver;
00656       
00657       if (getDriverFunction(driverName, CLOSE_STMT) != NULL)
00658         closeStmtDriver = getDriverFunction(driverName, CLOSE_STMT)->closeStmtDriver;
00659       else
00660         return FALSE;
00661       
00662       result = closeStmtDriver(QHandles[i]);
00663       if (result == FAILURE) {
00664         if (getDriverFunction(driverName, ERROR_MESG) != NULL)
00665           errorMesgDriver = getDriverFunction(driverName, ERROR_MESG)->errorMesgDriver;
00666         else
00667           return FALSE;
00668 
00669         errorMesg = errorMesgDriver();
00670         return FALSE;
00671       }
00672       freeQueryHandle(QHandles[i], i);
00673     }
00674   }
00675   
00676   return TRUE;
00677 }
00678 
00679 
00680 static void freeQueryHandle(struct xsb_queryHandle* qHandle, int pos)
00681 {
00682   int j;
00683   
00684   free(qHandle->handle);
00685   free(qHandle->query);
00686   free(qHandle);
00687   for (j = pos + 1 ; j < numQHandles ; j++)
00688     QHandles[j-1] = QHandles[j];
00689   QHandles[numQHandles-1] = NULL;
00690   numQHandles--;  
00691 }
00692 
00693 
00694 static struct xsb_connectionHandle* isConnectionHandle(char* handle)
00695 {
00696   int i;
00697   for (i = 0 ; i < numCHandles ; i++)
00698     if (!strcmp(CHandles[i]->handle, handle))
00699       return CHandles[i];
00700   return NULL;
00701 }
00702 
00703 
00704 static struct xsb_queryHandle* isQueryHandle(char* handle)
00705 {
00706   int i;
00707   for (i = 0 ; i < numQHandles ; i++)
00708     if (!strcmp(QHandles[i]->handle, handle))
00709       return QHandles[i];
00710   return NULL;
00711 }
00712 
00713 
00714 DllExport int call_conv registerXSBDriver(char* drivername, int num)
00715 {
00716   struct driver* dr;
00717   int i;
00718 
00719   for (i = 0 ; i < numDrivers ; i++) {
00720     if (!strcmp(DBdrivers[i]->driver, drivername)) {
00721       errorMesg = "XSB_DBI ERROR: driver already registered";
00722       errorNumber = "XSB_DBI_001";
00723       return -1;
00724     }
00725   }
00726   dr = (struct driver *)malloc(sizeof(struct driver));
00727   dr->driver = drivername;
00728   dr->numberFunctions = num;
00729   dr->functions =
00730     (struct driverFunction **)malloc(num * sizeof(struct driverFunction *));
00731   for (i = 0 ; i < num ; i++)
00732     dr->functions[i] = NULL;
00733 
00734   DBdrivers[numDrivers++] = dr;
00735   return 0;
00736 }
00737 
00738 
00739 DllExport int call_conv registerXSBFunction(char* drivername, int type, union functionPtrs* func)
00740 {
00741   int i, j;
00742 
00743   for (i = 0 ; i < numDrivers ; i++) {
00744     if (!strcmp(DBdrivers[i]->driver, drivername)) {
00745       for (j = 0 ; j < DBdrivers[i]->numberFunctions ; j++) {
00746         if (DBdrivers[i]->functions[j] == NULL) {
00747           DBdrivers[i]->functions[j] =
00748             (struct driverFunction *)malloc(sizeof(struct driverFunction));
00749           DBdrivers[i]->functions[j]->functionType = type;
00750           DBdrivers[i]->functions[j]->functionName = func;
00751           break;
00752         }
00753       }
00754     }
00755   }
00756 
00757   return 0;
00758 }
00759 
00760 
00761 static union functionPtrs* getDriverFunction(char* drivername, int type)
00762 {
00763   int i, j;
00764 
00765   for (i = 0 ; i < numDrivers ; i++) {
00766     if (!strcmp(DBdrivers[i]->driver, drivername)) {
00767       for (j = 0 ; j < DBdrivers[i]->numberFunctions ; j++) {
00768         if (DBdrivers[i]->functions[j]->functionType == type) {
00769           return DBdrivers[i]->functions[j]->functionName;
00770         }
00771       }
00772       errorMesg = "XSB_DBI ERROR: Function does not exist in this driver";
00773       errorNumber = "XSB_DBI_003";
00774       return NULL;
00775     }
00776   }
00777   errorMesg = "XSB_DBI ERROR: Driver does not exist";
00778   errorNumber = "XSB_DBI_002";
00779   return NULL;
00780 }

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