Mysql
 sql >> Base de données >  >> RDS >> Mysql

Type de colonne binaire Python-Sqlalchemy HEX() et UNHEX()

Uniquement pour les sélections et les insertions

Eh bien, pour sélectionner, vous pouvez utiliser :

>>> from sqlalchemy import func
>>> session = (...)
>>> (...)
>>> engine = create_engine('sqlite:///:memory:', echo=True)
>>> q = session.query(Model.id).filter(Model.some == func.HEX('asd'))
>>> print q.statement.compile(bind=engine)
SELECT model.id
FROM model
WHERE model.some = HEX(?)

Pour insérer :

>>> from sqlalchemy import func
>>> session = (...)
>>> (...)
>>> engine = create_engine('sqlite:///:memory:', echo=True)
>>> m = new Model(hash=func.HEX('asd'))
>>> session.add(m)
>>> session.commit()
INSERT INTO model (hash) VALUES (HEX(%s))

Une meilleure approche :colonne personnalisée qui convertit les données à l'aide de fonctions sql

Mais, je pense que le mieux pour vous est un personnalisé chronique sur sqlalchemy en utilisant n'importe quel process_bind_param , process_result_value , bind_expression et column_expression voir cet exemple .

Vérifiez ce code ci-dessous, il crée une colonne personnalisée qui, je pense, correspond à vos besoins :

from sqlalchemy.types import VARCHAR
from sqlalchemy import func

class HashColumn(VARCHAR):

    def bind_expression(self, bindvalue):
        # convert the bind's type from String to HEX encoded 
        return func.HEX(bindvalue)

    def column_expression(self, col):
        # convert select value from HEX encoded to String
        return func.UNHEX(col)

Vous pouvez modéliser votre table comme :

from sqlalchemy import Column, types
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class Model(Base):
    __tablename__ = "model"
    id = Column(types.Integer, primary_key=True)
    col = Column(HashColumn(20))

    def __repr__(self):
        return "Model(col=%r)" % self.col

Quelques utilisations :

>>> (...)
>>> session = create_session(...)
>>> (...)
>>> model = Model(col='Iuri Diniz')
>>> session.add(model)
>>> session.commit()

cela génère cette requête :

INSERT INTO model (col) VALUES (HEX(?)); -- ('Iuri Diniz',)

Plus d'utilisation :

>>> session.query(Model).first()
Model(col='Iuri Diniz')

cela génère cette requête :

SELECT 
    model.id AS model_id, UNHEX(model.col) AS model_col 
FROM model 
LIMIT ? ; -- (1,)

Un peu plus :

>>> session.query(Model).filter(Model.col == "Iuri Diniz").first()
Model(col='Iuri Diniz')

cela génère cette requête :

SELECT 
    model.id AS model_id, UNHEX(model.col) AS model_col 
FROM model 
WHERE model.col = HEX(?) 
LIMIT ? ; -- ('Iuri Diniz', 1)

Extra :colonne personnalisée qui convertit les données à l'aide de types Python

Peut-être souhaitez-vous utiliser de beaux types personnalisés et que vous voulez le convertir entre python et la base de données.

Dans l'exemple suivant, je convertis les UUID entre python et la base de données (le code est basé sur ceci lien ):

import uuid
from sqlalchemy.types import TypeDecorator, VARCHAR

class UUID4(TypeDecorator):
    """Portable UUID implementation

    >>> str(UUID4())
    'VARCHAR(36)'
    """

    impl = VARCHAR(36)

    def process_bind_param(self, value, dialect):
        if value is None:
            return value
        else:
            if not isinstance(value, uuid.UUID):
                return str(uuid.UUID(value))
            else:
                # hexstring
                return str(value)

    def process_result_value(self, value, dialect):
        if value is None:
            return value
        else:
            return uuid.UUID(value)