klen / peewee_migrate

Simple migration engine for Peewee

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Alter column with added default results in invalid PSQL query

cbautista1002 opened this issue · comments

If you have a model with some field that does not have a default value, and you then modify that model to include a default value, the generated migration for that will fail.

It fails because the resulting PSQL query is an invalid ALTER statement.

Following the formatting in #87

Steps

  1. Example model in models.py:
class Test(Model):
    class Meta:
        database = DB
        only_save_dirty = True

    id = AutoField()
    name = CharField(max_length=123, index=True)
  1. Create initial migration, and migrate it
$ pw_migrate create --auto --directory test/migrations --database $DATABASE_URL --auto-source test test1

$ pw_migrate migrate --directory test/migrations --database $DATABASE_URL --name 001_test1
  1. Change the model in models.py so that the name field now has a default:
name = CharField(max_length=123, index=True, default='D')
  1. Repeat step 2 to create a new migration and then attempt to migrate it.

Result: the generated PSQL query will be this invalid statement:

ALTER TABLE "test" ALTER COLUMN "name" VARCHAR(123) TYPE DEFAULT 'D'

Something like this PSQL statement would work and is would be more appropriate.

ALTER TABLE "test" ALTER COLUMN "name" SET DEFAULT 'D';

Version:

$ pip list | grep peewee
peewee                           3.9.3
peewee-migrate                   1.1.5

Thanks!

Here are the tracebacks in case thats helpful:

Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/peewee_migrate/router.py", line 152, in run_one
    migrator.run()
  File "/usr/local/lib/python3.6/site-packages/peewee_migrate/migrator.py", line 129, in run
    op.run()
  File "/usr/local/lib/python3.6/site-packages/playhouse/migrate.py", line 160, in run
    self._handle_result(method(*self.args, **kwargs))
  File "/usr/local/lib/python3.6/site-packages/playhouse/migrate.py", line 154, in _handle_result
    self._handle_result(item)
  File "/usr/local/lib/python3.6/site-packages/playhouse/migrate.py", line 149, in _handle_result
    self.execute(result)
  File "/usr/local/lib/python3.6/site-packages/playhouse/migrate.py", line 145, in execute
    self.migrator.database.execute(node)
  File "/usr/local/lib/python3.6/site-packages/playhouse/postgres_ext.py", line 464, in execute
    cursor = self.execute_sql(sql, params, commit=commit)
  File "/usr/local/lib/python3.6/site-packages/peewee.py", line 2876, in execute_sql
    cursor.execute(sql, params or ())
psycopg2.errors.SyntaxError: syntax error at or near "VARCHAR"
LINE 1: ALTER TABLE "pgtest2" ALTER COLUMN "name" VARCHAR(123) TYPE ...
                                                  ^

Traceback (most recent call last):
  File "/usr/local/bin/pw_migrate", line 11, in <module>
    sys.exit(cli())
  File "/usr/local/lib/python3.6/site-packages/click/core.py", line 764, in __call__
    return self.main(*args, **kwargs)
  File "/usr/local/lib/python3.6/site-packages/click/core.py", line 717, in main
    rv = self.invoke(ctx)
  File "/usr/local/lib/python3.6/site-packages/click/core.py", line 1137, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/usr/local/lib/python3.6/site-packages/click/core.py", line 956, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/usr/local/lib/python3.6/site-packages/click/core.py", line 555, in invoke
    return callback(*args, **kwargs)
  File "/usr/local/lib/python3.6/site-packages/peewee_migrate/cli.py", line 63, in migrate
    migrations = router.run(name, fake=fake)
  File "/usr/local/lib/python3.6/site-packages/peewee_migrate/router.py", line 180, in run
    self.run_one(mname, migrator, fake=fake, force=fake)
  File "/usr/local/lib/python3.6/site-packages/peewee_migrate/router.py", line 152, in run_one
    migrator.run()
  File "/usr/local/lib/python3.6/site-packages/peewee_migrate/migrator.py", line 129, in run
    op.run()
  File "/usr/local/lib/python3.6/site-packages/playhouse/migrate.py", line 160, in run
    self._handle_result(method(*self.args, **kwargs))
  File "/usr/local/lib/python3.6/site-packages/playhouse/migrate.py", line 154, in _handle_result
    self._handle_result(item)
  File "/usr/local/lib/python3.6/site-packages/playhouse/migrate.py", line 149, in _handle_result
    self.execute(result)
  File "/usr/local/lib/python3.6/site-packages/playhouse/migrate.py", line 145, in execute
    self.migrator.database.execute(node)
  File "/usr/local/lib/python3.6/site-packages/playhouse/postgres_ext.py", line 464, in execute
    cursor = self.execute_sql(sql, params, commit=commit)
  File "/usr/local/lib/python3.6/site-packages/peewee.py", line 2876, in execute_sql
    cursor.execute(sql, params or ())
psycopg2.errors.SyntaxError: syntax error at or near "VARCHAR"
LINE 1: ALTER TABLE "pgtest2" ALTER COLUMN "name" VARCHAR(123) TYPE ...
                                                  ^

The SQL that is being created is:
"ALTER TABLE "table_name" ALTER COLUMN "table_column" NUMERIC(24, 12) TYPE DEFAULT 0"

The word TYPE is being attached in the wrong place. (see this part of the code for Postgres.)
The DEFAULT clause shouldn't be included in the context._sql. I've made a (really ugly) workaround that removes the space and the DEFAULT clause and I could successfully apply the migrations

I can still reproduce this issue with peewee-migrate==1.1.6