|
26 | 26 | #include "php_pdo_sqlite.h" |
27 | 27 | #include "php_pdo_sqlite_int.h" |
28 | 28 |
|
| 29 | +#if defined(__APPLE__) |
| 30 | +// If more than one usage, a Zend macro could be created |
| 31 | +// around this runtime check |
| 32 | +#include <Availability.h> |
| 33 | +#endif |
29 | 34 |
|
30 | 35 | static int pdo_sqlite_stmt_dtor(pdo_stmt_t *stmt) |
31 | 36 | { |
@@ -387,21 +392,78 @@ static int pdo_sqlite_stmt_get_attribute(pdo_stmt_t *stmt, zend_long attr, zval |
387 | 392 | ZVAL_TRUE(val); |
388 | 393 | } |
389 | 394 | break; |
| 395 | + case PDO_SQLITE_ATTR_EXPLAIN_STATEMENT: |
| 396 | +#if SQLITE_VERSION_NUMBER >= 3041000 |
| 397 | +#if defined(__APPLE__) |
| 398 | + if (__builtin_available(macOS 14.2, *)) { |
| 399 | +#endif |
| 400 | + ZVAL_LONG(val, (zend_long)sqlite3_stmt_isexplain(S->stmt)); |
| 401 | + return 1; |
| 402 | +#if defined(__APPLE__) |
| 403 | + } else { |
| 404 | + zend_value_error("explain statement unsupported"); |
| 405 | + return 0; |
| 406 | + } |
| 407 | +#endif |
| 408 | +#else |
| 409 | + zend_value_error("explain statement unsupported"); |
| 410 | + return 0; |
| 411 | +#endif |
390 | 412 | default: |
391 | 413 | return 0; |
392 | 414 | } |
393 | 415 |
|
394 | 416 | return 1; |
395 | 417 | } |
396 | 418 |
|
| 419 | +static int pdo_sqlite_stmt_set_attribute(pdo_stmt_t *stmt, zend_long attr, zval *zval) |
| 420 | +{ |
| 421 | + pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data; |
| 422 | + |
| 423 | + switch (attr) { |
| 424 | + case PDO_SQLITE_ATTR_EXPLAIN_STATEMENT: |
| 425 | +#if SQLITE_VERSION_NUMBER >= 3041000 |
| 426 | +#if defined(__APPLE__) |
| 427 | + if (__builtin_available(macOS 14.2, *)) { |
| 428 | +#endif |
| 429 | + if (Z_TYPE_P(zval) != IS_LONG) { |
| 430 | + zend_type_error("explain mode must be of type int, %s given", zend_zval_value_name(zval)); |
| 431 | + return 0; |
| 432 | + } |
| 433 | + if (Z_LVAL_P(zval) < 0 || Z_LVAL_P(zval) > 2) { |
| 434 | + zend_value_error("explain mode must be one of the EXPLAIN_MODE_* constants"); |
| 435 | + return 0; |
| 436 | + } |
| 437 | + if (sqlite3_stmt_explain(S->stmt, (int)Z_LVAL_P(zval)) != SQLITE_OK) { |
| 438 | + return 0; |
| 439 | + } |
| 440 | + |
| 441 | + return 1; |
| 442 | +#if defined(__APPLE__) |
| 443 | + } else { |
| 444 | + zend_value_error("explain statement unsupported"); |
| 445 | + return 0; |
| 446 | + } |
| 447 | +#endif |
| 448 | +#else |
| 449 | + zend_value_error("explain statement unsupported"); |
| 450 | + return 0; |
| 451 | +#endif |
| 452 | + default: |
| 453 | + return 0; |
| 454 | + } |
| 455 | + |
| 456 | + return 1; |
| 457 | +} |
| 458 | + |
397 | 459 | const struct pdo_stmt_methods sqlite_stmt_methods = { |
398 | 460 | pdo_sqlite_stmt_dtor, |
399 | 461 | pdo_sqlite_stmt_execute, |
400 | 462 | pdo_sqlite_stmt_fetch, |
401 | 463 | pdo_sqlite_stmt_describe, |
402 | 464 | pdo_sqlite_stmt_get_col, |
403 | 465 | pdo_sqlite_stmt_param_hook, |
404 | | - NULL, /* set_attr */ |
| 466 | + pdo_sqlite_stmt_set_attribute, /* set_attr */ |
405 | 467 | pdo_sqlite_stmt_get_attribute, /* get_attr */ |
406 | 468 | pdo_sqlite_stmt_col_meta, |
407 | 469 | NULL, /* next_rowset */ |
|
0 commit comments