2424class IntoKeyword extends Component
2525{
2626
27+ /**
28+ * FIELDS/COLUMNS Options for `SELECT...INTO` statements.
29+ *
30+ * @var array
31+ */
32+ public static $ FIELDS_OPTIONS = array (
33+
34+ 'TERMINATED BY ' => array (1 , 'expr ' ),
35+ 'OPTIONALLY ' => 2 ,
36+ 'ENCLOSED BY ' => array (3 , 'expr ' ),
37+ 'ESCAPED BY ' => array (4 , 'expr ' ),
38+ );
39+
40+ /**
41+ * LINES Options for `SELECT...INTO` statements.
42+ *
43+ * @var array
44+ */
45+ public static $ LINES_OPTIONS = array (
46+
47+ 'STARTING BY ' => array (1 , 'expr ' ),
48+ 'TERMINATED BY ' => array (2 , 'expr ' ),
49+ );
50+
2751 /**
2852 * Type of target (OUTFILE or SYMBOL).
2953 *
@@ -52,6 +76,29 @@ class IntoKeyword extends Component
5276 */
5377 public $ values ;
5478
79+ /**
80+ * Options for FIELDS/COLUMNS keyword
81+ *
82+ * @var OptionsArray
83+ * @see static::$FIELDS_OPTIONS
84+ */
85+ public $ fields_options ;
86+
87+ /**
88+ * Whether to use `FIELDS` or `COLUMNS` while building
89+ *
90+ * @var boolean
91+ */
92+ public $ fields_keyword ;
93+
94+ /**
95+ * Options for OPTIONS keyword
96+ *
97+ * @var OptionsArray
98+ * @see static::$LINES_OPTIONS
99+ */
100+ public $ lines_options ;
101+
55102 /**
56103 * @param Parser $parser The parser that serves as context.
57104 * @param TokensList $list The list of tokens that are being parsed.
@@ -104,8 +151,10 @@ public static function parse(Parser $parser, TokensList $list, array $options =
104151 continue ;
105152 }
106153
107- // No other keyword is expected.
108- break ;
154+ // No other keyword is expected except for $state = 4, which expects `LINES`
155+ if ($ state !== 4 ) {
156+ break ;
157+ }
109158 }
110159
111160 if ($ state === 0 ) {
@@ -134,15 +183,55 @@ public static function parse(Parser $parser, TokensList $list, array $options =
134183 break ;
135184 } elseif ($ state === 2 ) {
136185 $ ret ->dest = $ token ->value ;
137- ++$ list ->idx ;
138- break ;
186+
187+ $ state = 3 ;
188+ } elseif ($ state == 3 ) {
189+ $ ret ->_parseFileOptions ($ parser , $ list , $ token ->value );
190+ $ state = 4 ;
191+ } elseif ($ state == 4 ) {
192+ if ($ token ->type === Token::TYPE_KEYWORD && $ token ->value !== 'LINES ' ) {
193+ $ parser ->error (
194+ __ ('Unexpected keyword. ' ),
195+ $ token
196+ );
197+ break ;
198+ }
199+
200+ $ ret ->_parseFileOptions ($ parser , $ list , $ token ->value );
201+ $ state = 5 ;
139202 }
140203 }
141204
142205 --$ list ->idx ;
143206 return $ ret ;
144207 }
145208
209+ private function _parseFileOptions (Parser $ parser , TokensList $ list , $ keyword ='FIELDS ' ) {
210+ ++$ list ->idx ;
211+
212+ if ($ keyword === 'FIELDS ' || $ keyword === 'COLUMNS ' ) {
213+ // parse field options
214+ $ this ->fields_options = OptionsArray::parse (
215+ $ parser ,
216+ $ list ,
217+ static ::$ FIELDS_OPTIONS
218+ );
219+
220+ if ($ keyword === 'FIELDS ' ) {
221+ $ this ->fields_keyword = true ;
222+ } else {
223+ $ this ->fields_keyword = false ;
224+ }
225+ } else {
226+ // parse line options
227+ $ this ->lines_options = OptionsArray::parse (
228+ $ parser ,
229+ $ list ,
230+ static ::$ LINES_OPTIONS
231+ );
232+ }
233+ }
234+
146235 /**
147236 * @param IntoKeyword $component The component to be built.
148237 * @param array $options Parameters for building.
@@ -158,7 +247,20 @@ public static function build($component, array $options = array())
158247 } elseif (isset ($ component ->values )) {
159248 return ExpressionArray::build ($ component ->values );
160249 } else {
161- return 'OUTFILE " ' . $ component ->dest . '" ' ;
250+ $ ret = 'OUTFILE " ' . $ component ->dest . '" ' ;
251+
252+ $ fields_options_str = OptionsArray::build ($ component ->fields_options );
253+ if (trim ($ fields_options_str ) !== '' ) {
254+ $ ret .= ($ component ->fields_keyword ) ? ' FIELDS ' : ' COLUMNS ' ;
255+ $ ret .= ' ' . $ fields_options_str ;
256+ }
257+
258+ $ lines_options_str = OptionsArray::build ($ component ->lines_options , array ('expr ' => true ));
259+ if (trim ($ lines_options_str ) !== '' ) {
260+ $ ret .= ' LINES ' . $ lines_options_str ;
261+ }
262+
263+ return $ ret ;
162264 }
163265 }
164266}
0 commit comments