Repository navigation
Conversation
LOAD DATA INFILE failed at INFILE, since LOAD DATA only read BigQuery's LOAD DATA INTO, and LOAD XML was read as DuckDB's LOAD of an extension named xml. Both now parse to MySqlLoadDataStatement with every clause of the MySQL 8.4 grammar, in the MySQL and MariaDB dialects and without a dialect. The other LOAD readings and the other dialects are unchanged. The FIELDS and LINES clauses become MySqlFileFormat, one model and one production shared with SELECT ... INTO OUTFILE, whose getters and setters now read and write it. As in MySQL, each clause needs a subclause and the subclauses may come in any order, so a bare FIELDS or LINES after INTO OUTFILE is now rejected. INTO OUTFILE also takes CHARSET and a quoted character set name. BigQuery's LOAD DATA now deparses its options through the expression deparser, and LOAD DATA and EXPORT DATA share one WITH CONNECTION production. Signed-off-by: minleejae <mmj9808@gmail.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Purpose
MySQL's
LOAD DATAandLOAD XMLfailed to parse, so a script that loads CSV or XML filesstopped at its first load:
LOAD DATA INFILEfailed atINFILE, becauseLOAD DATAonly read BigQuery'sLOAD DATA {INTO | OVERWRITE}. Any otherLOAD xwas DuckDB'sLOAD extension, soLOAD XML INFILE …failed atINFILE, afterLOAD XMLhad been read as an extension namedxml.SELECT … INTO OUTFILEuses the sameFIELDSandLINESclauses, and they differed fromMySQL's grammar there too:
FIELDSorLINES, which MySQL rejects, was accepted, and a bareLINESwas droppedfrom the output:
SELECT a INTO OUTFILE 'f' LINES FROM tprinted asSELECT a INTO OUTFILE 'f' FROM t.FIELDS ESCAPED BY '\\' TERMINATED BY ','.CHARSETand a quoted character set name (CHARACTER SET 'utf8mb4') were rejected.Current design (As-is)
LoadDataStatementmodels BigQuery'sLOAD DATA; it shares only the target table withMySQL's statement. Its deparse printed the
OPTIONSandFROM FILESexpressions withtoString(), bypassingExpressionDeParser.LOAD xwent toExtensionStatementunless the second word wasDATA.MySqlSelectIntoClauseheld theFIELDS/LINESsubclauses as seven flat fields, filled bythree OUTFILE-only productions that allowed only the documented order and an empty clause.
LoadDataStatementandExportDataStatementhad two copies of theWITH CONNECTIONproduction.
Target design (To-be)
MySqlLoadDataStatement(instatement.load, next to BigQuery'sLoadDataStatement)models both statements of the
MySQL 8.4 grammar:
getFormat()(DATAorXML),getLockOption()(LOW_PRIORITYorCONCURRENT),isLocal(),getFileName(),getDuplicateHandling()(REPLACEorIGNORE, reusingCreateTable.DuplicateHandlingofCREATE TABLE … SELECT),getTable(),getPartitions(),getCharacterSet()/isUseCharsetKeyword(),getRowsIdentifiedBy(),getFileFormat(),getIgnoreCount()/getIgnoreUnit()(LINESorROWS),getColumns()(columns and uservariables; empty for
()) andgetUpdateSets()(theSETclause asUpdateSets, one columnand one value each). As in MySQL's grammar,
LOAD DATAandLOAD XMLtake the same clauses inthe same order.
MySqlFileFormat(instatement) is the one model of the{FIELDS | COLUMNS}andLINESclauses, andMySqlFileFormat()is the one production, shared byLOAD DATAandSELECT … INTO OUTFILE. Each clause needs at least one subclause. Like MySQL'sfield_term_listandline_term_list, the subclauses may come in any order and repeat. Likethe server, the format keeps the last value of each and prints them in the documented order:
FIELDS ESCAPED BY '\\' TERMINATED BY ','prints asFIELDS TERMINATED BY ',' ESCAPED BY '\\'.An
OPTIONALLY ENCLOSED BYstays optional after a laterENCLOSED BY, as in the server.MySqlSelectIntoClausegainsgetFileFormat(). Its existing getters and setters(
getFieldsTerminatedBy(),setFieldsOptionallyEnclosed(),getFieldsKeyword(), …) stay, andread and write the shared format.
MySqlSelectIntoClause.FieldsKeywordstays and maps toMySqlFileFormat.FieldsKeyword.CHARACTER SETalso takesCHARSET(isUseCharsetKeyword())and a quoted name, with a production shared with
LOAD DATA. The clause now records its sourcerange, as every parsed object should since fix: give every parsed object a node spanning its source #2870.
LOAD {DATA | XML} [LOW_PRIORITY | CONCURRENT] [LOCAL] INFILEis MySQL'sstatement, in the MySQL and MariaDB dialects and without a dialect. BigQuery's
LOAD DATA INTO, DuckDB'sLOAD httpfs, PostgreSQL'sLOAD 'auto_explain'andLOAD xmlkeep their reading. The other dialects keep rejecting the MySQL forms. No token is added;
INFILEandCONCURRENTremain usable as names.FIELDS,COLUMNSorLINESafterINTO OUTFILEis now aparse error, as in MySQL.
IGNORE n LINESaccepts at most 2147483647, the limit of MySQL'sgrammar.
StatementVisitor(default methods),StatementVisitorAdapter(target table,column list,
SETclause),StatementDeParser(oneappendToshared withtoString(); thecolumn list and the
SETclause go throughExpressionDeParser),TablesNamesFinder(thetarget table and the tables of
SETsubqueries), feature analysis (MODIFIES_DATA) andvalidation (the existing
loadDatafeature, now in the MySQL and MariaDB capabilities).LOAD DATA'sOPTIONSandFROM FILESexpressionsnow go through
ExpressionDeParser, likeEXPORT DATA's, and both statements share oneWITH CONNECTIONproduction.Not included:
LOAD DATApage does not document(
FROM,URL,S3,COUNT n,IN PRIMARY KEY ORDER,COMPRESSION =,PARALLEL =,MEMORY =,ALGORITHM = BULK).TERMINATED BY 0x2c,X'2c',b'0'): the releasedMySqlSelectIntoClausegetters returnStringValue.:=in theSETclause andCHAR SET, whichUPDATEand column types do not read either.LOAD INDEX INTO CACHE.Validation
92 new test cases:
MySqlLoadDataStatementTest(66: every clause with the MySQL and MariaDBdialects and without one,
toString()andStatementDeParseroutput, re-parse, AST fields,subclauses in any order, rejected forms, other dialects and other
LOADreadings, statementboundaries, visitors,
TablesNamesFinder, feature analysis, source ranges, building in code),MySqlFileFormatTest(18:INTO OUTFILEforms, the delegating getters and setters, rejectedbare clauses),
LoadDataValidatorTest(3),StructuredStatementVisitorTest(+4: BigQuery andMySQL
LOAD DATAthrough a customExpressionDeParser) andStatementValidatorTest(+1).ASTNodeCoverageTestalso checks the source ranges of fourLOADandINTO OUTFILEstatements.
./gradlew spotlessApply cleanTest check jar: 13,027 tests, 0 failures, 25 skipped; the grammarhas no JavaCC choice conflicts; Checkstyle, PMD and SpotBugs pass.
Compared with
master(a30a67920) on the DDL/DCL survey corpora and on the non-DDLstatement corpora (MySQL and PostgreSQL, each with its dialect and without one): the three
MySQL
LOAD DATA/LOAD XMLstatements are fixed with the MySQL dialect and without one, withno regressions and no other changed result.
MySQL 8.4.11 accepts all 64 statements the tests accept for the MySQL dialect, 55 of which
masterrejects. They fail only when run, mostly with--secure-file-priv(1290) orLoading local data is disabled(3948). This includes the repeated and reorderedFIELDS/LINESsubclauses,ROWS IDENTIFIED BYinLOAD DATA,FIELDS/LINESinLOAD XML,IGNORE 2147483647 LINES,CHARACTER SET 'utf8mb4'and an empty column list. It reports a syntax error (1064) for all 34 statements the tests reject, including bareFIELDS/LINESafterINTO OUTFILE,IGNORE 2147483648 LINES,LOAD DATA LOCAL LOW_PRIORITY …and clauses out of order.AI assistance: prepared with Claude Code.