question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Add support for sqlalchemy.dialects.postgresql fields

See original GitHub issue

When I try to register a SQLAlchemyNode whose model has a postgres-specific field, I receive the error message Don't know how to convert the SQLAlchemy field [table_name].[field_name] (<class 'sqlalchemy.sql.schema.Column'>). It’d be great if these fields worked out of the box.

Issue Analytics

  • State:closed
  • Created 7 years ago
  • Reactions:2
  • Comments:8 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
patvdleercommented, Jun 6, 2018

Due a wrapper (for JSONB on Sqlite) I wrote (and stole/copied) I ran into the same error. Maybe this will help others.

import json

from graphene import JSONString
from graphene_sqlalchemy.converter import convert_sqlalchemy_type, get_column_doc, is_column_nullable
from sqlalchemy import types, TypeDecorator
from sqlalchemy.dialects.postgresql import JSONB
from sqlalchemy.ext.compiler import compiles
from sqlalchemy.sql import sqltypes
from sqlalchemy.sql.functions import FunctionElement


class SqliteJsonElement(FunctionElement):
    type = types.Text()
    name = "JsonElement"

    @property
    def astext(self):
        return self


@compiles(SqliteJsonElement)
def compileSqliteJsonElement(element, compiler, **kw):
    return "jsonExtract(%s)" % compiler.process(element.clauses)


class SqliteJson(TypeDecorator):
    impl = types.Text

    def process_bind_param(self, value, dialect):
        if isinstance(value, tuple) and len(value) == 1:
            value = value[0]
        return json.dumps(value or {})

    def process_result_value(self, value, dialect):
        if value is None:
            return {}
        return json.loads(value)

    class comparator_factory(sqltypes.Concatenable.Comparator):
        def __getitem__(self, other):
            """Get the value at a given key."""
            return SqliteJsonElement(self.expr, other)


class SqliteCompatiblePostgresOptimizedJson(TypeDecorator):
    # See: http://docs.sqlalchemy.org/en/latest/core/custom_types.html
    # impl = None
    impl = types.JSON

    def load_dialect_impl(self, dialect):
        dialectTypeMap = {
            'sqlite': SqliteJson,
            'postgresql': JSONB
        }

        self.impl = dialect.type_descriptor(dialectTypeMap[dialect.name])
        return self.impl

    def process_bind_param(self, value, dialect):
        return value

    def process_result_value(self, value, dialect):
        # Todo: refactor
        if isinstance(value, (tuple, list)) and len(value) == 1:
            value = value[0]
        if isinstance(value, dict) and len(value.keys()) == 1 and "meta" in value.keys():
            value = value["meta"]
        return value

    @property
    def comparator_factory(self):
        """express comparison behavior in terms of the base type"""
        return self.impl.comparator_factory


@convert_sqlalchemy_type.register(SqliteCompatiblePostgresOptimizedJson)
def convert_json_to_string(type, column, registry=None):
    return JSONString(description=get_column_doc(column), required=not(is_column_nullable(column)))
0reactions
syrusakbarycommented, Sep 11, 2016

Postgresql SQLAlchemy field conversion is now available in 1.0.dev (master branch).

Closing the issue!

Read more comments on GitHub >

github_iconTop Results From Across the Web

PostgreSQL - SQLAlchemy 1.4 Documentation
The PostgreSQL dialect supports arrays, both as multidimensional column types as well as array literals: ARRAY - ARRAY datatype. array - array literal....
Read more >
sqlalchemy.dialects postgresql Example Code
Python example code that shows how to use the postgresql callable from the sqlalchemy.dialects module of the SQLAlchemy project.
Read more >
PostgreSQL - SQLAlchemy 1.1 Documentation - Read the Docs
The Postgresql dialect supports arrays, both as multidimensional column types as well as array literals: postgresql.ARRAY - ARRAY datatype; postgresql.array - ...
Read more >
How to do a proper upsert using sqlalchemy on postgresql?
I basically want to insert a bulk of rows, and if one id is already taken, I want to update it with the...
Read more >
Beware of JSON fields in SQLAlchemy - Adrià Mercader
SQLAlchemy supports JSON fields natively so you can easily add support ... declarative_base from sqlalchemy.dialects.postgresql import JSONB ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found