update Postgres psql prompt if semicolon is forgotten - mysql

tldr: Can psql be altered to mimic the MySQL CLI w/ respect to improperly terminated statements?
In the MySQL CLI, when the user fails to properly terminate a statement, the prompt changes to indicate a semicolon was forgotten (indentation, adds ->):
MariaDB[(none)]> describe testing123
->
The Postgres psql CLI prompt doesn't change if a semicolon is forgotten:
zach=# \dt
List of relations
Schema | Name | Type | Owner
--------+------------+-------+-------
public | testing123 | table | zach
(1 row)
zach=# drop table testing123
zach-# ;
DROP TABLE
zach=#
Instead, you just don't see the expected confirmation message (in this case, DROP TABLE). So it's not nothing, but sorta a catch-22 if you don't know what message you should be looking for or if there is even a confirmation message at all for the command you're running.

\set PROMPT2 '-%# '
issue that at the start of your session, or you could add that to your .psqlrc file

I settled on updating .psqlrc to mimic the MySQL CLI by adding: \set PROMPT2 ' -> '
If you want a clue from psql about where your statement went wrong, another option is \set PROMPT2 '[more] %R > ' which tells you:
whether psql expects more input because the command wasn’t terminated yet, because you are inside a /* ... */ comment, or because you are inside a quoted or dollar-escaped string [ThoughtBot blog]

Related

How do you send multiple commands, including an SQL query, via an SSH-Tunnel with Plink? [duplicate]

This question already has answers here:
Escaping parentheses within parentheses for batch file
(4 answers)
Closed 2 years ago.
I am trying to create a Batch file from a Python script which executes Plink to send an SQL-Query to an external Database via SSH. The script would have to activate a batch file with multiple command lines to be sent to the server.
Researching on the internet I have found, that a solution akin to the code snipped below should work.
(
echo command 1
echo command 2
...
) | plink.exe user#hostname -i sshkey.ppk
Entering my commands would yield the following:
(
echo mysql -u admin -pPassword Database
echo INSERT INTO Table VALUES(DEFAULT, (SELECT ID FROM Another_Table WHERE Another_ID = 'foo'), 'bar', 'foobar', 0, 'date', 1);
) | plink.exe user#hostname -i sshkey.ppk
The problem I have is that I am getting the following error: 'bar' can't be processed syntactically at this point. (I am sorry if the translation might be off here, english is not my first language).
I have checked if some special characters have to be escaped, but have not found any conclusive answers. Note, that the first command is correct and works as intended on its own; only the second command seems to be faulty. Would anybody be willing to provide me a solution?
So the answer here is that you need to escape the closing parenthesis TWICE, not only once, and thus have to use three "^" characters. This is because the command inside the brackets is parsed twice and the second "^" needs to be escaped for the first parsing, thus requiring a third character.
See here for details: Escaping parentheses within parentheses for batch file
The code would therefore look like this:
(
echo mysql -u admin -pPassword Database
echo INSERT INTO Table VALUES(DEFAULT, (SELECT ID FROM Another_Table WHERE Another_ID = 'foo'^^^), 'bar', 'foobar', 0, 'date', 1^^^);
) | plink.exe user#hostname -i sshkey.ppk

Add multi line string from variable into mysql with bash

I'm running a python script which returns several lines of text, which I use the following truncate command tr and want to add to my database.
I start here: this removes the unformatted line delimiters.
tr -d '\15\32' < long_text > unixfile.txt
I'm then left with an output which looks like this:
Happy Birthday Stackoverflow
Happy Birthday to you
Happy Birthday Stackoverflow
I use the following command to place this into a variable:
lyrics=$(cat unixfile.txt)
mysql --user=USER --password=PASSWORD --database='DB' --execute='INSERT INTO `song_lyrics` (`id`, `song_id`, `lyrics`, `info`) VALUES ('"'$i'"', '"'$i'"', '"$lyrics"', '0');'
ERROR 1064 (42000) at line 1:
It seems that MySQL is seeing my entire 3 line string (shown above) in three different commands, because the output of the unixfile.txt appears in the error output.
This problem can be solved using the following:
Ensure the long text string is being captured in a file, instead of a variable - then re-capture the file/variable.
lyrics=$(cat unixfile.txt)
mysql --user="$user" --password="$password" --database="$my_db" <<END
use my_db;
INSERT INTO song_lyrics (id, song_id, lyrics, info) VALUES ("$i", "$i", "$lyrics", '0');
END
this method ensures the variable is passed properly.
the only remaining issues would be with various types of punctuation
although this post does not describe this.

Creating an SQL file in BASH

I am trying to create an sql script using bash but I keep getting this line after each iteration of my loop
: command not found
This is the case on Ubuntu as well as OSX.
At this stage I am not executing the sql script, I simply trying to create it. What am I missing so that it will not try to "execute" the query?
The queries are fine when tested in phpmyadmin
I don't understand why would need to set the $PATH variable if I am not executing the actual query, I am just creating the text file.
The code I use is:
SQL="";
cat people.txt | while read line
do
PW="my"$line"db";
DB="test_"$line;
$SQL=$SQL"CREATE DATABASE \`$DB\`;CREATE USER \`$line\`#\`localhost\`;SET PASSWORD FOR \`$line\`#\`localhost\` = PASSWORD(\"$PW\") ;GRANT ALL PRIVILEGES ON $DB.* TO \`$line\`#\`localhost\` IDENTIFIED BY \"$PW\";";
done
echo $SQL > t1.sql;
The list I am using for my imports:
bob123
john123
jane123
The output I am getting is:
./02_setup_mysqldb.sh: line 14: =CREATE DATABASE `test_bob123`;CREATEUSER `bob123`#`localhost`;SET PASSWORD FOR `bob123`#`localhost` = PASSWORD("mybob123db") ;GRANT ALL PRIVILEGES ON test_bob123.* TO `bob123`#`localhost` IDENTIFIED BY "mybob123db";: command not found
./02_setup_mysqldb.sh: line 14: =CREATE DATABASE `test_john123`;CREATE USER `john123`#`localhost`;SET PASSWORD FOR `john123`#`localhost` = PASSWORD("myjohn123db") ;GRANT ALL PRIVILEGES ON test_john123.* TO `john123`#`localhost` IDENTIFIED BY "myjohn123db";: command not found
There's an error in your variable assignment, it should be:
SQL=$SQL"CREATE DATABASE...
Note the missing $ in front of the variable name - variables don't need $ in front of the name when values are assigned.
Notes:
1.The assignment to SQL variable is incorrect, just change to SQL="$SQL...", just remove the $ character.
2.When you do cat people.txt | while read LINE, you are ignoring the last line, being necessary to have a blank line after the last line.
3.Your script has a large string concatenation in one line, just create variables to make it more readable.
Finally, code:
#!/bin/bash
while read line
do
PW="my${line}db"
DB="test_$line"
create_database="CREATE DATABASE \`$DB\`;\n"
create_user="CREATE USER \`$line\`#\`localhost\`;\n"
change_password="SET PASSWORD FOR \`$line\`#\`localhost\` = PASSWORD(\"$PW\");\n"
grant_privileges="GRANT ALL PRIVILEGES ON $DB.* TO \`$line\`#\`localhost\` IDENTIFIED BY \"$PW\";\n"
SQL="${SQL}${create_database}${create_user}${change_password}${grant_privileges}"
done < people.txt
echo -e ${SQL} > t1.sql

Mysql LOAD DATA from Powershell with variable

I try to insert the data from a csv file into a mysql database using a powershell script. When using a (dummy) variable in the LOAD DATA query I run into troubles.
Reproducible example:
Create a Mysql database and table with
CREATE DATABASE loadfiletest;
USE loadfiletest;
CREATE TABLE testtable (field1 INT, field2 INT DEFAULT 0);
Create a csv file named loadfiletestdata.csv containing
1,3
2,4
Create the powershell script (don't forget to change the db password and possibly the username)
[system.reflection.assembly]::LoadWithPartialName("MySql.Data")
$mysqlConn = New-Object -TypeName MySql.Data.MySqlClient.MySqlConnection
$mysqlConn.ConnectionString = "SERVER=localhost;DATABASE=loadfiletest;UID=root;PWD=pwd"
$mysqlConn.Open()
$MysqlQuery = New-Object -TypeName MySql.Data.MySqlClient.MySqlCommand
$MysqlQuery.Connection = $mysqlConn
$MysqlQuery.CommandText = "LOAD DATA LOCAL INFILE 'C:/path/to/files/loadfiletestdata.csv' INTO TABLE loadfiletest.testtable FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '""' LINES TERMINATED BY '\r\n' (field1, field2)"
$MysqlQuery.ExecuteNonQuery()
Put everything in the folder C:/path/to/files/ (should also be your path in the powershell script) and run the script. This populates the table testtable with
field1 field2
1 3
2 4
as one would expect. This implies that quotes and such are like they should be. Each time the script is executed, those values are inserted in the table. Now, when I replace in the one but last line of the powershell script (field1, field2) by (field1, #dummy), I would expect that the values
field1 field2
1 0
2 0
are inserted into the table. However, I receive the error
Exception calling "ExecuteNonQuery" with "0" argument(s): "Fatal error encountered during command execution."
At C:\path\to\files\loadfiletest.ps1:8 char:1
+ $queryOutput = $MysqlQuery.ExecuteNonQuery()
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : MySqlException
When running the query with #dummy from a mysql client it works. Also the syntax looks the same to me as what can be found in the mysql manual (somewhere in the middle of the page, look for #dummy).
A few further experiment that I did, suggest that any LOAD DATA query containing a variable #whatever gives the error.
So the questions:
Why doesn't it work?
Is there a way to execute a LOAD DATA query with (dummy) variables from powershell?
If not, is there an elegant workaround?
Obvious workarounds are creating an intermediate csv file according to the layout of the table or creating an intermediate table matching the layout of the csv file. However that seems ugly and cumbersome for something that imho should "just work".
Note: The present question is a follow up and generalization of this question. I chose to start a new one since replacing the old content would make the answers already given obsolete and adding the content of this question would make the old question veeeeery long and full of useless sidetracks.
I know this is old, but I had the same problem and I found the solution here:
http://blog.tjitjing.com/index.php/2009/05/mysqldatamysqlclientmysqlexception-parameter-id-must-be-defined.html
Quoting from the above blog:
"Starting from version 5.2.2 of the Connector you should add the Allow User Variables=True Connection String Setting in order to use User Defined Variables in your SQL statements.
Example of Connection String:
Database=testdb;Data Source=localhost;User Id=root;Password=hello;Allow User Variables=True"
Thank you for down-voting my answer.

Using shell script to insert data into remote MYSQL database

I've been trying to get a shell(bash) script to insert a row into a REMOTE database, but I've been having some trouble :(
The script is meant to upload a file to a server, get a URL, HASH, and a file size, connect to a remote mysql database, and insert the data into an existing table. I've gotten it working until the remote MYSQL database bit.
It looks like this:
#!/bin/bash
zxw=randomtext
description=randomtext2
for file in "$#"
do
echo -n *****
ident= *****
data= ****
size=` ****
hash=`****
mysql --host=randomhost --user=randomuser --password=randompass randomdb
insert into table (field1,field2,field3) values('http://www.example.com/$hash','$file','$size');
echo "done"
done
I'm a total noob at programming so yeah :P
Anyway, I added the \ to escape the brackets as I was getting errors. As it is right now, the script is works fine until connects to the mysql database. It just connects to the mysql database and doesn't do the insert command (and I don't even know if the insert command would work in bash).
PS: I've tried both the mysql commands from the command line one by one, and they worked, though I defined the hash/file/size and didn't have the escaping "".
Anyway, what do you guys think? Is what I'm trying to do even possible? If so how?
Any help would be appreciated :)
The insert statement has to be sent to mysql, not another line in the shell script, so you need to make it a "here document".
mysql --host=randomhost --user=randomuser --password=randompass randomdb << EOF
insert into table (field1,field2,field3) values('http://www.site.com/$hash','$file','$size');
EOF
The << EOF means take everything before the next line that contains nothing but EOF (no whitespace at the beginning) as standard input to the program.
This might not be exactly what you are looking for but it is an option.
If you want to bypass the annoyance of actually including your query in the sh script, you can save the query as .sql file (useful sometimes when the query is REALLY big and complicated). This can be done with simple file IO in whatever language you are using.
Then you can simply include in your sh scrip something like:
mysql -u youruser -p yourpass -h remoteHost < query.sql &
This is called batch mode execution. Optionally, you can include the ampersand at the end to ensure that that line of the sh script does not block.
Also if you are concerned about the same data getting entered multiple times and your rdbms getting inconsistent, you should explore MySql transactions (commit, rollback, etc).
Don't use raw SQL from bash; bash has no sane facility for sanitizing the data beforehand. Generate a CSV file and upload that instead.