PostgresSql Query
SELECT json_data FROM employee where json_data -> 'employee' #> '{"name":"Aman"}'
This query works fine when run in postgres. But when run with jdbctemplate, it throws an error.
Java Code
String sql="SELECT json_data FROM employee where json_data -> 'employee' #> '{\"name\":\"?\"}'";
List<Map<String, Object>> emp = jdbcTemplate.queryForList(sql,param);
On encountering the last line of the code,it throws an error:-
The column index is out of range: 1, number of columns: 0.; nested exception is org.postgresql.util.PSQLException.
It is not able to substitute the '?' placeholder.
Related
Found the issue:
SqlKata compiler was transforming the column names into string literals, so that was returned when a matching column was not located.
Updating the queries to use brackets instead of quotes resolved the issue.
Created github issue here regarding the issue: https://github.com/sqlkata/querybuilder/issues/655
Initial post contents retained below.
I was doing some unit testing against a Sqlite database, ensuring that my methods for creation and reading all work fine (They do). But One of the tests failed, and I am absolutely confused as to why.
The Sqlite db consists of a single table, defined below:
TableName: Students
Columns: ID (Primary Key), FirstName (string), LastName (string)
The following query works properly, returning the 'FirstName' value within the db:
"SELECT \"FirstName\" FROM \"Students\" WHERE \"ID\" = #p0"
The following query I would expect would cause an exception, since the column name does not exist:
"SELECT \"UnknownCol\" FROM \"Students\" WHERE \"ID\" = #p0"
Instead, I receive the value 'UnknownCol' as a string result.
For reference, I’m using the same method (which processes a DbCommand object) to perform the same thing at against an Excel file via OledbCommand. That function produces an exception (not a helpful one, but atleast it error our). So I know the underlying method works.
Why would sqlite return the name of a column that doesn't exist in that query?
Additional Info Edit:
Using an OledbConnection to read from an Excel sheet using the same method results in the following exception when I request an invalid column within the query (which while it doesn't tell you its a bad query due to invalid column name, atleast it errors out):
Exception Message: No value given for one or more required parameters.
Full code chain:
//db object has a method that returns a SqliteConnection, and has a 'Compiler' property that returns the SqlKata.Compiler object for SqlLite
var qry = new SqlKata.Query("Students").Select("UnknownCol").Where("ID",1);
return GetValue(db.GetConnection(), qry, db.Compiler);
//Results in the following sql:
"SELECT \"UnknownCol\" FROM \"Students\" WHERE \"ID\" = 1"
---
public static object GetValue(DbConnection connection, Query query, SqlKata.Compilers.Compiler compiler)
{
using (var cmd = connection.CreateCommand(query, compiler))
{
connection.Open();
try
{
return cmd.ExecuteScalar();
}
finally
{
connection.Close();
}
}
}
public static DbCommand CreateCommand(this DbConnection connection, SqlKata.Query query, SqlKata.Compilers.Compiler compiler)
{
if (connection is null) throw new ArgumentNullException(nameof(connection));
if (compiler is null) throw new ArgumentNullException(nameof(compiler));
var result = compiler.Compile(query ?? throw new ArgumentNullException(nameof(query)));
var cmd = connection.CreateCommand();
cmd.CommandText = result.Sql;
foreach (var p in result.NamedBindings)
{
_ = cmd.AddParameter(p.Key, p.Value);
}
return cmd;
}
public static DbParameter AddParameter(this DbCommand command, string name, object value)
{
var par = command.CreateParameter();
par.ParameterName = name;
par.Value = value;
command.Parameters.Add(par);
return par;
}
It's legal to select a string litteral in SQL. This is a valid SQL query which returns the mentioned string:
SELECT 'UnknownCol';
It will return a single row containing this string litteral.
The following query is similar
SELECT 'UnknownCol' FROM students;
For each row in your table, it will return a row with this string litteral.
Here is an example on a test table with a few rows in a test database:
sqlite> select 'a string litteral' from test;
a string litteral
a string litteral
a string litteral
a string litteral
a string litteral
sqlite> select count(1) from test;
5
sqlite>
If you want to query a specific column name instead of a string litteral you have to remove the '' characters around the column name.
Then this is the result with an undefined column:
sqlite> select unknowncol from test;
Parse error: no such column: unknowncol
select unknowncol from test;
^--- error here
sqlite>
or for a defined column:
sqlite> select id from test;
1
2
3
4
6
sqlite>
I would like to get two columns like SoccerStatus, SoccerDate from the SoccerAvailability in SQLite database into a list where SoccerDate="Today" using LINQ query ? I have tried the below query, but its throws exception, I need CurrentDate alone, no time is needed in my query.
List<SoccerAvailability> myList = (from x in conn.Table<SoccerAvailability>().Where(x => x.CurrentDate == DateTime.Now.ToString("ddMMyyyy")) select x).ToList();
Unhandled Exception:
SQLite.SQLiteException: no such function: tostring
convert the current date to a string before you execute your query
var currentDate = DateTime.Now.ToString("ddMMyyyy");
List<SoccerAvailability> myList = (from x in conn.Table<SoccerAvailability>().Where(x => x.CurrentDate == currentDate) select x).ToList();
Ok I am new to sqlite and python in general so please be nice =)
I have a simple dictionary -
time = data[0]['timestamp']
price = data[0]['price']
myprice = {'Date':time,'price':price}
myprice looks like this (time is a timestamp) -
{'Date': 1553549093, 'price': 1.7686}
I now want to add the data to sqlite3 database...so I created this -
#Create database if not exist...
db_filename = 'mydb_test.db'
connection = sqlite3.connect(db_filename)
#Get a SQL cursor to be able to execute SQL commands...
cursor = connection.cursor()
#Create table
sql = '''CREATE TABLE IF NOT EXISTS TEST
(PID INTEGER PRIMARY KEY AUTOINCREMENT,
DATE TIMESTAMP,
PRICE FLOAT)'''
#Now lets execute the above SQL
cursor.execute(sql)
#Insert data in sql
sql2 = ("INSERT INTO GBPCAD VALUES (?,?)", [(myprice['Date'],myprice['price'])])
cursor.execute(sql2)
cursor.commit()
connection.close()
But when executing this code I get ValueError: operation parameter must be str
What am I doing wrong?
Pass the arguments of the insert statement in execute():
sql2 = "INSERT INTO GBPCAD (DATE, PRICE) VALUES (?,?)"
cursor.execute(sql2, (myprice['Date'], myprice['price']))
Also include in the insert statement the names of the columns.
How to use DateTime with SQLite via the SQLProvider type-provider?
SQLite doesn't really have a date and time datatype (see Data types) and stores dates as text. I can pass a date string and query it, and get back a string. So this works, where Date1 in table3 was stored as a string:
query {
for r in table3 do
select (r.Date1)
} |> Seq.toList
val it : string list =
["2016/06/09 0:00:00"; "2016/06/05 0:00:00"; "2016/06/04 0:00:00";
"2016/06/12 0:00:00"; "2016/06/10 0:00:00"; "2016/06/06 0:00:00";
It is also possible to store Date1 as a DateTime, and in another table I have it as such. That is even though SQLite doesn't understand DateTime, I can create a column with the DateTime data type, and I can store a DateTime value in it. I can extract this value in C# (or LinqPad) for example. But when I try to access it via the type provider (the same type provider that let me store the DateTime value), it gives the following error:
System.FormatException: String was not recognized as a valid DateTime.
> at System.DateTimeParse.ParseExactMultiple(String s, String[] formats, DateTimeFormatInfo dtfi, DateTimeStyles style)
at System.Data.SQLite.SQLiteConvert.ToDateTime(String dateText, SQLiteDateFormats format, DateTimeKind kind, String formatString)
at System.Data.SQLite.SQLite3.GetDateTime(SQLiteStatement stmt, Int32 index)
at System.Data.SQLite.SQLite3.GetValue(SQLiteStatement stmt, SQLiteConnectionFlags flags, Int32 index, SQLiteType typ)
at System.Data.SQLite.SQLiteDataReader.GetValue(Int32 i)
at <StartupCode$FSharp-Data-SqlProvider>.$SqlRuntime.DataContext.FSharp-Data-Sql-Common-ISqlDataContext-ReadEntities#153.GenerateNext(IEnumerable`1& next)
at Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1.MoveNextImpl()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at Microsoft.FSharp.Collections.SeqModule.ToArray[T](IEnumerable`1 source)
at FSharp.Data.Sql.Runtime.QueryImplementation.executeQuery(ISqlDataContext dc, ISqlProvider provider, SqlExp sqlExp, List`1 ti)
at FSharp.Data.Sql.Runtime.QueryImplementation.SqlQueryable`1.System-Collections-Generic-IEnumerable`1-GetEnumerator()
at Microsoft.FSharp.Collections.SeqModule.ToList[T](IEnumerable`1 source)
at <StartupCode$FSI_0075>.$FSI_0075.main#()
The difference between the working (type provider) query in table3 and the one with the error in table2 is the data type of the column:
LinqPad correctly sees it as a DateTime in Table2 and this query works there:
var dt2 = new System.DateTime(2016,8,30,0,0,0,DateTimeKind.Local);
Table2
.Where(r => r.Date1 == dt2).Dump();
DateTime type is working as intended with the following versions with SQLProvider 1.0.31 and SQLite 1.0.102:
#if INTERACTIVE
#I #"..\packages\SQLProvider.1.0.31\lib"
#r "FSharp.Data.SqlProvider.dll"
#I #"..\packages\System.Data.SQLite.Core.1.0.102.0\lib\net46"
#r "System.Data.SQLite.dll"
#I #"..\packages\System.Data.SQLite.Linq.1.0.102.0\lib\net46"
#r "System.Data.SQLite.Linq.dll"
#endif
open System
open FSharp.Data.Sql
//open System.Data.SQLite
//open System.Data.SQLite.Linq
[<Literal>]
let connectionString = "Data Source="+ #"C:\tmp\databaseFile.db3"
[<Literal>]
let resolutionPath = __SOURCE_DIRECTORY__ + #"..\..\packages\System.Data.SQLite.Core.1.0.102.0\lib\net46"
type sql = SqlDataProvider<
Common.DatabaseProviderTypes.SQLITE,
connectionString,
ResolutionPath = resolutionPath,
CaseSensitivityChange = Common.CaseSensitivityChange.ORIGINAL>
let ctx = sql.GetDataContext()
let table2 = ctx.Main.Table2 //DateTime
let table3 = ctx.Main.Table3 //Text
How to insert data into table using row mapper?
I am trying this:
Employee user1 = jtemplate.queryForObject("INSERT INTO employee(id, name,salary) VALUES(10,'ABC',12333);",new BeanPropertyRowMapper<Employee>(Employee.class));
It gives me bad SQL grammar error.
But query works in SQL developer. What I am doing wrong?
Exception in thread "main" org.springframework.jdbc.BadSqlGrammarException: StatementCallback; bad SQL grammar [INSERT INTO employee(id, name,salary) VALUES(99,'ABC',12333)]; nested exception is java.sql.SQLSyntaxErrorException: ORA-00900: invalid SQL statement
at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:231)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:73)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:411)
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:466)
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:476)
at com.cts.orm.rowmapper.Test.main(Test.java:29)
Caused by: java.sql.SQLSyntaxErrorException: ORA-00900: invalid SQL statement
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:445)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:389)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:382)
at oracle.jdbc.driver.T4CTTIfun.processError(T4CTTIfun.java:600)
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:450)
at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:192)
at oracle.jdbc.driver.T4C8Odscrarr.doODNY(T4C8Odscrarr.java:98)
at oracle.jdbc.driver.T4CStatement.doDescribe(T4CStatement.java:805)
at oracle.jdbc.driver.OracleStatement.describe(OracleStatement.java:3978)
at oracle.jdbc.driver.OracleResultSetMetaData.<init>(OracleResultSetMetaData.java:55)
at oracle.jdbc.driver.OracleResultSetImpl.getMetaData(OracleResultSetImpl.java:175)
at org.springframework.jdbc.core.BeanPropertyRowMapper.mapRow(BeanPropertyRowMapper.java:240)
at org.springframework.jdbc.core.RowMapperResultSetExtractor.extractData(RowMapperResultSetExtractor.java:93)
at org.springframework.jdbc.core.RowMapperResultSetExtractor.extractData(RowMapperResultSetExtractor.java:60)
at org.springframework.jdbc.core.JdbcTemplate$1QueryStatementCallback.doInStatement(JdbcTemplate.java:455)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:400)
... 3 more
NamedParameterJdbcTemplate does what you want:
namedParameterJdbcTemplate.update(
"INSERT INTO employee(id, name, salary) VALUES (:id, :name, :salary)",
new BeanPropertySqlParameterSource(Employee.class));
removing the semi colon at the end of the statement should solve the problem use it like this. when using the jdbc templates it is not good to use semicolon at the end of sql statements
Employee user1 = jtemplate.queryForObject("INSERT INTO employee(id, name,salary) VALUES(10,'ABC',12333)",new BeanPropertyRowMapper<Employee>(Employee.class));
try using it like
jtemplate.update("INSERT INTO Employee(ID, NAME, Salary) VALUES (?, ?, ?)",
new Object[] { employee.getId(), employee.getName(), employee.getSalary() });
i am using this and it works correctly and displays no errors
Try this:
jdbcTemplate.update("INSERT INTO employee(id, name,salary) VALUES(?,?,?)", 10, "ABC", 12333);