原生建表SQL與SQLAlchemy Table映射

init.sql
CREATE TABLE department
(
  id          int          NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '主鍵id',
  name        varchar(32)  NOT NULL DEFAULT '' COMMENT '部門名字',
  parent_id   bigint       NOT NULL DEFAULT 0 COMMENT '部門父節(jié)點',
  delete_flag tinyint      NOT NULL DEFAULT 0 COMMENT '刪除標識',
  modify_time int UNSIGNED NOT NULL DEFAULT 0 COMMENT '修改時間',
  create_time int UNSIGNED NOT NULL DEFAULT 0 COMMENT '創(chuàng)建時間'
)
  ENGINE innodb
  CHARSET utf8mb4 COMMENT '部門列表';
Python代碼實現(xiàn)
"""
實現(xiàn)從建表sql語句到 SqlAlchemy Table的映射
"""
import re
import sqlalchemy as sa

TYPE_RELATION = {
    'varchar': sa.String,
    'int': sa.Integer,
    'smallint': sa.SmallInteger,
    'tinyint': sa.SmallInteger,
    'bigint': sa.BigInteger,
    'text': sa.TEXT
}


def extract_pure_field(sql_file):
    """去除多余空格慰毅,空行株灸, 注釋 配置 等"""
    content = ''
    with open(sql_file, mode='r') as fileObj:

        for line, data in enumerate(fileObj):

            line_text = data.strip()

            if re.match('^--.*|^set .*', line_text) is None:
                # 多個空格變?yōu)橐粋€空格
                line_text_after = re.sub(' +', ' ', line_text)

                content += line_text_after

    return content


def parse_table_sql(sql_file):

    tables_dict = {}

    content = extract_pure_field(sql_file)

    content = content.replace('\r', '').replace('\n', '')

    tables = [table for table in content.split(';') if table.lower().strip().startswith('create')]
    for table_sql in tables:

        table_name = re.findall('table(.*?)\(', table_sql.lower())[0].strip()
        fields = re.findall('(\(.*\))', table_sql)[0].split(',')

        fields_list = []
        for field in fields:

            field_sp = field.strip().split(' ')
            field_name = field_sp[0].strip()

            if len(field_sp) < 2:
                continue

            if field_name.lower() == 'unique' or field_name.lower() == 'key':
                continue

            field_type = field_sp[1].split('(')[0].strip().lower()

            comment = ''
            primary_key = False
            for idx, sp in enumerate(field_sp):

                sp_lower = sp.lower().strip()

                if sp_lower == 'comment':
                    comment = field_sp[idx + 1]

                elif sp_lower == 'primary':
                    primary_key = True

            fields_list.append(
                {
                    'name': field_name,
                    'type': field_type,
                    'comment': comment,
                    'primary_key': primary_key
                }
            )

        tables_dict[table_name] = {
            'fields': fields_list,
            'table_sql': table_sql
        }

    return tables_dict


class ModelMetaclass(type):
    """元類控制Model屬性讀寫
    """

    def __getattr__(cls, item):

        if item.endswith('sa') and hasattr(cls, '__tables__'):

            return getattr(cls, '__tables__')[item]

    def __setattr__(self, key, value):

        raise Exception('class Model not allow to be set attr')


class Model(metaclass=ModelMetaclass):

    __tables__ = {}
    __metadata__ = sa.MetaData()

    @classmethod
    def append(cls, table_sa: sa.Table):

        cls.__tables__[str(table_sa.name) + '_sa'] = table_sa


if __name__ == '__main__':

    file = './init.sql'
    tables_dict = parse_table_sql(file)

    for name, table_info in tables_dict.items():

        columns = []
        columns_list = table_info['fields']
        for c in columns_list:

            column = sa.Column(c['name'], TYPE_RELATION[c['type']], primary_key=c['primary_key'], comment=c['comment'])

            columns.append(column)

        table = sa.Table(name, Model.__metadata__, *columns)
        table.sql = table_info['table_sql']

        Model.append(table)

    print(type(Model.department_sa))
    print(Model.department_sa.sql)

out:
<class 'sqlalchemy.sql.schema.Table'>
CREATE TABLE department(id int NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '主鍵id',name varchar(32) NOT NULL DEFAULT '' COMMENT '部門名字',parent_id bigint NOT NULL DEFAULT 0 COMMENT '部門父節(jié)點',delete_flag tinyint NOT NULL DEFAULT 0 COMMENT '刪除標識',modify_time int UNSIGNED NOT NULL DEFAULT 0 COMMENT '修改時間',create_time int UNSIGNED NOT NULL DEFAULT 0 COMMENT '創(chuàng)建時間')ENGINE innodbCHARSET utf8mb4 COMMENT '部門列表'

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末腰鬼,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子沛善,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,470評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件益涧,死亡現(xiàn)場離奇詭異箩祥,居然都是意外死亡院崇,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評論 3 392
  • 文/潘曉璐 我一進店門袍祖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來底瓣,“玉大人,你說我怎么就攤上這事盲泛”舫郑” “怎么了?”我有些...
    開封第一講書人閱讀 162,577評論 0 353
  • 文/不壞的土叔 我叫張陵寺滚,是天一觀的道長柑营。 經(jīng)常有香客問我,道長村视,這世上最難降的妖魔是什么官套? 我笑而不...
    開封第一講書人閱讀 58,176評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上奶赔,老公的妹妹穿的比我還像新娘惋嚎。我一直安慰自己,他們只是感情好站刑,可當我...
    茶點故事閱讀 67,189評論 6 388
  • 文/花漫 我一把揭開白布另伍。 她就那樣靜靜地躺著,像睡著了一般绞旅。 火紅的嫁衣襯著肌膚如雪摆尝。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,155評論 1 299
  • 那天因悲,我揣著相機與錄音堕汞,去河邊找鬼。 笑死晃琳,一個胖子當著我的面吹牛讯检,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播卫旱,決...
    沈念sama閱讀 40,041評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼人灼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了誊涯?” 一聲冷哼從身側(cè)響起挡毅,我...
    開封第一講書人閱讀 38,903評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎暴构,沒想到半個月后跪呈,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,319評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡取逾,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,539評論 2 332
  • 正文 我和宋清朗相戀三年耗绿,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片砾隅。...
    茶點故事閱讀 39,703評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡误阻,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出晴埂,到底是詐尸還是另有隱情究反,我是刑警寧澤,帶...
    沈念sama閱讀 35,417評論 5 343
  • 正文 年R本政府宣布儒洛,位于F島的核電站精耐,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏琅锻。R本人自食惡果不足惜卦停,卻給世界環(huán)境...
    茶點故事閱讀 41,013評論 3 325
  • 文/蒙蒙 一向胡、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧惊完,春花似錦僵芹、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至凿跳,卻和暖如春攀痊,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背拄显。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留案站,地道東北人躬审。 一個月前我還...
    沈念sama閱讀 47,711評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像蟆盐,于是被迫代替她去往敵國和親承边。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,601評論 2 353

推薦閱讀更多精彩內(nèi)容