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

SQLite Compatibility #92

Open
swissspidy opened this issue Oct 21, 2023 · 5 comments
Open

SQLite Compatibility #92

swissspidy opened this issue Oct 21, 2023 · 5 comments

Comments

@swissspidy
Copy link
Member

When I manually run the tests locally with SQLite, the following scenarios are failing:

001 Scenario: Deleting all transients on single site # features/transient.feature:58
      Then STDOUT should be:                         # features/transient.feature:76
        $ wp transient delete --all
        Success: No transients found.

002 Scenario: Deleting expired transients on single site # features/transient.feature:123
      Then STDOUT should be:                             # features/transient.feature:134
        $ wp transient delete --expired
        Success: No expired transients found.

003 Scenario: Deleting all transients on multisite # features/transient.feature:194
      Then STDOUT should be:                       # features/transient.feature:215
        $ wp transient delete --all
        Success: No transients found.

004 Scenario: Deleting expired transients on multisite # features/transient.feature:286
      Then STDOUT should be:                           # features/transient.feature:301
        $ wp transient delete --expired
        Success: No expired transients found.

005 Scenario: List transients on single site # features/transient.feature:386
      Then STDOUT should contain:            # features/transient.feature:400
        $ wp transient list --format=csv
        name,value,expiration

006 Scenario: List transients on multisite # features/transient.feature:431
      Then STDOUT should contain:          # features/transient.feature:445
        $ wp transient list --format=csv
        name,value,expiration

007 Scenario: List transients with search and exclude pattern # features/transient.feature:476
      Then STDOUT should be:                                  # features/transient.feature:485
        $ wp transient list --format=csv --fields=name --search="foo"
        name

The transient command uses lots of custom MySQL queries. The SQLite integration plugin is supposed to make those SQLite-compatible, but perhaps something is not working there.

Or, since deletion and listing are failing, maybe the issue is that the insertion using set_transient() is failing in the first place.

Let's figure it out together. This could involve changes to the command, the tests, core, or the SQLite plugin.

@swissspidy
Copy link
Member Author

OK, so for the transient delete command there seem to be issue with the way LIKEs are being escaped by WordPress. The SQLite plugin might not be translating those properly and ending up deleting 0 rows. "Raw" queries without $wpdb->prepare do seem to work.
That said, the returned deletion counts seem to be wrong. Not sure if we need something like $wpdb->query( "SELECT changes() FROM {$wpdb->options}" ) as well.

@petitphp
Copy link
Contributor

@swissspidy I took a look at this, I'm not familiar with SQLite so I might be mistaking, but it seems that SQLite doesn't support DELETE statement for multiple tables like MySQL does :

DELETE a, b FROM {$wpdb->options} a, {$wpdb->options} b
WHERE a.option_name LIKE %s
AND a.option_name NOT LIKE %s
AND b.option_name = CONCAT( '_transient_timeout_', SUBSTRING( a.option_name, 12 ) )

I did manage to get the tests to pass by doing three queries to replicate what this DELETE statement, but maybe the SQLite WordPress plugin could handle that automatically.

@swissspidy
Copy link
Member Author

Interesting! Do you perhaps have a draft PR with that solution so that we could take a look?

It does seem like a case the SQLite plugin could handle, so If you could open an issues I'm sure the maintainers can take a look.

@petitphp
Copy link
Contributor

Turn out it's related to the escaping, like you suspected.

Looking at the wpdb::esc_like method in the SQLite integration plugin, they purposely remove the addslashes since SQLite doesn't care for the _% characters.

I'm able to fix the issue by modifying the Utils::esc_like to use the native wpdb method if available. But this will break the associated test in SQLite mode. We would need to create a new test to run in that mode.

function esc_like( $text ) {
	global $wpdb;

	if ( method_exists( $wpdb, 'esc_like' ) ) {
		return $wpdb->esc_like( $text );
	}

	return addcslashes( $text, '_%\\' );
}

@swissspidy
Copy link
Member Author

Let‘s try that 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants