Uploaded image for project: 'MariaDB Server'
  1. MariaDB Server
  2. MDEV-33717

ERROR 1901 (HY000) at line 29: Function or expression ... cannot be used in the GENERATED ALWAYS AS clause of ...

Details

    Description

      Customer has a database with tables that have columns defined like this:

        `StartDate` datetime(3) GENERATED ALWAYS AS 
          (json_unquote(json_value(`ObjData`,'$.StartDate'))) STORED,
      

      Table can be understood if software is updated to higher release, such as 10.11 (tested). Table can be dumped by mariadb-dump at any release.

      However, when the table is imported in any DB 10.5 or higher, you get the following error:

      ERROR 1901 (HY000) at line 29: Function or expression 
      'json_unquote(json_value(`ObjData`,'$.StartDate'))' cannot be used 
      in the GENERATED ALWAYS AS clause of `StartDate
      

      Attachments

        Issue Links

          Activity

            As a workaround, I have used this ALTER TABLE. After the table definition is changed this way, it can be created in another schema in 10.11 allowing for dumps/imports.

            alter table `CS0725681`.`tt_obj` 
              MODIFY COLUMN `StartDate` datetime(3) 
                GENERATED ALWAYS AS (cast(json_unquote(json_value(`ObjData`,'$.StartDate')) as char charset utf8)) STORED,
              MODIFY COLUMN `EndDate` datetime(3) 
                GENERATED ALWAYS AS (cast(json_unquote(json_value(`ObjData`,'$.EndDate')) as char charset utf8)) STORED;
            

            edward Edward Stoever added a comment - As a workaround , I have used this ALTER TABLE. After the table definition is changed this way, it can be created in another schema in 10.11 allowing for dumps/imports. alter table `CS0725681`.`tt_obj` MODIFY COLUMN `StartDate` datetime(3) GENERATED ALWAYS AS (cast(json_unquote(json_value(`ObjData`,'$.StartDate')) as char charset utf8)) STORED, MODIFY COLUMN `EndDate` datetime(3) GENERATED ALWAYS AS (cast(json_unquote(json_value(`ObjData`,'$.EndDate')) as char charset utf8)) STORED;
            bar Alexander Barkov added a comment - - edited

            Short answer: This is not a bug. The behavior was changed under terms of MDEV-18153, to avoid unsafe expressions in the GENERATED ALWAYS clause.

            Details:

            In some cases (including this one) after getting an error one can get some additional information by issuing a SHOW WARNING statement:

            SHOW WARNINGS;
            

            +---------+------+--------------------------------------------------------------------------------------------------------------------------------------------+
            | Level   | Code | Message                                                                                                                                    |
            +---------+------+--------------------------------------------------------------------------------------------------------------------------------------------+
            | Error   | 1901 | Function or expression 'json_unquote(json_value(`ObjData`,'$.StartDate'))' cannot be used in the GENERATED ALWAYS AS clause of `StartDate` |
            | Warning | 1105 | Expression depends on the @@sql_mode value TIME_ROUND_FRACTIONAL                                                                           |
            +---------+------+--------------------------------------------------------------------------------------------------------------------------------------------+
            

            It explains that the problem is that the expression depens on sql_mode. The reason is that the conversion from a string to a DATETIME depends on the TIME_ROUND_FRACTIONAL flag in sql_mode.

            The behavior was intentionally changed to warn about unsafe expressions under terms of MDEV-18153 in 10.4, then starting from 10.5 the warning was changed to error.

            To avoid sql_mode dependency, please specify an explicit call for ROUND() or TRUNCATE() depending on your preferences:

            CREATE OR REPLACE t1
            (
              ObjData TEXT,
              `StartDate` datetime(3) GENERATED ALWAYS AS
              (round(
                 json_unquote(json_value(`ObjData`,'$.StartDate')),
               3)
            );
            

            CREATE OR REPLACE t1
            (
              ObjData TEXT,
              `StartDate` datetime(3) GENERATED ALWAYS AS
              (truncate(
                 json_unquote(json_value(`ObjData`,'$.StartDate')),
              3)
            );
            

            bar Alexander Barkov added a comment - - edited Short answer: This is not a bug. The behavior was changed under terms of MDEV-18153 , to avoid unsafe expressions in the GENERATED ALWAYS clause. Details: In some cases (including this one) after getting an error one can get some additional information by issuing a SHOW WARNING statement: SHOW WARNINGS; +---------+------+--------------------------------------------------------------------------------------------------------------------------------------------+ | Level | Code | Message | +---------+------+--------------------------------------------------------------------------------------------------------------------------------------------+ | Error | 1901 | Function or expression 'json_unquote(json_value(`ObjData`,'$.StartDate'))' cannot be used in the GENERATED ALWAYS AS clause of `StartDate` | | Warning | 1105 | Expression depends on the @@sql_mode value TIME_ROUND_FRACTIONAL | +---------+------+--------------------------------------------------------------------------------------------------------------------------------------------+ It explains that the problem is that the expression depens on sql_mode. The reason is that the conversion from a string to a DATETIME depends on the TIME_ROUND_FRACTIONAL flag in sql_mode. The behavior was intentionally changed to warn about unsafe expressions under terms of MDEV-18153 in 10.4, then starting from 10.5 the warning was changed to error. To avoid sql_mode dependency, please specify an explicit call for ROUND() or TRUNCATE() depending on your preferences: CREATE OR REPLACE t1 ( ObjData TEXT, `StartDate` datetime(3) GENERATED ALWAYS AS (round( json_unquote(json_value(`ObjData`, '$.StartDate' )), 3) ); CREATE OR REPLACE t1 ( ObjData TEXT, `StartDate` datetime(3) GENERATED ALWAYS AS ( truncate ( json_unquote(json_value(`ObjData`, '$.StartDate' )), 3) );

            People

              bar Alexander Barkov
              edward Edward Stoever
              Votes:
              0 Vote for this issue
              Watchers:
              4 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Git Integration

                  Error rendering 'com.xiplink.jira.git.jira_git_plugin:git-issue-webpanel'. Please contact your Jira administrators.