Regex matching SQL with subqueries, indicate by bracket [duplicate] - c#

I need to write RegEx in C# to parse SQL join query which is given as a string. Can somebody please help me because I'm new at this. Thanks a lot
this is my problem:
string query = #"SELECT table1.column1, table1.column2, table2.coulmn1, table2.column2
FROM table1 INNER JOIN table2 ON table1.column5 = table2.column5";
what I actually need is to put all important data into separate variables, like this:
string class1 = table1
string class2 = table2
string joinForeignKey1 = table1.column5
string joinForeignKey2 = table2.column5
List<string> attributes1 = table1.column1, table1.column2
List<string> attributes2 = table2.column1, table2.column2
//COMMENT
I realized that I have made a mistake in sql query so there will be an ON clause.
I can force a user to provide me with the correct syntax, so that will be no problem.
The thing I haven't mentioned is that there can be more than one JOIN ON clause (multiple joins).
Thanks a lot and I will appreciative any given help.

Pulling this over from comments, since I think it's the right answer here:
SQL is #3 on the list of Stuff You Should Not Try To Parse With A Regex, just behind HTML and MUMPS. Use a dialect-specific, dedicated SQL parser, not a regex.

I personally do not recommend doing this unless you have a VERY, VERY valid reason to do so as well as full control over the way that the SQL would be written.
First and foremost the syntax that you noted for the SQL statement is the old style join syntax and not using the more common ON syntax.
Something like
SELECT A.ColumnA, B.ColumnB
FROM MyTable A
INNER JOIN YourTable B
ON (A.MyIdentity = B.MyForeignKey)
So unless you can force users to input queries in the old syntax you are already going down the road to a way that will not work.
If I was forced to do this type of thing, and I did have control over it, I personally wouldn't bother with RegEx, due to the fact that the process is so structured. i would just use basic string manipulation.

Related

How to write Nested LINQ for specific scenario

Apologized to post a problem for which i could not construct anything solid. it is very shameful for me to post like this kind of question even after having so high reputation for this web site.
Most of the time i write sql in store procedure in sql server and hardly use LINQ. so facing problem to construct a nested LINQ query for a specific scenario. just wonder if anyone could help me or give me hints to construct such query with linq.
here i am providing a sample sql query which i want to construct the same one with LINQ.
SELECT EmployeeName,
(Select count(*) from table1 where condition) as data1,
(Select count(*) from table1 where condition) as data2,
(Select count(*) from table1 where condition) as data3
though i have seen couple of nested linq sample from these urls but still could not figure out how to construct mine.
http://odetocode.com/blogs/scott/archive/2007/09/24/nested-selects-in-linq-to-sql.aspx
https://social.msdn.microsoft.com/Forums/en-US/00340c95-221a-4b16-9c47-d1acbf2415dc/linq-nested-select-issue?forum=linqtosql
http://www.mercurynewmedia.com/blog/blog-detail/mercury-new-media-blog/2014/05/19/linq-join-queries-vs-nested-sub-queries
http://www.codethinked.com/the-linq-selectmany-operator
Nested Select linq query
http://www.java2s.com/Code/CSharp/LINQ/Nestedquerylist.htm
so just wonder if anyone could help.
This is a good example of something to do in Linq. You will find that you can do this easily and even more powerful queries if you understand two things:
Don't try to overly literally translate from SQL into Linq.
Lambdas.
The first is easy to understand but hard to carry out. Some of the Linq keywords are intentionally like SQL keywords. Linq tries to mirror some aspects of SQL without working in exactly the same way. One key difference is that with Linq, each function yields (no pun intended) a Linq object which can be passed to another Linq function. Thus filtering, transforming, aggregating, etc. can be done repeatedly in the order the programmer chooses. In SQL a single query is built up of several elements such as WHERE, FROM, some of which are optional, and the SQL engine decides in which order to evaluate them.
Get LinqPad and use it for playing with queries, and for doing database queries instead of writing SQL code in SSMS. When you have seen and written enough Linq constructs, you will no longer be writing transliterated SQL, and you will be able to switch back and forth between the two.
Secondly, make sure you understand lambdas. What does
x => x + 23
mean? What is its type? What is the type of its argument and return value? What about
(x, y) => x + y * 23
and
() => "Fish"
?
Select in Linq takes as argument a function. What Select does is the simplest possible thing to understand - it takes an iterator of input objects and a function, and returns an iterator of output objects, which are the input objects having had the function applied to them. This is actually easier to understand with a lambda than with a named function.
Remember that everything in C# has a type. A lambda has a type, even if the type is not explicit. Error messages usually tell you exactly what is wrong, except that sometimes they can be misinterpreted and seem to be pointing to exactly the wrong piece of code, and this can be very time-consuming to figure out. Break down the code you are writing into as small pieces as possible, and debug them in Linqpad.
You can get a long way with this. Try looking at a suggestion for a similar query to yours below and see if you can build on it.
/* A very simple dataset */
string s = "THE QUICK BROWN FOX JUMPED OVER THE LAZY DOG";
var x = s.Split();
/* The letters list plays the role of your EmployeeName */
var letters = new List<String>{"A", "E", "I", "O", "U"};
var result = letters
.Select(letter => new {letter = letter,
startswith = x.Count(w => w.StartsWith(letter)),
contains = x.Count(w => w.Contains(letter)),
endswith = x.Count(w => w.EndsWith(letter))});
If you get this far, you might want to learn more about how the Linq functions operate on iterators. Check out Jon Skeet's Edulinq series of blog posts: http://codeblog.jonskeet.uk/2011/02/23/reimplementing-linq-to-objects-part-45-conclusion-and-list-of-posts/ He reimplements Linq to show how it might be designed and how it should work.
Linqpad and Edulinq and two of the best programming resources I know of, in any language, and I recommend them in almost every Linq question I answer. Check them out.

RegEx for parsing SQL query in C#

I need to write RegEx in C# to parse SQL join query which is given as a string. Can somebody please help me because I'm new at this. Thanks a lot
this is my problem:
string query = #"SELECT table1.column1, table1.column2, table2.coulmn1, table2.column2
FROM table1 INNER JOIN table2 ON table1.column5 = table2.column5";
what I actually need is to put all important data into separate variables, like this:
string class1 = table1
string class2 = table2
string joinForeignKey1 = table1.column5
string joinForeignKey2 = table2.column5
List<string> attributes1 = table1.column1, table1.column2
List<string> attributes2 = table2.column1, table2.column2
//COMMENT
I realized that I have made a mistake in sql query so there will be an ON clause.
I can force a user to provide me with the correct syntax, so that will be no problem.
The thing I haven't mentioned is that there can be more than one JOIN ON clause (multiple joins).
Thanks a lot and I will appreciative any given help.
Pulling this over from comments, since I think it's the right answer here:
SQL is #3 on the list of Stuff You Should Not Try To Parse With A Regex, just behind HTML and MUMPS. Use a dialect-specific, dedicated SQL parser, not a regex.
I personally do not recommend doing this unless you have a VERY, VERY valid reason to do so as well as full control over the way that the SQL would be written.
First and foremost the syntax that you noted for the SQL statement is the old style join syntax and not using the more common ON syntax.
Something like
SELECT A.ColumnA, B.ColumnB
FROM MyTable A
INNER JOIN YourTable B
ON (A.MyIdentity = B.MyForeignKey)
So unless you can force users to input queries in the old syntax you are already going down the road to a way that will not work.
If I was forced to do this type of thing, and I did have control over it, I personally wouldn't bother with RegEx, due to the fact that the process is so structured. i would just use basic string manipulation.

Joins and subqueries in LINQ

I am trying to do a join with a sub query and can't seem to get it. Here is what is looks like working in sql. How do I get to to work in linq?
SELECT po.*, p.PermissionID
FROM PermissibleObjects po
INNER JOIN PermissibleObjects_Permissions po_p ON (po.PermissibleObjectID = po_p.PermissibleObjectID)
INNER JOIN Permissions p ON (po_p.PermissionID = p.PermissionID)
LEFT OUTER JOIN
(
SELECT u_po.PermissionID, u_po.PermissibleObjectID
FROM Users_PermissibleObjects u_po
WHERE u_po.UserID = '2F160457-7355-4B59-861F-9871A45FD166'
) used ON (p.PermissionID = used.PermissionID AND po.PermissibleObjectID = used.PermissibleObjectID)
WHERE used.PermissionID is null
Without seeing your database and data model, it's pretty impossible to offer any real help. But, probably the best way to go is:
download linqpad - http://www.linqpad.net/
create a connection to your database
start with the innermost piece - the subquery with the "where" clause
get each small query working, then join them up. Linqpad will show you the generated SQL, as well as the results, so build your small queries up until they are right
So, basically, split your problem up into smaller pieces. Linqpad is fantastic as it lets you test these things out, and check your results as you go
hope this helps, good luck
Toby
The LINQ translation for your query is suprisingly simple:
from pop in PermissibleObjectPermissions
where !pop.UserPermissibleObjects.Any (
upo => upo.UserID == new Guid ("2F160457-7355-4B59-861F-9871A45FD166"))
select new { pop.PermissibleObject, pop.PermissionID }
In words: "From all object permissions, retrieve those with at least one user-permission whose UserID is 2F160457-7355-4B59-861F-9871A45FD16".
You'll notice that this query uses association properties for navigating relationships - this avoids the need for "joining" and simplfies the query. As a result, the LINQ query is much closer to its description in English than the original SQL query.
The trick, when writing LINQ queries, is to get out of the habit of "transliterating" SQL into LINQ.

Unicode String in Hibernate Queries

In SQL one can write a query that searches for a name of a person like this:
SELECT * FROM Person P WHERE P.Name LIKE N'%ike%'
This query would run with unicode characters (assuming that the Name column and database were setup to handle unicode support).
I have a similar query in HQL that is run by Hibernate (NHibernate). The generated query looks like:
SELECT P FROM SumTotal.TP.Models.Party.Person P join P.Demographics PD WHERE (PD.LastName LIKE '%カタカ%' )
Unfortunately, placing a 'N' in front of the literal in the HQL results in an error. I've tried escaping the unicode characters in the string and still no success.
The database is accepting and saving unicode characters from Hibernate. I've been able to successfully populate an object with a unicode string, save it with Hibernate, and verify it in the database. It would seem to me as a little odd that I cannot use unicode strings in custom queries (or I'm also assuming named queries).
Is this a known issue or limitation of Hibernate (Nhibernate)? How do you use unicode in HQL?
Several sites suggest using the Criteria queries. Due to constraints in the framework that I'm working in, this is not possible.
Have you tried with parameters:
IList<Person> people = session
.CreateQuery("from Person p where p.Name like :name")
.SetParameter("name", "%カタカ%")
.List<Person>();
They also have the advantage to protect your query against SQL injection.
I found a solution that works. I highly doubt it is the best solution. It is however the solution that I'm going to implement until I can authorize a rewrite of the entire query building section of the software that I'm working on.
In the instance:
SELECT P FROM SumTotal.TP.Models.Party.Person P join P.Demographics PD WHERE (PD.LastName LIKE '%カタカ%')
The where clause contains this literal:
'%カタカ%'
This literal can be broken up into nchars which Hibernate (Nhibernate) will unknowingly pass through to the SQL it generates. Odd, but it works. Thus the previous query could be written as:
SELECT P FROM SumTotal.TP.Models.Party.Person P join P.Demographics PD WHERE (PD.LastName LIKE '%' + nchar(0x30AB) + nchar(0x30BF) + nchar(0x30AB)+ '%')
This solution is far from optimal because it would require going through each character and determining if it was a multibyte character. However, in the case of where this code lives in its app it is used in a dynamic query generator that processes multiple different criteria under different operations. In the example I give it is looking for unicode anywhere in the string. It is possible that this function may be returning the where clause portion for a column equaling a specific numeric value or it could be looking for the starting characters of a string. The method that builds the operator uses a operator type and the term to hand back a string. I could rewrite that but it would be a large task. The above fix will allow me to process a string passed into this method. I offer this solution because it does work, but darin's answer is probably the best way I could find.
This problem arises because NHibernate tries to access the column without the type length. Hence in the HBM.xml its very important to mention length for Legacy databases otherwise it will fail for UNIcode related stuff.
Thanks,
Thani

Converting user-entered search query to where clause for use in SQL Server full-text search

What's the best way to convert search terms entered by a user, into a query that can be used in a where clause for full-text searching to query a table and get back relevant results? For example, the following query entered by the user:
+"e-mail" +attachment -"word document" -"e-learning"
Should translate into something like:
SELECT * FROM MyTable WHERE (CONTAINS(*, '"e-mail"')) AND (CONTAINS(*, '"attachment"')) AND (NOT CONTAINS(*, '"word document"')) AND (NOT CONTAINS(*, '"e-learning"'))
I'm using a query parser class at the moment, which parses the query entered by users into tokens using a regular expression, and then constructs the where clause from the tokens.
However, given that this is probably a common requirement by a lot of systems using full-text search, I'm curious as to how other developers have approached this problem, and whether there's a better way of doing things.
How to implement the accepted answer using .Net / C# / Entity Framework...
Install Irony using nuget.
Add the sample class from:
http://irony.codeplex.com/SourceControl/latest#Irony.Samples/FullTextSearchQueryConverter/SearchGrammar.cs
Write code like this to convert the user-entered string to a query.
var grammar = new Irony.Samples.FullTextSearch.SearchGrammar();
var parser = new Irony.Parsing.Parser(grammar);
var parseTree = parser.Parse(userEnteredSearchString);
string query = Irony.Samples.FullTextSearch.SearchGrammar.ConvertQuery(parseTree.Root);
Perhaps write a stored procedure like this:
create procedure [dbo].[SearchLivingFish]
#Query nvarchar(2000)
as
select *
from Fish
inner join containstable(Fish, *, #Query, 100) as ft
on ft.[Key] = FishId
where IsLiving = 1
order by rank desc
Run the query.
var fishes = db.SearchLivingFish(query);
This may not be exactly what you are looking for but it may offer you some further ideas.
http://www.sqlservercentral.com/articles/Full-Text+Search+(2008)/64248/
In addition to #franzo's answer above you probably also want to change the default stop word behaviour in SQL. Otherwise queries containing single digit numbers (or other stop words) will not return any results.
Either disable stop words, create your own stop word list and/or set noise words to be transformed as explained in SQL 2008: Turn off Stop Words for Full Text Search Query
To view the system list of (English) sql stop words, run:
select * from sys.fulltext_system_stopwords where language_id = 1033
I realize it's a bit of a side-step from your original question, but have you considered moving away from SQL fulltext indexes and using something like Lucene/Solr instead?
The easiest way to do this is to use dynamic SQL (I know, insert security issues here) and break the phrase into a correctly formatted string.
You can use a function to break the phrase into a table variable that you can use to create the new string.
A combination of GoldParser and Calitha should sort you out here.
This article: http://www.15seconds.com/issue/070719.htm has a googleToSql class as well, which does some of the translation for you.

Categories