diff --git a/src/Runtime/XSharp.SQLRdd/RDD/SQLRDD-Main.prg b/src/Runtime/XSharp.SQLRdd/RDD/SQLRDD-Main.prg
index 64e2db874a..e3dabdedda 100644
--- a/src/Runtime/XSharp.SQLRdd/RDD/SQLRDD-Main.prg
+++ b/src/Runtime/XSharp.SQLRdd/RDD/SQLRDD-Main.prg
@@ -65,12 +65,31 @@ 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
end get
end property
+ /// A numeric value representing the number of records in the current order.
+ /// When the table is in natural order or not in table mode 0 is returned
+ public property OrderKeyCount as dword
+ get
+ if self:_tableMode != TableMode.Table .or.;
+ self:CurrentOrder = null
+ return 0
+ endif
+ try
+ return self:_builder:GetOrderKeyCount()
+ catch as Exception
+ return 0
+ end try
+ end get
+ end property
+
#endregion
@@ -527,7 +546,13 @@ partial class SQLRDD inherit Workarea
return false
endif
SELF:_ClearTable()
- var nPage := SELF:RecCount / self:_oTd:PageSize
+ local nMaxRecNo as dword
+ if self:CurrentOrder = Null
+ nMaxRecNo := self:_builder:GetRecCount()
+ else
+ nMaxRecNo := self:OrderKeyCount
+ endif
+ var nPage := nMaxRecNo / self:_oTd:PageSize
if SELF:RecCount % self:_oTd:PageSize != 0
nPage += 1
ENDIF
diff --git a/src/Runtime/XSharp.SQLRdd/RDD/SQLRDD-Orders.prg b/src/Runtime/XSharp.SQLRdd/RDD/SQLRDD-Orders.prg
index eee84c87ed..a780e601f1 100644
--- a/src/Runtime/XSharp.SQLRdd/RDD/SQLRDD-Orders.prg
+++ b/src/Runtime/XSharp.SQLRdd/RDD/SQLRDD-Orders.prg
@@ -414,10 +414,9 @@ partial class SQLRDD
endif
case DBOI_KEYCOUNT
self:_ForceOpen()
- info:Result := self:RowCount
+ info:Result := self:OrderKeyCount
case DBOI_POSITION
- self:_ForceOpen()
- info:Result := self:OrderKeyNo
+ info:Result := self:RowNumber + (self:_currentPageNo-1) * self:_oTd:PageSize
case DBOI_RECNO
// our position is the row number in the local cursor
info:Result := self:RowNumber + (self:_currentPageNo-1) * self:_oTd:PageSize
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)