Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the correct way to make SQLalchemy store strings as lowercase?

I'm using SQLAlchemy to talk to my database. Because not many people will be using my application (at least initially), I figure SQLite is the quickest/easiest back end.

I've got a User, and it has a unique ID that's string based, e.g. [email protected], or Mr. Fnord. I don't care what format the id is in - just that it's unique. However, I want to this to be a case-insensitive uniqueness. So Mr. Fnord and mr. fNoRd would be equivalent.

Apparently there's a COLLATE setting on the schema you can use, but (at least with sqlite) it doesn't seem to be straignt forward. My solution was to use properties on the class to lowercase everything before it went to the table, but that seemed brittle/hackish.

Are properties the best way to handle lowercasing everything, or is there a better way to make things case insensitive via SQLAlchemy/SQLite?

like image 576
Wayne Werner Avatar asked Dec 27 '12 02:12

Wayne Werner


People also ask

How to convert string into lower case?

Java String toLowerCase() Method The toLowerCase() method converts a string to lower case letters. Note: The toUpperCase() method converts a string to upper case letters.

How to turn a string to lower case in Python?

In Python, lower() is a built-in method used for string handling. The lower() method returns the lowercased string from the given string. It converts all uppercase characters to lowercase. If no uppercase characters exist, it returns the original string.

What is lower() in Python?

The lower() method returns a string where all characters are lower case.

What is PickleType?

PickleType. Holds Python objects, which are serialized using pickle. SchemaType. Mark a type as possibly requiring schema-level DDL for usage.


1 Answers

I haven't tried this personally, but perhaps you could use a custom comparator operator? I.e.

class CaseInsensitiveColumnComparator(ColumnProperty.Comparator):
    def __eq__(self, other):
        return func.lower(self.__clause_element__()) == func.lower(other)

This way, your ID can be stored in any case, but will compare as lowercase.


Another idea - augment sqlalchemy.types.Text, and use that for your ID.

import sqlalchemy.types as types

class LowerCaseText(types.TypeDecorator):
    '''Converts strings to lower case on the way in.'''

    impl = types.Text

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

class User(Base):
    __tablename__ = 'user'
    id = Column(LowerCaseText, primary_key=True)
    ...
like image 68
Alex L Avatar answered Nov 14 '22 21:11

Alex L