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
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
mariadb
Commits
4864dce0
Commit
4864dce0
authored
Dec 13, 2004
by
acurtis@pcgem.rdg.cyberkinetica.com
Browse files
Options
Browse Files
Download
Plain Diff
Merge bk-internal.mysql.com:/home/bk/mysql-4.1
into pcgem.rdg.cyberkinetica.com:/usr/home/acurtis/work/wl2274.2
parents
450ea0e0
9818cadd
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
157 additions
and
69 deletions
+157
-69
mysql-test/r/insert_update.result
mysql-test/r/insert_update.result
+62
-0
mysql-test/t/insert_update.test
mysql-test/t/insert_update.test
+31
-0
sql/mysql_priv.h
sql/mysql_priv.h
+0
-1
sql/sql_class.h
sql/sql_class.h
+10
-0
sql/sql_insert.cc
sql/sql_insert.cc
+15
-12
sql/sql_lex.cc
sql/sql_lex.cc
+1
-0
sql/sql_lex.h
sql/sql_lex.h
+1
-1
sql/sql_parse.cc
sql/sql_parse.cc
+14
-31
sql/sql_prepare.cc
sql/sql_prepare.cc
+1
-1
sql/sql_yacc.yy
sql/sql_yacc.yy
+22
-23
No files found.
mysql-test/r/insert_update.result
View file @
4864dce0
...
...
@@ -105,3 +105,65 @@ a b
8 28
9 29
drop table t1;
CREATE TABLE t1 (a INT, b INT, c INT, UNIQUE (A), UNIQUE(B));
INSERT t1 VALUES (1,2,10), (3,4,20);
INSERT t1 SELECT 5,6,30 FROM DUAL ON DUPLICATE KEY UPDATE c=c+100;
SELECT * FROM t1;
a b c
1 2 10
3 4 20
5 6 30
INSERT t1 SELECT 5,7,40 FROM DUAL ON DUPLICATE KEY UPDATE c=c+100;
SELECT * FROM t1;
a b c
1 2 10
3 4 20
5 6 130
INSERT t1 SELECT 8,4,50 FROM DUAL ON DUPLICATE KEY UPDATE c=c+1000;
SELECT * FROM t1;
a b c
1 2 10
3 4 1020
5 6 130
INSERT t1 SELECT 1,4,60 FROM DUAL ON DUPLICATE KEY UPDATE c=c+10000;
SELECT * FROM t1;
a b c
1 2 10010
3 4 1020
5 6 130
INSERT t1 SELECT 1,9,70 FROM DUAL ON DUPLICATE KEY UPDATE c=c+100000, b=4;
ERROR 23000: Duplicate entry '4' for key 2
SELECT * FROM t1;
a b c
1 2 10010
3 4 1020
5 6 130
TRUNCATE TABLE t1;
INSERT t1 VALUES (1,2,10), (3,4,20);
CREATE TABLE t2 (x INT, y INT, z INT, d INT);
INSERT t2 VALUES (5,6,30,1), (7,4,40,1), (8,9,60,1);
INSERT t2 VALUES (2,1,11,2), (7,4,40,2);
INSERT t1 SELECT x,y,z FROM t2 WHERE d=1 ON DUPLICATE KEY UPDATE c=c+100;
SELECT * FROM t1;
a b c
1 2 10
3 4 120
5 6 30
8 9 60
INSERT t1 SET a=5 ON DUPLICATE KEY UPDATE b=0;
SELECT * FROM t1;
a b c
1 2 10
3 4 120
5 0 30
8 9 60
INSERT t1 SELECT x,y,z FROM t2 WHERE d=2 ON DUPLICATE KEY UPDATE c=c+VALUES(a);
SELECT *, VALUES(a) FROM t1;
a b c VALUES(a)
1 2 10 NULL
3 4 127 NULL
5 0 30 NULL
8 9 60 NULL
2 1 11 NULL
DROP TABLE t1;
DROP TABLE t2;
mysql-test/t/insert_update.test
View file @
4864dce0
...
...
@@ -48,3 +48,34 @@ disable_info;
select
*
from
t1
;
drop
table
t1
;
# WorkLog #2274 - enable INSERT .. SELECT .. UPDATE syntax
# Same tests as beginning of this test except that insert source
# is a result from a select statement
#
CREATE
TABLE
t1
(
a
INT
,
b
INT
,
c
INT
,
UNIQUE
(
A
),
UNIQUE
(
B
));
INSERT
t1
VALUES
(
1
,
2
,
10
),
(
3
,
4
,
20
);
INSERT
t1
SELECT
5
,
6
,
30
FROM
DUAL
ON
DUPLICATE
KEY
UPDATE
c
=
c
+
100
;
SELECT
*
FROM
t1
;
INSERT
t1
SELECT
5
,
7
,
40
FROM
DUAL
ON
DUPLICATE
KEY
UPDATE
c
=
c
+
100
;
SELECT
*
FROM
t1
;
INSERT
t1
SELECT
8
,
4
,
50
FROM
DUAL
ON
DUPLICATE
KEY
UPDATE
c
=
c
+
1000
;
SELECT
*
FROM
t1
;
INSERT
t1
SELECT
1
,
4
,
60
FROM
DUAL
ON
DUPLICATE
KEY
UPDATE
c
=
c
+
10000
;
SELECT
*
FROM
t1
;
--
error
1062
INSERT
t1
SELECT
1
,
9
,
70
FROM
DUAL
ON
DUPLICATE
KEY
UPDATE
c
=
c
+
100000
,
b
=
4
;
SELECT
*
FROM
t1
;
TRUNCATE
TABLE
t1
;
INSERT
t1
VALUES
(
1
,
2
,
10
),
(
3
,
4
,
20
);
CREATE
TABLE
t2
(
x
INT
,
y
INT
,
z
INT
,
d
INT
);
INSERT
t2
VALUES
(
5
,
6
,
30
,
1
),
(
7
,
4
,
40
,
1
),
(
8
,
9
,
60
,
1
);
INSERT
t2
VALUES
(
2
,
1
,
11
,
2
),
(
7
,
4
,
40
,
2
);
INSERT
t1
SELECT
x
,
y
,
z
FROM
t2
WHERE
d
=
1
ON
DUPLICATE
KEY
UPDATE
c
=
c
+
100
;
SELECT
*
FROM
t1
;
INSERT
t1
SET
a
=
5
ON
DUPLICATE
KEY
UPDATE
b
=
0
;
SELECT
*
FROM
t1
;
INSERT
t1
SELECT
x
,
y
,
z
FROM
t2
WHERE
d
=
2
ON
DUPLICATE
KEY
UPDATE
c
=
c
+
VALUES
(
a
);
SELECT
*
,
VALUES
(
a
)
FROM
t1
;
DROP
TABLE
t1
;
DROP
TABLE
t2
;
sql/mysql_priv.h
View file @
4864dce0
...
...
@@ -362,7 +362,6 @@ bool check_merge_table_access(THD *thd, char *db,
TABLE_LIST
*
table_list
);
int
multi_update_precheck
(
THD
*
thd
,
TABLE_LIST
*
tables
);
int
multi_delete_precheck
(
THD
*
thd
,
TABLE_LIST
*
tables
,
uint
*
table_count
);
int
insert_select_precheck
(
THD
*
thd
,
TABLE_LIST
*
tables
);
int
update_precheck
(
THD
*
thd
,
TABLE_LIST
*
tables
);
int
delete_precheck
(
THD
*
thd
,
TABLE_LIST
*
tables
);
int
insert_precheck
(
THD
*
thd
,
TABLE_LIST
*
tables
);
...
...
sql/sql_class.h
View file @
4864dce0
...
...
@@ -1238,6 +1238,16 @@ class select_insert :public select_result_interceptor {
bzero
((
char
*
)
&
info
,
sizeof
(
info
));
info
.
handle_duplicates
=
duplic
;
}
select_insert
(
TABLE
*
table_par
,
List
<
Item
>
*
fields_par
,
List
<
Item
>
*
update_fields
,
List
<
Item
>
*
update_values
,
enum_duplicates
duplic
)
:
table
(
table_par
),
fields
(
fields_par
),
last_insert_id
(
0
)
{
bzero
((
char
*
)
&
info
,
sizeof
(
info
));
info
.
handle_duplicates
=
duplic
;
info
.
update_fields
=
update_fields
;
info
.
update_values
=
update_values
;
}
~
select_insert
();
int
prepare
(
List
<
Item
>
&
list
,
SELECT_LEX_UNIT
*
u
);
bool
send_data
(
List
<
Item
>
&
items
);
...
...
sql/sql_insert.cc
View file @
4864dce0
...
...
@@ -197,15 +197,6 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
thd
->
used_tables
=
0
;
values
=
its
++
;
if
(
duplic
==
DUP_UPDATE
&&
!
table
->
insert_values
)
{
/* it should be allocated before Item::fix_fields() */
table
->
insert_values
=
(
byte
*
)
alloc_root
(
thd
->
mem_root
,
table
->
rec_buff_length
);
if
(
!
table
->
insert_values
)
goto
abort
;
}
if
(
mysql_prepare_insert
(
thd
,
table_list
,
insert_table_list
,
table
,
fields
,
values
,
update_fields
,
update_values
,
duplic
))
...
...
@@ -448,14 +439,24 @@ int mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
enum_duplicates
duplic
)
{
DBUG_ENTER
(
"mysql_prepare_insert"
);
if
(
check_insert_fields
(
thd
,
table
,
fields
,
*
values
,
1
)
||
if
(
duplic
==
DUP_UPDATE
&&
!
table
->
insert_values
)
{
/* it should be allocated before Item::fix_fields() */
table
->
insert_values
=
(
byte
*
)
alloc_root
(
thd
->
mem_root
,
table
->
rec_buff_length
);
if
(
!
table
->
insert_values
)
DBUG_RETURN
(
-
1
);
}
if
((
values
&&
check_insert_fields
(
thd
,
table
,
fields
,
*
values
,
1
))
||
setup_tables
(
insert_table_list
)
||
setup_fields
(
thd
,
0
,
insert_table_list
,
*
values
,
0
,
0
,
0
)
||
(
values
&&
setup_fields
(
thd
,
0
,
insert_table_list
,
*
values
,
0
,
0
,
0
)
)
||
(
duplic
==
DUP_UPDATE
&&
(
setup_fields
(
thd
,
0
,
insert_table_list
,
update_fields
,
1
,
0
,
0
)
||
setup_fields
(
thd
,
0
,
insert_table_list
,
update_values
,
1
,
0
,
0
))))
DBUG_RETURN
(
-
1
);
if
(
find_real_table_in_list
(
table_list
->
next
,
if
((
thd
->
lex
->
sql_command
==
SQLCOM_INSERT
||
thd
->
lex
->
sql_command
==
SQLCOM_REPLACE
)
&&
find_real_table_in_list
(
table_list
->
next
,
table_list
->
db
,
table_list
->
real_name
))
{
my_error
(
ER_UPDATE_TABLE_USED
,
MYF
(
0
),
table_list
->
real_name
);
...
...
@@ -550,8 +551,10 @@ int write_record(TABLE *table,COPY_INFO *info)
that matches, is updated. If update causes a conflict again,
an error is returned
*/
DBUG_ASSERT
(
table
->
insert_values
!=
NULL
);
store_record
(
table
,
insert_values
);
restore_record
(
table
,
record
[
1
]);
DBUG_ASSERT
(
info
->
update_fields
->
elements
==
info
->
update_values
->
elements
);
if
(
fill_record
(
*
info
->
update_fields
,
*
info
->
update_values
,
0
))
goto
err
;
if
((
error
=
table
->
file
->
update_row
(
table
->
record
[
1
],
table
->
record
[
0
])))
...
...
sql/sql_lex.cc
View file @
4864dce0
...
...
@@ -123,6 +123,7 @@ void lex_start(THD *thd, uchar *buf,uint length)
lex
->
unit
.
thd
=
thd
;
lex
->
select_lex
.
init_query
();
lex
->
value_list
.
empty
();
lex
->
update_list
.
empty
();
lex
->
param_list
.
empty
();
lex
->
unit
.
next
=
lex
->
unit
.
master
=
lex
->
unit
.
link_next
=
lex
->
unit
.
return_to
=
0
;
...
...
sql/sql_lex.h
View file @
4864dce0
...
...
@@ -587,7 +587,7 @@ typedef struct st_lex
List
<
LEX_COLUMN
>
columns
;
List
<
Key
>
key_list
;
List
<
create_field
>
create_list
;
List
<
Item
>
*
insert_list
,
field_list
,
value_list
;
List
<
Item
>
*
insert_list
,
field_list
,
value_list
,
update_list
;
List
<
List_item
>
many_values
;
List
<
set_var_base
>
var_list
;
List
<
Item_param
>
param_list
;
...
...
sql/sql_parse.cc
View file @
4864dce0
...
...
@@ -2717,7 +2717,7 @@ unsent_create_error:
if
((
res
=
insert_precheck
(
thd
,
tables
)))
break
;
res
=
mysql_insert
(
thd
,
tables
,
lex
->
field_list
,
lex
->
many_values
,
select_lex
->
item
_list
,
lex
->
value_list
,
lex
->
update
_list
,
lex
->
value_list
,
lex
->
duplicates
);
if
(
thd
->
net
.
report_error
)
res
=
-
1
;
...
...
@@ -2727,7 +2727,7 @@ unsent_create_error:
case
SQLCOM_INSERT_SELECT
:
{
TABLE_LIST
*
first_local_table
=
(
TABLE_LIST
*
)
select_lex
->
table_list
.
first
;
if
((
res
=
insert_
select_
precheck
(
thd
,
tables
)))
if
((
res
=
insert_precheck
(
thd
,
tables
)))
break
;
/* Fix lock for first table */
...
...
@@ -2749,11 +2749,16 @@ unsent_create_error:
select_lex
->
options
|=
OPTION_BUFFER_RESULT
;
}
if
(
!
(
res
=
open_and_lock_tables
(
thd
,
tables
))
&&
!
(
res
=
mysql_prepare_insert
(
thd
,
tables
,
first_local_table
,
tables
->
table
,
lex
->
field_list
,
0
,
lex
->
update_list
,
lex
->
value_list
,
lex
->
duplicates
))
&&
(
result
=
new
select_insert
(
tables
->
table
,
&
lex
->
field_list
,
&
lex
->
update_list
,
&
lex
->
value_list
,
lex
->
duplicates
)))
{
TABLE
*
table
=
tables
->
table
;
/* Skip first table, which is the table we are inserting in */
lex
->
select_lex
.
table_list
.
first
=
(
byte
*
)
first_local_table
->
next
;
/*
...
...
@@ -2766,6 +2771,7 @@ unsent_create_error:
lex
->
select_lex
.
table_list
.
first
=
(
byte
*
)
first_local_table
;
lex
->
select_lex
.
resolve_mode
=
SELECT_LEX
::
INSERT_MODE
;
delete
result
;
table
->
insert_values
=
0
;
if
(
thd
->
net
.
report_error
)
res
=
-
1
;
}
...
...
@@ -5304,33 +5310,6 @@ int multi_delete_precheck(THD *thd, TABLE_LIST *tables, uint *table_count)
}
/*
INSERT ... SELECT query pre-check
SYNOPSIS
insert_delete_precheck()
thd Thread handler
tables Global table list
RETURN VALUE
0 OK
1 Error (message is sent to user)
-1 Error (message is not sent to user)
*/
int
insert_select_precheck
(
THD
*
thd
,
TABLE_LIST
*
tables
)
{
DBUG_ENTER
(
"insert_select_precheck"
);
/*
Check that we have modify privileges for the first table and
select privileges for the rest
*/
ulong
privilege
=
(
thd
->
lex
->
duplicates
==
DUP_REPLACE
?
INSERT_ACL
|
DELETE_ACL
:
INSERT_ACL
);
DBUG_RETURN
(
check_one_table_access
(
thd
,
privilege
,
tables
)
?
1
:
0
);
}
/*
simple UPDATE query pre-check
...
...
@@ -5402,6 +5381,10 @@ int insert_precheck(THD *thd, TABLE_LIST *tables)
LEX
*
lex
=
thd
->
lex
;
DBUG_ENTER
(
"insert_precheck"
);
/*
Check that we have modify privileges for the first table and
select privileges for the rest
*/
ulong
privilege
=
INSERT_ACL
|
(
lex
->
duplicates
==
DUP_REPLACE
?
DELETE_ACL
:
0
)
|
(
lex
->
duplicates
==
DUP_UPDATE
?
UPDATE_ACL
:
0
);
...
...
@@ -5409,7 +5392,7 @@ int insert_precheck(THD *thd, TABLE_LIST *tables)
if
(
check_one_table_access
(
thd
,
privilege
,
tables
))
DBUG_RETURN
(
1
);
if
(
lex
->
select_lex
.
item
_list
.
elements
!=
lex
->
value_list
.
elements
)
if
(
lex
->
update
_list
.
elements
!=
lex
->
value_list
.
elements
)
{
my_error
(
ER_WRONG_VALUE_COUNT
,
MYF
(
0
));
DBUG_RETURN
(
-
1
);
...
...
sql/sql_prepare.cc
View file @
4864dce0
...
...
@@ -1343,7 +1343,7 @@ static int mysql_test_insert_select(Prepared_statement *stmt,
{
int
res
;
LEX
*
lex
=
stmt
->
lex
;
if
((
res
=
insert_
select_
precheck
(
stmt
->
thd
,
tables
)))
if
((
res
=
insert_precheck
(
stmt
->
thd
,
tables
)))
return
res
;
TABLE_LIST
*
first_local_table
=
(
TABLE_LIST
*
)
lex
->
select_lex
.
table_list
.
first
;
...
...
sql/sql_yacc.yy
View file @
4864dce0
...
...
@@ -4161,21 +4161,8 @@ expr_or_default:
opt_insert_update:
/* empty */
| ON DUPLICATE_SYM
{
LEX *lex= Lex;
/*
For simplicity, let's forget about INSERT ... SELECT ... UPDATE
for a moment.
*/
if (lex->sql_command != SQLCOM_INSERT)
{
yyerror(ER(ER_SYNTAX_ERROR));
YYABORT;
}
lex->duplicates= DUP_UPDATE;
}
KEY_SYM UPDATE_SYM update_list
| ON DUPLICATE_SYM { Lex->duplicates= DUP_UPDATE; }
KEY_SYM UPDATE_SYM insert_update_list
;
/* Update rows in a table */
...
...
@@ -4211,16 +4198,28 @@ update:
;
update_list:
update_list ',' simple_ident equal expr_or_default
update_list ',' update_elem
| update_elem;
update_elem:
simple_ident equal expr_or_default
{
if (add_item_to_list(YYTHD, $
3) || add_value_to_list(YYTHD, $5
))
if (add_item_to_list(YYTHD, $
1) || add_value_to_list(YYTHD, $3
))
YYABORT;
}
| simple_ident equal expr_or_default
{
if (add_item_to_list(YYTHD, $1) || add_value_to_list(YYTHD, $3))
YYABORT;
};
};
insert_update_list:
insert_update_list ',' insert_update_elem
| insert_update_elem;
insert_update_elem:
simple_ident equal expr_or_default
{
LEX *lex= Lex;
if (lex->update_list.push_back($1) ||
lex->value_list.push_back($3))
YYABORT;
};
opt_low_priority:
/* empty */ { $$= YYTHD->update_lock_default; }
...
...
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