31
31
#include "mysqli_priv.h"
32
32
#include "ext/mysqlnd/mysql_float_to_double.h"
33
33
34
+ #define ERROR_ARG_POS (arg_num ) (getThis() ? (arg_num-1) : (arg_num))
35
+
34
36
35
37
#ifndef MYSQLI_USE_MYSQLND
36
38
/* {{{ mysqli_tx_cor_options_to_string */
@@ -324,19 +326,19 @@ PHP_FUNCTION(mysqli_stmt_bind_param)
324
326
MYSQLI_FETCH_RESOURCE_STMT (stmt , mysql_stmt , MYSQLI_STATUS_VALID );
325
327
326
328
if (!types_len ) {
327
- php_error_docref ( NULL , E_WARNING , "Invalid type or no types specified " );
328
- RETURN_FALSE ;
329
+ zend_argument_value_error ( ERROR_ARG_POS ( 2 ), "cannot be empty " );
330
+ RETURN_THROWS () ;
329
331
}
330
332
331
333
if (types_len != (size_t ) argc ) {
332
334
/* number of bind variables doesn't match number of elements in type definition string */
333
- php_error_docref ( NULL , E_WARNING , "Number of elements in type definition string doesn't match number of bind variables" );
334
- RETURN_FALSE ;
335
+ zend_argument_count_error ( "The number of elements in the type definition string must match the number of bind variables" );
336
+ RETURN_THROWS () ;
335
337
}
336
338
337
339
if (types_len != mysql_stmt_param_count (stmt -> stmt )) {
338
- php_error_docref ( NULL , E_WARNING , "Number of variables doesn't match number of parameters in prepared statement" );
339
- RETURN_FALSE ;
340
+ zend_argument_count_error ( "The number of variables must match the number of parameters in the prepared statement" );
341
+ RETURN_THROWS () ;
340
342
}
341
343
342
344
RETVAL_BOOL (!mysqli_stmt_bind_param_do_bind (stmt , argc , args , types , getThis () ? 1 : 2 ));
@@ -557,8 +559,8 @@ PHP_FUNCTION(mysqli_stmt_bind_result)
557
559
MYSQLI_FETCH_RESOURCE_STMT (stmt , mysql_stmt , MYSQLI_STATUS_VALID );
558
560
559
561
if ((uint32_t )argc != mysql_stmt_field_count (stmt -> stmt )) {
560
- php_error_docref ( NULL , E_WARNING , "Number of bind variables doesn't match number of fields in prepared statement" );
561
- RETURN_FALSE ;
562
+ zend_argument_count_error ( "Number of bind variables doesn't match number of fields in prepared statement" );
563
+ RETURN_THROWS () ;
562
564
}
563
565
564
566
rc = mysqli_stmt_bind_result_do_bind (stmt , args , argc );
@@ -729,14 +731,23 @@ PHP_FUNCTION(mysqli_data_seek)
729
731
RETURN_THROWS ();
730
732
}
731
733
734
+ if (offset < 0 ) {
735
+ zend_argument_value_error (ERROR_ARG_POS (2 ), "must be greater than or equal to 0" );
736
+ RETURN_THROWS ();
737
+ }
738
+
732
739
MYSQLI_FETCH_RESOURCE (result , MYSQL_RES * , mysql_result , "mysqli_result" , MYSQLI_STATUS_VALID );
733
740
734
741
if (mysqli_result_is_unbuffered (result )) {
735
- php_error_docref (NULL , E_WARNING , "Function cannot be used with MYSQL_USE_RESULT" );
736
- RETURN_FALSE ;
742
+ if (getThis ()) {
743
+ zend_throw_error (NULL , "mysqli_result::data_seek() cannot be used with MYSQLI_USE_RESULT" );
744
+ } else {
745
+ zend_throw_error (NULL , "mysqli_data_seek() cannot be used with MYSQLI_USE_RESULT" );
746
+ }
747
+ RETURN_THROWS ();
737
748
}
738
749
739
- if (offset < 0 || (uint64_t )offset >= mysql_num_rows (result )) {
750
+ if ((uint64_t )offset >= mysql_num_rows (result )) {
740
751
RETURN_FALSE ;
741
752
}
742
753
@@ -1181,11 +1192,16 @@ PHP_FUNCTION(mysqli_fetch_field_direct)
1181
1192
RETURN_THROWS ();
1182
1193
}
1183
1194
1195
+ if (offset < 0 ) {
1196
+ zend_argument_value_error (ERROR_ARG_POS (2 ), "must be greater than or equal to 0" );
1197
+ RETURN_THROWS ();
1198
+ }
1199
+
1184
1200
MYSQLI_FETCH_RESOURCE (result , MYSQL_RES * , mysql_result , "mysqli_result" , MYSQLI_STATUS_VALID );
1185
1201
1186
- if (offset < 0 || offset >= (zend_long ) mysql_num_fields (result )) {
1187
- php_error_docref ( NULL , E_WARNING , "Field offset is invalid for resultset " );
1188
- RETURN_FALSE ;
1202
+ if (offset >= (zend_long ) mysql_num_fields (result )) {
1203
+ zend_argument_value_error ( ERROR_ARG_POS ( 2 ), "must be less than the number of fields for this result set " );
1204
+ RETURN_THROWS () ;
1189
1205
}
1190
1206
1191
1207
if (!(field = mysql_fetch_field_direct (result ,offset ))) {
@@ -1215,6 +1231,7 @@ PHP_FUNCTION(mysqli_fetch_lengths)
1215
1231
1216
1232
MYSQLI_FETCH_RESOURCE (result , MYSQL_RES * , mysql_result , "mysqli_result" , MYSQLI_STATUS_VALID );
1217
1233
1234
+ // TODO Warning?
1218
1235
if (!(ret = mysql_fetch_lengths (result ))) {
1219
1236
RETURN_FALSE ;
1220
1237
}
@@ -1260,9 +1277,16 @@ PHP_FUNCTION(mysqli_field_seek)
1260
1277
if (zend_parse_method_parameters (ZEND_NUM_ARGS (), getThis (), "Ol" , & mysql_result , mysqli_result_class_entry , & fieldnr ) == FAILURE ) {
1261
1278
RETURN_THROWS ();
1262
1279
}
1280
+
1281
+ if (fieldnr < 0 ) {
1282
+ zend_argument_value_error (ERROR_ARG_POS (2 ), "must be greater than or equal to 0" );
1283
+ RETURN_THROWS ();
1284
+ }
1285
+
1263
1286
MYSQLI_FETCH_RESOURCE (result , MYSQL_RES * , mysql_result , "mysqli_result" , MYSQLI_STATUS_VALID );
1264
1287
1265
- if (fieldnr < 0 || (uint32_t )fieldnr >= mysql_num_fields (result )) {
1288
+ if ((uint32_t )fieldnr >= mysql_num_fields (result )) {
1289
+ // TODO ValueError?
1266
1290
php_error_docref (NULL , E_WARNING , "Invalid field offset" );
1267
1291
RETURN_FALSE ;
1268
1292
}
@@ -1499,13 +1523,14 @@ PHP_FUNCTION(mysqli_kill)
1499
1523
if (zend_parse_method_parameters (ZEND_NUM_ARGS (), getThis (), "Ol" , & mysql_link , mysqli_link_class_entry , & processid ) == FAILURE ) {
1500
1524
RETURN_THROWS ();
1501
1525
}
1502
- MYSQLI_FETCH_RESOURCE_CONN (mysql , mysql_link , MYSQLI_STATUS_VALID );
1503
1526
1504
1527
if (processid <= 0 ) {
1505
- php_error_docref ( NULL , E_WARNING , "processid should have positive value " );
1506
- RETURN_FALSE ;
1528
+ zend_argument_value_error ( ERROR_ARG_POS ( 2 ), "must be greater than 0 " );
1529
+ RETURN_THROWS () ;
1507
1530
}
1508
1531
1532
+ MYSQLI_FETCH_RESOURCE_CONN (mysql , mysql_link , MYSQLI_STATUS_VALID );
1533
+
1509
1534
if (mysql_kill (mysql -> mysql , processid )) {
1510
1535
MYSQLI_REPORT_MYSQL_ERROR (mysql -> mysql );
1511
1536
RETURN_FALSE ;
@@ -1601,8 +1626,8 @@ PHP_FUNCTION(mysqli_num_rows)
1601
1626
MYSQLI_FETCH_RESOURCE (result , MYSQL_RES * , mysql_result , "mysqli_result" , MYSQLI_STATUS_VALID );
1602
1627
1603
1628
if (mysqli_result_is_unbuffered_and_not_everything_is_fetched (result )) {
1604
- php_error_docref (NULL , E_WARNING , "Function cannot be used with MYSQL_USE_RESULT " );
1605
- RETURN_LONG ( 0 );
1629
+ zend_throw_error (NULL , "mysqli_num_rows() cannot be used with MYSQLI_USE_RESULT " );
1630
+ RETURN_THROWS ( );
1606
1631
}
1607
1632
1608
1633
MYSQLI_RETURN_LONG_INT (mysql_num_rows (result ));
@@ -1922,12 +1947,14 @@ PHP_FUNCTION(mysqli_stmt_send_long_data)
1922
1947
if (zend_parse_method_parameters (ZEND_NUM_ARGS (), getThis (), "Ols" , & mysql_stmt , mysqli_stmt_class_entry , & param_nr , & data , & data_len ) == FAILURE ) {
1923
1948
RETURN_THROWS ();
1924
1949
}
1950
+
1925
1951
MYSQLI_FETCH_RESOURCE_STMT (stmt , mysql_stmt , MYSQLI_STATUS_VALID );
1926
1952
1927
1953
if (param_nr < 0 ) {
1928
- php_error_docref ( NULL , E_WARNING , "Invalid parameter number " );
1929
- RETURN_FALSE ;
1954
+ zend_argument_value_error ( ERROR_ARG_POS ( 2 ), "must be greater than or equal to 0 " );
1955
+ RETURN_THROWS () ;
1930
1956
}
1957
+
1931
1958
if (mysql_stmt_send_long_data (stmt -> stmt , param_nr , data , data_len )) {
1932
1959
RETURN_FALSE ;
1933
1960
}
@@ -1984,9 +2011,10 @@ PHP_FUNCTION(mysqli_stmt_data_seek)
1984
2011
if (zend_parse_method_parameters (ZEND_NUM_ARGS (), getThis (), "Ol" , & mysql_stmt , mysqli_stmt_class_entry , & offset ) == FAILURE ) {
1985
2012
RETURN_THROWS ();
1986
2013
}
2014
+
1987
2015
if (offset < 0 ) {
1988
- php_error_docref ( NULL , E_WARNING , "Offset must be positive " );
1989
- RETURN_FALSE ;
2016
+ zend_argument_value_error ( ERROR_ARG_POS ( 2 ), " must be greater than or equal to 0 " );
2017
+ RETURN_THROWS () ;
1990
2018
}
1991
2019
1992
2020
MYSQLI_FETCH_RESOURCE_STMT (stmt , mysql_stmt , MYSQLI_STATUS_VALID );
@@ -2216,7 +2244,7 @@ PHP_FUNCTION(mysqli_stmt_attr_set)
2216
2244
zval * mysql_stmt ;
2217
2245
zend_long mode_in ;
2218
2246
#if MYSQL_VERSION_ID >= 50107
2219
- my_bool mode_b ;
2247
+ my_bool mode_b ;
2220
2248
#endif
2221
2249
unsigned long mode ;
2222
2250
zend_long attr ;
@@ -2225,25 +2253,54 @@ PHP_FUNCTION(mysqli_stmt_attr_set)
2225
2253
if (zend_parse_method_parameters (ZEND_NUM_ARGS (), getThis (), "Oll" , & mysql_stmt , mysqli_stmt_class_entry , & attr , & mode_in ) == FAILURE ) {
2226
2254
RETURN_THROWS ();
2227
2255
}
2228
- MYSQLI_FETCH_RESOURCE_STMT (stmt , mysql_stmt , MYSQLI_STATUS_VALID );
2229
2256
2230
- if (mode_in < 0 ) {
2231
- php_error_docref (NULL , E_WARNING , "Mode should be non-negative, " ZEND_LONG_FMT " passed" , mode_in );
2232
- RETURN_FALSE ;
2233
- }
2257
+ MYSQLI_FETCH_RESOURCE_STMT (stmt , mysql_stmt , MYSQLI_STATUS_VALID );
2234
2258
2235
2259
switch (attr ) {
2236
2260
#if MYSQL_VERSION_ID >= 50107
2237
2261
case STMT_ATTR_UPDATE_MAX_LENGTH :
2262
+ if (mode_in != 0 && mode_in != 1 ) {
2263
+ zend_argument_value_error (ERROR_ARG_POS (3 ), "must be 0 or 1 for attribute MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH" );
2264
+ RETURN_THROWS ();
2265
+ }
2238
2266
mode_b = (my_bool ) mode_in ;
2239
2267
mode_p = & mode_b ;
2240
2268
break ;
2241
2269
#endif
2242
- default :
2270
+ case STMT_ATTR_CURSOR_TYPE :
2271
+ switch (mode_in ) {
2272
+ case CURSOR_TYPE_NO_CURSOR :
2273
+ case CURSOR_TYPE_READ_ONLY :
2274
+ case CURSOR_TYPE_FOR_UPDATE :
2275
+ case CURSOR_TYPE_SCROLLABLE :
2276
+ break ;
2277
+ default :
2278
+ zend_argument_value_error (ERROR_ARG_POS (3 ), "must be one of MYSQLI_CURSOR_TYPE_NO_CURSOR, "
2279
+ "MYSQLI_CURSOR_TYPE_READ_ONLY, MYSQLI_CURSOR_TYPE_FOR_UPDATE, or MYSQLI_CURSOR_TYPE_SCROLLABLE "
2280
+ "for attribute MYSQLI_STMT_ATTR_CURSOR_TYPE" );
2281
+ RETURN_THROWS ();
2282
+ }
2243
2283
mode = mode_in ;
2244
2284
mode_p = & mode ;
2245
2285
break ;
2286
+ case STMT_ATTR_PREFETCH_ROWS :
2287
+ if (mode_in < 1 ) {
2288
+ zend_argument_value_error (ERROR_ARG_POS (3 ), "must be greater than 0 for attribute MYSQLI_STMT_ATTR_PREFETCH_ROWS" );
2289
+ RETURN_THROWS ();
2290
+ }
2291
+ mode = mode_in ;
2292
+ mode_p = & mode ;
2293
+ break ;
2294
+ default :
2295
+ zend_argument_value_error (ERROR_ARG_POS (2 ), "must be one of "
2296
+ #if MYSQL_VERSION_ID >= 50107
2297
+ "MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH, "
2298
+ #endif
2299
+ "MYSQLI_STMT_ATTR_PREFETCH_ROWS, or STMT_ATTR_CURSOR_TYPE" );
2300
+ RETURN_THROWS ();
2246
2301
}
2302
+
2303
+ // TODO Can unify this?
2247
2304
#ifndef MYSQLI_USE_MYSQLND
2248
2305
if (mysql_stmt_attr_set (stmt -> stmt , attr , mode_p )) {
2249
2306
#else
@@ -2267,11 +2324,20 @@ PHP_FUNCTION(mysqli_stmt_attr_get)
2267
2324
if (zend_parse_method_parameters (ZEND_NUM_ARGS (), getThis (), "Ol" , & mysql_stmt , mysqli_stmt_class_entry , & attr ) == FAILURE ) {
2268
2325
RETURN_THROWS ();
2269
2326
}
2327
+
2270
2328
MYSQLI_FETCH_RESOURCE_STMT (stmt , mysql_stmt , MYSQLI_STATUS_VALID );
2271
2329
2272
2330
if ((rc = mysql_stmt_attr_get (stmt -> stmt , attr , & value ))) {
2273
- RETURN_FALSE ;
2274
- }
2331
+ /* Success corresponds to 0 return value and a non-zero value
2332
+ * should only happen if the attr/option is unknown */
2333
+ zend_argument_value_error (ERROR_ARG_POS (2 ), "must be one of "
2334
+ #if MYSQL_VERSION_ID >= 50107
2335
+ "MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH, "
2336
+ #endif
2337
+ "MYSQLI_STMT_ATTR_PREFETCH_ROWS, or STMT_ATTR_CURSOR_TYPE" );
2338
+ RETURN_THROWS ();
2339
+ }
2340
+
2275
2341
2276
2342
#if MYSQL_VERSION_ID >= 50107
2277
2343
if (attr == STMT_ATTR_UPDATE_MAX_LENGTH )
0 commit comments