Back to index

php5  5.3.10
php_mysql.c
Go to the documentation of this file.
00001 /*
00002    +----------------------------------------------------------------------+
00003    | PHP Version 5                                                        |
00004    +----------------------------------------------------------------------+
00005    | Copyright (c) 1997-2012 The PHP Group                                |
00006    +----------------------------------------------------------------------+
00007    | This source file is subject to version 3.01 of the PHP license,      |
00008    | that is bundled with this package in the file LICENSE, and is        |
00009    | available through the world-wide-web at the following url:           |
00010    | http://www.php.net/license/3_01.txt                                  |
00011    | If you did not receive a copy of the PHP license and are unable to   |
00012    | obtain it through the world-wide-web, please send a note to          |
00013    | license@php.net so we can mail you a copy immediately.               |
00014    +----------------------------------------------------------------------+
00015    | Authors: Zeev Suraski <zeev@zend.com>                                |
00016    |          Zak Greant <zak@mysql.com>                                  |
00017    |          Georg Richter <georg@php.net>                               |
00018    +----------------------------------------------------------------------+
00019 */
00020 
00021 /* $Id: php_mysql.c 321634 2012-01-01 13:15:04Z felipe $ */
00022 
00023 /* TODO:
00024  *
00025  * ? Safe mode implementation
00026  */
00027 
00028 #ifdef HAVE_CONFIG_H
00029 # include "config.h"
00030 #endif
00031 
00032 #include "php.h"
00033 #include "php_globals.h"
00034 #include "ext/standard/info.h"
00035 #include "ext/standard/php_string.h"
00036 #include "ext/standard/basic_functions.h"
00037 
00038 #ifdef ZEND_ENGINE_2
00039 # include "zend_exceptions.h"
00040 #else
00041   /* PHP 4 compat */
00042 # define OnUpdateLong       OnUpdateInt
00043 # define E_STRICT           E_NOTICE
00044 #endif
00045 
00046 #if HAVE_MYSQL
00047 
00048 #ifdef PHP_WIN32
00049 # include <winsock2.h>
00050 # define signal(a, b) NULL
00051 #elif defined(NETWARE)
00052 # include <sys/socket.h>
00053 # define signal(a, b) NULL
00054 #else
00055 # if HAVE_SIGNAL_H
00056 #  include <signal.h>
00057 # endif
00058 # if HAVE_SYS_TYPES_H
00059 #  include <sys/types.h>
00060 # endif
00061 # include <netdb.h>
00062 # include <netinet/in.h>
00063 # if HAVE_ARPA_INET_H
00064 #  include <arpa/inet.h>
00065 # endif
00066 #endif
00067 
00068 #include "php_ini.h"
00069 #include "php_mysql_structs.h"
00070 
00071 /* True globals, no need for thread safety */
00072 static int le_result, le_link, le_plink;
00073 
00074 #ifdef HAVE_MYSQL_REAL_CONNECT
00075 # ifdef HAVE_ERRMSG_H
00076 #  include <errmsg.h>
00077 # endif
00078 #endif
00079 
00080 #define SAFE_STRING(s) ((s)?(s):"")
00081 
00082 #if MYSQL_VERSION_ID > 32199 || defined(MYSQL_USE_MYSQLND)
00083 # define mysql_row_length_type unsigned long
00084 # define HAVE_MYSQL_ERRNO
00085 #else
00086 # define mysql_row_length_type unsigned int
00087 # ifdef mysql_errno
00088 #  define HAVE_MYSQL_ERRNO
00089 # endif
00090 #endif
00091 
00092 #if MYSQL_VERSION_ID >= 32032 || defined(MYSQL_USE_MYSQLND)
00093 #define HAVE_GETINFO_FUNCS
00094 #endif
00095 
00096 #if MYSQL_VERSION_ID > 32133 || defined(FIELD_TYPE_TINY)
00097 #define MYSQL_HAS_TINY
00098 #endif
00099 
00100 #if MYSQL_VERSION_ID >= 32200
00101 #define MYSQL_HAS_YEAR
00102 #endif
00103 
00104 #define MYSQL_ASSOC         1<<0
00105 #define MYSQL_NUM           1<<1
00106 #define MYSQL_BOTH          (MYSQL_ASSOC|MYSQL_NUM)
00107 
00108 #define MYSQL_USE_RESULT    0
00109 #define MYSQL_STORE_RESULT  1
00110 
00111 #if MYSQL_VERSION_ID < 32224
00112 #define PHP_MYSQL_VALID_RESULT(mysql)            \
00113        (mysql_num_fields(mysql)>0)
00114 #else
00115 #define PHP_MYSQL_VALID_RESULT(mysql)            \
00116        (mysql_field_count(mysql)>0)
00117 #endif
00118 
00119 ZEND_DECLARE_MODULE_GLOBALS(mysql)
00120 static PHP_GINIT_FUNCTION(mysql);
00121 
00122 typedef struct _php_mysql_conn {
00123        MYSQL *conn;
00124        int active_result_id;
00125        int multi_query;
00126 } php_mysql_conn;
00127 
00128 
00129 #if MYSQL_VERSION_ID >= 40101
00130 #define MYSQL_DISABLE_MQ if (mysql->multi_query) { \
00131        mysql_set_server_option(mysql->conn, MYSQL_OPTION_MULTI_STATEMENTS_OFF); \
00132        mysql->multi_query = 0; \
00133 }
00134 #else
00135 #define MYSQL_DISABLE_MQ
00136 #endif
00137 
00138 /* {{{ arginfo */
00139 ZEND_BEGIN_ARG_INFO_EX(arginfo_mysql_connect, 0, 0, 0)
00140        ZEND_ARG_INFO(0, hostname)
00141        ZEND_ARG_INFO(0, username)
00142        ZEND_ARG_INFO(0, password)
00143        ZEND_ARG_INFO(0, new)
00144        ZEND_ARG_INFO(0, flags)
00145 ZEND_END_ARG_INFO()
00146 
00147 ZEND_BEGIN_ARG_INFO_EX(arginfo_mysql_pconnect, 0, 0, 0)
00148        ZEND_ARG_INFO(0, hostname)
00149        ZEND_ARG_INFO(0, username)
00150        ZEND_ARG_INFO(0, password)
00151        ZEND_ARG_INFO(0, flags)
00152 ZEND_END_ARG_INFO()
00153 
00154 ZEND_BEGIN_ARG_INFO_EX(arginfo__optional_mysql_link, 0, 0, 0)
00155        ZEND_ARG_INFO(0, link_identifier)
00156 ZEND_END_ARG_INFO()
00157 
00158 ZEND_BEGIN_ARG_INFO_EX(arginfo_mysql_select_db, 0, 0, 1)
00159        ZEND_ARG_INFO(0, database_name)
00160        ZEND_ARG_INFO(0, link_identifier)
00161 ZEND_END_ARG_INFO()
00162 
00163 ZEND_BEGIN_ARG_INFO(arginfo__void_mysql_arg, 0)
00164 ZEND_END_ARG_INFO()
00165 
00166 ZEND_BEGIN_ARG_INFO_EX(arginfo_mysql_set_charset, 0, 0, 1)
00167        ZEND_ARG_INFO(0, charset_name)
00168        ZEND_ARG_INFO(0, link_identifier)
00169 ZEND_END_ARG_INFO()
00170 
00171 ZEND_BEGIN_ARG_INFO_EX(arginfo_mysql_query, 0, 0, 1)
00172        ZEND_ARG_INFO(0, query)
00173        ZEND_ARG_INFO(0, link_identifier)
00174 ZEND_END_ARG_INFO()
00175 
00176 ZEND_BEGIN_ARG_INFO_EX(arginfo_mysql_db_query, 0, 0, 2)
00177        ZEND_ARG_INFO(0, database_name)
00178        ZEND_ARG_INFO(0, query)
00179        ZEND_ARG_INFO(0, link_identifier)
00180 ZEND_END_ARG_INFO()
00181 
00182 ZEND_BEGIN_ARG_INFO_EX(arginfo_mysql_list_fields, 0, 0, 2)
00183        ZEND_ARG_INFO(0, database_name)
00184        ZEND_ARG_INFO(0, table_name)
00185        ZEND_ARG_INFO(0, link_identifier)
00186 ZEND_END_ARG_INFO()
00187 
00188 ZEND_BEGIN_ARG_INFO_EX(arginfo_mysql_escape_string, 0, 0, 1)
00189        ZEND_ARG_INFO(0, string)
00190 ZEND_END_ARG_INFO()
00191 
00192 ZEND_BEGIN_ARG_INFO_EX(arginfo_mysql_real_escape_string, 0, 0, 1)
00193        ZEND_ARG_INFO(0, string)
00194        ZEND_ARG_INFO(0, link_identifier)
00195 ZEND_END_ARG_INFO()
00196 
00197 ZEND_BEGIN_ARG_INFO_EX(arginfo_mysql_result, 0, 0, 2)
00198        ZEND_ARG_INFO(0, result)
00199        ZEND_ARG_INFO(0, row)
00200        ZEND_ARG_INFO(0, field)
00201 ZEND_END_ARG_INFO()
00202 
00203 ZEND_BEGIN_ARG_INFO_EX(arginfo__result_mysql_arg, 0, 0, 1)
00204        ZEND_ARG_INFO(0, result)
00205 ZEND_END_ARG_INFO()
00206 
00207 ZEND_BEGIN_ARG_INFO_EX(arginfo_mysql_fetch_object, 0, 0, 1)
00208        ZEND_ARG_INFO(0, result)
00209        ZEND_ARG_INFO(0, class_name)
00210        ZEND_ARG_INFO(0, ctor_params)
00211 ZEND_END_ARG_INFO()
00212 
00213 ZEND_BEGIN_ARG_INFO_EX(arginfo_mysql_fetch_array, 0, 0, 1)
00214        ZEND_ARG_INFO(0, result)
00215        ZEND_ARG_INFO(0, result_type)
00216 ZEND_END_ARG_INFO()
00217 
00218 ZEND_BEGIN_ARG_INFO_EX(arginfo_mysql_data_seek, 0, 0, 2)
00219        ZEND_ARG_INFO(0, result)
00220        ZEND_ARG_INFO(0, row_number)
00221 ZEND_END_ARG_INFO()
00222 
00223 ZEND_BEGIN_ARG_INFO_EX(arginfo_mysql_fetch_field, 0, 0, 1)
00224        ZEND_ARG_INFO(0, result)
00225        ZEND_ARG_INFO(0, field_offset)
00226 ZEND_END_ARG_INFO()
00227 
00228 ZEND_BEGIN_ARG_INFO_EX(arginfo_mysql_field_seek, 0, 0, 2)
00229        ZEND_ARG_INFO(0, result)
00230        ZEND_ARG_INFO(0, field_offset)
00231 ZEND_END_ARG_INFO()
00232 
00233 ZEND_BEGIN_ARG_INFO_EX(arginfo_mysql_field_name, 0, 0, 2)
00234        ZEND_ARG_INFO(0, result)
00235        ZEND_ARG_INFO(0, field_index)
00236 ZEND_END_ARG_INFO()
00237 /* }}} */
00238 
00239 /* {{{ mysql_functions[]
00240  */
00241 static const zend_function_entry mysql_functions[] = {
00242        PHP_FE(mysql_connect,                                                        arginfo_mysql_connect)
00243        PHP_FE(mysql_pconnect,                                                       arginfo_mysql_pconnect)
00244        PHP_FE(mysql_close,                                                          arginfo__optional_mysql_link)
00245        PHP_FE(mysql_select_db,                                                      arginfo_mysql_select_db)
00246 #ifndef NETWARE             /* The below two functions not supported on NetWare */
00247 #if MYSQL_VERSION_ID < 40000
00248        PHP_DEP_FE(mysql_create_db,                                           arginfo_mysql_select_db)
00249        PHP_DEP_FE(mysql_drop_db,                                             arginfo_mysql_select_db)
00250 #endif
00251 #endif /* NETWARE */
00252        PHP_FE(mysql_query,                                                          arginfo_mysql_query)
00253        PHP_FE(mysql_unbuffered_query,                                        arginfo_mysql_query)
00254        PHP_DEP_FE(mysql_db_query,                                            arginfo_mysql_db_query)
00255        PHP_FE(mysql_list_dbs,                                                       arginfo__optional_mysql_link)
00256        PHP_DEP_FE(mysql_list_tables,                                         arginfo_mysql_select_db)
00257        PHP_FE(mysql_list_fields,                                             arginfo_mysql_list_fields)
00258        PHP_FE(mysql_list_processes,                                          arginfo__optional_mysql_link)
00259        PHP_FE(mysql_error,                                                          arginfo__optional_mysql_link)
00260 #ifdef HAVE_MYSQL_ERRNO
00261        PHP_FE(mysql_errno,                                                          arginfo__optional_mysql_link)
00262 #endif
00263        PHP_FE(mysql_affected_rows,                                           arginfo__optional_mysql_link)
00264        PHP_FE(mysql_insert_id,                                                      arginfo__optional_mysql_link)
00265        PHP_FE(mysql_result,                                                  arginfo_mysql_result)
00266        PHP_FE(mysql_num_rows,                                                       arginfo__result_mysql_arg)
00267        PHP_FE(mysql_num_fields,                                              arginfo__result_mysql_arg)
00268        PHP_FE(mysql_fetch_row,                                                      arginfo__result_mysql_arg)
00269        PHP_FE(mysql_fetch_array,                                             arginfo_mysql_fetch_array)
00270        PHP_FE(mysql_fetch_assoc,                                             arginfo__result_mysql_arg)
00271        PHP_FE(mysql_fetch_object,                                            arginfo_mysql_fetch_object)
00272        PHP_FE(mysql_data_seek,                                                      arginfo_mysql_data_seek)
00273        PHP_FE(mysql_fetch_lengths,                                           arginfo__result_mysql_arg)
00274        PHP_FE(mysql_fetch_field,                                             arginfo_mysql_fetch_field)
00275        PHP_FE(mysql_field_seek,                                              arginfo_mysql_field_seek)
00276        PHP_FE(mysql_free_result,                                             arginfo__result_mysql_arg)
00277        PHP_FE(mysql_field_name,                                              arginfo_mysql_field_name)
00278        PHP_FE(mysql_field_table,                                             arginfo_mysql_field_seek)
00279        PHP_FE(mysql_field_len,                                                      arginfo_mysql_field_seek)
00280        PHP_FE(mysql_field_type,                                              arginfo_mysql_field_seek)
00281        PHP_FE(mysql_field_flags,                                             arginfo_mysql_field_seek)
00282        PHP_FE(mysql_escape_string,                                           arginfo_mysql_escape_string)
00283        PHP_FE(mysql_real_escape_string,                               arginfo_mysql_real_escape_string)
00284        PHP_FE(mysql_stat,                                                           arginfo__optional_mysql_link)
00285        PHP_FE(mysql_thread_id,                                                      arginfo__optional_mysql_link)
00286        PHP_FE(mysql_client_encoding,                                         arginfo__optional_mysql_link)
00287        PHP_FE(mysql_ping,                                                           arginfo__optional_mysql_link)
00288 #ifdef HAVE_GETINFO_FUNCS
00289        PHP_FE(mysql_get_client_info,                                         arginfo__void_mysql_arg)
00290        PHP_FE(mysql_get_host_info,                                           arginfo__optional_mysql_link)
00291        PHP_FE(mysql_get_proto_info,                                          arginfo__optional_mysql_link)
00292        PHP_FE(mysql_get_server_info,                                         arginfo__optional_mysql_link)
00293 #endif
00294 
00295        PHP_FE(mysql_info,                                                           arginfo__optional_mysql_link)
00296 #ifdef MYSQL_HAS_SET_CHARSET
00297        PHP_FE(mysql_set_charset,                                             arginfo_mysql_set_charset)
00298 #endif
00299        /* for downwards compatability */
00300        PHP_FALIAS(mysql,                         mysql_db_query,             arginfo_mysql_db_query)
00301        PHP_FALIAS(mysql_fieldname,        mysql_field_name,    arginfo_mysql_field_name)
00302        PHP_FALIAS(mysql_fieldtable,       mysql_field_table,   arginfo_mysql_field_seek)
00303        PHP_FALIAS(mysql_fieldlen,         mysql_field_len,     arginfo_mysql_field_seek)
00304        PHP_FALIAS(mysql_fieldtype,        mysql_field_type,    arginfo_mysql_field_seek)
00305        PHP_FALIAS(mysql_fieldflags,       mysql_field_flags,   arginfo_mysql_field_seek)
00306        PHP_FALIAS(mysql_selectdb,         mysql_select_db,     arginfo_mysql_select_db)
00307 #ifndef NETWARE             /* The below two functions not supported on NetWare */
00308 #if MYSQL_VERSION_ID < 40000
00309        PHP_DEP_FALIAS(mysql_createdb,     mysql_create_db,     arginfo_mysql_select_db)
00310        PHP_DEP_FALIAS(mysql_dropdb,       mysql_drop_db,              arginfo_mysql_select_db)
00311 #endif
00312 #endif /* NETWARE */
00313        PHP_FALIAS(mysql_freeresult,       mysql_free_result,   arginfo__result_mysql_arg)
00314        PHP_FALIAS(mysql_numfields,        mysql_num_fields,    arginfo__result_mysql_arg)
00315        PHP_FALIAS(mysql_numrows,          mysql_num_rows,             arginfo__result_mysql_arg)
00316        PHP_FALIAS(mysql_listdbs,          mysql_list_dbs,             arginfo__optional_mysql_link)
00317        PHP_DEP_FALIAS(mysql_listtables,mysql_list_tables,      arginfo_mysql_select_db)
00318        PHP_FALIAS(mysql_listfields,       mysql_list_fields,   arginfo_mysql_list_fields)
00319        PHP_FALIAS(mysql_db_name,          mysql_result,        arginfo_mysql_result)
00320        PHP_FALIAS(mysql_dbname,           mysql_result,        arginfo_mysql_result)
00321        PHP_FALIAS(mysql_tablename,        mysql_result,        arginfo_mysql_result)
00322        PHP_FALIAS(mysql_table_name,       mysql_result,        arginfo_mysql_result)
00323        PHP_FE_END
00324 };
00325 /* }}} */
00326 
00327 /* Dependancies */
00328 static const zend_module_dep mysql_deps[] = {
00329 #if defined(MYSQL_USE_MYSQLND)
00330        ZEND_MOD_REQUIRED("mysqlnd")
00331 #endif
00332        ZEND_MOD_END
00333 };
00334 
00335 /* {{{ mysql_module_entry
00336  */
00337 zend_module_entry mysql_module_entry = {
00338 #if ZEND_MODULE_API_NO >= 20050922
00339        STANDARD_MODULE_HEADER_EX, NULL,
00340        mysql_deps,
00341 #elif ZEND_MODULE_API_NO >= 20010901
00342        STANDARD_MODULE_HEADER,
00343 #endif
00344        "mysql",
00345        mysql_functions,
00346        ZEND_MODULE_STARTUP_N(mysql),
00347        PHP_MSHUTDOWN(mysql),
00348        PHP_RINIT(mysql),
00349        PHP_RSHUTDOWN(mysql),
00350        PHP_MINFO(mysql),
00351        "1.0",
00352        PHP_MODULE_GLOBALS(mysql),
00353        PHP_GINIT(mysql),
00354        NULL,
00355        NULL,
00356        STANDARD_MODULE_PROPERTIES_EX
00357 };
00358 /* }}} */
00359 
00360 #ifdef COMPILE_DL_MYSQL
00361 ZEND_GET_MODULE(mysql)
00362 #endif
00363 
00364 void timeout(int sig);
00365 
00366 #define CHECK_LINK(link) { if (link==-1) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "A link to the server could not be established"); RETURN_FALSE; } }
00367 
00368 #if defined(MYSQL_USE_MYSQLND)
00369 #define PHPMY_UNBUFFERED_QUERY_CHECK() \
00370 {\
00371        if (mysql->active_result_id) { \
00372               do {                               \
00373                      int type;                   \
00374                      MYSQL_RES *_mysql_result;   \
00375                                                  \
00376                      _mysql_result = (MYSQL_RES *) zend_list_find(mysql->active_result_id, &type);       \
00377                      if (_mysql_result && type==le_result) {                                      \
00378                             if (mysql_result_is_unbuffered(_mysql_result) && !mysql_eof(_mysql_result)) { \
00379                                    php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Function called without first fetching all rows from a previous unbuffered query");      \
00380                             }                                         \
00381                             zend_list_delete(mysql->active_result_id);       \
00382                             mysql->active_result_id = 0;                     \
00383                      } \
00384               } while(0); \
00385        }\
00386 }
00387 #else
00388 #define PHPMY_UNBUFFERED_QUERY_CHECK()                  \
00389 {                                                \
00390        if (mysql->active_result_id) {                   \
00391               do {                               \
00392                      int type;                   \
00393                      MYSQL_RES *mysql_result;    \
00394                                                  \
00395                      mysql_result = (MYSQL_RES *) zend_list_find(mysql->active_result_id, &type); \
00396                      if (mysql_result && type==le_result) {                                       \
00397                             if (!mysql_eof(mysql_result)) {                                       \
00398                                    php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Function called without first fetching all rows from a previous unbuffered query");      \
00399                                    while (mysql_fetch_row(mysql_result));    \
00400                             }                                         \
00401                             zend_list_delete(mysql->active_result_id);       \
00402                             mysql->active_result_id = 0;                     \
00403                      }                                                \
00404               } while(0);                                             \
00405        }                                                              \
00406 }
00407 #endif
00408 
00409 /* {{{ _free_mysql_result
00410  * This wrapper is required since mysql_free_result() returns an integer, and
00411  * thus, cannot be used directly
00412  */
00413 static void _free_mysql_result(zend_rsrc_list_entry *rsrc TSRMLS_DC)
00414 {
00415        MYSQL_RES *mysql_result = (MYSQL_RES *)rsrc->ptr;
00416 
00417        mysql_free_result(mysql_result);
00418        MySG(result_allocated)--;
00419 }
00420 /* }}} */
00421 
00422 /* {{{ php_mysql_set_default_link
00423  */
00424 static void php_mysql_set_default_link(int id TSRMLS_DC)
00425 {
00426        if (MySG(default_link) != -1) {
00427               zend_list_delete(MySG(default_link));
00428        }
00429        MySG(default_link) = id;
00430        zend_list_addref(id);
00431 }
00432 /* }}} */
00433 
00434 /* {{{ php_mysql_select_db
00435 */
00436 static int php_mysql_select_db(php_mysql_conn *mysql, char *db TSRMLS_DC)
00437 {
00438        PHPMY_UNBUFFERED_QUERY_CHECK();
00439 
00440        if (mysql_select_db(mysql->conn, db) != 0) {
00441               return 0;
00442        } else {
00443               return 1;
00444        }
00445 }
00446 /* }}} */
00447 
00448 /* {{{ _close_mysql_link
00449  */
00450 static void _close_mysql_link(zend_rsrc_list_entry *rsrc TSRMLS_DC)
00451 {
00452        php_mysql_conn *link = (php_mysql_conn *)rsrc->ptr;
00453        void (*handler) (int);
00454 
00455        handler = signal(SIGPIPE, SIG_IGN);
00456        mysql_close(link->conn);
00457        signal(SIGPIPE, handler);
00458        efree(link);
00459        MySG(num_links)--;
00460 }
00461 /* }}} */
00462 
00463 /* {{{ _close_mysql_plink
00464  */
00465 static void _close_mysql_plink(zend_rsrc_list_entry *rsrc TSRMLS_DC)
00466 {
00467        php_mysql_conn *link = (php_mysql_conn *)rsrc->ptr;
00468        void (*handler) (int);
00469 
00470        handler = signal(SIGPIPE, SIG_IGN);
00471        mysql_close(link->conn);
00472        signal(SIGPIPE, handler);
00473 
00474        free(link);
00475        MySG(num_persistent)--;
00476        MySG(num_links)--;
00477 }
00478 /* }}} */
00479 
00480 /* {{{ PHP_INI_MH
00481  */
00482 static PHP_INI_MH(OnMySQLPort)
00483 {
00484        if (new_value != NULL) { /* default port */
00485               MySG(default_port) = atoi(new_value);
00486        } else {
00487               MySG(default_port) = -1;
00488        }
00489 
00490        return SUCCESS;
00491 }
00492 /* }}} */
00493 
00494 /* {{{ PHP_INI */
00495 PHP_INI_BEGIN()
00496        STD_PHP_INI_BOOLEAN("mysql.allow_persistent",    "1",   PHP_INI_SYSTEM,             OnUpdateLong,        allow_persistent,    zend_mysql_globals,         mysql_globals)
00497        STD_PHP_INI_ENTRY_EX("mysql.max_persistent",     "-1",  PHP_INI_SYSTEM,             OnUpdateLong,        max_persistent,             zend_mysql_globals,         mysql_globals,       display_link_numbers)
00498        STD_PHP_INI_ENTRY_EX("mysql.max_links",                 "-1",  PHP_INI_SYSTEM,             OnUpdateLong,        max_links,                  zend_mysql_globals,         mysql_globals,       display_link_numbers)
00499        STD_PHP_INI_ENTRY("mysql.default_host",                 NULL,  PHP_INI_ALL,         OnUpdateString,             default_host,        zend_mysql_globals,         mysql_globals)
00500        STD_PHP_INI_ENTRY("mysql.default_user",                 NULL,  PHP_INI_ALL,         OnUpdateString,             default_user,        zend_mysql_globals,         mysql_globals)
00501        STD_PHP_INI_ENTRY("mysql.default_password",             NULL,  PHP_INI_ALL,         OnUpdateString,             default_password,    zend_mysql_globals,         mysql_globals)
00502        PHP_INI_ENTRY("mysql.default_port",                            NULL,  PHP_INI_ALL,         OnMySQLPort)
00503 #ifdef MYSQL_UNIX_ADDR
00504        STD_PHP_INI_ENTRY("mysql.default_socket",        MYSQL_UNIX_ADDR,PHP_INI_ALL,OnUpdateStringUnempty,      default_socket,      zend_mysql_globals,         mysql_globals)
00505 #else
00506        STD_PHP_INI_ENTRY("mysql.default_socket",        NULL,  PHP_INI_ALL,         OnUpdateStringUnempty,      default_socket,      zend_mysql_globals,         mysql_globals)
00507 #endif
00508        STD_PHP_INI_ENTRY("mysql.connect_timeout",              "60",  PHP_INI_ALL,         OnUpdateLong,        connect_timeout,     zend_mysql_globals,         mysql_globals)
00509        STD_PHP_INI_BOOLEAN("mysql.trace_mode",                 "0",   PHP_INI_ALL,         OnUpdateLong,        trace_mode,          zend_mysql_globals,         mysql_globals)
00510        STD_PHP_INI_BOOLEAN("mysql.allow_local_infile",  "1",   PHP_INI_SYSTEM,             OnUpdateLong,        allow_local_infile, zend_mysql_globals,          mysql_globals)
00511 PHP_INI_END()
00512 /* }}} */
00513 
00514 /* {{{ PHP_GINIT_FUNCTION
00515  */
00516 static PHP_GINIT_FUNCTION(mysql)
00517 {
00518        mysql_globals->num_persistent = 0;
00519        mysql_globals->default_socket = NULL;
00520        mysql_globals->default_host = NULL;
00521        mysql_globals->default_user = NULL;
00522        mysql_globals->default_password = NULL;
00523        mysql_globals->connect_errno = 0;
00524        mysql_globals->connect_error = NULL;
00525        mysql_globals->connect_timeout = 0;
00526        mysql_globals->trace_mode = 0;
00527        mysql_globals->allow_local_infile = 1;
00528        mysql_globals->result_allocated = 0;
00529 }
00530 /* }}} */
00531 
00532 /* {{{ PHP_MINIT_FUNCTION
00533  */
00534 ZEND_MODULE_STARTUP_D(mysql)
00535 {
00536        REGISTER_INI_ENTRIES();
00537        le_result = zend_register_list_destructors_ex(_free_mysql_result, NULL, "mysql result", module_number);
00538        le_link = zend_register_list_destructors_ex(_close_mysql_link, NULL, "mysql link", module_number);
00539        le_plink = zend_register_list_destructors_ex(NULL, _close_mysql_plink, "mysql link persistent", module_number);
00540        Z_TYPE(mysql_module_entry) = type;
00541 
00542        REGISTER_LONG_CONSTANT("MYSQL_ASSOC", MYSQL_ASSOC, CONST_CS | CONST_PERSISTENT);
00543        REGISTER_LONG_CONSTANT("MYSQL_NUM", MYSQL_NUM, CONST_CS | CONST_PERSISTENT);
00544        REGISTER_LONG_CONSTANT("MYSQL_BOTH", MYSQL_BOTH, CONST_CS | CONST_PERSISTENT);
00545        REGISTER_LONG_CONSTANT("MYSQL_CLIENT_COMPRESS", CLIENT_COMPRESS, CONST_CS | CONST_PERSISTENT);
00546 #if MYSQL_VERSION_ID >= 40000
00547        REGISTER_LONG_CONSTANT("MYSQL_CLIENT_SSL", CLIENT_SSL, CONST_CS | CONST_PERSISTENT);
00548 #endif
00549        REGISTER_LONG_CONSTANT("MYSQL_CLIENT_INTERACTIVE", CLIENT_INTERACTIVE, CONST_CS | CONST_PERSISTENT);
00550        REGISTER_LONG_CONSTANT("MYSQL_CLIENT_IGNORE_SPACE", CLIENT_IGNORE_SPACE, CONST_CS | CONST_PERSISTENT);
00551 
00552 #ifndef MYSQL_USE_MYSQLND
00553 #if MYSQL_VERSION_ID >= 40000
00554        if (mysql_server_init(0, NULL, NULL)) {
00555               return FAILURE;
00556        }
00557 #endif
00558 #endif
00559 
00560        return SUCCESS;
00561 }
00562 /* }}} */
00563 
00564 /* {{{ PHP_MSHUTDOWN_FUNCTION
00565  */
00566 PHP_MSHUTDOWN_FUNCTION(mysql)
00567 {
00568 #ifndef MYSQL_USE_MYSQLND
00569 #if MYSQL_VERSION_ID >= 40000
00570 #ifdef PHP_WIN32
00571        unsigned long client_ver = mysql_get_client_version();
00572        /*
00573          Can't call mysql_server_end() multiple times prior to 5.0.46 on Windows.
00574          PHP bug#41350 MySQL bug#25621
00575        */
00576        if ((client_ver >= 50046 && client_ver < 50100) || client_ver > 50122) {
00577               mysql_server_end();
00578        }
00579 #else
00580        mysql_server_end();
00581 #endif
00582 #endif
00583 #endif
00584 
00585        UNREGISTER_INI_ENTRIES();
00586        return SUCCESS;
00587 }
00588 /* }}} */
00589 
00590 /* {{{ PHP_RINIT_FUNCTION
00591  */
00592 PHP_RINIT_FUNCTION(mysql)
00593 {
00594 #if !defined(MYSQL_USE_MYSQLND) && defined(ZTS) && MYSQL_VERSION_ID >= 40000
00595        if (mysql_thread_init()) {
00596               return FAILURE;
00597        }
00598 #endif
00599        MySG(default_link)=-1;
00600        MySG(num_links) = MySG(num_persistent);
00601        /* Reset connect error/errno on every request */
00602        MySG(connect_error) = NULL;
00603        MySG(connect_errno) =0;
00604        MySG(result_allocated) = 0;
00605 
00606        return SUCCESS;
00607 }
00608 /* }}} */
00609 
00610 
00611 #if defined(A0) && defined(MYSQL_USE_MYSQLND)
00612 static int php_mysql_persistent_helper(zend_rsrc_list_entry *le TSRMLS_DC)
00613 {
00614        if (le->type == le_plink) {
00615               mysqlnd_end_psession(((php_mysql_conn *) le->ptr)->conn);
00616        }
00617        return ZEND_HASH_APPLY_KEEP;
00618 } /* }}} */
00619 #endif
00620 
00621 
00622 /* {{{ PHP_RSHUTDOWN_FUNCTION
00623  */
00624 PHP_RSHUTDOWN_FUNCTION(mysql)
00625 {
00626 #if !defined(MYSQL_USE_MYSQLND) && defined(ZTS) && MYSQL_VERSION_ID >= 40000
00627        mysql_thread_end();
00628 #endif
00629 
00630        if (MySG(trace_mode)) {
00631               if (MySG(result_allocated)){
00632                      php_error_docref("function.mysql-free-result" TSRMLS_CC, E_WARNING, "%lu result set(s) not freed. Use mysql_free_result to free result sets which were requested using mysql_query()", MySG(result_allocated));
00633               }
00634        }
00635 
00636        if (MySG(connect_error)!=NULL) {
00637               efree(MySG(connect_error));
00638        }
00639 
00640 #if defined(A0) && defined(MYSQL_USE_MYSQLND)
00641        zend_hash_apply(&EG(persistent_list), (apply_func_t) php_mysql_persistent_helper TSRMLS_CC);
00642 #endif
00643 
00644        return SUCCESS;
00645 }
00646 /* }}} */
00647 
00648 /* {{{ PHP_MINFO_FUNCTION
00649  */
00650 PHP_MINFO_FUNCTION(mysql)
00651 {
00652        char buf[32];
00653 
00654        php_info_print_table_start();
00655        php_info_print_table_header(2, "MySQL Support", "enabled");
00656        snprintf(buf, sizeof(buf), "%ld", MySG(num_persistent));
00657        php_info_print_table_row(2, "Active Persistent Links", buf);
00658        snprintf(buf, sizeof(buf), "%ld", MySG(num_links));
00659        php_info_print_table_row(2, "Active Links", buf);
00660        php_info_print_table_row(2, "Client API version", mysql_get_client_info());
00661 #if !defined (PHP_WIN32) && !defined (NETWARE) && !defined(MYSQL_USE_MYSQLND)
00662        php_info_print_table_row(2, "MYSQL_MODULE_TYPE", PHP_MYSQL_TYPE);
00663        php_info_print_table_row(2, "MYSQL_SOCKET", MYSQL_UNIX_ADDR);
00664        php_info_print_table_row(2, "MYSQL_INCLUDE", PHP_MYSQL_INCLUDE);
00665        php_info_print_table_row(2, "MYSQL_LIBS", PHP_MYSQL_LIBS);
00666 #endif
00667 
00668        php_info_print_table_end();
00669 
00670        DISPLAY_INI_ENTRIES();
00671 
00672 }
00673 /* }}} */
00674 
00675 /* {{{ php_mysql_do_connect
00676  */
00677 #define MYSQL_DO_CONNECT_CLEANUP() \
00678        if (free_host) {                          \
00679               efree(host);                       \
00680        }
00681 
00682 #define MYSQL_DO_CONNECT_RETURN_FALSE()          \
00683        MYSQL_DO_CONNECT_CLEANUP();                      \
00684        RETURN_FALSE;
00685 
00686 #ifdef MYSQL_USE_MYSQLND
00687 #define MYSQL_PORT 0
00688 #endif
00689 
00690 static void php_mysql_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent)
00691 {
00692        char *user=NULL, *passwd=NULL, *host_and_port=NULL, *socket=NULL, *tmp=NULL, *host=NULL;
00693        int  user_len, passwd_len, host_len;
00694        char *hashed_details=NULL;
00695        int hashed_details_length, port = MYSQL_PORT;
00696        long client_flags = 0;
00697        php_mysql_conn *mysql=NULL;
00698 #if MYSQL_VERSION_ID <= 32230
00699        void (*handler) (int);
00700 #endif
00701        zend_bool free_host=0, new_link=0;
00702        long connect_timeout;
00703 
00704 #if !defined(MYSQL_USE_MYSQLND)
00705        if ((MYSQL_VERSION_ID / 100) != (mysql_get_client_version() / 100)) {
00706               php_error_docref(NULL TSRMLS_CC, E_WARNING,
00707                                           "Headers and client library minor version mismatch. Headers:%d Library:%ld",
00708                                           MYSQL_VERSION_ID, mysql_get_client_version());
00709        }
00710 #endif
00711 
00712        connect_timeout = MySG(connect_timeout);
00713 
00714        socket = MySG(default_socket);
00715 
00716        if (MySG(default_port) < 0) {
00717 #if !defined(PHP_WIN32) && !defined(NETWARE)
00718               struct servent *serv_ptr;
00719               char *env;
00720 
00721               MySG(default_port) = MYSQL_PORT;
00722               if ((serv_ptr = getservbyname("mysql", "tcp"))) {
00723                      MySG(default_port) = (uint) ntohs((ushort) serv_ptr->s_port);
00724               }
00725               if ((env = getenv("MYSQL_TCP_PORT"))) {
00726                      MySG(default_port) = (uint) atoi(env);
00727               }
00728 #else
00729               MySG(default_port) = MYSQL_PORT;
00730 #endif
00731        }
00732 
00733        if (PG(sql_safe_mode)) {
00734               if (ZEND_NUM_ARGS()>0) {
00735                      php_error_docref(NULL TSRMLS_CC, E_NOTICE, "SQL safe mode in effect - ignoring host/user/password information");
00736               }
00737               host_and_port=passwd=NULL;
00738               user=php_get_current_user();
00739               hashed_details_length = spprintf(&hashed_details, 0, "mysql__%s_", user);
00740               client_flags = CLIENT_INTERACTIVE;
00741        } else {
00742               /* mysql_pconnect does not support new_link parameter */
00743               if (persistent) {
00744                      if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s!s!s!l", &host_and_port, &host_len,
00745                                                                &user, &user_len, &passwd, &passwd_len,
00746                                                                &client_flags)==FAILURE) {
00747                             return;
00748               }
00749               } else {
00750                      if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s!s!s!bl", &host_and_port, &host_len,
00751                                                                       &user, &user_len, &passwd, &passwd_len,
00752                                                                       &new_link, &client_flags)==FAILURE) {
00753                             return;
00754                      }
00755               }
00756 
00757               if (!host_and_port) {
00758                      host_and_port = MySG(default_host);
00759               }
00760               if (!user) {
00761                      user = MySG(default_user);
00762               }
00763               if (!passwd) {
00764                      passwd = MySG(default_password);
00765                      passwd_len = passwd? strlen(passwd):0;
00766               }
00767 
00768               /* disable local infile option for open_basedir */
00769 #if PHP_API_VERSION < 20100412
00770               if (((PG(open_basedir) && PG(open_basedir)[0] != '\0') || PG(safe_mode)) && (client_flags & CLIENT_LOCAL_FILES)) {
00771 #else
00772               if ((PG(open_basedir) && PG(open_basedir)[0] != '\0') && (client_flags & CLIENT_LOCAL_FILES)) {
00773 #endif
00774                      client_flags ^= CLIENT_LOCAL_FILES;
00775               }
00776 
00777 #ifdef CLIENT_MULTI_RESULTS
00778               client_flags |= CLIENT_MULTI_RESULTS; /* compatibility with 5.2, see bug#50416 */
00779 #endif
00780 #ifdef CLIENT_MULTI_STATEMENTS
00781               client_flags &= ~CLIENT_MULTI_STATEMENTS;   /* don't allow multi_queries via connect parameter */
00782 #endif
00783               hashed_details_length = spprintf(&hashed_details, 0, "mysql_%s_%s_%s_%ld", SAFE_STRING(host_and_port), SAFE_STRING(user), SAFE_STRING(passwd), client_flags);
00784        }
00785 
00786        /* We cannot use mysql_port anymore in windows, need to use
00787         * mysql_real_connect() to set the port.
00788         */
00789        if (host_and_port && (tmp=strchr(host_and_port, ':'))) {
00790               host = estrndup(host_and_port, tmp-host_and_port);
00791               free_host = 1;
00792               tmp++;
00793               if (tmp[0] != '/') {
00794                      port = atoi(tmp);
00795                      if ((tmp=strchr(tmp, ':'))) {
00796                             tmp++;
00797                             socket=tmp;
00798                      }
00799               } else {
00800                      socket = tmp;
00801               }
00802        } else {
00803               host = host_and_port;
00804               port = MySG(default_port);
00805        }
00806 
00807 #if MYSQL_VERSION_ID < 32200
00808        mysql_port = port;
00809 #endif
00810 
00811        if (!MySG(allow_persistent)) {
00812               persistent=0;
00813        }
00814        if (persistent) {
00815               zend_rsrc_list_entry *le;
00816 
00817               /* try to find if we already have this link in our persistent list */
00818               if (zend_hash_find(&EG(persistent_list), hashed_details, hashed_details_length+1, (void **) &le)==FAILURE) {  /* we don't */
00819                      zend_rsrc_list_entry new_le;
00820 
00821                      if (MySG(max_links) != -1 && MySG(num_links) >= MySG(max_links)) {
00822                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "Too many open links (%ld)", MySG(num_links));
00823                             efree(hashed_details);
00824                             MYSQL_DO_CONNECT_RETURN_FALSE();
00825                      }
00826                      if (MySG(max_persistent) != -1 && MySG(num_persistent) >= MySG(max_persistent)) {
00827                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "Too many open persistent links (%ld)", MySG(num_persistent));
00828                             efree(hashed_details);
00829                             MYSQL_DO_CONNECT_RETURN_FALSE();
00830                      }
00831                      /* create the link */
00832                      mysql = (php_mysql_conn *) malloc(sizeof(php_mysql_conn));
00833                      if (!mysql) {
00834                             php_error_docref(NULL TSRMLS_CC, E_ERROR, "Out of memory while allocating memory for a persistent link");
00835                      }
00836                      mysql->active_result_id = 0;
00837 #ifdef CLIENT_MULTI_STATEMENTS
00838                      mysql->multi_query = client_flags & CLIENT_MULTI_STATEMENTS? 1:0;
00839 #else
00840                      mysql->multi_query = 0;
00841 #endif
00842 
00843 #ifndef MYSQL_USE_MYSQLND
00844                      mysql->conn = mysql_init(NULL);
00845 #else
00846                      mysql->conn = mysql_init(persistent);
00847 #endif
00848 
00849                      if (connect_timeout != -1) {
00850                             mysql_options(mysql->conn, MYSQL_OPT_CONNECT_TIMEOUT, (const char *)&connect_timeout);
00851                      }
00852 #ifndef MYSQL_USE_MYSQLND
00853                      if (mysql_real_connect(mysql->conn, host, user, passwd, NULL, port, socket, client_flags)==NULL)
00854 #else
00855                      if (mysqlnd_connect(mysql->conn, host, user, passwd, passwd_len, NULL, 0, port, socket, client_flags TSRMLS_CC) == NULL)
00856 #endif
00857                      {
00858                             /* Populate connect error globals so that the error functions can read them */
00859                             if (MySG(connect_error) != NULL) {
00860                                    efree(MySG(connect_error));
00861                             }
00862                             MySG(connect_error) = estrdup(mysql_error(mysql->conn));
00863                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", MySG(connect_error));
00864 #if defined(HAVE_MYSQL_ERRNO)
00865                             MySG(connect_errno) = mysql_errno(mysql->conn);
00866 #endif
00867                             free(mysql);
00868                             efree(hashed_details);
00869                             MYSQL_DO_CONNECT_RETURN_FALSE();
00870                      }
00871                      mysql_options(mysql->conn, MYSQL_OPT_LOCAL_INFILE, (char *)&MySG(allow_local_infile));
00872 
00873                      /* hash it up */
00874                      Z_TYPE(new_le) = le_plink;
00875                      new_le.ptr = mysql;
00876                      if (zend_hash_update(&EG(persistent_list), hashed_details, hashed_details_length+1, (void *) &new_le, sizeof(zend_rsrc_list_entry), NULL)==FAILURE) {
00877                             free(mysql);
00878                             efree(hashed_details);
00879                             MYSQL_DO_CONNECT_RETURN_FALSE();
00880                      }
00881                      MySG(num_persistent)++;
00882                      MySG(num_links)++;
00883               } else {  /* The link is in our list of persistent connections */
00884                      if (Z_TYPE_P(le) != le_plink) {
00885                             MYSQL_DO_CONNECT_RETURN_FALSE();
00886                      }
00887                      mysql = (php_mysql_conn *) le->ptr;
00888                      mysql->active_result_id = 0;
00889 #ifdef CLIENT_MULTI_STATEMENTS
00890                      mysql->multi_query = client_flags & CLIENT_MULTI_STATEMENTS? 1:0;
00891 #else
00892                      mysql->multi_query = 0;
00893 #endif
00894                      /* ensure that the link did not die */
00895 #if defined(A0) && MYSQL_USE_MYSQLND
00896                      mysqlnd_end_psession(mysql->conn);
00897 #endif
00898                      if (mysql_ping(mysql->conn)) {
00899                             if (mysql_errno(mysql->conn) == 2006) {
00900 #ifndef MYSQL_USE_MYSQLND
00901                                    if (mysql_real_connect(mysql->conn, host, user, passwd, NULL, port, socket, client_flags)==NULL)
00902 #else
00903                                    if (mysqlnd_connect(mysql->conn, host, user, passwd, passwd_len, NULL, 0, port, socket, client_flags TSRMLS_CC) == NULL)
00904 #endif
00905                                    {
00906                                           php_error_docref(NULL TSRMLS_CC, E_WARNING, "Link to server lost, unable to reconnect");
00907                                           zend_hash_del(&EG(persistent_list), hashed_details, hashed_details_length+1);
00908                                           efree(hashed_details);
00909                                           MYSQL_DO_CONNECT_RETURN_FALSE();
00910                                    }
00911                                    mysql_options(mysql->conn, MYSQL_OPT_LOCAL_INFILE, (char *)&MySG(allow_local_infile));
00912                             }
00913                      } else {
00914 #ifdef MYSQL_USE_MYSQLND
00915                             mysqlnd_restart_psession(mysql->conn);
00916 #endif
00917                      }
00918               }
00919               ZEND_REGISTER_RESOURCE(return_value, mysql, le_plink);
00920        } else { /* non persistent */
00921               zend_rsrc_list_entry *index_ptr, new_index_ptr;
00922 
00923               /* first we check the hash for the hashed_details key.  if it exists,
00924                * it should point us to the right offset where the actual mysql link sits.
00925                * if it doesn't, open a new mysql link, add it to the resource list,
00926                * and add a pointer to it with hashed_details as the key.
00927                */
00928               if (!new_link && zend_hash_find(&EG(regular_list), hashed_details, hashed_details_length+1,(void **) &index_ptr)==SUCCESS) {
00929                      int type;
00930                      long link;
00931                      void *ptr;
00932 
00933                      if (Z_TYPE_P(index_ptr) != le_index_ptr) {
00934                             MYSQL_DO_CONNECT_RETURN_FALSE();
00935                      }
00936                      link = (long) index_ptr->ptr;
00937                      ptr = zend_list_find(link,&type);   /* check if the link is still there */
00938                      if (ptr && (type==le_link || type==le_plink)) {
00939                             zend_list_addref(link);
00940                             Z_LVAL_P(return_value) = link;
00941                             php_mysql_set_default_link(link TSRMLS_CC);
00942                             Z_TYPE_P(return_value) = IS_RESOURCE;
00943                             efree(hashed_details);
00944                             MYSQL_DO_CONNECT_CLEANUP();
00945                             return;
00946                      } else {
00947                             zend_hash_del(&EG(regular_list), hashed_details, hashed_details_length+1);
00948                      }
00949               }
00950               if (MySG(max_links) != -1 && MySG(num_links) >= MySG(max_links)) {
00951                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "Too many open links (%ld)", MySG(num_links));
00952                      efree(hashed_details);
00953                      MYSQL_DO_CONNECT_RETURN_FALSE();
00954               }
00955 
00956               mysql = (php_mysql_conn *) emalloc(sizeof(php_mysql_conn));
00957               mysql->active_result_id = 0;
00958 #ifdef CLIENT_MULTI_STATEMENTS
00959               mysql->multi_query = 1;
00960 #endif
00961 
00962 #ifndef MYSQL_USE_MYSQLND
00963               mysql->conn = mysql_init(NULL);
00964 #else
00965               mysql->conn = mysql_init(persistent);
00966 #endif
00967               if (!mysql->conn) {
00968                      MySG(connect_error) = estrdup("OOM");
00969                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "OOM");
00970                      efree(hashed_details);
00971                      efree(mysql);
00972                      MYSQL_DO_CONNECT_RETURN_FALSE();
00973               }
00974 
00975               if (connect_timeout != -1) {
00976                      mysql_options(mysql->conn, MYSQL_OPT_CONNECT_TIMEOUT, (const char *)&connect_timeout);
00977               }
00978 
00979 #ifndef MYSQL_USE_MYSQLND
00980               if (mysql_real_connect(mysql->conn, host, user, passwd, NULL, port, socket, client_flags)==NULL)
00981 #else
00982               if (mysqlnd_connect(mysql->conn, host, user, passwd, passwd_len, NULL, 0, port, socket, client_flags TSRMLS_CC) == NULL)
00983 #endif
00984               {
00985                      /* Populate connect error globals so that the error functions can read them */
00986                      if (MySG(connect_error) != NULL) {
00987                             efree(MySG(connect_error));
00988                      }
00989                      MySG(connect_error) = estrdup(mysql_error(mysql->conn));
00990                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", MySG(connect_error));
00991 #if defined(HAVE_MYSQL_ERRNO)
00992                      MySG(connect_errno) = mysql_errno(mysql->conn);
00993 #endif
00994                      /* free mysql structure */
00995 #ifdef MYSQL_USE_MYSQLND
00996                      mysqlnd_close(mysql->conn, MYSQLND_CLOSE_DISCONNECTED);
00997 #endif
00998                      efree(hashed_details);
00999                      efree(mysql);
01000                      MYSQL_DO_CONNECT_RETURN_FALSE();
01001               }
01002               mysql_options(mysql->conn, MYSQL_OPT_LOCAL_INFILE, (char *)&MySG(allow_local_infile));
01003 
01004               /* add it to the list */
01005               ZEND_REGISTER_RESOURCE(return_value, mysql, le_link);
01006 
01007               /* add it to the hash */
01008               new_index_ptr.ptr = (void *) Z_LVAL_P(return_value);
01009               Z_TYPE(new_index_ptr) = le_index_ptr;
01010               if (zend_hash_update(&EG(regular_list), hashed_details, hashed_details_length+1,(void *) &new_index_ptr, sizeof(zend_rsrc_list_entry), NULL)==FAILURE) {
01011                      efree(hashed_details);
01012                      MYSQL_DO_CONNECT_RETURN_FALSE();
01013               }
01014               MySG(num_links)++;
01015        }
01016 
01017        efree(hashed_details);
01018        php_mysql_set_default_link(Z_LVAL_P(return_value) TSRMLS_CC);
01019        MYSQL_DO_CONNECT_CLEANUP();
01020 }
01021 /* }}} */
01022 
01023 /* {{{ php_mysql_get_default_link
01024  */
01025 static int php_mysql_get_default_link(INTERNAL_FUNCTION_PARAMETERS)
01026 {
01027        if (MySG(default_link)==-1) { /* no link opened yet, implicitly open one */
01028               ht = 0;
01029               php_mysql_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
01030        }
01031        return MySG(default_link);
01032 }
01033 /* }}} */
01034 
01035 /* {{{ proto resource mysql_connect([string hostname[:port][:/path/to/socket] [, string username [, string password [, bool new [, int flags]]]]])
01036    Opens a connection to a MySQL Server */
01037 PHP_FUNCTION(mysql_connect)
01038 {
01039        php_mysql_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
01040 }
01041 /* }}} */
01042 
01043 /* {{{ proto resource mysql_pconnect([string hostname[:port][:/path/to/socket] [, string username [, string password [, int flags]]]])
01044    Opens a persistent connection to a MySQL Server */
01045 PHP_FUNCTION(mysql_pconnect)
01046 {
01047        php_mysql_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
01048 }
01049 /* }}} */
01050 
01051 /* {{{ proto bool mysql_close([int link_identifier])
01052    Close a MySQL connection */
01053 PHP_FUNCTION(mysql_close)
01054 {
01055        int resource_id;
01056        zval *mysql_link=NULL;
01057        php_mysql_conn *mysql;
01058 
01059        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|r", &mysql_link) == FAILURE) {
01060               return;
01061        }
01062 
01063        if (mysql_link) {
01064               ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, &mysql_link, -1, "MySQL-Link", le_link, le_plink);
01065        } else {
01066               ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, NULL, MySG(default_link), "MySQL-Link", le_link, le_plink);
01067        }
01068 
01069        resource_id = mysql_link ? Z_RESVAL_P(mysql_link) : MySG(default_link);
01070        PHPMY_UNBUFFERED_QUERY_CHECK();
01071 #ifdef MYSQL_USE_MYSQLND
01072        {
01073               int tmp;
01074               if ((mysql = zend_list_find(resource_id, &tmp)) && tmp == le_plink) {
01075                      mysqlnd_end_psession(mysql->conn);
01076               }
01077        }
01078 #endif
01079        zend_list_delete(resource_id);
01080 
01081        if (!mysql_link
01082               || (mysql_link && Z_RESVAL_P(mysql_link)==MySG(default_link))) {
01083               MySG(default_link) = -1;
01084               if (mysql_link) {
01085                      /* on an explicit close of the default connection it had a refcount of 2 so we need one more call */
01086                      zend_list_delete(resource_id);
01087               }
01088        }
01089 
01090        RETURN_TRUE;
01091 }
01092 /* }}} */
01093 
01094 /* {{{ proto bool mysql_select_db(string database_name [, int link_identifier])
01095    Selects a MySQL database */
01096 PHP_FUNCTION(mysql_select_db)
01097 {
01098        char *db;
01099        int db_len;
01100        zval *mysql_link = NULL;
01101        int id = -1;
01102        php_mysql_conn *mysql;
01103 
01104        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|r", &db, &db_len, &mysql_link) == FAILURE) {
01105               return;
01106        }
01107 
01108        if (!mysql_link) {
01109               id = php_mysql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU);
01110               CHECK_LINK(id);
01111        }
01112 
01113        ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, &mysql_link, id, "MySQL-Link", le_link, le_plink);
01114 
01115        if (php_mysql_select_db(mysql, db TSRMLS_CC)) {
01116               RETURN_TRUE;
01117        } else {
01118               RETURN_FALSE;
01119        }
01120 }
01121 /* }}} */
01122 
01123 #ifdef HAVE_GETINFO_FUNCS
01124 
01125 /* {{{ proto string mysql_get_client_info(void)
01126    Returns a string that represents the client library version */
01127 PHP_FUNCTION(mysql_get_client_info)
01128 {
01129        if (zend_parse_parameters_none() == FAILURE) {
01130               return;
01131        }
01132 
01133        RETURN_STRING((char *)mysql_get_client_info(),1);
01134 }
01135 /* }}} */
01136 
01137 /* {{{ proto string mysql_get_host_info([int link_identifier])
01138    Returns a string describing the type of connection in use, including the server host name */
01139 PHP_FUNCTION(mysql_get_host_info)
01140 {
01141        zval *mysql_link = NULL;
01142        int id = -1;
01143        php_mysql_conn *mysql;
01144 
01145        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|r", &mysql_link) == FAILURE) {
01146               return;
01147        }
01148 
01149        if (!mysql_link) {
01150               id = php_mysql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU);
01151               CHECK_LINK(id);
01152        }
01153 
01154        ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, &mysql_link, id, "MySQL-Link", le_link, le_plink);
01155 
01156        RETURN_STRING((char *)mysql_get_host_info(mysql->conn),1);
01157 }
01158 /* }}} */
01159 
01160 /* {{{ proto int mysql_get_proto_info([int link_identifier])
01161    Returns the protocol version used by current connection */
01162 PHP_FUNCTION(mysql_get_proto_info)
01163 {
01164        zval *mysql_link = NULL;
01165        int id = -1;
01166        php_mysql_conn *mysql;
01167 
01168        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|r", &mysql_link) == FAILURE) {
01169               return;
01170        }
01171 
01172        if (!mysql_link) {
01173               id = php_mysql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU);
01174               CHECK_LINK(id);
01175        }
01176 
01177        ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, &mysql_link, id, "MySQL-Link", le_link, le_plink);
01178 
01179        RETURN_LONG(mysql_get_proto_info(mysql->conn));
01180 }
01181 /* }}} */
01182 
01183 /* {{{ proto string mysql_get_server_info([int link_identifier])
01184    Returns a string that represents the server version number */
01185 PHP_FUNCTION(mysql_get_server_info)
01186 {
01187        zval *mysql_link = NULL;
01188        int id = -1;
01189        php_mysql_conn *mysql;
01190 
01191        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|r", &mysql_link) == FAILURE) {
01192               return;
01193        }
01194 
01195        if (!mysql_link) {
01196               id = php_mysql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU);
01197               CHECK_LINK(id);
01198        }
01199 
01200        ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, &mysql_link, id, "MySQL-Link", le_link, le_plink);
01201 
01202        RETURN_STRING((char *)mysql_get_server_info(mysql->conn),1);
01203 }
01204 /* }}} */
01205 
01206 /* {{{ proto string mysql_info([int link_identifier])
01207    Returns a string containing information about the most recent query */
01208 PHP_FUNCTION(mysql_info)
01209 {
01210        zval *mysql_link = NULL;
01211        int id = -1;
01212        char *str;
01213        php_mysql_conn *mysql;
01214 
01215        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|r", &mysql_link) == FAILURE) {
01216               return;
01217        }
01218 
01219        if (ZEND_NUM_ARGS() == 0) {
01220               id = php_mysql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU);
01221               CHECK_LINK(id);
01222        }
01223 
01224        ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, &mysql_link, id, "MySQL-Link", le_link, le_plink);
01225 
01226        if ((str = (char *)mysql_info(mysql->conn))) {
01227               RETURN_STRING(str,1);
01228        } else {
01229               RETURN_FALSE;
01230        }
01231 }
01232 /* }}} */
01233 
01234 /* {{{ proto int mysql_thread_id([int link_identifier])
01235        Returns the thread id of current connection */
01236 PHP_FUNCTION(mysql_thread_id)
01237 {
01238        zval *mysql_link = NULL;
01239        int  id = -1;
01240        php_mysql_conn *mysql;
01241 
01242        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|r", &mysql_link) == FAILURE) {
01243               return;
01244        }
01245 
01246        if (ZEND_NUM_ARGS() == 0) {
01247               id = php_mysql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU);
01248               CHECK_LINK(id);
01249        }
01250        ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, &mysql_link, id, "MySQL-Link", le_link, le_plink);
01251 
01252        RETURN_LONG((long) mysql_thread_id(mysql->conn));
01253 }
01254 /* }}} */
01255 
01256 /* {{{ proto string mysql_stat([int link_identifier])
01257        Returns a string containing status information */
01258 PHP_FUNCTION(mysql_stat)
01259 {
01260        zval *mysql_link = NULL;
01261        int id = -1;
01262        php_mysql_conn *mysql;
01263        char *stat;
01264 #ifdef MYSQL_USE_MYSQLND
01265        uint stat_len;
01266 #endif
01267 
01268        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|r", &mysql_link) == FAILURE) {
01269               return;
01270        }
01271 
01272        if (ZEND_NUM_ARGS() == 0) {
01273               id = php_mysql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU);
01274               CHECK_LINK(id);
01275        }
01276        ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, &mysql_link, id, "MySQL-Link", le_link, le_plink);
01277 
01278        PHPMY_UNBUFFERED_QUERY_CHECK();
01279 #ifndef MYSQL_USE_MYSQLND
01280        if ((stat = (char *)mysql_stat(mysql->conn))) {
01281               RETURN_STRING(stat, 1);
01282 #else
01283        if (mysqlnd_stat(mysql->conn, &stat, &stat_len) == PASS) {
01284               RETURN_STRINGL(stat, stat_len, 0);
01285 #endif
01286        } else {
01287               RETURN_FALSE;
01288        }
01289 }
01290 /* }}} */
01291 
01292 /* {{{ proto string mysql_client_encoding([int link_identifier])
01293        Returns the default character set for the current connection */
01294 PHP_FUNCTION(mysql_client_encoding)
01295 {
01296        zval *mysql_link = NULL;
01297        int id = -1;
01298        php_mysql_conn *mysql;
01299 
01300        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|r", &mysql_link) == FAILURE) {
01301               return;
01302        }
01303 
01304        if (ZEND_NUM_ARGS() == 0) {
01305               id = php_mysql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU);
01306               CHECK_LINK(id);
01307        }
01308 
01309        ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, &mysql_link, id, "MySQL-Link", le_link, le_plink);
01310        RETURN_STRING((char *)mysql_character_set_name(mysql->conn), 1);
01311 }
01312 /* }}} */
01313 #endif
01314 
01315 #ifdef MYSQL_HAS_SET_CHARSET
01316 /* {{{ proto bool mysql_set_charset(string csname [, int link_identifier])
01317    sets client character set */
01318 PHP_FUNCTION(mysql_set_charset)
01319 {
01320        zval *mysql_link = NULL;
01321        char *csname;
01322        int id = -1, csname_len;
01323        php_mysql_conn *mysql;
01324 
01325        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|r", &csname, &csname_len, &mysql_link) == FAILURE) {
01326               return;
01327        }
01328 
01329        if (ZEND_NUM_ARGS() == 1) {
01330               id = php_mysql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU);
01331               CHECK_LINK(id);
01332        }
01333 
01334        ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, &mysql_link, id, "MySQL-Link", le_link, le_plink);
01335 
01336        if (!mysql_set_character_set(mysql->conn, csname)) {
01337               RETURN_TRUE;
01338        } else {
01339               RETURN_FALSE;
01340        }
01341 }
01342 /* }}} */
01343 #endif
01344 
01345 #ifndef NETWARE             /* The below two functions not supported on NetWare */
01346 #if MYSQL_VERSION_ID < 40000
01347 /* {{{ proto bool mysql_create_db(string database_name [, int link_identifier])
01348    Create a MySQL database */
01349 PHP_FUNCTION(mysql_create_db)
01350 {
01351        char *db;
01352        int db_len;
01353        zval *mysql_link = NULL;
01354        int id = -1;
01355        php_mysql_conn *mysql;
01356 
01357        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|r", &db, &db_len, &mysql_link) == FAILURE) {
01358               return;
01359        }
01360 
01361        if (!mysql_link) {
01362               id = php_mysql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU);
01363               CHECK_LINK(id);
01364        }
01365 
01366        ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, &mysql_link, id, "MySQL-Link", le_link, le_plink);
01367 
01368        PHPMY_UNBUFFERED_QUERY_CHECK();
01369 
01370        if (mysql_create_db(mysql->conn, db)==0) {
01371               RETURN_TRUE;
01372        } else {
01373               RETURN_FALSE;
01374        }
01375 }
01376 /* }}} */
01377 
01378 /* {{{ proto bool mysql_drop_db(string database_name [, int link_identifier])
01379    Drops (delete) a MySQL database */
01380 PHP_FUNCTION(mysql_drop_db)
01381 {
01382        char *db;
01383        int db_len;
01384        zval *mysql_link = NULL;
01385        int id = -1;
01386        php_mysql_conn *mysql;
01387 
01388        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|r", &db, &db_len, &mysql_link) == FAILURE) {
01389               return;
01390        }
01391 
01392        if (!mysql_link) {
01393               id = php_mysql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU);
01394               CHECK_LINK(id);
01395        }
01396 
01397        ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, &mysql_link, id, "MySQL-Link", le_link, le_plink);
01398 
01399        if (mysql_drop_db(mysql->conn, db)==0) {
01400               RETURN_TRUE;
01401        } else {
01402               RETURN_FALSE;
01403        }
01404 }
01405 /* }}} */
01406 #endif
01407 #endif /* NETWARE */
01408 
01409 /* {{{ php_mysql_do_query_general
01410  */
01411 static void php_mysql_do_query_general(char *query, int query_len, zval *mysql_link, int link_id, char *db, int use_store, zval *return_value TSRMLS_DC)
01412 {
01413        php_mysql_conn *mysql;
01414        MYSQL_RES *mysql_result;
01415 
01416        ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, &mysql_link, link_id, "MySQL-Link", le_link, le_plink);
01417 
01418        if (db) {
01419               if (!php_mysql_select_db(mysql, db TSRMLS_CC)) {
01420                      RETURN_FALSE;
01421               }
01422        }
01423 
01424        PHPMY_UNBUFFERED_QUERY_CHECK();
01425 
01426        MYSQL_DISABLE_MQ;
01427 
01428 #ifndef MYSQL_USE_MYSQLND
01429        /* check explain */
01430        if (MySG(trace_mode)) {
01431               if (!strncasecmp("select", query, 6)){
01432                      MYSQL_ROW     row;
01433 
01434                      char *newquery;
01435                      int newql = spprintf (&newquery, 0, "EXPLAIN %s", query);
01436                      mysql_real_query(mysql->conn, newquery, newql);
01437                      efree (newquery);
01438                      if (mysql_errno(mysql->conn)) {
01439                             php_error_docref("http://www.mysql.com/doc" TSRMLS_CC, E_WARNING, "%s", mysql_error(mysql->conn));
01440                             RETURN_FALSE;
01441                      }
01442                      else {
01443                      mysql_result = mysql_use_result(mysql->conn);
01444                             while ((row = mysql_fetch_row(mysql_result))) {
01445                                    if (!strcmp("ALL", row[1])) {
01446                                           php_error_docref("http://www.mysql.com/doc" TSRMLS_CC, E_WARNING, "Your query requires a full tablescan (table %s, %s rows affected). Use EXPLAIN to optimize your query.", row[0], row[6]);
01447                                    } else if (!strcmp("INDEX", row[1])) {
01448                                           php_error_docref("http://www.mysql.com/doc" TSRMLS_CC, E_WARNING, "Your query requires a full indexscan (table %s, %s rows affected). Use EXPLAIN to optimize your query.", row[0], row[6]);
01449                                    }
01450                             }
01451                             mysql_free_result(mysql_result);
01452                      }
01453               }
01454        } /* end explain */
01455 #endif
01456 
01457        /* mysql_query is binary unsafe, use mysql_real_query */
01458 #if MYSQL_VERSION_ID > 32199
01459        if (mysql_real_query(mysql->conn, query, query_len)!=0) {
01460               /* check possible error */
01461               if (MySG(trace_mode)){
01462                      if (mysql_errno(mysql->conn)){
01463                             php_error_docref("http://www.mysql.com/doc" TSRMLS_CC, E_WARNING, "%s", mysql_error(mysql->conn));
01464                      }
01465               }
01466               RETURN_FALSE;
01467        }
01468 #else
01469        if (mysql_query(mysql->conn, query)!=0) {
01470               /* check possible error */
01471               if (MySG(trace_mode)){
01472                      if (mysql_errno(mysql->conn)){
01473                             php_error_docref("http://www.mysql.com/doc" TSRMLS_CC, E_WARNING, "%s", mysql_error(mysql->conn));
01474                      }
01475               }
01476               RETURN_FALSE;
01477        }
01478 #endif
01479        if(use_store == MYSQL_USE_RESULT) {
01480               mysql_result=mysql_use_result(mysql->conn);
01481        } else {
01482               mysql_result=mysql_store_result(mysql->conn);
01483        }
01484        if (!mysql_result) {
01485               if (PHP_MYSQL_VALID_RESULT(mysql->conn)) { /* query should have returned rows */
01486                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to save result set");
01487                      RETURN_FALSE;
01488               } else {
01489                      RETURN_TRUE;
01490               }
01491        }
01492        MySG(result_allocated)++;
01493        ZEND_REGISTER_RESOURCE(return_value, mysql_result, le_result);
01494        if (use_store == MYSQL_USE_RESULT) {
01495               mysql->active_result_id = Z_LVAL_P(return_value);
01496        }
01497 }
01498 /* }}} */
01499 
01500 /* {{{ php_mysql_do_query
01501  */
01502 static void php_mysql_do_query(INTERNAL_FUNCTION_PARAMETERS, int use_store)
01503 {
01504        char *query;
01505        int query_len;
01506        zval *mysql_link = NULL;
01507        int id = -1;
01508 
01509        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|r", &query, &query_len, &mysql_link) == FAILURE) {
01510               return;
01511        }
01512 
01513        if (!mysql_link) {
01514               id = php_mysql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU);
01515               CHECK_LINK(id);
01516        }
01517 
01518        php_mysql_do_query_general(query, query_len, mysql_link, id, NULL, use_store, return_value TSRMLS_CC);
01519 }
01520 /* }}} */
01521 
01522 /* {{{ proto resource mysql_query(string query [, int link_identifier])
01523    Sends an SQL query to MySQL */
01524 PHP_FUNCTION(mysql_query)
01525 {
01526        php_mysql_do_query(INTERNAL_FUNCTION_PARAM_PASSTHRU, MYSQL_STORE_RESULT);
01527 }
01528 /* }}} */
01529 
01530 
01531 /* {{{ proto resource mysql_unbuffered_query(string query [, int link_identifier])
01532    Sends an SQL query to MySQL, without fetching and buffering the result rows */
01533 PHP_FUNCTION(mysql_unbuffered_query)
01534 {
01535        php_mysql_do_query(INTERNAL_FUNCTION_PARAM_PASSTHRU, MYSQL_USE_RESULT);
01536 }
01537 /* }}} */
01538 
01539 
01540 /* {{{ proto resource mysql_db_query(string database_name, string query [, int link_identifier])
01541    Sends an SQL query to MySQL */
01542 PHP_FUNCTION(mysql_db_query)
01543 {
01544        char *db, *query;
01545        int db_len, query_len;
01546        zval *mysql_link = NULL;
01547        int id = -1;
01548 
01549        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|r", &db, &db_len, &query, &query_len, &mysql_link) == FAILURE) {
01550               return;
01551        }
01552 
01553        if (!mysql_link) {
01554               id = php_mysql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU);
01555               CHECK_LINK(id);
01556        }
01557 
01558        php_error_docref(NULL TSRMLS_CC, E_DEPRECATED, "This function is deprecated; use mysql_query() instead");
01559 
01560        php_mysql_do_query_general(query, query_len, mysql_link, id, db, MYSQL_STORE_RESULT, return_value TSRMLS_CC);
01561 }
01562 /* }}} */
01563 
01564 
01565 /* {{{ proto resource mysql_list_dbs([int link_identifier])
01566    List databases available on a MySQL server */
01567 PHP_FUNCTION(mysql_list_dbs)
01568 {
01569        zval *mysql_link = NULL;
01570        int id = -1;
01571        php_mysql_conn *mysql;
01572        MYSQL_RES *mysql_result;
01573 
01574        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|r", &mysql_link) == FAILURE) {
01575               return;
01576        }
01577 
01578        if (!mysql_link) {
01579               id = php_mysql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU);
01580               CHECK_LINK(id);
01581        }
01582 
01583        ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, &mysql_link, id, "MySQL-Link", le_link, le_plink);
01584 
01585        PHPMY_UNBUFFERED_QUERY_CHECK();
01586 
01587        if ((mysql_result=mysql_list_dbs(mysql->conn, NULL))==NULL) {
01588               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to save MySQL query result");
01589               RETURN_FALSE;
01590        }
01591        MySG(result_allocated)++;
01592        ZEND_REGISTER_RESOURCE(return_value, mysql_result, le_result);
01593 }
01594 /* }}} */
01595 
01596 
01597 /* {{{ proto resource mysql_list_tables(string database_name [, int link_identifier])
01598    List tables in a MySQL database */
01599 PHP_FUNCTION(mysql_list_tables)
01600 {
01601        char *db;
01602        int db_len;
01603        zval *mysql_link = NULL;
01604        int id = -1;
01605        php_mysql_conn *mysql;
01606        MYSQL_RES *mysql_result;
01607 
01608        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|r", &db, &db_len, &mysql_link) == FAILURE) {
01609               return;
01610        }
01611 
01612        if (!mysql_link) {
01613               id = php_mysql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU);
01614               CHECK_LINK(id);
01615        }
01616 
01617        ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, &mysql_link, id, "MySQL-Link", le_link, le_plink);
01618 
01619        if (!php_mysql_select_db(mysql, db TSRMLS_CC)) {
01620               RETURN_FALSE;
01621        }
01622 
01623        PHPMY_UNBUFFERED_QUERY_CHECK();
01624 
01625        if ((mysql_result=mysql_list_tables(mysql->conn, NULL))==NULL) {
01626               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to save MySQL query result");
01627               RETURN_FALSE;
01628        }
01629        MySG(result_allocated)++;
01630        ZEND_REGISTER_RESOURCE(return_value, mysql_result, le_result);
01631 }
01632 /* }}} */
01633 
01634 
01635 /* {{{ proto resource mysql_list_fields(string database_name, string table_name [, int link_identifier])
01636    List MySQL result fields */
01637 PHP_FUNCTION(mysql_list_fields)
01638 {
01639        char *db, *table;
01640        int db_len, table_len;
01641        zval *mysql_link = NULL;
01642        int id = -1;
01643        php_mysql_conn *mysql;
01644        MYSQL_RES *mysql_result;
01645 
01646        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|r", &db, &db_len, &table, &table_len, &mysql_link) == FAILURE) {
01647               return;
01648        }
01649 
01650        if (!mysql_link) {
01651               id = php_mysql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU);
01652               CHECK_LINK(id);
01653        }
01654 
01655        ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, &mysql_link, id, "MySQL-Link", le_link, le_plink);
01656 
01657        if (!php_mysql_select_db(mysql, db TSRMLS_CC)) {
01658               RETURN_FALSE;
01659        }
01660 
01661        PHPMY_UNBUFFERED_QUERY_CHECK();
01662 
01663        if ((mysql_result=mysql_list_fields(mysql->conn, table, NULL))==NULL) {
01664               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to save MySQL query result");
01665               RETURN_FALSE;
01666        }
01667        MySG(result_allocated)++;
01668        ZEND_REGISTER_RESOURCE(return_value, mysql_result, le_result);
01669 }
01670 /* }}} */
01671 
01672 /* {{{ proto resource mysql_list_processes([int link_identifier])
01673        Returns a result set describing the current server threads */
01674 PHP_FUNCTION(mysql_list_processes)
01675 {
01676        zval *mysql_link = NULL;
01677        int id = -1;
01678        php_mysql_conn *mysql;
01679        MYSQL_RES *mysql_result;
01680 
01681        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|r", &mysql_link) == FAILURE) {
01682               return;
01683        }
01684 
01685        if (ZEND_NUM_ARGS() == 0) {
01686               id = php_mysql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU);
01687               CHECK_LINK(id);
01688        }
01689 
01690        ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, &mysql_link, id, "MySQL-Link", le_link, le_plink);
01691 
01692        PHPMY_UNBUFFERED_QUERY_CHECK();
01693 
01694        mysql_result = mysql_list_processes(mysql->conn);
01695        if (mysql_result == NULL) {
01696               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to save MySQL query result");
01697               RETURN_FALSE;
01698        }
01699 
01700        MySG(result_allocated)++;
01701        ZEND_REGISTER_RESOURCE(return_value, mysql_result, le_result);
01702 }
01703 /* }}} */
01704 
01705 
01706 /* {{{ proto string mysql_error([int link_identifier])
01707    Returns the text of the error message from previous MySQL operation */
01708 PHP_FUNCTION(mysql_error)
01709 {
01710        zval *mysql_link = NULL;
01711        int id = -1;
01712        php_mysql_conn *mysql;
01713 
01714        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|r", &mysql_link) == FAILURE) {
01715               return;
01716        }
01717 
01718        if (!mysql_link) {
01719               id = MySG(default_link);
01720               if (id==-1) {
01721                      if (MySG(connect_error)!=NULL){
01722                             RETURN_STRING(MySG(connect_error),1);
01723                      } else {
01724                             RETURN_FALSE;
01725                      }
01726               }
01727        }
01728 
01729        ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, &mysql_link, id, "MySQL-Link", le_link, le_plink);
01730 
01731        RETURN_STRING((char *)mysql_error(mysql->conn), 1);
01732 }
01733 /* }}} */
01734 
01735 
01736 /* {{{ proto int mysql_errno([int link_identifier])
01737    Returns the number of the error message from previous MySQL operation */
01738 #ifdef HAVE_MYSQL_ERRNO
01739 PHP_FUNCTION(mysql_errno)
01740 {
01741        zval *mysql_link = NULL;
01742        int id = -1;
01743        php_mysql_conn *mysql;
01744 
01745        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|r", &mysql_link) == FAILURE) {
01746               return;
01747        }
01748 
01749        if (!mysql_link) {
01750               id = MySG(default_link);
01751               if (id==-1) {
01752                      if (MySG(connect_errno)!=0){
01753                             RETURN_LONG(MySG(connect_errno));
01754                      } else {
01755                             RETURN_FALSE;
01756                      }
01757               }
01758        }
01759 
01760        ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, &mysql_link, id, "MySQL-Link", le_link, le_plink);
01761 
01762        RETURN_LONG(mysql_errno(mysql->conn));
01763 }
01764 #endif
01765 /* }}} */
01766 
01767 
01768 /* {{{ proto int mysql_affected_rows([int link_identifier])
01769    Gets number of affected rows in previous MySQL operation */
01770 PHP_FUNCTION(mysql_affected_rows)
01771 {
01772        zval *mysql_link = NULL;
01773        int id = -1;
01774        php_mysql_conn *mysql;
01775 
01776        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|r", &mysql_link) == FAILURE) {
01777               return;
01778        }
01779 
01780        if (!mysql_link) {
01781               id = php_mysql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU);
01782               CHECK_LINK(id);
01783        }
01784 
01785        ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, &mysql_link, id, "MySQL-Link", le_link, le_plink);
01786 
01787        /* conversion from int64 to long happing here */
01788        Z_LVAL_P(return_value) = (long) mysql_affected_rows(mysql->conn);
01789        Z_TYPE_P(return_value) = IS_LONG;
01790 }
01791 /* }}} */
01792 
01793 
01794 /* {{{ proto string mysql_escape_string(string to_be_escaped)
01795    Escape string for mysql query */
01796 PHP_FUNCTION(mysql_escape_string)
01797 {
01798        char *str;
01799        int str_len;
01800 
01801        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &str_len) == FAILURE) {
01802               return;
01803        }
01804 
01805        /* assume worst case situation, which is 2x of the original string.
01806         * we don't realloc() down to the real size since it'd most probably not
01807         * be worth it
01808         */
01809 
01810        Z_STRVAL_P(return_value) = (char *) safe_emalloc(str_len, 2, 1);
01811        Z_STRLEN_P(return_value) = mysql_escape_string(Z_STRVAL_P(return_value), str, str_len);
01812        Z_TYPE_P(return_value) = IS_STRING;
01813 
01814        if (MySG(trace_mode)){
01815               php_error_docref("function.mysql-real-escape-string" TSRMLS_CC, E_DEPRECATED, "This function is deprecated; use mysql_real_escape_string() instead.");
01816        }
01817 }
01818 /* }}} */
01819 
01820 /* {{{ proto string mysql_real_escape_string(string to_be_escaped [, int link_identifier])
01821        Escape special characters in a string for use in a SQL statement, taking into account the current charset of the connection */
01822 PHP_FUNCTION(mysql_real_escape_string)
01823 {
01824        zval *mysql_link = NULL;
01825        char *str;
01826        char *new_str;
01827        int id = -1, str_len, new_str_len;
01828        php_mysql_conn *mysql;
01829 
01830 
01831        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|r", &str, &str_len, &mysql_link) == FAILURE) {
01832               return;
01833        }
01834 
01835        if (ZEND_NUM_ARGS() == 1) {
01836               id = php_mysql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU);
01837               CHECK_LINK(id);
01838        }
01839 
01840        ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, &mysql_link, id, "MySQL-Link", le_link, le_plink);
01841 
01842        new_str = safe_emalloc(str_len, 2, 1);
01843        new_str_len = mysql_real_escape_string(mysql->conn, new_str, str, str_len);
01844        new_str = erealloc(new_str, new_str_len + 1);
01845 
01846        RETURN_STRINGL(new_str, new_str_len, 0);
01847 }
01848 /* }}} */
01849 
01850 /* {{{ proto int mysql_insert_id([int link_identifier])
01851    Gets the ID generated from the previous INSERT operation */
01852 PHP_FUNCTION(mysql_insert_id)
01853 {
01854        zval *mysql_link = NULL;
01855        int id = -1;
01856        php_mysql_conn *mysql;
01857 
01858        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|r", &mysql_link) == FAILURE) {
01859               return;
01860        }
01861 
01862        if (!mysql_link) {
01863               id = php_mysql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU);
01864               CHECK_LINK(id);
01865        }
01866 
01867        ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, &mysql_link, id, "MySQL-Link", le_link, le_plink);
01868 
01869        /* conversion from int64 to long happing here */
01870        Z_LVAL_P(return_value) = (long) mysql_insert_id(mysql->conn);
01871        Z_TYPE_P(return_value) = IS_LONG;
01872 }
01873 /* }}} */
01874 
01875 
01876 /* {{{ proto mixed mysql_result(resource result, int row [, mixed field])
01877    Gets result data */
01878 PHP_FUNCTION(mysql_result)
01879 {
01880        zval *result, *field=NULL;
01881        long row;
01882        MYSQL_RES *mysql_result;
01883 #ifndef MYSQL_USE_MYSQLND
01884        MYSQL_ROW sql_row;
01885        mysql_row_length_type *sql_row_lengths;
01886 #endif
01887        int field_offset=0;
01888 
01889 /*
01890 johannes TODO:
01891 Do 2 zend_parse_paramters calls instead of type "z" and switch below
01892 Q: String or long first?
01893 */
01894        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl|z", &result, &row, &field) == FAILURE) {
01895               return;
01896        }
01897 
01898        ZEND_FETCH_RESOURCE(mysql_result, MYSQL_RES *, &result, -1, "MySQL result", le_result);
01899 
01900        if (row<0 || row>=(int)mysql_num_rows(mysql_result)) {
01901               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to jump to row %ld on MySQL result index %ld", row, Z_LVAL_P(result));
01902               RETURN_FALSE;
01903        }
01904        mysql_data_seek(mysql_result, row);
01905 
01906        if (field) {
01907               switch(Z_TYPE_P(field)) {
01908                      case IS_STRING: {
01909                                    int i=0;
01910                                    const MYSQL_FIELD *tmp_field;
01911                                    char *table_name, *field_name, *tmp;
01912 
01913                                    if ((tmp=strchr(Z_STRVAL_P(field), '.'))) {
01914                                           table_name = estrndup(Z_STRVAL_P(field), tmp-Z_STRVAL_P(field));
01915                                           field_name = estrdup(tmp+1);
01916                                    } else {
01917                                           table_name = NULL;
01918                                           field_name = estrndup(Z_STRVAL_P(field),Z_STRLEN_P(field));
01919                                    }
01920                                    mysql_field_seek(mysql_result, 0);
01921                                    while ((tmp_field=mysql_fetch_field(mysql_result))) {
01922                                           if ((!table_name || !strcasecmp(tmp_field->table, table_name)) && !strcasecmp(tmp_field->name, field_name)) {
01923                                                  field_offset = i;
01924                                                  break;
01925                                           }
01926                                           i++;
01927                                    }
01928                                    if (!tmp_field) { /* no match found */
01929                                           php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s%s%s not found in MySQL result index %ld",
01930                                                                (table_name?table_name:""), (table_name?".":""), field_name, Z_LVAL_P(result));
01931                                           efree(field_name);
01932                                           if (table_name) {
01933                                                  efree(table_name);
01934                                           }
01935                                           RETURN_FALSE;
01936                                    }
01937                                    efree(field_name);
01938                                    if (table_name) {
01939                                           efree(table_name);
01940                                    }
01941                             }
01942                             break;
01943                      default:
01944                             convert_to_long_ex(&field);
01945                             field_offset = Z_LVAL_P(field);
01946                             if (field_offset<0 || field_offset>=(int)mysql_num_fields(mysql_result)) {
01947                                    php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad column offset specified");
01948                                    RETURN_FALSE;
01949                             }
01950                             break;
01951               }
01952        }
01953 
01954 #ifndef MYSQL_USE_MYSQLND
01955        if ((sql_row=mysql_fetch_row(mysql_result))==NULL
01956               || (sql_row_lengths=mysql_fetch_lengths(mysql_result))==NULL) { /* shouldn't happen? */
01957               RETURN_FALSE;
01958        }
01959        if (sql_row[field_offset]) {
01960               Z_TYPE_P(return_value) = IS_STRING;
01961 
01962               if (PG(magic_quotes_runtime)) {
01963                      Z_STRVAL_P(return_value) = php_addslashes(sql_row[field_offset], sql_row_lengths[field_offset],&Z_STRLEN_P(return_value), 0 TSRMLS_CC);
01964               } else {
01965                      Z_STRLEN_P(return_value) = sql_row_lengths[field_offset];
01966                      Z_STRVAL_P(return_value) = (char *) safe_estrndup(sql_row[field_offset], Z_STRLEN_P(return_value));
01967               }
01968        } else {
01969               Z_TYPE_P(return_value) = IS_NULL;
01970        }
01971 #else
01972        mysqlnd_result_fetch_field_data(mysql_result, field_offset, return_value);
01973 #endif
01974 }
01975 /* }}} */
01976 
01977 
01978 /* {{{ proto int mysql_num_rows(resource result)
01979    Gets number of rows in a result */
01980 PHP_FUNCTION(mysql_num_rows)
01981 {
01982        zval *result;
01983        MYSQL_RES *mysql_result;
01984 
01985        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &result) == FAILURE) {
01986               return;
01987        }
01988 
01989        ZEND_FETCH_RESOURCE(mysql_result, MYSQL_RES *, &result, -1, "MySQL result", le_result);
01990 
01991        /* conversion from int64 to long happing here */
01992        Z_LVAL_P(return_value) = (long) mysql_num_rows(mysql_result);
01993        Z_TYPE_P(return_value) = IS_LONG;
01994 }
01995 /* }}} */
01996 
01997 /* {{{ proto int mysql_num_fields(resource result)
01998    Gets number of fields in a result */
01999 PHP_FUNCTION(mysql_num_fields)
02000 {
02001        zval *result;
02002        MYSQL_RES *mysql_result;
02003 
02004        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &result) == FAILURE) {
02005               return;
02006        }
02007 
02008        ZEND_FETCH_RESOURCE(mysql_result, MYSQL_RES *, &result, -1, "MySQL result", le_result);
02009 
02010        Z_LVAL_P(return_value) = mysql_num_fields(mysql_result);
02011        Z_TYPE_P(return_value) = IS_LONG;
02012 }
02013 /* }}} */
02014 
02015 /* {{{ php_mysql_fetch_hash
02016  */
02017 static void php_mysql_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, long result_type, int expected_args, int into_object)
02018 {
02019        MYSQL_RES *mysql_result;
02020        zval            *res, *ctor_params = NULL;
02021        zend_class_entry *ce = NULL;
02022 #ifndef MYSQL_USE_MYSQLND
02023        int i;
02024        MYSQL_FIELD *mysql_field;
02025        MYSQL_ROW mysql_row;
02026        mysql_row_length_type *mysql_row_lengths;
02027 #endif
02028 
02029 #ifdef ZEND_ENGINE_2
02030        if (into_object) {
02031               char *class_name = NULL;
02032               int class_name_len = 0;
02033 
02034               if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|sz", &res, &class_name, &class_name_len, &ctor_params) == FAILURE) {
02035                      return;
02036               }
02037 
02038               if (ZEND_NUM_ARGS() < 2) {
02039                      ce = zend_standard_class_def;
02040               } else {
02041                      ce = zend_fetch_class(class_name, class_name_len, ZEND_FETCH_CLASS_AUTO TSRMLS_CC);
02042               }
02043               if (!ce) {
02044                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not find class '%s'", class_name);
02045                      return;
02046               }
02047               result_type = MYSQL_ASSOC;
02048        } else
02049 #endif
02050        {
02051               if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &res, &result_type) == FAILURE) {
02052                      return;
02053               }
02054               if (!result_type) {
02055                      /* result_type might have been set outside, so only overwrite when not set */
02056                      result_type = MYSQL_BOTH;
02057               }
02058        }
02059 
02060        if (result_type & ~MYSQL_BOTH) {
02061               php_error_docref(NULL TSRMLS_CC, E_WARNING, "The result type should be either MYSQL_NUM, MYSQL_ASSOC or MYSQL_BOTH");
02062               result_type = MYSQL_BOTH;
02063        }
02064 
02065        ZEND_FETCH_RESOURCE(mysql_result, MYSQL_RES *, &res, -1, "MySQL result", le_result);
02066 
02067 #ifndef MYSQL_USE_MYSQLND
02068        if ((mysql_row = mysql_fetch_row(mysql_result)) == NULL  ||
02069               (mysql_row_lengths = mysql_fetch_lengths(mysql_result)) == NULL) {
02070               RETURN_FALSE;
02071        }
02072 
02073        array_init(return_value);
02074 
02075        mysql_field_seek(mysql_result, 0);
02076        for (mysql_field = mysql_fetch_field(mysql_result), i = 0;
02077                mysql_field;
02078                mysql_field = mysql_fetch_field(mysql_result), i++)
02079        {
02080               if (mysql_row[i]) {
02081                      zval *data;
02082 
02083                      MAKE_STD_ZVAL(data);
02084 
02085                      if (PG(magic_quotes_runtime)) {
02086                             Z_TYPE_P(data) = IS_STRING;
02087                             Z_STRVAL_P(data) = php_addslashes(mysql_row[i], mysql_row_lengths[i], &Z_STRLEN_P(data), 0 TSRMLS_CC);
02088                      } else {
02089                             ZVAL_STRINGL(data, mysql_row[i], mysql_row_lengths[i], 1);
02090                      }
02091 
02092                      if (result_type & MYSQL_NUM) {
02093                             add_index_zval(return_value, i, data);
02094                      }
02095                      if (result_type & MYSQL_ASSOC) {
02096                             if (result_type & MYSQL_NUM) {
02097                                    Z_ADDREF_P(data);
02098                             }
02099                             add_assoc_zval(return_value, mysql_field->name, data);
02100                      }
02101               } else {
02102                      /* NULL value. */
02103                      if (result_type & MYSQL_NUM) {
02104                             add_index_null(return_value, i);
02105                      }
02106 
02107                      if (result_type & MYSQL_ASSOC) {
02108                             add_assoc_null(return_value, mysql_field->name);
02109                      }
02110               }
02111        }
02112 #else
02113        mysqlnd_fetch_into(mysql_result, ((result_type & MYSQL_NUM)? MYSQLND_FETCH_NUM:0) | ((result_type & MYSQL_ASSOC)? MYSQLND_FETCH_ASSOC:0), return_value, MYSQLND_MYSQL);
02114 #endif
02115 
02116 #ifdef ZEND_ENGINE_2
02117        /* mysqlnd might return FALSE if no more rows */
02118        if (into_object && Z_TYPE_P(return_value) != IS_BOOL) {
02119               zval dataset = *return_value;
02120               zend_fcall_info fci;
02121               zend_fcall_info_cache fcc;
02122               zval *retval_ptr;
02123 
02124               object_and_properties_init(return_value, ce, NULL);
02125               zend_merge_properties(return_value, Z_ARRVAL(dataset), 1 TSRMLS_CC);
02126 
02127               if (ce->constructor) {
02128                      fci.size = sizeof(fci);
02129                      fci.function_table = &ce->function_table;
02130                      fci.function_name = NULL;
02131                      fci.symbol_table = NULL;
02132                      fci.object_ptr = return_value;
02133                      fci.retval_ptr_ptr = &retval_ptr;
02134                      if (ctor_params && Z_TYPE_P(ctor_params) != IS_NULL) {
02135                             if (Z_TYPE_P(ctor_params) == IS_ARRAY) {
02136                                    HashTable *htl = Z_ARRVAL_P(ctor_params);
02137                                    Bucket *p;
02138 
02139                                    fci.param_count = 0;
02140                                    fci.params = safe_emalloc(sizeof(zval*), htl->nNumOfElements, 0);
02141                                    p = htl->pListHead;
02142                                    while (p != NULL) {
02143                                           fci.params[fci.param_count++] = (zval**)p->pData;
02144                                           p = p->pListNext;
02145                                    }
02146                             } else {
02147                                    /* Two problems why we throw exceptions here: PHP is typeless
02148                                     * and hence passing one argument that's not an array could be
02149                                     * by mistake and the other way round is possible, too. The
02150                                     * single value is an array. Also we'd have to make that one
02151                                     * argument passed by reference.
02152                                     */
02153                                    zend_throw_exception(zend_exception_get_default(TSRMLS_C), "Parameter ctor_params must be an array", 0 TSRMLS_CC);
02154                                    return;
02155                             }
02156                      } else {
02157                             fci.param_count = 0;
02158                             fci.params = NULL;
02159                      }
02160                      fci.no_separation = 1;
02161 
02162                      fcc.initialized = 1;
02163                      fcc.function_handler = ce->constructor;
02164                      fcc.calling_scope = EG(scope);
02165                      fcc.called_scope = Z_OBJCE_P(return_value);
02166                      fcc.object_ptr = return_value;
02167 
02168                      if (zend_call_function(&fci, &fcc TSRMLS_CC) == FAILURE) {
02169                             zend_throw_exception_ex(zend_exception_get_default(TSRMLS_C), 0 TSRMLS_CC, "Could not execute %s::%s()", ce->name, ce->constructor->common.function_name);
02170                      } else {
02171                             if (retval_ptr) {
02172                                    zval_ptr_dtor(&retval_ptr);
02173                             }
02174                      }
02175                      if (fci.params) {
02176                             efree(fci.params);
02177                      }
02178               } else if (ctor_params) {
02179                      zend_throw_exception_ex(zend_exception_get_default(TSRMLS_C), 0 TSRMLS_CC, "Class %s does not have a constructor hence you cannot use ctor_params", ce->name);
02180               }
02181        }
02182 #endif
02183 
02184 }
02185 /* }}} */
02186 
02187 /* {{{ proto array mysql_fetch_row(resource result)
02188    Gets a result row as an enumerated array */
02189 PHP_FUNCTION(mysql_fetch_row)
02190 {
02191        php_mysql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, MYSQL_NUM, 1, 0);
02192 }
02193 /* }}} */
02194 
02195 
02196 /* {{{ proto object mysql_fetch_object(resource result [, string class_name [, NULL|array ctor_params]])
02197    Fetch a result row as an object */
02198 PHP_FUNCTION(mysql_fetch_object)
02199 {
02200        php_mysql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, MYSQL_ASSOC, 2, 1);
02201 
02202        if (Z_TYPE_P(return_value) == IS_ARRAY) {
02203               object_and_properties_init(return_value, ZEND_STANDARD_CLASS_DEF_PTR, Z_ARRVAL_P(return_value));
02204        }
02205 }
02206 /* }}} */
02207 
02208 
02209 /* {{{ proto array mysql_fetch_array(resource result [, int result_type])
02210    Fetch a result row as an array (associative, numeric or both) */
02211 PHP_FUNCTION(mysql_fetch_array)
02212 {
02213        php_mysql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 2, 0);
02214 }
02215 /* }}} */
02216 
02217 
02218 /* {{{ proto array mysql_fetch_assoc(resource result)
02219    Fetch a result row as an associative array */
02220 PHP_FUNCTION(mysql_fetch_assoc)
02221 {
02222        php_mysql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, MYSQL_ASSOC, 1, 0);
02223 }
02224 /* }}} */
02225 
02226 /* {{{ proto bool mysql_data_seek(resource result, int row_number)
02227    Move internal result pointer */
02228 PHP_FUNCTION(mysql_data_seek)
02229 {
02230        zval *result;
02231        long offset;
02232        MYSQL_RES *mysql_result;
02233 
02234        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &result, &offset)) {
02235               return;
02236        }
02237 
02238        ZEND_FETCH_RESOURCE(mysql_result, MYSQL_RES *, &result, -1, "MySQL result", le_result);
02239 
02240        if (offset<0 || offset>=(int)mysql_num_rows(mysql_result)) {
02241               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Offset %ld is invalid for MySQL result index %ld (or the query data is unbuffered)", offset, Z_LVAL_P(result));
02242               RETURN_FALSE;
02243        }
02244        mysql_data_seek(mysql_result, offset);
02245        RETURN_TRUE;
02246 }
02247 /* }}} */
02248 
02249 
02250 /* {{{ proto array mysql_fetch_lengths(resource result)
02251    Gets max data size of each column in a result */
02252 PHP_FUNCTION(mysql_fetch_lengths)
02253 {
02254        zval *result;
02255        MYSQL_RES *mysql_result;
02256        mysql_row_length_type *lengths;
02257        int num_fields;
02258        int i;
02259 
02260        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &result) == FAILURE) {
02261               return;
02262        }
02263 
02264        ZEND_FETCH_RESOURCE(mysql_result, MYSQL_RES *, &result, -1, "MySQL result", le_result);
02265 
02266        if ((lengths=mysql_fetch_lengths(mysql_result))==NULL) {
02267               RETURN_FALSE;
02268        }
02269        array_init(return_value);
02270        num_fields = mysql_num_fields(mysql_result);
02271 
02272        for (i=0; i<num_fields; i++) {
02273               add_index_long(return_value, i, lengths[i]);
02274        }
02275 }
02276 /* }}} */
02277 
02278 /* {{{ php_mysql_get_field_name
02279  */
02280 static char *php_mysql_get_field_name(int field_type)
02281 {
02282        switch(field_type) {
02283               case FIELD_TYPE_STRING:
02284               case FIELD_TYPE_VAR_STRING:
02285                      return "string";
02286                      break;
02287 #if MYSQL_VERSION_ID > 50002 || defined(MYSQL_USE_MYSQLND)
02288               case MYSQL_TYPE_BIT:
02289 #endif
02290 #ifdef MYSQL_HAS_TINY
02291               case FIELD_TYPE_TINY:
02292 #endif
02293               case FIELD_TYPE_SHORT:
02294               case FIELD_TYPE_LONG:
02295               case FIELD_TYPE_LONGLONG:
02296               case FIELD_TYPE_INT24:
02297                      return "int";
02298                      break;
02299               case FIELD_TYPE_FLOAT:
02300               case FIELD_TYPE_DOUBLE:
02301               case FIELD_TYPE_DECIMAL:
02302 #ifdef FIELD_TYPE_NEWDECIMAL
02303               case FIELD_TYPE_NEWDECIMAL:
02304 #endif
02305                      return "real";
02306                      break;
02307               case FIELD_TYPE_TIMESTAMP:
02308                      return "timestamp";
02309                      break;
02310 #ifdef MYSQL_HAS_YEAR
02311               case FIELD_TYPE_YEAR:
02312                      return "year";
02313                      break;
02314 #endif
02315               case FIELD_TYPE_DATE:
02316 #ifdef FIELD_TYPE_NEWDATE
02317               case FIELD_TYPE_NEWDATE:
02318 #endif
02319                      return "date";
02320                      break;
02321               case FIELD_TYPE_TIME:
02322                      return "time";
02323                      break;
02324               case FIELD_TYPE_SET:
02325                      return "set";
02326                      break;
02327               case FIELD_TYPE_ENUM:
02328                      return "enum";
02329                      break;
02330 #ifdef FIELD_TYPE_GEOMETRY
02331               case FIELD_TYPE_GEOMETRY:
02332                      return "geometry";
02333                      break;
02334 #endif
02335               case FIELD_TYPE_DATETIME:
02336                      return "datetime";
02337                      break;
02338               case FIELD_TYPE_TINY_BLOB:
02339               case FIELD_TYPE_MEDIUM_BLOB:
02340               case FIELD_TYPE_LONG_BLOB:
02341               case FIELD_TYPE_BLOB:
02342                      return "blob";
02343                      break;
02344               case FIELD_TYPE_NULL:
02345                      return "null";
02346                      break;
02347               default:
02348                      return "unknown";
02349                      break;
02350        }
02351 }
02352 /* }}} */
02353 
02354 /* {{{ proto object mysql_fetch_field(resource result [, int field_offset])
02355    Gets column information from a result and return as an object */
02356 PHP_FUNCTION(mysql_fetch_field)
02357 {
02358        zval *result;
02359        long field=0;
02360        MYSQL_RES *mysql_result;
02361        const MYSQL_FIELD *mysql_field;
02362 
02363        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &result, &field) == FAILURE) {
02364               return;
02365        }
02366 
02367        ZEND_FETCH_RESOURCE(mysql_result, MYSQL_RES *, &result, -1, "MySQL result", le_result);
02368 
02369        if (ZEND_NUM_ARGS() > 1) {
02370               if (field<0 || field>=(int)mysql_num_fields(mysql_result)) {
02371                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad field offset");
02372                      RETURN_FALSE;
02373               }
02374               mysql_field_seek(mysql_result, field);
02375        }
02376        if ((mysql_field=mysql_fetch_field(mysql_result))==NULL) {
02377               RETURN_FALSE;
02378        }
02379        object_init(return_value);
02380 
02381        add_property_string(return_value, "name", (char *) (mysql_field->name?mysql_field->name:""), 1);
02382        add_property_string(return_value, "table",(char *) (mysql_field->table?mysql_field->table:""), 1);
02383        add_property_string(return_value, "def",(mysql_field->def?mysql_field->def:""), 1);
02384        add_property_long(return_value, "max_length", mysql_field->max_length);
02385        add_property_long(return_value, "not_null", IS_NOT_NULL(mysql_field->flags)?1:0);
02386        add_property_long(return_value, "primary_key", IS_PRI_KEY(mysql_field->flags)?1:0);
02387        add_property_long(return_value, "multiple_key",(mysql_field->flags&MULTIPLE_KEY_FLAG?1:0));
02388        add_property_long(return_value, "unique_key",(mysql_field->flags&UNIQUE_KEY_FLAG?1:0));
02389        add_property_long(return_value, "numeric", IS_NUM(Z_TYPE_P(mysql_field))?1:0);
02390        add_property_long(return_value, "blob", IS_BLOB(mysql_field->flags)?1:0);
02391        add_property_string(return_value, "type", php_mysql_get_field_name(Z_TYPE_P(mysql_field)), 1);
02392        add_property_long(return_value, "unsigned",(mysql_field->flags&UNSIGNED_FLAG?1:0));
02393        add_property_long(return_value, "zerofill",(mysql_field->flags&ZEROFILL_FLAG?1:0));
02394 }
02395 /* }}} */
02396 
02397 
02398 /* {{{ proto bool mysql_field_seek(resource result, int field_offset)
02399    Sets result pointer to a specific field offset */
02400 PHP_FUNCTION(mysql_field_seek)
02401 {
02402        zval *result;
02403        long offset;
02404        MYSQL_RES *mysql_result;
02405 
02406        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &result, &offset) == FAILURE) {
02407               return;
02408        }
02409        ZEND_FETCH_RESOURCE(mysql_result, MYSQL_RES *, &result, -1, "MySQL result", le_result);
02410 
02411        if (offset<0 || offset>=(int)mysql_num_fields(mysql_result)) {
02412               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Field %ld is invalid for MySQL result index %ld", offset, Z_LVAL_P(result));
02413               RETURN_FALSE;
02414        }
02415        mysql_field_seek(mysql_result, offset);
02416        RETURN_TRUE;
02417 }
02418 /* }}} */
02419 
02420 
02421 #define PHP_MYSQL_FIELD_NAME 1
02422 #define PHP_MYSQL_FIELD_TABLE 2
02423 #define PHP_MYSQL_FIELD_LEN 3
02424 #define PHP_MYSQL_FIELD_TYPE 4
02425 #define PHP_MYSQL_FIELD_FLAGS 5
02426 
02427 /* {{{ php_mysql_field_info
02428  */
02429 static void php_mysql_field_info(INTERNAL_FUNCTION_PARAMETERS, int entry_type)
02430 {
02431        zval *result;
02432        long field;
02433        MYSQL_RES *mysql_result;
02434        const MYSQL_FIELD *mysql_field = {0};
02435        char buf[512];
02436        int  len;
02437 
02438        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &result, &field) == FAILURE) {
02439               return;
02440        }
02441 
02442        ZEND_FETCH_RESOURCE(mysql_result, MYSQL_RES *, &result, -1, "MySQL result", le_result);
02443 
02444        if (field<0 || field>=(int)mysql_num_fields(mysql_result)) {
02445               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Field %ld is invalid for MySQL result index %ld", field, Z_LVAL_P(result));
02446               RETURN_FALSE;
02447        }
02448        mysql_field_seek(mysql_result, field);
02449        if ((mysql_field=mysql_fetch_field(mysql_result))==NULL) {
02450               RETURN_FALSE;
02451        }
02452 
02453        switch (entry_type) {
02454               case PHP_MYSQL_FIELD_NAME:
02455                      Z_STRLEN_P(return_value) = strlen(mysql_field->name);
02456                      Z_STRVAL_P(return_value) = estrndup(mysql_field->name, Z_STRLEN_P(return_value));
02457                      Z_TYPE_P(return_value) = IS_STRING;
02458                      break;
02459               case PHP_MYSQL_FIELD_TABLE:
02460                      Z_STRLEN_P(return_value) = strlen(mysql_field->table);
02461                      Z_STRVAL_P(return_value) = estrndup(mysql_field->table, Z_STRLEN_P(return_value));
02462                      Z_TYPE_P(return_value) = IS_STRING;
02463                      break;
02464               case PHP_MYSQL_FIELD_LEN:
02465                      Z_LVAL_P(return_value) = mysql_field->length;
02466                      Z_TYPE_P(return_value) = IS_LONG;
02467                      break;
02468               case PHP_MYSQL_FIELD_TYPE:
02469                      Z_STRVAL_P(return_value) = php_mysql_get_field_name(Z_TYPE_P(mysql_field));
02470                      Z_STRLEN_P(return_value) = strlen(Z_STRVAL_P(return_value));
02471                      Z_STRVAL_P(return_value) = estrndup(Z_STRVAL_P(return_value), Z_STRLEN_P(return_value));
02472                      Z_TYPE_P(return_value) = IS_STRING;
02473                      break;
02474               case PHP_MYSQL_FIELD_FLAGS:
02475                      memcpy(buf, "", sizeof(""));
02476 #ifdef IS_NOT_NULL
02477                      if (IS_NOT_NULL(mysql_field->flags)) {
02478                             strcat(buf, "not_null ");
02479                      }
02480 #endif
02481 #ifdef IS_PRI_KEY
02482                      if (IS_PRI_KEY(mysql_field->flags)) {
02483                             strcat(buf, "primary_key ");
02484                      }
02485 #endif
02486 #ifdef UNIQUE_KEY_FLAG
02487                      if (mysql_field->flags&UNIQUE_KEY_FLAG) {
02488                             strcat(buf, "unique_key ");
02489                      }
02490 #endif
02491 #ifdef MULTIPLE_KEY_FLAG
02492                      if (mysql_field->flags&MULTIPLE_KEY_FLAG) {
02493                             strcat(buf, "multiple_key ");
02494                      }
02495 #endif
02496 #ifdef IS_BLOB
02497                      if (IS_BLOB(mysql_field->flags)) {
02498                             strcat(buf, "blob ");
02499                      }
02500 #endif
02501 #ifdef UNSIGNED_FLAG
02502                      if (mysql_field->flags&UNSIGNED_FLAG) {
02503                             strcat(buf, "unsigned ");
02504                      }
02505 #endif
02506 #ifdef ZEROFILL_FLAG
02507                      if (mysql_field->flags&ZEROFILL_FLAG) {
02508                             strcat(buf, "zerofill ");
02509                      }
02510 #endif
02511 #ifdef BINARY_FLAG
02512                      if (mysql_field->flags&BINARY_FLAG) {
02513                             strcat(buf, "binary ");
02514                      }
02515 #endif
02516 #ifdef ENUM_FLAG
02517                      if (mysql_field->flags&ENUM_FLAG) {
02518                             strcat(buf, "enum ");
02519                      }
02520 #endif
02521 #ifdef SET_FLAG
02522                      if (mysql_field->flags&SET_FLAG) {
02523                             strcat(buf, "set ");
02524                      }
02525 #endif
02526 #ifdef AUTO_INCREMENT_FLAG
02527                      if (mysql_field->flags&AUTO_INCREMENT_FLAG) {
02528                             strcat(buf, "auto_increment ");
02529                      }
02530 #endif
02531 #ifdef TIMESTAMP_FLAG
02532                      if (mysql_field->flags&TIMESTAMP_FLAG) {
02533                             strcat(buf, "timestamp ");
02534                      }
02535 #endif
02536                      len = strlen(buf);
02537                      /* remove trailing space, if present */
02538                      if (len && buf[len-1] == ' ') {
02539                             buf[len-1] = 0;
02540                             len--;
02541                      }
02542 
02543                      Z_STRLEN_P(return_value) = len;
02544                      Z_STRVAL_P(return_value) = estrndup(buf, len);
02545                      Z_TYPE_P(return_value) = IS_STRING;
02546                      break;
02547 
02548               default:
02549                      RETURN_FALSE;
02550        }
02551 }
02552 /* }}} */
02553 
02554 /* {{{ proto string mysql_field_name(resource result, int field_index)
02555    Gets the name of the specified field in a result */
02556 PHP_FUNCTION(mysql_field_name)
02557 {
02558        php_mysql_field_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_MYSQL_FIELD_NAME);
02559 }
02560 /* }}} */
02561 
02562 
02563 /* {{{ proto string mysql_field_table(resource result, int field_offset)
02564    Gets name of the table the specified field is in */
02565 PHP_FUNCTION(mysql_field_table)
02566 {
02567        php_mysql_field_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_MYSQL_FIELD_TABLE);
02568 }
02569 /* }}} */
02570 
02571 
02572 /* {{{ proto int mysql_field_len(resource result, int field_offset)
02573    Returns the length of the specified field */
02574 PHP_FUNCTION(mysql_field_len)
02575 {
02576        php_mysql_field_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_MYSQL_FIELD_LEN);
02577 }
02578 /* }}} */
02579 
02580 
02581 /* {{{ proto string mysql_field_type(resource result, int field_offset)
02582    Gets the type of the specified field in a result */
02583 PHP_FUNCTION(mysql_field_type)
02584 {
02585        php_mysql_field_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_MYSQL_FIELD_TYPE);
02586 }
02587 /* }}} */
02588 
02589 
02590 /* {{{ proto string mysql_field_flags(resource result, int field_offset)
02591    Gets the flags associated with the specified field in a result */
02592 PHP_FUNCTION(mysql_field_flags)
02593 {
02594        php_mysql_field_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_MYSQL_FIELD_FLAGS);
02595 }
02596 /* }}} */
02597 
02598 
02599 /* {{{ proto bool mysql_free_result(resource result)
02600    Free result memory */
02601 PHP_FUNCTION(mysql_free_result)
02602 {
02603        zval *result;
02604        MYSQL_RES *mysql_result;
02605 
02606        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &result) == FAILURE) {
02607               return;
02608        }
02609 
02610        if (Z_LVAL_P(result)==0) {
02611               RETURN_FALSE;
02612        }
02613 
02614        ZEND_FETCH_RESOURCE(mysql_result, MYSQL_RES *, &result, -1, "MySQL result", le_result);
02615 
02616        zend_list_delete(Z_LVAL_P(result));
02617        RETURN_TRUE;
02618 }
02619 /* }}} */
02620 
02621 /* {{{ proto bool mysql_ping([int link_identifier])
02622    Ping a server connection. If no connection then reconnect. */
02623 PHP_FUNCTION(mysql_ping)
02624 {
02625        zval           *mysql_link = NULL;
02626        int             id         = -1;
02627        php_mysql_conn *mysql;
02628 
02629        if (0 == ZEND_NUM_ARGS()) {
02630               id = php_mysql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU);
02631               CHECK_LINK(id);
02632        } else if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &mysql_link)==FAILURE) {
02633               return;
02634        }
02635 
02636        ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, &mysql_link, id, "MySQL-Link", le_link, le_plink);
02637 
02638        PHPMY_UNBUFFERED_QUERY_CHECK();
02639 
02640        RETURN_BOOL(! mysql_ping(mysql->conn));
02641 }
02642 /* }}} */
02643 
02644 #endif
02645 
02646 /*
02647  * Local variables:
02648  * tab-width: 4
02649  * c-basic-offset: 4
02650  * End:
02651  * vim600: sw=4 ts=4 fdm=marker
02652  * vim<600: sw=4 ts=4
02653  */