K idZddlmZddlZddlZddlZddlddlmZddlmZddlm Z ddlm Z dd lm Z dd lm Z dd lm Z dd lmZdd lmZddlmZddlmZ ddlmZGddeZdZdZGddeZGddeZGddeZGddeddZGdd eZGd!d"eZd#Zy#e$rdZYgwxYw)$ah Lightweight schema migrations. Example Usage ------------- Instantiate a migrator: # Postgres example: my_db = PostgresqlDatabase(...) migrator = PostgresqlMigrator(my_db) # SQLite example: my_db = SqliteDatabase('my_database.db') migrator = SqliteMigrator(my_db) Then you will use the `migrate` function to run various `Operation`s which are generated by the migrator: migrate( migrator.add_column('some_table', 'column_name', CharField(default='')) ) Migrations are not run inside a transaction, so if you wish the migration to run in a transaction you will need to wrap the call to `migrate` in a transaction block, e.g.: with my_db.transaction(): migrate(...) Supported Operations -------------------- Add new field(s) to an existing model: # Create your field instances. For non-null fields you must specify a # default value. pubdate_field = DateTimeField(null=True) comment_field = TextField(default='') # Run the migration, specifying the database table, field name and field. migrate( migrator.add_column('comment_tbl', 'pub_date', pubdate_field), migrator.add_column('comment_tbl', 'comment', comment_field), ) Renaming a field: # Specify the table, original name of the column, and its new name. migrate( migrator.rename_column('story', 'pub_date', 'publish_date'), migrator.rename_column('story', 'mod_date', 'modified_date'), ) Dropping a field: migrate( migrator.drop_column('story', 'some_old_field'), ) Making a field nullable or not nullable: # Note that when making a field not null that field must not have any # NULL values present. migrate( # Make `pub_date` allow NULL values. migrator.drop_not_null('story', 'pub_date'), # Prevent `modified_date` from containing NULL values. migrator.add_not_null('story', 'modified_date'), ) Renaming a table: migrate( migrator.rename_table('story', 'stories_tbl'), ) Adding an index: # Specify the table, column names, and whether the index should be # UNIQUE or not. migrate( # Create an index on the `pub_date` column. migrator.add_index('story', ('pub_date',), False), # Create a multi-column index on the `pub_date` and `status` fields. migrator.add_index('story', ('pub_date', 'status'), False), # Create a unique index on the category and title fields. migrator.add_index('story', ('category_id', 'title'), True), ) Dropping an index: # Specify the index name. migrate(migrator.drop_index('story', 'story_pub_date_status')) Adding or dropping table constraints: .. code-block:: python # Add a CHECK() constraint to enforce the price cannot be negative. migrate(migrator.add_constraint( 'products', 'price_check', Check('price >= 0'))) # Remove the price check constraint. migrate(migrator.drop_constraint('products', 'price_check')) # Add a UNIQUE constraint on the first and last names. migrate(migrator.add_unique('person', 'first_name', 'last_name')) ) namedtupleN)*) CommaNodeList)EnclosedNodeList)Entity) Expression)Node)NodeList)OP) callable_) sort_models)sqlite3)_truncate_constraint_name)CockroachDatabasec(eZdZdZdZdZdZdZy) Operationz/Encapsulate a single schema altering operation.c<||_||_||_||_yN)migratormethodargskwargs)selfrrrrs W/mnt/ssd/data/python-lab/Trading/venv/lib/python3.12/site-packages/playhouse/migrate.py__init__zOperation.__init__s     cN|jjj|yr)rdatabaseexecute)rnodes rrzOperation.executes &&t,rct|ttfr|j|yt|tr|j yt|t tfr|D]}|j|yyr) isinstancer Contextrrrunlisttuple_handle_result)rresultitems rr'zOperation._handle_results_ ftWo . LL  * JJL u . *##D) */rc|jj}d|d<t|j|j}|j ||j i|y)NT with_context)rcopygetattrrrr'r)rrrs rr$z Operation.runsN!!#!%~ 4 FDII889rN)__name__ __module__ __qualname____doc__rrr'r$rrrrs9 -*:rrcBtjfd}|S)Ncx|jdd}|r |g|i|St|jg|i|S)Nr+F)poprr.)rrrr+fns rinnerzoperation..innersFzz.%8 d,T,V, ,r{{??rc N|j}t|r|}|jjdj t |jdj t t |tj|j|dS)NzUPDATE z SET T)flat) defaultr rQliteralsqlrrr EQdb_value)rtable column_namefieldr_s r apply_defaultzSchemaMigrator.apply_defaults|-- W iG!!##VE]#!Z;'EENN7+   !rcT|jdjt|S)N ALTER TABLE )r`rar)rctxrds r _alter_tablezSchemaMigrator._alter_tables {{>*..ve}==rct|j||jdjt|S)N ALTER COLUMN rkr`rarrrjrdcolumns r _alter_columnzSchemaMigrator._alter_columns/c5))*VF^$ &rcX|j}|jdc}|_|j|k7r|x|_|_|j ||j dj |j|||_t|tr|j|||S)NTz ADD COLUMN ) rQnullrenamerkr`raddlr"ForeignKeyFieldadd_inline_fk_sql)rrdrerfrj field_nulls ralter_add_columnzSchemaMigrator.alter_add_columns!!&T EJ    +-8 8EJ* ,sE " '. ! #eiin  e_ -  " "3 . rc|j|j|jdjt |jdj|S)N ADD CONSTRAINT  rkrQr`rarrrdrt constraints radd_constraintzSchemaMigrator.add_constraintsJd//159+,VD\"Z  "rc ddj|z}ttdt|Dcgc] }t |c}f}|j |||Scc}w)Nzuniq_%sr<UNIQUE)r@r SQLrrr)rrd column_namesconstraint_namerprs r add_uniquezSchemaMigrator.add_uniquesa#chh|&<< M <HfVnH IKL ""5/:FFIsAc|j|j|jdjt |S)Nz DROP CONSTRAINT r}rrdrts rdrop_constraintzSchemaMigrator.drop_constraint s8d//159,-VD\" $rc|jdjt|jjj jdjt t|jjf}|j|jd|jz}|j|jd|jz}|S)N REFERENCES r| ON DELETE %s ON UPDATE %s) r`rar rel_model_metarFr rel_fieldre on_delete on_updaterrjrfs rrwz SchemaMigrator.add_inline_fk_sqls'F5??00;;<= $fU__-H-H&I%KLM ?? &++o?@C ?? &++o?@C rNcf|xs d|d|d|}|jjdjt|jdjtt |jdjt t|fjdjt|jdjt|jd } || jd |z} || jd |z} | S) Nfk_r<_refs_rir{z FOREIGN KEY r ()rr)rQr`rarrr) rrdrerel rel_columnrrrrrjs radd_foreign_key_constraintz)SchemaMigrator.add_foreign_key_constraints%Ce>I>A)C  'F5M"*+F4Z@AB($f[&9%;<='F3K  F:&'    ++o 9:C  ++o 9:C rc |js|jtd|zt|t}|r|j s td|j |||g}|js4|j|j||||j||g|rw|jrk|j|j|||jjj|j j |j"|j$|j&s |j(r;t+|dd}|j|j-||f|j(||S)Nz!%s is not null but has no defaultz$Foreign keys must specify a `field`. index_type)rsr_rZr"rvrryextendrg add_not_nullexplicit_create_foreign_keyappendrrrrFrerrindexuniquer- add_index)rrdrerfis_foreign_key operationsusings r add_columnzSchemaMigrator.add_column9sG zzemm3@;NO O#E?; %//CD D++E;FG zz   ""5+u=!!%57 8 d>>   //OO))44OO//OOOO % & ;;%,,E<6E   dnnU[N-2\\5B CrctrNotImplementedError)rrdres rdrop_foreign_key_constraintz*SchemaMigrator.drop_foreign_key_constraint`!!rct|j}|j||jdjt ||r|jd|j j |Dcgc]}|j}}||vr |jr|j|||gS|Scc}w)N DROP COLUMN  CASCADE) rQrkr`rarrget_foreign_keysrpexplicit_delete_foreign_keyr)rrdrecascaderj foreign_key fk_columnss r drop_columnzSchemaMigrator.drop_columnds!  3 & '/ " #f[! "  KK # $}}==eDF   F F * $)I)I44UKH#N N Fs:B5c|j|j|jdjt |jdjt |S)N RENAME COLUMN  TO r})rrdold_namenew_names r rename_columnzSchemaMigrator.rename_columnvsQd//159*+VH%&VH%&  (rcb|j|j||jdS)Nz SET NOT NULLrqrQr`rrdrps rrzSchemaMigrator.add_not_nulls+t002E6B) +rcb|j|j||jdS)Nz DROP NOT NULLrrs r drop_not_nullzSchemaMigrator.drop_not_nulls,t002E6B)* ,rcb| tdt|r|}t|tr|j dr t |}|j |j|jdjt|jdj|S)N `default` must be not None/NULL.r'rmz SET DEFAULT ) rZr r"strendswithrrkrQr`rar)rrdrpr_s radd_column_defaultz!SchemaMigrator.add_column_defaults ??@ @ W iG gs #(8(8(D'lGd//159)*VF^$)W  rc|j|j|jdjt |jdS)Nrmz DROP DEFAULTr}rs rdrop_column_defaultz"SchemaMigrator.drop_column_defaultsBd//159)*VF^$)  +rc |j}|j|||jdj|j |}|;t |t s t|}|jdj|}|S)Nz TYPE z USING )rQrqr`ra ddl_datatyper"r rrrdrprfcastrjs ralter_column_typez SchemaMigrator.alter_column_types! c5&1!E&&s+,   dD)4y++i(,,T2C rc|j|j|jdjt |S)Nz RENAME TO r}rrrs r rename_tablezSchemaMigrator.rename_tables8d//18<'VH%& (rc|j}t||}t|}|Dcgc]}t|j|} }t ||| ||} |j | Scc}w)N)rr)rQrJTabler-cIndexra) rrdrGrrrjrH table_objrpcolsrs rrzSchemaMigrator.add_indexsi!$UG4 %L ;BC V,CCj)T&Nwwu~DsA,cp|jjdjt|S)N DROP INDEX rQr`rarrrdrHs r drop_indexzSchemaMigrator.drop_indexs*'VJ'( *r)NNN)Tr)FN)r.r/r0rrrrQ classmethodr\r:rgrkrqryrrrrwrrrrrrrrrrrrrr2rrrLrLs"'"'!/ @ @ ! !>& (""GG$$ =A372$$L"""((++ ,, "++  (( **rrLc>eZdZdZedZefdZxZS)rUcd}|jj||z}|jDcgc]}|d c}Scc}w)Nai SELECT pg_attribute.attname FROM pg_index, pg_class, pg_attribute WHERE pg_class.oid = '%s'::regclass AND indrelid = pg_class.oid AND pg_attribute.attrelid = pg_class.oid AND pg_attribute.attnum = any(pg_index.indkey) AND indisprimary; r)r execute_sqlfetchall)rtblquerycursorrows r_primary_key_columnsz'PostgresqlMigrator._primary_key_columnssB  **53;7"(//"343A444s AcF|jjd|zS)NzSET search_path TO %s)rQr`)r schema_names rset_search_pathz"PostgresqlMigrator.set_search_paths"0;>? Arcn|j|}tt|}|j||dg}t |dk(ro|d|dd}d}|j j ||f}t|jr,|d|dd} |j|j|| |S)NT)r+r<r_seqz SELECT 1 FROM information_schema.sequences WHERE LOWER(sequence_name) = LOWER(%s) ) rsuperrUrrArrboolfetchoner) rrrpk_names ParentClassrseq_namerr new_seq_name __class__s rrzPostgresqlMigrator.rename_tables,,X6.5   $ $Xxd $ KM  x=A &. > LLX '  LLV % LLZ ) :: LL]+ , :: LLTZZ )rNN)r.r/r0propertyrrrrar2rrrrsA     ""rr_Column)rtr rsrr_r ceZdZdZdZdZedZdZdZ edZ dZ edZ ed Z ed Zedd Zed Zy )rWTct|j||jdjt|S)N MODIFY rnros rrqzMySQLMigrator._alter_column/s.c5)$VF^$ &rc|jjdjt|jdjt|S)Nz RENAME TABLE rrrs rrzMySQLMigrator.rename_table5sB)VH%&VH%&  (rc|jjd|z}|j}|D]}t|}|j|k(s|cSy)NzDESCRIBE `%s`;F)rrrrrt)rrdrerrowsrrps r_get_column_definitionz$MySQLMigrator._get_column_definition>sW**+;e+CD  C #&F{{k)  rc|jjd||f}|j}|std|d|d|dS)NzSELECT constraint_name FROM information_schema.key_column_usage WHERE table_schema = DATABASE() AND table_name = %s AND column_name = %s AND referenced_table_name IS NOT NULL AND referenced_column_name IS NOT NULL;z+Unable to find foreign key constraint for "z " on table "z".r)rrrAttributeError)rrdrerr(s rget_foreign_key_constraintz(MySQLMigrator.get_foreign_key_constraintGsY**3K "" ). => >ayrc|j||}|j|j|jdj t |S)Nz DROP FOREIGN KEY )rrkrQr`rar)rrdre fk_constraints rrz)MySQLMigrator.drop_foreign_key_constraintXsK77{K d//159-.VM*+ -rcyrr2rs rrwzMySQLMigrator.add_inline_fk_sql`rrc|j||}|j|j|jdj |j d}t d|j j|D}||vr|S||}|j||||j|||j|jfS)NrFrc38K|]}|j|fywrrp.0fks r z-MySQLMigrator.add_not_null..k =YYO=) rrkrQr`radictrrrr dest_table dest_column)rrdrp column_defr fk_objects fk_metadatas rrzMySQLMigrator.add_not_nullcs00? %d&7&7&95A ,Z^^E^:;  =mm44U;==   #  ( 00?//**++ -. .rc|j||}|jr td|j|j |j dj |j dS)NzPrimary keys can not be nullrTr )rrrZrkrQr`rars rrzMySQLMigrator.drop_not_nullzsc,,UF; <<;< <d//159$VZZZ-. 0rctd|jj|D}||v}|j||}|j |j |j djt|j dj|j|}|r@||}|j||||j|||j|jgS|S)Nc38K|]}|j|fywrr"r#s rr&z.MySQLMigrator.rename_column..r'r(z CHANGE r|)re) r)rrrrkrQr`rarrrr*r+) rrdrrr-rrp rename_ctxr.s rrzMySQLMigrator.rename_columns=mm44U;== "Z/,,UH=#|D$5$5$7?wz*s6(+,ws|s6::(:;<  $X.K00A//**++ -  rNc| td|j}|j||jdj t |jdj |j |S)Nz5alter_column_type() does not support cast with MySQL.rr|)rZrQrkr`rarrurs rrzMySQLMigrator.alter_column_typeso  &' '!c5)$VF^$UYYs^$  &rc|jjdjt|jdjt|S)Nrz ON rrs rrzMySQLMigrator.drop_indexsA'VJ'(VE]#  %rr)r.r/r0rrrqr:rrrrrwrrrrrr2rrrWrW+s"&"&& (("-- ..,006 & &%%rrWceZdZdZej dZej dZej dZej dejZ dZ dZ e dZd Ze dd Ze dd Ze d Ze d Ze dZe dZe ddZe dZe dZe ddZy)rYz SQLite supports a subset of ALTER TABLE queries, view the docs for the full details http://sqlite.org/lang_altertable.html z (.+?)\((.+)\)z(?:[^,(]|\([^)]*\))+z ["`']?([\w]+)z FOREIGN KEY\s+\("?([\w]+)"?\)\s+c|jjd|z}|jDcgc]}|d c}Scc}w)Nzselect * from "%s" limit 1r)rr description)rrdresr)s r_get_column_namesz SqliteMigrator._get_column_namess8mm''(Du(LM$'OO4DQ444s <cz|jjdd|jg}|jS)NzBselect name, sql from sqlite_master where type=? and LOWER(name)=?rd)rrlowerr)rrdr8s r_get_create_tablez SqliteMigrator._get_create_tables7mm''. ekkm $&||~rctdjj|D}|j|vrt d|d|dj |\}}jj |}jj|tjdd|}jj|j\}}jj|} | D cgc]} | j} } g} g} g}d}| D]}j j#|j\}||k(rk|||}|s?| j%||j%|j j#|j\}| j%|| j%||jj'|r| j%||j%|t)t+|| }|j-|d}sd }n |k7rfd }g}| D]Q}j.j#|}||jd |k(r||}|sA|j%|S|d z}tj0d |ztj2}|jd|z|}dj5|}t7t9dt;|gt9|jd|dg}t7t9dt;|t=| D cgc] } t;| c} t9dt?|D cgc] } t;| c} t9dt;|f}t7t9dt;|g}|||jA||gz }tCd|D]r}||jDvr%|j%t9|jF6s9jI|jF|}|Y|j%t9|t|Scc} wcc} wcc} w)Nc3PK|]}|jj ywr)rtr;)r$rps rr&z0SqliteMigrator._update_column..s'F kk'')Fs$&zColumn "z" does not exist on ""z\s+r|)zforeign zprimary z constraint zcheck c|Srr2r,s rz/SqliteMigrator._update_column..s*rcyrr2rAs rrBz/SqliteMigrator._update_column..rcBjjdz|S)NzFOREIGN KEY ("%s") )fk_resub)r, new_columnrs rrBz/SqliteMigrator._update_column.. sdjjnn% 2/rr__tmp__z ("?)%s("?)z\1%s\2, zDROP TABLE IF EXISTSrrz INSERT INTOSELECTFROMz DROP TABLEc|jSr)ra)idxs rrBz/SqliteMigrator._update_column..6s r)%setr get_columnsr;rZr< get_indexesrrerG column_researchgroupscolumn_split_refindallstripcolumn_name_rematchr startswithr)zipgetrFcompileIr@r rrrrrfilterrGra _fix_index) rrdcolumn_to_updater6rG create_tableindexes raw_create raw_columns split_columnscol column_defsnew_column_defsnew_column_namesoriginal_column_namesconstraint_termsr,renew_column_deforiginal_to_new fk_filter_fncleaned_columnsrZ temp_tablergxcreatequeriespopulate_table drop_originalrrarHs ` @r_update_columnzSqliteMigrator._update_columns7F$(MM$=$=e$DFF  ! ! #7 2.78 8#44U;|--++E2 &&u-vvfc<8 #'.."7"7 "E"L"L"N K,,44[A .;J..44Z@GGILK..!#K!<!#**>:)00=#'#6#6#<#<&$((.!K$++K8&&z2"'')445EF$++K8)00=# >(s#8:JKL$(()9: 4 2L + +L) 3JJJ$$Z0E U\\^A%6:J%J)*5 &&z2  3Y& jj-rtt4  #  ))O, c016*3EF G V\\^W5 68 "   :  5EFcfSkF G M 2GH36#;H I K 5M#!#l"3VE]!CD       j% 02 2/9 -Eu}}4s599~.ooeii1A:N?NN3s8,  -q=BGHs>Q0Q5Q:cH|j|}t|dk(r|j||S|jdd\}}t|j|dk(r|d|j||S|jdddjd}|Dcgc]}|j d}}g} |D]=} t j d|z| r|| t|dz} | j| ?|dd jd | DdScc}w) N(rrr,z"`[]' z%s(?:[\'"`\]]?\s|$)rJc3&K|] }d|z yw)z"%s"Nr2)r$rs rr&z,SqliteMigrator._fix_index..]s)D&1*)Ds) splitrAreplacersplitrXrRrZrr@) rrarbrHrlhsrhspartrGcleanrps rrazSqliteMigrator._fix_index@s$ *+ u:?;;/< <::c1%S syy)* +q 0!3;;/?#LM M 3"1%++C05:;T4::i(;;  !Fxx.1AA6J#fS1A-B-C&DD LL  !  )De)D DEE.grDr)rsqlite_version_inforQrkr`rarrx)rrdrerlegacyrjs rrzSqliteMigrator.drop_column_sd  & &* 4V##%C   sE *go&c&%&J""5+7HIIrc:tjdk\rp|sn|j|j|j dj t |j dj t Sfd}|j|||S)N)rrrrc(|j|Srr)rer,rs r_renamez-SqliteMigrator.rename_column.._renamers%%k8< ._add_not_nullxs  + +rrx)rrdrprs rrzSqliteMigrator.add_not_nullvs ,""5&-@@rc.d}|j|||S)Nc&|jddS)Nr rrs r_drop_not_nullz4SqliteMigrator.drop_not_null.._drop_not_null~s%%j"5 5rr)rrdrprs rrzSqliteMigrator.drop_not_null|s 6""5&.AArc tdtrttr&j dsj sdzfd}|j |||S)Nrrz'%s'c|dzzS)Nz DEFAULT %sr2)rer,r_s r _add_defaultz7SqliteMigrator.add_column_default.._add_defaults  77 7r)rZr r"rrisdigitrx)rrdrpr_rs ` rrz!SqliteMigrator.add_column_defaultsj ??@ @ W iG w $W-=-=j-IOO%w&G 8""5&,??rc.d}|j|||S)Ncptjdd|tj}|jS)NzDEFAULT\s+[\w"\'\(\)]+(\s|$)r)flags)rRrGr_rX)rer,rhs r _drop_defaultz9SqliteMigrator.drop_column_default.._drop_defaults*&&8"jPRPTPTUC99; rr)rrdrprs rrz"SqliteMigrator.drop_column_defaults ""5&-@@rNcv| td|jfd}|j||S)Nz6alter_column_type() does not support cast with Sqlite.cj}jtj|j\}}|Sr)rurarr)rer, node_listrar<rprjrfs r_alter_column_typez._alter_column_types? #IWWVF^,00;AACFCJr)rZrQrx)rrdrprfrrrjs `` @rrz SqliteMigrator.alter_column_typesF  '( (! ""5&2DEErctrrr~s rrzSqliteMigrator.add_constraintrrctrrrs rrzSqliteMigrator.drop_constraintrrctrr)rrdrerfrrs rrz)SqliteMigrator.add_foreign_key_constraints "!r)TF)Frr)r.r/r0r1rRr^rSrVrYr_rFr9r<r:rxrarrrrrrrrrrr2rrrYrYsQ +,I bjj!89ORZZ 45N BJJ:BDD AE5qqfF>JJ = =AA BB  @ @AA  F F""""=A""rrYc2|D]}|jyr)r$)rrr:s rmigraters  r) r1 collectionsrr8rBrRpeeweerrrrr r r r r rrplayhouse.cockroachdbr ImportErrorobjectrr:rJrLrUrSrrWrYrr2rrrsqd#  #,7 ::6Q*VQ*h++\ &, & *Y)=> FI%NI%Xw"^w"tWsCC  C