def parse_fks():
    FK_PATTERN = '(?:CONSTRAINT (\\w+) +)?FOREIGN KEY *\\( *(.+?) *\\) +REFERENCES +(?:(?:"(.+?)")|([a-z0-9_]+)) *\\((.+?)\\) *((?:ON (?:DELETE|UPDATE) (?:SET NULL|SET DEFAULT|CASCADE|RESTRICT|NO ACTION) *)*)'
    for match in re.finditer(FK_PATTERN, table_data, re.I):
        (constraint_name, constrained_columns, referred_quoted_name, referred_name, referred_columns, onupdatedelete) = match.group(1, 2, 3, 4, 5, 6)
        constrained_columns = list(self._find_cols_in_sig(constrained_columns))
        if (not referred_columns):
            referred_columns = constrained_columns
        else:
            referred_columns = list(self._find_cols_in_sig(referred_columns))
        referred_name = (referred_quoted_name or referred_name)
        options = {}
        for token in re.split(' *\\bON\\b *', onupdatedelete.upper()):
            if token.startswith('DELETE'):
                ondelete = token[6:].strip()
                if (ondelete and (ondelete != 'NO ACTION')):
                    options['ondelete'] = ondelete
            elif token.startswith('UPDATE'):
                onupdate = token[6:].strip()
                if (onupdate and (onupdate != 'NO ACTION')):
                    options['onupdate'] = onupdate
        (yield (constraint_name, constrained_columns, referred_name, referred_columns, options))
def parse_fks():
    FK_PATTERN = '(?:CONSTRAINT (\\w+) +)?FOREIGN KEY *\\( *(.+?) *\\) +REFERENCES +(?:(?:"(.+?)")|([a-z0-9_]+)) *\\((.+?)\\) *((?:ON (?:DELETE|UPDATE) (?:SET NULL|SET DEFAULT|CASCADE|RESTRICT|NO ACTION) *)*)'
    for match in re.finditer(FK_PATTERN, table_data, re.I):
        (constraint_name, constrained_columns, referred_quoted_name, referred_name, referred_columns, onupdatedelete) = match.group(1, 2, 3, 4, 5, 6)
        constrained_columns = list(self._find_cols_in_sig(constrained_columns))
        if (not referred_columns):
            referred_columns = constrained_columns
        else:
            referred_columns = list(self._find_cols_in_sig(referred_columns))
        referred_name = (referred_quoted_name or referred_name)
        options = {}
        for token in re.split(' *\\bON\\b *', onupdatedelete.upper()):
            if token.startswith('DELETE'):
                ondelete = token[6:].strip()
                if (ondelete and (ondelete != 'NO ACTION')):
                    options['ondelete'] = ondelete
            elif token.startswith('UPDATE'):
                onupdate = token[6:].strip()
                if (onupdate and (onupdate != 'NO ACTION')):
                    options['onupdate'] = onupdate
        (yield (constraint_name, constrained_columns, referred_name, referred_columns, options))