mirror of
https://github.com/php/php-src.git
synced 2025-08-15 13:38:49 +02:00
Implemented PDO Driver specific SQL parsers
RFC: http://wiki.php.net/rfc/pdo_driver_specific_parsers
This commit is contained in:
parent
ac947925c0
commit
715b9aaa09
31 changed files with 391 additions and 44 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -137,7 +137,7 @@ php
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
/ext/json/json_scanner.c
|
/ext/json/json_scanner.c
|
||||||
/ext/json/php_json_scanner_defs.h
|
/ext/json/php_json_scanner_defs.h
|
||||||
/ext/pdo/pdo_sql_parser.c
|
/ext/pdo*/*_sql_parser.c
|
||||||
/ext/phar/phar_path_check.c
|
/ext/phar/phar_path_check.c
|
||||||
/ext/standard/url_scanner_ex.c
|
/ext/standard/url_scanner_ex.c
|
||||||
/ext/standard/var_unserializer.c
|
/ext/standard/var_unserializer.c
|
||||||
|
|
32
ext/pdo/pdo_sql_parser.h
Normal file
32
ext/pdo/pdo_sql_parser.h
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
/*
|
||||||
|
+----------------------------------------------------------------------+
|
||||||
|
| Copyright (c) The PHP Group |
|
||||||
|
+----------------------------------------------------------------------+
|
||||||
|
| This source file is subject to version 3.01 of the PHP license, |
|
||||||
|
| that is bundled with this package in the file LICENSE, and is |
|
||||||
|
| available through the world-wide-web at the following url: |
|
||||||
|
| http://www.php.net/license/3_01.txt |
|
||||||
|
| If you did not receive a copy of the PHP license and are unable to |
|
||||||
|
| obtain it through the world-wide-web, please send a note to |
|
||||||
|
| license@php.net so we can mail you a copy immediately. |
|
||||||
|
+----------------------------------------------------------------------+
|
||||||
|
| Author: George Schlossnagle <george@omniti.com> |
|
||||||
|
+----------------------------------------------------------------------+
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define PDO_PARSER_TEXT 1
|
||||||
|
#define PDO_PARSER_BIND 2
|
||||||
|
#define PDO_PARSER_BIND_POS 3
|
||||||
|
#define PDO_PARSER_ESCAPED_QUESTION 4
|
||||||
|
#define PDO_PARSER_EOI 5
|
||||||
|
|
||||||
|
#define PDO_PARSER_BINDNO_ESCAPED_CHAR -1
|
||||||
|
|
||||||
|
#define RET(i) {s->cur = cursor; return i; }
|
||||||
|
#define SKIP_ONE(i) {s->cur = s->tok + 1; return i; }
|
||||||
|
|
||||||
|
#define YYCTYPE unsigned char
|
||||||
|
#define YYCURSOR cursor
|
||||||
|
#define YYLIMIT s->end
|
||||||
|
#define YYMARKER s->ptr
|
||||||
|
#define YYFILL(n) { RET(PDO_PARSER_EOI); }
|
|
@ -17,29 +17,9 @@
|
||||||
#include "php.h"
|
#include "php.h"
|
||||||
#include "php_pdo_driver.h"
|
#include "php_pdo_driver.h"
|
||||||
#include "php_pdo_int.h"
|
#include "php_pdo_int.h"
|
||||||
|
#include "pdo_sql_parser.h"
|
||||||
|
|
||||||
#define PDO_PARSER_TEXT 1
|
static int default_scanner(pdo_scanner_t *s)
|
||||||
#define PDO_PARSER_BIND 2
|
|
||||||
#define PDO_PARSER_BIND_POS 3
|
|
||||||
#define PDO_PARSER_ESCAPED_QUESTION 4
|
|
||||||
#define PDO_PARSER_EOI 5
|
|
||||||
|
|
||||||
#define PDO_PARSER_BINDNO_ESCAPED_CHAR -1
|
|
||||||
|
|
||||||
#define RET(i) {s->cur = cursor; return i; }
|
|
||||||
#define SKIP_ONE(i) {s->cur = s->tok + 1; return i; }
|
|
||||||
|
|
||||||
#define YYCTYPE unsigned char
|
|
||||||
#define YYCURSOR cursor
|
|
||||||
#define YYLIMIT s->end
|
|
||||||
#define YYMARKER s->ptr
|
|
||||||
#define YYFILL(n) { RET(PDO_PARSER_EOI); }
|
|
||||||
|
|
||||||
typedef struct Scanner {
|
|
||||||
const char *ptr, *cur, *tok, *end;
|
|
||||||
} Scanner;
|
|
||||||
|
|
||||||
static int scan(Scanner *s)
|
|
||||||
{
|
{
|
||||||
const char *cursor = s->cur;
|
const char *cursor = s->cur;
|
||||||
|
|
||||||
|
@ -47,18 +27,16 @@ static int scan(Scanner *s)
|
||||||
/*!re2c
|
/*!re2c
|
||||||
BINDCHR = [:][a-zA-Z0-9_]+;
|
BINDCHR = [:][a-zA-Z0-9_]+;
|
||||||
QUESTION = [?];
|
QUESTION = [?];
|
||||||
ESCQUESTION = [?][?];
|
|
||||||
COMMENTS = ("/*"([^*]+|[*]+[^/*])*[*]*"*/"|"--"[^\r\n]*);
|
COMMENTS = ("/*"([^*]+|[*]+[^/*])*[*]*"*/"|"--"[^\r\n]*);
|
||||||
SPECIALS = [:?"'-/];
|
SPECIALS = [:?"'/-];
|
||||||
MULTICHAR = [:]{2,};
|
MULTICHAR = ([:]{2,}|[?]{2,});
|
||||||
ANYNOEOF = [\001-\377];
|
ANYNOEOF = [\001-\377];
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*!re2c
|
/*!re2c
|
||||||
(["](([\\]ANYNOEOF)|ANYNOEOF\["\\])*["]) { RET(PDO_PARSER_TEXT); }
|
(["]((["]["])|ANYNOEOF\["])*["]) { RET(PDO_PARSER_TEXT); }
|
||||||
(['](([\\]ANYNOEOF)|ANYNOEOF\['\\])*[']) { RET(PDO_PARSER_TEXT); }
|
(['](([']['])|ANYNOEOF\['])*[']) { RET(PDO_PARSER_TEXT); }
|
||||||
MULTICHAR { RET(PDO_PARSER_TEXT); }
|
MULTICHAR { RET(PDO_PARSER_TEXT); }
|
||||||
ESCQUESTION { RET(PDO_PARSER_ESCAPED_QUESTION); }
|
|
||||||
BINDCHR { RET(PDO_PARSER_BIND); }
|
BINDCHR { RET(PDO_PARSER_BIND); }
|
||||||
QUESTION { RET(PDO_PARSER_BIND_POS); }
|
QUESTION { RET(PDO_PARSER_BIND_POS); }
|
||||||
SPECIALS { SKIP_ONE(PDO_PARSER_TEXT); }
|
SPECIALS { SKIP_ONE(PDO_PARSER_TEXT); }
|
||||||
|
@ -81,7 +59,7 @@ static void free_param_name(zval *el) {
|
||||||
|
|
||||||
PDO_API int pdo_parse_params(pdo_stmt_t *stmt, zend_string *inquery, zend_string **outquery)
|
PDO_API int pdo_parse_params(pdo_stmt_t *stmt, zend_string *inquery, zend_string **outquery)
|
||||||
{
|
{
|
||||||
Scanner s;
|
pdo_scanner_t s;
|
||||||
char *newbuffer;
|
char *newbuffer;
|
||||||
ptrdiff_t t;
|
ptrdiff_t t;
|
||||||
uint32_t bindno = 0;
|
uint32_t bindno = 0;
|
||||||
|
@ -91,6 +69,9 @@ PDO_API int pdo_parse_params(pdo_stmt_t *stmt, zend_string *inquery, zend_string
|
||||||
struct pdo_bound_param_data *param;
|
struct pdo_bound_param_data *param;
|
||||||
int query_type = PDO_PLACEHOLDER_NONE;
|
int query_type = PDO_PLACEHOLDER_NONE;
|
||||||
struct placeholder *placeholders = NULL, *placetail = NULL, *plc = NULL;
|
struct placeholder *placeholders = NULL, *placetail = NULL, *plc = NULL;
|
||||||
|
int (*scan)(pdo_scanner_t *s);
|
||||||
|
|
||||||
|
scan = stmt->dbh->methods->scanner ? stmt->dbh->methods->scanner : default_scanner;
|
||||||
|
|
||||||
s.cur = ZSTR_VAL(inquery);
|
s.cur = ZSTR_VAL(inquery);
|
||||||
s.end = s.cur + ZSTR_LEN(inquery) + 1;
|
s.end = s.cur + ZSTR_LEN(inquery) + 1;
|
||||||
|
|
|
@ -24,6 +24,7 @@ typedef struct _pdo_dbh_t pdo_dbh_t;
|
||||||
typedef struct _pdo_dbh_object_t pdo_dbh_object_t;
|
typedef struct _pdo_dbh_object_t pdo_dbh_object_t;
|
||||||
typedef struct _pdo_stmt_t pdo_stmt_t;
|
typedef struct _pdo_stmt_t pdo_stmt_t;
|
||||||
typedef struct _pdo_row_t pdo_row_t;
|
typedef struct _pdo_row_t pdo_row_t;
|
||||||
|
typedef struct _pdo_scanner_t pdo_scanner_t;
|
||||||
struct pdo_bound_param_data;
|
struct pdo_bound_param_data;
|
||||||
|
|
||||||
#ifndef TRUE
|
#ifndef TRUE
|
||||||
|
@ -33,7 +34,7 @@ struct pdo_bound_param_data;
|
||||||
# define FALSE 0
|
# define FALSE 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define PDO_DRIVER_API 20170320
|
#define PDO_DRIVER_API 20240423
|
||||||
|
|
||||||
/* Doctrine hardcodes these constants, avoid changing their values. */
|
/* Doctrine hardcodes these constants, avoid changing their values. */
|
||||||
enum pdo_param_type {
|
enum pdo_param_type {
|
||||||
|
@ -275,6 +276,9 @@ typedef void (*pdo_dbh_request_shutdown)(pdo_dbh_t *dbh);
|
||||||
* with any zvals in the driver_data that would be freed if the handle is destroyed. */
|
* with any zvals in the driver_data that would be freed if the handle is destroyed. */
|
||||||
typedef void (*pdo_dbh_get_gc_func)(pdo_dbh_t *dbh, zend_get_gc_buffer *buffer);
|
typedef void (*pdo_dbh_get_gc_func)(pdo_dbh_t *dbh, zend_get_gc_buffer *buffer);
|
||||||
|
|
||||||
|
/* driver specific re2s sql parser, overrides the default one if present */
|
||||||
|
typedef int (*pdo_dbh_sql_scanner)(pdo_scanner_t *s);
|
||||||
|
|
||||||
/* for adding methods to the dbh or stmt objects
|
/* for adding methods to the dbh or stmt objects
|
||||||
pointer to a list of driver specific functions. The convention is
|
pointer to a list of driver specific functions. The convention is
|
||||||
to prefix the function names using the PDO driver name; this will
|
to prefix the function names using the PDO driver name; this will
|
||||||
|
@ -307,6 +311,7 @@ struct pdo_dbh_methods {
|
||||||
/* if defined to NULL, PDO will use its internal transaction tracking state */
|
/* if defined to NULL, PDO will use its internal transaction tracking state */
|
||||||
pdo_dbh_txn_func in_transaction;
|
pdo_dbh_txn_func in_transaction;
|
||||||
pdo_dbh_get_gc_func get_gc;
|
pdo_dbh_get_gc_func get_gc;
|
||||||
|
pdo_dbh_sql_scanner scanner;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
@ -647,6 +652,10 @@ struct _pdo_row_t {
|
||||||
pdo_stmt_t *stmt;
|
pdo_stmt_t *stmt;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct _pdo_scanner_t {
|
||||||
|
const char *ptr, *cur, *tok, *end;
|
||||||
|
};
|
||||||
|
|
||||||
/* Call this in MINIT to register the PDO driver.
|
/* Call this in MINIT to register the PDO driver.
|
||||||
* Registering the driver might fail and should be reported accordingly in MINIT. */
|
* Registering the driver might fail and should be reported accordingly in MINIT. */
|
||||||
PDO_API zend_result php_pdo_register_driver(const pdo_driver_t *driver);
|
PDO_API zend_result php_pdo_register_driver(const pdo_driver_t *driver);
|
||||||
|
|
|
@ -436,7 +436,8 @@ static const struct pdo_dbh_methods dblib_methods = {
|
||||||
NULL, /* get driver methods */
|
NULL, /* get driver methods */
|
||||||
NULL, /* request shutdown */
|
NULL, /* request shutdown */
|
||||||
NULL, /* in transaction, use PDO's internal tracking mechanism */
|
NULL, /* in transaction, use PDO's internal tracking mechanism */
|
||||||
NULL /* get gc */
|
NULL, /* get gc */
|
||||||
|
NULL /* scanner */
|
||||||
};
|
};
|
||||||
|
|
||||||
static int pdo_dblib_handle_factory(pdo_dbh_t *dbh, zval *driver_options)
|
static int pdo_dblib_handle_factory(pdo_dbh_t *dbh, zval *driver_options)
|
||||||
|
|
|
@ -1274,7 +1274,8 @@ static const struct pdo_dbh_methods firebird_methods = { /* {{{ */
|
||||||
NULL, /* get driver methods */
|
NULL, /* get driver methods */
|
||||||
NULL, /* request shutdown */
|
NULL, /* request shutdown */
|
||||||
pdo_firebird_in_manually_transaction,
|
pdo_firebird_in_manually_transaction,
|
||||||
NULL /* get gc */
|
NULL, /* get gc */
|
||||||
|
NULL /* scanner */
|
||||||
};
|
};
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
|
7
ext/pdo_mysql/Makefile.frag
Normal file
7
ext/pdo_mysql/Makefile.frag
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
$(srcdir)/mysql_sql_parser.c: $(srcdir)/mysql_sql_parser.re
|
||||||
|
@(cd $(top_srcdir); \
|
||||||
|
if test -f ./mysql_sql_parser.re; then \
|
||||||
|
$(RE2C) $(RE2C_FLAGS) --no-generation-date -o mysql_sql_parser.c mysql_sql_parser.re; \
|
||||||
|
else \
|
||||||
|
$(RE2C) $(RE2C_FLAGS) --no-generation-date -o ext/pdo_mysql/mysql_sql_parser.c ext/pdo_mysql/mysql_sql_parser.re; \
|
||||||
|
fi)
|
3
ext/pdo_mysql/Makefile.frag.w32
Normal file
3
ext/pdo_mysql/Makefile.frag.w32
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
ext\pdo_mysql\mysql_sql_parser.c: ext\pdo_mysql\mysql_sql_parser.re
|
||||||
|
cd $(PHP_SRC_DIR)
|
||||||
|
$(RE2C) $(RE2C_FLAGS) --no-generation-date -o ext/pdo_mysql/mysql_sql_parser.c ext/pdo_mysql/mysql_sql_parser.re
|
|
@ -85,9 +85,10 @@ if test "$PHP_PDO_MYSQL" != "no"; then
|
||||||
AC_DEFINE_UNQUOTED(PDO_MYSQL_UNIX_ADDR, "$PDO_MYSQL_SOCKET", [ ])
|
AC_DEFINE_UNQUOTED(PDO_MYSQL_UNIX_ADDR, "$PDO_MYSQL_SOCKET", [ ])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
PHP_NEW_EXTENSION(pdo_mysql, pdo_mysql.c mysql_driver.c mysql_statement.c, $ext_shared,, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1)
|
PHP_NEW_EXTENSION(pdo_mysql, pdo_mysql.c mysql_driver.c mysql_statement.c mysql_sql_parser.c, $ext_shared,, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1)
|
||||||
|
|
||||||
PHP_ADD_EXTENSION_DEP(pdo_mysql, pdo)
|
PHP_ADD_EXTENSION_DEP(pdo_mysql, pdo)
|
||||||
|
PHP_ADD_MAKEFILE_FRAGMENT
|
||||||
|
|
||||||
if test "$PHP_PDO_MYSQL" = "yes" || test "$PHP_PDO_MYSQL" = "mysqlnd"; then
|
if test "$PHP_PDO_MYSQL" = "yes" || test "$PHP_PDO_MYSQL" = "mysqlnd"; then
|
||||||
PHP_ADD_EXTENSION_DEP(pdo_mysql, mysqlnd)
|
PHP_ADD_EXTENSION_DEP(pdo_mysql, mysqlnd)
|
||||||
|
|
|
@ -6,15 +6,17 @@ if (PHP_PDO_MYSQL != "no") {
|
||||||
if (PHP_PDO_MYSQL == "yes" || PHP_PDO_MYSQL == "mysqlnd") {
|
if (PHP_PDO_MYSQL == "yes" || PHP_PDO_MYSQL == "mysqlnd") {
|
||||||
AC_DEFINE('PDO_USE_MYSQLND', 1, 'Using MySQL native driver');
|
AC_DEFINE('PDO_USE_MYSQLND', 1, 'Using MySQL native driver');
|
||||||
STDOUT.WriteLine("INFO: mysqlnd build");
|
STDOUT.WriteLine("INFO: mysqlnd build");
|
||||||
EXTENSION("pdo_mysql", "pdo_mysql.c mysql_driver.c mysql_statement.c");
|
EXTENSION("pdo_mysql", "pdo_mysql.c mysql_driver.c mysql_statement.c mysql_sql_parser.c");
|
||||||
ADD_EXTENSION_DEP('pdo_mysql', 'pdo');
|
ADD_EXTENSION_DEP('pdo_mysql', 'pdo');
|
||||||
|
ADD_MAKEFILE_FRAGMENT();
|
||||||
} else {
|
} else {
|
||||||
if (CHECK_LIB("libmysql.lib", "pdo_mysql", PHP_PDO_MYSQL) &&
|
if (CHECK_LIB("libmysql.lib", "pdo_mysql", PHP_PDO_MYSQL) &&
|
||||||
CHECK_HEADER_ADD_INCLUDE("mysql.h", "CFLAGS_PDO_MYSQL",
|
CHECK_HEADER_ADD_INCLUDE("mysql.h", "CFLAGS_PDO_MYSQL",
|
||||||
PHP_PDO_MYSQL + "\\include;" +
|
PHP_PDO_MYSQL + "\\include;" +
|
||||||
PHP_PHP_BUILD + "\\include\\mysql;" +
|
PHP_PHP_BUILD + "\\include\\mysql;" +
|
||||||
PHP_PDO_MYSQL)) {
|
PHP_PDO_MYSQL)) {
|
||||||
EXTENSION("pdo_mysql", "pdo_mysql.c mysql_driver.c mysql_statement.c", null, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1");
|
EXTENSION("pdo_mysql", "pdo_mysql.c mysql_driver.c mysql_statement.c mysql_sql_parser.c", null, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1");
|
||||||
|
ADD_MAKEFILE_FRAGMENT();
|
||||||
} else {
|
} else {
|
||||||
WARNING("pdo_mysql not enabled; libraries and headers not found");
|
WARNING("pdo_mysql not enabled; libraries and headers not found");
|
||||||
}
|
}
|
||||||
|
|
|
@ -650,7 +650,8 @@ static const struct pdo_dbh_methods mysql_methods = {
|
||||||
NULL,
|
NULL,
|
||||||
pdo_mysql_request_shutdown,
|
pdo_mysql_request_shutdown,
|
||||||
pdo_mysql_in_transaction,
|
pdo_mysql_in_transaction,
|
||||||
NULL /* get_gc */
|
NULL, /* get_gc */
|
||||||
|
pdo_mysql_scanner
|
||||||
};
|
};
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
|
48
ext/pdo_mysql/mysql_sql_parser.re
Normal file
48
ext/pdo_mysql/mysql_sql_parser.re
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
+----------------------------------------------------------------------+
|
||||||
|
| Copyright (c) The PHP Group |
|
||||||
|
+----------------------------------------------------------------------+
|
||||||
|
| This source file is subject to version 3.01 of the PHP license, |
|
||||||
|
| that is bundled with this package in the file LICENSE, and is |
|
||||||
|
| available through the world-wide-web at the following url: |
|
||||||
|
| https://www.php.net/license/3_01.txt |
|
||||||
|
| If you did not receive a copy of the PHP license and are unable to |
|
||||||
|
| obtain it through the world-wide-web, please send a note to |
|
||||||
|
| license@php.net so we can mail you a copy immediately. |
|
||||||
|
+----------------------------------------------------------------------+
|
||||||
|
| Author: Matteo Beccati <mbeccati@php.net> |
|
||||||
|
+----------------------------------------------------------------------+
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "php.h"
|
||||||
|
#include "ext/pdo/php_pdo_driver.h"
|
||||||
|
#include "ext/pdo/php_pdo_int.h"
|
||||||
|
#include "ext/pdo/pdo_sql_parser.h"
|
||||||
|
|
||||||
|
int pdo_mysql_scanner(pdo_scanner_t *s)
|
||||||
|
{
|
||||||
|
const char *cursor = s->cur;
|
||||||
|
|
||||||
|
s->tok = cursor;
|
||||||
|
/*!re2c
|
||||||
|
BINDCHR = [:][a-zA-Z0-9_]+;
|
||||||
|
QUESTION = [?];
|
||||||
|
COMMENTS = ("/*"([^*]+|[*]+[^/*])*[*]*"*/"|("--"|[#])[^\r\n]*);
|
||||||
|
SPECIALS = [:?"'`/#-];
|
||||||
|
MULTICHAR = ([:]{2,}|[?]{2,});
|
||||||
|
ANYNOEOF = [\001-\377];
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!re2c
|
||||||
|
(["]((["]["])|([\\]ANYNOEOF)|ANYNOEOF\["\\])*["]) { RET(PDO_PARSER_TEXT); }
|
||||||
|
(['](([']['])|([\\]ANYNOEOF)|ANYNOEOF\['\\])*[']) { RET(PDO_PARSER_TEXT); }
|
||||||
|
([`]([`][`]|ANYNOEOF\[`])*[`]) { RET(PDO_PARSER_TEXT); }
|
||||||
|
MULTICHAR { RET(PDO_PARSER_TEXT); }
|
||||||
|
BINDCHR { RET(PDO_PARSER_BIND); }
|
||||||
|
QUESTION { RET(PDO_PARSER_BIND_POS); }
|
||||||
|
SPECIALS { SKIP_ONE(PDO_PARSER_TEXT); }
|
||||||
|
COMMENTS { RET(PDO_PARSER_TEXT); }
|
||||||
|
(ANYNOEOF\SPECIALS)+ { RET(PDO_PARSER_TEXT); }
|
||||||
|
*/
|
||||||
|
}
|
|
@ -147,6 +147,8 @@ typedef struct {
|
||||||
|
|
||||||
extern const pdo_driver_t pdo_mysql_driver;
|
extern const pdo_driver_t pdo_mysql_driver;
|
||||||
|
|
||||||
|
extern int pdo_mysql_scanner(pdo_scanner_t *s);
|
||||||
|
|
||||||
extern int _pdo_mysql_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, const char *file, int line);
|
extern int _pdo_mysql_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, const char *file, int line);
|
||||||
#define pdo_mysql_error(s) _pdo_mysql_error(s, NULL, __FILE__, __LINE__)
|
#define pdo_mysql_error(s) _pdo_mysql_error(s, NULL, __FILE__, __LINE__)
|
||||||
#define pdo_mysql_error_stmt(s) _pdo_mysql_error(stmt->dbh, stmt, __FILE__, __LINE__)
|
#define pdo_mysql_error_stmt(s) _pdo_mysql_error(stmt->dbh, stmt, __FILE__, __LINE__)
|
||||||
|
|
58
ext/pdo_mysql/tests/pdo_mysql_parser.phpt
Normal file
58
ext/pdo_mysql/tests/pdo_mysql_parser.phpt
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
--TEST--
|
||||||
|
MySQL PDO Parser custom syntax
|
||||||
|
--EXTENSIONS--
|
||||||
|
pdo_mysql
|
||||||
|
--SKIPIF--
|
||||||
|
<?php
|
||||||
|
require_once __DIR__ . '/inc/mysql_pdo_test.inc';
|
||||||
|
MySQLPDOTest::skip();
|
||||||
|
?>
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
require_once __DIR__ . '/inc/mysql_pdo_test.inc';
|
||||||
|
$db = MySQLPDOTest::factory();
|
||||||
|
|
||||||
|
$table = 'pdo_mysql_parser';
|
||||||
|
|
||||||
|
$db->exec("DROP TABLE IF EXISTS {$table}");
|
||||||
|
$db->exec("CREATE TABLE {$table} (`a``?` int NOT NULL)");
|
||||||
|
$db->exec("INSERT INTO {$table} VALUES (1)");
|
||||||
|
|
||||||
|
// No parameters
|
||||||
|
$queries = [
|
||||||
|
"SELECT * FROM {$table}",
|
||||||
|
"SELECT * FROM {$table} -- ?",
|
||||||
|
"SELECT * FROM {$table} # ?",
|
||||||
|
"SELECT * FROM {$table} /* ? */",
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($queries as $k => $query) {
|
||||||
|
$stmt = $db->prepare($query);
|
||||||
|
$stmt->execute();
|
||||||
|
var_dump($stmt->fetch(PDO::FETCH_NUM) === [0 => 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// One parameter
|
||||||
|
$queries = [
|
||||||
|
"SELECT * FROM {$table} WHERE 1 = ?",
|
||||||
|
"SELECT * FROM {$table} WHERE \"?\" IN (?, '?')",
|
||||||
|
"SELECT * FROM {$table} WHERE `a``?` = ?",
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($queries as $k => $query) {
|
||||||
|
$stmt = $db->prepare($query);
|
||||||
|
$stmt->execute([1]);
|
||||||
|
var_dump($stmt->fetch(PDO::FETCH_NUM) === [0 => 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$db->exec("DROP TABLE pdo_mysql_parser");
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
bool(true)
|
||||||
|
bool(true)
|
||||||
|
bool(true)
|
||||||
|
bool(true)
|
||||||
|
bool(true)
|
||||||
|
bool(true)
|
||||||
|
bool(true)
|
|
@ -461,7 +461,8 @@ static const struct pdo_dbh_methods odbc_methods = {
|
||||||
NULL, /* get_driver_methods */
|
NULL, /* get_driver_methods */
|
||||||
NULL, /* request_shutdown */
|
NULL, /* request_shutdown */
|
||||||
NULL, /* in transaction, use PDO's internal tracking mechanism */
|
NULL, /* in transaction, use PDO's internal tracking mechanism */
|
||||||
NULL /* get_gc */
|
NULL, /* get_gc */
|
||||||
|
NULL /* scanner */
|
||||||
};
|
};
|
||||||
|
|
||||||
static int pdo_odbc_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* {{{ */
|
static int pdo_odbc_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* {{{ */
|
||||||
|
|
7
ext/pdo_pgsql/Makefile.frag
Normal file
7
ext/pdo_pgsql/Makefile.frag
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
$(srcdir)/pgsql_sql_parser.c: $(srcdir)/pgsql_sql_parser.re
|
||||||
|
@(cd $(top_srcdir); \
|
||||||
|
if test -f ./pgsql_sql_parser.re; then \
|
||||||
|
$(RE2C) $(RE2C_FLAGS) --no-generation-date -o pgsql_sql_parser.c pgsql_sql_parser.re; \
|
||||||
|
else \
|
||||||
|
$(RE2C) $(RE2C_FLAGS) --no-generation-date -o ext/pdo_pgsql/pgsql_sql_parser.c ext/pdo_pgsql/pgsql_sql_parser.re; \
|
||||||
|
fi)
|
3
ext/pdo_pgsql/Makefile.frag.w32
Normal file
3
ext/pdo_pgsql/Makefile.frag.w32
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
ext\pdo_pgsql\pgsql_sql_parser.c: ext\pdo_pgsql\pgsql_sql_parser.re
|
||||||
|
cd $(PHP_SRC_DIR)
|
||||||
|
$(RE2C) $(RE2C_FLAGS) --no-generation-date -o ext/pdo_pgsql/pgsql_sql_parser.c ext/pdo_pgsql/pgsql_sql_parser.re
|
|
@ -79,6 +79,7 @@ if test "$PHP_PDO_PGSQL" != "no"; then
|
||||||
|
|
||||||
PHP_CHECK_PDO_INCLUDES
|
PHP_CHECK_PDO_INCLUDES
|
||||||
|
|
||||||
PHP_NEW_EXTENSION(pdo_pgsql, pdo_pgsql.c pgsql_driver.c pgsql_statement.c, $ext_shared)
|
PHP_NEW_EXTENSION(pdo_pgsql, pdo_pgsql.c pgsql_driver.c pgsql_statement.c pgsql_sql_parser.c, $ext_shared)
|
||||||
PHP_ADD_EXTENSION_DEP(pdo_pgsql, pdo)
|
PHP_ADD_EXTENSION_DEP(pdo_pgsql, pdo)
|
||||||
|
PHP_ADD_MAKEFILE_FRAGMENT
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -5,7 +5,7 @@ ARG_WITH("pdo-pgsql", "PostgreSQL support for PDO", "no");
|
||||||
if (PHP_PDO_PGSQL != "no") {
|
if (PHP_PDO_PGSQL != "no") {
|
||||||
if (CHECK_LIB("libpq.lib", "pdo_pgsql", PHP_PDO_PGSQL) &&
|
if (CHECK_LIB("libpq.lib", "pdo_pgsql", PHP_PDO_PGSQL) &&
|
||||||
CHECK_HEADER_ADD_INCLUDE("libpq-fe.h", "CFLAGS_PDO_PGSQL", PHP_PDO_PGSQL + "\\include;" + PHP_PHP_BUILD + "\\include\\pgsql;" + PHP_PHP_BUILD + "\\include\\libpq;")) {
|
CHECK_HEADER_ADD_INCLUDE("libpq-fe.h", "CFLAGS_PDO_PGSQL", PHP_PDO_PGSQL + "\\include;" + PHP_PHP_BUILD + "\\include\\pgsql;" + PHP_PHP_BUILD + "\\include\\libpq;")) {
|
||||||
EXTENSION("pdo_pgsql", "pdo_pgsql.c pgsql_driver.c pgsql_statement.c");
|
EXTENSION("pdo_pgsql", "pdo_pgsql.c pgsql_driver.c pgsql_statement.c pgsql_sql_parser.c");
|
||||||
|
|
||||||
if (X64) {
|
if (X64) {
|
||||||
ADD_FLAG('CFLAGS_PDO_PGSQL', "/D HAVE_PG_LO64=1");
|
ADD_FLAG('CFLAGS_PDO_PGSQL', "/D HAVE_PG_LO64=1");
|
||||||
|
@ -14,6 +14,7 @@ if (PHP_PDO_PGSQL != "no") {
|
||||||
AC_DEFINE('HAVE_PDO_PGSQL', 1, 'Have PostgreSQL library');
|
AC_DEFINE('HAVE_PDO_PGSQL', 1, 'Have PostgreSQL library');
|
||||||
|
|
||||||
ADD_EXTENSION_DEP('pdo_pgsql', 'pdo');
|
ADD_EXTENSION_DEP('pdo_pgsql', 'pdo');
|
||||||
|
ADD_MAKEFILE_FRAGMENT();
|
||||||
} else {
|
} else {
|
||||||
WARNING("pdo_pgsql not enabled; libraries and headers not found");
|
WARNING("pdo_pgsql not enabled; libraries and headers not found");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1321,7 +1321,8 @@ static const struct pdo_dbh_methods pgsql_methods = {
|
||||||
pdo_pgsql_get_driver_methods, /* get_driver_methods */
|
pdo_pgsql_get_driver_methods, /* get_driver_methods */
|
||||||
NULL,
|
NULL,
|
||||||
pgsql_handle_in_transaction,
|
pgsql_handle_in_transaction,
|
||||||
NULL /* get_gc */
|
NULL, /* get_gc */
|
||||||
|
pdo_pgsql_scanner
|
||||||
};
|
};
|
||||||
|
|
||||||
static int pdo_pgsql_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* {{{ */
|
static int pdo_pgsql_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* {{{ */
|
||||||
|
|
49
ext/pdo_pgsql/pgsql_sql_parser.re
Normal file
49
ext/pdo_pgsql/pgsql_sql_parser.re
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
+----------------------------------------------------------------------+
|
||||||
|
| Copyright (c) The PHP Group |
|
||||||
|
+----------------------------------------------------------------------+
|
||||||
|
| This source file is subject to version 3.01 of the PHP license, |
|
||||||
|
| that is bundled with this package in the file LICENSE, and is |
|
||||||
|
| available through the world-wide-web at the following url: |
|
||||||
|
| http://www.php.net/license/3_01.txt |
|
||||||
|
| If you did not receive a copy of the PHP license and are unable to |
|
||||||
|
| obtain it through the world-wide-web, please send a note to |
|
||||||
|
| license@php.net so we can mail you a copy immediately. |
|
||||||
|
+----------------------------------------------------------------------+
|
||||||
|
| Author: Matteo Beccati <mbeccati@php.net> |
|
||||||
|
+----------------------------------------------------------------------+
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "php.h"
|
||||||
|
#include "ext/pdo/php_pdo_driver.h"
|
||||||
|
#include "ext/pdo/php_pdo_int.h"
|
||||||
|
#include "ext/pdo/pdo_sql_parser.h"
|
||||||
|
|
||||||
|
int pdo_pgsql_scanner(pdo_scanner_t *s)
|
||||||
|
{
|
||||||
|
const char *cursor = s->cur;
|
||||||
|
|
||||||
|
s->tok = cursor;
|
||||||
|
/*!re2c
|
||||||
|
BINDCHR = [:][a-zA-Z0-9_]+;
|
||||||
|
QUESTION = [?];
|
||||||
|
ESCQUESTION = [?][?];
|
||||||
|
COMMENTS = ("/*"([^*]+|[*]+[^/*])*[*]*"*/"|"--"[^\r\n]*);
|
||||||
|
SPECIALS = [:?"'/-];
|
||||||
|
MULTICHAR = [:]{2,};
|
||||||
|
ANYNOEOF = [\001-\377];
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!re2c
|
||||||
|
(["]((["]["])|ANYNOEOF\["])*["]) { RET(PDO_PARSER_TEXT); }
|
||||||
|
(['](([']['])|ANYNOEOF\['])*[']) { RET(PDO_PARSER_TEXT); }
|
||||||
|
MULTICHAR { RET(PDO_PARSER_TEXT); }
|
||||||
|
ESCQUESTION { RET(PDO_PARSER_ESCAPED_QUESTION); }
|
||||||
|
BINDCHR { RET(PDO_PARSER_BIND); }
|
||||||
|
QUESTION { RET(PDO_PARSER_BIND_POS); }
|
||||||
|
SPECIALS { SKIP_ONE(PDO_PARSER_TEXT); }
|
||||||
|
COMMENTS { RET(PDO_PARSER_TEXT); }
|
||||||
|
(ANYNOEOF\SPECIALS)+ { RET(PDO_PARSER_TEXT); }
|
||||||
|
*/
|
||||||
|
}
|
|
@ -74,6 +74,8 @@ typedef struct {
|
||||||
|
|
||||||
extern const pdo_driver_t pdo_pgsql_driver;
|
extern const pdo_driver_t pdo_pgsql_driver;
|
||||||
|
|
||||||
|
extern int pdo_pgsql_scanner(pdo_scanner_t *s);
|
||||||
|
|
||||||
extern int _pdo_pgsql_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, int errcode, const char *sqlstate, const char *msg, const char *file, int line);
|
extern int _pdo_pgsql_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, int errcode, const char *sqlstate, const char *msg, const char *file, int line);
|
||||||
#define pdo_pgsql_error(d,e,z) _pdo_pgsql_error(d, NULL, e, z, NULL, __FILE__, __LINE__)
|
#define pdo_pgsql_error(d,e,z) _pdo_pgsql_error(d, NULL, e, z, NULL, __FILE__, __LINE__)
|
||||||
#define pdo_pgsql_error_msg(d,e,m) _pdo_pgsql_error(d, NULL, e, NULL, m, __FILE__, __LINE__)
|
#define pdo_pgsql_error_msg(d,e,m) _pdo_pgsql_error(d, NULL, e, NULL, m, __FILE__, __LINE__)
|
||||||
|
|
7
ext/pdo_sqlite/Makefile.frag
Normal file
7
ext/pdo_sqlite/Makefile.frag
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
$(srcdir)/sqlite_sql_parser.c: $(srcdir)/sqlite_sql_parser.re
|
||||||
|
@(cd $(top_srcdir); \
|
||||||
|
if test -f ./sqlite_sql_parser.re; then \
|
||||||
|
$(RE2C) $(RE2C_FLAGS) --no-generation-date -o sqlite_sql_parser.c sqlite_sql_parser.re; \
|
||||||
|
else \
|
||||||
|
$(RE2C) $(RE2C_FLAGS) --no-generation-date -o ext/pdo_sqlite/sqlite_sql_parser.c ext/pdo_sqlite/sqlite_sql_parser.re; \
|
||||||
|
fi)
|
3
ext/pdo_sqlite/Makefile.frag.w32
Normal file
3
ext/pdo_sqlite/Makefile.frag.w32
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
ext\pdo_sqlite\sqlite_sql_parser.c: ext\pdo_sqlite\sqlite_sql_parser.re
|
||||||
|
cd $(PHP_SRC_DIR)
|
||||||
|
$(RE2C) $(RE2C_FLAGS) --no-generation-date -o ext/pdo_sqlite/sqlite_sql_parser.c ext/pdo_sqlite/sqlite_sql_parser.re
|
|
@ -29,8 +29,9 @@ if test "$PHP_PDO_SQLITE" != "no"; then
|
||||||
)
|
)
|
||||||
|
|
||||||
PHP_SUBST(PDO_SQLITE_SHARED_LIBADD)
|
PHP_SUBST(PDO_SQLITE_SHARED_LIBADD)
|
||||||
PHP_NEW_EXTENSION(pdo_sqlite, pdo_sqlite.c sqlite_driver.c sqlite_statement.c,
|
PHP_NEW_EXTENSION(pdo_sqlite, pdo_sqlite.c sqlite_driver.c sqlite_statement.c sqlite_sql_parser.c,
|
||||||
$ext_shared)
|
$ext_shared)
|
||||||
|
|
||||||
PHP_ADD_EXTENSION_DEP(pdo_sqlite, pdo)
|
PHP_ADD_EXTENSION_DEP(pdo_sqlite, pdo)
|
||||||
|
PHP_ADD_MAKEFILE_FRAGMENT
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -4,11 +4,12 @@ ARG_WITH("pdo-sqlite", "for pdo_sqlite support", "no");
|
||||||
|
|
||||||
if (PHP_PDO_SQLITE != "no") {
|
if (PHP_PDO_SQLITE != "no") {
|
||||||
if (SETUP_SQLITE3("pdo_sqlite", PHP_PDO_SQLITE, PHP_PDO_SQLITE_SHARED)) {
|
if (SETUP_SQLITE3("pdo_sqlite", PHP_PDO_SQLITE, PHP_PDO_SQLITE_SHARED)) {
|
||||||
EXTENSION("pdo_sqlite", "pdo_sqlite.c sqlite_driver.c sqlite_statement.c");
|
EXTENSION("pdo_sqlite", "pdo_sqlite.c sqlite_driver.c sqlite_statement.c sqlite_sql_parser.c");
|
||||||
|
|
||||||
ADD_EXTENSION_DEP('pdo_sqlite', 'pdo');
|
ADD_EXTENSION_DEP('pdo_sqlite', 'pdo');
|
||||||
AC_DEFINE("HAVE_SQLITE3_COLUMN_TABLE_NAME", 1, "have sqlite3_column_table_name");
|
AC_DEFINE("HAVE_SQLITE3_COLUMN_TABLE_NAME", 1, "have sqlite3_column_table_name");
|
||||||
AC_DEFINE("HAVE_SQLITE3_CLOSE_V2", 1, "have sqlite3_close_v2");
|
AC_DEFINE("HAVE_SQLITE3_CLOSE_V2", 1, "have sqlite3_close_v2");
|
||||||
|
ADD_MAKEFILE_FRAGMENT();
|
||||||
} else {
|
} else {
|
||||||
WARNING("pdo_sqlite not enabled; libraries and/or headers not found");
|
WARNING("pdo_sqlite not enabled; libraries and/or headers not found");
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,6 +61,8 @@ typedef struct {
|
||||||
|
|
||||||
extern const pdo_driver_t pdo_sqlite_driver;
|
extern const pdo_driver_t pdo_sqlite_driver;
|
||||||
|
|
||||||
|
extern int pdo_sqlite_scanner(pdo_scanner_t *s);
|
||||||
|
|
||||||
extern int _pdo_sqlite_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, const char *file, int line);
|
extern int _pdo_sqlite_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, const char *file, int line);
|
||||||
#define pdo_sqlite_error(s) _pdo_sqlite_error(s, NULL, __FILE__, __LINE__)
|
#define pdo_sqlite_error(s) _pdo_sqlite_error(s, NULL, __FILE__, __LINE__)
|
||||||
#define pdo_sqlite_error_stmt(s) _pdo_sqlite_error(stmt->dbh, stmt, __FILE__, __LINE__)
|
#define pdo_sqlite_error_stmt(s) _pdo_sqlite_error(stmt->dbh, stmt, __FILE__, __LINE__)
|
||||||
|
|
|
@ -743,7 +743,8 @@ static const struct pdo_dbh_methods sqlite_methods = {
|
||||||
get_driver_methods,
|
get_driver_methods,
|
||||||
pdo_sqlite_request_shutdown,
|
pdo_sqlite_request_shutdown,
|
||||||
pdo_sqlite_in_transaction,
|
pdo_sqlite_in_transaction,
|
||||||
pdo_sqlite_get_gc
|
pdo_sqlite_get_gc,
|
||||||
|
pdo_sqlite_scanner
|
||||||
};
|
};
|
||||||
|
|
||||||
static char *make_filename_safe(const char *filename)
|
static char *make_filename_safe(const char *filename)
|
||||||
|
|
48
ext/pdo_sqlite/sqlite_sql_parser.re
Normal file
48
ext/pdo_sqlite/sqlite_sql_parser.re
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
+----------------------------------------------------------------------+
|
||||||
|
| Copyright (c) The PHP Group |
|
||||||
|
+----------------------------------------------------------------------+
|
||||||
|
| This source file is subject to version 3.01 of the PHP license, |
|
||||||
|
| that is bundled with this package in the file LICENSE, and is |
|
||||||
|
| available through the world-wide-web at the following url: |
|
||||||
|
| https://www.php.net/license/3_01.txt |
|
||||||
|
| If you did not receive a copy of the PHP license and are unable to |
|
||||||
|
| obtain it through the world-wide-web, please send a note to |
|
||||||
|
| license@php.net so we can mail you a copy immediately. |
|
||||||
|
+----------------------------------------------------------------------+
|
||||||
|
| Author: Matteo Beccati <mbeccati@php.net> |
|
||||||
|
+----------------------------------------------------------------------+
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "php.h"
|
||||||
|
#include "ext/pdo/php_pdo_driver.h"
|
||||||
|
#include "ext/pdo/php_pdo_int.h"
|
||||||
|
#include "ext/pdo/pdo_sql_parser.h"
|
||||||
|
|
||||||
|
int pdo_sqlite_scanner(pdo_scanner_t *s)
|
||||||
|
{
|
||||||
|
const char *cursor = s->cur;
|
||||||
|
|
||||||
|
s->tok = cursor;
|
||||||
|
/*!re2c
|
||||||
|
BINDCHR = [:][a-zA-Z0-9_]+;
|
||||||
|
QUESTION = [?];
|
||||||
|
COMMENTS = ("/*"([^*]+|[*]+[^/*])*[*]*"*/"|"--"[^\r\n]*);
|
||||||
|
SPECIALS = [:?"'`/-];
|
||||||
|
MULTICHAR = ([:]{2,}|[?]{2,});
|
||||||
|
ANYNOEOF = [\001-\377];
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!re2c
|
||||||
|
(["]((["]["])|ANYNOEOF)*["]) { RET(PDO_PARSER_TEXT); }
|
||||||
|
(['](([']['])|ANYNOEOF)*[']) { RET(PDO_PARSER_TEXT); }
|
||||||
|
([`](([`][`])|ANYNOEOF)*[`]) { RET(PDO_PARSER_TEXT); }
|
||||||
|
MULTICHAR { RET(PDO_PARSER_TEXT); }
|
||||||
|
BINDCHR { RET(PDO_PARSER_BIND); }
|
||||||
|
QUESTION { RET(PDO_PARSER_BIND_POS); }
|
||||||
|
SPECIALS { SKIP_ONE(PDO_PARSER_TEXT); }
|
||||||
|
COMMENTS { RET(PDO_PARSER_TEXT); }
|
||||||
|
(ANYNOEOF\SPECIALS)+ { RET(PDO_PARSER_TEXT); }
|
||||||
|
*/
|
||||||
|
}
|
58
ext/pdo_sqlite/tests/pdo_sqlite_parser.phpt
Normal file
58
ext/pdo_sqlite/tests/pdo_sqlite_parser.phpt
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
--TEST--
|
||||||
|
PDO_sqlite: Parser custom syntax
|
||||||
|
--EXTENSIONS--
|
||||||
|
pdo_sqlite
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$filename = __DIR__ . DIRECTORY_SEPARATOR . "pdo_sqlite_parser.db";
|
||||||
|
|
||||||
|
// Default open flag is read-write|create
|
||||||
|
$db = new PDO('sqlite:' . $filename, null, null, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
|
||||||
|
|
||||||
|
$table = 'pdo_sqlite_parser';
|
||||||
|
|
||||||
|
$db->exec("CREATE TABLE {$table} (`a``?` int NOT NULL)");
|
||||||
|
$db->exec("INSERT INTO {$table} VALUES (1)");
|
||||||
|
|
||||||
|
// No parameters
|
||||||
|
$queries = [
|
||||||
|
"SELECT * FROM {$table}",
|
||||||
|
"SELECT * FROM {$table} -- ?",
|
||||||
|
"SELECT * FROM {$table} /* ? */",
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($queries as $k => $query) {
|
||||||
|
$stmt = $db->prepare($query);
|
||||||
|
$stmt->execute();
|
||||||
|
var_dump($stmt->fetch(PDO::FETCH_NUM) === [0 => 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// One parameter
|
||||||
|
$queries = [
|
||||||
|
"SELECT * FROM {$table} WHERE '1' = ?",
|
||||||
|
"SELECT * FROM {$table} WHERE \"?\" IN (?, '?')",
|
||||||
|
"SELECT * FROM {$table} WHERE `a``?` = ?",
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($queries as $k => $query) {
|
||||||
|
$stmt = $db->prepare($query);
|
||||||
|
$stmt->execute([1]);
|
||||||
|
var_dump($stmt->fetch(PDO::FETCH_NUM) === [0 => 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
--CLEAN--
|
||||||
|
<?php
|
||||||
|
$filename = __DIR__ . DIRECTORY_SEPARATOR . "pdo_sqlite_parser.db";
|
||||||
|
if (file_exists($filename)) {
|
||||||
|
unlink($filename);
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
bool(true)
|
||||||
|
bool(true)
|
||||||
|
bool(true)
|
||||||
|
bool(true)
|
||||||
|
bool(true)
|
||||||
|
bool(true)
|
|
@ -125,6 +125,21 @@ $MAKE RE2C="$RE2C" RE2C_FLAGS="$RE2C_FLAGS" srcdir=ext/pdo builddir=ext/pdo top_
|
||||||
-f ext/pdo/Makefile.frag \
|
-f ext/pdo/Makefile.frag \
|
||||||
ext/pdo/pdo_sql_parser.c
|
ext/pdo/pdo_sql_parser.c
|
||||||
|
|
||||||
|
echo "genfiles: Generating PDO_mysql lexer file"
|
||||||
|
$MAKE RE2C="$RE2C" RE2C_FLAGS="$RE2C_FLAGS" srcdir=ext/pdo_mysql builddir=ext/pdo_mysql top_srcdir=. \
|
||||||
|
-f ext/pdo_mysql/Makefile.frag \
|
||||||
|
ext/pdo_mysql/mysql_sql_parser.c
|
||||||
|
|
||||||
|
echo "genfiles: Generating PDO_pgsql lexer file"
|
||||||
|
$MAKE RE2C="$RE2C" RE2C_FLAGS="$RE2C_FLAGS" srcdir=ext/pdo_pgsql builddir=ext/pdo_pgsql top_srcdir=. \
|
||||||
|
-f ext/pdo_pgsql/Makefile.frag \
|
||||||
|
ext/pdo_pgsql/pgsql_sql_parser.c
|
||||||
|
|
||||||
|
echo "genfiles: Generating PDO_sqlite lexer file"
|
||||||
|
$MAKE RE2C="$RE2C" RE2C_FLAGS="$RE2C_FLAGS" srcdir=ext/pdo_sqlite builddir=ext/pdo_sqlite top_srcdir=. \
|
||||||
|
-f ext/pdo_sqlite/Makefile.frag \
|
||||||
|
ext/pdo_sqlite/sqlite_sql_parser.c
|
||||||
|
|
||||||
echo "genfiles: Generating standard extension lexer files"
|
echo "genfiles: Generating standard extension lexer files"
|
||||||
$MAKE RE2C="$RE2C" RE2C_FLAGS="$RE2C_FLAGS" srcdir=ext/standard builddir=ext/standard top_srcdir=. \
|
$MAKE RE2C="$RE2C" RE2C_FLAGS="$RE2C_FLAGS" srcdir=ext/standard builddir=ext/standard top_srcdir=. \
|
||||||
-f ext/standard/Makefile.frag \
|
-f ext/standard/Makefile.frag \
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue