general: ensure jsonfields are using jsonb columns (#52915)
This commit is contained in:
parent
4021e5d3b0
commit
21976d8f20
|
@ -0,0 +1,17 @@
|
|||
# Generated by Django 2.2.12 on 2021-04-11 15:54
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
from combo.utils.db import EnsureJsonbType
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('dataviz', '0016_auto_20201215_1624'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
EnsureJsonbType(model_name='Statistic', field_name='filters'),
|
||||
EnsureJsonbType(model_name='ChartNgCell', field_name='filter_params'),
|
||||
]
|
|
@ -0,0 +1,20 @@
|
|||
# Generated by Django 2.2.12 on 2021-04-11 15:54
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
from combo.utils.db import EnsureJsonbType
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('lingo', '0041_regie_can_pay_only_one_basket_item'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
EnsureJsonbType(model_name='PaymentBackend', field_name='service_options'),
|
||||
EnsureJsonbType(model_name='Regie', field_name='transaction_options'),
|
||||
EnsureJsonbType(model_name='BasketItem', field_name='request_data'),
|
||||
EnsureJsonbType(model_name='Transaction', field_name='bank_data'),
|
||||
EnsureJsonbType(model_name='TransactionOperation', field_name='bank_result'),
|
||||
]
|
|
@ -0,0 +1,17 @@
|
|||
# Generated by Django 2.2.12 on 2021-04-11 15:54
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
from combo.utils.db import EnsureJsonbType
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('pwa', '0006_auto_20190628_1042'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
EnsureJsonbType(model_name='PwaSettings', field_name='push_notifications_infos'),
|
||||
EnsureJsonbType(model_name='PushSubscription', field_name='subscription_info'),
|
||||
]
|
|
@ -0,0 +1,16 @@
|
|||
# Generated by Django 2.2.12 on 2021-04-11 15:54
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
from combo.utils.db import EnsureJsonbType
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('search', '0008_searchcell_input_placeholder'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
EnsureJsonbType(model_name='SearchCell', field_name='_search_services'),
|
||||
]
|
|
@ -0,0 +1,21 @@
|
|||
# Generated by Django 2.2.12 on 2021-04-11 15:54
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
from combo.db.utils import EnsureJsonbType
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('wcs', '0025_submission_categories'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
EnsureJsonbType(model_name='WcsFormCell', field_name='cached_json'),
|
||||
EnsureJsonbType(model_name='WcsCurrentFormsCell', field_name='categories'),
|
||||
EnsureJsonbType(model_name='WcsCurrentDraftsCell', field_name='categories'),
|
||||
EnsureJsonbType(model_name='WcsFormsOfCategoryCell', field_name='manual_order'),
|
||||
EnsureJsonbType(model_name='WcsCardInfosCell', field_name='cached_json'),
|
||||
EnsureJsonbType(model_name='BackofficeSubmissionCell', field_name='categories'),
|
||||
]
|
|
@ -0,0 +1,50 @@
|
|||
# combo - content management system
|
||||
# Copyright (C) 2015-2021 Entr'ouvert
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Affero General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from django.apps import apps
|
||||
from django.core.management.base import BaseCommand, CommandError
|
||||
from django.db import connection
|
||||
|
||||
from jsonfield import JSONField
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = 'Ensure all JSON fields are of type jsonb'
|
||||
|
||||
def handle(self, **options):
|
||||
for app in apps.get_models():
|
||||
for field in app._meta.get_fields():
|
||||
if isinstance(field, JSONField):
|
||||
table_name = app._meta.db_table
|
||||
column_name = app._meta.get_field(field.name).column
|
||||
with connection.cursor() as cursor:
|
||||
query = '''SELECT table_schema
|
||||
FROM information_schema.columns
|
||||
WHERE table_name = %s AND column_name = %s AND data_type != %s'''
|
||||
cursor.execute(query, [table_name, column_name, 'jsonb'])
|
||||
for line in cursor.fetchall():
|
||||
alter_query = '''ALTER TABLE "%(schema_name)s"."%(table_name)s"
|
||||
ALTER COLUMN "%(column_name)s"
|
||||
TYPE jsonb USING "%(column_name)s"::jsonb'''
|
||||
params = {
|
||||
'schema_name': line[0],
|
||||
'table_name': table_name,
|
||||
'column_name': column_name,
|
||||
}
|
||||
try:
|
||||
cursor.execute(alter_query % params)
|
||||
except Exception as e:
|
||||
raise CommandError(e)
|
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 2.2.12 on 2021-04-11 15:54
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
from combo.utils.db import EnsureJsonbType
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('data', '0045_link_list_limit'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
EnsureJsonbType(model_name='Page', field_name='related_cells'),
|
||||
EnsureJsonbType(model_name='PageSnapshot', field_name='serialization'),
|
||||
EnsureJsonbType(model_name='ConfigJsonCell', field_name='parameters'),
|
||||
]
|
|
@ -0,0 +1,47 @@
|
|||
# combo - content management system
|
||||
# Copyright (C) 2015-2021 Entr'ouvert
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Affero General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from django.db.migrations.operations.base import Operation
|
||||
|
||||
|
||||
class EnsureJsonbType(Operation):
|
||||
|
||||
reversible = True
|
||||
|
||||
def __init__(self, model_name, field_name):
|
||||
self.model_name = model_name
|
||||
self.field_name = field_name
|
||||
|
||||
def state_forwards(self, app_label, state):
|
||||
pass
|
||||
|
||||
def database_forwards(self, app_label, schema_editor, from_state, to_state):
|
||||
model = from_state.apps.get_model(app_label, self.model_name)
|
||||
table_name = model._meta.db_table
|
||||
field = model._meta.get_field(self.field_name)
|
||||
_, column_name = field.get_attname_column()
|
||||
with schema_editor.connection.cursor() as cursor:
|
||||
cursor.execute(
|
||||
'ALTER TABLE {table} ALTER COLUMN {col} TYPE jsonb USING {col}::jsonb;'.format(
|
||||
table=table_name, col=column_name
|
||||
)
|
||||
)
|
||||
|
||||
def database_backwards(self, app_label, schema_editor, from_state, to_state):
|
||||
pass
|
||||
|
||||
def describe(self):
|
||||
return "Migrate to postgres jsonb type"
|
|
@ -0,0 +1,61 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import pytest
|
||||
|
||||
from django.core.management import call_command
|
||||
from django.db import connection
|
||||
|
||||
pytestmark = pytest.mark.django_db
|
||||
|
||||
|
||||
@pytest.mark.skipif(connection.vendor != 'postgresql', reason='only postgresql is supported')
|
||||
def test_ensure_jsonb_fields():
|
||||
json_fields = (
|
||||
'bank_data',
|
||||
'bank_result',
|
||||
'cached_json',
|
||||
'cached_json',
|
||||
'categories',
|
||||
'categories',
|
||||
'categories',
|
||||
'filter_params',
|
||||
'filters',
|
||||
'manual_order',
|
||||
'parameters',
|
||||
'push_notifications_infos',
|
||||
'related_cells',
|
||||
'request_data',
|
||||
'_search_services',
|
||||
'serialization',
|
||||
'service_options',
|
||||
'subscription_info',
|
||||
'transaction_options',
|
||||
)
|
||||
|
||||
with connection.cursor() as cursor:
|
||||
query = '''SELECT table_name, column_name, data_type
|
||||
FROM information_schema.columns
|
||||
WHERE column_name IN %(json_fields)s'''
|
||||
cursor.execute(query, {'json_fields': json_fields})
|
||||
|
||||
# make sure the data_type is correct
|
||||
for line in cursor.fetchall():
|
||||
assert line[2] == 'jsonb'
|
||||
|
||||
# alter columns
|
||||
cursor.execute(
|
||||
'''ALTER TABLE wcs_wcsformsofcategorycell
|
||||
ALTER COLUMN manual_order TYPE text USING manual_order::text'''
|
||||
)
|
||||
|
||||
call_command('ensure_jsonb')
|
||||
|
||||
with connection.cursor() as cursor:
|
||||
query = '''SELECT table_name, column_name, data_type
|
||||
FROM information_schema.columns
|
||||
WHERE column_name IN %(json_fields)s'''
|
||||
cursor.execute(query, {'json_fields': json_fields})
|
||||
|
||||
# check the data_type is correct
|
||||
for line in cursor.fetchall():
|
||||
assert line[2] == 'jsonb'
|
Loading…
Reference in New Issue