Как я могу воспользоваться преимуществами sqlite манифеста типизации / типа с использованием sqlalchemy? - PullRequest
1 голос
/ 15 июня 2010

Мне нравится идея манифеста типизации sqlite / сходство типов:

http://www.sqlite.org/datatype3.html

По сути, если я установлю сходство столбца как «числовое», оно будет пригружать целые числа или числа с плавающей запятой, чтобы хранить их как таковые, но все же позволит мне сохранять строки, если захочу. Мне кажется, это лучший тип по умолчанию для столбца, когда я заранее не уверен, какие данные я хочу сохранить в нем.

итак, я иду:

metadata = MetaData()
new_table = Table(table_name, metadata )
for col_name in column_headings:
    new_table.append_column(Column(col_name, 
                                   sqlite.NUMERIC, #this should duck-type numbers but can handle strings as well
                                   primary_key=col_name in primary_key_columns))
new_table.create(self.engine, checkfirst=False)

но когда я пытаюсь сохранить некоторые строковые значения, например, "abc" в таблице, sqlalchemy падает:

  File "[...]\sqlalchemy\processors.py", line 79, in to_float
    return float(value)
ValueError: invalid literal for float(): abc

Бу, шипение. Итак, есть ли способ убедить sqlalchemy позволить sqlite печатать? возможно я могу использовать тип из sqlalchemy.types вместо sqlachemy.dialects.sqlite?

[edit:] для бонусных баллов: мне нужно иметь возможность доступа к таблицам через самоанализ / размышление. так что какой-то способ работы с meta.reflect () был бы великолепен! ; -)

Ответы [ 2 ]

1 голос
/ 15 июня 2010

ОК, вот что я придумала:

Определите пользовательский тип столбца, как указано в http://www.sqlalchemy.org/docs/reference/sqlalchemy/types.html#custom-types

, комбинация документации и некоторые методы проб и ошибок дали мнеthis:

class MyDuckType(sqlalchemy.types.TypeDecorator):
    """
    SQLALchemy custom column type, designed to let sqlite handle the typing 
    using 'numeric affinity' which intelligently handles both numbers and strings
    """
    impl = sqlite.NUMERIC

    def bind_processor(self, dialect):
        #function for type coercion during db write
        return None #ie pass value as-is, let sqlite do the typing

    def result_processor(self, dialect, coltype):
        #function for type coercion during db read
        return None #ie pass value as sqlite has stored it, should be ducktyped already

    def process_bind_param(self, value, dialect):
        #any changes to an individual value before store in DN
        return value

    def process_result_value(self, value, dialect):
        #any changes to an individual value after retrieve from DB
        return value

    def copy(self):
        #not quite sure what this is for
        return MyDuckType()

Текущий тип диалекта sqlalchemy возвращает to_float в bind_processor, поэтому я и раньше получал ошибки.imvvho, это ошибка.

для моих бонусных баллов: ручная установка типа столбца в MyDuckType в моем коде metadata.reflect ():

def get_database_tables(engine):
    meta = MetaData()
    meta.reflect(bind=engine)
    tables = meta.raw_tables
    for tbl in tables.values():
        for col in tbl.c:
            col.type = MyDuckType()
    return tables

, кажется, работает для меня.Есть предложения / улучшения?

0 голосов
/ 03 июля 2010

По сути, если я установлю сходство столбца как «числовое», оно будет использовать целочисленные значения типа float для хранения их как таковых, но все же позволит мне сохранять строки, если захочу.

Если вы вообще не объявляете тип столбца, SQLite позволит вам хранить любой тип без выполнения преобразований.Это может быть лучшим выбором, если вы хотите отличить 123 от '123'.

...