Syntax error at end of input in PostgreSQL - postgresql

I have used the next SQL statement in both MySQL and PostgreSQL, but it fails in PostgreSQL
db.Query(`SELECT COUNT(*) as N FROM email WHERE address = ?`, email)
with this error:
pq: F:"scan.l" M:"syntax error at end of input" S:"ERROR" C:"42601" P:"50" R:"scanner_yyerror" L:"993"
What's the problem? The error messages in PostgreSQL are very cryptic.

You haven't provided any details about the language/environment, but I'll try a wild guess anyway:
MySQL's prepared statements natively use ? as the parameter placeholder, but PostgreSQL uses $1, $2 etc. Try replacing the ? with $1 and see if it works:
WHERE address = $1
The error messages in PostgreSQL are very cryptic.
In general, I've found that Postgres error messages are better than competing products (ahem, MySQL and especially Oracle), but in this instance you've managed to confuse the parser beyond sanity. :)

In golang for queries we have use
MySQL uses the ? variant
PostgreSQL uses an enumerated $1, $2, etc bindvar syntax
SQLite accepts both ? and $1 syntax
Oracle uses a :name syntax

You are using Go right?
try:
db.Query(`SELECT COUNT(*) as N FROM email WHERE address = $1`, email)

In my case, it was due to using a -- line comment where the program that was responsible for interacting with the database read in the multiple lines of my query all as one giant line. This meant that the line comment corrupted the remainder of the query. The fix was to use a /* block comment */ instead.

Related

Why getting error syntax error at end of input [duplicate]

I have used the next SQL statement in both MySQL and PostgreSQL, but it fails in PostgreSQL
db.Query(`SELECT COUNT(*) as N FROM email WHERE address = ?`, email)
with this error:
pq: F:"scan.l" M:"syntax error at end of input" S:"ERROR" C:"42601" P:"50" R:"scanner_yyerror" L:"993"
What's the problem? The error messages in PostgreSQL are very cryptic.
You haven't provided any details about the language/environment, but I'll try a wild guess anyway:
MySQL's prepared statements natively use ? as the parameter placeholder, but PostgreSQL uses $1, $2 etc. Try replacing the ? with $1 and see if it works:
WHERE address = $1
The error messages in PostgreSQL are very cryptic.
In general, I've found that Postgres error messages are better than competing products (ahem, MySQL and especially Oracle), but in this instance you've managed to confuse the parser beyond sanity. :)
In golang for queries we have use
MySQL uses the ? variant
PostgreSQL uses an enumerated $1, $2, etc bindvar syntax
SQLite accepts both ? and $1 syntax
Oracle uses a :name syntax
You are using Go right?
try:
db.Query(`SELECT COUNT(*) as N FROM email WHERE address = $1`, email)
In my case, it was due to using a -- line comment where the program that was responsible for interacting with the database read in the multiple lines of my query all as one giant line. This meant that the line comment corrupted the remainder of the query. The fix was to use a /* block comment */ instead.

sql injection. What is the difference between " 'OR 1=1 #" and " ' OR 1=1 -- "?

There are several version of sql injection method, but I don't know why there are slightly difference exactly.
How can I know the difference among the environments?
TL;DR — the # form is usable only on MySQL. The -- form is usable on any brand of SQL.
Both # and -- are used to introduce comments. The purpose of both in an SQL injection attack is to make sure the rest of the line is ignored.
SELECT * FROM MyTable WHERE name = '$unsafe_variable' AND id = 12345
An SQL injection attack might be able to interfere with the $unsafe_variable but the query would still be limited to the one row with a specific id. But what if the SQL injection attack could effectively neutralize the second term?
SELECT * FROM MyTable WHERE name = '' OR 1=1 -- ' AND id = 12345
^^^^^^^^^^^^
Anything past the -- is a comment, so it will be ignored by the query. It doesn't matter that the comment contains content that looks like more SQL syntax.
The -- is the only comment syntax that is specified by standard ANSI SQL, and all SQL implementations should support this syntax.
But most if not all SQL implementations support other comment syntax, because developers are more familiar with using it. Notably the /* comment */ syntax, because it allows multi-line comments, and it's supported by many other programming languages.
Both -- comment or /* comment */ are supported by all SQL brands I checked:
MySQL
Oracle 10g
Microsoft SQL Server
PostgreSQL
SQLite
IBM DB2
Firebird
Informix
The # comment syntax is supported only by MySQL.
The { comment } syntax is supported only by Informix.
simply it is different syntax between DB engines “ OR 1=1 #” it works with mysql DB because comment there is using # but “ OR 1=1 — ” works with sql server BD becsuase comment there using -- for more details about sql injection methods samples check this link

Can I get Ecto to log raw SQL?

I am building an Ecto query like this:
from item in query,
where: like(item.description, ^"%#{text}%")
I'm concerned that this allows SQL injection in text. Before trying to fix that, I want to see how the query is actually sent to the database.
If I inspect the query or look at what is logged, I see some SQL, but it's not valid.
For instance, inspecting the query shows me this:
{"SELECT i0.\"id\", i0.\"store_id\", i0.\"title\", i0.\"description\"
FROM \"items\" AS i0 WHERE (i0.\"description\" LIKE $1)",
["%foo%"]}
When I pass this query to Repo.all, it logs this:
SELECT i0."id", i0."store_id", i0."title", i0."description"
FROM "items" AS i0 WHERE (i0."description" LIKE $1) ["%foo%"]
But if I copy and paste that into psql, PostgreSQL gives me an error:
ERROR: 42P02: there is no parameter $1
It seems as though Ecto may actually be doing a parameterized query, like this:
PREPARE bydesc(text) AS SELECT i0."id",
i0."store_id", i0."title", i0."description"
FROM "items" AS i0 WHERE (i0."description" LIKE $1);
EXECUTE bydesc('foo');
If so, I think that would prevent SQL injection. But I'm just guessing that this is what Ecto does.
How can I see the actual SQL that Ecto is executing?
Ecto uses only prepared statements. When using ecto query syntax, introducing SQL injection is not possible. The query syntax verifies at compile-time that no SQL injection is possible.
Showing exactly the queries executed might be difficult because of couple reasons:
Postgrex (and hence Ecto) uses the postgresql binary protocol (instead of the most common, but less efficient, text protocol), so the PREPARE query never actually exists as a string.
For most cases all you would see would be one initial PREPARE 64237612638712636123(...) AS ... and later a lot of EXECUTE 64237612638712636123(...) which isn't that helpful. Trying to relate one to another would be horrible.
From my experience most software of that kind, use prepare statements and log them instead of raw queries, since it's much more helpful in understanding the behaviour of the system.
Yes, that is the exact SQL that is being executed by Ecto (it uses prepared queries through the db_connection package internally) and no SQL injection is possible in that code. This can be verified by turning on logging of all executed SQL queries by changing log_statement to all in postgresql.conf:
...
log_statement = 'all'
...
and then restarting PostgreSQL and running a query. For the following queries:
Repo.get(Post, 1)
Repo.get(Post, 2)
this is logged:
LOG: execute ecto_818: SELECT p0."id", p0."title", p0."user_id", p0."inserted_at", p0."updated_at" FROM "posts" AS p0 WHERE (p0."id" = $1)
DETAIL: parameters: $1 = '1'
LOG: execute ecto_818: SELECT p0."id", p0."title", p0."user_id", p0."inserted_at", p0."updated_at" FROM "posts" AS p0 WHERE (p0."id" = $1)
DETAIL: parameters: $1 = '2'

Is it possible to get explain plan with bind variables in DB2?

With Oracle, the syntax is:
explain plan for
select * from users WHERE user_name = :user_name AND user_dob = :user_dob
Is it possible to do the same in DB2? The statement below does not seem to work.
explain plan with snapshot for
select * from users WHERE user_name = :user_name AND user_dob = :user_dob
Thank you.
The answer may depend on your DB2 version and platform, which you chose not to share with us for some reason. This works fine on DB2 for LUW (v10.1, but I'm sure it would work with v9.7 and up):
$ db2 "explain plan with snapshot for select * from syscat.schemata where schemaname = :blah"
DB20000I The SQL command completed successfully.
You may want to try replacing named parameter markers with questions marks.
Apparently, the answer is in the IBM website, but it is not easy to make sense of.
http://publib.boulder.ibm.com/infocenter/db2luw/v9/index.jsp?topic=%2Fcom.ibm.db2.udb.admin.doc%2Fdoc%2Fr0000952.htm
FOR explainable-sql-statement
Specifies the SQL statement to be explained. This statement can be any
valid CALL, Compound SQL (Dynamic), DELETE, INSERT, MERGE, SELECT,
SELECT INTO, UPDATE, VALUES, or VALUES INTO SQL statement. If the
EXPLAIN statement is embedded in a program, the
explainable-sql-statement can contain references to host variables
(these variables must be defined in the program). Similarly, if
EXPLAIN is being dynamically prepared, the explainable-sql-statement
can contain parameter markers.
But it does not tell you what "parameter markers" are, so you have to go and search for it.

DB2 Equivalent to SQL's GO?

I have written a DB2 query to do the following:
Create a temp table
Select from a monster query / insert into the temp table
Select from the temp table / delete from old table
Select from the temp table / insert into a different table
In MSSQL, I am allowed to run the commands one after another as one long query. Failing that, I can delimit them with 'GO' commands. When I attempt this in DB2, I get the error:
DB2CLI.DLL: ERROR [42601] [IBM][CLI Driver][DB2] SQL0199N The use of the reserved
word "GO" following "" is not valid. Expected tokens may include: "".
SQLSTATE=42601
What can I use to delimit these instructions without the temp table going out of scope?
GO is something that is used in MSSQL Studio, I have my own app for running upates into live and use "GO" to break the statements apart.
Does DB2 support the semi-colon (;)? This is a standard delimiter in many SQL implementations.
have you tried using just a semi-colon instead of "GO"?
This link suggests that the semi-colon should work for DB2 - http://www.scribd.com/doc/16640/IBM-DB2
I would try wrapping what you are looking to do in BEGIN and END to set the scope.
GO is not a SQL command, it's not even a TSQL command. It is an instruction for the parser. I don't know DB2, but I would imagine that GO is not neccessary.
From Devx.com Tips
Although GO is not a T-SQL statement, it is often used in T-SQL code and unless you know what it is it can be a mystery. So what is its purpose? Well, it causes all statements from the beginning of the script or the last GO statement (whichever is closer) to be compiled into one execution plan and sent to the server independent of any other batches.