postgresql: run SQL commands using psql in commandline - postgresql

I have the below three lines to be run in commandline using psql how can i do it.
CREATE DATABASE myproject;
CREATE USER myprojectuser WITH PASSWORD 'password';
GRANT ALL PRIVILEGES ON DATABASE myproject TO myprojectuser;
I just want to pass the sql strings as it is.

As per the docs psql -c 'command;'
psql -c 'CREATE DATABASE myproject;' -c "CREATE USER myprojectuser WITH PASSWORD 'password';" -c 'GRANT ALL PRIVILEGES ON DATABASE myproject TO myprojectuser;'

As #horse suggested -f filename is a better option. You can also put them into a variable using a here document and execute it with the -c option .
read -r -d '' my_sqls << EOM
CREATE DATABASE myproject;
CREATE USER myprojectuser WITH PASSWORD 'password';
GRANT ALL PRIVILEGES ON DATABASE myproject TO myprojectuser;
EOM
psql -c "$my_sqls" # running all the lines.

Related

Restoring the Dump using PostgreSQL's psql

I'm trying to restore the DB from an SQL file using
psql dbname < dumpfile
but after I connect to my DB psql provides a prompt with the name of the database to which psql is currently connected, followed by the string =>. For example:
testdb=>
So how can I enter the command, or which Meta-Command should I use to restore the DB with the psql command? (Already connected to my DB)
psql is the command line client. You cannot call psql when you are already in an interactive psql session.
Either you connect with psql -d testdb in an interactive session and import the dump with \i dumpfile, or you stay on the shell and call psql in a non-interactive session with the dump file as script: psql -d testdb -f dumpfile
you can use \c <database_name>
it will connect you to the desired database
for example
global=> \l
List of databases
Name | Owner | Encoding
test | pgadmins | UTF8
global=> \c test
You are now connected to database "test" as user "user1".
test=>

How to execute "DROP OWNED BY" only if the user exists?

I'm trying to write a bash script that will create a Postgres database, as well as the user and the user privileges to access that database. I'm using Postgres 9.6. I have the below ...
create_db_command="SELECT 'CREATE DATABASE $DB_NAME' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = '$DB_NAME')\gexec"
drop_owned_by_command="DROP OWNED BY $DB_USER;"
drop_role_command="DROP ROLE IF EXISTS $DB_USER;"
create_user_command="create user $DB_USER with encrypted password '$DB_PASS';"
grant_privs_command="grant all privileges on database $DB_NAME to $DB_USER;"
PGPASSWORD=$ROOT_PASSWORD
# This command creates the db if it doesn't already exist
echo "SELECT 'CREATE DATABASE $DB_NAME' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = '$DB_NAME')\gexec" | psql -U$PG_USER
psql -U$PG_USER $DB_NAME -c "$drop_owned_by_command"
psql -U$PG_USER -c "$drop_role_command"
psql -U$PG_USER -c "$create_user_command"
psql -U$PG_USER -c "$grant_privs_command"
The problem is when the script is run the very first time, the command
DROP OWNED BY $DB_USER;
fails because the user does not yet exist. Is there a way to write the above command so that it will only run if the user exists? Similar to DROP USER IF EXISTS ..., but DROP OWNED has no IF EXISTS clause.
You can use a similar technique like you already have for CREATE DATABASE.
In the shell:
drop_owned_by_command="SELECT 'DROP OWNED BY $DB_USER' FROM pg_roles WHERE rolname = '$DB_USER'\gexec"
echo $drop_owned_by_command | psql -U$PG_USER $DB_NAME
The SELECT only returns a row (containing the DDL command) if the role a actually exists. This is in turn executed by the psql command \gexec.
So we have a combination of SQL and psql commands and cannot use psql -c since, quoting the manual on --command:
command must be either a command string that is completely parsable by the server (i.e., it contains no psql-specific features),
or a single backslash command. Thus you cannot mix SQL and psql
meta-commands within a -c option.
Instead, pipe the echo to psql like demonstrated - and like suggested in the manual and in my related answer below and like you already do for CREATE DATABASE.
Related:
Simulate CREATE DATABASE IF NOT EXISTS for PostgreSQL?
Shell script to execute pgsql commands in files

Postgres - npm script to drop/add database

I want to simplify my life and automate the process of adding/dropping my test db via an npm script, however I am running into issues.
Attempt 1:
"drop-db:local": "psql postgres \"drop database blog_db; create database blog_db; \\c blog_db; CREATE EXTENSION \"pgcrypto\";\""
After running this, I keep getting the following error
psql: error: could not connect to server: FATAL: Peer authentication failed for user "drop database blog_db; create database blog_db; \c "
Attempt 2:
changed
psql postgres
to
psql -h localhost -U rm postgres
So this opens the db in my terminal but that seems to ignore some stuff as mentioned in the msg below
psql: warning: extra command-line argument "drop database blog_db; create database blog_db; \c blog_db; CREATE EXTENSION pgcrypto;" ignored
What am I doing wrong?
This is a list of my db users
postgres=# \du
List of roles
Role name | Attributes | Member of
-----------+------------------------------------------------------------+-----------
postgres | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
rm | Superuser, Create DB | {}
db version: psql (12.2 (Ubuntu 12.2-2.pgdg18.04+1))
You need to use -c or -f with your psql command.
As the psql help shows:
-c, --command=COMMAND run only single command (SQL or internal) and exit
-f, --file=FILENAME execute commands from file, then exit
As you are using multiple commands so it will be better of you use -f followed by a sql file name that has all the commands e.g your drop_create_db.sql file can have following code:
drop database blog_db;
create database blog_db;
\c blog_db;
CREATE EXTENSION "pgcrypto";
And you may run this file by using the following command
"drop-db:local": psql -U postgres -d postgres -p 5432 -f /tmp/drop_create_db.sql

Relation does not exist when trying to grant privileges

I'm currently writing a script to build my vagrant box. I got PHP 7 and some other tools installed, as well as PostgreSQL, but when creating the database and trying to grant privileges I'm getting the following error
ERROR: relation "projectname" does not exist
This is my script (the important stuff)
#!/usr/bin/env bash
projectname='projectname'
echo "Initializing database"
sudo apt-get install -y postgresql
sudo -u postgres psql -c "CREATE USER $projectname WITH PASSWORD 'xxxx';"
sudo -u postgres psql -c "CREATE DATABASE $projectname;"
sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON $projectname TO $projectname;"
Everything works until the last step
sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON $projectname TO $projectname;"
When trying this out, I'm getting the above error. I also tried to write it manually
sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON projectname TO projectname;"
Same error.
I also tried to wrap it in quotation marks
sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON 'feedparser' TO 'feedparser';"
sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON \"feedparser\" TO \"feedparser\";"
What exactly am I doing wrong here?
Documentation about GRANT PRIVILEGES says that your version GRANT command is suitable for grant rights to table. If you want to grant rights to database you should use GRANT ALL PRIVILEGES ON DATABASE projectname TO projectname;. Below I show the results of this commands:
postgres=# CREATE USER projectname WITH PASSWORD 'projectname';
CREATE ROLE
postgres=# CREATE DATABASE projectname;
CREATE DATABASE
postgres=# GRANT ALL PRIVILEGES ON projectname TO projectname;
ERROR: relation "projectname" does not exist
postgres=# GRANT ALL PRIVILEGES ON DATABASE projectname TO projectname;
GRANT

How to alter role from command line in postgresql?

I'm trying to build a setup script to automate the development environments creation, but I'm having trouble both trying to pipe or using the -c modifier for psql.
I've tried:
sudo su postgres psql -c "ALTER ROLE postgres WITH password 'pass'"
and
sudo su postgres psql -c "ALTER ROLE postgres WITH password 'pass';"
Both of which say "ALTER: command not found"
I've also tried pipe, but I'm not able to combine it with su correctly
eg: I tried something like
sudo su postgres echo "ALTER ROLE postgres WITH password 'pass'" | psql
But postgres can't execute "echo"
And:
echo "ALTER ROLE postgres WITH password 'pass'" | sudo su psql
Which just doesn't work.
So, my first question is: how can I execute this simple command from a sh file?
And the second one, less related: how can I use different users in the commands chained with pipe?
What's wrong is the lack of -c or --command for su to indicate that the rest of the line is a command.
But su is not needed anyway, because there's already sudo. Do this instead:
sudo -u postgres psql -c "ALTER ROLE postgres WITH password 'pass'"
If you are just like me, make sure you are not running this from:
bash-4.2$
but:
postgres=#