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

Emulate JSON_OBJECT's ABSENT ON NULL clause in MySQL #13249

Closed
lukaseder opened this issue Mar 9, 2022 · 3 comments
Closed

Emulate JSON_OBJECT's ABSENT ON NULL clause in MySQL #13249

lukaseder opened this issue Mar 9, 2022 · 3 comments

Comments

@lukaseder
Copy link
Member

An interesting solution to implementing ABSENT ON NULL support in MySQL is described here:
https://stackoverflow.com/a/69907488/521799

For example:

WITH j (o) AS (
  SELECT json_object('a', 'a', 'b', null, 'c', 'c', 'd', null)
)
SELECT 
  j.o, (
    SELECT JSON_OBJECTAGG(k, JSON_EXTRACT(j.o, CONCAT('$."', jt.k, '"')))
    FROM JSON_TABLE(
      JSON_KEYS(o), '$[*]'
      COLUMNS (
        k VARCHAR(200) PATH '$'
      )
    ) jt
    WHERE JSON_EXTRACT(j.o, CONCAT('$."', jt.k, '"')) != CAST('null' AS JSON)
  ) removed
FROM j;

The result being:

|o                                         |removed             |
|------------------------------------------|--------------------|
|{"a": "a", "b": null, "c": "c", "d": null}|{"a": "a", "c": "c"}|

(It works on MySQL only, in this form. There's probably a MariaDB version)

@lukaseder
Copy link
Member Author

Looking into this now for MySQL (let's ignore MariaDB for now). The emulation requires support for correlated derived tables, which has been implemented in some MySQL 8 version only. MariaDB doesn't support it.

@lukaseder lukaseder changed the title Emulate JSON_OBJECT's ABSENT ON NULL clause in MySQL, MariaDB Emulate JSON_OBJECT's ABSENT ON NULL clause in MySQL Sep 30, 2022
@lukaseder
Copy link
Member Author

lukaseder commented Sep 30, 2022

The actual query is this one:

-- Original
select json_object('a', null absent on null)

-- Emulated, on MySQL
select (
  select coalesce( -- Coalesce is essential
    json_objectagg(`jt`.`k`, json_extract(
      `j`.`o`,
      concat('$."', `jt`.`k`, '"')
    )), 
    json_object()
  )
  from -- Working with derived tables, to avoid trouble
    (
      select json_object('a', null) as `o` -- original `JSON_OBJECT()` constructor here
    ) as `j`,
    json_table(
      json_keys(`j`.`o`),
      '$[*]'
      columns (`k` text path '$')
    ) as `jt`
  where json_extract(
    `j`.`o`,
    concat('$."', `jt`.`k`, '"')
  ) <> cast('null' as json)
);

@lukaseder
Copy link
Member Author

The JSON_KEYS() function used here is probably worth supporting on its own: #14046

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

No branches or pull requests

1 participant