Skip to content

Commit

Permalink
Improved creating multiple table joins. Closes #6. Closes #7.
Browse files Browse the repository at this point in the history
Creating a single table join remains the same, there is no breaking change to the API. However, creating two or more table joins is now more intuitive. The return value from 'table1AndTable2 = sqlSelect.Tables.Joins.Add(table1, Type.Inner, table2)' can then be used in subsequent table join calls i.e. 'sqlSelect.Tables.Joins.Add(table1AndTable2 , Type.Inner, table3)'. This indicates that the table1AndTable2 join created in the first step is then joined to table3.

Also changed the SQLSelectTableJoinCondition to accept SQLExpression objects rather than the left and right table field names. This was required because now that the left table for a join can be either a table or a joined table the left field table alias may be unknown if it is an table join. In which case the table alias must come from an SQLFieldExpression (inherits SQLExpression) which will indicate the table alias. The way it was working where it would obtain the table name from the join was incorrect. So also closing issue #7.
  • Loading branch information
hisystems committed Mar 4, 2012
1 parent c9cf306 commit 6f65497
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 65 deletions.
2 changes: 1 addition & 1 deletion SQL/Select/SQLSelectTableBase.vb
Expand Up @@ -16,7 +16,7 @@ Namespace SQL
Protected MustOverride ReadOnly Property Source(ByVal eConnectionType As Database.ConnectionType) As String
Friend MustOverride Function GetPrefix() As String

Private pstrAlias As String
Private pstrAlias As String = String.Empty

Public Sub New()

Expand Down
53 changes: 24 additions & 29 deletions SQL/Select/SQLSelectTableJoin.vb
Expand Up @@ -12,6 +12,7 @@ Option Explicit On
Namespace SQL

Public Class SQLSelectTableJoin
Inherits SQLSelectTableBase

Public Enum Type
Inner
Expand Down Expand Up @@ -94,30 +95,17 @@ Namespace SQL
End Set
End Property

Friend ReadOnly Property SQL(ByVal eConnectionType As Database.ConnectionType) As String
Get
Friend Overrides Function GetPrefix() As String

Dim strSQL As String = String.Empty
Dim strJoin As String = String.Empty

Select Case Me.TheType
Case SQLSelectTableJoin.Type.Inner
strJoin = "INNER JOIN"
Case SQLSelectTableJoin.Type.FullOuter
strJoin = "FULL OUTER JOIN"
Case SQLSelectTableJoin.Type.LeftOuter
strJoin = "LEFT OUTER JOIN"
Case SQLSelectTableJoin.Type.RightOuter
strJoin = "RIGHT OUTER JOIN"
End Select

If Index() = 0 Then
strSQL = pobjLeftTable.SQL(eConnectionType)
Else
strSQL = pobjParent(Index() - 1).SQL(eConnectionType)
End If
Return MyBase.Alias

End Function

strSQL &= " " & strJoin & " " & pobjRightTable.SQL(eConnectionType)
Protected Overrides ReadOnly Property Source(ByVal eConnectionType As Database.ConnectionType) As String
Get

Dim strSQL As String = _
pobjLeftTable.SQL(eConnectionType) & " " & GetJoinString(Me.TheType) & " " & pobjRightTable.SQL(eConnectionType)

If Not pobjConditions Is Nothing AndAlso Not pobjConditions.IsEmpty Then
strSQL &= " ON " & pobjConditions.SQL(eConnectionType)
Expand All @@ -129,13 +117,20 @@ Namespace SQL
End Get
End Property

Private Function Index() As Integer

For intIndex As Integer = 0 To pobjParent.Count - 1
If pobjParent(intIndex) Is Me Then
Return intIndex
End If
Next
Private Shared Function GetJoinString(eJoinType As Type) As String

Select Case eJoinType
Case SQLSelectTableJoin.Type.Inner
Return "INNER JOIN"
Case SQLSelectTableJoin.Type.FullOuter
Return "FULL OUTER JOIN"
Case SQLSelectTableJoin.Type.LeftOuter
Return "LEFT OUTER JOIN"
Case SQLSelectTableJoin.Type.RightOuter
Return "RIGHT OUTER JOIN"
Case Else
Throw New NotImplementedException(eJoinType.ToString)
End Select

End Function

Expand Down
39 changes: 14 additions & 25 deletions SQL/Select/SQLSelectTableJoinCondition.vb
Expand Up @@ -13,9 +13,9 @@ Namespace SQL

Public Class SQLSelectTableJoinCondition

Private pstrLeftTableFieldName As String
Private pobjLeftExpression As SQLExpression
Private peCompare As ComparisonOperator
Private pstrRightTableFieldName As String
Private pobjRightExpression As SQLExpression
Private pobjParent As SQLSelectTableJoinConditions

Friend Sub New(ByVal objParent As SQLSelectTableJoinConditions)
Expand All @@ -24,16 +24,16 @@ Namespace SQL

End Sub

Public Property RightTableFieldName() As String
Public Property RightExpression() As SQLExpression
Get

Return pstrRightTableFieldName
Return pobjRightExpression

End Get

Set(ByVal Value As String)
Set(ByVal Value As SQLExpression)

pstrRightTableFieldName = Value
pobjRightExpression = Value

End Set
End Property
Expand All @@ -52,38 +52,27 @@ Namespace SQL
End Set
End Property

Public Property LeftTableFieldName() As String
Public Property LeftExpression() As SQLExpression
Get

Return pstrLeftTableFieldName
Return pobjLeftExpression

End Get

Set(ByVal Value As String)
Set(ByVal Value As SQLExpression)

pstrLeftTableFieldName = Value
pobjLeftExpression = Value

End Set
End Property

Friend ReadOnly Property SQL(ByVal eConnectionType As Database.ConnectionType) As String
Get

Dim strSQL As String

If LeftTableFieldName.Trim = String.Empty Then
Throw New Exceptions.DatabaseObjectsException("LeftTableFieldName has not been specified.")
End If

If RightTableFieldName.Trim = String.Empty Then
Throw New Exceptions.DatabaseObjectsException("RightTableFieldName has not been specified.")
End If

strSQL = _
SQLFieldNameAndTablePrefix(pobjParent.Parent.LeftTable, LeftTableFieldName, eConnectionType) & " " & _
SQLConvertCompare(Compare) & " " & SQLFieldNameAndTablePrefix(pobjParent.Parent.RightTable, RightTableFieldName, eConnectionType)

Return strSQL
Return _
pobjLeftExpression.SQL(eConnectionType) & " " & _
SQLConvertCompare(Compare) & " " & _
pobjRightExpression.SQL(eConnectionType)

End Get
End Property
Expand Down
52 changes: 44 additions & 8 deletions SQL/Select/SQLSelectTableJoinConditions.vb
Expand Up @@ -44,25 +44,61 @@ Namespace SQL
ByVal eCompare As ComparisonOperator, _
ByVal strRightTableFieldName As String) As SQLSelectTableJoinCondition

'Add the AND operator if an operator hasn't been called after the previous Add call
If pobjLogicalOperators.Count() < pobjConditions.Count() Then
Me.AddLogicalOperator(LogicalOperator.And)
'The Add function is here basically for backward compatibility when the conditions could only accept field names and the left and right tables from the parent join were used as table aliases.
'Now that that SQLSelectTableBase is being used (which can represent a table or joined tables) we need to check that parent left and right tables are only SQLSelectTable objects.
If Not TypeOf pobjParent.LeftTable Is SQLSelectTable Then
Throw New ArgumentException("The left table is expected to be an SQLSelectTable so that the left table alias can be utilised for the strLeftTableFieldName argument. Use the Add(SQLExpression, ComparisonOperator, SQLExpression) overload instead.")
ElseIf Not TypeOf pobjParent.RightTable Is SQLSelectTable Then
Throw New ArgumentException("The right table is expected to be an SQLSelectTable so that the right table alias can be utilised for the strRightTableFieldName argument. Use the Add(SQLExpression, ComparisonOperator, SQLExpression) overload instead.")
End If

If eCompare = ComparisonOperator.Like Or eCompare = ComparisonOperator.NotLike Then
Throw New Exceptions.DatabaseObjectsException("LIKE operator is not supported for table joins.")
End If
EnsureComparisonOperatorValid(eCompare)
AddLogicalOperatorIfRequired()

Add = New SQLSelectTableJoinCondition(Me)
Add.LeftExpression = New SQLFieldExpression(DirectCast(pobjParent.LeftTable, SQLSelectTable), strLeftTableFieldName)
Add.Compare = eCompare
Add.RightExpression = New SQLFieldExpression(DirectCast(pobjParent.RightTable, SQLSelectTable), strRightTableFieldName)

pobjConditions.Add(Add)

End Function

Public Function Add( _
ByVal objLeftExpression As SQLExpression, _
ByVal eCompare As ComparisonOperator, _
ByVal objRightExpression As SQLExpression) As SQLSelectTableJoinCondition

EnsureComparisonOperatorValid(eCompare)
AddLogicalOperatorIfRequired()

Add = New SQLSelectTableJoinCondition(Me)

Add.LeftTableFieldName = strLeftTableFieldName
Add.LeftExpression = objLeftExpression
Add.Compare = eCompare
Add.RightTableFieldName = strRightTableFieldName
Add.RightExpression = objRightExpression

pobjConditions.Add(Add)

End Function

Private Sub AddLogicalOperatorIfRequired()

'Add the AND operator if an operator hasn't been called after the previous Add call
If pobjLogicalOperators.Count() < pobjConditions.Count() Then
Me.AddLogicalOperator(LogicalOperator.And)
End If

End Sub

Private Sub EnsureComparisonOperatorValid(eCompare As ComparisonOperator)

If eCompare = ComparisonOperator.Like Or eCompare = ComparisonOperator.NotLike Then
Throw New Exceptions.DatabaseObjectsException("LIKE operator is not supported for table joins.")
End If

End Sub

Public Sub AddLogicalOperator( _
ByVal eLogicalOperator As LogicalOperator)

Expand Down
4 changes: 2 additions & 2 deletions SQL/Select/SQLSelectTableJoins.vb
Expand Up @@ -33,9 +33,9 @@ Namespace SQL
End Function

Public Function Add( _
ByVal objLeftTable As SQLSelectTable, _
ByVal objLeftTable As SQLSelectTableBase, _
ByVal eJoin As SQLSelectTableJoin.Type, _
ByVal objRightTable As SQLSelectTable) As SQLSelectTableJoin
ByVal objRightTable As SQLSelectTableBase) As SQLSelectTableJoin

Dim objJoin As SQLSelectTableJoin = New SQLSelectTableJoin(Me)

Expand Down

0 comments on commit 6f65497

Please sign in to comment.