From 598e09fb062daed36fd4f10943ce9b4381843c9e Mon Sep 17 00:00:00 2001 From: Joshua Harlow Date: Wed, 3 Jun 2015 21:55:15 -0700 Subject: [PATCH] Use the sqlalchemy-utils json type instead of our own Change-Id: Ie01ea85e74f1daed6bfa5158c0faa476d06873ba --- ...984f2864_switch_postgres_to_json_native.py | 58 +++++++++++++++++++ .../persistence/backends/sqlalchemy/tables.py | 31 +++------- test-requirements.txt | 1 + 3 files changed, 67 insertions(+), 23 deletions(-) create mode 100644 taskflow/persistence/backends/sqlalchemy/alembic/versions/2ad4984f2864_switch_postgres_to_json_native.py diff --git a/taskflow/persistence/backends/sqlalchemy/alembic/versions/2ad4984f2864_switch_postgres_to_json_native.py b/taskflow/persistence/backends/sqlalchemy/alembic/versions/2ad4984f2864_switch_postgres_to_json_native.py new file mode 100644 index 00000000..e795dfce --- /dev/null +++ b/taskflow/persistence/backends/sqlalchemy/alembic/versions/2ad4984f2864_switch_postgres_to_json_native.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2012-2013 Yahoo! Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +"""Switch postgres to json native type. + +Revision ID: 2ad4984f2864 +Revises: 589dccdf2b6e +Create Date: 2015-06-04 13:08:36.667948 + +""" + +# revision identifiers, used by Alembic. +revision = '2ad4984f2864' +down_revision = '589dccdf2b6e' + +from alembic import op + + +_ALTER_TO_JSON_TPL = 'ALTER TABLE %s ALTER COLUMN %s TYPE JSON USING %s::JSON' +_TABLES_COLS = tuple([ + ('logbooks', 'meta'), + ('flowdetails', 'meta'), + ('atomdetails', 'meta'), + ('atomdetails', 'failure'), + ('atomdetails', 'revert_failure'), + ('atomdetails', 'results'), + ('atomdetails', 'revert_results'), +]) +_ALTER_TO_TEXT_TPL = 'ALTER TABLE %s ALTER COLUMN %s TYPE TEXT' + + +def upgrade(): + b = op.get_bind() + if b.dialect.name.startswith('postgresql'): + for (table_name, col_name) in _TABLES_COLS: + q = _ALTER_TO_JSON_TPL % (table_name, col_name, col_name) + op.execute(q) + + +def downgrade(): + b = op.get_bind() + if b.dialect.name.startswith('postgresql'): + for (table_name, col_name) in _TABLES_COLS: + q = _ALTER_TO_TEXT_TPL % (table_name, col_name) + op.execute(q) diff --git a/taskflow/persistence/backends/sqlalchemy/tables.py b/taskflow/persistence/backends/sqlalchemy/tables.py index 65969fb2..b9b065e9 100644 --- a/taskflow/persistence/backends/sqlalchemy/tables.py +++ b/taskflow/persistence/backends/sqlalchemy/tables.py @@ -16,11 +16,10 @@ import collections -from oslo_serialization import jsonutils from oslo_utils import timeutils from oslo_utils import uuidutils from sqlalchemy import Table, Column, String, ForeignKey, DateTime, Enum -from sqlalchemy import types +import sqlalchemy_utils as su from taskflow.persistence import models from taskflow import states @@ -35,20 +34,6 @@ STATE_LENGTH = 255 VERSION_LENGTH = 64 -class Json(types.TypeDecorator): - impl = types.Text - - def process_bind_param(self, value, dialect): - if not value: - return None - return jsonutils.dumps(value) - - def process_result_value(self, value, dialect): - if not value: - return None - return jsonutils.loads(value) - - def fetch(metadata): """Returns the master set of table objects (which is also there schema).""" logbooks = Table('logbooks', metadata, @@ -56,7 +41,7 @@ def fetch(metadata): default=timeutils.utcnow), Column('updated_at', DateTime, onupdate=timeutils.utcnow), - Column('meta', Json), + Column('meta', su.JSONType), Column('name', String(length=NAME_LENGTH)), Column('uuid', String(length=UUID_LENGTH), primary_key=True, nullable=False, unique=True, @@ -69,7 +54,7 @@ def fetch(metadata): Column('parent_uuid', String(length=UUID_LENGTH), ForeignKey('logbooks.uuid', ondelete='CASCADE')), - Column('meta', Json), + Column('meta', su.JSONType), Column('name', String(length=NAME_LENGTH)), Column('state', String(length=STATE_LENGTH)), Column('uuid', String(length=UUID_LENGTH), @@ -80,7 +65,7 @@ def fetch(metadata): default=timeutils.utcnow), Column('updated_at', DateTime, onupdate=timeutils.utcnow), - Column('meta', Json), + Column('meta', su.JSONType), Column('parent_uuid', String(length=UUID_LENGTH), ForeignKey('flowdetails.uuid', ondelete='CASCADE')), @@ -90,10 +75,10 @@ def fetch(metadata): Column('uuid', String(length=UUID_LENGTH), primary_key=True, nullable=False, unique=True, default=uuidutils.generate_uuid), - Column('failure', Json), - Column('results', Json), - Column('revert_results', Json), - Column('revert_failure', Json), + Column('failure', su.JSONType), + Column('results', su.JSONType), + Column('revert_results', su.JSONType), + Column('revert_failure', su.JSONType), Column('atom_type', Enum(*models.ATOM_TYPES, name='atom_types')), Column('intention', Enum(*states.INTENTIONS, diff --git a/test-requirements.txt b/test-requirements.txt index e9bca9bc..8279bd93 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -25,6 +25,7 @@ redis>=2.10.0 SQLAlchemy<1.1.0,>=0.9.9 alembic>=0.8.0 psycopg2>=2.5 +sqlalchemy-utils # BSD License PyMySQL>=0.6.2 # MIT License # Used for making sure we still work with eventlet.