hi,
ich komme aus der Xbase (alle Version) Welt und habe mich die letzten Monate mit der libpq.dll beschäftigt.
die Umsetzung der DLL Calls nach Xbase++, mittels ot4xb ( www.xbwin.com ) war schnell erledigt und der “Import” von DBF Daten in PG Table funktioniert.
ich habe nun grosse Datenmengen ( >500000 ) zum “spielen” … nur ich kann es nicht “so” machen wie ich es unter Xbase++ “gewohnt” bin. es geht dabei nicht um die Syntax sondern um das Konzept : Xbase (alle Versionen ) ist Datensatz orientiert.
angenommen ich habe 1 Field “cText” und 26 Records : A - Z
SELECT * FROM MyTable WHERE cText="K" ORDER BY cText
dann bekomme ich ein Result Set mit 1 Row
Frage : was ist dann die aktuelle “RECNO()” ( Xbase Befehl ) die Nummer 11 ( = “K” ) sein sollte ?
mir ist schon klar das PG keine “RECNO()” hat ( ich lege dafür ein internes Field __record an ) es geht aber um die nächste Frage : wie komme ich zum “L” ? oder korrekt wie “SKIP” ich einen __record zum nächsten ?
ich “weiss” ja nicht was in Field “cText” als nächstes kommt im meinem Beispiel … wie dann ein “WHERE” abschicken ?
unter Xbase ( alle Version ) ist ein “GO BOTTOM” genau so schnell wie ein “GO TOP”.
unter PostgreSQL funktioniert ein OFFSET bei grossen Table nur mit viel “Power” ( i7 statt P4 ) schnell
wenn ich nun ein DBF öffne zum “Browsen” ( Liste ) dann starte er von der “Position” wo er sich “gerade befindet”. Der “Skipper” des “Browse” lädt nun solange Daten “hintereinander” weg bis der Bildschirm “voll” ist.
ein “positionieren” mittels OFFSET ist also nicht die optimale Lösung und ich habe das nun um ein “Browse” ( Liste ) zu “füllen”
METHOD JimBrowse:NextCursor( cTable, cField, cWhere, cOrder, cLimit, cOffset )
...
cVar1 := "BEGIN WORK;"
cVar2 := "DECLARE MyCursor CURSOR FOR SELECT " + cField + " FROM " + cTable + " ORDER BY " + cOrder +";"
cVar3 := "MOVE FORWARD " + cOffset + " IN MyCursor;"
cVar4 := "FETCH FORWARD " + cLimit + " FROM MyCursor;"
// hier das Result Set abspeichern
cVar5 := "CLOSE MyCursor;"
cVar6 := "COMMIT WORK;"
jede Query wird einzeln abgesendet und nach dem FETCH hole ich mir das Result Set “für eine Seite” ( cLimit ) einer Liste.
ich “navigiere” also mittels “CURSOR” und “MOVE” …
Frage : ist das “korrekt” ?
nun hat eine Liste gewöhnlich mehr als eine Column, also möchte man mit einem “klick” auf den Header “umschalten” können.
ORDER BY blabla
gibt mit die “Sortierung” nach Field “blabla”.
so weit so gut, aber damit steht meine Anzeige auf dem ersten Treffer eines Result Set … nicht mehr da wo ich “vorher” stand
nun habe ich ja ein interes Field __record angelegt … das frage ich VOR dem neuen “ORDER BY” ab und “suche” dann die Nummer in der neue “Sortierung” zum “re-positionieren” über ein Array …
METHOD JimBrowse:MakeIndex( oPG2, cTable, cOrder )
LOCAL cDBSfield := "__record"
cQuery := "SELECT " + cDBSfield + " FROM " + cTable + " ORDER BY " + cOrder
oPG2:Exec( cQuery )
oResult := oPG2:result
iMax := oResult:rows
IF iMax > 0
FOR i := 1 TO iMax
cDBSfield := Var2Char( oResult:FieldGet( i - 1, 0 ) )
AADD( ::aIndex, { cDBSfield, i } )
NEXT
// sort cDBSfield
::aIndex := ASORT( ::aIndex,,, { | aX, aY | aX[ 1 ] < aY[ 1 ] } )
ENDIF
Frage : wie lösen PostgreSQL Profis das “Problem” mit dem “re-positionieren” ?
nun steht ich also wieder auf mein “alten” Position mit der neuen “Sortierung” aber statt “K” wollte ich ja zum “L” … dazu muss der User also jetzt “L” drücken um ein
WHERE cText2 = "L"
abzuschicken … und wenn der User “weiter tippt” ( inkrementelle Suche ) ?
jedes “WHERE” das ich abschicke benötigt ja “Zeit” bis ich ein Result Set bekomme und es darstellen kann.
bei > 500000 ist mein jetziges Konzept nicht wirklich “schnell” …
Frage : wie machen PostgreSQL Profis eine “Listendarstellung” ( Listview wäre möglich ) ?