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
d836f52b
Commit
d836f52b
authored
Feb 07, 2017
by
Alexander Barkov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
MDEV-12007 Allow ROW variables as a cursor FETCH target
parent
72f43df6
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
316 additions
and
4 deletions
+316
-4
mysql-test/r/sp.result
mysql-test/r/sp.result
+106
-0
mysql-test/suite/compat/oracle/r/sp-cursor.result
mysql-test/suite/compat/oracle/r/sp-cursor.result
+29
-0
mysql-test/suite/compat/oracle/t/sp-cursor.test
mysql-test/suite/compat/oracle/t/sp-cursor.test
+27
-0
mysql-test/t/sp.test
mysql-test/t/sp.test
+114
-0
sql/field.h
sql/field.h
+6
-0
sql/sp_rcontext.cc
sql/sp_rcontext.cc
+32
-4
sql/sp_rcontext.h
sql/sp_rcontext.h
+2
-0
No files found.
mysql-test/r/sp.result
View file @
d836f52b
...
...
@@ -8127,3 +8127,109 @@ v_name v_total
c 1
DROP PROCEDURE p1;
DROP TABLE t1;
#
# Start of 10.3 tests
#
#
# MDEV-12007 Allow ROW variables as a cursor FETCH target
#
# The cursor and the ROW variable in FETCH must have the same number of fields
CREATE PROCEDURE p1()
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE rec ROW(aa INT, bb VARCHAR(32), cc INT);
DECLARE cur CURSOR FOR SELECT 10 AS a,'b10' AS b;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cur;
read_loop:
LOOP
FETCH cur INTO rec;
IF done THEN
LEAVE read_loop;
END IF;
END LOOP;
CLOSE cur;
END;
$$
CALL p1();
ERROR HY000: Incorrect number of FETCH variables
DROP PROCEDURE p1;
# Multiple ROW variables in FETCH
CREATE PROCEDURE p1()
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE rec1 ROW(aa INT);
DECLARE rec2 ROW(aa INT);
DECLARE cur CURSOR FOR SELECT 10 AS a, 20 AS b;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cur;
read_loop:
LOOP
FETCH cur INTO rec1, rec2;
IF done THEN
LEAVE read_loop;
END IF;
END LOOP;
CLOSE cur;
END;
$$
CALL p1();
ERROR 21000: Operand should contain 1 column(s)
DROP PROCEDURE p1;
# A complete working example
CREATE TABLE t1 (a INT, b VARCHAR(32));
INSERT INTO t1 VALUES (10,'b10');
INSERT INTO t1 VALUES (20,'b20');
INSERT INTO t1 VALUES (30,'b30');
CREATE PROCEDURE p1()
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE rec ROW(aa INT, bb VARCHAR(32));
DECLARE cur CURSOR FOR SELECT a,b FROM t1;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cur;
read_loop:
LOOP
FETCH cur INTO rec;
IF done THEN
LEAVE read_loop;
END IF;
SELECT CONCAT('rec=(',rec.aa,',',rec.bb,')') AS c;
END LOOP;
CLOSE cur;
END;
$$
CALL p1();
c
rec=(10,b10)
c
rec=(20,b20)
c
rec=(30,b30)
DROP PROCEDURE p1;
DROP TABLE t1;
# A ROW variable with a single field
CREATE PROCEDURE p1()
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE rec ROW(aa INT);
DECLARE cur CURSOR FOR SELECT 10 AS a UNION SELECT 20;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cur;
read_loop:
LOOP
FETCH cur INTO rec;
IF done THEN
LEAVE read_loop;
END IF;
SELECT CONCAT('rec=(',rec.aa,')') AS c;
END LOOP;
CLOSE cur;
END;
$$
CALL p1();
c
rec=(10)
c
rec=(20)
DROP PROCEDURE p1;
mysql-test/suite/compat/oracle/r/sp-cursor.result
View file @
d836f52b
...
...
@@ -783,3 +783,32 @@ a b c
DROP TABLE t2;
DROP PROCEDURE p1;
DROP TABLE t1;
#
# MDEV-12007 Allow ROW variables as a cursor FETCH target
#
CREATE TABLE t1 (a INT, b VARCHAR(32));
INSERT INTO t1 VALUES (10,'b10');
INSERT INTO t1 VALUES (20,'b20');
INSERT INTO t1 VALUES (30,'b30');
CREATE PROCEDURE p1 AS
rec ROW(a INT, b VARCHAR(32));
CURSOR c IS SELECT a,b FROM t1;
BEGIN
OPEN c;
LOOP
FETCH c INTO rec;
EXIT WHEN c%NOTFOUND;
SELECT ('rec=(' || rec.a ||','|| rec.b||')') AS c;
END LOOP;
CLOSE c;
END;
$$
CALL p1();
c
rec=(10,b10)
c
rec=(20,b20)
c
rec=(30,b30)
DROP PROCEDURE p1;
DROP TABLE t1;
mysql-test/suite/compat/oracle/t/sp-cursor.test
View file @
d836f52b
...
...
@@ -783,3 +783,30 @@ SELECT * FROM t2;
DROP
TABLE
t2
;
DROP
PROCEDURE
p1
;
DROP
TABLE
t1
;
--
echo
#
--
echo
# MDEV-12007 Allow ROW variables as a cursor FETCH target
--
echo
#
CREATE
TABLE
t1
(
a
INT
,
b
VARCHAR
(
32
));
INSERT
INTO
t1
VALUES
(
10
,
'b10'
);
INSERT
INTO
t1
VALUES
(
20
,
'b20'
);
INSERT
INTO
t1
VALUES
(
30
,
'b30'
);
DELIMITER
$$
;
CREATE
PROCEDURE
p1
AS
rec
ROW
(
a
INT
,
b
VARCHAR
(
32
));
CURSOR
c
IS
SELECT
a
,
b
FROM
t1
;
BEGIN
OPEN
c
;
LOOP
FETCH
c
INTO
rec
;
EXIT
WHEN
c
%
NOTFOUND
;
SELECT
(
'rec=('
||
rec
.
a
||
','
||
rec
.
b
||
')'
)
AS
c
;
END
LOOP
;
CLOSE
c
;
END
;
$$
DELIMITER
;
$$
CALL
p1
();
DROP
PROCEDURE
p1
;
DROP
TABLE
t1
;
mysql-test/t/sp.test
View file @
d836f52b
...
...
@@ -9588,3 +9588,117 @@ DELIMITER ;|
CALL
p1
();
DROP
PROCEDURE
p1
;
DROP
TABLE
t1
;
--
echo
#
--
echo
# Start of 10.3 tests
--
echo
#
--
echo
#
--
echo
# MDEV-12007 Allow ROW variables as a cursor FETCH target
--
echo
#
--
echo
# The cursor and the ROW variable in FETCH must have the same number of fields
DELIMITER
$$
;
CREATE
PROCEDURE
p1
()
BEGIN
DECLARE
done
INT
DEFAULT
FALSE
;
DECLARE
rec
ROW
(
aa
INT
,
bb
VARCHAR
(
32
),
cc
INT
);
DECLARE
cur
CURSOR
FOR
SELECT
10
AS
a
,
'b10'
AS
b
;
DECLARE
CONTINUE
HANDLER
FOR
NOT
FOUND
SET
done
=
TRUE
;
OPEN
cur
;
read_loop
:
LOOP
FETCH
cur
INTO
rec
;
IF
done
THEN
LEAVE
read_loop
;
END
IF
;
END
LOOP
;
CLOSE
cur
;
END
;
$$
DELIMITER
;
$$
--
error
ER_SP_WRONG_NO_OF_FETCH_ARGS
CALL
p1
();
DROP
PROCEDURE
p1
;
--
echo
# Multiple ROW variables in FETCH
DELIMITER
$$
;
CREATE
PROCEDURE
p1
()
BEGIN
DECLARE
done
INT
DEFAULT
FALSE
;
DECLARE
rec1
ROW
(
aa
INT
);
DECLARE
rec2
ROW
(
aa
INT
);
DECLARE
cur
CURSOR
FOR
SELECT
10
AS
a
,
20
AS
b
;
DECLARE
CONTINUE
HANDLER
FOR
NOT
FOUND
SET
done
=
TRUE
;
OPEN
cur
;
read_loop
:
LOOP
FETCH
cur
INTO
rec1
,
rec2
;
IF
done
THEN
LEAVE
read_loop
;
END
IF
;
END
LOOP
;
CLOSE
cur
;
END
;
$$
DELIMITER
;
$$
--
error
ER_OPERAND_COLUMNS
CALL
p1
();
DROP
PROCEDURE
p1
;
--
echo
# A complete working example
CREATE
TABLE
t1
(
a
INT
,
b
VARCHAR
(
32
));
INSERT
INTO
t1
VALUES
(
10
,
'b10'
);
INSERT
INTO
t1
VALUES
(
20
,
'b20'
);
INSERT
INTO
t1
VALUES
(
30
,
'b30'
);
DELIMITER
$$
;
CREATE
PROCEDURE
p1
()
BEGIN
DECLARE
done
INT
DEFAULT
FALSE
;
DECLARE
rec
ROW
(
aa
INT
,
bb
VARCHAR
(
32
));
DECLARE
cur
CURSOR
FOR
SELECT
a
,
b
FROM
t1
;
DECLARE
CONTINUE
HANDLER
FOR
NOT
FOUND
SET
done
=
TRUE
;
OPEN
cur
;
read_loop
:
LOOP
FETCH
cur
INTO
rec
;
IF
done
THEN
LEAVE
read_loop
;
END
IF
;
SELECT
CONCAT
(
'rec=('
,
rec
.
aa
,
','
,
rec
.
bb
,
')'
)
AS
c
;
END
LOOP
;
CLOSE
cur
;
END
;
$$
DELIMITER
;
$$
CALL
p1
();
DROP
PROCEDURE
p1
;
DROP
TABLE
t1
;
--
echo
# A ROW variable with a single field
DELIMITER
$$
;
CREATE
PROCEDURE
p1
()
BEGIN
DECLARE
done
INT
DEFAULT
FALSE
;
DECLARE
rec
ROW
(
aa
INT
);
DECLARE
cur
CURSOR
FOR
SELECT
10
AS
a
UNION
SELECT
20
;
DECLARE
CONTINUE
HANDLER
FOR
NOT
FOUND
SET
done
=
TRUE
;
OPEN
cur
;
read_loop
:
LOOP
FETCH
cur
INTO
rec
;
IF
done
THEN
LEAVE
read_loop
;
END
IF
;
SELECT
CONCAT
(
'rec=('
,
rec
.
aa
,
')'
)
AS
c
;
END
LOOP
;
CLOSE
cur
;
END
;
$$
DELIMITER
;
$$
CALL
p1
();
DROP
PROCEDURE
p1
;
sql/field.h
View file @
d836f52b
...
...
@@ -4037,6 +4037,12 @@ class Spvar_definition: public Column_definition
{
return
m_row_field_definitions
!=
NULL
;
}
// Check if "this" defines a ROW variable with n elements
uint
is_row
(
uint
n
)
const
{
return
m_row_field_definitions
!=
NULL
&&
m_row_field_definitions
->
elements
==
n
;
}
Row_definition_list
*
row_field_definitions
()
const
{
return
m_row_field_definitions
;
...
...
sql/sp_rcontext.cc
View file @
d836f52b
...
...
@@ -572,6 +572,22 @@ int sp_rcontext::set_variable_row_field(THD *thd, uint var_idx, uint field_idx,
}
int
sp_rcontext
::
set_variable_row
(
THD
*
thd
,
uint
var_idx
,
List
<
Item
>
&
items
)
{
DBUG_ENTER
(
"sp_rcontext::set_variable_row"
);
DBUG_ASSERT
(
thd
->
spcont
->
get_item
(
var_idx
)
->
cols
()
==
items
.
elements
);
List_iterator
<
Item
>
it
(
items
);
Item
*
item
;
for
(
uint
i
=
0
;
(
item
=
it
++
)
;
i
++
)
{
int
rc
;
if
((
rc
=
thd
->
spcont
->
set_variable_row_field
(
thd
,
var_idx
,
i
,
&
item
)))
DBUG_RETURN
(
rc
);
}
DBUG_RETURN
(
0
);
}
Item_cache
*
sp_rcontext
::
create_case_expr_holder
(
THD
*
thd
,
const
Item
*
item
)
const
{
...
...
@@ -688,7 +704,9 @@ int sp_cursor::fetch(THD *thd, List<sp_variable> *vars)
MYF
(
0
));
return
-
1
;
}
if
(
vars
->
elements
!=
result
.
get_field_count
())
if
(
vars
->
elements
!=
result
.
get_field_count
()
&&
(
vars
->
elements
!=
1
||
!
vars
->
head
()
->
field_def
.
is_row
(
result
.
get_field_count
())))
{
my_message
(
ER_SP_WRONG_NO_OF_FETCH_ARGS
,
ER_THD
(
thd
,
ER_SP_WRONG_NO_OF_FETCH_ARGS
),
MYF
(
0
));
...
...
@@ -743,15 +761,16 @@ int sp_cursor::Select_fetch_into_spvars::prepare(List<Item> &fields,
}
int
sp_cursor
::
Select_fetch_into_spvars
::
send_data
(
List
<
Item
>
&
items
)
bool
sp_cursor
::
Select_fetch_into_spvars
::
send_data_to_variable_list
(
List
<
sp_variable
>
&
vars
,
List
<
Item
>
&
items
)
{
List_iterator_fast
<
sp_variable
>
spvar_iter
(
*
spvar_list
);
List_iterator_fast
<
sp_variable
>
spvar_iter
(
vars
);
List_iterator_fast
<
Item
>
item_iter
(
items
);
sp_variable
*
spvar
;
Item
*
item
;
/* Must be ensured by the caller */
DBUG_ASSERT
(
spvar_list
->
elements
==
items
.
elements
);
DBUG_ASSERT
(
vars
.
elements
==
items
.
elements
);
/*
Assign the row fetched from a server side cursor to stored
...
...
@@ -764,3 +783,12 @@ int sp_cursor::Select_fetch_into_spvars::send_data(List<Item> &items)
}
return
false
;
}
int
sp_cursor
::
Select_fetch_into_spvars
::
send_data
(
List
<
Item
>
&
items
)
{
return
(
spvar_list
->
elements
==
1
&&
(
spvar_list
->
head
())
->
field_def
.
is_row
(
items
.
elements
))
?
thd
->
spcont
->
set_variable_row
(
thd
,
spvar_list
->
head
()
->
offset
,
items
)
:
send_data_to_variable_list
(
*
spvar_list
,
items
);
}
sql/sp_rcontext.h
View file @
d836f52b
...
...
@@ -190,6 +190,7 @@ class sp_rcontext : public Sql_alloc
void
set_variable_row_field_to_null
(
THD
*
thd
,
uint
var_idx
,
uint
field_idx
);
int
set_variable_row_field
(
THD
*
thd
,
uint
var_idx
,
uint
field_idx
,
Item
**
value
);
int
set_variable_row
(
THD
*
thd
,
uint
var_idx
,
List
<
Item
>
&
items
);
Item
*
get_item
(
uint
var_idx
)
const
{
return
m_var_items
[
var_idx
];
}
...
...
@@ -419,6 +420,7 @@ class sp_cursor : public Sql_alloc
{
List
<
sp_variable
>
*
spvar_list
;
uint
field_count
;
bool
send_data_to_variable_list
(
List
<
sp_variable
>
&
vars
,
List
<
Item
>
&
items
);
public:
Select_fetch_into_spvars
(
THD
*
thd_arg
)
:
select_result_interceptor
(
thd_arg
)
{}
uint
get_field_count
()
{
return
field_count
;
}
...
...
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