{ "info": { "author": "Bogdan Klichuk", "author_email": "klichukb@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 3 - Alpha", "Framework :: Django", "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Natural Language :: English", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5" ], "description": "django-migrate-sql\n==================\n\n|Build Status| |codecov.io|\n\nDjango Migrations support for raw SQL.\n\nAbout\n-----\n\nThis tool implements mechanism for managing changes to custom SQL\nentities (functions, types, indices, triggers) using built-in migration\nmechanism. Technically creates a sophistication layer on top of the\n``RunSQL`` Django operation.\n\nWhat it does\n------------\n\n- Makes maintaining your SQL functions, custom composite types, indices\n and triggers easier.\n- Structures SQL into configuration of **SQL items**, that are\n identified by names and divided among apps, just like models.\n- Automatically gathers and persists changes of your custom SQL into\n migrations using ``makemigrations``.\n- Properly executes backwards/forwards keeping integrity of database.\n- Create -> Drop -> Recreate approach for changes to items that do not\n support altering and require dropping and recreating.\n- Dependencies system for SQL items, which solves the problem of\n updating items, that rely on others (for example custom\n types/functions that use other custom types), and require dropping\n all dependency tree previously with further recreation.\n\nWhat it does not\n----------------\n\n- Does not parse SQL nor validate queries during ``makemigrations`` or\n ``migrate`` because is database-agnostic. For this same reason\n setting up proper dependencies is user's responsibility.\n- Does not create ``ALTER`` queries for items that support this, for\n example ``ALTER TYPE`` in Postgre SQL, because is database-agnostic.\n In case your tools allow rolling all the changes through ``ALTER``\n queries, you can consider not using this app **or** restructure\n migrations manually after creation by nesting generated operations\n into ```state_operations`` of\n ``RunSQL`` `__\n that does ``ALTER``.\n- (**TODO**)During ``migrate`` does not restore full state of items for\n analysis, thus does not notify about existing changes to schema that\n are not migrated **nor** does not recognize circular dependencies\n during migration execution.\n\nInstallation\n------------\n\nInstall from PyPi:\n\n::\n\n $ pip install django-migrate-sql\n\nAdd ``migrate_sql`` to ``INSTALLED_APPS``:\n\n.. code:: python\n\n INSTALLED_APPS = [\n # ...\n 'migrate_sql',\n ]\n\nApp defines a custom ``makemigrations`` command, that inherits from\nDjango's core one, so in order ``migrate_sql`` app to kick in put it\nafter any other apps that redefine ``makemigrations`` command too.\n\nUsage\n-----\n\n1) Create ``sql_config.py`` module to root of a target app you want to\n manage custom SQL for.\n\n2) Define SQL items in it (``sql_items``), for example:\n\n.. code:: python\n\n # PostgreSQL example.\n # Let's define a simple function and let `migrate_sql` manage it's changes.\n\n from migrate_sql.config import SQLItem\n\n sql_items = [\n SQLItem(\n 'make_sum', # name of the item\n 'create or replace function make_sum(a int, b int) returns int as $$ '\n 'begin return a + b; end; '\n '$$ language plpgsql;', # forward sql\n reverse_sql='drop function make_sum(int, int);', # sql for removal\n ),\n ]\n\n3) Create migration ``./manage.py makemigrations``:\n\n ::\n\n Migrations for 'app_name':\n 0002_auto_xxxx.py:\n - Create SQL \"make_sum\"\n\nYou can take a look at content this generated:\n\n.. code:: python\n\n # -*- coding: utf-8 -*-\n from __future__ import unicode_literals\n from django.db import migrations, models\n import migrate_sql.operations\n\n\n class Migration(migrations.Migration):\n dependencies = [\n ('app_name', '0001_initial'),\n ]\n operations = [\n migrate_sql.operations.CreateSQL(\n name='make_sum',\n sql='create or replace function make_sum(a int, b int) returns int as $$ begin return a + b; end; $$ language plpgsql;',\n reverse_sql='drop function make_sum(int, int);',\n ),\n ]\n\n4) Execute migration ``./manage.py migrate``:\n\n ::\n\n Operations to perform:\n Apply all migrations: app_name\n Running migrations:\n Rendering model states... DONE\n Applying app_name.0002_xxxx... OK\n\nCheck result in ``./manage.py dbshell``:\n\n::\n\n db_name=# select make_sum(12, 15);\n make_sum\n ----------\n 27\n (1 row)\n\nNow, say, you want to change the function implementation so that it\ntakes a custom type as argument:\n\n5) Edit your ``sql_config.py``:\n\n.. code:: python\n\n # PostgreSQL example #2.\n # Function and custom type.\n\n from migrate_sql.config import SQLItem\n\n sql_items = [\n SQLItem(\n 'make_sum', # name of the item\n 'create or replace function make_sum(a mynum, b mynum) returns mynum as $$ '\n 'begin return (a.num + b.num, 'result')::mynum; end; '\n '$$ language plpgsql;', # forward sql\n reverse_sql='drop function make_sum(mynum, mynum);', # sql for removal\n # depends on `mynum` since takes it as argument. we won't be able to drop function\n # without dropping `mynum` first.\n dependencies=[('app_name', 'mynum')],\n ),\n SQLItem(\n 'mynum' # name of the item\n 'create type mynum as (num int, name varchar(20));', # forward sql\n reverse_sql='drop type mynum;', # sql for removal\n ),\n ]\n\n6) Generate migration ``./manage.py makemigrations``:\n\n::\n\n Migrations for 'app_name':\n 0003_xxxx:\n - Reverse alter SQL \"make_sum\"\n - Create SQL \"mynum\"\n - Alter SQL \"make_sum\"\n - Alter SQL state \"make_sum\"\n\nYou can take a look at the content this generated:\n\n.. code:: python\n\n # -*- coding: utf-8 -*-\n from __future__ import unicode_literals\n from django.db import migrations, models\n import migrate_sql.operations\n\n\n class Migration(migrations.Migration):\n dependencies = [\n ('app_name', '0002_xxxx'),\n ]\n operations = [\n migrate_sql.operations.ReverseAlterSQL(\n name='make_sum',\n sql='drop function make_sum(int, int);',\n reverse_sql='create or replace function make_sum(a int, b int) returns int as $$ begin return a + b; end; $$ language plpgsql;',\n ),\n migrate_sql.operations.CreateSQL(\n name='mynum',\n sql='create type mynum as (num int, name varchar(20));',\n reverse_sql='drop type mynum;',\n ),\n migrate_sql.operations.AlterSQL(\n name='make_sum',\n sql='create or replace function make_sum(a mynum, b mynum) returns mynum as $$ begin return (a.num + b.num, \\'result\\')::mynum; end; $$ language plpgsql;',\n reverse_sql='drop function make_sum(mynum, mynum);',\n ),\n migrate_sql.operations.AlterSQLState(\n name='make_sum',\n add_dependencies=(('app_name', 'mynum'),),\n ),\n ]\n\n***NOTE:** Previous function is completely dropped before creation\nbecause definition of it changed. ``CREATE OR REPLACE`` would create\nanother version of it, so ``DROP`` makes it clean.*\n\n***If you put ``replace=True`` as kwarg to an ``SQLItem`` definition, it\nwill NOT drop + create it, but just rerun forward SQL, which is\n``CREATE OR REPLACE`` in this example.***\n\n7) Execute migration ``./manage.py migrate``:\n\n::\n\n Operations to perform:\n Apply all migrations: app_name\n Running migrations:\n Rendering model states... DONE\n Applying brands.0003_xxxx... OK\n\nCheck results:\n\n::\n\n db_name=# select make_sum((5, 'a')::mynum, (3, 'b')::mynum);\n make_sum\n ------------\n (8,result)\n (1 row)\n\n db_name=# select make_sum(12, 15);\n ERROR: function make_sum(integer, integer) does not exist\n LINE 1: select make_sum(12, 15);\n ^\n HINT: No function matches the given name and argument types. You might need to add explicit type casts.\n\nFor more examples see ``tests``.\n\nFeel free to `open new\nissues `__.\n\n.. |Build Status| image:: https://travis-ci.org/klichukb/django-migrate-sql.svg?branch=master\n :target: https://travis-ci.org/klichukb/django-migrate-sql\n.. |codecov.io| image:: https://img.shields.io/codecov/c/github/klichukb/django-migrate-sql/master.svg\n :target: https://codecov.io/github/klichukb/django-migrate-sql?branch=master", "description_content_type": null, "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/klichukb/django-migrate-sql", "keywords": "", "license": "BSD", "maintainer": "", "maintainer_email": "", "name": "django-migrate-sql", "package_url": "https://pypi.org/project/django-migrate-sql/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/django-migrate-sql/", "project_urls": { "Homepage": "https://github.com/klichukb/django-migrate-sql" }, "release_url": "https://pypi.org/project/django-migrate-sql/0.1.1/", "requires_dist": null, "requires_python": null, "summary": "Migration support for raw SQL in Django", "version": "0.1.1" }, "last_serial": 1902191, "releases": { "0.1.0": [], "0.1.1": [ { "comment_text": "", "digests": { "md5": "04b69fc7379f35a4be57ea68158f0644", "sha256": "435e0ef19ee4e8dcfba2b733ae672b33517e74610ce767f0da0ea2f4e0d93317" }, "downloads": -1, "filename": "django_migrate_sql-0.1.1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "04b69fc7379f35a4be57ea68158f0644", "packagetype": "bdist_wheel", "python_version": "2.7", "requires_python": null, "size": 37804, "upload_time": "2016-01-12T20:35:37", "url": "https://files.pythonhosted.org/packages/1a/f7/abd0463d78229403b1e0ffcd826e0d84768ac74b9107ffafee99a8d50a21/django_migrate_sql-0.1.1-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "4e432b58be2324548d98ad155ceb5e0c", "sha256": "07d0abfb51c4881c9cfcb1ecf5b78460aa5feeb76b51975338a4b705db415a3b" }, "downloads": -1, "filename": "django-migrate-sql-0.1.1.tar.gz", "has_sig": false, "md5_digest": "4e432b58be2324548d98ad155ceb5e0c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 25485, "upload_time": "2016-01-12T20:35:31", "url": "https://files.pythonhosted.org/packages/26/d7/73f75fb8c96a55a0a1475a431f2f6760a4432bde7cc37897caaae0e0092b/django-migrate-sql-0.1.1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "04b69fc7379f35a4be57ea68158f0644", "sha256": "435e0ef19ee4e8dcfba2b733ae672b33517e74610ce767f0da0ea2f4e0d93317" }, "downloads": -1, "filename": "django_migrate_sql-0.1.1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "04b69fc7379f35a4be57ea68158f0644", "packagetype": "bdist_wheel", "python_version": "2.7", "requires_python": null, "size": 37804, "upload_time": "2016-01-12T20:35:37", "url": "https://files.pythonhosted.org/packages/1a/f7/abd0463d78229403b1e0ffcd826e0d84768ac74b9107ffafee99a8d50a21/django_migrate_sql-0.1.1-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "4e432b58be2324548d98ad155ceb5e0c", "sha256": "07d0abfb51c4881c9cfcb1ecf5b78460aa5feeb76b51975338a4b705db415a3b" }, "downloads": -1, "filename": "django-migrate-sql-0.1.1.tar.gz", "has_sig": false, "md5_digest": "4e432b58be2324548d98ad155ceb5e0c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 25485, "upload_time": "2016-01-12T20:35:31", "url": "https://files.pythonhosted.org/packages/26/d7/73f75fb8c96a55a0a1475a431f2f6760a4432bde7cc37897caaae0e0092b/django-migrate-sql-0.1.1.tar.gz" } ] }