Skip to content

Conversation

@anze3db
Copy link
Contributor

@anze3db anze3db commented Jun 8, 2024

Trac ticket number

ticket-33548

Branch description

Use the ->> operator to implement KeyTransform for JSON fields on SQLite.

I didn't add the version check because Python 3.10 upgraded SQLite to 3.39 in the 3.10.9 release https://docs.python.org/3.10/whatsnew/changelog.html#id26

Checklist

  • This PR targets the main branch.
  • The commit message is written in past tense, mentions the ticket number, and ends with a period.
  • I have checked the "Has patch" ticket flag in the Trac system.
  • I have added or updated relevant tests.
  • I have added or updated relevant docs, including release notes if applicable.
  • I have attached screenshots in both light and dark modes for any UI changes.

@anze3db anze3db closed this Jun 8, 2024
@anze3db anze3db reopened this Jun 8, 2024
@anze3db anze3db changed the title Fixed #33548 Use ->> operator to implement KeyTransform on SQLite 3.38+ Fixed #33548 -- Use ->> operator to implement KeyTransform on SQLite 3.38+ Jun 8, 2024
@LilyFirefly
Copy link
Contributor

Can we add a test for this?

@charettes
Copy link
Member

Can we add a test for this?

I think there are plenty of tests already for this in the suite, the question is more along the lines of whether CI is running SQLite < or >= 3.38+ and exercise this new code path.

One way to test it out locally is via export LD_PRELOAD=/usr/lib/sqlite3/libsqlite3.so.

@anze3db
Copy link
Contributor Author

anze3db commented Jun 10, 2024

I'm not sure how to check what Jenkins is running, but Debian bookworm is on 3.40 while Debian bullseye is on 3.36.

I'm happy to add a test that mocks the get_database_version() call and makes sure both paths are executed. Let me know!

@LilyFirefly
Copy link
Contributor

LilyFirefly commented Jun 10, 2024

Hmm, if we don't cover this only because Jenkins doesn't have both versions, I think it's fine as-is if local testing passes.

@sarahboyce
Copy link
Contributor

@anze3db did you also have a look at the JSON_EXTRACTs in KeyTransformIn and KeyTransformExact (see 71ec102)?

"(CASE WHEN JSON_TYPE(%s, %%s) IN (%s) "
"THEN JSON_TYPE(%s, %%s) ELSE JSON_EXTRACT(%s, %%s) END)"
) % (lhs, datatype_values, lhs, lhs), (tuple(params) + (json_path,)) * 3
if connection.get_database_version() >= (3, 38):
Copy link
Member

Choose a reason for hiding this comment

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

I'd change it to the SQLite-specific feature flag.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'll add the feature flag if we decide to move forward with this (#18241 (comment))

Comment on lines +394 to +397
return (
"(CASE WHEN JSON_TYPE(%s, %%s) IN (%s) "
"THEN JSON_TYPE(%s, %%s) ELSE JSON_EXTRACT(%s, %%s) END)"
) % (lhs, datatype_values, lhs, lhs), (tuple(params) + (json_path,)) * 3
Copy link
Member

Choose a reason for hiding this comment

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

What about comment in SQLite operations:

# List of datatypes to that cannot be extracted with JSON_EXTRACT() on
# SQLite. Use JSON_TYPE() instead.
jsonfield_datatype_values = frozenset(["null", "false", "true"])

Do we still need a JSON_TYPE workaround? If yes, I don't see much value in this change, TBH 🤷

Copy link
Contributor Author

@anze3db anze3db Jul 23, 2024

Choose a reason for hiding this comment

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

From what I can tell the ->> operator behaves the same way as JSON_EXTRACT so we still need the JSON_TYPE workaround if we use it.

The -> operator, handles the null, false, true values the way as the CASE statement with JSON_TYPE:

sqlite> select JSON_TYPE('null', '$');
null
sqlite> select JSON_TYPE('true', '$');
true
sqlite> select JSON_TYPE('false', '$');
false

sqlite> select 'null' -> "$";
null
sqlite> select 'true' -> "$";
true
sqlite> select 'false' -> "$";
false

But there are other differences, one example:

sqlite> select JSON_EXTRACT('"7"', "$");
7
sqlite> select '"7"' -> "$";
"7"

If I switch the CASE statement with -> it causes failures=29, errors=2 in test_jsonfield.py, and I'm not exactly sure how to fix it.

I think you might be correct about there not being much value in having this merged. I'm happy if we can close the ticket as won't do instead.

@felixxm
Copy link
Member

felixxm commented Jul 22, 2024

I can check it next week with various SQLite versions.

@anze3db
Copy link
Contributor Author

anze3db commented Jul 23, 2024

@anze3db did you also have a look at the JSON_EXTRACTs in KeyTransformIn and KeyTransformExact (see 71ec102)?

@sarahboyce I have not, but I can update those if we decide to go forward with this and how (ref: #18241 (comment)).

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants