Subsonic - Bit operation in Where Clause - subsonic

I'm trying to make something like this:
int count = new Select().From(tblSchema).Where("Type & 1").IsEqualTo("1").GetRecordCount();
And the error message is:
Incorrect syntax near '&'.
Must declare the scalar variable "#Deleted".
Is it possible to do that with SubSonic?

Must declare the scalar variable
"#Deleted"
The second error would be caused by using logical deletes on the table you are querying (the table has an isDeleted or Deleted column).
But I'm looking through the code, I'm not sure how that parameter is getting in there. The SqlQuery.GetRecordCount method doesn't call CheckLogicalDelete(), from what I can tell. Is that error message unrelated?

This seems to be a bug in the way SubSonic is naming it's parameters when it generates the SQL to be executed.
What's happening is that SubSonic is looking at "Type & 1" and then creating a parameter to compare against called #Type&10 which is not a valid SQL parameter name. So you'll end up with the following SQL from your original query. You should submit a bug to http://code.google.com/p/subsonicproject/
Meanwhile you can workaround the bug for now by using an inline query:
http://subsonicproject.com/docs/Inline_Query_Tool

It is a little fuzzy as to what you are trying to accomplish but here is a best guess.
int count = new Select().From(tbl.Schema).Where(tbl.TypeColumn).IsEqualTo(true).GetRecordCount();

Related

Is it possible to combine 'field' and table record inside 'select' in JOOQ?

I'm using an auto incremental session variable temporary column, to get some kind of sequence for a specific sort-order. The query looks something like this:
return ctx.select(
field("rowNumber"),
TABLE.ID
).from(/* Get an inner query here */)
.where(TABLE.ID.eq(someValue))
.orderBy(field("rowNumber").asc());
But, when I try to execute the above query, it returns the following error:
Unknown column 'TABLE.ID' in 'field list'
The only way I can make it work, is when TABLE.ID is passed as field("ID") inside ctx.select().
Is it so that JOOQ doesn't support specifying the column(s) using a combination of TableRecord and field("column")?
Turns out, it is possible to do so. Apparently, the improper aliasing might have had something to do with the issue. Solved it like this:
TABLE t = TABLE.as("t");
return ctx.select(
field("rowNumber"),
t.ID
).from(getInnerQuery().asTable("t"))
.where(t.ID.eq(someValue))
.orderBy(field("rowNumber").asc());

Curly brackets in OrmLite select query throws error

It seems like OrmLite plain select extension method (Select<T>) tries to format the query string (like SelectFmt<T>), and so it throws an error if the query string contains curly brackets, which it assumes are missing arguments.
Example query:
db.Select<Company>("Website='http://www.test.com/?session={123}'");
Error thrown:
Index (zero based) must be greater than or equal to zero and less than the size of the argument list.
Ideally, Select<T> should just execute the query verbatim, without any string formatting.
Is it a bug in OrmLite, or something else?!
Update: Seems like the issue is here in OrmLiteDialectProviderBase class. It should have a check for params length etc.
You can use SqlList<T> API's for executing Custom SQL that skips pre-processing by OrmLite, but you'll need to provide the full SQL Statement, e.g:
var results = db.SqlList<Company>(
"SELECT * FROM Company WHERE Website='http://www.test.com/?session={123}'");

Select only one row in dql subquery

I have to execute following query:
create dm_myobject object
set my_id_attribute = (select r_object_id from dm_otherobject where <some clause here>)
where ...
But subquery in brackets returns more than one id. I can't make whereclause more detailed to retrieve only one value.
How to take first?
ENABLE(FETCH_ALL_RESULTS 1) or ENABLE(RETURN_TOP 1) doesn't help.
In my experience it is impossible to use DQL hints in a sub query like you suggested, because the hint is applied to the query as a whole. It is indeed possible to use, say, ENABLE(RETURN_TOP 1) on a query that contains a sub query, however that hint will then be used on the outer query and never on the inner one. In your case, however, you'll end up with an error message telling that the sub query returns more than one result.
Try using an aggregate function on the selected attribute instead:
CREATE dm_myobject OBJECT
SET my_id_attribute = (
SELECT MIN(r_object_id)
FROM dm_otherobject
WHERE <some clause>
)
The MIN and MAX functions work with ints and strings, and I suspect they work with IDs too. Since it is ok for you to set only the first ID that's returned from your sub query, I suspect you're returning them in a sorted order and want to use the first -- hence the usage of the MIN function.
An alternative approach would of course be to write a script or a small Java program that executes several DQL statements, but that might or might not work for you in your case.

subsonic query problem

I'm using subsonic 2.2 in an app. I'm running a little complicated query in I have used both "And" and "Or" for a field, I'm little confused about how it is going to be translated into sql statement
MytableCollection col = DB.Select().From("mytable").Where("prop1").IsEqualTo(obj.prop1)
.And("prop2").IsEqualTo(obj.prop2)
.And("prop3").IsEqualTo(obj.prop3)
.Or("prop1").IsEqualTo(1)
.ExecuteAsCollection<MytableCollection>();
I want to perform query like this.
select * from mytable where (prop1=obj.prop1 or prop1=1) and prop2=obj.prop2 and prop23=obj.prop3
As Andra says you can use AndExpression. This should do what you want:
MytableCollection col = DB.Select().From(Mytable.Schema)
.Where(Mytable.Columns.Prop2).IsEqualTo(obj.prop2)
.And(Mytable.Columns.Prop3).IsEqualTo(obj.prop3)
.AndExpression(Mytable.Columns.Prop1).IsEqualTo(obj.prop1)
.Or(Mytable.Columns.Prop1).IsEqualTo(1)
.ExecuteAsCollection<MytableCollection>();
N.B. using MyTable.Schema and MyTable.Columns will catch a lot of issues at compile time if you rename tablees and will save errors caused by mistyping
Something that is REALLY useful to know about is also the following two methods to call in your query building:
.OpenExpression()
and
.CloseExpression()
Mix those bad buoys and you have a lot better control over knowing where things start and finish
you can use expression in subsonic 2.2.
MytableCollection col = new Select(Mytable.Schema)
.WhereExpression("prop1").IsEqualTo(obj.prop1).Or("prop1").IsEqualTo(1)
.AndExpression("prop2").IsEqualTo(obj.prop2)
.AndExpression("prop3").IsEqualTo(obj.prop3)
.ExecuteAsCollection<MytableCollection>();

Subsonic : Same column name different tables

I have a query where I need to do a "Where" clause for two different columns in two different tables but subsonic creates the same parametrized parameter name for both which is causing an issue. How can I fix this?
string _RawSql = new Select()
.From(Tables.Table1)
.InnerJoin(Tables.Table2)
.InnerJoin(Table3.SidColumn, Table2.Table3SidColumn)
.Where(Table1.SidColumn).IsEqualTo(2)
.And(Table3.SidColumn).IsEqualTo(1)
.BuildSqlStatement();
The query this is creating is
SELECT ....
FROM [dbo].[Table1]
INNER JOIN [dbo].[Table2] ON [dbo].[Table1].[Table2Sid] = [dbo].[Table2].[Sid]
INNER JOIN [dbo].[Table3] ON [dbo].[Table2].[Table3Sid] = [dbo].[Table3].[Sid]
WHERE [dbo].[Table1].[Sid] = #Sid
AND [dbo].[Table3].[Sid] = #Sid
Note that in the last two lines its using #Sid for both Table1 and Table3. How go I do it so it uses #Sid0 and #Sid1?
Any help would be appreciated. Thanks
Thanks for the response, I really appreciate it. I am using 2.1
I am already using TableColumn. Below is the c# subsonic code...
.Where(Table1.SidColumn).IsEqualTo(2)
.And(Table3.SidColumn).IsEqualTo(1)
which creates the following sql when viewed in sql profiler
WHERE [dbo].[Table1].[Sid] = #Sid
AND [dbo].[Table3].[Sid] = #Sid
Could you please show me how can I replace these lines with the way you are suggesting? I would really rather not use literal "Table2.Sid = 2"
ranmore, the issue is same with variables or with constants.
I have even tried
.Where("Table1.Sid").IsEqualTo(2)
.And("Table3.Sid").IsEqualTo(1)
This creates the query as
WHERE Table1.Sid = #Table1.Sid0
AND Table3.Sid = #Table3.Sid1
I finally get different parametrized vars in this case but now SQL Server complains because it does not like . in the parametrized var names.
I have no clue how to perform a join with 2 where clauses for 2 different tables!
What version are you using? In 2.2 You can use the TableColumn object to get around this (it may be the same for 2.1 as well. So instead of using the struct, as you're doing, you can use the object (Table2.SidColumn).
If push comes to shove - you can override everything with a string - so in your case you could use "Table1.Sid" and "Table2.Sid" right in the Where() method.
I haven't been able to confirm this, but perhaps the problem only happens with literals? (not sure if your sample code is like that for brevity's sake)
int table1SidColumnValue = 2;
int table3SidColumnValue = 1;
.Where(Table1.SidColumn).IsEqualTo(table1SidColumnValue)
.And(Table3.SidColumn).IsEqualTo(table2SidColumnValue)
I remember seeing a problem with this when using multiple .In() clauses with literal values, not sure if that applies to your problem though.
I'm not sure what version of the code I have but your query produces numbered parameters for me.
If you look at Line 255 of ANSISqlGenerator.cs
https://github.com/subsonic/SubSonic-2.0/blob/master/SubSonic/SqlQuery/SqlGenerators/ANSISqlGenerator.cs
c.ParameterName = String.Concat(col.ParameterName, query.Constraints.IndexOf(c));
The where parameters really should have numbers appended to them... maybe pull the latest version?

Resources