Imports System.io
Public Class DQLSession
#Region "Primary Sorting of Commands"
Public Function Run(ByVal command As String) As String
Dim query As New ArrayList 'arraylist to hold each word of query
Dim queryreader
As New StringReader(command) 'reader to read query character by character
Dim querytermbuffer As String 'buffer to hold partial words of query
Dim protectedflag As Boolean 'flag to show if data is protected by quotes
Dim queryreaderbuffer As String 'buffer to hold latest character of query
Dim
returnval As String 'string to hold return value
Do Until queryreader.Peek =
-1
queryreaderbuffer = queryreader.Read
Select Case queryreaderbuffer
Case " " 'if space then, if not protected, new word
If protectedflag = False Then
query.Add(querytermbuffer)
querytermbuffer = ""
Else
querytermbuffer = querytermbuffer & queryreaderbuffer
End If
Case """"
'if quote, change protected flag
If protectedflag = True Then
protectedflag = False
Else
protectedflag = True
End If
Case Else
'if else, add to buffer
querytermbuffer = querytermbuffer & queryreaderbuffer
End Select
Loop
queryreader.Close()
Select Case query(0) 'go to appropriate sub based on kind of command
Case "RETURN"
returnval = ReturnDat(query)
Case "SETDAT"
returnval = SetDat(query)
Case "INSERT"
returnval = Insert(query)
Case "DELETE"
returnval = Delete(query)
Case "FORMAT"
returnval = Me.Format(query)
Case Else
Throw New Exception("Query
not recognised!")
End Select
Return
returnval
End Function
Private Function ReturnDat(ByVal query As ArrayList)
'make an arraylist of all records
Dim records As New ArrayList
Dim arraylistcounter As Integer
Dim sortflag As Boolean
Dim returntable As String
For arraylistcounter = 1 To GetNoOfRecords()
records.Add(arraylistcounter)
Next
'check for word WHERE, if present then go to sub to deal with it
For arraylistcounter
= 1 To query.Count - 1
If query(arraylistcounter) =
"WHERE" Then
records = Where(query,
records, arraylistcounter)
ElseIf query(arraylistcounter)
= "SORT" Then
records = Sort(query,
arraylistcounter, records.Count)
Exit For
End If
Next
'now build a new table with the result in
returntable = BuildTable(query, records)
Return returntable
End Function
Private Function SetDat(ByVal query As ArrayList)
'deal
with a setdat command here
End Function
Private Function Insert(ByVal query As ArrayList)
'deal
with an insert command (new database elemnt) here
End Function
Private Function Delete(ByVal query As ArrayList)
'deal
with a delete command here (remove table element)
End Function
Private Function Format(ByVal query As ArrayList)
'deal
with a format command (get or sset database properties) here
End Function
#End Region
#Region "Comparison Logic"
Private Function Where(ByVal query As ArrayList, ByVal records As ArrayList, ByVal currentposition
As Integer) As ArrayList
Dim newrecords As New ArrayList
Dim orreflection As New ArrayList
Dim table As String
Dim column As String
Dim andflag As Boolean
Dim orflag As Boolean
Do
Do
If query(currentposition
+ 1) = "TABLE" Then
'if table is specified, use this
table = query(currentposition + 2)
currentposition = currentposition + 2
ElseIf table = "" Then
'if not, then if only one table is specified in original request, use this table; if more or none throw error
Dim querycounter As Integer
Dim tablealreadypresent As Boolean = False
For querycounter = 1 To currentposition - 1
If query(querycounter) = "TABLE" Then
If tablealreadypresent = False Then
table = query(querycounter + 1)
tablealreadypresent = True
Else
Throw New Exception("Unable to resolve table to perform WHERE comparison on!")
End If
End If
Next
If tablealreadypresent = False Then
Throw New Exception("Unable to resolve table to perform WHERE comparison on!")
End If
End If
If query(currentposition + 1) = "COLUMN" Then
'if column is specified, use this
column = query(currentposition + 2)
currentposition = currentposition + 2
ElseIf column = "" Then
'if not, and there is no previous column to use, then if only one table is specified in original request, use this table;
if more or none throw error
Dim querycounter As Integer
Dim columnalreadypresent As Boolean = False
For querycounter = 1 To currentposition - 1
If query(querycounter) = "COLUMN" Then
If columnalreadypresent = False Then
column = query(querycounter + 1)
columnalreadypresent = True
Else
Throw New Exception("Unable to resolve column to perform WHERE comparison on!")
End If
End If
Next
If columnalreadypresent = False Then
Throw New Exception("Unable to resolve column to perform WHERE comparison on!")
End If
End If
'now check to see if we need an or reflection
If query.Count >= currentposition + 3 Then
Select Case query(currentposition + 3)
Case "AND"
andflag = True
orflag = False
Case "OR"
andflag = False
orflag = True
Case Else
andflag = False
orflag = False
End Select
Else
andflag = False
orflag = False
End If
'now we have decided which table and column to use, create a holder for the data of the appropriate type and run the comparison
If orflag = True Then
Dim trueflag As Boolean
Select Case GetColumnType(table, column)
Case "Char" Or "Byte" Or "Short" Or "Integer" Or "Long"
Dim recordstep As Integer
For recordstep = 0 To records.Count - 1
If IntegerComparison(query, currentposition, records(recordstep), column, table) = False Then
records.RemoveAt(recordstep)
orreflection.Add(recordstep)
End If
Next
Case "Single" Or "Double" Or "Decimal"
Dim recordstep As Integer
For recordstep = 0 To records.Count - 1
If DecimalComparison(query, currentposition, records(recordstep), column, table) = False Then
records.RemoveAt(recordstep)
orreflection.Add(recordstep)
End If
Next
Case "Date"
Dim recordstep As Integer
For recordstep = 0 To records.Count - 1
If DateComparison(query, currentposition, records(recordstep), column, table) = False Then
records.RemoveAt(recordstep)
orreflection.Add(recordstep)
End If
Next
Case "String"
Dim recordstep As Integer
For recordstep = 0 To records.Count - 1
If StringComparison(query, currentposition, records(recordstep), column, table) = False Then
records.RemoveAt(recordstep)
orreflection.Add(recordstep)
End If
Next
Case "Boolean"
Dim recordstep As Integer
For recordstep = 0 To records.Count - 1
If BooleanComparison(query, currentposition, records(recordstep), column, table) = False Then
records.RemoveAt(recordstep)
orreflection.Add(recordstep)
End If
Next
Case Else
Throw New Exception("This datatype is not supported!")
End Select
'now do a little arraylist juggling
records.TrimToSize()
Dim recordcounter As Integer
For recordcounter = 1 To records.Count
newrecords.Add(records(recordcounter))
Next
records = orreflection
Else
Dim trueflag As Boolean
Select Case GetColumnType(table, column)
Case "Char" Or "Byte" Or "Short" Or "Integer" Or "Long"
Dim recordstep As Integer
For recordstep = 0 To records.Count - 1
If IntegerComparison(query, currentposition, records(recordstep), column, table) = False Then
records.RemoveAt(recordstep)
End If
Next
Case "Single" Or "Double" Or "Decimal"
Dim recordstep As Integer
For recordstep = 0 To records.Count - 1
If DecimalComparison(query, currentposition, records(recordstep), column, table) = False Then
records.RemoveAt(recordstep)
End If
Next
Case "Date"
Dim recordstep As Integer
For recordstep = 0 To records.Count - 1
If DateComparison(query, currentposition, records(recordstep), column, table) = False Then
records.RemoveAt(recordstep)
End If
Next
Case "String"
Dim recordstep As Integer
For recordstep = 0 To records.Count - 1
If StringComparison(query, currentposition, records(recordstep), column, table) = False Then
records.RemoveAt(recordstep)
End If
Next
Case "Boolean"
Dim recordstep As Integer
For recordstep = 0 To records.Count - 1
If BooleanComparison(query, currentposition, records(recordstep), column, table) = False Then
records.RemoveAt(recordstep)
End If
Next
Case Else
Throw New Exception("This datatype is not supported!")
End Select
records.TrimToSize()
End If
'move the cursor
currentposition
= currentposition + 3
orreflection.Clear()
Loop While orflag = True
If andflag = True Then
records = newrecords
newrecords.Clear()
End If
Loop While andflag = True
Return newrecords
End Function
Private Function IntegerComparison(ByVal query As ArrayList, ByVal currentposition As Integer, ByVal
record As Integer, ByVal column As String, ByVal table As String)
Select Case
query(currentposition + 1)
Case "="
If CLng(GetData(table, column, record)) = CLng(query(currentposition + 2)) Then
Return True
End If
Case ">"
If CLng(GetData(table,
column, record)) > CLng(query(currentposition + 2)) Then
Return True
End If
Case ">="
If CLng(GetData(table,
column, record)) >= CLng(query(currentposition + 2)) Then
Return True
End If
Case "<"
If CLng(GetData(table,
column, record)) < CLng(query(currentposition + 2)) Then
Return True
End If
Case "<="
If CLng(GetData(table,
column, record)) <= CLng(query(currentposition + 2)) Then
Return True
End If
Case "<>"
If CLng(GetData(table,
column, record)) <> CLng(query(currentposition + 2)) Then
Return True
End If
Case Else
Throw New Exception("This
comparison is not supported for this datatype!")
End Select
Return False
End Function
Private Function DecimalComparison(ByVal query As ArrayList, ByVal currentposition As Integer, ByVal
record As Integer, ByVal column As String, ByVal table As String)
Select Case
query(currentposition + 1)
Case "="
If CDec(GetData(table, column, record)) = CDec(query(currentposition + 2)) Then
Return True
End If
Case ">"
If CDec(GetData(table,
column, record)) > CDec(query(currentposition + 2)) Then
Return True
End If
Case ">="
If CDec(GetData(table,
column, record)) >= CDec(query(currentposition + 2)) Then
Return True
End If
Case "<"
If CDec(GetData(table,
column, record)) < CDec(query(currentposition + 2)) Then
Return True
End If
Case "<="
If CDec(GetData(table,
column, record)) <= CDec(query(currentposition + 2)) Then
Return True
End If
Case "<>"
If CDec(GetData(table,
column, record)) <> CDec(query(currentposition + 2)) Then
Return True
End If
Case Else
Throw New Exception("This
comparison is not supported for this datatype!")
End Select
Return False
End Function
Private Function DateComparison(ByVal query As ArrayList, ByVal currentposition As Integer, ByVal
record As Integer, ByVal column As String, ByVal table As String)
Dim date1
As Date = CDate(GetData(table, column, record))
Dim date2 As Date = CDate(query(currentposition
+ 2))
Select Case query(currentposition + 1)
Case "IS"
If date1 = date2 Then
Return True
Case "ISSAMEYEAR"
If date1.Year = date2.Year Then Return True
Case "ISSAMEMONTH"
If date1.Year = date2.Year AndAlso date1.Month = date2.Month Then Return True
Case "ISSAMEDAY"
If date1.Date
= date2.Date Then Return True
Case "ISSAMEDATEHOUR"
If date1.Date = date2.Date AndAlso date1.Hour = date2.Hour Then Return True
Case "ISSAMEDATEMINUTE"
If date1.Date
= date2.Date AndAlso date1.Hour = date2.Hour AndAlso date1.Minute = date2.Minute Then Return True
Case "ISSAMEDATESECOND"
If date1.Date
= date2.Date AndAlso date1.Hour = date2.Hour AndAlso date1.Minute = date2.Minute AndAlso date1.Second = date2.Second Then
Return True
Case "ISSAMEDATEMILLISECOND"
If date1.Date = date2.Date AndAlso date1.Hour = date2.Hour AndAlso date1.Minute = date2.Minute AndAlso date1.Second = date2.Second
AndAlso date1.Millisecond = date2.Millisecond Then Return True
Case "ISSAMEDAYOFWEEK"
If date1.DayOfWeek
= date2.DayOfWeek Then Return True
Case "ISSAMEHOUR"
If date1.Hour = date2.Hour Then Return True
Case "ISSAMEMINUTE"
If date1.Hour = date2.Hour AndAlso date1.Minute = date2.Minute Then Return True
Case "ISSAMESECOND"
If date1.Hour
= date2.Hour AndAlso date1.Minute = date2.Minute AndAlso date1.Second = date2.Second Then Return True
Case "ISSAMEMILLISECOND"
If
date1.Hour = date2.Hour AndAlso date1.Minute = date2.Minute AndAlso date1.Second = date2.Second AndAlso date1.Millisecond
= date2.Millisecond Then Return True
Case "ISNOT"
If date1 <> date2 Then Return True
Case "ISNOTSAMEYEAR"
If date1.Year <> date2.Year Then Return True
Case
"ISNOTSAMEMONTH"
If date1.Year
<> date2.Year OrElse date1.Month <> date2.Month Then Return True
Case "ISNOTSAMEDAY"
If date1.Date
<> date2.Date Then Return True
Case "ISNOTSAMEDATEHOUR"
If date1.Date <> date2.Date OrElse date1.Hour <> date2.Hour Then Return True
Case "ISNOTSAMEDATEMINUTE"
If
date1.Date <> date2.Date OrElse date1.Hour <> date2.Hour OrElse date1.Minute <> date2.Minute Then Return
True
Case "ISNOTSAMEDATESECOND"
If date1.Date <> date2.Date OrElse date1.Hour <> date2.Hour OrElse date1.Minute <> date2.Minute OrElse date1.Second
<> date2.Second Then Return True
Case "ISNOTSAMEDATEMILLISECOND"
If date1.Date <> date2.Date OrElse date1.Hour <> date2.Hour OrElse date1.Minute <> date2.Minute OrElse date1.Second
<> date2.Second OrElse date1.Millisecond <> date2.Millisecond Then Return True
Case "ISNOTSAMEDAYOFWEEK"
If
date1.DayOfWeek <> date2.DayOfWeek Then Return True
Case "ISNOTSAMEHOUR"
If date1.Hour
<> date2.Hour Then Return True
Case "ISNOTSAMEMINUTE"
If date1.Hour <> date2.Hour OrElse date1.Minute <> date2.Minute Then Return True
Case "ISNOTSAMESECOND"
If date1.Hour
<> date2.Hour OrElse date1.Minute <> date2.Minute OrElse date1.Second <> date2.Second Then Return True
Case "ISNOTSAMEMILLISECOND"
If date1.Hour <> date2.Hour OrElse date1.Minute <> date2.Minute OrElse date1.Second <> date2.Second OrElse
date1.Millisecond <> date2.Millisecond Then Return True
Case "ISBEFORE"
If date1 <
date2 Then Return True
Case "ISNOTBEFORE"
If date1 >= date2 Then Return True
Case "ISAFTER"
If date1 > date2 Then Return True
Case "ISNOTAFTER"
If date1 <= date2 Then Return True
Case Else
Throw New Exception("This comparison is not supported for this datatype!")
End
Select
Return False
End Function
Private Function StringComparison(ByVal query As ArrayList, ByVal currentposition As Integer, ByVal
record As Integer, ByVal column As String, ByVal table As String)
Select Case
query(currentposition + 1)
Case "IS"
If GetData(table, column, record) = query(currentposition + 2) Then Return True
Case "ISNOT"
If GetData(table,
column, record) <> query(currentposition + 2) Then Return True
Case "ISBEFORE"
If String.Compare(GetData(table,
column, record), query(currentposition + 2)) = -1 Then Return True
Case "ISAFTER"
If String.Compare(GetData(table,
column, record), query(currentposition + 2)) = 1 Then Return True
Case "ISNOTBEFORE"
If String.Compare(GetData(table,
column, record), query(currentposition + 2)) = 1 Or GetData(table, column, record) = query(currentposition + 2) Then Return
True
Case "ISNOTAFTER"
If String.Compare(GetData(table, column, record), query(currentposition + 2)) = -1 Or GetData(table, column, record) = query(currentposition
+ 2) Then Return True
Case Else
Throw New Exception("This comparison is not supported for this datatype!")
End
Select
Return False
End Function
Private Function BooleanComparison(ByVal query As ArrayList, ByVal currentposition As Integer, ByVal
record As Integer, ByVal column As String, ByVal table As String)
Select Case
query(currentposition + 1)
Case "IS"
If GetData(table, column, record) = query(currentposition + 1) Then Return True
Case "ISNOT"
If GetData(table,
column, record) <> query(currentposition + 1) Then Return True
Case Else
Throw New Exception("This
comparison is not supported for this datatype!")
End Select
Return False
End Function
#End Region
#Region "Database Structure Info"
Private Function GetNoOfRecords() As Integer
'does what
it says on the tin
End Function
Private Function GetColumnType(ByVal table As String, ByVal column As String) As String
'similar philosiphy to above
End Function
#End Region
#Region "Table Building"
Private Function BuildTable(ByVal query As ArrayList, ByVal records As ArrayList) As String
Dim rtsb As New Text.StringBuilder
Dim writer As New StringWriter(rtsb)
writer.WriteLine("<DQL 0.1 RETURNTABLE>")
writer.WriteLine("<STRUCT>")
Dim tables As New ArrayList
Dim columns As New ArrayList
Dim andflag As Boolean
Dim table As String
Dim currentposition As Integer = 1
Dim recordcounter As Integer
Dim counter As Integer
Do
If query(currentposition + 1) = "TABLE" Then
table = query(currentposition + 2)
currentposition = currentposition + 2
Else
If table = "" Then Throw New Exception("Unable to resolve table to read data from!")
End If
If query(currentposition + 1) = "COLUMN" Then
columns.Add(query(currentposition + 2))
tables.Add(table)
Else
Throw New Exception("Unable to resolve column to read data from!")
End If
If query.Count > currentposition + 2 AndAlso
query(currentposition + 3) = "AND" Then
currentposition = currentposition + 3
andflag = True
Else
andflag = False
End If
Loop
writer.WriteLine("<COLUMNS>" & columns.Count & "</COLUMNS>")
For counter = 1 To columns.Count
writer.WriteLine("<COLUMN
" & counter & ">")
writer.WriteLine("<NAME>"
& columns(counter - 1) & "</NAME>")
writer.WriteLine("TYPE"
& GetColumnType(tables(counter - 1), columns(counter)) & "</TYPE>")
writer.WriteLine("</COLUMN " & counter & ">")
Next
writer.WriteLine("/STRUCT")
writer.WriteLine("<DATA>")
For recordcounter = 1 To records.Count
writer.WriteLine("<RECORD
" & recordcounter & ">")
For counter = 1
To columns.Count
writer.WriteLine("<"
& DirectCast(columns(counter - 1), String).ToUpper & ">" & GetData(tables(counter - 1), columns(counter - 1),
records(recordcounter - 1)) & "</" & DirectCast(columns(counter - 1), String).ToUpper & ">")
Next
writer.WriteLine("</RECORD " & recordcounter
& ">")
Next
writer.WriteLine("</DATA>")
writer.WriteLine("</DQL 0.1 RETURNTABLE>")
writer.Close()
Return rtsb.ToString
End Function
Private Function Sort(ByVal query As ArrayList, ByVal currentposition As Integer, ByVal records As
Integer)
Dim table As String
Dim
column As String
Dim counter As Integer
Dim returnarray As New ArrayList
'find what to sort by
If query(currentposition + 1) = "TABLE" Then
table =
query(currentposition + 2)
currentposition = currentposition
+ 2
ElseIf query(1) = "TABLE" AndAlso query(5) <> "AND" Then
table = query(2)
Else
Throw New Exception("Could not resolve table to sort by!")
End If
If query(currentposition + 1) = "COLUMN" Then
column
= query(currentposition + 1)
currentposition = currentposition
+ 2
ElseIf query(3) = "COLUMN" And query(5) <> "AND" Then
column = query(4)
Else
Throw New Exception("Could not resolve column to sort by!")
End If
Dim hashtable As New Hashtable
Select Case GetColumnType(table, column)
Case "Char" Or "Byte" Or "Short" Or "Integer" Or "Long" Or "Single" Or "Double" Or "Decimal"
Dim holder As Decimal
For counter
= 1 To records
holder = GetData(table, column, counter)
hashtable.Add(counter - 1, holder)
returnarray.Add(holder)
Next
If query(currentposition + 2) = "ASC" Then
returnarray.Sort()
ElseIf query(currentposition
+ 2) = "DESC" Then
returnarray.Sort()
Dim mirrorarray As New ArrayList
For counter = returnarray.Count - 1 To 0 Step -1
mirrorarray.Add(returnarray(counter))
Next
returnarray = mirrorarray
mirrorarray = Nothing
Else
Throw New Exception("This sort criteria is not supported!")
End If
Case "Date"
Dim holder As Date
For counter
= 1 To records
holder = GetData(table, column, counter)
hashtable.Add(counter - 1, holder)
returnarray.Add(holder)
Next
If query(currentposition + 2) = "ASC" Then
returnarray.Sort()
ElseIf query(currentposition
+ 2) = "DESC" Then
returnarray.Sort()
Dim mirrorarray As New ArrayList
For counter = returnarray.Count - 1 To 0 Step -1
mirrorarray.Add(returnarray(counter))
Next
returnarray = mirrorarray
mirrorarray = Nothing
Else
Throw New Exception("This sort criteria is not supported!")
End If
Case "String"
Dim holder As String
For counter
= 1 To records
holder = GetData(table, column, counter)
hashtable.Add(counter - 1, holder)
returnarray.Add(holder)
Next
If query(currentposition + 2) = "ASC" Then
returnarray.Sort()
ElseIf query(currentposition
+ 2) = "DESC" Then
returnarray.Sort()
Dim mirrorarray As New ArrayList
For counter = returnarray.Count - 1 To 0 Step -1
mirrorarray.Add(returnarray(counter))
Next
returnarray = mirrorarray
mirrorarray = Nothing
Else
Throw New Exception("This sort criteria is not supported!")
End If
Case "Boolean"
Dim holder As Boolean
For counter
= 1 To records
holder = GetData(table, column, counter)
hashtable.Add(counter - 1, holder)
returnarray.Add(holder)
Next
If query(currentposition + 2) = "ASC" Then
returnarray.Sort()
ElseIf query(currentposition
+ 2) = "DESC" Then
returnarray.Sort()
Dim mirrorarray As New ArrayList
For counter = returnarray.Count - 1 To 0 Step -1
mirrorarray.Add(returnarray(counter))
Next
returnarray = mirrorarray
mirrorarray = Nothing
Else
Throw New Exception("This sort criteria is not supported!")
End If
Case Else
Throw New Exception("This datatype is not supported!")
End Select
'run through every element in the array and use the hashtable in reverse to find the key
Dim indexarray As New ArrayList
Dim newholder As String
Dim recordcounter As Integer
For counter = 0 To returnarray.Count - 1
newholder = returnarray(counter)
For recordcounter =
1 To records
If hashtable.Item(recordcounter)
= newholder AndAlso indexarray.Contains(recordcounter) = False Then
indexarray.Add(recordcounter)
Exit For
End If
Next
Next
Return indexarray
End Function
#End Region
#Region "Basic Data Retrieval"
Private Sub ReadPast(ByRef reader As StringReader, ByVal value As String)
Dim bufferlength As Integer = value.Length
Dim buffer As String
Dim loopflag As Boolean = True
Do
buffer = buffer & reader.Read
If buffer.Length >
bufferlength Then
buffer = buffer.Substring(1)
End If
If buffer = value Then Return
Loop Until reader.Peek = -1
Return
End Sub
Private Function GetData(ByVal table As String, ByVal column As String, ByVal record As Integer) As
String
'take a guess
'pulls a
specific piece of data from specified location and returns it in string form
End Function
#End Region
End Class