psycopg2 генерирует неопределенную ошибку строки в кавычках в долларах или около "$ body $" - PullRequest
0 голосов
/ 09 ноября 2018

Я пытаюсь создать версию миграции alembic для создания пользовательской функции на сервере PostgreSQL версии 10.2, однако скрипт продолжает выдавать ошибку:

sqlalchemy.exc.ProgrammingError: (psycopg2.ProgrammingError) unterminated dollar-quoted string at or near "$body$
                select string_agg(convert_to(coalesce(r[2], length(length(r[1])::text) || length(r[1])::text || r[1]), 'SQL_ASCII'), '"
    LINE 6:         as $body$
                       ^
     [SQL: "\n        create or replace function naturalsort(text)\n          returns bytea\n          language sql\n          immutable strict\n        as $body$ \n            select string_agg(convert_to(coalesce(r[2], length(length(r[1])::text) || length(r[1])::text || r[1]), 'SQL_ASCII'), '\x00') from regexp_matches($1, '0*([0-9]+)|([^0-9]+)', 'g') r; \n        $body$;\n    "] (Background on this error at: http://sqlalche.me/e/f405)

Скрипт, который я запускаю:

def upgrade():
    conn = op.get_bind()

    conn.execute('DROP FUNCTION IF EXISTS "naturalsort"')

    conn.execute("""
        create or replace function naturalsort(text)
          returns bytea
          language sql
          immutable strict
        as $body$ 
            select string_agg(convert_to(coalesce(r[2], length(length(r[1])::text) || length(r[1])::text || r[1]), 'SQL_ASCII'), '\x00') from regexp_matches($1, '0*([0-9]+)|([^0-9]+)', 'g') r; 
        $body$;
    """)

Код должен предусматривать естественную сортировку столбцов и является копией / вставкой из родиевой жабы .

Поскольку строки в кавычках в долларах - это способ переписать строковые константы, альтернативой может быть (обратите внимание на двойные одинарные кавычки в соответствии с документацией postgresql: «Чтобы включить символ одинарных кавычек в строковую константу, напишите два соседние одинарные кавычки, например, лошадь Дайанны. Обратите внимание, что это не то же самое, что символ двойной кавычки (")."):

conn.execute("""
    create or replace function naturalsort(text)
      returns bytea
      language sql
      immutable strict
    as 'select string_agg(convert_to(coalesce(r[2], length(length(r[1])::text) || length(r[1])::text || r[1]), ''SQL_ASCII''), ''\x00'') from regexp_matches($1, ''0*([0-9]+)|([^0-9]+)'', ''g'') r;';
""")

однако это выдает похожую ошибку:

sqlalchemy.exc.ProgrammingError: (psycopg2.ProgrammingError) unterminated quoted string at or near "'select string_agg(convert_to(coalesce(r[2], length(length(r[1])::text) || length(r[1])::text || r[1]), ''SQL_ASCII''), ''"
LINE 6:         as 'select string_agg(convert_to(coalesce(r[2], leng...
                   ^
 [SQL: "\n        create or replace function naturalsort(text)\n          returns bytea\n          language sql\n          immutable strict\n        as 'select string_agg(convert_to(coalesce(r[2], length(length(r[1])::text) || length(r[1])::text || r[1]), ''SQL_ASCII''), ''\x00'') from regexp_matches($1, ''0*([0-9]+)|([^0-9]+)'', ''g'') r;';\n    "] (Background on this error at: http://sqlalche.me/e/f405)

Странно то, что эти запросы прекрасно выполняются в pgAdmin, и alembic, похоже, генерирует допустимый SQL (alembic upgrade: --sql):

DROP FUNCTION IF EXISTS "naturalsort";

create or replace function naturalsort(text)
          returns bytea
          language sql
          immutable strict
        as $body$
            select string_agg(convert_to(coalesce(r[2], length(length(r[1])::text) || length(r[1])::text || r[1]), 'SQL_ASCII'), '') from regexp_matches($1, '0*([0-9]+)|([^0-9]+)', 'g') r;
        $body$;;

UPDATE alembic_version SET version_num='ad99fdcb28bc' WHERE alembic_version.version_num = 'ff00ac684617';

COMMIT;

Есть какие-нибудь подсказки, почему psycopg2 продолжает выдавать ошибку unterminated dollar-quoted string at or near "$body$?

Ответы [ 2 ]

0 голосов
/ 05 июня 2019
def upgrade():
    op.execute('DROP FUNCTION IF EXISTS "naturalsort"')

    op.execute("""
      create or replace function naturalsort(text)
      returns bytea
      language sql
      immutable strict
    as $my_body$
        select string_agg(convert_to(coalesce(r[2], length(length(r[1])::text) || length(r[1])::text || r[1]), 'SQL_ASCII'), '') from regexp_matches($1, '0*([0-9]+)|([^0-9]+)', 'g') r;
    $my_body$;;
    """)


def downgrade():
    op.execute('DROP FUNCTION IF EXISTS "naturalsort"')

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

SELECT * FROM public.requirement ORDER BY naturalsort(eid) asc

Использование комментария PvdL о my_body сработало частично, он выдаст синтаксическую ошибку, если я добавлю '\x00' там, где сейчас пустая строка (после SQL_ASCII)

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

$body - это псевдоним, который не может содержать $, замените $body$ на имя типа my_body, и оно должно работать

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