Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Specifying an Array(String) column type results in a KeyError during Alembic Migrations #118

Closed
geudrik opened this issue Sep 8, 2021 · 7 comments · Fixed by #119
Closed
Assignees
Labels
api: spanner Issues related to the googleapis/python-spanner-sqlalchemy API. priority: p2 Moderately-important priority. Fix may not be included in next release. type: bug Error or flaw in code with unintended results or allowing sub-optimal usage patterns.

Comments

@geudrik
Copy link

geudrik commented Sep 8, 2021

Environment details

  • Programming language: Python 3.8
  • OS: Docker (Debian Slim base)
  • Language runtime version: Py3.8
  • Package version: master@a0ebf758eda351c0a20103f9e8c2243f002b2e6e

Steps to reproduce

  1. Define a table with a column with an array type permissions: List[String] = Column(ARRAY(String))
  2. Run an Alembic automigration

I added two prints in my local version to produce dict and two arrays - see the NOTE THIS LINE below

root@8da01ba789c0:/app# alembic revision --autogenerate -m "test"
INFO  [alembic.runtime.migration] Context impl SpannerImpl.
INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
{'BOOL': <class 'sqlalchemy.sql.sqltypes.Boolean'>, 'BYTES': <class 'sqlalchemy.sql.sqltypes.LargeBinary'>, 'DATE': <class 'sqlalchemy.sql.sqltypes.DATE'>, 'DATETIME': <class 'sqlalchemy.sql.sqltypes.DATETIME'>, 'FLOAT64': <class 'sqlalchemy.sql.sqltypes.Float'>, 'INT64': <class 'sqlalchemy.sql.sqltypes.BIGINT'>, 'NUMERIC': NUMERIC(precision=38, scale=9), 'STRING': <class 'sqlalchemy.sql.sqltypes.String'>, 'TIME': <class 'sqlalchemy.sql.sqltypes.TIME'>, 'TIMESTAMP': <class 'sqlalchemy.sql.sqltypes.TIMESTAMP'>}
['time', 'TIMESTAMP', 'YES']
['permissions', 'ARRAY<STRING(MAX)>', 'YES']   <-- NOTE THIS LINE
Traceback (most recent call last):
  File "/usr/local/bin/alembic", line 8, in <module>
    sys.exit(main())
  File "/usr/local/lib/python3.8/site-packages/alembic/config.py", line 588, in main
    CommandLine(prog=prog).main(argv=argv)
  File "/usr/local/lib/python3.8/site-packages/alembic/config.py", line 582, in main
    self.run_cmd(cfg, options)
  File "/usr/local/lib/python3.8/site-packages/alembic/config.py", line 559, in run_cmd
    fn(
  File "/usr/local/lib/python3.8/site-packages/alembic/command.py", line 227, in revision
    script_directory.run_env()
  File "/usr/local/lib/python3.8/site-packages/alembic/script/base.py", line 563, in run_env
    util.load_python_file(self.dir, "env.py")
  File "/usr/local/lib/python3.8/site-packages/alembic/util/pyfiles.py", line 92, in load_python_file
    module = load_module_py(module_id, path)
  File "/usr/local/lib/python3.8/site-packages/alembic/util/pyfiles.py", line 108, in load_module_py
    spec.loader.exec_module(module)  # type: ignore
  File "<frozen importlib._bootstrap_external>", line 783, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "alembic/env.py", line 72, in <module>
    run_migrations_online()
  File "alembic/env.py", line 66, in run_migrations_online
    context.run_migrations()
  File "<string>", line 8, in run_migrations
  File "/usr/local/lib/python3.8/site-packages/alembic/runtime/environment.py", line 851, in run_migrations
    self.get_context().run_migrations(**kw)
  File "/usr/local/lib/python3.8/site-packages/alembic/runtime/migration.py", line 600, in run_migrations
    for step in self._migrations_fn(heads, self):
  File "/usr/local/lib/python3.8/site-packages/alembic/command.py", line 203, in retrieve_migrations
    revision_context.run_autogenerate(rev, context)
  File "/usr/local/lib/python3.8/site-packages/alembic/autogenerate/api.py", line 520, in run_autogenerate
    self._run_environment(rev, migration_context, True)
  File "/usr/local/lib/python3.8/site-packages/alembic/autogenerate/api.py", line 567, in _run_environment
    compare._populate_migration_script(
  File "/usr/local/lib/python3.8/site-packages/alembic/autogenerate/compare.py", line 53, in _populate_migration_script
    _produce_net_changes(autogen_context, upgrade_ops)
  File "/usr/local/lib/python3.8/site-packages/alembic/autogenerate/compare.py", line 87, in _produce_net_changes
    comparators.dispatch("schema", autogen_context.dialect.name)(
  File "/usr/local/lib/python3.8/site-packages/alembic/util/langhelpers.py", line 266, in go
    fn(*arg, **kw)
  File "/usr/local/lib/python3.8/site-packages/alembic/autogenerate/compare.py", line 126, in _autogen_for_tables
    _compare_tables(
  File "/usr/local/lib/python3.8/site-packages/alembic/autogenerate/compare.py", line 212, in _compare_tables
    sqla_compat._reflect_table(inspector, t, None)
  File "/usr/local/lib/python3.8/site-packages/alembic/util/sqla_compat.py", line 226, in _reflect_table
    return inspector.reflecttable(table, None)
  File "/usr/local/lib/python3.8/site-packages/sqlalchemy/engine/reflection.py", line 664, in reflecttable
    for col_d in self.get_columns(
  File "/usr/local/lib/python3.8/site-packages/sqlalchemy/engine/reflection.py", line 390, in get_columns
    col_defs = self.dialect.get_columns(
  File "/usr/local/lib/python3.8/site-packages/google/cloud/sqlalchemy_spanner/sqlalchemy_spanner.py", line 104, in wrapper
    return function(self, connection, *args, **kwargs)
  File "/usr/local/lib/python3.8/site-packages/google/cloud/sqlalchemy_spanner/sqlalchemy_spanner.py", line 490, in get_columns
    type_ = _type_map[col[1]]
KeyError: 'ARRAY<STRING(MAX)>'

print() were added on line 476 and 489 for debugging sake

image

@geudrik geudrik added priority: p2 Moderately-important priority. Fix may not be included in next release. type: bug Error or flaw in code with unintended results or allowing sub-optimal usage patterns. labels Sep 8, 2021
@product-auto-label product-auto-label bot added the api: spanner Issues related to the googleapis/python-spanner-sqlalchemy API. label Sep 8, 2021
@geudrik
Copy link
Author

geudrik commented Sep 8, 2021

Oh, I also tried via the latest commit hash, same issue.

@IlyaFaer
Copy link
Contributor

Interesting, the original SQLAlchemy reflection tests suite doesn't contain any single case for arrays?!
Okay. I've reproduced the error and already have a solution. Just adding some tests and etc.

@geudrik
Copy link
Author

geudrik commented Sep 10, 2021

Why test when you can use production as test? 😄 Appreciate the quick fix!

@geudrik
Copy link
Author

geudrik commented Sep 14, 2021

I think there are some additional bugs here / this successive issue should block #119

Error parsing Spanner DDL statement: ALTER TABLE ttp_mitre_enterprise ALTER COLUMN parent_id DROP NOT NULL

This is the alembic error I get using this branch trying to run a migration. In this case, the alembic migration is attempting to execute the following alembic code - altering a column and dropping the NOT NULL constraint

op.alter_column('ttp_mitre_enterprise', 'parent_id',
               existing_type=sa.String(length=2621440),
               nullable=True)

@larkee
Copy link
Contributor

larkee commented Sep 15, 2021

The error mentioned in #118 (comment) is an issue of differing syntax. FWICT, the generated query is using the PostGres syntax:

ALTER TABLE table_id ALTER COLUMN column_id DROP NOT NULL

However, the Spanner way of doing this would be:

ALTER TABLE table_id ALTER COLUMN column_id column_type [null_constaint]

e.g. to remove NOT NULL

ALTER TABLE Venue ALTER COLUMN LastUpdateTime TIMESTAMP

e.g. to add NOT NULL

ALTER TABLE Venue ALTER COLUMN LastUpdateTime TIMESTAMP NOT NULL

@IlyaFaer Would you be able to look into adding this support?

@IlyaFaer
Copy link
Contributor

IlyaFaer commented Sep 15, 2021

@larkee, yeah, I'll take a look, of course. Though it seems like a second issue.

@larkee
Copy link
Contributor

larkee commented Sep 15, 2021

@larkee, yeah, I'll take a look, of course. Though it seems like a second issue.

Good point. I'll create another issue 👍

gcf-merge-on-green bot pushed a commit that referenced this issue Sep 16, 2021
gcf-merge-on-green bot pushed a commit that referenced this issue Dec 9, 2021
🤖 I have created a release \*beep\* \*boop\*
---
## [1.0.0](https://www.github.com/googleapis/python-spanner-sqlalchemy/compare/v0.1.0...v1.0.0) (2021-12-08)


### Features

* add code samples ([#55](https://www.github.com/googleapis/python-spanner-sqlalchemy/issues/55)) ([406c34b](https://www.github.com/googleapis/python-spanner-sqlalchemy/commit/406c34bdb21e01a1317c074fab34d87bb3d61020))
* set user-agent string to distinguish SQLAlchemy requests ([#116](https://www.github.com/googleapis/python-spanner-sqlalchemy/issues/116)) ([b5e1a21](https://www.github.com/googleapis/python-spanner-sqlalchemy/commit/b5e1a211a0475690feed36fd222a41c216d8fb82))
* support computed columns ([#139](https://www.github.com/googleapis/python-spanner-sqlalchemy/issues/139)) ([046ca97](https://www.github.com/googleapis/python-spanner-sqlalchemy/commit/046ca975778f4793e2c37d70d2a602546f9d4699)), closes [#137](https://www.github.com/googleapis/python-spanner-sqlalchemy/issues/137)
* support JSON data type ([#135](https://www.github.com/googleapis/python-spanner-sqlalchemy/issues/135)) ([184a7d5](https://www.github.com/googleapis/python-spanner-sqlalchemy/commit/184a7d576a790bbbd049fe80d589af78831379b4))
* support read_only connections ([#125](https://www.github.com/googleapis/python-spanner-sqlalchemy/issues/125)) ([352c47d](https://www.github.com/googleapis/python-spanner-sqlalchemy/commit/352c47de7bb4ea1c30b50a7fe5aee0c4d102e80e))
* support stale reads ([#146](https://www.github.com/googleapis/python-spanner-sqlalchemy/issues/146)) ([d80cb27](https://www.github.com/googleapis/python-spanner-sqlalchemy/commit/d80cb2792437731c24905c7a6919468c37779c67))


### Bug Fixes

* ALTER COLUMN NOT NULL directive fails because of inappropriate syntax ([#124](https://www.github.com/googleapis/python-spanner-sqlalchemy/issues/124)) ([c433cda](https://www.github.com/googleapis/python-spanner-sqlalchemy/commit/c433cda99fd8544810c878328a272a3a9430630f))
* array columns reflection ([#119](https://www.github.com/googleapis/python-spanner-sqlalchemy/issues/119)) ([af3b97b](https://www.github.com/googleapis/python-spanner-sqlalchemy/commit/af3b97bfa4b3ed4b223384c9ed3fa0643204d8c9)), closes [#118](https://www.github.com/googleapis/python-spanner-sqlalchemy/issues/118)
* calculate limit value correctly for offset only queries ([#160](https://www.github.com/googleapis/python-spanner-sqlalchemy/issues/160)) ([6844336](https://www.github.com/googleapis/python-spanner-sqlalchemy/commit/684433682ed29d9cde8c9898796024cefeb38493))
* correct typo in spanner_interleave_on_delete_cascade keyword ([#99](https://www.github.com/googleapis/python-spanner-sqlalchemy/issues/99)) ([a0ebf75](https://www.github.com/googleapis/python-spanner-sqlalchemy/commit/a0ebf758eda351c0a20103f9e8c2243f002b2e6e))
* raise Unimplemented error when creating temporary tables ([#159](https://www.github.com/googleapis/python-spanner-sqlalchemy/issues/159)) ([646d6ac](https://www.github.com/googleapis/python-spanner-sqlalchemy/commit/646d6ac24ccd0643b67abff9da28118e0a6f6e55))
* rollback failed exception log ([#106](https://www.github.com/googleapis/python-spanner-sqlalchemy/issues/106)) ([809e6ab](https://www.github.com/googleapis/python-spanner-sqlalchemy/commit/809e6abb29f82a7fbe6587d606e8d75283f2a2fe))


### Documentation

* add query hints example ([#153](https://www.github.com/googleapis/python-spanner-sqlalchemy/issues/153)) ([9c23804](https://www.github.com/googleapis/python-spanner-sqlalchemy/commit/9c23804746bc8c638b6c22f2cb6ea57778f7fd19))
* reformatted README titles ([#141](https://www.github.com/googleapis/python-spanner-sqlalchemy/issues/141)) ([a3ccbac](https://www.github.com/googleapis/python-spanner-sqlalchemy/commit/a3ccbac476679fe8048ed2109e5489b873278c9c))
* update benchmarks ([#155](https://www.github.com/googleapis/python-spanner-sqlalchemy/issues/155)) ([3500653](https://www.github.com/googleapis/python-spanner-sqlalchemy/commit/35006536e4de31dbcba022b73f0aadf39bc89e39))


### Miscellaneous Chores

* setup release 1.0.0 ([#165](https://www.github.com/googleapis/python-spanner-sqlalchemy/issues/165)) ([37a415d](https://www.github.com/googleapis/python-spanner-sqlalchemy/commit/37a415d071d39e99f233a1c15c1c4b89bd436570))
---


This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api: spanner Issues related to the googleapis/python-spanner-sqlalchemy API. priority: p2 Moderately-important priority. Fix may not be included in next release. type: bug Error or flaw in code with unintended results or allowing sub-optimal usage patterns.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants