Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backport the SQLite rewrite from the standalone plugin #677

Closed
wants to merge 19 commits into from

Conversation

aristath
Copy link
Member

@aristath aristath commented Mar 16, 2023

Summary

This PR backports the SQLite rewrite from the standalone plugin.
The rewrite of the implementation uses a Lexer and a Translator for the queries, and offers significantly better security as well as compatibility with a wider array of MySQL queries.

Relevant technical choices

Checklist

  • PR has either [Focus] or Infrastructure label.
  • PR has a [Type] label.
  • PR has a milestone or the no milestone label.

@aristath aristath added [Type] Bug An existing feature is broken no milestone PRs that do not have a defined milestone for release [Focus] Database labels Mar 16, 2023
Copy link
Member

@felixarntz felixarntz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@aristath I didn't review all the actual code, since it's a whole lot and it's already part of the SQLite standalone plugin, so probably not needed anyway.

One small feedback below for integrating this into the main repo, since right now we still have the modules around (which will change in the future of course).

@felixarntz felixarntz removed the no milestone PRs that do not have a defined milestone for release label Apr 3, 2023
@felixarntz felixarntz added this to the 2.2.0 milestone Apr 3, 2023
@aristath
Copy link
Member Author

I faced a lot of issues with the activation/deactivation routines... A plugin doesn't work the same as a module, and plugins need to use different hooks to activate/deactivate things etc.
As a result, in order to keep things simple I reverted all the changes regarding the plugin activation/deactivation and only backported the actual database-engine changes from the standalone plugin.
Once we have a better idea on how standalone plugins will be added & deployed from this repo I can do a followup PR with the plugin-specific files.

Copy link
Member

@mukeshpanchal27 mukeshpanchal27 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @aristath, for the update. I quickly review the PR and found some nitpicks; other than that, I don't have any more feedback. We need more eyes on this so we can merge.

modules/database/sqlite/can-load.php Outdated Show resolved Hide resolved
@@ -133,11 +158,10 @@ public function print_error( $str = '' ) {
wp_load_translations_early();

$caller = $this->get_caller();
$caller = $caller ? $caller : __( '(unknown)', 'performance-lab' );
$caller = $caller ? $caller : '(unknown)';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Translation is missing on this file. Check other instances for the same.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was on purpose.
These are not user-facing messages and translating them is not necessary. These strings are intended for error-logging only.
If there is an error in the database, in some scenarios it happens before the translations functions have even loaded. Using the __() function here was throwing a fatal error and prevented the actual DB error from getting logged.
Translations are only required for user-facing strings, so we removed them from strings that are intended for error-logging and are never shown to users.

modules/database/sqlite/constants.php Outdated Show resolved Hide resolved
@mukeshpanchal27 mukeshpanchal27 modified the milestones: 2.2.0, 2.3.0 Apr 11, 2023
Copy link
Member

@felixarntz felixarntz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@aristath This looks almost good to go, just a few points of feedback for consideration.

if ( defined( 'PERFLAB_SQLITE_DB_DROPIN_VERSION' ) ) {
define( 'DATABASE_TYPE', 'sqlite' );
if ( ! defined( 'DB_ENGINE' ) ) {
if ( defined( 'SQLITE_DB_DROPIN_VERSION' ) ) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on the code above in line 10-12, we would need to use PERFLAB_SQLITE_DB_DROPIN_VERSION instead, as above you set that constant based on the other one. Which one is considered the source of truth? Given the standalone plugin uses SQLITE_DB_DROPIN_VERSION, we should probably use that.

// Backwards-compatibility.
if ( ! defined( 'PERFLAB_SQLITE_DB_DROPIN_VERSION' ) && defined( 'SQLITE_DB_DROPIN_VERSION' ) ) {
define( 'PERFLAB_SQLITE_DB_DROPIN_VERSION', SQLITE_DB_DROPIN_VERSION );
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See my other comment, we also need to ensure backward compatibility the other direction, especially as I'm assuming SQLITE_DB_DROPIN_VERSION will be our main constant going forward.

Suggested change
}
}
if ( ! defined( 'SQLITE_DB_DROPIN_VERSION' ) && defined( 'PERFLAB_SQLITE_DB_DROPIN_VERSION' ) ) {
define( 'SQLITE_DB_DROPIN_VERSION', PERFLAB_SQLITE_DB_DROPIN_VERSION );
}

*/
function perflab_sqlite_plugin_filter_debug_data( $info ) {
$database_type = defined( 'DATABASE_TYPE' ) && 'sqlite' === DATABASE_TYPE ? 'sqlite' : 'mysql';
function sqlite_plugin_filter_debug_data( $info ) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why remove the doc block here? Not having a doc block is worse than having one :)

Additionally, we should be careful about prefixing our code properly. sqlite_plugin_ works well as a prefix, since that makes it very clear it's for the plugin and won't conflict when that code is eventually part of WordPress core. But we shouldn't use just sqlite_ or wp_sqlite_, because those are at risk for conflicts.

@@ -11,14 +11,14 @@
*
* It also rewrites some methods that use mysql specific functions.
*/
class Perflab_SQLite_DB extends wpdb {
class WP_SQLite_DB extends wpdb {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See my above comment, I don't think it's a good idea to use the WP_SQLite_ prefix. This code is not part of core (yet), so we shouldn't use a prefix that is preferably reserved for WordPress core.

How about SQLite_Plugin_DB or SQLite_Database_Integration_DB or something else that clearly scopes this code to the SQLite plugin or module?

/**
* The query rewriter class.
*/
class WP_SQLite_Query_Rewriter {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment above applies here and elsewhere on the other classes introduced here. Shouldn't we use a safer plugin-specific prefix for our code?

@aristath
Copy link
Member Author

Closing this one, see #661 (comment)

@aristath aristath closed this Apr 25, 2023
@felixarntz felixarntz removed this from the 2.3.0 milestone Apr 25, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Type] Bug An existing feature is broken
Projects
None yet
Development

Successfully merging this pull request may close these issues.

SQLite: Error in prepare_query with DELETE / delete_expired_transients
4 participants