Why this error happens with groovy sql jdbc builder? - sql

Why this code does not get the string for sql.execute("$y")?
import groovy.sql.Sql
def sql = Sql.newInstance("jdbc:mysql://localhost", "root","password", "com.mysql.jdbc.Driver")
def y= "select * from table"
table(sql,y)
def table(sql,x){
println ("$x")
sql.execute("$x")
}
The Output:
'select * from table'
Sep 02, 2017 3:49:39 PM groovy.sql.Sql$AbstractQueryCommand execute
WARNING: Failed to execute: ? because: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ''select * from table'' at line 1
Caught: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ''select * from table'' at line 1
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ''select * from table'' at line 1

sql.execute("$x")
in groovy double-quoted string with $expression inside is actually a groovy.lang.GString
so you are calling this method: Sql.execute(Gstring query)
this method replaces all $expressions in groovy string with ?
creates prepared statement and pass all $expressions as parameters of this prepared statement
in your case "$x" converted to "?" and executed.
Mysql tries to parse this query "?" and gives you an error:
MySQLSyntaxErrorException: You have an error in your SQL syntax
if you change your code to this:
sql.execute("$x" as String)
You'll beat this problem but you will face another one: you can't select rows with method Sql.execute(...)
examples with parameters
The following commands are equivalent:
def rows = sql.rows("select * from mytable where fieldA = $value")
def rows = sql.rows("select * from mytable where fieldA = ?", [value] )
def parms = [VALUE: value]
def rows = sql.rows(parms, "select * from mytable where fieldA = :VALUE")
all of them will be executed as a prepared statement "select * from mytable where fieldA = ?"

This problem solved by the method shown below.
import groovy.sql.Sql
def sql = Sql.newInstance("jdbc:mysql://localhost", "root","password", "com.mysql.jdbc.Driver")
def y= "select * from tablename"
table(sql,y)
def table(sql,x){
println (x)
sql.execute(x)
}
"select * from table" query can't work. Because table is a keyword in sql.
This simple change works without any errors. Thanks for your responses.

Related

SQL error when using format() function with pyodbc in Django

I want to execute a command using pyodbc in my Django app. When I do simple update with one column it works great:
cursor.execute("UPDATE dbo.Table SET attr = 1 WHERE id = {}".format(id))
However when I try to use a string as a column value it throws error:
cursor.execute("UPDATE dbo.Table SET attr = 1, user = '{}' WHERE id = {}".format(id, str(request.user.username)))
Here's error message:
('42S22', "[42S22] [Microsoft][ODBC SQL Server Driver][SQL Server]Invalid column name 'Admin'. (207) (SQLExecDirectW)")
Suprisingly this method works:
cursor.execute("UPDATE dbo.Table SET attr = 1, user = 'Admin' WHERE id = {}".format(id))
What seems to be the problem? Why is sql mistaking column value for its name?
As mentioned above, you have your arguments backwards, but if you're going to use cursor.execute(), the far more important thing to do is use positional parameters (%s). This will pass the SQL and values separately to the database backend, and protect you from SQL injection:
from django.db import connection
cursor = connection.cursor()
cursor.execute("""
UPDATE dbo.Table
SET attr = 1,
user = %s
WHERE id = %s
""", [
request.user.username,
id,
])
You've got your format arguments backwards. You're passing id to user, and username to the id WHERE clause.

How to pass in parameters to a SQL statement in Python

I have a Python script that is calling a function that executes a SQL select statement but I keep getting errors that the Token ? was not valid. How do I pass in variables so that they work with the SQL statement? Here is my code:
def get_jde_udc_info(connection,product_code,userCode,librTable):
c1=connection.cursor()
length=c1.execute("select dtcdl, dtcnum from ?",(librTable) + " where dtsy=?",(product_code) + " and dtrt=?",(userCode))
length=c1.fetchall() # <-- Using the .fetchone method from the Python cursor class that will return a single record or None if no more rows are available
print(length)
Here is the function call in my script:
get_jde_udc_info(connection,"41","s1","testctl.f0004")
I like to use %
Like:
"SELECT field1, field2 FROM %s WHERE email = '%s'" % ('table', 'johndoe#gmail.com')

R Pass required variable from ODBC/HANA connection to sql statement

I have a table I am trying to call with my usual method
sql <- 'SELECT TOP 10 *
FROM "_SYS_BIC"."data-path.self-service.DOIP/table_name"'
df <- dbGetQuery(jdbcConnection, sql)
and receive the error
Error in .verify.JDBC.result(r, "Unable to retrieve JDBC result set for ", :
Unable to retrieve JDBC result set for SELECT TOP 10 *
FROM "_SYS_BIC"."data-path.self-service.DOIP/table_name" (SAP DBTech JDBC: [2048]: column store error: search table error: [34023] Instantiation of calculation model failed;exception 306106: Undefined variable: $$IP_ExtractionWeekFrom$$. Variable is marked as required but not set in the query)
I've been trying to insert IP_ExtractionWeekFrom into the sql statement with a where clause with no luck
param1 <- 201943
sql <- 'SELECT TOP 10 *
FROM "_SYS_BIC"."ccf-edw.self-service.DOIP/R_CA_B_DemandPlan" where
"$$IP_ExtractionWeek$$" = ?'
SpringVisit <- dbGetQuery(jdbcConnection, sql, param1)
I've tried the term surrounded by the "$$" and without, and both with and without "$$" sourrounded in quotes and not. Usually am met with an "invalid column name" error.
Is this supposed to be called with something other than a where clause?
Consider maintaining your working Tableau query with the integration of parameters in R with properly handling of double quotes for identifiers and single quotes for literals.
Additionally, parameterization is not supported with the old ('PLACEHOLDER'= ('<varname>', <varvalue>)) syntax.
Instead, as explained in How to escape sql injection from HANA placeholder use the PLACEHOLDER."<varname>" => ? syntax.
param1 <- 201943
sql <- "SELECT TOP 10 *
FROM \"_SYS_BIC\".\"ccf-edw.self-service.DOIP/R_CA_B_DemandPlan\"(
PLACEHOLDER.\"$$IP_ExtractionWeekFrom$$\", ?),
PLACEHOLDER.\"$$IP_ExtractionWeekTo$$\",?)
)\"_SYS_BIC\".\"ccf-edw.self-service.DOIP/R_CA_B_DemandPlan\"
WHERE (1 <> 0)"
SpringVisit <- dbGetQuery(jdbcConnection, sql, param1, param1)
Additionally, if your JDBC already connects to the schema_SYS_BIC, use the synonymous qualifier :: as original query in order to reference package and calculation view:
sql <- "SELECT TOP 10 *
FROM \"ccf-edw.self-service.DOIP::R_CA_B_DemandPlan\"(
PLACEHOLDER.\"$$IP_ExtractionWeekFrom$$\", ?),
PLACEHOLDER.\"$$IP_ExtractionWeekTo$$\", ? )
)\"ccf-edw.self-service.DOIP::R_CA_B_DemandPlan\"
WHERE (1 <> 0)"

Passing a parameter to a sql query using pyodbc failing

I have read dozens of similar posts and tried everything but I still get an error message when trying to pass a parameter to a simple query using pyodbc. Apologies if there is an answer to this elsewhere but I cannot find it
I have a very simple table:
select * from Test
yields
a
b
c
This works fine:
import pyodbc
import pandas
connection = pyodbc.connect('DSN=HyperCube SYSTEST',autocommit=True)
result = pandas.read_sql("""select * from Test where value = 'a'""",connection,params=None)
print(result)
result:
value
0 a
However if I try to do the where clause with a parameter it fails
result = pandas.read_sql("""select * from Test where value = ?""",connection,params='a')
yields
Error: ('01S02', '[01S02] Unknown column/parameter value (9001) (SQLPrepare)')
I also tried this
cursor = connection.cursor()
cursor.execute("""select * from Test where value = ?""",['a'])
pyodbcResults = cursor.fetchall()
and still received the same error
Does anyone know what is going on? Could it be an issue with the database I am querying?
PS. I looked at the following post and the syntax there in the first part of answer 9 where dates are passed by strings looks identical to what I am doing
pyodbc the sql contains 0 parameter markers but 1 parameters were supplied' 'hy000'
Thanks
pandas.read_sql(sql, con, index_col=None, coerce_float=True, params=None, parse_dates=None, columns=None, chunksize=None)[https://pandas.pydata.org/pandas-docs/stable/generated/pandas.read_sql.html]ΒΆ
params : list, tuple or dict, optional, default: None
example:
cursor.execute("select * from Test where value = %s",['a'])
or Named arguments example:
result = pandas.read_sql(('select * from Test where value = %(par)s'),
db,params={"par":'p'})
in pyodbc write parms directly after sql parameter:
cursor.execute(sql, *parameters)
for example:
onepar = 'a'
cursor.execute("select * from Test where value = ?", onepar)
cursor.execute("select a from tbl where b=? and c=?", x, y)

dynamically set the db in a sql query

I try to run the same query in several dbs in mysql:
def m='xxx'
def dbs = ['DB05DEC05','DB06DEC06','DB07DEC07','DB08DEC08','DB09DEC09','DB10DEC10']
def sql =Sql.newInstance("jdbc:mysql://localhost:3306", "root","", "org.gjt.mm.mysql.Driver")
dbs.each{
db-> sql.eachRow("select * from ${db}.mail where mid=$m", { println "\t$db ${it.mid}"} );
}
This gives an error:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''DBJAN05DEC05'.mail where mid='xxx'
Groovy apparently does some custom stuff with quotes and asks you not to use quotes in the sql (notice mid=$m, if you use mid='$m' it warns you against using the quotes).
The problem is that in the first $ I dont know want quotes at all, the quotes are the problem...
groovy 1.7 on vista.
thanks
editing: I have found a similar question, but it does not have an accepted answer either... Groovy GString issues
The problem is that the SQL query method sees the GString, with its embedded variable references, and turns each reference into a ? in a prepared statement.
So:
sql.query("select * from table where col = ${value}")
... is equivalent to:
sql.query("select * from table where col = ?", [ value ])
But also:
sql.query("select * from ${db}.table where col = ${value}")
is equivalent to:
sql.query("select * from ?.table where col = ?", [ db, value ])
... which fails at the DB layer because the select statement is not valid.
The obvious workaround is to use the explicit prepared statement version of query().
dbs.each{ db->
sql.eachRow("select * from ${db}.mail where mid=?", m, {
println "\t$db ${it.mid}"
});
}
However, the Sql class gives you an expand() method, that appears to be designed for this purpose.
dbs.each{ db ->
sql.eachRow(
"select * from ${Sql.expand(db)}.mail where mid=${m}",
{ println "\t$db ${it.mid}"} );
}