Рецепт sqlalchemy 'SELECT * INTO ## temptable' не компилируется с литеральными связями - PullRequest
0 голосов
/ 08 ноября 2018

для моего конкретного случая использования мне нужно:

SELECT * INTO ## tmp FROM some_table

Конструкция сервера SQL, и мне нужно, чтобы полностью скомпилированный оператор (с включенными встроенными параметрами) был показан человеку в командной строке до того, как оператор фактически будет передан в базу данных.

Я использовал следующий рецепт (слегка подправлен для синтаксиса SQL Server): https://groups.google.com/forum/#!msg/sqlalchemy/O4M6srJYzk0/B8Umq9y08EoJ

и пока он работает, я не могу заставить его отображать встроенные параметры.

Вот фактический код:

from sqlalchemy.sql import Select, table, column
from sqlalchemy.ext.compiler import compiles

class SelectInto(Select):
    def __init__(self, columns, into, *arg, **kw):
        super(SelectInto, self).__init__(columns, *arg, **kw)
        self.into = into

@compiles(SelectInto)
def s_into(element, compiler, **kw):
    text = compiler.visit_select(element)
    text = text.replace('FROM', f'INTO {element.into} \nFROM')
    return text


employee = table('employee', column('id'), column('name'))
select_into = SelectInto([employee.c.id, employee.c.name], "##tmp").select_from(employee).where(employee.c.id.in_([1, 3, 6]))
print(select_into.compile(compile_kwargs={'literal_binds': True}).string)

Однако, это возвращает:

SELECT employee.id, employee.name 
INTO ##tmp 
FROM employee 
WHERE employee.id IN (:id_1, :id_2, :id_3)

вместо:

SELECT employee.id, employee.name 
INTO ##tmp 
FROM employee 
WHERE employee.id IN (1, 3, 6)

Я потратил так много времени, пытаясь понять, почему, и я просто понятия не имею. Этот класс SelectInto подклассирует класс Select sqlalchemy, и этот класс без каких-либо проблем компилирует операторы со встроенными литералами связывания.

Почему здесь не работает?

Любая помощь будет очень признательна

1 Ответ

0 голосов
/ 08 ноября 2018

Переслать аргументы ключевого слова в ваш пользовательский компилятор:

@compiles(SelectInto)
def s_into(element, compiler, **kw):
    text = compiler.visit_select(element, **kw)
    text = text.replace('FROM', f'INTO {element.into} \nFROM')
    return text

В настоящее время visit_select() не видит аргумент literal_binds, поэтому вместо него по умолчанию компилируются заполнители.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...