Skip to content

Commit 7412ea4

Browse files
committed
feat: support load data in mariadb
1 parent 705fca0 commit 7412ea4

2 files changed

Lines changed: 78 additions & 5 deletions

File tree

pegjs/mariadb.pegjs

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,7 @@ cmd_stmt
252252
/ grant_stmt
253253
/ explain_stmt
254254
/ transaction_stmt
255+
/ load_data_stmt
255256

256257
create_stmt
257258
= create_table_stmt
@@ -1808,6 +1809,70 @@ transaction_stmt
18081809
}
18091810
}
18101811

1812+
load_data_field
1813+
= k:('FIELDS'i / 'COLUMNS'i) __ t:('TERMINATED'i __ 'BY'i __ ident_without_kw_type)? __ en:(('OPTIONALLY'i)? __ 'ENCLOSED'i __ 'BY'i __ ident_without_kw_type)? __ es:('ESCAPED'i __ 'BY'i __ ident_without_kw_type)? {
1814+
if (t) t[4].prefix = 'TERMINATED BY'
1815+
if (en) en[6].prefix = `${en[0] && en[0].toUpperCase() === 'OPTIONALLY' ? 'OPTIONALLY ' : ''}ENCLOSED BY`
1816+
if (es) es[4].prefix = 'ESCAPED BY'
1817+
return {
1818+
keyword: k,
1819+
terminated: t && t[4],
1820+
enclosed: en && en[6],
1821+
escaped: es && es[4]
1822+
}
1823+
}
1824+
1825+
load_data_line_starting
1826+
= k:('STARTING'i / 'TERMINATED'i) __ 'BY'i __ s:ident_without_kw_type {
1827+
s.prefix = `${k.toUpperCase()} BY`
1828+
return {
1829+
type: k.toLowerCase(),
1830+
[k.toLowerCase()]: s
1831+
}
1832+
}
1833+
load_data_line
1834+
= k:'LINES'i __ s:load_data_line_starting? __ t:load_data_line_starting? {
1835+
if (s && t && s.type === t.type) throw new Error('LINES cannot be specified twice')
1836+
if (s) Reflect.deleteProperty(s, 'type')
1837+
if (t) Reflect.deleteProperty(t, 'type')
1838+
return {
1839+
keyword: k,
1840+
...(s || {}),
1841+
...(t || {})
1842+
}
1843+
}
1844+
1845+
load_data_stmt
1846+
= 'LOAD'i __ 'DATA'i __ lc:('LOW_PRIORITY'i / 'CONCURRENT'i)? __ lo:('LOCAL'i)? __
1847+
'INFILE'i __ file:ident_without_kw_type __ ri:replace_insert? __
1848+
'INTO'i __ 'TABLE'i __ table:table_name __
1849+
pa:insert_partition? __
1850+
cs:(create_option_character_set_kw __ ident_without_kw_type)? __
1851+
fields:load_data_field? __
1852+
lines:load_data_line? __
1853+
ig:(KW_IGNORE __ literal_numeric __ ('LINES'i / 'ROWS'i))? __
1854+
co:column_clause? __
1855+
set:(KW_SET __ set_list)? {
1856+
return {
1857+
type: 'load_data',
1858+
mode: lc,
1859+
local: lo,
1860+
file: file,
1861+
replace_ignore: ri,
1862+
table: table,
1863+
partition: pa,
1864+
character_set: cs,
1865+
fields: fields,
1866+
lines: lines,
1867+
ignore: ig && {
1868+
count: ig[2],
1869+
suffix: ig[4]
1870+
},
1871+
column: co,
1872+
set: set && set[2]
1873+
}
1874+
}
1875+
18111876
lock_type
18121877
= "READ"i __ s:("LOCAL"i)? {
18131878
return {
@@ -3092,7 +3157,7 @@ double_quoted_ident
30923157
}
30933158

30943159
single_quoted_ident
3095-
= "'" chars:[^']+ "'" {
3160+
= "'" chars:[^']* "'" {
30963161
return {
30973162
type: 'single_quote_string',
30983163
value: chars.join('')

test/mysql-mariadb.spec.js

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1406,13 +1406,21 @@ describe('mysql', () => {
14061406
describe('load data', () => {
14071407
it('should support load data', () => {
14081408
let sql = `LOAD DATA LOCAL INFILE "mycsv.csv" INTO TABLE mytable FIELDS TERMINATED BY ' ^' IGNORE 1 LINES;`
1409-
expect(getParsedSql(sql)).to.equal(`LOAD DATA LOCAL INFILE "mycsv.csv" INTO TABLE \`mytable\` FIELDS TERMINATED BY ' ^' IGNORE 1 LINES`)
1409+
let parsedSQL = `LOAD DATA LOCAL INFILE "mycsv.csv" INTO TABLE \`mytable\` FIELDS TERMINATED BY ' ^' IGNORE 1 LINES`
1410+
expect(getParsedSql(sql)).to.equal(parsedSQL)
1411+
expect(getParsedSql(sql, mariadb)).to.equal(parsedSQL)
14101412
sql = `LOAD DATA LOW_PRIORITY LOCAL INFILE '/tmp/test.txt' REPLACE INTO TABLE test FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' STARTING BY ''`
1411-
expect(getParsedSql(sql)).to.equal("LOAD DATA LOW_PRIORITY LOCAL INFILE '/tmp/test.txt' REPLACE INTO TABLE `test` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES STARTING BY '' TERMINATED BY '\n'")
1413+
parsedSQL = "LOAD DATA LOW_PRIORITY LOCAL INFILE '/tmp/test.txt' REPLACE INTO TABLE `test` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES STARTING BY '' TERMINATED BY '\n'"
1414+
expect(getParsedSql(sql)).to.equal(parsedSQL)
1415+
expect(getParsedSql(sql, mariadb)).to.equal(parsedSQL)
14121416
sql = `LOAD DATA LOW_PRIORITY LOCAL INFILE '/tmp/test.txt' REPLACE INTO TABLE test FIELDS TERMINATED BY '\t' OPTIONALLY ENCLOSED BY '' ESCAPED BY '\\' IGNORE 1 LINES (column1, @var1) SET column2 = @var1/100;`
1413-
expect(getParsedSql(sql)).to.equal("LOAD DATA LOW_PRIORITY LOCAL INFILE '/tmp/test.txt' REPLACE INTO TABLE \`test\` FIELDS TERMINATED BY '\t' OPTIONALLY ENCLOSED BY '' ESCAPED BY '\\' IGNORE 1 LINES (`column1`, @var1) SET `column2` = @var1 / 100")
1417+
parsedSQL = "LOAD DATA LOW_PRIORITY LOCAL INFILE '/tmp/test.txt' REPLACE INTO TABLE \`test\` FIELDS TERMINATED BY '\t' OPTIONALLY ENCLOSED BY '' ESCAPED BY '\\' IGNORE 1 LINES (`column1`, @var1) SET `column2` = @var1 / 100"
1418+
expect(getParsedSql(sql)).to.equal(parsedSQL)
1419+
expect(getParsedSql(sql, mariadb)).to.equal(parsedSQL)
14141420
sql = `LOAD DATA INFILE 'file.txt' INTO TABLE t1 (column1, column2) SET column3 = CURRENT_TIMESTAMP;`
1415-
expect(getParsedSql(sql)).to.equal("LOAD DATA INFILE 'file.txt' INTO TABLE `t1` (`column1`, `column2`) SET `column3` = CURRENT_TIMESTAMP")
1421+
parsedSQL = "LOAD DATA INFILE 'file.txt' INTO TABLE `t1` (`column1`, `column2`) SET `column3` = CURRENT_TIMESTAMP"
1422+
expect(getParsedSql(sql)).to.equal(parsedSQL)
1423+
expect(getParsedSql(sql, mariadb)).to.equal(parsedSQL)
14161424
})
14171425
})
14181426
})

0 commit comments

Comments
 (0)