php-interbase-5.4.6/0000775000175000017500000000000012027124153014220 5ustar jtaylorjtaylorphp-interbase-5.4.6/config.m40000664000175000017500000000236512012622335015734 0ustar jtaylorjtaylordnl dnl $Id$ dnl PHP_ARG_WITH(interbase,for InterBase support, [ --with-interbase[=DIR] Include InterBase support. DIR is the InterBase base install directory [/usr/interbase]]) if test "$PHP_INTERBASE" != "no"; then if test "$PHP_INTERBASE" = "yes"; then IBASE_INCDIR=/usr/interbase/include IBASE_LIBDIR=/usr/interbase/lib else IBASE_INCDIR=$PHP_INTERBASE/include IBASE_LIBDIR=$PHP_INTERBASE/$PHP_LIBDIR fi PHP_CHECK_LIBRARY(fbclient, isc_detach_database, [ IBASE_LIBNAME=fbclient ], [ PHP_CHECK_LIBRARY(gds, isc_detach_database, [ IBASE_LIBNAME=gds ], [ PHP_CHECK_LIBRARY(ib_util, isc_detach_database, [ IBASE_LIBNAME=ib_util ], [ AC_MSG_ERROR([libgds, libib_util or libfbclient not found! Check config.log for more information.]) ], [ -L$IBASE_LIBDIR ]) ], [ -L$IBASE_LIBDIR ]) ], [ -L$IBASE_LIBDIR ]) PHP_ADD_LIBRARY_WITH_PATH($IBASE_LIBNAME, $IBASE_LIBDIR, INTERBASE_SHARED_LIBADD) PHP_ADD_INCLUDE($IBASE_INCDIR) AC_DEFINE(HAVE_IBASE,1,[ ]) PHP_NEW_EXTENSION(interbase, interbase.c ibase_query.c ibase_service.c ibase_events.c ibase_blobs.c, $ext_shared) PHP_SUBST(INTERBASE_SHARED_LIBADD) fi php-interbase-5.4.6/interbase.dsp0000664000175000017500000001347312012622335016713 0ustar jtaylorjtaylor# Microsoft Developer Studio Project File - Name="interbase" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 CFG=interbase - 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 "interbase.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 "interbase.mak" CFG="interbase - Win32 Debug_TS" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "interbase - Win32 Debug_TS" (based on "Win32 (x86) Dynamic-Link Library") !MESSAGE "interbase - Win32 Release_TS" (based on "Win32 (x86) Dynamic-Link Library") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "interbase" # PROP Scc_LocalPath "." CPP=cl.exe MTL=midl.exe RSC=rc.exe !IF "$(CFG)" == "interbase - 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 Ignore_Export_Lib 0 # 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 /MDd /W3 /Gm /GX /ZI /Od /I "..\..\main" /I "..\.." /I "..\..\Zend" /I "..\..\TSRM" /I "..\..\..\php_build\Interbase SDK\include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "INTERBASE_EXPORTS" /D "ZEND_WIN32" /D "PHP_WIN32" /D ZEND_DEBUG=1 /YX /FD /GZ /c # ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\..\main" /I "..\.." /I "..\..\Zend" /I "..\..\TSRM" /I "..\..\..\php_build\Interbase SDK\include" /I "..\..\..\bindlib_w32" /D "_DEBUG" /D ZEND_DEBUG=1 /D "ZTS" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "INTERBASE_EXPORTS" /D "ZEND_WIN32" /D "PHP_WIN32" /D HAVE_IBASE=1 /D "COMPILE_DL_INTERBASE" /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 ib_util_ms.lib gds32_ms.lib php5ts_debug.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 php5ts_debug.lib gds32_ms.lib /nologo /dll /debug /machine:I386 /out:"..\..\Debug_TS/php_interbase.dll" /pdbtype:sept /libpath:"..\..\..\php_build\Interbase SDK\lib_ms" /libpath:"..\..\Debug_TS" !ELSEIF "$(CFG)" == "interbase - 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 Ignore_Export_Lib 0 # 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 /MD /W3 /GX /O2 /I "..\..\main" /I "..\.." /I "..\..\Zend" /I "..\..\TSRM" /I "..\..\..\php_build\Interbase SDK\include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "INTERBASE_EXPORTS" /D "ZEND_WIN32" /D "PHP_WIN32" /D HAVE_IBASE=1 /D ZEND_DEBUG=0 /YX /FD /c # ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\main" /I "..\.." /I "..\..\Zend" /I "..\..\TSRM" /I "..\..\..\php_build\Interbase SDK\include" /I "..\..\..\bindlib_w32" /D "NDEBUG" /D ZEND_DEBUG=0 /D "ZTS" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "INTERBASE_EXPORTS" /D "ZEND_WIN32" /D "PHP_WIN32" /D HAVE_IBASE=1 /D "COMPILE_DL_INTERBASE" /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 php5ts.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ib_util_ms.lib gds32_ms.lib /nologo /dll /machine:I386 # ADD LINK32 php5ts.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib gds32_ms.lib /nologo /dll /machine:I386 /out:"..\..\Release_TS/php_interbase.dll" /libpath:"..\..\..\php_build\Interbase SDK\lib_ms" /libpath:"..\..\Release_TS" /libpath:"..\..\Release_TS_Inline" !ENDIF # Begin Target # Name "interbase - Win32 Debug_TS" # Name "interbase - Win32 Release_TS" # Begin Group "Source Files" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File SOURCE=.\ibase_blobs.c # End Source File # Begin Source File SOURCE=.\ibase_events.c # End Source File # Begin Source File SOURCE=.\ibase_query.c # End Source File # Begin Source File SOURCE=.\ibase_service.c # End Source File # Begin Source File SOURCE=.\interbase.c # End Source File # End Group # Begin Group "Header Files" # PROP Default_Filter "h;hpp;hxx;hm;inl" # Begin Source File SOURCE=.\php_interbase.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" # Begin Source File SOURCE=.\interbase.rc # ADD BASE RSC /l 0x413 # ADD RSC /l 0x413 /i "..\..\main" /i "..\..\win32" /d "PHP_H" # End Source File # End Group # End Target # End Project php-interbase-5.4.6/php_interbase.h0000664000175000017500000000641512012622335017221 0ustar jtaylorjtaylor/* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2012 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.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: Jouni Ahto | | Andrew Avdeev | | Ard Biesheuvel | +----------------------------------------------------------------------+ */ /* $Id$ */ #ifndef PHP_INTERBASE_H #define PHP_INTERBASE_H extern zend_module_entry ibase_module_entry; #define phpext_interbase_ptr &ibase_module_entry PHP_MINIT_FUNCTION(ibase); PHP_RINIT_FUNCTION(ibase); PHP_MSHUTDOWN_FUNCTION(ibase); PHP_RSHUTDOWN_FUNCTION(ibase); PHP_MINFO_FUNCTION(ibase); PHP_FUNCTION(ibase_connect); PHP_FUNCTION(ibase_pconnect); PHP_FUNCTION(ibase_close); PHP_FUNCTION(ibase_drop_db); PHP_FUNCTION(ibase_query); PHP_FUNCTION(ibase_fetch_row); PHP_FUNCTION(ibase_fetch_assoc); PHP_FUNCTION(ibase_fetch_object); PHP_FUNCTION(ibase_free_result); PHP_FUNCTION(ibase_name_result); PHP_FUNCTION(ibase_prepare); PHP_FUNCTION(ibase_execute); PHP_FUNCTION(ibase_free_query); PHP_FUNCTION(ibase_timefmt); PHP_FUNCTION(ibase_gen_id); PHP_FUNCTION(ibase_num_fields); PHP_FUNCTION(ibase_num_params); #if abies_0 PHP_FUNCTION(ibase_num_rows); #endif PHP_FUNCTION(ibase_affected_rows); PHP_FUNCTION(ibase_field_info); PHP_FUNCTION(ibase_param_info); PHP_FUNCTION(ibase_trans); PHP_FUNCTION(ibase_commit); PHP_FUNCTION(ibase_rollback); PHP_FUNCTION(ibase_commit_ret); PHP_FUNCTION(ibase_rollback_ret); PHP_FUNCTION(ibase_blob_create); PHP_FUNCTION(ibase_blob_add); PHP_FUNCTION(ibase_blob_cancel); PHP_FUNCTION(ibase_blob_open); PHP_FUNCTION(ibase_blob_get); PHP_FUNCTION(ibase_blob_close); PHP_FUNCTION(ibase_blob_echo); PHP_FUNCTION(ibase_blob_info); PHP_FUNCTION(ibase_blob_import); PHP_FUNCTION(ibase_add_user); PHP_FUNCTION(ibase_modify_user); PHP_FUNCTION(ibase_delete_user); PHP_FUNCTION(ibase_service_attach); PHP_FUNCTION(ibase_service_detach); PHP_FUNCTION(ibase_backup); PHP_FUNCTION(ibase_restore); PHP_FUNCTION(ibase_maintain_db); PHP_FUNCTION(ibase_db_info); PHP_FUNCTION(ibase_server_info); PHP_FUNCTION(ibase_errmsg); PHP_FUNCTION(ibase_errcode); PHP_FUNCTION(ibase_wait_event); PHP_FUNCTION(ibase_set_event_handler); PHP_FUNCTION(ibase_free_event_handler); #else #define phpext_interbase_ptr NULL #endif /* PHP_INTERBASE_H */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: */ php-interbase-5.4.6/ibase_query.c0000664000175000017500000016217612012622335016710 0ustar jtaylorjtaylor/* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2012 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.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: Ard Biesheuvel | +----------------------------------------------------------------------+ */ /* $Id$ */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "php.h" #include "php_ini.h" #if HAVE_IBASE #include "ext/standard/php_standard.h" #include "php_interbase.h" #include "php_ibase_includes.h" #define ISC_LONG_MIN INT_MIN #define ISC_LONG_MAX INT_MAX #define QUERY_RESULT 1 #define EXECUTE_RESULT 2 #define FETCH_ROW 1 #define FETCH_ARRAY 2 typedef struct { ISC_ARRAY_DESC ar_desc; ISC_LONG ar_size; /* size of entire array in bytes */ unsigned short el_type, el_size; } ibase_array; typedef struct { ibase_db_link *link; ibase_trans *trans; struct _ib_query *query; isc_stmt_handle stmt; unsigned short type; unsigned char has_more_rows, statement_type; XSQLDA *out_sqlda; ibase_array out_array[1]; /* last member */ } ibase_result; typedef struct _ib_query { ibase_db_link *link; ibase_trans *trans; ibase_result *result; int result_res_id; isc_stmt_handle stmt; XSQLDA *in_sqlda, *out_sqlda; ibase_array *in_array, *out_array; unsigned short in_array_cnt, out_array_cnt; unsigned short dialect; char statement_type; char *query; long trans_res_id; } ibase_query; typedef struct { unsigned short vary_length; char vary_string[1]; } IBVARY; /* sql variables union * used for convert and binding input variables */ typedef struct { union { short sval; float fval; ISC_LONG lval; ISC_QUAD qval; ISC_TIMESTAMP tsval; ISC_DATE dtval; ISC_TIME tmval; } val; short sqlind; } BIND_BUF; static int le_result, le_query; #define LE_RESULT "Firebird/InterBase result" #define LE_QUERY "Firebird/InterBase query" static void _php_ibase_free_xsqlda(XSQLDA *sqlda) /* {{{ */ { int i; XSQLVAR *var; IBDEBUG("Free XSQLDA?"); if (sqlda) { IBDEBUG("Freeing XSQLDA..."); var = sqlda->sqlvar; for (i = 0; i < sqlda->sqld; i++, var++) { efree(var->sqldata); if (var->sqlind) { efree(var->sqlind); } } efree(sqlda); } } /* }}} */ static void _php_ibase_free_stmt_handle(ibase_db_link *link, isc_stmt_handle stmt TSRMLS_DC) /* {{{ */ { static char info[] = { isc_info_base_level, isc_info_end }; if (stmt) { char res_buf[8]; IBDEBUG("Dropping statement handle (free_stmt_handle)..."); /* Only free statement if db-connection is still open */ if (SUCCESS == isc_database_info(IB_STATUS, &link->handle, sizeof(info), info, sizeof(res_buf), res_buf)) { if (isc_dsql_free_statement(IB_STATUS, &stmt, DSQL_drop)) { _php_ibase_error(TSRMLS_C); } } } } /* }}} */ static void _php_ibase_free_result(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */ { ibase_result *ib_result = (ibase_result *) rsrc->ptr; IBDEBUG("Freeing result by dtor..."); if (ib_result) { _php_ibase_free_xsqlda(ib_result->out_sqlda); if (ib_result->query != NULL) { IBDEBUG("query still valid; don't drop statement handle"); ib_result->query->result = NULL; /* Indicate to query, that result is released */ } else { _php_ibase_free_stmt_handle(ib_result->link, ib_result->stmt TSRMLS_CC); } efree(ib_result); } } /* }}} */ static void _php_ibase_free_query(ibase_query *ib_query TSRMLS_DC) /* {{{ */ { IBDEBUG("Freeing query..."); if (ib_query->in_sqlda) { efree(ib_query->in_sqlda); } if (ib_query->out_sqlda) { efree(ib_query->out_sqlda); } if (ib_query->result != NULL) { IBDEBUG("result still valid; don't drop statement handle"); ib_query->result->query = NULL; /* Indicate to result, that query is released */ } else { _php_ibase_free_stmt_handle(ib_query->link, ib_query->stmt TSRMLS_CC); } if (ib_query->in_array) { efree(ib_query->in_array); } if (ib_query->out_array) { efree(ib_query->out_array); } if (ib_query->query) { efree(ib_query->query); } } /* }}} */ static void php_ibase_free_query_rsrc(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */ { ibase_query *ib_query = (ibase_query *)rsrc->ptr; if (ib_query != NULL) { IBDEBUG("Preparing to free query by dtor..."); _php_ibase_free_query(ib_query TSRMLS_CC); efree(ib_query); } } /* }}} */ void php_ibase_query_minit(INIT_FUNC_ARGS) /* {{{ */ { le_result = zend_register_list_destructors_ex(_php_ibase_free_result, NULL, "interbase result", module_number); le_query = zend_register_list_destructors_ex(php_ibase_free_query_rsrc, NULL, "interbase query", module_number); } /* }}} */ static int _php_ibase_alloc_array(ibase_array **ib_arrayp, XSQLDA *sqlda, /* {{{ */ isc_db_handle link, isc_tr_handle trans, unsigned short *array_cnt TSRMLS_DC) { unsigned short i, n; ibase_array *ar; /* first check if we have any arrays at all */ for (i = *array_cnt = 0; i < sqlda->sqld; ++i) { if ((sqlda->sqlvar[i].sqltype & ~1) == SQL_ARRAY) { ++*array_cnt; } } if (! *array_cnt) return SUCCESS; ar = safe_emalloc(sizeof(ibase_array), *array_cnt, 0); for (i = n = 0; i < sqlda->sqld; ++i) { unsigned short dim; unsigned long ar_size = 1; XSQLVAR *var = &sqlda->sqlvar[i]; if ((var->sqltype & ~1) == SQL_ARRAY) { ibase_array *a = &ar[n++]; ISC_ARRAY_DESC *ar_desc = &a->ar_desc; if (isc_array_lookup_bounds(IB_STATUS, &link, &trans, var->relname, var->sqlname, ar_desc)) { _php_ibase_error(TSRMLS_C); efree(ar); return FAILURE; } switch (ar_desc->array_desc_dtype) { case blr_text: case blr_text2: a->el_type = SQL_TEXT; a->el_size = ar_desc->array_desc_length; break; case blr_short: a->el_type = SQL_SHORT; a->el_size = sizeof(short); break; case blr_long: a->el_type = SQL_LONG; a->el_size = sizeof(ISC_LONG); break; case blr_float: a->el_type = SQL_FLOAT; a->el_size = sizeof(float); break; case blr_double: a->el_type = SQL_DOUBLE; a->el_size = sizeof(double); break; case blr_int64: a->el_type = SQL_INT64; a->el_size = sizeof(ISC_INT64); break; case blr_timestamp: a->el_type = SQL_TIMESTAMP; a->el_size = sizeof(ISC_TIMESTAMP); break; case blr_sql_date: a->el_type = SQL_TYPE_DATE; a->el_size = sizeof(ISC_DATE); break; case blr_sql_time: a->el_type = SQL_TYPE_TIME; a->el_size = sizeof(ISC_TIME); break; case blr_varying: case blr_varying2: /** * IB has a strange way of handling VARCHAR arrays. It doesn't store * the length in the first short, as with VARCHAR fields. It does, * however, expect the extra short to be allocated for each element. */ a->el_type = SQL_TEXT; a->el_size = ar_desc->array_desc_length + sizeof(short); break; case blr_quad: case blr_blob_id: case blr_cstring: case blr_cstring2: /** * These types are mentioned as array types in the manual, but I * wouldn't know how to create an array field with any of these * types. I assume these types are not applicable to arrays, and * were mentioned erroneously. */ default: _php_ibase_module_error("Unsupported array type %d in relation '%s' column '%s'" TSRMLS_CC, ar_desc->array_desc_dtype, var->relname, var->sqlname); efree(ar); return FAILURE; } /* switch array_desc_type */ /* calculate elements count */ for (dim = 0; dim < ar_desc->array_desc_dimensions; dim++) { ar_size *= 1 + ar_desc->array_desc_bounds[dim].array_bound_upper -ar_desc->array_desc_bounds[dim].array_bound_lower; } a->ar_size = a->el_size * ar_size; } /* if SQL_ARRAY */ } /* for column */ *ib_arrayp = ar; return SUCCESS; } /* }}} */ /* allocate and prepare query */ static int _php_ibase_alloc_query(ibase_query *ib_query, ibase_db_link *link, /* {{{ */ ibase_trans *trans, char *query, unsigned short dialect, int trans_res_id TSRMLS_DC) { static char info_type[] = {isc_info_sql_stmt_type}; char result[8]; /* Return FAILURE, if querystring is empty */ if (*query == '\0') { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Querystring empty."); return FAILURE; } ib_query->link = link; ib_query->trans = trans; ib_query->result_res_id = 0; ib_query->result = NULL; ib_query->stmt = NULL; ib_query->in_array = NULL; ib_query->out_array = NULL; ib_query->dialect = dialect; ib_query->query = estrdup(query); ib_query->trans_res_id = trans_res_id; ib_query->out_sqlda = NULL; ib_query->in_sqlda = NULL; if (isc_dsql_allocate_statement(IB_STATUS, &link->handle, &ib_query->stmt)) { _php_ibase_error(TSRMLS_C); goto _php_ibase_alloc_query_error; } ib_query->out_sqlda = (XSQLDA *) emalloc(XSQLDA_LENGTH(1)); ib_query->out_sqlda->sqln = 1; ib_query->out_sqlda->version = SQLDA_CURRENT_VERSION; if (isc_dsql_prepare(IB_STATUS, &ib_query->trans->handle, &ib_query->stmt, 0, query, dialect, ib_query->out_sqlda)) { _php_ibase_error(TSRMLS_C); goto _php_ibase_alloc_query_error; } /* find out what kind of statement was prepared */ if (isc_dsql_sql_info(IB_STATUS, &ib_query->stmt, sizeof(info_type), info_type, sizeof(result), result)) { _php_ibase_error(TSRMLS_C); goto _php_ibase_alloc_query_error; } ib_query->statement_type = result[3]; /* not enough output variables ? */ if (ib_query->out_sqlda->sqld > ib_query->out_sqlda->sqln) { ib_query->out_sqlda = erealloc(ib_query->out_sqlda, XSQLDA_LENGTH(ib_query->out_sqlda->sqld)); ib_query->out_sqlda->sqln = ib_query->out_sqlda->sqld; ib_query->out_sqlda->version = SQLDA_CURRENT_VERSION; if (isc_dsql_describe(IB_STATUS, &ib_query->stmt, SQLDA_CURRENT_VERSION, ib_query->out_sqlda)) { _php_ibase_error(TSRMLS_C); goto _php_ibase_alloc_query_error; } } /* maybe have input placeholders? */ ib_query->in_sqlda = emalloc(XSQLDA_LENGTH(1)); ib_query->in_sqlda->sqln = 1; ib_query->in_sqlda->version = SQLDA_CURRENT_VERSION; if (isc_dsql_describe_bind(IB_STATUS, &ib_query->stmt, SQLDA_CURRENT_VERSION, ib_query->in_sqlda)) { _php_ibase_error(TSRMLS_C); goto _php_ibase_alloc_query_error; } /* not enough input variables ? */ if (ib_query->in_sqlda->sqln < ib_query->in_sqlda->sqld) { ib_query->in_sqlda = erealloc(ib_query->in_sqlda, XSQLDA_LENGTH(ib_query->in_sqlda->sqld)); ib_query->in_sqlda->sqln = ib_query->in_sqlda->sqld; ib_query->in_sqlda->version = SQLDA_CURRENT_VERSION; if (isc_dsql_describe_bind(IB_STATUS, &ib_query->stmt, SQLDA_CURRENT_VERSION, ib_query->in_sqlda)) { _php_ibase_error(TSRMLS_C); goto _php_ibase_alloc_query_error; } } /* no, haven't placeholders at all */ if (ib_query->in_sqlda->sqld == 0) { efree(ib_query->in_sqlda); ib_query->in_sqlda = NULL; } else if (FAILURE == _php_ibase_alloc_array(&ib_query->in_array, ib_query->in_sqlda, link->handle, trans->handle, &ib_query->in_array_cnt TSRMLS_CC)) { goto _php_ibase_alloc_query_error; } if (ib_query->out_sqlda->sqld == 0) { efree(ib_query->out_sqlda); ib_query->out_sqlda = NULL; } else if (FAILURE == _php_ibase_alloc_array(&ib_query->out_array, ib_query->out_sqlda, link->handle, trans->handle, &ib_query->out_array_cnt TSRMLS_CC)) { goto _php_ibase_alloc_query_error; } return SUCCESS; _php_ibase_alloc_query_error: if (ib_query->out_sqlda) { efree(ib_query->out_sqlda); } if (ib_query->in_sqlda) { efree(ib_query->in_sqlda); } if (ib_query->out_array) { efree(ib_query->out_array); } if (ib_query->query) { efree(ib_query->query); } return FAILURE; } /* }}} */ static int _php_ibase_bind_array(zval *val, char *buf, unsigned long buf_size, /* {{{ */ ibase_array *array, int dim TSRMLS_DC) { zval null_val, *pnull_val = &null_val; int u_bound = array->ar_desc.array_desc_bounds[dim].array_bound_upper, l_bound = array->ar_desc.array_desc_bounds[dim].array_bound_lower, dim_len = 1 + u_bound - l_bound; ZVAL_NULL(pnull_val); if (dim < array->ar_desc.array_desc_dimensions) { unsigned long slice_size = buf_size / dim_len; unsigned short i; zval **subval = &val; if (Z_TYPE_P(val) == IS_ARRAY) { zend_hash_internal_pointer_reset(Z_ARRVAL_P(val)); } for (i = 0; i < dim_len; ++i) { if (Z_TYPE_P(val) == IS_ARRAY && zend_hash_get_current_data(Z_ARRVAL_P(val), (void *) &subval) == FAILURE) { subval = &pnull_val; } if (_php_ibase_bind_array(*subval, buf, slice_size, array, dim+1 TSRMLS_CC) == FAILURE) { return FAILURE; } buf += slice_size; if (Z_TYPE_P(val) == IS_ARRAY) { zend_hash_move_forward(Z_ARRVAL_P(val)); } } if (Z_TYPE_P(val) == IS_ARRAY) { zend_hash_internal_pointer_reset(Z_ARRVAL_P(val)); } } else { /* expect a single value */ if (Z_TYPE_P(val) == IS_NULL) { memset(buf, 0, buf_size); } else if (array->ar_desc.array_desc_scale < 0) { /* no coercion for array types */ double l; convert_to_double(val); if (Z_DVAL_P(val) > 0) { l = Z_DVAL_P(val) * pow(10, -array->ar_desc.array_desc_scale) + .5; } else { l = Z_DVAL_P(val) * pow(10, -array->ar_desc.array_desc_scale) - .5; } switch (array->el_type) { case SQL_SHORT: if (l > SHRT_MAX || l < SHRT_MIN) { _php_ibase_module_error("Array parameter exceeds field width" TSRMLS_CC); return FAILURE; } *(short*) buf = (short) l; break; case SQL_LONG: if (l > ISC_LONG_MAX || l < ISC_LONG_MIN) { _php_ibase_module_error("Array parameter exceeds field width" TSRMLS_CC); return FAILURE; } *(ISC_LONG*) buf = (ISC_LONG) l; break; case SQL_INT64: { long double l; convert_to_string(val); if (!sscanf(Z_STRVAL_P(val), "%Lf", &l)) { _php_ibase_module_error("Cannot convert '%s' to long double" TSRMLS_CC, Z_STRVAL_P(val)); return FAILURE; } if (l > 0) { *(ISC_INT64 *) buf = (ISC_INT64) (l * pow(10, -array->ar_desc.array_desc_scale) + .5); } else { *(ISC_INT64 *) buf = (ISC_INT64) (l * pow(10, -array->ar_desc.array_desc_scale) - .5); } } break; } } else { struct tm t = { 0, 0, 0, 0, 0, 0 }; switch (array->el_type) { unsigned short n; ISC_INT64 l; case SQL_SHORT: convert_to_long(val); if (Z_LVAL_P(val) > SHRT_MAX || Z_LVAL_P(val) < SHRT_MIN) { _php_ibase_module_error("Array parameter exceeds field width" TSRMLS_CC); return FAILURE; } *(short *) buf = (short) Z_LVAL_P(val); break; case SQL_LONG: convert_to_long(val); #if (SIZEOF_LONG > 4) if (Z_LVAL_P(val) > ISC_LONG_MAX || Z_LVAL_P(val) < ISC_LONG_MIN) { _php_ibase_module_error("Array parameter exceeds field width" TSRMLS_CC); return FAILURE; } #endif *(ISC_LONG *) buf = (ISC_LONG) Z_LVAL_P(val); break; case SQL_INT64: #if (SIZEOF_LONG >= 8) convert_to_long(val); *(long *) buf = Z_LVAL_P(val); #else convert_to_string(val); if (!sscanf(Z_STRVAL_P(val), "%" LL_MASK "d", &l)) { _php_ibase_module_error("Cannot convert '%s' to long integer" TSRMLS_CC, Z_STRVAL_P(val)); return FAILURE; } else { *(ISC_INT64 *) buf = l; } #endif break; case SQL_FLOAT: convert_to_double(val); *(float*) buf = (float) Z_DVAL_P(val); break; case SQL_DOUBLE: convert_to_double(val); *(double*) buf = Z_DVAL_P(val); break; case SQL_TIMESTAMP: convert_to_string(val); #ifdef HAVE_STRPTIME strptime(Z_STRVAL_P(val), INI_STR("ibase.timestampformat"), &t); #else n = sscanf(Z_STRVAL_P(val), "%d%*[/]%d%*[/]%d %d%*[:]%d%*[:]%d", &t.tm_mon, &t.tm_mday, &t.tm_year, &t.tm_hour, &t.tm_min, &t.tm_sec); if (n != 3 && n != 6) { _php_ibase_module_error("Invalid date/time format (expected 3 or 6 fields, got %d." " Use format 'm/d/Y H:i:s'. You gave '%s')" TSRMLS_CC, n, Z_STRVAL_P(val)); return FAILURE; } t.tm_year -= 1900; t.tm_mon--; #endif isc_encode_timestamp(&t, (ISC_TIMESTAMP * ) buf); break; case SQL_TYPE_DATE: convert_to_string(val); #ifdef HAVE_STRPTIME strptime(Z_STRVAL_P(val), INI_STR("ibase.dateformat"), &t); #else n = sscanf(Z_STRVAL_P(val), "%d%*[/]%d%*[/]%d", &t.tm_mon, &t.tm_mday, &t.tm_year); if (n != 3) { _php_ibase_module_error("Invalid date format (expected 3 fields, got %d. " "Use format 'm/d/Y' You gave '%s')" TSRMLS_CC, n, Z_STRVAL_P(val)); return FAILURE; } t.tm_year -= 1900; t.tm_mon--; #endif isc_encode_sql_date(&t, (ISC_DATE *) buf); break; case SQL_TYPE_TIME: convert_to_string(val); #ifdef HAVE_STRPTIME strptime(Z_STRVAL_P(val), INI_STR("ibase.timeformat"), &t); #else n = sscanf(Z_STRVAL_P(val), "%d%*[:]%d%*[:]%d", &t.tm_hour, &t.tm_min, &t.tm_sec); if (n != 3) { _php_ibase_module_error("Invalid time format (expected 3 fields, got %d. " "Use format 'H:i:s'. You gave '%s')" TSRMLS_CC, n, Z_STRVAL_P(val)); return FAILURE; } #endif isc_encode_sql_time(&t, (ISC_TIME *) buf); break; default: convert_to_string(val); strlcpy(buf, Z_STRVAL_P(val), buf_size); } } } return SUCCESS; } /* }}} */ static int _php_ibase_bind(XSQLDA *sqlda, zval ***b_vars, BIND_BUF *buf, /* {{{ */ ibase_query *ib_query TSRMLS_DC) { int i, array_cnt = 0, rv = SUCCESS; for (i = 0; i < sqlda->sqld; ++i) { /* bound vars */ zval *b_var = *b_vars[i]; XSQLVAR *var = &sqlda->sqlvar[i]; var->sqlind = &buf[i].sqlind; /* check if a NULL should be inserted */ switch (Z_TYPE_P(b_var)) { int force_null; case IS_STRING: force_null = 0; /* for these types, an empty string can be handled like a NULL value */ switch (var->sqltype & ~1) { case SQL_SHORT: case SQL_LONG: case SQL_INT64: case SQL_FLOAT: case SQL_DOUBLE: case SQL_TIMESTAMP: case SQL_TYPE_DATE: case SQL_TYPE_TIME: force_null = (Z_STRLEN_P(b_var) == 0); } if (! force_null) break; case IS_NULL: buf[i].sqlind = -1; if (var->sqltype & SQL_ARRAY) ++array_cnt; continue; } /* if we make it to this point, we must provide a value for the parameter */ buf[i].sqlind = 0; var->sqldata = (void*)&buf[i].val; switch (var->sqltype & ~1) { struct tm t; case SQL_TIMESTAMP: case SQL_TYPE_DATE: case SQL_TYPE_TIME: if (Z_TYPE_P(b_var) == IS_LONG) { struct tm *res; res = php_gmtime_r(&Z_LVAL_P(b_var), &t); if (!res) { return FAILURE; } } else { #ifdef HAVE_STRPTIME char *format = INI_STR("ibase.timestampformat"); convert_to_string(b_var); switch (var->sqltype & ~1) { case SQL_TYPE_DATE: format = INI_STR("ibase.dateformat"); break; case SQL_TYPE_TIME: format = INI_STR("ibase.timeformat"); } if (!strptime(Z_STRVAL_P(b_var), format, &t)) { /* strptime() cannot handle it, so let IB have a try */ break; } #else /* ifndef HAVE_STRPTIME */ break; /* let IB parse it as a string */ #endif } switch (var->sqltype & ~1) { default: /* == case SQL_TIMESTAMP */ isc_encode_timestamp(&t, &buf[i].val.tsval); break; case SQL_TYPE_DATE: isc_encode_sql_date(&t, &buf[i].val.dtval); break; case SQL_TYPE_TIME: isc_encode_sql_time(&t, &buf[i].val.tmval); break; } continue; case SQL_BLOB: convert_to_string(b_var); if (Z_STRLEN_P(b_var) != BLOB_ID_LEN || !_php_ibase_string_to_quad(Z_STRVAL_P(b_var), &buf[i].val.qval)) { ibase_blob ib_blob = { NULL, BLOB_INPUT }; if (isc_create_blob(IB_STATUS, &ib_query->link->handle, &ib_query->trans->handle, &ib_blob.bl_handle, &ib_blob.bl_qd)) { _php_ibase_error(TSRMLS_C); return FAILURE; } if (_php_ibase_blob_add(&b_var, &ib_blob TSRMLS_CC) != SUCCESS) { return FAILURE; } if (isc_close_blob(IB_STATUS, &ib_blob.bl_handle)) { _php_ibase_error(TSRMLS_C); return FAILURE; } buf[i].val.qval = ib_blob.bl_qd; } continue; case SQL_ARRAY: if (Z_TYPE_P(b_var) != IS_ARRAY) { convert_to_string(b_var); if (Z_STRLEN_P(b_var) != BLOB_ID_LEN || !_php_ibase_string_to_quad(Z_STRVAL_P(b_var), &buf[i].val.qval)) { _php_ibase_module_error("Parameter %d: invalid array ID" TSRMLS_CC,i+1); rv = FAILURE; } } else { /* convert the array data into something IB can understand */ ibase_array *ar = &ib_query->in_array[array_cnt]; void *array_data = emalloc(ar->ar_size); ISC_QUAD array_id = { 0, 0 }; if (FAILURE == _php_ibase_bind_array(b_var, array_data, ar->ar_size, ar, 0 TSRMLS_CC)) { _php_ibase_module_error("Parameter %d: failed to bind array argument" TSRMLS_CC,i+1); efree(array_data); rv = FAILURE; continue; } if (isc_array_put_slice(IB_STATUS, &ib_query->link->handle, &ib_query->trans->handle, &array_id, &ar->ar_desc, array_data, &ar->ar_size)) { _php_ibase_error(TSRMLS_C); efree(array_data); return FAILURE; } buf[i].val.qval = array_id; efree(array_data); } ++array_cnt; continue; } /* switch */ /* we end up here if none of the switch cases handled the field */ convert_to_string(b_var); var->sqldata = Z_STRVAL_P(b_var); var->sqllen = Z_STRLEN_P(b_var); var->sqltype = SQL_TEXT; } /* for */ return rv; } /* }}} */ static void _php_ibase_alloc_xsqlda(XSQLDA *sqlda) /* {{{ */ { int i; for (i = 0; i < sqlda->sqld; i++) { XSQLVAR *var = &sqlda->sqlvar[i]; switch (var->sqltype & ~1) { case SQL_TEXT: var->sqldata = safe_emalloc(sizeof(char), var->sqllen, 0); break; case SQL_VARYING: var->sqldata = safe_emalloc(sizeof(char), var->sqllen + sizeof(short), 0); break; case SQL_SHORT: var->sqldata = emalloc(sizeof(short)); break; case SQL_LONG: var->sqldata = emalloc(sizeof(ISC_LONG)); break; case SQL_FLOAT: var->sqldata = emalloc(sizeof(float)); break; case SQL_DOUBLE: var->sqldata = emalloc(sizeof(double)); break; case SQL_INT64: var->sqldata = emalloc(sizeof(ISC_INT64)); break; case SQL_TIMESTAMP: var->sqldata = emalloc(sizeof(ISC_TIMESTAMP)); break; case SQL_TYPE_DATE: var->sqldata = emalloc(sizeof(ISC_DATE)); break; case SQL_TYPE_TIME: var->sqldata = emalloc(sizeof(ISC_TIME)); break; case SQL_BLOB: case SQL_ARRAY: var->sqldata = emalloc(sizeof(ISC_QUAD)); break; } /* switch */ if (var->sqltype & 1) { /* sql NULL flag */ var->sqlind = emalloc(sizeof(short)); } else { var->sqlind = NULL; } } /* for */ } /* }}} */ static int _php_ibase_exec(INTERNAL_FUNCTION_PARAMETERS, ibase_result **ib_resultp, /* {{{ */ ibase_query *ib_query, zval ***args) { XSQLDA *in_sqlda = NULL, *out_sqlda = NULL; BIND_BUF *bind_buf = NULL; int i, rv = FAILURE; static char info_count[] = { isc_info_sql_records }; char result[64]; ISC_STATUS isc_result; int argc = ib_query->in_sqlda ? ib_query->in_sqlda->sqld : 0; RESET_ERRMSG; for (i = 0; i < argc; ++i) { SEPARATE_ZVAL(args[i]); } switch (ib_query->statement_type) { isc_tr_handle tr; ibase_tr_list **l; ibase_trans *trans; case isc_info_sql_stmt_start_trans: /* a SET TRANSACTION statement should be executed with a NULL trans handle */ tr = NULL; if (isc_dsql_execute_immediate(IB_STATUS, &ib_query->link->handle, &tr, 0, ib_query->query, ib_query->dialect, NULL)) { _php_ibase_error(TSRMLS_C); goto _php_ibase_exec_error; } trans = (ibase_trans *) emalloc(sizeof(ibase_trans)); trans->handle = tr; trans->link_cnt = 1; trans->affected_rows = 0; trans->db_link[0] = ib_query->link; if (ib_query->link->tr_list == NULL) { ib_query->link->tr_list = (ibase_tr_list *) emalloc(sizeof(ibase_tr_list)); ib_query->link->tr_list->trans = NULL; ib_query->link->tr_list->next = NULL; } /* link the transaction into the connection-transaction list */ for (l = &ib_query->link->tr_list; *l != NULL; l = &(*l)->next); *l = (ibase_tr_list *) emalloc(sizeof(ibase_tr_list)); (*l)->trans = trans; (*l)->next = NULL; ZEND_REGISTER_RESOURCE(return_value, trans, le_trans); return SUCCESS; case isc_info_sql_stmt_commit: case isc_info_sql_stmt_rollback: if (isc_dsql_execute_immediate(IB_STATUS, &ib_query->link->handle, &ib_query->trans->handle, 0, ib_query->query, ib_query->dialect, NULL)) { _php_ibase_error(TSRMLS_C); goto _php_ibase_exec_error; } if (ib_query->trans->handle == NULL && ib_query->trans_res_id != 0) { /* transaction was released by the query and was a registered resource, so we have to release it */ zend_list_delete(ib_query->trans_res_id); } RETVAL_TRUE; return SUCCESS; default: RETVAL_FALSE; } /* allocate sqlda and output buffers */ if (ib_query->out_sqlda) { /* output variables in select, select for update */ ibase_result *res; IBDEBUG("Query wants XSQLDA for output"); res = emalloc(sizeof(ibase_result)+sizeof(ibase_array)*max(0,ib_query->out_array_cnt-1)); res->link = ib_query->link; res->trans = ib_query->trans; res->stmt = ib_query->stmt; /* ib_result and ib_query point at each other to handle release of statement handle properly */ res->query = ib_query; ib_query->result = res; res->statement_type = ib_query->statement_type; res->has_more_rows = 1; out_sqlda = res->out_sqlda = emalloc(XSQLDA_LENGTH(ib_query->out_sqlda->sqld)); memcpy(out_sqlda, ib_query->out_sqlda, XSQLDA_LENGTH(ib_query->out_sqlda->sqld)); _php_ibase_alloc_xsqlda(out_sqlda); if (ib_query->out_array) { memcpy(&res->out_array, ib_query->out_array, sizeof(ibase_array)*ib_query->out_array_cnt); } *ib_resultp = res; } if (ib_query->in_sqlda) { /* has placeholders */ IBDEBUG("Query wants XSQLDA for input"); in_sqlda = emalloc(XSQLDA_LENGTH(ib_query->in_sqlda->sqld)); memcpy(in_sqlda, ib_query->in_sqlda, XSQLDA_LENGTH(ib_query->in_sqlda->sqld)); bind_buf = safe_emalloc(sizeof(BIND_BUF), ib_query->in_sqlda->sqld, 0); if (_php_ibase_bind(in_sqlda, args, bind_buf, ib_query TSRMLS_CC) == FAILURE) { IBDEBUG("Could not bind input XSQLDA"); goto _php_ibase_exec_error; } } if (ib_query->statement_type == isc_info_sql_stmt_exec_procedure) { isc_result = isc_dsql_execute2(IB_STATUS, &ib_query->trans->handle, &ib_query->stmt, SQLDA_CURRENT_VERSION, in_sqlda, out_sqlda); } else { isc_result = isc_dsql_execute(IB_STATUS, &ib_query->trans->handle, &ib_query->stmt, SQLDA_CURRENT_VERSION, in_sqlda); } if (isc_result) { IBDEBUG("Could not execute query"); _php_ibase_error(TSRMLS_C); goto _php_ibase_exec_error; } ib_query->trans->affected_rows = 0; switch (ib_query->statement_type) { unsigned long affected_rows; case isc_info_sql_stmt_insert: case isc_info_sql_stmt_update: case isc_info_sql_stmt_delete: case isc_info_sql_stmt_exec_procedure: if (isc_dsql_sql_info(IB_STATUS, &ib_query->stmt, sizeof(info_count), info_count, sizeof(result), result)) { _php_ibase_error(TSRMLS_C); goto _php_ibase_exec_error; } affected_rows = 0; if (result[0] == isc_info_sql_records) { unsigned i = 3, result_size = isc_vax_integer(&result[1],2); while (result[i] != isc_info_end && i < result_size) { short len = (short)isc_vax_integer(&result[i+1],2); if (result[i] != isc_info_req_select_count) { affected_rows += isc_vax_integer(&result[i+3],len); } i += len+3; } } ib_query->trans->affected_rows = affected_rows; if (!ib_query->out_sqlda) { /* no result set is being returned */ if (affected_rows) { RETVAL_LONG(affected_rows); } else { RETVAL_TRUE; } break; } default: RETVAL_TRUE; } rv = SUCCESS; _php_ibase_exec_error: if (in_sqlda) { efree(in_sqlda); } if (bind_buf) efree(bind_buf); if (rv == FAILURE) { if (*ib_resultp) { efree(*ib_resultp); *ib_resultp = NULL; } if (out_sqlda) { _php_ibase_free_xsqlda(out_sqlda); } } return rv; } /* }}} */ /* {{{ proto mixed ibase_query([resource link_identifier, [ resource link_identifier, ]] string query [, mixed bind_arg [, mixed bind_arg [, ...]]]) Execute a query */ PHP_FUNCTION(ibase_query) { zval *zlink, *ztrans, ***bind_args = NULL; char *query; int bind_i, query_len, bind_num; long trans_res_id = 0; ibase_db_link *ib_link = NULL; ibase_trans *trans = NULL; ibase_query ib_query = { NULL, NULL, 0, 0 }; ibase_result *result = NULL; RESET_ERRMSG; RETVAL_FALSE; switch (ZEND_NUM_ARGS()) { long l; default: if (SUCCESS == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, 3 TSRMLS_CC, "rrs", &zlink, &ztrans, &query, &query_len)) { ZEND_FETCH_RESOURCE2(ib_link, ibase_db_link*, &zlink, -1, LE_LINK, le_link, le_plink); ZEND_FETCH_RESOURCE(trans, ibase_trans*, &ztrans, -1, LE_TRANS, le_trans); trans_res_id = Z_LVAL_P(ztrans); bind_i = 3; break; } case 2: if (SUCCESS == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, 2 TSRMLS_CC, "rs", &zlink, &query, &query_len)) { _php_ibase_get_link_trans(INTERNAL_FUNCTION_PARAM_PASSTHRU, &zlink, &ib_link, &trans); if (trans != NULL) { trans_res_id = Z_LVAL_P(zlink); } bind_i = 2; break; } /* the statement is 'CREATE DATABASE ...' if the link argument is IBASE_CREATE */ if (SUCCESS == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "ls", &l, &query, &query_len) && l == PHP_IBASE_CREATE) { isc_db_handle db = NULL; isc_tr_handle trans = NULL; if (PG(sql_safe_mode)) { _php_ibase_module_error("CREATE DATABASE is not allowed in SQL safe mode" TSRMLS_CC); } else if (((l = INI_INT("ibase.max_links")) != -1) && (IBG(num_links) >= l)) { _php_ibase_module_error("CREATE DATABASE is not allowed: maximum link count " "(%ld) reached" TSRMLS_CC, l); } else if (isc_dsql_execute_immediate(IB_STATUS, &db, &trans, (short)query_len, query, SQL_DIALECT_CURRENT, NULL)) { _php_ibase_error(TSRMLS_C); } else if (!db) { _php_ibase_module_error("Connection to created database could not be " "established" TSRMLS_CC); } else { /* register the link as a resource; unfortunately, we cannot register it in the hash table, because we don't know the connection params */ ib_link = (ibase_db_link *) emalloc(sizeof(ibase_db_link)); ib_link->handle = db; ib_link->dialect = SQL_DIALECT_CURRENT; ib_link->tr_list = NULL; ib_link->event_head = NULL; ZEND_REGISTER_RESOURCE(return_value, ib_link, le_link); zend_list_addref(Z_LVAL_P(return_value)); IBG(default_link) = Z_LVAL_P(return_value); ++IBG(num_links); } return; } case 1: case 0: if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() ? 1 : 0 TSRMLS_CC, "s", &query, &query_len)) { ZEND_FETCH_RESOURCE2(ib_link, ibase_db_link *, NULL, IBG(default_link), LE_LINK, le_link, le_plink); bind_i = 1; break; } return; } /* open default transaction */ if (ib_link == NULL || FAILURE == _php_ibase_def_trans(ib_link, &trans TSRMLS_CC) || FAILURE == _php_ibase_alloc_query(&ib_query, ib_link, trans, query, ib_link->dialect, trans_res_id TSRMLS_CC)) { return; } do { int bind_n = ZEND_NUM_ARGS() - bind_i, expected_n = ib_query.in_sqlda ? ib_query.in_sqlda->sqld : 0; if (bind_n != expected_n) { php_error_docref(NULL TSRMLS_CC, (bind_n < expected_n) ? E_WARNING : E_NOTICE, "Statement expects %d arguments, %d given", expected_n, bind_n); if (bind_n < expected_n) { break; } } else if (bind_n > 0) { if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &bind_args, &bind_num) == FAILURE) { return; } } if (FAILURE == _php_ibase_exec(INTERNAL_FUNCTION_PARAM_PASSTHRU, &result, &ib_query, &bind_args[bind_i])) { break; } if (result != NULL) { /* statement returns a result */ result->type = QUERY_RESULT; /* EXECUTE PROCEDURE returns only one row => statement can be released immediately */ if (ib_query.statement_type != isc_info_sql_stmt_exec_procedure) { ib_query.stmt = NULL; /* keep stmt when free query */ } ZEND_REGISTER_RESOURCE(return_value, result, le_result); } } while (0); _php_ibase_free_query(&ib_query TSRMLS_CC); if (bind_args) { efree(bind_args); } } /* }}} */ /* {{{ proto int ibase_affected_rows( [ resource link_identifier ] ) Returns the number of rows affected by the previous INSERT, UPDATE or DELETE statement */ PHP_FUNCTION(ibase_affected_rows) { ibase_trans *trans = NULL; ibase_db_link *ib_link; zval *arg = NULL; RESET_ERRMSG; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|r", &arg) == FAILURE) { return; } if (!arg) { ZEND_FETCH_RESOURCE2(ib_link, ibase_db_link *, NULL, IBG(default_link), LE_LINK, le_link, le_plink); if (ib_link->tr_list == NULL || ib_link->tr_list->trans == NULL) { RETURN_FALSE; } trans = ib_link->tr_list->trans; } else { /* one id was passed, could be db or trans id */ _php_ibase_get_link_trans(INTERNAL_FUNCTION_PARAM_PASSTHRU, &arg, &ib_link, &trans); if (trans == NULL) { ZEND_FETCH_RESOURCE2(ib_link, ibase_db_link *, &arg, -1, LE_LINK, le_link, le_plink); if (ib_link->tr_list == NULL || ib_link->tr_list->trans == NULL) { RETURN_FALSE; } trans = ib_link->tr_list->trans; } } RETURN_LONG(trans->affected_rows); } /* }}} */ /* {{{ proto int ibase_num_rows( resource result_identifier ) Return the number of rows that are available in a result */ #if abies_0 PHP_FUNCTION(ibase_num_rows) { /** * As this function relies on the InterBase API function isc_dsql_sql_info() * which has a couple of limitations (which I hope will be fixed in future * releases of Firebird), this function is fairly useless. I'm leaving it * in place for people who can live with the limitations, which I only * found out about after I had implemented it anyway. * * Currently, there's no way to determine how many rows can be fetched from * a cursor. The only number that _can_ be determined is the number of rows * that have already been pre-fetched by the client library. * This implies the following: * - num_rows() always returns zero before the first fetch; * - num_rows() for SELECT ... FOR UPDATE is broken -> never returns a * higher number than the number of records fetched so far (no pre-fetch); * - the result of num_rows() for other statements is merely a lower bound * on the number of records => calling ibase_num_rows() again after a couple * of fetches will most likely return a new (higher) figure for large result * sets. */ zval *result_arg; ibase_result *ib_result; static char info_count[] = {isc_info_sql_records}; char result[64]; RESET_ERRMSG; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &result_arg) == FAILURE) { return; } ZEND_FETCH_RESOURCE(ib_result, ibase_result *, &result_arg, -1, LE_RESULT, le_result); if (isc_dsql_sql_info(IB_STATUS, &ib_result->stmt, sizeof(info_count), info_count, sizeof(result), result)) { _php_ibase_error(TSRMLS_C); RETURN_FALSE; } if (result[0] == isc_info_sql_records) { unsigned i = 3, result_size = isc_vax_integer(&result[1],2); while (result[i] != isc_info_end && i < result_size) { short len = (short)isc_vax_integer(&result[i+1],2); if (result[i] == isc_info_req_select_count) { RETURN_LONG(isc_vax_integer(&result[i+3],len)); } i += len+3; } } } #endif /* }}} */ static int _php_ibase_var_zval(zval *val, void *data, int type, int len, /* {{{ */ int scale, int flag TSRMLS_DC) { static ISC_INT64 const scales[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, LL_LIT(10000000000), LL_LIT(100000000000), LL_LIT(1000000000000), LL_LIT(10000000000000), LL_LIT(100000000000000), LL_LIT(1000000000000000), LL_LIT(10000000000000000), LL_LIT(100000000000000000), LL_LIT(1000000000000000000) }; switch (type & ~1) { unsigned short l; long n; char string_data[255]; struct tm t; char *format; case SQL_VARYING: len = ((IBVARY *) data)->vary_length; data = ((IBVARY *) data)->vary_string; /* no break */ case SQL_TEXT: ZVAL_STRINGL(val,(char *) data,len,1); break; case SQL_SHORT: n = *(short *) data; goto _sql_long; case SQL_INT64: #if (SIZEOF_LONG >= 8) n = *(long *) data; goto _sql_long; #else if (scale == 0) { l = slprintf(string_data, sizeof(string_data), "%" LL_MASK "d", *(ISC_INT64 *) data); ZVAL_STRINGL(val,string_data,l,1); } else { ISC_INT64 n = *(ISC_INT64 *) data, f = scales[-scale]; if (n >= 0) { l = slprintf(string_data, sizeof(string_data), "%" LL_MASK "d.%0*" LL_MASK "d", n / f, -scale, n % f); } else if (n <= -f) { l = slprintf(string_data, sizeof(string_data), "%" LL_MASK "d.%0*" LL_MASK "d", n / f, -scale, -n % f); } else { l = slprintf(string_data, sizeof(string_data), "-0.%0*" LL_MASK "d", -scale, -n % f); } ZVAL_STRINGL(val,string_data,l,1); } break; #endif case SQL_LONG: n = *(ISC_LONG *) data; _sql_long: if (scale == 0) { ZVAL_LONG(val,n); } else { long f = (long) scales[-scale]; if (n >= 0) { l = slprintf(string_data, sizeof(string_data), "%ld.%0*ld", n / f, -scale, n % f); } else if (n <= -f) { l = slprintf(string_data, sizeof(string_data), "%ld.%0*ld", n / f, -scale, -n % f); } else { l = slprintf(string_data, sizeof(string_data), "-0.%0*ld", -scale, -n % f); } ZVAL_STRINGL(val,string_data,l,1); } break; case SQL_FLOAT: ZVAL_DOUBLE(val, *(float *) data); break; case SQL_DOUBLE: ZVAL_DOUBLE(val, *(double *) data); break; case SQL_DATE: /* == case SQL_TIMESTAMP: */ format = INI_STR("ibase.timestampformat"); isc_decode_timestamp((ISC_TIMESTAMP *) data, &t); goto format_date_time; case SQL_TYPE_DATE: format = INI_STR("ibase.dateformat"); isc_decode_sql_date((ISC_DATE *) data, &t); goto format_date_time; case SQL_TYPE_TIME: format = INI_STR("ibase.timeformat"); isc_decode_sql_time((ISC_TIME *) data, &t); format_date_time: /* XXX - Might have to remove this later - seems that isc_decode_date() always sets tm_isdst to 0, sometimes incorrectly (InterBase 6 bug?) */ t.tm_isdst = -1; #if HAVE_TM_ZONE t.tm_zone = tzname[0]; #endif if (flag & PHP_IBASE_UNIXTIME) { ZVAL_LONG(val, mktime(&t)); } else { #if HAVE_STRFTIME l = strftime(string_data, sizeof(string_data), format, &t); #else switch (type & ~1) { default: l = slprintf(string_data, sizeof(string_data), "%02d/%02d/%4d %02d:%02d:%02d", t.tm_mon+1, t.tm_mday, t.tm_year + 1900, t.tm_hour, t.tm_min, t.tm_sec); break; case SQL_TYPE_DATE: l = slprintf(string_data, sizeof(string_data), "%02d/%02d/%4d", t.tm_mon + 1, t.tm_mday, t.tm_year+1900); break; case SQL_TYPE_TIME: l = slprintf(string_data, sizeof(string_data), "%02d:%02d:%02d", t.tm_hour, t.tm_min, t.tm_sec); break; } #endif ZVAL_STRINGL(val,string_data,l,1); break; } } /* switch (type) */ return SUCCESS; } /* }}} */ static int _php_ibase_arr_zval(zval *ar_zval, char *data, unsigned long data_size, /* {{{ */ ibase_array *ib_array, int dim, int flag TSRMLS_DC) { /** * Create multidimension array - recursion function */ int u_bound = ib_array->ar_desc.array_desc_bounds[dim].array_bound_upper, l_bound = ib_array->ar_desc.array_desc_bounds[dim].array_bound_lower, dim_len = 1 + u_bound - l_bound; unsigned short i; if (dim < ib_array->ar_desc.array_desc_dimensions) { /* array again */ unsigned long slice_size = data_size / dim_len; array_init(ar_zval); for (i = 0; i < dim_len; ++i) { zval *slice_zval; ALLOC_INIT_ZVAL(slice_zval); /* recursion here */ if (FAILURE == _php_ibase_arr_zval(slice_zval, data, slice_size, ib_array, dim + 1, flag TSRMLS_CC)) { return FAILURE; } data += slice_size; add_index_zval(ar_zval,l_bound+i,slice_zval); } } else { /* data at last */ if (FAILURE == _php_ibase_var_zval(ar_zval, data, ib_array->el_type, ib_array->ar_desc.array_desc_length, ib_array->ar_desc.array_desc_scale, flag TSRMLS_CC)) { return FAILURE; } /* fix for peculiar handling of VARCHAR arrays; truncate the field to the cstring length */ if (ib_array->ar_desc.array_desc_dtype == blr_varying || ib_array->ar_desc.array_desc_dtype == blr_varying2) { Z_STRLEN_P(ar_zval) = strlen(Z_STRVAL_P(ar_zval)); } } return SUCCESS; } /* }}} */ static void _php_ibase_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, int fetch_type) /* {{{ */ { zval *result_arg; long i, array_cnt = 0, flag = 0; ibase_result *ib_result; RESET_ERRMSG; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &result_arg, &flag)) { return; } ZEND_FETCH_RESOURCE(ib_result, ibase_result *, &result_arg, -1, LE_RESULT, le_result); if (ib_result->out_sqlda == NULL || !ib_result->has_more_rows) { RETURN_FALSE; } if (ib_result->statement_type != isc_info_sql_stmt_exec_procedure) { if (isc_dsql_fetch(IB_STATUS, &ib_result->stmt, 1, ib_result->out_sqlda)) { ib_result->has_more_rows = 0; if (IB_STATUS[0] && IB_STATUS[1]) { /* error in fetch */ _php_ibase_error(TSRMLS_C); } RETURN_FALSE; } } else { ib_result->has_more_rows = 0; } array_init(return_value); for (i = 0; i < ib_result->out_sqlda->sqld; ++i) { XSQLVAR *var = &ib_result->out_sqlda->sqlvar[i]; char buf[METADATALENGTH+4], *alias = var->aliasname; if (! (fetch_type & FETCH_ROW)) { int i = 0; char const *base = "FIELD"; /* use 'FIELD' if name is empty */ /** * Ensure no two columns have identical names: * keep generating new names until we find one that is unique. */ switch (*alias) { void *p; default: i = 1; base = alias; while (SUCCESS == zend_symtable_find( Z_ARRVAL_P(return_value),alias,strlen(alias)+1,&p)) { case '\0': snprintf(alias = buf, sizeof(buf), "%s_%02d", base, i++); } } } if (((var->sqltype & 1) == 0) || *var->sqlind != -1) { zval *result; ALLOC_INIT_ZVAL(result); switch (var->sqltype & ~1) { default: _php_ibase_var_zval(result, var->sqldata, var->sqltype, var->sqllen, var->sqlscale, flag TSRMLS_CC); break; case SQL_BLOB: if (flag & PHP_IBASE_FETCH_BLOBS) { /* fetch blob contents into hash */ ibase_blob blob_handle; unsigned long max_len = 0; static char bl_items[] = {isc_info_blob_total_length}; char bl_info[20]; unsigned short i; blob_handle.bl_handle = NULL; blob_handle.bl_qd = *(ISC_QUAD *) var->sqldata; if (isc_open_blob(IB_STATUS, &ib_result->link->handle, &ib_result->trans->handle, &blob_handle.bl_handle, &blob_handle.bl_qd)) { _php_ibase_error(TSRMLS_C); goto _php_ibase_fetch_error; } if (isc_blob_info(IB_STATUS, &blob_handle.bl_handle, sizeof(bl_items), bl_items, sizeof(bl_info), bl_info)) { _php_ibase_error(TSRMLS_C); goto _php_ibase_fetch_error; } /* find total length of blob's data */ for (i = 0; i < sizeof(bl_info); ) { unsigned short item_len; char item = bl_info[i++]; if (item == isc_info_end || item == isc_info_truncated || item == isc_info_error || i >= sizeof(bl_info)) { _php_ibase_module_error("Could not determine BLOB size (internal error)" TSRMLS_CC); goto _php_ibase_fetch_error; } item_len = (unsigned short) isc_vax_integer(&bl_info[i], 2); if (item == isc_info_blob_total_length) { max_len = isc_vax_integer(&bl_info[i+2], item_len); break; } i += item_len+2; } if (max_len == 0) { ZVAL_STRING(result, "", 1); } else if (SUCCESS != _php_ibase_blob_get(result, &blob_handle, max_len TSRMLS_CC)) { goto _php_ibase_fetch_error; } if (isc_close_blob(IB_STATUS, &blob_handle.bl_handle)) { _php_ibase_error(TSRMLS_C); goto _php_ibase_fetch_error; } } else { /* blob id only */ ISC_QUAD bl_qd = *(ISC_QUAD *) var->sqldata; ZVAL_STRINGL(result,_php_ibase_quad_to_string(bl_qd), BLOB_ID_LEN, 0); } break; case SQL_ARRAY: if (flag & PHP_IBASE_FETCH_ARRAYS) { /* array can be *huge* so only fetch if asked */ ISC_QUAD ar_qd = *(ISC_QUAD *) var->sqldata; ibase_array *ib_array = &ib_result->out_array[array_cnt++]; void *ar_data = emalloc(ib_array->ar_size); if (isc_array_get_slice(IB_STATUS, &ib_result->link->handle, &ib_result->trans->handle, &ar_qd, &ib_array->ar_desc, ar_data, &ib_array->ar_size)) { _php_ibase_error(TSRMLS_C); efree(ar_data); goto _php_ibase_fetch_error; } if (FAILURE == _php_ibase_arr_zval(result, ar_data, ib_array->ar_size, ib_array, 0, flag TSRMLS_CC)) { efree(ar_data); goto _php_ibase_fetch_error; } efree(ar_data); } else { /* blob id only */ ISC_QUAD ar_qd = *(ISC_QUAD *) var->sqldata; ZVAL_STRINGL(result,_php_ibase_quad_to_string(ar_qd), BLOB_ID_LEN, 0); } break; _php_ibase_fetch_error: zval_dtor(result); FREE_ZVAL(result); RETURN_FALSE; } /* switch */ if (fetch_type & FETCH_ROW) { add_index_zval(return_value, i, result); } else { add_assoc_zval(return_value, alias, result); } } else { if (fetch_type & FETCH_ROW) { add_index_null(return_value, i); } else { add_assoc_null(return_value, alias); } } } /* for field */ } /* }}} */ /* {{{ proto array ibase_fetch_row(resource result [, int fetch_flags]) Fetch a row from the results of a query */ PHP_FUNCTION(ibase_fetch_row) { _php_ibase_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, FETCH_ROW); } /* }}} */ /* {{{ proto array ibase_fetch_assoc(resource result [, int fetch_flags]) Fetch a row from the results of a query */ PHP_FUNCTION(ibase_fetch_assoc) { _php_ibase_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, FETCH_ARRAY); } /* }}} */ /* {{{ proto object ibase_fetch_object(resource result [, int fetch_flags]) Fetch a object from the results of a query */ PHP_FUNCTION(ibase_fetch_object) { _php_ibase_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, FETCH_ARRAY); if (Z_TYPE_P(return_value) == IS_ARRAY) { object_and_properties_init(return_value, ZEND_STANDARD_CLASS_DEF_PTR, Z_ARRVAL_P(return_value)); } } /* }}} */ /* {{{ proto bool ibase_name_result(resource result, string name) Assign a name to a result for use with ... WHERE CURRENT OF statements */ PHP_FUNCTION(ibase_name_result) { zval *result_arg; char *name_arg; int name_arg_len; ibase_result *ib_result; RESET_ERRMSG; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &result_arg, &name_arg, &name_arg_len) == FAILURE) { return; } ZEND_FETCH_RESOURCE(ib_result, ibase_result *, &result_arg, -1, LE_RESULT, le_result); if (isc_dsql_set_cursor_name(IB_STATUS, &ib_result->stmt, name_arg, 0)) { _php_ibase_error(TSRMLS_C); RETURN_FALSE; } RETURN_TRUE; } /* }}} */ /* {{{ proto bool ibase_free_result(resource result) Free the memory used by a result */ PHP_FUNCTION(ibase_free_result) { zval *result_arg; ibase_result *ib_result; RESET_ERRMSG; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &result_arg) == FAILURE) { return; } ZEND_FETCH_RESOURCE(ib_result, ibase_result *, &result_arg, -1, LE_RESULT, le_result); zend_list_delete(Z_RESVAL_P(result_arg)); RETURN_TRUE; } /* }}} */ /* {{{ proto resource ibase_prepare(resource link_identifier[, string query [, resource trans_identifier ]]) Prepare a query for later execution */ PHP_FUNCTION(ibase_prepare) { zval *link_arg, *trans_arg; ibase_db_link *ib_link; ibase_trans *trans = NULL; int query_len, trans_res_id = 0; ibase_query *ib_query; char *query; RESET_ERRMSG; if (ZEND_NUM_ARGS() == 1) { if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &query, &query_len) == FAILURE) { return; } ZEND_FETCH_RESOURCE2(ib_link, ibase_db_link *, NULL, IBG(default_link), LE_LINK, le_link, le_plink); } else if (ZEND_NUM_ARGS() == 2) { if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &link_arg, &query, &query_len) == FAILURE) { return; } _php_ibase_get_link_trans(INTERNAL_FUNCTION_PARAM_PASSTHRU, &link_arg, &ib_link, &trans); if (trans != NULL) { trans_res_id = Z_RESVAL_P(link_arg); } } else { if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rrs", &link_arg, &trans_arg, &query, &query_len) == FAILURE) { return; } ZEND_FETCH_RESOURCE2(ib_link, ibase_db_link *, &link_arg, -1, LE_LINK, le_link, le_plink); ZEND_FETCH_RESOURCE(trans, ibase_trans *, &trans_arg, -1, LE_TRANS, le_trans); trans_res_id = Z_RESVAL_P(trans_arg); } if (FAILURE == _php_ibase_def_trans(ib_link, &trans TSRMLS_CC)) { RETURN_FALSE; } ib_query = (ibase_query *) emalloc(sizeof(ibase_query)); if (FAILURE == _php_ibase_alloc_query(ib_query, ib_link, trans, query, ib_link->dialect, trans_res_id TSRMLS_CC)) { efree(ib_query); RETURN_FALSE; } ZEND_REGISTER_RESOURCE(return_value, ib_query, le_query); } /* }}} */ /* {{{ proto mixed ibase_execute(resource query [, mixed bind_arg [, mixed bind_arg [, ...]]]) Execute a previously prepared query */ PHP_FUNCTION(ibase_execute) { zval *query, ***args = NULL; ibase_query *ib_query; ibase_result *result = NULL; ALLOCA_FLAG(use_heap) RESET_ERRMSG; RETVAL_FALSE; if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() ? 1 : 0 TSRMLS_CC, "r", &query)) { return; } ZEND_FETCH_RESOURCE(ib_query, ibase_query *, &query, -1, LE_QUERY, le_query); do { int bind_n = ZEND_NUM_ARGS() - 1, expected_n = ib_query->in_sqlda ? ib_query->in_sqlda->sqld : 0; if (bind_n != expected_n) { php_error_docref(NULL TSRMLS_CC, (bind_n < expected_n) ? E_WARNING : E_NOTICE, "Statement expects %d arguments, %d given", expected_n, bind_n); if (bind_n < expected_n) { break; } } /* have variables to bind */ args = (zval ***) do_alloca((expected_n + 1) * sizeof(zval **), use_heap); if (FAILURE == zend_get_parameters_array_ex((expected_n + 1), args)) { break; } /* Have we used this cursor before and it's still open (exec proc has no cursor) ? */ if (ib_query->result_res_id != 0 && ib_query->statement_type != isc_info_sql_stmt_exec_procedure) { IBDEBUG("Implicitly closing a cursor"); if (isc_dsql_free_statement(IB_STATUS, &ib_query->stmt, DSQL_close)) { _php_ibase_error(TSRMLS_C); break; } /* invalidate previous results returned by this query (not necessary for exec proc) */ zend_list_delete(ib_query->result_res_id); } if (FAILURE == _php_ibase_exec(INTERNAL_FUNCTION_PARAM_PASSTHRU, &result, ib_query, &args[1])) { break; } /* free the query if trans handle was released */ if (ib_query->trans->handle == NULL) { zend_list_delete(Z_LVAL_P(query)); } if (result != NULL) { result->type = EXECUTE_RESULT; if (ib_query->statement_type == isc_info_sql_stmt_exec_procedure) { result->stmt = NULL; } ib_query->result_res_id = zend_list_insert(result, le_result TSRMLS_CC); RETVAL_RESOURCE(ib_query->result_res_id); } } while (0); if (args) { free_alloca(args, use_heap); } } /* }}} */ /* {{{ proto bool ibase_free_query(resource query) Free memory used by a query */ PHP_FUNCTION(ibase_free_query) { zval *query_arg; ibase_query *ib_query; RESET_ERRMSG; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &query_arg) == FAILURE) { return; } ZEND_FETCH_RESOURCE(ib_query, ibase_query *, &query_arg, -1, LE_QUERY, le_query); zend_list_delete(Z_RESVAL_P(query_arg)); RETURN_TRUE; } /* }}} */ /* {{{ proto int ibase_num_fields(resource query_result) Get the number of fields in result */ PHP_FUNCTION(ibase_num_fields) { zval *result; int type; XSQLDA *sqlda; RESET_ERRMSG; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &result) == FAILURE) { return; } zend_list_find(Z_RESVAL_P(result), &type); if (type == le_query) { ibase_query *ib_query; ZEND_FETCH_RESOURCE(ib_query, ibase_query *, &result, -1, LE_QUERY, le_query); sqlda = ib_query->out_sqlda; } else { ibase_result *ib_result; ZEND_FETCH_RESOURCE(ib_result, ibase_result *, &result, -1, LE_RESULT, le_result); sqlda = ib_result->out_sqlda; } if (sqlda == NULL) { RETURN_LONG(0); } else { RETURN_LONG(sqlda->sqld); } } /* }}} */ static void _php_ibase_field_info(zval *return_value, XSQLVAR *var) /* {{{ */ { unsigned short len; char buf[16], *s = buf; array_init(return_value); add_index_stringl(return_value, 0, var->sqlname, var->sqlname_length, 1); add_assoc_stringl(return_value, "name", var->sqlname, var->sqlname_length, 1); add_index_stringl(return_value, 1, var->aliasname, var->aliasname_length, 1); add_assoc_stringl(return_value, "alias", var->aliasname, var->aliasname_length, 1); add_index_stringl(return_value, 2, var->relname, var->relname_length, 1); add_assoc_stringl(return_value, "relation", var->relname, var->relname_length, 1); len = slprintf(buf, 16, "%d", var->sqllen); add_index_stringl(return_value, 3, buf, len, 1); add_assoc_stringl(return_value, "length", buf, len, 1); if (var->sqlscale < 0) { unsigned short precision = 0; switch (var->sqltype & ~1) { case SQL_SHORT: precision = 4; break; case SQL_LONG: precision = 9; break; case SQL_INT64: precision = 18; break; } len = slprintf(buf, 16, "NUMERIC(%d,%d)", precision, -var->sqlscale); add_index_stringl(return_value, 4, s, len, 1); add_assoc_stringl(return_value, "type", s, len, 1); } else { switch (var->sqltype & ~1) { case SQL_TEXT: s = "CHAR"; break; case SQL_VARYING: s = "VARCHAR"; break; case SQL_SHORT: s = "SMALLINT"; break; case SQL_LONG: s = "INTEGER"; break; case SQL_FLOAT: s = "FLOAT"; break; case SQL_DOUBLE: case SQL_D_FLOAT: s = "DOUBLE PRECISION"; break; case SQL_INT64: s = "BIGINT"; break; case SQL_TIMESTAMP: s = "TIMESTAMP"; break; case SQL_TYPE_DATE: s = "DATE"; break; case SQL_TYPE_TIME: s = "TIME"; break; case SQL_BLOB: s = "BLOB"; break; case SQL_ARRAY: s = "ARRAY"; break; /* FIXME: provide more detailed information about the field type, field size * and array dimensions */ case SQL_QUAD: s = "QUAD"; break; } add_index_string(return_value, 4, s, 1); add_assoc_string(return_value, "type", s, 1); } } /* }}} */ /* {{{ proto array ibase_field_info(resource query_result, int field_number) Get information about a field */ PHP_FUNCTION(ibase_field_info) { zval *result_arg; long field_arg; int type; XSQLDA *sqlda; RESET_ERRMSG; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &result_arg, &field_arg) == FAILURE) { return; } zend_list_find(Z_RESVAL_P(result_arg), &type); if (type == le_query) { ibase_query *ib_query; ZEND_FETCH_RESOURCE(ib_query, ibase_query *, &result_arg, -1, LE_QUERY, le_query); sqlda = ib_query->out_sqlda; } else { ibase_result *ib_result; ZEND_FETCH_RESOURCE(ib_result, ibase_result *, &result_arg, -1, LE_RESULT, le_result); sqlda = ib_result->out_sqlda; } if (sqlda == NULL) { _php_ibase_module_error("Trying to get field info from a non-select query" TSRMLS_CC); RETURN_FALSE; } if (field_arg < 0 || field_arg >= sqlda->sqld) { RETURN_FALSE; } _php_ibase_field_info(return_value, sqlda->sqlvar + field_arg); } /* }}} */ /* {{{ proto int ibase_num_params(resource query) Get the number of params in a prepared query */ PHP_FUNCTION(ibase_num_params) { zval *result; ibase_query *ib_query; RESET_ERRMSG; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &result) == FAILURE) { return; } ZEND_FETCH_RESOURCE(ib_query, ibase_query *, &result, -1, LE_QUERY, le_query); if (ib_query->in_sqlda == NULL) { RETURN_LONG(0); } else { RETURN_LONG(ib_query->in_sqlda->sqld); } } /* }}} */ /* {{{ proto array ibase_param_info(resource query, int field_number) Get information about a parameter */ PHP_FUNCTION(ibase_param_info) { zval *result_arg; long field_arg; ibase_query *ib_query; RESET_ERRMSG; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &result_arg, &field_arg) == FAILURE) { return; } ZEND_FETCH_RESOURCE(ib_query, ibase_query *, &result_arg, -1, LE_QUERY, le_query); if (ib_query->in_sqlda == NULL) { RETURN_FALSE; } if (field_arg < 0 || field_arg >= ib_query->in_sqlda->sqld) { RETURN_FALSE; } _php_ibase_field_info(return_value,ib_query->in_sqlda->sqlvar + field_arg); } /* }}} */ #endif /* HAVE_IBASE */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: sw=4 ts=4 fdm=marker * vim<600: sw=4 ts=4 */ php-interbase-5.4.6/ibase_blobs.c0000664000175000017500000003641412012622335016637 0ustar jtaylorjtaylor/* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2012 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.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: Ard Biesheuvel | +----------------------------------------------------------------------+ */ /* $Id$ */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "php.h" #if HAVE_IBASE #include "php_interbase.h" #include "php_ibase_includes.h" #define BLOB_CLOSE 1 #define BLOB_CANCEL 2 static int le_blob; static void _php_ibase_free_blob(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */ { ibase_blob *ib_blob = (ibase_blob *)rsrc->ptr; if (ib_blob->bl_handle != NULL) { /* blob open*/ if (isc_cancel_blob(IB_STATUS, &ib_blob->bl_handle)) { _php_ibase_module_error("You can lose data. Close any blob after reading from or " "writing to it. Use ibase_blob_close() before calling ibase_close()" TSRMLS_CC); } } efree(ib_blob); } /* }}} */ void php_ibase_blobs_minit(INIT_FUNC_ARGS) /* {{{ */ { le_blob = zend_register_list_destructors_ex(_php_ibase_free_blob, NULL, "interbase blob", module_number); } /* }}} */ int _php_ibase_string_to_quad(char const *id, ISC_QUAD *qd) /* {{{ */ { /* shortcut for most common case */ if (sizeof(ISC_QUAD) == sizeof(ISC_UINT64)) { return sscanf(id, BLOB_ID_MASK, (ISC_UINT64 *) qd); } else { ISC_UINT64 res; if (sscanf(id, BLOB_ID_MASK, &res)) { qd->gds_quad_high = (ISC_LONG) (res >> 0x20); qd->gds_quad_low = (ISC_LONG) (res & 0xFFFFFFFF); return 1; } return 0; } } /* }}} */ char *_php_ibase_quad_to_string(ISC_QUAD const qd) /* {{{ */ { char *result; /* shortcut for most common case */ if (sizeof(ISC_QUAD) == sizeof(ISC_UINT64)) { spprintf(&result, BLOB_ID_LEN+1, "0x%0*" LL_MASK "x", 16, *(ISC_UINT64*)(void *) &qd); } else { ISC_UINT64 res = ((ISC_UINT64) qd.gds_quad_high << 0x20) | qd.gds_quad_low; spprintf(&result, BLOB_ID_LEN+1, "0x%0*" LL_MASK "x", 16, res); } return result; } /* }}} */ typedef struct { /* {{{ */ ISC_LONG max_segment; /* Length of longest segment */ ISC_LONG num_segments; /* Total number of segments */ ISC_LONG total_length; /* Total length of blob */ int bl_stream; /* blob is stream ? */ /* }}} */ } IBASE_BLOBINFO; int _php_ibase_blob_get(zval *return_value, ibase_blob *ib_blob, unsigned long max_len TSRMLS_DC) /* {{{ */ { if (ib_blob->bl_qd.gds_quad_high || ib_blob->bl_qd.gds_quad_low) { /*not null ?*/ ISC_STATUS stat; char *bl_data; unsigned long cur_len; unsigned short seg_len; bl_data = safe_emalloc(1, max_len, 1); for (cur_len = stat = 0; (stat == 0 || stat == isc_segment) && cur_len < max_len; cur_len += seg_len) { unsigned short chunk_size = (max_len-cur_len) > USHRT_MAX ? USHRT_MAX : (unsigned short)(max_len-cur_len); stat = isc_get_segment(IB_STATUS, &ib_blob->bl_handle, &seg_len, chunk_size, &bl_data[cur_len]); } bl_data[cur_len] = '\0'; if (IB_STATUS[0] == 1 && (stat != 0 && stat != isc_segstr_eof && stat != isc_segment)) { efree(bl_data); _php_ibase_error(TSRMLS_C); return FAILURE; } RETVAL_STRINGL(bl_data, cur_len, 0); } else { /* null blob */ RETVAL_STRING("", 1); /* empty string */ } return SUCCESS; } /* }}} */ int _php_ibase_blob_add(zval **string_arg, ibase_blob *ib_blob TSRMLS_DC) /* {{{ */ { unsigned long put_cnt = 0, rem_cnt; unsigned short chunk_size; convert_to_string_ex(string_arg); for (rem_cnt = Z_STRLEN_PP(string_arg); rem_cnt > 0; rem_cnt -= chunk_size) { chunk_size = rem_cnt > USHRT_MAX ? USHRT_MAX : (unsigned short)rem_cnt; if (isc_put_segment(IB_STATUS, &ib_blob->bl_handle, chunk_size, &Z_STRVAL_PP(string_arg)[put_cnt] )) { _php_ibase_error(TSRMLS_C); return FAILURE; } put_cnt += chunk_size; } return SUCCESS; } /* }}} */ static int _php_ibase_blob_info(isc_blob_handle bl_handle, IBASE_BLOBINFO *bl_info TSRMLS_DC) /* {{{ */ { static char bl_items[] = { isc_info_blob_num_segments, isc_info_blob_max_segment, isc_info_blob_total_length, isc_info_blob_type }; char bl_inf[sizeof(long)*8], *p; bl_info->max_segment = 0; bl_info->num_segments = 0; bl_info->total_length = 0; bl_info->bl_stream = 0; if (isc_blob_info(IB_STATUS, &bl_handle, sizeof(bl_items), bl_items, sizeof(bl_inf), bl_inf)) { _php_ibase_error(TSRMLS_C); return FAILURE; } for (p = bl_inf; *p != isc_info_end && p < bl_inf + sizeof(bl_inf);) { unsigned short item_len; int item = *p++; item_len = (short) isc_vax_integer(p, 2); p += 2; switch (item) { case isc_info_blob_num_segments: bl_info->num_segments = isc_vax_integer(p, item_len); break; case isc_info_blob_max_segment: bl_info->max_segment = isc_vax_integer(p, item_len); break; case isc_info_blob_total_length: bl_info->total_length = isc_vax_integer(p, item_len); break; case isc_info_blob_type: bl_info->bl_stream = isc_vax_integer(p, item_len); break; case isc_info_end: break; case isc_info_truncated: case isc_info_error: /* hmm. don't think so...*/ _php_ibase_module_error("PHP module internal error" TSRMLS_CC); return FAILURE; } /* switch */ p += item_len; } /* for */ return SUCCESS; } /* }}} */ /* {{{ proto resource ibase_blob_create([resource link_identifier]) Create blob for adding data */ PHP_FUNCTION(ibase_blob_create) { zval *link = NULL; ibase_db_link *ib_link; ibase_trans *trans = NULL; ibase_blob *ib_blob; RESET_ERRMSG; if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|r", &link)) { RETURN_FALSE; } PHP_IBASE_LINK_TRANS(link, ib_link, trans); ib_blob = (ibase_blob *) emalloc(sizeof(ibase_blob)); ib_blob->bl_handle = NULL; ib_blob->type = BLOB_INPUT; if (isc_create_blob(IB_STATUS, &ib_link->handle, &trans->handle, &ib_blob->bl_handle, &ib_blob->bl_qd)) { _php_ibase_error(TSRMLS_C); efree(ib_blob); RETURN_FALSE; } ZEND_REGISTER_RESOURCE(return_value, ib_blob, le_blob); } /* }}} */ /* {{{ proto resource ibase_blob_open([ resource link_identifier, ] string blob_id) Open blob for retrieving data parts */ PHP_FUNCTION(ibase_blob_open) { char *blob_id; int blob_id_len; zval *link = NULL; ibase_db_link *ib_link; ibase_trans *trans = NULL; ibase_blob *ib_blob; RESET_ERRMSG; switch (ZEND_NUM_ARGS()) { default: WRONG_PARAM_COUNT; case 1: if (FAILURE == zend_parse_parameters(1 TSRMLS_CC, "s", &blob_id, &blob_id_len)) { RETURN_FALSE; } break; case 2: if (FAILURE == zend_parse_parameters(2 TSRMLS_CC, "rs", &link, &blob_id, &blob_id_len)) { RETURN_FALSE; } break; } PHP_IBASE_LINK_TRANS(link, ib_link, trans); ib_blob = (ibase_blob *) emalloc(sizeof(ibase_blob)); ib_blob->bl_handle = NULL; ib_blob->type = BLOB_OUTPUT; do { if (! _php_ibase_string_to_quad(blob_id, &ib_blob->bl_qd)) { _php_ibase_module_error("String is not a BLOB ID" TSRMLS_CC); break; } if (isc_open_blob(IB_STATUS, &ib_link->handle, &trans->handle, &ib_blob->bl_handle, &ib_blob->bl_qd)) { _php_ibase_error(TSRMLS_C); break; } ZEND_REGISTER_RESOURCE(return_value, ib_blob, le_blob); return; } while (0); efree(ib_blob); RETURN_FALSE; } /* }}} */ /* {{{ proto bool ibase_blob_add(resource blob_handle, string data) Add data into created blob */ PHP_FUNCTION(ibase_blob_add) { zval **blob_arg, **string_arg; ibase_blob *ib_blob; RESET_ERRMSG; if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &blob_arg, &string_arg) == FAILURE) { WRONG_PARAM_COUNT; } ZEND_FETCH_RESOURCE(ib_blob, ibase_blob *, blob_arg, -1, "Interbase blob", le_blob); if (ib_blob->type != BLOB_INPUT) { _php_ibase_module_error("BLOB is not open for input" TSRMLS_CC); RETURN_FALSE; } if (_php_ibase_blob_add(string_arg, ib_blob TSRMLS_CC) != SUCCESS) { RETURN_FALSE; } } /* }}} */ /* {{{ proto string ibase_blob_get(resource blob_handle, int len) Get len bytes data from open blob */ PHP_FUNCTION(ibase_blob_get) { zval **blob_arg, **len_arg; ibase_blob *ib_blob; RESET_ERRMSG; if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &blob_arg, &len_arg) == FAILURE) { WRONG_PARAM_COUNT; } ZEND_FETCH_RESOURCE(ib_blob, ibase_blob *, blob_arg, -1, "Interbase blob", le_blob); if (ib_blob->type != BLOB_OUTPUT) { _php_ibase_module_error("BLOB is not open for output" TSRMLS_CC); RETURN_FALSE; } convert_to_long_ex(len_arg); if (_php_ibase_blob_get(return_value, ib_blob, Z_LVAL_PP(len_arg) TSRMLS_CC) != SUCCESS) { RETURN_FALSE; } } /* }}} */ static void _php_ibase_blob_end(INTERNAL_FUNCTION_PARAMETERS, int bl_end) /* {{{ */ { zval **blob_arg; ibase_blob *ib_blob; RESET_ERRMSG; if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &blob_arg) == FAILURE) { WRONG_PARAM_COUNT; } ZEND_FETCH_RESOURCE(ib_blob, ibase_blob *, blob_arg, -1, "Interbase blob", le_blob); if (bl_end == BLOB_CLOSE) { /* return id here */ if (ib_blob->bl_qd.gds_quad_high || ib_blob->bl_qd.gds_quad_low) { /*not null ?*/ if (isc_close_blob(IB_STATUS, &ib_blob->bl_handle)) { _php_ibase_error(TSRMLS_C); RETURN_FALSE; } } ib_blob->bl_handle = NULL; RETVAL_STRINGL(_php_ibase_quad_to_string(ib_blob->bl_qd), BLOB_ID_LEN, 0); } else { /* discard created blob */ if (isc_cancel_blob(IB_STATUS, &ib_blob->bl_handle)) { _php_ibase_error(TSRMLS_C); RETURN_FALSE; } ib_blob->bl_handle = NULL; RETVAL_TRUE; } zend_list_delete(Z_LVAL_PP(blob_arg)); } /* }}} */ /* {{{ proto string ibase_blob_close(resource blob_handle) Close blob */ PHP_FUNCTION(ibase_blob_close) { _php_ibase_blob_end(INTERNAL_FUNCTION_PARAM_PASSTHRU, BLOB_CLOSE); } /* }}} */ /* {{{ proto bool ibase_blob_cancel(resource blob_handle) Cancel creating blob */ PHP_FUNCTION(ibase_blob_cancel) { _php_ibase_blob_end(INTERNAL_FUNCTION_PARAM_PASSTHRU, BLOB_CANCEL); } /* }}} */ /* {{{ proto array ibase_blob_info([ resource link_identifier, ] string blob_id) Return blob length and other useful info */ PHP_FUNCTION(ibase_blob_info) { char *blob_id; int blob_id_len; zval *link = NULL; ibase_db_link *ib_link; ibase_trans *trans = NULL; ibase_blob ib_blob = { NULL, BLOB_INPUT }; IBASE_BLOBINFO bl_info; RESET_ERRMSG; switch (ZEND_NUM_ARGS()) { default: WRONG_PARAM_COUNT; case 1: if (FAILURE == zend_parse_parameters(1 TSRMLS_CC, "s", &blob_id, &blob_id_len)) { RETURN_FALSE; } break; case 2: if (FAILURE == zend_parse_parameters(2 TSRMLS_CC, "rs", &link, &blob_id, &blob_id_len)) { RETURN_FALSE; } break; } PHP_IBASE_LINK_TRANS(link, ib_link, trans); if (! _php_ibase_string_to_quad(blob_id, &ib_blob.bl_qd)) { _php_ibase_module_error("Unrecognized BLOB ID" TSRMLS_CC); RETURN_FALSE; } if (ib_blob.bl_qd.gds_quad_high || ib_blob.bl_qd.gds_quad_low) { /* not null ? */ if (isc_open_blob(IB_STATUS, &ib_link->handle, &trans->handle, &ib_blob.bl_handle, &ib_blob.bl_qd)) { _php_ibase_error(TSRMLS_C); RETURN_FALSE; } if (_php_ibase_blob_info(ib_blob.bl_handle, &bl_info TSRMLS_CC)) { RETURN_FALSE; } if (isc_close_blob(IB_STATUS, &ib_blob.bl_handle)) { _php_ibase_error(TSRMLS_C); RETURN_FALSE; } } else { /* null blob, all values to zero */ bl_info.max_segment = 0; bl_info.num_segments = 0; bl_info.total_length = 0; bl_info.bl_stream = 0; } array_init(return_value); add_index_long(return_value, 0, bl_info.total_length); add_assoc_long(return_value, "length", bl_info.total_length); add_index_long(return_value, 1, bl_info.num_segments); add_assoc_long(return_value, "numseg", bl_info.num_segments); add_index_long(return_value, 2, bl_info.max_segment); add_assoc_long(return_value, "maxseg", bl_info.max_segment); add_index_bool(return_value, 3, bl_info.bl_stream); add_assoc_bool(return_value, "stream", bl_info.bl_stream); add_index_bool(return_value, 4, (!ib_blob.bl_qd.gds_quad_high && !ib_blob.bl_qd.gds_quad_low)); add_assoc_bool(return_value, "isnull", (!ib_blob.bl_qd.gds_quad_high && !ib_blob.bl_qd.gds_quad_low)); } /* }}} */ /* {{{ proto bool ibase_blob_echo([ resource link_identifier, ] string blob_id) Output blob contents to browser */ PHP_FUNCTION(ibase_blob_echo) { char *blob_id; int blob_id_len; zval *link = NULL; ibase_db_link *ib_link; ibase_trans *trans = NULL; ibase_blob ib_blob_id = { NULL, BLOB_OUTPUT }; char bl_data[IBASE_BLOB_SEG]; unsigned short seg_len; RESET_ERRMSG; switch (ZEND_NUM_ARGS()) { default: WRONG_PARAM_COUNT; case 1: if (FAILURE == zend_parse_parameters(1 TSRMLS_CC, "s", &blob_id, &blob_id_len)) { RETURN_FALSE; } break; case 2: if (FAILURE == zend_parse_parameters(2 TSRMLS_CC, "rs", &link, &blob_id, &blob_id_len)) { RETURN_FALSE; } break; } PHP_IBASE_LINK_TRANS(link, ib_link, trans); if (! _php_ibase_string_to_quad(blob_id, &ib_blob_id.bl_qd)) { _php_ibase_module_error("Unrecognized BLOB ID" TSRMLS_CC); RETURN_FALSE; } do { if (isc_open_blob(IB_STATUS, &ib_link->handle, &trans->handle, &ib_blob_id.bl_handle, &ib_blob_id.bl_qd)) { break; } while (!isc_get_segment(IB_STATUS, &ib_blob_id.bl_handle, &seg_len, sizeof(bl_data), bl_data) || IB_STATUS[1] == isc_segment) { PHPWRITE(bl_data, seg_len); } if (IB_STATUS[0] && (IB_STATUS[1] != isc_segstr_eof)) { break; } if (isc_close_blob(IB_STATUS, &ib_blob_id.bl_handle)) { break; } RETURN_TRUE; } while (0); _php_ibase_error(TSRMLS_C); RETURN_FALSE; } /* }}} */ /* {{{ proto string ibase_blob_import([ resource link_identifier, ] resource file) Create blob, copy file in it, and close it */ PHP_FUNCTION(ibase_blob_import) { zval *link = NULL, *file; int size; unsigned short b; ibase_blob ib_blob = { NULL, 0 }; ibase_db_link *ib_link; ibase_trans *trans = NULL; char bl_data[IBASE_BLOB_SEG]; php_stream *stream; RESET_ERRMSG; if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|r", (ZEND_NUM_ARGS()-1) ? &link : &file, &file)) { RETURN_FALSE; } PHP_IBASE_LINK_TRANS(link, ib_link, trans); php_stream_from_zval(stream, &file); do { if (isc_create_blob(IB_STATUS, &ib_link->handle, &trans->handle, &ib_blob.bl_handle, &ib_blob.bl_qd)) { break; } for (size = 0; (b = php_stream_read(stream, bl_data, sizeof(bl_data))); size += b) { if (isc_put_segment(IB_STATUS, &ib_blob.bl_handle, b, bl_data)) { break; } } if (isc_close_blob(IB_STATUS, &ib_blob.bl_handle)) { break; } RETURN_STRINGL( _php_ibase_quad_to_string(ib_blob.bl_qd), BLOB_ID_LEN, 0); } while (0); _php_ibase_error(TSRMLS_C); RETURN_FALSE; } /* }}} */ #endif /* HAVE_IBASE */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: sw=4 ts=4 fdm=marker * vim<600: sw=4 ts=4 */ php-interbase-5.4.6/php_ibase_includes.h0000775000175000017500000001332212012622335020214 0ustar jtaylorjtaylor/* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2012 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.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: Jouni Ahto | | Andrew Avdeev | | Ard Biesheuvel | +----------------------------------------------------------------------+ */ /* $Id$ */ #ifndef PHP_IBASE_INCLUDES_H #define PHP_IBASE_INCLUDES_H #include #ifndef SQLDA_CURRENT_VERSION #define SQLDA_CURRENT_VERSION SQLDA_VERSION1 #endif #ifndef METADATALENGTH #define METADATALENGTH 68 #endif #define RESET_ERRMSG do { IBG(errmsg)[0] = '\0'; IBG(sql_code) = 0; } while (0) #define IB_STATUS (IBG(status)) #ifdef ZEND_DEBUG_ #define IBDEBUG(a) php_printf("::: %s (%d)\n", a, __LINE__); #endif #ifndef IBDEBUG #define IBDEBUG(a) #endif extern int le_link, le_plink, le_trans; #define LE_LINK "Firebird/InterBase link" #define LE_PLINK "Firebird/InterBase persistent link" #define LE_TRANS "Firebird/InterBase transaction" #define IBASE_MSGSIZE 512 #define MAX_ERRMSG (IBASE_MSGSIZE*2) #define IB_DEF_DATE_FMT "%Y-%m-%d" #define IB_DEF_TIME_FMT "%H:%M:%S" /* this value should never be > USHRT_MAX */ #define IBASE_BLOB_SEG 4096 ZEND_BEGIN_MODULE_GLOBALS(ibase) ISC_STATUS status[20]; long default_link; long num_links, num_persistent; char errmsg[MAX_ERRMSG]; long sql_code; ZEND_END_MODULE_GLOBALS(ibase) ZEND_EXTERN_MODULE_GLOBALS(ibase) typedef struct { isc_db_handle handle; struct tr_list *tr_list; unsigned short dialect; struct event *event_head; } ibase_db_link; typedef struct { isc_tr_handle handle; unsigned short link_cnt; unsigned long affected_rows; ibase_db_link *db_link[1]; /* last member */ } ibase_trans; typedef struct tr_list { ibase_trans *trans; struct tr_list *next; } ibase_tr_list; typedef struct { isc_blob_handle bl_handle; unsigned short type; ISC_QUAD bl_qd; } ibase_blob; typedef struct event { ibase_db_link *link; long link_res_id; ISC_LONG event_id; unsigned short event_count; char **events; char *event_buffer, *result_buffer; zval *callback; void **thread_ctx; struct event *event_next; enum event_state { NEW, ACTIVE, DEAD } state; } ibase_event; enum php_interbase_option { PHP_IBASE_DEFAULT = 0, PHP_IBASE_CREATE = 0, /* fetch flags */ PHP_IBASE_FETCH_BLOBS = 1, PHP_IBASE_FETCH_ARRAYS = 2, PHP_IBASE_UNIXTIME = 4, /* transaction access mode */ PHP_IBASE_WRITE = 1, PHP_IBASE_READ = 2, /* transaction isolation level */ PHP_IBASE_CONCURRENCY = 4, PHP_IBASE_COMMITTED = 8, PHP_IBASE_REC_NO_VERSION = 32, PHP_IBASE_REC_VERSION = 64, PHP_IBASE_CONSISTENCY = 16, /* transaction lock resolution */ PHP_IBASE_WAIT = 128, PHP_IBASE_NOWAIT = 256 }; #ifdef ZTS #define IBG(v) TSRMG(ibase_globals_id, zend_ibase_globals *, v) #else #define IBG(v) (ibase_globals.v) #endif #define BLOB_ID_LEN 18 #define BLOB_ID_MASK "0x%" LL_MASK "x" #define BLOB_INPUT 1 #define BLOB_OUTPUT 2 #ifdef PHP_WIN32 #define LL_MASK "I64" #define LL_LIT(lit) lit ## I64 typedef void (__stdcall *info_func_t)(char*); #else #define LL_MASK "ll" #define LL_LIT(lit) lit ## ll typedef void (*info_func_t)(char*); #endif void _php_ibase_error(TSRMLS_D); void _php_ibase_module_error(char * TSRMLS_DC, ...) PHP_ATTRIBUTE_FORMAT(printf,1,PHP_ATTR_FMT_OFFSET +2); /* determine if a resource is a link or transaction handle */ #define PHP_IBASE_LINK_TRANS(pzval, lh, th) \ do { if (!pzval) { \ ZEND_FETCH_RESOURCE2(lh, ibase_db_link *, NULL, IBG(default_link), \ "InterBase link", le_link, le_plink) } \ else \ _php_ibase_get_link_trans(INTERNAL_FUNCTION_PARAM_PASSTHRU, &pzval, &lh, &th); \ if (SUCCESS != _php_ibase_def_trans(lh, &th TSRMLS_CC)) { RETURN_FALSE; } \ } while (0) int _php_ibase_def_trans(ibase_db_link *ib_link, ibase_trans **trans TSRMLS_DC); void _php_ibase_get_link_trans(INTERNAL_FUNCTION_PARAMETERS, zval **link_id, ibase_db_link **ib_link, ibase_trans **trans); /* provided by ibase_query.c */ void php_ibase_query_minit(INIT_FUNC_ARGS); /* provided by ibase_blobs.c */ void php_ibase_blobs_minit(INIT_FUNC_ARGS); int _php_ibase_string_to_quad(char const *id, ISC_QUAD *qd); char *_php_ibase_quad_to_string(ISC_QUAD const qd); int _php_ibase_blob_get(zval *return_value, ibase_blob *ib_blob, unsigned long max_len TSRMLS_DC); int _php_ibase_blob_add(zval **string_arg, ibase_blob *ib_blob TSRMLS_DC); /* provided by ibase_events.c */ void php_ibase_events_minit(INIT_FUNC_ARGS); void _php_ibase_free_event(ibase_event *event TSRMLS_DC); /* provided by ibase_service.c */ void php_ibase_service_minit(INIT_FUNC_ARGS); #ifndef max #define max(a,b) ((a)>(b)?(a):(b)) #endif #endif /* PHP_IBASE_INCLUDES_H */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: */ php-interbase-5.4.6/php_ibase_udf.c0000664000175000017500000002750612012622335017165 0ustar jtaylorjtaylor/* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2012 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.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. | +----------------------------------------------------------------------+ | Author: Ard Biesheuvel | +----------------------------------------------------------------------+ */ /* $Id$ */ /** * This UDF library adds the ability to call PHP functions from SQL * statements. Because of SQL's strong typing, you will have to declare * an external function for every combination { output type, #args } that * your application requires. * * Declare the functions like this: * * DECLARE EXTERNAL FUNCTION CALL_PHP1 * CSTRING(xx), * BY DESCRIPTOR, * INTEGER BY DESCRIPTOR * RETURNS PARAMETER 2 * ENTRY_POINT 'udf_call_php1' MODULE_NAME 'php_ibase_udf' * * DECLARE EXTERNAL FUNCTION CALL_PHP2 * CSTRING(xx), * BY DESCRIPTOR, * INTEGER BY DESCRIPTOR, * INTEGER BY DESCRIPTOR * RETURNS PARAMETER 2 * ENTRY_POINT 'udf_call_php2' MODULE_NAME 'php_ibase_udf' * * ... and so on. [for up to 8 input arguments] * * The first input parameter contains the name of the PHP function you want * to call. The second argument is the result. (omit this argument when calling * the function) The return type of the function is the declared type of the * result. The value returned from the PHP function being called will * automatically be converted if necessary. * The arguments should have their types declared as well, but you're free * to pass arguments of other types instead. They will be converted to the * best matching PHP type before being passed to the PHP function. * * The declared functions can be called from SQL like: * * SELECT * FROM WHERE CALL_PHP1('soundex',) NOT LIKE ? * or * UPDATE
SET = CALL_PHP1('ucwords',) * * Additionally, there's a function 'exec_php' which allows the contents * of text BLOB fields to be parsed and executed by PHP. This is most useful * for declaring functions that can then be called with CALL_PHPx. * * DECLARE EXTERNAL FUNCTION EXEC_PHP * BLOB, * INTEGER BY DESCRIPTOR, * SMALLINT * RETURNS PARAMETER 2 * ENTRY_POINT 'exec_php' MODULE_NAME 'php_ibase_udf' * * The function will return 1 if execution succeeded and 0 if an error * occurred. The result that is returned from the executed PHP code is * ignored. You can pass a non-zero value as second argument to force * the embedded PHP engine to re-initialise. * * There are several ways to build this library, depending on which way the * database is accessed. If you're using the classic server on a local * connection, you should compile the library like this: * * gcc -shared `php-config --includes` `php-config --ldflags` \ * `php-config --libs` -o php_ibase_udf.so php_ibase_udf.c * * If you connect to the classic server by TCP/IP, you should build the * PHP embedded static library and link against that. * * gcc -shared `php-config --includes` `php-config --ldflags` \ * `php-config --libs` -o php_ibase_udf.so php_ibase_udf.c \ * /usr/lib/libphp5.a * * If you use the super server, you should also link against the embedded * library, but be sure to enable thread safety, as the super server is * multi-threaded. After building, copy the resulting file to the folder * where your database expects to find its UDFs. */ #include "zend.h" #include "zend_API.h" #include "php.h" #include "php_ini.h" #include "ibase.h" #define min(a,b) ((a)<(b)?(a):(b)) #ifdef PHP_WIN32 #define LL_LIT(lit) lit ## I64 #else #define LL_LIT(lit) lit ## ll #endif #ifdef ZTS # include static void ***tsrm_ls; pthread_mutex_t mtx_res = PTHREAD_MUTEX_INITIALIZER; #define LOCK() do { pthread_mutex_lock(&mtx_res); } while (0) #define UNLOCK() do { pthread_mutex_unlock(&mtx_res); } while (0) #else #define LOCK() #define UNLOCK() #endif #ifdef PHP_EMBED # include "php_main.h" # include "sapi/embed/php_embed.h" static void __attribute__((constructor)) init() { php_embed_init(0, NULL PTSRMLS_CC); } static void __attribute__((destructor)) fini() { php_embed_shutdown(TSRMLS_C); } #endif /** * Gets the contents of the BLOB b and offers it to Zend for parsing/execution */ void exec_php(BLOBCALLBACK b, PARAMDSC *res, ISC_SHORT *init) { int result, remaining = b->blob_total_length, i = 0; char *code = pemalloc(remaining+1, 1); ISC_USHORT read; for (code[remaining] = '\0'; remaining > 0; remaining -= read) b->blob_get_segment(b->blob_handle, &code[i++<<16],min(0x10000,remaining), &read); LOCK(); switch (init && *init) { default: #ifdef PHP_EMBED php_request_shutdown(NULL); if (FAILURE == (result = php_request_startup(TSRMLS_C))) { break; } case 0: #endif /* feed it to the parser */ zend_first_try { result = zend_eval_stringl(code, b->blob_total_length, NULL, "Firebird Embedded PHP engine" TSRMLS_CC); } zend_end_try(); } UNLOCK(); free(code); res->dsc_dtype = dtype_long; *(ISC_LONG*)res->dsc_address = (result == SUCCESS); } static ISC_INT64 const scales[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 100000000, 1000000000, 1000000000, LL_LIT(10000000000),LL_LIT(100000000000),LL_LIT(10000000000000),LL_LIT(100000000000000), LL_LIT(1000000000000000),LL_LIT(1000000000000000),LL_LIT(1000000000000000000) }; static void call_php(char *name, PARAMDSC *r, int argc, PARAMDSC **argv) { do { zval callback, args[4], *argp[4], return_value; PARAMVARY *res = (PARAMVARY*)r->dsc_address; int i; INIT_ZVAL(callback); ZVAL_STRING(&callback,name,0); LOCK(); /* check if the requested function exists */ if (!zend_is_callable(&callback, 0, NULL TSRMLS_CC)) { break; } UNLOCK(); /* create the argument array */ for (i = 0; i < argc; ++i) { INIT_ZVAL(args[i]); argp[i] = &args[i]; /* test arg for null */ if (argv[i]->dsc_flags & DSC_null) { ZVAL_NULL(argp[i]); continue; } switch (argv[i]->dsc_dtype) { ISC_INT64 l; struct tm t; char const *fmt; char d[64]; case dtype_cstring: ZVAL_STRING(argp[i], (char*)argv[i]->dsc_address,0); break; case dtype_text: ZVAL_STRINGL(argp[i], (char*)argv[i]->dsc_address, argv[i]->dsc_length,0); break; case dtype_varying: ZVAL_STRINGL(argp[i], ((PARAMVARY*)argv[i]->dsc_address)->vary_string, ((PARAMVARY*)argv[i]->dsc_address)->vary_length,0); break; case dtype_short: if (argv[i]->dsc_scale == 0) { ZVAL_LONG(argp[i], *(short*)argv[i]->dsc_address); } else { ZVAL_DOUBLE(argp[i], ((double)*(short*)argv[i]->dsc_address)/scales[-argv[i]->dsc_scale]); } break; case dtype_long: if (argv[i]->dsc_scale == 0) { ZVAL_LONG(argp[i], *(ISC_LONG*)argv[i]->dsc_address); } else { ZVAL_DOUBLE(argp[i], ((double)*(ISC_LONG*)argv[i]->dsc_address)/scales[-argv[i]->dsc_scale]); } break; case dtype_int64: l = *(ISC_INT64*)argv[i]->dsc_address; if (argv[i]->dsc_scale == 0 && l <= LONG_MAX && l >= LONG_MIN) { ZVAL_LONG(argp[i], (long)l); } else { ZVAL_DOUBLE(argp[i], ((double)l)/scales[-argv[i]->dsc_scale]); } break; case dtype_real: ZVAL_DOUBLE(argp[i], *(float*)argv[i]->dsc_address); break; case dtype_double: ZVAL_DOUBLE(argp[i], *(double*)argv[i]->dsc_address); break; case dtype_sql_date: isc_decode_sql_date((ISC_DATE*)argv[i]->dsc_address, &t); ZVAL_STRINGL(argp[i], d, strftime(d, sizeof(d), INI_STR("ibase.dateformat"), &t),1); break; case dtype_sql_time: isc_decode_sql_time((ISC_TIME*)argv[i]->dsc_address, &t); ZVAL_STRINGL(argp[i], d, strftime(d, sizeof(d), INI_STR("ibase.timeformat"), &t),1); break; case dtype_timestamp: isc_decode_timestamp((ISC_TIMESTAMP*)argv[i]->dsc_address, &t); ZVAL_STRINGL(argp[i], d, strftime(d, sizeof(d), INI_STR("ibase.timestampformat"), &t),1); break; } } LOCK(); /* now call the function */ if (FAILURE == call_user_function(EG(function_table), NULL, &callback, &return_value, argc, argp TSRMLS_CC)) { UNLOCK(); break; } UNLOCK(); for (i = 0; i < argc; ++i) { switch (argv[i]->dsc_dtype) { case dtype_sql_date: case dtype_sql_time: case dtype_timestamp: zval_dtor(argp[i]); } } /* return whatever type we got back from the callback: let DB handle conversion */ switch (Z_TYPE(return_value)) { case IS_LONG: r->dsc_dtype = dtype_long; *(long*)r->dsc_address = Z_LVAL(return_value); r->dsc_length = sizeof(long); break; case IS_DOUBLE: r->dsc_dtype = dtype_double; *(double*)r->dsc_address = Z_DVAL(return_value); r->dsc_length = sizeof(double); break; case IS_NULL: r->dsc_flags |= DSC_null; break; default: convert_to_string(&return_value); case IS_STRING: r->dsc_dtype = dtype_varying; memcpy(res->vary_string, Z_STRVAL(return_value), (res->vary_length = min(r->dsc_length-2,Z_STRLEN(return_value)))); r->dsc_length = res->vary_length+2; break; } zval_dtor(&return_value); return; } while (0); /** * If we end up here, we should report an error back to the DB engine, but * that's not possible. We can however report it back to PHP. */ LOCK(); php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error calling function '%s' from database", name); UNLOCK(); } /* Entry points for the DB engine */ void udf_call_php1(char *name, PARAMDSC *r, PARAMDSC *arg1) { PARAMDSC *args[1] = { arg1 }; call_php(name, r, 1, args); } void udf_call_php2(char *name, PARAMDSC *r, PARAMDSC *arg1, PARAMDSC *arg2) { PARAMDSC *args[2] = { arg1, arg2 }; call_php(name, r, 2, args); } void udf_call_php3(char *name, PARAMDSC *r, PARAMDSC *arg1, PARAMDSC *arg2, PARAMDSC *arg3) { PARAMDSC *args[3] = { arg1, arg2, arg3 }; call_php(name, r, 3, args); } void udf_call_php4(char *name, PARAMDSC *r, PARAMDSC *arg1, PARAMDSC *arg2, PARAMDSC *arg3, PARAMDSC *arg4) { PARAMDSC *args[4] = { arg1, arg2, arg3, arg4 }; call_php(name, r, 4, args); } void udf_call_php5(char *name, PARAMDSC *r, PARAMDSC *arg1, PARAMDSC *arg2, PARAMDSC *arg3, PARAMDSC *arg4, PARAMDSC *arg5) { PARAMDSC *args[5] = { arg1, arg2, arg3, arg4, arg5 }; call_php(name, r, 5, args); } void udf_call_php6(char *name, PARAMDSC *r, PARAMDSC *arg1, PARAMDSC *arg2, PARAMDSC *arg3, PARAMDSC *arg4, PARAMDSC *arg5, PARAMDSC *arg6) { PARAMDSC *args[6] = { arg1, arg2, arg3, arg4, arg5, arg6 }; call_php(name, r, 6, args); } void udf_call_php7(char *name, PARAMDSC *r, PARAMDSC *arg1, PARAMDSC *arg2, PARAMDSC *arg3, PARAMDSC *arg4, PARAMDSC *arg5, PARAMDSC *arg6, PARAMDSC *arg7) { PARAMDSC *args[7] = { arg1, arg2, arg3, arg4, arg5, arg6, arg7 }; call_php(name, r, 7, args); } void udf_call_php8(char *name, PARAMDSC *r, PARAMDSC *arg1, PARAMDSC *arg2, PARAMDSC *arg3, PARAMDSC *arg4, PARAMDSC *arg5, PARAMDSC *arg6, PARAMDSC *arg7, PARAMDSC *arg8) { PARAMDSC *args[8] = { arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8 }; call_php(name, r, 8, args); } php-interbase-5.4.6/config.w320000664000175000017500000000133012012622335016016 0ustar jtaylorjtaylor// $Id$ // vim:ft=javascript ARG_WITH("interbase", "InterBase support", "no"); if (PHP_INTERBASE != "no") { if (CHECK_HEADER_ADD_INCLUDE("ibase.h", "CFLAGS_INTERBASE", PHP_PHP_BUILD + "\\include\\interbase;" + PHP_PHP_BUILD + "\\interbase\\include;" + PHP_INTERBASE) && (CHECK_LIB("fbclient_ms.lib", "interbase", PHP_PHP_BUILD + "\\interbase\\lib_ms;" + PHP_INTERBASE) || CHECK_LIB("gds32_ms.lib", "interbase", PHP_PHP_BUILD + "\\interbase\\lib_ms;" + PHP_INTERBASE))) { EXTENSION("interbase", "interbase.c ibase_query.c ibase_service.c ibase_events.c ibase_blobs.c"); AC_DEFINE('HAVE_IBASE', 1, 'Have interbase library'); } else { WARNING("interbase not enabled; libraries and headers not found"); } } php-interbase-5.4.6/ibase_events.c0000664000175000017500000002762712012622335017050 0ustar jtaylorjtaylor/* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2012 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.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: Ard Biesheuvel | +----------------------------------------------------------------------+ */ /* $Id$ */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "php.h" #if HAVE_IBASE #include "php_interbase.h" #include "php_ibase_includes.h" static int le_event; static void _php_ibase_event_free(char *event_buf, char *result_buf) /* {{{ */ { isc_free(event_buf); isc_free(result_buf); } /* }}} */ void _php_ibase_free_event(ibase_event *event TSRMLS_DC) /* {{{ */ { unsigned short i; event->state = DEAD; if (event->link != NULL) { ibase_event **node; if (event->link->handle != NULL && isc_cancel_events(IB_STATUS, &event->link->handle, &event->event_id)) { _php_ibase_error(TSRMLS_C); } /* delete this event from the link struct */ for (node = &event->link->event_head; *node != event; node = &(*node)->event_next); *node = event->event_next; } if (event->callback) { zval_dtor(event->callback); FREE_ZVAL(event->callback); event->callback = NULL; _php_ibase_event_free(event->event_buffer,event->result_buffer); for (i = 0; i < event->event_count; ++i) { efree(event->events[i]); } efree(event->events); } } /* }}} */ static void _php_ibase_free_event_rsrc(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */ { ibase_event *e = (ibase_event *) rsrc->ptr; _php_ibase_free_event(e TSRMLS_CC); efree(e); } /* }}} */ void php_ibase_events_minit(INIT_FUNC_ARGS) /* {{{ */ { le_event = zend_register_list_destructors_ex(_php_ibase_free_event_rsrc, NULL, "interbase event", module_number); } /* }}} */ static void _php_ibase_event_block(ibase_db_link *ib_link, unsigned short count, /* {{{ */ char **events, unsigned short *l, char **event_buf, char **result_buf) { ISC_STATUS dummy_result[20]; unsigned long dummy_count[15]; /** * Unfortunately, there's no clean and portable way in C to pass arguments to * a variadic function if you don't know the number of arguments at compile time. * (And even if there were a way, the Interbase API doesn't provide a version of * this function that takes a va_list as an argument) * * In this case, the number of arguments is limited to 18 by the underlying API, * so we can work around it. */ *l = (unsigned short) isc_event_block(event_buf, result_buf, count, events[0], events[1], events[2], events[3], events[4], events[5], events[6], events[7], events[8], events[9], events[10], events[11], events[12], events[13], events[14]); /** * Currently, this is the only way to correctly initialize an event buffer. * This is clearly something that should be fixed, cause the semantics of * isc_wait_for_event() indicate that it blocks until an event occurs. * If the Firebird people ever fix this, these lines should be removed, * otherwise, events will have to fire twice before ibase_wait_event() returns. */ isc_wait_for_event(dummy_result, &ib_link->handle, *l, *event_buf, *result_buf); isc_event_counts(dummy_count, *l, *event_buf, *result_buf); } /* }}} */ /* {{{ proto string ibase_wait_event([resource link_identifier,] string event [, string event [, ...]]) Waits for any one of the passed Interbase events to be posted by the database, and returns its name */ PHP_FUNCTION(ibase_wait_event) { zval ***args; ibase_db_link *ib_link; int num_args; char *event_buffer, *result_buffer, *events[15]; unsigned short i = 0, event_count = 0, buffer_size; unsigned long occurred_event[15]; RESET_ERRMSG; /* no more than 15 events */ if (ZEND_NUM_ARGS() < 1 || ZEND_NUM_ARGS() > 16) { WRONG_PARAM_COUNT; } if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &args, &num_args) == FAILURE) { return; } if (Z_TYPE_PP(args[0]) == IS_RESOURCE) { if (!ZEND_FETCH_RESOURCE2_NO_RETURN(ib_link, ibase_db_link *, args[0], -1, "InterBase link", le_link, le_plink)) { efree(args); RETURN_FALSE; } i = 1; } else { if (ZEND_NUM_ARGS() > 15) { efree(args); WRONG_PARAM_COUNT; } if (!ZEND_FETCH_RESOURCE2_NO_RETURN(ib_link, ibase_db_link *, NULL, IBG(default_link), "InterBase link", le_link, le_plink)) { efree(args); RETURN_FALSE; } } for (; i < ZEND_NUM_ARGS(); ++i) { convert_to_string_ex(args[i]); events[event_count++] = Z_STRVAL_PP(args[i]); } /* fills the required data structure with information about the events */ _php_ibase_event_block(ib_link, event_count, events, &buffer_size, &event_buffer, &result_buffer); /* now block until an event occurs */ if (isc_wait_for_event(IB_STATUS, &ib_link->handle, buffer_size, event_buffer, result_buffer)) { _php_ibase_error(TSRMLS_C); _php_ibase_event_free(event_buffer,result_buffer); efree(args); RETURN_FALSE; } /* find out which event occurred */ isc_event_counts(occurred_event, buffer_size, event_buffer, result_buffer); for (i = 0; i < event_count; ++i) { if (occurred_event[i]) { char *result = estrdup(events[i]); _php_ibase_event_free(event_buffer,result_buffer); efree(args); RETURN_STRING(result,0); } } /* If we reach this line, isc_wait_for_event() did return, but we don't know which event fired. */ _php_ibase_event_free(event_buffer,result_buffer); efree(args); RETURN_FALSE; } /* }}} */ static isc_callback _php_ibase_callback(ibase_event *event, /* {{{ */ unsigned short buffer_size, char *result_buf) { /* this function is called asynchronously by the Interbase client library. */ TSRMLS_FETCH_FROM_CTX(event->thread_ctx); /** * The callback function is called when the event is first registered and when the event * is cancelled. I consider this is a bug. By clearing event->callback first and setting * it to -1 later, we make sure nothing happens if no event was actually posted. */ switch (event->state) { unsigned short i; unsigned long occurred_event[15]; zval event_name, link_id, return_value, *args[2]; default: /* == DEAD */ break; case ACTIVE: args[0] = &event_name; args[1] = &link_id; /* copy the updated results into the result buffer */ memcpy(event->result_buffer, result_buf, buffer_size); INIT_ZVAL(event_name); INIT_ZVAL(link_id); ZVAL_RESOURCE(&link_id, event->link_res_id); /* find out which event occurred */ isc_event_counts(occurred_event, buffer_size, event->event_buffer, event->result_buffer); for (i = 0; i < event->event_count; ++i) { if (occurred_event[i]) { ZVAL_STRING(&event_name,event->events[i],0); break; } } /* call the callback provided by the user */ if (SUCCESS != call_user_function(EG(function_table), NULL, event->callback, &return_value, 2, args TSRMLS_CC)) { _php_ibase_module_error("Error calling callback %s" TSRMLS_CC, Z_STRVAL_P(event->callback)); break; } if (Z_TYPE(return_value) == IS_BOOL && !Z_BVAL(return_value)) { event->state = DEAD; break; } case NEW: /* re-register the event */ if (isc_que_events(IB_STATUS, &event->link->handle, &event->event_id, buffer_size, event->event_buffer,(isc_callback)_php_ibase_callback, (void *)event)) { _php_ibase_error(TSRMLS_C); } event->state = ACTIVE; } return 0; } /* }}} */ /* {{{ proto resource ibase_set_event_handler([resource link_identifier,] callback handler, string event [, string event [, ...]]) Register the callback for handling each of the named events */ PHP_FUNCTION(ibase_set_event_handler) { /** * The callback passed to this function should take an event name (string) and a * link resource id (int) as arguments. The value returned from the function is * used to determine if the event handler should remain set. */ char *cb_name; zval ***args, **cb_arg; ibase_db_link *ib_link; ibase_event *event; unsigned short i = 1, buffer_size; int link_res_id, num_args; RESET_ERRMSG; /* Minimum and maximum number of arguments allowed */ if (ZEND_NUM_ARGS() < 2 || ZEND_NUM_ARGS() > 17) { WRONG_PARAM_COUNT; } if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &args, &num_args) == FAILURE) { return; } /* get a working link */ if (Z_TYPE_PP(args[0]) != IS_STRING) { /* resource, callback, event_1 [, ... event_15] * No more than 15 events */ if (ZEND_NUM_ARGS() < 3 || ZEND_NUM_ARGS() > 17) { efree(args); WRONG_PARAM_COUNT; } cb_arg = args[1]; i = 2; if (!ZEND_FETCH_RESOURCE2_NO_RETURN(ib_link, ibase_db_link *, args[0], -1, "InterBase link", le_link, le_plink)) { efree(args); RETURN_FALSE; } convert_to_long_ex(args[0]); link_res_id = Z_LVAL_PP(args[0]); } else { /* callback, event_1 [, ... event_15] * No more than 15 events */ if (ZEND_NUM_ARGS() < 2 || ZEND_NUM_ARGS() > 16) { efree(args); WRONG_PARAM_COUNT; } cb_arg = args[0]; if (!ZEND_FETCH_RESOURCE2_NO_RETURN(ib_link, ibase_db_link *, NULL, IBG(default_link), "InterBase link", le_link, le_plink)) { efree(args); RETURN_FALSE; } link_res_id = IBG(default_link); } /* get the callback */ if (!zend_is_callable(*cb_arg, 0, &cb_name TSRMLS_CC)) { _php_ibase_module_error("Callback argument %s is not a callable function" TSRMLS_CC, cb_name); efree(cb_name); efree(args); RETURN_FALSE; } efree(cb_name); /* allocate the event resource */ event = (ibase_event *) safe_emalloc(sizeof(ibase_event), 1, 0); TSRMLS_SET_CTX(event->thread_ctx); event->link_res_id = link_res_id; event->link = ib_link; event->event_count = 0; event->state = NEW; event->events = (char **) safe_emalloc(sizeof(char *),ZEND_NUM_ARGS()-i,0); ALLOC_ZVAL(event->callback); *event->callback = **cb_arg; INIT_PZVAL(event->callback); zval_copy_ctor(event->callback); for (; i < ZEND_NUM_ARGS(); ++i) { convert_to_string_ex(args[i]); event->events[event->event_count++] = estrdup(Z_STRVAL_PP(args[i])); } /* fills the required data structure with information about the events */ _php_ibase_event_block(ib_link, event->event_count, event->events, &buffer_size, &event->event_buffer, &event->result_buffer); /* now register the events with the Interbase API */ if (isc_que_events(IB_STATUS, &ib_link->handle, &event->event_id, buffer_size, event->event_buffer,(isc_callback)_php_ibase_callback, (void *)event)) { _php_ibase_error(TSRMLS_C); efree(event); efree(args); RETURN_FALSE; } event->event_next = ib_link->event_head; ib_link->event_head = event; ZEND_REGISTER_RESOURCE(return_value, event, le_event); zend_list_addref(Z_LVAL_P(return_value)); efree(args); } /* }}} */ /* {{{ proto bool ibase_free_event_handler(resource event) Frees the event handler set by ibase_set_event_handler() */ PHP_FUNCTION(ibase_free_event_handler) { zval *event_arg; RESET_ERRMSG; if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &event_arg)) { ibase_event *event; ZEND_FETCH_RESOURCE(event, ibase_event *, &event_arg, -1, "Interbase event", le_event); event->state = DEAD; zend_list_delete(Z_LVAL_P(event_arg)); RETURN_TRUE; } else { RETURN_FALSE; } } /* }}} */ #endif /* HAVE_IBASE */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: sw=4 ts=4 fdm=marker * vim<600: sw=4 ts=4 */ php-interbase-5.4.6/ibase_service.c0000664000175000017500000005160012012622335017170 0ustar jtaylorjtaylor/* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2012 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.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: Ard Biesheuvel | +----------------------------------------------------------------------+ */ /* $Id$ */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "php.h" #if HAVE_IBASE #include "php_interbase.h" #include "php_ibase_includes.h" typedef struct { isc_svc_handle handle; char *hostname; char *username; long res_id; } ibase_service; static int le_service; static void _php_ibase_free_service(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */ { ibase_service *sv = (ibase_service *) rsrc->ptr; if (isc_service_detach(IB_STATUS, &sv->handle)) { _php_ibase_error(TSRMLS_C); } if (sv->hostname) { efree(sv->hostname); } if (sv->username) { efree(sv->username); } efree(sv); } /* }}} */ /* the svc api seems to get confused after an error has occurred, so invalidate the handle on errors */ #define IBASE_SVC_ERROR(svm) \ do { zend_list_delete(svm->res_id); _php_ibase_error(TSRMLS_C); } while (0) void php_ibase_service_minit(INIT_FUNC_ARGS) /* {{{ */ { le_service = zend_register_list_destructors_ex(_php_ibase_free_service, NULL, "interbase service manager handle", module_number); /* backup options */ REGISTER_LONG_CONSTANT("IBASE_BKP_IGNORE_CHECKSUMS", isc_spb_bkp_ignore_checksums, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_BKP_IGNORE_LIMBO", isc_spb_bkp_ignore_limbo, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_BKP_METADATA_ONLY", isc_spb_bkp_metadata_only, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_BKP_NO_GARBAGE_COLLECT", isc_spb_bkp_no_garbage_collect, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_BKP_OLD_DESCRIPTIONS", isc_spb_bkp_old_descriptions, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_BKP_NON_TRANSPORTABLE", isc_spb_bkp_non_transportable, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_BKP_CONVERT", isc_spb_bkp_convert, CONST_PERSISTENT); /* restore options */ REGISTER_LONG_CONSTANT("IBASE_RES_DEACTIVATE_IDX", isc_spb_res_deactivate_idx, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_RES_NO_SHADOW", isc_spb_res_no_shadow, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_RES_NO_VALIDITY", isc_spb_res_no_validity, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_RES_ONE_AT_A_TIME", isc_spb_res_one_at_a_time, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_RES_REPLACE", isc_spb_res_replace, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_RES_CREATE", isc_spb_res_create, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_RES_USE_ALL_SPACE", isc_spb_res_use_all_space, CONST_PERSISTENT); /* manage options */ REGISTER_LONG_CONSTANT("IBASE_PRP_PAGE_BUFFERS", isc_spb_prp_page_buffers, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_PRP_SWEEP_INTERVAL", isc_spb_prp_sweep_interval, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_PRP_SHUTDOWN_DB", isc_spb_prp_shutdown_db, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_PRP_DENY_NEW_TRANSACTIONS", isc_spb_prp_deny_new_transactions, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_PRP_DENY_NEW_ATTACHMENTS", isc_spb_prp_deny_new_attachments, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_PRP_RESERVE_SPACE", isc_spb_prp_reserve_space, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_PRP_RES_USE_FULL", isc_spb_prp_res_use_full, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_PRP_RES", isc_spb_prp_res, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_PRP_WRITE_MODE", isc_spb_prp_write_mode, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_PRP_WM_ASYNC", isc_spb_prp_wm_async, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_PRP_WM_SYNC", isc_spb_prp_wm_sync, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_PRP_ACCESS_MODE", isc_spb_prp_access_mode, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_PRP_AM_READONLY", isc_spb_prp_am_readonly, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_PRP_AM_READWRITE", isc_spb_prp_am_readwrite, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_PRP_SET_SQL_DIALECT", isc_spb_prp_set_sql_dialect, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_PRP_ACTIVATE", isc_spb_prp_activate, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_PRP_DB_ONLINE", isc_spb_prp_db_online, CONST_PERSISTENT); /* repair options */ REGISTER_LONG_CONSTANT("IBASE_RPR_CHECK_DB", isc_spb_rpr_check_db, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_RPR_IGNORE_CHECKSUM", isc_spb_rpr_ignore_checksum, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_RPR_KILL_SHADOWS", isc_spb_rpr_kill_shadows, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_RPR_MEND_DB", isc_spb_rpr_mend_db, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_RPR_VALIDATE_DB", isc_spb_rpr_validate_db, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_RPR_FULL", isc_spb_rpr_full, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_RPR_SWEEP_DB", isc_spb_rpr_sweep_db, CONST_PERSISTENT); /* db info arguments */ REGISTER_LONG_CONSTANT("IBASE_STS_DATA_PAGES", isc_spb_sts_data_pages, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_STS_DB_LOG", isc_spb_sts_db_log, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_STS_HDR_PAGES", isc_spb_sts_hdr_pages, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_STS_IDX_PAGES", isc_spb_sts_idx_pages, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_STS_SYS_RELATIONS", isc_spb_sts_sys_relations, CONST_PERSISTENT); /* server info arguments */ REGISTER_LONG_CONSTANT("IBASE_SVC_SERVER_VERSION", isc_info_svc_server_version, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_SVC_IMPLEMENTATION", isc_info_svc_implementation, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_SVC_GET_ENV", isc_info_svc_get_env, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_SVC_GET_ENV_LOCK", isc_info_svc_get_env_lock, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_SVC_GET_ENV_MSG", isc_info_svc_get_env_msg, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_SVC_USER_DBPATH", isc_info_svc_user_dbpath, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_SVC_SVR_DB_INFO", isc_info_svc_svr_db_info, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_SVC_GET_USERS", isc_info_svc_get_users, CONST_PERSISTENT); } /* }}} */ static void _php_ibase_user(INTERNAL_FUNCTION_PARAMETERS, char operation) /* {{{ */ { /* user = 0, password = 1, first_name = 2, middle_name = 3, last_name = 4 */ static char const user_flags[] = { isc_spb_sec_username, isc_spb_sec_password, isc_spb_sec_firstname, isc_spb_sec_middlename, isc_spb_sec_lastname }; char buf[128], *args[] = { NULL, NULL, NULL, NULL, NULL }; int i, args_len[] = { 0, 0, 0, 0, 0 }; unsigned short spb_len = 1; zval *res; ibase_service *svm; RESET_ERRMSG; if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, (operation == isc_action_svc_delete_user) ? "rs" : "rss|sss", &res, &args[0], &args_len[0], &args[1], &args_len[1], &args[2], &args_len[2], &args[3], &args_len[3], &args[4], &args_len[4])) { RETURN_FALSE; } ZEND_FETCH_RESOURCE(svm, ibase_service *, &res, -1, "Interbase service manager handle", le_service); buf[0] = operation; for (i = 0; i < sizeof(user_flags); ++i) { if (args[i] != NULL) { int chunk = slprintf(&buf[spb_len], sizeof(buf) - spb_len, "%c%c%c%s", user_flags[i], (char)args_len[i], (char)(args_len[i] >> 8), args[i]); if ((spb_len + chunk) > sizeof(buf) || chunk <= 0) { _php_ibase_module_error("Internal error: insufficient buffer space for SPB (%d)" TSRMLS_CC, spb_len); RETURN_FALSE; } spb_len += chunk; } } /* now start the job */ if (isc_service_start(IB_STATUS, &svm->handle, NULL, spb_len, buf)) { IBASE_SVC_ERROR(svm); RETURN_FALSE; } RETURN_TRUE; } /* }}} */ /* {{{ proto bool ibase_add_user(resource service_handle, string user_name, string password [, string first_name [, string middle_name [, string last_name]]]) Add a user to security database */ PHP_FUNCTION(ibase_add_user) { _php_ibase_user(INTERNAL_FUNCTION_PARAM_PASSTHRU, isc_action_svc_add_user); } /* }}} */ /* {{{ proto bool ibase_modify_user(resource service_handle, string user_name, string password [, string first_name [, string middle_name [, string last_name]]]) Modify a user in security database */ PHP_FUNCTION(ibase_modify_user) { _php_ibase_user(INTERNAL_FUNCTION_PARAM_PASSTHRU, isc_action_svc_modify_user); } /* }}} */ /* {{{ proto bool ibase_delete_user(resource service_handle, string user_name, string password [, string first_name [, string middle_name [, string last_name]]]) Delete a user from security database */ PHP_FUNCTION(ibase_delete_user) { _php_ibase_user(INTERNAL_FUNCTION_PARAM_PASSTHRU, isc_action_svc_delete_user); } /* }}} */ /* {{{ proto resource ibase_service_attach(string host, string dba_username, string dba_password) Connect to the service manager */ PHP_FUNCTION(ibase_service_attach) { int hlen, ulen, plen, spb_len; ibase_service *svm; char buf[128], *host, *user, *pass, *loc; isc_svc_handle handle = NULL; RESET_ERRMSG; if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sss", &host, &hlen, &user, &ulen, &pass, &plen)) { RETURN_FALSE; } /* construct the spb, hack the service name into it as well */ spb_len = slprintf(buf, sizeof(buf), "%c%c%c%c%s%c%c%s" "%s:service_mgr", isc_spb_version, isc_spb_current_version, isc_spb_user_name, (char)ulen, user, isc_spb_password, (char)plen, pass, host); if (spb_len > sizeof(buf) || spb_len == -1) { _php_ibase_module_error("Internal error: insufficient buffer space for SPB (%d)" TSRMLS_CC, spb_len); RETURN_FALSE; } spb_len -= hlen + 12; loc = buf + spb_len; /* points to %s:service_mgr part */ /* attach to the service manager */ if (isc_service_attach(IB_STATUS, 0, loc, &handle, (unsigned short)spb_len, buf)) { _php_ibase_error(TSRMLS_C); RETURN_FALSE; } svm = (ibase_service*)emalloc(sizeof(ibase_service)); svm->handle = handle; svm->hostname = estrdup(host); svm->username = estrdup(user); ZEND_REGISTER_RESOURCE(return_value, svm, le_service); svm->res_id = Z_LVAL_P(return_value); } /* }}} */ /* {{{ proto bool ibase_service_detach(resource service_handle) Disconnect from the service manager */ PHP_FUNCTION(ibase_service_detach) { zval *res; RESET_ERRMSG; if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &res)) { RETURN_FALSE; } zend_list_delete(Z_LVAL_P(res)); RETURN_TRUE; } /* }}} */ static void _php_ibase_service_query(INTERNAL_FUNCTION_PARAMETERS, /* {{{ */ ibase_service *svm, char info_action) { static char spb[] = { isc_info_svc_timeout, 10, 0, 0, 0 }; char res_buf[400], *result, *heap_buf = NULL, *heap_p; long heap_buf_size = 200, line_len; /* info about users requires an action first */ if (info_action == isc_info_svc_get_users) { static char action[] = { isc_action_svc_display_user }; if (isc_service_start(IB_STATUS, &svm->handle, NULL, sizeof(action), action)) { IBASE_SVC_ERROR(svm); RETURN_FALSE; } } query_loop: result = res_buf; if (isc_service_query(IB_STATUS, &svm->handle, NULL, sizeof(spb), spb, 1, &info_action, sizeof(res_buf), res_buf)) { IBASE_SVC_ERROR(svm); RETURN_FALSE; } while (*result != isc_info_end) { switch (*result++) { default: RETURN_FALSE; case isc_info_svc_line: if (! (line_len = isc_vax_integer(result, 2))) { /* done */ if (heap_buf) { RETURN_STRING(heap_buf,0); } else { RETURN_TRUE; } } if (!heap_buf || (heap_p - heap_buf + line_len +2) > heap_buf_size) { long res_size = heap_buf ? heap_p - heap_buf : 0; while (heap_buf_size < (res_size + line_len +2)) { heap_buf_size *= 2; } heap_buf = (char*) erealloc(heap_buf, heap_buf_size); heap_p = heap_buf + res_size; } result += 2; *(result+line_len) = 0; snprintf(heap_p, heap_buf_size - (heap_p - heap_buf), "%s\n", result); heap_p += line_len +1; goto query_loop; /* repeat until result is exhausted */ case isc_info_svc_server_version: case isc_info_svc_implementation: case isc_info_svc_get_env: case isc_info_svc_get_env_lock: case isc_info_svc_get_env_msg: case isc_info_svc_user_dbpath: RETURN_STRINGL(result + 2, isc_vax_integer(result, 2), 1); case isc_info_svc_svr_db_info: array_init(return_value); do { switch (*result++) { int len; case isc_spb_num_att: add_assoc_long(return_value, "attachments", isc_vax_integer(result,4)); result += 4; break; case isc_spb_num_db: add_assoc_long(return_value, "databases", isc_vax_integer(result,4)); result += 4; break; case isc_spb_dbname: len = isc_vax_integer(result,2); add_next_index_stringl(return_value, result +2, len, 1); result += len+2; } } while (*result != isc_info_flag_end); return; case isc_info_svc_get_users: { zval *user; array_init(return_value); while (*result != isc_info_end) { switch (*result++) { int len; case isc_spb_sec_username: /* it appears that the username is always first */ ALLOC_INIT_ZVAL(user); array_init(user); add_next_index_zval(return_value, user); len = isc_vax_integer(result,2); add_assoc_stringl(user, "user_name", result +2, len, 1); result += len+2; break; case isc_spb_sec_firstname: len = isc_vax_integer(result,2); add_assoc_stringl(user, "first_name", result +2, len, 1); result += len+2; break; case isc_spb_sec_middlename: len = isc_vax_integer(result,2); add_assoc_stringl(user, "middle_name", result +2, len, 1); result += len+2; break; case isc_spb_sec_lastname: len = isc_vax_integer(result,2); add_assoc_stringl(user, "last_name", result +2, len, 1); result += len+2; break; case isc_spb_sec_userid: add_assoc_long(user, "user_id", isc_vax_integer(result, 4)); result += 4; break; case isc_spb_sec_groupid: add_assoc_long(user, "group_id", isc_vax_integer(result, 4)); result += 4; break; } } return; } } } } /* }}} */ static void _php_ibase_backup_restore(INTERNAL_FUNCTION_PARAMETERS, char operation) /* {{{ */ { /** * It appears that the service API is a little bit confused about which flag * to use for the source and destination in the case of a restore operation. * When passing the backup file as isc_spb_dbname and the destination db as * bpk_file, things work well. */ zval *res; char *db, *bk, buf[200]; int dblen, bklen, spb_len; long opts = 0; zend_bool verbose = 0; ibase_service *svm; RESET_ERRMSG; if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss|lb", &res, &db, &dblen, &bk, &bklen, &opts, &verbose)) { RETURN_FALSE; } ZEND_FETCH_RESOURCE(svm, ibase_service *, &res, -1, "Interbase service manager handle", le_service); /* fill the param buffer */ spb_len = slprintf(buf, sizeof(buf), "%c%c%c%c%s%c%c%c%s%c%c%c%c%c", operation, isc_spb_dbname, (char)dblen, (char)(dblen >> 8), db, isc_spb_bkp_file, (char)bklen, (char)(bklen >> 8), bk, isc_spb_options, (char)opts,(char)(opts >> 8), (char)(opts >> 16), (char)(opts >> 24)); if (verbose) { buf[spb_len++] = isc_spb_verbose; } if (spb_len > sizeof(buf) || spb_len <= 0) { _php_ibase_module_error("Internal error: insufficient buffer space for SPB (%d)" TSRMLS_CC, spb_len); RETURN_FALSE; } /* now start the backup/restore job */ if (isc_service_start(IB_STATUS, &svm->handle, NULL, (unsigned short)spb_len, buf)) { IBASE_SVC_ERROR(svm); RETURN_FALSE; } if (!verbose) { RETURN_TRUE; } else { _php_ibase_service_query(INTERNAL_FUNCTION_PARAM_PASSTHRU, svm, isc_info_svc_line); } } /* }}} */ /* {{{ proto mixed ibase_backup(resource service_handle, string source_db, string dest_file [, int options [, bool verbose]]) Initiates a backup task in the service manager and returns immediately */ PHP_FUNCTION(ibase_backup) { _php_ibase_backup_restore(INTERNAL_FUNCTION_PARAM_PASSTHRU, isc_action_svc_backup); } /* }}} */ /* {{{ proto mixed ibase_restore(resource service_handle, string source_file, string dest_db [, int options [, bool verbose]]) Initiates a restore task in the service manager and returns immediately */ PHP_FUNCTION(ibase_restore) { _php_ibase_backup_restore(INTERNAL_FUNCTION_PARAM_PASSTHRU, isc_action_svc_restore); } /* }}} */ static void _php_ibase_service_action(INTERNAL_FUNCTION_PARAMETERS, char svc_action) /* {{{ */ { zval *res; char buf[128], *db; int dblen, spb_len; long action, argument = 0; ibase_service *svm; RESET_ERRMSG; if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsl|l", &res, &db, &dblen, &action, &argument)) { RETURN_FALSE; } ZEND_FETCH_RESOURCE(svm, ibase_service *, &res, -1, "Interbase service manager handle", le_service); if (svc_action == isc_action_svc_db_stats) { switch (action) { default: goto unknown_option; case isc_spb_sts_data_pages: case isc_spb_sts_db_log: case isc_spb_sts_hdr_pages: case isc_spb_sts_idx_pages: case isc_spb_sts_sys_relations: goto options_argument; } } else { /* these actions all expect different types of arguments */ switch (action) { default: unknown_option: _php_ibase_module_error("Unrecognised option (%ld)" TSRMLS_CC, action); RETURN_FALSE; case isc_spb_rpr_check_db: case isc_spb_rpr_ignore_checksum: case isc_spb_rpr_kill_shadows: case isc_spb_rpr_mend_db: case isc_spb_rpr_validate_db: case isc_spb_rpr_sweep_db: svc_action = isc_action_svc_repair; case isc_spb_prp_activate: case isc_spb_prp_db_online: options_argument: argument |= action; action = isc_spb_options; case isc_spb_prp_page_buffers: case isc_spb_prp_sweep_interval: case isc_spb_prp_shutdown_db: case isc_spb_prp_deny_new_transactions: case isc_spb_prp_deny_new_attachments: case isc_spb_prp_set_sql_dialect: spb_len = slprintf(buf, sizeof(buf), "%c%c%c%c%s%c%c%c%c%c", svc_action, isc_spb_dbname, (char)dblen, (char)(dblen >> 8), db, (char)action, (char)argument, (char)(argument >> 8), (char)(argument >> 16), (char)(argument >> 24)); break; case isc_spb_prp_reserve_space: case isc_spb_prp_write_mode: case isc_spb_prp_access_mode: spb_len = slprintf(buf, sizeof(buf), "%c%c%c%c%s%c%c", isc_action_svc_properties, isc_spb_dbname, (char)dblen, (char)(dblen >> 8), db, (char)action, (char)argument); } } if (spb_len > sizeof(buf) || spb_len == -1) { _php_ibase_module_error("Internal error: insufficient buffer space for SPB (%d)" TSRMLS_CC, spb_len); RETURN_FALSE; } if (isc_service_start(IB_STATUS, &svm->handle, NULL, (unsigned short)spb_len, buf)) { IBASE_SVC_ERROR(svm); RETURN_FALSE; } if (svc_action == isc_action_svc_db_stats) { _php_ibase_service_query(INTERNAL_FUNCTION_PARAM_PASSTHRU, svm, isc_info_svc_line); } else { RETURN_TRUE; } } /* }}} */ /* {{{ proto bool ibase_maintain_db(resource service_handle, string db, int action [, int argument]) Execute a maintenance command on the database server */ PHP_FUNCTION(ibase_maintain_db) { _php_ibase_service_action(INTERNAL_FUNCTION_PARAM_PASSTHRU, isc_action_svc_properties); } /* }}} */ /* {{{ proto string ibase_db_info(resource service_handle, string db, int action [, int argument]) Request statistics about a database */ PHP_FUNCTION(ibase_db_info) { _php_ibase_service_action(INTERNAL_FUNCTION_PARAM_PASSTHRU, isc_action_svc_db_stats); } /* }}} */ /* {{{ proto string ibase_server_info(resource service_handle, int action) Request information about a database server */ PHP_FUNCTION(ibase_server_info) { zval *res; long action; ibase_service *svm; RESET_ERRMSG; if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &res, &action)) { RETURN_FALSE; } ZEND_FETCH_RESOURCE(svm, ibase_service *, &res, -1, "Interbase service manager handle", le_service); _php_ibase_service_query(INTERNAL_FUNCTION_PARAM_PASSTHRU, svm, (char)action); } /* }}} */ #else void php_ibase_register_service_constants(INIT_FUNC_ARGS) { /* nop */ } #endif /* HAVE_IBASE */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: sw=4 ts=4 fdm=marker * vim<600: sw=4 ts=4 */ php-interbase-5.4.6/CREDITS0000664000175000017500000000006412012622335015237 0ustar jtaylorjtaylorInterBase Jouni Ahto, Andrew Avdeev, Ard Biesheuvel php-interbase-5.4.6/tests/0000775000175000017500000000000012012622335015361 5ustar jtaylorjtaylorphp-interbase-5.4.6/tests/bug46543.phpt0000664000175000017500000000131112012622335017435 0ustar jtaylorjtaylor--TEST-- Bug #46543 (ibase_trans() memory leaks when using wrong parameters) --SKIPIF-- --FILE-- --EXPECTF-- Warning: ibase_trans(): no Firebird/InterBase link resource supplied in %s on line %d Warning: ibase_trans(): no Firebird/InterBase link resource supplied in %s on line %d Warning: ibase_trans(): no Firebird/InterBase link resource supplied in %s on line %d Warning: ibase_trans(): supplied resource is not a valid Firebird/InterBase link resource in %s on line %d php-interbase-5.4.6/tests/ibase_errmsg_001.phpt0000664000175000017500000000064112012622335021301 0ustar jtaylorjtaylor--TEST-- ibase_errmsg(): Basic test --SKIPIF-- --FILE-- --EXPECTF-- Warning: ibase_query(): Dynamic SQL Error SQL error code = -104 %s on line %d string(%d) "Dynamic SQL Error SQL error code = -104 %s" bool(false) php-interbase-5.4.6/tests/008.phpt0000775000175000017500000000151612012622335016573 0ustar jtaylorjtaylor--TEST-- InterBase: event handling --SKIPIF-- --FILE-- 5) echo "FAIL ($count)\n"; echo "end of test\n"; ?> --EXPECT-- end of test php-interbase-5.4.6/tests/ibase_affected_rows_001.phpt0000664000175000017500000000121112012622335022607 0ustar jtaylorjtaylor--TEST-- ibase_affected_rows(): Basic test --SKIPIF-- --FILE-- --EXPECTF-- int(3) int(0) Warning: ibase_query(): Dynamic SQL Error SQL error code = -104 %s on line %d int(0) php-interbase-5.4.6/tests/skipif.inc0000775000175000017500000000031412012622335017342 0ustar jtaylorjtaylor php-interbase-5.4.6/tests/003.phpt0000664000175000017500000001253412012622335016565 0ustar jtaylorjtaylor--TEST-- InterBase: misc sql types (may take a while) --SKIPIF-- --FILE-- V_CHAR,0,strlen($v_char)) != $v_char){ echo " CHAR fail:\n"; echo " in: $v_char\n"; echo " out: $row->V_CHAR\n"; } if($row->V_DATE != $v_date){ echo " DATE fail\n"; echo " in: $v_date\n"; echo " out: $row->V_DATE\n"; } if($row->V_DECIMAL4_2 != $v_decimal4_2){ echo " DECIMAL4_2 fail\n"; echo " in: $v_decimal4_2\n"; echo " out: $row->V_DECIMAL4_2\n"; } if($row->V_DECIMAL4_0 != $v_decimal4_0){ echo " DECIMAL4_0 fail\n"; echo " in: $v_decimal4_0\n"; echo " out: $row->V_DECIMAL4_0\n"; } if($row->V_DECIMAL7_2 != $v_decimal7_2){ echo " DECIMAL7_2 fail\n"; echo " in: $v_decimal7_2\n"; echo " out: $row->V_DECIMAL7_2\n"; } if($row->V_DECIMAL7_0 != $v_decimal7_0){ echo " DECIMAL7_0 fail\n"; echo " in: $v_decimal7_0\n"; echo " out: $row->V_DECIMAL7_0\n"; } if($row->V_NUMERIC15_15 != $v_numeric15_15){ echo " NUMERIC15_15 fail\n"; echo " in: $v_numeric15_15\n"; echo " out: $row->V_NUMERIC15_15\n"; } if($row->V_NUMERIC15_0 != (string)$v_numeric15_0){ echo " NUMERIC15_0 fail\n"; echo " in: $v_numeric15_0\n"; echo " out: $row->V_NUMERIC15_0\n"; } if(abs($row->V_DOUBLE - $v_double) > abs($v_double / 1E15)){ echo " DOUBLE fail\n"; echo " in: $v_double\n"; echo " out: $row->V_DOUBLE\n"; } if(abs($row->V_FLOAT - $v_float) > abs($v_float / 1E7)){ echo " FLOAT fail\n"; echo " in: $v_float\n"; echo " out: $row->V_FLOAT\n"; } if($row->V_INTEGER != $v_integer){ echo " INTEGER fail\n"; echo " in: $v_integer\n"; echo " out: $row->V_INTEGER\n"; } if($row->V_SMALLINT != $v_smallint){ echo " SMALLINT fail\n"; echo " in: $v_smallint\n"; echo " out: $row->V_SMALLINT\n"; } if(substr($row->V_VARCHAR,0,strlen($v_varchar)) != $v_varchar){ echo " VARCHAR fail:\n"; echo " in: $v_varchar\n"; echo " out: $row->V_VARCHAR\n"; } ibase_free_result($sel); } /* for($iter) */ /* check for correct handling of duplicate field names */ $q = ibase_query('SELECT 1 AS id, 2 AS id, 3 AS id, 4 AS id, 5 AS id, 6 AS id, 7 AS id, 8 AS id, 9 AS id, 10 AS id, 11 AS id, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22 FROM rdb$database'); var_dump(ibase_fetch_assoc($q)); ibase_close(); echo "end of test\n"; ?> --EXPECT-- array(22) { ["ID"]=> int(1) ["ID_01"]=> int(2) ["ID_02"]=> int(3) ["ID_03"]=> int(4) ["ID_04"]=> int(5) ["ID_05"]=> int(6) ["ID_06"]=> int(7) ["ID_07"]=> int(8) ["ID_08"]=> int(9) ["ID_09"]=> int(10) ["ID_10"]=> int(11) ["CONSTANT"]=> int(12) ["CONSTANT_01"]=> int(13) ["CONSTANT_02"]=> int(14) ["CONSTANT_03"]=> int(15) ["CONSTANT_04"]=> int(16) ["CONSTANT_05"]=> int(17) ["CONSTANT_06"]=> int(18) ["CONSTANT_07"]=> int(19) ["CONSTANT_08"]=> int(20) ["CONSTANT_09"]=> int(21) ["CONSTANT_10"]=> int(22) } end of test php-interbase-5.4.6/tests/bug45575.phpt0000664000175000017500000000113412012622335017444 0ustar jtaylorjtaylor--TEST-- Bug #45575 (Segfault with invalid non-string as event handler callback) --SKIPIF-- --FILE-- --EXPECTF-- Warning: ibase_set_event_handler(): Callback argument is not a callable function in %s on line %d Warning: ibase_set_event_handler(): Callback argument 1 is not a callable function in %s on line %d php-interbase-5.4.6/tests/007.phpt0000664000175000017500000001163212012622335016567 0ustar jtaylorjtaylor--TEST-- InterBase: array handling --SKIPIF-- --FILE-- V_CHAR[$i],$v_char[$i],strlen($v_char[$i])) != 0) { echo " CHAR[$i] fail:\n"; echo " in: ".$v_char[$i]."\n"; echo " out: ".$row->V_CHAR[$i]."\n"; } if($row->V_DATE[$i] != $v_date[$i]) { echo " DATE[$i] fail\n"; echo " in: ".$v_date[$i]."\n"; echo " out: ".$row->V_DATE[$i]."\n"; } if($row->V_DECIMAL[$i] != $v_decimal[$i]) { echo " DECIMAL[$i] fail\n"; echo " in: ".$v_decimal[$i]."\n"; echo " out: ".$row->V_DECIMAL[$i]."\n"; } if(abs($row->V_DOUBLE[$i] - $v_double[$i]) > abs($v_double[$i] / 1E15)) { echo " DOUBLE[$i] fail\n"; echo " in: ".$v_double[$i]."\n"; echo " out: ".$row->V_DOUBLE[$i]."\n"; } if(abs($row->V_FLOAT[$i] - $v_float[$i]) > abs($v_float[$i] / 1E7)) { echo " FLOAT[$i] fail\n"; echo " in: ".$v_float[$i]."\n"; echo " out: ".$row->V_FLOAT[$i]."\n"; } if($row->V_INTEGER[$i] != $v_integer[$i]) { echo " INTEGER[$i] fail\n"; echo " in: ".$v_integer[$i]."\n"; echo " out: ".$row->V_INTEGER[$i]."\n"; } if ($row->V_NUMERIC[$i] != $v_numeric[$i]) { echo " NUMERIC[$i] fail\n"; echo " in: ".$v_numeric[$i]."\n"; echo " out: ".$row->V_NUMERIC[$i]."\n"; } if ($row->V_SMALLINT[$i] != $v_smallint[$i]) { echo " SMALLINT[$i] fail\n"; echo " in: ".$v_smallint[$i]."\n"; echo " out: ".$row->V_SMALLINT[$i]."\n"; } if ($row->V_VARCHAR[$i] != $v_varchar[$i]) { echo " VARCHAR[$i] fail:\n"; echo " in: ".$v_varchar[$i]."\n"; echo " out: ".$row->V_VARCHAR[$i]."\n"; } } ibase_free_result($sel); }/* for($iter) */ echo "select\n"; $sel = ibase_query("SELECT v_multi[5,5,5],v_multi[10,10,10] FROM test7 WHERE iter = 0"); print_r(ibase_fetch_row($sel)); ibase_free_result($sel); for($iter = 1; $iter <= 3; $iter++) { if(!($sel = ibase_query( "select iter from test7 where v_char[$iter] LIKE ?", $v_char[$iter]."%")) || !ibase_fetch_row($sel)) { echo "CHAR fail\n"; } ibase_free_result($sel); if(!($sel = ibase_query( "select iter from test7 where v_date[$iter] = ?", $v_date[$iter])) || !ibase_fetch_row($sel)) { echo "DATE fail\n"; } ibase_free_result($sel); if(!($sel = ibase_query( "select iter from test7 where v_decimal[$iter] = ?", $v_decimal[$iter])) || !ibase_fetch_row($sel)) { echo "DECIMAL fail\n"; } ibase_free_result($sel); if(!($sel = ibase_query( "select iter from test7 where v_integer[$iter] = ?", $v_integer[$iter])) || !ibase_fetch_row($sel)) { echo "INTEGER fail\n"; } ibase_free_result($sel); if(!($sel = ibase_query( "select iter from test7 where v_numeric[$iter] = ?", $v_numeric[$iter])) || !ibase_fetch_row($sel)) { echo "NUMERIC fail\n"; } ibase_free_result($sel); if(!($sel = ibase_query( "select iter from test7 where v_smallint[$iter] = ?", $v_smallint[$iter])) || !ibase_fetch_row($sel)) { echo "SMALLINT fail\n"; } ibase_free_result($sel); } ibase_close(); echo "end of test\n"; ?> --EXPECT-- insert select Array ( [0] => 125 [1] => 1000 ) end of test php-interbase-5.4.6/tests/ibase_rollback_001.phpt0000664000175000017500000000145312012622335021575 0ustar jtaylorjtaylor--TEST-- ibase_rollback(): Basic test --SKIPIF-- --FILE-- --EXPECTF-- array(1) { [0]=> int(3) } bool(true) array(1) { [0]=> int(0) } bool(true) Warning: ibase_rollback(): invalid transaction handle (expecting explicit transaction start) in %s on line %d bool(false) php-interbase-5.4.6/tests/bug46247.phpt0000664000175000017500000000177412012622335017453 0ustar jtaylorjtaylor--TEST-- Bug #46247 (ibase_set_event_handler() is allowing to pass callback without event) --SKIPIF-- --FILE-- --EXPECTF-- Warning: Wrong parameter count for ibase_set_event_handler() in %s on line %d Warning: ibase_set_event_handler(): supplied argument is not a valid InterBase link resource in %s on line %d Warning: ibase_set_event_handler(): Callback argument foo is not a callable function in %s on line %d Warning: ibase_set_event_handler(): Callback argument foo is not a callable function in %s on line %d Warning: ibase_set_event_handler(): supplied argument is not a valid InterBase link resource in %s on line %d php-interbase-5.4.6/tests/ibase_free_query_001.phpt0000664000175000017500000000126712012622335022155 0ustar jtaylorjtaylor--TEST-- ibase_free_query(): Basic test --SKIPIF-- --FILE-- --EXPECTF-- bool(true) Warning: ibase_free_query(): 11 is not a valid Firebird/InterBase query resource in %s on line %d bool(false) Warning: ibase_free_query(): supplied resource is not a valid Firebird/InterBase query resource in %s on line %d bool(false) php-interbase-5.4.6/tests/002.phpt0000664000175000017500000000110612012622335016555 0ustar jtaylorjtaylor--TEST-- InterBase: connect, close and pconnect --SKIPIF-- --FILE-- --EXPECT-- --- test1 --- 1 test table not created with isql --- --- test1 --- 1 test table not created with isql --- php-interbase-5.4.6/tests/004.phpt0000664000175000017500000002077612012622335016575 0ustar jtaylorjtaylor--TEST-- InterBase: BLOB test --SKIPIF-- --FILE-- V_BLOB); $blob = ''; while($piece = ibase_blob_get($bl_h, 1 + rand() % 1024)) $blob .= $piece; if($blob != $blob_str) echo " BLOB 1 fail (1)\n"; ibase_blob_close($bl_h); $bl_h = ibase_blob_open($link,$row->V_BLOB); $blob = ''; while($piece = ibase_blob_get($bl_h, 100 * 1024)) $blob .= $piece; if($blob != $blob_str) echo " BLOB 1 fail (2)\n"; ibase_blob_close($bl_h); ibase_free_result($q); unset($blob); echo "create blob 2\n"; ibase_query("INSERT INTO test4 (v_integer, v_blob) VALUES (2, ?)", $blob_str); echo "test blob 2\n"; $q = ibase_query("SELECT v_blob FROM test4 WHERE v_integer = 2"); $row = ibase_fetch_object($q,IBASE_TEXT); if($row->V_BLOB != $blob_str) echo " BLOB 2 fail\n"; ibase_free_result($q); unset($blob); echo "create blob 3\n"; $bl_h = ibase_blob_create($link); ibase_blob_add($bl_h, "+----------------------------------------------------------------------+\n"); ibase_blob_add($bl_h, "| PHP HTML Embedded Scripting Language Version 3.0 |\n"); ibase_blob_add($bl_h, "+----------------------------------------------------------------------+\n"); ibase_blob_add($bl_h, "| Copyright (c) 1997-2000 PHP Development Team (See Credits file) |\n"); ibase_blob_add($bl_h, "+----------------------------------------------------------------------+\n"); ibase_blob_add($bl_h, "| This program is free software; you can redistribute it and/or modify |\n"); ibase_blob_add($bl_h, "| it under the terms of one of the following licenses: |\n"); ibase_blob_add($bl_h, "| |\n"); ibase_blob_add($bl_h, "| A) the GNU General Public License as published by the Free Software |\n"); ibase_blob_add($bl_h, "| Foundation; either version 2 of the License, or (at your option) |\n"); ibase_blob_add($bl_h, "| any later version. |\n"); ibase_blob_add($bl_h, "| |\n"); ibase_blob_add($bl_h, "| B) the PHP License as published by the PHP Development Team and |\n"); ibase_blob_add($bl_h, "| included in the distribution in the file: LICENSE |\n"); ibase_blob_add($bl_h, "| |\n"); ibase_blob_add($bl_h, "| This program is distributed in the hope that it will be useful, |\n"); ibase_blob_add($bl_h, "| but WITHOUT ANY WARRANTY; without even the implied warranty of |\n"); ibase_blob_add($bl_h, "| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |\n"); ibase_blob_add($bl_h, "| GNU General Public License for more details. |\n"); ibase_blob_add($bl_h, "| |\n"); ibase_blob_add($bl_h, "| You should have received a copy of both licenses referred to here. |\n"); ibase_blob_add($bl_h, "| If you did not, or have any questions about PHP licensing, please |\n"); ibase_blob_add($bl_h, "| contact core@php.net. |\n"); ibase_blob_add($bl_h, "+----------------------------------------------------------------------+\n"); $bl_s = ibase_blob_close($bl_h); ibase_query("INSERT INTO test4 (v_integer, v_blob) VALUES (3, ?)", $bl_s); ibase_commit(); echo "echo blob 3\n"; $q = ibase_query("SELECT v_blob FROM test4 WHERE v_integer = 3"); $row = ibase_fetch_object($q); ibase_commit(); ibase_close(); ibase_connect($test_base); ibase_blob_echo($link, $row->V_BLOB); ibase_free_result($q); echo "fetch blob 3\n"; $q = ibase_query("SELECT v_blob FROM test4 WHERE v_integer = 3"); $row = ibase_fetch_object($q,IBASE_TEXT); echo $row->V_BLOB; ibase_free_result($q); ibase_close(); unlink($name); echo "end of test\n"; ?> --EXPECT-- import blob 1 test blob 1 create blob 2 test blob 2 create blob 3 echo blob 3 +----------------------------------------------------------------------+ | PHP HTML Embedded Scripting Language Version 3.0 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2000 PHP Development Team (See Credits file) | +----------------------------------------------------------------------+ | This program is free software; you can redistribute it and/or modify | | it under the terms of one of the following licenses: | | | | A) the GNU General Public License as published by the Free Software | | Foundation; either version 2 of the License, or (at your option) | | any later version. | | | | B) the PHP License as published by the PHP Development Team and | | included in the distribution in the file: LICENSE | | | | This program is distributed in the hope that it will be useful, | | but WITHOUT ANY WARRANTY; without even the implied warranty of | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | | GNU General Public License for more details. | | | | You should have received a copy of both licenses referred to here. | | If you did not, or have any questions about PHP licensing, please | | contact core@php.net. | +----------------------------------------------------------------------+ fetch blob 3 +----------------------------------------------------------------------+ | PHP HTML Embedded Scripting Language Version 3.0 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2000 PHP Development Team (See Credits file) | +----------------------------------------------------------------------+ | This program is free software; you can redistribute it and/or modify | | it under the terms of one of the following licenses: | | | | A) the GNU General Public License as published by the Free Software | | Foundation; either version 2 of the License, or (at your option) | | any later version. | | | | B) the PHP License as published by the PHP Development Team and | | included in the distribution in the file: LICENSE | | | | This program is distributed in the hope that it will be useful, | | but WITHOUT ANY WARRANTY; without even the implied warranty of | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | | GNU General Public License for more details. | | | | You should have received a copy of both licenses referred to here. | | If you did not, or have any questions about PHP licensing, please | | contact core@php.net. | +----------------------------------------------------------------------+ end of test php-interbase-5.4.6/tests/ibase_close_001.phpt0000664000175000017500000000076412012622335021115 0ustar jtaylorjtaylor--TEST-- ibase_close(): Basic test --SKIPIF-- --FILE-- --EXPECTF-- bool(true) bool(true) Warning: ibase_close(): %d is not a valid Firebird/InterBase link resource in %s on line %d bool(false) Warning: ibase_close() expects parameter 1 to be resource,%string given in %s on line %d NULL php-interbase-5.4.6/tests/ibase_num_fields_001.phpt0000664000175000017500000000076112012622335022132 0ustar jtaylorjtaylor--TEST-- ibase_num_fields(): Basic test --SKIPIF-- --FILE-- --EXPECTF-- int(2) Warning: ibase_num_fields() expects parameter 1 to be resource, integer given in %s on line %d NULL Warning: ibase_num_fields() expects exactly 1 parameter, 0 given in %s on line %d NULL php-interbase-5.4.6/tests/ibase_drop_db_001.phpt0000664000175000017500000000136412012622335021416 0ustar jtaylorjtaylor--TEST-- ibase_drop_db(): Basic test --SKIPIF-- --FILE-- --EXPECTF-- resource(%d) of type (Firebird/InterBase link) bool(true) Warning: ibase_drop_db() expects parameter 1 to be resource, integer given in %s on line %d NULL Warning: ibase_drop_db() expects parameter 1 to be resource, null given in %s on line %d NULL php-interbase-5.4.6/tests/ibase_param_info_001.phpt0000664000175000017500000000142012012622335022111 0ustar jtaylorjtaylor--TEST-- ibase_param_info(): Basic test --SKIPIF-- --FILE-- --EXPECTF-- array(10) { [0]=> string(0) "" ["name"]=> string(0) "" [1]=> string(0) "" ["alias"]=> string(0) "" [2]=> string(0) "" ["relation"]=> string(0) "" [3]=> string(1) "4" ["length"]=> string(1) "4" [4]=> string(7) "INTEGER" ["type"]=> string(7) "INTEGER" } --- bool(false) --- Warning: ibase_param_info() expects exactly 2 parameters, 1 given in %s on line %d NULL php-interbase-5.4.6/tests/006.phpt0000664000175000017500000001472212012622335016571 0ustar jtaylorjtaylor--TEST-- InterBase: binding (may take a while) --SKIPIF-- --FILE-- V_CHAR,0,strlen($v_char)) != $v_char) { echo " CHAR fail:\n"; echo " in: $v_char\n"; echo " out: $row->V_CHAR\n"; } if($row->V_DATE != $v_date) { echo " DATE fail\n"; echo " in: $v_date\n"; echo " out: $row->V_DATE\n"; } if($row->V_DECIMAL != $v_decimal) { echo " DECIMAL fail\n"; echo " in: $v_decimal\n"; echo " out: $row->V_DECIMAL\n"; } if(abs($row->V_DOUBLE - $v_double) > abs($v_double / 1E15)) { echo " DOUBLE fail\n"; echo " in: $v_double\n"; echo " out: $row->V_DOUBLE\n"; } if(abs($row->V_FLOAT - $v_float) > abs($v_float / 1E7)) { echo " FLOAT fail\n"; echo " in: $v_float\n"; echo " out: $row->V_FLOAT\n"; } if($row->V_INTEGER != $v_integer) { echo " INTEGER fail\n"; echo " in: $v_integer\n"; echo " out: $row->V_INTEGER\n"; } if ($row->V_NUMERIC != $v_numeric) { echo " NUMERIC fail\n"; echo " in: $v_numeric\n"; echo " out: $row->V_NUMERIC\n"; } if ($row->V_SMALLINT != $v_smallint) { echo " SMALLINT fail\n"; echo " in: $v_smallint\n"; echo " out: $row->V_SMALLINT\n"; } if ($row->V_VARCHAR != $v_varchar) { echo " VARCHAR fail:\n"; echo " in: $v_varchar\n"; echo " out: $row->V_VARCHAR\n"; } ibase_free_result($sel); }/* for($iter)*/ echo "select\n"; for($iter = 0; $iter < 3; $iter++) { /* prepare data */ $v_char = rand_str(1000); $v_date = (int)rand_number(10,0,0); $v_decimal = rand_number(12,3); $v_double = rand_number(20); $v_float = rand_number(7); $v_integer = rand_number(9,0); $v_numeric = rand_number(4,2); $v_smallint = rand_number(5) % 32767; $v_varchar = rand_str(10000); /* clear table*/ ibase_query("delete from test6"); /* make one record */ ibase_query("insert into test6 (iter, v_char,v_date,v_decimal, v_integer,v_numeric,v_smallint,v_varchar) values (666, '$v_char',?,$v_decimal, $v_integer, $v_numeric, $v_smallint, '$v_varchar')",$v_date); /* test all types */ if(!($sel = ibase_query( "select iter from test6 where v_char = ?", $v_char)) || !ibase_fetch_row($sel)) { echo "CHAR fail\n"; } ibase_free_result($sel); if(!($sel = ibase_query( "select iter from test6 where v_date = ?", $v_date)) || !ibase_fetch_row($sel)) { echo "DATE fail\n"; } ibase_free_result($sel); if(!($sel = ibase_query( "select iter from test6 where v_decimal = ?", $v_decimal)) || !ibase_fetch_row($sel)) { echo "DECIMAL fail\n"; } ibase_free_result($sel); if(!($sel = ibase_query( "select iter from test6 where v_integer = ?", $v_integer)) || !ibase_fetch_row($sel)) { echo "INTEGER fail\n"; } ibase_free_result($sel); if(!($sel = ibase_query( "select iter from test6 where v_numeric = ?", $v_numeric)) || !ibase_fetch_row($sel)) { echo "NUMERIC fail\n"; } ibase_free_result($sel); if(!($sel = ibase_query( "select iter from test6 where v_smallint = ?", $v_smallint)) || !ibase_fetch_row($sel)) { echo "SMALLINT fail\n"; } ibase_free_result($sel); if(!($sel = ibase_query( "select iter from test6 where v_varchar = ?", $v_varchar)) || !ibase_fetch_row($sel)) { echo "VARCHAR fail\n"; } ibase_free_result($sel); } /*for iter*/ echo "prepare and exec insert\n"; /* prepare table */ ibase_query("delete from test6"); /* prepare query */ $query = ibase_prepare( "insert into test6 (v_integer) values (?)"); for($i = 0; $i < 10; $i++) { ibase_execute($query, $i); } out_table("test6"); ibase_free_query($query); echo "prepare and exec select\n"; /* prepare query */ $query = ibase_prepare("select * from test6 where v_integer between ? and ?"); $low_border = 2; $high_border = 6; $res = ibase_execute($query, $low_border, $high_border); out_result($res, "test6"); ibase_free_result($res); $low_border = 0; $high_border = 4; $res = ibase_execute($query, $low_border, $high_border); out_result($res, "test6"); ibase_free_result($res); $res = ibase_execute($query, "5", 7.499); out_result($res, "test6"); ibase_free_result($res); ibase_free_query($query); /* test execute procedure */ $query = ibase_prepare("execute procedure add1(?)"); $res = array(); for ($i = 0; $i < 10; $i++) { $res[] = ibase_execute($query,$i); } ibase_free_query($query); foreach ($res as $r) { out_result($r, "proc add1"); ibase_free_result($r); } ibase_close(); echo "end of test\n"; ?> --EXPECT-- insert select prepare and exec insert --- test6 --- 0 1 2 3 4 5 6 7 8 9 --- prepare and exec select --- test6 --- 2 3 4 5 6 --- --- test6 --- 0 1 2 3 4 --- --- test6 --- 5 6 7 --- --- proc add1 --- 1 --- --- proc add1 --- 2 --- --- proc add1 --- 3 --- --- proc add1 --- 4 --- --- proc add1 --- 5 --- --- proc add1 --- 6 --- --- proc add1 --- 7 --- --- proc add1 --- 8 --- --- proc add1 --- 9 --- --- proc add1 --- 10 --- end of test php-interbase-5.4.6/tests/ibase_num_params_001.phpt0000664000175000017500000000137612012622335022152 0ustar jtaylorjtaylor--TEST-- ibase_num_params(): Basic test --SKIPIF-- --FILE-- --EXPECTF-- int(2) Warning: ibase_num_params() expects exactly 1 parameter, 0 given in %s on line %d NULL Warning: ibase_prepare(): Dynamic SQL Error SQL error code = -206 %s in %s on line %d Warning: ibase_num_params() expects parameter 1 to be resource, boolean given in %s on line %d NULL php-interbase-5.4.6/tests/005.phpt0000664000175000017500000001323512012622335016566 0ustar jtaylorjtaylor--TEST-- InterBase: transactions --SKIPIF-- --FILE-- --EXPECT-- default transaction: empty table --- test5 --- --- one row --- test5 --- 1 --- after rollback table empty again --- test5 --- --- one row --- test5 --- 2 --- one row --- test5 --- 2 --- one row... again. --- test5 --- 2 --- one row. --- test5 --- 2 --- one row --- test5 --- 2 --- two rows --- test5 --- 2 3 --- two rows again --- test5 --- 2 4 --- one row in second transaction --- test5 --- 2 --- three rows in third transaction --- test5 --- 2 3 4 --- three rows in fourth transaction with deadlock --- test5 --- 2 3 4 errmsg [lock conflict on no wait transaction deadlock ] --- three rows --- test5 --- 2 3 4 --- four rows --- test5 --- 2 3 4 5 --- four rows again --- test5 --- 2 3 4 5 --- end of test php-interbase-5.4.6/tests/ibase_trans_002.phpt0000664000175000017500000000106112012622335021127 0ustar jtaylorjtaylor--TEST-- ibase_trans(): Basic operations --SKIPIF-- --FILE-- --EXPECT-- int(1) array(2) { ["I"]=> int(100) ["C"]=> string(3) "100" } php-interbase-5.4.6/tests/bug45373.phpt0000664000175000017500000000203412012622335017440 0ustar jtaylorjtaylor--TEST-- Bug #45373 (php crash on query with errors in params) --SKIPIF-- --FILE-- --EXPECTF-- array(2) { ["I"]=> int(1) ["C"]=> string(32) "test table not created with isql" } Notice: ibase_execute(): Statement expects 2 arguments, 3 given in %s on line %d array(2) { ["I"]=> int(1) ["C"]=> string(32) "test table not created with isql" } Warning: ibase_execute(): Statement expects 2 arguments, 1 given in %s on line %d Warning: ibase_fetch_assoc() expects parameter 1 to be resource, boolean given in %s on line %d NULL php-interbase-5.4.6/tests/ibase_trans_001.phpt0000664000175000017500000000062412012622335021132 0ustar jtaylorjtaylor--TEST-- ibase_trans(): Basic test --SKIPIF-- --FILE-- --EXPECTF-- resource(%d) of type (Firebird/InterBase transaction) resource(%d) of type (Firebird/InterBase transaction) bool(true) bool(true) php-interbase-5.4.6/tests/interbase.inc0000775000175000017500000000545512012622335020044 0ustar jtaylorjtaylor php-interbase-5.4.6/interbase.c0000664000175000017500000013215112012622335016342 0ustar jtaylorjtaylor/* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2012 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.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: Jouni Ahto | | Andrew Avdeev | | Ard Biesheuvel | +----------------------------------------------------------------------+ */ /* $Id$ */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #define _GNU_SOURCE #include "php.h" #if HAVE_IBASE #include "php_ini.h" #include "ext/standard/php_standard.h" #include "ext/standard/md5.h" #include "php_interbase.h" #include "php_ibase_includes.h" #include "SAPI.h" #include #define ROLLBACK 0 #define COMMIT 1 #define RETAIN 2 #define CHECK_LINK(link) { if (link==-1) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "A link to the server could not be established"); RETURN_FALSE; } } ZEND_DECLARE_MODULE_GLOBALS(ibase) static PHP_GINIT_FUNCTION(ibase); /* {{{ arginfo */ ZEND_BEGIN_ARG_INFO(arginfo_ibase_errmsg, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO(arginfo_ibase_errcode, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_connect, 0, 0, 1) ZEND_ARG_INFO(0, database) ZEND_ARG_INFO(0, username) ZEND_ARG_INFO(0, password) ZEND_ARG_INFO(0, charset) ZEND_ARG_INFO(0, buffers) ZEND_ARG_INFO(0, dialect) ZEND_ARG_INFO(0, role) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_pconnect, 0, 0, 1) ZEND_ARG_INFO(0, database) ZEND_ARG_INFO(0, username) ZEND_ARG_INFO(0, password) ZEND_ARG_INFO(0, charset) ZEND_ARG_INFO(0, buffers) ZEND_ARG_INFO(0, dialect) ZEND_ARG_INFO(0, role) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_close, 0, 0, 0) ZEND_ARG_INFO(0, link_identifier) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_drop_db, 0, 0, 0) ZEND_ARG_INFO(0, link_identifier) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_trans, 0, 0, 0) ZEND_ARG_INFO(0, trans_args) ZEND_ARG_INFO(0, link_identifier) ZEND_ARG_INFO(0, trans_args) ZEND_ARG_INFO(0, link_identifier) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_commit, 0, 0, 1) ZEND_ARG_INFO(0, link_identifier) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_rollback, 0, 0, 1) ZEND_ARG_INFO(0, link_identifier) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_commit_ret, 0, 0, 1) ZEND_ARG_INFO(0, link_identifier) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_rollback_ret, 0, 0, 1) ZEND_ARG_INFO(0, link_identifier) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_gen_id, 0, 0, 1) ZEND_ARG_INFO(0, generator) ZEND_ARG_INFO(0, increment) ZEND_ARG_INFO(0, link_identifier) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_blob_create, 0, 0, 0) ZEND_ARG_INFO(0, link_identifier) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_blob_open, 0, 0, 0) ZEND_ARG_INFO(0, link_identifier) ZEND_ARG_INFO(0, blob_id) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_blob_add, 0, 0, 2) ZEND_ARG_INFO(0, blob_handle) ZEND_ARG_INFO(0, data) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_blob_get, 0, 0, 2) ZEND_ARG_INFO(0, blob_handle) ZEND_ARG_INFO(0, len) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_blob_close, 0, 0, 1) ZEND_ARG_INFO(0, blob_handle) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_blob_cancel, 0, 0, 1) ZEND_ARG_INFO(0, blob_handle) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_blob_info, 0, 0, 0) ZEND_ARG_INFO(0, link_identifier) ZEND_ARG_INFO(0, blob_id) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_blob_echo, 0, 0, 0) ZEND_ARG_INFO(0, link_identifier) ZEND_ARG_INFO(0, blob_id) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_blob_import, 0, 0, 0) ZEND_ARG_INFO(0, link_identifier) ZEND_ARG_INFO(0, file) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_query, 0, 0, 0) ZEND_ARG_INFO(0, link_identifier) ZEND_ARG_INFO(0, link_identifier) ZEND_ARG_INFO(0, query) ZEND_ARG_INFO(0, bind_arg) ZEND_ARG_INFO(0, bind_arg) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_affected_rows, 0, 0, 0) ZEND_ARG_INFO(0, link_identifier) ZEND_END_ARG_INFO() #if abies_0 ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_num_rows, 0, 0, 1) ZEND_ARG_INFO(0, result_identifier) ZEND_END_ARG_INFO() #endif ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_fetch_row, 0, 0, 1) ZEND_ARG_INFO(0, result) ZEND_ARG_INFO(0, fetch_flags) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_fetch_assoc, 0, 0, 1) ZEND_ARG_INFO(0, result) ZEND_ARG_INFO(0, fetch_flags) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_fetch_object, 0, 0, 1) ZEND_ARG_INFO(0, result) ZEND_ARG_INFO(0, fetch_flags) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_name_result, 0, 0, 2) ZEND_ARG_INFO(0, result) ZEND_ARG_INFO(0, name) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_free_result, 0, 0, 1) ZEND_ARG_INFO(0, result) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_prepare, 0, 0, 0) ZEND_ARG_INFO(0, link_identifier) ZEND_ARG_INFO(0, query) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_execute, 0, 0, 1) ZEND_ARG_INFO(0, query) ZEND_ARG_INFO(0, bind_arg) ZEND_ARG_INFO(0, bind_arg) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_free_query, 0, 0, 1) ZEND_ARG_INFO(0, query) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_num_fields, 0, 0, 1) ZEND_ARG_INFO(0, query_result) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_field_info, 0, 0, 2) ZEND_ARG_INFO(0, query_result) ZEND_ARG_INFO(0, field_number) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_num_params, 0, 0, 1) ZEND_ARG_INFO(0, query) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_param_info, 0, 0, 2) ZEND_ARG_INFO(0, query) ZEND_ARG_INFO(0, field_number) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_add_user, 0, 0, 3) ZEND_ARG_INFO(0, service_handle) ZEND_ARG_INFO(0, user_name) ZEND_ARG_INFO(0, password) ZEND_ARG_INFO(0, first_name) ZEND_ARG_INFO(0, middle_name) ZEND_ARG_INFO(0, last_name) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_modify_user, 0, 0, 3) ZEND_ARG_INFO(0, service_handle) ZEND_ARG_INFO(0, user_name) ZEND_ARG_INFO(0, password) ZEND_ARG_INFO(0, first_name) ZEND_ARG_INFO(0, middle_name) ZEND_ARG_INFO(0, last_name) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_delete_user, 0, 0, 3) ZEND_ARG_INFO(0, service_handle) ZEND_ARG_INFO(0, user_name) ZEND_ARG_INFO(0, password) ZEND_ARG_INFO(0, first_name) ZEND_ARG_INFO(0, middle_name) ZEND_ARG_INFO(0, last_name) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_service_attach, 0, 0, 3) ZEND_ARG_INFO(0, host) ZEND_ARG_INFO(0, dba_username) ZEND_ARG_INFO(0, dba_password) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_service_detach, 0, 0, 1) ZEND_ARG_INFO(0, service_handle) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_backup, 0, 0, 3) ZEND_ARG_INFO(0, service_handle) ZEND_ARG_INFO(0, source_db) ZEND_ARG_INFO(0, dest_file) ZEND_ARG_INFO(0, options) ZEND_ARG_INFO(0, verbose) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_restore, 0, 0, 3) ZEND_ARG_INFO(0, service_handle) ZEND_ARG_INFO(0, source_file) ZEND_ARG_INFO(0, dest_db) ZEND_ARG_INFO(0, options) ZEND_ARG_INFO(0, verbose) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_maintain_db, 0, 0, 3) ZEND_ARG_INFO(0, service_handle) ZEND_ARG_INFO(0, db) ZEND_ARG_INFO(0, action) ZEND_ARG_INFO(0, argument) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_db_info, 0, 0, 3) ZEND_ARG_INFO(0, service_handle) ZEND_ARG_INFO(0, db) ZEND_ARG_INFO(0, action) ZEND_ARG_INFO(0, argument) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_server_info, 0, 0, 2) ZEND_ARG_INFO(0, service_handle) ZEND_ARG_INFO(0, action) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_wait_event, 0, 0, 1) ZEND_ARG_INFO(0, link_identifier) ZEND_ARG_INFO(0, event) ZEND_ARG_INFO(0, event2) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_set_event_handler, 0, 0, 2) ZEND_ARG_INFO(0, link_identifier) ZEND_ARG_INFO(0, handler) ZEND_ARG_INFO(0, event) ZEND_ARG_INFO(0, event2) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_free_event_handler, 0, 0, 1) ZEND_ARG_INFO(0, event) ZEND_END_ARG_INFO() /* }}} */ /* {{{ extension definition structures */ const zend_function_entry ibase_functions[] = { PHP_FE(ibase_connect, arginfo_ibase_connect) PHP_FE(ibase_pconnect, arginfo_ibase_pconnect) PHP_FE(ibase_close, arginfo_ibase_close) PHP_FE(ibase_drop_db, arginfo_ibase_drop_db) PHP_FE(ibase_query, arginfo_ibase_query) PHP_FE(ibase_fetch_row, arginfo_ibase_fetch_row) PHP_FE(ibase_fetch_assoc, arginfo_ibase_fetch_assoc) PHP_FE(ibase_fetch_object, arginfo_ibase_fetch_object) PHP_FE(ibase_free_result, arginfo_ibase_free_result) PHP_FE(ibase_name_result, arginfo_ibase_name_result) PHP_FE(ibase_prepare, arginfo_ibase_prepare) PHP_FE(ibase_execute, arginfo_ibase_execute) PHP_FE(ibase_free_query, arginfo_ibase_free_query) PHP_FE(ibase_gen_id, arginfo_ibase_gen_id) PHP_FE(ibase_num_fields, arginfo_ibase_num_fields) PHP_FE(ibase_num_params, arginfo_ibase_num_params) #if abies_0 PHP_FE(ibase_num_rows, arginfo_ibase_num_rows) #endif PHP_FE(ibase_affected_rows, arginfo_ibase_affected_rows) PHP_FE(ibase_field_info, arginfo_ibase_field_info) PHP_FE(ibase_param_info, arginfo_ibase_param_info) PHP_FE(ibase_trans, arginfo_ibase_trans) PHP_FE(ibase_commit, arginfo_ibase_commit) PHP_FE(ibase_rollback, arginfo_ibase_rollback) PHP_FE(ibase_commit_ret, arginfo_ibase_commit_ret) PHP_FE(ibase_rollback_ret, arginfo_ibase_rollback_ret) PHP_FE(ibase_blob_info, arginfo_ibase_blob_info) PHP_FE(ibase_blob_create, arginfo_ibase_blob_create) PHP_FE(ibase_blob_add, arginfo_ibase_blob_add) PHP_FE(ibase_blob_cancel, arginfo_ibase_blob_cancel) PHP_FE(ibase_blob_close, arginfo_ibase_blob_close) PHP_FE(ibase_blob_open, arginfo_ibase_blob_open) PHP_FE(ibase_blob_get, arginfo_ibase_blob_get) PHP_FE(ibase_blob_echo, arginfo_ibase_blob_echo) PHP_FE(ibase_blob_import, arginfo_ibase_blob_import) PHP_FE(ibase_errmsg, arginfo_ibase_errmsg) PHP_FE(ibase_errcode, arginfo_ibase_errcode) PHP_FE(ibase_add_user, arginfo_ibase_add_user) PHP_FE(ibase_modify_user, arginfo_ibase_modify_user) PHP_FE(ibase_delete_user, arginfo_ibase_delete_user) PHP_FE(ibase_service_attach, arginfo_ibase_service_attach) PHP_FE(ibase_service_detach, arginfo_ibase_service_detach) PHP_FE(ibase_backup, arginfo_ibase_backup) PHP_FE(ibase_restore, arginfo_ibase_restore) PHP_FE(ibase_maintain_db, arginfo_ibase_maintain_db) PHP_FE(ibase_db_info, arginfo_ibase_db_info) PHP_FE(ibase_server_info, arginfo_ibase_server_info) PHP_FE(ibase_wait_event, arginfo_ibase_wait_event) PHP_FE(ibase_set_event_handler, arginfo_ibase_set_event_handler) PHP_FE(ibase_free_event_handler, arginfo_ibase_free_event_handler) /** * These aliases are provided in order to maintain forward compatibility. As Firebird * and InterBase are developed independently, functionality might be different between * the two branches in future versions. * Firebird users should use the aliases, so future InterBase-specific changes will * not affect their code */ PHP_FALIAS(fbird_connect, ibase_connect, arginfo_ibase_connect) PHP_FALIAS(fbird_pconnect, ibase_pconnect, arginfo_ibase_pconnect) PHP_FALIAS(fbird_close, ibase_close, arginfo_ibase_close) PHP_FALIAS(fbird_drop_db, ibase_drop_db, arginfo_ibase_drop_db) PHP_FALIAS(fbird_query, ibase_query, arginfo_ibase_query) PHP_FALIAS(fbird_fetch_row, ibase_fetch_row, arginfo_ibase_fetch_row) PHP_FALIAS(fbird_fetch_assoc, ibase_fetch_assoc, arginfo_ibase_fetch_assoc) PHP_FALIAS(fbird_fetch_object, ibase_fetch_object, arginfo_ibase_fetch_object) PHP_FALIAS(fbird_free_result, ibase_free_result, arginfo_ibase_free_result) PHP_FALIAS(fbird_name_result, ibase_name_result, arginfo_ibase_name_result) PHP_FALIAS(fbird_prepare, ibase_prepare, arginfo_ibase_prepare) PHP_FALIAS(fbird_execute, ibase_execute, arginfo_ibase_execute) PHP_FALIAS(fbird_free_query, ibase_free_query, arginfo_ibase_free_query) PHP_FALIAS(fbird_gen_id, ibase_gen_id, arginfo_ibase_gen_id) PHP_FALIAS(fbird_num_fields, ibase_num_fields, arginfo_ibase_num_fields) PHP_FALIAS(fbird_num_params, ibase_num_params, arginfo_ibase_num_params) #if abies_0 PHP_FALIAS(fbird_num_rows, ibase_num_rows, arginfo_ibase_num_rows) #endif PHP_FALIAS(fbird_affected_rows, ibase_affected_rows, arginfo_ibase_affected_rows) PHP_FALIAS(fbird_field_info, ibase_field_info, arginfo_ibase_field_info) PHP_FALIAS(fbird_param_info, ibase_param_info, arginfo_ibase_param_info) PHP_FALIAS(fbird_trans, ibase_trans, arginfo_ibase_trans) PHP_FALIAS(fbird_commit, ibase_commit, arginfo_ibase_commit) PHP_FALIAS(fbird_rollback, ibase_rollback, arginfo_ibase_rollback) PHP_FALIAS(fbird_commit_ret, ibase_commit_ret, arginfo_ibase_commit_ret) PHP_FALIAS(fbird_rollback_ret, ibase_rollback_ret, arginfo_ibase_rollback_ret) PHP_FALIAS(fbird_blob_info, ibase_blob_info, arginfo_ibase_blob_info) PHP_FALIAS(fbird_blob_create, ibase_blob_create, arginfo_ibase_blob_create) PHP_FALIAS(fbird_blob_add, ibase_blob_add, arginfo_ibase_blob_add) PHP_FALIAS(fbird_blob_cancel, ibase_blob_cancel, arginfo_ibase_blob_cancel) PHP_FALIAS(fbird_blob_close, ibase_blob_close, arginfo_ibase_blob_close) PHP_FALIAS(fbird_blob_open, ibase_blob_open, arginfo_ibase_blob_open) PHP_FALIAS(fbird_blob_get, ibase_blob_get, arginfo_ibase_blob_get) PHP_FALIAS(fbird_blob_echo, ibase_blob_echo, arginfo_ibase_blob_echo) PHP_FALIAS(fbird_blob_import, ibase_blob_import, arginfo_ibase_blob_import) PHP_FALIAS(fbird_errmsg, ibase_errmsg, arginfo_ibase_errmsg) PHP_FALIAS(fbird_errcode, ibase_errcode, arginfo_ibase_errcode) PHP_FALIAS(fbird_add_user, ibase_add_user, arginfo_ibase_add_user) PHP_FALIAS(fbird_modify_user, ibase_modify_user, arginfo_ibase_modify_user) PHP_FALIAS(fbird_delete_user, ibase_delete_user, arginfo_ibase_delete_user) PHP_FALIAS(fbird_service_attach, ibase_service_attach, arginfo_ibase_service_attach) PHP_FALIAS(fbird_service_detach, ibase_service_detach, arginfo_ibase_service_detach) PHP_FALIAS(fbird_backup, ibase_backup, arginfo_ibase_backup) PHP_FALIAS(fbird_restore, ibase_restore, arginfo_ibase_restore) PHP_FALIAS(fbird_maintain_db, ibase_maintain_db, arginfo_ibase_maintain_db) PHP_FALIAS(fbird_db_info, ibase_db_info, arginfo_ibase_db_info) PHP_FALIAS(fbird_server_info, ibase_server_info, arginfo_ibase_server_info) PHP_FALIAS(fbird_wait_event, ibase_wait_event, arginfo_ibase_wait_event) PHP_FALIAS(fbird_set_event_handler, ibase_set_event_handler, arginfo_ibase_set_event_handler) PHP_FALIAS(fbird_free_event_handler, ibase_free_event_handler, arginfo_ibase_free_event_handler) PHP_FE_END }; zend_module_entry ibase_module_entry = { STANDARD_MODULE_HEADER, "interbase", ibase_functions, PHP_MINIT(ibase), PHP_MSHUTDOWN(ibase), NULL, PHP_RSHUTDOWN(ibase), PHP_MINFO(ibase), NO_VERSION_YET, PHP_MODULE_GLOBALS(ibase), PHP_GINIT(ibase), NULL, NULL, STANDARD_MODULE_PROPERTIES_EX }; #ifdef COMPILE_DL_INTERBASE ZEND_GET_MODULE(ibase) #endif /* True globals, no need for thread safety */ int le_link, le_plink, le_trans; /* }}} */ /* error handling ---------------------------- */ /* {{{ proto string ibase_errmsg(void) Return error message */ PHP_FUNCTION(ibase_errmsg) { if (zend_parse_parameters_none() == FAILURE) { return; } if (IBG(sql_code) != 0) { RETURN_STRING(IBG(errmsg), 1); } RETURN_FALSE; } /* }}} */ /* {{{ proto int ibase_errcode(void) Return error code */ PHP_FUNCTION(ibase_errcode) { if (zend_parse_parameters_none() == FAILURE) { return; } if (IBG(sql_code) != 0) { RETURN_LONG(IBG(sql_code)); } RETURN_FALSE; } /* }}} */ /* print interbase error and save it for ibase_errmsg() */ void _php_ibase_error(TSRMLS_D) /* {{{ */ { char *s = IBG(errmsg); ISC_STATUS *statusp = IB_STATUS; IBG(sql_code) = isc_sqlcode(IB_STATUS); while ((s - IBG(errmsg)) < MAX_ERRMSG - (IBASE_MSGSIZE + 2) && isc_interprete(s, &statusp)) { strcat(IBG(errmsg), " "); s = IBG(errmsg) + strlen(IBG(errmsg)); } php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", IBG(errmsg)); } /* }}} */ /* print php interbase module error and save it for ibase_errmsg() */ void _php_ibase_module_error(char *msg TSRMLS_DC, ...) /* {{{ */ { va_list ap; #ifdef ZTS va_start(ap, TSRMLS_C); #else va_start(ap, msg); #endif /* vsnprintf NUL terminates the buf and writes at most n-1 chars+NUL */ vsnprintf(IBG(errmsg), MAX_ERRMSG, msg, ap); va_end(ap); IBG(sql_code) = -999; /* no SQL error */ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", IBG(errmsg)); } /* }}} */ /* {{{ internal macros, functions and structures */ typedef struct { isc_db_handle *db_ptr; long tpb_len; char *tpb_ptr; } ISC_TEB; /* }}} */ /* Fill ib_link and trans with the correct database link and transaction. */ void _php_ibase_get_link_trans(INTERNAL_FUNCTION_PARAMETERS, /* {{{ */ zval **link_id, ibase_db_link **ib_link, ibase_trans **trans) { int type; IBDEBUG("Transaction or database link?"); if (zend_list_find(Z_LVAL_PP(link_id), &type)) { if (type == le_trans) { /* Transaction resource: make sure it refers to one link only, then fetch it; database link is stored in ib_trans->db_link[]. */ IBDEBUG("Type is le_trans"); ZEND_FETCH_RESOURCE(*trans, ibase_trans *, link_id, -1, LE_TRANS, le_trans); if ((*trans)->link_cnt > 1) { _php_ibase_module_error("Link id is ambiguous: transaction spans multiple connections." TSRMLS_CC); return; } *ib_link = (*trans)->db_link[0]; return; } } IBDEBUG("Type is le_[p]link or id not found"); /* Database link resource, use default transaction. */ *trans = NULL; ZEND_FETCH_RESOURCE2(*ib_link, ibase_db_link *, link_id, -1, LE_LINK, le_link, le_plink); } /* }}} */ /* destructors ---------------------- */ static void _php_ibase_commit_link(ibase_db_link *link TSRMLS_DC) /* {{{ */ { unsigned short i = 0, j; ibase_tr_list *l; ibase_event *e; IBDEBUG("Checking transactions to close..."); for (l = link->tr_list; l != NULL; ++i) { ibase_tr_list *p = l; if (p->trans != NULL) { if (i == 0) { if (p->trans->handle != NULL) { IBDEBUG("Committing default transaction..."); if (isc_commit_transaction(IB_STATUS, &p->trans->handle)) { _php_ibase_error(TSRMLS_C); } } efree(p->trans); /* default transaction is not a registered resource: clean up */ } else { if (p->trans->handle != NULL) { /* non-default trans might have been rolled back by other call of this dtor */ IBDEBUG("Rolling back other transactions..."); if (isc_rollback_transaction(IB_STATUS, &p->trans->handle)) { _php_ibase_error(TSRMLS_C); } } /* set this link pointer to NULL in the transaction */ for (j = 0; j < p->trans->link_cnt; ++j) { if (p->trans->db_link[j] == link) { p->trans->db_link[j] = NULL; break; } } } } l = l->next; efree(p); } link->tr_list = NULL; for (e = link->event_head; e; e = e->event_next) { _php_ibase_free_event(e TSRMLS_CC); e->link = NULL; } } /* }}} */ static void php_ibase_commit_link_rsrc(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */ { ibase_db_link *link = (ibase_db_link *) rsrc->ptr; _php_ibase_commit_link(link TSRMLS_CC); } /* }}} */ static void _php_ibase_close_link(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */ { ibase_db_link *link = (ibase_db_link *) rsrc->ptr; _php_ibase_commit_link(link TSRMLS_CC); if (link->handle != NULL) { IBDEBUG("Closing normal link..."); isc_detach_database(IB_STATUS, &link->handle); } IBG(num_links)--; efree(link); } /* }}} */ static void _php_ibase_close_plink(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */ { ibase_db_link *link = (ibase_db_link *) rsrc->ptr; _php_ibase_commit_link(link TSRMLS_CC); IBDEBUG("Closing permanent link..."); if (link->handle != NULL) { isc_detach_database(IB_STATUS, &link->handle); } IBG(num_persistent)--; IBG(num_links)--; free(link); } /* }}} */ static void _php_ibase_free_trans(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */ { ibase_trans *trans = (ibase_trans *)rsrc->ptr; unsigned short i; IBDEBUG("Cleaning up transaction resource..."); if (trans->handle != NULL) { IBDEBUG("Rolling back unhandled transaction..."); if (isc_rollback_transaction(IB_STATUS, &trans->handle)) { _php_ibase_error(TSRMLS_C); } } /* now remove this transaction from all the connection-transaction lists */ for (i = 0; i < trans->link_cnt; ++i) { if (trans->db_link[i] != NULL) { ibase_tr_list **l; for (l = &trans->db_link[i]->tr_list; *l != NULL; l = &(*l)->next) { if ( (*l)->trans == trans) { ibase_tr_list *p = *l; *l = p->next; efree(p); break; } } } } efree(trans); } /* }}} */ /* TODO this function should be part of either Zend or PHP API */ static PHP_INI_DISP(php_ibase_password_displayer_cb) { TSRMLS_FETCH(); if ((type == PHP_INI_DISPLAY_ORIG && ini_entry->orig_value) || (type == PHP_INI_DISPLAY_ACTIVE && ini_entry->value)) { PUTS("********"); } else if (!sapi_module.phpinfo_as_text) { PUTS("no value"); } else { PUTS("no value"); } } /* {{{ startup, shutdown and info functions */ PHP_INI_BEGIN() PHP_INI_ENTRY_EX("ibase.allow_persistent", "1", PHP_INI_SYSTEM, NULL, zend_ini_boolean_displayer_cb) PHP_INI_ENTRY_EX("ibase.max_persistent", "-1", PHP_INI_SYSTEM, NULL, display_link_numbers) PHP_INI_ENTRY_EX("ibase.max_links", "-1", PHP_INI_SYSTEM, NULL, display_link_numbers) PHP_INI_ENTRY("ibase.default_db", NULL, PHP_INI_SYSTEM, NULL) PHP_INI_ENTRY("ibase.default_user", NULL, PHP_INI_ALL, NULL) PHP_INI_ENTRY_EX("ibase.default_password", NULL, PHP_INI_ALL, NULL, php_ibase_password_displayer_cb) PHP_INI_ENTRY("ibase.default_charset", NULL, PHP_INI_ALL, NULL) PHP_INI_ENTRY("ibase.timestampformat", IB_DEF_DATE_FMT " " IB_DEF_TIME_FMT, PHP_INI_ALL, NULL) PHP_INI_ENTRY("ibase.dateformat", IB_DEF_DATE_FMT, PHP_INI_ALL, NULL) PHP_INI_ENTRY("ibase.timeformat", IB_DEF_TIME_FMT, PHP_INI_ALL, NULL) PHP_INI_END() static PHP_GINIT_FUNCTION(ibase) { ibase_globals->num_persistent = ibase_globals->num_links = 0; ibase_globals->sql_code = *ibase_globals->errmsg = 0; ibase_globals->default_link = -1; } PHP_MINIT_FUNCTION(ibase) { REGISTER_INI_ENTRIES(); le_link = zend_register_list_destructors_ex(_php_ibase_close_link, NULL, LE_LINK, module_number); le_plink = zend_register_list_destructors_ex(php_ibase_commit_link_rsrc, _php_ibase_close_plink, LE_PLINK, module_number); le_trans = zend_register_list_destructors_ex(_php_ibase_free_trans, NULL, LE_TRANS, module_number); REGISTER_LONG_CONSTANT("IBASE_DEFAULT", PHP_IBASE_DEFAULT, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_CREATE", PHP_IBASE_CREATE, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_TEXT", PHP_IBASE_FETCH_BLOBS, CONST_PERSISTENT); /* deprecated, for BC only */ REGISTER_LONG_CONSTANT("IBASE_FETCH_BLOBS", PHP_IBASE_FETCH_BLOBS, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_FETCH_ARRAYS", PHP_IBASE_FETCH_ARRAYS, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_UNIXTIME", PHP_IBASE_UNIXTIME, CONST_PERSISTENT); /* transactions */ REGISTER_LONG_CONSTANT("IBASE_WRITE", PHP_IBASE_WRITE, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_READ", PHP_IBASE_READ, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_COMMITTED", PHP_IBASE_COMMITTED, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_CONSISTENCY", PHP_IBASE_CONSISTENCY, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_CONCURRENCY", PHP_IBASE_CONCURRENCY, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_REC_VERSION", PHP_IBASE_REC_VERSION, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_REC_NO_VERSION", PHP_IBASE_REC_NO_VERSION, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_NOWAIT", PHP_IBASE_NOWAIT, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IBASE_WAIT", PHP_IBASE_WAIT, CONST_PERSISTENT); php_ibase_query_minit(INIT_FUNC_ARGS_PASSTHRU); php_ibase_blobs_minit(INIT_FUNC_ARGS_PASSTHRU); php_ibase_events_minit(INIT_FUNC_ARGS_PASSTHRU); php_ibase_service_minit(INIT_FUNC_ARGS_PASSTHRU); return SUCCESS; } PHP_MSHUTDOWN_FUNCTION(ibase) { #ifndef PHP_WIN32 /** * When the Interbase client API library libgds.so is first loaded, it registers a call to * gds__cleanup() with atexit(), in order to clean up after itself when the process exits. * This means that the library is called at process shutdown, and cannot be unloaded beforehand. * PHP tries to unload modules after every request [dl()'ed modules], and right before the * process shuts down [modules loaded from php.ini]. This results in a segfault for this module. * By NULLing the dlopen() handle in the module entry, Zend omits the call to dlclose(), * ensuring that the module will remain present until the process exits. However, the functions * and classes exported by the module will not be available until the module is 'reloaded'. * When reloaded, dlopen() will return the handle of the already loaded module. The module will * be unloaded automatically when the process exits. */ zend_module_entry *ibase_entry; if (SUCCESS == zend_hash_find(&module_registry, ibase_module_entry.name, strlen(ibase_module_entry.name) +1, (void*) &ibase_entry)) { ibase_entry->handle = NULL; } #endif UNREGISTER_INI_ENTRIES(); return SUCCESS; } PHP_RSHUTDOWN_FUNCTION(ibase) { IBG(num_links) = IBG(num_persistent); IBG(default_link)= -1; RESET_ERRMSG; return SUCCESS; } PHP_MINFO_FUNCTION(ibase) { char tmp[64], *s; php_info_print_table_start(); php_info_print_table_row(2, "Firebird/InterBase Support", #ifdef COMPILE_DL_INTERBASE "dynamic"); #else "static"); #endif #ifdef FB_API_VER snprintf( (s = tmp), sizeof(tmp), "Firebird API version %d", FB_API_VER); #elif (SQLDA_CURRENT_VERSION > 1) s = "Interbase 7.0 and up"; #elif !defined(DSC_null) s = "Interbase 6"; #else s = "Firebird 1.0"; #endif php_info_print_table_row(2, "Compile-time Client Library Version", s); #if defined(__GNUC__) || defined(PHP_WIN32) do { info_func_t info_func = NULL; #ifdef __GNUC__ info_func = (info_func_t)dlsym(RTLD_DEFAULT, "isc_get_client_version"); #else HMODULE l = GetModuleHandle("fbclient"); if (!l && !(l = GetModuleHandle("gds32"))) { break; } info_func = (info_func_t)GetProcAddress(l, "isc_get_client_version"); #endif if (info_func) { info_func(s = tmp); } else { s = "Firebird 1.0/Interbase 6"; } php_info_print_table_row(2, "Run-time Client Library Version", s); } while (0); #endif php_info_print_table_end(); DISPLAY_INI_ENTRIES(); } /* }}} */ enum connect_args { DB = 0, USER = 1, PASS = 2, CSET = 3, ROLE = 4, BUF = 0, DLECT = 1, SYNC = 2 }; static char const dpb_args[] = { 0, isc_dpb_user_name, isc_dpb_password, isc_dpb_lc_ctype, isc_dpb_sql_role_name, 0 }; int _php_ibase_attach_db(char **args, int *len, long *largs, isc_db_handle *db TSRMLS_DC) { short i, dpb_len, buf_len = 257-2; /* version byte at the front, and a null at the end */ char dpb_buffer[257] = { isc_dpb_version1, 0 }, *dpb; dpb = dpb_buffer + 1; for (i = 0; i < sizeof(dpb_args); ++i) { if (dpb_args[i] && args[i] && len[i] && buf_len > 0) { dpb_len = slprintf(dpb, buf_len, "%c%c%s", dpb_args[i],(unsigned char)len[i],args[i]); dpb += dpb_len; buf_len -= dpb_len; } } if (largs[BUF] && buf_len > 0) { dpb_len = slprintf(dpb, buf_len, "%c\2%c%c", isc_dpb_num_buffers, (char)(largs[BUF] >> 8), (char)(largs[BUF] & 0xff)); dpb += dpb_len; buf_len -= dpb_len; } if (largs[SYNC] && buf_len > 0) { dpb_len = slprintf(dpb, buf_len, "%c\1%c", isc_dpb_force_write, largs[SYNC] == isc_spb_prp_wm_sync ? 1 : 0); dpb += dpb_len; buf_len -= dpb_len; } if (isc_attach_database(IB_STATUS, (short)len[DB], args[DB], db, (short)(dpb-dpb_buffer), dpb_buffer)) { _php_ibase_error(TSRMLS_C); return FAILURE; } return SUCCESS; } /* }}} */ static void _php_ibase_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) /* {{{ */ { char *c, hash[16], *args[] = { NULL, NULL, NULL, NULL, NULL }; int i, len[] = { 0, 0, 0, 0, 0 }; long largs[] = { 0, 0, 0 }; PHP_MD5_CTX hash_context; zend_rsrc_list_entry new_index_ptr, *le; isc_db_handle db_handle = NULL; ibase_db_link *ib_link; RESET_ERRMSG; if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ssssllsl", &args[DB], &len[DB], &args[USER], &len[USER], &args[PASS], &len[PASS], &args[CSET], &len[CSET], &largs[BUF], &largs[DLECT], &args[ROLE], &len[ROLE], &largs[SYNC])) { RETURN_FALSE; } /* restrict to the server/db in the .ini if in safe mode */ if ((!len[DB] || PG(sql_safe_mode)) && (c = INI_STR("ibase.default_db"))) { args[DB] = c; len[DB] = strlen(c); } if (!len[USER] && (c = INI_STR("ibase.default_user"))) { args[USER] = c; len[USER] = strlen(c); } if (!len[PASS] && (c = INI_STR("ibase.default_password"))) { args[PASS] = c; len[PASS] = strlen(c); } if (!len[CSET] && (c = INI_STR("ibase.default_charset"))) { args[CSET] = c; len[CSET] = strlen(c); } /* don't want usernames and passwords floating around */ PHP_MD5Init(&hash_context); for (i = 0; i < sizeof(args)/sizeof(char*); ++i) { PHP_MD5Update(&hash_context,args[i],len[i]); } for (i = 0; i < sizeof(largs)/sizeof(long); ++i) { PHP_MD5Update(&hash_context,(char*)&largs[i],sizeof(long)); } PHP_MD5Final(hash, &hash_context); /* try to reuse a connection */ if (SUCCESS == zend_hash_find(&EG(regular_list), hash, sizeof(hash), (void *) &le)) { long xlink; int type; if (Z_TYPE_P(le) != le_index_ptr) { RETURN_FALSE; } xlink = (long) le->ptr; if (zend_list_find(xlink, &type) && ((!persistent && type == le_link) || type == le_plink)) { zend_list_addref(xlink); RETURN_RESOURCE(IBG(default_link) = xlink); } else { zend_hash_del(&EG(regular_list), hash, sizeof(hash)); } } /* ... or a persistent one */ switch (zend_hash_find(&EG(persistent_list), hash, sizeof(hash), (void *) &le)) { long l; static char info[] = { isc_info_base_level, isc_info_end }; char result[8]; ISC_STATUS status[20]; case SUCCESS: if (Z_TYPE_P(le) != le_plink) { RETURN_FALSE; } /* check if connection has timed out */ ib_link = (ibase_db_link *) le->ptr; if (!isc_database_info(status, &ib_link->handle, sizeof(info), info, sizeof(result), result)) { ZEND_REGISTER_RESOURCE(return_value, ib_link, le_plink); break; } zend_hash_del(&EG(persistent_list), hash, sizeof(hash)); default: /* no link found, so we have to open one */ if ((l = INI_INT("ibase.max_links")) != -1 && IBG(num_links) >= l) { _php_ibase_module_error("Too many open links (%ld)" TSRMLS_CC, IBG(num_links)); RETURN_FALSE; } /* create the ib_link */ if (FAILURE == _php_ibase_attach_db(args, len, largs, &db_handle TSRMLS_CC)) { RETURN_FALSE; } /* use non-persistent if allowed number of persistent links is exceeded */ if (!persistent || ((l = INI_INT("ibase.max_persistent") != -1) && IBG(num_persistent) >= l)) { ib_link = (ibase_db_link *) emalloc(sizeof(ibase_db_link)); ZEND_REGISTER_RESOURCE(return_value, ib_link, le_link); } else { zend_rsrc_list_entry new_le; ib_link = (ibase_db_link *) malloc(sizeof(ibase_db_link)); if (!ib_link) { RETURN_FALSE; } /* hash it up */ Z_TYPE(new_le) = le_plink; new_le.ptr = ib_link; if (FAILURE == zend_hash_update(&EG(persistent_list), hash, sizeof(hash), (void *) &new_le, sizeof(zend_rsrc_list_entry), NULL)) { free(ib_link); RETURN_FALSE; } ZEND_REGISTER_RESOURCE(return_value, ib_link, le_plink); ++IBG(num_persistent); } ib_link->handle = db_handle; ib_link->dialect = largs[DLECT] ? (unsigned short)largs[DLECT] : SQL_DIALECT_CURRENT; ib_link->tr_list = NULL; ib_link->event_head = NULL; ++IBG(num_links); } /* add it to the hash */ new_index_ptr.ptr = (void *) Z_LVAL_P(return_value); Z_TYPE(new_index_ptr) = le_index_ptr; if (FAILURE == zend_hash_update(&EG(regular_list), hash, sizeof(hash), (void *) &new_index_ptr, sizeof(zend_rsrc_list_entry), NULL)) { RETURN_FALSE; } zend_list_addref(IBG(default_link) = Z_LVAL_P(return_value)); } /* }}} */ /* {{{ proto resource ibase_connect(string database [, string username [, string password [, string charset [, int buffers [, int dialect [, string role]]]]]]) Open a connection to an InterBase database */ PHP_FUNCTION(ibase_connect) { _php_ibase_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); } /* }}} */ /* {{{ proto resource ibase_pconnect(string database [, string username [, string password [, string charset [, int buffers [, int dialect [, string role]]]]]]) Open a persistent connection to an InterBase database */ PHP_FUNCTION(ibase_pconnect) { _php_ibase_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, INI_INT("ibase.allow_persistent")); } /* }}} */ /* {{{ proto bool ibase_close([resource link_identifier]) Close an InterBase connection */ PHP_FUNCTION(ibase_close) { zval *link_arg = NULL; ibase_db_link *ib_link; int link_id; RESET_ERRMSG; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|r", &link_arg) == FAILURE) { return; } if (ZEND_NUM_ARGS() == 0) { link_id = IBG(default_link); CHECK_LINK(link_id); IBG(default_link) = -1; } else { link_id = Z_RESVAL_P(link_arg); } ZEND_FETCH_RESOURCE2(ib_link, ibase_db_link *, &link_arg, link_id, LE_LINK, le_link, le_plink); zend_list_delete(link_id); RETURN_TRUE; } /* }}} */ /* {{{ proto bool ibase_drop_db([resource link_identifier]) Drop an InterBase database */ PHP_FUNCTION(ibase_drop_db) { zval *link_arg = NULL; ibase_db_link *ib_link; ibase_tr_list *l; int link_id; RESET_ERRMSG; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|r", &link_arg) == FAILURE) { return; } if (ZEND_NUM_ARGS() == 0) { link_id = IBG(default_link); CHECK_LINK(link_id); IBG(default_link) = -1; } else { link_id = Z_RESVAL_P(link_arg); } ZEND_FETCH_RESOURCE2(ib_link, ibase_db_link *, &link_arg, link_id, LE_LINK, le_link, le_plink); if (isc_drop_database(IB_STATUS, &ib_link->handle)) { _php_ibase_error(TSRMLS_C); RETURN_FALSE; } /* isc_drop_database() doesn't invalidate the transaction handles */ for (l = ib_link->tr_list; l != NULL; l = l->next) { if (l->trans != NULL) l->trans->handle = NULL; } zend_list_delete(link_id); RETURN_TRUE; } /* }}} */ /* {{{ proto resource ibase_trans([int trans_args [, resource link_identifier [, ... ], int trans_args [, resource link_identifier [, ... ]] [, ...]]]) Start a transaction over one or several databases */ #define TPB_MAX_SIZE (8*sizeof(char)) PHP_FUNCTION(ibase_trans) { unsigned short i, link_cnt = 0, tpb_len = 0; int argn; char last_tpb[TPB_MAX_SIZE]; ibase_db_link **ib_link = NULL; ibase_trans *ib_trans; isc_tr_handle tr_handle = NULL; ISC_STATUS result; RESET_ERRMSG; argn = ZEND_NUM_ARGS(); /* (1+argn) is an upper bound for the number of links this trans connects to */ ib_link = (ibase_db_link **) safe_emalloc(sizeof(ibase_db_link *),1+argn,0); if (argn > 0) { long trans_argl = 0; char *tpb; ISC_TEB *teb; zval ***args = NULL; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &args, &argn) == FAILURE) { efree(args); efree(ib_link); RETURN_FALSE; } teb = (ISC_TEB *) safe_emalloc(sizeof(ISC_TEB),argn,0); tpb = (char *) safe_emalloc(TPB_MAX_SIZE,argn,0); /* enumerate all the arguments: assume every non-resource argument specifies modifiers for the link ids that follow it */ for (i = 0; i < argn; ++i) { if (Z_TYPE_PP(args[i]) == IS_RESOURCE) { if (!ZEND_FETCH_RESOURCE2_NO_RETURN(ib_link[link_cnt], ibase_db_link *, args[i], -1, LE_LINK, le_link, le_plink)) { efree(teb); efree(tpb); efree(ib_link); efree(args); RETURN_FALSE; } /* copy the most recent modifier string into tbp[] */ memcpy(&tpb[TPB_MAX_SIZE * link_cnt], last_tpb, TPB_MAX_SIZE); /* add a database handle to the TEB with the most recently specified set of modifiers */ teb[link_cnt].db_ptr = &ib_link[link_cnt]->handle; teb[link_cnt].tpb_len = tpb_len; teb[link_cnt].tpb_ptr = &tpb[TPB_MAX_SIZE * link_cnt]; ++link_cnt; } else { tpb_len = 0; convert_to_long_ex(args[i]); trans_argl = Z_LVAL_PP(args[i]); if (trans_argl != PHP_IBASE_DEFAULT) { last_tpb[tpb_len++] = isc_tpb_version3; /* access mode */ if (PHP_IBASE_READ == (trans_argl & PHP_IBASE_READ)) { last_tpb[tpb_len++] = isc_tpb_read; } else if (PHP_IBASE_WRITE == (trans_argl & PHP_IBASE_WRITE)) { last_tpb[tpb_len++] = isc_tpb_write; } /* isolation level */ if (PHP_IBASE_COMMITTED == (trans_argl & PHP_IBASE_COMMITTED)) { last_tpb[tpb_len++] = isc_tpb_read_committed; if (PHP_IBASE_REC_VERSION == (trans_argl & PHP_IBASE_REC_VERSION)) { last_tpb[tpb_len++] = isc_tpb_rec_version; } else if (PHP_IBASE_REC_NO_VERSION == (trans_argl & PHP_IBASE_REC_NO_VERSION)) { last_tpb[tpb_len++] = isc_tpb_no_rec_version; } } else if (PHP_IBASE_CONSISTENCY == (trans_argl & PHP_IBASE_CONSISTENCY)) { last_tpb[tpb_len++] = isc_tpb_consistency; } else if (PHP_IBASE_CONCURRENCY == (trans_argl & PHP_IBASE_CONCURRENCY)) { last_tpb[tpb_len++] = isc_tpb_concurrency; } /* lock resolution */ if (PHP_IBASE_NOWAIT == (trans_argl & PHP_IBASE_NOWAIT)) { last_tpb[tpb_len++] = isc_tpb_nowait; } else if (PHP_IBASE_WAIT == (trans_argl & PHP_IBASE_WAIT)) { last_tpb[tpb_len++] = isc_tpb_wait; } } } } if (link_cnt > 0) { result = isc_start_multiple(IB_STATUS, &tr_handle, link_cnt, teb); } efree(args); efree(tpb); efree(teb); } if (link_cnt == 0) { link_cnt = 1; if (!ZEND_FETCH_RESOURCE2_NO_RETURN(ib_link[0], ibase_db_link *, NULL, IBG(default_link), LE_LINK, le_link, le_plink)) { efree(ib_link); RETURN_FALSE; } result = isc_start_transaction(IB_STATUS, &tr_handle, 1, &ib_link[0]->handle, tpb_len, last_tpb); } /* start the transaction */ if (result) { _php_ibase_error(TSRMLS_C); efree(ib_link); RETURN_FALSE; } /* register the transaction in our own data structures */ ib_trans = (ibase_trans *) safe_emalloc(link_cnt-1, sizeof(ibase_db_link *), sizeof(ibase_trans)); ib_trans->handle = tr_handle; ib_trans->link_cnt = link_cnt; ib_trans->affected_rows = 0; for (i = 0; i < link_cnt; ++i) { ibase_tr_list **l; ib_trans->db_link[i] = ib_link[i]; /* the first item in the connection-transaction list is reserved for the default transaction */ if (ib_link[i]->tr_list == NULL) { ib_link[i]->tr_list = (ibase_tr_list *) emalloc(sizeof(ibase_tr_list)); ib_link[i]->tr_list->trans = NULL; ib_link[i]->tr_list->next = NULL; } /* link the transaction into the connection-transaction list */ for (l = &ib_link[i]->tr_list; *l != NULL; l = &(*l)->next); *l = (ibase_tr_list *) emalloc(sizeof(ibase_tr_list)); (*l)->trans = ib_trans; (*l)->next = NULL; } efree(ib_link); ZEND_REGISTER_RESOURCE(return_value, ib_trans, le_trans); } /* }}} */ int _php_ibase_def_trans(ibase_db_link *ib_link, ibase_trans **trans TSRMLS_DC) /* {{{ */ { if (ib_link == NULL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid database link"); return FAILURE; } /* the first item in the connection-transaction list is reserved for the default transaction */ if (ib_link->tr_list == NULL) { ib_link->tr_list = (ibase_tr_list *) emalloc(sizeof(ibase_tr_list)); ib_link->tr_list->trans = NULL; ib_link->tr_list->next = NULL; } if (*trans == NULL) { ibase_trans *tr = ib_link->tr_list->trans; if (tr == NULL) { tr = (ibase_trans *) emalloc(sizeof(ibase_trans)); tr->handle = NULL; tr->link_cnt = 1; tr->affected_rows = 0; tr->db_link[0] = ib_link; ib_link->tr_list->trans = tr; } if (tr->handle == NULL) { if (isc_start_transaction(IB_STATUS, &tr->handle, 1, &ib_link->handle, 0, NULL)) { _php_ibase_error(TSRMLS_C); return FAILURE; } } *trans = tr; } return SUCCESS; } /* }}} */ static void _php_ibase_trans_end(INTERNAL_FUNCTION_PARAMETERS, int commit) /* {{{ */ { ibase_trans *trans = NULL; int res_id = 0; ISC_STATUS result; ibase_db_link *ib_link; zval *arg = NULL; int type; RESET_ERRMSG; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|r", &arg) == FAILURE) { return; } if (ZEND_NUM_ARGS() == 0) { ZEND_FETCH_RESOURCE2(ib_link, ibase_db_link *, NULL, IBG(default_link), LE_LINK, le_link, le_plink); if (ib_link->tr_list == NULL || ib_link->tr_list->trans == NULL) { /* this link doesn't have a default transaction */ _php_ibase_module_error("Default link has no default transaction" TSRMLS_CC); RETURN_FALSE; } trans = ib_link->tr_list->trans; } else { /* one id was passed, could be db or trans id */ if (zend_list_find(Z_RESVAL_P(arg), &type) && type == le_trans) { ZEND_FETCH_RESOURCE(trans, ibase_trans *, &arg, -1, LE_TRANS, le_trans); res_id = Z_RESVAL_P(arg); } else { ZEND_FETCH_RESOURCE2(ib_link, ibase_db_link *, &arg, -1, LE_LINK, le_link, le_plink); if (ib_link->tr_list == NULL || ib_link->tr_list->trans == NULL) { /* this link doesn't have a default transaction */ _php_ibase_module_error("Link has no default transaction" TSRMLS_CC); RETURN_FALSE; } trans = ib_link->tr_list->trans; } } switch (commit) { default: /* == case ROLLBACK: */ result = isc_rollback_transaction(IB_STATUS, &trans->handle); break; case COMMIT: result = isc_commit_transaction(IB_STATUS, &trans->handle); break; case (ROLLBACK | RETAIN): result = isc_rollback_retaining(IB_STATUS, &trans->handle); break; case (COMMIT | RETAIN): result = isc_commit_retaining(IB_STATUS, &trans->handle); break; } if (result) { _php_ibase_error(TSRMLS_C); RETURN_FALSE; } /* Don't try to destroy implicitly opened transaction from list... */ if ((commit & RETAIN) == 0 && res_id != 0) { zend_list_delete(res_id); } RETURN_TRUE; } /* }}} */ /* {{{ proto bool ibase_commit( resource link_identifier ) Commit transaction */ PHP_FUNCTION(ibase_commit) { _php_ibase_trans_end(INTERNAL_FUNCTION_PARAM_PASSTHRU, COMMIT); } /* }}} */ /* {{{ proto bool ibase_rollback( resource link_identifier ) Rollback transaction */ PHP_FUNCTION(ibase_rollback) { _php_ibase_trans_end(INTERNAL_FUNCTION_PARAM_PASSTHRU, ROLLBACK); } /* }}} */ /* {{{ proto bool ibase_commit_ret( resource link_identifier ) Commit transaction and retain the transaction context */ PHP_FUNCTION(ibase_commit_ret) { _php_ibase_trans_end(INTERNAL_FUNCTION_PARAM_PASSTHRU, COMMIT | RETAIN); } /* }}} */ /* {{{ proto bool ibase_rollback_ret( resource link_identifier ) Rollback transaction and retain the transaction context */ PHP_FUNCTION(ibase_rollback_ret) { _php_ibase_trans_end(INTERNAL_FUNCTION_PARAM_PASSTHRU, ROLLBACK | RETAIN); } /* }}} */ /* {{{ proto int ibase_gen_id(string generator [, int increment [, resource link_identifier ]]) Increments the named generator and returns its new value */ PHP_FUNCTION(ibase_gen_id) { zval *link = NULL; char query[128], *generator; int gen_len; long inc = 1; ibase_db_link *ib_link; ibase_trans *trans = NULL; XSQLDA out_sqlda; ISC_INT64 result; RESET_ERRMSG; if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lr", &generator, &gen_len, &inc, &link)) { RETURN_FALSE; } if (gen_len > 31) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid generator name"); RETURN_FALSE; } PHP_IBASE_LINK_TRANS(link, ib_link, trans); snprintf(query, sizeof(query), "SELECT GEN_ID(%s,%ld) FROM rdb$database", generator, inc); /* allocate a minimal descriptor area */ out_sqlda.sqln = out_sqlda.sqld = 1; out_sqlda.version = SQLDA_CURRENT_VERSION; /* allocate the field for the result */ out_sqlda.sqlvar[0].sqltype = SQL_INT64; out_sqlda.sqlvar[0].sqlscale = 0; out_sqlda.sqlvar[0].sqllen = sizeof(result); out_sqlda.sqlvar[0].sqldata = (void*) &result; /* execute the query */ if (isc_dsql_exec_immed2(IB_STATUS, &ib_link->handle, &trans->handle, 0, query, SQL_DIALECT_CURRENT, NULL, &out_sqlda)) { _php_ibase_error(TSRMLS_C); RETURN_FALSE; } /* don't return the generator value as a string unless it doesn't fit in a long */ #if SIZEOF_LONG < 8 if (result < LONG_MIN || result > LONG_MAX) { char *res; int l; l = spprintf(&res, 0, "%" LL_MASK "d", result); RETURN_STRINGL(res, l, 0); } #endif RETURN_LONG((long)result); } /* }}} */ #endif /* HAVE_IBASE */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: sw=4 ts=4 fdm=marker * vim<600: sw=4 ts=4 */