mysql_driver.c

00001 /* File: mysql_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 driver for connecting to a MySQL database.
00025 ** This is invoked from the middle_layer module in emu.
00026 */
00027 
00028 #ifdef WIN_NT
00029 #include <windows.h>
00030 #endif
00031 
00032 #ifdef WIN_NT
00033 #define XSB_DLL
00034 #endif
00035 
00036 #include "mysql_driver_defs.h"
00037 
00038 static void driverMySQL_error(MYSQL* mysql);
00039 static int driverMySQL_getXSBType(MYSQL_FIELD* field);
00040 static struct xsb_data** driverMySQL_getNextRow(struct driverMySQL_queryInfo* query);
00041 
00042 struct driverMySQL_connectionInfo* mysqlHandles[MAX_HANDLES];
00043 struct driverMySQL_queryInfo* mysqlQueries[MAX_QUERIES];
00044 int numHandles, numQueries;
00045 const char* errorMesg;
00046 
00047 //struct driverMySQL_preparedresultset* prepQueries[MAX_PREP_QUERIES];
00048 
00049 
00050 DllExport int call_conv driverMySQL_initialise()
00051 {
00052         numHandles = 0;
00053         numQueries = 0;
00054         errorMesg = NULL;
00055 
00056         return TRUE;
00057 }
00058 
00059 
00060 DllExport int call_conv driverMySQL_connect(struct xsb_connectionHandle* handle)
00061 {
00062         struct driverMySQL_connectionInfo* mysqlHandle;
00063         MYSQL* mysql;
00064 
00065         mysql = (MYSQL *)malloc(sizeof(MYSQL));
00066         if (!mysql_init(mysql))
00067         {
00068                 driverMySQL_error(mysql);
00069                 free(mysql);
00070                 return FAILURE;
00071         }
00072         
00073         if (!mysql_real_connect(mysql, handle->server, handle->user, handle->password, handle->database, 0, NULL, 0))
00074         {
00075                 driverMySQL_error(mysql);
00076                 free(mysql);
00077                 return FAILURE; 
00078         }
00079         
00080         mysqlHandle = (struct driverMySQL_connectionInfo *)malloc(sizeof(struct driverMySQL_connectionInfo));
00081         mysqlHandle->handle = (char *)malloc((strlen(handle->handle) + 1) * sizeof(char));
00082         strcpy(mysqlHandle->handle, handle->handle);
00083         mysqlHandle->mysql = mysql;
00084         mysqlHandles[numHandles++] = mysqlHandle;
00085 
00086         return SUCCESS;
00087 }
00088 
00089 
00090 DllExport int call_conv driverMySQL_disconnect(struct xsb_connectionHandle* handle)
00091 {
00092         int i, j;
00093 
00094         for (i = 0 ; i < numHandles ; i++)
00095         {
00096                 if (!strcmp(handle->handle, mysqlHandles[i]->handle))
00097                 {
00098                         mysql_close(mysqlHandles[i]->mysql);
00099                         free(mysqlHandles[i]->mysql);
00100                         for (j = i + 1 ; j < numHandles ; j++)
00101                                 mysqlHandles[j-1] = mysqlHandles[j];
00102                         numHandles--;
00103                         break;
00104                 }
00105         }
00106 
00107         return SUCCESS;
00108 }
00109 
00110 
00111 DllExport struct xsb_data** call_conv driverMySQL_query(struct xsb_queryHandle* handle)
00112 {
00113         struct driverMySQL_connectionInfo* connection;
00114         struct driverMySQL_queryInfo* query;
00115         MYSQL_RES* resultSet;
00116         int i;
00117 
00118         query = NULL;
00119         connection = NULL;
00120         if (handle->state == QUERY_RETRIEVE)
00121         {
00122                 for (i = 0 ; i < numQueries ; i++)
00123                 {
00124                         if (!strcmp(mysqlQueries[i]->handle, handle->handle))
00125                         {
00126                                 query = mysqlQueries[i];
00127                                 break;
00128                         }
00129                 }
00130         }
00131         else if (handle->state == QUERY_BEGIN)
00132         {
00133                 for (i = 0 ; i < numHandles ; i++)
00134                 {
00135                         if (!strcmp(mysqlHandles[i]->handle, handle->connHandle->handle))
00136                         {
00137                                 connection = mysqlHandles[i];
00138                                 break;
00139                         }
00140                 }
00141                 query = (struct driverMySQL_queryInfo *)malloc(sizeof(struct driverMySQL_queryInfo));
00142                 query->handle = (char *)malloc((strlen(handle->handle) + 1) * sizeof(char));
00143                 strcpy(query->handle, handle->handle);
00144                 query->query = (char *)malloc((strlen(handle->query) + 1) * sizeof(char));
00145                 strcpy(query->query, handle->query);
00146                 query->connection = connection;
00147 
00148                 if (mysql_query(query->connection->mysql, query->query))
00149                 {
00150                         driverMySQL_error(query->connection->mysql);
00151                         return NULL;    
00152                 }
00153                 else
00154                 {
00155                         if ((resultSet = mysql_use_result(query->connection->mysql)) == NULL)
00156                         {
00157                                 driverMySQL_error(query->connection->mysql);
00158                                 return NULL;
00159                         }
00160                         query->resultSet = resultSet;
00161                         mysqlQueries[numQueries++] = query;
00162                         handle->state = QUERY_RETRIEVE;
00163                         handle->numResultCols = mysql_num_fields(resultSet);
00164                 }
00165         }
00166 
00167         return driverMySQL_getNextRow(query);
00168 }
00169 
00170 
00171 static struct xsb_data** driverMySQL_getNextRow(struct driverMySQL_queryInfo* query)
00172 {
00173         struct xsb_data** result;
00174         MYSQL_ROW row;
00175         int numFields;
00176         int i, j;
00177 
00178         result = NULL;
00179         if ((row = mysql_fetch_row(query->resultSet)) == NULL)
00180         {
00181                 if (mysql_errno(query->connection->mysql))
00182                         driverMySQL_error(query->connection->mysql);
00183                 else
00184                 {
00185                         for (i = 0 ; i < numQueries ; i++)
00186                         {
00187                                 if (!strcmp(mysqlQueries[i]->handle, query->handle))
00188                                 {
00189                                         mysql_free_result(query->resultSet);
00190                                         free(query->query);
00191                                         free(query->handle);
00192                                         free(query);
00193                                         for (j = i + 1 ; j < numQueries ; j++)
00194                                                 mysqlQueries[j-1] = mysqlQueries[j];
00195                                         numQueries--;
00196                                 }
00197                         }
00198                 }
00199                 return NULL;
00200         }
00201 
00202         numFields = mysql_num_fields(query->resultSet);
00203         result = (struct xsb_data **)malloc(numFields * sizeof(struct xsb_data *));
00204         for (i = 0 ; i < numFields ; i++)
00205         {
00206                 result[i] = (struct xsb_data *)malloc(sizeof(struct xsb_data));
00207                 result[i]->val = (union xsb_value *)malloc(sizeof(union xsb_value));
00208                 result[i]->type = driverMySQL_getXSBType(mysql_fetch_field_direct(query->resultSet, i));
00209                 switch (result[i]->type)
00210                 {
00211                         case INT_TYPE:
00212                                         result[i]->val->i_val = (int *)malloc(sizeof(int));
00213                                         result[i]->val->i_val = (int *)row[i];
00214                                         break;
00215 
00216                         case FLOAT_TYPE:
00217                                         result[i]->val->f_val = (double *)malloc(sizeof(double));
00218                                         result[i]->val->f_val = (double *)row[i];
00219                                         break;
00220 
00221                         case STRING_TYPE:
00222                                         result[i]->val->str_val = (char *)malloc(strlen(row[i]) * sizeof(char));
00223                                         strcpy(result[i]->val->str_val, (char *)row[i]);
00224                                         break;
00225                 }
00226         }
00227 
00228         return result;
00229 }
00230 
00231 
00232 /* **** PREPARED STATEMENT FUNCTIONALITY (from MySQL 4.1 version) *****
00233 
00234 
00235 int driverMySQL_prepareStatement(char* SQLQuery, struct xsb_queryHandle* handle)
00236 {
00237         struct driverMySQL_preparedresultset* rs;
00238         MYSQL* mysql;
00239         MYSQL_STMT* stmt;
00240         MYSQL_RES* res;
00241         MYSQL_FIELD* field;
00242         int i;
00243         
00244         mysql = mysqlHandles[handle->connHandle->index];
00245         if ((stmt = mysql_prepare(mysql, SQLQuery, strlen(SQLQuery))) == NULL)
00246         {
00247                 printf("MySQL ERROR: %s\n", mysql_error(mysql));
00248                 return -1;              
00249         }
00250         if ((res = mysql_prepare_result(stmt)) == NULL)
00251         {
00252                 printf("MySQL ERROR: %s\n", mysql_error(mysql));
00253                 return -1;
00254         }
00255         rs = (struct driverMySQL_preparedresultset *)malloc(sizeof(struct driverMySQL_preparedresultset));
00256         rs->statement = stmt;
00257         rs->handle = handle;
00258         rs->handle->parameters = mysql_param_count(stmt);
00259         rs->returnFields = mysql_num_fields(res);
00260         rs->metaInfo = (struct xsb_data **)malloc(rs->returnFields * sizeof(struct xsb_data *));
00261         handle->numResultCols = rs->returnFields;
00262         for (i = 0 ; i < rs->returnFields ; i++)
00263         {
00264                 rs->metaInfo[i] = (struct xsb_data *)malloc(sizeof(struct xsb_data));
00265                 MYSQL_FIELD* field = mysql_fetch_field_direct(res, i);
00266                 rs->metaInfo[i]->type = driverMySQL_type(field);
00267                 rs->metaInfo[i]->length = field->length;
00268         }
00269         prepQueries[numPrepQueries++] = rs;
00270         
00271         return (numPrepQueries - 1);
00272 }
00273 
00274 struct xsb_data** driverMySQL_execPrepareStmt(struct xsb_data** bindValues, struct xsb_queryHandle* handle)
00275 {
00276         struct driverMySQL_preparedresultset* rs;
00277         int i;
00278 
00279         rs = prepQueries[handle->index];
00280         if (handle->state == QUERY_RETRIEVE)
00281                 return driverMySQL_prepNextRow(rs);             
00282         
00283         MYSQL_BIND** bind = (MYSQL_BIND **)malloc(handle->parameters * sizeof(MYSQL_BIND *));
00284         for (i = 0 ; i < handle->parameters ; i++)
00285         {
00286                 bind[i] = (MYSQL_BIND *)malloc(sizeof(MYSQL_BIND));
00287                 if (bindValues[i]->type == INT_TYPE)
00288                 {       
00289                 }
00290                 else if (bindValues[i]->type == FLOAT_TYPE)
00291                 {
00292                 }
00293                 else if (bindValues[i]->type == STRING_TYPE)
00294                 {
00295                         bind[i]->buffer_type = MYSQL_TYPE_VAR_STRING;
00296                         bind[i]->buffer_length = sizeof(bindValues[i]->val->str_val);
00297                         bind[i]->buffer = bindValues[i]->val->str_val;
00298                 }
00299         }
00300         if (mysql_bind_param(query->statement, bind))
00301         {
00302                 printf("MySQL ERROR: %s\n", mysql_error(mysql));
00303                 return NULL;
00304         }
00305         if (mysql_execute(query->statement))
00306         {
00307                 printf("MySQL ERROR: %s\n", mysql_error(mysql));
00308                 return NULL;
00309         }
00310         handle->state = QUERY_RETRIEVE;
00311 
00312         return driverMySQL_prepNextRow(rs);
00313 }
00314 
00315 struct xsb_data** driverMySQL_prepNextRow(struct driverMySQL_preparedresultset* rs)
00316 {
00317         struct xsb_data** result;
00318         MYSQL_BIND** bindResult;
00319         int i;
00320 
00321         result = (struct xsb_data **)malloc(rs->returnFields * sizeof(struct xsb_data *));
00322         bindResult = (MYSQL_BIND **)malloc(rs->returnFields * sizeof(MYSQL_BIND *));
00323         for (i = 0 ; i < rs->returnFields ; i++)
00324         {
00325                 result[i] = (struct xsb_data *)malloc(sizeof(struct xsb_data));
00326                 bindResult[i] = (MYSQL_BIND *)malloc(sizeof(MYSQL_BIND));
00327                 result[i]->type = rs->metaInfo[i]->type;
00328                 result[i]->length = rs->metaInfo[i]->length;
00329                 result[i]->val = (union value *)malloc(sizeof(union value));
00330                 switch (result[i]->type)
00331                 {
00332                         case INT_TYPE:
00333                                         break;
00334 
00335                         case FLOAT_TYPE:
00336                                         break;
00337                         
00338                         case STRING_TYPE:
00339                                         result[i]->val->str_val = (char *)malloc(result[i]->length * sizeof(char));
00340                                         bindResult[i]->buffer_type = MYSQL_TYPE_VAR_STRING;
00341                                         bindResult[i]->buffer = result[i]->val->str_val;
00342                                         break;
00343                 }
00344         }
00345         
00346         if (mysql_bind_result(rs->statement, bindResult))
00347         {
00348                 printf("MySQL ERROR: %s\n", mysql_error(mysql));
00349                 return NULL;
00350         }
00351         
00352         if (mysql_fetch(rs->statement) == MYSQL_NO_DATA)
00353                 return NULL;
00354         
00355         return result;
00356 }
00357 
00358 ***** END OF PREPARED STATEMENT FUNCTIONALITY ***** */
00359 
00360 
00361 DllExport char* call_conv driverMySQL_errorMesg()
00362 {
00363         char* temp;
00364         if (errorMesg != NULL)
00365         {
00366                 temp = (char *)malloc((strlen(errorMesg) + 1) * sizeof(char));
00367                 strcpy(temp, errorMesg);
00368                 errorMesg = NULL;
00369         }
00370         return NULL;
00371 }
00372 
00373 
00374 static void driverMySQL_error(MYSQL* mysql)
00375 {
00376         errorMesg = mysql_error(mysql);
00377 }
00378 
00379 
00380 static int driverMySQL_getXSBType(MYSQL_FIELD* field)
00381 {
00382         int type;
00383 
00384         type = 0;
00385         switch (field->type)
00386         {
00387                 case FIELD_TYPE_TINY:
00388                 case FIELD_TYPE_SHORT:
00389                 case FIELD_TYPE_LONG:
00390                 case FIELD_TYPE_INT24:
00391                 case FIELD_TYPE_LONGLONG:
00392                                 type = INT_TYPE;
00393                                 break;
00394                 
00395                 case FIELD_TYPE_DECIMAL:
00396                 case FIELD_TYPE_FLOAT:
00397                 case FIELD_TYPE_DOUBLE:
00398                                 type = FLOAT_TYPE;
00399                                 break;
00400 
00401                 case FIELD_TYPE_STRING:
00402                 case FIELD_TYPE_DATE:
00403                 case FIELD_TYPE_TIMESTAMP:
00404                 case FIELD_TYPE_TIME:
00405                 case FIELD_TYPE_DATETIME:
00406                 case FIELD_TYPE_YEAR:
00407                 case FIELD_TYPE_NEWDATE:
00408                 case FIELD_TYPE_ENUM:
00409                 case FIELD_TYPE_SET:
00410                 case FIELD_TYPE_TINY_BLOB:
00411                 case FIELD_TYPE_MEDIUM_BLOB:
00412                 case FIELD_TYPE_LONG_BLOB:
00413                 case FIELD_TYPE_BLOB:
00414                 case FIELD_TYPE_VAR_STRING:
00415                 case FIELD_TYPE_NULL:
00416                 default:
00417                                 type = STRING_TYPE;
00418                                 break;
00419         }
00420 
00421         return type;
00422 }
00423 
00424 
00425 DllExport int call_conv driverMySQL_register(void)
00426 {
00427         union functionPtrs* funcConnect;
00428         union functionPtrs* funcDisconnect;
00429         union functionPtrs* funcQuery;
00430         union functionPtrs* funcErrorMesg;
00431         //union functionPtrs* funcPrepare;
00432         //union functionPtrs* funcExecPrepare;
00433 
00434         registerXSBDriver("mysql", 4);
00435 
00436         funcConnect = (union functionPtrs *)malloc(sizeof(union functionPtrs));
00437         funcConnect->connectDriver = driverMySQL_connect;
00438         registerXSBFunction("mysql", CONNECT, funcConnect);
00439 
00440         funcDisconnect = (union functionPtrs *)malloc(sizeof(union functionPtrs));
00441         funcDisconnect->disconnectDriver = driverMySQL_disconnect;
00442         registerXSBFunction("mysql", DISCONNECT, funcDisconnect);
00443 
00444         funcQuery = (union functionPtrs *)malloc(sizeof(union functionPtrs));
00445         funcQuery->queryDriver = driverMySQL_query;
00446         registerXSBFunction("mysql", QUERY, funcQuery);
00447 
00448         funcErrorMesg = (union functionPtrs *)malloc(sizeof(union functionPtrs));
00449         funcErrorMesg->errorMesgDriver = driverMySQL_errorMesg;
00450         registerXSBFunction("mysql", ERROR_MESG, funcErrorMesg);
00451 
00452         //funcPrepare = (union functionPtrs *)malloc(sizeof(union functionPtrs));
00453         //funcPrepare->prepareStmtDriver = driverMySQL_prepareStatement;
00454         //registerXSBFunction("mysql", PREPARE, funcPrepare);
00455 
00456         //funcExecPrepare = (union functionPtrs *)malloc(sizeof(union functionPtrs));
00457         //funcExecPrepare->executeStmtDriver = driverMySQL_execPrepareStmt;
00458         //registerXSBFunction("mysql", EXEC_PREPARE, funcExecPrepare);
00459         
00460         return TRUE;
00461 }
00462 

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