diff --git a/src/Runtime/XSharp.SQLRdd/RDD/SQLRDD-Main.prg b/src/Runtime/XSharp.SQLRdd/RDD/SQLRDD-Main.prg index 64e2db874a..33fc286e95 100644 --- a/src/Runtime/XSharp.SQLRdd/RDD/SQLRDD-Main.prg +++ b/src/Runtime/XSharp.SQLRdd/RDD/SQLRDD-Main.prg @@ -65,7 +65,10 @@ partial class SQLRDD inherit Workarea return 0 endif try - return self:_builder:GetOrderKeyNo() + SELF:_command:CommandText := _builder:BuildRowNumberStatement(self:RecNo) + var result := SELF:_command:ExecuteScalar(SELF:_oTd:Name) + var iResult := Convert.ToUInt32(result) + return iResult catch as Exception return 0 end try diff --git a/src/Runtime/XSharp.SQLRdd/RDD/SQLRDD-Private.prg b/src/Runtime/XSharp.SQLRdd/RDD/SQLRDD-Private.prg index 6f2af289e0..a8fde2d65b 100644 --- a/src/Runtime/XSharp.SQLRdd/RDD/SQLRDD-Private.prg +++ b/src/Runtime/XSharp.SQLRdd/RDD/SQLRDD-Private.prg @@ -550,7 +550,7 @@ partial class SQLRDD endif var maxTableSize := _oTd:PageSize * _oTd:BufferSize var sizeBefore := maxTableSize - _oTd:PageSize - var lForward := nNewPageNo > _currentPageNo + var lForward := nNewPageNo >= _currentPageNo if self:RowCount + _oTd:PageSize > maxTableSize // We must delete rows if lForward @@ -605,6 +605,8 @@ partial class SQLRDD SELF:_command:CommandText := _builder:BuildRowNumberStatement(nRec) var result := SELF:_command:ExecuteScalar(SELF:_oTd:Name) var iResult := Convert.ToInt64(result) + // shouldn't this be ToUInt32? + // determine correct page SELF:_currentPageNo := (INT) ((iResult - 1) / SELF:_oTd:PageSize) + 1 SELF:_ClearTable() diff --git a/src/Runtime/XSharp.SQLRdd/Support/SqlDbTableCommandBuilder.prg b/src/Runtime/XSharp.SQLRdd/Support/SqlDbTableCommandBuilder.prg index afc24c9608..9fe159f8ae 100644 --- a/src/Runtime/XSharp.SQLRdd/Support/SqlDbTableCommandBuilder.prg +++ b/src/Runtime/XSharp.SQLRdd/Support/SqlDbTableCommandBuilder.prg @@ -190,8 +190,37 @@ internal class SqlDbTableCommandBuilder METHOD BuildRowNumberStatement(nRec as DWORD) AS STRING var sb := System.Text.StringBuilder{} + + // current filters, scopes and conditions must be respected + // to calculate the correct pagenumber ! + var currentOrder := _oRdd:CurrentOrder + var whereClauses := List{} + if SELF:_oTable:HasServerFilter .and. !String.IsNullOrEmpty(_oTable:ServerFilter) + whereClauses:Add(_oTable:ServerFilter) + endif + if currentOrder != null + var sWhere := currentOrder:GetScopeClause() + if !String.IsNullOrEmpty(sWhere) + whereClauses:Add(sWhere) + endif + sWhere := currentOrder:SqlWhere + if !String.IsNullOrEmpty(sWhere) + whereClauses:Add(sWhere) + endif + endif + var sWhereClause := SELF:CombineWhereClauses(whereClauses) + sWhereClause := _connection:RaiseStringEvent(_connection, SqlRDDEventReason.WhereClause, _cTable, sWhereClause) + sb:Append(Provider:RowNumberStatement) - sb:Replace(SqlDbProvider.TableNameMacro, Provider:QuoteIdentifier(self:_oTable:RealName)) + + // not sure if this is a clever solution, + // but WhereMacro is already used for nRec + var cFromWhere := Provider:QuoteIdentifier(self:_oTable:RealName) + if ! String.IsNullOrEmpty(sWhereClause) + cFromWhere += SqlDbProvider.WhereClause+sWhereClause + endif + sb:Replace(SqlDbProvider.TableNameMacro, cFromWhere) + var cOrderby := Functions.List2String(_oRdd:CurrentOrder:OrderList) if SELF:_oTable:HasRecnoColumn if ! String.IsNullOrEmpty(cOrderby) @@ -320,161 +349,6 @@ internal class SqlDbTableCommandBuilder endif return maxVal + 1 - method GetOrderKeyNo() as DWORD - /* - SELECT COUNT(*) - FROM table - WHERE - [FILTER], - [SCOPE], - [ORDERCONDITION], - [(K1 {<|>} @K1) - OR (K1 = @K1 AND K2 {<|>} @K2) - OR ... - OR (K1 = @K1 AND ... AND xs_recno <= @xs_recno)] - */ - - local nKeyNo as DWORD - local scopeWhere := null as string - local sWhereClause := null as string - - var sb := System.Text.StringBuilder{} - var currentOrder := _oRdd:CurrentOrder - var recNoSql := Functions.XsValueToSqlValue(SELF:_oRdd:RecNo) - - sb:Append(SqlDbProvider.SelectClause) - sb:Append("count(*)") - sb:Append(SqlDbProvider.FromClause) - sb:Append(Provider.QuoteIdentifier(_oTable:RealName)) - - var whereClauses := List{} - - if SELF:_oTable:HasServerFilter .and. !String.IsNullOrEmpty(_oTable:ServerFilter) - whereClauses:Add(_oTable:ServerFilter) - endif - - if currentOrder != null - var cCompareOp := " < " - if currentOrder:Descending - cCompareOp := " > " - endif - - scopeWhere := currentOrder:GetScopeClause() - if !String.IsNullOrEmpty(scopeWhere) - whereClauses:Add(scopeWhere) - endif - - if !String.IsNullOrEmpty(currentOrder:SqlWhere) - whereClauses:Add(currentOrder:SqlWhere) - endif - - var rawParts := currentOrder:SQLKey:Split({'+'}) - var keyParts := List{} - - foreach var cPart in rawParts - var cExpr := cPart:Trim() - if !String.IsNullOrEmpty(cExpr) - keyParts:Add(cExpr) - endif - next - - if keyParts:Count = 0 - return 0 - endif - - var sbWhere := StringBuilder{} - var sbEquals := StringBuilder{} - - var sbValue := StringBuilder{} - sbValue:Append(SqlDbProvider.SelectClause) - sbValue:Append(String.Join(",", keyParts)) - sbValue:Append(SqlDbProvider.FromClause) - sbValue:Append(Provider.QuoteIdentifier(_oTable:RealName)) - sbValue:Append(SqlDbProvider.WhereClause) - sbValue:Append(SELF:_oTable:RecnoColumn) - sbValue:Append("=") - sbValue:Append(recNoSql) - - var reader := _connection:ExecuteReader(sbValue:ToString()) - try - if !reader:Read() - return 0 - endif - - for var nPart := 0 upto keyParts:Count - 1 - var cExpr := keyParts[nPart] - var uKeyVal := reader[nPart] - var cKeyVal := Functions.XsValueToSqlValue(uKeyVal) - - if nPart = 0 - sbWhere:Append("(") - sbWhere:Append(cExpr) - sbWhere:Append(cCompareOp) - sbWhere:Append(cKeyVal) - sbWhere:Append(")") - else - sbWhere:Append(SqlDbProvider.OrClause) - sbWhere:Append("(") - sbWhere:Append(sbEquals:ToString()) - sbWhere:Append(SqlDbProvider.AndClause) - sbWhere:Append(cExpr) - sbWhere:Append(cCompareOp) - sbWhere:Append(cKeyVal) - sbWhere:Append(")") - endif - - if sbEquals:Length > 0 - sbEquals:Append(SqlDbProvider.AndClause) - endif - sbEquals:Append(cExpr) - sbEquals:Append(" = ") - sbEquals:Append(cKeyVal) - next - - if sbEquals:Length = 0 - return 0 - endif - - if sbWhere:Length > 0 - sbWhere:Append(SqlDbProvider.OrClause) - endif - - sbWhere:Append("(") - sbWhere:Append(sbEquals:ToString()) - sbWhere:Append(SqlDbProvider.AndClause) - sbWhere:Append(SELF:_oTable:RecnoColumn) - sbWhere:Append(" <= ") - sbWhere:Append(recNoSql) - sbWhere:Append(")") - - sWhereClause := sbWhere:ToString() - - finally - reader:Dispose() - end try - - else - sWhereClause := SELF:_oTable:RecnoColumn + " <= " + recNoSql - endif - - if !String.IsNullOrEmpty(sWhereClause) - whereClauses:Add(sWhereClause) - endif - - sWhereClause := SELF:CombineWhereClauses(whereClauses) - sWhereClause := _connection:RaiseStringEvent(_connection, SqlRDDEventReason.WhereClause, _cTable, sWhereClause) - - if !String.IsNullOrEmpty(sWhereClause) - sb:Append(SqlDbProvider.WhereClause) - sb:Append(sWhereClause) - endif - - var stmt := sb:ToString() - var result := _connection:ExecuteScalar(stmt) - nKeyNo := Convert.ToUInt32(result) - - return nKeyNo - method ZapStatement() as STRING var sb := StringBuilder{} sb:Append(Provider:DeleteAllRowsStatement)