Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
MariaDB
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
MariaDB
Commits
9ca355a5
Commit
9ca355a5
authored
Jul 10, 2024
by
Alexey Botchkov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
MDEV-20250
The Insert_prelocking_strategy class added that prunes partition for the INSERT INTO.
parent
7c5fdc9b
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
651 additions
and
5 deletions
+651
-5
sql/field.h
sql/field.h
+6
-0
sql/item.cc
sql/item.cc
+14
-0
sql/item.h
sql/item.h
+2
-0
sql/sql_base.cc
sql/sql_base.cc
+10
-2
sql/sql_base.h
sql/sql_base.h
+3
-2
sql/sql_insert.cc
sql/sql_insert.cc
+576
-1
sql/sql_trigger.cc
sql/sql_trigger.cc
+37
-0
sql/sql_trigger.h
sql/sql_trigger.h
+3
-0
No files found.
sql/field.h
View file @
9ca355a5
...
...
@@ -1223,6 +1223,12 @@ class Field: public Value_source
return
unireg_check
==
TIMESTAMP_DN_FIELD
||
unireg_check
==
TIMESTAMP_DNUN_FIELD
;
}
bool
has_default_update_unireg_check
()
const
{
return
unireg_check
==
TIMESTAMP_UN_FIELD
||
unireg_check
==
TIMESTAMP_DNUN_FIELD
;
}
/*
Mark the field as having a value supplied by the client, thus it should
...
...
sql/item.cc
View file @
9ca355a5
...
...
@@ -910,6 +910,20 @@ bool Item_field::register_field_in_bitmap(void *arg)
}
/*
@brief
Remove field from bitmap supplied as *arg
*/
bool
Item_field
::
remove_field_from_bitmap
(
void
*
arg
)
{
MY_BITMAP
*
bitmap
=
(
MY_BITMAP
*
)
arg
;
DBUG_ASSERT
(
bitmap
);
bitmap_clear_bit
(
bitmap
,
field
->
field_index
);
return
0
;
}
/*
Mark field in write_map
...
...
sql/item.h
View file @
9ca355a5
...
...
@@ -2215,6 +2215,7 @@ class Item :public Value_source,
virtual
bool
register_field_in_read_map
(
void
*
arg
)
{
return
0
;
}
virtual
bool
register_field_in_write_map
(
void
*
arg
)
{
return
0
;
}
virtual
bool
register_field_in_bitmap
(
void
*
arg
)
{
return
0
;
}
virtual
bool
remove_field_from_bitmap
(
void
*
arg
)
{
return
0
;
}
virtual
bool
update_table_bitmaps_processor
(
void
*
arg
)
{
return
0
;
}
virtual
bool
enumerate_field_refs_processor
(
void
*
arg
)
{
return
0
;
}
...
...
@@ -3783,6 +3784,7 @@ class Item_field :public Item_ident,
bool
register_field_in_read_map
(
void
*
arg
)
override
;
bool
register_field_in_write_map
(
void
*
arg
)
override
;
bool
register_field_in_bitmap
(
void
*
arg
)
override
;
bool
remove_field_from_bitmap
(
void
*
arg
)
override
;
bool
check_partition_func_processor
(
void
*
)
override
{
return
false
;}
bool
post_fix_fields_part_expr_processor
(
void
*
bool_arg
)
override
;
bool
check_valid_arguments_processor
(
void
*
bool_arg
)
override
;
...
...
sql/sql_base.cc
View file @
9ca355a5
...
...
@@ -9005,7 +9005,7 @@ static bool vers_update_or_validate_fields(TABLE *table)
bool
fill_record
(
THD
*
thd
,
TABLE
*
table_arg
,
List
<
Item
>
&
fields
,
List
<
Item
>
&
values
,
bool
ignore_errors
,
bool
update
)
bool
ignore_errors
,
bool
update
,
MY_BITMAP
*
bitmap
)
{
List_iterator_fast
<
Item
>
f
(
fields
),
v
(
values
);
Item
*
value
,
*
fld
;
...
...
@@ -9035,6 +9035,9 @@ fill_record(THD *thd, TABLE *table_arg, List<Item> &fields, List<Item> &values,
value
=
v
++
;
DBUG_ASSERT
(
value
);
rfield
=
field
->
field
;
/* If bitmap over wanted fields are set, skip non marked fields. */
if
(
bitmap
&&
!
bitmap_is_set
(
bitmap
,
rfield
->
field_index
))
continue
;
table
=
rfield
->
table
;
if
(
table
->
next_number_field
&&
rfield
->
field_index
==
table
->
next_number_field
->
field_index
)
...
...
@@ -9289,7 +9292,8 @@ fill_record_n_invoke_before_triggers(THD *thd, TABLE *table,
bool
fill_record
(
THD
*
thd
,
TABLE
*
table
,
Field
**
ptr
,
List
<
Item
>
&
values
,
bool
ignore_errors
,
bool
use_value
,
bool
check_for_computability
)
bool
ignore_errors
,
bool
use_value
,
bool
check_for_computability
,
MY_BITMAP
*
bitmap
)
{
List_iterator_fast
<
Item
>
v
(
values
);
List
<
TABLE
>
tbl_list
;
...
...
@@ -9329,6 +9333,10 @@ fill_record(THD *thd, TABLE *table, Field **ptr, List<Item> &values,
/* Ensure the end of the list of values is not reached */
DBUG_ASSERT
(
value
);
/* If bitmap over wanted fields are set, skip non marked fields. */
if
(
bitmap
&&
!
bitmap_is_set
(
bitmap
,
field
->
field_index
))
continue
;
if
(
check_for_computability
&&
value
->
check_is_evaluable_expression_or_error
())
goto
err
;
...
...
sql/sql_base.h
View file @
9ca355a5
...
...
@@ -194,10 +194,11 @@ bool setup_fields(THD *thd, Ref_ptr_array ref_pointer_array,
bool
allow_sum_func
);
void
unfix_fields
(
List
<
Item
>
&
items
);
bool
fill_record
(
THD
*
thd
,
TABLE
*
table_arg
,
List
<
Item
>
&
fields
,
List
<
Item
>
&
values
,
bool
ignore_errors
,
bool
update
);
List
<
Item
>
&
values
,
bool
ignore_errors
,
bool
update
,
MY_BITMAP
*
bitmap
=
NULL
);
bool
fill_record
(
THD
*
thd
,
TABLE
*
table
,
Field
**
field
,
List
<
Item
>
&
values
,
bool
ignore_errors
,
bool
use_value
,
bool
check_for_evaluability
);
bool
check_for_evaluability
,
MY_BITMAP
*
bitmap
=
NULL
);
Field
*
find_field_in_tables
(
THD
*
thd
,
Item_ident
*
item
,
...
...
sql/sql_insert.cc
View file @
9ca355a5
...
...
@@ -700,6 +700,576 @@ Field **TABLE::field_to_fill()
}
class
Insert_prelocking_strategy
:
public
DML_prelocking_strategy
{
bool
m_done
;
TABLE_LIST
*
m_table_list
;
enum_duplicates
m_duplic
;
List
<
Item
>
*
m_fields
;
List
<
Item
>
*
m_update_fields
;
List
<
List_item
>
*
m_values
;
// bool has_prelocking_list;
public:
Insert_prelocking_strategy
(
TABLE_LIST
*
table_list
,
List
<
Item
>
*
fields
,
List
<
Item
>
*
update_fields
,
List
<
List_item
>
*
values
,
enum_duplicates
duplic
)
:
DML_prelocking_strategy
(),
m_table_list
(
table_list
),
m_duplic
(
duplic
),
m_fields
(
fields
),
m_update_fields
(
update_fields
),
m_values
(
values
)
{}
void
reset
(
THD
*
thd
);
bool
handle_end
(
THD
*
thd
);
};
void
Insert_prelocking_strategy
::
reset
(
THD
*
thd
)
{
m_done
=
false
;
}
/**
Allocates and initializes a MY_BITMAP bitmap, containing one bit per column
in the table. The table THD's MEM_ROOT is used to allocate memory.
@param table The table whose columns should be used as a template
for the bitmap.
@param[out] bitmap A pointer to the allocated bitmap.
@retval false Success.
@retval true Memory allocation error.
*/
static
bool
allocate_column_bitmap
(
TABLE
*
table
,
MY_BITMAP
**
bitmap
)
{
DBUG_ENTER
(
"allocate_column_bitmap"
);
const
uint
number_bits
=
table
->
s
->
fields
;
MY_BITMAP
*
the_struct
;
my_bitmap_map
*
the_bits
;
DBUG_ASSERT
(
current_thd
==
table
->
in_use
);
if
(
multi_alloc_root
(
table
->
in_use
->
mem_root
,
&
the_struct
,
sizeof
(
MY_BITMAP
),
&
the_bits
,
bitmap_buffer_size
(
number_bits
),
NULL
)
==
NULL
)
DBUG_RETURN
(
true
);
if
(
my_bitmap_init
(
the_struct
,
the_bits
,
number_bits
)
!=
0
)
DBUG_RETURN
(
true
);
*
bitmap
=
the_struct
;
DBUG_RETURN
(
false
);
}
enum
operation_type
{
INSERT_OPERATION
,
UPDATE_OPERATION
};
static
void
clear_bitmap_fields
(
List
<
Item
>
*
columns
,
MY_BITMAP
*
col_bitmap
)
{
/*
Remove explicitly assigned columns from the bitmap. The assignment
target (lvalue) may not always be a column (Item_field), e.g. we could
be inserting into a view, whose column is actually a base table's column
converted with COLLATE: the lvalue would then be an
Item_func_set_collation.
If the lvalue is an expression tree, we clear all columns in it from the
bitmap.
*/
List_iterator
<
Item
>
lvalue_it
(
*
columns
);
Item
*
lvalue_item
;
while
((
lvalue_item
=
lvalue_it
++
))
lvalue_item
->
walk
(
&
Item
::
remove_field_from_bitmap
,
1
,
col_bitmap
);
}
static
MY_BITMAP
*
get_function_default_columns
(
TABLE
*
table
,
operation_type
optype
,
List
<
Item
>
*
changed_columns
,
List
<
Item
>
*
changed_columns2
)
{
MY_BITMAP
*
function_default_columns
;
DBUG_ENTER
(
"get_function_default_columns"
);
if
(
allocate_column_bitmap
(
table
,
&
function_default_columns
))
DBUG_RETURN
(
NULL
);
/*
Find columns with function default on insert or update, mark them in
bitmap.
*/
for
(
uint
i
=
0
;
i
<
table
->
s
->
fields
;
++
i
)
{
Field
*
f
=
table
->
field
[
i
];
if
((
optype
==
INSERT_OPERATION
&&
f
->
has_default_now_unireg_check
())
||
(
optype
==
UPDATE_OPERATION
&&
f
->
has_default_update_unireg_check
()))
bitmap_set_bit
(
function_default_columns
,
f
->
field_index
);
}
if
(
bitmap_is_clear_all
(
function_default_columns
))
goto
end
;
// no bit set, next step unneeded
clear_bitmap_fields
(
changed_columns
,
function_default_columns
);
if
(
changed_columns2
)
clear_bitmap_fields
(
changed_columns2
,
function_default_columns
);
end:
DBUG_RETURN
(
function_default_columns
);
}
static
MY_BITMAP
*
add_function_default_columns
(
TABLE
*
table
,
MY_BITMAP
*
columns
,
List
<
Item
>
*
changed_columns
,
List
<
Item
>
*
changed_columns2
)
{
MY_BITMAP
*
function_default_columns
;
if
((
function_default_columns
=
get_function_default_columns
(
table
,
INSERT_OPERATION
,
changed_columns
,
changed_columns2
))
==
NULL
)
return
NULL
;
bitmap_union
(
columns
,
function_default_columns
);
return
function_default_columns
;
}
#ifdef WITH_PARTITION_STORAGE_ENGINE
#include "partition_info.h"
/**
Check if fields are in the partitioning expression.
@param fields List of Items (fields)
@return True if any field in the fields list is used by a partitioning expr.
@retval true At least one field in the field list is found.
@retval false No field is within any partitioning expression.
*/
static
bool
is_fields_in_part_expr
(
const
partition_info
*
part_info
,
List
<
Item
>
&
fields
)
{
List_iterator
<
Item
>
it
(
fields
);
Item
*
item
;
Item_field
*
field
;
DBUG_ENTER
(
"is_fields_in_part_expr"
);
while
((
item
=
it
++
))
{
field
=
item
->
field_for_view_update
();
DBUG_ASSERT
(
field
->
field
->
table
==
part_info
->
table
);
if
(
bitmap_is_set
(
&
part_info
->
full_part_field_set
,
field
->
field
->
field_index
))
DBUG_RETURN
(
true
);
}
DBUG_RETURN
(
false
);
}
/*
Check if all partitioning fields are included.
*/
static
bool
is_full_part_expr_in_fields
(
partition_info
*
part_info
,
List
<
Item
>
&
fields
)
{
Field
**
part_field
=
part_info
->
full_part_field_array
;
DBUG_ENTER
(
"is_full_part_expr_in_fields"
);
DBUG_ASSERT
(
*
part_field
);
/*
We could use part_info->full_part_field_set, but since the number of
partitioning fields is (usually) small, it seems better to loop through
them.
*/
do
{
List_iterator
<
Item
>
it
(
fields
);
Item
*
item
;
while
((
item
=
it
++
))
{
Field
*
field
;
field
=
item
->
field_for_view_update
()
->
field
;
if
(
*
part_field
==
field
)
break
;
}
if
(
!
item
)
DBUG_RETURN
(
false
);
}
while
(
*
(
++
part_field
));
DBUG_RETURN
(
true
);
}
static
void
set_function_defaults
(
MY_BITMAP
*
default_columns
,
TABLE
*
table
)
{
DBUG_ENTER
(
"set_function_defaults"
);
/* Quick reject test for checking the case when no defaults are invoked. */
if
(
bitmap_is_clear_all
(
default_columns
))
DBUG_VOID_RETURN
;
//for (uint i= 0; i < table->s->fields; ++i)
// if (bitmap_is_set(m_function_default_columns, i))
// {
// DBUG_ASSERT(bitmap_is_set(table->write_set, i));
// switch (m_optype)
// {
// case INSERT_OPERATION:
// table->field[i]->evaluate_insert_default_function();
// break;
// case UPDATE_OPERATION:
// table->field[i]->evaluate_update_default_function();
// break;
// }
// }
DBUG_VOID_RETURN
;
}
enum
enum_can_prune
{
PRUNE_NO
=
0
,
PRUNE_DEFAULTS
,
PRUNE_YES
};
/**
Checks if possible to do prune partitions on insert.
@param thd Thread context
@param duplic How to handle duplicates
@param update In case of ON DUPLICATE UPDATE, default function fields
@param update_fields In case of ON DUPLICATE UPDATE, which fields to update
@param fields Listed fields
@param empty_values True if values is empty (only defaults)
@param[out] prune_needs_default_values Set on return if copying of default
values is needed
@param[out] can_prune_partitions Enum showing if possible to prune
@param[inout] used_partitions If possible to prune the bitmap
is initialized and cleared
@return Operation status
@retval false Success
@retval true Failure
*/
static
bool
can_prune_insert
(
partition_info
*
part_info
,
THD
*
thd
,
enum_duplicates
duplic
,
const
MY_BITMAP
*
update_function_default_columns
,
List
<
Item
>
&
update_fields
,
List
<
Item
>
&
fields
,
bool
empty_values
,
enum_can_prune
*
can_prune_partitions
,
bool
*
prune_needs_default_values
,
MY_BITMAP
*
used_partitions
)
{
my_bitmap_map
*
bitmap_buf
;
uint
bitmap_bytes
;
uint
num_partitions
=
0
;
TABLE
*
table
=
part_info
->
table
;
DBUG_ENTER
(
"can_prune_insert"
);
*
can_prune_partitions
=
PRUNE_NO
;
if
(
table
->
s
->
db_type
()
->
partition_flags
()
&
HA_USE_AUTO_PARTITION
)
DBUG_RETURN
(
false
);
/*
Cannot prune if there are BEFORE INSERT triggers that change any
partitioning column, since they may change the row to be in another
partition.
*/
if
(
table
->
triggers
&&
table
->
triggers
->
has_triggers
(
TRG_EVENT_INSERT
,
TRG_ACTION_BEFORE
)
&&
table
->
triggers
->
is_fields_updated_in_trigger
(
&
part_info
->
full_part_field_set
,
TRG_EVENT_INSERT
,
TRG_ACTION_BEFORE
))
DBUG_RETURN
(
false
);
/*
Can't prune partitions over generated columns, as their values are
calculated much later.
*/
if
(
table
->
vfield
)
{
Field
**
fld
;
for
(
fld
=
table
->
vfield
;
*
fld
;
fld
++
)
{
if
(
bitmap_is_set
(
&
part_info
->
full_part_field_set
,
(
*
fld
)
->
field_index
))
DBUG_RETURN
(
false
);
}
}
/*
Do not prune if the auto_increment field is used in partioning expression.
TODO: If all rows have not null values and
is not 0 (with NO_AUTO_VALUE_ON_ZERO sql_mode), then pruning is possible!
*/
if
(
table
->
found_next_number_field
&&
bitmap_is_set
(
&
part_info
->
full_part_field_set
,
table
->
found_next_number_field
->
field_index
))
DBUG_RETURN
(
false
);
/*
If updating a field in the partitioning expression, we cannot prune.
Note: TIMESTAMP_AUTO_SET_ON_INSERT is handled by converting Item_null
to the start time of the statement. Which will be the same as in
write_row(). So pruning of TIMESTAMP DEFAULT CURRENT_TIME will work.
But TIMESTAMP_AUTO_SET_ON_UPDATE cannot be pruned if the timestamp
column is a part of any part/subpart expression.
*/
if
(
duplic
==
DUP_UPDATE
)
{
/*
Cannot prune if any field in the partitioning expression can
be updated by ON DUPLICATE UPDATE.
*/
if
(
bitmap_is_overlapping
(
update_function_default_columns
,
&
part_info
->
full_part_field_set
))
DBUG_RETURN
(
false
);
/*
TODO: add check for static update values, which can be pruned.
*/
if
(
is_fields_in_part_expr
(
part_info
,
update_fields
))
DBUG_RETURN
(
false
);
/*
Cannot prune if there are BEFORE UPDATE triggers that changes any
partitioning column, since they may change the row to be in another
partition.
*/
if
(
table
->
triggers
&&
table
->
triggers
->
has_triggers
(
TRG_EVENT_UPDATE
,
TRG_ACTION_BEFORE
)
&&
table
->
triggers
->
is_fields_updated_in_trigger
(
&
part_info
->
full_part_field_set
,
TRG_EVENT_UPDATE
,
TRG_ACTION_BEFORE
))
{
DBUG_RETURN
(
false
);
}
}
/*
If not all partitioning fields are given,
we also must set all non given partitioning fields
to get correct defaults.
TODO: If any gain, we could enhance this by only copy the needed default
fields by
1) check which fields need to be set.
2) only copy those fields from the default record.
*/
if
(
fields
.
elements
)
{
/*
INSERT INTO t (a, b) VALUES ... or
INSERT INTO t SET a=1, b=2;
*/
*
prune_needs_default_values
=
!
is_full_part_expr_in_fields
(
part_info
,
fields
);
}
else
if
(
empty_values
)
/* INSERT INTO t () VALUES () */
*
prune_needs_default_values
=
true
;
else
{
/*
INSERT INTO t VALUES (...) we must get values for
all fields in table from VALUES (...) part, so no defaults
are needed.
*/
*
prune_needs_default_values
=
false
;
}
/* Pruning possible, have to initialize the used_partitions bitmap. */
num_partitions
=
part_info
->
lock_partitions
.
n_bits
;
bitmap_bytes
=
bitmap_buffer_size
(
num_partitions
);
if
(
!
(
bitmap_buf
=
(
my_bitmap_map
*
)
thd
->
alloc
(
bitmap_bytes
)))
{
my_error
(
ER_OUTOFMEMORY
,
MYF
(
ME_FATAL
),
bitmap_bytes
);
DBUG_RETURN
(
true
);
}
/* Can't fails - buffer prealloced. */
(
void
)
my_bitmap_init
(
used_partitions
,
bitmap_buf
,
num_partitions
);
/* If no partitioning field in set (e.g. defaults) check pruning only once. */
if
(
fields
.
elements
&&
!
is_fields_in_part_expr
(
part_info
,
fields
))
*
can_prune_partitions
=
PRUNE_DEFAULTS
;
else
*
can_prune_partitions
=
PRUNE_YES
;
DBUG_RETURN
(
false
);
}
static
bool
set_used_partition
(
partition_info
*
part_info
,
List
<
Item
>
&
fields
,
List
<
Item
>
&
values
,
MY_BITMAP
*
default_columns
,
bool
copy_default_values
,
MY_BITMAP
*
used_partitions
)
{
TABLE
*
table
=
part_info
->
table
;
THD
*
thd
=
table
->
in_use
;
uint32
part_id
;
Dummy_error_handler
error_handler
;
bool
ret
=
true
;
DBUG_ENTER
(
"set_used_partition"
);
DBUG_ASSERT
(
thd
);
/* Only allow checking of constant values */
List_iterator_fast
<
Item
>
v
(
values
);
Item
*
item
;
while
((
item
=
v
++
))
{
if
(
!
item
->
const_item
())
goto
err
;
}
if
(
copy_default_values
)
restore_record
(
table
,
s
->
default_values
);
thd
->
push_internal_handler
(
&
error_handler
);
if
(
fields
.
elements
||
!
values
.
elements
)
{
/*
INSERT INTO t1 (fields) VALUES ...
INSERT INTO t1 VALUES ()
*/
if
(
fill_record
(
thd
,
table
,
fields
,
values
,
false
,
false
,
&
part_info
->
full_part_field_set
))
goto
err
;
}
else
{
/*
INSERT INTO t1 VALUES (values)
*/
if
(
fill_record
(
thd
,
table
,
table
->
field
,
values
,
false
,
false
,
&
part_info
->
full_part_field_set
))
goto
err
;
}
DBUG_ASSERT
(
!
table
->
auto_increment_field_not_null
);
/*
Evaluate DEFAULT functions like CURRENT_TIMESTAMP.
TODO: avoid setting non partitioning fields default value, to avoid
overhead. Not yet done, since mostly only one DEFAULT function per
table, or at least very few such columns.
*/
if
(
bitmap_is_overlapping
(
default_columns
,
&
part_info
->
full_part_field_set
))
set_function_defaults
(
default_columns
,
table
);
{
/*
This function is used in INSERT; 'values' are supplied by user,
or are default values, not values read from a table, so read_set is
irrelevant.
*/
MY_BITMAP
*
old_map
=
dbug_tmp_use_all_columns
(
table
,
&
table
->
read_set
);
longlong
func_value
;
const
int
rc
=
part_info
->
get_partition_id
(
part_info
,
&
part_id
,
&
func_value
);
dbug_tmp_restore_column_map
(
&
table
->
read_set
,
old_map
);
if
(
rc
)
goto
err
;
}
DBUG_PRINT
(
"info"
,
(
"Insert into partition %u"
,
part_id
));
bitmap_set_bit
(
used_partitions
,
part_id
);
ret
=
false
;
err:
thd
->
pop_internal_handler
();
DBUG_RETURN
(
ret
);
}
bool
Insert_prelocking_strategy
::
handle_end
(
THD
*
thd
)
{
MY_BITMAP
*
function_default_columns
;
MY_BITMAP
*
upd_function_default_columns
;
bool
prune_needs_default_values
;
enum_can_prune
can_prune_partitions
;
MY_BITMAP
used_partitions
;
List_item
*
values
;
/*uint num_partitions= 0;*/
DBUG_ENTER
(
"Insert_prelocking_strategy::handle_end"
);
if
(
m_done
)
DBUG_RETURN
(
false
);
m_done
=
true
;
TABLE
*
table
=
m_table_list
->
table
;
if
(
table
->
part_info
==
NULL
||
m_table_list
->
lock_type
==
TL_WRITE_DELAYED
)
DBUG_RETURN
(
false
);
/*
if (mysql_handle_derived(lex, DT_INIT) ||
mysql_handle_derived(lex, DT_MERGE_FOR_INSERT) ||
mysql_handle_derived(lex, DT_PREPARE))
DBUG_RETURN(1);
if (table_list->has_period() && table_list->is_view_or_derived())
{
my_error(ER_IT_IS_A_VIEW, MYF(0), table_list->table_name.str);
DBUG_RETURN(TRUE);
}
*/
/* Must be done before can_prune_insert, due to internal initialization. */
if
((
function_default_columns
=
add_function_default_columns
(
table
,
table
->
write_set
,
m_fields
,
NULL
)))
goto
abort
;
if
(
m_duplic
==
DUP_UPDATE
&&
(
upd_function_default_columns
=
add_function_default_columns
(
table
,
table
->
write_set
,
m_update_fields
,
NULL
)))
goto
abort
;
/* if (!is_locked) check insert_delayed */
{
List_iterator_fast
<
List_item
>
its
(
*
m_values
);
values
=
its
++
;
if
(
can_prune_insert
(
table
->
part_info
,
thd
,
m_duplic
,
upd_function_default_columns
,
*
m_update_fields
,
*
m_fields
,
!
MY_TEST
(
values
->
elements
),
&
can_prune_partitions
,
&
prune_needs_default_values
,
&
used_partitions
))
goto
abort
;
if
(
can_prune_partitions
!=
PRUNE_NO
)
{
/*num_partitions= table->part_info->lock_partitions.n_bits;*/
/*
Pruning probably possible, all partitions is unmarked for read/lock,
and we must now add them on row by row basis.
Check the first INSERT value.
Do not fail here, since that would break MyISAM behavior of inserting
all rows before the failing row.
PRUNE_DEFAULTS means the partitioning fields are only set to DEFAULT
values, so we only need to check the first INSERT value, since all the
rest will be in the same partition.
*/
if
(
set_used_partition
(
table
->
part_info
,
*
m_fields
,
*
values
,
function_default_columns
,
prune_needs_default_values
,
&
used_partitions
))
can_prune_partitions
=
PRUNE_NO
;
}
}
DBUG_RETURN
(
0
);
abort:
DBUG_RETURN
(
1
);
}
#endif
/*WITH_PARTITION_STORAGE_ENGINE*/
/**
INSERT statement implementation
...
...
@@ -779,7 +1349,12 @@ bool mysql_insert(THD *thd, TABLE_LIST *table_list,
}
else
{
if
(
open_and_lock_tables
(
thd
,
table_list
,
TRUE
,
0
))
Insert_prelocking_strategy
prelocking_strategy
(
table_list
,
&
fields
,
&
update_fields
,
&
values_list
,
duplic
);
if
(
open_and_lock_tables
(
thd
,
thd
->
lex
->
create_info
,
table_list
,
TRUE
,
0
,
&
prelocking_strategy
))
DBUG_RETURN
(
TRUE
);
}
...
...
sql/sql_trigger.cc
View file @
9ca355a5
...
...
@@ -2597,6 +2597,43 @@ add_tables_and_routines_for_triggers(THD *thd,
}
/**
Check if any of the marked fields are used in the trigger.
@param used_fields Bitmap over fields to check
@param event_type Type of event triggers for which we are going to inspect
@param action_time Type of trigger action time we are going to inspect
*/
bool
Table_triggers_list
::
is_fields_updated_in_trigger
(
MY_BITMAP
*
used_fields
,
trg_event_type
event_type
,
trg_action_time_type
action_time
)
{
DBUG_ASSERT
(
used_fields
->
n_bits
==
trigger_table
->
s
->
fields
);
for
(
Trigger
*
trigger
=
get_trigger
(
event_type
,
action_time
);
trigger
;
trigger
=
trigger
->
next
)
{
for
(
SQL_I_List
<
Item_trigger_field
>
*
trg_fld_lst
=
trigger
->
body
->
m_trg_table_fields
.
first
;
trg_fld_lst
;
trg_fld_lst
=
trg_fld_lst
->
first
->
next_trig_field_list
)
{
for
(
Item_trigger_field
*
trg_field
=
trg_fld_lst
->
first
;
trg_field
;
trg_field
=
trg_field
->
next_trg_field
)
{
if
(
trg_field
->
field_idx
!=
NO_CACHED_FIELD_INDEX
&&
bitmap_is_set
(
used_fields
,
trg_field
->
field_idx
)
&&
trg_field
->
get_settable_routine_parameter
())
return
true
;
}
}
}
return
false
;
}
/**
Mark fields of subject table which we read/set in its triggers
as such.
...
...
sql/sql_trigger.h
View file @
9ca355a5
...
...
@@ -307,6 +307,9 @@ class Table_triggers_list: public Sql_alloc
Query_tables_list
*
prelocking_ctx
,
TABLE_LIST
*
table_list
);
bool
is_fields_updated_in_trigger
(
MY_BITMAP
*
used_fields
,
trg_event_type
event_type
,
trg_action_time_type
action_time
);
Field
**
nullable_fields
()
{
return
record0_field
;
}
void
reset_extra_null_bitmap
()
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment