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
e54134fd
Commit
e54134fd
authored
Dec 02, 2002
by
serg@serg.mysql.com
Browse files
Options
Browse Files
Download
Plain Diff
merged
parents
5483796c
2320923a
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
131 additions
and
26 deletions
+131
-26
mysql-test/r/insert_update.result
mysql-test/r/insert_update.result
+44
-0
mysql-test/t/insert_update.test
mysql-test/t/insert_update.test
+19
-0
sql/mysql_priv.h
sql/mysql_priv.h
+4
-3
sql/sql_class.h
sql/sql_class.h
+5
-2
sql/sql_insert.cc
sql/sql_insert.cc
+46
-16
sql/sql_parse.cc
sql/sql_parse.cc
+10
-3
sql/sql_yacc.yy
sql/sql_yacc.yy
+3
-2
No files found.
mysql-test/r/insert_update.result
0 → 100644
View file @
e54134fd
DROP TABLE IF EXISTS 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 VALUES (5,6,30) ON DUPLICATE KEY UPDATE SET c=c+100;
SELECT * FROM t1;
a b c
1 2 10
3 4 20
5 6 30
INSERT t1 VALUES (5,7,40) ON DUPLICATE KEY UPDATE SET c=c+100;
SELECT * FROM t1;
a b c
1 2 10
3 4 20
5 6 130
INSERT t1 VALUES (8,4,50) ON DUPLICATE KEY UPDATE SET c=c+1000;
SELECT * FROM t1;
a b c
1 2 10
3 4 1020
5 6 130
INSERT t1 VALUES (1,4,60) ON DUPLICATE KEY UPDATE SET c=c+10000;
SELECT * FROM t1;
a b c
1 2 10010
3 4 1020
5 6 130
INSERT t1 VALUES (1,9,70) ON DUPLICATE KEY UPDATE SET c=c+100000, b=4;
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);
INSERT t1 VALUES (5,6,30), (7,4,40), (8,9,60) ON DUPLICATE KEY UPDATE SET c=c+100;
SELECT * FROM t1;
a b c
1 2 10
3 4 120
5 6 30
8 9 60
DROP TABLE t1;
mysql-test/t/insert_update.test
0 → 100644
View file @
e54134fd
DROP
TABLE
IF
EXISTS
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
VALUES
(
5
,
6
,
30
)
ON
DUPLICATE
KEY
UPDATE
SET
c
=
c
+
100
;
SELECT
*
FROM
t1
;
INSERT
t1
VALUES
(
5
,
7
,
40
)
ON
DUPLICATE
KEY
UPDATE
SET
c
=
c
+
100
;
SELECT
*
FROM
t1
;
INSERT
t1
VALUES
(
8
,
4
,
50
)
ON
DUPLICATE
KEY
UPDATE
SET
c
=
c
+
1000
;
SELECT
*
FROM
t1
;
INSERT
t1
VALUES
(
1
,
4
,
60
)
ON
DUPLICATE
KEY
UPDATE
SET
c
=
c
+
10000
;
SELECT
*
FROM
t1
;
--
error
1062
INSERT
t1
VALUES
(
1
,
9
,
70
)
ON
DUPLICATE
KEY
UPDATE
SET
c
=
c
+
100000
,
b
=
4
;
SELECT
*
FROM
t1
;
TRUNCATE
TABLE
t1
;
INSERT
t1
VALUES
(
1
,
2
,
10
),
(
3
,
4
,
20
);
INSERT
t1
VALUES
(
5
,
6
,
30
),
(
7
,
4
,
40
),
(
8
,
9
,
60
)
ON
DUPLICATE
KEY
UPDATE
SET
c
=
c
+
100
;
SELECT
*
FROM
t1
;
DROP
TABLE
t1
;
sql/mysql_priv.h
View file @
e54134fd
...
...
@@ -429,7 +429,7 @@ int mysql_alter_table(THD *thd, char *new_db, char *new_name,
bool
drop_primary
,
enum
enum_duplicates
handle_duplicates
,
enum
enum_enable_or_disable
keys_onoff
=
LEAVE_AS_IS
,
bool
simple_alter
=
0
);
bool
simple_alter
=
0
);
bool
mysql_rename_table
(
enum
db_type
base
,
const
char
*
old_db
,
const
char
*
old_name
,
...
...
@@ -440,11 +440,12 @@ int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys);
int
mysql_drop_index
(
THD
*
thd
,
TABLE_LIST
*
table_list
,
List
<
Alter_drop
>
&
drop_list
);
int
mysql_update
(
THD
*
thd
,
TABLE_LIST
*
tables
,
List
<
Item
>
&
fields
,
List
<
Item
>
&
values
,
COND
*
conds
,
List
<
Item
>
&
values
,
COND
*
conds
,
ORDER
*
order
,
ha_rows
limit
,
enum
enum_duplicates
handle_duplicates
);
int
mysql_insert
(
THD
*
thd
,
TABLE_LIST
*
table
,
List
<
Item
>
&
fields
,
List
<
List_item
>
&
values
,
enum_duplicates
flag
);
List
<
List_item
>
&
values
,
List
<
Item
>
&
update_fields
,
List
<
Item
>
&
update_values
,
enum_duplicates
flag
);
void
kill_delayed_threads
(
void
);
int
mysql_delete
(
THD
*
thd
,
TABLE_LIST
*
table
,
COND
*
conds
,
ORDER
*
order
,
ha_rows
rows
,
ulong
options
);
...
...
sql/sql_class.h
View file @
e54134fd
...
...
@@ -29,12 +29,12 @@ class Slave_log_event;
enum
enum_enable_or_disable
{
LEAVE_AS_IS
,
ENABLE
,
DISABLE
};
enum
enum_ha_read_modes
{
RFIRST
,
RNEXT
,
RPREV
,
RLAST
,
RKEY
};
enum
enum_duplicates
{
DUP_ERROR
,
DUP_REPLACE
,
DUP_IGNORE
};
enum
enum_duplicates
{
DUP_ERROR
,
DUP_REPLACE
,
DUP_IGNORE
,
DUP_UPDATE
};
enum
enum_log_type
{
LOG_CLOSED
,
LOG_NORMAL
,
LOG_NEW
,
LOG_BIN
};
enum
enum_delay_key_write
{
DELAY_KEY_WRITE_NONE
,
DELAY_KEY_WRITE_ON
,
DELAY_KEY_WRITE_ALL
};
// log info errors
// log info errors
#define LOG_INFO_EOF -1
#define LOG_INFO_IO -2
#define LOG_INFO_INVALID -3
...
...
@@ -188,6 +188,9 @@ typedef struct st_copy_info {
ha_rows
error_count
;
enum
enum_duplicates
handle_duplicates
;
int
escape_char
,
last_errno
;
/* for INSERT ... UPDATE */
List
<
Item
>
*
update_fields
;
List
<
Item
>
*
update_values
;
}
COPY_INFO
;
...
...
sql/sql_insert.cc
View file @
e54134fd
...
...
@@ -97,8 +97,12 @@ check_insert_fields(THD *thd,TABLE *table,List<Item> &fields,
}
int
mysql_insert
(
THD
*
thd
,
TABLE_LIST
*
table_list
,
List
<
Item
>
&
fields
,
List
<
List_item
>
&
values_list
,
enum_duplicates
duplic
)
int
mysql_insert
(
THD
*
thd
,
TABLE_LIST
*
table_list
,
List
<
Item
>
&
fields
,
List
<
List_item
>
&
values_list
,
List
<
Item
>
&
update_fields
,
List
<
Item
>
&
update_values
,
enum_duplicates
duplic
)
{
int
error
;
bool
log_on
=
((
thd
->
options
&
OPTION_UPDATE_LOG
)
||
...
...
@@ -126,7 +130,8 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
if
((
lock_type
==
TL_WRITE_DELAYED
&&
((
specialflag
&
(
SPECIAL_NO_NEW_FUNC
|
SPECIAL_SAFE_MODE
))
||
thd
->
slave_thread
))
||
(
lock_type
==
TL_WRITE_CONCURRENT_INSERT
&&
duplic
==
DUP_REPLACE
))
(
lock_type
==
TL_WRITE_CONCURRENT_INSERT
&&
duplic
==
DUP_REPLACE
)
||
(
duplic
==
DUP_UPDATE
))
lock_type
=
TL_WRITE
;
table_list
->
lock_type
=
lock_type
;
...
...
@@ -166,7 +171,10 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
values
=
its
++
;
if
(
check_insert_fields
(
thd
,
table
,
fields
,
*
values
,
1
)
||
setup_tables
(
insert_table_list
)
||
setup_fields
(
thd
,
insert_table_list
,
*
values
,
0
,
0
,
0
))
setup_fields
(
thd
,
insert_table_list
,
*
values
,
0
,
0
,
0
)
||
(
duplic
==
DUP_UPDATE
&&
(
setup_fields
(
thd
,
insert_table_list
,
update_fields
,
0
,
0
,
0
)
||
setup_fields
(
thd
,
insert_table_list
,
update_values
,
0
,
0
,
0
))))
{
table
->
time_stamp
=
save_time_stamp
;
goto
abort
;
...
...
@@ -203,6 +211,8 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
info
.
records
=
info
.
deleted
=
info
.
copied
=
0
;
info
.
handle_duplicates
=
duplic
;
info
.
update_fields
=&
update_fields
;
info
.
update_values
=&
update_values
;
// Don't count warnings for simple inserts
if
(
values_list
.
elements
>
1
||
(
thd
->
options
&
OPTION_WARNINGS
))
thd
->
count_cuted_fields
=
1
;
...
...
@@ -212,7 +222,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
error
=
0
;
id
=
0
;
thd
->
proc_info
=
"update"
;
if
(
duplic
==
DUP_IGNORE
||
duplic
==
DUP_REPLACE
)
if
(
duplic
!=
DUP_ERROR
)
table
->
file
->
extra
(
HA_EXTRA_IGNORE_DUP_KEY
);
if
((
bulk_insert
=
(
values_list
.
elements
>=
MIN_ROWS_TO_USE_BULK_INSERT
&&
lock_type
!=
TL_WRITE_DELAYED
&&
...
...
@@ -358,7 +368,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
table
->
next_number_field
=
0
;
thd
->
count_cuted_fields
=
0
;
thd
->
next_insert_id
=
0
;
// Reset this if wrongly used
if
(
duplic
==
DUP_IGNORE
||
duplic
==
DUP_REPLACE
)
if
(
duplic
!=
DUP_ERROR
)
table
->
file
->
extra
(
HA_EXTRA_NO_IGNORE_DUP_KEY
);
if
(
error
)
goto
abort
;
...
...
@@ -410,7 +420,8 @@ int write_record(TABLE *table,COPY_INFO *info)
char
*
key
=
0
;
info
->
records
++
;
if
(
info
->
handle_duplicates
==
DUP_REPLACE
)
if
(
info
->
handle_duplicates
==
DUP_REPLACE
||
info
->
handle_duplicates
==
DUP_UPDATE
)
{
while
((
error
=
table
->
file
->
write_row
(
table
->
record
[
0
])))
{
...
...
@@ -427,7 +438,9 @@ int write_record(TABLE *table,COPY_INFO *info)
was used. This ensures that we don't get a problem when the
whole range of the key has been used.
*/
if
(
table
->
next_number_field
&&
key_nr
==
table
->
next_number_index
&&
if
(
info
->
handle_duplicates
==
DUP_REPLACE
&&
table
->
next_number_field
&&
key_nr
==
table
->
next_number_index
&&
table
->
file
->
auto_increment_column_changed
)
goto
err
;
if
(
table
->
file
->
table_flags
()
&
HA_DUPP_POS
)
...
...
@@ -459,16 +472,33 @@ int write_record(TABLE *table,COPY_INFO *info)
HA_READ_KEY_EXACT
))))
goto
err
;
}
if
(
last_uniq_key
(
table
,
key_nr
)
)
if
(
info
->
handle_duplicates
==
DUP_UPDATE
)
{
if
((
error
=
table
->
file
->
update_row
(
table
->
record
[
1
],
table
->
record
[
0
])))
goto
err
;
info
->
deleted
++
;
break
;
/* Update logfile and count */
/* we don't check for other UNIQUE keys - the first row
that matches, is updated. If update causes a conflict again,
an error is returned
*/
restore_record
(
table
,
1
);
if
(
fill_record
(
*
info
->
update_fields
,
*
info
->
update_values
))
goto
err
;
if
((
error
=
table
->
file
->
update_row
(
table
->
record
[
1
],
table
->
record
[
0
])))
goto
err
;
info
->
deleted
++
;
break
;
}
else
/* DUP_REPLACE */
{
if
(
last_uniq_key
(
table
,
key_nr
))
{
if
((
error
=
table
->
file
->
update_row
(
table
->
record
[
1
],
table
->
record
[
0
])))
goto
err
;
info
->
deleted
++
;
break
;
/* Update logfile and count */
}
else
if
((
error
=
table
->
file
->
delete_row
(
table
->
record
[
1
])))
goto
err
;
info
->
deleted
++
;
}
else
if
((
error
=
table
->
file
->
delete_row
(
table
->
record
[
1
])))
goto
err
;
info
->
deleted
++
;
}
info
->
copied
++
;
}
...
...
sql/sql_parse.cc
View file @
e54134fd
...
...
@@ -1972,14 +1972,21 @@ mysql_execute_command(THD *thd)
case
SQLCOM_REPLACE
:
case
SQLCOM_INSERT
:
{
my_bool
update
=
(
lex
->
value_list
.
elements
?
UPDATE_ACL
:
0
);
ulong
privilege
=
(
lex
->
duplicates
==
DUP_REPLACE
?
INSERT_ACL
|
DELETE_ACL
:
INSERT_ACL
);
INSERT_ACL
|
DELETE_ACL
:
INSERT_ACL
|
update
);
if
(
check_access
(
thd
,
privilege
,
tables
->
db
,
&
tables
->
grant
.
privilege
))
goto
error
;
/* purecov: inspected */
if
(
grant_option
&&
check_grant
(
thd
,
privilege
,
tables
))
goto
error
;
if
(
select_lex
->
item_list
.
elements
!=
lex
->
value_list
.
elements
)
{
send_error
(
thd
,
ER_WRONG_VALUE_COUNT
);
DBUG_VOID_RETURN
;
}
res
=
mysql_insert
(
thd
,
tables
,
lex
->
field_list
,
lex
->
many_values
,
lex
->
duplicates
);
select_lex
->
item_list
,
lex
->
value_list
,
(
update
?
DUP_UPDATE
:
lex
->
duplicates
));
if
(
thd
->
net
.
report_error
)
res
=
-
1
;
break
;
...
...
@@ -2302,7 +2309,7 @@ mysql_execute_command(THD *thd)
case
SQLCOM_LOAD
:
{
uint
privilege
=
(
lex
->
duplicates
==
DUP_REPLACE
?
INSERT_ACL
|
UPDATE_ACL
|
DELETE_ACL
:
INSERT_ACL
);
INSERT_ACL
|
DELETE_ACL
:
INSERT_ACL
);
if
(
!
lex
->
local_file
)
{
...
...
sql/sql_yacc.yy
View file @
e54134fd
...
...
@@ -1461,7 +1461,7 @@ alter_list_item:
lex->simple_alter=0;
}
| RENAME opt_to table_ident
{
{
LEX *lex=Lex;
lex->select_lex.db=$3->db.str;
lex->name= $3->table.str;
...
...
@@ -3053,7 +3053,7 @@ expr_or_default:
opt_insert_update:
/* empty */
| ON DUPLICATE
KEY_SYM UPDATE_SYM SET update_list
| ON DUPLICATE
{ /* for simplisity, let's forget about
INSERT ... SELECT ... UPDATE
for a moment */
...
...
@@ -3063,6 +3063,7 @@ opt_insert_update:
YYABORT;
}
}
KEY_SYM UPDATE_SYM SET update_list
;
/* Update rows in a table */
...
...
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