List:Commits« Previous MessageNext Message »
From:ahristov Date:March 8 2007 10:15am
Subject:PHP mysqlnd svn commit: r94 - trunk/ext/mysqli/mysqlnd
View as plain text  
Author: ahristov
Date: 2007-03-08 10:15:49 +0100 (Thu, 08 Mar 2007)
New Revision: 94

Modified:
   trunk/ext/mysqli/mysqlnd/mysqlnd.c
   trunk/ext/mysqli/mysqlnd/mysqlnd.h
   trunk/ext/mysqli/mysqlnd/mysqlnd_ps.c
   trunk/ext/mysqli/mysqlnd/mysqlnd_ps_codec.c
Log:
Add empty mysqlnd_stmt_param_metadata()

Fix various bugs to pass stmt tests


Modified: trunk/ext/mysqli/mysqlnd/mysqlnd.c
===================================================================
--- trunk/ext/mysqli/mysqlnd/mysqlnd.c	2007-03-07 17:52:02 UTC (rev 93)
+++ trunk/ext/mysqli/mysqlnd/mysqlnd.c	2007-03-08 09:15:49 UTC (rev 94)
@@ -1456,11 +1456,17 @@
 static enum_func_status
 _mysqlnd_data_seek(MYSQLND_RES *result, mynd_ulonglong row)
 {
-	if (!result->data || row >= result->row_count) {
+	if (!result->data) {
 		return FAIL;
 	}
-	result->data_cursor = result->data + row;
 
+	/* libmysql just moves to the end, it does traversing of a linked list */
+	if (row >= result->row_count) {
+		result->data_cursor = NULL;
+	} else {
+		result->data_cursor = result->data + row;
+	}
+
 	return PASS;
 }
 /* }}} */
@@ -1657,8 +1663,8 @@
 		  a protocol of giving back -1. Thus we have to follow it :(
 		*/
 		conn->upsert_status.affected_rows = -1;	
-	} else {
-		ret = mysqlnd_simple_command(conn, COM_PROCESS_KILL, buff, 4, PROT_LAST, FALSE
TSRMLS_CC);
+	} else if (PASS == (ret = mysqlnd_simple_command(conn, COM_PROCESS_KILL, buff,
+													 4, PROT_LAST, FALSE TSRMLS_CC))) {
 		conn->state = CONN_QUIT_SENT;
 	}
 	return ret;
@@ -1785,7 +1791,8 @@
 /* {{{ _mysqlnd_num_fields */
 mynd_ulonglong _mysqlnd_num_rows(const MYSQLND_RES * const res)
 {
-	return res->row_count;
+	/* Be compatible with libmysql. We count row_count, but will return 0 */
+	return res->data? res->row_count:0;
 }
 /* }}} */
 

Modified: trunk/ext/mysqli/mysqlnd/mysqlnd.h
===================================================================
--- trunk/ext/mysqli/mysqlnd/mysqlnd.h	2007-03-07 17:52:02 UTC (rev 93)
+++ trunk/ext/mysqli/mysqlnd/mysqlnd.h	2007-03-08 09:15:49 UTC (rev 94)
@@ -24,7 +24,7 @@
 #define MYSQLND_H
 
 /* This forces inlining some accessor functions */
-#define MYSQLND_USE_OPTIMISATIONS 1
+#define MYSQLND_USE_OPTIMISATIONS 0
 /*
   This force mysqlnd to do a single (or more depending on ammount of data)
   non-blocking read() calls before sending a command to the server. Useful
@@ -578,6 +578,8 @@
 	enum_func_status	(*bind_result)(MYSQLND_STMT * const stmt, MYSQLND_RESULT_BIND * const
result_bind);
 	enum_func_status	(*send_long_data)(MYSQLND_STMT * const stmt, unsigned int param_num,
 										  const char * const data, unsigned long length TSRMLS_DC);
+	MYSQLND_RES			(*get_param_metadata)(MYSQLND_STMT * const stmt);
+
 	mynd_ulonglong		(*get_last_insert_id)(const MYSQLND_STMT * const stmt);
 	mynd_ulonglong		(*get_affected_rows)(const MYSQLND_STMT * const stmt);
 	mynd_ulonglong		(*get_num_rows)(const MYSQLND_STMT * const stmt);
@@ -754,6 +756,7 @@
 	unsigned char				send_types_to_server;
 	MYSQLND_PARAM_BIND			*param_bind;
 	MYSQLND_RESULT_BIND			*result_bind;
+	zend_bool					result_zvals_separated_once;
 
 	mysqlnd_upsert_status		upsert_status;
 
@@ -834,7 +837,7 @@
 #define mysqlnd_get_proto_info(conn)	(conn)->protocol_version
 #define mysqlnd_thread_id(conn)			(conn)->thread_id
 
-#define mysqlnd_num_rows(result)		(result)->row_count
+#define mysqlnd_num_rows(result)		((result)->data? (result)->row_count:0)
 #define mysqlnd_num_fields(result)		(result)->field_count
 
 #define mysqlnd_fetch_lengths(result)	((result)->m.fetch_lengths?
(result)->m.fetch_lengths((result)):NULL)
@@ -851,7 +854,7 @@
 /* PS */
 #define mysqlnd_stmt_insert_id(stmt)		(stmt)->upsert_status.last_insert_id
 #define mysqlnd_stmt_affected_rows(stmt)	(stmt)->upsert_status.affected_rows
-#define mysqlnd_stmt_num_rows(stmt)			((stmt)->result?
(stmt)->result->row_count:0)
+#define mysqlnd_stmt_num_rows(stmt)			(stmt)->result?
mysqlnd_num_rows((stmt)->result):0
 #define mysqlnd_stmt_param_count(stmt)		(stmt)->param_count
 #define mysqlnd_stmt_field_count(stmt)		(stmt)->field_count
 #define mysqlnd_stmt_warning_count(stmt)	(stmt)->upsert_status.warning_count
@@ -948,6 +951,7 @@
 #define mysqlnd_stmt_send_long_data(s,p,d,l) (s)->m->send_long_data((s), (p), (d),
(l) TSRMLS_CC)
 #define mysqlnd_stmt_bind_param(stmt,bind)	(stmt)->m->bind_param((stmt), (bind))
 #define mysqlnd_stmt_bind_result(stmt,bind)	(stmt)->m->bind_result((stmt), (bind))
+#define mysqlnd_stmt_param_metadata(stmt)	(stmt)->m->get_param_metadata((stmt))
 
 #define	mysqlnd_stmt_free_result(stmt)		(stmt)->m->free_result((stmt) TSRMLS_CC)
 #define	mysqlnd_stmt_close(stmt, implicit)	(stmt)->m->dtor((stmt), (implicit)
TSRMLS_CC)

Modified: trunk/ext/mysqli/mysqlnd/mysqlnd_ps.c
===================================================================
--- trunk/ext/mysqli/mysqlnd/mysqlnd_ps.c	2007-03-07 17:52:02 UTC (rev 93)
+++ trunk/ext/mysqli/mysqlnd/mysqlnd_ps.c	2007-03-08 09:15:49 UTC (rev 94)
@@ -53,7 +53,7 @@
 											   unsigned int flags,
 											   zend_bool *fetched_anything TSRMLS_DC);
 
-void mysqlnd_stmt_separate_result_bind(MYSQLND_STMT *stmt);
+void mysqlnd_stmt_separate_result_bind(MYSQLND_STMT * const stmt);
 
 
 /* {{{ _mysqlnd_stmt_store_result */
@@ -352,11 +352,21 @@
 	SET_ERROR_AFF_ROWS(stmt->conn);
 	
 	if (stmt->state > MYSQLND_STMT_PREPARED && stmt->field_count) {
-		if (stmt->result_bind && stmt->state >= MYSQLND_STMT_USER_FETCHING) {
+		if (stmt->result_bind &&
+			stmt->result_zvals_separated_once == TRUE && 
+			stmt->state >= MYSQLND_STMT_USER_FETCHING)
+		{
 			/*
 			  We need to copy the data from the buffers which we will clean.
 			  The bound variables point to them only if the user has started
 			  to fetch data (MYSQLND_STMT_USER_FETCHING).
+			  We need to check 'result_zvals_separated_once' or we will leak
+			  in the following scenation
+			  prepare("select 1 from dual");
+			  execute();
+			  fetch(); <-- no binding, but that's not a problem
+			  bind_result();
+			  execute(); <-- here we will leak because we separate without need
 			*/
 			unsigned int i;
 			for (i = 0; i < stmt->field_count; i++) {
@@ -467,23 +477,26 @@
 
 	/* If we haven't read everything */
 	if (result->data_cursor && (result->data_cursor - result->data) <
result->row_count) {
-		zval **current_row = *result->data_cursor;
-		for (i = 0; i < result->field_count; i++) {
-			/* copy the type */
-			if (stmt->result_bind[i].bound == TRUE) {
-				if (Z_TYPE_P(current_row[i]) != IS_NULL) {
-					/*
-					  Copy the value.
-					  Pre-condition is that the zvals in the result_bind buffer
-					  have been  ZVAL_NULL()-ed or to another simple type
-					  (int, double, bool but not string). Because of the reference
-					  counting the user can't delete the strings the variables point to.
-					*/
+		/* The user could have skipped binding - don't crash*/
+		if (stmt->result_bind) {
+			zval **current_row = *result->data_cursor;
+			for (i = 0; i < result->field_count; i++) {
+				/* copy the type */
+				if (stmt->result_bind[i].bound == TRUE) {
+					if (Z_TYPE_P(current_row[i]) != IS_NULL) {
+						/*
+						  Copy the value.
+						  Pre-condition is that the zvals in the result_bind buffer
+						  have been  ZVAL_NULL()-ed or to another simple type
+						  (int, double, bool but not string). Because of the reference
+						  counting the user can't delete the strings the variables point to.
+						*/
 
-					Z_TYPE_P(stmt->result_bind[i].zv) = Z_TYPE_P(current_row[i]);
-					stmt->result_bind[i].zv->value = current_row[i]->value;
-				} else {
-					ZVAL_NULL(stmt->result_bind[i].zv);
+						Z_TYPE_P(stmt->result_bind[i].zv) = Z_TYPE_P(current_row[i]);
+						stmt->result_bind[i].zv->value = current_row[i]->value;
+					} else {
+						ZVAL_NULL(stmt->result_bind[i].zv);
+					}
 				}
 			}
 		}
@@ -521,7 +534,7 @@
 		return FAIL;
 	}
 	/* Let the row packet fill our buffer and skip additional malloc + memcpy */
-	row_packet->skip_extraction = stmt? FALSE:TRUE;
+	row_packet->skip_extraction = stmt && stmt->result_bind? FALSE:TRUE;
 
 	/*
 	  If we skip rows (row == NULL) we have to
@@ -659,6 +672,8 @@
 		return FAIL;
 	}
 
+	row_packet->skip_extraction = stmt->result_bind? FALSE:TRUE;
+
 	if (PASS == (ret = PACKET_READ(row_packet, result->conn)) &&
!row_packet->eof) {
 		unsigned int i, field_count = result->field_count;
 		mysqlnd_unbuffered_free_last_data(result);
@@ -667,21 +682,23 @@
 		result->last_row_buffer = row_packet->row_buffer;
 		row_packet->fields = NULL;
 		row_packet->row_buffer = NULL;
+		if (!row_packet->skip_extraction) {
+			/* If no result bind, do nothing. We consumed the data */
+			for (i = 0; i < field_count; i++) {
+				if (stmt->result_bind[i].bound == TRUE) {
+					zval *data = result->last_row_data[i];
+					/*
+					  stmt->result_bind[i].zv has been already destructed
+					  in mysqlnd_unbuffered_free_last_data()
+					*/
 
-		for (i = 0; i < field_count; i++) {
-			if (stmt->result_bind[i].bound == TRUE) {
-				zval *data = result->last_row_data[i];
-				/*
-				  stmt->result_bind[i].zv has been already destructed
-				  in mysqlnd_unbuffered_free_last_data()
-				*/
-
-				if (IS_NULL != (Z_TYPE_P(stmt->result_bind[i].zv) = Z_TYPE_P(data)) ) {
-					stmt->result_bind[i].zv->value = data->value;
-					if ((Z_TYPE_P(data) == IS_STRING || Z_TYPE_P(data) == IS_UNICODE)
-						 && (result->fields[i].max_length < Z_STRLEN_P(data)))
-					{
-						result->fields[i].max_length = Z_STRLEN_P(data);
+					if (IS_NULL != (Z_TYPE_P(stmt->result_bind[i].zv) = Z_TYPE_P(data)) ) {
+						stmt->result_bind[i].zv->value = data->value;
+						if ((Z_TYPE_P(data) == IS_STRING || Z_TYPE_P(data) == IS_UNICODE)
+							 && (result->fields[i].max_length < Z_STRLEN_P(data)))
+						{
+							result->fields[i].max_length = Z_STRLEN_P(data);
+						}
 					}
 				}
 			}
@@ -723,16 +740,22 @@
 enum_func_status
 mysqlnd_stmt_fetch(MYSQLND_STMT * const stmt, zend_bool * const fetched_anything
TSRMLS_DC)
 {
-	if (!stmt->result || !stmt->result_bind ||
+	if (!stmt->result ||
 		stmt->state < MYSQLND_STMT_WAITING_USE_OR_STORE) {
 		return FAIL;
 	} else if (stmt->state == MYSQLND_STMT_WAITING_USE_OR_STORE) {
 		/* Execute only once. We have to free the previous contents of user's bound vars */
 
 		stmt->default_rset_handler(stmt TSRMLS_CC);
+		stmt->state = MYSQLND_STMT_USER_FETCHING;
 	}
 	/* no else please */
-	if (stmt->state == MYSQLND_STMT_USE_OR_STORE_CALLED) {
+
+	/*
+	  The user might have not bound any variables for result.
+	  Do the binding once she does it.
+	*/
+	if (stmt->result_bind && !stmt->result_zvals_separated_once) {
 		unsigned int i;
 		/*
 		  mysqlnd_stmt_store_result() has been called free the bind
@@ -744,9 +767,8 @@
 				ZVAL_NULL(stmt->result_bind[i].zv);
 			}
 		}
-		stmt->state = MYSQLND_STMT_USER_FETCHING;
+		stmt->result_zvals_separated_once = TRUE;
 	}
-	/* no else clause here please */
 
 	MYSQLND_INC_CONN_STATISTIC(&stmt->conn->stats, STAT_ROWS_FETCHED_FROM_CLIENT);
 
@@ -989,6 +1011,7 @@
 _mysqlnd_stmt_bind_result(MYSQLND_STMT * const stmt, MYSQLND_RESULT_BIND * const
result_bind)
 {
 	int i = 0;
+
 	if (stmt->state < MYSQLND_STMT_PREPARED) {
 		SET_STMT_ERROR(stmt, CR_NO_PREPARE_STMT, UNKNOWN_SQLSTATE, mysqlnd_stmt_not_prepared);
 		return FAIL;
@@ -997,11 +1020,10 @@
 	if (stmt->field_count) {
 		if (!result_bind) {
 			return FAIL;
-		} else if (stmt->result_bind) {
-			mysqlnd_stmt_separate_result_bind(stmt);
-			efree(stmt->result_bind);
 		}
 
+		mysqlnd_stmt_separate_result_bind(stmt);
+
 		stmt->result_bind = result_bind;
 		for (i = 0; i < stmt->field_count; i++) {
 			/* Prevent from freeing */
@@ -1038,7 +1060,7 @@
 static
 mynd_ulonglong _mysqlnd_stmt_num_rows(const MYSQLND_STMT * const stmt)
 {
-	return stmt->result? stmt->result->row_count:0;
+	return stmt->result? mysqlnd_num_rows(stmt->result):0;
 }
 /* }}} */
 
@@ -1106,6 +1128,19 @@
 /* }}} */
 
 
+/* {{{ _mysqlnd_stmt_param_metadata */
+static
+MYSQLND_RES * _mysqlnd_stmt_param_metadata(MYSQLND_STMT * const stmt)
+{
+	if (!stmt->param_count) {
+		return NULL;
+	}
+
+	return NULL;
+}
+/* }}} */
+
+
 /* {{{ _mysqlnd_stmt_attr_set */
 static enum_func_status
 _mysqlnd_stmt_attr_set(MYSQLND_STMT * const stmt, enum mysqlnd_stmt_attr attr_type, const
void * const value)
@@ -1188,9 +1223,7 @@
 		  Separate the bound variables, which point to the result set, then
 		  destroy the set.
 		*/
-		if (stmt->result_bind) {
-			mysqlnd_stmt_separate_result_bind(stmt);
-		}
+		mysqlnd_stmt_separate_result_bind(stmt);
 
 		/* Now we can destroy the result set */
 		stmt->result->m.free_result_buffers(stmt->result);
@@ -1208,12 +1241,14 @@
 
 
 /* {{{ mysqlnd_stmt_separate_result_bind */
-void mysqlnd_stmt_separate_result_bind(MYSQLND_STMT *stmt)
+void mysqlnd_stmt_separate_result_bind(MYSQLND_STMT * const stmt)
 {
 	int i;
+
 	if (!stmt->result_bind) {
 		return;
 	}
+
 	/*
 	  Because only the bound variables can point to our internal buffers, then
 	  separate or free only them. Free is possible because the user could have
@@ -1248,6 +1283,8 @@
 			}
 		}
 	}
+	efree(stmt->result_bind);
+	stmt->result_bind = NULL;
 }
 /* }}} */
 
@@ -1278,12 +1315,7 @@
 	  First separate the bound variables, which point to the result set, then
 	  destroy the set.
 	*/
-	if (stmt->result_bind) {
-		mysqlnd_stmt_separate_result_bind(stmt);
-
-		efree(stmt->result_bind);
-		stmt->result_bind = NULL;
-	}
+	mysqlnd_stmt_separate_result_bind(stmt);
 	/* Not every statement has a result set attached */
 	if (stmt->result) {
 		mysqlnd_internal_free_result(stmt->result TSRMLS_CC);
@@ -1321,6 +1353,7 @@
 	_mysqlnd_stmt_bind_param,
 	_mysqlnd_stmt_bind_result,
 	_mysqlnd_stmt_send_long_data,
+	_mysqlnd_stmt_param_metadata,
 
 	_mysqlnd_stmt_insert_id,
 	_mysqlnd_stmt_affected_rows,

Modified: trunk/ext/mysqli/mysqlnd/mysqlnd_ps_codec.c
===================================================================
--- trunk/ext/mysqli/mysqlnd/mysqlnd_ps_codec.c	2007-03-07 17:52:02 UTC (rev 93)
+++ trunk/ext/mysqli/mysqlnd/mysqlnd_ps_codec.c	2007-03-08 09:15:49 UTC (rev 94)
@@ -155,7 +155,8 @@
 		 * use MYSQLND_LL_SPEC.
 		 */
 		sprintf((char *)&tmp, uns == TRUE? MYSQLND_LLU_SPEC : MYSQLND_LL_SPEC, llval);
-		ZVAL_UTF8_STRING(zv, tmp, ZSTR_DUPLICATE);
+//		ZVAL_UTF8_STRING(zv, tmp, ZSTR_DUPLICATE);
+		ZVAL_STRING(zv, tmp, 1);
 	} else {
 		ZVAL_LONG(zv, llval);
 	}

Thread
PHP mysqlnd svn commit: r94 - trunk/ext/mysqli/mysqlndahristov8 Mar