Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bugfixing for mysql_fdw #239

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

MinhLA1410
Copy link

  • Support Subscripting Array syntax
    Please check describe in commmit:
    (MinhLA1410@1152ff0)

  • Not pushdown system column instead of raise error
    Please check describe in commmit:
    (MinhLA1410@e4cc9ff)

  • Do not allocate when natts is 0
    Please check describe in commmit:
    MinhLA1410@4d42bba

LeAnhMinh added 3 commits March 29, 2022 15:14
**Describe the bug**
mysql_fdw deparse the Subscripting Array to be the same as postgres_fdw.
However, MySQL have no type as ARRAY in Postgresql, so we don't pushdown Array Subscripting.

**To Reproduce**
1. Create table on MySQL server
 mysql -h $MYSQL_HOST -u $MYSQL_USER_NAME -D $MYSQL_PORT -D mysql_fdw_regress -e "CREATE TABLE s6(id int PRIMARY KEY, c1 int, c2 int, c3 text);"

2. Execute SQL
CREATE FOREIGN TABLE ft5 (id int, c1 int, c2 int, c3 text)
  SERVER mysql_svr OPTIONS (dbname 'mysql_fdw_regress', table_name 's6');

INSERT INTO ft5
        SELECT  id,
                id,
                id % 5,
                to_char(id, 'FM00000')
        FROM generate_series(1, 10) id;

3. Result before fixing
EXPLAIN VERBOSE
        SELECT * FROM ft5 t1 WHERE c1 = (ARRAY[c1,c2,3])[2];
ERROR:  failed to prepare the MySQL query:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '[`c1`, `c2`, 3])[2])))' at line 1

**Result after fixing**
EXPLAIN VERBOSE
        SELECT * FROM ft5 t1 WHERE c1 = (ARRAY[c1,c2,3])[2];
                                                     QUERY PLAN
--------------------------------------------------------------------------------------------------------------------
 Foreign Scan on public.ft5 t1  (cost=100.00..125.17 rows=6 width=44)
   Output: id, c1, c2, c3
   Local server startup cost: 10
   Remote query: SELECT `id`, `c1`, `c2`, `c3` FROM `mysql_fdw_regress`.`s6` WHERE ((`c1` = ELT(2, `c1`, `c2`, 3)))
(4 rows)

**Additional context**
Use Mysql ELT(N,str1,str2,str3,...) function to support array subscripting function:
+ Support 1D array subscription.
+ Do not support multiple dimension array
+ Do not support slice function
+ Do not support Var subscription.
**Describe the bug**
Because MySQL does not support tableoid, ctid,...
So not pushdown system column instead of raise error.

**To Reproduce**
1. Execute SQL
CREATE FOREIGN TABLE ft1 (
        c0 int,
        c1 int NOT NULL,
        c2 int NOT NULL,
        c3 text,
        c4 timestamptz,
        c5 timestamp,
        c6 varchar(10),
        c7 char(10) default 'ft1',
        c8 user_enum
) SERVER mysql_svr OPTIONS (dbname 'mysql_fdw_post');

EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 ORDER BY t1.c3, t1.c1, t1.tableoid OFFSET 100 LIMIT 10;

2.Result before fixing
EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 ORDER BY t1.c3, t1.c1, t1.tableoid OFFSET 100 LIMIT 10;
ERROR: system attribute tableoid can't be fetched from remote relation

**Result after fixing**
                                                   QUERY PLAN
----------------------------------------------------------------------------------------------------------------
 Limit
   Output: c1, c2, c3, c4, c5, c6, c7, c8, tableoid
   ->  Sort
         Output: c1, c2, c3, c4, c5, c6, c7, c8, tableoid
         Sort Key: t1.c3, t1.c1, t1.tableoid
         ->  Foreign Scan on public.ft1 t1
               Output: c1, c2, c3, c4, c5, c6, c7, c8, tableoid
               Remote query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM `mysql_fdw_post`.`T 1`
(8 rows)
**Describe the bug**
Failed to bind the MySQL query when foreign scan will select NULL from an inner join.

**To Reproduce**
1. On MySQL server
DROP DATABASE IF EXISTS join_limit;
CREATE DATABASE join_limit;
USE join_limit;

CREATE TABLE J1_TBL ( i integer, j integer, t text);
CREATE TABLE J2_TBL ( i integer, k integer);
CREATE TABLE J3_TBL ( i integer, t text);

INSERT INTO J1_TBL VALUES (1, 4, 'one');
INSERT INTO J1_TBL VALUES (2, 3, 'two');
INSERT INTO J1_TBL VALUES (3, 2, 'three');
INSERT INTO J1_TBL VALUES (4, 1, 'four');
INSERT INTO J1_TBL VALUES (5, 0, 'five');
INSERT INTO J1_TBL VALUES (6, 6, 'six');
INSERT INTO J1_TBL VALUES (7, 7, 'seven');
INSERT INTO J1_TBL VALUES (8, 8, 'eight');
INSERT INTO J1_TBL VALUES (0, NULL, 'zero');
INSERT INTO J1_TBL VALUES (NULL, NULL, 'null');
INSERT INTO J1_TBL VALUES (NULL, 0, 'zero');

INSERT INTO J2_TBL VALUES (1, -1);
INSERT INTO J2_TBL VALUES (2, 2);
INSERT INTO J2_TBL VALUES (3, -3);
INSERT INTO J2_TBL VALUES (2, 4);
INSERT INTO J2_TBL VALUES (5, -5);
INSERT INTO J2_TBL VALUES (5, -5);
INSERT INTO J2_TBL VALUES (0, NULL);
INSERT INTO J2_TBL VALUES (NULL, NULL);
INSERT INTO J2_TBL VALUES (NULL, 0);

INSERT INTO J3_TBL VALUES (1, 'first');
INSERT INTO J3_TBL VALUES (2, NULL);
INSERT INTO J3_TBL VALUES (2, 'second');
INSERT INTO J3_TBL VALUES (3, 'third');
INSERT INTO J3_TBL VALUES (4, 'forth');
INSERT INTO J3_TBL VALUES (5, 'five');

2. Execute SQL

CREATE FOREIGN TABLE J1_TBL__mysql_svr__0 ( i integer, j integer, t text) SERVER mysql_svr OPTIONS (dbname 'join_limit', table_name 'J1_TBL');
CREATE FOREIGN TABLE J2_TBL__mysql_svr__0 ( i integer, k integer) SERVER mysql_svr OPTIONS (dbname 'join_limit', table_name 'J2_TBL');
CREATE FOREIGN TABLE J3_TBL__mysql_svr__0 ( i integer, t text) SERVER mysql_svr OPTIONS (dbname 'join_limit', table_name 'J3_TBL');

SELECT * FROM j2_tbl__mysql_svr__0 where exists (select t3.i, t from j3_tbl__mysql_svr__0 t3 join j2_tbl__mysql_svr__0 t2 on t2.i = t3.i);

3. Result before fixing
SELECT * FROM j2_tbl__mysql_svr__0 where exists (select t3.i, t from j3_tbl__mysql_svr__0 t3 join j2_tbl__mysql_svr__0 t2 on t2.i = t3.i);
ERROR:  failed to bind the MySQL query

**Result after fixing**
 i | k
---+----
 1 | -1
 2 |  2
 3 | -3
 2 |  4
 5 | -5
 5 | -5
 0 |
   |
   |  0
(9 rows)

**Additional context**
Because with tupleDescriptor->natts = 0 is used to palloc for table->mysql_bind.
But it will return invalid memory like address: 0x7f7f7f7f7f7f7f7f.
With this allocated memory, the binding will fail and it causes error "failed to bind the MySQL query".

When natts is 0, it means the PostgreSQL/PGSpider core does not need any result in tuple slot.
Therefore, no need to allocate memory for festate->table in this case.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant