]> granicus.if.org Git - php/commitdiff
Added dbx module (database abstraction) to the repositorty (/ext/dbx).
authorMarc Boeren <mboeren@php.net>
Thu, 22 Mar 2001 11:07:04 +0000 (11:07 +0000)
committerMarc Boeren <mboeren@php.net>
Thu, 22 Mar 2001 11:07:04 +0000 (11:07 +0000)
Compiles under Linux (--enable-dbx) and Windows.
Supports MySQL and ODBC modules (more to be added later).
@ Added dbx module (database abstraction) to the repository. (Marc)

13 files changed:
ext/dbx/CREDITS [new file with mode: 0644]
ext/dbx/INSTALL [new file with mode: 0644]
ext/dbx/LICENSE [new file with mode: 0644]
ext/dbx/Makefile.in [new file with mode: 0644]
ext/dbx/config.m4 [new file with mode: 0644]
ext/dbx/dbx.c [new file with mode: 0644]
ext/dbx/dbx.dsp [new file with mode: 0644]
ext/dbx/dbx.h [new file with mode: 0644]
ext/dbx/dbx_mysql.c [new file with mode: 0644]
ext/dbx/dbx_mysql.h [new file with mode: 0644]
ext/dbx/dbx_odbc.c [new file with mode: 0644]
ext/dbx/dbx_odbc.h [new file with mode: 0644]
ext/dbx/php_dbx.h [new file with mode: 0644]

diff --git a/ext/dbx/CREDITS b/ext/dbx/CREDITS
new file mode 100644 (file)
index 0000000..57d1fa5
--- /dev/null
@@ -0,0 +1,2 @@
+dbx
+Marc Boeren
diff --git a/ext/dbx/INSTALL b/ext/dbx/INSTALL
new file mode 100644 (file)
index 0000000..99ba67c
--- /dev/null
@@ -0,0 +1,25 @@
+
+If you downloaded this separately, you can place the dbx folder 
+in the php-source-folders under the ext/folder. Be sure to 
+use buildconf to rebuild the configure script.
+
+Linux:
+
+Compile php with the --enable-dbx switch
+
+Windows:
+
+This should set all includepaths to the right 
+relative folders. Open the .dsp and compile. You could also
+add this project to the php_modules project.
+It generates a php_dbx.dll in your extensions folder, and you
+must enable it in your php.ini file.
+
+
+When you run phpinfo(), dbx-support should be visible in the
+resulting table.
+
+Good luck and enjoy!
+
+Marc Boeren
+march 16th, 2001
diff --git a/ext/dbx/LICENSE b/ext/dbx/LICENSE
new file mode 100644 (file)
index 0000000..a784d4f
--- /dev/null
@@ -0,0 +1,71 @@
+-------------------------------------------------------------------- 
+                  The DBX License, version 0.01
+Copyright (c) 2001 Guidance bv. All rights reserved.
+-------------------------------------------------------------------- 
+
+Redistribution and use in source and binary forms, with or without
+modification, is permitted provided that the following conditions
+are met:
+
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer. 
+  2. Redistributions in binary form must reproduce the above 
+     copyright notice, this list of conditions and the following 
+     disclaimer in the documentation and/or other materials provided
+     with the distribution.
+  3. The name "DBX" must not be used to endorse or promote products 
+     derived from this software without prior permission from 
+     Guidance bv.  This does not apply to add-on libraries or tools
+     that work in conjunction with DBX.  In such a case the DBX
+     name may be used to indicate that the product supports DBX.
+  4. Guidance bv may publish revised and/or new versions of the
+     license from time to time. Each version will be given a
+     distinguishing version number.
+     Once covered code has been published under a particular version
+     of the license, you may always continue to use it under the
+     terms of that version. You may also choose to use such covered
+     code under the terms of any subsequent version of the license
+     published by Guidance bv. No one other than Guidance bv has
+     the right to modify the terms applicable to covered code created
+     under this License.
+
+  5. Redistributions of any form whatsoever must retain the following
+     acknowledgment:
+     "This product includes DBX, freely available from
+     http://www.guidance.nl/dbx".
+
+  6. The software is an add-on to PHP, which is freely available from 
+     http://www.php.net. Be sure to read their license as well.
+
+
+THIS SOFTWARE IS PROVIDED BY GUIDANCE BV ``AS IS'' AND 
+ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 
+PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL GUIDANCE BV
+ OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-------------------------------------------------------------------- 
+
+Guidance bv can be contacted via Email at m.boeren@guidance.nl.
+
+For more information on Guidance bv and the DBX project, 
+please see <http://www.guidance.nl>.
+
+The software is an add-on to the PHP project, whihc consists of 
+voluntary contributions made by many individuals on behalf of the 
+PHP Group.
+
+The PHP Group can be contacted via Email at group@php.net.
+
+For more information on the PHP Group and the PHP project, 
+please see <http://www.php.net>.
diff --git a/ext/dbx/Makefile.in b/ext/dbx/Makefile.in
new file mode 100644 (file)
index 0000000..8f40151
--- /dev/null
@@ -0,0 +1,6 @@
+
+LTLIBRARY_NAME = libdbx.la
+LTLIBRARY_SOURCES = dbx.c dbx_mysql.c dbx_odbc.c
+LTLIBRARY_SHARED_NAME = dbx.la
+
+include $(top_srcdir)/build/dynlib.mk
diff --git a/ext/dbx/config.m4 b/ext/dbx/config.m4
new file mode 100644 (file)
index 0000000..5cf4885
--- /dev/null
@@ -0,0 +1,7 @@
+
+PHP_ARG_ENABLE(dbx,whether to enable dbx support,
+[  --enable-dbx            Enable dbx])
+
+if test "$PHP_DBX" != "no"; then
+  PHP_EXTENSION(dbx, $ext_shared)
+fi
diff --git a/ext/dbx/dbx.c b/ext/dbx/dbx.c
new file mode 100644 (file)
index 0000000..b99a9fc
--- /dev/null
@@ -0,0 +1,832 @@
+/*
+   +----------------------------------------------------------------------+
+   | stentor module version 1.0                                           |
+   +----------------------------------------------------------------------+
+   | Copyright (c) 2001 Guidance Rotterdam BV                             |
+   +----------------------------------------------------------------------+
+   | This source file is subject to version 1.0  of the STENTOR license,  |
+   | that is bundled with this package in the file LICENSE, and is        |
+   | available through the world-wide-web at                              |
+   | http://www.guidance.nl/php/dbx/license/1_00.txt.                     |
+   | If you did not receive a copy of the STENTOR license and are unable  |
+   | to obtain it through the world-wide-web, please send a note to       |
+   | license@guidance.nl so we can mail you a copy immediately.           |
+   +----------------------------------------------------------------------+
+   | Author : Marc Boeren         <marc@guidance.nl>                      |
+   +----------------------------------------------------------------------+
+ */
+
+#include "php.h"
+#include "php_ini.h"
+#include "php_config.h"
+#include "php_dbx.h"
+#include "ext/standard/info.h"
+
+// defines for supported databases
+#define DBX_UNKNOWN 0
+#define DBX_MYSQL 1
+#define DBX_ODBC 2
+// includes for supported databases
+#include "dbx.h"
+#include "dbx_mysql.h"
+#include "dbx_odbc.h"
+
+// support routines
+int module_exists(char * module_name) {
+    zend_module_entry * zme;
+    int r;
+    r = zend_hash_find(&module_registry, module_name, strlen(module_name)+1, (void **) &zme);
+    return r==0?1:0;
+    }
+
+int get_module_identifier(char * module_name) {
+    if (!strcmp("mysql", module_name)) return DBX_MYSQL;
+    if (!strcmp("odbc", module_name)) return DBX_ODBC;
+    return DBX_UNKNOWN;
+    }
+
+int split_dbx_handle_object(zval ** dbx_object, zval *** pdbx_handle, zval *** pdbx_module) {
+    convert_to_object_ex(dbx_object);
+    if (zend_hash_find((*dbx_object)->value.obj.properties, "handle", 7, (void **) pdbx_handle)==FAILURE || zend_hash_find((*dbx_object)->value.obj.properties, "module", 7, (void **) pdbx_module)==FAILURE) {
+        return 0;
+        }
+    return 1;
+    }
+
+// from dbx.h, to be used in support-files (dbx_mysql.c etc...)
+void dbx_call_any_function(INTERNAL_FUNCTION_PARAMETERS, char * function_name, zval ** returnvalue, int number_of_arguments, zval *** params) {
+    zval * zval_function_name;
+    MAKE_STD_ZVAL(zval_function_name);
+    ZVAL_STRING(zval_function_name, function_name, 1);
+    if (call_user_function_ex(EG(function_table), NULL, zval_function_name, returnvalue, number_of_arguments, params, 0, NULL) == FAILURE) {
+        zend_error(E_ERROR, "function '%s' not found", zval_function_name->value.str.val);
+        }
+    zval_dtor(zval_function_name); // to free stringvalue memory
+    FREE_ZVAL(zval_function_name);
+    }
+
+// switch_dbx functions declarations
+// each must be supported in the x/dbx_module files as dbx_module_function,
+//   e.g. switch_dbx_connect expects a dbx_mysql_connect in de x/dbx_mysql files
+//   all params except the dbx_module param are passed on
+// each must return the expected zval * 's in the rv parameter, which are passed on unmodified
+// do NOT use the return_value parameter from INTERNAL_FUNCTION_PARAMETERS
+// you can additionally return 0 or 1 for failure or success which will also be returned by the switches
+
+int switch_dbx_connect(zval ** rv, zval ** host, zval ** db, zval ** username, zval ** password, INTERNAL_FUNCTION_PARAMETERS, zval ** dbx_module);
+    // returns connection handle as resource on success or 0 as long on failure
+int switch_dbx_pconnect(zval ** rv, zval ** host, zval ** db, zval ** username, zval ** password, INTERNAL_FUNCTION_PARAMETERS, zval ** dbx_module);
+    // returns persistent connection handle as resource on success or 0 as long on failure
+int switch_dbx_close(zval ** rv, zval ** dbx_handle, INTERNAL_FUNCTION_PARAMETERS, zval ** dbx_module);
+    // returns 1 as long on success or 0 as long on failure
+int switch_dbx_query(zval ** rv, zval ** dbx_handle, zval ** sql_statement, INTERNAL_FUNCTION_PARAMETERS, zval ** dbx_module);
+    // returns 1 as long or result identifier as resource on success or 0 as long on failure
+int switch_dbx_getcolumncount(zval ** rv, zval ** result_handle, INTERNAL_FUNCTION_PARAMETERS, zval ** dbx_module);
+    // returns column-count as long on success or 0 as long on failure
+int switch_dbx_getcolumnname(zval ** rv, zval ** result_handle, long column_index, INTERNAL_FUNCTION_PARAMETERS, zval ** dbx_module);
+    // returns column-name as string on success or 0 as long on failure
+int switch_dbx_getcolumntype(zval ** rv, zval ** result_handle, long column_index, INTERNAL_FUNCTION_PARAMETERS, zval ** dbx_module);
+    // returns column-type as string on success or 0 as long on failure
+int switch_dbx_getrow(zval ** rv, zval ** result_handle, INTERNAL_FUNCTION_PARAMETERS, zval ** dbx_module);
+    // returns array[0..columncount-1] as strings on success or 0 as long on failure
+int switch_dbx_error(zval ** rv, zval ** dbx_handle, INTERNAL_FUNCTION_PARAMETERS, zval ** dbx_module);
+    // returns string
+
+/* If you declare any globals in php_dbx.h uncomment this: */
+//ZEND_DECLARE_MODULE_GLOBALS(dbx)
+/* True global resources - no need for thread safety here */
+static int le_dbx;
+
+/* Every user visible function must have an entry in dbx_functions[].
+*/
+function_entry dbx_functions[] = {
+    ZEND_FE(dbx_connect,       NULL)
+    ZEND_FE(dbx_close,         NULL)
+    ZEND_FE(dbx_query,         NULL)
+    ZEND_FE(dbx_error,     NULL)
+
+    ZEND_FE(dbx_sort,    NULL)
+    ZEND_FE(dbx_cmp_asc,    NULL)
+    ZEND_FE(dbx_cmp_desc,    NULL)
+
+    ZEND_FE(dbx_test,      NULL)
+
+       {NULL, NULL, NULL}      /* Must be the last line in dbx_functions[] */
+    };
+
+zend_module_entry dbx_module_entry = {
+       "dbx",
+    dbx_functions,
+    ZEND_MINIT(dbx),
+    ZEND_MSHUTDOWN(dbx),
+    NULL, /*ZEND_RINIT(dbx),           /* Replace with NULL if there's nothing to do at request start */
+       NULL, /*ZEND_RSHUTDOWN(dbx),    /* Replace with NULL if there's nothing to do at request end */
+       ZEND_MINFO(dbx),
+       STANDARD_MODULE_PROPERTIES
+    };
+
+#ifdef COMPILE_DL_DBX
+ZEND_GET_MODULE(dbx)
+#endif
+
+//ZEND_INI_BEGIN()
+//    ZEND_INI_ENTRY("dbx.defaulttype", "mysql", ZEND_INI_SYSTEM, NULL)
+//ZEND_INI_END()
+
+ZEND_MINIT_FUNCTION(dbx)
+{
+//    zend_dbx_globals *dbx_globals;
+//     ZEND_INIT_MODULE_GLOBALS(dbx, NULL, NULL);
+
+//     REGISTER_INI_ENTRIES();
+
+    REGISTER_LONG_CONSTANT("DBX_PERSISTENT", DBX_PERSISTENT, CONST_CS | CONST_PERSISTENT);
+    REGISTER_LONG_CONSTANT("DBX_RESULT_INFO", DBX_RESULT_INFO, CONST_CS | CONST_PERSISTENT);
+    REGISTER_LONG_CONSTANT("DBX_RESULT_INDEX", DBX_RESULT_INDEX, CONST_CS | CONST_PERSISTENT);
+    REGISTER_LONG_CONSTANT("DBX_RESULT_ASSOC", DBX_RESULT_ASSOC, CONST_CS | CONST_PERSISTENT);
+
+//    dbx_globals = ts_resource(dbx_globals_id);
+//    global_dbx_ctor(&DBXG(dbx_global)); 
+
+    return SUCCESS;
+    }
+
+ZEND_MSHUTDOWN_FUNCTION(dbx)
+{
+//    DBXLS_FETCH();
+//    global_dbx_dtor(&DBXG(dbx_global)); 
+
+//    UNREGISTER_INI_ENTRIES();
+       return SUCCESS;
+    }
+    
+/* Remove if there's nothing to do at request start */
+/*ZEND_RINIT_FUNCTION(dbx)
+{      return SUCCESS;
+}*/
+
+/* Remove if there's nothing to do at request end */
+/*ZEND_RSHUTDOWN_FUNCTION(dbx)
+{   return SUCCESS;
+}*/
+
+ZEND_MINFO_FUNCTION(dbx)
+{
+    php_info_print_table_start();
+    php_info_print_table_row(2, "dbx support", "enabled");
+    php_info_print_table_row(2, "dbx support for MySQL", "enabled");
+    php_info_print_table_row(2, "dbx support for ODBC", "enabled");
+    php_info_print_table_end();
+//    DISPLAY_INI_ENTRIES();
+}
+
+//
+// actual implementation of the dbx functions
+//
+//
+//
+//
+
+/* {{{ proto dbx_handle_object dbx_connect(string module_name, string host, string db, string username, string password [, bool persistent])
+   returns a dbx_handle_object on success
+   returns 0 on failure
+*/
+ZEND_FUNCTION(dbx_connect)
+{
+    int number_of_arguments=5;
+    zval ** arguments[6];
+
+    int result;
+    long module_identifier;
+    zval * dbx_module;
+    zval * rv_dbx_handle;
+    int persistent=0;
+
+    if ( !(ZEND_NUM_ARGS()==number_of_arguments+1 || ZEND_NUM_ARGS()==number_of_arguments) || zend_get_parameters_array_ex(ZEND_NUM_ARGS(), arguments) == FAILURE) {
+               WRONG_PARAM_COUNT;
+       }
+    if (ZEND_NUM_ARGS()==number_of_arguments+1) {
+        convert_to_long_ex(arguments[5]);
+        if ((*arguments[5])->value.lval!=0) persistent=1;
+        }
+
+    convert_to_string_ex(arguments[0]);
+    if (!module_exists((*arguments[0])->value.str.val)) {
+        zend_error(E_WARNING, "dbx: module '%s' not loaded.\n", (*arguments[0])->value.str.val);
+        return;
+        }
+    module_identifier=get_module_identifier((*arguments[0])->value.str.val);
+    if (!module_identifier) {
+        zend_error(E_WARNING, "dbx: unsupported module '%s'.\n", (*arguments[0])->value.str.val);
+        return;
+        }
+
+    MAKE_STD_ZVAL(dbx_module); 
+    ZVAL_LONG(dbx_module, module_identifier);
+    MAKE_STD_ZVAL(rv_dbx_handle); 
+    ZVAL_LONG(rv_dbx_handle, 0);
+    convert_to_string_ex(arguments[1]);
+    convert_to_string_ex(arguments[2]);
+    convert_to_string_ex(arguments[3]);
+    convert_to_string_ex(arguments[4]);
+    if (persistent) {
+        result = switch_dbx_pconnect(&rv_dbx_handle, arguments[1], arguments[2], arguments[3], arguments[4], INTERNAL_FUNCTION_PARAM_PASSTHRU, &dbx_module);
+        }
+    else {
+        result = switch_dbx_connect(&rv_dbx_handle, arguments[1], arguments[2], arguments[3], arguments[4], INTERNAL_FUNCTION_PARAM_PASSTHRU, &dbx_module);
+        }
+    if (!result) {
+        FREE_ZVAL(dbx_module);
+        FREE_ZVAL(rv_dbx_handle);
+        RETURN_LONG(0);
+        }
+
+    if (object_init(return_value) != SUCCESS) {
+        zend_error(E_ERROR, "dbx: unable to create resulting object...");
+        FREE_ZVAL(dbx_module);
+        FREE_ZVAL(rv_dbx_handle);
+        RETURN_LONG(0);
+        }
+
+    zend_hash_update(return_value->value.obj.properties, "handle", 7, (void *)&(rv_dbx_handle), sizeof(zval *), NULL);
+    zend_hash_update(return_value->value.obj.properties, "module", 7, (void *)&(dbx_module), sizeof(zval *), NULL);
+}
+/* }}} */
+
+/* {{{ proto bool dbx_close(dbx_handle_object dbx_handle)
+   Returns success or failure */
+ZEND_FUNCTION(dbx_close)
+{
+    int number_of_arguments=1;
+    zval ** arguments[1];
+
+    int result;
+    zval ** dbx_handle;
+    zval ** dbx_module;
+    zval * rv_success;
+
+    if (ZEND_NUM_ARGS() !=number_of_arguments || zend_get_parameters_array_ex(number_of_arguments, arguments) == FAILURE) {
+               WRONG_PARAM_COUNT;
+           }
+    if (!split_dbx_handle_object(arguments[0], &dbx_handle, &dbx_module)) {
+        zend_error(E_WARNING, "dbx_close: not a valid dbx_handle-object...");
+        RETURN_LONG(0);
+        }
+
+    MAKE_STD_ZVAL(rv_success); 
+
+    result = switch_dbx_close(&rv_success, dbx_handle, INTERNAL_FUNCTION_PARAM_PASSTHRU, dbx_module);
+
+    result = (result && rv_success->value.lval)?1:0;
+
+    FREE_ZVAL(rv_success);
+
+    RETURN_LONG(result?1:0);
+}
+/* }}} */
+
+/* {{{ proto data[rowinfo+rows][colinfo+cols] dbx_query(dbx_handle_object dbx_handle, string sql_statement [, long flags])
+   Returns results combined with query-information or false for failure or true for success on execution query
+   flags parameters is not implemented yet and if specified generates a WRONG_PARAM_COUNT 
+   it will be used to indicate what column info should be returned, and if fieldnames should be used
+   as assoc column indicators in the result-set */
+ZEND_FUNCTION(dbx_query)
+{
+    int min_number_of_arguments=2;
+    int number_of_arguments=3;
+    zval ** arguments[3];
+
+    int result;
+    zval ** dbx_handle;
+    zval ** dbx_module;
+    zval * rv_result_handle;
+    zval * rv_column_count;
+    long col_index;
+    long row_count;
+    zval * info;
+    long info_flags;
+//    long result_row_offset;
+//    long result_row_count;
+    zval * data;
+
+    if (ZEND_NUM_ARGS()<min_number_of_arguments || ZEND_NUM_ARGS()>number_of_arguments || zend_get_parameters_array_ex(ZEND_NUM_ARGS(), arguments) == FAILURE) {
+               WRONG_PARAM_COUNT;
+           }
+    if (!split_dbx_handle_object(arguments[0], &dbx_handle, &dbx_module)) {
+        zend_error(E_WARNING, "dbx_query: not a valid dbx_handle-object...");
+        RETURN_LONG(0);
+        }
+    // default values
+    info_flags = DBX_RESULT_INFO | DBX_RESULT_INDEX | DBX_RESULT_ASSOC;
+//    result_row_offset = 0;
+//    result_row_count = -1;
+    // parameter overrides
+    if (ZEND_NUM_ARGS()>2) {
+        convert_to_long_ex(arguments[2]);
+        info_flags = (*arguments[2])->value.lval;
+        // fieldnames are needed for association!
+        if (info_flags & DBX_RESULT_ASSOC) {
+            info_flags |= DBX_RESULT_INFO;
+            }
+        }
+//    if (ZEND_NUM_ARGS()>3) {
+//        convert_to_long_ex(arguments[3]);
+//        result_row_offset = (*arguments[3])->value.lval;
+//        }
+//    if (ZEND_NUM_ARGS()>4) {
+//        convert_to_long_ex(arguments[4]);
+//        result_row_count = (*arguments[4])->value.lval;
+//        }
+
+    MAKE_STD_ZVAL(rv_result_handle); 
+    convert_to_string_ex(arguments[1]);
+    result = switch_dbx_query(&rv_result_handle, dbx_handle, arguments[1], INTERNAL_FUNCTION_PARAM_PASSTHRU, dbx_module);
+    // boolean return value means either failure for any query or success for queries that don't return anything 
+    if (!result || (rv_result_handle && rv_result_handle->type==IS_BOOL)) {
+        result = (result && rv_result_handle->value.lval)?1:0;
+        FREE_ZVAL(rv_result_handle);
+        RETURN_LONG(result?1:0);
+        }
+    // if you get here, the query succeeded and returned results, so we'll return them
+    // rv_result_handle holds a resource
+    //  
+    // init return_value as object (of rows)
+    if (object_init(return_value) != SUCCESS) {
+        zend_error(E_ERROR, "dbx_query: unable to create resulting object...");
+        FREE_ZVAL(rv_result_handle);
+        RETURN_LONG(0);
+        }
+    // add result_handle property to return_value
+    zend_hash_update(return_value->value.obj.properties, "handle", 7, (void *)&(rv_result_handle), sizeof(zval *), NULL);
+    // init info property as array and add to return_value as a property
+    if (info_flags & DBX_RESULT_INFO) {
+        MAKE_STD_ZVAL(info); 
+        if (array_init(info) != SUCCESS) {
+            zend_error(E_ERROR, "dbx_query: unable to create info-array for results...");
+            FREE_ZVAL(info);
+            RETURN_LONG(0);
+            }
+        zend_hash_update(return_value->value.obj.properties, "info", 5, (void *)&(info), sizeof(zval *), NULL);
+        }
+    // init data property as array and add to return_value as a property
+    MAKE_STD_ZVAL(data); 
+    if (array_init(data) != SUCCESS) {
+        zend_error(E_ERROR, "dbx_query: unable to create data-array for results...");
+        FREE_ZVAL(data);
+        RETURN_LONG(0);
+        }
+    zend_hash_update(return_value->value.obj.properties, "data", 5, (void *)&(data), sizeof(zval *), NULL);
+    // get columncount and add to returnvalue as property
+    MAKE_STD_ZVAL(rv_column_count); 
+    result = switch_dbx_getcolumncount(&rv_column_count, &rv_result_handle, INTERNAL_FUNCTION_PARAM_PASSTHRU, dbx_module);
+    if (!result) { 
+        zend_error(E_ERROR, "dbx_query: get column_count failed...");
+        FREE_ZVAL(rv_column_count);
+        RETURN_LONG(0); 
+        }
+    zend_hash_update(return_value->value.obj.properties, "cols", 5, (void *)&(rv_column_count), sizeof(zval *), NULL);
+    // fill the info array with columnnames (only indexed (maybe assoc))
+    if (info_flags & DBX_RESULT_INFO) {
+        zval * info_row;
+        MAKE_STD_ZVAL(info_row);
+        if (array_init(info_row) != SUCCESS) {
+            zend_error(E_ERROR, "dbx_query: unable to create info_row-array for results...");
+            FREE_ZVAL(info_row);
+            RETURN_LONG(0);
+            }
+        for (col_index=0; col_index<rv_column_count->value.lval; ++col_index) {
+            zval * rv_column_name;
+            MAKE_STD_ZVAL(rv_column_name);
+            result = switch_dbx_getcolumnname(&rv_column_name, &rv_result_handle, col_index, INTERNAL_FUNCTION_PARAM_PASSTHRU, dbx_module);
+            if (result) { 
+                zend_hash_index_update(info_row->value.ht, col_index, (void *)&(rv_column_name), sizeof(zval *), NULL);
+                }
+            else {
+                FREE_ZVAL(rv_column_name);
+                }
+            }
+        zend_hash_update(info->value.ht, "name", 5, (void *) &info_row, sizeof(zval *), NULL);
+        }
+    // fill the info array with columntypes (indexed and assoc)
+    if (info_flags & DBX_RESULT_INFO) {
+        zval * info_row;
+        MAKE_STD_ZVAL(info_row);
+        if (array_init(info_row) != SUCCESS) {
+            zend_error(E_ERROR, "dbx_query: unable to create info_row-array for results...");
+            FREE_ZVAL(info_row);
+            RETURN_LONG(0);
+            }
+        for (col_index=0; col_index<rv_column_count->value.lval; ++col_index) {
+            zval * rv_column_type;
+            MAKE_STD_ZVAL(rv_column_type);
+            result = switch_dbx_getcolumntype(&rv_column_type, &rv_result_handle, col_index, INTERNAL_FUNCTION_PARAM_PASSTHRU, dbx_module);
+            if (result) { 
+                zend_hash_index_update(info_row->value.ht, col_index, (void *)&(rv_column_type), sizeof(zval *), NULL);
+                }
+            else {
+                FREE_ZVAL(rv_column_type);
+                }
+            }
+        zend_hash_update(info->value.ht, "type", 5, (void *) &info_row, sizeof(zval *), NULL);
+        }
+    // fill each row array with fieldvalues (indexed and assoc)
+    row_count=0;
+    result=1;
+    while (result) {
+        zval * rv_row;
+        MAKE_STD_ZVAL(rv_row);
+        result = switch_dbx_getrow(&rv_row, &rv_result_handle, INTERNAL_FUNCTION_PARAM_PASSTHRU, dbx_module);
+        if (result) {
+//            if (row_count>=result_row_offset && (result_row_count==-1 || row_count<result_row_offset+result_row_count)) {
+                zval ** row_ptr;
+                zend_hash_index_update(data->value.ht, row_count, (void *)&(rv_row), sizeof(zval *), (void **) &row_ptr);
+                // associate results with fieldnames
+                if (info_flags & DBX_RESULT_ASSOC) {
+                    zval **columnname_ptr, **actual_ptr, **reference_ptr;
+                    zval *dummy, **inforow_ptr;
+                    ALLOC_ZVAL(dummy);
+                    INIT_ZVAL(*dummy); 
+                    zend_hash_find(info->value.ht, "name", 5, (void **) &inforow_ptr);
+                    for (col_index=0; col_index<rv_column_count->value.lval; ++col_index) {
+                        zend_hash_index_find((*inforow_ptr)->value.ht, col_index, (void **) &columnname_ptr);
+                        zend_hash_index_find((*row_ptr)->value.ht, col_index, (void **) &actual_ptr);
+                        zend_hash_update((*row_ptr)->value.ht, (*columnname_ptr)->value.str.val, (*columnname_ptr)->value.str.len + 1, &dummy, sizeof(zval *), (void **) &reference_ptr);
+                        zend_assign_to_variable_reference(NULL, reference_ptr, actual_ptr, NULL ELS_CC);
+                        }
+                    }
+//                }
+//            else {
+//                FREE_ZVAL(rv_row);
+//                }
+            ++row_count;
+            }
+        else {
+            FREE_ZVAL(rv_row);
+            }
+        }
+    // add row_count property
+    add_property_long(return_value, "rows", row_count);
+    // thank you for watching.
+}
+/* }}} */
+
+/* {{{ proto void dbx_error()
+   Returns success or failure */
+ZEND_FUNCTION(dbx_error)
+{
+    int number_of_arguments=1;
+    zval ** arguments[1];
+
+    int result;
+    zval ** dbx_handle;
+    zval ** dbx_module;
+    zval * rv_errormsg;
+
+    if (ZEND_NUM_ARGS() !=number_of_arguments || zend_get_parameters_array_ex(number_of_arguments, arguments) == FAILURE) {
+               WRONG_PARAM_COUNT;
+           }
+    if (!split_dbx_handle_object(arguments[0], &dbx_handle, &dbx_module)) {
+        zend_error(E_WARNING, "dbx_error: not a valid dbx_handle-object...");
+        RETURN_LONG(0);
+        }
+
+    MAKE_STD_ZVAL(rv_errormsg); 
+    result = switch_dbx_error(&rv_errormsg, NULL, INTERNAL_FUNCTION_PARAM_PASSTHRU, dbx_module);
+    if (!result) {
+        FREE_ZVAL(rv_errormsg);
+        RETURN_STRING("", 1); 
+        }
+    MOVE_RETURNED_TO_RV(&return_value, rv_errormsg);
+}
+/* }}} */
+
+/////////// dbx functions that are database independent... like sorting result_objects!
+
+/* {{{ proto long dbx_cmp_asc(array row_x, array row_y, string columnname)
+   returns row_x[columnname] - row_y[columnname], converted to -1, 0 or 1
+*/
+ZEND_FUNCTION(dbx_cmp_asc)
+{
+    int number_of_arguments=3;
+    double dtemp;
+    long ltemp;
+    zval ** arguments[3];
+    zval ** zv_a;
+    zval ** zv_b;
+    int result=0;
+    if (ZEND_NUM_ARGS() !=number_of_arguments || zend_get_parameters_array_ex(number_of_arguments, arguments) == FAILURE) {
+               WRONG_PARAM_COUNT;
+           }
+
+    if ((*arguments[0])->type != IS_ARRAY
+    || (*arguments[1])->type != IS_ARRAY) {
+        zend_error(E_WARNING, "Wrong argument type for compare");
+        RETURN_LONG(0);
+        }
+    convert_to_string_ex(arguments[2]); // field name
+
+    if (zend_hash_find((*arguments[0])->value.ht, (*arguments[2])->value.str.val, (*arguments[2])->value.str.len+1, (void **) &zv_a)==FAILURE
+    || zend_hash_find((*arguments[1])->value.ht, (*arguments[2])->value.str.val, (*arguments[2])->value.str.len+1, (void **) &zv_b)==FAILURE)  {
+        zend_error(E_WARNING, "Field '%s' not available in result-object", (*arguments[2])->value.str.val);
+        RETURN_LONG(0);
+        }
+
+    if ((*zv_a)->type != (*zv_b)->type) {
+        convert_to_string_ex(zv_a);
+        convert_to_string_ex(zv_b);
+        }
+    switch ((*zv_a)->type) {
+        case IS_LONG:
+        case IS_BOOL:
+            ltemp = (*zv_a)->value.lval - (*zv_b)->value.lval;
+            result = (ltemp==0?0: (ltemp>0?1:-1));
+            break;
+        case IS_DOUBLE:
+            dtemp = ((*zv_a)->value.dval - (*zv_b)->value.dval);
+            result = (dtemp==0?0: (dtemp>0?1:-1));
+            break;
+        case IS_STRING:
+            ltemp = strcmp((*zv_a)->value.str.val, (*zv_b)->value.str.val);
+            result = (ltemp==0?0: (ltemp>0?1:-1));
+            break;
+        default:
+            result=0;
+            break;
+        }
+
+    RETURN_LONG(result);
+}
+
+/* {{{ proto long dbx_cmp_desc(array row_x, array row_y, string columnname)
+   returns row_y[columnname] - row_x[columnname], converted to -1, 0 or 1
+*/
+ZEND_FUNCTION(dbx_cmp_desc)
+{
+    int number_of_arguments=3;
+    double dtemp;
+    long ltemp;
+    zval ** arguments[3];
+    zval ** zv_a;
+    zval ** zv_b;
+    int result=0;
+    if (ZEND_NUM_ARGS() !=number_of_arguments || zend_get_parameters_array_ex(number_of_arguments, arguments) == FAILURE) {
+               WRONG_PARAM_COUNT;
+           }
+
+    if ((*arguments[0])->type != IS_ARRAY
+    || (*arguments[1])->type != IS_ARRAY) {
+        zend_error(E_WARNING, "Wrong argument type for compare");
+        RETURN_LONG(0);
+        }
+    convert_to_string_ex(arguments[2]); // field name
+
+    if (zend_hash_find((*arguments[0])->value.ht, (*arguments[2])->value.str.val, (*arguments[2])->value.str.len+1, (void **) &zv_a)==FAILURE
+    || zend_hash_find((*arguments[1])->value.ht, (*arguments[2])->value.str.val, (*arguments[2])->value.str.len+1, (void **) &zv_b)==FAILURE)  {
+        zend_error(E_WARNING, "Field '%s' not available in result-object", (*arguments[2])->value.str.val);
+        RETURN_LONG(0);
+        }
+
+    if ((*zv_a)->type != (*zv_b)->type) {
+        convert_to_string_ex(zv_a);
+        convert_to_string_ex(zv_b);
+        }
+    switch ((*zv_a)->type) {
+        case IS_LONG:
+        case IS_BOOL:
+            ltemp = (*zv_b)->value.lval - (*zv_a)->value.lval;
+            result = (ltemp==0?0: (ltemp>0?1:-1));
+            break;
+        case IS_DOUBLE:
+            dtemp = ((*zv_b)->value.dval - (*zv_a)->value.dval);
+            result = (dtemp==0?0: (dtemp>0?1:-1));
+            break;
+        case IS_STRING:
+            ltemp = strcmp((*zv_b)->value.str.val, (*zv_a)->value.str.val);
+            result = (ltemp==0?0: (ltemp>0?1:-1));
+            break;
+        default:
+            result=0;
+            break;
+        }
+
+    RETURN_LONG(result);
+}
+
+/* {{{ proto long dbx_sort(dbx_result_object stn_search_keywords_result, string compare_function_name)
+   returns 0 on failure, 1 on success
+*/
+ZEND_FUNCTION(dbx_sort)
+{
+    int number_of_arguments=2;
+    zval ** arguments[2];
+    zval ** zval_data;
+    zval * returned_zval;
+    int result=0;
+    if (ZEND_NUM_ARGS() !=number_of_arguments || zend_get_parameters_array_ex(number_of_arguments, arguments) == FAILURE) {
+               WRONG_PARAM_COUNT;
+           }
+
+    if ((*arguments[0])->type != IS_OBJECT
+    || (*arguments[1])->type != IS_STRING) {
+        zend_error(E_WARNING, "Wrong argument type for sort");
+        RETURN_LONG(0);
+        }
+
+    if (zend_hash_find((*arguments[0])->value.obj.properties, "data", 5, (void **) &zval_data)==FAILURE
+    || (*zval_data)->type != IS_ARRAY) {
+        zend_error(E_WARNING, "Wrong argument type for sort");
+        RETURN_LONG(0);
+        }
+
+    arguments[0] = zval_data;
+    dbx_call_any_function(INTERNAL_FUNCTION_PARAM_PASSTHRU, "usort", &returned_zval, number_of_arguments, arguments);
+    zval_dtor(returned_zval);
+    FREE_ZVAL(returned_zval);
+
+    RETURN_LONG(1);
+}
+
+/////////////////
+
+/* {{{ proto long dbx_test(???)
+   */
+ZEND_FUNCTION(dbx_test)
+{
+    zval **args[2];
+    zval *rowheader[2];
+    zval *row[2];
+    int result;
+    zval * sz;
+//    char psz[6];
+
+    array_init(return_value);
+
+    MAKE_STD_ZVAL(sz);
+//    strcpy(psz, "blaaa");
+    ZVAL_STRING(sz, "blaaa", 0);
+
+       zend_hash_index_update(return_value->value.ht, 2, (void *) &sz, sizeof(zval *), NULL);
+    zend_hash_update(return_value->value.ht, "two", 4, (void *) &sz, sizeof(zval *), NULL);
+
+
+//add_index_string(return_value, 2, sz->value.str.val, 1);
+//add_assoc_string(return_value, "two", sz->value.str.val, 0);
+
+
+//    zend_hash_update(return_value->value.ht, "x", 2, (void *)&sz, sizeof(zval *), NULL);
+//    FREE_ZVAL(sz);
+    return;
+
+//   DBXLS_FETCH();
+    for (result=0; result<2; ++result) {
+        args[result]=NULL;
+        }
+
+       if (ZEND_NUM_ARGS() !=2 || zend_get_parameters_array_ex(2, args) == FAILURE) {
+               WRONG_PARAM_COUNT;
+           }   
+
+    convert_to_long_ex(args[0]); // resource is also a long
+    convert_to_string_ex(args[1]);
+
+    if (array_init(return_value) != SUCCESS) {
+        zend_error(E_ERROR, "Unable to create array for results...");
+        RETURN_LONG(0);
+        }
+
+    for (result=0; result<2; ++result) {
+        MAKE_STD_ZVAL(rowheader[result]);
+        if (array_init(rowheader[result]) != SUCCESS) {
+            zend_error(E_ERROR, "Unable to create array for rowheader %d...", result);
+            }
+        }
+    for (result=0; result<2; ++result) {
+        MAKE_STD_ZVAL(row[result]);
+        if (array_init(row[result]) != SUCCESS) {
+            zend_error(E_ERROR, "Unable to create array for row %d...", result);
+            }
+        }
+    
+    add_index_string(rowheader[0], 0, "header0", 1); add_assoc_string(rowheader[0], "header0", "header0", 0);
+    add_index_string(rowheader[0], 1, "header1", 1); add_assoc_string(rowheader[0], "header1", "header1", 0);
+    add_index_string(rowheader[1], 0, "string", 1); add_assoc_string(rowheader[1], "header0", "string", 0);
+    add_index_string(rowheader[1], 1, "string", 1); add_assoc_string(rowheader[1], "header1", "string", 0);
+    add_index_string(row[0], 0, "bla00", 0); add_assoc_string(row[0], "header0", "bla00", 1);
+    add_index_string(row[0], 1, "bla10", 0); add_assoc_string(row[0], "header1", "bla10", 1);
+    add_index_string(row[1], 0, "bla01", 0); add_assoc_string(row[1], "header0", "bla01", 1);
+    add_index_string(row[1], 1, "bla11", 1); add_assoc_string(row[1], "header1", "bla11", 1);
+
+    add_index_string(row[1], 2, "bla12", 1);
+
+    zend_hash_update(return_value->value.ht, "fieldname", 10, (void *)&(rowheader[0]), sizeof(zval *), NULL);
+    zend_hash_update(return_value->value.ht, "fieldtype", 10, (void *)&(rowheader[1]), sizeof(zval *), NULL);
+    zend_hash_index_update(return_value->value.ht, 0, (void *)&(row[0]), sizeof(zval *), NULL);
+    zend_hash_index_update(return_value->value.ht, 1, (void *)&(row[1]), sizeof(zval *), NULL);
+
+}
+/* }}} */
+
+
+
+
+
+
+//
+// switch_dbx functions
+//
+int switch_dbx_connect(zval ** rv, zval ** host, zval ** db, zval ** username, zval ** password, INTERNAL_FUNCTION_PARAMETERS, zval ** dbx_module) {
+    // returns connection handle as resource on success or 0 as long on failure
+    switch ((*dbx_module)->value.lval) {
+        case DBX_MYSQL: return dbx_mysql_connect(rv, host, db, username, password, INTERNAL_FUNCTION_PARAM_PASSTHRU);        
+        case DBX_ODBC: return dbx_odbc_connect(rv, host, db, username, password, INTERNAL_FUNCTION_PARAM_PASSTHRU);        
+        }
+    zend_error(E_WARNING, "dbx_connect: not supported in this module");
+    return 0;
+    }
+
+int switch_dbx_pconnect(zval ** rv, zval ** host, zval ** db, zval ** username, zval ** password, INTERNAL_FUNCTION_PARAMETERS, zval ** dbx_module) {
+    // returns persistent connection handle as resource on success or 0 as long on failure
+    switch ((*dbx_module)->value.lval) {
+        case DBX_MYSQL: return dbx_mysql_pconnect(rv, host, db, username, password, INTERNAL_FUNCTION_PARAM_PASSTHRU);        
+        case DBX_ODBC: return dbx_odbc_pconnect(rv, host, db, username, password, INTERNAL_FUNCTION_PARAM_PASSTHRU);        
+        }
+    zend_error(E_WARNING, "dbx_pconnect: not supported in this module");
+    return 0;
+    }
+
+int switch_dbx_close(zval ** rv, zval ** dbx_handle, INTERNAL_FUNCTION_PARAMETERS, zval ** dbx_module) {
+    // returns 1 as long on success or 0 as long on failure
+    switch ((*dbx_module)->value.lval) {
+        case DBX_MYSQL: return dbx_mysql_close(rv, dbx_handle, INTERNAL_FUNCTION_PARAM_PASSTHRU);        
+        case DBX_ODBC: return dbx_odbc_close(rv, dbx_handle, INTERNAL_FUNCTION_PARAM_PASSTHRU);        
+        }
+    zend_error(E_WARNING, "dbx_close: not supported in this module");
+    return 0;
+    }
+
+int switch_dbx_query(zval ** rv, zval ** dbx_handle, zval ** sql_statement, INTERNAL_FUNCTION_PARAMETERS, zval ** dbx_module) {
+    // returns 1 as long or result identifier as resource on success or 0 as long on failure
+    switch ((*dbx_module)->value.lval) {
+        case DBX_MYSQL: return dbx_mysql_query(rv, dbx_handle, sql_statement, INTERNAL_FUNCTION_PARAM_PASSTHRU);        
+        case DBX_ODBC: return dbx_odbc_query(rv, dbx_handle, sql_statement, INTERNAL_FUNCTION_PARAM_PASSTHRU);        
+        }
+    zend_error(E_WARNING, "dbx_query: not supported in this module");
+    return 0;
+    }
+
+int switch_dbx_getcolumncount(zval ** rv, zval ** result_handle, INTERNAL_FUNCTION_PARAMETERS, zval ** dbx_module) {
+    // returns column-count as long on success or 0 as long on failure
+    switch ((*dbx_module)->value.lval) {
+        case DBX_MYSQL: return dbx_mysql_getcolumncount(rv, result_handle, INTERNAL_FUNCTION_PARAM_PASSTHRU);        
+        case DBX_ODBC: return dbx_odbc_getcolumncount(rv, result_handle, INTERNAL_FUNCTION_PARAM_PASSTHRU);        
+        }
+    zend_error(E_WARNING, "dbx_getcolumncount: not supported in this module");
+    return 0;
+    }
+
+int switch_dbx_getcolumnname(zval ** rv, zval ** result_handle, long column_index, INTERNAL_FUNCTION_PARAMETERS, zval ** dbx_module) {
+    // returns column-name as string on success or 0 as long on failure
+    switch ((*dbx_module)->value.lval) {
+        case DBX_MYSQL: return dbx_mysql_getcolumnname(rv, result_handle, column_index, INTERNAL_FUNCTION_PARAM_PASSTHRU);        
+        case DBX_ODBC: return dbx_odbc_getcolumnname(rv, result_handle, column_index, INTERNAL_FUNCTION_PARAM_PASSTHRU);        
+        }
+    zend_error(E_WARNING, "dbx_getcolumnname: not supported in this module");
+    return 0;
+    }
+
+int switch_dbx_getcolumntype(zval ** rv, zval ** result_handle, long column_index, INTERNAL_FUNCTION_PARAMETERS, zval ** dbx_module) {
+    // returns column-type as string on success or 0 as long on failure
+    switch ((*dbx_module)->value.lval) {
+        case DBX_MYSQL: return dbx_mysql_getcolumntype(rv, result_handle, column_index, INTERNAL_FUNCTION_PARAM_PASSTHRU);        
+        case DBX_ODBC: return dbx_odbc_getcolumntype(rv, result_handle, column_index, INTERNAL_FUNCTION_PARAM_PASSTHRU);        
+        }
+    zend_error(E_WARNING, "dbx_getcolumntype: not supported in this module");
+    return 0;
+    }
+
+int switch_dbx_getrow(zval ** rv, zval ** result_handle, INTERNAL_FUNCTION_PARAMETERS, zval ** dbx_module) {
+    // returns array[0..columncount-1] as strings on success or 0 as long on failure
+    switch ((*dbx_module)->value.lval) {
+        case DBX_MYSQL: return dbx_mysql_getrow(rv, result_handle, INTERNAL_FUNCTION_PARAM_PASSTHRU);        
+        case DBX_ODBC: return dbx_odbc_getrow(rv, result_handle, INTERNAL_FUNCTION_PARAM_PASSTHRU);        
+        }
+    zend_error(E_WARNING, "dbx_getrow: not supported in this module");
+    return 0;
+    }
+
+int switch_dbx_error(zval ** rv, zval ** dbx_handle, INTERNAL_FUNCTION_PARAMETERS, zval ** dbx_module) {
+    // returns string
+    switch ((*dbx_module)->value.lval) {
+        case DBX_MYSQL: return dbx_mysql_error(rv, dbx_handle, INTERNAL_FUNCTION_PARAM_PASSTHRU);        
+        case DBX_ODBC: return dbx_odbc_error(rv, dbx_handle, INTERNAL_FUNCTION_PARAM_PASSTHRU);        
+        }
+    zend_error(E_WARNING, "dbx_error: not supported in this module");
+    return 0;
+    }
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/ext/dbx/dbx.dsp b/ext/dbx/dbx.dsp
new file mode 100644 (file)
index 0000000..4998d59
--- /dev/null
@@ -0,0 +1,141 @@
+# Microsoft Developer Studio Project File - Name="dbx" - Package Owner=<4>\r
+# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
+# ** DO NOT EDIT **\r
+\r
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102\r
+\r
+CFG=dbx - Win32 Release_TS\r
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
+!MESSAGE use the Export Makefile command and run\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "dbx.mak".\r
+!MESSAGE \r
+!MESSAGE You can specify a configuration when running NMAKE\r
+!MESSAGE by defining the macro CFG on the command line. For example:\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "dbx.mak" CFG="dbx - Win32 Release_TS"\r
+!MESSAGE \r
+!MESSAGE Possible choices for configuration are:\r
+!MESSAGE \r
+!MESSAGE "dbx - Win32 Release_TS" (based on "Win32 (x86) Dynamic-Link Library")\r
+!MESSAGE "dbx - Win32 Debug_TS" (based on "Win32 (x86) Dynamic-Link Library")\r
+!MESSAGE \r
+\r
+# Begin Project\r
+# PROP AllowPerConfigDependencies 0\r
+# PROP Scc_ProjName ""\r
+# PROP Scc_LocalPath ""\r
+CPP=cl.exe\r
+MTL=midl.exe\r
+RSC=rc.exe\r
+\r
+!IF  "$(CFG)" == "dbx - Win32 Release_TS"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 0\r
+# PROP BASE Output_Dir "Release_TS"\r
+# PROP BASE Intermediate_Dir "Release_TS"\r
+# PROP BASE Ignore_Export_Lib 0\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 0\r
+# PROP Output_Dir "Release_TS"\r
+# PROP Intermediate_Dir "Release_TS"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /I "..\.." /I "..\..\..\Zend" /I "..\..\..\bindlib_w32" /I "..\..\..\TSRM" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "COMPILE_DL_dbx" /D ZTS=1 /YX /FD /c\r
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\.." /I "..\..\main" /I "..\..\Zend" /I "..\..\..\bindlib_w32" /I "..\..\TSRM" /D "WIN32" /D "dbx_EXPORTS" /D "COMPILE_DL_dbx" /D ZTS=1 /D HAVE_LIBINTL=1 /D ZEND_DEBUG=0 /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "ZEND_WIN32" /D "PHP_WIN32" /FR /YX /FD /c\r
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
+# ADD BASE RSC /l 0x406 /d "NDEBUG"\r
+# ADD RSC /l 0x406 /d "NDEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# 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 php4ts.lib /nologo /dll /machine:I386 /out:"..\..\Release_TS/php_dbx.dll" /libpath:"..\..\Release_TS" /libpath:"..\..\Release_TS_Inline"\r
+# ADD LINK32 php4ts.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 /nologo /dll /machine:I386 /out:"..\..\Release_TS/php_dbx.dll" /libpath:"..\..\Release_TS" /libpath:"..\..\Release_TS_Inline"\r
+\r
+!ELSEIF  "$(CFG)" == "dbx - Win32 Debug_TS"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 0\r
+# PROP BASE Output_Dir "Debug_TS"\r
+# PROP BASE Intermediate_Dir "Debug_TS"\r
+# PROP BASE Ignore_Export_Lib 0\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 0\r
+# PROP Output_Dir "Debug_TS"\r
+# PROP Intermediate_Dir "Debug_TS"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /I "..\.." /I "..\..\Zend" /I "..\..\..\bindlib_w32" /I "..\..\TSRM" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MSSQL_EXPORTS" /D "COMPILE_DL_dbx" /D ZTS=1 /YX /FD /c\r
+# ADD CPP /nologo /MDd /W3 /GX /ZI /Od /I "..\.." /I "..\..\main" /I "..\..\Zend" /I "..\..\..\bindlib_w32" /I "..\..\TSRM" /D ZEND_DEBUG=1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "dbx_EXPORTS" /D "COMPILE_DL_dbx" /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /D HAVE_LIBINTL=1 /FR /YX /FD /c\r
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
+# ADD BASE RSC /l 0x406 /d "NDEBUG"\r
+# ADD RSC /l 0x406 /d "NDEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# 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 php4ts.lib /nologo /dll /machine:I386 /out:"../../Debug_TS/php_dbx.dll" /libpath:"..\..\Debug_TS"\r
+# ADD LINK32 php4ts_debug.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 /nologo /dll /incremental:yes /debug /machine:I386 /out:"../../Debug_TS/php_dbx.dll" /libpath:"..\..\Debug_TS"\r
+\r
+!ENDIF \r
+\r
+# Begin Target\r
+\r
+# Name "dbx - Win32 Release_TS"\r
+# Name "dbx - Win32 Debug_TS"\r
+# Begin Group "Source Files"\r
+\r
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"\r
+# Begin Source File\r
+\r
+SOURCE=.\dbx.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\dbx_mysql.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\dbx_odbc.c\r
+# End Source File\r
+# End Group\r
+# Begin Group "Header Files"\r
+\r
+# PROP Default_Filter "h;hpp;hxx;hm;inl"\r
+# Begin Source File\r
+\r
+SOURCE=.\dbx.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\dbx_mysql.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\x\dbx_mysql.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\dbx_odbc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\x\dbx_odbc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\php_dbx.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Resource Files"\r
+\r
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"\r
+# End Group\r
+# End Target\r
+# End Project\r
diff --git a/ext/dbx/dbx.h b/ext/dbx/dbx.h
new file mode 100644 (file)
index 0000000..f98e1de
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+   +----------------------------------------------------------------------+
+   | stentor module version 1.0                                           |
+   +----------------------------------------------------------------------+
+   | Copyright (c) 2001 Guidance Rotterdam BV                             |
+   +----------------------------------------------------------------------+
+   | This source file is subject to version 1.0  of the STENTOR license,  |
+   | that is bundled with this package in the file LICENSE, and is        |
+   | available through the world-wide-web at                              |
+   | http://www.guidance.nl/php/dbx/license/1_00.txt.                     |
+   | If you did not receive a copy of the STENTOR license and are unable  |
+   | to obtain it through the world-wide-web, please send a note to       |
+   | license@guidance.nl so we can mail you a copy immediately.           |
+   +----------------------------------------------------------------------+
+   | Author : Marc Boeren         <marc@guidance.nl>                      |
+   +----------------------------------------------------------------------+
+ */
+
+#ifndef ZEND_DBX_H
+#define ZEND_DBX_H
+
+#ifndef INIT_FUNC_ARGS
+#include "zend_modules.h"
+#endif
+
+#include "php.h"
+
+#define DBX_PERSISTENT        1
+#define DBX_RESULT_INFO      1
+#define DBX_RESULT_INDEX    2
+#define DBX_RESULT_ASSOC   4
+
+#define MOVE_RETURNED_TO_RV(rv, returned_zval) { **rv = *returned_zval; zval_copy_ctor(*rv); zval_ptr_dtor(&returned_zval); }
+
+void dbx_call_any_function(INTERNAL_FUNCTION_PARAMETERS, char * function_name, zval ** returnvalue, int number_of_arguments, zval *** params);
+
+#endif /* ZEND_DBX_H */
+
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/ext/dbx/dbx_mysql.c b/ext/dbx/dbx_mysql.c
new file mode 100644 (file)
index 0000000..0b755e7
--- /dev/null
@@ -0,0 +1,217 @@
+/*
+   +----------------------------------------------------------------------+
+   | stentor module version 1.0                                           |
+   +----------------------------------------------------------------------+
+   | Copyright (c) 2001 Guidance Rotterdam BV                             |
+   +----------------------------------------------------------------------+
+   | This source file is subject to version 1.0  of the STENTOR license,  |
+   | that is bundled with this package in the file LICENSE, and is        |
+   | available through the world-wide-web at                              |
+   | http://www.guidance.nl/php/dbx/license/1_00.txt.                     |
+   | If you did not receive a copy of the STENTOR license and are unable  |
+   | to obtain it through the world-wide-web, please send a note to       |
+   | license@guidance.nl so we can mail you a copy immediately.           |
+   +----------------------------------------------------------------------+
+   | Author : Marc Boeren         <marc@guidance.nl>                      |
+   +----------------------------------------------------------------------+
+ */
+
+#include "dbx.h"
+#include "dbx_mysql.h"
+
+#define MYSQL_ASSOC            1<<0
+#define MYSQL_NUM              1<<1
+
+int dbx_mysql_connect(zval ** rv, zval ** host, zval ** db, zval ** username, zval ** password, INTERNAL_FUNCTION_PARAMETERS) {
+    // returns connection handle as resource on success or 0 as long on failure
+    int number_of_arguments=3;
+    zval ** arguments[3];
+    zval * returned_zval=NULL;
+    zval * select_db_zval=NULL;
+
+    arguments[0]=host;
+    arguments[1]=username;
+    arguments[2]=password;
+    dbx_call_any_function(INTERNAL_FUNCTION_PARAM_PASSTHRU, "mysql_connect", &returned_zval, number_of_arguments, arguments);
+    if (!returned_zval || returned_zval->type!=IS_RESOURCE) {
+        if (returned_zval) zval_ptr_dtor(&returned_zval);
+        return 0;
+        }
+    MOVE_RETURNED_TO_RV(rv, returned_zval);
+
+    number_of_arguments=2;
+    arguments[0]=db;
+    arguments[1]=rv;
+    dbx_call_any_function(INTERNAL_FUNCTION_PARAM_PASSTHRU, "mysql_select_db", &select_db_zval, number_of_arguments, arguments);
+    zval_ptr_dtor(&select_db_zval);
+
+    return 1;
+    }
+
+int dbx_mysql_pconnect(zval ** rv, zval ** host, zval ** db, zval ** username, zval ** password, INTERNAL_FUNCTION_PARAMETERS) {
+    // returns persistent connection handle as resource on success or 0 as long on failure
+    int number_of_arguments=3;
+    zval ** arguments[3];
+    zval * returned_zval=NULL;
+    zval * select_db_zval=NULL;
+
+    arguments[0]=host;
+    arguments[1]=username;
+    arguments[2]=password;
+    dbx_call_any_function(INTERNAL_FUNCTION_PARAM_PASSTHRU, "mysql_pconnect", &returned_zval, number_of_arguments, arguments);
+    if (!returned_zval || returned_zval->type!=IS_RESOURCE) {
+        if (returned_zval) zval_ptr_dtor(&returned_zval);
+        return 0;
+        }
+    MOVE_RETURNED_TO_RV(rv, returned_zval);
+
+    number_of_arguments=2;
+    arguments[0]=db;
+    arguments[1]=rv;
+    dbx_call_any_function(INTERNAL_FUNCTION_PARAM_PASSTHRU, "mysql_select_db", &select_db_zval, number_of_arguments, arguments);
+    zval_ptr_dtor(&select_db_zval);
+
+    return 1;
+    }
+
+int dbx_mysql_close(zval ** rv, zval ** dbx_handle, INTERNAL_FUNCTION_PARAMETERS) {
+    // returns 1 as long on success or 0 as long on failure
+    int number_of_arguments=1;
+    zval ** arguments[1];
+    zval * returned_zval=NULL;
+
+    arguments[0]=dbx_handle;
+    dbx_call_any_function(INTERNAL_FUNCTION_PARAM_PASSTHRU, "mysql_close", &returned_zval, number_of_arguments, arguments);
+    if (!returned_zval || returned_zval->type!=IS_BOOL) {
+        if (returned_zval) zval_ptr_dtor(&returned_zval);
+        return 0;
+        }
+    MOVE_RETURNED_TO_RV(rv, returned_zval);
+    return 1;
+    }
+
+int dbx_mysql_query(zval ** rv, zval ** dbx_handle, zval ** sql_statement, INTERNAL_FUNCTION_PARAMETERS) {
+    // returns 1 as long or a result identifier as resource on success  or 0 as long on failure
+    int number_of_arguments=2;
+    zval ** arguments[2];
+    zval * returned_zval=NULL;
+
+    arguments[0]=sql_statement;
+    arguments[1]=dbx_handle;
+    dbx_call_any_function(INTERNAL_FUNCTION_PARAM_PASSTHRU, "mysql_query", &returned_zval, number_of_arguments, arguments);
+    // mysql_query returns a bool for success or failure, or a result_identifier for select statements
+    if (!returned_zval || (returned_zval->type!=IS_BOOL && returned_zval->type!=IS_RESOURCE)) {
+        if (returned_zval) zval_ptr_dtor(&returned_zval);
+        return 0;
+        }
+    MOVE_RETURNED_TO_RV(rv, returned_zval);
+    return 1;
+    }
+
+int dbx_mysql_getcolumncount(zval ** rv, zval ** result_handle, INTERNAL_FUNCTION_PARAMETERS) {
+    // returns column-count as long on success or 0 as long on failure
+    int number_of_arguments=1;
+    zval ** arguments[1];
+    zval * returned_zval=NULL;
+
+    arguments[0]=result_handle;
+    dbx_call_any_function(INTERNAL_FUNCTION_PARAM_PASSTHRU, "mysql_num_fields", &returned_zval, number_of_arguments, arguments);
+    if (!returned_zval || returned_zval->type!=IS_LONG) {
+        if (returned_zval) zval_ptr_dtor(&returned_zval);
+        return 0;
+        }
+    MOVE_RETURNED_TO_RV(rv, returned_zval);
+    return 1;
+    }
+
+int dbx_mysql_getcolumnname(zval ** rv, zval ** result_handle, long column_index, INTERNAL_FUNCTION_PARAMETERS) {
+    // returns column-name as string on success or 0 as long on failure
+    int number_of_arguments=2;
+    zval ** arguments[2];
+    zval * zval_column_index;
+    zval * returned_zval=NULL;
+
+    MAKE_STD_ZVAL(zval_column_index);
+    ZVAL_LONG(zval_column_index, column_index);
+    arguments[0]=result_handle;
+    arguments[1]=&zval_column_index;
+    dbx_call_any_function(INTERNAL_FUNCTION_PARAM_PASSTHRU, "mysql_field_name", &returned_zval, number_of_arguments, arguments);
+    // mysql_field_name returns a string
+    if (!returned_zval || returned_zval->type!=IS_STRING) {
+        if (returned_zval) zval_ptr_dtor(&returned_zval);
+        FREE_ZVAL(zval_column_index);
+        return 0;
+        }
+    FREE_ZVAL(zval_column_index);
+    MOVE_RETURNED_TO_RV(rv, returned_zval);
+    return 1;
+    }
+
+int dbx_mysql_getcolumntype(zval ** rv, zval ** result_handle, long column_index, INTERNAL_FUNCTION_PARAMETERS) {
+    // returns column-type as string on success or 0 as long on failure
+    int number_of_arguments=2;
+    zval ** arguments[2];
+    zval * zval_column_index;
+    zval * returned_zval=NULL;
+
+    MAKE_STD_ZVAL(zval_column_index);
+    ZVAL_LONG(zval_column_index, column_index);
+    arguments[0]=result_handle;
+    arguments[1]=&zval_column_index;
+    dbx_call_any_function(INTERNAL_FUNCTION_PARAM_PASSTHRU, "mysql_field_type", &returned_zval, number_of_arguments, arguments);
+    // mysql_field_name returns a string
+    if (!returned_zval || returned_zval->type!=IS_STRING) {
+        if (returned_zval) zval_ptr_dtor(&returned_zval);
+        FREE_ZVAL(zval_column_index);
+        return 0;
+        }
+    FREE_ZVAL(zval_column_index);
+    MOVE_RETURNED_TO_RV(rv, returned_zval);
+    return 1;
+    }
+
+int dbx_mysql_getrow(zval ** rv, zval ** result_handle, INTERNAL_FUNCTION_PARAMETERS) {
+    // returns array[0..columncount-1] as strings on success or 0 as long on failure
+    int number_of_arguments=2;
+    zval ** arguments[2];
+    zval * zval_resulttype=NULL;
+    zval * returned_zval=NULL;
+
+    MAKE_STD_ZVAL(zval_resulttype);
+    ZVAL_LONG(zval_resulttype, MYSQL_NUM);
+    arguments[0]=result_handle;
+    arguments[1]=&zval_resulttype;
+    dbx_call_any_function(INTERNAL_FUNCTION_PARAM_PASSTHRU, "mysql_fetch_array", &returned_zval, number_of_arguments, arguments);
+    if (!returned_zval || returned_zval->type!=IS_ARRAY) {
+        if (returned_zval) zval_ptr_dtor(&returned_zval);
+        FREE_ZVAL(zval_resulttype);
+        return 0;
+        }
+    FREE_ZVAL(zval_resulttype);
+    MOVE_RETURNED_TO_RV(rv, returned_zval);
+    return 1;
+    }
+
+int dbx_mysql_error(zval ** rv, zval ** dbx_handle, INTERNAL_FUNCTION_PARAMETERS) {
+    // returns string
+    int number_of_arguments=1;
+    zval ** arguments[1];
+    zval * returned_zval=NULL;
+
+    arguments[0]=dbx_handle;
+    if (!dbx_handle) number_of_arguments=0;
+    dbx_call_any_function(INTERNAL_FUNCTION_PARAM_PASSTHRU, "mysql_error", &returned_zval, number_of_arguments, arguments);
+    if (!returned_zval || returned_zval->type!=IS_STRING) {
+        if (returned_zval) zval_ptr_dtor(&returned_zval);
+        return 0;
+        }
+    MOVE_RETURNED_TO_RV(rv, returned_zval);
+    return 1;
+    }
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/ext/dbx/dbx_mysql.h b/ext/dbx/dbx_mysql.h
new file mode 100644 (file)
index 0000000..1867ba9
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+   +----------------------------------------------------------------------+
+   | stentor module version 1.0                                           |
+   +----------------------------------------------------------------------+
+   | Copyright (c) 2001 Guidance Rotterdam BV                             |
+   +----------------------------------------------------------------------+
+   | This source file is subject to version 1.0  of the STENTOR license,  |
+   | that is bundled with this package in the file LICENSE, and is        |
+   | available through the world-wide-web at                              |
+   | http://www.guidance.nl/php/dbx/license/1_00.txt.                     |
+   | If you did not receive a copy of the STENTOR license and are unable  |
+   | to obtain it through the world-wide-web, please send a note to       |
+   | license@guidance.nl so we can mail you a copy immediately.           |
+   +----------------------------------------------------------------------+
+   | Author : Marc Boeren         <marc@guidance.nl>                      |
+   +----------------------------------------------------------------------+
+ */
+
+#ifndef ZEND_DBX_MYSQL_H
+#define ZEND_DBX_MYSQL_H
+
+#ifndef INIT_FUNC_ARGS
+#include "zend_modules.h"
+#endif
+
+#include "php.h"
+
+int dbx_mysql_connect(zval ** rv, zval ** host, zval ** db, zval ** username, zval ** password, INTERNAL_FUNCTION_PARAMETERS);
+    // returns connection handle as resource on success or 0 as long on failure
+int dbx_mysql_pconnect(zval ** rv, zval ** host, zval ** db, zval ** username, zval ** password, INTERNAL_FUNCTION_PARAMETERS);
+    // returns persistent connection handle as resource on success or 0 as long on failure
+int dbx_mysql_close(zval ** rv, zval ** dbx_handle, INTERNAL_FUNCTION_PARAMETERS);
+    // returns 1 as long on success or 0 as long on failure
+int dbx_mysql_query(zval ** rv, zval ** dbx_handle, zval ** sql_statement, INTERNAL_FUNCTION_PARAMETERS);
+    // returns 1 as long or a result identifier as resource on success  or 0 as long on failure
+int dbx_mysql_getcolumncount(zval ** rv, zval ** result_handle, INTERNAL_FUNCTION_PARAMETERS);
+    // returns column-count as long on success or 0 as long on failure
+int dbx_mysql_getcolumnname(zval ** rv, zval ** result_handle, long column_index, INTERNAL_FUNCTION_PARAMETERS);
+    // returns column-name as string on success or 0 as long on failure
+int dbx_mysql_getcolumntype(zval ** rv, zval ** result_handle, long column_index, INTERNAL_FUNCTION_PARAMETERS);
+    // returns column-type as string on success or 0 as long on failure
+int dbx_mysql_getrow(zval ** rv, zval ** result_handle, INTERNAL_FUNCTION_PARAMETERS);
+    // returns array[0..columncount-1] as strings on success or 0 as long on failure
+int dbx_mysql_error(zval ** rv, zval ** dbx_handle, INTERNAL_FUNCTION_PARAMETERS);
+    // returns string
+
+#endif /* ZEND_DBX_MYSQL_H */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/ext/dbx/dbx_odbc.c b/ext/dbx/dbx_odbc.c
new file mode 100644 (file)
index 0000000..ac12d3b
--- /dev/null
@@ -0,0 +1,239 @@
+/*
+   +----------------------------------------------------------------------+
+   | stentor module version 1.0                                           |
+   +----------------------------------------------------------------------+
+   | Copyright (c) 2001 Guidance Rotterdam BV                             |
+   +----------------------------------------------------------------------+
+   | This source file is subject to version 1.0  of the STENTOR license,  |
+   | that is bundled with this package in the file LICENSE, and is        |
+   | available through the world-wide-web at                              |
+   | http://www.guidance.nl/php/dbx/license/1_00.txt.                     |
+   | If you did not receive a copy of the STENTOR license and are unable  |
+   | to obtain it through the world-wide-web, please send a note to       |
+   | license@guidance.nl so we can mail you a copy immediately.           |
+   +----------------------------------------------------------------------+
+   | Author : Marc Boeren         <marc@guidance.nl>                      |
+   +----------------------------------------------------------------------+
+ */
+
+#include "dbx.h"
+#include "dbx_odbc.h"
+
+#define ODBC_ASSOC     1
+#define ODBC_NUM        2 
+
+int dbx_odbc_connect(zval ** rv, zval ** host, zval ** db, zval ** username, zval ** password, INTERNAL_FUNCTION_PARAMETERS) {
+    // returns connection handle as resource on success or 0 as long on failure
+    int number_of_arguments=3;
+    zval ** arguments[3];
+    zval * returned_zval=NULL;
+
+    arguments[0]=db;
+    arguments[1]=username;
+    arguments[2]=password;
+    dbx_call_any_function(INTERNAL_FUNCTION_PARAM_PASSTHRU, "odbc_connect", &returned_zval, number_of_arguments, arguments);
+    if (!returned_zval || returned_zval->type!=IS_RESOURCE) {
+        if (returned_zval) zval_ptr_dtor(&returned_zval);
+        return 0;
+        }
+    MOVE_RETURNED_TO_RV(rv, returned_zval);
+    return 1;
+    }
+
+int dbx_odbc_pconnect(zval ** rv, zval ** host, zval ** db, zval ** username, zval ** password, INTERNAL_FUNCTION_PARAMETERS) {
+    // returns connection handle as resource on success or 0 as long on failure
+    int number_of_arguments=3;
+    zval ** arguments[3];
+    zval * returned_zval=NULL;
+
+    arguments[0]=db;
+    arguments[1]=username;
+    arguments[2]=password;
+    dbx_call_any_function(INTERNAL_FUNCTION_PARAM_PASSTHRU, "odbc_pconnect", &returned_zval, number_of_arguments, arguments);
+    if (!returned_zval || returned_zval->type!=IS_RESOURCE) {
+        if (returned_zval) zval_ptr_dtor(&returned_zval);
+        return 0;
+        }
+    MOVE_RETURNED_TO_RV(rv, returned_zval);
+    return 1;
+    }
+
+int dbx_odbc_close(zval ** rv, zval ** dbx_handle, INTERNAL_FUNCTION_PARAMETERS) {
+    // returns 1 as long on success or 0 as long on failure
+    int number_of_arguments=1;
+    zval ** arguments[1];
+    zval * returned_zval=NULL;
+
+    arguments[0]=dbx_handle;
+    dbx_call_any_function(INTERNAL_FUNCTION_PARAM_PASSTHRU, "odbc_close", &returned_zval, number_of_arguments, arguments);
+    if (!returned_zval || returned_zval->type!=IS_BOOL) {
+        if (returned_zval) zval_ptr_dtor(&returned_zval);
+        return 0;
+        }
+    MOVE_RETURNED_TO_RV(rv, returned_zval);
+    return 1;
+    }
+
+int dbx_odbc_query(zval ** rv, zval ** dbx_handle, zval ** sql_statement, INTERNAL_FUNCTION_PARAMETERS) {
+    // returns 1 as long or a result identifier as resource on success  or 0 as long on failure
+    int number_of_arguments=2;
+    zval ** arguments[2];
+    zval * queryresult_zval=NULL;
+    zval * num_fields_zval=NULL;
+
+    arguments[0]=dbx_handle;
+    arguments[1]=sql_statement;
+    dbx_call_any_function(INTERNAL_FUNCTION_PARAM_PASSTHRU, "odbc_exec", &queryresult_zval, number_of_arguments, arguments);
+    // odbc_query returns a bool for failure, or a result_identifier for success
+    if (!queryresult_zval || queryresult_zval->type!=IS_RESOURCE) {
+        if (queryresult_zval) zval_ptr_dtor(&queryresult_zval);
+        return 0;
+        }
+    MAKE_STD_ZVAL(num_fields_zval);
+    if (!dbx_odbc_getcolumncount(&num_fields_zval, &queryresult_zval, INTERNAL_FUNCTION_PARAM_PASSTHRU)) {
+        FREE_ZVAL(num_fields_zval);
+        if (queryresult_zval) zval_ptr_dtor(&queryresult_zval);
+        return 0;
+        }
+    if (num_fields_zval->value.lval==0) {
+        (*rv)->type=IS_BOOL;
+        (*rv)->value.lval=1; // success, but no data
+        FREE_ZVAL(num_fields_zval);
+        if (queryresult_zval) zval_ptr_dtor(&queryresult_zval);
+        return 1;
+        }
+    FREE_ZVAL(num_fields_zval);
+    MOVE_RETURNED_TO_RV(rv, queryresult_zval);
+    return 1;
+    }
+
+int dbx_odbc_getcolumncount(zval ** rv, zval ** result_handle, INTERNAL_FUNCTION_PARAMETERS) {
+    // returns column-count as long on success or 0 as long on failure
+    int number_of_arguments=1;
+    zval ** arguments[1];
+    zval * returned_zval=NULL;
+
+    arguments[0]=result_handle;
+    dbx_call_any_function(INTERNAL_FUNCTION_PARAM_PASSTHRU, "odbc_num_fields", &returned_zval, number_of_arguments, arguments);
+    if (!returned_zval || returned_zval->type!=IS_LONG || returned_zval->value.lval<0) {
+        if (returned_zval) zval_ptr_dtor(&returned_zval);
+        return 0;
+        }
+    MOVE_RETURNED_TO_RV(rv, returned_zval);
+    return 1;
+    }
+
+int dbx_odbc_getcolumnname(zval ** rv, zval ** result_handle, long column_index, INTERNAL_FUNCTION_PARAMETERS) {
+    // returns column-name as string on success or 0 as long on failure
+    int number_of_arguments=2;
+    zval ** arguments[2];
+    zval * zval_column_index;
+    zval * returned_zval=NULL;
+
+    MAKE_STD_ZVAL(zval_column_index);
+    ZVAL_LONG(zval_column_index, column_index+1);
+    arguments[0]=result_handle;
+    arguments[1]=&zval_column_index;
+    dbx_call_any_function(INTERNAL_FUNCTION_PARAM_PASSTHRU, "odbc_field_name", &returned_zval, number_of_arguments, arguments);
+    // odbc_field_name returns a string
+    if (!returned_zval || returned_zval->type!=IS_STRING) {
+        if (returned_zval) zval_ptr_dtor(&returned_zval);
+        FREE_ZVAL(zval_column_index);
+        return 0;
+        }
+    FREE_ZVAL(zval_column_index);
+    MOVE_RETURNED_TO_RV(rv, returned_zval);
+    return 1;
+    }
+
+int dbx_odbc_getcolumntype(zval ** rv, zval ** result_handle, long column_index, INTERNAL_FUNCTION_PARAMETERS) {
+    // returns column-type as string on success or 0 as long on failure
+    int number_of_arguments=2;
+    zval ** arguments[2];
+    zval * zval_column_index;
+    zval * returned_zval=NULL;
+
+    MAKE_STD_ZVAL(zval_column_index);
+    ZVAL_LONG(zval_column_index, column_index+1);
+    arguments[0]=result_handle;
+    arguments[1]=&zval_column_index;
+    dbx_call_any_function(INTERNAL_FUNCTION_PARAM_PASSTHRU, "odbc_field_type", &returned_zval, number_of_arguments, arguments);
+    // odbc_field_name returns a string
+    if (!returned_zval || returned_zval->type!=IS_STRING) {
+        if (returned_zval) zval_ptr_dtor(&returned_zval);
+        FREE_ZVAL(zval_column_index);
+        return 0;
+        }
+    FREE_ZVAL(zval_column_index);
+    MOVE_RETURNED_TO_RV(rv, returned_zval);
+    return 1;
+    }
+
+int dbx_odbc_getrow(zval ** rv, zval ** result_handle, INTERNAL_FUNCTION_PARAMETERS) {
+    // returns array[0..columncount-1] as strings on success or 0 as long on failure
+    int number_of_arguments;
+    zval ** arguments[2];
+    zval * num_fields_zval=NULL;
+    zval * fetch_row_result_zval=NULL;
+    zval * field_result_zval=NULL;
+    zval * field_index_zval;
+    zval * returned_zval=NULL;
+    long field_index;
+    long field_count=-1;
+
+    // get # fields
+    MAKE_STD_ZVAL(num_fields_zval);
+    if (!dbx_odbc_getcolumncount(&num_fields_zval, result_handle, INTERNAL_FUNCTION_PARAM_PASSTHRU)) {
+        return 0;
+        }
+    field_count=num_fields_zval->value.lval;
+    FREE_ZVAL(num_fields_zval);
+    // fetch row
+    number_of_arguments=1;
+    arguments[0]=result_handle;
+    dbx_call_any_function(INTERNAL_FUNCTION_PARAM_PASSTHRU, "odbc_fetch_row", &fetch_row_result_zval, number_of_arguments, arguments);
+    if (!fetch_row_result_zval || fetch_row_result_zval->type!=IS_BOOL) {
+        if (fetch_row_result_zval) zval_ptr_dtor(&fetch_row_result_zval);
+        return 0;
+        }
+    if (fetch_row_result_zval->value.lval==0) {
+        (*rv)->type=IS_LONG;
+        (*rv)->value.lval=0; // ok, no more rows
+        zval_ptr_dtor(&fetch_row_result_zval);
+        return 0;
+        }
+    zval_ptr_dtor(&fetch_row_result_zval);
+    // fill array with field results...
+    MAKE_STD_ZVAL(returned_zval);
+    if (array_init(returned_zval) != SUCCESS) {
+        zend_error(E_ERROR, "dbx_odbc_getrow: unable to create result-array...");
+        FREE_ZVAL(returned_zval);
+        return 0;
+        }
+    MAKE_STD_ZVAL(field_index_zval);
+    number_of_arguments=2;
+    for (field_index=0; field_index<field_count; ++field_index) {
+        ZVAL_LONG(field_index_zval, field_index+1);
+        arguments[0]=result_handle;
+        arguments[1]=&field_index_zval;
+        dbx_call_any_function(INTERNAL_FUNCTION_PARAM_PASSTHRU, "odbc_result", &field_result_zval, number_of_arguments, arguments);
+        zend_hash_index_update(returned_zval->value.ht, field_index, (void *)&(field_result_zval), sizeof(zval *), NULL);
+        }
+    FREE_ZVAL(field_index_zval);
+
+    MOVE_RETURNED_TO_RV(rv, returned_zval);
+    return 1;
+    }
+
+int dbx_odbc_error(zval ** rv, zval ** dbx_handle, INTERNAL_FUNCTION_PARAMETERS) {
+    // returns empty string // no equivalent in odbc module (yet???)
+    ZVAL_EMPTY_STRING((*rv));
+    return 1;
+    }
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/ext/dbx/dbx_odbc.h b/ext/dbx/dbx_odbc.h
new file mode 100644 (file)
index 0000000..003505e
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+   +----------------------------------------------------------------------+
+   | stentor module version 1.0                                           |
+   +----------------------------------------------------------------------+
+   | Copyright (c) 2001 Guidance Rotterdam BV                             |
+   +----------------------------------------------------------------------+
+   | This source file is subject to version 1.0  of the STENTOR license,  |
+   | that is bundled with this package in the file LICENSE, and is        |
+   | available through the world-wide-web at                              |
+   | http://www.guidance.nl/php/dbx/license/1_00.txt.                     |
+   | If you did not receive a copy of the STENTOR license and are unable  |
+   | to obtain it through the world-wide-web, please send a note to       |
+   | license@guidance.nl so we can mail you a copy immediately.           |
+   +----------------------------------------------------------------------+
+   | Author : Marc Boeren         <marc@guidance.nl>                      |
+   +----------------------------------------------------------------------+
+ */
+
+#ifndef ZEND_DBX_ODBC_H
+#define ZEND_DBX_ODBC_H
+
+#ifndef INIT_FUNC_ARGS
+#include "zend_modules.h"
+#endif
+
+#include "php.h"
+
+int dbx_odbc_connect(zval ** rv, zval ** host, zval ** db, zval ** username, zval ** password, INTERNAL_FUNCTION_PARAMETERS);
+    // returns connection handle as resource on success or 0 as long on failure
+int dbx_odbc_pconnect(zval ** rv, zval ** host, zval ** db, zval ** username, zval ** password, INTERNAL_FUNCTION_PARAMETERS);
+    // returns persisten connection handle as resource on success or 0 as long on failure
+int dbx_odbc_close(zval ** rv, zval ** dbx_handle, INTERNAL_FUNCTION_PARAMETERS);
+    // returns 1 as long on success or 0 as long on failure
+int dbx_odbc_query(zval ** rv, zval ** dbx_handle, zval ** sql_statement, INTERNAL_FUNCTION_PARAMETERS);
+    // returns 1 as long or a result identifier as resource on success  or 0 as long on failure
+int dbx_odbc_getcolumncount(zval ** rv, zval ** result_handle, INTERNAL_FUNCTION_PARAMETERS);
+    // returns column-count as long on success or 0 as long on failure
+int dbx_odbc_getcolumnname(zval ** rv, zval ** result_handle, long column_index, INTERNAL_FUNCTION_PARAMETERS);
+    // returns column-name as string on success or 0 as long on failure
+int dbx_odbc_getcolumntype(zval ** rv, zval ** result_handle, long column_index, INTERNAL_FUNCTION_PARAMETERS);
+    // returns column-type as string on success or 0 as long on failure
+int dbx_odbc_getrow(zval ** rv, zval ** result_handle, INTERNAL_FUNCTION_PARAMETERS);
+    // returns array[0..columncount-1] as strings on success or 0 as long on failure
+int dbx_odbc_error(zval ** rv, zval ** dbx_handle, INTERNAL_FUNCTION_PARAMETERS);
+    // returns string
+
+#endif /* ZEND_DBX_ODBC_H */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/ext/dbx/php_dbx.h b/ext/dbx/php_dbx.h
new file mode 100644 (file)
index 0000000..4e7f7ae
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+   +----------------------------------------------------------------------+
+   | stentor module version 1.0                                           |
+   +----------------------------------------------------------------------+
+   | Copyright (c) 2001 Guidance Rotterdam BV                             |
+   +----------------------------------------------------------------------+
+   | This source file is subject to version 1.0  of the STENTOR license,  |
+   | that is bundled with this package in the file LICENSE, and is        |
+   | available through the world-wide-web at                              |
+   | http://www.guidance.nl/php/dbx/license/1_00.txt.                     |
+   | If you did not receive a copy of the STENTOR license and are unable  |
+   | to obtain it through the world-wide-web, please send a note to       |
+   | license@guidance.nl so we can mail you a copy immediately.           |
+   +----------------------------------------------------------------------+
+   | Author : Marc Boeren         <marc@guidance.nl>                      |
+   +----------------------------------------------------------------------+
+ */
+
+#ifndef ZEND_PHP_DBX_H
+#define ZEND_PHP_DBX_H
+
+#ifndef INIT_FUNC_ARGS
+#include "zend_modules.h"
+#endif
+
+extern zend_module_entry dbx_module_entry;
+#define phpext_dbx_ptr &dbx_module_entry
+
+#ifdef ZEND_WIN32
+#define ZEND_DBX_API __declspec(dllexport)
+#else
+#define ZEND_DBX_API
+#endif
+
+ZEND_MINIT_FUNCTION(dbx);
+ZEND_MSHUTDOWN_FUNCTION(dbx);
+//ZEND_RINIT_FUNCTION(dbx);
+//ZEND_RSHUTDOWN_FUNCTION(dbx);
+ZEND_MINFO_FUNCTION(dbx);
+
+ZEND_FUNCTION(dbx_connect);
+ZEND_FUNCTION(dbx_close);
+ZEND_FUNCTION(dbx_query);
+ZEND_FUNCTION(dbx_error);
+
+ZEND_FUNCTION(dbx_sort);
+ZEND_FUNCTION(dbx_cmp_asc);
+ZEND_FUNCTION(dbx_cmp_desc);
+
+ZEND_FUNCTION(dbx_test);
+
+/* 
+       Declare any global variables you may need between the BEGIN
+       and END macros here:     
+*/
+//ZEND_BEGIN_MODULE_GLOBALS(dbx)
+//     void * dbx_global;
+//ZEND_END_MODULE_GLOBALS(dbx)
+
+
+/* In every function that needs to use variables in php_dbx_globals,
+   do call dbxLS_FETCH(); after declaring other variables used by
+   that function, and always refer to them as dbxG(variable).
+   You are encouraged to rename these macros something shorter, see
+   examples in any other php module directory.
+*/
+
+#ifdef ZTS
+#define DBXG(v) (dbx_globals->v)
+#define DBXLS_FETCH() zend_dbx_globals *dbx_globals = ts_resource(dbx_globals_id)
+#else
+#define DBXG(v) (dbx_globals.v)
+#define DBXLS_FETCH()
+#endif
+
+#endif /* ZEND_PHP_DBX_H */
+
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ */