Skip to content

Conversation

@khvn26
Copy link
Member

@khvn26 khvn26 commented Jul 25, 2025

Thanks for submitting a PR! Please check the boxes below:

  • I have added information to docs/ if required so people know about the feature!
  • I have filled in the "Changes" section below?
  • I have filled in the "How did you test this code" section below?
  • I have used a Conventional Commit title for this Pull Request

Changes

This migrates all the labels fields added in #5623 to jsonb as the hstore support turned out to be problematic:

  1. The hstore extension requires enabling additional parameter sets in some cloud environments (e.g. Azure).
  2. Psycopg2 type adpaters don't play well with CockroachDB, which should be compatible otherwise.

Note that due to problem 1, I've removed the CREATE EXTENSION operation from the original migration.

How did you test this code?

Migrations and tests run ok.
Will be smoke-tested against CockroachDB as well.

@khvn26 khvn26 requested a review from a team as a code owner July 25, 2025 14:33
@khvn26 khvn26 requested review from emyller and removed request for a team July 25, 2025 14:33
@vercel
Copy link

vercel bot commented Jul 25, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

3 Skipped Deployments
Name Status Preview Comments Updated (UTC)
docs ⬜️ Ignored (Inspect) Visit Preview Aug 6, 2025 7:30am
flagsmith-frontend-preview ⬜️ Ignored (Inspect) Visit Preview Aug 6, 2025 7:30am
flagsmith-frontend-staging ⬜️ Ignored (Inspect) Visit Preview Aug 6, 2025 7:30am

@github-actions github-actions bot added api Issue related to the REST API feature New feature or request labels Jul 25, 2025
@github-actions
Copy link
Contributor

github-actions bot commented Jul 25, 2025

Docker builds report

Image Build Status Security report
ghcr.io/flagsmith/flagsmith-api-test:pr-5833 Finished ✅ Skipped
ghcr.io/flagsmith/flagsmith-e2e:pr-5833 Finished ✅ Skipped
ghcr.io/flagsmith/flagsmith-api:pr-5833 Finished ✅ Results
ghcr.io/flagsmith/flagsmith-frontend:pr-5833 Finished ✅ Results
ghcr.io/flagsmith/flagsmith:pr-5833 Finished ✅ Results
ghcr.io/flagsmith/flagsmith-private-cloud:pr-5833 Finished ✅ Results

@github-actions github-actions bot added feature New feature or request and removed feature New feature or request labels Jul 25, 2025
@codecov
Copy link

codecov bot commented Jul 25, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 97.82%. Comparing base (1411f54) to head (e0789c3).

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #5833   +/-   ##
=======================================
  Coverage   97.82%   97.82%           
=======================================
  Files        1258     1259    +1     
  Lines       44745    44747    +2     
=======================================
+ Hits        43771    43773    +2     
  Misses        974      974           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@scarlson
Copy link
Contributor

Confirming this fix allows CockroachDB to work without needing to update Psycopg to 3.1+.

Copy link
Contributor

@Zaimwa9 Zaimwa9 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The migrations look redundant except if I am missing something? Can we see to merge them together maybe ?

@khvn26
Copy link
Member Author

khvn26 commented Jul 28, 2025

@Zaimwa9 Indeed these migrations look very similar, but their purpose is actually different:

  • 0006 adds correct jsonb columns to the tables. The original migration is modified to avoid customers having to add hstore capability to their databases since it's no longer a requirement. This exists primarily for new installations/fresh dbs.
  • 0007 alters existing hstore columns to jsonb. This has to happen for installations where previous 0006 migration was already applied.

So, to answer your question, no, we can't merge these migrations as they cater for different scenarios, and I argue they are not in fact redundant.

@khvn26 khvn26 requested a review from Zaimwa9 July 28, 2025 13:39
Zaimwa9
Zaimwa9 previously approved these changes Jul 28, 2025
Copy link
Contributor

@Zaimwa9 Zaimwa9 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright thanks for the details, I felt that under the hood there was a migration purpose

Comment on lines 12 to 32
operations = [
migrations.AlterField(
model_name="apiusagebucket",
name="labels",
field=models.JSONField(default=dict),
),
migrations.AlterField(
model_name="apiusageraw",
name="labels",
field=models.JSONField(default=dict),
),
migrations.AlterField(
model_name="featureevaluationbucket",
name="labels",
field=models.JSONField(default=dict),
),
migrations.AlterField(
model_name="featureevaluationraw",
name="labels",
field=models.JSONField(default=dict),
),
Copy link
Contributor

@emyller emyller Jul 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To my understanding, this will lead to multiple alter column ... type statements. Is casting hstore to json as simple as that in, at least, Postgres?

I'm also curious as to the impact of this to existing installs.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, we actually need a USING clause. Added in 091006e.

@emyller
Copy link
Contributor

emyller commented Jul 28, 2025

I forgot to add as notes to my last review: not actually requesting any changes unless proven necessary by the comment I added.

@github-actions github-actions bot added feature New feature or request and removed feature New feature or request labels Aug 6, 2025
Comment on lines +37 to +70
migrations.RunSQL(
# Only alter the columns that are currently hstore.
# See 0006_add_labels to understand why we are doing this.
sql="""
DO $$
BEGIN
FOR relname IN
SELECT c.relname
FROM pg_class c
JOIN pg_attribute a ON a.attrelid = c.oid
JOIN pg_type t ON a.atttypid = t.oid
WHERE c.relname IN (
'app_analytics_apiusagebucket',
'app_analytics_apiusageraw',
'app_analytics_featureevaluationbucket',
'app_analytics_featureevaluationraw'
)
AND a.attname = 'labels'
AND t.typname = 'hstore'
LOOP
EXECUTE format(
'ALTER TABLE %I
ALTER COLUMN labels TYPE jsonb USING hstore_to_json(labels),
ALTER COLUMN labels SET DEFAULT ''{}''::jsonb',
relname
);
END LOOP;
END
$$;
""",
# We don't want hstore in the database at all,
# so don't do anything for reverse SQL.
reverse_sql="",
),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The SQL code looks fine, though I think we should benefit from the ORM abstraction until we need to fall back to raw SQL.

Here's an untested brain dump.

Given:

def upgrade_field(model_name: str, field_name: str) -> Callable[[Apps, SchemaEditor], None]:
    def upgrade(apps: Apps, schema_editor: SchemaEditor) -> None:
        model = apps.get_model("app_analytics", model_name)
        field = model._meta.get_field(field_name)
        if isinstance(field, models.JSONField):
            continue
        schema_editor.execute(f"""
            ALTER TABLE {model._meta.db_table}
            ALTER COLUMN {field.column} TYPE jsonb USING hstore_to_json({field.column}),
            ALTER COLUMN {field.column} SET DEFAULT '{{}}'::jsonb
        """)
    return upgrade

Suggested replacement for the SQL script:

Suggested change
migrations.RunSQL(
# Only alter the columns that are currently hstore.
# See 0006_add_labels to understand why we are doing this.
sql="""
DO $$
BEGIN
FOR relname IN
SELECT c.relname
FROM pg_class c
JOIN pg_attribute a ON a.attrelid = c.oid
JOIN pg_type t ON a.atttypid = t.oid
WHERE c.relname IN (
'app_analytics_apiusagebucket',
'app_analytics_apiusageraw',
'app_analytics_featureevaluationbucket',
'app_analytics_featureevaluationraw'
)
AND a.attname = 'labels'
AND t.typname = 'hstore'
LOOP
EXECUTE format(
'ALTER TABLE %I
ALTER COLUMN labels TYPE jsonb USING hstore_to_json(labels),
ALTER COLUMN labels SET DEFAULT ''{}''::jsonb',
relname
);
END LOOP;
END
$$;
""",
# We don't want hstore in the database at all,
# so don't do anything for reverse SQL.
reverse_sql="",
),
migrations.RunPython(
code=upgrade_field("apiusagebucket", "labels"),
reverse_code=migrations.RunPython.noop,
),
migrations.RunPython(
code=upgrade_field("apiusageraw", "labels"),
reverse_code=migrations.RunPython.noop,
),
migrations.RunPython(
code=upgrade_field("featureevaluationbucket", "labels"),
reverse_code=migrations.RunPython.noop,
),
migrations.RunPython(
code=upgrade_field("featureevaluationraw", "labels"),
reverse_code=migrations.RunPython.noop,
),

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api Issue related to the REST API feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants