srhdZddlmZddlZddlZddlZddlTddlmZddlmZddlm Z ddlm Z dd lm Z dd lm Z dd lm Z dd lmZdd lmZddlmZddlmZ ddlmZn #e$rdZYnwxYwGddeZdZdZGddeZGddeZGddeZGddeddZGdd eZGd!d"eZd#ZdS)$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)EnclosedNodeListEntity) Expression)Node)NodeList)OP) callable_) sort_models)sqlite3)_truncate_constraint_name)CockroachDatabasec*eZdZdZdZdZdZdZdS) Operationz/Encapsulate a single schema altering operation.c>||_||_||_||_dSN)migratormethodargskwargs)selfrrrrs ]/var/lib/jenkins/jobs/Dev/workspace/my-venv/lib/python3.11/site-packages/playhouse/migrate.py__init__zOperation.__init__s"     cD|jj|dSr)rdatabaseexecute)rnodes rr zOperation.executes! &&t,,,,,rc2t|ttfr||dSt|tr|dSt|t tfr|D]}||dSdSr) isinstancer Contextr rrunlisttuple_handle_result)rresultitems rr(zOperation._handle_results ftWo . . * LL  * * * JJLLLLL u . . * * *##D)))) * * * *rc|j}d|d<t|j|j}|||ji|dS)NT with_context)rcopygetattrrrr(r)rrrs rr%z Operation.runs]!!##!%~ 44 FFDI88899999rN)__name__ __module__ __qualname____doc__rr r(r%rrrrsV99 ---***:::::rrcFtjfd}|S)Ncx|dd}|r |g|Ri|St|jg|Ri|S)Nr,F)poprr/)rrrr,fns rinnerzoperation..inners`zz.%88  -2d,T,,,V,, ,r{???rc |j}t|r |}|dt |dt t |tj| |dS)NzUPDATE z SET T)flat) defaultr rRliteralsqlrr r EQdb_value)rtable column_namefieldr`s r apply_defaultzSchemaMigrator.apply_defaults- W   giiG!!####VE]]##!!Z;''ENN7++    !rcl|dt|S)N ALTER TABLE )rarbr)rctxres r _alter_tablezSchemaMigrator._alter_tables({{>**..ve}}===rc|||dt|S)N ALTER COLUMN rlrarbrrrkrecolumns r _alter_columnzSchemaMigrator._alter_columns:c5)))**VF^^$$ &rc|}|jdc}|_|j|kr|x|_|_|||d||||_t|tr| |||S)NTz ADD COLUMN ) rRnullrfnamerlrarbddlr#ForeignKeyFieldadd_inline_fk_sql)rrerfrgrk field_nulls ralter_add_columnzSchemaMigrator.alter_add_columns!!!&T EJ   + +-8 8EJ* ,sE " " '. ! ! #eiinn    e_ - - /  " "3 . . . rc|||dt |d|S)N ADD CONSTRAINT  rlrRrarbrrreru constraints radd_constraintzSchemaMigrator.add_constraints\d//11599+,,VD\\""Z  "rcdd|z}ttdtd|Df}||||S)Nzuniq_%sr=UNIQUEc,g|]}t|Sr3r.0rqs r z-SchemaMigrator.add_unique.. sHHHfVnnHHHr)rAr SQLrr)rre column_namesconstraint_namers r add_uniquezSchemaMigrator.add_uniquesl#chh|&<&<< MM HH<HHH I IKLL ""5/:FFFrc|||dt |S)Nz DROP CONSTRAINT r~rrerus rdrop_constraintzSchemaMigrator.drop_constraint sFd//11599,--VD\\"" $rc|dt|jjjdt t|jjf}|j |d|j z}|j |d|j z}|S)N REFERENCES r} ON DELETE %s ON UPDATE %s) rarbr rel_model_metarGr rel_fieldrf on_delete on_updaterrkrgs rrxz SchemaMigrator.add_inline_fk_sqls''F5?0;<<== $fU_-H&I&I%KLLMM ? &++o?@@C ? &++o?@@C rNc |p d|d|d|}|dt|dtt |dt t|fdt|dt|d } || d |z} || d |z} | S) Nfk_r=_refs_rjr|z FOREIGN KEY r ()rr)rRrarbrrr) rrerfrel rel_columnrrrrrks radd_foreign_key_constraintz)SchemaMigrator.add_foreign_key_constraintsD%CCeee>Ikk>Ac)C  ''F5MM""*++F4Z@@AABB(($f[&9&9%;<<==''F3KK   F:&&''    ++o 9::C  ++o 9::C rc |js|jtd|zt|t}|r|jstd||||g}|js@|||||| ||g|rW|j rP| | |||j jj|jj|j|j|js|jrBt+|dd}| |||f|j||S)Nz!%s is not null but has no defaultz$Foreign keys must specify a `field`. index_type)rtr`r[r#rwrrzextendrh add_not_nullexplicit_create_foreign_keyappendrrrrGrfrrindexuniquer. add_index)rrerfrgis_foreign_key operationsusings r add_columnzSchemaMigrator.add_column9s z Pem3@;NOO O#E?;;  E%/ ECDD D++E;FFG z 8   ""5+u==!!%557 8 8 8  &d> &   //O)4O/OO %% & & & ; C%, CE<66E   dnnU[N-2\5BB C C CrctrNotImplementedError)rrerfs rdrop_foreign_key_constraintz*SchemaMigrator.drop_foreign_key_constraint`!!rTc||}|||dt ||r|dd|j|D}||vr|jr||||gS|S)N DROP COLUMN  CASCADEcg|] }|j Sr3rq)r foreign_keys rrz.SchemaMigrator.drop_column..ns1FFF  FFFr) rRrlrarbrrget_foreign_keysexplicit_delete_foreign_keyr)rrerfcascaderk fk_columnss r drop_columnzSchemaMigrator.drop_columnds!!  3 & & '/ " " #f[!! " " "  $ KK # # #FF#}==eDDFFF  * $ $)I $44UKHH#N N rc|||dt |dt |S)N RENAME COLUMN  TO r~)rreold_namenew_names r rename_columnzSchemaMigrator.rename_columnvshd//11599*++VH%%&&VH%%&&  (rcz||||dS)Nz SET NOT NULLrrrRrarrerqs rrzSchemaMigrator.add_not_nulls4t0022E6BB)) +rcz||||dS)Nz DROP NOT NULLrrs r drop_not_nullzSchemaMigrator.drop_not_nulls5t0022E6BB)** ,rc|tdt|r |}t|tr$|drt |}|||d t|d |S)N `default` must be not None/NULL.r'rnz SET DEFAULT ) r[r r#strendswithrrlrRrarbr)rrerqr`s radd_column_defaultz!SchemaMigrator.add_column_defaults ??@@ @ W   giiG gs # # #(8(8(D(D #'llGd//11599)**VF^^$$))W  rc|||dt |dS)Nrnz DROP DEFAULTr~rs rdrop_column_defaultz"SchemaMigrator.drop_column_defaultsSd//11599)**VF^^$$))  +rcj|}||||d||}|Lt |t st|}|d|}|S)Nz TYPE z USING )rRrrrarb ddl_datatyper#r rrrerqrgcastrks ralter_column_typez SchemaMigrator.alter_column_types!! c5&11!!E&&s++,,   dD)) !4yy++i((,,T22C rc|||dt |S)Nz RENAME TO r~rrrs r rename_tablezSchemaMigrator.rename_tablesGd//118<<''VH%%&& (rc |}t||}t| fd|D}t| |||}||S)Nc:g|]}tj|Sr3)r.c)rrq table_objs rrz,SchemaMigrator.add_index..s%CCC V,,CCCr)rr)rRrKTableIndexrb) rrerHrrrkrIcolsrrs @rrzSchemaMigrator.add_indexso!!$UG44 %LL CCCC7CCCj)T&NNNwwu~~rc|dt|S)N DROP INDEX rRrarbrrrerIs r drop_indexzSchemaMigrator.drop_indexs5''VJ''(( *r)NNN)Tr)FN)r/r0r1rrrrR classmethodr]r;rhrlrrrzrrrrxrrrrrrrrrrrrrr3rrrMrMs"'"'!!!/// @ @[ @ ! !Y !>>>&&& Y(""Y"GGYG$$Y$   =A37Y2$$Y$L""Y"Y"((Y(++Y+ ,,Y, Y"++Y+   Y ((Y( Y**Y***rrMcJeZdZdZedZefdZxZS)rVc|d}|j||z}d|DS)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; cg|] }|d Srr3)rrows rrz;PostgresqlMigrator._primary_key_columns..s4443A444r)r execute_sqlfetchall)rtblquerycursors r_primary_key_columnsz'PostgresqlMigrator._primary_key_columnssB  **53;7744&//"3"34444rcV|d|zS)NzSET search_path TO %s)rRra)r schema_names rset_search_pathz"PostgresqlMigrator.set_search_paths'0;>?? Arc||}tt|}|||dg}t |dkr|d|dd}d}|j||f}t|r7|d|dd} | ||| |S)NT)r,r=r_seqz SELECT 1 FROM information_schema.sequences WHERE LOWER(sequence_name) = LOWER(%s) ) rsuperrVrrBrrboolfetchoner) rrrpk_names ParentClassrseq_namerr new_seq_name __class__s rrzPostgresqlMigrator.rename_tables,,X66.55   $ $Xxd $ K KM  x==A  &.hh  ( LLX ' ' '  * LLV % % % % LLZ ) ) ) : - LL]++ , , , : * LLTZ ) ) )rNN)r/r0r1propertyr rrrbr3rrrrsw   X   X ""X"rr_Column)rurrtr r`rceZdZdZdZdZedZdZdZ edZ dZ edZ ed Z ed Zedd Zed Zd S)rXTc|||dt|S)N MODIFY rorps rrrzMySQLMigrator._alter_column/s9c5))$$VF^^$$ &rc|dt|dt|S)Nz RENAME TABLE rrrs rrzMySQLMigrator.rename_table5sU))VH%%&&VH%%&&  (rc|jd|z}|}|D]}t|}|j|kr|cSdS)NzDESCRIBE `%s`;F)rrrrru)rrerfrrowsrrqs r_get_column_definitionz$MySQLMigrator._get_column_definition>se**+;e+CDD    C #&F{k)) *urc|jd||f}|}|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)rrerfrr)s rget_foreign_key_constraintz(MySQLMigrator.get_foreign_key_constraintGss**3K """" > .). =>> >ayrc|||}|||dt |S)Nz DROP FOREIGN KEY )r%rlrRrarbr)rrerf fk_constraints rrz)MySQLMigrator.drop_foreign_key_constraintXs]77{KK d//11599-..VM**++ -rcdSrr3rs rrxzMySQLMigrator.add_inline_fk_sql`rrc|||}|||d|d}t d|j|D}||vr|S||}||||| |||j |j fS)NrFrc3(K|] }|j|fVdSrrrfks r z-MySQLMigrator.add_not_null..k<==YO======r) r"rlrRrarbdictrrrr dest_table dest_column)rrerq column_defr fk_objects fk_metadatas rrzMySQLMigrator.add_not_nullcs00?? %d&7&7&9&95AA ,,Z^^E^::;;  ==m44U;;=====   # #  ( 00??//*+ --. .rc|||}|jrtd|||d|dS)NzPrimary keys can not be nullrTr*)r"r r[rlrRrarbrs rrzMySQLMigrator.drop_not_nullzs{,,UF;; < =;<< <d//11599$$VZZZ--.. 0rcLtd|j|D}||v}|||}|||dt|d||}|rA||}| |||| |||j |j gS|S)Nc3(K|] }|j|fVdSrrr,s rr.z.MySQLMigrator.rename_column..r/rz CHANGE r})rf) r0rrr"rlrRrarbrrrr1r2) rrerrr4rrq rename_ctxr5s rrzMySQLMigrator.rename_columns*==m44U;;===== "Z/,,UH==#|D$5$5$7$7??wz**s6(++,,ws||s6::(:;;<<   $X.K00AA//*+ --  rNcP|td|}|||dt |d||S)Nz5alter_column_type() does not support cast with MySQL.rr})r[rRrlrarbrrvrs rrzMySQLMigrator.alter_column_types  &'' '!!c5))$$VF^^$$UYYs^^$$  &rc|dt|dt|S)Nrz ON rrs rrzMySQLMigrator.drop_indexsS''VJ''((VE]]##  %rr)r/r0r1rrrrr;rr"r%rrxrrrrrr3rrrXrX+s"&"&&&& ((Y("--Y-   ..Y.,00Y0Y6 & & &Y &%%Y%%%rrXceZdZdZejdZejdZejdZejdej Z dZ dZ e dZd Ze dd Ze dd Ze dZe dZe dZe dZe ddZe dZe dZe ddZdS)rZz 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^|jd|z}d|jDS)Nzselect * from "%s" limit 1cg|] }|d Srr3)rr*s rrz4SqliteMigrator._get_column_names..s444DQ444r)rr descriptionrreress r_get_column_namesz SqliteMigrator._get_column_namess3m''(Du(LMM44CO4444rc|jdd|g}|S)NzBselect name, sql from sqlite_master where type=? and LOWER(name)=?re)rrlowerrr@s r_get_create_tablez SqliteMigrator._get_create_tables>m''. ekkmm $&&||~~rc  tdj|D}||vrt d|d|d|\}}j|}j|tj dd|}j | \}}j |} d| D} g} g} g} d}| D]}j| \}||kr||||}|rm| || |j| \}| || |||s*| || |t't)| | }||d }sd }n |krfd }g}| D]^}j|}|)| d |kr ||}|r||_|d z}tjd|ztj}| d|z|}d|}t5t7dt9|gt7|d|dg}t5t7dt9|t=d| Dt7dt?d| Dt7dt9|f}t5t7dt9|g}||| ||gz }tCd|D]u}||j"vr(|t7|j#3r@$|j#|}|"|t7|v|S)Nc3HK|]}|jVdSr)rurDrs rr.z0SqliteMigrator._update_column..sLFF k''))FFFFFFrzColumn "z" does not exist on ""z\s+r}c6g|]}|Sr3striprcols rrz1SqliteMigrator._update_column..s <<z/SqliteMigrator._update_column..s*rcdSrr3rOs rrPz/SqliteMigrator._update_column..sdrc@jdz|S)NzFOREIGN KEY ("%s") )fk_resub)r3 new_columnrs rrPz/SqliteMigrator._update_column.. s"djnn% 2//rr__tmp__z ("?)%s("?)z\1%s\2, zDROP TABLE IF EXISTSrrz INSERT INTOc,g|]}t|Sr3rrLs rrz1SqliteMigrator._update_column..'sFFFcfSkkFFFrSELECTc,g|]}t|Sr3rrLs rrz1SqliteMigrator._update_column..)sHHH36#;;HHHrFROMz DROP TABLEc|jSr)rb)idxs rrPz/SqliteMigrator._update_column..6sr)%setr get_columnsrDr[rE get_indexesrrerT column_researchgroupscolumn_split_refindallcolumn_name_rematchr startswithr0zipgetrScompileIrAr rrrKrrrfilterrHrb _fix_index)rrecolumn_to_updater7rH create_tableindexes raw_create raw_columns split_columns column_defsnew_column_defsnew_column_namesoriginal_column_namesconstraint_termsr3rfnew_column_deforiginal_to_new fk_filter_fncleaned_columnsrh temp_tablergxcreatequeriespopulate_table drop_originalrrbrUs` @r_update_columnzSqliteMigrator._update_columnsDFF$(M$=$=e$D$DFFFFF  ! ! # #7 2 2*...788 8#44U;;|-++E22 &&u---vfc<88 #'."7"7 "E"E"L"L"N"N K,44[AA < >J.44Z@@GGIILK...!#K!:::)00===#'#6#<#<&$($((.!K$++K888&&z222"''))445EFF>$++K888)00===s#8:JKKLL$(()9:: 44  22LL + + +L) 3 3JJ$$Z00E U\\^^A%6:J%J%J)\*55  3&&z222Y& j-rt44  #  ))O,, c0116*3E3EF G G V\\^^^^WWW5 6 68 "    :   FF5EFFF G G MM HH2GHHH I I KK 5MM#!#l"3"3VE]]!CDD       j% 0 02 2//99 - -Eu}44s59~~.... -ooei1A:NN?NN3s88,,,rc||}t|dkr|||S|dd\}}t||dkr|d|||S|dddd}d|D}g}|D]I} t jd|z| r|| t|dz} || J|dd d |DdS) N(rrr,c8g|]}|dS)z"`[]' rJ)rparts rrz-SqliteMigrator._fix_index..Rs$;;;T4::i((;;;rz%s(?:[\'"`\]]?\s|$)rWc3 K|] }d|zV dS)z"%s"Nr3)rrs rr.z,SqliteMigrator._fix_index..]s&)D)D&1*)D)D)D)D)D)Dr)splitrBreplacersplitrarhrrA) rrbrprUrlhsrhsrHcleanrqs rrozSqliteMigrator._fix_index@sf *++ u::??;;/<< <::c1%%S syy)** + +q 0 0!cc3;;/?#L#L#LM M 3""1%++C00;;U;;;  ! !Fx.1AA6JJ E#fS1A-B-B-C-C&DD LL 33 )D)De)D)D)D D D D DEErTFctjdkra|s_|}|||dt ||S|||dS)N)#rrcdSrr3)abs rrPz,SqliteMigrator.drop_column..gsDr)rsqlite_version_inforRrlrarbrr)rrerfrlegacyrks rrzSqliteMigrator.drop_column_s  &* 4 4V 4##%%C   sE * *go&&c&%%&&&J""5+7H7HIIIrc|tjdkr|s|||dt |dt Sfd}||||S)N)rrrrc0||Srr)rfr3rs r_renamez-SqliteMigrator.rename_column.._renamers%%k8<< ._add_not_nullxs  + +rr)rrerqrs rrzSqliteMigrator.add_not_nullvs) , , ,""5&-@@@rc6d}||||S)Nc.|ddS)Nrrrs r_drop_not_nullz4SqliteMigrator.drop_not_null.._drop_not_null~s%%j"55 5rr)rrerqrs rrzSqliteMigrator.drop_not_null|s) 6 6 6""5&.AAArctdtr ttr.dssdzfd}||||S)Nrrz'%s'c|dzzS)Nz DEFAULT %sr3)rfr3r`s r _add_defaultz7SqliteMigrator.add_column_default.._add_defaults  77 7r)r[r r#rrisdigitr)rrerqr`rs ` rrz!SqliteMigrator.add_column_defaults ??@@ @ W   giiG w $ $ 'W-=-=j-I-I 'OO%% 'w&G 8 8 8 8 8""5&,???rc6d}||||S)Ncltjdd|tj}|S)NzDEFAULT\s+[\w"\'\(\)]+(\s|$)r)rarTrmrK)rfr3rMs r _drop_defaultz9SqliteMigrator.drop_column_default.._drop_defaults(&8"j"$OOC99;; rr)rrerqrs rrz"SqliteMigrator.drop_column_defaults+   ""5&-@@@rNc|td|fd}|||S)Nz6alter_column_type() does not support cast with Sqlite.c}t|\}}|Sr)rvrbrr)rfr3 node_listrbr=rqrkrgs r_alter_column_typez._alter_column_typesL #IWWVF^^,,00;;AACCFCJr)r[rRr)rrerqrgrrrks `` @rrz SqliteMigrator.alter_column_typesq  '(( (!!       ""5&2DEEErctrrrs rrzSqliteMigrator.add_constraintrrctrrrs rrzSqliteMigrator.drop_constraintrrctrr)rrerfrgrrs rrz)SqliteMigrator.add_foreign_key_constraints "!r)TF)Frr)r/r0r1r2rarlrbrergrmrSrBrEr;rrorrrrrrrrrrr3rrrZrZs +,,I bj!899ORZ 455N BJ:BD A AE555qqYqfFFF>JJJYJ = = =Y =AAYA BBYB  @ @Y @AAYA  F F FY F""Y"""Y"=A"""Y"""rrZc8|D]}|dSr)r%)rrr;s rmigraters*  r) r2 collectionsrr9rCrapeeweerrrr r r r r rrrplayhouse.cockroachdbr ImportErrorobjectrr;rKrMrVrTrrXrZrr3rrrsqqd#"""""  ######,,,,,,7777777::::::::6Q*Q*Q*Q*Q*VQ*Q*Q*h++++++++\ & & & & &, & & &     **Y)=>>   FI%I%I%I%I%NI%I%I%Xw"w"w"w"w"^w"w"w"tsA##A-,A-