1
0
mirror of https://github.com/MariaDB/server.git synced 2025-11-09 11:41:36 +03:00
Commit Graph

8684 Commits

Author SHA1 Message Date
Sergei Golubchik
3928c7e29a Merge branch '11.2' into 11.3 2023-09-30 14:12:12 +02:00
Vlad Lesin
275f434392 MDEV-25163 Rowid filter does not process storage engine error correctly.
The fix is to return 3-state value from Range_rowid_filter::build()
call:
1. The filter was built successfully;
2. The filter was not built, but the error was not fatal, i.e. there is
no need to rollback transaction. For example, if the size of container to
storevrow ids is not enough;
3. The filter was not built because of fatal error, for example,
deadlock or lock wait timeout from storage engine. In this case we
should stop query plan execution and roll back transaction.

Reviewed by: Sergey Petrunya
2023-09-25 15:13:07 +03:00
Sergei Golubchik
f031889ae4 Merge branch '11.0' into 11.1 2023-09-24 01:46:43 +02:00
Nikita Malyavin
28b4037242 Merge branch '11.2' into 11.3 2023-09-21 14:15:04 +04:00
Sergei Petrunia
e987b9350c MDEV-31496: Make optimizer handle UCASE(varchar_col)=...
(Review input addressed)
(Added handling of UPDATE/DELETE and partitioning w/o index)

If the properties of the used collation allow, do the following
equivalent rewrites:

1. UPPER(key_col)=expr  ->  key_col=expr
   expr=UPPER(key_col)  ->  expr=key_col
   (also rewrite both sides of the equality at the same time)

2. UPPER(key_col) IN (constant-list)  -> key_col IN (constant-list)

- Mark utf8mb{3,4}_general_ci as collations that allow this.
- Add optimizer_switch='sargable_casefold=ON' to control this.
  (ON by default in this patch)
- Cover the rewrite in Optimizer Trace, rewrite name is
  "sargable_casefold_removal".
2023-09-12 17:14:43 +03:00
Dmitry Shulga
de5dba9ebe Merge branch '10.5' into 10.6 2023-09-05 14:44:52 +07:00
Dmitry Shulga
68a925b325 Merge branch '10.4' into 10.5 2023-09-05 12:41:49 +07:00
Dmitry Shulga
d8574dbba3 MDEV-14959: Moved calculation the number of items reserved for exists to in transformation
It is done now before call of select_lex->setup_ref_array()
in order to avoid allocation of SP/PS's memory on its second invocation.
2023-09-02 13:00:00 +07:00
Alexander Barkov
781ec16bd9 An addon change for MDEV-32002 Remove my_casedn_str() in append_identifier() context
There was one more place with my_casedn_str() in append_identifier() context
in TABLE_LIST::print() forgotten in the main patch for MDEV-32002.
Reusing append_identifier_opt_casedn() in this code.
2023-08-24 16:20:37 +04:00
Alexander Barkov
baf00fc553 Merge remote-tracking branch 'origin/10.11' into 11.0 2023-08-18 07:34:54 +04:00
Sergei Petrunia
725bd56834 Merge 10.10 into 10.11 2023-08-17 13:44:05 +03:00
Sergei Petrunia
8aaacb5509 MDEV-31432 tmp_table field accessed after free
Before this patch, the code in Item_field::print() used
this convention (described in sql_explain.h:ExplainDataStructureLifetime):

- By default, the table that Item_field refers to is accessible.
- ANALYZE and SHOW {EXPLAIN|ANALYZE} may print Items after some
  temporary tables have been dropped. They use
  QT_DONT_ACCESS_TMP_TABLES flag. When it is ON, Item_field::print
  will not access the table it refers to, if it is a temp.table

The bug was that EXPLAIN statement also may compute subqueries (depending
on subquery context and @@expensive_subquery_limit setting). After the
computation, the subquery calls JOIN::cleanup(true) which drops some of
its temporary tables. Calling Item_field::print() that refer to such table
will cause an access to free'd memory.

In this patch, we take into account that query optimization can compute
a subquery and discard its temporary tables. Item_field::print() now
assumes that any temporary table might have already been dropped.
This means QT_DONT_ACCESS_TMP_TABLES flag is not needed - we imply it is
always present.

But we also make one exception: derived tables are not freed in
JOIN::cleanup() call. They are freed later in close_thread_tables(),
at the same time when regular tables are closed.
Because of that, Item_field::print may assume that temp.tables
representing derived tables are available.

Initial patch by: Rex Jonston
Reviewed by: Monty <monty@mariadb.org>
2023-08-16 17:26:37 +03:00
Marko Mäkelä
9cd2989589 Merge 10.6 into 10.10 2023-08-16 15:28:42 +03:00
Monty
ca5c122adc MDEV-9938 Prepared statement return wrong result (missing row)
The problem is that the first execution of the prepared statement makes
a permanent optimization of converting the LEFT JOIN to an INNER JOIN.

This is based on the assumption that all the user parameters (?) are
always constants and that parameters to Item_cond() will not change value
from true and false between different executions.

(The example was using IS NULL, which will change value if parameter
depending on if the parameter is NULL or not).

The fix is to change Item_cond::fix_fields() and
Item_cond::eval_not_null_tables() to not threat user parameters as
constants. This will ensure that we don't do the LEFT_JOIN -> INNER
JOIN conversion that causes problems.

There is also some things that needs to be improved regarding
calculations of not_null_tables_cache as we get a different value for
WHERE 1 or t1.a=1
compared to
WHERE t1.a= or 1

Changes done:
- Mark Item_param with the PARAM flag to be able to quickly check
  in Item_cond::eval_not_null_tables() if an item contains a
  prepared statement parameter (just like we check for stored procedure
  parameters).
- Fixed that Item_cond::not_null_tables_cache is not depending on
  order of arguments.
- Don't call item->eval_const_cond() for items that are NOT on the top
  level of the WHERE clause. This removed a lot of unnecessary
  warnings in the test suite!
- Do not reset not_null_tables_cache for not top level items.
- Simplified Item_cond::fix_fields by calling eval_not_null_tables()
  instead of having duplication of all the code in
  eval_not_null_tables().
- Return an error if Item_cond::fix_field() generates an error
  The old code did generate an error in some cases, but not in all
   cases.
  - Fixed all handling of the above error in make_cond_for_tables().
    The error handling by the callers did not exists before which
    could lead to asserts in many different places in the old code).
  - All changes in sql_select.cc are just checking the return value of
    fix_fields() and make_cond_for_tables() and returning an error
    value if fix_fields() returns true or make_cond_for_tables()
    returns NULL and is_error() is set.
- Mark Item_cond as const_item if all arguments returns true for
  can_eval_in_optimize().

Reviewer: Sergei Petrunia <sergey@mariadb.com>
2023-08-15 21:41:01 +03:00
Marko Mäkelä
39b0c2b82a Merge mariadb-11.0.3 into 11.0 2023-08-15 12:01:23 +03:00
Monty
af7a22d2fa MDEV-31501 Assertion `cond_selectivity <= 1.000000001' failed (actual value 1.125)
The problem was that because there was no good indexes for the lineitem
table make_join_select() tried to do a last attempt to find a usable key
and called test_quick_select().
test_quick_select() found an index with fewer matching rows then every
before and that caused a problem in get_range_limit_read_cost(),
which assumes that 'best_rows' is the minium rows matched when all
conditions has been taken into account and thus smaller than rows found
in the range.
Fixed by adjusting best_rows to the least rows in any index after
test_quick_select() has been called.
2023-08-09 10:28:00 +03:00
Oleksandr Byelkin
f5fae75652 Merge branch '11.0' into 11.1 2023-08-09 08:25:14 +02:00
Oleksandr Byelkin
51f9d62005 Merge branch '10.11' into 11.0 2023-08-09 07:53:48 +02:00
Monty
fccfad153f MDEV-31864 Assertion `d >= 0' failed in COST_ADD with join_cache_level > 2 and partitions
The problem was a partitioned table had 0 rows, which caused a division by
zero at hash_join_fanout()
Fix: Do not call hash_join_fanout with 0 rows.
2023-08-08 23:54:48 +03:00
Oleksandr Byelkin
036df5f970 Merge branch '10.10' into 10.11 2023-08-08 14:57:31 +02:00
Oleksandr Byelkin
ced243a099 Merge branch '10.9' into 10.10 2023-08-05 20:34:09 +02:00
Oleksandr Byelkin
998edc374e Merge branch '10.6' into 10.9 2023-08-04 13:27:20 +02:00
Oleksandr Byelkin
c7b6707fe1 Merge branch '10.5' into 10.6 2023-08-04 12:14:00 +02:00
Oleksandr Byelkin
34a8e78581 Merge branch '10.6' into 10.9 2023-08-04 08:01:06 +02:00
Oleg Smirnov
8e8c020fb3 MDEV-31743 Server crash in store_length, assertion failure in Type_handler_string_result::sort_length
After MDEV-21580 the truncation of SORT_FIELD::length
  set_if_smaller(sortorder->length, thd->variables.max_sort_length)

became conditional:
  if (is_variable_sized())
    set_if_smaller(length, thd->variables.max_sort_length)

To provide correct functioning of is_variable_sized() SORT_FIELD::type
must be set properly. This commit adds the necessary initialization
of SORT_FIELD::type to JOIN_TAB::remove_duplicates() as it is done
in filesort's sortlength() function.

DBUG_ASSERT is added to sortlength() just in case to prevent
a possible uint32 overflow
2023-08-03 18:03:31 +07:00
Sergei Petrunia
691e964d23 MDEV-31764: ASAN use-after-poison in trace_engine_stats in ANALYZE JSON
Do not attempt to produce "r_engine_stats" on the temporary (=work) tables.
These tables may be
- re-created during the query execution
- freed during the query execution (This is done e.g. in JOIN::cleanup(),
  before we produce ANALYZE FORMAT=JSON output).

- (Also, make save_explain_data() functions not set handler_for_stats
  to point to handler objects that do not have handler->handler_stats set.
  If the storage engine is not collecting handler_stats, it will not have
  them when we're producing ANALYZE FORMAT=JSON output, either).
2023-08-01 22:32:54 +03:00
Oleksandr Byelkin
6bf8483cac Merge branch '10.5' into 10.6 2023-08-01 15:08:52 +02:00
Marko Mäkelä
c6ac1e39b6 Merge 11.0 into 11.1 2023-07-26 15:13:43 +03:00
Marko Mäkelä
f2b4972bd4 Merge 10.11 into 11.0 2023-07-26 15:13:06 +03:00
Marko Mäkelä
bce3ee704f Merge 10.10 into 10.11 2023-07-26 14:44:43 +03:00
Marko Mäkelä
b1b47264d2 Merge 10.9 into 10.10 2023-07-26 14:17:36 +03:00
Marko Mäkelä
864bbd4d09 Merge 10.6 into 10.9 2023-07-26 13:42:23 +03:00
Sergei Petrunia
6e484c3bd9 MDEV-31577: Make ANALYZE FORMAT=JSON print innodb stats
ANALYZE FORMAT=JSON output now includes table.r_engine_stats which
has the engine statistics. Only non-zero members are printed.

Internally: EXPLAIN data structures Explain_table_acccess and
Explain_update now have handler* handler_for_stats pointer.
It is used to read statistics from handler_for_stats->handler_stats.

The following applies only to 10.9+, backport doesn't use it:

Explain data structures exist after the tables are closed. We avoid
walking invalid pointers using this:
- SQL layer calls Explain_query::notify_tables_are_closed() before
  closing tables.
- After that call, printing of JSON output is disabled. Non-JSON output
  can be printed but we don't access handler_for_stats when doing that.
2023-07-21 16:50:11 +03:00
Oleksandr Byelkin
f52954ef42 Merge commit '10.4' into 10.5 2023-07-20 11:54:52 +02:00
Marko Mäkelä
7cde5c539b Merge 10.6 into 10.9 2023-07-10 11:22:21 +03:00
Monty
99bd226059 MDEV-31558 Add InnoDB engine information to the slow query log
The new statistics is enabled by adding the "engine", "innodb" or "full"
option to --log-slow-verbosity

Example output:

 # Pages_accessed: 184  Pages_read: 95  Pages_updated: 0  Old_rows_read: 1
 # Pages_read_time: 17.0204  Engine_time: 248.1297

Page_read_time is time doing physical reads inside a storage engine.
(Writes cannot be tracked as these are usually done in the background).
Engine_time is the time spent inside the storage engine for the full
duration of the read/write/update calls. It uses the same code as
'analyze statement' for calculating the time spent.

The engine statistics is done with a generic interface that should be
easy for any engine to use. It can also easily be extended to provide
even more statistics.

Currently only InnoDB has counters for Pages_% and Undo_% status.
Engine_time works for all engines.

Implementation details:

class ha_handler_stats holds all engine stats.  This class is included
in handler and THD classes.
While a query is running, all statistics is updated in the handler. In
close_thread_tables() the statistics is added to the THD.

handler::handler_stats is a pointer to where statistics should be
collected. This is set to point to handler::active_handler_stats if
stats are requested. If not, it is set to 0.
handler_stats has also an element, 'active' that is 1 if stats are
requested. This is to allow engines to avoid doing any 'if's while
updating the statistics.

Cloned or partition tables have the pointer set to the base table if
status are requested.

There is a small performance impact when using --log-slow-verbosity=engine:
- All engine calls in 'select' will be timed.
- IO calls for InnoDB reads will be timed.
- Incrementation of counters are done on local variables and accesses
  are inline, so these should have very little impact.
- Statistics has to be reset for each statement for the THD and each
  used handler. This is only 40 bytes, which should be neglectable.
- For partition tables we have to loop over all partitions to update
  the handler_status as part of table_init(). Can be optimized in the
  future to only do this is log-slow-verbosity changes. For this to work
  we have to update handler_status for all opened partitions and
  also for all partitions opened in the future.

Other things:
- Added options 'engine' and 'full' to log-slow-verbosity.
- Some of the new files in the test suite comes from Percona server, which
  has similar status information.
- buf_page_optimistic_get(): Do not increment any counter, since we are
  only validating a pointer, not performing any buf_pool.page_hash lookup.
- Added THD argument to save_explain_data_intern().
- Switched arguments for save_explain_.*_data() to have
  always THD first (generates better code as other functions also have THD
  first).
2023-07-07 12:53:18 +03:00
Sergei Golubchik
1570c6e3e0 bugfix: join a=b where cast(a as type_of_b) can produce NULL
optimizer implicitly assumed that if `a` in `a=b` is not NULL,
then it's safe to convert `a` to the type of `b` and search the
result in the index(b).

which is not always the case, as converting a non-null value
to a different type might produce NULL. And searching for NULL
in the index might find NULL there, so NULL will be equal to NULL,
making `a=b` behave as if it was `a<=>b`
2023-07-05 22:08:29 +02:00
Sergei Golubchik
22e5a5ff6e generalize ER_QUERY_EXCEEDED_ROWS_EXAMINED_LIMIT
make it "query reached <some limit> result may be incomplete"
2023-07-03 15:46:24 +02:00
Oleg Smirnov
d6c6102cad MDEV-30828 Prevent pushing down unions with incorrect ORDER BY
Fake_select_lex->join was prepared at the unit execution stage so
the validation of fake_select_lex before the unit pushdown
was incomplete. That caused pushing down of statements having
an incorrect ORDER BY clause.
This commit moves preparation of the fake_select_lex->join to the unit
prepare() method, before initializing of the pushdown handler,
so incorrect clauses error out before being pushed down
2023-06-30 12:36:47 +07:00
Marko Mäkelä
8290a46d50 Merge 11.0 into 11.1 2023-06-28 09:38:59 +03:00
Marko Mäkelä
71a1a28a49 Merge 10.10 into 10.11 2023-06-27 17:45:06 +03:00
Marko Mäkelä
135e976696 Merge 10.9 into 10.10 2023-06-27 17:43:31 +03:00
Marko Mäkelä
eb6b521f1b Merge 10.6 into 10.9 2023-06-27 13:48:46 +03:00
Marko Mäkelä
493083833b Merge 10.5 into 10.6 2023-06-26 17:11:38 +03:00
Monty
3d617fdc7f MDEV-31375 Assertion `dbl_records <= s->records' failed with optimizer_use_condition_selectivity=1
The reason for the crash wad that 'best splitting' optimization
predicted less rows to be found than what opt_range did.
This code in apply_selectivity_for_table(), when using use_cond_selectivity=1,
was not prepared for this case which caused an assert in debug builds.
Production builds is not affected.

The fix is to choose the smaller of the two row counts. It will have a
minimum on costs when using use_cond_selectivity=1 and should not cause
any problems in production.
2023-06-21 15:44:25 +03:00
Sergei Petrunia
f7e9ac0d88 MDEV-31449: Assertion s->table->opt_range_condition_rows <= s->found_records
Fix a typo in make_join_statistics(): when updating statistics for
derived table, set s->table->... not "table->..."
2023-06-15 11:27:31 +03:00
Marko Mäkelä
3883eb63dc Merge 11.0 into 11.1 2023-06-08 14:09:21 +03:00
Marko Mäkelä
5fb2c031f7 Merge 10.11 into 11.0 2023-06-08 13:49:48 +03:00
Marko Mäkelä
cb9d97ef38 Merge mariadb-11.0.2 into 11.0 2023-06-08 11:35:36 +03:00
Marko Mäkelä
5d7b957eb0 Merge 10.10 into 10.11 2023-06-08 11:23:08 +03:00