List:Commits« Previous MessageNext Message »
From:ahristov Date:August 22 2007 2:59pm
Subject:PHP mysqlnd svn commit: r940 - trunk/mysqlnd
View as plain text  
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/mysqlndahristov22 Aug