From: Frank M. Kromann Date: Tue, 13 Mar 2001 20:58:47 +0000 (+0000) Subject: Initial check-in of FrontBase extension X-Git-Tag: php-4.0.6RC1~706 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d5e1266dc5774e4559eed2f590efa89318efa518;p=php Initial check-in of FrontBase extension --- diff --git a/ext/fbsql/Makefile.in b/ext/fbsql/Makefile.in new file mode 100644 index 0000000000..66bec05fac --- /dev/null +++ b/ext/fbsql/Makefile.in @@ -0,0 +1,10 @@ + +LTLIBRARY_NAME = libfbsql.la +LTLIBRARY_SOURCES = php_fbsql.c +LTLIBRARY_LIBADD = $(FBSQL_LIBADD) +LTLIBRARY_SHARED_NAME = fbsql.la +LTLIBRARY_SHARED_LIBADD = $(FBSQL_SHARED_LIBADD) + +SUBDIRS = $(FBSQL_SUBDIRS) + +include $(top_srcdir)/build/dynlib.mk diff --git a/ext/fbsql/config.m4 b/ext/fbsql/config.m4 new file mode 100644 index 0000000000..b166ba3655 --- /dev/null +++ b/ext/fbsql/config.m4 @@ -0,0 +1,41 @@ +dnl $Id$ + +PHP_ARG_WITH(fbsql, for FrontBase SQL92 (fbsql) support, +[ --with-fbsql[=DIR] Include FrontBase support. DIR is the FrontBase base + directory. .], yes) + +if test "$PHP_FBSQL" != "no"; then + AC_DEFINE(HAVE_FBSQL, 1, [Whether you have FrontBase]) + PHP_EXTENSION(fbsql,$ext_shared) +fi + +FBSQL_INSTALLATION_DIR="" +if test "$PHP_FBSQL" = "yes"; then + for i in /Local/Library /usr /usr/local /opt /Library + do + if test -f $i/FrontBase/include/FBCAccess/FBCAccess.h + then + FBSQL_INSTALLATION_DIR=$i/FrontBase + break + fi + done + if test -z "$FBSQL_INSTALLATION_DIR" + then + AC_MSG_ERROR(Cannot find FrontBase in well know installation directories) + fi +elif test "$PHP_FBSQL" != "no"; then + if test -f $PHP_FBSQL/include/FBCAccess/FBCAccess.h + then + FBSQL_INSTALLATION_DIR=$PHP_FBSQL + else + AC_MSG_ERROR(Directory $PHP_FBSQL is not a FrontBase installation directory) + fi +fi + +if test ! -f "$FBSQL_INSTALLATION_DIR/lib/libFBCAccess.a" +then + AC_MSG_ERROR(Could not find $FBSQL_INSTALLATION_DIR/lib/libFBCAccess.a) +fi +AC_ADD_LIBRARY_WITH_PATH(FBCAccess, $FBSQL_INSTALLATION_DIR/lib, $FBSQL_INSTALLATION_DIR/lib) +AC_ADD_INCLUDE($FBSQL_INSTALLATION_DIR/include) + diff --git a/ext/fbsql/fbsql.dsp b/ext/fbsql/fbsql.dsp new file mode 100644 index 0000000000..791f5722ec --- /dev/null +++ b/ext/fbsql/fbsql.dsp @@ -0,0 +1,171 @@ +# Microsoft Developer Studio Project File - Name="fbsql" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=fbsql - Win32 Debug_TS +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "fbsql.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "fbsql.mak" CFG="fbsql - Win32 Debug_TS" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "fbsql - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "fbsql - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "fbsql - Win32 Debug_TS" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "fbsql - Win32 Release_TS" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "fbsql - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FBSQL_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\.." /I "..\..\Zend" /I "..\..\..\bindlib_w32" /I "..\..\TSRM" /D "NDEBUG" /D "FBSQL_EXPORTS" /D "COMPILE_DL_FBSQL_FBSQL" /D HAVE_FBSQL=1 /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "ZEND_WIN32" /D "PHP_WIN32" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40d /d "NDEBUG" +# ADD RSC /l 0x40d /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib php4nts.lib /nologo /dll /machine:I386 /out:"Release/php_fbsql.dll" /libpath:"..\..\Release" + +!ELSEIF "$(CFG)" == "fbsql - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FBSQL_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\.." /I "..\..\Zend" /I "..\..\..\bindlib_w32" /I "..\..\TSRM" /D "_DEBUG" /D ZEND_DEBUG=1 /D "FBSQL_EXPORTS" /D "COMPILE_DL_FBSQL_FBSQL" /D HAVE_FBSQL=1 /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "ZEND_WIN32" /D "PHP_WIN32" /FR /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40d /d "_DEBUG" +# ADD RSC /l 0x40d /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib php4nts_debug.lib /nologo /dll /debug /machine:I386 /out:"Debug/php_fbsql.dll" /pdbtype:sept /libpath:"..\..\Debug" + +!ELSEIF "$(CFG)" == "fbsql - Win32 Debug_TS" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug_TS" +# PROP BASE Intermediate_Dir "Debug_TS" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug_TS" +# PROP Intermediate_Dir "Debug_TS" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\.." /I "..\..\..\Zend" /I "..\..\..\bindlib_w32" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FBSQL_EXPORTS" /D "COMPILE_DL_FBSQL" /D HAVE_FBSQL=1 /FR /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\.." /I "..\..\main" /I "..\..\Zend" /I "..\..\..\bindlib_w32" /I "..\..\TSRM" /I "\usr\FrontBase\Include" /D "_DEBUG" /D ZEND_DEBUG=1 /D "ZTS" /D "FBSQL_EXPORTS" /D "COMPILE_DL_FBSQL" /D HAVE_FBSQL=1 /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "ZEND_WIN32" /D "PHP_WIN32" /FR /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40d /d "_DEBUG" +# ADD RSC /l 0x40d /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib php4ts_debug.lib FBCAccess.lib /nologo /dll /debug /machine:I386 /nodefaultlib:"LIBC" /out:"..\..\Debug_TS/php_fbsql.dll" /pdbtype:sept /libpath:"..\..\Debug_TS" /libpath:"\usr\FrontBase\lib" + +!ELSEIF "$(CFG)" == "fbsql - Win32 Release_TS" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release_TS" +# PROP BASE Intermediate_Dir "Release_TS" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release_TS" +# PROP Intermediate_Dir "Release_TS" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /I "..\.." /I "..\..\..\Zend" /I "..\..\..\bindlib_w32" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FBSQL_EXPORTS" /D "COMPILE_DL_FBSQL" /D HAVE_FBSQL=1 /YX /FD /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\.." /I "..\..\main" /I "..\..\Zend" /I "..\..\..\bindlib_w32" /I "..\..\TSRM" /I "\usr\FrontBase\Include" /D "NDEBUG" /D "ZTS" /D ZEND_DEBUG=0 /D "FBSQL_EXPORTS" /D "COMPILE_DL_FBSQL" /D HAVE_FBSQL=1 /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "ZEND_WIN32" /D "PHP_WIN32" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40d /d "NDEBUG" +# ADD RSC /l 0x40d /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib php4ts.lib FBCAccess.lib wsock32.lib /nologo /dll /machine:I386 /nodefaultlib:"LIBC" /out:"..\..\Release_TS/php_fbsql.dll" /libpath:"..\..\Release_TS" /libpath:"\usr\FrontBase\lib" + +!ENDIF + +# Begin Target + +# Name "fbsql - Win32 Release" +# Name "fbsql - Win32 Debug" +# Name "fbsql - Win32 Debug_TS" +# Name "fbsql - Win32 Release_TS" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\php_fbsql.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\php_fbsql.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# Begin Source File + +SOURCE=.\Readme_w32.txt +# End Source File +# End Target +# End Project diff --git a/ext/fbsql/php_fbsql.c b/ext/fbsql/php_fbsql.c new file mode 100644 index 0000000000..cbd78d1aa2 --- /dev/null +++ b/ext/fbsql/php_fbsql.c @@ -0,0 +1,3039 @@ +/* + +----------------------------------------------------------------------+ + | 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 diff --git a/ext/fbsql/php_fbsql.h b/ext/fbsql/php_fbsql.h new file mode 100644 index 0000000000..135b33971c --- /dev/null +++ b/ext/fbsql/php_fbsql.h @@ -0,0 +1,144 @@ +/* + +----------------------------------------------------------------------+ + | 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$ */ + +#define HAVE_FBSQL 1 + +#ifndef _PHP_FBSQL_H +#define _PHP_FBSQL_H + +#if COMPILE_DL_FBSQL +#undef HAVE_FBSQL +#define HAVE_FBSQL 1 +#endif +#if HAVE_FBSQL + +#ifdef ZTS +#include "TSRM.h" +#endif + +extern zend_module_entry fbsql_module_entry; +#define fbsql_module_ptr &fbsql_module_entry + +#include + +extern PHP_MINIT_FUNCTION(fbsql); +extern PHP_RINIT_FUNCTION(fbsql); +extern PHP_MSHUTDOWN_FUNCTION(fbsql); +PHP_MINFO_FUNCTION(fbsql); +PHP_FUNCTION(fbsql_connect); +PHP_FUNCTION(fbsql_pconnect); +PHP_FUNCTION(fbsql_close); +PHP_FUNCTION(fbsql_select_db); +PHP_FUNCTION(fbsql_change_user); +PHP_FUNCTION(fbsql_create_db); +PHP_FUNCTION(fbsql_drop_db); +PHP_FUNCTION(fbsql_start_db); +PHP_FUNCTION(fbsql_stop_db); +PHP_FUNCTION(fbsql_query); +PHP_FUNCTION(fbsql_db_query); +PHP_FUNCTION(fbsql_list_dbs); +PHP_FUNCTION(fbsql_list_tables); +PHP_FUNCTION(fbsql_list_fields); +PHP_FUNCTION(fbsql_error); +PHP_FUNCTION(fbsql_errno); +PHP_FUNCTION(fbsql_affected_rows); +PHP_FUNCTION(fbsql_insert_id); +PHP_FUNCTION(fbsql_result); +PHP_FUNCTION(fbsql_next_result); +PHP_FUNCTION(fbsql_num_rows); +PHP_FUNCTION(fbsql_num_fields); +PHP_FUNCTION(fbsql_fetch_row); +PHP_FUNCTION(fbsql_fetch_array); +PHP_FUNCTION(fbsql_fetch_object); +PHP_FUNCTION(fbsql_data_seek); +PHP_FUNCTION(fbsql_fetch_lengths); +PHP_FUNCTION(fbsql_fetch_field); +PHP_FUNCTION(fbsql_field_seek); +PHP_FUNCTION(fbsql_free_result); +PHP_FUNCTION(fbsql_field_name); +PHP_FUNCTION(fbsql_field_table); +PHP_FUNCTION(fbsql_field_len); +PHP_FUNCTION(fbsql_field_type); +PHP_FUNCTION(fbsql_field_flags); +PHP_FUNCTION(fbsql_autocommit); +PHP_FUNCTION(fbsql_commit); +PHP_FUNCTION(fbsql_rollback); +PHP_FUNCTION(fbsql_hostname); +PHP_FUNCTION(fbsql_database); +PHP_FUNCTION(fbsql_database_password); +PHP_FUNCTION(fbsql_username); +PHP_FUNCTION(fbsql_password); +PHP_FUNCTION(fbsql_warnings); + +ZEND_BEGIN_MODULE_GLOBALS(fbsql) + long allowPersistent; + long generateWarnings; + long autoCommit; + long maxPersistant; + long maxLinks; + long maxConnections; + long maxResults; + long batchSize; + char *hostName; + char *databaseName; + char *databasePassword; + char *userName; + char *userPassword; + long persistantCount; + long linkCount; + long databaseCount; + long resultCount; + + int linkIndex; + int databaseIndex; + int resultIndex; +ZEND_END_MODULE_GLOBALS(fbsql) + +#ifdef ZTS +# define FBSQLLS_D zend_fbsql_globals *fbsql_globals +# define FBSQLLS_DC , FBSQLLS_D +# define FBSQLLS_C fbsql_globals +# define FBSQLLS_CC , FBSQLLS_C +# define FB_SQL_G(v) (fbsql_globals->v) +# define FBSQLLS_FETCH() zend_fbsql_globals *fbsql_globals = ts_resource(fbsql_globals_id) +#else +# define FBSQLLS_D +# define FBSQLLS_DC +# define FBSQLLS_C +# define FBSQLLS_CC +# define FB_SQL_G(v) (fbsql_globals.v) +# define FBSQLLS_FETCH() +#endif + + + +//#ifndef ZTS // No need for external definitions +//extern fbsql_module* phpfbModule; +//#endif + +#else // HAVE_FBSQL + +#define fbsql_module_ptr NULL +#error not ok +#endif // HAVE_FBSQL + +#define phpext_fbsql_ptr fbsql_module_ptr + +#endif /* _PHP_FBSQL_H */