summaryrefslogtreecommitdiff
path: root/ext/dbx/howto_extend_dbx.html
diff options
context:
space:
mode:
Diffstat (limited to 'ext/dbx/howto_extend_dbx.html')
-rw-r--r--ext/dbx/howto_extend_dbx.html316
1 files changed, 0 insertions, 316 deletions
diff --git a/ext/dbx/howto_extend_dbx.html b/ext/dbx/howto_extend_dbx.html
deleted file mode 100644
index 8cbd0f69fc..0000000000
--- a/ext/dbx/howto_extend_dbx.html
+++ /dev/null
@@ -1,316 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN">
-<html>
-<head>
-<title>HOWTO extend dbx</title>
-
-</head>
-
-<body marginwidth="0" marginheight="0">
-<style type="text/css">
-<!--
-
-body, p, td, input, select, a, h1, h2, h3, h4, h5, h6, marquee, blink
- { font-family: Verdana,sans-serif; font-size: 10pt; color: #000000; }
-h1 { font-size: 16pt; font-weight: bold; }
-h2 { font-size: 14pt; font-weight: bold; }
-h3 { font-size: 12pt; font-weight: bold; }
-h4 { font-size: 10pt; font-weight: bold; }
-h5 { font-size: 8pt;}
-h6 { font-size: 6pt;}
-
-body { background-color: #F0F0F0; }
-a { color: #000088; }
-
-.title { font-size: 14pt; font-weight: bold; }
-.fn-title { font-size: 12pt; font-weight: bold; }
-.fn-phpversion { font-size: 10pt; font-weight: normal; }
-.fn-def { margin-top: 8px; margin-bottom: 8px; background-color: #99BBDD; }
-.fn-defname { font-weight: bold; }
-.fn-name { font-size: 12pt; font-weight: bold; }
-.fn-param { font-weight: bold; }
-.example { margin-top: 12px; font-weight: bold; }
-.text { margin: 8px; }
-.code { margin: 16px; font-family: Courier; background-color: #CCCCCC; }
-.bold { font-weight: bold; }
-
-.indent { margin-left: 16px; }
-.newpage { border-top: 2px solid #000088; margin-bottom: 8px; }
-.tab { margin-left: 16px; }
-
-
--->
-</style>
-
-
-
-
-
-<a name="top"></a>
-<div class="title">
-How-to code support for another database<br>
-</div>
-<div class="text">
-Every supported database module must be loaded by PHP before it can be used. Every supported database module must be added to the dbx-module before it can be used. Currently there is support for MySQL, PostgreSQL, Microsoft SQL Server and ODBC, but it is not difficult to add support for more databases.<br>
-<br>
-The dbx module is found in de PHP ext/dbx folder. The support-code is found in the same folder <br>
-<br>
-To add support for module 'blabla' the following steps must be taken: <br>
-1. the dbx.c source file must be extended to recognize module 'blabla' and switch to the 'blabla' functions.<br>
-2. the files dbx_blabla.h and dbx_blabla.c must be created and edited to produce the required response.<br>
-3. add the files from step 2 to the project.<br>
-4. compile.<br>
-5. enjoy.<br>
-<br>
-You may need a bit of help for step 1 and 2. If you need help for step 3 or 4, you shouldn't try to attempt this probably :-). If you need help with step 5 you're in big trouble ;o)<br>
-Help for step 1 and 2 is given below, bold text in code indicate the important bits.<br>
-</div>
-<p>
-<a href="index.html">home</a><br>
-<div class="newpage"></div>
-
-<div class="fn-title"><a name="step1"></a>
-1. the dbx.c source file must be extended<br>
-</div>
-<div class="text">
-Define a module identifier and assign it a unique number. Include your header file here as well.<br>
-<pre class="code">
-// defines for supported databases
-#define DBX_UNKNOWN 0
-#define DBX_MYSQL 1
-#define DBX_ODBC 2
-<span class="bold">#define DBX_BLABLA 3</span>
-// includes for supported databases
-#include "dbx.h"
-#include "dbx_mysql.h"
-#include "dbx_odbc.h"
-<span class="bold">#include "dbx_blabla.h"</span>
-</pre>
-Add code to the module_identifier_exists function so DBX_BLABLA will be recognized:<br>
-<pre class="code">
-int module_identifier_exists(long module_identifier) {
- switch (module_identifier) {
- case DBX_MYSQL: return module_exists("mysql");
- case DBX_ODBC: return module_exists("odbc");
- <span class="bold">case DBX_BLABLA: return module_exists("blabla");</span>
- }
- return 0;
- }
-</pre>
-Add code to the get_module_identifier function so your extension will be recognized:<br>
-<pre class="code">
-int get_module_identifier(char * module_name) {
- if (!strcmp("mysql", module_name)) return DBX_MYSQL;
- if (!strcmp("odbc", module_name)) return DBX_ODBC;
- <span class="bold">if (!strcmp("blabla", module_name)) return DBX_BLABLA;</span>
- return DBX_UNKNOWN;
- }
-</pre>
-Add code for exposing the DBX_BLABLA constant to the world:<br>
-<pre class="code">
-ZEND_MINIT_FUNCTION(dbx)
-{
-/*/ REGISTER_INI_ENTRIES(); /*/
-
- REGISTER_LONG_CONSTANT("DBX_MYSQL", DBX_MYSQL, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("DBX_ODBC", DBX_ODBC, CONST_CS | CONST_PERSISTENT);
- <span class="bold">REGISTER_LONG_CONSTANT("DBX_BLABLA", DBX_BLABLA CONST_CS | CONST_PERSISTENT);</span>
-
- [...]
-
- return SUCCESS;
- }
-</pre>
-Add code for inclusion in the phpinfo() function (optional, but recommended):<br>
-<pre class="code">
-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");
- <span class="bold">php_info_print_table_row(2, "dbx support for BlaBla", "enabled");</span>
- php_info_print_table_end();
- DISPLAY_INI_ENTRIES();
-}
-</pre>
-Finally, for the implementation of all switch_dbx_XXXXX functions, copy a 'case'-line for every function that you support (should be all functions!). Here is an example for only the switch_dbx_connect function:<br>
-<pre class="code">
-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)-&gt;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);
- <span class="bold">case DBX_BLABLA: return dbx_blabla_connect(rv, host, db, username, password, INTERNAL_FUNCTION_PARAM_PASSTHRU);</span>
- }
- zend_error(E_WARNING, "dbx_connect: not supported in this module");
- return 0;
- }
-</pre>
-This should be done for all switch_dbx_XXXXX functions. They are listed below:<br>
-<pre class="code">
-int <a href="#connect">switch_dbx_connect(...)</a>;
-int <a href="#pconnect">switch_dbx_pconnect(...)</a>;
-int <a href="#close">switch_dbx_close(...)</a>;
-int <a href="#query">switch_dbx_query(...)</a>;
-int <a href="#getcolumncount">switch_dbx_getcolumncount(...)</a>;
-int <a href="#getcolumnname">switch_dbx_getcolumnname(...)</a>;
-int <a href="#getcolumntype">switch_dbx_getcolumntype(...)</a>;
-int <a href="#getrow">switch_dbx_getrow(...)</a>;
-int <a href="#error">switch_dbx_error(...)</a>;
-</pre>
-This concludes the changes for the dbx.c file. All that is needed now is to actually code the dbx_blabla_connect and other functions, which we will see in the following step.<br>
-</div>
-<p>
-<a href="#top">top</a><br>
-<div class="newpage"></div>
-
-<div class="fn-title"><a name="step1"></a>
-2. the files dbx_blabla.h and dbx_blabla.c<br>
-</div>
-<div class="text">
-The dbx_blabla.h and dbx_blabla.c file are created in the folder /ext/dbx.<br>
-The easiest method is to just copy dbx_mysql.h en dbx_mysql.c, open both files, and do a search and replace ('blabla' for 'mysql' and 'BLABLA' for 'MYSQL'). Yes, case-sensitive.<br>
-For the .h file, that's all. <br>
-For the .c file, the fun has just started :-)<br>
-In the .c is the actual realization of the database abstraction, where a call to a standard function is translated into one or more database-specific calls. For mysql, a dbx_connect translates to a mysql_connect followed by a mysql_select_db. Refer to the dbx_mysql.c and dbx_odbc.c files regularly for examples!<br>
-In dbx.h one macro and one function are defined to make the calling of external module functions and returning of the results easier: dbx_call_any_function and MOVE_RETURNED_TO_RV.<br>
-<p>
- The details of what each of the functions do, what parameters they get, and what parameters they should return are discussed below. But first, the dbx_mysql_connect function is presented and explained, so you get an idea of how things work.<br>
-<pre class="code">
-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;
- zval ** arguments[3];
- zval * returned_zval=NULL;
- zval * select_db_zval=NULL;
-
- number_of_arguments=3;
- arguments[0]=host;
- arguments[1]=username;
- arguments[2]=password;
- dbx_call_any_function(INTERNAL_FUNCTION_PARAM_PASSTHRU, <span class="bold">"mysql_connect"</span>, &returned_zval, number_of_arguments, arguments);
- if (!returned_zval || returned_zval-&gt;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, <span class="bold">"mysql_select_db"</span>, &select_db_zval, number_of_arguments, arguments);
- zval_ptr_dtor(&select_db_zval);
-
- return 1;
- }
-</pre>
-First of all, all functions return 0 on failure and 1 on success. These values are used in the dbx-routines, they are never actually given back to the PHP-script writer that calls the dbx_connect function.<br>
-The actual value that is of interest to the caller is returned in the <span class="bold">rv</span> parameter. In this case it is a connection handle (or link identifier, in mysql-speak), that is also returned if the database selection doesn't succeed. <br>
-The parameters that are of interest to the function are located between the <span class="bold">rv</span> and <span class="bold">INTERNAL_FUNCTION_PARAMETERS</span> parameters, in this case it is a <span class="bold">host</span> name, a <span class="bold">db</span> name, a <span class="bold">username</span> and a <span class="bold">password</span>. These are the values that the user specifies if he calls dbx_connect(); These parameters are used in the calls to the mysql-database functions. The user actually also specifies a module-name, that decides which connect-function should be called. Here, he specified 'mysql'.<br>
-To actually call a mysql module function, you can use <span class="bold">dbx_call_any_function</span> where you specify the function name (it is used twice in dbx_mysql_connect, see <span class="bold">'mysql_connect'</span> and <span class="bold">'mysql_select_db'</span>, they are printed bold in the code). The value that is returned from the function will be stored in the next argument, a zval * (e.g. <span class="bold">returned_zval</span>) parameter that you must declare locally. To actually return such a parameter, use the <span class="bold">MOVE_RETURNED_TO_RV(rv, returned_zval)</span> macro, which copies the values to <span class="bold">rv</span> and frees anything that may be left in <span class="bold">returned_zval</span>. Parameters that must be passed to the mysql-function are stored in the <span class="bold">arguments</span> array, which must be large enough to hold all parameters to the function-call that requires the most parameters (in this case, mysql_connect expects 3 parameters, mysql_select_db expects two parameters, so the <span class="bold">arguments</span> array is defined 'zval ** arguments[<span class="bold">3</span>]'). The <span class="bold">number_of_arguments</span> parameter is set to the actual number of arguments that the function-call requires. As you can see it is initialized to 3, for the first call to mysql_connect. Then it is set to 2, for the call to mysql_select_db. If you call a function that retrieves a value, and you don't return it with MOVE_RETURNED_TO_RV, then you must free the value using <span class="bold">zval_ptr_dtor</span>, as can be seen right after the call to mysql_select_db. This can also be seen directly after the call to mysql_connect, if somehow this function failed or didn't return a resource (on a successful connect mysql_connect returns a resource) the returned value is freed as well (and 0 is returned because the connection failed).<br>
-<p>
-OK, now the description of all functions that you should implement, and what is expected of them...<br>
-<a name="connect"></a><pre class="code">
-int <span class="fn-name">dbx_blabla_connect</span>(zval ** rv, zval ** <span class="fn-param">host</span>, zval ** <span class="fn-param">db</span>, zval ** <span class="fn-param">username</span>, zval ** <span class="fn-param">password</span>, INTERNAL_FUNCTION_PARAMETERS);
-// int: returns 0 on connect-failure and 1 on success
-// rv: connection handle as resource on success or nothing on failure
-</pre>
-dbx_blabla_connect creates a connection to a database on a specified host, using username and password for authentication. This may be done by connecting to a server and selecting a database (as mysql does), or connecting to a specific database directly (as in ODBC). <br>
-What must be returned (in <span class="bold">rv</span>) is the link identifier that is returned from the blabla_connect function, in it's native form so the end-user can use $db-&gt;handle to call other blabla_* functions that expect this parameter.<br>
-What must be returned from the function is a 1 on success and a 0 on failure. Remember that a failed database selection can still return a 1 because the connection succeeded!<br>
-The host (string) is the name of the machine the server is run on, but it may be empty if a database name is enough to establish a connection.<br>
-The db (string) is the name of the database to select, or, for e.g. ODBC, the identifier that is needed to actually select the database.<br>
-The username (string) and password (string) are used for authentication.<br>
-<a name="pconnect"></a><pre class="code">
-int <span class="fn-name">dbx_blabla_pconnect</span>(zval ** rv, zval ** <span class="fn-param">host</span>, zval ** <span class="fn-param">db</span>, zval ** <span class="fn-param">username</span>, zval ** <span class="fn-param">password</span>, INTERNAL_FUNCTION_PARAMETERS);
-// int: returns 0 on pconnect-failure and 1 on success
-// rv: persistent connection handle as resource on success or nothing
-// on failure
-</pre>
-dbx_blabla_pconnect is identical to dbx_blabla_connect except that it will create a persistent connection.<br>
-<a name="close"></a><pre class="code">
-int <span class="fn-name">dbx_blabla_close</span>(zval ** rv, zval ** <span class="fn-param">dbx_handle</span>, INTERNAL_FUNCTION_PARAMETERS);
-// int: returns 0 on close-failure and 1 on success
-// rv: 1 as bool on success or nothing on failure
-</pre>
-dbx_blabla_close closes an open connection, whether it was created persistently or not.<br>
-What must be returned (in <span class="bold">rv</span>) is a boolean true that indicates when the connection was closed successfully. If it wasn't, no value is returned in <span class="bold">rv</span>.<br>
-What must be returned from the function is a 1 on success and a 0 on failure. Note that an unsuccessful close is still a succeeded function call.<br>
-The dbx_handle is the same value that you returned from dbx_blabla_connect or dbx_blabla_pconnect.<br>
-<a name="query"></a><pre class="code">
-int <span class="fn-name">dbx_blabla_query</span>(zval ** rv, zval ** <span class="fn-param">dbx_handle</span>, zval ** <span class="fn-param">sql_statement</span>, INTERNAL_FUNCTION_PARAMETERS);
-// int: returns 0 on query-failure and 1 on success
-// rv: 1 as bool or a result identifier as resource on success
-// or nothing on failure
-</pre>
-dbx_blabla_query executes an SQL statement over the connection.<br>
-What must be returned (in <span class="bold">rv</span>) is a nothing on failure, on success it must return either a boolean 1 for queries that don't return data (like INSERT INTO) or a native result-handle for queries that do return data (SELECT). The native result handle ($q-&gt;handle) can be used by the end-user to call other blabla_* functions that expect this parameter.<br>
-What must be returned from the function is a 1 on success and a 0 on failure. Note that a failed query execution can still return a 1 because the query function succeeded!<br>
-The dbx_handle is the same value that you returned from dbx_blabla_connect or dbx_blabla_pconnect.<br>
-The sql_statement (string) can have any value.<br>
-<a name="getcolumncount"></a><pre class="code">
-int <span class="fn-name">dbx_blabla_getcolumncount</span>(zval ** rv, zval ** <span class="fn-param">result_handle</span>, INTERNAL_FUNCTION_PARAMETERS);
-// int: returns 0 on query-failure and 1 on success
-// returns column-count as long on success or nothing on failure
-</pre>
-dbx_blabla_getcolumncount gets the number of fields that the query-result contains.<br>
-What must be returned (in <span class="bold">rv</span>) is the number of fields as long from the query result specified by the result_handle.<br>
-What must be returned from the function is a 1 on success and a 0 on failure. <br>
-The result_handle is the same value that you returned from dbx_query.<br>
-<a name="getcolumnname"></a><pre class="code">
-int <span class="fn-name">dbx_blabla_getcolumnname</span>(zval ** rv, zval ** <span class="fn-param">result_handle</span>, long <span class="fn-param">column_index</span>, INTERNAL_FUNCTION_PARAMETERS);
-// int: returns 0 on failure and 1 on success
-// returns column-name as string on success or nothing on failure
-</pre>
-dbx_blabla_getcolumnname gets the fieldname of the specified column.<br>
-What must be returned (in <span class="bold">rv</span>) is the fieldname as string of the given column.<br>
-What must be returned from the function is a 1 on success and a 0 on failure. <br>
-The result_handle is the same value that you returned from dbx_query.<br>
-The column_index is a long that ranges from 0 to the value you returned from dbx_blabla_getcolumncount minus 1 [0..columncount-1].<br>
-<a name="getcolumntype"></a><pre class="code">
-int <span class="fn-name">dbx_blabla_getcolumntype</span>(zval ** rv, zval ** <span class="fn-param">result_handle</span>, long <span class="fn-param">column_index</span>, INTERNAL_FUNCTION_PARAMETERS);
-// int: returns 0 on failure and 1 on success
-// returns column-type as string on success or nothing on failure
-</pre>
-dbx_blabla_getcolumnname gets the field type of the specified column.<br>
-What must be returned (in <span class="bold">rv</span>) is the field type as string of the given column.<br>
-What must be returned from the function is a 1 on success and a 0 on failure. <br>
-The result_handle is the same value that you returned from dbx_query.<br>
-The column_index is a long that ranges from 0 to the value you returned from dbx_blabla_getcolumncount minus 1 [0..columncount-1].<br>
-<a name="getrow"></a><pre class="code">
-int <span class="fn-name">dbx_blabla_getrow</span>(zval ** rv, zval ** <span class="fn-param">result_handle</span>, long <span class="fn-param">row_number</span>, INTERNAL_FUNCTION_PARAMETERS);
-// int: returns 0 on failure and 1 on success
-// returns array[0..columncount-1] as strings on success or 0 as long
-// on failure
-</pre>
-dbx_blabla_getrow gets the next row from the query-results.<br>
-In some cases (PostgreSQL) the rownumber is needed to actually fetch the row. This will be provided (it will be indexed starting at 0) by the dbx_query function. In other cases it is not needed and thus not used.<br>
-What must be returned (in <span class="bold">rv</span>) is an indexed array[0..columncount-1] of strings, containing the data from the row (for mysql this is easy since it already performs this way, for ODBC the array has to be constructed inside this function from a loop that fetches the data for each column).<br>
-What must be returned from the function is a 1 on success and a 0 on failure (function failed or there are no more rows available). <br>
-The result_handle is the same value that you returned from dbx_query.<br>
-<a name="error"></a><pre class="code">
-int <span class="fn-name">dbx_blabla_error</span>(zval ** rv, zval ** <span class="fn-param">dbx_handle</span>, INTERNAL_FUNCTION_PARAMETERS);
-// int: returns 0 on failure and 1 on success
-// returns error message as string
-</pre>
-dbx_blabla_error gets the error message from the last database call.<br>
-What must be returned (in <span class="bold">rv</span>) is the error message as a string.<br>
-What must be returned from the function is a 1 on success and a 0 on failure. <br>
-The dbx_handle is the same value that you returned from dbx_blabla_connect or dbx_blabla_pconnect.<br>
-</div>
-<p>
-<a href="#top">top</a><br>
-<div class="newpage"></div>
-<p>
-<div class="text">
-For specifics or the finer details you can always refer to dbx_mysql.c and dbx_odbc.c to see everything in action. <br>
-More Zend API documentation can be found at <a href="http://www.zend.com/apidoc">http://www.zend.com/apidoc</a>.<br>
-This document can be found at <a href="http://www.guidance.nl/php/dbx">http://www.guidance.nl/php/dbx</a>.<br>
-</div>
-<p>
-<a href="#top">top</a><br>
-<div class="newpage"></div>
-
-</body>
-</html>