2019-09-25 15:43:36 +08:00
|
|
|
import * as dtSqlParser from '../src';
|
|
|
|
import { SyntaxResult } from '../src/core/sqlSyntaxParser';
|
2019-05-31 15:58:34 +08:00
|
|
|
const parser = dtSqlParser.parser;
|
|
|
|
const filter = dtSqlParser.filter;
|
2019-09-25 15:43:36 +08:00
|
|
|
const flinksqlParser = dtSqlParser.flinksqlParser;
|
2019-05-31 15:58:34 +08:00
|
|
|
|
|
|
|
|
|
|
|
describe('complete test', () => {
|
|
|
|
describe('hive', () => {
|
|
|
|
test('complete result', () => {
|
2019-12-31 18:34:31 +08:00
|
|
|
const sql = 'select id,name from `user` ;';
|
2019-09-25 15:43:36 +08:00
|
|
|
const result = parser.parserSql([sql, ''], dtSqlParser.parser.sqlType.Hive);
|
2019-05-31 15:58:34 +08:00
|
|
|
expect(result.locations).toBeInstanceOf(Array);
|
|
|
|
expect(result.suggestKeywords).toBeInstanceOf(Array);
|
|
|
|
});
|
|
|
|
test('empty result', () => {
|
|
|
|
const sql = 'i';
|
2019-09-25 15:43:36 +08:00
|
|
|
const result = parser.parserSql([sql, ''], dtSqlParser.parser.sqlType.Hive);
|
2019-05-31 15:58:34 +08:00
|
|
|
expect(result.locations).toBeInstanceOf(Array);
|
|
|
|
expect(result.locations).toHaveLength(0);
|
|
|
|
expect(result.suggestKeywords).toBeInstanceOf(Array);
|
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
describe('syntax test', () => {
|
2019-12-23 17:57:22 +08:00
|
|
|
describe('impala', () => {
|
|
|
|
test('no error', () => {
|
2019-12-31 18:34:31 +08:00
|
|
|
const sql = 'select id,name from user1 ';
|
2019-12-23 17:57:22 +08:00
|
|
|
const result = parser.parseSyntax([sql, ''], dtSqlParser.parser.sqlType.Impala);
|
|
|
|
expect(result).toBe(false);
|
|
|
|
});
|
|
|
|
test('insert', () => {
|
2019-12-31 18:34:31 +08:00
|
|
|
const sql = `insert into user1 (id, name) values (1 ,'a')`;
|
2019-12-23 17:57:22 +08:00
|
|
|
const result = parser.parseSyntax([sql, ''], dtSqlParser.parser.sqlType.Impala);
|
|
|
|
expect(result).toBe(false);
|
|
|
|
});
|
|
|
|
test('WITH SERDEPROPERTIES', () => {
|
|
|
|
const sql =`CREATE TABLE ih.h_b_py_detail (
|
|
|
|
contract_no STRING,
|
|
|
|
region_code STRING,
|
|
|
|
credit_code STRING
|
|
|
|
)
|
|
|
|
PARTITIONED BY (
|
|
|
|
cdate STRING
|
|
|
|
)
|
|
|
|
ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n'
|
|
|
|
WITH SERDEPROPERTIES ('field.delim'=',', 'line.delim'='\n', 'serialization.format'=',')
|
|
|
|
STORED AS TEXTFILE
|
|
|
|
LOCATION 'hdfs://kudu1'
|
2019-12-25 10:58:12 +08:00
|
|
|
TBLPROPERTIES ('last_modified_by'='anonymous', 'last_modified_time'='1577082098', 'skip.header.line.count'='1')
|
|
|
|
lifecycle 888`;
|
2019-12-23 17:57:22 +08:00
|
|
|
const result = parser.parseSyntax([sql, ''], dtSqlParser.parser.sqlType.Impala);
|
|
|
|
expect(result).toBe(false);
|
|
|
|
})
|
2019-12-27 19:30:37 +08:00
|
|
|
test('left function', () => {
|
|
|
|
const sql = `select left(a) from sa;`
|
|
|
|
const result = parser.parseSyntax([sql, ''], dtSqlParser.parser.sqlType.Impala);
|
|
|
|
expect(result).toBe(false);
|
|
|
|
})
|
2020-01-10 17:00:09 +08:00
|
|
|
test('create as select', () => {
|
|
|
|
const sql = `create table partitions_yes partitioned by (year, month)
|
|
|
|
as select s, year, month from partitions_no;`
|
|
|
|
const result = parser.parseSyntax([sql, ''], dtSqlParser.parser.sqlType.Impala);
|
|
|
|
expect(result).toBe(false);
|
|
|
|
})
|
|
|
|
test('show grant ', () => {
|
|
|
|
const sql = `show grant role 18_112_a;`
|
|
|
|
const result = parser.parseSyntax([sql, ''], dtSqlParser.parser.sqlType.Impala);
|
|
|
|
expect(result).toBe(false);
|
|
|
|
})
|
2019-12-23 17:57:22 +08:00
|
|
|
});
|
2019-05-31 15:58:34 +08:00
|
|
|
describe('hive', () => {
|
|
|
|
test('no error', () => {
|
2019-12-31 18:34:31 +08:00
|
|
|
const sql = 'select id,name from user1 ';
|
2019-09-25 15:43:36 +08:00
|
|
|
const result = parser.parseSyntax([sql, ''], dtSqlParser.parser.sqlType.Hive);
|
2019-05-31 15:58:34 +08:00
|
|
|
expect(result).toBe(false);
|
|
|
|
});
|
2020-03-26 11:47:47 +08:00
|
|
|
test('insert', () => {
|
2020-03-26 13:06:16 +08:00
|
|
|
const sql = `insert into table user1 values (1, 'a'), (2, 'b'), (3, 'b')`;
|
2020-03-26 11:47:47 +08:00
|
|
|
const result = parser.parseSyntax([sql, ''], dtSqlParser.parser.sqlType.Hive);
|
|
|
|
expect(result).toBe(false);
|
|
|
|
});
|
2019-05-31 15:58:34 +08:00
|
|
|
test('select table should not be null', () => {
|
|
|
|
const sql = 'select id,name from ';
|
2019-09-25 15:43:36 +08:00
|
|
|
const result = parser.parseSyntax([sql, ''], dtSqlParser.parser.sqlType.Hive) as SyntaxResult;
|
2019-05-31 15:58:34 +08:00
|
|
|
expect(result.loc).toEqual({
|
|
|
|
first_line: 1,
|
|
|
|
last_line: 1,
|
|
|
|
first_column: 20,
|
|
|
|
last_column: 20
|
|
|
|
})
|
|
|
|
});
|
|
|
|
test('sql contains the wrong keyword', () => {
|
|
|
|
const sql = `create table if not 1exists ods_order_header (
|
|
|
|
order_header_id string comment 'order id'
|
|
|
|
,order_date bigint comment 'order date'
|
|
|
|
)comment 'order table'
|
|
|
|
PARTITIONED BY (ds string);`;
|
2019-09-25 15:43:36 +08:00
|
|
|
const result = parser.parseSyntax([sql, ''], dtSqlParser.parser.sqlType.Hive) as SyntaxResult;
|
2019-05-31 15:58:34 +08:00
|
|
|
expect(result.text).toBe('1exists');
|
|
|
|
expect(result.loc).toEqual({
|
|
|
|
first_line: 1,
|
|
|
|
last_line: 1,
|
|
|
|
first_column: 20,
|
|
|
|
last_column: 27
|
|
|
|
})
|
|
|
|
});
|
|
|
|
})
|
2019-09-25 15:43:36 +08:00
|
|
|
describe('flinksql', () => {
|
|
|
|
test('no error', () => {
|
2019-12-31 18:34:31 +08:00
|
|
|
const sql = `select id from use1r.id;`;
|
2019-09-25 15:43:36 +08:00
|
|
|
const result = flinksqlParser(sql);
|
|
|
|
expect(result).toBeNull();
|
|
|
|
});
|
|
|
|
test('empty sql', () => {
|
|
|
|
const sql = ``;
|
|
|
|
const result = flinksqlParser(sql);
|
|
|
|
expect(result).toBeNull();
|
|
|
|
});
|
2019-09-25 16:48:19 +08:00
|
|
|
test('sql comment', () => {
|
|
|
|
const sql = `-- name asf
|
|
|
|
-- type FlinkSQL
|
|
|
|
-- author admin@dtstack.com
|
|
|
|
-- create time 2019-06-12 18:11:05
|
|
|
|
-- desc `;
|
|
|
|
const result = flinksqlParser(sql);
|
|
|
|
expect(result).toBeNull();
|
|
|
|
});
|
2019-09-25 17:04:43 +08:00
|
|
|
test('position', () => {
|
|
|
|
const sql = `selec`;
|
|
|
|
const result = flinksqlParser(sql);
|
|
|
|
expect(result.token.start).toBe(0);
|
|
|
|
expect(result.token.stop).toBe(4);
|
|
|
|
});
|
2019-10-08 17:22:35 +08:00
|
|
|
test('test lateral table', () => {
|
|
|
|
const sql = `select
|
|
|
|
id
|
|
|
|
FROM
|
|
|
|
userTable, LATERAL table(json(mess)) as t(ord, name_id);`;
|
|
|
|
const result = flinksqlParser(sql);
|
|
|
|
expect(result).toBeNull();
|
|
|
|
});
|
2019-09-25 15:43:36 +08:00
|
|
|
test('syntax error', () => {
|
2019-12-31 18:34:31 +08:00
|
|
|
const sql = 'select id from us1er.id; \nselect id from us*er.id; \nselect id from *u1ser.id;';
|
2019-09-25 15:43:36 +08:00
|
|
|
const result = flinksqlParser(sql);
|
|
|
|
expect(result).toMatchObject({
|
|
|
|
line: 2,
|
|
|
|
column: 17,
|
|
|
|
});
|
2019-12-31 18:34:31 +08:00
|
|
|
expect(result.token.start).toBe(43);
|
|
|
|
expect(result.token.stop).toBe(43);
|
2019-09-29 17:38:52 +08:00
|
|
|
const sql2 = `CREATE TABLE MyTable(
|
|
|
|
message.after.id int AS id,
|
|
|
|
message.after.userid varchar AS userid,
|
|
|
|
message.after.username varchar AS username,
|
|
|
|
message.after.prodid varchar AS prodid,
|
|
|
|
message.after.price double AS price,
|
|
|
|
message.after.amount int AS amount,
|
|
|
|
message.after.discount double AS discount,
|
|
|
|
message.after.tm timestamp AS tm,
|
|
|
|
WATERMARK FOR tm AS withOffset(tm,1000)
|
|
|
|
)WITH(
|
|
|
|
'type' ='kafka11,
|
|
|
|
topic ='1'
|
|
|
|
);
|
|
|
|
|
|
|
|
CREATE TABLE MyResult(
|
|
|
|
a double,
|
|
|
|
b timestamp,
|
|
|
|
c timestamp
|
|
|
|
)WITH(
|
|
|
|
type ='mysql',
|
|
|
|
url ='jdbc:mysql://1:3306/yanxi?charset=utf8'
|
|
|
|
);
|
|
|
|
|
|
|
|
insert into MyResult
|
|
|
|
select
|
|
|
|
sum(price * amount * discount) as a,
|
|
|
|
TUMBLE_START( ROWTIME, INTERVAL '30' SECOND) as b
|
|
|
|
from MyTable
|
|
|
|
group by
|
|
|
|
TUMBLE( ROWTIME, INTERVAL '30' SECOND);`;
|
|
|
|
const result2 = flinksqlParser(sql2);
|
|
|
|
expect(result2).not.toBeNull();
|
|
|
|
});
|
2019-10-21 16:52:16 +08:00
|
|
|
test('MATCH_RECOGNIZE', () => {
|
|
|
|
const sql = `SELECT *
|
|
|
|
FROM Ticker
|
|
|
|
MATCH_RECOGNIZE (
|
|
|
|
PARTITION BY symbol
|
|
|
|
ORDER BY rowtime
|
|
|
|
MEASURES
|
|
|
|
START_ROW.rowtime AS start_tstamp,
|
|
|
|
LAST(PRICE_DOWN.rowtime) AS bottom_tstamp,
|
|
|
|
LAST(PRICE_UP.rowtime) AS end_tstamp
|
|
|
|
ONE ROW PER MATCH
|
|
|
|
AFTER MATCH SKIP TO LAST PRICE_UP
|
|
|
|
PATTERN (START_ROW PRICE_DOWN+ PRICE_UP)
|
|
|
|
DEFINE
|
|
|
|
PRICE_DOWN AS
|
|
|
|
(LAST(PRICE_DOWN.price, 1) IS NULL AND PRICE_DOWN.price < START_ROW.price) OR
|
|
|
|
PRICE_DOWN.price < LAST(PRICE_DOWN.price, 1),
|
|
|
|
PRICE_UP AS
|
|
|
|
PRICE_UP.price > LAST(PRICE_DOWN.price, 1)
|
|
|
|
) MR;`;
|
|
|
|
const result = flinksqlParser(sql);
|
|
|
|
expect(result).toBeNull();
|
|
|
|
})
|
2019-11-15 11:01:55 +08:00
|
|
|
test('test primary key', () => {
|
|
|
|
const sql = `create table aa(
|
|
|
|
name.a[1].a varchar as name ,
|
|
|
|
ts int,
|
|
|
|
primary key (id, id[2])
|
|
|
|
) with (
|
|
|
|
type = 'kafka',
|
|
|
|
aa = '12'
|
|
|
|
);`;
|
|
|
|
const result = flinksqlParser(sql);
|
|
|
|
expect(result).toBeNull();
|
|
|
|
})
|
2019-09-25 15:43:36 +08:00
|
|
|
})
|
2019-05-31 15:58:34 +08:00
|
|
|
})
|