wenn man nun den "bearbeitete" Indexkey() in einem Array und die Table hat geht es an die Reihenfolge der Indexe.
daraus mach ich nun
die Method dazu sieht so aus
Code: Alles auswählen
METHOD JimBrowse:OrdSetfocus(xValue)
LOCAL cOrder := ""
LOCAL nPosi
IF Valtype(xValue) = "N"
cOrder := aIndex[xValue][AUSDRUCK]
ELSEIF Valtype(xValue) = "C"
nPosi := ASCAN(aIndex, { |o| o[TAGNAME] = xValue } )
IF nPosi > 0
cOrder := aIndex[nPosi][AUSDRUCK]
ENDIF
ENDIF
IF !EMPTY(cOrder)
::NextCursor(,,, cOrder,, )
ENDIF
RETURN
damit kann man unter PostgreSQL den "Kontrollierenden Index" einstellen
---
der Kern für die "Navigation" steckt in der Method NextCursor()
Code: Alles auswählen
METHOD JimBrowse:NextCursor( cTable, cField, cWhere, cOrder, cLimit, cOffset )
...
DEFAULT cTable TO ::_cTable
DEFAULT cField TO ::_cField
DEFAULT cWhere TO ::_cWhere
DEFAULT cOrder TO ::_cOrder
DEFAULT cLimit TO ::_cLimit
DEFAULT cOffset TO ::_cOffset
IF ( ::_cLastTable <> cTable .OR. ::_cLastOrder <> cOrder )
über den OFFSET kann man ISAM Befehle wie SKIP simulieren
das SELECT verpackt man in einen CURSOR und ab Server 9 kann man die PostgreSQL Function row_number() mit einbauen.
row_number() ist eine neue Column im Result-Set und enthält die relative Satznummer ( -> DbPosition) einer Sortierung.
Code: Alles auswählen
cVar1 := "BEGIN WORK;"
IF SP_nVersion() < 9 // Server Version
cVar2 := "DECLARE MyCursor CURSOR FOR SELECT " + cField +;
" FROM " + cTable + ;
IF( EMPTY( cWhere ), "", " WHERE " + cWhere ) + ;
" ORDER BY " + cOrder
ELSE
cVar2 := "DECLARE MyCursor CURSOR FOR SELECT " + cField +;
", row_number() OVER (ORDER BY " + cOrder + ")"+;
" FROM " + cTable + ;
IF( EMPTY( cWhere ), "", " WHERE " + cWhere ) + ;
" ORDER BY " + cOrder
ENDIF
cVar3 := "MOVE FORWARD " + cOffset + " IN MyCursor"
cVar4 := "FETCH FORWARD " + cLimit + " FROM MyCursor"
cVar5 := "CLOSE MyCursor;"
cVar6 := "COMMIT WORK;"
das nun die 6 Strings die hintereinander als Qwery abschickt werden.
Code: Alles auswählen
::oPG:exec( cVar1 )
...
IF ResultStatus( ::oPG, ::_Post2Loop )
::oPG:exec( cVar2 )
...
IF ResultStatus( ::oPG, ::_Post2Loop )
IF VAL( cOffset ) > 0
::oPG:exec( cVar3 )
...
IF ResultStatus( ::oPG, ::_Post2Loop )
oRes := ::oPG:result
ENDIF
ENDIF
::oPG:exec( cVar4 )
IF ResultStatus( ::oPG, ::_Post2Loop )
...
ENDIF
ENDIF
ENDIF
::oPG:exec( cVar5 )
IF ResultStatus( ::oPG, ::_Post2Loop )
...
ENDIF
::oPG:exec( cVar6 )
die Zugriffszeit der jeweiligen ::oPG:exec() muss man mit dem HrTimer messen da die bei < 1/100 Sek. liegen
... wenn man nicht ein riesiges LIMIT wählt
Anmerkung : der "Inhalt" der Strings wird hier nicht überprüft was gewisse Sicherheitsstands nicht erfüllt wie Carlo hinwies.
---
aus xBase ist man gewohnt alle Daten im Zugriff zu haben aber ein Bildschirm kann nur eine begrenzte Anzahl anzeigen.
es reicht also das LIMIT auf die Anzahl der möglichen Zeilen einzustellen und per "DbSkipper" weitere anzufordern.
einen umfangreichen "DbSkipper" braucht man nicht weil man zur akuellen Position nur +/- nSkip "berechnen" muss für die neue OFFSET Position.
damit ist die "Navigation" mit dem Keyboard oder dem extern Scrollbar einfach.
---
Zwischenfazit :
ohne "Optimierung" bestehenden Source wird es nicht gehen.
wenn man nun sein Konzept Richtung Dbserver() erweitert dann hätte man eine sehr gute Grundlage für eine SQL CLASS mit den selben Namen für die Method(en)
statt die DBE zu tauschen würde man die CLASS wechseln aber der Effekt wäre der gleiche
Theoretisch könnte man eine CLASS mit einen eigenes Datenformat haben und mit den selben Method(en) navigieren.
eine ISAM Emu zm "navigieren" ist auch bei BTREE nicht notwendig. Tatsächlich wird BTREE um so schneller je grösser die Datenmenge ist.
eine "Navigation" über den OFFSET ist (relative) langsam aber sie "kostet" weniger als die Pflege der internen Index FIELD
die Reduktion der "Kosten" merkt man an der gestiegenen Performance
also "unnötiges" streichen wenn man es anderes "günstiger" das selbe Ergebnis erzielt
---
Ich möchte euch bitten Fragen zunächst zu dem vorgestellten erweiterten native Konzept zu machen.
wo seht ihr noch Probleme das es mit eurem Source nicht "passt" (Express++ ... wohl per ODBC)