mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00
ext/sqlite3: explain statement support addition.
similar to what have been done for pdo/sqlite as having statement explain support to simulate how a query would operate or for more advanced users, analysing the VM routines used for possible optimisations. close GH-18853
This commit is contained in:
parent
e9310171f7
commit
22bd2ae63f
5 changed files with 500 additions and 1 deletions
2
NEWS
2
NEWS
|
@ -247,6 +247,8 @@ PHP NEWS
|
||||||
- Sqlite:
|
- Sqlite:
|
||||||
. Added Sqlite3Stmt::busy to check if a statement is still being executed.
|
. Added Sqlite3Stmt::busy to check if a statement is still being executed.
|
||||||
(David Carlier)
|
(David Carlier)
|
||||||
|
. Added Sqlite3Stmt::explain to produce a explain query plan from
|
||||||
|
the statement. (David Carlier)
|
||||||
|
|
||||||
- Standard:
|
- Standard:
|
||||||
. Fixed crypt() tests on musl when using --with-external-libcrypt
|
. Fixed crypt() tests on musl when using --with-external-libcrypt
|
||||||
|
|
|
@ -26,6 +26,9 @@
|
||||||
#include "SAPI.h"
|
#include "SAPI.h"
|
||||||
|
|
||||||
#include <sqlite3.h>
|
#include <sqlite3.h>
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#include <Availability.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "zend_exceptions.h"
|
#include "zend_exceptions.h"
|
||||||
#include "sqlite3_arginfo.h"
|
#include "sqlite3_arginfo.h"
|
||||||
|
@ -1500,6 +1503,60 @@ PHP_METHOD(SQLite3Stmt, busy)
|
||||||
RETURN_FALSE;
|
RETURN_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if SQLITE_VERSION_NUMBER >= 3043000
|
||||||
|
PHP_METHOD(SQLite3Stmt, explain)
|
||||||
|
{
|
||||||
|
#ifdef __APPLE__
|
||||||
|
if (__builtin_available(macOS 14.2, *)) {
|
||||||
|
#endif
|
||||||
|
php_sqlite3_stmt *stmt_obj;
|
||||||
|
zval *object = ZEND_THIS;
|
||||||
|
stmt_obj = Z_SQLITE3_STMT_P(object);
|
||||||
|
|
||||||
|
ZEND_PARSE_PARAMETERS_NONE();
|
||||||
|
|
||||||
|
SQLITE3_CHECK_INITIALIZED(stmt_obj->db_obj, stmt_obj->initialised, SQLite3);
|
||||||
|
SQLITE3_CHECK_INITIALIZED_STMT(stmt_obj->stmt, SQLite3Stmt);
|
||||||
|
|
||||||
|
RETURN_LONG((zend_long)sqlite3_stmt_isexplain(stmt_obj->stmt));
|
||||||
|
#ifdef __APPLE__
|
||||||
|
} else {
|
||||||
|
zend_throw_error(NULL, "explain statement unsupported");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
PHP_METHOD(SQLite3Stmt, setExplain)
|
||||||
|
{
|
||||||
|
#ifdef __APPLE__
|
||||||
|
if (__builtin_available(macOS 14.2, *)) {
|
||||||
|
#endif
|
||||||
|
php_sqlite3_stmt *stmt_obj;
|
||||||
|
zend_long mode;
|
||||||
|
zval *object = ZEND_THIS;
|
||||||
|
stmt_obj = Z_SQLITE3_STMT_P(object);
|
||||||
|
|
||||||
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
||||||
|
Z_PARAM_LONG(mode)
|
||||||
|
ZEND_PARSE_PARAMETERS_END();
|
||||||
|
|
||||||
|
if (mode < 0 || mode > 2) {
|
||||||
|
zend_argument_value_error(1, "must be one of the SQLite3Stmt::EXPLAIN_MODE_* constants");
|
||||||
|
RETURN_THROWS();
|
||||||
|
}
|
||||||
|
|
||||||
|
SQLITE3_CHECK_INITIALIZED(stmt_obj->db_obj, stmt_obj->initialised, SQLite3);
|
||||||
|
SQLITE3_CHECK_INITIALIZED_STMT(stmt_obj->stmt, SQLite3Stmt);
|
||||||
|
|
||||||
|
RETURN_BOOL(sqlite3_stmt_explain(stmt_obj->stmt, (int)mode) == SQLITE_OK);
|
||||||
|
#ifdef __APPLE__
|
||||||
|
} else {
|
||||||
|
zend_throw_error(NULL, "explain statement unsupported");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* bind parameters to a statement before execution */
|
/* bind parameters to a statement before execution */
|
||||||
static int php_sqlite3_bind_params(php_sqlite3_stmt *stmt_obj) /* {{{ */
|
static int php_sqlite3_bind_params(php_sqlite3_stmt *stmt_obj) /* {{{ */
|
||||||
{
|
{
|
||||||
|
|
|
@ -274,6 +274,15 @@ class SQLite3Stmt
|
||||||
public function reset(): bool {}
|
public function reset(): bool {}
|
||||||
|
|
||||||
public function busy(): bool {}
|
public function busy(): bool {}
|
||||||
|
|
||||||
|
#if SQLITE_VERSION_NUMBER >= 3043000
|
||||||
|
public const int EXPLAIN_MODE_PREPARED = 0;
|
||||||
|
public const int EXPLAIN_MODE_EXPLAIN = 1;
|
||||||
|
public const int EXPLAIN_MODE_EXPLAIN_QUERY_PLAN = 2;
|
||||||
|
|
||||||
|
public function explain(): int {}
|
||||||
|
public function setExplain(int $mode): bool {}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @not-serializable */
|
/** @not-serializable */
|
||||||
|
|
43
ext/sqlite3/sqlite3_arginfo.h
generated
43
ext/sqlite3/sqlite3_arginfo.h
generated
|
@ -1,5 +1,5 @@
|
||||||
/* This is a generated file, edit the .stub.php file instead.
|
/* This is a generated file, edit the .stub.php file instead.
|
||||||
* Stub hash: 28132e0e4df61f19dc4b23a7c9f79be6b3e40a8e */
|
* Stub hash: c3216eada9881743cbd3aa1510f1200b7ce0d942 */
|
||||||
|
|
||||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_SQLite3___construct, 0, 0, 1)
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_SQLite3___construct, 0, 0, 1)
|
||||||
ZEND_ARG_TYPE_INFO(0, filename, IS_STRING, 0)
|
ZEND_ARG_TYPE_INFO(0, filename, IS_STRING, 0)
|
||||||
|
@ -147,6 +147,15 @@ ZEND_END_ARG_INFO()
|
||||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_SQLite3Stmt_busy, 0, 0, _IS_BOOL, 0)
|
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_SQLite3Stmt_busy, 0, 0, _IS_BOOL, 0)
|
||||||
ZEND_END_ARG_INFO()
|
ZEND_END_ARG_INFO()
|
||||||
|
|
||||||
|
#if SQLITE_VERSION_NUMBER >= 3043000
|
||||||
|
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_SQLite3Stmt_explain, 0, 0, IS_LONG, 0)
|
||||||
|
ZEND_END_ARG_INFO()
|
||||||
|
|
||||||
|
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_SQLite3Stmt_setExplain, 0, 1, _IS_BOOL, 0)
|
||||||
|
ZEND_ARG_TYPE_INFO(0, mode, IS_LONG, 0)
|
||||||
|
ZEND_END_ARG_INFO()
|
||||||
|
#endif
|
||||||
|
|
||||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_SQLite3Result___construct, 0, 0, 0)
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_SQLite3Result___construct, 0, 0, 0)
|
||||||
ZEND_END_ARG_INFO()
|
ZEND_END_ARG_INFO()
|
||||||
|
|
||||||
|
@ -206,6 +215,10 @@ ZEND_METHOD(SQLite3Stmt, paramCount);
|
||||||
ZEND_METHOD(SQLite3Stmt, readOnly);
|
ZEND_METHOD(SQLite3Stmt, readOnly);
|
||||||
ZEND_METHOD(SQLite3Stmt, reset);
|
ZEND_METHOD(SQLite3Stmt, reset);
|
||||||
ZEND_METHOD(SQLite3Stmt, busy);
|
ZEND_METHOD(SQLite3Stmt, busy);
|
||||||
|
#if SQLITE_VERSION_NUMBER >= 3043000
|
||||||
|
ZEND_METHOD(SQLite3Stmt, explain);
|
||||||
|
ZEND_METHOD(SQLite3Stmt, setExplain);
|
||||||
|
#endif
|
||||||
ZEND_METHOD(SQLite3Result, __construct);
|
ZEND_METHOD(SQLite3Result, __construct);
|
||||||
ZEND_METHOD(SQLite3Result, numColumns);
|
ZEND_METHOD(SQLite3Result, numColumns);
|
||||||
ZEND_METHOD(SQLite3Result, columnName);
|
ZEND_METHOD(SQLite3Result, columnName);
|
||||||
|
@ -258,6 +271,10 @@ static const zend_function_entry class_SQLite3Stmt_methods[] = {
|
||||||
ZEND_ME(SQLite3Stmt, readOnly, arginfo_class_SQLite3Stmt_readOnly, ZEND_ACC_PUBLIC)
|
ZEND_ME(SQLite3Stmt, readOnly, arginfo_class_SQLite3Stmt_readOnly, ZEND_ACC_PUBLIC)
|
||||||
ZEND_ME(SQLite3Stmt, reset, arginfo_class_SQLite3Stmt_reset, ZEND_ACC_PUBLIC)
|
ZEND_ME(SQLite3Stmt, reset, arginfo_class_SQLite3Stmt_reset, ZEND_ACC_PUBLIC)
|
||||||
ZEND_ME(SQLite3Stmt, busy, arginfo_class_SQLite3Stmt_busy, ZEND_ACC_PUBLIC)
|
ZEND_ME(SQLite3Stmt, busy, arginfo_class_SQLite3Stmt_busy, ZEND_ACC_PUBLIC)
|
||||||
|
#if SQLITE_VERSION_NUMBER >= 3043000
|
||||||
|
ZEND_ME(SQLite3Stmt, explain, arginfo_class_SQLite3Stmt_explain, ZEND_ACC_PUBLIC)
|
||||||
|
ZEND_ME(SQLite3Stmt, setExplain, arginfo_class_SQLite3Stmt_setExplain, ZEND_ACC_PUBLIC)
|
||||||
|
#endif
|
||||||
ZEND_FE_END
|
ZEND_FE_END
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -540,6 +557,30 @@ static zend_class_entry *register_class_SQLite3Stmt(void)
|
||||||
|
|
||||||
INIT_CLASS_ENTRY(ce, "SQLite3Stmt", class_SQLite3Stmt_methods);
|
INIT_CLASS_ENTRY(ce, "SQLite3Stmt", class_SQLite3Stmt_methods);
|
||||||
class_entry = zend_register_internal_class_with_flags(&ce, NULL, ZEND_ACC_NOT_SERIALIZABLE);
|
class_entry = zend_register_internal_class_with_flags(&ce, NULL, ZEND_ACC_NOT_SERIALIZABLE);
|
||||||
|
#if SQLITE_VERSION_NUMBER >= 3043000
|
||||||
|
|
||||||
|
zval const_EXPLAIN_MODE_PREPARED_value;
|
||||||
|
ZVAL_LONG(&const_EXPLAIN_MODE_PREPARED_value, 0);
|
||||||
|
zend_string *const_EXPLAIN_MODE_PREPARED_name = zend_string_init_interned("EXPLAIN_MODE_PREPARED", sizeof("EXPLAIN_MODE_PREPARED") - 1, 1);
|
||||||
|
zend_declare_typed_class_constant(class_entry, const_EXPLAIN_MODE_PREPARED_name, &const_EXPLAIN_MODE_PREPARED_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG));
|
||||||
|
zend_string_release(const_EXPLAIN_MODE_PREPARED_name);
|
||||||
|
#endif
|
||||||
|
#if SQLITE_VERSION_NUMBER >= 3043000
|
||||||
|
|
||||||
|
zval const_EXPLAIN_MODE_EXPLAIN_value;
|
||||||
|
ZVAL_LONG(&const_EXPLAIN_MODE_EXPLAIN_value, 1);
|
||||||
|
zend_string *const_EXPLAIN_MODE_EXPLAIN_name = zend_string_init_interned("EXPLAIN_MODE_EXPLAIN", sizeof("EXPLAIN_MODE_EXPLAIN") - 1, 1);
|
||||||
|
zend_declare_typed_class_constant(class_entry, const_EXPLAIN_MODE_EXPLAIN_name, &const_EXPLAIN_MODE_EXPLAIN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG));
|
||||||
|
zend_string_release(const_EXPLAIN_MODE_EXPLAIN_name);
|
||||||
|
#endif
|
||||||
|
#if SQLITE_VERSION_NUMBER >= 3043000
|
||||||
|
|
||||||
|
zval const_EXPLAIN_MODE_EXPLAIN_QUERY_PLAN_value;
|
||||||
|
ZVAL_LONG(&const_EXPLAIN_MODE_EXPLAIN_QUERY_PLAN_value, 2);
|
||||||
|
zend_string *const_EXPLAIN_MODE_EXPLAIN_QUERY_PLAN_name = zend_string_init_interned("EXPLAIN_MODE_EXPLAIN_QUERY_PLAN", sizeof("EXPLAIN_MODE_EXPLAIN_QUERY_PLAN") - 1, 1);
|
||||||
|
zend_declare_typed_class_constant(class_entry, const_EXPLAIN_MODE_EXPLAIN_QUERY_PLAN_name, &const_EXPLAIN_MODE_EXPLAIN_QUERY_PLAN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG));
|
||||||
|
zend_string_release(const_EXPLAIN_MODE_EXPLAIN_QUERY_PLAN_name);
|
||||||
|
#endif
|
||||||
|
|
||||||
return class_entry;
|
return class_entry;
|
||||||
}
|
}
|
||||||
|
|
390
ext/sqlite3/tests/sqlite3_explain.phpt
Normal file
390
ext/sqlite3/tests/sqlite3_explain.phpt
Normal file
|
@ -0,0 +1,390 @@
|
||||||
|
--TEST--
|
||||||
|
Sqlite3Stmt::explain/setExplain usage
|
||||||
|
--EXTENSIONS--
|
||||||
|
sqlite3
|
||||||
|
--SKIPIF--
|
||||||
|
<?php
|
||||||
|
if (PHP_OS_FAMILY === "Darwin") die("skip on darwin for now");
|
||||||
|
$version = SQLite3::version()['versionNumber'];
|
||||||
|
if ($version <= 3043000) die("skip for sqlite3 < 3.43.0");
|
||||||
|
?>
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require_once(__DIR__ . '/new_db.inc');
|
||||||
|
|
||||||
|
$db->exec('CREATE TABLE test_explain (a string);');
|
||||||
|
$stmt = $db->prepare('INSERT INTO test_explain VALUES ("first insert"), ("second_insert")');
|
||||||
|
$stmt->setExplain(Sqlite3Stmt::EXPLAIN_MODE_EXPLAIN);
|
||||||
|
var_dump($stmt->explain() == Sqlite3Stmt::EXPLAIN_MODE_EXPLAIN);
|
||||||
|
$r = $stmt->execute();
|
||||||
|
$result = [];
|
||||||
|
while (($arr = $r->fetchArray(SQLITE3_ASSOC)) !== false) $result[] = $arr;
|
||||||
|
var_dump($result);
|
||||||
|
$stmts = $db->prepare('SELECT * FROM test_explain');
|
||||||
|
$stmts->setExplain(Sqlite3Stmt::EXPLAIN_MODE_EXPLAIN_QUERY_PLAN);
|
||||||
|
$r = $stmts->execute();
|
||||||
|
$result = [];
|
||||||
|
while (($arr = $r->fetchArray(SQLITE3_ASSOC)) !== false) $result[] = $arr;
|
||||||
|
var_dump($result);
|
||||||
|
|
||||||
|
$stmt = $db->prepare('INSERT INTO test_explain VALUES ("first insert"), ("second_insert")');
|
||||||
|
$stmt->setExplain(Sqlite3Stmt::EXPLAIN_MODE_PREPARED);
|
||||||
|
$stmt->execute();
|
||||||
|
$stmts = $db->prepare('SELECT * FROM test_explain');
|
||||||
|
$stmts->setExplain(Sqlite3Stmt::EXPLAIN_MODE_PREPARED);
|
||||||
|
$r = $stmts->execute();
|
||||||
|
$result = [];
|
||||||
|
while (($arr = $r->fetchArray(SQLITE3_ASSOC)) !== false) $result[] = $arr;
|
||||||
|
var_dump($result);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$stmts->setExplain(-1);
|
||||||
|
} catch (\ValueError $e) {
|
||||||
|
echo $e->getMessage(), PHP_EOL;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$stmts->setExplain(256);
|
||||||
|
} catch (\ValueError $e) {
|
||||||
|
echo $e->getMessage(), PHP_EOL;
|
||||||
|
}
|
||||||
|
|
||||||
|
var_dump($stmts->explain() == Sqlite3Stmt::EXPLAIN_MODE_PREPARED);
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
bool(true)
|
||||||
|
array(%d) {
|
||||||
|
[0]=>
|
||||||
|
array(8) {
|
||||||
|
["addr"]=>
|
||||||
|
int(0)
|
||||||
|
["opcode"]=>
|
||||||
|
string(4) "Init"
|
||||||
|
["p1"]=>
|
||||||
|
int(0)
|
||||||
|
["p2"]=>
|
||||||
|
int(%d)
|
||||||
|
["p3"]=>
|
||||||
|
int(0)
|
||||||
|
["p4"]=>
|
||||||
|
NULL
|
||||||
|
["p5"]=>
|
||||||
|
int(0)
|
||||||
|
["comment"]=>
|
||||||
|
%a
|
||||||
|
}
|
||||||
|
[1]=>
|
||||||
|
array(8) {
|
||||||
|
["addr"]=>
|
||||||
|
int(1)
|
||||||
|
["opcode"]=>
|
||||||
|
string(13) "InitCoroutine"
|
||||||
|
["p1"]=>
|
||||||
|
int(3)
|
||||||
|
["p2"]=>
|
||||||
|
int(%d)
|
||||||
|
["p3"]=>
|
||||||
|
int(2)
|
||||||
|
["p4"]=>
|
||||||
|
NULL
|
||||||
|
["p5"]=>
|
||||||
|
int(0)
|
||||||
|
["comment"]=>
|
||||||
|
%a
|
||||||
|
}
|
||||||
|
%A
|
||||||
|
array(8) {
|
||||||
|
["addr"]=>
|
||||||
|
int(%d)
|
||||||
|
["opcode"]=>
|
||||||
|
string(7) "String8"
|
||||||
|
["p1"]=>
|
||||||
|
int(0)
|
||||||
|
["p2"]=>
|
||||||
|
int(2)
|
||||||
|
["p3"]=>
|
||||||
|
int(0)
|
||||||
|
["p4"]=>
|
||||||
|
string(12) "first insert"
|
||||||
|
["p5"]=>
|
||||||
|
int(0)
|
||||||
|
["comment"]=>
|
||||||
|
%a
|
||||||
|
}
|
||||||
|
%A
|
||||||
|
array(8) {
|
||||||
|
["addr"]=>
|
||||||
|
int(%d)
|
||||||
|
["opcode"]=>
|
||||||
|
string(5) "Yield"
|
||||||
|
["p1"]=>
|
||||||
|
int(3)
|
||||||
|
["p2"]=>
|
||||||
|
int(0)
|
||||||
|
["p3"]=>
|
||||||
|
int(0)
|
||||||
|
["p4"]=>
|
||||||
|
NULL
|
||||||
|
["p5"]=>
|
||||||
|
int(0)
|
||||||
|
["comment"]=>
|
||||||
|
%a
|
||||||
|
}
|
||||||
|
%A
|
||||||
|
array(8) {
|
||||||
|
["addr"]=>
|
||||||
|
int(%d)
|
||||||
|
["opcode"]=>
|
||||||
|
string(7) "String8"
|
||||||
|
["p1"]=>
|
||||||
|
int(0)
|
||||||
|
["p2"]=>
|
||||||
|
int(2)
|
||||||
|
["p3"]=>
|
||||||
|
int(0)
|
||||||
|
["p4"]=>
|
||||||
|
string(13) "second_insert"
|
||||||
|
["p5"]=>
|
||||||
|
int(0)
|
||||||
|
["comment"]=>
|
||||||
|
%a
|
||||||
|
}
|
||||||
|
[%d]=>
|
||||||
|
array(8) {
|
||||||
|
["addr"]=>
|
||||||
|
int(%d)
|
||||||
|
["opcode"]=>
|
||||||
|
string(5) "Yield"
|
||||||
|
["p1"]=>
|
||||||
|
int(3)
|
||||||
|
["p2"]=>
|
||||||
|
int(0)
|
||||||
|
["p3"]=>
|
||||||
|
int(0)
|
||||||
|
["p4"]=>
|
||||||
|
NULL
|
||||||
|
["p5"]=>
|
||||||
|
int(0)
|
||||||
|
["comment"]=>
|
||||||
|
%a
|
||||||
|
}
|
||||||
|
[%d]=>
|
||||||
|
array(8) {
|
||||||
|
["addr"]=>
|
||||||
|
int(%d)
|
||||||
|
["opcode"]=>
|
||||||
|
string(12) "EndCoroutine"
|
||||||
|
["p1"]=>
|
||||||
|
int(3)
|
||||||
|
["p2"]=>
|
||||||
|
int(0)
|
||||||
|
["p3"]=>
|
||||||
|
int(0)
|
||||||
|
["p4"]=>
|
||||||
|
NULL
|
||||||
|
["p5"]=>
|
||||||
|
int(0)
|
||||||
|
["comment"]=>
|
||||||
|
%a
|
||||||
|
}
|
||||||
|
[%d]=>
|
||||||
|
array(8) {
|
||||||
|
["addr"]=>
|
||||||
|
int(%d)
|
||||||
|
["opcode"]=>
|
||||||
|
string(9) "OpenWrite"
|
||||||
|
["p1"]=>
|
||||||
|
int(0)
|
||||||
|
["p2"]=>
|
||||||
|
int(2)
|
||||||
|
["p3"]=>
|
||||||
|
int(0)
|
||||||
|
["p4"]=>
|
||||||
|
string(1) "1"
|
||||||
|
["p5"]=>
|
||||||
|
int(0)
|
||||||
|
["comment"]=>
|
||||||
|
%a
|
||||||
|
}
|
||||||
|
[%d]=>
|
||||||
|
array(8) {
|
||||||
|
["addr"]=>
|
||||||
|
int(%d)
|
||||||
|
["opcode"]=>
|
||||||
|
string(5) "Yield"
|
||||||
|
["p1"]=>
|
||||||
|
int(3)
|
||||||
|
["p2"]=>
|
||||||
|
int(%d)
|
||||||
|
["p3"]=>
|
||||||
|
int(0)
|
||||||
|
["p4"]=>
|
||||||
|
NULL
|
||||||
|
["p5"]=>
|
||||||
|
int(0)
|
||||||
|
["comment"]=>
|
||||||
|
%a
|
||||||
|
}
|
||||||
|
[%d]=>
|
||||||
|
array(8) {
|
||||||
|
["addr"]=>
|
||||||
|
int(%d)
|
||||||
|
["opcode"]=>
|
||||||
|
string(8) "NewRowid"
|
||||||
|
["p1"]=>
|
||||||
|
int(0)
|
||||||
|
["p2"]=>
|
||||||
|
int(1)
|
||||||
|
["p3"]=>
|
||||||
|
int(0)
|
||||||
|
["p4"]=>
|
||||||
|
NULL
|
||||||
|
["p5"]=>
|
||||||
|
int(0)
|
||||||
|
["comment"]=>
|
||||||
|
%a
|
||||||
|
}
|
||||||
|
[%d]=>
|
||||||
|
array(8) {
|
||||||
|
["addr"]=>
|
||||||
|
int(%d)
|
||||||
|
["opcode"]=>
|
||||||
|
string(10) "MakeRecord"
|
||||||
|
["p1"]=>
|
||||||
|
int(2)
|
||||||
|
["p2"]=>
|
||||||
|
int(1)
|
||||||
|
["p3"]=>
|
||||||
|
int(4)
|
||||||
|
["p4"]=>
|
||||||
|
string(1) "C"
|
||||||
|
["p5"]=>
|
||||||
|
int(0)
|
||||||
|
["comment"]=>
|
||||||
|
%a
|
||||||
|
}
|
||||||
|
[%d]=>
|
||||||
|
array(8) {
|
||||||
|
["addr"]=>
|
||||||
|
int(%d)
|
||||||
|
["opcode"]=>
|
||||||
|
string(6) "Insert"
|
||||||
|
["p1"]=>
|
||||||
|
int(0)
|
||||||
|
["p2"]=>
|
||||||
|
int(4)
|
||||||
|
["p3"]=>
|
||||||
|
int(1)
|
||||||
|
["p4"]=>
|
||||||
|
string(12) "test_explain"
|
||||||
|
["p5"]=>
|
||||||
|
int(57)
|
||||||
|
["comment"]=>
|
||||||
|
%a
|
||||||
|
}
|
||||||
|
[%d]=>
|
||||||
|
array(8) {
|
||||||
|
["addr"]=>
|
||||||
|
int(%d)
|
||||||
|
["opcode"]=>
|
||||||
|
string(4) "Goto"
|
||||||
|
["p1"]=>
|
||||||
|
int(0)
|
||||||
|
["p2"]=>
|
||||||
|
int(%d)
|
||||||
|
["p3"]=>
|
||||||
|
int(0)
|
||||||
|
["p4"]=>
|
||||||
|
NULL
|
||||||
|
["p5"]=>
|
||||||
|
int(0)
|
||||||
|
["comment"]=>
|
||||||
|
%a
|
||||||
|
}
|
||||||
|
[%d]=>
|
||||||
|
array(8) {
|
||||||
|
["addr"]=>
|
||||||
|
int(%d)
|
||||||
|
["opcode"]=>
|
||||||
|
string(4) "Halt"
|
||||||
|
["p1"]=>
|
||||||
|
int(0)
|
||||||
|
["p2"]=>
|
||||||
|
int(0)
|
||||||
|
["p3"]=>
|
||||||
|
int(0)
|
||||||
|
["p4"]=>
|
||||||
|
NULL
|
||||||
|
["p5"]=>
|
||||||
|
int(0)
|
||||||
|
["comment"]=>
|
||||||
|
%a
|
||||||
|
}
|
||||||
|
[%d]=>
|
||||||
|
array(8) {
|
||||||
|
["addr"]=>
|
||||||
|
int(%d)
|
||||||
|
["opcode"]=>
|
||||||
|
string(11) "Transaction"
|
||||||
|
["p1"]=>
|
||||||
|
int(0)
|
||||||
|
["p2"]=>
|
||||||
|
int(1)
|
||||||
|
["p3"]=>
|
||||||
|
int(1)
|
||||||
|
["p4"]=>
|
||||||
|
string(1) "0"
|
||||||
|
["p5"]=>
|
||||||
|
int(1)
|
||||||
|
["comment"]=>
|
||||||
|
%a
|
||||||
|
}
|
||||||
|
[%d]=>
|
||||||
|
array(8) {
|
||||||
|
["addr"]=>
|
||||||
|
int(%d)
|
||||||
|
["opcode"]=>
|
||||||
|
string(4) "Goto"
|
||||||
|
["p1"]=>
|
||||||
|
int(0)
|
||||||
|
["p2"]=>
|
||||||
|
int(1)
|
||||||
|
["p3"]=>
|
||||||
|
int(0)
|
||||||
|
["p4"]=>
|
||||||
|
NULL
|
||||||
|
["p5"]=>
|
||||||
|
int(0)
|
||||||
|
["comment"]=>
|
||||||
|
%a
|
||||||
|
}
|
||||||
|
}
|
||||||
|
array(1) {
|
||||||
|
[0]=>
|
||||||
|
array(4) {
|
||||||
|
["id"]=>
|
||||||
|
int(2)
|
||||||
|
["parent"]=>
|
||||||
|
int(0)
|
||||||
|
["notused"]=>
|
||||||
|
int(0)
|
||||||
|
["detail"]=>
|
||||||
|
string(17) "SCAN test_explain"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
array(2) {
|
||||||
|
[0]=>
|
||||||
|
array(1) {
|
||||||
|
["a"]=>
|
||||||
|
string(12) "first insert"
|
||||||
|
}
|
||||||
|
[1]=>
|
||||||
|
array(1) {
|
||||||
|
["a"]=>
|
||||||
|
string(13) "second_insert"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SQLite3Stmt::setExplain(): Argument #1 ($mode) must be one of the SQLite3Stmt::EXPLAIN_MODE_* constants
|
||||||
|
SQLite3Stmt::setExplain(): Argument #1 ($mode) must be one of the SQLite3Stmt::EXPLAIN_MODE_* constants
|
||||||
|
bool(true)
|
Loading…
Add table
Add a link
Reference in a new issue