DBF zu PostgresSQL

Alles zum SQL-Dialekt

Moderator: Moderatoren

Antworten
georg1956
Rookie
Rookie
Beiträge: 6
Registriert: Di, 01. Okt 2013 22:20

DBF zu PostgresSQL

Beitrag von georg1956 »

Ich arbeite noch mit xBase++ 1.9 und den alten DBF Datenbanken. Gibt es ein Modul mit dem ich, ohne den Quellcode großartig umschreiben zu müssen, PostgresSQL Datenbanken ansprechen kann.
mfg Georg
georg
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2823
Registriert: Fr, 08. Feb 2008 21:29
Hat sich bedankt: 95 Mal
Danksagung erhalten: 13 Mal

Re: DBF zu PostgresSQL

Beitrag von georg »

Hallo, Georg -


nein.

Zwar soll die nächste Version von Xbase++ die Möglichkeit bieten, auf PostgreSQL wie auf eine DBF-Datei zuzugreifen, aber ich warte schon seit Jahren drauf, dass die "fast versandfertige" Version endlich kommt.

Hector Peroza hat einen Wrapper für MySQL geschrieben, mit dem ich seit einigen Jahren (!) erfolgreich arbeite, und zwar, nachdem mir das Warten auf Alaska zu lange dauerte. Hector wollte einen zweiten Wrapper für PostgreSQL schreiben, allerdings habe ich daran kein Interesse gehabt und kann Dir daher über den Stand nichts sagen.

Generell muss ich Dir aber schreiben, dass eine DBF-Datei und eine SQL-Tabelle sehr verschieden "angepackt" werden müssen. Man kann vieles recht einfach umstellen (Browses), manches andere ist aber einfach anders.

Eine DBF-Datei ist z.B. immer als Ganzes im Zugriff (von dbgotop() bis dbgobottom(), dbgoto() und dbskip() aus gesehen), während Du in SQL immer mir einem Result Set arbeitest, das per Definition eine Untermenge der Datensätze enthalten kann, alle Datensätze, oder noch viel mehr Datensätze. Diese Besonderheiten (auch was Sperren und dergleichen angeht) muss man berücksichtigen. Oder das Fehlen des ghost record (lastrec() + 1) - wenn eine DBF leer ist, kannst Du sie immer noch browsen, weil die Feldbeschreibungen vorhanden sind. Ein leeres Result Set hat keine Feldbeschreibungen, und darum kann man es standardmässig nicht browsen, da der Browser mit 0 Feldern nichts anfangen kann ...

Meine private Meinung: Alaska hat für die PostgreSQL-Implementierung die SQL-Tabellen derart vergewaltigt, dass man schon fast nicht mehr von einer SQL-Tabelle sprechen kann. Prokrustes fällt mir dazu nur ein.

Wenn Du Dir die Mühe machst, Dein Programm auf SQL umzustellen (z.B. über Hector's Wrapper) dann gewinnst Du deutlich mehr - aber, je nach Grösse des Projekts, ist der Aufwand auch nicht trivial. Aber zukunftssicher.
Liebe Grüsse aus der Eifel,

Georg S. Lorrig
Redakteur der Wiki des Deutschprachigen Xbase-Entwickler e.V.
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12903
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 44 Mal

Re: DBF zu PostgresSQL

Beitrag von AUGE_OHR »

georg1956 hat geschrieben:Gibt es ein Modul mit dem ich, ohne den Quellcode großartig umschreiben zu müssen, PostgresSQL Datenbanken ansprechen kann.
theoretisch sollte das pgDBE machen welches mit Xbase++ V2.x kommt.

wie Georg aber schon sagte ist SQL einfach "anders" als DBF und die Umsetzung als DBE wird in vielen Fällen wohl nicht optimal ( sprich langsamer als DBF) sein.
DBE bedeutet das du zum navigieren die gewohnten Datenbank Befehle wie GOTO(), SEEK() oder auch Browse benutzen kannst.

leider gibt es kein Informationen / API von Alaska für die DBE und somit ist der Zugriff per 3-PP ( SQLExpress / ODBC ) oder auch native
nur mit eigenen Classen, welche die Befehle simulieren, möglich und somit nicht unbedingt kompatible zu bestehenden Sourcen.

es gibt, von Phil Ide, eine Class welches die native PostgreSQL Schnittstelle per API benutzt.
diese habe ich mit Hilfe von Pablo, Edgar und Hector mittels ot4xb in PGU.EXE / DLL zusammengefasst. (siehe Wissensbasis)
gruss by OHR
Jimmy
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15688
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: DBF zu PostgresSQL

Beitrag von brandelh »

Georg hat geschrieben:Meine private Meinung: Alaska hat für die PostgreSQL-Implementierung die SQL-Tabellen derart vergewaltigt, dass man schon fast nicht mehr von einer SQL-Tabelle sprechen kann.
Prokrustes fällt mir dazu nur ein.
Wenn Du Dir die Mühe machst, Dein Programm auf SQL umzustellen (z.B. über Hector's Wrapper) dann gewinnst Du deutlich mehr - aber, je nach Grösse des Projekts, ist der Aufwand auch nicht trivial. Aber zukunftssicher.
da stimme ich voll zu :D

Falls du SQLExpress() in Betracht ziehst, kannst du deine Anwendung sogar unabhängig vom SQL Server machen (MySQL z.B. auch nutzen), allerdings muss man sich dann auf das beschränken, wa bei beiden gleich ist.
AUGE_OHR hat geschrieben: es gibt, von Phil Ide, eine Class welches die native PostgreSQL Schnittstelle per API benutzt.
diese habe ich mit Hilfe von Pablo, Edgar und Hector mittels ot4xb in PGU.EXE / DLL zusammengefasst. (siehe Wissensbasis)
das ist irgendwie an mir vorbei gegangen ... allerdings ist Hektors/Georges Umsetzung der API jünger, PHIL ist leider nicht mehr aktiv (oder gar schon gestorben).
georg1956 hat geschrieben:Gibt es ein Modul mit dem ich, ohne den Quellcode großartig umschreiben zu müssen, PostgresSQL Datenbanken ansprechen kann.
eigentlich sollte dafür schon die OCDBDBE ausreichen, mit der bin ich aber nie warm geworden. Ich persönlich ziehe eine Lösung mit einem Datenbankobjekt wie SQLExpress() vor.

sicherlich muss man den Code umstellen, aber SQL ist einfach eine andere Welt. Man gibt dem Server nur vor WAS man möchte, wie er dazu kommt geht uns nichts an.
Mit Xbase++ konnte man ja auch mit (fast) keinen code Änderungen eine Programm von CLIPPER-DOS nach WIN32 bringen. Das stimmt und es funktioniert !
Dieses Programm kann aber nicht mehr als bisher, wenn man mit der alten Optik zufrienden ist und kein CUT & PASTE will geht das auch wirklich gut.

ABER ES BLEIBT EIN ALTES DOS PROGRAMM !

Keine Fenster, keine GUI, wer mehr will muss Teile ändern.

Hierbei nimmt man dann idealer Weise auch die Programmlogik genau unter die Lupe, was unter DOS alle möglichen umständlichen Verrenkungen (mehrere Fenster, Speicherplatz etc.) benötigte
geht nun nach einem Redisign ganz einfach.

Ähnlich ist es auch mit den Daten, altes DBF/NTX/CDX Denken (erst das, dann das ...) sollte man gegen mengenorientiertes Denken austauschen.
Sicherlich ist nicht alles Gold was glänzt, aber wenn man den Umstieg erledigt hat, kann JEDER SQL Admin mit der Datei umgehen,
andere Anwendungen (egal mit welcher Sprache) können mit der Datenbank zusammenarbeiten.

Das geht nicht, wenn man den UPSIZE Prozess genutzt hat, zwar wird Alaska wohl mit triggern und ähnlichem den Betrieb so kompatibel wie möglich machen,
aber wenn man einem Admin erklären soll was er alles davon nicht anrühren darf ... oder noch besser wofür es gut ist ... :roll:
Gruß
Hubert
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12903
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 44 Mal

Re: DBF zu PostgresSQL

Beitrag von AUGE_OHR »

brandelh hat geschrieben:
AUGE_OHR hat geschrieben: es gibt, von Phil Ide, eine Class welches die native PostgreSQL Schnittstelle per API benutzt.
diese habe ich mit Hilfe von Pablo, Edgar und Hector mittels ot4xb in PGU.EXE / DLL zusammengefasst. (siehe Wissensbasis)
das ist irgendwie an mir vorbei gegangen ... allerdings ist Hektors/Georges Umsetzung der API jünger, PHIL ist leider nicht mehr aktiv (oder gar schon gestorben).
Nope, denn Phil hat ja noch die PostgreSQL v8.x Version / BAP benutzt wären ich mit ot4xb die v9.x und deren Möglichkeiten ( Cursor mit MOVE / Offset ) nutze.

ein "aufbohren" des MySQL Wrapper von Hector, was ich probiert habe, bringt es nicht ... da bekomme ich das PostgreSQL v9.x Konzept nicht rein ohne alles umzuschreiben.

PGU enthält auch die für pgDBE nötige "Upsize" Routine mit

Method PGUDialog:Check_ISAM_Table()
Method PGUDialog:Create_ISAM_Orders()
Method PGUDialog:Create_ISAM_Tables()
Method PGUDialog:Create_ISAM_SysConnections()
Method PGUDialog:Check_ISAM_Trigger()
Method PGUDialog:Create_ISAM_Rowversion()
Method PGUDialog:Create_ISAM_Tablemeta()

d.h. die Trigger werden ebenfalls angelegt jedoch KEINE ( Function ) Indexe !
Wenn man (echte) Index haben möchte muss man die selbst anlegen.
gruss by OHR
Jimmy
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15688
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: DBF zu PostgresSQL

Beitrag von brandelh »

AUGE_OHR hat geschrieben:Nope, denn Phil hat ja noch die PostgreSQL v8.x Version / BAP benutzt wären ich mit ot4xb die v9.x und deren Möglichkeiten ( Cursor mit MOVE / Offset ) nutze.
ein "aufbohren" des MySQL Wrapper von Hector, was ich probiert habe, bringt es nicht ... da bekomme ich das PostgreSQL v9.x Konzept nicht rein ohne alles umzuschreiben.
sorry, aber NOPE verstehe ich jetzt nicht. Nutzt deine Klasse eine neuere API als die von Hektor ?
Gruß
Hubert
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12903
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 44 Mal

Re: DBF zu PostgresSQL

Beitrag von AUGE_OHR »

brandelh hat geschrieben:Nutzt deine Klasse eine neuere API als die von Hektor ?
Die API hat sich nicht verändert.
Die API beschreibt im Prinzip nur die Client / Server Connection.
es geht um die Query wo man die neuen PostgreSQL Kommandos und Funktionen verwenden kann.

Die ehemalige Class von Phil Ide wurde mit PostgreSQL v7.x / v8.x und BAP entwickelt.
Pablo hat dann die ot4xb daraus gemacht.
PGU nutzt nun die Fähigkeiten der Version 9.x um die neue Kommandos und Funktionen "in" einer SQL Query zu verwenden.


Das Problem, aus DBF Sicht, ist in SQL das navigieren.
Dort wo wir einen DBE Befehl, wie DbGoto() / DbSkip() ..., absetzten
muss an den SQL Server eine neue Query gesendet werden.

in der Postgre v7x / v8x würde ein grosser OFFSET Wert ( DbGoto() ) eine ganze Weile dauern ...
unter Verwendung der Postgre Version 9.x kann man nun folgendes machen

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
...
   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"
   cVar5 := "CLOSE MyCursor;"
   cVar6 := "COMMIT WORK;"

das MOVE Kommando kann man so nun auch mit grossen OFFSET verwenden und das LIMIT kann man auf eine Seite des Bildschirm zum blättern begrenzen.

p.s. das funktioniert auch mit (echten) SQL Index wenn man

Code: Alles auswählen

row_number() OVER 
in der Query verwendet
gruss by OHR
Jimmy
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15688
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: DBF zu PostgresSQL

Beitrag von brandelh »

AUGE_OHR hat geschrieben:Das Problem, aus DBF Sicht, ist in SQL das navigieren.
Dort wo wir einen DBE Befehl, wie DbGoto() / DbSkip() ..., absetzten
muss an den SQL Server eine neue Query gesendet werden.
das sehe ich nicht so, wobei ich nicht viel Erfahrung mit SQL habe ...
Angenommen ich habe einen Stammsatz und will im Browse darunter alle Datensätze aus einer zweiten Datei zeigen die zu diesem passen.

Bei einer DBF hätte ich oben einen Satz, unten hätte ich einen SCOPE gesetzt und den Inhalt im Browser angezeigt.
Eventuell aber auch schon ein Array als Zwischenspeicher genutzt.

Wie würde ich das bei SQL machen ?
Zunächst hätte ich statt der RecNo() ein Feld mit einer eindeutigen ID (RecNo ;-) ), in der abhängigen Tabelle zusätzlich noch ein Feld in dem die ID des Stammsatzes steht.
Cursor - das habe ich mir so gemerkt - sind je nach Server und Einstellung unterschiedlich (was die Möglichkeiten angeht und die Performance), ich habe bisher immer ReadOnly Forward genutzt.

Ich setze also eine Query auf die Stammdaten und kann den einen Treffer sofort verarbeiten.
Dann eine Query auf die abhängige Datei, Suchbegriff ist die ID des Stammsatzes, sortiert je nach Wunsch eine der Spalten.
Ich würde diese Query aber nicht direkt browsen, sondern in ein Array einlesen (wieder mit der ID RecNo in einer Spalte kt ändern könnte wenn ich müsste).

Ein Array im Browser bietet einfach bessere Performance und man kann (mit Erweiterungen) leicht Spaltenweise sortieren ohne den Server zu nerven.
Natürlich ist es dann ein eingefrohrener Stand (ein Update Button also Pflicht).

Ein neues Query unten ist nur nötig, wenn ich die Anzeige refreshen will oder aber im Hauptsatz vor bzw. zurück springe.
Ein Hauptsatz wechsel würde ich mir je nach Suchbedingung eine Liste der möglichen IDs holen, den aktuellen dort finden und den Vorgänger bzw. Nachfolger ermitteln.
Mit dieser ID würde ich dann wieder die beiden Queries wie oben beschrieben durchführen.

So habe ich das z.B. bei einer App mit B4A und SQLite gemacht.

PS: komplette DBFs im Browser anzeigen habe ich mir schon lange abgewöhnt. Schon unter VO konnte das sehr langsam werden.
Ich nutze gerne XbpQuickBrowse() mit DAC..., da dies zwischenpuffert oder gleich Arrays.
Gruß
Hubert
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9345
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 100 Mal
Danksagung erhalten: 359 Mal
Kontaktdaten:

Re: DBF zu PostgresSQL

Beitrag von Tom »

Die Fragestellung ist etwas irritierend. Soll das Programm einschließlich Tabellen auf PostGre umgestellt werden? Wenn das der Fall ist, ist Xbase++ 2.0, das ja "Artica", also genau die Lösung für dieses Problem enthält, die richtige Wahl - vorausgesetzt, es wird alsbald veröffentlicht (derzeit ist ein "Release Candidate" erhältlich). Das würde die Migration der Tabellen nach PostGre und ihre Nutzung mit geringen Codeänderungen gestatten. Oder soll dieses Programm zusätzlich auf PostGre zugreifen? Dann würde ich SQLexpress empfehlen.
Herzlich,
Tom
georg1956
Rookie
Rookie
Beiträge: 6
Registriert: Di, 01. Okt 2013 22:20

Re: DBF zu PostgresSQL

Beitrag von georg1956 »

Großen Dank für die zahlreichen Anregungen. Ich weiß jetzt doch zumindest, daß es nicht so einfach gehen wird! Nochmal Danke.
Gruß
Georg
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12903
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 44 Mal

Re: DBF zu PostgresSQL

Beitrag von AUGE_OHR »

georg1956 hat geschrieben:Ich weiß jetzt doch zumindest, daß es nicht so einfach gehen wird!
ohne Arbeit wird es kaum gehen ;)

@Hubert : bei einem Browse arbeite ich ja schon mit einer "Menge" ... da ist ein SKIP kein Problem

aber warum ein Resultset in ein Array um-schaufeln wenn man direkt die Tuple (ROW = Datensatz) ansprechen kann.
hier mal ein PostgreSQL "Skipper" ( ex. Phil Ide )

Code: Alles auswählen

   // Navigation code blocks for the browser
   ::skipBlock     := {|n| (::PgSkipper(n)) }
   ::goTopBlock    := {| | (::oPG:GoTop())      }
   ::goBottomBlock := {| | (::oPG:GoBottom())   }
   ::phyPosBlock   := {| | (::oPG:recNo())        }

   // Navigation code blocks for the vertical scroll bar
   ::posBlock      := {| | (::oPG:Position())    }
   ::goPosBlock    := {|n| (::oPG:GoPosition(n)) }
   ::lastPosBlock  := {| | 100             }
   ::firstPosBlock := {| | 0               }



method CLASS_NAME:PgSkipper( n )
   local nDir
   local nDone := 0
   default n to 0

   nDir := iif( n > 0, 1, -1 )
   while n <> 0 .and. iif( nDir > 0, !::oPG:eof(), !::oPG:bof() )
      ::oPG:Skip(nDir)
      if ::oPG:eof()
         exit
      elseif ::oPG:bof()
         exit
      endif
      if !Eval(::whileClause)
         ::oPG:Skip(-nDir)
         if !Eval(::whileClause) // oops, no recs available
            ::oPG:GoBottom()
            ::oPG:Skip()
         endif
         exit
      endif
      n     -= nDir
      nDone += nDir
   enddo
   if valtype(::cChild) == "O"
      ::cChild:goTop()
      ::cChild:refreshAll()
   endif
   return (nDone)
gruss by OHR
Jimmy
Antworten