django-migrate-sql-3


Namedjango-migrate-sql-3 JSON
Version 3.0.2 PyPI version JSON
download
home_pageNone
SummaryA package parsing the PostgreSQL connection service file
upload_time2024-04-19 09:51:12
maintainerNone
docs_urlNone
authorNone
requires_python>=3.9
licenseMIT License
keywords postgres service
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # django-migrate-sql


This package is a fork of the `django-migrate-sql` package, originally
published by Bogdan Klichuk, later by @festicket. These packages appears unmaintained, so we
decided to start a fork as we depended on it. Most of the code is from
him.
:::


Django Migrations support for raw SQL.

## About

This tool implements mechanism for managing changes to custom SQL
entities (functions, types, indices, triggers) using built-in migration
mechanism. Technically creates a sophistication layer on top of the
`RunSQL` Django operation.

## What it does

-   Makes maintaining your SQL functions, custom composite types,
    indices and triggers easier.
-   Structures SQL into configuration of **SQL items**, that are
    identified by names and divided among apps, just like models.
-   Automatically gathers and persists changes of your custom SQL into
    migrations using `makemigrations`.
-   Properly executes backwards/forwards keeping integrity of database.
-   Create -\> Drop -\> Recreate approach for changes to items that do
    not support altering and require dropping and recreating.
-   Dependencies system for SQL items, which solves the problem of
    updating items, that rely on others (for example custom
    types/functions that use other custom types), and require dropping
    all dependency tree previously with further recreation.

## What it does not

-   Does not parse SQL nor validate queries during `makemigrations` or
    `migrate` because is database-agnostic. For this same reason setting
    up proper dependencies is user\'s responsibility.
-   Does not create `ALTER` queries for items that support this, for
    example `ALTER TYPE` in Postgre SQL, because is database-agnostic.
    In case your tools allow rolling all the changes through `ALTER`
    queries, you can consider not using this app **or** restructure
    migrations manually after creation by nesting generated operations
    into `` `state_operations `` of `RunSQL`
    \<<https://docs.djangoproject.com/en/1.8/ref/migration-operations/#runsql>\>[\_\_
    that does ]{.title-ref}[ALTER]{.title-ref}\`.
-   (**TODO**)During `migrate` does not restore full state of items for
    analysis, thus does not notify about existing changes to schema that
    are not migrated **nor** does not recognize circular dependencies
    during migration execution.

## Installation

Install from PyPi:

    $ pip install django-migrate-sql-3

Add `migrate_sql` to `INSTALLED_APPS`:

``` python
INSTALLED_APPS = [
    # ...
    'migrate_sql',
]
```

App defines a custom `makemigrations` command, that inherits from
Django\'s core one, so in order `migrate_sql` app to kick in put it
after any other apps that redefine `makemigrations` command too.

## Usage

1)  Create `sql_config.py` module to root of a target app you want to
    manage custom SQL for.
2)  Define SQL items in it (`sql_items`), for example:

``` python
# PostgreSQL example.
# Let's define a simple function and let `migrate_sql` manage it's changes.

from migrate_sql.config import SQLItem

sql_items = [
    SQLItem(
        'make_sum',   # name of the item
        'create or replace function make_sum(a int, b int) returns int as $$ '
        'begin return a + b; end; '
        '$$ language plpgsql;',  # forward sql
        reverse_sql='drop function make_sum(int, int);',  # sql for removal
    ),
]
```

3)  Create migration `./manage.py makemigrations`:

        Migrations for 'app_name':
          0002_auto_xxxx.py:
        - Create SQL "make_sum"

You can take a look at content this generated:

``` python
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
import migrate_sql.operations


class Migration(migrations.Migration):
    dependencies = [
        ('app_name', '0001_initial'),
    ]
    operations = [
        migrate_sql.operations.CreateSQL(
            name='make_sum',
            sql='create or replace function make_sum(a int, b int) returns int as $$ begin return a + b; end; $$ language plpgsql;',
            reverse_sql='drop function make_sum(int, int);',
        ),
    ]
```

4)  Execute migration `./manage.py migrate`:

        Operations to perform:
          Apply all migrations: app_name
        Running migrations:
          Rendering model states... DONE
          Applying app_name.0002_xxxx... OK

Check result in `./manage.py dbshell`:

    db_name=# select make_sum(12, 15);
     make_sum
    ----------
           27
    (1 row)

Now, say, you want to change the function implementation so that it
takes a custom type as argument:

5)  Edit your `sql_config.py`:

``` python
# PostgreSQL example #2.
# Function and custom type.

from migrate_sql.config import SQLItem

sql_items = [
    SQLItem(
        'make_sum',  # name of the item
        'create or replace function make_sum(a mynum, b mynum) returns mynum as $$ '
        'begin return (a.num + b.num, 'result')::mynum; end; '
        '$$ language plpgsql;',  # forward sql
        reverse_sql='drop function make_sum(mynum, mynum);',  # sql for removal
        # depends on `mynum` since takes it as argument. we won't be able to drop function
        # without dropping `mynum` first.
        dependencies=[('app_name', 'mynum')],
    ),
    SQLItem(
        'mynum'   # name of the item
        'create type mynum as (num int, name varchar(20));',  # forward sql
        reverse_sql='drop type mynum;',  # sql for removal
    ),
]
```

6)  Generate migration `./manage.py makemigrations`:

```{=html}
<!-- -->
```
    Migrations for 'app_name':
      0003_xxxx:
        - Reverse alter SQL "make_sum"
        - Create SQL "mynum"
        - Alter SQL "make_sum"
        - Alter SQL state "make_sum"

You can take a look at the content this generated:

``` python
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
import migrate_sql.operations


class Migration(migrations.Migration):
    dependencies = [
        ('app_name', '0002_xxxx'),
    ]
    operations = [
        migrate_sql.operations.ReverseAlterSQL(
            name='make_sum',
            sql='drop function make_sum(int, int);',
            reverse_sql='create or replace function make_sum(a int, b int) returns int as $$ begin return a + b; end; $$ language plpgsql;',
        ),
        migrate_sql.operations.CreateSQL(
            name='mynum',
            sql='create type mynum as (num int, name varchar(20));',
            reverse_sql='drop type mynum;',
        ),
        migrate_sql.operations.AlterSQL(
            name='make_sum',
            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;',
            reverse_sql='drop function make_sum(mynum, mynum);',
        ),
        migrate_sql.operations.AlterSQLState(
            name='make_sum',
            add_dependencies=(('app_name', 'mynum'),),
        ),
    ]
```

**\*NOTE:** Previous function is completely dropped before creation
because definition of it changed. `CREATE OR REPLACE` would create
another version of it, so `DROP` makes it clean.\*

**\*If you put \`\`replace=True\`\` as kwarg to an \`\`SQLItem\`\`
definition, it will NOT drop + create it, but just rerun forward SQL,
which is \`\`CREATE OR REPLACE\`\` in this example.**\*

7)  Execute migration `./manage.py migrate`:

```{=html}
<!-- -->
```
    Operations to perform:
      Apply all migrations: app_name
    Running migrations:
      Rendering model states... DONE
      Applying brands.0003_xxxx... OK

Check results:

    db_name=# select make_sum((5, 'a')::mynum, (3, 'b')::mynum);
      make_sum  
    ------------
     (8,result)
    (1 row)

    db_name=# select make_sum(12, 15);
    ERROR:  function make_sum(integer, integer) does not exist
    LINE 1: select make_sum(12, 15);
                   ^
    HINT:  No function matches the given name and argument types. You might need to add explicit type casts.

For more examples see `tests`.

Feel free to [open new
issues](https://github.com/opengisch/django-migrate-sql/issues).

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "django-migrate-sql-3",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.9",
    "maintainer_email": null,
    "keywords": "postgres, service",
    "author": null,
    "author_email": "Bogdan Klichuk <klichuk@github.com>, Festicket <festicket@github.com>, Denis Rouzaud <info@opengis.ch>",
    "download_url": "https://files.pythonhosted.org/packages/8f/30/43c4b6ec2654ccd03d2c2c1b6cb467eb77bc0260330d823d623081ad5b26/django_migrate_sql_3-3.0.2.tar.gz",
    "platform": null,
    "description": "# django-migrate-sql\n\n\nThis package is a fork of the `django-migrate-sql` package, originally\npublished by Bogdan Klichuk, later by @festicket. These packages appears unmaintained, so we\ndecided to start a fork as we depended on it. Most of the code is from\nhim.\n:::\n\n\nDjango Migrations support for raw SQL.\n\n## About\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\n## What it does\n\n-   Makes maintaining your SQL functions, custom composite types,\n    indices 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\n    not 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\n## What it does not\n\n-   Does not parse SQL nor validate queries during `makemigrations` or\n    `migrate` because is database-agnostic. For this same reason setting\n    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 `RunSQL`\n    \\<<https://docs.djangoproject.com/en/1.8/ref/migration-operations/#runsql>\\>[\\_\\_\n    that does ]{.title-ref}[ALTER]{.title-ref}\\`.\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\n## Installation\n\nInstall from PyPi:\n\n    $ pip install django-migrate-sql-3\n\nAdd `migrate_sql` to `INSTALLED_APPS`:\n\n``` python\nINSTALLED_APPS = [\n    # ...\n    'migrate_sql',\n]\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\n## Usage\n\n1)  Create `sql_config.py` module to root of a target app you want to\n    manage custom SQL for.\n2)  Define SQL items in it (`sql_items`), for example:\n\n``` python\n# PostgreSQL example.\n# Let's define a simple function and let `migrate_sql` manage it's changes.\n\nfrom migrate_sql.config import SQLItem\n\nsql_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```\n\n3)  Create migration `./manage.py makemigrations`:\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``` python\n# -*- coding: utf-8 -*-\nfrom __future__ import unicode_literals\nfrom django.db import migrations, models\nimport migrate_sql.operations\n\n\nclass 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```\n\n4)  Execute migration `./manage.py migrate`:\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    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``` python\n# PostgreSQL example #2.\n# Function and custom type.\n\nfrom migrate_sql.config import SQLItem\n\nsql_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```\n\n6)  Generate migration `./manage.py makemigrations`:\n\n```{=html}\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``` python\n# -*- coding: utf-8 -*-\nfrom __future__ import unicode_literals\nfrom django.db import migrations, models\nimport migrate_sql.operations\n\n\nclass 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\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\\`\\`\ndefinition, it will NOT drop + create it, but just rerun forward SQL,\nwhich is \\`\\`CREATE OR REPLACE\\`\\` in this example.**\\*\n\n7)  Execute migration `./manage.py migrate`:\n\n```{=html}\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    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](https://github.com/opengisch/django-migrate-sql/issues).\n",
    "bugtrack_url": null,
    "license": "MIT License",
    "summary": "A package parsing the PostgreSQL connection service file",
    "version": "3.0.2",
    "project_urls": {
        "homepage": "https://github.com/opengisch/django-migrate-sql",
        "repository": "https://github.com/opengisch/django-migrate-sql",
        "tracker": "https://github.com/opengisch/django-migrate-sql/issues"
    },
    "split_keywords": [
        "postgres",
        " service"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "9a28efd044461cf09ce9a4c2f2c68b9a7a38d08f28c39174a413c936b27868c3",
                "md5": "8ab005f73cd7a095ead2c20372f30324",
                "sha256": "d5e04cb5b51f63a7260783445b9bc4b4eaf160e2b7faec1146f34b587f189dee"
            },
            "downloads": -1,
            "filename": "django_migrate_sql_3-3.0.2-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "8ab005f73cd7a095ead2c20372f30324",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.9",
            "size": 12673,
            "upload_time": "2024-04-19T09:51:10",
            "upload_time_iso_8601": "2024-04-19T09:51:10.355786Z",
            "url": "https://files.pythonhosted.org/packages/9a/28/efd044461cf09ce9a4c2f2c68b9a7a38d08f28c39174a413c936b27868c3/django_migrate_sql_3-3.0.2-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "8f3043c4b6ec2654ccd03d2c2c1b6cb467eb77bc0260330d823d623081ad5b26",
                "md5": "ef3db18e5dbfb80ac6d4caa4b0cbd726",
                "sha256": "486770e7f4c670c0fbbc7937c57b9bb614db372624dce67657387c9f7c1da257"
            },
            "downloads": -1,
            "filename": "django_migrate_sql_3-3.0.2.tar.gz",
            "has_sig": false,
            "md5_digest": "ef3db18e5dbfb80ac6d4caa4b0cbd726",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.9",
            "size": 25082,
            "upload_time": "2024-04-19T09:51:12",
            "upload_time_iso_8601": "2024-04-19T09:51:12.916180Z",
            "url": "https://files.pythonhosted.org/packages/8f/30/43c4b6ec2654ccd03d2c2c1b6cb467eb77bc0260330d823d623081ad5b26/django_migrate_sql_3-3.0.2.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-04-19 09:51:12",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "opengisch",
    "github_project": "django-migrate-sql",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "requirements": [],
    "lcname": "django-migrate-sql-3"
}
        
Elapsed time: 0.45003s