in core/lib/sqlparse/create.py [0:0]
def parse(cls, sql):
try:
if not isinstance(sql, str):
sql = sql.decode("utf-8")
result = cls.get_parser().parseString(sql)
except ParseException as e:
raise ParseError(
"Failed to parse SQL, unsupported syntax: {}".format(e),
e.line,
e.column,
)
inline_pri_exists = False
table = models.Table()
table.name = result.table_name
table_options = [
"engine",
"charset",
"collate",
"row_format",
"key_block_size",
"compression",
"auto_increment",
"comment",
]
for table_option in table_options:
if table_option in result:
setattr(table, table_option, result.get(table_option))
if "partition" in result:
# pyparsing will convert newline into two after parsing. So we
# need to dedup here
table.partition = result.partition.replace("\n\n", "\n")
try:
presult = cls.parse_partitions(table.partition)
table.partition_config = cls.partition_to_model(presult)
except ParseException as e:
raise ParseError(
f"Failed to parse partitions config, unsupported syntax {e},"
f" line: {e.line} col {e.column}"
)
except PartitionParseError as mpe:
raise ParseError(
f"Failed to init model from partitions config: {mpe}, "
f"ParseResult: {presult.dump()}\nRaw: {table.partition}"
)
if "constraint" in result:
table.constraint = result.constraint
for column_def in result.column_list:
if column_def.column_type == "ENUM":
column = models.EnumColumn()
for enum_value in column_def.enum_value_list:
column.enum_list.append(enum_value)
elif column_def.column_type == "SET":
column = models.SetColumn()
for set_value in column_def.set_value_list:
column.set_list.append(set_value)
elif column_def.column_type in ("TIMESTAMP", "DATETIME"):
column = models.TimestampColumn()
if "on_update" in column_def:
if "on_update_ts_len" in column_def:
column.on_update_current_timestamp = "{}({})".format(
column_def.on_update, column_def.on_update_ts_len
)
else:
column.on_update_current_timestamp = column_def.on_update
else:
column = models.Column()
column.name = column_def.column_name
column.column_type = column_def.column_type
if column.column_type == "JSON":
table.has_80_features = True
# We need to check whether each column property exist in the
# create table string, because not specifying a "COMMENT" is
# different from specifying "COMMENT" equals to empty string.
# The former one will ends up being
# column=None
# and the later one being
# column=''
if "comment" in column_def:
column.comment = column_def.comment
if "nullable" in column_def:
if column_def.nullable == "NULL":
column.nullable = True
elif column_def.nullable == "NOT NULL":
column.nullable = False
if "unsigned" in column_def:
if column_def.unsigned == "UNSIGNED":
column.unsigned = True
if "default" in column_def:
if "ts_len" in column_def:
column.default = "{}({})".format(
column_def.default, column_def.ts_len
)
else:
column.default = column_def.default
if "is_bit" in column_def:
column.is_default_bit = True
if "charset" in column_def:
column.charset = column_def.charset
if "length" in column_def:
column.length = column_def.length
if "collate" in column_def:
column.collate = column_def.collate
if "auto_increment" in column_def:
column.auto_increment = True
if "primary" in column_def:
idx_col = models.IndexColumn()
idx_col.name = column_def.column_name
table.primary_key.column_list.append(idx_col)
inline_pri_exists = True
table.column_list.append(column)
if "pri_list" in result:
if inline_pri_exists:
raise ParseError("Multiple primary keys defined")
table.primary_key.name = "PRIMARY"
for col in result.pri_list:
for name, length, order in col:
idx_col = models.IndexColumn()
idx_col.name = name
idx_col.order = order
if order.upper() == "DESC":
table.has_80_features = True
if length:
idx_col.length = length
table.primary_key.column_list.append(idx_col)
if "idx_key_block_size" in result:
table.primary_key.key_block_size = result.pri_key_block_size
if "idx_comment" in result:
table.primary_key.comment = result.idx_comment
if "index_section" in result:
for idx_def in result.index_section:
idx = models.TableIndex()
idx.name = idx_def.index_name
if "idx_key_block_size" in idx_def:
idx.key_block_size = idx_def.idx_key_block_size
if "idx_comment" in idx_def:
idx.comment = idx_def.idx_comment
if "idx_using" in idx_def:
idx.using = idx_def.idx_using
if "key_type" in idx_def:
idx.key_type = idx_def.key_type
if "unique" in idx_def:
idx.is_unique = True
for col in idx_def.index_col_list:
for col_def in col:
if len(col_def) == 4 and col_def[1].upper() == "AS":
(document_path, word_as, key_type, length) = col_def
idx_col = models.DocStoreIndexColumn()
idx_col.document_path = document_path
idx_col.key_type = key_type
if length:
idx_col.length = length
idx.column_list.append(idx_col)
else:
(name, length, order) = col_def
idx_col = models.IndexColumn()
idx_col.name = name
idx_col.order = order
if order.upper() == "DESC":
table.has_80_features = True
if length:
idx_col.length = length
idx.column_list.append(idx_col)
table.indexes.append(idx)
return table