Compare commits

..

11 Commits

Author SHA1 Message Date
Clemens Schwaighofer
ba11a936db DB IO remove debug placeholder output 2024-12-11 10:36:31 +09:00
Clemens Schwaighofer
5343034768 Fix DB IO placeholder detect and count regex
comment regex: (?:\-\-[^\r\n]*?\r?\n)*

Which is AFTER the element search as the comment can appear anywhere after the tag trigger
2024-12-11 10:30:41 +09:00
Clemens Schwaighofer
880f15ac6f Merge branch 'development' 2024-12-10 15:26:24 +09:00
Clemens Schwaighofer
a46601fe03 Sync folder is master and not trunk 2024-12-10 15:25:17 +09:00
Clemens Schwaighofer
022c39e791 Add missing phpunit test folder for deprecated session var load test 2024-12-10 15:24:45 +09:00
Clemens Schwaighofer
a7742bd5c8 DB IO count params fix for comments 2024-12-10 13:36:57 +09:00
Clemens Schwaighofer
78591d6ba4 Fix Param regex lookup
Query was not counting params after "--" comment strings
2024-12-10 12:01:06 +09:00
Clemens Schwaighofer
98bf3a40cd Add logout button to class.test.php for logout test, ANY placeholder db test 2024-12-06 14:54:09 +09:00
Clemens Schwaighofer
cbd47fb015 edit log table update, Change all DB tests serial to identity for primary key 2024-12-05 14:59:49 +09:00
Clemens Schwaighofer
5f89917abd Add composer keywords 2024-12-05 14:30:12 +09:00
Clemens Schwaighofer
eeaff3042e phpstan config file update with phpVersion information 2024-12-05 14:16:57 +09:00
11 changed files with 250 additions and 56 deletions

View File

@@ -13,7 +13,7 @@ if [ "${GO}" != "go" ]; then
fi;
BASE="/storage/var/www/html/developers/clemens/core_data/";
SOURCE="${BASE}php_libraries/trunk/"
SOURCE="${BASE}php_libraries/master/"
TARGET="${BASE}composer-packages/CoreLibs-Composer-All/"
rsync ${DRY_RUN}-Plzvrupt --stats --delete ${SOURCE}4dev/tests/ ${TARGET}test/phpunit/

View File

@@ -10,10 +10,10 @@ CREATE TABLE edit_log (
edit_log_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
euid INT, -- this is a foreign key, but I don't nedd to reference to it
FOREIGN KEY (euid) REFERENCES edit_user (edit_user_id) MATCH FULL ON UPDATE CASCADE ON DELETE SET NULL,
username VARCHAR,
password VARCHAR,
ecuid VARCHAR,
ecuuid UUID,
username VARCHAR,
password VARCHAR,
event_date TIMESTAMP WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP,
ip VARCHAR,
error TEXT,

View File

@@ -321,7 +321,7 @@ CREATE TABLE edit_generic (
-- DROP TABLE edit_visible_group;
CREATE TABLE edit_visible_group (
edit_visible_group_id SERIAL PRIMARY KEY,
edit_visible_group_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
name VARCHAR,
flag VARCHAR
) INHERITS (edit_generic) WITHOUT OIDS;
@@ -336,7 +336,7 @@ CREATE TABLE edit_visible_group (
-- DROP TABLE edit_menu_group;
CREATE TABLE edit_menu_group (
edit_menu_group_id SERIAL PRIMARY KEY,
edit_menu_group_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
name VARCHAR,
flag VARCHAR,
order_number INT NOT NULL
@@ -354,7 +354,7 @@ CREATE TABLE edit_menu_group (
-- DROP TABLE edit_page;
CREATE TABLE edit_page (
edit_page_id SERIAL PRIMARY KEY,
edit_page_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
content_alias_edit_page_id INT, -- alias for page content, if the page content is defined on a different page, ege for ajax backend pages
FOREIGN KEY (content_alias_edit_page_id) REFERENCES edit_page (edit_page_id) MATCH FULL ON DELETE RESTRICT ON UPDATE CASCADE,
filename VARCHAR,
@@ -378,7 +378,7 @@ CREATE TABLE edit_page (
-- DROP TABLE edit_query_string;
CREATE TABLE edit_query_string (
edit_query_string_id SERIAL PRIMARY KEY,
edit_query_string_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
edit_page_id INT NOT NULL,
FOREIGN KEY (edit_page_id) REFERENCES edit_page (edit_page_id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE,
enabled SMALLINT NOT NULL DEFAULT 0,
@@ -430,7 +430,7 @@ CREATE TABLE edit_page_menu_group (
-- DROP TABLE edit_access_right;
CREATE TABLE edit_access_right (
edit_access_right_id SERIAL PRIMARY KEY,
edit_access_right_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
name VARCHAR,
level SMALLINT,
type VARCHAR,
@@ -447,7 +447,7 @@ CREATE TABLE edit_access_right (
-- DROP TABLE edit_scheme;
CREATE TABLE edit_scheme (
edit_scheme_id SERIAL PRIMARY KEY,
edit_scheme_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
enabled SMALLINT NOT NULL DEFAULT 0,
name VARCHAR,
header_color VARCHAR,
@@ -466,7 +466,7 @@ CREATE TABLE edit_scheme (
-- DROP TABLE edit_language;
CREATE TABLE edit_language (
edit_language_id SERIAL PRIMARY KEY,
edit_language_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
enabled SMALLINT NOT NULL DEFAULT 0,
lang_default SMALLINT NOT NULL DEFAULT 0,
long_name VARCHAR,
@@ -485,7 +485,7 @@ CREATE TABLE edit_language (
-- DROP TABLE edit_group;
CREATE TABLE edit_group (
edit_group_id SERIAL PRIMARY KEY,
edit_group_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
edit_scheme_id INT,
FOREIGN KEY (edit_scheme_id) REFERENCES edit_scheme (edit_scheme_id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE,
edit_access_right_id INT NOT NULL,
@@ -507,7 +507,7 @@ CREATE TABLE edit_group (
-- DROP TABLE edit_page_access;
CREATE TABLE edit_page_access (
edit_page_access_id SERIAL PRIMARY KEY,
edit_page_access_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
edit_group_id INT NOT NULL,
FOREIGN KEY (edit_group_id) REFERENCES edit_group (edit_group_id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE,
edit_page_id INT NOT NULL,
@@ -530,7 +530,7 @@ CREATE TABLE edit_page_access (
-- DROP TABLE edit_page_content;
CREATE TABLE edit_page_content (
edit_page_content_id SERIAL PRIMARY KEY,
edit_page_content_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
edit_page_id INT NOT NULL,
FOREIGN KEY (edit_page_id) REFERENCES edit_page (edit_page_id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE,
edit_access_right_id INT NOT NULL,
@@ -551,7 +551,7 @@ CREATE TABLE edit_page_content (
-- DROP TABLE edit_user;
CREATE TABLE edit_user (
edit_user_id SERIAL PRIMARY KEY,
edit_user_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
connect_edit_user_id INT, -- possible reference to other user
FOREIGN KEY (connect_edit_user_id) REFERENCES edit_user (edit_user_id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE,
edit_language_id INT NOT NULL,
@@ -652,11 +652,11 @@ COMMENT ON COLUMN edit_user.additional_acl IS 'Additional Access Control List st
-- DROP TABLE edit_log;
CREATE TABLE edit_log (
edit_log_id SERIAL PRIMARY KEY,
edit_log_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
euid INT, -- this is a foreign key, but I don't nedd to reference to it
FOREIGN KEY (euid) REFERENCES edit_user (edit_user_id) MATCH FULL ON UPDATE CASCADE ON DELETE SET NULL,
ecuid VARCHAR,
ecuuid UUID,
FOREIGN KEY (euid) REFERENCES edit_user (edit_user_id) MATCH FULL ON UPDATE CASCADE ON DELETE SET NULL,
username VARCHAR,
password VARCHAR,
event_date TIMESTAMP WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP,
@@ -712,7 +712,7 @@ ALTER TABLE edit_log_overflow ADD CONSTRAINT edit_log_overflow_euid_fkey FOREIGN
-- DROP TABLE edit_access;
CREATE TABLE edit_access (
edit_access_id SERIAL PRIMARY KEY,
edit_access_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
enabled SMALLINT NOT NULL DEFAULT 0,
protected SMALLINT DEFAULT 0,
deleted SMALLINT DEFAULT 0,
@@ -733,7 +733,7 @@ CREATE TABLE edit_access (
-- DROP TABLE edit_access_user;
CREATE TABLE edit_access_user (
edit_access_user_id SERIAL PRIMARY KEY,
edit_access_user_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
edit_access_id INT NOT NULL,
FOREIGN KEY (edit_access_id) REFERENCES edit_access (edit_access_id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE,
edit_user_id INT NOT NULL,
@@ -754,7 +754,7 @@ CREATE TABLE edit_access_user (
-- DROP TABLE edit_access_data;
CREATE TABLE edit_access_data (
edit_access_data_id SERIAL PRIMARY KEY,
edit_access_data_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
edit_access_id INT NOT NULL,
FOREIGN KEY (edit_access_id) REFERENCES edit_access (edit_access_id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE,
enabled SMALLINT NOT NULL DEFAULT 0,

View File

@@ -17,7 +17,7 @@ Table with Primary Key: table_with_primary_key
Table without Primary Key: table_without_primary_key
Table with primary key has additional row:
row_primary_key SERIAL PRIMARY KEY,
row_primary_key INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
Each table has the following rows
row_int INT,
row_numeric NUMERIC,
@@ -160,7 +160,6 @@ final class CoreLibsDBIOTest extends TestCase
// create the tables
$db->dbExec(
// primary key name is table + '_id'
// table_with_primary_key_id SERIAL PRIMARY KEY,
<<<SQL
CREATE TABLE table_with_primary_key (
table_with_primary_key_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
@@ -5136,6 +5135,67 @@ final class CoreLibsDBIOTest extends TestCase
SQL,
'count' => 6,
'convert' => false,
],
'comments in insert' => [
'query' => <<<SQL
INSERT INTO table_with_primary_key (
row_int, row_numeric, row_varchar, row_varchar_literal
) VALUES (
-- comment 1 かな
$1, $2,
-- comment 2 -
$3
-- comment 3
, $4
)
SQL,
'count' => 4,
'convert' => false
],
'comment in update' => [
'query' => <<<SQL
UPDATE table_with_primary_key SET
row_int =
-- COMMENT 1
$1,
row_numeric =
$2 -- COMMENT 2
,
row_varchar -- COMMENT 3
= $3
WHERE
row_varchar = $4
SQL,
'count' => 4,
'convert' => false,
],
// Note some are not set
'a complete set of possible' => [
'query' => <<<SQL
UPDATE table_with_primary_key SET
-- ROW
row_varchar = $1
WHERE
row_varchar = ANY($2) AND row_varchar <> $3
AND row_varchar > $4 AND row_varchar < $5
AND row_varchar >= $6 AND row_varchar <=$7
AND row_jsonb->'a' = $8 AND row_jsonb->>$9 = 'a'
AND row_jsonb<@$10 AND row_jsonb@>$11
AND row_varchar ^@ $12
SQL,
'count' => 12,
'convert' => false,
],
// all the same
'all the same numbered' => [
'query' => <<<SQL
UPDATE table_with_primary_key SET
row_int = $1::INT, row_numeric = $1::NUMERIC, row_varchar = $1
WHERE
row_varchar = $1
SQL,
'count' => 1,
'convert' => false,
]
];
}

View File

@@ -0,0 +1,2 @@
*
!.gitignore

View File

@@ -2,6 +2,7 @@
"name": "egrajp/development-corelibs-dev",
"version": "dev-master",
"description": "CoreLibs: Development package",
"keywords": ["corelib", "logging", "database", "templating", "tools"],
"type": "library",
"require": {
"php": ">=8.3"

View File

@@ -14,6 +14,9 @@ parameters:
# allRules: false
checkMissingCallableSignature: true
treatPhpDocTypesAsCertain: false
# phpVersion:
# min: 80200 # PHP 8.2.0
# max: 80300 # PHP latest
paths:
- %currentWorkingDirectory%/www
bootstrapFiles:

View File

@@ -28,7 +28,6 @@ $log = new CoreLibs\Logging\Logging([
'log_per_date' => true,
]);
$PAGE_NAME = 'TEST CLASS: DB CONVERT PLACEHOLDER';
print "<!DOCTYPE html>";
print "<html><head><title>" . $PAGE_NAME . "</title></head>";

View File

@@ -53,6 +53,9 @@ if (($dbh = $db->dbGetDbh()) instanceof \PgSql\Connection) {
} else {
print "NO DB HANDLER<br>";
}
// REGEX for placeholder count
print "Placeholder regex: <pre>" . CoreLibs\DB\Support\ConvertPlaceholder::REGEX_LOOKUP_PLACEHOLDERS . "</pre>";
// turn on debug replace for placeholders
$db->dbSetDebugReplacePlaceholder(true);
@@ -62,59 +65,115 @@ $db->dbExec("TRUNCATE test_foo");
$uniqid = \CoreLibs\Create\Uids::uniqIdShort();
$binary_data = $db->dbEscapeBytea(file_get_contents('class_test.db.php') ?: '');
$query_params = [
$uniqid,
true,
'STRING A',
2,
2.5,
1,
date('H:m:s'),
date('Y-m-d H:i:s'),
json_encode(['a' => 'string', 'b' => 1, 'c' => 1.5, 'f' => true, 'g' => ['a', 1, 1.5]]),
null,
'{"a", "b"}',
'{1,2}',
'{"(array Text A, 5, 8.8)","(array Text B, 10, 15.2)"}',
'("Text", 4, 6.3)',
$binary_data
$uniqid, // test
true, // some_bool
'STRING A', // string_a
2, // number_a
2.5, // numeric_a
1, // smallint
date('H:m:s'), // some_internval
date('Y-m-d H:i:s'), // some_timestamp
json_encode(['a' => 'string', 'b' => 1, 'c' => 1.5, 'f' => true, 'g' => ['a', 1, 1.5]]), // json_string
null, // null_var
'{"a", "b"}', // array_char_1
'{1,2}', // array_int_1
'{"(array Text A, 5, 8.8)","(array Text B, 10, 15.2)"}', // array_composite
'("Text", 4, 6.3)', // composite_item
$binary_data, // some_binary
date('Y-m-d'), // some_date
date('H:i:s'), // some_time
'{"c", "d", "e"}', // array_char_2
'{3,4,5}', // array_int_2
12345667778818, // bigint
1.56, // numbrer_real
3.75, // number_double
124.5, // numeric_3
\CoreLibs\Create\Uids::uuidv4() // uuid_var
];
$query_insert = <<<SQL
INSERT INTO test_foo (
test, some_bool, string_a, number_a, number_a_numeric, smallint_a,
some_time, some_timestamp, json_string, null_var,
-- row 1
test, some_bool, string_a, number_a, numeric_a, smallint_a,
-- row 2
some_internval, some_timestamp, json_string, null_var,
-- row 3
array_char_1, array_int_1,
-- row 4
array_composite,
-- row 5
composite_item,
some_binary
-- row 6
some_binary,
-- row 7
some_date, some_time,
-- row 8
array_char_2, array_int_2,
-- row 9
bigint_a, number_real, number_double, numeric_3,
-- row 10
uuid_var
) VALUES (
-- row 1
$1, $2, $3, $4, $5, $6,
-- row 2
$7, $8, $9, $10,
-- row 3
$11, $12,
-- row 4
$13,
-- row 5
$14,
$15
-- row 6
$15,
-- row 7
$16, $17,
-- row 8
$18, $19,
-- row 9
$20, $21, $22, $23,
-- row 10
$24
)
RETURNING
test_foo_id,
test, some_bool, string_a, number_a, number_a_numeric, smallint_a,
some_time, some_timestamp, json_string, null_var,
test_foo_id, number_serial, identity_always, identitiy_default, default_uuid,
test, some_bool, string_a, number_a, numeric_a, smallint_a,
some_internval, some_timestamp, json_string, null_var,
array_char_1, array_int_1,
array_composite,
composite_item,
some_binary
some_binary,
some_date,
array_char_2, array_int_2,
bigint_a, number_real, number_double, numeric_3,
uuid_var
SQL;
$status = $db->dbExecParams($query_insert, $query_params);
echo "<b>*</b><br>";
echo "INSERT ALL COLUMN TYPES: "
. Support::printToString($query_params) . " |<br>"
. "QUERY: " . $db->dbGetQuery() . " |<br>"
. "QUERY: <pre>" . $db->dbGetQuery() . "</pre> |<br>"
. "PRIMARY KEY: " . Support::printToString($db->dbGetInsertPK()) . " |<br>"
. "RETURNING EXT: <pre>" . print_r($db->dbGetReturningExt(), true) . "</pre> |<br>"
. "RETURNING RETURN: <pre>" . print_r($db->dbGetReturningArray(), true) . "<pre> |<br>"
. "ERROR: " . $db->dbGetLastError(true) . "<br>";
echo "<hr>";
print "<b>ANY call</b><br>";
$query = <<<SQL
SELECT test
FROM test_foo
WHERE string_a = ANY($1)
SQL;
$query_value = '{'
. join(',', ['STRING A'])
. '}';
while (is_array($res = $db->dbReturnParams($query, [$query_value]))) {
print "Result: " . Support::prAr($res) . "<br>";
}
echo "<hr>";
// test connectors: = , <> () for query detection
// convert placeholder tests
@@ -131,6 +190,16 @@ SQL,
'params' => [],
'direction' => 'pg',
],
'numbers' => [
'query' => <<<SQL
SELECT test, string_a, number_a
FROM test_foo
WHERE
foo = $1 AND bar = $1 AND foobar = $2
SQL,
'params' => [\CoreLibs\Create\Uids::uniqIdShort(), 'string A-1', 1234],
'direction' => 'pdo',
],
'a?' => [
'query' => <<<SQL
INSERT INTO test_foo (
@@ -157,6 +226,18 @@ SQL,
],
'direction' => 'pg',
],
'select, compare $' => [
'query' => <<<SQL
SELECT string_a
FROM test_foo
WHERE
number_a >= $1 OR number_a <= $2 OR
number_a > $3 OR number_a < $4
OR number_a = $5 OR number_a <> $6
SQL,
'params' => [1, 2, 3, 4, 5, 6],
'direction' => 'pg'
]
];
$db->dbSetConvertPlaceholder(true);
@@ -169,11 +250,12 @@ foreach ($test_queries as $info => $data) {
// . "<br>";
if ($db->dbCheckQueryForSelect($query)) {
$row = $db->dbReturnRowParams($query, $params);
print "[$info] SELECT: " . Support::prAr($row) . "<br>";
print "<b>[$info]</b> SELECT: " . Support::prAr($row) . "<br>";
} else {
$db->dbExecParams($query, $params);
}
print "[$info] " . Support::printAr($db->dbGetPlaceholderConverted()) . "<br>";
print "ERROR: " . $db->dbGetLastError(true) . "<br>";
print "<b>[$info]</b> " . Support::printAr($db->dbGetPlaceholderConverted()) . "<br>";
echo "<hr>";
}
@@ -188,22 +270,29 @@ SQL,
['string A-1']
))
) {
print "RES: " . Support::prAr($res) . "<br>";
print "<b>RES</b>: " . Support::prAr($res) . "<br>";
}
print "ERROR: " . $db->dbGetLastError(true) . "<br>";
echo "<hr>";
print "CursorExt: " . Support::prAr($db->dbGetCursorExt(<<<SQL
SELECT test, string_a, number_a
FROM test_foo
WHERE string_a = ?
SQL, ['string A-1']));
echo "<hr>";
// ERROR BELOW: missing params
$res = $db->dbReturnRowParams(<<<SQL
SELECT test, string_a, number_a
FROM test_foo
WHERE string_a = $1
SQL, []);
print "PL: " . Support::PrAr($db->dbGetPlaceholderConverted()) . "<br>";
print "ERROR: " . $db->dbGetLastError(true) . "<br>";
echo "<hr>";
// ERROR BELOW: LIKE cannot have placeholder
echo "dbReturn read LIKE: <br>";
while (
is_array($res = $db->dbReturnParams(
@@ -217,6 +306,7 @@ SQL,
) {
print "RES: " . Support::prAr($res) . "<br>";
}
print "ERROR: " . $db->dbGetLastError(true) . "<br>";
print "</body></html>";
$db->log->debug('DEBUGEND', '==================================== [END]');

View File

@@ -62,15 +62,36 @@ $backend = new CoreLibs\Admin\Backend(
$backend->db->dbInfo(true);
ob_end_flush();
print "<!DOCTYPE html>";
print "<html><head><title>TEST CLASS</title></head>";
print "<body>";
print <<<HTML
<!DOCTYPE html>
<html><head>
<title>TEST CLASS</title>
<script language="JavaScript">
function loginLogout()
{
const form = document.createElement('form');
form.method = 'post';
const hiddenField = document.createElement('input');
hiddenField.type = 'hidden';
hiddenField.name = 'login_logout';
hiddenField.value = 'Logout';
form.appendChild(hiddenField);
document.body.appendChild(form);
form.submit();
}
</script>
</head>
<body>
<div style="margin: 20px 0;">
<button onclick="loginLogout();" type="button">Logout</button>
</div>
HTML;
// key: file name, value; name
$test_files = [
'class_test.db.php' => 'Class Test: DB',
'class_test.db.types.php' => 'Class Test: DB column type convert',
'class_test.db.query-placeholder.php' => 'Class Test: DB query placeholder convert',
'class_test.db.query-placeholder.php' => 'Class Test: DB placeholder queries',
'class_test.db.dbReturn.php' => 'Class Test: DB dbReturn',
'class_test.db.single.php' => 'Class Test: DB single query tests',
'class_test.db.convert-placeholder.php' => 'Class Test: DB convert placeholder',

View File

@@ -14,10 +14,24 @@ namespace CoreLibs\DB\Support;
class ConvertPlaceholder
{
/** @var string split regex */
private const PATTERN_QUERY_SPLIT = '[(<>=,?-]|->|->>|#>|#>>|@>|<@|\?\|\?\&|\|\||#-';
// NOTE for missing: range */+ are not iplemented in the regex below, but - is for now
// NOTE some combinations are allowed, but the query will fail before this
/** @var string split regex, entries before $ group */
private const PATTERN_QUERY_SPLIT =
'\?\?|' // UNKNOWN: double ??, is this to avoid something?
. '[\(,]|' // for ',' and '(' mostly in INSERT or ANY()
. '[<>=]|' // general set for <, >, = in any query with any combination
. '\^@|' // text search for start from text with ^@
. '\|\||' // concats two elements
. '&&|' // array overlap
. '\-\|\-|' // range overlap for array
. '[^-]-{1}|' // single -, used in JSON too
. '->|->>|#>|#>>|@>|<@|@@|@\?|\?{1}|\?\||\?&|#-'; //JSON searches, Array searchs, etc
/** @var string the main regex including the pattern query split */
private const PATTERN_ELEMENT = '(?:\'.*?\')?\s*(?:\?\?|' . self::PATTERN_QUERY_SPLIT . ')\s*';
private const PATTERN_ELEMENT = '(?:\'.*?\')?\s*(?:' . self::PATTERN_QUERY_SPLIT . ')\s*';
/** @var string comment regex
* anything that starts with -- and ends with a line break but any character that is not line break inbetween */
private const PATTERN_COMMENT = '(?:\-\-[^\r\n]*?\r?\n)*\s*';
/** @var string parts to ignore in the SQL */
private const PATTERN_IGNORE =
// digit -> ignore
@@ -34,6 +48,7 @@ class ConvertPlaceholder
/** @var string replace regex for named (:...) entries */
public const REGEX_REPLACE_NAMED = '/'
. '(' . self::PATTERN_ELEMENT . ')'
. self::PATTERN_COMMENT
. '('
. self::PATTERN_IGNORE
. self::PATTERN_NAMED
@@ -42,6 +57,7 @@ class ConvertPlaceholder
/** @var string replace regex for question mark (?) entries */
public const REGEX_REPLACE_QUESTION_MARK = '/'
. '(' . self::PATTERN_ELEMENT . ')'
. self::PATTERN_COMMENT
. '('
. self::PATTERN_IGNORE
. self::PATTERN_QUESTION_MARK
@@ -50,6 +66,7 @@ class ConvertPlaceholder
/** @var string replace regex for numbered ($n) entries */
public const REGEX_REPLACE_NUMBERED = '/'
. '(' . self::PATTERN_ELEMENT . ')'
. self::PATTERN_COMMENT
. '('
. self::PATTERN_IGNORE
. self::PATTERN_NUMBERED
@@ -60,6 +77,7 @@ class ConvertPlaceholder
// prefix string part, must match towards
// seperator for ( = , ? - [and json/jsonb in pg doc section 9.15]
. self::PATTERN_ELEMENT
. self::PATTERN_COMMENT
// match for replace part
. '(?:'
// ignore parts