adodb-504/0000755000175000017500000000000010642245331012247 5ustar raphaelraphaeladodb-504/test-adodb.php0000644000175000017500000000120107636431022015003 0ustar raphaelraphaelConnect($server,$user,$pwd,$database); $rs = $db->Execute('select productname,unitsinstock from products'); while (!$rs->EOF) { print_r($rs->fields); print "
"; adodb_movenext($rs); ## ADODB extension function } $rs->Close(); echo '
'; $rs = $db->Execute("select productname, unitsinstock from products where productid < 5"); $arr = adodb_getall($rs); ## ADOdb extension function echo '
'; print_r($arr); echo '
'; ?> adodb-504/config.m40000644000175000017500000000363107636425546014002 0ustar raphaelraphaeldnl $Id$ dnl config.m4 for extension adodb dnl Comments in this file start with the string 'dnl'. dnl Remove where necessary. This file will not work dnl without editing. dnl If your extension references something external, use with: dnl PHP_ARG_WITH(adodb, for adodb support, dnl Make sure that the comment is aligned: dnl [ --with-adodb Include adodb support]) dnl Otherwise use enable: PHP_ARG_ENABLE(adodb, whether to enable adodb support, [ --enable-adodb Enable adodb support]) if test "$PHP_ADODB" != "no"; then dnl Write more examples of tests here... dnl # --with-adodb -> check with-path dnl SEARCH_PATH="/usr/local /usr" # you might want to change this dnl SEARCH_FOR="/include/adodb.h" # you most likely want to change this dnl if test -r $PHP_ADODB/; then # path given as parameter dnl ADODB_DIR=$PHP_ADODB dnl else # search default path list dnl AC_MSG_CHECKING([for adodb files in default path]) dnl for i in $SEARCH_PATH ; do dnl if test -r $i/$SEARCH_FOR; then dnl ADODB_DIR=$i dnl AC_MSG_RESULT(found in $i) dnl fi dnl done dnl fi dnl dnl if test -z "$ADODB_DIR"; then dnl AC_MSG_RESULT([not found]) dnl AC_MSG_ERROR([Please reinstall the adodb distribution]) dnl fi dnl # --with-adodb -> add include path dnl PHP_ADD_INCLUDE($ADODB_DIR/include) dnl # --with-adodb -> chech for lib and symbol presence dnl LIBNAME=adodb # you may want to change this dnl LIBSYMBOL=adodb # you most likely want to change this dnl PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL, dnl [ dnl PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $ADODB_DIR/lib, ADODB_SHARED_LIBADD) dnl AC_DEFINE(HAVE_ADODBLIB,1,[ ]) dnl ],[ dnl AC_MSG_ERROR([wrong adodb lib version or lib not found]) dnl ],[ dnl -L$ADODB_DIR/lib -lm -ldl dnl ]) dnl dnl PHP_SUBST(ADODB_SHARED_LIBADD) PHP_NEW_EXTENSION(adodb, adodb.c, $ext_shared) fi adodb-504/README.txt0000644000175000017500000000604210341743634013754 0ustar raphaelraphael Now compatible with PHP5 and PHP4. Links ===== D'load: http://adodb.sourceforge.net/ Forum: http://phplens.com/lens/lensforum/topics.php?id=4 The ADODB Extension =================== This extension requires the ADOdb classes to be used for data access. When ADOdb detects the constant ADODB_EXTENSION is set, it will use the extension to perform the following speedups: 1. Emulation of recordcount is substantially faster. Up to 75% faster for oracle oci8 for example. This does not help mysql or postgresql as both databases support native record- count. Recordcount emulation occurs for every SELECT statement when $ADODB_COUNTRECS = true, so Oracle, Sybase, Informix, MSSQL, Access, and many ODBC/ADO database drivers will get a big boost in speed. 2. The $rs->Move($offset) function is faster for databases that do not provide a native seek function on the recordset. 3. $rs->GetArray() will use the highly optimized adodb_getall() function. You can directly call adodb extension functions: 1. function adodb_getall($rs) Returns a 2D array containing all records in recordset from current record position. 2. function adodb_movenext($rs) Equivalent to $rs->MoveNext(). The constant ADODB_EXTENSION will contain the version number of the extension, which should be 3.32 or later. 3.32 Initial Release 4.00 Recompiled without debugging (oops!). LICENSE ======= BSD-style. (c) 2003-2005 John Lim. All rights reserved. TESTS ===== I have stress tested this with ab -n1000 -c20 http://server/php/test-adodb.php with satisfactory results. The test php file is included in this release. WINDOWS ======= This release should come with a pre-compiled version of adodb. See the appropriate php-win-$version directory for php_adodb.dll. You will need to copy it to your extension directory and modify php.ini. For PHP4, add to php.ini: extension=php_adodb.dll For PHP5, add to php.ini: extension=adodb.dll If you have Visual C++ 6.0, you can open the project file adodb.dsp and compile adodb yourself on windows. Use the Release_TS version. UNIX ==== To compile under *NIX as an .so extension 1. Go to adodb directory 2. Run phpize from the command-line (the $ is the prompt). If phpize is missing, then you probably do not have the development version of php installed. Download and install php from php.net. Then the following should work: $ phpize This will create the appropriate configuration files. 3. You might get some warning messages to run aclocal. I'm not sure about this, so run aclocal anyway. 4. Now run configure with $ ./configure 5. Then compile files to create ./modules/adodb.so $ make 6. Then install in extensions directory with $ make install 7. You can either dynamicly load with dl('adodb.so'); or add it to your php.ini with extension=adodb.so 8. Have a look at the test scripts to see what you can do with the adodb extension. adodb-504/CREDITS0000644000175000017500000000001707636432266013303 0ustar raphaelraphaeladodb John Lim adodb-504/EXPERIMENTAL0000644000175000017500000000000007636425700014066 0ustar raphaelraphaeladodb-504/adodb.c0000644000175000017500000003643710341740730013500 0ustar raphaelraphael/* ADOdb Extension for PHP (c) 2003-2005 John Lim. All rights reserved Licensed under BSD-style license. Set tabs to 4 for best viewing. We implement two high speed helper functions for ADOdb: adodb_movenext() and adodb_getall() Usage: $rs = $db->Execute($sql); while (!$rs->EOF) { print_r($rs->fields); adodb_movenext($rs); # this is 100% C code! } $rs = $db->Execute($sql); $array2d = adodb_getall($rs); # more vitamin C This code requires ADOdb 3.30 or higher. We replace _fetch for mysql, oci8 and postgresql with our own C implementations. CHANGELOG 5.04 Fixed problem with mysqli 5.03 Added support for PHP 4.4 and 5.1. Added thread safety to adodb_compile_params(). Means that this dll was not thread-safe previously for PHP 5 :-( 5.02 Added support for PHP 5.0.3 5.00 24 July 2004 Added php5 compat. 4.00 16 Nov 2003 Added more constant definitions 3.32 18 March 2002 Stack corruption bug in adodb_movenext fixed. 3.31 First release NOTES #define IS_NULL 0 #define IS_LONG 1 #define IS_DOUBLE 2 #define IS_STRING 3 #define IS_ARRAY 4 #define IS_OBJECT 5 #define IS_BOOL 6 #define IS_RESOURCE 7 #define IS_CONSTANT 8 #define IS_CONSTANT_ARRAY 9 */ #define ADODB_MAXPARAMS 8 #define COMPILE_DL_ADODB 1 #ifdef WIN32 #define ZEND_DEBUG 0 #define ZTS 1 #define ZEND_WIN32 1 #define PHP_WIN32 1 #endif #include "php.h" #include "ext/standard/info.h" /* define('ADODB_FETCH_DEFAULT',0); define('ADODB_FETCH_NUM',1); define('ADODB_FETCH_ASSOC',2); define('ADODB_FETCH_BOTH',3); */ #define ADODB_EXTENSION 5.04 /* All the functions that will be exported (available) must be declared */ ZEND_FUNCTION(adodb_movenext); ZEND_FUNCTION(adodb_getall); PHP_MINFO_FUNCTION(adodb); PHP_MINIT_FUNCTION(adodb); #if defined(BYREF_FORCE) /* PHP 4 */ unsigned char adodb_byref[] = {1,BYREF_FORCE}; /* function list so that the Zend engine will know whatÂ’s here */ zend_function_entry adodb_functions[] = { ZEND_FE(adodb_movenext, adodb_byref) ZEND_FE(adodb_getall, adodb_byref) {NULL, NULL, NULL} }; #else /* PHP 5 */ function_entry adodb_functions[] = { PHP_FE(adodb_movenext,NULL) PHP_FE(adodb_getall,NULL) {NULL, NULL, NULL} }; #endif /* module information */ zend_module_entry adodb_module_entry = { STANDARD_MODULE_HEADER, "ADOdb", adodb_functions, PHP_MINIT(adodb), NULL, NULL, NULL, PHP_MINFO(adodb), NO_VERSION_YET, STANDARD_MODULE_PROPERTIES }; #if COMPILE_DL_ADODB ZEND_GET_MODULE(adodb) #endif PHP_MINFO_FUNCTION(adodb) { char vers[32]; sprintf(vers,"%4.2f", (float) ADODB_EXTENSION); php_info_print_table_start(); php_info_print_table_row(2, "Info", "Extension requires ADOdb classes"); php_info_print_table_row(2, "Download", "http://php.weblogs.com/adodb"); php_info_print_table_row(2, "API Version", vers); php_info_print_table_end(); } #define REGISTER_DBL_CONSTANT(__c) REGISTER_DOUBLE_CONSTANT(#__c, __c, CONST_CS | CONST_PERSISTENT) #define REGISTER_LNG_CONSTANT(__c) REGISTER_LONG_CONSTANT(#__c, __c, CONST_CS | CONST_PERSISTENT) #define REGISTER_STR_CONSTANT(__c) REGISTER_STRING_CONSTANT(#__c, __c, CONST_CS | CONST_PERSISTENT) static zval adodb_zvals[5]; #define zval_fetch 0 #define zval_ocifetch 1 #define zval_mysqlfetch 2 #define zval_pgfetch 3 static void adodb_init_zval(zval *v, char *s) { v->type = IS_STRING; v->value.str.val = s; v->value.str.len = strlen(s); v->is_ref = 0; v->refcount = 1; } /* {{{ PHP_MINIT_FUNCTION */ PHP_MINIT_FUNCTION(adodb) { long ADODB_PHPVER; int a,b,c; a = sizeof(zval); sscanf(PHP_VERSION,"%d.%d.%d",&a,&b,&c); ADODB_PHPVER = (a << 12) & 0xffff; ADODB_PHPVER += (b << 8) & 0xfff; ADODB_PHPVER += (c << 4) & 0xff; REGISTER_DBL_CONSTANT(ADODB_EXTENSION); #define ADODB_FETCH_DEFAULT 0 #define ADODB_FETCH_NUM 1 #define ADODB_FETCH_ASSOC 2 #define ADODB_FETCH_BOTH 3 #define TIMESTAMP_FIRST_YEAR 100 #define ADODB_PREFETCH_ROWS 10 REGISTER_LNG_CONSTANT(ADODB_FETCH_DEFAULT); REGISTER_LNG_CONSTANT(ADODB_FETCH_NUM); REGISTER_LNG_CONSTANT(ADODB_FETCH_ASSOC); REGISTER_LNG_CONSTANT(ADODB_FETCH_BOTH); REGISTER_LNG_CONSTANT(ADODB_PHPVER); REGISTER_LNG_CONSTANT(TIMESTAMP_FIRST_YEAR); REGISTER_LNG_CONSTANT(ADODB_PREFETCH_ROWS); REGISTER_STRING_CONSTANT("ADODB_TABLE_REGEX", "([]0-9a-z_\\`\\.\\@\\[-]*)", CONST_CS | CONST_PERSISTENT); REGISTER_STRING_CONSTANT("ADODB_BAD_RS", "

Bad $rs in %s. Connection or SQL invalid. Try using $connection->debug=true;

", CONST_CS | CONST_PERSISTENT); adodb_init_zval(&adodb_zvals[zval_fetch],"_fetch"); adodb_init_zval(&adodb_zvals[zval_mysqlfetch],"mysql_fetch_array"); adodb_init_zval(&adodb_zvals[zval_pgfetch],"pg_fetch_array"); adodb_init_zval(&adodb_zvals[zval_ocifetch],"ocifetchinto"); return SUCCESS; } /* Setup params to maximize speed of adodb_call_fetch. */ static int adodb_compile_params(char * dbType, zval **rs, zval ***params TSRMLS_DC) { zend_hash_find(Z_OBJPROP_P(*rs), "fields", sizeof("fields"), (void **) ¶ms[0]); if (params[0] == NULL) return -1; if (strncmp(dbType,"mysql",5) == 0 && strncmp(dbType,"mysqli",6) != 0) { zend_hash_find(Z_OBJPROP_P(*rs), "_queryID", sizeof("_queryID"), (void **) ¶ms[1]); zend_hash_find(Z_OBJPROP_P(*rs), "fetchMode", sizeof("fetchMode"), (void **) ¶ms[2]); if (params[1] == NULL || params[2] == NULL) return -1; return zval_mysqlfetch; } if (strncmp(dbType,"oci8",4) == 0) { if (strlen(dbType) == 4) { zend_hash_find(Z_OBJPROP_P(*rs), "_queryID", sizeof("_queryID"), (void **) ¶ms[1]); params[2] = params[0]; zend_hash_find(Z_OBJPROP_P(*rs), "fetchMode", sizeof("fetchMode"), (void **) ¶ms[3]); if (params[1] == NULL || params[3] == NULL) return -1; return zval_ocifetch; } else { return zval_fetch; } } if (strncmp(dbType,"postg",5) == 0) { zend_hash_find(Z_OBJPROP_P(*rs), "_queryID", sizeof("_queryID"), (void **) ¶ms[1]); zend_hash_find(Z_OBJPROP_P(*rs), "_currentRow", sizeof("_currentRow"), (void **) ¶ms[2]); zend_hash_find(Z_OBJPROP_P(*rs), "fetchMode", sizeof("fetchMode"), (void **) ¶ms[3]); zend_hash_find(Z_OBJPROP_P(*rs), "_blobArr", sizeof("_blobArr"), (void **) ¶ms[4]); zend_hash_find(Z_OBJPROP_P(*rs), "_numOfRows", sizeof("_numOfRows"), (void **) ¶ms[5]); if (params[1] == NULL || params[2] == NULL || params[3] == NULL || params[4] == NULL|| params[5] == NULL) return -1; if (params[4] != NULL && Z_TYPE(**params[4]) != IS_NULL) return zval_fetch; /* we need to do blob fixup, call high-level _fetch */ return zval_pgfetch; } return zval_fetch; } /* Fetch a single row. Return error flag, 0 is ok, 1 is error */ static long adodb_call_fetch(zval **rs, int type, zval ***params TSRMLS_DC) { zval *retval = NULL; long error; unsigned long save_error_reporting; zval **fields; #if !defined(BYREF_FORCE) zend_fcall_info fci; fci.size = sizeof(fci); fci.function_table = EG(function_table); fci.function_name = &adodb_zvals[zval_ocifetch]; fci.symbol_table = NULL; fci.object_pp = NULL; fci.retval_ptr_ptr = &retval; fci.param_count = 2; fci.params = ¶ms[1]; fci.no_separation = 0; #endif fields = params[0]; /* We special case oci8, postgresql, mysql for further tuning... */ /*-------- oci8 */ switch(type) { case zval_ocifetch: error = call_user_function_ex(EG(function_table), NULL, &adodb_zvals[zval_ocifetch], &retval, 3, ¶ms[1], 0, NULL TSRMLS_CC); if (error) { /* convert_to_boolean_ex(fields);*/ ZVAL_BOOL(*fields,0); error = 1; } else { /* convert_to_boolean_ex(&retval);*/ error = !Z_LVAL(*retval); } break; case zval_mysqlfetch: error = call_user_function_ex(EG(function_table), NULL, &adodb_zvals[zval_mysqlfetch], &retval, 2, ¶ms[1], 0, NULL TSRMLS_CC); if (error) { convert_to_boolean_ex(fields); ZVAL_BOOL(*fields,0); error = 1; } else { zval_add_ref(&retval); zval_ptr_dtor(fields); *fields = retval; if (Z_TYPE(**fields) == IS_BOOL ||Z_TYPE(**fields) == IS_NULL ) error = 1; else error = 0; } break; case zval_pgfetch: /* if ($this->_currentRow >= $this->_numOfRows && $this->_numOfRows >= 0) return false; */ if (Z_LVAL(**params[2]) >= Z_LVAL(**params[5]) && Z_LVAL(**params[5]) >= 0) { error = 1; break; } /* pg_fetch_array gives a warning message if currentRow is out of range */ save_error_reporting = EG(error_reporting); EG(error_reporting) &= ~E_WARNING; error = call_user_function_ex(EG(function_table), NULL, &adodb_zvals[zval_pgfetch], &retval, 3, ¶ms[1], 0, NULL TSRMLS_CC); EG(error_reporting) = save_error_reporting; if (error) { convert_to_boolean_ex(fields); ZVAL_BOOL(*fields,0); error = 1; } else { zval_add_ref(&retval); zval_ptr_dtor(fields); *fields = retval; if (Z_TYPE(**fields) == IS_BOOL) error = 1; else error = 0; } break; default: error = call_user_function_ex(EG(function_table), rs, &adodb_zvals[zval_fetch], &retval, 0, NULL, 0, NULL TSRMLS_CC); ; if (error == FAILURE) { php_error(E_ERROR, "Unable to call _fetch\n"); error = 1; } else { error = !Z_LVAL(*retval); } break; } /*--------- // cleanup */ if (retval) { zval_ptr_dtor(&retval); } return error; } /* Fetch all records and store in returned 2-D array. Usage: $rs = $conn->Execute($sql); $array = adodb_getall($rs); Using this function, adodb benchmark was 0.73 secs vs. 1.38 secs using pure PHP. The more rows, the faster this will run compared to PHP code... Oci8 MoveNext test ADODB_COUNTRECS ADODB_EXTENSION Time (s) true false 1.99 true true 1.63 false false 1.38 false true 1.38 Oci8 ADOConnection::GetAll test true false 1.68 true true 1.33 false false 1.68 false true 1.33 */ ZEND_FUNCTION(adodb_getall) { zval **rs,**maxp; /* function parameters */ zval **eof = NULL; /* rs properties */ zval **currentRow = NULL, **dbType = NULL, **params[ADODB_MAXPARAMS]; zval *retval = NULL; /* return value from method */ long error,recs = 0, max = -1; int argc = ZEND_NUM_ARGS(); int type; if (!(0 < argc && argc <= 2)) { WRONG_PARAM_COUNT; return; } if (argc == 1) { if (zend_get_parameters_ex(1, &rs) == FAILURE) { RETVAL_FALSE; return; } } else if (argc == 2) { if (zend_get_parameters_ex(2, &rs, &maxp) == FAILURE) { RETVAL_FALSE; return; } convert_to_long_ex(maxp); max = Z_LVAL(**maxp); } if (Z_TYPE(**rs) != IS_OBJECT) { php_error(E_ERROR, "adodb_getall: parameter 1 is not an object\n"); RETVAL_FALSE; return; } zend_hash_find(Z_OBJPROP_P(*rs), "databaseType", sizeof("databaseType"), (void **)&dbType); if (dbType == NULL) { php_error(E_WARNING,"adodb_getall: The property databaseType is undefined"); RETVAL_FALSE; return; } if (max < 0 && strncmp(Z_STRVAL(**dbType),"array",5) == 0) { zval **array; /* Optimize array recordset access, as internally it is already an array */ /* WARNING: does not support skiprow1 feature */ zend_hash_find(Z_OBJPROP_P(*rs), "_array", sizeof("_array"), (void **)&array); if (array) { zval_add_ref(array); zval_ptr_dtor(&return_value); return_value = *array; return; } } /* Compile parameters so no further hash lookups required */ type = adodb_compile_params(Z_STRVAL(**dbType),rs, (zval ***)¶ms TSRMLS_CC); if (type == -1) { php_error(E_WARNING,"adodb_getall: (Invalid recordset object"); RETVAL_FALSE; return; } zend_hash_find(Z_OBJPROP_P(*rs), "_currentRow", sizeof("_currentRow"), (void **)¤tRow); zend_hash_find(Z_OBJPROP_P(*rs), "EOF", sizeof("EOF"), (void **)&eof); if (eof == NULL || currentRow == NULL) { php_error(E_WARNING,"adodb_getall: invalid recordset object"); RETVAL_FALSE; return; } /* While not EOF, suck in the records */ array_init(return_value); while (!Z_LVAL(**eof) && recs != max) { recs += 1; zval_add_ref(params[0]); Z_LVAL(**currentRow) += 1; /* no diffenece in speed using this: zend_hash_index_update(Z_ARRVAL_P(return_value), Z_LVAL(**currentRow), params[0], sizeof(zval *), NULL); */ add_next_index_zval(return_value,*params[0]); error = adodb_call_fetch(rs, type, (zval***) ¶ms TSRMLS_CC); ZVAL_BOOL(*eof,error ? 1 : 0); } } /* Move internal cursor to next record, and populate $rs->fields. Returns true if ok, false if error or EOF. Usage: $rs = $connection->Execute($sql); while (!$rs->EOF) { print_r($rs->fields); adodb_movenext($rs); } Timings: 0.91 PHP MoveNext calls adodb_movenext internally -------------------------------------------------------------------- 0.89 PHP MoveNext calls original PHP code - this is the baseline -------------------------------------------------------------------- 0.84 adodb_movenext (no mysql_fetch_array()) -- 6% speedup from baseline 0.70 adodb_movenext with mysql_fetch_array -- 27% speedup from baseline 0.63 native mysql */ ZEND_FUNCTION(adodb_movenext) { zval **rs,**dbType; zval **eof = NULL,**currentRow = NULL, **fields = NULL; long error = SUCCESS; int argc = ZEND_NUM_ARGS(); zval **params[ADODB_MAXPARAMS]; int type; if (argc != 1) { WRONG_PARAM_COUNT; return; } if (zend_get_parameters_ex(1, &rs) == FAILURE) { RETVAL_FALSE; return; } if (Z_TYPE(**rs) != IS_OBJECT) { php_error(E_ERROR, "adodb_movenext: parameter 1 is not an object\n"); RETVAL_FALSE; return; } /* EOF */ zend_hash_find(Z_OBJPROP_P(*rs), "EOF", sizeof("EOF"), (void **)&eof); if (eof == NULL) { php_error(E_ERROR, "adodb_movenext: The property EOF is undefined\n"); RETVAL_FALSE; return; } if (Z_LVAL(**eof)) { RETVAL_FALSE; return; } /* _currentRow */ zend_hash_find(Z_OBJPROP_P(*rs), "_currentRow", sizeof("_currentRow"), (void **)¤tRow); if (currentRow == NULL) { php_error(E_ERROR, "adodb_movenext: The property _currentRow is undefined\n"); RETVAL_FALSE; return; } Z_LVAL(**currentRow) += 1; zend_hash_find(Z_OBJPROP_P(*rs), "databaseType", sizeof("databaseType"), (void **)&dbType); if (dbType == NULL) { php_error(E_WARNING,"adodb_movenext: The property databaseType is undefined"); RETVAL_FALSE; return; } type = adodb_compile_params(Z_STRVAL(**dbType),rs, (zval ***)¶ms TSRMLS_CC); if (type == -1) { php_error(E_WARNING,"adodb_movenext: Invalid recordset object"); RETVAL_FALSE; } /* OK, we fetch the field now... */ error = adodb_call_fetch(rs, type, (zval***)¶ms TSRMLS_CC); ZVAL_BOOL(*eof,error ? 1 : 0); if (Z_LVAL(**eof)) { RETVAL_FALSE; } else { RETVAL_TRUE; } }