In Dynamic SQL, ScriptDom is finding IF statements, but not UPDATE statements - scriptdom

I'm using TransactSQL.ScriptDom to parse SQL statements. I have rules defined where I want to find a) IF statements and b) UPDATE statements. When I'm looking through non-dynamic SQL, the rules work just fine. However, when I'm looking through dynamic SQL, my code only detects the IF blocks; it does not detect the UPDATE statements.
For instance, this code gets hit in a debugger in both the non-dynamic and dynamic scenarios:
public override void Visit(IfStatement ifStatement)
{
...
}
However, this code does not get hit in any dynamic SQL scenario, and I've also tried using UpdateSpecification:
public override void Visit(UpdateStatement updateStatement)
{
...
}
Now, if I change the code to Visit(TSqlFragment test), the code will get hit, but I only see a node of type AsciiStringLiteral for my UPDATE statement. Is there a better way to get my code to visit an UPDATE statement?

Disregard, this was user error. I had a type-o in my dynamic SQL where I was incorrectly using single-quotes. In other words, I was using this:
#"EXEC('UPDATE dbo.MyTable
SET MyColumn = 'MyValue';');",
... instead of this:
#"EXEC('UPDATE dbo.MyTable
SET MyColumn = ''MyValue'';');",
(I considered deleting this question altogether, but I'll leave it up in case it helps others.)

Related

Querydsl selecting from a subquery runtime exception

I'm stuck on how to select from a subquery using Querydsl on SQL. The code compiles fine, but I'm getting a runtime exception: Undeclared path 'cases'. Add this path as a source to the query to be able to reference it.
The code looks approximately like this:
private ListSubQuery<Integer> getStudyCaseSubQuery(CaseQuery query) {
SQLSubQuery sq = new SQLSubQuery().from(cases);
... stuff happens
return sq.list(cases.id);
}
...
public List<JsonObject> getData(...) {
// Build a common subquery for a bunch of other queries
ListSubQuery<Integer> caseQuery = getStudyCaseSubQuery(...);
// This fails with runtime exception
List<Integer> caseIds = caseQuery.list(Expressions.path(Integer.class, cases, "id"));
}
I can see where the problem is: I can't find a way to specify an alias for the subquery apart from a whole table, which isn't the case here. There's a bunch of examples that use Alias and Path but nothing that matches in the tests or tutorials that I can adapt to this problem. Although I know SQL pretty well, aliasing tables and columns appear entirely different in Querydsl, but the examples I've found don't really elaborate on the differences, so clarification would be extremely helpful.

How to run a function using a nhibernate criteria?

We have a search routine that uses criteria to build SQL query (because its restrictions added dynamically).
In a particular case (a very complicated case) we need to search over a table-valued function.(our model object is mapped to the function).
The result would be something like this :
SELECT count(*) FROM dbo.GetSubStaffsLetterInstances(#staffId) WHERE LetterNumber="1234";
The problem is I don't know how to pass #staffId to my criteria(I tried adding an Eq restrictions without success since restrictions are working on properties)
I know I can add a parameter to an IQuery but I don't know how I can do it using an ICriteria object.
If I understand your question completely, you can resort back to standard SQL:-
var sql = "SELECT count(*) FROM dbo.GetSubStaffsLetterInstances(:staffId)
WHERE LetterNumber=:letterNum";
var count = session.CreateSqlQuery(sql)
.setInt32("staffId", 12345)
.setString("letternum", "A1")
.UniqueResult<int>();
or try .UniqueResult<long>(); as I can't remember which one HQL returns

Rails and SQL Injection: Is this safe?

#usersfound = User.find_by_sql(["
SELECT * from users where name ## plainto_tsquery('english', ?) LIMIT 20 offset ?
",#query,#offset])
See above, is this safe from sql injection? I am very new to doing direct sql commands on a database in rails. (I am aware there may be other ways of doing this SPECIFIC query, but I am wondering if in general, using find_by_sql and that kind of insertion of vars is safe - I have some difficult queries with subselects and joins that are really possible to do with ActiveRecord.
Thanks.
Yes, that should be safe. If you trace through the code you'll find that your find_by_sql call ends up calling PGconn#send_query_prepared with the bind parameters being carried along as little more than baggage; the send_query_prepared method is just a wrapper for the PQsendQueryPrepared API call in libpq:
static VALUE
pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
{
/* ... bunch of boiler plate marshalling stuff ... */
result = PQsendQueryPrepared(conn, StringValuePtr(name), nParams,
(const char * const *)paramValues, paramLengths, paramFormats,
resultFormat);
/* ... */
}
The bind parameters end up in paramValues. So you should be fine unless there are bugs in PostgreSQL's C library prepared statement handling.
Inserting dynamic values into a query using query parameters is safe.
But it depends on whether Rails is "faking" query parameters, and is actually combining #query and #offset into the SQL string before preparing the statement. Then it's only as safe as the implementation of escaping in Rails.

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.

How to retrieve multiple rows from a stored procedure with Linq to SQL?

I've recently started to work with Linq to SQL and wondered how to get multiple rows as a result of executing a stored procedure,here's a simple sp i want to work with:
CREATE PROCEDURE gsp_ftsmultiple
#SearchKey varchar(100)
AS
BEGIN
SET NOCOUNT ON;
SELECT Label, theContent
FROM FtsTest
WHERE FREETEXT( theContent, #SearchKey )
END
Executing this sp from management studio is fine,but the corresponding method in the generated context class returns a int value, and I don't know how to get the actual rows, tried using the OUT parameters, but they can return only one result.
I think all you need to do is make a class that matches your result schema and make sure the function in the dbml has it as a return type.
see here on msdn
Try creating the fulltext predicates as wrapper functions instead of sprocs, like this. Worked for me.
When sqlmetal generates the code for this procedure, it doesn't pass a valid argument for the query to work.
Try to put something like this on the top of you SP:
IF #SearchKey IS NULL OR LEN(#SearchKey) = 0
BEGIN
SELECT N'' AS Label, N'' AS theContent WHERE 1 = 0
END
[...]
It will now deduce that 2 NVARCHAR columns are the usual output and generate code accordingly
PS. Code off my head, untested
Mike
I tested the following code snippet and it worked fine. If you put the generated code here, I can take a look and check where is the problem. Anyway, you can create a partial class as same name as your generated data context class and add the desired method manually as follows.
public partial class FooDataContext: System.Data.Linq.DataContext
{
[System.Data.Linq.Mapping.Function(Name = "GetFoo")]
public System.Data.Linq.ISingleResult<Foo> GetFoo()
{
System.Data.Linq.IExecuteResult res = base.ExecuteMethodCall(this, (System.Reflection.MethodInfo)System.Reflection.MethodInfo.GetCurrentMethod());
return (System.Data.Linq.ISingleResult<Foo>)res.ReturnValue;
}
}
You'd might be better off just running the query in itself, seeing as you're not really doing anything that requires a procedure. Just make sure you escape the search key properly.