Commit 9e5bc9adc90 for php.net

commit 9e5bc9adc905a864dc6fee11ee94d68ccfcd9459
Author: Calvin Buckley <calvinb@php.net>
Date:   Fri Jun 26 10:28:24 2026 -0300

    ext/odbc: Fast ZPP conversion (#21893)

    Uses PATH_OR_NULL for strings to avoid surprise null terminators.

diff --git a/ext/odbc/php_odbc.c b/ext/odbc/php_odbc.c
index a6218cab727..17120e88af0 100644
--- a/ext/odbc/php_odbc.c
+++ b/ext/odbc/php_odbc.c
@@ -627,9 +627,10 @@ void php_odbc_fetch_attribs(INTERNAL_FUNCTION_PARAMETERS, int mode)
 	zval *pv_res;
 	zend_long flag;

-	if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ol", &pv_res, odbc_result_ce, &flag) == FAILURE) {
-		RETURN_THROWS();
-	}
+	ZEND_PARSE_PARAMETERS_START(2, 2)
+		Z_PARAM_OBJECT_OF_CLASS(pv_res, odbc_result_ce)
+		Z_PARAM_LONG(flag)
+	ZEND_PARSE_PARAMETERS_END();

 	result = Z_ODBC_RESULT_P(pv_res);
 	CHECK_ODBC_RESULT(result);
@@ -753,9 +754,9 @@ void odbc_transact(INTERNAL_FUNCTION_PARAMETERS, int type)
 	RETCODE rc;
 	zval *pv_conn;

-	if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &pv_conn, odbc_connection_ce) == FAILURE) {
-		RETURN_THROWS();
-	}
+	ZEND_PARSE_PARAMETERS_START(1, 1)
+		Z_PARAM_OBJECT_OF_CLASS(pv_conn, odbc_connection_ce)
+	ZEND_PARSE_PARAMETERS_END();

 	odbc_connection *conn = Z_ODBC_CONNECTION_P(pv_conn);
 	CHECK_ODBC_CONNECTION(conn);
@@ -778,9 +779,10 @@ void odbc_column_lengths(INTERNAL_FUNCTION_PARAMETERS, int type)
 	zval *pv_res;
 	zend_long pv_num;

-	if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ol", &pv_res, odbc_result_ce, &pv_num) == FAILURE) {
-		RETURN_THROWS();
-	}
+	ZEND_PARSE_PARAMETERS_START(2, 2)
+		Z_PARAM_OBJECT_OF_CLASS(pv_res, odbc_result_ce)
+		Z_PARAM_LONG(pv_num)
+	ZEND_PARSE_PARAMETERS_END();

 	result = Z_ODBC_RESULT_P(pv_res);
 	CHECK_ODBC_RESULT(result);
@@ -854,9 +856,10 @@ PHP_FUNCTION(odbc_prepare)
 	int i;
 	SQLUINTEGER      scrollopts;

-	if (zend_parse_parameters(ZEND_NUM_ARGS(), "Os", &pv_conn, odbc_connection_ce, &query, &query_len) == FAILURE) {
-		RETURN_THROWS();
-	}
+	ZEND_PARSE_PARAMETERS_START(2, 2)
+		Z_PARAM_OBJECT_OF_CLASS(pv_conn, odbc_connection_ce)
+		Z_PARAM_STRING(query, query_len)
+	ZEND_PARSE_PARAMETERS_END();

 	odbc_connection *conn = Z_ODBC_CONNECTION_P(pv_conn);
 	CHECK_ODBC_CONNECTION(conn);
@@ -967,9 +970,11 @@ PHP_FUNCTION(odbc_execute)
 	int i;
 	RETCODE rc;

-	if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|h", &pv_res, odbc_result_ce, &pv_param_ht) == FAILURE) {
-		RETURN_THROWS();
-	}
+	ZEND_PARSE_PARAMETERS_START(1, 2)
+		Z_PARAM_OBJECT_OF_CLASS(pv_res, odbc_result_ce)
+		Z_PARAM_OPTIONAL
+		Z_PARAM_ARRAY_HT(pv_param_ht)
+	ZEND_PARSE_PARAMETERS_END();

 	result = Z_ODBC_RESULT_P(pv_res);
 	CHECK_ODBC_RESULT(result);
@@ -1120,9 +1125,9 @@ PHP_FUNCTION(odbc_cursor)
 	odbc_result *result;
 	RETCODE rc;

-	if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &pv_res, odbc_result_ce) == FAILURE) {
-		RETURN_THROWS();
-	}
+	ZEND_PARSE_PARAMETERS_START(1, 1)
+		Z_PARAM_OBJECT_OF_CLASS(pv_res, odbc_result_ce)
+	ZEND_PARSE_PARAMETERS_END();

 	result = Z_ODBC_RESULT_P(pv_res);
 	CHECK_ODBC_RESULT(result);
@@ -1175,9 +1180,10 @@ PHP_FUNCTION(odbc_data_source)
 	UCHAR server_name[100], desc[200];
 	SQLSMALLINT len1=0, len2=0, fetch_type;

-	if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ol", &zv_conn, odbc_connection_ce, &zv_fetch_type) == FAILURE) {
-		RETURN_THROWS();
-	}
+	ZEND_PARSE_PARAMETERS_START(2, 2)
+		Z_PARAM_OBJECT_OF_CLASS(zv_conn, odbc_connection_ce)
+		Z_PARAM_LONG(zv_fetch_type)
+	ZEND_PARSE_PARAMETERS_END();

 	fetch_type = (SQLSMALLINT) zv_fetch_type;

@@ -1233,9 +1239,10 @@ PHP_FUNCTION(odbc_exec)
 	RETCODE rc;
 	SQLUINTEGER      scrollopts;

-	if (zend_parse_parameters(ZEND_NUM_ARGS(), "Os", &pv_conn, odbc_connection_ce, &query, &query_len) == FAILURE) {
-		RETURN_THROWS();
-	}
+	ZEND_PARSE_PARAMETERS_START(2, 2)
+		Z_PARAM_OBJECT_OF_CLASS(pv_conn, odbc_connection_ce)
+		Z_PARAM_STRING(query, query_len)
+	ZEND_PARSE_PARAMETERS_END();

 	odbc_connection *conn = Z_ODBC_CONNECTION_P(pv_conn);
 	CHECK_ODBC_CONNECTION(conn);
@@ -1722,9 +1729,11 @@ PHP_FUNCTION(odbc_result_all)
 	size_t i, pv_format_len = 0;
 	SQLSMALLINT sql_c_type;

-	if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|s", &pv_res, odbc_result_ce, &pv_format, &pv_format_len) == FAILURE) {
-		RETURN_THROWS();
-	}
+	ZEND_PARSE_PARAMETERS_START(1, 2)
+		Z_PARAM_OBJECT_OF_CLASS(pv_res, odbc_result_ce)
+		Z_PARAM_OPTIONAL
+		Z_PARAM_STRING(pv_format, pv_format_len)
+	ZEND_PARSE_PARAMETERS_END();

 	result = Z_ODBC_RESULT_P(pv_res);
 	CHECK_ODBC_RESULT(result);
@@ -1850,9 +1859,9 @@ PHP_FUNCTION(odbc_free_result)
 	zval *pv_res;
 	odbc_result *result;

-	if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &pv_res, odbc_result_ce) == FAILURE) {
-		RETURN_THROWS();
-	}
+	ZEND_PARSE_PARAMETERS_START(1, 1)
+		Z_PARAM_OBJECT_OF_CLASS(pv_res, odbc_result_ce)
+	ZEND_PARSE_PARAMETERS_END();

 	result = Z_ODBC_RESULT_P(pv_res);
 	CHECK_ODBC_RESULT(result);
@@ -2019,8 +2028,8 @@ void odbc_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent)
 	ZEND_PARSE_PARAMETERS_START(1, 4)
 		Z_PARAM_STRING(db, db_len)
 		Z_PARAM_OPTIONAL
-		Z_PARAM_STRING_OR_NULL(uid, uid_len)
-		Z_PARAM_STRING_OR_NULL(pwd, pwd_len)
+		Z_PARAM_PATH_OR_NULL(uid, uid_len)
+		Z_PARAM_PATH_OR_NULL(pwd, pwd_len)
 		Z_PARAM_LONG(pv_opt)
 	ZEND_PARSE_PARAMETERS_END();

@@ -2169,9 +2178,9 @@ PHP_FUNCTION(odbc_close)
 	zval *pv_conn;
 	odbc_link *link;

-	if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &pv_conn, odbc_connection_ce) == FAILURE) {
-		RETURN_THROWS();
-	}
+	ZEND_PARSE_PARAMETERS_START(1, 1)
+		Z_PARAM_OBJECT_OF_CLASS(pv_conn, odbc_connection_ce)
+	ZEND_PARSE_PARAMETERS_END();

 	link = Z_ODBC_LINK_P(pv_conn);
 	odbc_connection *connection = Z_ODBC_CONNECTION_P(pv_conn);
@@ -2192,9 +2201,9 @@ PHP_FUNCTION(odbc_num_rows)
 	SQLLEN rows;
 	zval *pv_res;

-	if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &pv_res, odbc_result_ce) == FAILURE) {
-		RETURN_THROWS();
-	}
+	ZEND_PARSE_PARAMETERS_START(1, 1)
+		Z_PARAM_OBJECT_OF_CLASS(pv_res, odbc_result_ce)
+	ZEND_PARSE_PARAMETERS_END();

 	result = Z_ODBC_RESULT_P(pv_res);
 	CHECK_ODBC_RESULT(result);
@@ -2211,9 +2220,9 @@ PHP_FUNCTION(odbc_next_result)
 	zval *pv_res;
 	int rc, i;

-	if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &pv_res, odbc_result_ce) == FAILURE) {
-		RETURN_THROWS();
-	}
+	ZEND_PARSE_PARAMETERS_START(1, 1)
+		Z_PARAM_OBJECT_OF_CLASS(pv_res, odbc_result_ce)
+	ZEND_PARSE_PARAMETERS_END();

 	result = Z_ODBC_RESULT_P(pv_res);
 	CHECK_ODBC_RESULT(result);
@@ -2257,9 +2266,9 @@ PHP_FUNCTION(odbc_num_fields)
 	odbc_result *result;
 	zval *pv_res;

-	if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &pv_res, odbc_result_ce) == FAILURE) {
-		RETURN_THROWS();
-	}
+	ZEND_PARSE_PARAMETERS_START(1, 1)
+		Z_PARAM_OBJECT_OF_CLASS(pv_res, odbc_result_ce)
+	ZEND_PARSE_PARAMETERS_END();

 	result = Z_ODBC_RESULT_P(pv_res);
 	CHECK_ODBC_RESULT(result);
@@ -2275,9 +2284,10 @@ PHP_FUNCTION(odbc_field_name)
 	zval *pv_res;
 	zend_long pv_num;

-	if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ol", &pv_res, odbc_result_ce, &pv_num) == FAILURE) {
-		RETURN_THROWS();
-	}
+	ZEND_PARSE_PARAMETERS_START(2, 2)
+		Z_PARAM_OBJECT_OF_CLASS(pv_res, odbc_result_ce)
+		Z_PARAM_LONG(pv_num)
+	ZEND_PARSE_PARAMETERS_END();

 	result = Z_ODBC_RESULT_P(pv_res);
 	CHECK_ODBC_RESULT(result);
@@ -2310,9 +2320,10 @@ PHP_FUNCTION(odbc_field_type)
 	zval		*pv_res;
 	zend_long		pv_num;

-	if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ol", &pv_res, odbc_result_ce, &pv_num) == FAILURE) {
-		RETURN_THROWS();
-	}
+	ZEND_PARSE_PARAMETERS_START(2, 2)
+		Z_PARAM_OBJECT_OF_CLASS(pv_res, odbc_result_ce)
+		Z_PARAM_LONG(pv_num)
+	ZEND_PARSE_PARAMETERS_END();

 	result = Z_ODBC_RESULT_P(pv_res);
 	CHECK_ODBC_RESULT(result);
@@ -2359,9 +2370,10 @@ PHP_FUNCTION(odbc_field_num)
 	odbc_result *result;
 	zval *pv_res;

-	if (zend_parse_parameters(ZEND_NUM_ARGS(), "Os", &pv_res, odbc_result_ce, &fname, &fname_len) == FAILURE) {
-		RETURN_THROWS();
-	}
+	ZEND_PARSE_PARAMETERS_START(2, 2)
+		Z_PARAM_OBJECT_OF_CLASS(pv_res, odbc_result_ce)
+		Z_PARAM_STRING(fname, fname_len)
+	ZEND_PARSE_PARAMETERS_END();

 	result = Z_ODBC_RESULT_P(pv_res);
 	CHECK_ODBC_RESULT(result);
@@ -2394,9 +2406,11 @@ PHP_FUNCTION(odbc_autocommit)
 	bool pv_onoff = false;
 	bool pv_onoff_is_null = true;

-	if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|b!", &pv_conn, odbc_connection_ce, &pv_onoff, &pv_onoff_is_null) == FAILURE) {
-		RETURN_THROWS();
-	}
+	ZEND_PARSE_PARAMETERS_START(1, 2)
+		Z_PARAM_OBJECT_OF_CLASS(pv_conn, odbc_connection_ce)
+		Z_PARAM_OPTIONAL
+		Z_PARAM_BOOL_OR_NULL(pv_onoff, pv_onoff_is_null)
+	ZEND_PARSE_PARAMETERS_END();

 	odbc_connection *conn = Z_ODBC_CONNECTION_P(pv_conn);
 	CHECK_ODBC_CONNECTION(conn);
@@ -2442,9 +2456,10 @@ static void php_odbc_lasterror(INTERNAL_FUNCTION_PARAMETERS, int mode)
 	zval *pv_handle = NULL;
 	char *ret;

-	if (zend_parse_parameters(ZEND_NUM_ARGS(), "|O!", &pv_handle, odbc_connection_ce) == FAILURE) {
-		RETURN_THROWS();
-	}
+	ZEND_PARSE_PARAMETERS_START(0, 1)
+		Z_PARAM_OPTIONAL
+		Z_PARAM_OBJECT_OF_CLASS(pv_handle, odbc_connection_ce)
+	ZEND_PARSE_PARAMETERS_END();

 	if (pv_handle) {
 		conn = Z_ODBC_CONNECTION_P(pv_handle);
@@ -2496,9 +2511,12 @@ PHP_FUNCTION(odbc_setoption)
 	zval *pv_handle;
 	zend_long pv_which, pv_opt, pv_val;

-	if (zend_parse_parameters(ZEND_NUM_ARGS(), "olll", &pv_handle, &pv_which, &pv_opt, &pv_val) == FAILURE) {
-		RETURN_THROWS();
-	}
+	ZEND_PARSE_PARAMETERS_START(4, 4)
+		Z_PARAM_OBJECT(pv_handle)
+		Z_PARAM_LONG(pv_which)
+		Z_PARAM_LONG(pv_opt)
+		Z_PARAM_LONG(pv_val)
+	ZEND_PARSE_PARAMETERS_END();

 	switch (pv_which) {
 		case 1:		/* SQLSetConnectOption */
@@ -2556,10 +2574,14 @@ PHP_FUNCTION(odbc_tables)
 	size_t cat_len = 0, schema_len = 0, table_len = 0, type_len = 0;
 	RETCODE rc;

-	if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|s!s!s!s!", &pv_conn, odbc_connection_ce, &cat, &cat_len, &schema, &schema_len,
-		&table, &table_len, &type, &type_len) == FAILURE) {
-		RETURN_THROWS();
-	}
+	ZEND_PARSE_PARAMETERS_START(1, 5)
+		Z_PARAM_OBJECT_OF_CLASS(pv_conn, odbc_connection_ce)
+		Z_PARAM_OPTIONAL
+		Z_PARAM_PATH_OR_NULL(cat, cat_len)
+		Z_PARAM_PATH_OR_NULL(schema, schema_len)
+		Z_PARAM_PATH_OR_NULL(table, table_len)
+		Z_PARAM_PATH_OR_NULL(type, type_len)
+	ZEND_PARSE_PARAMETERS_END();

 	odbc_connection *conn = Z_ODBC_CONNECTION_P(pv_conn);
 	CHECK_ODBC_CONNECTION(conn);
@@ -2621,10 +2643,14 @@ PHP_FUNCTION(odbc_columns)
 	size_t cat_len = 0, schema_len = 0, table_len = 0, column_len = 0;
 	RETCODE rc;

-	if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|s!s!s!s!", &pv_conn, odbc_connection_ce, &cat, &cat_len, &schema, &schema_len,
-		&table, &table_len, &column, &column_len) == FAILURE) {
-		RETURN_THROWS();
-	}
+	ZEND_PARSE_PARAMETERS_START(1, 5)
+		Z_PARAM_OBJECT_OF_CLASS(pv_conn, odbc_connection_ce)
+		Z_PARAM_OPTIONAL
+		Z_PARAM_PATH_OR_NULL(cat, cat_len)
+		Z_PARAM_PATH_OR_NULL(schema, schema_len)
+		Z_PARAM_PATH_OR_NULL(table, table_len)
+		Z_PARAM_PATH_OR_NULL(column, column_len)
+	ZEND_PARSE_PARAMETERS_END();

 	odbc_connection *conn = Z_ODBC_CONNECTION_P(pv_conn);
 	CHECK_ODBC_CONNECTION(conn);
@@ -2688,10 +2714,13 @@ PHP_FUNCTION(odbc_columnprivileges)
 	size_t cat_len = 0, schema_len, table_len, column_len;
 	RETCODE rc;

-	if (zend_parse_parameters(ZEND_NUM_ARGS(), "Os!sss", &pv_conn, odbc_connection_ce, &cat, &cat_len, &schema, &schema_len,
-		&table, &table_len, &column, &column_len) == FAILURE) {
-		RETURN_THROWS();
-	}
+	ZEND_PARSE_PARAMETERS_START(5, 5)
+		Z_PARAM_OBJECT_OF_CLASS(pv_conn, odbc_connection_ce)
+		Z_PARAM_PATH_OR_NULL(cat, cat_len)
+		Z_PARAM_STRING(schema, schema_len)
+		Z_PARAM_STRING(table, table_len)
+		Z_PARAM_STRING(column, column_len)
+	ZEND_PARSE_PARAMETERS_END();

 	odbc_connection *conn = Z_ODBC_CONNECTION_P(pv_conn);
 	CHECK_ODBC_CONNECTION(conn);
@@ -2748,10 +2777,15 @@ PHP_FUNCTION(odbc_foreignkeys)
 	size_t pcat_len = 0, pschema_len, ptable_len, fcat_len, fschema_len, ftable_len;
 	RETCODE rc;

-	if (zend_parse_parameters(ZEND_NUM_ARGS(), "Os!sssss", &pv_conn, odbc_connection_ce, &pcat, &pcat_len, &pschema, &pschema_len,
-		&ptable, &ptable_len, &fcat, &fcat_len, &fschema, &fschema_len, &ftable, &ftable_len) == FAILURE) {
-		RETURN_THROWS();
-	}
+	ZEND_PARSE_PARAMETERS_START(7, 7)
+		Z_PARAM_OBJECT_OF_CLASS(pv_conn, odbc_connection_ce)
+		Z_PARAM_PATH_OR_NULL(pcat, pcat_len)
+		Z_PARAM_STRING(pschema, pschema_len)
+		Z_PARAM_STRING(ptable, ptable_len)
+		Z_PARAM_STRING(fcat, fcat_len)
+		Z_PARAM_STRING(fschema, fschema_len)
+		Z_PARAM_STRING(ftable, ftable_len)
+	ZEND_PARSE_PARAMETERS_END();

 #if defined(HAVE_IBMDB2)
 #define EMPTY_TO_NULL(xstr) \
@@ -2822,9 +2856,11 @@ PHP_FUNCTION(odbc_gettypeinfo)
 	RETCODE rc;
 	SQLSMALLINT data_type;

-	if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|l", &pv_conn, odbc_connection_ce, &pv_data_type) == FAILURE) {
-		RETURN_THROWS();
-	}
+	ZEND_PARSE_PARAMETERS_START(1, 2)
+		Z_PARAM_OBJECT_OF_CLASS(pv_conn, odbc_connection_ce)
+		Z_PARAM_OPTIONAL
+		Z_PARAM_LONG(pv_data_type)
+	ZEND_PARSE_PARAMETERS_END();

 	data_type = (SQLSMALLINT) pv_data_type;

@@ -2879,9 +2915,12 @@ PHP_FUNCTION(odbc_primarykeys)
 	size_t cat_len = 0, schema_len, table_len;
 	RETCODE rc;

-	if (zend_parse_parameters(ZEND_NUM_ARGS(), "Os!ss", &pv_conn, odbc_connection_ce, &cat, &cat_len, &schema, &schema_len, &table, &table_len) == FAILURE) {
-		RETURN_THROWS();
-	}
+	ZEND_PARSE_PARAMETERS_START(4, 4)
+		Z_PARAM_OBJECT_OF_CLASS(pv_conn, odbc_connection_ce)
+		Z_PARAM_PATH_OR_NULL(cat, cat_len)
+		Z_PARAM_STRING(schema, schema_len)
+		Z_PARAM_STRING(table, table_len)
+	ZEND_PARSE_PARAMETERS_END();

 	odbc_connection *conn = Z_ODBC_CONNECTION_P(pv_conn);
 	CHECK_ODBC_CONNECTION(conn);
@@ -2937,10 +2976,13 @@ PHP_FUNCTION(odbc_procedurecolumns)
 	size_t cat_len = 0, schema_len = 0, proc_len = 0, col_len = 0;
 	RETCODE rc;

-	if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|s!s!s!s!", &pv_conn, odbc_connection_ce, &cat, &cat_len, &schema, &schema_len,
-		&proc, &proc_len, &col, &col_len) == FAILURE) {
-		RETURN_THROWS();
-	}
+	ZEND_PARSE_PARAMETERS_START(1, 5)
+		Z_PARAM_OBJECT_OF_CLASS(pv_conn, odbc_connection_ce)
+		Z_PARAM_PATH_OR_NULL(cat, cat_len)
+		Z_PARAM_PATH_OR_NULL(schema, schema_len)
+		Z_PARAM_PATH_OR_NULL(proc, proc_len)
+		Z_PARAM_PATH_OR_NULL(col, col_len)
+	ZEND_PARSE_PARAMETERS_END();

 	odbc_connection *conn = Z_ODBC_CONNECTION_P(pv_conn);
 	CHECK_ODBC_CONNECTION(conn);
@@ -2997,9 +3039,12 @@ PHP_FUNCTION(odbc_procedures)
 	size_t cat_len = 0, schema_len = 0, proc_len = 0;
 	RETCODE rc;

-	if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|s!s!s!", &pv_conn, odbc_connection_ce, &cat, &cat_len, &schema, &schema_len, &proc, &proc_len) == FAILURE) {
-		RETURN_THROWS();
-	}
+	ZEND_PARSE_PARAMETERS_START(1, 4)
+		Z_PARAM_OBJECT_OF_CLASS(pv_conn, odbc_connection_ce)
+		Z_PARAM_PATH_OR_NULL(cat, cat_len)
+		Z_PARAM_PATH_OR_NULL(schema, schema_len)
+		Z_PARAM_PATH_OR_NULL(proc, proc_len)
+	ZEND_PARSE_PARAMETERS_END();

 	odbc_connection *conn = Z_ODBC_CONNECTION_P(pv_conn);
 	CHECK_ODBC_CONNECTION(conn);
@@ -3057,10 +3102,15 @@ PHP_FUNCTION(odbc_specialcolumns)
 	SQLUSMALLINT type, scope, nullable;
 	RETCODE rc;

-	if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ols!ssll", &pv_conn, odbc_connection_ce, &vtype, &cat, &cat_len, &schema, &schema_len,
-		&name, &name_len, &vscope, &vnullable) == FAILURE) {
-		RETURN_THROWS();
-	}
+	ZEND_PARSE_PARAMETERS_START(7, 7)
+		Z_PARAM_OBJECT_OF_CLASS(pv_conn, odbc_connection_ce)
+		Z_PARAM_LONG(vtype)
+		Z_PARAM_PATH_OR_NULL(cat, cat_len)
+		Z_PARAM_STRING(schema, schema_len)
+		Z_PARAM_STRING(name, name_len)
+		Z_PARAM_LONG(vscope)
+		Z_PARAM_LONG(vnullable)
+	ZEND_PARSE_PARAMETERS_END();

 	type = (SQLUSMALLINT) vtype;
 	scope = (SQLUSMALLINT) vscope;
@@ -3124,10 +3174,14 @@ PHP_FUNCTION(odbc_statistics)
 	SQLUSMALLINT unique, reserved;
 	RETCODE rc;

-	if (zend_parse_parameters(ZEND_NUM_ARGS(), "Os!ssll", &pv_conn, odbc_connection_ce, &cat, &cat_len, &schema, &schema_len,
-		&name, &name_len, &vunique, &vreserved) == FAILURE) {
-		RETURN_THROWS();
-	}
+	ZEND_PARSE_PARAMETERS_START(6, 6)
+		Z_PARAM_OBJECT_OF_CLASS(pv_conn, odbc_connection_ce)
+		Z_PARAM_PATH_OR_NULL(cat, cat_len)
+		Z_PARAM_STRING(schema, schema_len)
+		Z_PARAM_STRING(name, name_len)
+		Z_PARAM_LONG(vunique)
+		Z_PARAM_LONG(vreserved) /* XXX: Documented as 'accuracy' */
+	ZEND_PARSE_PARAMETERS_END();

 	unique = (SQLUSMALLINT) vunique;
 	reserved = (SQLUSMALLINT) vreserved;
@@ -3188,9 +3242,12 @@ PHP_FUNCTION(odbc_tableprivileges)
 	size_t cat_len = 0, schema_len, table_len;
 	RETCODE rc;

-	if (zend_parse_parameters(ZEND_NUM_ARGS(), "Os!ss", &pv_conn, odbc_connection_ce, &cat, &cat_len, &schema, &schema_len, &table, &table_len) == FAILURE) {
-		RETURN_THROWS();
-	}
+	ZEND_PARSE_PARAMETERS_START(4, 4)
+		Z_PARAM_OBJECT_OF_CLASS(pv_conn, odbc_connection_ce)
+		Z_PARAM_PATH_OR_NULL(cat, cat_len)
+		Z_PARAM_STRING(schema, schema_len)
+		Z_PARAM_STRING(table, table_len)
+	ZEND_PARSE_PARAMETERS_END();

 	odbc_connection *conn = Z_ODBC_CONNECTION_P(pv_conn);
 	CHECK_ODBC_CONNECTION(conn);