IntelliJ IDEA: inject language with String.format() - intellij-idea

I have an SQL query which unfortunately cannot be written as a prepared statement because it has variable column names. Because of this, I have to build my SQL using String formatting.
The language (SQL dialect) I'm using is PostgreSQL, but because I have String.format() in my queries, IntelliJ complains about syntax errors in my code.
public class Example {
public String getUniqueFeatureCountSqlQuery(String feature, Long sourceUserId) {
//language=PostgreSQL
return String.format("SELECT COUNT(DISTINCT targetUserId), %s FROM userComments GROUP BY %s WHERE userId = %d",
feature, feature, sourceUserId);
}
}
How do I make IntelliJ recognize this string properly? It should know that it is PostgreSQL which is first formatted by String.format().

Thanks to #WillHumphreys I found a solution via youtrack.
You have to go the the User Parameters settings under Tools -> Database -> User Parameters, or use the find action command.
Then make these changes.
You may also have to use the argument index string format notation (String.format("SELECT %1s ...", ...)) for the parameters to be distinguishable when attempting to alt-enter run the query in the console.

Related

ERROR [37000] [IBM][CLI Driver] CLI0118E Invalid SQL syntax. SQLSTATE=37000

I have a simple SQL statement query that is executed as command from C# code. It is targetting DB2. I created variables for the server/schemas as follows. It throws error.
private const string DB2Query
= #"SELECT Name as Name FROM {Schema}.Application WHERE ID = ?";
I get this error.
ERROR [37000] [IBM][CLI Driver] CLI0118E Invalid SQL syntax. SQLSTATE=37000
However, I don't get that error when executing from SQL as follows:
SELECT Name as Name
FROM MyServer..FOR3.Application
WHERE ID = 'MOM'
To support this, I tried to also do something like below in code, still throws different error.
private const string DB2Query
= #"SELECT Name as Name FROM {ServerName}..{Schema}.Application WHERE ID = ?";
It throws error on this line of code:
DataApplicationBlockHelper<string>.Get(db, dbCommand, Obj);
UPDATE
I found the culprit. It's not replacing the {Schema} placeholder. When I actually removed that from query and placed the schema name, it worked like a charm. It's a .net thing I believe? Can someone please help how to replace {Schema} with a value fetched from web.config?
While I can't really speak to the syntax of DB2 queries themselves, so I'll rely on your assertion that the query itself should work...
What you have in C# is simply a string and nothing more:
private const string DB2Query = #"SELECT Name as Name FROM {Schema}.Application WHERE ID = ?";
Note that there's no need for the # operator in this string definition, so let's simplify:
private const string DB2Query = "SELECT Name as Name FROM {Schema}.Application WHERE ID = ?";
While this string appears intuitively to have a placeholder that can be replaced with a value, if there's no code which does that anywhere then it won't happen. For that you have a few options. For example, you can use a placeholder that string.Format() understands:
private const string DB2Query = "SELECT Name as Name FROM {0}.Application WHERE ID = ?";
And then later in a method somewhere, when you want to use that string, apply the format value to it:
var sql = string.Format(DB2Query, someVariable);
In this case someVariable (which doesn't even need to be a variable and could be a string literal) would be used to replace the placeholder in the string.
Or, if you want to keep the named placeholder, you can potentially replace it manually:
private const string DB2Query = "SELECT Name as Name FROM {Schema}.Application WHERE ID = ?";
and later in a method:
var sql = DB2Query.Replace("{Schema}", someVariable);
This would observably accomplish the same thing, perhaps with an extremely minor performance difference.
You could also take advantage of both approaches by using the more recent language feature of string interpolation. This would use the $ operator to apply format placeholders in place directly. I don't think you can use this in a const, it's more for a local variable. Something like this:
var sql = $"SELECT Name as Name FROM {someVariable}.Application WHERE ID = ?";
This would still perform the same replacement, putting someVariable where the placeholder is, it's just using a more concise syntax than a call to string.Format(). One thing to note about this syntax is that it makes it look more like this interpolation is happening directly in-place on the string. It's still a multi-step process behind the scenes, which is why it likely won't work on a const or on class members at all (and should I imagine produce a compiler error).
Remember that strings are immutable, so any operation you perform which modifies a string would be returning a new string rather than modifying the existing one in place.
In any case, you'll of course also need to apply your query parameter for the ? placeholder. Note that what C# considers to be a placeholder in a string formatting/interpolating operation and what DB2 considers to be a placeholder for a query parameter are two entirely different things which happen at different times in different environments. (One in the .NET runtime, one in the database server's query execution.) But again, I'm relying on your assertion that the database query itself works and the only problem we're focusing on here is the C# string placeholder.

Pass Java List to SQL query Grails

i have a populated list:
def someList=... (string values)
and I want to pass this into a SQL statement to restrict which columns the query selects.
db.rows("select ${someList} from arch_application")
However, I get this error when I try to do so:
There is a ? parameter in the select list. This is not allowed.
Anyone have an ideas? Thanks!
When you pass a GString to Sql.rows, it gets parsed differently than normal in groovy. In particular, it creates a PreparedStatement with replaceable parameters for ${} substitutions. In your case this is probably not what you want. Try forcing the GString to a Java string:
db.rows("select ${someList.join(',')} from arch_application" as String)

Escape dot from GString

I would like to learn how to escape dot in GString so groovy (1.8) does not treat it as a part of an variable inside sql.execute. I have the following code:
Map<String, String> dbSettings = [schemaName:"testSchema"];
String myDbPrefix = dbSetting.schemaName + ".";
sql.execute "DELETE FROM ${myDbPrefix}myTable"
And I got this error:
Ignoring groovy.lang.MissingPropertyException: No such property: myTable for class: java.lang.String
Clearly indicating that . was interpreted as part of variable ${myDbPrefix}.
Does escaping the embedded variable help?
  sql.execute "DELETE FROM ${Sql.expand myDbPrefix}myTable"
I got hit by this problem today. GStrings get handled by a special way in GroovySQL. It's mentioned in the javadoc. It does automatic parameter binding.
Each value in the GString will become a parameter (?) which gets set as a JDBC prepared statement parameter.
What a surprise!
I'm going to fix the problem in my application by subclassing the Sql class and overriding the GString handling with plain ".toString()" .
Documented in Groovy wiki:
GString Use Cases - GSQL Another use case for GString is GSQL where
parameters can be passed into SQL statements using this same mechanism
which makes for a neat way to integrate Groovy with other languages
like SQL. GroovySql then converts the expressions to ? and uses a JDBC
PreparedStatement and passes the values in, preserving their types.
If you explicitly want to coerce the GString to a String you can use
the toString() method. Groovy can also automatically coerce GStrings
into Strings for you.

NHibernate ISQLQuery SetParameter issue

This is probably fairly straightforward but i can't seem to find a reasonable explanation in any documentation.
I'm trying to use an NHibernate.ISQLQuery and using SetResultTransformer() to return a custom set of results from a custom SQL query. Like so:
public virtual IList<T> GetSQLObject<T>(string sql, IDbParameter[] parameters = null)
{
ISQLQuery qry = _sess.CreateSQLQuery(sql);
qry.SetResultTransformer(Transformers.AliasToBean(typeof(T)));
if (parameters != null) {
foreach (IDbParameter parameter in parameters) {
qry.SetParameter(parameter.Name, parameter.Value);
}
}
return qry.List<T>();
}
From looking at the examples, it seems that in the sql query I have to use parameters in the format :param1 instead of #param1 as I would in a standard SQL query. If i use the latter syntax in the query, it throws an error at qry.SetParameter().
Is there a reason why ISQLQuery/NHibernate requires them in this format and won't work with the normal syntax?
SQL Server uses #param, but not every other database does. For example, MySQL uses ?param
NHibernate allows you to swap out 1 database implementation for another with little to no reworking of your DAL. It sets the parameters based on the database you configured when you setup the NH Configuration.
Edit: Also I think :param came about from Hibernate being targeted at Oracle when it was initially developed, since Oracle uses :param
Phil has answered the "why"; so perhaps I can recommend a "how"; why not just add a new extension method to the IDbParameter type (something like .GetNHibernateName() ) that will return the parameter name with the "#" replaced with a ":"; that should be trivial to implement.

VB.NET logical expression evaluator

I need to test a logical expression held in a string to see if it evaluate to TRUE or FALSE.(the strig is built dynamically)
For example the resulting string may contain "'dog'<'cat' OR (1>4 AND 4<6)". There are no variables in the string, it will logically evaluate. It will only contain simple operators = > < >< >= <= and AND , OR and Open and Close Brackets, string constants and numbers. (converted to correct syntax && || etc.)
I currently acheive this by creating a jscipt function and compiling it into a .dll. I then reference the .dll in my VB.NET project.
class ExpressionEvaluator
{
function Evaluate(Expression : String)
{
return eval(Expression);
}
}
Is there a simpler method using built in .NET functions or Lamdba expressions.
I tried the demo out for this project and you might like it over you current method of evaluating. Note, it doesn't use lamdba expressions or any build it .NET methods.
http://web1.codeproject.com/KB/vb/expression_evaluator.aspx?msg=1151870
try out: http://www.codeproject.com/KB/cs/ExpressionEval.aspx
More guidance :http://www.thefreakparade.com/2008/07/evaluating-expressions-at-runtime-in-net-c/
Good one: http://flee.codeplex.com/
Boolean Example which you are looking for : http://flee.codeplex.com/wikipage?title=BooleanExpression&referringTitle=Examples (ignore the variable adding part as you are not looking for variable)