Public Sub BuildQuery(WithPageLimit As Boolean) As Object()
Dim c As Int
Dim n As Int
Dim SortColumn As String
Dim strFind As String
Dim sb As StringBuilder
Dim lstCurrentArgs As List
Dim lstCurrentArgsIsText As List
Dim TotalCount As Int
sb.Initialize
sb.Append("SELECT rowid")
For Each col As B4XTableColumn In VisibleColumns
If col.ColumnType = COLUMN_TYPE_VOID Then Continue
sb.Append(",").Append(col.SQLID)
If col.InternalSortMode <> "" Then
SortColumn = " ORDER BY " & col.SQLID & " " & col.InternalSortMode
End If
Next
sb.Append(" FROM ").Append(SQLTableName).Append(" ")
lstCurrentArgs.Initialize
lstCurrentArgsIsText.Initialize
Log("B4XTable, BuildQuery, miSearchConditions: " & miSearchConditions)
If miSearchConditions = 0 Then
TotalCount = CountAll
mCurrentCount = CountAll
'Log("B4XTable, BuildQuery, mCurrentCount: " & mCurrentCount)
miCountOfPages = Ceil(mCurrentCount / mRowsPerPage)
Else
For Each col As B4XTableColumn In VisibleColumns
If col.Searchable Then
For n = 0 To arrCheckConditions(c) - 1
lstCurrentArgsIsText.Add(arrConditions(c, n).bIsTextArgument)
strFind = arrConditions(c, n).strSearchText
'Log("BuildQuery, strFind: " & strFind)
If lstCurrentArgs.Size = 0 Then
sb.Append(" WHERE ")
Else
If arrConditions(c, n).bSQL_OR Then
'this used to be all OR
sb.Append(" OR ")
Else
sb.Append(" AND ")
End If
End If
If col.ColumnType = COLUMN_TYPE_INTEGER Or col.ColumnType = COLUMN_TYPE_DOUBLE Then
If arrConditions(c, n).strOperator.Length = 0 Then
sb.Append(col.SQLID).Append(" = ? ") 'this may not always work with double values
lstCurrentArgs.Add(strFind)
Else 'If arrConditions(c, n).strOperator.Length = 0
If arrConditions(c, n).strOperator.StartsWith("between") Then
Dim arrFind() As String = Regex.Split(",", strFind)
If col.ColumnType = COLUMN_TYPE_DOUBLE Then
Dim arrFindDouble(2) As Double
arrFindDouble(0) = arrFind(0)
arrFindDouble(1) = arrFind(1)
sb.Append(col.SQLID).Append(" between cast(? as real) and cast(? as real)")
lstCurrentArgs.Add(arrFindDouble(0))
lstCurrentArgs.Add(arrFindDouble(1))
Else
Dim arrFindInt(2) As Int
arrFindInt(0) = arrFind(0)
arrFindInt(1) = arrFind(1)
sb.Append(col.SQLID).Append(" between cast(? as integer) and cast(? as integer)")
lstCurrentArgs.Add(arrFindInt(0))
lstCurrentArgs.Add(arrFindInt(1))
End If
Else
If arrConditions(c, n).strOperator.StartsWith("length") Then
Select Case arrConditions(c, n).strOperator
Case "length ="
sb.Append("length(coalesce(").Append(col.SQLID).Append(", '')) = cast(? as integer) ")
Case "length >"
sb.Append("length(coalesce(").Append(col.SQLID).Append(", '')) > cast(? as integer) ")
Case "length <"
sb.Append("length(coalesce(").Append(col.SQLID).Append(", '')) < cast(? as integer) ")
Case "length <>"
sb.Append("length(coalesce(").Append(col.SQLID).Append(", '')) <> cast(? as integer) ")
End Select
Else
sb.Append(col.SQLID).Append(" ").Append(arrConditions(c, n).strOperator).Append(" ? ")
End If
lstCurrentArgs.Add(strFind)
End If
End If 'If arrConditions(c, n).strOperator.Length = 0
Else 'If col.ColumnType = COLUMN_TYPE_INTEGER Or col.ColumnType = COLUMN_TYPE_DOUBLE
If arrConditions(c, n).strOperator.StartsWith("between") Then
Dim arrFind() As String = Regex.Split(",", strFind)
sb.Append(col.SQLID).Append(" between ? and ?")
lstCurrentArgs.Add(arrFind(0))
lstCurrentArgs.Add(arrFind(1))
Else
If arrConditions(c, n).strOperator.StartsWith("length") Then
Select Case arrConditions(c, n).strOperator
Case "length ="
sb.Append("length(coalesce(").Append(col.SQLID).Append(", '')) = cast(? as integer) ")
Case "length >"
sb.Append("length(coalesce(").Append(col.SQLID).Append(", '')) > cast(? as integer) ")
Case "length <"
sb.Append("length(coalesce(").Append(col.SQLID).Append(", '')) < cast(? as integer) ")
Case "length <>"
sb.Append("length(coalesce(").Append(col.SQLID).Append(", '')) <> cast(? as integer) ")
End Select
lstCurrentArgs.Add(strFind)
Else
If arrConditions(c,n).bWildCard Then
If arrConditions(c,n).bCaseSensitive Then
sb.Append(col.SQLID).Append(" GlOB ? ")
If arrConditions(c,n).bPrefixSearch Then
lstCurrentArgs.Add(strFind & "*")
Else
lstCurrentArgs.Add("*" & strFind & "*")
End If
Else
sb.Append(col.SQLID).Append(" LIKE ? ")
If arrConditions(c,n).bPrefixSearch Then
lstCurrentArgs.Add(strFind & "%")
Else
lstCurrentArgs.Add("%" & strFind & "%")
End If
End If
Else
If arrConditions(c, n).bCaseSensitive Then
If arrConditions(c, n).strOperator.Length = 0 Then
sb.Append(col.SQLID).Append(" = ? ")
Else
sb.Append(col.SQLID).Append(" ").Append(arrConditions(c, n).strOperator).Append(" ? ")
End If
lstCurrentArgs.Add(strFind)
Else
If arrConditions(c, n).strOperator.Length = 0 Then
sb.Append("lower(").Append(col.SQLID).Append(") = ? ")
Else
sb.Append("lower(").Append(col.SQLID).Append(") ").Append(arrConditions(c, n).strOperator).Append(" ? ")
End If
lstCurrentArgs.Add(strFind.ToLowerCase)
End If
End If
End If
End If
End If 'If col.ColumnType = COLUMN_TYPE_INTEGER Or col.ColumnType = COLUMN_TYPE_DOUBLE
Next
End If
c = c + 1
Next
TotalCount = -1 'so TotalCount will be -1 if we are doing a search
End If
Log("B4XTable, BuildQuery, SortColumn.Length: " & SortColumn.Length)
If SortColumn <> "" Then
sb.Append(SortColumn)
End If
If sb.ToString.ToLowerCase.Contains(" where ") Then
strCurrentWhereClause = GetWhereClauseFromQuery(sb.ToString)
Log("BuildQuery, strCurrentWhereClause: |" & strCurrentWhereClause & "|")
End If
If WithPageLimit Then
Dim limit As Int = mRowsPerPage
If TotalCount < 0 Then limit = limit + 1 'this will be the case if we are doing a search
sb.Append($" LIMIT ${mFirstRowIndex}, ${limit}"$) 'LIMIT offset, row_count
End If
Log("B4XTable, BuildQuery, sb.ToString: " & sb.ToString)
#if B4A
Dim aargs(lstCurrentArgs.Size) As String
For i = 0 To lstCurrentArgs.Size - 1
aargs(i) = lstCurrentArgs.Get(i)
Next
#else
Dim aargs As List = args
#End If
Return Array(sb.ToString, aargs, TotalCount)
End Sub
Private Sub ImplUpdateDataFromQuery (Query As String, Args As Object, TotalCount As Int, DontSleep As Boolean)
Dim i As Int
Dim iCol As Int
Dim arrArgs() As String = Args
SQLIndex = SQLIndex + 1
If mRowsPerPage = 0 Then Return
Dim MyIndex As Int = SQLIndex
If DontSleep = False Then
Sleep(40)
End If
If MyIndex <> SQLIndex Then
Return
End If
VisibleRowIds.Clear
Dim rs As ResultSet = sql1.ExecQuery2(Query, arrArgs)
'Log("B4XTable, ImplUpdateDataFromQuery, rs.RowCount: " & rs.RowCount)
Dim success As Boolean = True
If success Then
Dim RowNumber As Int = 1
Do While RowNumber <= mRowsPerPage And rs.NextRow
VisibleRowIds.Add(rs.GetLong("rowid"))
iCol = 0
For Each c As B4XTableColumn In VisibleColumns
Dim lbl As B4XView = GetLabelFromColumn(c, RowNumber)
Select c.ColumnType
Case COLUMN_TYPE_TEXT
SetTextToCell(rs.GetString(c.SQLID), lbl, c.Searchable, iCol)
Case COLUMN_TYPE_INTEGER
'c.Formatter.FormatLabel(rs.GetInt(c.SQLID), lbl)
lbl.Text = rs.GetInt(c.SQLID)
Case COLUMN_TYPE_DOUBLE
c.Formatter.FormatLabel(rs.GetDouble(c.SQLID), lbl)
Case COLUMN_TYPE_DATE
lbl.Text = DateTime.Date(rs.GetLong(c.SQLID))
End Select
iCol = iCol + 1
Next
RowNumber = RowNumber + 1
Loop
Dim bAreThereMoreResults As Boolean = RowNumber = mRowsPerPage + 1 And rs.NextRow
rs.Close
For i = RowNumber To mRowsPerPage
iCol = 0
For Each c As B4XTableColumn In VisibleColumns
#if B4J
SetTextToCell("", GetLabelFromColumn(c, i), c.Searchable, iCol)
#else
GetLabelFromColumn(c, i).Text = ""
#End If
iCol = iCol + 1
Next
VisibleRowIds.Add(0)
Next
mLastRowIndex = mFirstRowIndex - 2 + RowNumber
If TotalCount > -1 Then
'as the previous and next page views are not done in the custom view anymore we are just dealing with Boolean variables here
'---------------------------------------------------------------------------------------------------------------------------
bCanDoNextPage = mLastRowIndex < TotalCount - 1
mCurrentCount = TotalCount 'this used to be just past this If block, but that meant mCurrentCount could be -1 (seems to indicate that current row count is unknown)
Else
'TotalCount -1 means we ran a search and mCurrentCount will be set later by SetCurrentCountAfterSearch (run from the DataUpdated Event)
'--------------------------------------------------------------------------------------------------------------------------------------
bCanDoNextPage = bAreThereMoreResults
'this is to get the total number of rows obtained in the search (user initiated search) and pass this to the B4XPage
'-------------------------------------------------------------------------------------------------------------------
marrSearchArgs = arrArgs
End If
bCanDoPreviousPage = mFirstRowIndex > 0
'This used to be here, see above comment!
'----------------------------------------
'mCurrentCount = TotalCount
Log("B4XTable, ImplUpdateDataFromQuery, mCurrentCount: " & mCurrentCount)
miCountOfPages = Ceil(mCurrentCount / mRowsPerPage)
mCurrentPage = Ceil(mFirstRowIndex / mRowsPerPage) + 1
rs.Close
Else
Log(LastException)
End If
If xui.SubExists(mCallBack, mEventName & "_DataUpdated", 0) Then
CallSub(mCallBack, mEventName & "_DataUpdated")
End If
End Sub