Author: ahristov
Date: 2007-08-22 16:59:22 +0200 (Wed, 22 Aug 2007)
New Revision: 940
Modified:
trunk/mysqlnd/mysqlnd.c
trunk/mysqlnd/mysqlnd.h
trunk/mysqlnd/mysqlnd_palloc.c
trunk/mysqlnd/mysqlnd_result.c
trunk/mysqlnd/mysqlnd_result_meta.c
trunk/mysqlnd/mysqlnd_wireprotocol.c
trunk/mysqlnd/mysqlnd_wireprotocol.h
Log:
COM_FIELD_LIST (mysqlnd_list_fields) now works like mysql_field_list
of libmysql
Modified: trunk/mysqlnd/mysqlnd.c
===================================================================
--- trunk/mysqlnd/mysqlnd.c 2007-08-21 15:07:41 UTC (rev 939)
+++ trunk/mysqlnd/mysqlnd.c 2007-08-22 14:59:22 UTC (rev 940)
@@ -800,10 +800,69 @@
/* }}} */
+/*
+ COM_FIELD_LIST is special, different from a SHOW FIELDS FROM :
+ - There is no result set header - status from the command, which
+ impacts us to allocate big chunk of memory for reading the metadata.
+ - The EOF packet is consumed by the metadata packet reader.
+*/
+
+/* {{{ mysqlnd_conn::list_fields */
+MYSQLND_RES *
+MYSQLND_METHOD(mysqlnd_conn, list_fields)(MYSQLND *conn, const char *table, const char
*achtung_wild TSRMLS_DC)
+{
+ /* db + \0 + wild + \0 (for wild) */
+ char buff[MYSQLND_MAX_ALLOWED_DB_LEN * 4 * 2 + 1 + 1], *p;
+ size_t table_len, wild_len;
+ MYSQLND_RES *result = NULL;
+ DBG_ENTER("mysqlnd_conn::list_fields");
+ DBG_INF_FMT("conn=%llu table=%s wild=%s", conn->thread_id, table?
table:"",achtung_wild? achtung_wild:"");
+
+ p = buff;
+ if (table && (table_len = strlen(table))) {
+ memcpy(p, table, MIN(table_len, MYSQLND_MAX_ALLOWED_DB_LEN * 4));
+ p += table_len;
+ *p++ = '\0';
+ }
+
+ if (achtung_wild && (wild_len = strlen(achtung_wild))) {
+ memcpy(p, achtung_wild, MIN(wild_len, MYSQLND_MAX_ALLOWED_DB_LEN * 4));
+ p += wild_len;
+ *p++ = '\0';
+ }
+
+ if (PASS != mysqlnd_simple_command(conn, COM_FIELD_LIST, buff, p - buff,
+ PROT_LAST /* we will handle the OK packet*/,
+ FALSE TSRMLS_CC)) {
+ DBG_RETURN(NULL);
+ }
+ /*
+ Prepare for the worst case.
+ MyISAM goes to 2500 BIT columns, double it for safety.
+ */
+ result = mysqlnd_result_init(5000,
mysqlnd_palloc_get_thd_cache_reference(conn->zval_cache) TSRMLS_CC);
+
+
+ if (FAIL == result->m.read_result_metadata(result, conn TSRMLS_CC)) {
+ DBG_ERR("Error ocurred while reading metadata");
+ result->m.free_result(result, TRUE TSRMLS_CC);
+ DBG_RETURN(NULL);
+ }
+
+ result->type = MYSQLND_RES_NORMAL;
+ result->m.fetch_row = result->m.fetch_row_normal_unbuffered;
+ result->unbuf = ecalloc(1, sizeof(MYSQLND_RES_UNBUFFERED));
+ result->unbuf->eof_reached = TRUE;
+
+ DBG_RETURN(result);
+}
+/* }}} */
+
+
/* {{{ mysqlnd_conn::list_method */
MYSQLND_RES *
MYSQLND_METHOD(mysqlnd_conn, list_method)(MYSQLND *conn, const char *query,
- char *achtung_wild, char *par1 TSRMLS_DC)
+ const char *achtung_wild, char *par1 TSRMLS_DC)
{
char *show_query = NULL;
size_t show_query_len;
@@ -1713,6 +1772,7 @@
MYSQLND_METHOD(mysqlnd_conn, get_proto_info),
MYSQLND_METHOD(mysqlnd_conn, info),
MYSQLND_METHOD(mysqlnd_conn, charset_name),
+ MYSQLND_METHOD(mysqlnd_conn, list_fields),
MYSQLND_METHOD(mysqlnd_conn, list_method),
MYSQLND_METHOD(mysqlnd_conn, insert_id),
Modified: trunk/mysqlnd/mysqlnd.h
===================================================================
--- trunk/mysqlnd/mysqlnd.h 2007-08-21 15:07:41 UTC (rev 939)
+++ trunk/mysqlnd/mysqlnd.h 2007-08-22 14:59:22 UTC (rev 940)
@@ -371,7 +371,8 @@
unsigned int (*get_protocol_information)(const MYSQLND * const conn);
const char * (*get_last_message)(const MYSQLND * const conn);
const char * (*charset_name)(const MYSQLND * const conn);
- MYSQLND_RES * (*list_method)(MYSQLND *conn, const char *query, char *achtung_wild, char
*par1 TSRMLS_DC);
+ MYSQLND_RES * (*list_fields)(MYSQLND *conn, const char *table, const char *achtung_wild
TSRMLS_DC);
+ MYSQLND_RES * (*list_method)(MYSQLND *conn, const char *query, const char
*achtung_wild, char *par1 TSRMLS_DC);
mynd_ulonglong (*get_last_insert_id)(const MYSQLND * const conn);
mynd_ulonglong (*get_affected_rows)(const MYSQLND * const conn);
@@ -838,7 +839,7 @@
#define mysqlnd_commit(conn) (conn)->m->query((conn), "COMMIT",
sizeof("COMMIT")-1 TSRMLS_CC)
#define mysqlnd_rollback(conn) (conn)->m->query((conn), "ROLLBACK",
sizeof("ROLLBACK")-1 TSRMLS_CC)
#define mysqlnd_list_dbs(conn, wild) (conn)->m->list_method((conn), wild? "SHOW
DATABASES LIKE %s":"SHOW DATABASES", (wild), NULL TSRMLS_CC)
-#define mysqlnd_list_fields(conn, tab,wild) (conn)->m->list_method((conn), wild?
"SHOW FIELDS FROM %s LIKE %s":"SHOW FIELDS FROM %s", wild, tab TSRMLS_CC)
+#define mysqlnd_list_fields(conn, tab,wild) (conn)->m->list_fields((conn), (tab),
(wild) TSRMLS_CC)
#define mysqlnd_list_processes(conn) (conn)->m->list_method((conn), "SHOW
PROCESSLIST", NULL, NULL TSRMLS_CC)
#define mysqlnd_list_tables(conn, wild) (conn)->m->list_method((conn), wild? "SHOW
TABLES LIKE %s":"SHOW TABLES", (wild), NULL TSRMLS_CC)
#define
mysqlnd_dump_debug_info(conn) (conn)->m->server_dump_debug_information((conn)
TSRMLS_CC)
@@ -904,7 +905,7 @@
/* There two should not be used from outside */
-void * mysqlnd_palloc_get_zval(MYSQLND_THD_ZVAL_PCACHE * const cache, zend_bool
*allocated);
+void * mysqlnd_palloc_get_zval(MYSQLND_THD_ZVAL_PCACHE * const cache, zend_bool
*allocated TSRMLS_DC);
void mysqlnd_palloc_zval_ptr_dtor(zval **zv, MYSQLND_THD_ZVAL_PCACHE * const cache,
enum_mysqlnd_res_type type, zend_bool *copy_ctor_called TSRMLS_DC);
Modified: trunk/mysqlnd/mysqlnd_palloc.c
===================================================================
--- trunk/mysqlnd/mysqlnd_palloc.c 2007-08-21 15:07:41 UTC (rev 939)
+++ trunk/mysqlnd/mysqlnd_palloc.c 2007-08-22 14:59:22 UTC (rev 940)
@@ -23,6 +23,7 @@
#include "mysqlnd.h"
#include "mysqlnd_priv.h"
#include "mysqlnd_palloc.h"
+#include "mysqlnd_debug.h"
#define MYSQLND_SILENT
@@ -285,15 +286,14 @@
/* {{{ mysqlnd_palloc_get_zval */
-void *mysqlnd_palloc_get_zval(MYSQLND_THD_ZVAL_PCACHE * const thd_cache, zend_bool
*allocated)
+void *mysqlnd_palloc_get_zval(MYSQLND_THD_ZVAL_PCACHE * const thd_cache, zend_bool
*allocated TSRMLS_DC)
{
void *ret = NULL;
-#ifndef MYSQLND_SILENT
- php_printf("[mysqlnd_palloc_get_zval %p] *last_added=%p free_items=%d\n",
+ DBG_ENTER("mysqlnd_palloc_get_zval");
+ DBG_INF_FMT("cache=%p *last_added=%p free_items=%d\n",
thd_cache, thd_cache? thd_cache->parent->free_list.last_added:NULL,
thd_cache->parent->free_items);
-#endif
if (thd_cache) {
MYSQLND_ZVAL_PCACHE *cache = thd_cache->parent;
@@ -328,7 +328,8 @@
ZVAL_ADDREF(&(((mysqlnd_zval *)ret)->zv));
}
- return ret;
+ DBG_INF_FMT("allocated=%d ret=%p", *allocated, ret);
+ DBG_RETURN(ret);
}
/* }}} */
Modified: trunk/mysqlnd/mysqlnd_result.c
===================================================================
--- trunk/mysqlnd/mysqlnd_result.c 2007-08-21 15:07:41 UTC (rev 939)
+++ trunk/mysqlnd/mysqlnd_result.c 2007-08-22 14:59:22 UTC (rev 940)
@@ -125,6 +125,7 @@
{
DBG_ENTER("mysqlnd_res::free_result_buffers");
DBG_INF_FMT("%s", result->unbuf? "unbuffered":(result->data?
"buffered":"unknown"));
+
if (result->unbuf) {
mysqlnd_unbuffered_free_last_data(result TSRMLS_CC);
efree(result->unbuf);
Modified: trunk/mysqlnd/mysqlnd_result_meta.c
===================================================================
--- trunk/mysqlnd/mysqlnd_result_meta.c 2007-08-21 15:07:41 UTC (rev 939)
+++ trunk/mysqlnd/mysqlnd_result_meta.c 2007-08-22 14:59:22 UTC (rev 940)
@@ -161,6 +161,9 @@
PACKET_FREE_ALLOCA(field_packet);
DBG_RETURN(FAIL);
}
+ if (field_packet.stupid_list_fields_eof == TRUE) {
+ break;
+ }
if (mysqlnd_ps_fetch_functions[meta->fields[i].type].func == NULL) {
DBG_ERR_FMT("Unknown type %d sent by the server. Please send a report to the
developers",
Modified: trunk/mysqlnd/mysqlnd_wireprotocol.c
===================================================================
--- trunk/mysqlnd/mysqlnd_wireprotocol.c 2007-08-21 15:07:41 UTC (rev 939)
+++ trunk/mysqlnd/mysqlnd_wireprotocol.c 2007-08-22 14:59:22 UTC (rev 940)
@@ -1069,11 +1069,18 @@
if (packet->skip_parsing) {
DBG_RETURN(PASS);
}
+ if (*p == 0xFE && packet->header.size < 8) {
+ /* Premature EOF. That should be COM_FIELD_LIST */
+ DBG_INF("Premature EOF. That should be COM_FIELD_LIST");
+ packet->stupid_list_fields_eof = TRUE;
+ DBG_RETURN(PASS);
+ }
meta = packet->metadata;
for (i = 0; i < field_count; i += 2) {
- switch ((len = php_mysqlnd_net_field_length(&p))) {
+ len = php_mysqlnd_net_field_length(&p);
+ switch ((len)) {
case 0:
*(char **)(((char*)meta) + rset_field_offsets[i]) = mysqlnd_empty_string;
*(unsigned int *)(((char*)meta) + rset_field_offsets[i+1]) = 0;
@@ -1120,8 +1127,16 @@
}
- /* def could be empty, thus don't allocate on the root */
- if (packet->header.size > (p - buf) && (len =
php_mysqlnd_net_field_length(&p))) {
+ /*
+ def could be empty, thus don't allocate on the root.
+ NULL_LENGTH (0xFB) comes from COM_FIELD_LIST when the default value is NULL.
+ Otherwise the string is length encoded.
+ */
+ if (packet->header.size > (p - buf) &&
+ (len = php_mysqlnd_net_field_length(&p)) &&
+ len != MYSQLND_NULL_LENGTH)
+ {
+ DBG_INF_FMT("Def found, length %lu", len);
meta->def = emalloc(len + 1);
memcpy(meta->def, p, len);
meta->def[len] = '\0';
@@ -1186,8 +1201,8 @@
faulty_fake:
DBG_ERR_FMT("Protocol error. Server sent NULL_LENGTH. The server is faulty");
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Protocol error. Server sent NULL_LENGTH.",
- " The server is faulty. PID=%d", getpid());
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Protocol error. Server sent NULL_LENGTH."
+ " The server is faulty");
DBG_RETURN(FAIL);
}
/* }}} */
@@ -1306,7 +1321,7 @@
for (i = 0; current_field < end_field; current_field++, i++) {
#if 1
- obj = mysqlnd_palloc_get_zval(conn->zval_cache, &allocated);
+ obj = mysqlnd_palloc_get_zval(conn->zval_cache, &allocated TSRMLS_CC);
if (allocated) {
*current_field = (zval *) obj;
} else {
@@ -1362,7 +1377,7 @@
/* php_mysqlnd_net_field_length() call should be after *this_field_len_pos = p; */
unsigned long len = php_mysqlnd_net_field_length(&p);
- obj = mysqlnd_palloc_get_zval(conn->zval_cache, &allocated);
+ obj = mysqlnd_palloc_get_zval(conn->zval_cache, &allocated TSRMLS_CC);
if (allocated) {
*current_field = (zval *) obj;
} else {
@@ -1392,8 +1407,10 @@
ZVAL_NULL(*current_field);
last_field_was_string = FALSE;
} else {
+#if PHP_MAJOR_VERSION >= 6 || defined(MYSQLND_STRING_TO_INT_CONVERSION)
struct st_mysqlnd_perm_bind perm_bind =
mysqlnd_ps_fetch_functions[packet->fields_metadata[i].type];
+#endif
#ifdef MYSQLND_STRING_TO_INT_CONVERSION
if (as_int && perm_bind.php_type == IS_LONG &&
Modified: trunk/mysqlnd/mysqlnd_wireprotocol.h
===================================================================
--- trunk/mysqlnd/mysqlnd_wireprotocol.h 2007-08-21 15:07:41 UTC (rev 939)
+++ trunk/mysqlnd/mysqlnd_wireprotocol.h 2007-08-22 14:59:22 UTC (rev 940)
@@ -237,6 +237,7 @@
MYSQLND_FIELD *metadata;
/* For table definitions, empty for result sets */
zend_bool skip_parsing;
+ zend_bool stupid_list_fields_eof;
} php_mysql_packet_res_field;
| Thread |
|---|
| • PHP mysqlnd svn commit: r940 - trunk/mysqlnd | ahristov | 22 Aug |