this is a function I've written to extract the from part of a SQL query. When you first get this assignment it sounds simple. But once you start thinking about it, it becomes more and more complex. How do you handle sub-queries in the select and where clause. How do you handle unions, ...
The function I've written works by calculating the nesting level of your query. This is done by adding 1 to a counter if you encounter a ( and subtracting 1 from the counter if you find a ). If you then find the word "from" and the nesting level = 0 you've got the from part. The next problem is what if the query contains an extra ( or )
This can happen for example with the following query: select replace(field,'(',' '),* from table
So this simple query would ruin my whole function :-)
I solved this by only increasing and decreasing the nesting level if there are no quotes open.
I've included two functions, one which can handles union and returns the from part of every separate query joined by a union. The first function can't cope with a union, but you can use this if you know there won't be a union. If anyone finds other queries which these functions can't handle, please let me know.
Public Function GetFromPartOfAQuery(SourceQuery As String) As String
Dim nestLevel As Integer = 0
Dim blnQuoteOpen As Boolean = False
Dim strReturn As String = ""
Dim iIndex As Integer = 0
Dim strWord As String = ""
For Each c As Char In query
iIndex += 1
If c = "'"c And blnQuoteOpen = False Then
blnQuoteOpen = True
Else
If c = "'"c And blnQuoteOpen = True Then
blnQuoteOpen = False
End If
End If
If c = "(" AndAlso blnQuoteOpen = False Then
nestLevel += 1
End If
If c = ")" AndAlso blnQuoteOpen = False Then
nestLevel -= 1
End If
If c = " "c Then
strWord = ""
Else
strWord &= c
End If
If strWord.ToLower = "from" And nestLevel = 0 Then
strReturn = Mid(query, iIndex - 3, query.Length - (iIndex - 4))
Exit For
End If
Next
Return lstReturn
End Function
Public Function GetFromPartOfAQuery(SourceQuery As String) As List(Of String)
Dim nestLevel As Integer = 0
Dim blnQuoteOpen As Boolean = False
Dim lstReturn As New List(Of String)
Dim iIndex As Integer = 0
Dim strWord As String = ""
Dim queries As String() = SourceQuery.ToLower.Split(New String() {"union"}, StringSplitOptions.None)
For Each query As String In queries
iIndex = 0
strWord = ""
blnQuoteOpen = False
For Each c As Char In query
iIndex += 1
If c = "'"c And blnQuoteOpen = False Then
blnQuoteOpen = True
Else
If c = "'"c And blnQuoteOpen = True Then
blnQuoteOpen = False
End If
End If
If c = "(" AndAlso blnQuoteOpen = False Then
nestLevel += 1
End If
If c = ")" AndAlso blnQuoteOpen = False Then
nestLevel -= 1
End If
If c = " "c Then
strWord = ""
Else
strWord &= c
End If
If strWord.ToLower = "from" And nestLevel = 0 Then
lstReturn.Add(Mid(query, iIndex - 3, query.Length - (iIndex - 4)))
Exit For
End If
Next
Next
Return lstReturn
End Function
No comments:
Post a Comment