Запрос Python Postgres с блокировкой транзакции по одному соединению - PullRequest
0 голосов
/ 02 ноября 2018

В настоящее время у меня есть два отдельных заявления, которые передаются в Postgres (Greenplum). 1. Обрезает таблицу 2. загружает данные, используя \ copy

myStr="export PGPASSWORD=" + dbPass + "; psql -h " + dbHost + " -p " + dbPort + " -d " + dbName + " -U " + dbUser + " -c " + "\"" + "truncate table " + dbTable + ";\""
print(myStr)
subprocess.call(myStr,shell=True)
myStr="export PGPASSWORD=" + dbPass + "; psql -h " + dbHost + " -p " + dbPort + " -d " + dbName + " -U " + dbUser + " -c " + "\"" + "\\" + "copy " + dbTable + " from " + "'" + csvfile + "' with " + copyOpts + ";" + "select count(*) from " + dbTable + ";\""
print(myStr)
subprocess.call(myStr,shell=True)

Иногда при загрузке возникают ошибки, но усечение уже произошло, поэтому я пытаюсь выполнить два оператора в одном соединении, чтобы можно было таким образом поместить блок транскрипции (BEGIN ... COMMIT;), если загрузка данных не удалась произойдет откат до того, как произойдет усечение.

Я попробовал следующий метод:

myStr="export PGPASSWORD=" + dbPass + "; psql -h " + dbHost + " -p " + dbPort + " -d " + dbName + " -U " + dbUser + " -c " + "\"" + "truncate table " + dbTable + ";" + " \\" + "copy " + dbTable + " from " + "'" + csvfile + "' with " + copyOpts + ";" + "select count(*) from " + dbTable + ";\""
print(myStr)

Что разрешает команду:

export PGPASSWORD=abcde; 
psql -h abcde.testserver.corp 
-p 5432 -d namem -U username -c 
"truncate table schema.example; 
\copy schema.example from 
'/home/testing/schema/schema.example_export.csv' 
with header null as '' escape 'off' delimiter E',' ;
select count(*) from schema.example;"

Однако я получаю сообщение об ошибке:

ОШИБКА: синтаксическая ошибка в или около "\"

Полагаю, это связано с тем, что команды \ должны находиться на отдельной строке.

Есть ли способ разбить команду на отдельные строки, чтобы я мог выполнить все команды в одном соединении?

1 Ответ

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

Проблема в том, что вы не можете отделить команды обратной косой черты от других команд, если вы используете опцию -c. Вы можете отправить свои команды через STDIN на psql, используя echo:

export PGPASSWORD=abcde;
echo "truncate table schema.example; 
\copy schema.example from '/home/testing/schema/schema.example_export.csv' with header null as '' escape 'off' delimiter E',' ;
select count(*) from schema.example;" | psql -h abcde.testserver.corp -p 5432 -d namem -U username

Это немного неуклюже. Лучше использовать subprocess.Popen

theCommand = """truncate table schema.example; 
\copy schema.example from 
'/home/testing/schema/schema.example_export.csv' 
with header null as '' escape 'off' delimiter E',' ;
select count(*) from schema.example;"""
theProcess = subprocess.Popen("psql -h abcde.testserver.corp -p 5432 -d namem -U username", 
    stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
theOutput, theErrors = theProcess.communicate(input = theCommand)

Но лучше всего избегать команд оболочки и использовать адаптер базы данных, такой как PyGreSQL.

...