Skip to content

Commit 71a2544

Browse files
committed
ext/pdo_sqlite: EXPLAIN mode support for SQL statements.
available since 3.41.0 we can reprepare a statement in either explain, explain query plan or the usual prepared mode. close GH-18829
1 parent 5740038 commit 71a2544

File tree

7 files changed

+511
-3
lines changed

7 files changed

+511
-3
lines changed

NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,9 @@ PHP NEWS
148148
has a wrong return type. (David Carlier)
149149
. Added Pdo_Sqlite::ATTR_BUSY_STATEMENT constant to check
150150
if a statement is currently executing. (David Carlier)
151+
. Added Pdo_Sqlite::ATTR_EXPLAIN_STATEMENT constant to set a statement
152+
in either EXPLAIN_MODE_PREPARED, EXPLAIN_MODE_EXPLAIN,
153+
EXPLAIN_MODE_EXPLAIN_QUERY_PLAN modes. (David Carlier)
151154

152155
- PGSQL:
153156
. Added pg_close_stmt to close a prepared statement while allowing

UPGRADING

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,9 @@ PHP 8.5 UPGRADE NOTES
198198

199199
- PDO_Sqlite:
200200
. Added class constant Pdo_Sqlite::ATTR_BUSY_STATEMENT.
201+
. Added class constants Pdo_Sqlite::ATTR_EXPLAIN_STATEMENT,
202+
Pdo_Sqlite::EXPLAIN_MODE_PREPARED, Pdo_Sqlite::EXPLAIN_MODE_EXPLAIN,
203+
Pdo_Sqlite::EXPLAIN_MODE_EXPLAIN_QUERY_PLAN.
201204

202205
- SOAP:
203206
. Enumeration cases are now dumped in __getTypes().

ext/pdo_sqlite/pdo_sqlite.stub.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,15 @@ class Sqlite extends \PDO
3636
/** @cvalue PDO_SQLITE_ATTR_BUSY_STATEMENT */
3737
public const int ATTR_BUSY_STATEMENT = UNKNOWN;
3838

39+
/** @cvalue PDO_SQLITE_ATTR_EXPLAIN_STATEMENT */
40+
public const int ATTR_EXPLAIN_STATEMENT = UNKNOWN;
41+
42+
#if SQLITE_VERSION_NUMBER >= 3041000
43+
public const int EXPLAIN_MODE_PREPARED = 0;
44+
public const int EXPLAIN_MODE_EXPLAIN = 1;
45+
public const int EXPLAIN_MODE_EXPLAIN_QUERY_PLAN = 2;
46+
#endif
47+
3948
/** @cvalue SQLITE_OK */
4049
public const int OK = UNKNOWN;
4150

ext/pdo_sqlite/pdo_sqlite_arginfo.h

Lines changed: 31 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ext/pdo_sqlite/php_pdo_sqlite_int.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@ enum {
7474
PDO_SQLITE_ATTR_OPEN_FLAGS = PDO_ATTR_DRIVER_SPECIFIC,
7575
PDO_SQLITE_ATTR_READONLY_STATEMENT,
7676
PDO_SQLITE_ATTR_EXTENDED_RESULT_CODES,
77-
PDO_SQLITE_ATTR_BUSY_STATEMENT
77+
PDO_SQLITE_ATTR_BUSY_STATEMENT,
78+
PDO_SQLITE_ATTR_EXPLAIN_STATEMENT
7879
};
7980

8081
typedef int pdo_sqlite_create_collation_callback(void*, int, const void*, int, const void*);

ext/pdo_sqlite/sqlite_statement.c

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@
2626
#include "php_pdo_sqlite.h"
2727
#include "php_pdo_sqlite_int.h"
2828

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
2934

3035
static int pdo_sqlite_stmt_dtor(pdo_stmt_t *stmt)
3136
{
@@ -387,21 +392,78 @@ static int pdo_sqlite_stmt_get_attribute(pdo_stmt_t *stmt, zend_long attr, zval
387392
ZVAL_TRUE(val);
388393
}
389394
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
390412
default:
391413
return 0;
392414
}
393415

394416
return 1;
395417
}
396418

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+
397459
const struct pdo_stmt_methods sqlite_stmt_methods = {
398460
pdo_sqlite_stmt_dtor,
399461
pdo_sqlite_stmt_execute,
400462
pdo_sqlite_stmt_fetch,
401463
pdo_sqlite_stmt_describe,
402464
pdo_sqlite_stmt_get_col,
403465
pdo_sqlite_stmt_param_hook,
404-
NULL, /* set_attr */
466+
pdo_sqlite_stmt_set_attribute, /* set_attr */
405467
pdo_sqlite_stmt_get_attribute, /* get_attr */
406468
pdo_sqlite_stmt_col_meta,
407469
NULL, /* next_rowset */

0 commit comments

Comments
 (0)