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

Assertion `got_name == named_item_expected()' failed in Json_writer::on_start_object on JSON-less testcase using optimizer_trace

Details

    Description

      Seems related to MDEV-27204, yet this testcase does not use JSON nor do versions affected match.

      SET sql_mode='';
      CREATE TABLE t (a INT KEY,b INT,KEY(b)) ENGINE=MEMORY;
      SET optimizer_trace=1;
      INSERT INTO t VALUES (0,0);
      SELECT a FROM t WHERE (a,b) in (SELECT @c,@d);
      

      Leads to:

      10.7.2 979b23d5bfb11bb698ea65c9468b374978737ec0 (Debug)

      mysqld: /test/10.7_dbg/sql/my_json_writer.cc:42: void Json_writer::on_start_object(): Assertion `got_name == named_item_expected()' failed.
      

      10.7.2 979b23d5bfb11bb698ea65c9468b374978737ec0 (Debug)

      Core was generated by `/test/MD121221-mariadb-10.7.2-linux-x86_64-dbg/bin/mysqld --no-defaults --core-'.
      Program terminated with signal SIGABRT, Aborted.
      #0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
      [Current thread is 1 (Thread 0x14e8a0d6e700 (LWP 3592433))]
      (gdb) bt
      #0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
      #1  0x000014e8abfd2859 in __GI_abort () at abort.c:79
      #2  0x000014e8abfd2729 in __assert_fail_base (fmt=0x14e8ac168588 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n", assertion=0x5645bb249e18 "got_name == named_item_expected()", file=0x5645bb249d20 "/test/10.7_dbg/sql/my_json_writer.cc", line=42, function=<optimized out>) at assert.c:92
      #3  0x000014e8abfe3f36 in __GI___assert_fail (assertion=assertion@entry=0x5645bb249e18 "got_name == named_item_expected()", file=file@entry=0x5645bb249d20 "/test/10.7_dbg/sql/my_json_writer.cc", line=line@entry=42, function=function@entry=0x5645bb249f18 "void Json_writer::on_start_object()") at assert.c:101
      #4  0x00005645ba72ab95 in Json_writer::on_start_object (this=0x5645bcecb130) at /test/10.7_dbg/sql/my_json_writer.cc:42
      #5  Json_writer::start_object (this=this@entry=0x5645bcecb130) at /test/10.7_dbg/sql/my_json_writer.cc:51
      #6  0x00005645ba5c744d in Json_writer_object::Json_writer_object (str=0x0, writer=0x5645bcecb130, this=<synthetic pointer>) at /test/10.7_dbg/sql/my_json_writer.h:444
      #7  Json_writer_object::Json_writer_object (str=0x0, thd=<optimized out>, this=<synthetic pointer>) at /test/10.7_dbg/sql/my_json_writer.h:449
      #8  JOIN::optimize_inner (this=this@entry=0x14e7e0016fd8) at /test/10.7_dbg/sql/sql_select.cc:1986
      #9  0x00005645ba5c8e3a in JOIN::optimize (this=0x14e7e0016fd8) at /test/10.7_dbg/sql/sql_select.cc:1809
      #10 0x00005645ba9482be in subselect_single_select_engine::exec (this=0x14e7e0015fb0) at /test/10.7_dbg/sql/item_subselect.cc:4034
      #11 0x00005645ba947ba6 in Item_subselect::exec (this=this@entry=0x14e7e0015ce0) at /test/10.7_dbg/sql/item_subselect.cc:853
      #12 0x00005645ba94d3e9 in Item_in_subselect::exec (this=0x14e7e0015ce0) at /test/10.7_dbg/sql/item_subselect.cc:1035
      #13 0x00005645ba946a75 in Item_in_subselect::val_bool (this=0x14e7e0015ce0) at /test/10.7_dbg/sql/item_subselect.cc:1965
      #14 0x00005645ba3ecd77 in Item::val_bool_result (this=<optimized out>) at /test/10.7_dbg/sql/item.h:1783
      #15 0x00005645ba88e738 in Item_in_optimizer::val_int (this=0x14e7e0017650) at /test/10.7_dbg/sql/item_cmpfunc.cc:1637
      #16 0x00005645ba5a50ab in make_join_select (join=join@entry=0x14e7e00168e8, select=0x14e7e00cb820, cond=0x14e7e0017650) at /test/10.7_dbg/sql/sql_select.cc:11727
      #17 0x00005645ba5c56dd in JOIN::optimize_stage2 (this=this@entry=0x14e7e00168e8) at /test/10.7_dbg/sql/sql_select.cc:2742
      #18 0x00005645ba5c8b47 in JOIN::optimize_inner (this=this@entry=0x14e7e00168e8) at /test/10.7_dbg/sql/sql_select.cc:2479
      #19 0x00005645ba5c8e3a in JOIN::optimize (this=this@entry=0x14e7e00168e8) at /test/10.7_dbg/sql/sql_select.cc:1809
      #20 0x00005645ba5c94de in mysql_select (thd=thd@entry=0x14e7e0000db8, tables=0x14e7e0014468, fields=@0x14e7e0014128: {<base_list> = {<Sql_alloc> = {<No data fields>}, first = 0x14e7e0014420, last = 0x14e7e0014420, elements = 1}, <No data fields>}, conds=0x14e7e0015ce0, og_num=0, order=0x0, group=0x0, having=0x0, proc_param=0x0, select_options=2147748608, result=0x14e7e00168c0, unit=0x14e7e00051c0, select_lex=0x14e7e0013e88) at /test/10.7_dbg/sql/sql_select.cc:4979
      #21 0x00005645ba5c97e2 in handle_select (thd=thd@entry=0x14e7e0000db8, lex=lex@entry=0x14e7e00050e8, result=result@entry=0x14e7e00168c0, setup_tables_done_option=setup_tables_done_option@entry=0) at /test/10.7_dbg/sql/sql_select.cc:545
      #22 0x00005645ba528c1e in execute_sqlcom_select (thd=thd@entry=0x14e7e0000db8, all_tables=0x14e7e0014468) at /test/10.7_dbg/sql/sql_parse.cc:6253
      #23 0x00005645ba535af1 in mysql_execute_command (thd=thd@entry=0x14e7e0000db8, is_called_from_prepared_stmt=is_called_from_prepared_stmt@entry=false) at /test/10.7_dbg/sql/sql_parse.cc:3944
      #24 0x00005645ba521e0f in mysql_parse (thd=thd@entry=0x14e7e0000db8, rawbuf=<optimized out>, length=<optimized out>, parser_state=parser_state@entry=0x14e8a0d6d400) at /test/10.7_dbg/sql/sql_parse.cc:8028
      #25 0x00005645ba530aab in dispatch_command (command=command@entry=COM_QUERY, thd=thd@entry=0x14e7e0000db8, packet=packet@entry=0x14e7e000b879 "SELECT a FROM t WHERE (a,b) in (SELECT @c,@d)", packet_length=packet_length@entry=45, blocking=blocking@entry=true) at /test/10.7_dbg/sql/sql_class.h:1360
      #26 0x00005645ba533eea in do_command (thd=0x14e7e0000db8, blocking=blocking@entry=true) at /test/10.7_dbg/sql/sql_parse.cc:1402
      #27 0x00005645ba6ad902 in do_handle_one_connection (connect=<optimized out>, connect@entry=0x5645bceaae48, put_in_cache=put_in_cache@entry=true) at /test/10.7_dbg/sql/sql_connect.cc:1418
      #28 0x00005645ba6adf07 in handle_one_connection (arg=arg@entry=0x5645bceaae48) at /test/10.7_dbg/sql/sql_connect.cc:1312
      #29 0x00005645bab2e33e in pfs_spawn_thread (arg=0x5645bcdbe738) at /test/10.7_dbg/storage/perfschema/pfs.cc:2201
      #30 0x000014e8ac4e1609 in start_thread (arg=<optimized out>) at pthread_create.c:477
      #31 0x000014e8ac0cf293 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
      

      Bug confirmed present in:
      MariaDB: 10.4.23 (dbg), 10.5.14 (dbg), 10.6.6 (dbg), 10.7.2 (dbg), 10.8.0 (dbg)

      Bug (or feature/syntax) confirmed not present in:
      MariaDB: 10.2.42 (dbg), 10.2.42 (opt), 10.3.33 (dbg), 10.3.33 (opt), 10.4.23 (opt), 10.5.14 (opt), 10.6.6 (opt), 10.7.2 (opt), 10.8.0 (opt)
      MySQL: 5.5.62 (dbg), 5.5.62 (opt), 5.6.51 (dbg), 5.6.51 (opt), 5.7.36 (dbg), 5.7.36 (opt), 8.0.27 (dbg), 8.0.27 (opt)

      Attachments

        Issue Links

          Activity

            The fix is kind of obvious.

            What I find odd is this:

            1. Optimization for select #1 reaches "plan refinement" stage in
            make_join_select.
            2. It tries to evaluate a constant subquery.
            3. It finds out that the subquery has no query plan yet
            4. It tries to compute a query plan.

            The particularly odd is the combination of #2 and #3.

            There are other places in the optimizer where it will evaluate "constant"
            items. Does this mean that we need to make sure that for any of these places,
            the calling side leaves the Optimizer Trace in the right state (that is, a
            state where one can start tracing an optimization?)

            psergei Sergei Petrunia added a comment - The fix is kind of obvious. What I find odd is this: 1. Optimization for select #1 reaches "plan refinement" stage in make_join_select. 2. It tries to evaluate a constant subquery. 3. It finds out that the subquery has no query plan yet 4. It tries to compute a query plan. The particularly odd is the combination of #2 and #3. There are other places in the optimizer where it will evaluate "constant" items. Does this mean that we need to make sure that for any of these places, the calling side leaves the Optimizer Trace in the right state (that is, a state where one can start tracing an optimization?)

            There is optimize_constant_subqueries() call made from early phase of
            JOIN::optimize()... but the subquery is not yet constant at that point.

            The subquery should become constant when table t is found to be constant.
            This call is made

            conds->update_used_tables();
            

            and it partially makes the subquery constant:

            conds->used_tables()=0
            conds->const_item()= false
            

            const_item=false(), because Item_subselect::const_item_cache remains false...
            which happens, because because engine->uncacheable()= UNCACHEABLE_EXPLAIN | UNCACHEABLE_SIDEEFFECT.

            and this code doesn't make it non-constant:

            void Item_subselect::update_used_tables()
            {
              if (!forced_const)
              {
                recalc_used_tables(parent_select, FALSE);
                if (!(engine->uncacheable() & ~UNCACHEABLE_EXPLAIN))
                {
                  // did all used tables become static?
                  if (!(used_tables_cache & ~engine->upper_select_const_tables()) &&
                      ! with_recursive_reference)
                    const_item_cache= 1;
                }
              }
            }
            

            psergei Sergei Petrunia added a comment - There is optimize_constant_subqueries() call made from early phase of JOIN::optimize()... but the subquery is not yet constant at that point. The subquery should become constant when table t is found to be constant. This call is made conds->update_used_tables(); and it partially makes the subquery constant: conds->used_tables()=0 conds->const_item()= false const_item=false(), because Item_subselect::const_item_cache remains false... which happens, because because engine->uncacheable()= UNCACHEABLE_EXPLAIN | UNCACHEABLE_SIDEEFFECT. and this code doesn't make it non-constant: void Item_subselect::update_used_tables() { if (!forced_const) { recalc_used_tables(parent_select, FALSE); if (!(engine->uncacheable() & ~UNCACHEABLE_EXPLAIN)) { // did all used tables become static? if (!(used_tables_cache & ~engine->upper_select_const_tables()) && ! with_recursive_reference) const_item_cache= 1; } } }

            Trying a similar but non-degenerate subquery:

            explain 
            SELECT a FROM t 
            WHERE t.a < (select max(a) from ten where ten.a+t.a<333);
            

            It doesn't crash.

            Reason:
            make_join_select() doesn't try to evaluate it, because const_cond->is_expensive()=false.

            Item_subselect::is_expensive() returns
            1. FALSE for "degenerate" subqueries
            2. TRUE when the subquery doesn't have a query plan, yet.

            The original query takes path#1, this query takes path#2.

            psergei Sergei Petrunia added a comment - Trying a similar but non-degenerate subquery: explain SELECT a FROM t WHERE t.a < (select max(a) from ten where ten.a+t.a<333); It doesn't crash. Reason: make_join_select() doesn't try to evaluate it, because const_cond->is_expensive()=false. Item_subselect::is_expensive() returns 1. FALSE for "degenerate" subqueries 2. TRUE when the subquery doesn't have a query plan, yet. The original query takes path#1, this query takes path#2.

            That is, this bug only applies to "degenerate" subqueries.
            Other places in the optimizer that call item->val_int() for constant items are not affected because they check the
            const_item()=true, or can_eval_in_optimize()=true which is even more restrictive than that.

            psergei Sergei Petrunia added a comment - That is, this bug only applies to "degenerate" subqueries. Other places in the optimizer that call item->val_int() for constant items are not affected because they check the const_item()=true , or can_eval_in_optimize()=true which is even more restrictive than that.

            People

              psergei Sergei Petrunia
              Roel Roel Van de Paar
              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.