SOCI Session Sql return Values - oracle

In my office I m asked to write some test cases on basic areas where db connections check and test, so that is a technology we gona implement newly so nobody there to ask for helping hand well and what they asked it to do for me is write Gtest(google test) for C++ with soci,
so now I have testcase like this,
Whether table got dropped or not,
so I wrote some code like this,
TEST(CheckNull, DropTable)
{
bool output = true;
session sql(oracle, "service=LOCAL user=ROOT password=123");
string query = "drop table GTestAutomation";
sql<<query;
EXPECT_EQ(true,output);
}
now I wanted to check whether my sql statement successfully executed or not can I do something like this?
if(sql<<query)
{
output = true ;
}
else
{
output = false;
}
so that I can check my condition EXPECT_EQ(true,output); like this.
Need help, If you dont know correct way of doing or answer plz dont put etc etc comments.
Thanks

If you're statement was not successfully executed, soci would throw a soci::soci_error exception, which you can catch. So you could write something like this:
TEST(CheckNull, DropTable)
{
bool output = true;
session sql(oracle, "service=LOCAL user=ROOT password=123");
string query = "drop table GTestAutomation";
try{
sql<<query;
} catch (soci::soci_error &e) {
output = false;
}
EXPECT_EQ(true,output);
}

Related

How do I know if my linq will return a useable object or a null

I am working on a web service. I am using linq to query a database. Seemingly simple, but I've run into an issue. Here is my code for reference:
List<Comment> res = new List<Comment>();
using (ApplicationHistoryEntities ahe = new ApplicationHistoryEntities())
{
res = (from columns in ahe.Comments
where columns.NetforumId == actionuniqueid
select columns).ToList();
}
If I have no entries in the database, will my .ToList() throw an error? I could deploy it, and just try it out but I want to know more about the mechanism that my linq is using. If ahe.Comments database has no rows... what will the (from...) section return?
I could just add a null reference check, use dynamics etc but I want to really understand it.
I found this Q: how to know if my linq query returns null but it seems like all of the answers are in conflict on how it really should be done...
example answers:
Either you can convert it to list and then check the count
Best approach is to check there is null(no items) in list use Any() instead of count()
LINQ queries should never return null and you should not get an exception if the result is empty. You probably have an error in your code.
You can realise the result as a list then check the items.
You can see why I question how it works.
Edit:
Final code looks like this:
List<Comment> res;
using (ApplicationHistoryEntities ahe = new ApplicationHistoryEntities())
{
res = ahe.Comments?.Where(rowItem => rowItem.NetforumId == actionuniqueid).ToList() ??
new List<Comment>().ToList();
}
Look at this example:
List<string> test = new List<string>();
var test1 = test.Where(x => x == "a").ToList();
If test exists but is empty the query returns an empty list. If test is null the query throws an error. So you can adapt the query as follows
List<string> test = new List<string>();
test = null;
var test1 = test?.Where(x => x == "a") ?? new List<string>().ToList();
The query is now 'safe'. Both of the above examples return an empty list i.e. test1.Count() will return zero but will be usable.
You can also look at the definitions of Where and ToList

If there a way to compile (not execute) a query syntaxicly and semanticly with JDBC?

I have numerous queries which contains syntax error (and without unit test, but that's another problem) and I'd like to massively check if there are no errors.
For that, I've done the following at first:
String q = ...; // some query
try (PreparedStatement stmt = connection.prepareStatement(q)) {
final ParameterMetaData pmd = stmt.getParameterMetaData();
for (int i = 1; i <= pmd.getParameterCount(); ++i) {
stmt.setNull(i, java.sql.Types.NULL);
}
stmt.execute();
} catch (SQLException e) {
...
} finally {
connection.rollback();
}
It works, but then I came into such errors: http://www.oracle-error.com/11g/ORA-30081.html
Basically, somewhere in my query, I have that:
select *
from table T
where id = ? or ( ? - INTERVAL '1' DAY ) between date_start and date_end
If I execute the same query, replacing ? by NULL, in TOAD, I've got the same error.
The ParameterMetaData does not help either, because it don't store the information I want (eg: what Oracle expect as parameter).
Is there some solution to compile the query syntactically and semantically (to check for missing columns, etc) ignoring parameters along the way?
As of now, I am replacing the ? by NULL, except if after the "?" I found some date stuff, where I use sysdate.
eg:
select *
from table T
where id = NULL or ( sysdate - INTERVAL '1' DAY ) between date_start and date_end
Not directly through JDBC, but you can do it indirectly; heavily inspired by this, you can do:
String q = ...; // some query
try (PreparedStatement stmt = connection.prepareStatement("declare c integer;
begin
c := dbms_sql.open_cursor;
dbms_sql.parse(c,?,dbms_sql.native);
dbms_sql.close_cursor(c);
end;")) {
stmt.setString(1, q.replace("?", ":b0"));
stmt.execute();
} catch (SQLException e) {
...
}
The statement you prepare is now an anonymous block, and the single bind variable is now your original query to validate. You don't need to know anything about the query's parameters. The replace converts the JDBC ? placeholders to generic :b0 bind variables so the parser doesn't object to them.
You could be more advanced and replace each placeholder with a different bind variable (:b0, :b1) etc. but I don't think it will generally be necessary. This crude replace would also potentially modify string literals though, of course, which may be something you need to consider; a regular expression approach would be more robust.
One other option to try might be to use the EXPLAIN PLAN statement available in Oracle and in some other DBMSes (possibly in a slightly different form). Prepend 'EXPLAIN PLAN FOR ' to your statement and execute() (no need to prepare). The original statement won't actually run, but it will be parsed and compiled, and you don't need to bind any parameters.
Proof.
It may still choke on untyped parameter markers in some cases though.

what does a linq query return when no results are found

i'm using a query to see if a user already exists in the database. if it finds a user, it adds it to the list (not database), and presents a message. if the user does NOT already exist, the program moves on to add the user.
the problem exists when adding the query result to a list, when the result found nothing. if the query found nothing (user does not yet exist) the returned value isn't null or 0, so i'm not sure how to check for this.
my code works fine, but my problem is trying to find a more elegant approach. i try to add the query results to a list. if it his the "catch", it means the user does not exist and it shall be added. right now my code is:
var userIsNew =
from f in controlEntities.Users
where (f.UserId == userIdTextBox.Text)
select f;
List<Users> temp = new List<Users>();
try
{
temp = userIsNew.ToList<Users>();
}
catch
{
//do nothing
}
if (temp.Count > 0)
{
MessageBox.Show("This UserId already exists in the Database. \nPlease try another UserId.");
}
thank you for your help!
var userIsNew = (from f in controlEntities.Users
where (f.UserId == userIdTextBox.Text)
select f).FirstOrDefault();
if (userIsNew != null)
{
MessageBox.Show("This UserId already exists in the Database. \nPlease try another UserId.");
}
Another way would be:
bool userIsNew = controlEntities.Users.
Count(f => f.UserId == userIdTextBox.Text) == 0;
if (!userIsNew)
{
MessageBox.Show("This UserId already exists in the Database. \nPlease try another UserId.");
}
It's efficient because the data server returns only a number instead of a resulset.

Debugging Entity Framework queries

This is a bit of subjective question about a specific situation. Main goal for this question for me is to remind my self to code up the solution. However if there is already a solution, or an alternate approach, I would like to know it.
I'm working on a project and I'm using Entity Framework 4 for database access. The database design is something that I don't have control over. The database was designed many years ago, and in my opinion the database design does not fit for the current database purposes. This results in very complicated queries.
This is the first time I'm using Entity Framework in a project, but I have extensive experience in development against MS SQL Server.
What I found myself doing again and again is this:
I write a complex L2E query. The query either slow or returns wrong results
I'm looking at my L2E query and I have absolutely no idea how to improve it
I fire up SQL Profiler and capture the SQL that EF generated from my query
I want to execute part of that sql to identify the part of the query that is giving problems
The query comes through as sp_executesql with a dozen of parameters, because if a parameter is used 3 times in a query, L2E creates 3 parameters and passes to all of them the same value. Same deal with every parameter.
Now I have to extract the SQL from sp_executesql, unescape all escaped apostrophes, and substitute every parameter in the query with its value
After this is done I finally can run parts of the query and pin-point the problem.
I go back to my L2E code, change it to fix the problem I found and the cycle repeats.
To be honest, I'm starting thinking that one should not use an ORM if you don't own database design.
This aside, the process of unescaping the sql and substituting the parameters is the one that I want to automate. The goal is to get 'naked', de-parametrized sql, that I can run in SSMS.
This a very simple example of what I see in the profile and what I want to get in result. My real cases are many times more complex.
The capture:
exec sp_executesql N'SELECT
[Extent1].[ProductName] AS [ProductName]
FROM [dbo].[Products] AS [Extent1]
INNER JOIN [dbo].[Categories] AS [Extent2] ON [Extent1].[CategoryID] = [Extent2].[CategoryID]
WHERE ([Extent1].[UnitPrice] > #p__linq__0) AND ([Extent2].[CategoryName] = #p__linq__1) AND (N''Chang'' <> [Extent1].[ProductName])',N'#p__linq__0 decimal(1,0),#p__linq__1 nvarchar(4000)',#p__linq__0=1,#p__linq__1=N'Beverages'
Desired result:
SELECT
[Extent1].[ProductName] AS [ProductName]
FROM [dbo].[Products] AS [Extent1]
INNER JOIN [dbo].[Categories] AS [Extent2] ON [Extent1].[CategoryID] = [Extent2].[CategoryID]
WHERE ([Extent1].[UnitPrice] > 1) AND ([Extent2].[CategoryName] = N'Beverages') AND (N'Chang' <> [Extent1].[ProductName])
I'm just going to write code to convert the likes of first to the likes of second if there is nothing better, I'll post the solution here. But maybe it's already done by someone? Or maybe there is a profiler or something, that can give me sql code I can execute partially in SSMS?
So here is what I ended up with. A couple of notes:
This won't work in 100% of cases, but this is good enough for me
There is a lot to improve in terms of usability. Currently I put a shortcut to the compiled binary on the desktop, cut the text to convert to clipboard, double-click the shortcut and paste the result.
using System;
using System.Text.RegularExpressions;
using System.Windows.Forms;
namespace EFC
{
static class Program
{
[STAThread]
static void Main()
{
try
{
string input = Clipboard.GetText();
const string header = "exec sp_executesql N'";
CheckValidInput(input.StartsWith(header), "Input does not start with {0}", header);
// Find part of the statement that constitutes whatever sp_executesql has to execute
int bodyStartIndex = header.Length;
int bodyEndIndex = FindClosingApostroph(input, bodyStartIndex);
CheckValidInput(bodyEndIndex > 0, "Unable to find closing \"'\" in the body");
string body = input.Substring(bodyStartIndex, bodyEndIndex - bodyStartIndex);
// Unescape 's
body = body.Replace("''", "'");
// Work out where the paramters are
int blobEndIndex = FindClosingApostroph(input, bodyEndIndex + 4);
CheckValidInput(bodyEndIndex > 0, "Unable to find closing \"'\" in the params");
string ps = input.Substring(blobEndIndex);
// Reverse, so that P__linq_2 does not get substituted in p__linq_20
Regex regexEf = new Regex(#"(?<name>#p__linq__(?:\d+))=(?<value>(?:.+?)((?=,#p)|($)))", RegexOptions.RightToLeft);
Regex regexLinqToSql = new Regex(#"(?<name>#p(?:\d+))=(?<value>(?:.+?)((?=,#p)|($)))", RegexOptions.RightToLeft);
MatchCollection mcEf = regexEf.Matches(ps);
MatchCollection mcLinqToSql = regexLinqToSql.Matches(ps);
MatchCollection mc = mcEf.Count > 0 ? mcEf : mcLinqToSql;
// substitutes parameters in the statement with their values
foreach (Match m in mc)
{
string name = m.Groups["name"].Value;
string value = m.Groups["value"].Value;
body = body.Replace(name, value);
}
Clipboard.SetText(body);
MessageBox.Show("Done!", "CEF");
}
catch (ApplicationException ex)
{
MessageBox.Show(ex.Message, "Error");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error");
MessageBox.Show(ex.StackTrace, "Error");
}
}
static int FindClosingApostroph(string input, int bodyStartIndex)
{
for (int i = bodyStartIndex; i < input.Length; i++)
{
if (input[i] == '\'' && i + 1 < input.Length)
{
if (input[i + 1] != '\'')
{
return i;
}
i++;
}
}
return -1;
}
static void CheckValidInput(bool isValid, string message, params object[] args)
{
if (!isValid)
{
throw new ApplicationException(string.Format(message, args));
}
}
}
}
Well,may be this will be helpfull. MSVS 2010 has IntelliTrace. Every time when EF make a query there is an ADO.Net Event with a query
Execute Reader "SELECT TOP (1)
[Extent1].[id] AS [id],
[Extent1].[Sid] AS [Sid],
[Extent1].[Queue] AS [Queue],
[Extent1].[Extension] AS [Extension]
FROM [dbo].[Operators] AS [Extent1]
WHERE [Extent1].[Sid] = #p__linq__0" Command Text = "SELECT TOP (1) \r\n[Extent1].[id] AS [id], \r\n[Extent1].[Sid] AS [Sid], \r\n[Extent1].[Queue] AS [Queue], \r\n[Extent1].[Extension] AS [Extension]\r\nFROM [dbo].[Operators] AS [Extent1]\r\nWHERE [Extent1].[Sid] = #p__linq__0",
Connection String = "Data Source=paris;Initial Catalog=telephony;Integrated Security=True;MultipleActiveResultSets=True"

linq 'range variable' problem

I have a strange problem when deleteting records using linq, my suspicion is that it has something to do with the range variable (named source). After deleting a record all targets for a customer are retrieved using the following statement:
var q = from source in unitOfWork.GetRepository<db_Target>().Find()
where source.db_TargetBase.db_Person.fk_Customer == customerID
select source.FromLinq();
where FromLinq is in extention method on db_target:
public static Target FromLinq(this db_Target source)
{
return new Target
{
id = source.id,
LastModified = source.db_TargetBase.LastModified,
...
}
}
When a record is deleted both db_Target and db_TargetBase are deleted. When, for example, two users are deleting records, linq tries to retrieve a record for user2 which is deleted by user1, causing a crash on the LastModified = source.db_TargetBase.LastModified line because db_TargetBase is null.
When using the following code the problem does not occure and only the non-deleted records are retrieved:
var q = from source in unitOfWork.GetRepository<db_Target>().Find()
where source.db_TargetBase.db_Person.fk_Customer == customerID
select new Target
{
id = source.id,
LastModified = source.db_TargetBase.LastModified,
...
};
This spawns two questions:
What is happening here? Am I making a copy of the range variable source because I'm using it in a extention method?
How can I "wrap" the return new Target code? I am using this in multiple places and do not want to copy it every time. Making my code harder to maintain.
TIA,
JJ
In the first set of code - since the initializer lives an a non-translatable method (extension or otherwise), it cannot be translated - so it is run locally.
In the second set of code - the initializer is represented by an elementinit expression, which is translated (examine/compare the select clause of the generated sql for proof).
if you want to wrap this, you need to have an Expression<Func<db_Target, Target>> that anyone can grab and use in thier query. Fortunately, that's easy to do:
public Expression<Func<db_Target, Target>> GetFromLinqExpressionForTarget()
{
return
source => new Target
{
id = source.id,
LastModified = source.db_TargetBase.LastModified,
...
}
}
Which may be used like so:
var FromLinq = GetFromLinqExpressionForTarget();
var q =
(
from source in ...
...
...
select source
).Select(FromLinq);
Now ... I'm really running on a guess here and am only about 60% confident that my answer is correct. So if someone wants to confirm this, that'll make my day. :)

Resources