Commit Graph

129 Commits

Author SHA1 Message Date
Matthew Bucci
a2e25163ff remove custom last_insert_ID logic 2024-02-26 23:47:53 -08:00
Matthew Bucci
2d5f178426 improve primary key detection to use first column found if no primary key found 2024-02-26 23:44:17 -08:00
Matthew Bucci
10d8047776 Merge branch 'returning-replaces-seq' into rc-3.4 2024-02-26 16:30:07 -08:00
Matthew Bucci
ed7cbf106c correct the REGEX for returning statements to account for backticks around table name 2024-02-26 16:29:49 -08:00
Matthew Bucci
cf88b4d075 formatting 2024-02-26 16:15:07 -08:00
Matthew Bucci
8d420dca52 replace calls to seq by adding a RETURNING * to all insert statements 2024-02-21 20:22:43 -08:00
Matthew Bucci
98bcd4aad0 improve performance of sequence lookup 2024-01-16 21:49:06 -08:00
Matthew Bucci
66d8a3df0e update sequence handling to support bigserial and serial types 2024-01-16 21:35:32 -08:00
mattbucci
94259e408b style fixes 2024-01-07 23:07:50 +00:00
laotoutou
1b08e302c0 bugfix: $dbname is not used in driver_pgsql.php 2023-12-31 13:32:41 +08:00
Matthew Bucci
3d164e15a6 remove the field function because it's already accounted for in the rewriter 2023-11-10 11:24:49 -08:00
Matthew Bucci
2485f31cdc Change connections to pass by reference to better emulate the mysqli driver 2023-11-10 11:11:04 -08:00
Matthew Bucci
54b4ffb4df add connect error handling 2023-11-09 23:01:26 -08:00
Matthew Bucci
31ce063e06 ignore multi query as part of flush 2023-11-09 22:51:55 -08:00
Matthew Bucci
1f3692d4f9 implement pg_ping 2023-11-09 21:28:21 -08:00
Matthew Bucci
259a58b144 remove nonexistant PG_query mode 2023-11-09 21:24:38 -08:00
Matthew Bucci
20f0d7b9e9 driver fixes 2023-11-09 20:19:02 -08:00
Matthew Bucci
eb3a4c1711 port over what exists from the old pgsql driver 2023-11-09 19:53:49 -08:00
Matthew Bucci
ed00779cf5 add connection to pg_last_error call 2023-11-07 15:32:19 -08:00
Matthew Bucci
dad1f0d264 formatting 2023-11-07 15:29:37 -08:00
Matthew Bucci
83002198b1 Polymorphic refactor + improvements to select sql rewriting 2023-10-28 02:56:41 -07:00
Matthew Bucci
a45338251e Merge branch 'postgres15-compatibility' into mb-php8-wp6-support 2023-10-28 02:54:37 -07:00
Matthew Bucci
8816e1dcaa replace incorrect constant 2023-10-28 02:50:05 -07:00
Matthew Bucci
aef2e89812 patches for postgres 15 compatibility, various warnings fixes and more 2023-10-28 02:27:14 -07:00
ycz
f2a05dddbe fix meta_value compares bug 2019-07-23 21:19:40 +00:00
Kevin Locke
06884bd732 Move pg4wp_rewrite_field out of pg4wp_rewrite
To fix "Cannot redeclare pg4wp_rewrite_field"

Signed-off-by: Kevin Locke <kevin@kevinlocke.name>
2017-09-24 15:41:21 -06:00
Kevin Locke
54042c1bcc Convert MySQL RAND() to PostgreSQL RANDOM()
These functions are compatible, with the exception that MySQL RAND()
optionally takes a seed argument.  If future queries require seed
support, a call to PostgreSQL SETSEED() can be added.

Fixes: #12

Signed-off-by: Kevin Locke <kevin@kevinlocke.name>
2017-09-24 14:18:25 -06:00
Kevin Locke
f896bb1759 Rewrite MySQL FIELD function to CASE statement
PostgreSQL does not provide an equivalent to the MySQL FIELD function.
It is possible to create such a function, although the syntax is
version-dependent (and creates a persistent database object, which so
far has not been done by this plugin).  So use a generic CASE statement.

Fixes: #12

Signed-off-by: Kevin Locke <kevin@kevinlocke.name>
2017-09-24 14:07:40 -06:00
Kevin Locke
35e0af4252 Convert HAVING without GROUP BY to WHERE
Fixes #9

Signed-off-by: Kevin Locke <kevin@kevinlocke.name>
2017-04-14 12:54:14 -06:00
Kevin Locke
6587b4085b Create MySQL-compatible field function on connect
Fixes: #8

Signed-off-by: Kevin Locke <kevin@kevinlocke.name>
2017-04-08 16:20:58 -06:00
Kevin Locke
1d2666ca1d Remove unnecessary isset() before empty()
Signed-off-by: Kevin Locke <kevin@kevinlocke.name>
2017-04-08 16:20:39 -06:00
Kevin Locke
7c4d76a0b6 Fix connection failure handling
If the connection fails, bail early.  Otherwise the processing of the
queued SQL statements will cause an infinite loop by continually pushing
the same statement into the queue due to lack of connection.

Also add a local variable for the connection for clarity and
performance.

Signed-off-by: Kevin Locke <kevin@kevinlocke.name>
2017-04-08 13:33:13 -06:00
Kevin Locke
68d8ead5ad Partially revert 650f768
Although calling wpsql_select_db from wpsql_connect did set the
connection globally, it also caused early clearing of the connection
string when WP_INSTALLING is defined and ran queued early SQL commands
before select is called by external code (which was dubious).  Revert
it, but keep using the best guess at the database name, since this often
saves a connection.

Signed-off-by: Kevin Locke <kevin@kevinlocke.name>
2016-08-22 18:21:10 -06:00
Kevin Locke
bb7c8076a0 Remove obsolete comment
Signed-off-by: Kevin Locke <kevin@kevinlocke.name>
2016-08-22 17:59:03 -06:00
Kevin Locke
650f768e69 Call wpsql_select_db from wpsql_connect
Rather than calling pg_connect directly, call wpsql_select_db with the
best guess at the database name.  This sets $GLOBALS['pg4wp_conn'] and avoids reconnecting whenever the guess is correct.

Signed-off-by: Kevin Locke <kevin@kevinlocke.name>
2016-08-22 17:58:59 -06:00
Kevin Locke
5f6e9200c0 Match wpsql_ping formatting to adjacent functions
Although I am not a big fan of the existing style, I think consistency
adds enough value to justify keeping the formatting as standardized as
possible.

Signed-off-by: Kevin Locke <kevin@kevinlocke.name>
2016-08-22 15:45:34 -06:00
David BARBION
8a80acdf6e fix caompatibility with WordPress 4.6 2016-08-17 22:35:24 +02:00
Kevin Locke
5b7e9a80ff Protect against undefined $wpdb in _rewrite
The wpdb constructor makes some queries (e.g. for SQL_MODE) which are
rewritten.  This occurs before the constructor returns and therefore
before the $wpdb global is set.  Handle this without errors.

Signed-off-by: Kevin Locke <kevin@kevinlocke.name>
2016-06-30 15:38:14 -07:00
Kevin Locke
3a5afabcae Support using integers as booleans in expressions
For MySQL compatibility, support using integers as booleans in
expressions.  This is an expensive and unreliable check, so limit it to
the cases currently observed in the wild.  We can expand the checks
later if more uses appear.

The current appearance is from the query:

SELECT SQL_CALC_FOUND_ROWS  wp_posts.ID FROM wp_posts  WHERE 1=1 AND 0
ORDER BY wp_posts.post_date DESC LIMIT 0, 10

made by require('wp-blog-header.php'), wp, WP->main, WP->query_posts,
WP_Query->query, WP_Query->get_posts

I can't determine the exact source of the calls or whether it is
URL-dependent.  But for me that is irrelevant, since it is a case that I
need to support.

Signed-off-by: Kevin Locke <kevin@kevinlocke.name>
2015-10-02 14:02:31 -07:00
Kevin Locke
33740e34e5 Replace split() with explode() for PHP 7
It appears that the split function, which has been deprecated since PHP
5.3.0, has finally been removed in PHP 7.  Since it is being used to
split on a literal string, use explode() instead.

Fixes #1

Signed-off-by: Kevin Locke <kevin@kevinlocke.name>
2015-09-22 08:40:02 -07:00
Kevin Locke
2ab93ef3a4 Log the SQL for errors in wpsql_insert_id
If the query produces an error, log the query which produced the error
in addition to the insert statement which preceded it.  This helped me
track down an issue with a mis-named sequence from a bad
MySQL->PostgreSQL migration.

Signed-off-by: Kevin Locke <kevin@kevinlocke.name>
2015-09-12 09:53:23 -07:00
Kevin Locke
b9479d4559 Fix match for string-quoted identifier
The pattern added in 785307ee only matches single-character identifiers,
but should match identifiers of any non-zero length.  Fix it.

Signed-off-by: Kevin Locke <kevin@kevinlocke.name>
2015-09-12 09:51:11 -07:00
Kevin Locke
42c63a916f [nextgen-gallery] Remove ORDER BY from DELETE where possible
MySQL supports the ORDER BY clause on DELETE statements for use with
the LIMIT clause to choose which rows are deleted.  PostgreSQL does
not support this clause, which leads to errors such as:

Error running :
DELETE FROM wp_posts  WHERE 1=1  AND wp_posts.post_type = 'display_type' AND ((wp_posts.post_status <> 'trash' AND wp_posts.post_status <> 'auto-draft'))  ORDER BY wp_posts.post_date DESC
---- converted to ----
DELETE FROM wp_posts  WHERE 1=1  AND wp_posts.post_type = 'display_type' AND ((wp_posts.post_status <> 'trash' AND wp_posts.post_status <> 'auto-draft'))  ORDER BY wp_posts.post_date DESC
----> ERROR:  syntax error at or near "ORDER"
LINE 1: ...rash' AND wp_posts.post_status <> 'auto-draft'))  ORDER BY w...

When the ORDER BY clause is specified without a LIMIT clause, as it is
in the above error, it does not have any effect that I am aware of (due
to how transactions are handled).  In these cases, we remove the ORDER
BY clause to avoid the error.

Signed-off-by: Kevin Locke <kevin@kevinlocke.name>
2015-06-06 21:48:28 -06:00
Kevin Locke
a9edb3a572 [nextgen-gallery] Check ORDER BY in SELECT DISTINCT
MySQL supports ordering by columns which do not appear in the field list
for a SELECT DISTINCT statement while PostgreSQL does not.  This results
in errors such as:

Error running :
SELECT DISTINCT pid , GROUP_CONCAT(CONCAT_WS('@@', meta_key, meta_value)) AS `extras` FROM `wp_ngg_pictures` LEFT OUTER JOIN `wp_postmeta` ON `wp_postmeta`.`post_id` = `extras_post_id`  WHERE (`exclude` = 0) AND (`galleryid` IN (2)) GROUP BY wp_ngg_pictures.pid ORDER BY `sortorder` ASC
---- converted to ----
SELECT DISTINCT pid , string_agg(CONCAT_WS('@@', meta_key, meta_value), ',') AS extras FROM wp_ngg_pictures LEFT OUTER JOIN wp_postmeta ON wp_postmeta.post_id = extras_post_id  WHERE (exclude = 0) AND (galleryid IN (2)) GROUP BY wp_ngg_pictures.pid ORDER BY sortorder ASC
----> ERROR:  for SELECT DISTINCT, ORDER BY expressions must appear in select list
LINE 1: ...yid IN (2)) GROUP BY wp_ngg_pictures.pid ORDER BY sortorder ...
                                                             ^
To avoid this error, ensure that the field listed in the ORDER BY
statement also appears in the SELECT statement.  To support GROUP BY
statements, ensure that it is aggregated using MIN() to mimic the MySQL
behavior.

Signed-off-by: Kevin Locke <kevin@kevinlocke.name>
2015-06-06 21:48:28 -06:00
Kevin Locke
c2f5a06ae6 [nextgen-gallery] Support SIGNED data type in CAST()
MySQL recognizes SIGNED and UNSIGNED in place of SIGNED INTEGER and
UNSIGNED INTEGER.  Notice this in calls to CAST() and replace it with
INTEGER (which is signed by default).

Signed-off-by: Kevin Locke <kevin@kevinlocke.name>
2015-06-06 21:48:28 -06:00
Kevin Locke
cf3f571dbf [nextgen-gallery] Support for CONVERT() in place of CAST()
MySQL provides a CONVERT function for doing data type conversion.
This currently results in errors such as:

Error running :
SELECT image_slug, SUBSTR(image_slug, 10) AS 'i' FROM wp_ngg_pictures WHERE (image_slug LIKE 'img_0601-%' AND CONVERT(SUBSTR(image_slug, 10), SIGNED) BETWEEN 1 AND 2147483647) OR image_slug = 'img_0601' ORDER BY i DESC LIMIT 1
---- converted to ----
SELECT image_slug, SUBSTR(image_slug, 10) AS "i" FROM wp_ngg_pictures WHERE (image_slug ILIKE 'img_0601-%' AND CONVERT(SUBSTR(image_slug, 10), SIGNED) BETWEEN 1 AND 2147483647) OR image_slug = 'img_0601' ORDER BY i DESC LIMIT 1
----> ERROR:  column "signed" does not exist
LINE 1: ... 'img_0601-%' AND CONVERT(SUBSTR(image_slug, 10), SIGNED) BE...

Recognize this function and replace it with CAST().

Signed-off-by: Kevin Locke <kevin@kevinlocke.name>
2015-06-06 21:48:28 -06:00
Kevin Locke
55a671b9f7 [nextgen-gallery] Convert GROUP_CONCAT() to STRING_AGG()
PostgreSQL does not support the MySQL GROUP_CONCAT() aggregation
function.  This results in errors such as:

Error running :
SELECT DISTINCT wp_ngg_gallery.* , GROUP_CONCAT(CONCAT_WS('@@', meta_key, meta_value)) AS `extras` FROM `wp_ngg_gallery` LEFT OUTER JOIN `wp_postmeta` ON `wp_postmeta`.`post_id` = `extras_post_id`  GROUP BY wp_ngg_gallery.gid ORDER BY `gid` ASC LIMIT 25
---- converted to ----
SELECT DISTINCT wp_ngg_gallery.* , GROUP_CONCAT(CONCAT_WS('@@', meta_key, meta_value)) AS extras FROM wp_ngg_gallery LEFT OUTER JOIN wp_postmeta ON wp_postmeta.post_id = extras_post_id  GROUP BY wp_ngg_gallery.gid ORDER BY gid ASC LIMIT 25
----> ERROR:  function group_concat(text) does not exist
LINE 1: SELECT DISTINCT wp_ngg_gallery.* , GROUP_CONCAT(CONCAT_WS('@...
                                           ^
HINT:  No function matches the given name and argument types. You might need to add explicit type casts.

However, PostgreSQL 9.0 and later provide the STRING_AGG() aggregation
function for the same purpose.  Therefore, replace calls to
GROUP_CONCAT() with STRING_AGG().

Signed-off-by: Kevin Locke <kevin@kevinlocke.name>
2015-06-06 21:48:28 -06:00
Kevin Locke
785307ee95 [nextgen-gallery] Fix identifiers quoted as strings
MySQL allows quoting identifiers, such as column names, as strings using
single-quotes in addition to quoting as identifiers using grave accents.
PostgreSQL does not, resulting in errors such as:

Error running :
SELECT DISTINCT wp_ngg_pictures.* , GROUP_CONCAT(CONCAT_WS('@@', meta_key, meta_value)) AS 'extras' FROM `wp_ngg_pictures` LEFT OUTER JOIN `wp_postmeta` ON `wp_postmeta`.`post_id` = `extras_post_id`  GROUP BY wp_ngg_pictures.pid LIMIT 1
---- converted to ----
SELECT DISTINCT wp_ngg_pictures.* , GROUP_CONCAT(CONCAT_WS('@@', meta_key, meta_value)) AS 'extras' FROM wp_ngg_pictures LEFT OUTER JOIN wp_postmeta ON wp_postmeta.post_id = extras_post_id  GROUP BY wp_ngg_pictures.pid LIMIT 1
----> ERROR:  syntax error at or near "'extras'"
LINE 1: ..._CONCAT(CONCAT_WS('@@', meta_key, meta_value)) AS 'extras' F...
                                                             ^

Fix this by replacing single quotes with grave accents when they occur
after ") AS ".  This strategy obviously has both false-positive and
false-negative issues, but suits the current needs and should be
relatively safe from false-positives.  Proper replacement would require
parsing the SQL.

Signed-off-by: Kevin Locke <kevin@kevinlocke.name>
2015-06-06 21:48:28 -06:00
Kevin Locke
e5353f70d6 Support INSERT IGNORE
MySQL supports the IGNORE modifier on INSERT statements, which ignores
uniqueness errors resulting from the INSERT.  This causes syntax errors
in PostgreSQL such as the following:

Error running :
INSERT IGNORE INTO `wp_options` ( `option_name`, `option_value`, `autoload` ) VALUES ('auto_updater.lock', '1433306517', 'no') /* LOCK */
---- converted to ----
INSERT IGNORE INTO wp_options ( option_name, option_value, autoload ) VALUES ('auto_updater.lock', '1433306517', 'no') /* LOCK */
----> ERROR:  syntax error at or near "IGNORE"
LINE 1: INSERT IGNORE INTO wp_options ( option_name, option_value, a...
               ^

Provide support for INSERT IGNORE using a PostgreSQL DO statement with
an exception handler for uniqueness errors.

This has the drawback that it requires PostgreSQL 9.0 or later, support
for plpgsql, and USAGE privileges for plpgsql for the current user.  But
these are all common, and it allows us to support INSERT IGNORE
statements generically.  If this is later found to be too much of a
problem, it is possible to rewrite the query on a query-specific basis
to an INSERT SELECT statement without a FROM clause.

Signed-off-by: Kevin Locke <kevin@kevinlocke.name>
2015-06-06 21:48:28 -06:00
Kevin Locke
6d55670e42 Tighten quoting of ID identifiers
The quoting of identifiers which contain "ID" can match things other
than identifiers, such as strings which contain "ID" and subsequently
"=".  An example of this occurring in practice is:

Error running :
UPDATE `wp_ngg_pictures` SET `pid` = '42', `post_id` = 0, `galleryid` = '3', `filename` = 'img_0683.jpg', `description` = '', `alttext` = 'img_0683', `imagedate` = '2011-02-05 11:52:31', `exclude` = '0', `sortorder` = '0', `meta_data` = 'eyIwIjpmYWxzZSwiYXBlcnR1cmUiOiJGIDUuNiIsImNyZWRpdCI6ZmFsc2UsImNhbWVyYSI6IkNhbm9uIEVPUyBSRUJFTCBUMWkiLCJjYXB0aW9uIjpmYWxzZSwiY3JlYXRlZF90aW1lc3RhbXAiOiJGZWJydWFyeSA1LCAyMDExIDExOjUyIGFtIiwiY29weXJpZ2h0IjpmYWxzZSwiZm9jYWxfbGVuZ3RoIjoiNTUgbW0iLCJpc28iOjQwMCwic2h1dHRlcl9zcGVlZCI6IjFcLzYwIHNlYyIsImZsYXNoIjoiRmlyZWQiLCJ0aXRsZSI6ZmFsc2UsImtleXdvcmRzIjpmYWxzZSwid2lkdGgiOjE2MDAsImhlaWdodCI6MTA2Nywic2F2ZWQiOnRydWUsInRodW1ibmFpbCI6eyJ3aWR0aCI6MTAwLCJoZWlnaHQiOjc1fSwibmdnMGR5bi0weDI1MC0wMGYwdzAxMWMwMTByMTEwZjExMHIwMTB0MDEwIjp7IndpZHRoIjozNzUsImhlaWdodCI6MjUwLCJmaWxlbmFtZSI6ImltZ18wNjgzLmpwZy1uZ2dpZDAyNDItbmdnMGR5bi0weDI1MC0wMGYwdzAxMWMwMTByMTEwZjExMHIwMTB0MDEwLmpwZyIsImdlbmVyYXRlZCI6IjAuNjczMzIxMDAgMTQzMzYyOTQxMiJ9fQ==', `image_slug` = 'img_0683', `extras_post_id` = '310', `updated_at` = '1433629412' WHERE `pid` = '42'
---- converted to ----
UPDATE wp_ngg_pictures SET pid = '42', post_id = 0, galleryid = '3', filename = 'img_0683.jpg', description = '', alttext = 'img_0683', imagedate = '2011-02-05 11:52:31', exclude = '0', sortorder = '0', meta_data = "'eyIwIjpmYWxzZSwiYXBlcnR1cmUiOiJGIDUuNiIsImNyZWRpdCI6ZmFsc2UsImNhbWVyYSI6IkNhbm9uIEVPUyBSRUJFTCBUMWkiLCJjYXB0aW9uIjpmYWxzZSwiY3JlYXRlZF90aW1lc3RhbXAiOiJGZWJydWFyeSA1LCAyMDExIDExOjUyIGFtIiwiY29weXJpZ2h0IjpmYWxzZSwiZm9jYWxfbGVuZ3RoIjoiNTUgbW0iLCJpc28iOjQwMCwic2h1dHRlcl9zcGVlZCI6IjFcLzYwIHNlYyIsImZsYXNoIjoiRmlyZWQiLCJ0aXRsZSI6ZmFsc2UsImtleXdvcmRzIjpmYWxzZSwid2lkdGgiOjE2MDAsImhlaWdodCI6MTA2Nywic2F2ZWQiOnRydWUsInRodW1ibmFpbCI6eyJ3aWR0aCI6MTAwLCJoZWlnaHQiOjc1fSwibmdnMGR5bi0weDI1MC0wMGYwdzAxMWMwMTByMTEwZjExMHIwMTB0MDEwIjp7IndpZHRoIjozNzUsImhlaWdodCI6MjUwLCJmaWxlbmFtZSI6ImltZ18wNjgzLmpwZy1uZ2dpZDAyNDItbmdnMGR5bi0weDI1MC0wMGYwdzAxMWMwMTByMTEwZjExMHIwMTB0MDEwLmpwZyIsImdlbmVyYXRlZCI6IjAuNjczMzIxMDAgMTQzMzYyOTQxMiJ9fQ=" =', image_slug = 'img_0683', extras_post_id = '310', updated_at = '1433629412' WHERE pid = '42'
----> ERROR:  syntax error at or near "img_0683"
LINE 1: ...jczMzIxMDAgMTQzMzYyOTQxMiJ9fQ=" =', image_slug = 'img_0683',...

To avoid this, ensure that the matched substring is not part of a SQL
string literal.

Signed-off-by: Kevin Locke <kevin@kevinlocke.name>
2015-06-06 21:48:28 -06:00