Given that key part lengths may differ on two sides of foreign key relation,
it's important to use a child (referenced) table's keys during the lengths
calculation.
Two different problems are fixed here:
1. A bogus inet6 -> time match turned to be possible:
inet6 size is 20, while time size is 3, so the bigger is pointing to a smaller
When innodb makes a referencial check, it compares to the min(len1, len2), i.e.
in this case 3 bytes, and then checks that the rest is filled with 0x20,
that is, space-padded.
Probably, this is just a bogus hole in semantic checks, but now this reference
is possible. Yet, implementing correct checks for such cases will require a lot
of effort, so let's just skip such keys.
2. char(15) -> varchar(15) record check caused use-of-uninitialized.
This is a tough one. A from-table and a to-table store data in different
formats, both in and in key, which was a problem for key_copy.
The solution is to use save_in_field to first convert the data to the format of
the to-table's record, and then use a to-table's field to store the string in
the key.
Note that varchar(15) -> char(15) even doesn't work well in innodb, and
insertion is impossible, unless foreign_key_checks is off. However, cascade
deletions do work, though, again, with a quirk (see the tests).
LOAD INDEX doesn't initialize Lex->check_opt and mysql_preload_keys doesn't use
it. However, Check_table_prelocking_strategy did, and it's always used in
opening table.
One solution could be using a different prelocking strategy for
mysql_preload_keys.
Let's instead just pass a correct check_opt to Check_table_prelocking_strategy.
Base task: MDEV-34309
... TABLE with FK
The normal order of things in prepared statement is:
1. open tables during prepare
2. use them during all the executions
Currently, tables are opened in the body of CHECK TABLE's execution part.
This is motivated by the nature of this statement: we have to run the checks for
all the tables specified in the list, event if some of them fail to open.
Rewriting it as in normal order is possible, but is out of scope of this task.
That is, we shouldn't activate stmt_arena when constructing the referential
tables list.
It's not enough, since the next statement execution will try to reuse all the
TABLE_LIST's in lex->query_list, but the referential tables are allocated on the
normal query arena, so they should be cleaned up from that list.
Given how specific the open_only_one_table work is, we only have to re-link
table lists as they were before the tables are opened. It's enough to just
assign next_local to next_global for each table specified by
user, i.e. in lex->first_select_lex().
lex->query_tables_last and other lex fields are already maintained by that
function.
Base task: MDEV-34309
In BIT -> TIME reference, BIT length is 1, and TIME length is 4.
It's likely a quirk, that such relation is possible, since 0 -> 0 is not a valid
reference.
However, some parts of key_copy should be fixed:
1. Make sure that key_length is deduced according to to_key_info key_parts.
2. Mind the case when to_key_part is NOT NULL, but key_part is NULL.
3. Use correct length in field->get_key_image call.
Also fix the double run of checks of self-referencing keys.
Base task: MDEV-34309
### Preamble
C++ initializes objects in three stages:
1. Optionally, zero-initializes the object fields.
2. Member-initializes fields that are explicitly set.
3. If applicable, calls a constructor.
The following expressions:
x = new T[N];
x = new T;
T x;
only member-initialize and call a default constructor. Stage 1 is skipped,
because () braces are omitted.
This is known as default-initialization.
Apart from Stage 2, the following:
x = new T[N]();
x = new T();
const T &x = T();
Is known as value-initialization:
If no default constructor is present, infer zero-initialization.
Otherwise, the default constructor is called.
Note that it's not possible to write `T x();`, as it is ambiguous to a function
call.
Since C++11, it's also possible to zero initialize objects with '{}' braces:
x = new T[N]{};
x = new T{};
T x{};
This also both zero-initializes and calls a default constructor.
There is no much difference in between empty-braced () and {}. Both call a
default constructor or initializer-list constructor, when available. Having both
constructors is ambiguous.
Scalars (i.e. fundamental data types) and POD types have no constructor.
Therefore, stage 2 for them is skipped.
Other than that, there is no much difference in the result
Exambles:
new char[123] -- would return an uninitialized array of char.
new char[123]() -- forces zero-initialization
new char[123]{} -- forces zero-initialization
new char[123]{123} -- forces zero-initialization, and also value-initializes
the first element to 123
struct A {
int x = 0xaf;
int y;
}
All of the following:
A a;
A *a = new A;
A *a = new A[123];
Causes member A::x be initialized to 0xaf, since it happens at
value-initialization stage. A::y is left uninitialized.
A *a = new A[123] {};
and other similars result in {.x=0xaf, .y=0}.
### In this commit
Change all the calls to thd->calloc() to new(thd) T[N]{}, or new(thd) T{}.
POD types will be zero-initialized, so a special attention should be put to
classes with default constructors.
Among all uses, two cases of interest were found:
1. TABLE_LIST: has a default constructor TABLE_LIST() = default. This infers
zero-initialization behavior (i.e. as if there's no constructor).
2. USER_AUTH: has a default constructor, that initializes all fields. Strings
are initialized to "", which is fine.
3. Security_context: had a custom default constructor, initializing only two
fields. It was removed, and fields are made member-initialized.
QUICK_RANGE_SELECT::clone is never used, and besides it does not inherit
Sql_alloc, so the usage of `new` without agruments would be leak-prone.
So, remove it.
Remove THD:alloc() completely.
THD::calloc will still stay. It's still possible to use thd_alloc() as a plain C
replacement.
my_bitmap.h: add my_bitmap_array_size(bits) to count in my_bitmap_map, which is
ulonglong
All the bitmap arrays are now allocated with new my_bitmap_map[size]. This is
bigger than it was before, but essentially aligns the allocated array to
my_bitmap_map size, which was violated before.
sql_select: replace thd->alloc() with thd_alloc()
table_status_by_host_context: add default
sql_parse.cc: add_proc_to_list: add struct Order_Item
Made as a part of MDEV-34309
Note that List and QUICK_RANGE inherit Sql_alloc, so they use new (mem_root).
sql_select.cc: remove rollup_fields->empty() since it's now done by a List
constructor.
Made as a part of MDEV-34309
Sql_alloc: add operator new(size_t, const THD *) noexcept. Also change throw()
to noexcept in other Sql_alloc operators.
Item: add operator new(size_t, const THD *).
The implementations are in the bottom of item.cc and sql_class.cc.
Made as a part of MDEV-34309
Ignore snapshot isolation conflict during fragment removal, before
streaming transaction commits. This happens when a streaming
transaction creates a read view that precedes the INSERTion of
fragments into the streaming_log table. Fragments are INSERTed
using a different transaction. These fragment are then removed
as part of COMMIT of the streaming transaction. This fragment
removal operation could fail when the fragments were not part
the transaction's read view, thus violating snapshot isolation.
Item_char_typecast::val_str_generic() uses Item::str_value as a buffer.
Item::val_str_ascii() also used Item::str_value as a buffer.
As a result, str_value tried to copy to itself.
Fixing val_str_ascii() to use a local buffer instead of str_value.
Backport of 2f5174e556:
MDEV-33075 Resolve server shutdown issues on macOS, Solaris, and FreeBSD.
This commit addresses multiple server shutdown problems observed on macOS,
Solaris, and FreeBSD:
1. Corrected a non-portable assumption where socket shutdown was expected
to wake up poll() with listening sockets in the main thread.
Use more robust self-pipe to wake up poll() by writing to the pipe's write
end.
Signed-off-by: Ivan Prisyazhnyy <john.koepi@gmail.com>
Backport of 2f5174e556:
MDEV-33075 Resolve server shutdown issues on macOS, Solaris, and FreeBSD.
This commit addresses multiple server shutdown problems observed on macOS,
Solaris, and FreeBSD:
2. Fixed a random crash on macOS from pthread_kill(signal_handler)
when the signal_handler was detached and the thread had already exited.
Use more robust `kill(getpid(), SIGTERM)` to wake up the signal handler
thread.
Additionally, the shutdown code underwent light refactoring
for better readability and maintainability:
- Modified `break_connect_loop()` to no longer wait for the main thread,
aligning behavior with Windows (since 10.4).
Backport of 2f5174e556:
MDEV-33075 Resolve server shutdown issues on macOS, Solaris, and FreeBSD.
This commit addresses multiple server shutdown problems observed on macOS,
Solaris, and FreeBSD:
3. Made sure, that signal handler thread always exits once `abort_loop` is
set, and also calls `my_thread_end()` and clears `signal_thread_in_use`
when exiting.
This fixes warning "1 thread did not exit" by `my_global_thread_end()`
seen on FreeBSD/macOS when the process is terminated via signal.
Additionally, the shutdown code underwent light refactoring
for better readability and maintainability:
- Removed dead code related to the unused `USE_ONE_SIGNAL_HAND`
preprocessor constant.
Signed-off-by: Ivan Prisyazhnyy <john.koepi@gmail.com>
Backport of 2f5174e556:
MDEV-33075 Resolve server shutdown issues on macOS, Solaris, and FreeBSD.
Eliminated support for `#ifndef HAVE_POLL` in `handle_connection_sockets`
This code is also dead, since 10.4
Signed-off-by: Ivan Prisyazhnyy <john.koepi@gmail.com>
Problem was that at wsrep_to_isolation_end saved_lock_wait_timeout
variable was set to thd->variables.lock_wait_timeout when RSU
is used and variable value was 0 leading sporadic lock wait timeout
errors. Fixed by removing incorrect variable set.
Signed-off-by: Julius Goryavsky <julius.goryavsky@mariadb.com>
Partial commit of the greater MDEV-34348 scope.
MDEV-34348: MariaDB is violating clang-16 -Wcast-function-type-strict
Various additional fixes, each too small to put into
their own commit.
Reviewed By:
============
Marko Mäkelä <marko.makela@mariadb.com>
Partial commit of the greater MDEV-34348 scope.
MDEV-34348: MariaDB is violating clang-16 -Wcast-function-type-strict
Reviewed By:
============
Marko Mäkelä <marko.makela@mariadb.com>
Partial commit of the greater MDEV-34348 scope.
MDEV-34348: MariaDB is violating clang-16 -Wcast-function-type-strict
Reviewed By:
============
Marko Mäkelä <marko.makela@mariadb.com>
Partial commit of the greater MDEV-34348 scope.
MDEV-34348: MariaDB is violating clang-16 -Wcast-function-type-strict
Reviewed By:
============
Marko Mäkelä <marko.makela@mariadb.com>
Partial commit of the greater MDEV-34348 scope.
MDEV-34348: MariaDB is violating clang-16 -Wcast-function-type-strict
Change the type of my_hash_get_key to:
1) Return const
2) Change the context parameter to be const void*
Also fix casting in hash adjacent areas.
Reviewed By:
============
Marko Mäkelä <marko.makela@mariadb.com>
Partial commit of the greater MDEV-34348 scope.
MDEV-34348: MariaDB is violating clang-16 -Wcast-function-type-strict
The functions queue_compare, qsort2_cmp, and qsort_cmp2
all had similar interfaces, and were used interchangable
and unsafely cast to one another.
This patch consolidates the functions all into the
qsort_cmp2 interface.
Reviewed By:
============
Marko Mäkelä <marko.makela@mariadb.com>
Item_{date|datetime}_typecase::get_date() erroneously passed the
TIME_INTERVAL_DAY flag from the caller to args[0] which made
CAST('100000:00:00' AS DATETIME) parse '100000:00:00' as TIME
rather that DATETIME.
Suppressing this flag.
LEAST() and GREATEST() erroneously calcucalted the result as signed
for BIGINT UNSIGNED arguments.
Adding a new method for unsigned arguments:
Item_func_min_max::val_uint_native()
Item_func_substr::fix_length_and_dec() incorrecltly calculated its max_length
to 0 when a huge number was passed as the third argument:
substring('hello', 1, 4294967295)
Fixing this.
Limit only signed integer fields fields to LONGLONG_MAX.
Double and decimal fields do not need this limit, as they
can store integers up to ULONGLONG_MAX without problems.