php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Return to Bug #63356
Patch Firebird_Native_Data_Types revision 2012-10-25 08:11 UTC by james at kenjim dot com

Patch Firebird_Native_Data_Types for PDO Firebird Bug #63356

Patch version 2012-10-25 08:11 UTC

Return to Bug #63356 | Download this patch
Patch Revisions:

Developer: james@kenjim.com

diff --git a/ext/pdo/pdo_stmt.c b/ext/pdo/pdo_stmt.c
index 31932eb..6f20c4a 100644
--- a/ext/pdo/pdo_stmt.c
+++ b/ext/pdo/pdo_stmt.c
@@ -564,8 +564,9 @@ static inline void fetch_value(pdo_stmt_t *stmt, zval *dest, int colno, int *typ
 		case PDO_PARAM_ZVAL:
 			if (value && value_len == sizeof(zval)) {
 				int need_copy = (new_type != PDO_PARAM_ZVAL || stmt->dbh->stringify) ? 1 : 0;
-				zval *zv = *(zval**)value;
-				ZVAL_ZVAL(dest, zv, need_copy, 1);
+				zval *zv = (zval*)value;
+				ZVAL_ZVAL(dest, zv, need_copy, caller_frees);
+				caller_frees = 0;
 			} else {
 				ZVAL_NULL(dest);
 			}
diff --git a/ext/pdo_firebird/firebird_statement.c b/ext/pdo_firebird/firebird_statement.c
index ae05870..eed817b 100644
--- a/ext/pdo_firebird/firebird_statement.c
+++ b/ext/pdo_firebird/firebird_statement.c
@@ -208,7 +208,7 @@ static int firebird_stmt_describe(pdo_stmt_t *stmt, int colno TSRMLS_DC) /* {{{
 	}
 	memmove(cp, var->aliasname, var->aliasname_length);
 	*(cp+var->aliasname_length) = '\0';
-	col->param_type = PDO_PARAM_STR;
+	col->param_type = PDO_PARAM_ZVAL;
 
 	return 1;
 }
@@ -269,7 +269,7 @@ static int firebird_fetch_blob(pdo_stmt_t *stmt, int colno, char **ptr, /* {{{ *
 		unsigned short seg_len;
 		ISC_STATUS stat;
 
-		*ptr = S->fetch_buf[colno] = erealloc(*ptr, *len+1);
+		*ptr = erealloc(*ptr, *len+1);
 	
 		for (cur_len = stat = 0; (!stat || stat == isc_segment) && cur_len < *len; cur_len += seg_len) {
 	
@@ -302,12 +302,18 @@ static int firebird_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr,  /* {{
 {
 	pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
 	XSQLVAR const *var = &S->out_sqlda.sqlvar[colno];
+	zval *result;
 
 	if (*var->sqlind == -1) {
 		/* A NULL value */
 		*ptr = NULL;
 		*len = 0;
 	} else {
+		MAKE_STD_ZVAL(result);
+		*len = sizeof(zval);
+		*ptr = (char*)result;
+		*caller_frees = 1;
+
 		if (var->sqlscale < 0) {
 			static ISC_INT64 const scales[] = { 1, 10, 100, 1000, 
 				10000, 
@@ -339,49 +345,55 @@ static int firebird_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr,  /* {{
 					n = *(ISC_INT64*)var->sqldata;
 			}
 				
-			*ptr = FETCH_BUF(S->fetch_buf[colno], char, CHAR_BUF_LEN, NULL);
+			char* tmp = FETCH_BUF(S->fetch_buf[colno], char, CHAR_BUF_LEN, NULL);
+			int tmp_len = 0;
 			
 			if (n >= 0) {
-				*len = slprintf(*ptr, CHAR_BUF_LEN, "%" LL_MASK "d.%0*" LL_MASK "d", 
+				tmp_len = slprintf(tmp, CHAR_BUF_LEN, "%" LL_MASK "d.%0*" LL_MASK "d", 
 					n / f, -var->sqlscale, n % f);
 			} else if (n < -f) {
-				*len = slprintf(*ptr, CHAR_BUF_LEN, "%" LL_MASK "d.%0*" LL_MASK "d",
+				tmp_len = slprintf(tmp, CHAR_BUF_LEN, "%" LL_MASK "d.%0*" LL_MASK "d",
 					n / f, -var->sqlscale, -n % f);				
-			 } else {
-				*len = slprintf(*ptr, CHAR_BUF_LEN, "-0.%0*" LL_MASK "d", -var->sqlscale, -n % f);
+			} else {
+				tmp_len = slprintf(tmp, CHAR_BUF_LEN, "-0.%0*" LL_MASK "d", -var->sqlscale, -n % f);
 			}
+			ZVAL_STRINGL(result, tmp, tmp_len, 0);
 		} else {
 			switch (var->sqltype & ~1) {
 				struct tm t;
 				char *fmt;				
 
 				case SQL_VARYING:
-					*ptr = &var->sqldata[2];
-					*len = *(short*)var->sqldata;
+					ZVAL_STRINGL(result, &var->sqldata[2], *(short*)var->sqldata, 1);
 					break;
 				case SQL_TEXT:
-					*ptr = var->sqldata;
-					*len = var->sqllen;
+					ZVAL_STRINGL(result, var->sqldata, var->sqllen, 1);
 					break;
 				case SQL_SHORT:
-				    *ptr = FETCH_BUF(S->fetch_buf[colno], char, CHAR_BUF_LEN, NULL);
-					*len = slprintf(*ptr, CHAR_BUF_LEN, "%d", *(short*)var->sqldata);
+					ZVAL_LONG(result, *(short*)var->sqldata);
 					break;
 				case SQL_LONG:
-					*ptr = FETCH_BUF(S->fetch_buf[colno], char, CHAR_BUF_LEN, NULL);
-					*len = slprintf(*ptr, CHAR_BUF_LEN, "%ld", *(ISC_LONG*)var->sqldata);
+					ZVAL_LONG(result, *(ISC_LONG*)var->sqldata);
 					break;
 				case SQL_INT64:
-					*ptr = FETCH_BUF(S->fetch_buf[colno], char, CHAR_BUF_LEN, NULL);
-					*len = slprintf(*ptr, CHAR_BUF_LEN, "%" LL_MASK "d", *(ISC_INT64*)var->sqldata);
+					{
+						ISC_INT64 tmpValue = *(ISC_INT64*)var->sqldata;
+						if((tmpValue > LONG_MAX) || (tmpValue < LONG_MIN)) { //Too big to fit in a long.
+							char* tmp = FETCH_BUF(S->fetch_buf[colno], char, CHAR_BUF_LEN, NULL);
+							int temp_len = slprintf(tmp, CHAR_BUF_LEN, "%" LL_MASK "d", *(ISC_INT64*)var->sqldata);
+							ZVAL_STRINGL(result, tmp, temp_len, 0);
+						} else {
+							ZVAL_LONG(result, *(ISC_INT64*)var->sqldata);
+						}
+
+					}
+
 					break;
 				case SQL_FLOAT:
-					*ptr = FETCH_BUF(S->fetch_buf[colno], char, CHAR_BUF_LEN, NULL);
-					*len = slprintf(*ptr, CHAR_BUF_LEN, "%F", *(float*)var->sqldata);
+					ZVAL_DOUBLE(result, *(float*)var->sqldata);
 					break;
 				case SQL_DOUBLE:
-					*ptr = FETCH_BUF(S->fetch_buf[colno], char, CHAR_BUF_LEN, NULL);
-					*len = slprintf(*ptr, CHAR_BUF_LEN, "%F" , *(double*)var->sqldata);
+					ZVAL_DOUBLE(result, *(double*)var->sqldata);
 					break;
 				case SQL_TYPE_DATE:
 					isc_decode_sql_date((ISC_DATE*)var->sqldata, &t);
@@ -396,13 +408,27 @@ static int firebird_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr,  /* {{
 						fmt = S->H->timestamp_format ? S->H->timestamp_format : PDO_FB_DEF_TIMESTAMP_FMT;
 					}
 					/* convert the timestamp into a string */
-					*len = 80;
-					*ptr = FETCH_BUF(S->fetch_buf[colno], char, *len, NULL);
-					*len = strftime(*ptr, *len, fmt, &t);
+					char *buffer = FETCH_BUF(S->fetch_buf[colno], char, 80, NULL);
+					int temp_len = strftime(buffer, 80, fmt, &t);
+					ZVAL_STRINGL(result, buffer, temp_len, 1);
 					break;
 				case SQL_BLOB:
-					return firebird_fetch_blob(stmt,colno,ptr,len,
-						(ISC_QUAD*)var->sqldata TSRMLS_CC);
+					{
+						char *blob_buffer = NULL;
+						unsigned long blob_len = 0;
+						if(!firebird_fetch_blob(stmt,colno,
+									&blob_buffer, &blob_len,
+									(ISC_QUAD*)var->sqldata TSRMLS_CC)) {
+							ZVAL_NULL(result);
+							return 0;
+						}
+
+	
+						if(blob_len > INT_MAX) {
+							blob_len = INT_MAX;
+						}
+						ZVAL_STRINGL(result, blob_buffer, blob_len, 0);
+					}
 			}
 		}
 	}
@@ -424,30 +450,28 @@ static int firebird_bind_blob(pdo_stmt_t *stmt, ISC_QUAD *blob_id, zval *param T
 		return 0;
 	}
 
-	SEPARATE_ZVAL(&param);
-
-	convert_to_string_ex(&param);
+	//Blobs are always strings or nulls.
+	if(Z_TYPE_P(param) == IS_STRING) { //Make sure we did not get passed a NULL
+		char *buffer = Z_STRVAL_P(param);
+		for (rem_cnt = Z_STRLEN_P(param); rem_cnt > 0; rem_cnt -= chunk_size)  {
 	
-	for (rem_cnt = Z_STRLEN_P(param); rem_cnt > 0; rem_cnt -= chunk_size)  {
-
-		chunk_size = rem_cnt > USHRT_MAX ? USHRT_MAX : (unsigned short)rem_cnt;
-
-		if (isc_put_segment(H->isc_status, &h, chunk_size, &Z_STRVAL_P(param)[put_cnt])) {
-			RECORD_ERROR(stmt);
-			result = 0;
-			break;
+			chunk_size = rem_cnt > USHRT_MAX ? USHRT_MAX : (unsigned short)rem_cnt;
+	
+			if (isc_put_segment(H->isc_status, &h, chunk_size, &buffer[put_cnt])) {
+				RECORD_ERROR(stmt);
+				result = 0;
+				break;
+			}
+			put_cnt += chunk_size;
 		}
-		put_cnt += chunk_size;
 	}
-	
-	zval_dtor(param);
 
 	if (isc_close_blob(H->isc_status, &h)) {
 		RECORD_ERROR(stmt);
 		return 0;
 	}
 	return result;
-}	
+}
 
 static int firebird_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data *param, /* {{{ */
 	enum pdo_param_event event_type TSRMLS_DC)
@@ -582,49 +606,23 @@ static int firebird_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_dat
 			break;
 
 		case PDO_PARAM_EVT_FETCH_POST:
-                        if (param->paramno == -1) {
-                            return 0;
-                        }
-			if (param->is_param) {
-				break;
+			if (param->paramno == -1) {
+				return 0;
 			}
-			value = NULL;
-			value_len = 0;
-			caller_frees = 0;
-			
-			if (firebird_stmt_get_col(stmt, param->paramno, &value, &value_len, &caller_frees TSRMLS_CC)) {
-				switch (PDO_PARAM_TYPE(param->param_type)) {
-					case PDO_PARAM_STR:
-						if (value) {
-							ZVAL_STRINGL(param->parameter, value, value_len, 1);
-							break;
-						}
-					case PDO_PARAM_INT:
-						if (value) {
-							ZVAL_LONG(param->parameter, *(long*)value);
-							break;
-						}
-                                        case PDO_PARAM_EVT_NORMALIZE:
-                                                 if (!param->is_param) {
-                                                      char *s = param->name;
-                                                      while (*s != '\0') {
-                                                           *s = toupper(*s);
-                                                            s++;
-                                                      }
-                                                 }
-                                                        break;
-					default:
-						ZVAL_NULL(param->parameter);
-				}
-				if (value && caller_frees) {
-					efree(value);
+			break;
+
+		case PDO_PARAM_EVT_NORMALIZE:
+			if (!param->is_param) {
+				char *s = param->name;
+				while (*s != '\0') {
+					*s = toupper(*s);
+					s++;
 				}
-				return 1;
 			}
-			return 0;
+			break;
 		default:
 			;
-	}		
+	}
 	return 1;
 }
 /* }}} */
diff --git a/ext/pdo_mysql/mysql_statement.c b/ext/pdo_mysql/mysql_statement.c
index fc5ec51..b408a88 100644
--- a/ext/pdo_mysql/mysql_statement.c
+++ b/ext/pdo_mysql/mysql_statement.c
@@ -719,7 +719,7 @@ static int pdo_mysql_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, unsig
 #if PDO_USE_MYSQLND
 	if (S->stmt) {
 		Z_ADDREF_P(S->stmt->data->result_bind[colno].zv);
-		*ptr = (char*)&S->stmt->data->result_bind[colno].zv;
+		*ptr = (char*)S->stmt->data->result_bind[colno].zv;
 		*len = sizeof(zval);
 		PDO_DBG_RETURN(1);
 	}
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Fri Mar 29 10:01:28 2024 UTC