Commit graph

141 commits

Author SHA1 Message Date
Igor Babaev
540eeebbb0 Fixed bug mdev-4420.
The code of JOIN::optimize that performed substitutions for the best equal
field in all ref items did not take into account that a multiple equality
could contain the result of the single-value subquery if the subquery is
inexpensive. This code was corrected.
Also made necessary corresponding corrections in the code of make_join_select().
2013-08-23 07:25:45 -07:00
Sergey Petrunya
9651a6f574 mdev-4173: Wrong result (extra row) with semijoin=on, joins in outer query, LEFT JOIN in the subquery
Apply the patch from Patryk Pomykalski:
- create_internal_tmp_table_from_heap() will now return information whether
  the last row that we tried to write was a duplicate row.
(mysql-5.6 also has this change)
2013-07-16 09:22:17 +04:00
Sergey Petrunya
ddd341b71a MDEV-4071: Valgrind warnings 'Invalid read' in subselect_engine::calc_const_tables with ...
- Call tmp_having->update_used_tables() *before* we have call JOIN::cleanup().
  Making the call after join::cleanup() is not allowed, because subquery 
  predicate items walk parent join's JOIN_TAB structures. Which can be 
  invalidated by JOIN::cleanup().
2013-05-04 20:42:43 +04:00
Sergey Petrunya
71422d7b14 MDEV-389: Wrong result (missing row) with semijoin, join_cache_level>4 ...
- Added testcase
2013-05-04 21:02:07 +04:00
Sergey Petrunya
7868367270 Merge 5.3 -> 5.5 2013-04-03 18:51:29 +04:00
Sergey Petrunya
3345e7564d MDEV-4335: Unexpected results when selecting on information_schema
- When converting a subquery to a semi-join, propagate OPTION_SCHEMA_TABLE.
2013-03-29 19:27:06 +04:00
Sergei Golubchik
213f1c76a0 5.3->5.5 merge 2013-02-28 22:47:29 +01:00
Igor Babaev
c9b63e6a49 Fixed bug mdev-3913.
The wrong result set returned by the left join query  from
the bug test case happened due to several inconsistencies 
and bugs of the legacy mysql code.

The bug test case uses an execution plan that employs a scan
of a materialized IN subquery from the WHERE condition.
When materializing such an IN- subquery the optimizer injects
additional equalities  into the WHERE clause. These equalities
express the constraints imposed by the subquery predicate.
The injected equality of the query in the  test case happens
to belong to the same equality class, and a new equality 
imposing a condition on the rows of the materialized subquery
is inferred from this class. Simultaneously the multiple
equality is added to the ON expression of the LEFT JOIN
used in the main query.
  
The inferred equality of the form f1=f2 is taken into account
when optimizing the scan of  the rows the temporary table 
that is the result of the subquery materialization: only the 
values of the field f1 are read from the table into the record 
buffer. Meanwhile the inferred equality is removed from the
WHERE conditions altogether as a constraint on the fields
of the temporary table that has been used when filling this table. 
This equality is supposed to be removed from the ON expression
when the multiple equalities of the ON expression are converted
into an optimal set of equality predicates. It supposed to be
removed from the ON expression as an equality inferred from only
equalities of the WHERE condition. Yet, it did not happened
due to the following bug in the code.

Erroneously the code tried to build multiple equality for ON
expression twice: the first time, when it called optimize_cond()
for the WHERE condition, the second time, when it called
this function for the HAVING condition. When executing
optimize_con() for the WHERE condition  a reference
to the multiple equality of the WHERE condition is set
in the multiple equality of the  ON expression. This reference
would allow later to convert multiple equalities of the
ON expression into equality predicates. However the 
the second call of build_equal_items() for the ON expression
that happened when optimize_cond() was called for the
HAVING condition reset this reference to NULL.

This bug fix blocks calling build_equal_items() for ON
expressions for the second time. In general, it will be
beneficial for many queries as it removes from ON 
expressions any equalities that are to be checked for the
WHERE condition.
The patch also fixes two bugs in the list manipulation
operations and a bug in the function  
substitute_for_best_equal_field() that resulted
in passing wrong reference to the multiple equalities
of where conditions when processing multiple
equalities  of ON expressions.

The code of substitute_for_best_equal_field() and
the code the helper function eliminate_item_equal()
were also streamlined and cleaned up.
Now the conversion of the multiple equalities into
an optimal set of equality predicates first produces
the sequence of the all equalities processing multiple
equalities one by one, and, only after this, it inserts
the equalities at the beginning of the other conditions.

The multiple changes in the output of EXPLAIN
EXTENDED are mainly the result of this streamlining,
but in some cases is the result of the removal of
unneeded equalities from ON expressions. In
some test cases this removal were reflected in the
output of EXPLAIN resulted in disappearance of 
“Using where” in some rows of the execution plans.
2013-02-20 18:01:36 -08:00
Sergei Golubchik
87de27e46b 5.3 merge 2013-01-28 13:36:05 +01:00
unknown
298008dc4f The problem was that expression with field after transformation (on the first execution)
reached by fix_fields() (via reference) before row which it belongs to (on the second execution)
and fix_field for row did not follow usual protocol for Items with argument
(first check that the item fixed then call fix_fields).

Item_row::fix_field fixed.
2013-01-25 16:56:57 +02:00
Sergei Golubchik
1f0e6837d1 backport a test case for a 5.5 bug fix from the 5.6 tree 2013-01-15 19:15:51 +01:00
Sergei Golubchik
3e3606d21d merge with 5.3.
Take only test cases from MDEV-136 Non-blocking "set read_only"
2012-06-04 17:26:11 +02:00
Sergey Petrunya
5b73a17b3a BUG#1002630: Valgrind warnings 'Invalid read' in subselect_engine::calc_const_tables with SELECT
- In JOIN::exec(), make the having->update_used_tables() call before we've
  made the JOIN::cleanup(full=true) call. The latter frees SJ-Materialization
  structures, which correlated subquery predicate items attempt to walk afterwards.
2012-05-25 01:20:40 +04:00
Sergey Petrunya
6d41fa0d54 BUG#998236: Assertion failure or valgrind errors at best_access_path ...
- Let fix_semijoin_strategies_for_picked_join_order() set 
  POSITION::prefix_record_count for POSITION records that it copies from
  SJ_MATERIALIZATION_INFO::tables. 
  (These records do not have prefix_record_count set, because they are optimized
   as joins-inside-semijoin-nests, without full advance_sj_state() processing).
2012-05-13 13:15:17 +04:00
Sergei Golubchik
1185420da0 5.3 merge 2012-05-21 20:54:41 +02:00
Sergei Golubchik
44cf9ee5f7 5.3 merge 2012-05-04 07:16:38 +02:00
Sergey Petrunya
b9bbe4a18b BUG#978479: Wrong result (extra rows) with derived_with_keys+loosescan+semijoin=ON, materialization=OFF
- Part#2: Don't try to construct a LooseScan access on indexes that do not guarantee 
  index-ordered reads.
2012-04-19 05:37:16 +04:00
Sergey Petrunya
994c6db2d1 BUG#978479: Wrong result (extra rows) with derived_with_keys+loosescan+semijoin=ON, materialization=OFF
Part#1: make EXPLAIN's plan match the one by actual execution: 
Item_subselect::used_tables() should return the same value irrespectively 
of whether we're running an EXPLAIN or a SELECT.
2012-04-19 04:50:32 +04:00
Sergei Golubchik
f860b2aad4 merge 2012-04-07 15:58:46 +02:00
Sergey Petrunya
2a16e7674b BUG#913030: Optimizer chooses a suboptimal excution plan for Q18 from DBT-3
- When doing join optimization, pre-sort the tables so that they mimic the execution
  order we've had with 'semijoin=off'. 
- That way, we will not get regressions when there are two query plans (the old and the
  new) that have indentical costs but different execution times (because of factors that
  the optimizer was not able to take into account).
2012-04-02 21:41:54 +04:00
unknown
335de5db18 Merge mariadb 5.3->mariadb 5.5 2012-03-24 18:21:22 +01:00
Sergey Petrunya
1153d656a9 Merge BUG#952372 2012-03-21 11:18:20 +04:00
Sergey Petrunya
91d17a9c20 BUG#952583: Server crashes in Item_field::fix_after_pullout on INSERT .. SELECT
- Take into account that there may exist Item_field objects with context==NULL.
2012-03-19 01:04:55 +04:00
Sergey Petrunya
5805908bf9 BUG#952372: Server crashes on 2nd execution of PS in find_field_in_tables with semijoin+materialization
- The problem was that convert_subq_to_jtbm() attached the semi-join
  TABLE_LIST object into the wrong list: they used to attach it to the 
  end of parent_lex->leaf_tables.head()->next_local->...->next_local.
  This was apparently inccorect, as one can construct an example where 
  JTBM nest is attached to a table that is inside some mergeable VIEW, which
  breaks (causes crash) for name resolution on the subsequent statement
  re-execution.
- Solution: Attach to the "right" list. The "wording" was copied from
  st_select_lex::handle_derived.
2012-03-18 23:58:20 +04:00
Igor Babaev
8b469eb515 Merge 5.3->5.5. 2012-03-01 14:22:22 -08:00
Igor Babaev
841a74a4d6 Fixed LP bug #939009.
The result of materialization of the right part of an IN subquery predicate
is placed into a temporary table. Each row of the materialized table is
distinct. A unique key over all fields of the temporary table is defined and
created. It allows to perform key look-ups into the table.
The table created for a materialized subquery can be accessed by key as
any other table. The function best_access-path search for the best access
to join a table to a given partial join. With some where conditions this
function considers a possibility of a ref_or_null access. If such access
employs the unique key on the temporary table then when estimating
the cost this access the function tries to use the array rec_per_key. Yet,
such array is not built for this unique key. This causes a crash of the server.

Rows returned by the subquery that contain nulls don't have to be placed
into temporary table, as they cannot be match any row produced by the
left part of the subquery predicate. So all fields of the temporary table
can be defined as non-nullable. In this case any ref_or_null access
to the temporary table does not make any sense and it does not make sense
to estimate such an access.

The fix makes sure that the temporary table for a materialized IN subquery
is defined with columns that are all non-nullable. The also ensures that 
any row with nulls returned by the subquery is not placed into the
temporary table.
2012-02-24 16:50:22 -08:00
Sergei Golubchik
25609313ff 5.3.4 merge 2012-02-15 18:08:08 +01:00
Sergey Petrunya
12bd3dfe29 BUG#923246: Loosescan reports different result than other semijoin methods
- If LooseScan is used with quick select, require that quick select produces 
  data in key order (this disables use of MRR, which can return data in arbitrary order).
2012-01-30 20:34:47 +04:00
Igor Babaev
d25f6bb3eb Merge. 2012-01-27 19:23:08 -08:00
Igor Babaev
4e2b6d45e0 Back-ported test cases for bug #59919 of mysql-5.6 code line. The bug could
not be reproduced in the latest release of mariadb-5.3 as it was was fixed
by Sergey Petrunia when working on the problems concerning outer joins within
in subqueries converted to semi-joins.
2012-01-27 19:01:26 -08:00
Sergey Petrunya
424f56b3ba BUG#920713: Wrong result (missing rows) with firstmatch+BNL, IN subquery, ...
- Disable use of join cache when we're using FirstMatch strategy, and the join
  order is such that subquery's inner tables are interleaved with outer.  Join 
  buffering code is incapable of handling such join orders.

- The testcase requires use of @@debug_optimizer_prefer_join_prefix to hit the bug, 
  but I'm pushing it anyway (including the mention of the variable in .test file), 
  so that it can be found and enabled when/if we get something comparable in the 
  main tree.
2012-01-25 22:05:20 +04:00
Sergey Petrunya
364c07934c Merge 2012-01-25 18:36:57 +04:00
Sergey Petrunya
73cc529b51 BUG#920255: Wrong result (extra rows) with loosescan and IN subquery
The problem was that LooseScan execution code assumed that tab->key holds 
the index used for looseScan. This is only true when range or full index
scan are used. In case of ref access, the index is in tab->ref.key (and 
tab->index==0 which explains how LooseScan passed tests with ref access: they 
used one index)

Fixed by setting/using loosescan_key, which always the correct index#.
2012-01-25 18:33:57 +04:00
Igor Babaev
7bdbdb05ce Back-ported test cases for bugs #54437, #55955, #52329, #57623 from subquery_sj
of mysql-5.6 code line. The bugs could not be reproduced in the latest release
of mariadb-5.3 as they were fixed either when the code of subquery optimization
was back-ported from mysql-6.0 or later when some other bugs were fixed.
2012-01-22 12:54:30 -08:00
Igor Babaev
80009f5862 Back-ported test cases for bugs #53060, #53305, #50358, #49453 from subquery_sj
of mysql-5.6 code line. The bugs could not be reproduced in the latest release
of mariadb-5.3 as they were fixed either when the code of subquery optimization
was back-ported from mysql-6.0 or later when some other bugs were fixed.
2012-01-21 20:58:23 -08:00
Sergei Golubchik
4f435bddfd 5.3 merge 2012-01-13 15:50:02 +01:00
Sergey Petrunya
0b590282fc BUG#912510: Crash in do_copy_not_null with semijoin=ON, firstmatch=ON, aggregate ...
- Create/use do_copy_nullable_row_to_notnull() function for ref access, which is used 
  when copying from not-NULL field in table that can be NULL-complemented to not-NULL field.
2012-01-08 14:43:14 +04:00
Igor Babaev
2b1f0b8757 Back-ported the patch of the mysql-5.6 code line that
fixed several defects in the greedy optimization:

1) The greedy optimizer calculated the 'compare-cost' (CPU-cost)
   for iterating over the partial plan result at each level in
   the query plan as 'record_count / (double) TIME_FOR_COMPARE'

   This cost was only used locally for 'best' calculation at each
   level, and *not* accumulated into the total cost for the query plan.

   This fix added the 'CPU-cost' of processing 'current_record_count'
   records at each level to 'current_read_time' *before* it is used as
   'accumulated cost' argument to recursive 
   best_extension_by_limited_search() calls. This ensured that the
   cost of a huge join-fanout early in the QEP was correctly
   reflected in the cost of the final QEP.

   To get identical cost for a 'best' optimized query and a
   straight_join with the same join order, the same change was also
   applied to optimize_straight_join() and get_partial_join_cost()

2) Furthermore to get equal cost for 'best' optimized query and a
   straight_join the new code substrcated the same '0.001' in
   optimize_straight_join() as it had been already done in
   best_extension_by_limited_search()

3) When best_extension_by_limited_search() aggregated the 'best' plan a
   plan was 'best' by the check :

   'if ((search_depth == 1) || (current_read_time < join->best_read))'

   The term '(search_depth == 1' incorrectly caused a new best plan to be
   collected whenever the specified 'search_depth' was reached - even if
   this partial query plan was more expensive than what we had already
   found.
2011-12-24 08:55:10 -08:00
Igor Babaev
919f19110f Merge 2011-12-15 15:55:00 -08:00
Sergey Petrunya
04e9004fa3 BUG#901399: Wrong result (extra row) with semijoin=ON, materialization=OFF, optimizer_prune_level=0
- Correctly handle plan refinement stage for LooseScan plans: run create_ref_for_key() if LooseScan 
  plan includes a ref access, and if we don't have any fixed key components, switch to a full index scan.
2011-12-16 03:44:25 +04:00
Igor Babaev
a910e8ef5b Made join_cache_level == 2 by default. 2011-12-15 14:26:59 -08:00
Igor Babaev
f5dac20f38 Made the optimizer switch flags 'outer_join_with_cache', 'semijoin_with_cache'
set to 'on' by default.
2011-12-15 00:21:15 -08:00
Igor Babaev
63d32c115d Fixed LP bug #901709.
The cause of the reported assertion failure was a division of a double value by 0.
2011-12-11 19:41:53 -08:00
Michael Widenius
24e452a208 Merge with 5.1 & fixes to IGNORE handling 2011-12-11 19:28:05 +02:00
Michael Widenius
6d4224a31c Merge with 5.2.
no_error handling for select (used by INSERT ... SELECT) still needs to be fixed, but I will do that in a separate commit
2011-12-11 11:34:44 +02:00
Igor Babaev
8a09adb3ea Fixed LP bug #901312.
The function setup_sj_materialization_part1() forgot to set the value
of TABLE::map for any materialized IN subquery. 
This could lead to wrong results for queries with subqueries that were
converted to queries with semijoins.
2011-12-09 14:30:50 -08:00
Sergey Petrunya
255fd6c929 Make subquery Materialization, as well as semi-join Materialization be shown
in EXPLAIN as select_type==MATERIALIZED. 

Before, we had select_type==SUBQUERY and it was difficult to tell materialized
subqueries from uncorrelated scalar-context subqueries.
2011-12-05 01:31:42 +04:00
Sergei Golubchik
effed09bd7 5.3->5.5 merge 2011-11-27 17:46:20 +01:00
Igor Babaev
17b4e4a194 Set new default values for the optimizer switch flags 'derived_merge'
and 'derived_with_keys'. Now they are set on by default.
2011-11-26 14:23:00 -08:00
Sergey Petrunya
3a9edc5f77 Merge 2011-11-25 14:28:43 +04:00