Passando argumentos para o psql


10

Estou executando um script plpgsql no Postgres 8.3 - gostaria de passar argumentos para esse script via psql. Atualmente, estou executando o script como:

psql -d database -u user -f update_file.sql 

Me deparei com este link que explica a variável de ambiente PGOPTIONS, mas isso não funciona para argumentos "personalizados". ou seja, recebo um erro porque a configuração não está listada no arquivo postgres.conf.

-bash-3.2$ export PGOPTIONS='--pretend=true'
-bash-3.2$ psql -d my_db -f update_database.sql
psql: FATAL:  unrecognized configuration parameter "pretend"

Alguma outra ideia? Idealmente, gostaria de evitar variáveis ​​de ambiente ...


Eu acho que você está procurando o -vargumento do psql.
Dez

Eu tentei isso - para recuperá-lo no script, estou chamando "SELECT current_setting ('fingir') INTO _result" - sem sucesso.
Jmoney38

Respostas:


5

Estritamente falando, não existe um "script plpgsql" - PL / pgSQL é a linguagem procedural padrão do PostgreSQL. É um script SQL ou uma função / procedimento plpgsql. Seu exemplo parece indicar um script SQL.

Você pode criar uma função plpgsql (ou sql) (do lado do servidor ) , que aceita qualquer número de argumentos. É muito simples, desde que os argumentos sejam values. Fica um pouco mais complicado se os argumentos incluem identificadores. Então você terá que usar PL / pgSQL com SQL dinâmico e EXECUTE.

O PL / pgSQL é pré-instalado por padrão no PostgreSQL 9.0 ou posterior. Você precisa instalá-lo uma vez por banco de dados no Postgres 8.3, no entanto:

CREATE LANGUGAGE plpgsql;

Falando da versão: você deve considerar a atualização para uma versão atual do PostgreSQL. A v8.3 já é muito antiga e está em fim de vida no início de 2013.

Como você parece ter um script SQL pronto, demonstrarei uma função SQL. Função fictícia simples com dois argumentos inteiros:

CREATE OR REPLACE FUNCTION func(int, int)
    LANGUAGE sql RETURNS void AS 
$func$
    UPDATE tbl1 SET col1 = $1 WHERE id = $2;
    UPDATE tbl2 SET col1 = $1 WHERE id = $2;
$func$;

Você pode encontrar muitos exemplos mais sofisticados de plpgsql aqui no dba.SE ou no SO .

Você pode chamar esta função e entregar parâmetros em um script de shell: Exemplo básico para uma chamada em um script de shell que usa parâmetros de entrada para parâmetros inteiros (sem aspas simples em torno do valor necessário):

psql mydb -c "SELECT func($1, $2)"

Ou com qualquer tipo de dados:

psql mydb -c "SELECT func2('$1'::text, '$2'::numeric)"

-cexecuta uma sequência de comandos e sai. Mais sobre argumentos de linha de comando do psql no manual .


Obrigado pela resposta - eu estou realmente ciente do plpgsql - Este script ao qual estou me referindo é um arquivo que contém várias funções. Eu tenho uma função "principal" no sentido de programação orientada a C. As duas últimas linhas do script / arquivo são 1) chamando a função "principal" e 2) descartando a função. Portanto, nesta configuração, eu basicamente tenho um script independente que pode ser executado para fazer o trabalho (psql -f). Eu gosto do seu ponto de chamar uma função com o "aplicativo args" via psql -c. Provavelmente vou seguir esse caminho, porque não posso seguir o caminho de adicionar valores ao arquivo postgres.conf.
Jmoney38

5

Para adicionar outra funcionalidade para -v... Se você estiver tentando adicionar a cotação, adicione-a na linha de comando:

psql -v action="'drop'"

e isso executará o código para:

select * where :action;

O mesmo que

select * where 'drop';

4

Tente -v:

$ psql -U postgres -v something=\'blah-blah\'
psql (9.1.3)
Type "help" for help.

postgres=# select :something;
 ?column?
----------
 blah-blah
(1 row)

Se você deseja usar current_settinge SETou setval, é necessário anexar uma linha postgresql.confpara adicionar a opção.


2

Da minha experiência, desreffing uma variável psql dentro de uma declaração plpgsql, como em CREATE FUNCTION BEGIN ou DO BEGIN, resulta em um erro de sintaxe:

/tmp $ psql -U jmindek -v action=drop
psql (9.3.4)
Type "help" for help.

jmindek=# select :'action';
 ?column? 
----------
 drop
(1 row)

jmindek=# DO $$ BEGIN RAISE INFO 'The value in variable action is (%)',:x; END $$;     
ERROR:  syntax error at or near ":"
LINE 1: ... RAISE INFO 'The value in variable action is (%)',:x; END $$...

Minha solução é criar uma tabela temporária com uma única coluna e armazenar o valor nela. Esta tabela temporária é acessível via plpgsql e, portanto, posso passar variáveis ​​psql usadas nos blocos DO.

 ~ $ psql -v action=drop
psql (9.3.4)
Type "help" for help.

jmindek=# create temporary table actions (type text);                                                             CREATE TABLE
jmindek=# insert into actions values (:'action');                                                                 INSERT 0 1
jmindek=# do $$                                                                                                   declare                                                                                                            action_type text := null;                                                                                        begin                                                                                                               select type from actions into action_type;                                                                        raise info 'Hello, the action is (%)',action_type;                                                              end $$;
INFO:  Hello, the action is (drop)
DO
jmindek=#

Para usar variáveis ​​psql adicionais nas declarações CREATE FUNCTION ou DO, você pode criar uma coluna por variável necessária.


0

Isso não é muito elegante, mas funciona (pseudocódigo):

cat <<EOF
   UPDATE tablename SET field=$arg1 WHERE field = $arg2;
EOF | psql database

0

Essa abordagem fornecerá a resolução total em tempo de execução dos env vars ... assim que seu script definir antecipadamente todas as variáveis ​​de shell abaixo, ele funcionará ( foi executado milhares de vezes em diferentes dbs e hosts ):

    -- start run.sh

       # 01 create / modify the app user
       sql_script="$pgsql_scripts_dir/01.create-qto-app-user.pgsql"
       PGPASSWORD="${postgres_db_useradmin_pw:-}" psql -q -t -X -w -U "${postgres_db_useradmin:-}" \
          -h $postgres_db_host -p $postgres_db_port \
          -v ON_ERROR_STOP=1 \
          -v postgres_db_user_pw="${postgres_db_user_pw:-}" \
          -v postgres_db_name="${postgres_db_name:-}" \
          -f "$sql_script" "${postgres_db_name:-}" > "$tmp_log_file" 2>&1
       ret=$?
       cat "$tmp_log_file" ; cat "$tmp_log_file" >> $log_file # show it and save it
       test $ret -ne 0 && sleep 3
       test $ret -ne 0 && doExit 1 "pid: $$ psql ret $ret - failed to run sql_script: $sql_script !!!"
    -- stop run.sh

    -- start fun.sql
            DO
            $do$
            BEGIN
               IF NOT EXISTS (
                  SELECT
                  FROM   pg_catalog.pg_roles
                  WHERE  rolname = 'usrqtoapp') THEN
                     CREATE ROLE usrqtoapp WITH PASSWORD ':postgres_db_user_pw' LOGIN ;
               END IF;
            END
            $do$;
            ALTER ROLE usrqtoapp WITH PASSWORD  :'postgres_db_user_pw' LOGIN ;

    -- eof run.sql
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.