/* +----------------------------------------------------------------------+ | PHP version 4.0 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2001 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 2.02 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available at through the world-wide-web at | | http://www.php.net/license/2_02.txt. | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Authors: Frank M. Kromann frank@frontbase.com> | +----------------------------------------------------------------------+ */ /* $Id$ */ /* TODO: * * ? Safe mode implementation */ // SB's list: // - BLOBs // - API for a more natural FB connect semantic // - Connect & set session // - Autoreconnect when disconnected // - Comments and cleanup // - Documentation // // - Format database error messages as HTML. // // BUGS // - Select db with no arguments // - Query with everything defaulted // #include "php.h" #include "php_globals.h" #include "php_globals.h" #include "ext/standard/info.h" #include "ext/standard/php_string.h" #if WIN32|WINNT #include #else #include #include #if HAVE_SYS_TYPES_H #include #endif #include #include #endif #include "php_ini.h" #define HAVE_FBSQL 1 #if HAVE_FBSQL #include "php_fbsql.h" #include static int le_result, le_link, le_plink, le_dba; struct PHPFBDatabase; typedef struct PHPFBDatabase PHPFBDatabase; struct PHPFBResult; typedef struct PHPFBResult PHPFBResult; struct PHPFBLink; typedef struct PHPFBLink PHPFBLink; // The PHPFBLink structure represents a fbsql link. The lion is used for // a connection to a machine, it may be persistant and is reference counted. // The reason for refcounting is mostly to avoid to think, it work independent of // any wierd and unforseen allocation deallocation order. // // The PHPFBDatabse structure implements to actual connection to a FrontBase server // ot may be persistant is the link it is connected to is persistant, and refcounted // for the same reasons as above. // // The PHPFBResult structure implements a result from the FrontBase server, and does all // required buffereing from of results. // // In the PHP code the 3 above a data structures are referenced by means of integers in the // range from 1 to som configurable maximum. You can put a limit to the number of links, databases // and results. The integer identifications is implemented by insertion in the list, which is passed // as an argument to all the functions, please note the list is polymorph. // // Database objects and link objects are all reused, base on the host name user name, host name database name // user name. So connecting twice to the same database as the same user will return the same database id. // We use the same coding for that as fbsql does, explioiting the underlying implementation of the lists. // // Persistant objects are put in the persistent list as well, but only by name, if you connect to a persistant object // and it is not in the list it is simply added and get a new index, and refcounted. Tricky, tricky ... // // Some functions which should be exported from FBCAccess void* fbaObjectAtIndex(); void fbcInitialize(); void fbaRelease(); unsigned int fbaCount(); struct PHPFBDatabase { unsigned int retainCount; // The refcount unsigned int index; // The index in the list PHPFBLink* link; // A pointer to the corresponding link object, may be NULL if no link were used char* databaseName; // The name of the database char* databasePassword; // The database password FBCDatabaseConnection* connection; // The connection to the database unsigned int errorNo; // The latest error on the connection, 0 is ok. char* errorText; // The error text unsigned int resultCount; // Number of active result for this database unsigned int rowIndex; // The row index of the latest row inserted into the database PHPFBResult** results; // Pointer to the active results }; struct PHPFBResult { unsigned int retainCount; // The refcount unsigned int index; // The index into the list PHPFBLink* link; // The link for the result, may be NULL if no link PHPFBDatabase* database; // The database for the result, may be NULL of no database is related to the result FBCDatabaseConnection* connection; // The database connection, just a convinience char* fetchHandle; // The fetch handle, the id used by the server. FBCMetaData* metaData; // The metadata describing the result FBCMetaData* ResultmetaData; // The metadata describing the result FBCRowHandler* rowHandler; // The row handler, the Frontbase structure used for accessing rows in the result unsigned int batchSize; // The number of row to fetch when expanding the number of rows in the row handler int rowCount; // The number of rows in the results set. The number of row is not in // general known when the select is done, one typically needs to fetch all the row // to figure out how many row you got. When the rowCount is unknown the value is // 0x7ffffffff int columnCount; // Number of columns in the row set. int rowIndex; // The current row index. int columnIndex; // The current column index void** row; // The last row accessed FBArray* array; // The link may return a result set, the database list, we implement that by the // FBArray, just a list of strings. FBCPList* list; // The same special kind result just for property list from extract, schema info. unsigned int selectResults; // number of results in select unsigned int currentResult; // current result number }; struct PHPFBLink { unsigned int retainCount; // The refcount unsigned int index; // The index in the list int persistant; // persistant ? char* hostName; // Host name char* userName; // User name char* userPassword; // User password FBCExecHandler* execHandler; // The exechandler, can be used for database operations unsigned int affectedRows; long autoCommit; // Enable or disable autoCommit PHPFBDatabase* currentDatabase; // The latest referenced database on this link unsigned int databaseCount; // The number of database connect to the link PHPFBDatabase** databases; // and the pointers unsigned int resultCount; // The number of link results PHPFBResult** results; // and the pointers. Only used for list_dbs }; #define FBSQL_ASSOC 1<<0 #define FBSQL_NUM 1<<1 #define FBSQL_BOTH (FBSQL_ASSOC|FBSQL_NUM) function_entry fbsql_functions[] = { PHP_FE(fbsql_connect, NULL) PHP_FE(fbsql_pconnect, NULL) PHP_FE(fbsql_close, NULL) PHP_FE(fbsql_select_db, NULL) PHP_FE(fbsql_create_db, NULL) PHP_FE(fbsql_drop_db, NULL) PHP_FE(fbsql_start_db, NULL) PHP_FE(fbsql_stop_db, NULL) PHP_FE(fbsql_query, NULL) PHP_FE(fbsql_db_query, NULL) PHP_FE(fbsql_list_dbs, NULL) PHP_FE(fbsql_list_tables, NULL) PHP_FE(fbsql_list_fields, NULL) PHP_FE(fbsql_error, NULL) PHP_FE(fbsql_errno, NULL) PHP_FE(fbsql_affected_rows, NULL) PHP_FE(fbsql_insert_id, NULL) PHP_FE(fbsql_result, NULL) PHP_FE(fbsql_next_result, NULL) PHP_FE(fbsql_num_rows, NULL) PHP_FE(fbsql_num_fields, NULL) PHP_FE(fbsql_fetch_row, NULL) PHP_FE(fbsql_fetch_array, NULL) PHP_FE(fbsql_fetch_object, NULL) PHP_FE(fbsql_data_seek, NULL) PHP_FE(fbsql_fetch_lengths, NULL) PHP_FE(fbsql_fetch_field, NULL) PHP_FE(fbsql_field_seek, NULL) PHP_FE(fbsql_free_result, NULL) PHP_FE(fbsql_field_name, NULL) PHP_FE(fbsql_field_table, NULL) PHP_FE(fbsql_field_len, NULL) PHP_FE(fbsql_field_type, NULL) PHP_FE(fbsql_field_flags, NULL) // Fontbase additions: PHP_FE(fbsql_autocommit, NULL) PHP_FE(fbsql_commit, NULL) PHP_FE(fbsql_rollback, NULL) PHP_FE(fbsql_hostname, NULL) PHP_FE(fbsql_database, NULL) PHP_FE(fbsql_database_password, NULL) PHP_FE(fbsql_username, NULL) PHP_FE(fbsql_password, NULL) PHP_FE(fbsql_warnings, NULL) // Aliases: PHP_FALIAS(fbsql, fbsql_db_query, NULL) {NULL, NULL, NULL} }; zend_module_entry fbsql_module_entry = { "fbsql", fbsql_functions, PHP_MINIT(fbsql), PHP_MSHUTDOWN(fbsql), PHP_RINIT(fbsql), NULL, PHP_MINFO(fbsql), STANDARD_MODULE_PROPERTIES }; ZEND_DECLARE_MODULE_GLOBALS(fbsql) #ifdef COMPILE_DL_FBSQL ZEND_GET_MODULE(fbsql) #endif void phpfbReleaseResult ( PHPFBResult* result ); void phpfbReleaseDatabase ( PHPFBDatabase* database ); void phpfbReleaseLink ( PHPFBLink* link ); PHPFBResult* phpfbRetainResult ( PHPFBResult* result ) { if (result) result->retainCount++; return result; } void phpfbReleaseResult ( PHPFBResult* result ) { unsigned int i; FBSQLLS_FETCH(); if (result) { result->retainCount--; //printf("Release result %x %d %d\n",result,result->index,result->retainCount); if (result->retainCount == 0) { if (result->fetchHandle) fbcdcCancelFetch(result->connection,result->fetchHandle); if (result->rowHandler) fbcrhRelease(result->rowHandler); if (result->ResultmetaData) fbcmdRelease(result->ResultmetaData); // if (result->metaData) fbcmdRelease(result->metaData); if (result->list) fbcplRelease(result->list); if (result->array) fbaRelease(result->array); if ( result->database) { for (i=0; i < result->database->resultCount; i++) { if (result->database->results[i] == result) { result->database->results[i] = NULL; break; } } phpfbReleaseDatabase(result->database); } if (result->link) { for (i=0; i < result->link->resultCount; i++) { if (result->link->results[i] == result) { result->link->results[i] = NULL; break; } } phpfbReleaseLink(result->link); } result->link = 0; result->database = 0; result->connection = NULL; result->fetchHandle = NULL; result->metaData = NULL; result->rowHandler = NULL; result->batchSize = 0; result->rowCount = -1; result->rowIndex = 0; result->columnIndex = 0; result->row = NULL; result->array = NULL; result->list = NULL; free(result); } } } PHPFBDatabase* phpfbRetainDatabase ( PHPFBDatabase* database ) { if (database) database->retainCount++; return database; } void phpfbReleaseDatabase ( PHPFBDatabase* database ) { if (database) { database->retainCount--; //printf("Release database %x %d %d\n", database, database->index, database->retainCount); if (database->retainCount == 0) { unsigned int i; // if (FB_SQL_G(databaseIndex == database->index) FB_SQL_G(databaseIndex = 0; if (database->link) { for (i=0; i < database->link->databaseCount; i++) { if (database->link->databases[i] == database) { database->link->databases[i] = NULL; break; } } phpfbReleaseLink(database->link); } fbcdcClose(database->connection); fbcdcRelease(database->connection); free(database->databaseName); free(database->databasePassword); free(database->results); free(database); } } } PHPFBLink* phpfbRetainLink ( PHPFBLink* link) { if (link) link->retainCount++; return link; } void phpfbReleaseLink ( PHPFBLink* link) { // printf("Release %x %d %d\n",link,link->index,link->retainCount); if (link) { link->retainCount--; //printf("Release link %x %d %d\n", link, link->index, link->retainCount); if (link->retainCount == 0) { // if (link->index == FB_SQL_G(linkIndex) FB_SQL_G(linkIndex = 0; free(link->hostName); free(link->userName); free(link->userPassword); if (link->results) free(link->results); if (link->databases) free(link->databases); free(link); } } } PHPFBResult* phpfbQuery (INTERNAL_FUNCTION_PARAMETERS, char* sql, PHPFBDatabase* database); PHP_INI_BEGIN() STD_PHP_INI_BOOLEAN ("fbsql.allow_persistant", "1" , PHP_INI_SYSTEM, OnUpdateInt, allowPersistent, zend_fbsql_globals, fbsql_globals) STD_PHP_INI_BOOLEAN ("fbsql.generate_warnings", "0", PHP_INI_SYSTEM, OnUpdateInt, generateWarnings, zend_fbsql_globals, fbsql_globals) STD_PHP_INI_BOOLEAN ("fbsql.autocommit", "1", PHP_INI_SYSTEM, OnUpdateInt, autoCommit, zend_fbsql_globals, fbsql_globals) STD_PHP_INI_ENTRY_EX ("fbsql.max_persistent", "-1", PHP_INI_SYSTEM, OnUpdateInt, maxPersistant, zend_fbsql_globals, fbsql_globals, display_link_numbers) STD_PHP_INI_ENTRY_EX ("fbsql.max_links", "128", PHP_INI_SYSTEM, OnUpdateInt, maxLinks, zend_fbsql_globals, fbsql_globals, display_link_numbers) STD_PHP_INI_ENTRY_EX ("fbsql.max_connections", "128", PHP_INI_SYSTEM, OnUpdateInt, maxConnections, zend_fbsql_globals, fbsql_globals, display_link_numbers) STD_PHP_INI_ENTRY_EX ("fbsql.max_results", "128", PHP_INI_SYSTEM, OnUpdateInt, maxResults, zend_fbsql_globals, fbsql_globals, display_link_numbers) STD_PHP_INI_ENTRY_EX ("fbsql.mbatchSize", "1000", PHP_INI_SYSTEM, OnUpdateInt, batchSize, zend_fbsql_globals, fbsql_globals, display_link_numbers) STD_PHP_INI_ENTRY ("fbsql.default_host", NULL, PHP_INI_SYSTEM, OnUpdateString, hostName, zend_fbsql_globals, fbsql_globals) STD_PHP_INI_ENTRY ("fbsql.default_user", "_SYSTEM", PHP_INI_SYSTEM, OnUpdateString, userName, zend_fbsql_globals, fbsql_globals) STD_PHP_INI_ENTRY ("fbsql.default_password", "", PHP_INI_SYSTEM, OnUpdateString, userPassword, zend_fbsql_globals, fbsql_globals) STD_PHP_INI_ENTRY ("fbsql.default_database", "", PHP_INI_SYSTEM, OnUpdateString, databaseName, zend_fbsql_globals, fbsql_globals) STD_PHP_INI_ENTRY ("fbsql.default_database_password", "", PHP_INI_SYSTEM, OnUpdateString, databasePassword, zend_fbsql_globals, fbsql_globals) PHP_INI_END() static void php_fbsql_init_globals(zend_fbsql_globals *fbsql_globals) { fbsql_globals->persistantCount = 0; if (fbsql_globals->hostName==NULL) { char name[256]; gethostname(name,sizeof(name)); name[sizeof(name)-1] = 0; fbsql_globals->hostName = strdup(name); } // fbsql_globals->userName = strdup(fbsql_globals->userName); // fbsql_globals->userPassword = strdup(fbsql_globals->userPassword); // fbsql_globals->databaseName = strdup(fbsql_globals->databaseName); // fbsql_globals->databasePassword = strdup(fbsql_globals->databasePassword); fbsql_globals->persistantCount = 0; fbsql_globals->linkCount = 0; fbsql_globals->resultCount = 0; fbsql_globals->linkIndex = 0; fbsql_globals->databaseIndex = 0; fbsql_globals->resultIndex = 0; } PHP_MINIT_FUNCTION(fbsql) { ZEND_INIT_MODULE_GLOBALS(fbsql, php_fbsql_init_globals, NULL); REGISTER_INI_ENTRIES(); fbcInitialize(); le_result = register_list_destructors(phpfbReleaseResult,NULL); le_link = register_list_destructors(phpfbReleaseLink,NULL); le_dba = register_list_destructors(phpfbReleaseDatabase,NULL); REGISTER_LONG_CONSTANT("FBSQL_ASSOC", FBSQL_ASSOC, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("FBSQL_NUM", FBSQL_NUM, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("FBSQL_BOTH", FBSQL_BOTH, CONST_CS | CONST_PERSISTENT); return SUCCESS; } PHP_MSHUTDOWN_FUNCTION(fbsql) { UNREGISTER_INI_ENTRIES(); return SUCCESS; } PHP_RINIT_FUNCTION(fbsql) { return SUCCESS; } PHP_MINFO_FUNCTION(fbsql) { char buf[32]; FBSQLLS_FETCH(); php_info_print_table_start(); php_info_print_table_header(2, "FrontBase support", "enabled"); php_info_print_table_row(2, "Client API version", "2.20" ); if (FB_SQL_G(allowPersistent)) { sprintf(buf, "%ld", FB_SQL_G(persistantCount)); php_info_print_table_row(2, "Active Persistant Links", buf); } sprintf(buf, "%ld", FB_SQL_G(linkCount)); php_info_print_table_row(2, "Active Links", buf); sprintf(buf, "%ld", FB_SQL_G(resultCount)); php_info_print_table_row(2, "Active Result Sets", buf); php_info_print_table_end(); DISPLAY_INI_ENTRIES(); } PHPFBLink* phpfbConnect ( INTERNAL_FUNCTION_PARAMETERS, char* hostName, char* userName, char* userPassword, int persistant ) { // Ref count databases and links!! // Search for the database/link in the hash plist and in the hashed list // If a link was non persistant then an is opened peristant just insert it // in the persistant list // // Insert the persistant in the list and in the hash p list // Insert the non persistant in the PHPFBLink* result; list_entry *lep; int type; char name[1024]; FBSQLLS_FETCH(); if (hostName == NULL) hostName = FB_SQL_G(hostName); if (userName == NULL) userName = FB_SQL_G(userName); if (userPassword == NULL) userPassword = FB_SQL_G(userPassword); //printf("Connection %s %s\n",hostName,userName); sprintf(name,"fbsql_%s_%s",hostName,userName); //printf("Hash find '%s'",name); if(zend_hash_find(&EG(persistent_list), name, strlen(name), (void **) &lep) == SUCCESS) { PHPFBLink* lnk; result = lep->ptr; lnk = zend_list_find(result->index,&type); if (lnk != result) result->index = zend_list_insert(result, le_link); //printf(" Persistant %x %d \n",result,result->index); } else if(zend_hash_find (&EG(regular_list),name,strlen(name),(void **)&lep) == SUCCESS) { result = lep->ptr; //printf(" Non persistant %x %d \n",result,result->index); } else if ( FB_SQL_G(linkCount) == FB_SQL_G(maxLinks)) { php_error(E_WARNING,"FrontBase link limit %d exceeded ", FB_SQL_G(maxLinks)); return NULL; } else { FBCExecHandler* execHandler = fbcehHandlerForHost(hostName,128); list_entry le; if (execHandler == NULL) { php_error(E_WARNING,"Cannot connect to host '%s'",hostName); php_error(E_WARNING,fbcehClassErrorMessage()); return NULL; } result = malloc(sizeof(PHPFBLink)); result->retainCount = 1; result->persistant = persistant; result->hostName = strdup(hostName); result->userName = strdup(userName); result->userPassword = strdup(userPassword); result->execHandler = execHandler; result->affectedRows = 0; result->autoCommit = FB_SQL_G(autoCommit); result->currentDatabase = NULL; result->databaseCount = 0; result->databases = NULL; result->resultCount = 0; result->results = NULL; le.ptr = result; le.type = le_link; if (zend_hash_update(persistant?&EG(persistent_list):&EG(regular_list), name, strlen(name), &le, sizeof(le), NULL)==FAILURE) { phpfbReleaseLink(result); return NULL; } result->index = zend_list_insert (phpfbRetainLink(result), le_link); FB_SQL_G(linkCount)++; //printf(" new %x %d \n",result,result->index); //printf("Ny connection %x %x\n",result,result->execHandler); } return result; } int phpfbFetchRow ( PHPFBResult* result, int row) { if (result->rowHandler == NULL) { void *rawData = fbcdcFetch(result->connection,result->batchSize,result->fetchHandle); if (rawData == NULL) result->rowCount = 0; else result->rowHandler = fbcrhInitWith(rawData, result->metaData); } for (;;) { void *rawData; if ( row >= result->rowCount) return 0; if (fbcrhRowCount(result->rowHandler) > (unsigned int)row) return 1; rawData = fbcdcFetch(result->connection,result->batchSize,result->fetchHandle); if (!fbcrhAddBatch(result->rowHandler,rawData)) result->rowCount = fbcrhRowCount(result->rowHandler); } return 0; } // int fbsql_connect(string [hostname] , string [username] , string [password] ); void phpfbDoConnect(INTERNAL_FUNCTION_PARAMETERS,int persistant) { PHPFBLink* result; char* hostName = NULL; char* userName = NULL; char* userPassword = NULL; int argc = ARG_COUNT(ht); pval* argv[3]; FBSQLLS_FETCH(); if ((argc < 0 ) || (argc > 3)) WRONG_PARAM_COUNT; if (zend_get_parameters(ht,argc,&argv[0],&argv[1],&argv[2])==FAILURE) RETURN_FALSE; if (argc >= 1) { convert_to_string(argv[0]); hostName = argv[0]->value.str.val; } if (argc >= 2 ) { convert_to_string(argv[1]); userName = argv[1]->value.str.val; } if (argc == 3 ) { convert_to_string(argv[2]); userPassword = argv[2]->value.str.val; } result = phpfbConnect(INTERNAL_FUNCTION_PARAM_PASSTHRU,hostName,userName,userPassword,persistant); if (result == NULL) RETURN_FALSE; FB_SQL_G(linkIndex) = result->index; return_value->value.lval = result->index; return_value->type = IS_LONG; } // int fbsql_connect(string [hostname] , string [username] , string [password] ); PHP_FUNCTION(fbsql_connect) { phpfbDoConnect(INTERNAL_FUNCTION_PARAM_PASSTHRU,0); } // int fbsql_pconnect(string [hostname] , string [username] , string [password] ); PHP_FUNCTION(fbsql_pconnect) { phpfbDoConnect(INTERNAL_FUNCTION_PARAM_PASSTHRU,1); } PHPFBLink* phpfbGetLink(int id) { int type; PHPFBLink* phpLink = NULL; FBSQLLS_FETCH(); if (id == 0 ) { php_error(E_WARNING,"FrontBase has no default connection"); } else if ((!(phpLink = (PHPFBLink*) zend_list_find (id,&type))) || (( type != le_link))) { php_error(E_WARNING,"%d is not a FBSQL link index",id); phpLink = NULL; } return phpLink; } PHPFBResult* phpfbGetResult(int id) { int type; PHPFBResult* result = NULL; FBSQLLS_FETCH(); if (id == 0 ) { php_error(E_WARNING,"FBSQL no default result"); } else if ((!(result = (PHPFBResult*) zend_list_find (id,&type))) || (( type != le_result))) { php_error(E_WARNING,"%d is not a FBSQL result index",id); result = NULL; } return result; } // int fbsql_close([int link_identifier]) PHP_FUNCTION(fbsql_close) { int argc = ARG_COUNT(ht); unsigned i,j; char name[1024]; PHPFBLink* phpLink = NULL; pval* argv[1]; FBSQLLS_FETCH(); if ((argc < 0 ) || (argc > 1 )) WRONG_PARAM_COUNT; if (zend_get_parameters(ht,argc, &argv[0])==FAILURE) RETURN_FALSE; if (argc == 1) { convert_to_long(argv[0]); phpLink = phpfbGetLink(argv[0]->value.lval); } else if (FB_SQL_G(linkIndex) != 0) { phpLink = phpfbGetLink(FB_SQL_G(linkIndex)); } if (phpLink == NULL) RETURN_FALSE; for (i=0; i < phpLink->databaseCount; i++) { PHPFBDatabase* database = phpLink->databases[i]; if (database) { for (j=0; j < database->resultCount; j++) if (database->results[j]) { zend_list_delete (database->results[j]->index); FB_SQL_G(resultCount)--; } zend_list_delete (database->index); FB_SQL_G(databaseCount)--; } } sprintf(name,"fbsql_%s_%s",phpLink->hostName,phpLink->userName); FB_SQL_G(linkCount)--; if (phpLink->persistant)FB_SQL_G(persistantCount)--; zend_hash_del (&EG(regular_list),name,strlen(name)); zend_list_delete(phpLink->index); RETURN_TRUE; } // int fbsql_select_db(string database_name [, int link_identifier] PHPFBDatabase* phpfbSelectDB ( INTERNAL_FUNCTION_PARAMETERS, char* databaseName, char* databasePassword, PHPFBLink* link ) { PHPFBDatabase* result = NULL; list_entry *lep; unsigned i; char name[1024]; FBSQLLS_FETCH(); sprintf(name,"fbsql_%s@%s:%s",databaseName,link->hostName,link->userName); if(zend_hash_find(&EG(persistent_list),name,strlen(name),(void **)&lep) == SUCCESS) { PHPFBDatabase* dba; int type; result = lep->ptr; dba = zend_list_find(result->index,&type); if (dba != result) result->index = zend_list_insert(result, le_dba); } else if(zend_hash_find(&EG(regular_list),name,strlen(name),(void **)&lep) == SUCCESS) { result = lep->ptr; } else if (FB_SQL_G(databaseCount) == FB_SQL_G(maxConnections)) { php_error(E_WARNING,"FrontBase connection limit %d exceeded", FB_SQL_G(maxConnections)); return NULL; } else { list_entry le; FBCDatabaseConnection* c = fbcdcConnectToDatabase(databaseName,link->hostName,databasePassword); FBCMetaData* md; if (c == NULL) { php_error(E_WARNING, fbcdcClassErrorMessage()); return NULL; } md = fbcdcCreateSession(c,"PHP",link->userName,link->userPassword,link->userName); if (fbcmdErrorsFound(md)) { FBCErrorMetaData* emd = fbcdcErrorMetaData(c,md); char* emg = fbcemdAllErrorMessages(emd); if (emg) php_error(E_WARNING, emg); else php_error(E_WARNING,"No message"); free(emg); fbcemdRelease(emd); fbcmdRelease(md); fbcdcClose(c); fbcdcRelease(c); return NULL; } fbcmdRelease(md); if (c) { if (link->autoCommit) md = fbcdcExecuteDirectSQL(c,"SET COMMIT TRUE;"); else md = fbcdcExecuteDirectSQL(c,"SET COMMIT FALSE;"); fbcmdRelease(md); } fbcdcSetOutputCharacterSet(c,FBC_ISO8859_1); fbcdcSetInputCharacterSet(c,FBC_ISO8859_1); le.type = le_dba; le.ptr = result = malloc(sizeof(PHPFBDatabase)); if (zend_hash_update(link->persistant?&EG(persistent_list):&EG(regular_list), name, strlen(name), &le, sizeof(le), NULL)==FAILURE) { fbcdcClose(c); fbcdcRelease(c); free(result); //printf("Returning Null\n"); return NULL; } result->retainCount = 2; result->index = zend_list_insert((PHPFBDatabase*)(le.ptr), le_dba); result->link = phpfbRetainLink(link); result->databaseName = strdup(databaseName); result->databasePassword = strdup(databasePassword); result->connection = c; result->errorNo = 0; result->errorText = NULL; result->resultCount = 0; result->rowIndex = 0; result->results = NULL; for (i=0; i < link->databaseCount; i++) if ((link->databases[i]) == NULL) break; if (i==link->databaseCount) { unsigned j; link->databaseCount += 5; link->databases = realloc(link->databases,sizeof(PHPFBDatabase*)*link->databaseCount); for (j=i; j < link->databaseCount; j++) link->databases[j] = NULL; } link->databases[i] = result; FB_SQL_G(databaseCount)++; // printf("Return database %x %x\n",result,c); } link->currentDatabase = result; return_value->value.lval = result->index; return_value->type = IS_LONG; FB_SQL_G(databaseIndex) = result->index; return result; } void phpfbestrdup (const char * s, int* length, char** value ) { int l = s?strlen(s):0; if (value) { char* r = emalloc(l+1); if (s) strcpy(r,s); else r[0] = 0; *value = r; } *length = l; } // bool fbsql_list_autocommit(int link_identifier [, bool OnOff]) PHP_FUNCTION(fbsql_autocommit) { int argc = ARG_COUNT(ht); pval* argv[2]; PHPFBLink* phpLink = NULL; FBCMetaData* md; zend_bool OnOff; FBSQLLS_FETCH(); if ((argc < 1 ) || (argc > 2 )) WRONG_PARAM_COUNT; if (zend_get_parameters(ht,argc,&argv[0],&argv[1])==FAILURE) RETURN_FALSE; convert_to_long(argv[0]); phpLink = phpfbGetLink(argv[0]->value.lval); if (argc == 2 ) { convert_to_boolean(argv[1]); OnOff = Z_BVAL_P(argv[1]); if (OnOff) md = fbcdcExecuteDirectSQL(phpLink->currentDatabase->connection , "SET COMMIT TRUE;"); else md = fbcdcExecuteDirectSQL(phpLink->currentDatabase->connection, "SET COMMIT FALSE;"); fbcmdRelease(md); RETURN_TRUE; } else { RETURN_BOOL(phpLink->autoCommit); } } // int fbsql_list_commit([int link_identifier]) PHP_FUNCTION(fbsql_commit) { int argc = ARG_COUNT(ht); pval* argv[1]; PHPFBLink* phpLink = NULL; FBCMetaData* md; int link; FBSQLLS_FETCH(); link = FB_SQL_G(linkIndex); if ((argc < 0 ) || (argc > 1 )) WRONG_PARAM_COUNT; if (zend_get_parameters(ht,argc,&argv[0],&argv[1])==FAILURE) RETURN_FALSE; if (argc == 1 ) { convert_to_long(argv[0]); link = argv[0]->value.lval; } phpLink = phpfbGetLink(link); if (phpLink == NULL) RETURN_FALSE; md = fbcdcCommit(phpLink->currentDatabase->connection); if (md) { fbcmdRelease(md); RETURN_TRUE; } else RETURN_FALSE; } // int fbsql_list_rollback([int link_identifier]) PHP_FUNCTION(fbsql_rollback) { int argc = ARG_COUNT(ht); pval* argv[1]; PHPFBLink* phpLink = NULL; FBCMetaData* md; int link; FBSQLLS_FETCH(); link = FB_SQL_G(linkIndex); if ((argc < 0 ) || (argc > 1 )) WRONG_PARAM_COUNT; if (zend_get_parameters(ht,argc,&argv[0],&argv[1])==FAILURE) RETURN_FALSE; if (argc == 1 ) { convert_to_long(argv[0]); link = argv[0]->value.lval; } phpLink = phpfbGetLink(link); if (phpLink == NULL) RETURN_FALSE; md = fbcdcRollback(phpLink->currentDatabase->connection); if (md) { fbcmdRelease(md); RETURN_TRUE; } else RETURN_FALSE; } // string fbsql_hostname([string host_name]) PHP_FUNCTION(fbsql_hostname) { int argc = ARG_COUNT(ht); pval* argv[1]; FBSQLLS_FETCH(); if ((argc < 0) || (argc > 1 )) WRONG_PARAM_COUNT; if (zend_get_parameters(ht,argc, &argv[0])==FAILURE) RETURN_FALSE; phpfbestrdup(FB_SQL_G(hostName), &return_value->value.str.len, &return_value->value.str.val); return_value->type = IS_STRING; if (argc >= 1) { convert_to_string(argv[0]); free(FB_SQL_G(hostName)); FB_SQL_G(hostName) = strdup(argv[0]->value.str.val); } } // string fbsql_database([string database]) PHP_FUNCTION(fbsql_database) { int argc = ARG_COUNT(ht); pval* argv[1]; FBSQLLS_FETCH(); if ((argc < 0) || (argc > 1 )) WRONG_PARAM_COUNT; if (zend_get_parameters(ht,argc, &argv[0])==FAILURE) RETURN_FALSE; phpfbestrdup(FB_SQL_G(databaseName), &return_value->value.str.len, &return_value->value.str.val); return_value->type = IS_STRING; if (argc >= 1) { convert_to_string(argv[0]); free(FB_SQL_G(databaseName)); FB_SQL_G(databaseName) = strdup(argv[0]->value.str.val); } } // string fbsql_database_password([string database_password]) PHP_FUNCTION(fbsql_database_password) { int argc = ARG_COUNT(ht); pval* argv[1]; FBSQLLS_FETCH(); if ((argc < 0) || (argc > 1 )) WRONG_PARAM_COUNT; if (zend_get_parameters(ht,argc, &argv[0])==FAILURE) RETURN_FALSE; if (argc >= 1) { convert_to_string(argv[0]); free(FB_SQL_G(hostName)); FB_SQL_G(databasePassword) = strdup(argv[0]->value.str.val); } } // string fbsql_username([string username]) PHP_FUNCTION(fbsql_username) { int argc = ARG_COUNT(ht); pval* argv[1]; FBSQLLS_FETCH(); if ((argc < 0) || (argc > 1 )) WRONG_PARAM_COUNT; if (zend_get_parameters(ht,argc, &argv[0])==FAILURE) RETURN_FALSE; phpfbestrdup(FB_SQL_G(userName), &return_value->value.str.len, &return_value->value.str.val); return_value->type = IS_STRING; if (argc >= 1) { convert_to_string(argv[0]); free(FB_SQL_G(userName)); FB_SQL_G(userName) = strdup(argv[0]->value.str.val); } } // string fbsql_username([string password]) PHP_FUNCTION(fbsql_password) { int argc = ARG_COUNT(ht); pval* argv[1]; FBSQLLS_FETCH(); if ((argc < 0) || (argc > 1 )) WRONG_PARAM_COUNT; if (zend_get_parameters(ht,argc, &argv[0])==FAILURE) RETURN_FALSE; if (argc >= 1) { convert_to_string(argv[0]); free(FB_SQL_G(userPassword)); FB_SQL_G(userPassword) = strdup(argv[0]->value.str.val); } } // int fbsql_select_db([string database_name [, int link_identifier]]) PHP_FUNCTION(fbsql_select_db) { int argc = ARG_COUNT(ht); pval* argv[2]; char* name; PHPFBLink* phpLink = NULL; PHPFBDatabase* database = NULL; FBSQLLS_FETCH(); name = FB_SQL_G(databaseName); if ((argc < 1) || (argc > 2 )) WRONG_PARAM_COUNT; if (zend_get_parameters(ht,argc, &argv[0],&argv[1])==FAILURE) RETURN_FALSE; if (argc >= 1) { convert_to_string(argv[0]); name = argv[0]->value.str.val; } if (argc >= 2 ) { convert_to_long(argv[1]); phpLink = phpfbGetLink(argv[1]->value.lval); } else if (FB_SQL_G(linkIndex) == 0 ) { phpLink = phpfbConnect(INTERNAL_FUNCTION_PARAM_PASSTHRU,NULL,NULL,NULL,0); } else { phpLink = phpfbGetLink(FB_SQL_G(linkIndex)); } if (phpLink == NULL) RETURN_FALSE; //printf("Select db at link %s@%s\n",phpLink->hostName,phpLink->userName); database = phpfbSelectDB(INTERNAL_FUNCTION_PARAM_PASSTHRU,name,"",phpLink); if (database == NULL) RETURN_FALSE; phpLink->currentDatabase = database; FB_SQL_G(linkIndex) = phpLink->index; return_value->value.lval = database->index; return_value->type = IS_LONG; } // int fbsql_change_user(string user, string password, string [database] , int [link_identifier] ); PHP_FUNCTION(fbsql_change_user) { int argc = ARG_COUNT(ht); pval* argv[4]; int link; PHPFBLink* phpLink; PHPFBDatabase * phpDatabase; char* userName; char* userPassword; char* databaseName; FBSQLLS_FETCH(); link = FB_SQL_G(linkIndex); databaseName = FB_SQL_G(databaseName); if ((argc < 2) || (argc > 4)) WRONG_PARAM_COUNT; if (zend_get_parameters(ht,argc,&argv[0],&argv[1],&argv[2],&argv[3])==FAILURE) RETURN_FALSE; convert_to_string(argv[0]); userName = argv[0]->value.str.val; convert_to_string(argv[1]); userPassword = argv[1]->value.str.val; if (argc >= 3) { convert_to_string(argv[2]); databaseName = argv[2]->value.str.val; } if (argc >= 4) { convert_to_long(argv[3]); link = argv[3]->value.lval; } if ((phpLink = phpfbGetLink(link))==NULL) RETURN_FALSE; if ((phpDatabase = phpfbSelectDB(INTERNAL_FUNCTION_PARAM_PASSTHRU,databaseName,"",phpLink)) == NULL) RETURN_FALSE; { char buffer[1024]; sprintf(buffer,"SET AUTHORIZATION %s;",userName); phpfbQuery(INTERNAL_FUNCTION_PARAM_PASSTHRU,buffer, phpDatabase); if (return_value->value.lval) { free(phpLink->userName); phpLink->userName = strdup(userName); } } } // int fbsql_create_db([string database_name [, int link_identifier]]) PHP_FUNCTION(fbsql_create_db) { PHPFBLink* phpLink = NULL; int i; int argc = ARG_COUNT(ht); pval* argv[2]; int link; char* databaseName; char* hostName; FBDatabaseStatus status; FBSQLLS_FETCH(); link = FB_SQL_G(linkIndex); hostName = FB_SQL_G(hostName); if ((argc < 1) || (argc > 2)) WRONG_PARAM_COUNT; if (zend_get_parameters(ht,argc,&argv[0],&argv[1])==FAILURE) RETURN_FALSE; convert_to_string(argv[0]); databaseName = argv[0]->value.str.val; if (argc == 2 ) { convert_to_long(argv[1]); link = argv[1]->value.lval; phpLink = phpfbGetLink(link); if (phpLink == NULL) RETURN_FALSE; } if (phpLink == NULL) { phpLink = phpfbConnect(INTERNAL_FUNCTION_PARAM_PASSTHRU,NULL,NULL,NULL,0); if (phpLink == NULL) RETURN_FALSE; } status = fbcehStatusForDatabaseNamed(phpLink->execHandler,databaseName); if (status != FBUnknownStatus) { char* txt = "Unknown status"; if ( status == FBStopped ) txt = "stopped"; else if ( status == FBStarting ) txt = "starting"; else if ( status == FBRunning ) txt = "running"; else if ( status == FBStopping ) txt = "stopping"; else if ( status == FBNoExec ) txt = "no exec"; php_error(E_WARNING, "Could not create %s@%s, database is %s",databaseName,hostName,txt); RETURN_FALSE; } if (!fbcehCreateDatabaseNamedWithOptions(phpLink->execHandler, databaseName, "")) { char* error = fbechErrorMessage(phpLink->execHandler); php_error(E_WARNING, "Could not create %s@%s. %s.",databaseName,hostName,error); RETURN_FALSE; } for (i=0; i < 20; i++) { #ifdef PHP_WIN32 Sleep(1000); #else sleep(1); #endif status = fbcehStatusForDatabaseNamed(phpLink->execHandler,databaseName); if (status == FBRunning) break; } FB_SQL_G(linkIndex) = phpLink->index; if (status != FBRunning) { php_error(E_WARNING, "Database %s@%s created -- status unknown",databaseName,hostName); RETURN_FALSE; } RETURN_TRUE; } // int fbsql_drop_db(string database_name [, int link_identifier]) PHP_FUNCTION(fbsql_drop_db) { char* databaseName; int argc = ARG_COUNT(ht); pval* argv[2]; PHPFBLink* phpLink; FBDatabaseStatus status; int i; FBSQLLS_FETCH(); if ((argc < 1) || (argc > 2)) WRONG_PARAM_COUNT; if (zend_get_parameters(ht,argc,&argv[0],&argv[1],&argv[2])==FAILURE) RETURN_FALSE; convert_to_string(argv[0]); databaseName = argv[0]->value.str.val; if (argc == 2) { convert_to_long(argv[1]); phpLink = phpfbGetLink(argv[1]->value.lval); if (phpLink == NULL) RETURN_FALSE; } else { phpLink = phpfbGetLink(FB_SQL_G(linkIndex)); } if (phpLink == NULL) { phpLink = phpfbConnect(INTERNAL_FUNCTION_PARAM_PASSTHRU,NULL,NULL,NULL,0); if (phpLink) RETURN_FALSE; } status = fbcehStatusForDatabaseNamed(phpLink->execHandler,databaseName); if (status != FBStopped) { char* txt = "Unknown status"; if ( status == FBStopped ) txt = "stopped"; else if ( status == FBUnknownStatus ) txt = "nonexisting"; else if ( status == FBStarting ) txt = "starting"; else if ( status == FBRunning ) txt = "running"; else if ( status == FBStopping ) txt = "stopping"; else if ( status == FBNoExec ) txt = "no exec"; php_error(E_WARNING, "Could not drop %s@%s, database is %s.",databaseName,phpLink->hostName,txt); RETURN_FALSE; } if (! fbcehDeleteDatabaseNamed (phpLink->execHandler, databaseName)) { char* error = fbechErrorMessage(phpLink->execHandler); php_error(E_WARNING, "Could not drop %s@%s. %s.",databaseName,phpLink->hostName,error); RETURN_FALSE; } for (i=0; i < 20; i++) { #ifdef PHP_WIN32 Sleep(1000); #else sleep(1); #endif status = fbcehStatusForDatabaseNamed(phpLink->execHandler,databaseName); if (status == FBUnknownStatus) break; } if (status != FBUnknownStatus) { php_error(E_WARNING, "Database %s@%s dropped -- status unknown",databaseName,phpLink->hostName); RETURN_FALSE; } } // int fbsql_stop_db(string database_name [, int link_identifier]) PHP_FUNCTION(fbsql_stop_db) { PHPFBDatabase* phpDatabase; PHPFBLink* phpLink = NULL; FBDatabaseStatus status; char* databaseName; int argc = ARG_COUNT(ht); pval* argv[2]; int link; unsigned i; char name[1024]; FBSQLLS_FETCH(); link = FB_SQL_G(linkIndex); if ((argc < 0) || (argc > 2)) WRONG_PARAM_COUNT; if (zend_get_parameters(ht,argc,&argv[0],&argv[1],&argv[2])==FAILURE) RETURN_FALSE; convert_to_string(argv[0]); databaseName = argv[0]->value.str.val; if (argc == 2) { convert_to_long(argv[1]); link = argv[1]->value.lval; phpLink = phpfbGetLink(link); if (phpLink == NULL) RETURN_FALSE; } if (phpLink == NULL) { phpLink = phpfbConnect(INTERNAL_FUNCTION_PARAM_PASSTHRU,NULL,NULL,NULL,0); if (phpLink == NULL) RETURN_FALSE; } phpDatabase = phpfbSelectDB(INTERNAL_FUNCTION_PARAM_PASSTHRU, databaseName,"",phpLink); if (phpDatabase == NULL) RETURN_FALSE; //printf("Stop db %x\n",phpDatabase->connection); if (!fbcdcStopDatabase(phpDatabase->connection)) { php_error(E_WARNING, "Cannot stop database %s@%s",databaseName,phpLink->hostName); RETURN_FALSE; } for (i=0; i < 20; i++) { status = fbcehStatusForDatabaseNamed(phpLink->execHandler,databaseName); if (status == FBStopped) break; #ifdef PHP_WIN32 Sleep(1000); #else sleep(1); #endif } for (i=0; i < phpLink->databaseCount; i++) if (phpLink->databases[i] == phpDatabase) phpLink->databases[i] = NULL; for (i=0; i < phpDatabase->resultCount; i++) if (phpDatabase->results[i]) { FB_SQL_G(resultCount)--; zend_list_delete(phpDatabase->results[i]->index); } // printf("Database %X %d %d\n",phpDatabase,phpDatabase->index,phpDatabase->retainCount); sprintf(name,"fbsql_%s@%s:%s",databaseName,phpLink->hostName, phpLink->userName); zend_list_delete(phpDatabase->index); FB_SQL_G(databaseCount)--; zend_hash_del(&EG(regular_list),name,strlen(name)); // printf("After list delete\n"); RETURN_TRUE; } // int fbsql_start_db(string database_name [, int link_identifier]) PHP_FUNCTION(fbsql_start_db) { PHPFBLink* phpLink = NULL; int i; int argc = ARG_COUNT(ht); pval* argv[2]; char* databaseName; char* hostName; FBDatabaseStatus status; FBSQLLS_FETCH(); hostName = FB_SQL_G(hostName); if ((argc < 1) || (argc > 2)) WRONG_PARAM_COUNT; if (zend_get_parameters(ht,argc,&argv[0],&argv[1])==FAILURE) RETURN_FALSE; convert_to_string(argv[0]); databaseName = argv[0]->value.str.val; if (argc >= 2 ) { convert_to_long(argv[1]); phpLink = phpfbGetLink(argv[1]->value.lval); } else if ( FB_SQL_G(linkIndex) == 0 ) { phpLink = phpfbConnect(INTERNAL_FUNCTION_PARAM_PASSTHRU,NULL,NULL,NULL,0); } else { phpLink = phpfbGetLink(FB_SQL_G(linkIndex)); } if (phpLink == NULL) RETURN_FALSE; //printf("Start db at link %s@%s\n",phpLink->hostName,phpLink->userName); status = fbcehStatusForDatabaseNamed(phpLink->execHandler,databaseName); if ((status != FBStopped) && (status != FBRunning) && ( status != FBStarting)) { char* txt = "Unknown status"; if ( status == FBStopped ) txt = "stopped"; else if ( status == FBStarting ) txt = "starting"; else if ( status == FBRunning ) txt = "running"; else if ( status == FBStopping ) txt = "stopping"; else if ( status == FBNoExec ) txt = "no exec"; php_error(E_WARNING, "Could not start %s@%s, as database is %s.",databaseName,hostName,txt); RETURN_FALSE; } if (status == FBStopped) { if (!fbcehStartDatabaseNamed (phpLink->execHandler, databaseName)) { char* error = fbechErrorMessage(phpLink->execHandler); php_error(E_WARNING, "Could not start %s@%s. %s.",databaseName,hostName,error); RETURN_FALSE; } } for (i=0; i < 20; i++) { #ifdef PHP_WIN32 Sleep(1000); #else sleep(1); #endif status = fbcehStatusForDatabaseNamed(phpLink->execHandler,databaseName); if (status == FBRunning) break; } if (status != FBRunning) { php_error(E_WARNING, "Database %s@%s started -- status unknown",databaseName,hostName); RETURN_FALSE; } RETURN_TRUE; } int mdOk(PHPFBDatabase* database, FBCMetaData* md ) { FBCDatabaseConnection* c = database->connection; int result = 1; FBSQLLS_FETCH(); database->errorNo = 0; if (database->errorText) { free(database->errorText); database->errorText = NULL; } if (md == NULL) { database->errorNo = 1; database->errorText = strdup("Connection was database server was lost"); if (FB_SQL_G(generateWarnings)) php_error(E_WARNING, database->errorText); result = 0; } else if (fbcmdErrorsFound(md)) { FBCErrorMetaData* emd = fbcdcErrorMetaData(c,md); char* emg = fbcemdAllErrorMessages(emd); if (FB_SQL_G(generateWarnings)) { if (emg) php_error(E_WARNING, emg); else php_error(E_WARNING,"No message"); } database->errorText = emg; database->errorNo = 1; fbcemdRelease(emd); result = 0; } return result; } PHPFBResult* phpfbQuery(INTERNAL_FUNCTION_PARAMETERS, char* sql, PHPFBDatabase* database ) { PHPFBLink* link = database->link; PHPFBResult* result = NULL; FBCMetaData* md, *meta; int ok; char* tp; char* fh; unsigned int sR = 1, cR = 0; FBSQLLS_FETCH(); meta = fbcdcExecuteDirectSQL(database->connection,sql); if (fbcmdHasMetaDataArray(meta)) { sR = fbcmdMetaDataArrayCount(meta); md = (FBCMetaData*)fbcmdMetaDataAtIndex(meta, cR); } else md = meta; ok = mdOk(database,md); tp = fbcmdStatementType(md); return_value->value.lval = ok?-1:0; return_value->type = IS_LONG; // printf("Result kind %s\n",tp); if (!ok || (tp[0] == 'C') || (tp[0] == 'R')) { unsigned i; for (i=0; i < database->resultCount; i++) { PHPFBResult* result = database->results[i]; if (result) { // printf("Delete from list %d %x",i,database->results[i],database->results[i]->index); zend_list_delete(database->results[i]->index); FB_SQL_G(databaseCount)--; database->results[i] = NULL; } } } else if (tp[0] == 'I') { database->rowIndex = fbcmdRowIndex(md); } else if ((fh = fbcmdFetchHandle(md)) && (FB_SQL_G(resultCount) == FB_SQL_G(maxResults))) { fbcdcCancelFetch(database->connection,fh); php_error(E_WARNING,"FrontBase result set limit %d exceeded",FB_SQL_G(maxResults)); } else if (fh || (tp[0] == 'E')) { unsigned i; result = malloc(sizeof(PHPFBResult)); result->retainCount = 1; result->index = zend_list_insert(result,le_result); result->link = NULL; result->database = phpfbRetainDatabase(database); result->connection = database->connection; result->fetchHandle = fh; result->ResultmetaData = meta; result->metaData = md; result->rowHandler = NULL; result->batchSize = FB_SQL_G(batchSize); result->rowCount = 0x7fffffff; result->columnCount = 0; result->rowIndex = 0; result->columnIndex = 0; result->row = NULL; result->array = NULL; result->list = NULL; result->selectResults = sR; result->currentResult = cR; FB_SQL_G(resultCount)++; for (i=0; i < database->resultCount; i++) if (database->results[i] == NULL) break; if (i == database->resultCount ) { unsigned j; database->resultCount += 5; database->results = realloc(database->results,sizeof(PHPFBResult*)*database->resultCount); for (j=i; j < database->resultCount; j++) database->results[j] = NULL; } database->results[i] = result; return_value->value.lval = result->index; if (tp[0] != 'E') { result->rowCount = 0x7fffffff; result->columnCount = fbcmdColumnCount(md); result->fetchHandle = fh; result->batchSize = FB_SQL_G(batchSize); } else { char* r = fbcmdMessage(result->metaData); if (( result->list = fbcplParse(r))) { result->rowCount = fbcplCount(result->list); result->columnCount = 7; } } } if (link) link->affectedRows = fbcmdRowCount(md); if (result == NULL) fbcmdRelease(md); return result; } // int fbsql_query(string query [, int link_identifier]) PHP_FUNCTION(fbsql_query) { PHPFBDatabase* phpDatabase; PHPFBLink* phpLink = NULL; PHPFBResult* phpResult; char* sql; int argc = ARG_COUNT(ht); pval* argv[2]; FBSQLLS_FETCH(); if ((argc < 1) || (argc > 2)) WRONG_PARAM_COUNT; if (zend_get_parameters(ht,argc,&argv[0],&argv[1])==FAILURE) RETURN_FALSE; convert_to_string(argv[0]); sql = argv[0]->value.str.val; if (argc >= 2 ) { convert_to_long(argv[1]); phpLink = phpfbGetLink(argv[1]->value.lval); } else if (FB_SQL_G(linkIndex) == 0 ) { phpLink = phpfbConnect(INTERNAL_FUNCTION_PARAM_PASSTHRU,NULL,NULL,NULL,0); } else { phpLink = phpfbGetLink(FB_SQL_G(linkIndex)); } if (phpLink == NULL) RETURN_FALSE; //printf("Query db at link %s@%s\n",phpLink->hostName,phpLink->userName); phpDatabase = phpLink->currentDatabase; if (phpDatabase == NULL) RETURN_FALSE; phpResult = phpfbQuery(INTERNAL_FUNCTION_PARAM_PASSTHRU,sql,phpDatabase); if (return_value->value.lval) { FB_SQL_G(linkIndex) = phpLink->index; if (phpResult) FB_SQL_G(resultIndex) = phpResult->index; } } // int fbsql_db_query(string database_name, string query [, int link_identifier]) PHP_FUNCTION(fbsql_db_query) { PHPFBDatabase* phpDatabase; PHPFBLink* phpLink; PHPFBResult* phpResult; char* sql; char* databaseName; int argc = ARG_COUNT(ht); pval* argv[3]; FBSQLLS_FETCH(); if ((argc < 2) || (argc > 3)) WRONG_PARAM_COUNT; if (zend_get_parameters(ht,argc,&argv[0],&argv[1],&argv[2])==FAILURE) RETURN_FALSE; convert_to_string(argv[0]); databaseName = argv[0]->value.str.val; convert_to_string(argv[1]); sql = argv[1]->value.str.val; if (argc >= 3 ) { convert_to_long(argv[2]); phpLink = phpfbGetLink(argv[2]->value.lval); } else if (FB_SQL_G(linkIndex) == 0 ) { phpLink = phpfbConnect(INTERNAL_FUNCTION_PARAM_PASSTHRU,NULL,NULL,NULL,0); } else { phpLink = phpfbGetLink(FB_SQL_G(linkIndex)); } if (phpLink == NULL) RETURN_FALSE; //printf("Query db at link %s@%s\n",phpLink->hostName,phpLink->userName); phpDatabase = phpfbSelectDB(INTERNAL_FUNCTION_PARAM_PASSTHRU, databaseName,"",phpLink); if ( phpDatabase == NULL) RETURN_FALSE; phpResult = phpfbQuery(INTERNAL_FUNCTION_PARAM_PASSTHRU,sql,phpDatabase); if (return_value->value.lval) { FB_SQL_G(linkIndex) = phpLink->index; if (phpResult) FB_SQL_G(resultIndex) = phpResult->index; } } // int fbsql_list_dbs([int link_identifier]) PHP_FUNCTION(fbsql_list_dbs) { PHPFBLink* phpLink = NULL; PHPFBResult* phpResult; unsigned i; int argc = ARG_COUNT(ht); pval* argv[1]; FBSQLLS_FETCH(); if ((argc < 0) || (argc > 1 )) WRONG_PARAM_COUNT; if (zend_get_parameters(ht,argc, &argv[0])==FAILURE) RETURN_FALSE; if (argc == 1 ) { convert_to_long(argv[0]); phpLink = phpfbGetLink(argv[0]->value.lval); } else if (FB_SQL_G(linkIndex) == 0 ) { phpLink = phpfbConnect(INTERNAL_FUNCTION_PARAM_PASSTHRU,NULL,NULL,NULL,0); } else { phpLink = phpfbGetLink(FB_SQL_G(linkIndex)); } if (phpLink == NULL) RETURN_FALSE; if (FB_SQL_G(resultCount) == FB_SQL_G(maxResults)) { php_error(E_WARNING,"FrontBase result set limit %d exceeded",FB_SQL_G(maxResults)); RETURN_FALSE } phpResult = malloc(sizeof(PHPFBResult)); phpResult->retainCount = 1; phpResult->index = zend_list_insert(phpResult, le_result); phpResult->link = phpfbRetainLink(phpLink); phpResult->database = NULL; phpResult->connection = NULL; phpResult->fetchHandle = NULL; phpResult->rowHandler = NULL; phpResult->metaData = NULL; phpResult->batchSize = FB_SQL_G(batchSize); phpResult->columnCount = 1; phpResult->rowIndex = 0; phpResult->columnIndex = 0; phpResult->row = NULL; phpResult->array = fbcehAvailableDatabases(phpLink->execHandler); phpResult->rowCount = fbaCount(phpResult->array); phpResult->list = NULL; FB_SQL_G(resultCount)++; for (i=0; i < phpLink->resultCount; i++) if (phpLink->results[i] == NULL) break; if (i == phpLink->resultCount ) { unsigned j; phpLink->resultCount += 5; phpLink->results = realloc( phpLink->results,sizeof(PHPFBResult*)* phpLink->resultCount); for (j=i; j < phpLink->resultCount ; j++)phpLink->results[j] = NULL; } phpLink->results[i] = phpResult; return_value->value.lval = phpResult->index; return_value->type = IS_LONG; FB_SQL_G(resultIndex) = phpResult->index; FB_SQL_G(linkIndex) = phpLink->index; } // int fbsql_list_tables(string database, int [link_identifier] ); PHP_FUNCTION(fbsql_list_tables) { PHPFBDatabase* phpDatabase; PHPFBLink* phpLink; PHPFBResult* phpResult; char* sql = "select t0.\"table_name\"from information_schema.tables t0, information_schema.SCHEMATA t1 where t0.schema_pk = t1.schema_pk and t1.\"schema_name\" = current_schema;"; char* databaseName = NULL; int argc = ARG_COUNT(ht); pval* argv[2]; FBSQLLS_FETCH(); if ((argc < 0) || (argc > 2)) WRONG_PARAM_COUNT; if (zend_get_parameters(ht,argc,&argv[0],&argv[1])==FAILURE) RETURN_FALSE; if ( argc >= 1 ) { convert_to_string(argv[0]); databaseName = argv[0]->value.str.val; } if (argc >= 2 ) { convert_to_long(argv[1]); phpLink = phpfbGetLink(argv[1]->value.lval); } else if (FB_SQL_G(linkIndex) == 0 ) { phpLink = phpfbConnect(INTERNAL_FUNCTION_PARAM_PASSTHRU,NULL,NULL,NULL,0); } else { phpLink = phpfbGetLink(FB_SQL_G(linkIndex)); } if (phpLink == NULL) RETURN_FALSE; if ( databaseName == NULL ) { phpLink->currentDatabase = phpfbSelectDB(INTERNAL_FUNCTION_PARAM_PASSTHRU, FB_SQL_G(databaseName),"",phpLink); } else { phpLink->currentDatabase = phpfbSelectDB(INTERNAL_FUNCTION_PARAM_PASSTHRU, databaseName,"",phpLink); } phpDatabase = phpLink->currentDatabase; if (phpDatabase == NULL) RETURN_FALSE; phpResult = phpfbQuery(INTERNAL_FUNCTION_PARAM_PASSTHRU,sql,phpDatabase); if (return_value->value.lval) { FB_SQL_G(linkIndex) = phpLink->index; if (phpResult) FB_SQL_G(resultIndex) = phpResult->index; } } //int fbsql_list_fields(string database_name, string table_name [, int link_identifier]) PHP_FUNCTION(fbsql_list_fields) { PHPFBDatabase* phpDatabase; PHPFBLink* phpLink; PHPFBResult* phpResult; char sql[1024]; char* databaseName = NULL; char* tableName = NULL; int argc = ARG_COUNT(ht); pval* argv[2]; FBSQLLS_FETCH(); if ((argc < 2) || (argc > 3)) WRONG_PARAM_COUNT; if (zend_get_parameters(ht,argc,&argv[0],&argv[1])==FAILURE) RETURN_FALSE; if ( argc >= 1 ) { convert_to_string(argv[0]); databaseName = argv[0]->value.str.val; } if ( argc >= 2 ) { convert_to_string(argv[1]); tableName = argv[1]->value.str.val; } if (argc >= 3 ) { convert_to_long(argv[2]); phpLink = phpfbGetLink(argv[2]->value.lval); } else if (FB_SQL_G(linkIndex) == 0 ) { phpLink = phpfbConnect(INTERNAL_FUNCTION_PARAM_PASSTHRU,NULL,NULL,NULL,0); } else { phpLink = phpfbGetLink(FB_SQL_G(linkIndex)); } if (phpLink == NULL) RETURN_FALSE; phpDatabase = phpfbSelectDB(INTERNAL_FUNCTION_PARAM_PASSTHRU, databaseName,"",phpLink); phpLink->currentDatabase = phpDatabase; if (phpDatabase == NULL) RETURN_FALSE; sprintf(sql,"EXTRACT TABLE %s;",tableName); phpResult = phpfbQuery(INTERNAL_FUNCTION_PARAM_PASSTHRU,sql,phpDatabase); if (return_value->value.lval) { FB_SQL_G(linkIndex) = phpLink->index; if (phpResult) FB_SQL_G(resultIndex) = phpResult->index; } } // string fbsql_error([int link_identifier]) PHP_FUNCTION(fbsql_error) { PHPFBLink* phpLink = NULL; PHPFBDatabase* phpDatabase; int argc = ARG_COUNT(ht); pval* argv[1]; FBSQLLS_FETCH(); if ((argc < 0 ) || (argc > 1)) WRONG_PARAM_COUNT; if (zend_get_parameters(ht,argc,&argv[0])==FAILURE) RETURN_FALSE; if (argc >= 1) { convert_to_long(argv[0]); phpLink = phpfbGetLink(argv[0]->value.lval); } else if (FB_SQL_G(linkIndex) != 0 ) { phpLink = phpfbGetLink(FB_SQL_G(linkIndex)); } if (phpLink == NULL) RETURN_FALSE; //printf("Query db at link %s@%s\n",phpLink->hostName,phpLink->userName); phpDatabase = phpLink->currentDatabase; if ((phpDatabase == NULL) || (phpDatabase->errorText == NULL)) RETURN_FALSE; phpfbestrdup(phpDatabase->errorText,&return_value->value.str.len,&return_value->value.str.val); return_value->type = IS_STRING; } // int fbsql_errno([int link_identifier]) PHP_FUNCTION(fbsql_errno) { PHPFBLink* phpLink = NULL; PHPFBDatabase* phpDatabase; int argc = ARG_COUNT(ht); pval* argv[1]; FBSQLLS_FETCH(); if ((argc < 0 ) || (argc > 1)) WRONG_PARAM_COUNT; if (zend_get_parameters(ht,argc,&argv[0])==FAILURE) RETURN_FALSE; if (argc >= 1) { convert_to_long(argv[0]); phpLink = phpfbGetLink(argv[0]->value.lval); } else if (FB_SQL_G(linkIndex) != 0 ) { phpLink = phpfbGetLink(FB_SQL_G(linkIndex)); } if (phpLink == NULL) RETURN_FALSE; //printf("Query db at link %s@%s\n",phpLink->hostName,phpLink->userName); phpDatabase = phpLink->currentDatabase; if (phpDatabase == NULL) RETURN_FALSE; return_value->value.lval = phpDatabase->errorNo; return_value->type = IS_LONG; } // int fbsql_generate_warnings( [int flag]); PHP_FUNCTION(fbsql_warnings) { int argc = ARG_COUNT(ht); pval* argv[1]; FBSQLLS_FETCH(); if ((argc < 0 ) || (argc > 1)) WRONG_PARAM_COUNT; if (zend_get_parameters(ht,argc,&argv[0])==FAILURE) RETURN_FALSE; return_value->value.lval = FB_SQL_G(generateWarnings); return_value->type = IS_LONG; if (argc >= 1) { convert_to_long(argv[0]); FB_SQL_G(generateWarnings) = argv[0]->value.lval != 0; } } //int fbsql_affected_rows([int link_identifier]) PHP_FUNCTION(fbsql_affected_rows) { PHPFBLink* phpLink; int argc = ARG_COUNT(ht); pval* argv[1]; int link; FBSQLLS_FETCH(); link = FB_SQL_G(linkIndex); if (argc > 1) WRONG_PARAM_COUNT; if (zend_get_parameters(ht,argc,&argv[0])==FAILURE) RETURN_FALSE; if (argc == 1 ) { convert_to_string(argv[0]); link = argv[0]->value.lval; } phpLink = phpfbGetLink(link); if (phpLink == NULL) RETURN_FALSE; return_value->value.lval = phpLink->affectedRows; return_value->type = IS_LONG; } // int fbsql_insert_id([int link_identifier]) PHP_FUNCTION(fbsql_insert_id) { PHPFBLink* phpLink; PHPFBDatabase* phpDatabase; int argc = ARG_COUNT(ht); pval* argv[1]; FBSQLLS_FETCH(); if ((argc < 0 ) || (argc > 1 )) WRONG_PARAM_COUNT; if (zend_get_parameters(ht,argc, &argv[0])==FAILURE) RETURN_FALSE; if (argc == 1 ) { convert_to_long(argv[0]); phpLink = phpfbGetLink(argv[0]->value.lval); } else if (FB_SQL_G(linkIndex) == 0 ) { phpLink = phpfbConnect(INTERNAL_FUNCTION_PARAM_PASSTHRU,NULL,NULL,NULL,0); } else { phpLink = phpfbGetLink(FB_SQL_G(linkIndex)); } if (phpLink == NULL) RETURN_FALSE; if ( phpLink->currentDatabase == NULL) { phpLink->currentDatabase = phpfbSelectDB(INTERNAL_FUNCTION_PARAM_PASSTHRU, FB_SQL_G(databaseName),"",phpLink); } phpDatabase = phpLink->currentDatabase; if (phpDatabase == NULL) RETURN_FALSE; return_value->value.lval = phpDatabase->rowIndex; return_value->type = IS_LONG; FB_SQL_G(linkIndex) = phpLink->index; } int phpSizeOfInt ( int i ) { int s = 1; if ( i < 0 ) { s++; i = -i; } while ((i = i / 10)) s++; return s; } void phpfbColumnAsString ( PHPFBResult* result, int column, void* data ,int* length, char** value) { FBCMetaData* md = result->metaData; const FBCDatatypeMetaData* dtmd = fbcmdDatatypeMetaDataAtIndex(md, column); unsigned dtc = fbcdmdDatatypeCode(dtmd); switch (dtc) { case FB_Boolean: { unsigned char v = *((unsigned char*)(data)); if (v == 255) phpfbestrdup("Unknown",length,value); else if (v == 0 ) phpfbestrdup("False",length,value); else phpfbestrdup("True",length,value); } break; case FB_PrimaryKey: case FB_Integer: { int v = *((int*)data); char b[128]; sprintf(b,"%d",v); phpfbestrdup(b,length,value); } break; case FB_SmallInteger: { short v = *((short*)data); char b[128]; sprintf(b,"%d",v); phpfbestrdup(b,length,value); } break; case FB_Float: case FB_Real: case FB_Double: case FB_Numeric: case FB_Decimal: { double v = *((double*)data); char b[128]; sprintf(b,"%f",v); phpfbestrdup(b,length,value); } break; case FB_Character: case FB_VCharacter: { char* v = (char*)data; phpfbestrdup(v,length,value); } break; case FB_Bit: case FB_VBit: { const FBCColumnMetaData* clmd = fbcmdColumnMetaDataAtIndex(md,column); struct bitValue { unsigned int nBytes; unsigned char* bytes; }; struct bitValue* ptr = data; unsigned nBits = ptr->nBytes * 8; if (dtc == FB_Bit) nBits = fbcdmdLength(fbccmdDatatype(clmd)); if (nBits %8 == 0 ) { unsigned i; unsigned int l = nBits / 8; *length = l + 5; if (value) { char* r = emalloc(l*2+3+1); r[0] = 'X'; r[1] = '\''; for ( i = 0; i < nBits / 8; i++) { char c[4]; sprintf(c,"%02x",ptr->bytes[i]); r[i*2+2] = c[0]; r[i*2+3] = c[1]; } r[i*2+2] = '\''; r[i*2+3] = 0; *value = r; } } else { unsigned i; unsigned int l = nBits; *length = l + 5; if (value) { char* r = emalloc(l*2+3+1); r[0] = 'B'; r[1] = '\''; for ( i = 0; i < nBits; i++) { int bit = 0; if (i/8 < ptr->nBytes) bit = ptr->bytes[i/8] & (1<<(7-(i%8))); r[i*2+2] = bit?'1':'0'; } r[i*2+2] = '\''; r[i*2+3] = 0; *value = r; } } } break; case FB_Date: case FB_Time: case FB_TimeTZ: case FB_Timestamp: case FB_TimestampTZ: { char* v = (char*)data; phpfbestrdup(v,length,value); } break; case FB_YearMonth: { char b[128]; int v = *((unsigned int*)data); sprintf(b,"%d",v); phpfbestrdup(b,length,value); } break; case FB_DayTime: { char b[128]; double seconds = *((double*)data); sprintf(b,"%f",seconds); phpfbestrdup(b,length,value); } break; case FB_CLOB: case FB_BLOB: // { // unsigned char* bytes = (unsigned char*)data; // if (*bytes == '\1') // { // Direct // unsigned int l = *((unsigned int*)(bytes+1)); // unsigned char* ptr = *((unsigned char**)(bytes+5)); // unsigned int i; // mf(file,"%4d:",l); // for (i=0; i < l; i++) // { // if (i) // { // if ((i % 32) == 0) mf(file,"\n %*d:",lw+4,i); // else if ((i % 4) == 0) mf(file," "); // } // mf(file,"%02x",*ptr++); // } // } // else //{ // mf(file,"%s",bytes+1); // } // } // break; default: php_error(E_WARNING,"Unimplemented type"); break; } } void phpfbSqlResult ( INTERNAL_FUNCTION_PARAMETERS, PHPFBResult* result, int rowIndex, int columnIndex ) { void** row; if (result->list) { FBCPList* columns = (FBCPList*)fbcplValueForKey(result->list,"COLUMNS"); FBCPList* column = (FBCPList*)fbcplValueAtIndex(columns,result->rowIndex); if ( columnIndex == 0 ) { // Name FBCPList* name = (FBCPList*)fbcplValueForKey(column,"NAME"); return_value->type = IS_STRING; phpfbestrdup(fbcplString(( FBCPList*)name), &return_value->value.str.len, &return_value->value.str.val); } else if ( columnIndex == 2 ) { // Length FBCPList* name = (FBCPList*)fbcplValueForKey(column,"WIDTH"); return_value->type = IS_STRING; phpfbestrdup((const char*)fbcplString(name), &return_value->value.str.len, &return_value->value.str.val); } else if ( columnIndex == 1 ) { // Type FBCPList* name = (FBCPList*)fbcplValueForKey(column,"DATATYPE"); return_value->type = IS_STRING; phpfbestrdup((const char*)fbcplString(name), &return_value->value.str.len, &return_value->value.str.val); } else if ( columnIndex == 3 ) { // Flags return_value->type = IS_STRING; phpfbestrdup("", &return_value->value.str.len, &return_value->value.str.val); } else { return_value->type = IS_STRING; phpfbestrdup("", &return_value->value.str.len, &return_value->value.str.val); } } else if (result->array) { // Special case for get dbs phpfbestrdup((char*)fbaObjectAtIndex(result->array,rowIndex), &return_value->value.str.len, &return_value->value.str.val); return_value->type = IS_STRING; } else if (!phpfbFetchRow(result,rowIndex)) { // php_error(E_WARNING,"No such row %d in result set %d",resultIndex+1,rowIndex); RETURN_FALSE; } else if (columnIndex >= result->columnCount) { php_error(E_WARNING,"No such column %d in result set %d",columnIndex,rowIndex); RETURN_FALSE; } else { row = fbcrhRowAtIndex(result->rowHandler,rowIndex); if (row == NULL) { RETURN_FALSE; } else if (row[columnIndex]) { phpfbColumnAsString(result,columnIndex,row[columnIndex],&return_value->value.str.len,&return_value->value.str.val); return_value->type = IS_STRING; } else { return_value->type = IS_NULL; } } } // int fbsql_result(int result, int row [, mixed field]) PHP_FUNCTION(fbsql_result) { int argc = ARG_COUNT(ht); pval* argv[3]; PHPFBResult* result; int resultIndex; int rowIndex; int columnIndex; FBSQLLS_FETCH(); resultIndex = FB_SQL_G(resultIndex); if ((argc < 0) || (argc > 3 )) WRONG_PARAM_COUNT; if (zend_get_parameters(ht,argc,&argv[0],&argv[1],&argv[2])==FAILURE) RETURN_FALSE; if (argc >= 1) { convert_to_long(argv[0]); resultIndex = argv[0]->value.lval; } result = phpfbGetResult(resultIndex); if (result == NULL) RETURN_FALSE; rowIndex = result->rowIndex; if (argc >= 2) { convert_to_long(argv[1]); rowIndex = argv[1]->value.lval; } columnIndex = result->columnIndex; if (argc == 3) { if ((argv[2]->type == IS_STRING) && (result->metaData)) { for (columnIndex =0; columnIndex < result->columnCount; columnIndex ++) { const FBCColumnMetaData* cmd = fbcmdColumnMetaDataAtIndex(result->metaData, columnIndex); const char* lbl = fbccmdLabelName(cmd); if (strcmp((char*)lbl, argv[2]->value.str.val) == 0 ) break; } if (columnIndex == result->columnCount) RETURN_FALSE; } else { convert_to_long(argv[2]); columnIndex = argv[2]->value.lval; if ( columnIndex < 0 ) { php_error(E_WARNING,"Illegal column index - %d",columnIndex); RETURN_FALSE; } } } phpfbSqlResult(INTERNAL_FUNCTION_PARAM_PASSTHRU,result,rowIndex,columnIndex); FB_SQL_G(resultIndex) = resultIndex; result->columnIndex++; if (result->columnIndex == result->columnCount) { result->rowIndex++; result->columnIndex = 0; } } // int fbsql_next_result(int result) PHP_FUNCTION(fbsql_next_result) { int argc = ARG_COUNT(ht); pval* argv[1]; PHPFBResult* result; int resultIndex; FBSQLLS_FETCH(); resultIndex = FB_SQL_G(resultIndex); if ((argc < 0) || (argc > 1 )) WRONG_PARAM_COUNT; if (zend_get_parameters(ht,argc,&argv[0])==FAILURE) RETURN_FALSE; convert_to_long(argv[0]); result = phpfbGetResult(argv[0]->value.lval); if (result == NULL) RETURN_FALSE; result->currentResult++; if (result->currentResult < result->selectResults) { if (result->fetchHandle) fbcdcCancelFetch(result->connection, result->fetchHandle); if (result->rowHandler) fbcrhRelease(result->rowHandler); result->metaData = (FBCMetaData*)fbcmdMetaDataAtIndex(result->ResultmetaData, result->currentResult); result->fetchHandle = fbcmdFetchHandle(result->metaData); result->rowHandler = NULL; result->batchSize = FB_SQL_G(batchSize); result->rowCount = 0x7fffffff; result->columnCount = fbcmdColumnCount(result->metaData);; result->rowIndex = 0; result->columnIndex = 0; result->row = NULL; result->array = NULL; result->list = NULL; if (result->database->link) result->database->link->affectedRows = fbcmdRowCount(result->metaData); RETURN_TRUE; } else { RETURN_FALSE; } } // int fbsql_num_rows(int result) PHP_FUNCTION(fbsql_num_rows) { int argc = ARG_COUNT(ht); pval* argv[1]; int resultIndex; PHPFBResult* result; int rowCount; FBSQLLS_FETCH(); resultIndex = FB_SQL_G(resultIndex); if ((argc < 0 ) || (argc > 1 )) WRONG_PARAM_COUNT; if (zend_get_parameters(ht,argc,&argv[0])==FAILURE) RETURN_FALSE; if (argc >= 1) { convert_to_long(argv[0]); resultIndex = argv[0]->value.lval; } result = phpfbGetResult(resultIndex); if (result == NULL) RETURN_FALSE; rowCount = fbcmdRowCount (result->metaData); if (rowCount == -1 ) { phpfbFetchRow(result,0x7fffffff); rowCount = result->rowCount; } return_value->value.lval = rowCount; return_value->type = IS_LONG; } // int fbsql_num_fields(int result) PHP_FUNCTION(fbsql_num_fields) { int argc = ARG_COUNT(ht); pval* argv[1]; int resultIndex; PHPFBResult* result; FBSQLLS_FETCH(); resultIndex = FB_SQL_G(resultIndex); if ((argc < 0 ) || (argc > 1 )) WRONG_PARAM_COUNT; if (zend_get_parameters(ht,argc,&argv[0])==FAILURE) RETURN_FALSE; if (argc >= 1) { convert_to_long(argv[0]); resultIndex = argv[0]->value.lval; } result = phpfbGetResult(resultIndex); if (result == NULL) RETURN_FALSE; return_value->value.lval = result->columnCount; return_value->type = IS_LONG; FB_SQL_G(resultIndex) = resultIndex; } // object fbsql_fetch_object(int result [, int result_typ]) PHP_FUNCTION(fbsql_fetch_object) { PHP_FN(fbsql_fetch_array)(INTERNAL_FUNCTION_PARAM_PASSTHRU); if (return_value->type==IS_ARRAY) { return_value->type=IS_OBJECT; return_value->value.obj.properties = return_value->value.ht; return_value->value.obj.ce = &zend_standard_class_def; } } // array fbsql_fetch_row(int result) PHP_FUNCTION(fbsql_fetch_row) { int argc = ARG_COUNT(ht); pval* argv[2]; int i; int resultIndex; PHPFBResult* result; int rowIndex ; void** row; FBSQLLS_FETCH(); resultIndex = FB_SQL_G(resultIndex); if ((argc < 0) || (argc > 1 )) WRONG_PARAM_COUNT; if (zend_get_parameters(ht,argc,&argv[0])==FAILURE) RETURN_FALSE; if (argc >= 1 ) { convert_to_long(argv[0]); resultIndex = argv[0]->value.lval; } result = phpfbGetResult(resultIndex); if (result == NULL) RETURN_FALSE; rowIndex = result->rowIndex; if (result->fetchHandle == NULL) { RETURN_FALSE; } if (result->rowCount == 0x7fffffff) { if (!phpfbFetchRow(result,rowIndex)) { RETURN_FALSE; } } if (!(row = fbcrhRowAtIndex(result->rowHandler,rowIndex))) { RETURN_FALSE; } if (array_init(return_value)==FAILURE) { RETURN_FALSE; } result->row = row; for (i=0; i < result->columnCount; i++) { char* value; unsigned int length; if (row[i]) { phpfbColumnAsString(result,i,row[i],&length,&value); add_index_stringl(return_value,i,value,length,0); } else { add_index_unset(return_value,i); } } result->rowIndex = rowIndex+1; result->columnIndex = 0; FB_SQL_G(resultIndex) = resultIndex; } // array fbsql_fetch_array(int result [, int result_typ]) PHP_FUNCTION(fbsql_fetch_array) { int argc = ARG_COUNT(ht); pval* argv[2]; int i; int resultIndex; PHPFBResult* result; int rowIndex; int result_type = FBSQL_BOTH; void** row; FBSQLLS_FETCH(); resultIndex = FB_SQL_G(resultIndex); if ((argc < 0) || (argc > 2 )) WRONG_PARAM_COUNT; if (zend_get_parameters(ht,argc,&argv[0],&argv[1])==FAILURE) RETURN_FALSE; if (argc >= 1) { convert_to_long(argv[0]); resultIndex = argv[0]->value.lval; } result = phpfbGetResult(resultIndex); if (result == NULL) RETURN_FALSE; rowIndex = result->rowIndex; if (argc == 2 ) { convert_to_long(argv[1]); result_type = argv[1]->value.lval; if (((result_type & FBSQL_NUM) != FBSQL_NUM) && ((result_type & FBSQL_ASSOC) != FBSQL_ASSOC)) { php_error(E_WARNING,"Illegal result type use FBSQL_NUM, FBSQL_ASSOC, or FBSQL_BOTH."); RETURN_FALSE; } } if (result->fetchHandle == NULL) { RETURN_FALSE; } if (result->rowCount == 0x7fffffff) { phpfbFetchRow(result,result->rowIndex); } row = fbcrhRowAtIndex(result->rowHandler,rowIndex); if (row == NULL) { RETURN_FALSE; } if (array_init(return_value)==FAILURE) { RETURN_FALSE; } for (i=0; i < result->columnCount; i++) { if (row[i]) { char* value; unsigned int length; unsigned int c = 0; phpfbColumnAsString(result,i,row[i],&length,&value); if (result_type & FBSQL_NUM) { add_index_stringl(return_value,i,value,length,c); c = 1; } if (result_type & FBSQL_ASSOC) { char* key = (char*)fbccmdLabelName(fbcmdColumnMetaDataAtIndex(result->metaData, i)); add_assoc_stringl(return_value,key, value, length, c); } } else { if (result_type & FBSQL_NUM) { add_index_unset(return_value,i); } if (result_type & FBSQL_ASSOC) { char* key = (char*)fbccmdLabelName(fbcmdColumnMetaDataAtIndex(result->metaData, i)); add_assoc_unset(return_value,key); } } } result->rowIndex = result->rowIndex+1; result->columnIndex = 0; } // int fbsql_data_seek(int result, int row_number) PHP_FUNCTION(fbsql_data_seek) { int argc = ARG_COUNT(ht); pval* argv[2]; int resultIndex; PHPFBResult* result; int rowIndex; FBSQLLS_FETCH(); if (argc != 2 ) WRONG_PARAM_COUNT; if (zend_get_parameters(ht,argc,&argv[0],&argv[1])==FAILURE) RETURN_FALSE; convert_to_long(argv[0]); resultIndex = argv[0]->value.lval; result = phpfbGetResult(resultIndex); if (result == NULL) RETURN_FALSE; convert_to_long(argv[1]); rowIndex = argv[1]->value.lval; if (rowIndex < 0 ) { php_error(E_WARNING,"Illegal index",resultIndex+1); RETURN_FALSE; } if (result->rowCount == 0x7fffffff) phpfbFetchRow(result,rowIndex); if (rowIndex > result->rowCount) RETURN_FALSE; result->rowIndex = rowIndex; RETURN_TRUE; } // array fbsql_fetch_lengths(int result) PHP_FUNCTION(fbsql_fetch_lengths) { int argc = ARG_COUNT(ht); pval* argv[2]; int i; int resultIndex; PHPFBResult* result; FBSQLLS_FETCH(); resultIndex = FB_SQL_G(resultIndex); if ((argc < 0) || ( argc > 1 )) WRONG_PARAM_COUNT; if (zend_get_parameters(ht,argc,&argv[0])==FAILURE) RETURN_FALSE; if (argc >= 1 ) { convert_to_long(argv[0]); resultIndex = argv[0]->value.lval; } result = phpfbGetResult(resultIndex); if (result == NULL) RETURN_FALSE; if (result->row == NULL) RETURN_FALSE; if (array_init(return_value)==FAILURE) RETURN_FALSE; for (i=0; i < result->columnCount; i++) { unsigned length = 0; if (result->row[i]) phpfbColumnAsString(result,i, result->row[i],&length,NULL); add_index_long(return_value, i, length); } FB_SQL_G(resultIndex) = resultIndex; } // object fbsql_fetch_field(int result [, int field_offset]) PHP_FUNCTION(fbsql_fetch_field) { int argc = ARG_COUNT(ht); pval* argv[2]; int resultIndex; PHPFBResult* result; int column; FBSQLLS_FETCH(); resultIndex = FB_SQL_G(resultIndex); if ((argc < 0 ) || (argc > 2 )) WRONG_PARAM_COUNT; if (zend_get_parameters(ht,argc,&argv[0],&argv[1])==FAILURE) RETURN_FALSE; if (argc >= 1 ) { convert_to_long(argv[0]); resultIndex = argv[0]->value.lval; } result = phpfbGetResult(resultIndex); if (result == NULL) RETURN_FALSE; column = result->columnIndex; if (argc >= 2 ) { convert_to_long(argv[1]); column = argv[1]->value.lval; if (column < 0 ) { php_error(E_WARNING,"Illegal index",resultIndex+1); RETURN_FALSE; } if (column >= result->columnCount) { php_error(E_WARNING,"%d no such column in result",column); RETURN_FALSE; } } if (object_init(return_value)==FAILURE) { RETURN_FALSE; } add_property_string(return_value, "name", (char*)fbccmdLabelName(fbcmdColumnMetaDataAtIndex(result->metaData, column)),1); add_property_string(return_value, "table", (char*)fbccmdTableName(fbcmdColumnMetaDataAtIndex(result->metaData,column)),1); add_property_long(return_value, "max_length", fbcdmdLength(fbccmdDatatype(fbcmdColumnMetaDataAtIndex(result->metaData,column)))); add_property_string(return_value, "type", (char*)fbcdmdDatatypeString (fbcmdDatatypeMetaDataAtIndex(result->metaData, column)),1); // Remember to add the rest // add_property_long(return_value, "not_null",IS_NOT_NULL(mysql_field->flags)?1:0); // add_property_long(return_value, "primary_key",IS_PRI_KEY(mysql_field->flags)?1:0); // add_property_long(return_value, "multiple_key",(mysql_field->flags&MULTIPLE_KEY_FLAG?1:0)); // add_property_long(return_value, "unique_key",(mysql_field->flags&UNIQUE_KEY_FLAG?1:0)); // add_property_long(return_value, "numeric",IS_NUM(mysql_field->type)?1:0); // add_property_long(return_value, "blob",IS_BLOB(mysql_field->flags)?1:0); // add_property_string(return_value, "type",php_mysql_get_field_name(mysql_field->type), 1); // add_property_long(return_value, "unsigned",(mysql_field->flags&UNSIGNED_FLAG?1:0)); // add_property_long(return_value, "zerofill",(mysql_field->flags&ZEROFILL_FLAG?1:0)); } // int fbsql_field_seek(int result, int field_offset) PHP_FUNCTION(fbsql_field_seek) { int argc = ARG_COUNT(ht); pval* argv[2]; int resultIndex; PHPFBResult* result; int column; FBSQLLS_FETCH(); resultIndex = FB_SQL_G(resultIndex); if ((argc < 0 ) || ( argc > 2 )) WRONG_PARAM_COUNT; if (zend_get_parameters(ht,argc,&argv[0],&argv[1])==FAILURE) RETURN_FALSE; if (argc >= 1 ) { convert_to_long(argv[0]); resultIndex = argv[0]->value.lval; } result = phpfbGetResult(resultIndex); if (result == NULL) RETURN_FALSE; column = result->columnIndex; if (argc>=2) { convert_to_long(argv[1]); column = argv[1]->value.lval; } if (column < 0 ) { php_error(E_WARNING,"Illegal column index %d",column); RETURN_FALSE; } if (column >= result->columnCount) { php_error(E_WARNING,"No such column %d in result %d",column,resultIndex); RETURN_FALSE; } FB_SQL_G(resultIndex) = resultIndex; result->columnIndex = column; RETURN_TRUE; } // string mysql_field_name(int result, int field_index) PHP_FUNCTION(fbsql_field_name) { int argc = ARG_COUNT(ht); pval* argv[2]; int resultIndex; PHPFBResult* result; int column; FBSQLLS_FETCH(); resultIndex = FB_SQL_G(resultIndex); if ((argc < 0 ) || (argc > 2 )) WRONG_PARAM_COUNT; if (zend_get_parameters(ht,argc,&argv[0],&argv[1])==FAILURE) RETURN_FALSE; if (argc >= 1 ) { convert_to_long(argv[0]); resultIndex = argv[0]->value.lval; } result = phpfbGetResult(resultIndex); if (result == NULL) RETURN_FALSE; column = result->columnIndex; if (argc >= 2 ) { convert_to_long(argv[1]); column = argv[1]->value.lval; if (column < 0 ) { php_error(E_WARNING,"Illegal index",resultIndex+1); RETURN_FALSE; } if (column >= result->columnCount) { php_error(E_WARNING,"%d no such row in result",column); RETURN_FALSE; } } if (result->list) { phpfbSqlResult(INTERNAL_FUNCTION_PARAM_PASSTHRU,result,result->rowIndex,0); } else if (result->metaData) { phpfbestrdup(fbccmdLabelName(fbcmdColumnMetaDataAtIndex(result->metaData, column)), &return_value->value.str.len, &return_value->value.str.val); return_value->type = IS_STRING; FB_SQL_G(resultIndex) = resultIndex; result->columnIndex = column; } } // string fbsql_field_table(int result, int field_index) PHP_FUNCTION(fbsql_field_table) { int argc = ARG_COUNT(ht); pval* argv[2]; int resultIndex; PHPFBResult* result; int column; FBSQLLS_FETCH(); resultIndex = FB_SQL_G(resultIndex); if ((argc < 0 ) || (argc > 2 )) WRONG_PARAM_COUNT; if (zend_get_parameters(ht,argc,&argv[0],&argv[1])==FAILURE) RETURN_FALSE; if (argc >= 1 ) { convert_to_long(argv[0]); resultIndex = argv[0]->value.lval; } result = phpfbGetResult(resultIndex); if (result == NULL) RETURN_FALSE; column = result->columnIndex; if (argc >= 2 ) { convert_to_long(argv[1]); column = argv[1]->value.lval; if (column < 0 ) { php_error(E_WARNING,"Illegal index",resultIndex+1); RETURN_FALSE; } if (column >= result->columnCount) { php_error(E_WARNING,"%d no such row in result",column); RETURN_FALSE; } } phpfbestrdup(fbccmdTableName(fbcmdColumnMetaDataAtIndex(result->metaData,column)), &return_value->value.str.len, &return_value->value.str.val); return_value->type = IS_STRING; } // string fbsql_field_lene(int result, int field_index) PHP_FUNCTION(fbsql_field_len) { int argc = ARG_COUNT(ht); pval* argv[2]; int resultIndex; PHPFBResult* result; int column; FBSQLLS_FETCH(); resultIndex = FB_SQL_G(resultIndex); if ((argc < 0 ) || (argc > 2 )) WRONG_PARAM_COUNT; if (zend_get_parameters(ht,argc,&argv[0],&argv[1])==FAILURE) RETURN_FALSE; if (argc >= 1 ) { convert_to_long(argv[0]); resultIndex = argv[0]->value.lval; } result = phpfbGetResult(resultIndex); if (result == NULL) RETURN_FALSE; column = result->columnIndex; if (argc >= 2 ) { convert_to_long(argv[1]); column = argv[1]->value.lval; if (column < 0 ) { php_error(E_WARNING,"Illegal index",resultIndex+1); RETURN_FALSE; } if (column >= result->columnCount) { php_error(E_WARNING,"%d no such row in result",column); RETURN_FALSE; } } if (result->list) { phpfbSqlResult(INTERNAL_FUNCTION_PARAM_PASSTHRU,result,result->rowIndex,2); } else if (result->metaData) { unsigned int length = fbcdmdLength(fbccmdDatatype(fbcmdColumnMetaDataAtIndex(result->metaData,column))); char buffer[50]; sprintf(buffer,"%d",length); phpfbestrdup(buffer, &return_value->value.str.len, &return_value->value.str.val); return_value->type = IS_STRING; } else { RETURN_FALSE; } } // string fbsql_field_type(int result, int field_index) PHP_FUNCTION(fbsql_field_type) { int argc = ARG_COUNT(ht); pval* argv[2]; int resultIndex; PHPFBResult* result; int column; FBSQLLS_FETCH(); resultIndex = FB_SQL_G(resultIndex); if ((argc < 0 ) || (argc > 2 )) WRONG_PARAM_COUNT; if (zend_get_parameters(ht,argc,&argv[0],&argv[1])==FAILURE) RETURN_FALSE; if (argc >= 1 ) { convert_to_long(argv[0]); resultIndex = argv[0]->value.lval; } result = phpfbGetResult(resultIndex); if (result == NULL) RETURN_FALSE; column = result->columnIndex; if (argc >= 2 ) { convert_to_long(argv[1]); column = argv[1]->value.lval; if (column < 0 ) { php_error(E_WARNING,"Illegal index",resultIndex+1); RETURN_FALSE; } if (column >= result->columnCount) { php_error(E_WARNING,"%d no such column in result",column); RETURN_FALSE; } } if (result->list) { phpfbSqlResult(INTERNAL_FUNCTION_PARAM_PASSTHRU,result,result->rowIndex,1); } else if (result->metaData) { phpfbestrdup(fbcdmdDatatypeString (fbcmdDatatypeMetaDataAtIndex(result->metaData, column)), &return_value->value.str.len, &return_value->value.str.val); return_value->type = IS_STRING; } else { RETURN_FALSE; } } // string fbsql_field_flags(int result, int field_index) PHP_FUNCTION(fbsql_field_flags) { int argc = ARG_COUNT(ht); pval* argv[2]; int resultIndex; PHPFBResult* result; int column; FBSQLLS_FETCH(); resultIndex = FB_SQL_G(resultIndex); if ((argc < 0 ) || (argc > 2 )) WRONG_PARAM_COUNT; if (zend_get_parameters(ht,argc,&argv[0],&argv[1])==FAILURE) RETURN_FALSE; if (argc >= 1 ) { convert_to_long(argv[0]); resultIndex = argv[0]->value.lval; } result = phpfbGetResult(resultIndex); if (result == NULL) RETURN_FALSE; column = result->columnIndex; if (argc >= 2 ) { convert_to_long(argv[1]); column = argv[1]->value.lval; if (column < 0 ) { php_error(E_WARNING,"Illegal index",resultIndex+1); RETURN_FALSE; } if (column >= result->columnCount) { php_error(E_WARNING,"%d no such column in result",column); RETURN_FALSE; } } if (array_init(return_value)==FAILURE) { RETURN_FALSE; } // We should create the result -- currently empty } // int fbsql_free_result(int result) PHP_FUNCTION(fbsql_free_result) { int argc = ARG_COUNT(ht); pval* argv[1]; int resultIndex; PHPFBResult* result; FBSQLLS_FETCH(); resultIndex = FB_SQL_G(resultIndex); if ((argc < 0) || (argc > 1)) WRONG_PARAM_COUNT; if (zend_get_parameters(ht,argc,&argv[0])==FAILURE) RETURN_FALSE; if (argc >= 1 ) { convert_to_long(argv[0]); resultIndex = argv[0]->value.lval; } result = phpfbGetResult(resultIndex); if (result == NULL) RETURN_FALSE; zend_list_delete(result->index); FB_SQL_G(resultCount)--; FB_SQL_G(resultIndex) = 0; RETURN_TRUE; } #endif