Custom JPA repository query with spring boot - sql

I am trying to execute a custom query through jpa repository interface like this:
#Query(
value = "SELECT (TRIM(TYPE_NAME) ||'.'|| TRIM(NAME)) AS NAMES FROM ?1",
nativeQuery = true)
public List<String> getNamesFromView( String viewName);
I want to pass the name of the table to fetch from, dynamically by the user.
I am getting runtime exception
nested exception is org.hibernate.exception.SQLGrammarException: could not prepare statement
If I hardcode the table name, this is working fine

Table names can not be parametarized, that's the reason why your getting error.
The bind variables exist primarily for performance reasons, parametarized query will be compiled only once by DB and for later subsequent executions same compiled version is used.
The value for the placeholder would be a string.
So SELECT (TRIM(TYPE_NAME) ||'.'|| TRIM(NAME)) AS NAMES FROM ?1 with xyz as the table name would actually translates to
SELECT (TRIM(TYPE_NAME) ||'.'|| TRIM(NAME)) AS NAMES FROM 'xyz', which is invalid SQL
As you mentioned you have entityManager's instance, you can execute the query like below:
entityManager.query(String.format("SELECT (TRIM(TYPE_NAME) ||'.'|| TRIM(NAME)) AS NAMES FROM %s", viewName));

Related

Can I use a query parameter in a table name?

I want to do something along the lines of:
SELECT some_things
FROM `myproject.mydataset.mytable_#suffix`
But this doesn't work because the parameter isn't expanded inside the table name.
This does work, using wildcard tables:
SELECT some_things
FROM `myproject.mydataset.mytable_*`
WHERE _TABLE_SUFFIX = #suffix
However, it has some problems:
If I mistype the parameter, this query silently returns zero rows, rather than yelling at me loudly.
Query caching stops working when querying with a wildcard.
If other tables exist with the mytable_ prefix, they must have the same schema, even if they don't match the suffix. Otherwise, weird stuff happens. It seems like BigQuery either computes the union of all columns, or takes the schema of an arbitrary table; it's not documented and I didn't look at it in detail.
Is there a better way to query a single table whose name depends on a query parameter?
Yes, you can, here's a working example:
DECLARE tablename STRING;
DECLARE tableQuery STRING;
##get list of tables
CREATE TEMP TABLE tableNames as select table_name from nomo_nausea.INFORMATION_SCHEMA.TABLES where table_name not in ('_sdc_primary_keys', '_sdc_rejected', 'fba_all_order_report_data');
WHILE (select count(*) from tableNames) >= 1 DO
SET tablename = (select table_name from tableNames LIMIT 1);
##build dataset + table name
SET tableQuery = CONCAT('nomo_nausea.' , tablename);
##use concat to build string and execute
EXECUTE IMMEDIATE CONCAT('SELECT * from `', tableQuery, '` where _sdc_deleted_at is not null');
DELETE FROM tableNames where table_name = tablename;
END WHILE;
In order to answer your stated problems:
Table scanning happens in FROM clause, in WHERE clause happens filtering [1] thus if WHERE condition is not match an empty result would be returned.
"Currently, Cached results are not supported when querying with wildcard" [2].
"BigQuery uses the schema for the most recently created table that matches the wildcard as the schema" [3]. What kind of weird stuff you have faced in your use case? "A wildcard table represents a union of all the tables that match the wildcard expression" [4].
In BigQuery parameterized queries can be run, But table names can not be parameterized [5]. Your wildcard solution seems to be the only way.
You can actually use tables as parameters if you use the Python API, but it's not documented yet. If you pass the tables as parameters through a formatted text string vs. a docstring, your query should work.
SQL example:
sql = "SELECT max(_last_updt) FROM `{0}.{1}.{2}` WHERE _last_updt >= TIMESTAMP(" +
"CURRENT_DATE('-06:00'))".format(project_id, dataset_name, table_name)
SQL in context of Python API:
bigquery_client = bigquery.Client() #setup the client
query_job = bigquery_client.query(sql) #run the query
results = query_job.result() # waits for job to complete
for row in results:
print row

Create SQLite view as a union with source table name field [duplicate]

I want to write a query that examines all the tables in an SQLite database for a piece of information in order to simplify my post-incident diagnostics (performance doesn't matter).
I was hoping to write a query that uses the sqlite_master table to get a list of tables and then query them, all in one query:
SELECT Name
FROM sqlite_master
WHERE Type = 'table' AND (
SELECT count(*)
FROM Name
WHERE conditions
) > 0;
However when attempting to execute this style of query, I receive an error no such table: Name. Is there an alternate syntax that allows this, or is it simply not supported?
SQLite is designed as an embedded database, i.e., to be used together with a 'real' programming language.
To be able to use such dynamic constructs, you must go outside of SQLite itself:
cursor.execute("SELECT name FROM sqlite_master")
rows = cursor.fetchall()
for row in rows:
sql = "SELECT ... FROM {} WHERE ...".format(row[0])
cursor.execute(sql)

SqlQuery and SqlFieldsQuery

it looks that SqlQuery only supports sql that starts with select *? Doesn't it support other sql that only select some columns like
select id, name from person and maps the columns to the corresponding POJO?
If I use SqlFieldQuery to run sql, the result is a QueryCursor of List(each List contains one record of the result). But if the sql starts with select *, the this list's contents would be different with field query like:
select id,name,age from person
For the select *, each List is constructed with 3 parts:
the first elment is the key of the cache
the second element is the pojo object that contains the data
the tailing element are the values for each column.
Why was it so designed? If I don't know what the sql that SqlFieldsQuery runs , then I need additional effort to figure out what the List contains.
SqlQuery returns key and value objects, while SqlFieldsQuery allows to select specific fields. Which one to use depends on your use case.
Currently select * indeed includes predefined _key and _val fields, and this will be improved in the future. However, generally it's a good practice to list fields you want to fetch when running SQL queries (this is true for any SQL database, not only Ignite). This way your code will be protected from unexpected behavior in case schema is changed, for example.

Is it possible to use a returned column value as a table name in an SQLite query?

I want to write a query that examines all the tables in an SQLite database for a piece of information in order to simplify my post-incident diagnostics (performance doesn't matter).
I was hoping to write a query that uses the sqlite_master table to get a list of tables and then query them, all in one query:
SELECT Name
FROM sqlite_master
WHERE Type = 'table' AND (
SELECT count(*)
FROM Name
WHERE conditions
) > 0;
However when attempting to execute this style of query, I receive an error no such table: Name. Is there an alternate syntax that allows this, or is it simply not supported?
SQLite is designed as an embedded database, i.e., to be used together with a 'real' programming language.
To be able to use such dynamic constructs, you must go outside of SQLite itself:
cursor.execute("SELECT name FROM sqlite_master")
rows = cursor.fetchall()
for row in rows:
sql = "SELECT ... FROM {} WHERE ...".format(row[0])
cursor.execute(sql)

Worklight SQL Adapter - can't pass a param to IN clause

i want to pass a list of values as a string to an IN clause in my Worklight 6.1 SQL Adapter:
SQL_Query= select * from USERS where name in (?);
i pass the following string as a param:
'john','mike','joe'
The call to the SQL procedure failed with the following error:
java.sql.SQLException: Invalid column index
So my question is: how to deal with IN params in a SQL Adapter?
The point was to use a length-variable parameter, as i don't know how many people to retrieve (the number depends on context).
Actually, it's not possible to do such with a PreparedStatement (JDBC). It can only be used with a Statement. Unfortunately, Worklight API does not propose statement but only preparedstatement.
The following is working, but i have to limit my search to 3 people:
SQL_Query= select * from USERS where name in (?,?,?);
or (dirty):
SQL_Query= select * from USERS where name = ? or name = ? or name = ?;