@@ -296,7 +296,7 @@ function parse_create_definition($tokens, &$i){
296296 $ fields = array ();
297297 $ indexes = array ();
298298
299- while ($ tokens [$ i ] != ') ' ){
299+ while ($ i < count ( $ tokens ) && $ tokens [$ i ] != ') ' ){
300300
301301 $ these_tokens = $ this ->slice_until_next_field ($ tokens , $ i );
302302
@@ -452,23 +452,54 @@ function parse_field_or_key(&$tokens, &$fields, &$indexes){
452452 return ;
453453
454454
455- # unsupported
455+ # FOREIGN KEY [index_name] (index_col_name,...) reference_definition
456+ # reference_definition:
457+ # REFERENCES tbl_name (index_col_name,...)
458+ # [MATCH FULL | MATCH PARTIAL | MATCH SIMPLE]
459+ # [ON DELETE reference_option]
460+ # [ON UPDATE reference_option]
456461
457462 case 'FOREIGN KEY ' :
458463
459- # TODO
460- $ fields [] = array (
461- '_ ' => 'FOREIGN KEY ' ,
462- 'tokens ' => $ tokens ,
464+ $ index = array (
465+ 'type ' => 'FOREIGN ' ,
463466 );
467+
468+ array_shift ($ tokens );
469+
470+ if ($ tokens [0 ] != '( ' ){
471+ $ index ['name ' ] = $ this ->decode_identifier (array_shift ($ tokens ));
472+ }
473+
474+ $ this ->parse_index_columns ($ tokens , $ index );
475+
476+ if ($ tokens [0 ] == 'REFERENCES ' ){
477+ array_shift ($ tokens );
478+ $ index ['ref_table ' ] = $ this ->decode_identifier (array_shift ($ tokens ));
479+
480+ $ old_cols = $ index ['cols ' ];
481+ $ index ['cols ' ] = array ();
482+ $ this ->parse_index_columns ($ tokens , $ index );
483+ $ index ['ref_cols ' ] = $ index ['cols ' ];
484+ $ index ['cols ' ] = $ old_cols ;
485+
486+ if (count ($ tokens ) >= 1 && $ tokens [0 ] == 'MATCH FULL ' ){ $ index ['ref_match ' ] = 'FULL ' ; array_shift ($ tokens ); }
487+ if (count ($ tokens ) >= 1 && $ tokens [0 ] == 'MATCH PARTIAL ' ){ $ index ['ref_match ' ] = 'PARTIAL ' ; array_shift ($ tokens ); }
488+ if (count ($ tokens ) >= 1 && $ tokens [0 ] == 'MATCH SIMPLE ' ){ $ index ['ref_match ' ] = 'SIMPLE ' ; array_shift ($ tokens ); }
489+
490+ if (count ($ tokens ) > 1 && $ tokens [0 ] == 'ON DELETE ' ){ array_shift ($ tokens ); $ index ['ref_on_delete ' ] = array_shift ($ tokens ); }
491+ if (count ($ tokens ) > 1 && $ tokens [0 ] == 'ON UPDATE ' ){ array_shift ($ tokens ); $ index ['ref_on_delete ' ] = array_shift ($ tokens ); }
492+ }
493+
494+ if (count ($ tokens )) $ index ['more ' ] = $ tokens ;
495+ $ indexes [] = $ index ;
464496 return ;
465497
466498 case 'CHECK ' :
467499
468- # TODO
469- $ fields [] = array (
470- '_ ' => 'CHECK ' ,
471- 'tokens ' => $ tokens ,
500+ $ indexes [] = array (
501+ 'type ' => 'CHECK ' ,
502+ 'tokens ' => array_slice ($ tokens , 1 ),
472503 );
473504 return ;
474505 }
@@ -481,7 +512,7 @@ function slice_until_next_field($tokens, &$i){
481512 $ out = array ();
482513 $ stack = 0 ;
483514
484- while ($ i <= count ($ tokens )){
515+ while ($ i < count ($ tokens )){
485516 $ next = $ tokens [$ i ];
486517 if ($ next == '( ' ){
487518 $ stack ++;
@@ -748,6 +779,14 @@ function _extract_tokens($sql, &$source_map){
748779 'IF NOT EXISTS ' ,
749780 'NOT NULL ' ,
750781 'WITH PARSER ' ,
782+ 'MATCH FULL ' ,
783+ 'MATCH PARTIAL ' ,
784+ 'MATCH SIMPLE ' ,
785+ 'ON DELETE ' ,
786+ 'ON UPDATE ' ,
787+ 'SET NULL ' ,
788+ 'NO ACTION ' ,
789+ 'SET DEFAULT ' ,
751790 );
752791
753792 $ singles = array (
0 commit comments