Indexaufbau per INDEX ON

Alle Fragen um die Programmierung, die sich sonst nicht kategorisieren lassen. Von Makro bis Codeblock, von IF bis ENDIF

Moderator: Moderatoren

Antworten
Benutzeravatar
Magic
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 343
Registriert: Mo, 11. Jul 2011 12:01

Indexaufbau per INDEX ON

Beitrag von Magic »

Hallo Forengemeinde,

ich habe in einer Datenbank Infos zum Index vorliegen.
Nummer, Name, Key und je eine Spalte mit Infos zu UNIQUE, DESCENDING, CANDIDATE, SUBINDEX hier steht ein „X“, wenn zutreffend, sonst leer.

In einer Schleife versuche ich nun den Index (CDX) mit INDEX ON anzulegen.

Code: Alles auswählen

      // Indexstruktur erzeugen
      WHILE ! DB_INDEX->( Eof() )

         // Indexinformationen zusammen stellen
         cIndexDatei := pcVerzeichnis + "\" + Alltrim( pcScope ) + ".CDX"
         cIndexKey   := Alltrim( DB_INDEX->ORDKEY )
         cIndexTag   := Alltrim( DB_INDEX->ORDNAME )
         lUnique     := IIF( DB_INDEX->ORDUNIQUE  == "X", .T., .F. )
         lDescend    := IIF( DB_INDEX->ORDDESCEND == "X", .T., .F. )
         lCandidate  := IIF( DB_INDEX->ORDCANDIDA == "X", .T., .F. )
         lSubindex   := IIF( DB_INDEX->ORDSUBINDE == "X", .T., .F. )

         // Index erzeugen
         IF .NOT. lUnique
            INDEX ON &cIndexKey TAG &cIndexTag TO &cIndexDatei

         ELSEIF lDescend .OR. lCandidate .OR. lSubindex

            cTxt := "Index konnte nicht automatisch erstellt werden, " + ;
                              "da er eine der Eingenschaften 'Descend, Candidate, Subindex' enthält!"

            Write_Protokol( cTxt, .F. )

         ELSE
            INDEX ON &cIndexKey TAG &cIndexTag TO &cIndexDatei UNIQUE
         ENDIF

         DB_INDEX->( DbSkip() )

      END
Wie kann ich bei INDEX ON die Eigenschaften DESCENDING, CANDIDATE, SUBINDEX mit angeben. Einfach hinter anhängen funktioniert nicht. Ich stelle mir etwa so was vor:

Code: Alles auswählen

      // Indexstruktur erzeugen
      WHILE ! DB_INDEX->( Eof() )

         // Indexinformationen zusammen stellen
         cIndexDatei := pcVerzeichnis + "\" + Alltrim( pcScope ) + ".CDX"
         cIndexKey   := Alltrim( DB_INDEX->ORDKEY )
         cIndexTag   := Alltrim( DB_INDEX->ORDNAME )
         lUnique     := IIF( DB_INDEX->ORDUNIQUE  == "X", .T., .F. )
         lDescend    := IIF( DB_INDEX->ORDDESCEND == "X", .T., .F. )
         lCandidate  := IIF( DB_INDEX->ORDCANDIDA == "X", .T., .F. )
         lSubindex   := IIF( DB_INDEX->ORDSUBINDE == "X", .T., .F. )

         INDEX ON &cIndexKey TAG &cIndexTag TO &cIndexDatei IIF(lUnique, UNIQUE, NIL) IIF(lDescend, DESCENDING, NIL) IIF(lCandidate, CANDIDATE, NIL) IIF(lSubindex, SUBINDEX, NIL)

         DB_INDEX->( DbSkip() )

      END
Das funktioniert schon alleine aufgrund des Syntaxfehler nicht. Aber vielleicht verdeutlicht das etwas genauer was ich meine. Alle Kombinationen (es müssten dann 4 hoch 4 sein) kann ich ja nicht einzeln über IF oder CASE abfangen. Es ginge zwar schon, aber das kann nicht die endgültige Lösung sein. Mir fehlt hier einfach die Idee.

Jeder Tipp ist willkommen.

Viele Grüße,
Magic
Gruß,
Magic
Benutzeravatar
Manfred
Foren-Administrator
Foren-Administrator
Beiträge: 21248
Registriert: Di, 29. Nov 2005 16:58
Wohnort: Kreis Wesel
Hat sich bedankt: 211 Mal
Danksagung erhalten: 71 Mal

Re: Indexaufbau per INDEX ON

Beitrag von Manfred »

Hi Magic,

gibt es einen besonderen Grund, warum Du nicht OrdCreate() im Zusammenhang mit OrdCondSet() nutzt? Ich denke mal, damit dürfte das einfacher klappen.
Gruß Manfred
Mitglied der XUG Osnabrück
Schatzmeister des Deutschsprachige Xbase-Entwickler e.V.
großer Fan des Xbaseentwicklerwiki https://wiki.xbaseentwickler.de/index.p ... Hauptseite
Doof kann man sein, man muß sich nur zu helfen wissen!!
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9394
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 105 Mal
Danksagung erhalten: 364 Mal
Kontaktdaten:

Re: Indexaufbau per INDEX ON

Beitrag von Tom »

Eben. OrdCreate hat entsprechende Parameter, wodurch sich das ganze in einer einzigen Zeile machen ließe, außerdem kann man auf bremsende Makros verzichten. Übrigens geht das sowieso - Dateinamen usw. einfach klammern:

Code: Alles auswählen

INDEX ON (cIndexKey) TAG (cIndexTag) TO (cIndexDatei) UNIQUE
Herzlich,
Tom
Benutzeravatar
Magic
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 343
Registriert: Mo, 11. Jul 2011 12:01

Re: Indexaufbau per INDEX ON

Beitrag von Magic »

Hallo Manfred,
hallo Tom,
Tom hat geschrieben:OrdCreate hat entsprechende Parameter
bin ich blind?
Das mit den Klammern werde ich umstellen. Die Notation ist für mich neu.

Manfred hat geschrieben:gibt es einen besonderen Grund, warum Du nicht OrdCreate() im Zusammenhang mit OrdCondSet() nutzt?
Nein. Ich bin bisher einfach nicht auf die Kombination gekommen.

Grüße,
Magic
Gruß,
Magic
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15710
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 73 Mal
Danksagung erhalten: 38 Mal
Kontaktdaten:

Re: Indexaufbau per INDEX ON

Beitrag von brandelh »

Magic hat geschrieben:Das mit den Klammern werde ich umstellen. Die Notation ist für mich neu.
immer wenn Xbase++ im code einen String erwartet, der aber keine " benötigt (z.B. use Adress.dbf)
muss der Präprozessor das auf einen richtigen Parameter umsetzen.
Dies kann man mit der Klammer aber direkt erzwingen und hierbei auch Variablen benutzen:

Code: Alles auswählen

cPfad := "c:\test\"
cDatei := "Adress.dbf"
USE cPfad+cDBF // => gibt Fehler, weil der Dateinamen nach "cPfad+cDBF" übersetzt wird
USE (cPfad+cDBF) // macht was man möchte
oder auch 
copy file (cPfad+cDBF) TO (cNeuZiel)
Unter Clipper hat man sowas häufig mit & gemacht, das setzt aber PRIVATE voraus, (cLocalVar) geht auch mit lokalen Variablen.
Magic hat geschrieben:Nein. Ich bin bisher einfach nicht auf die Kombination gekommen.
wenn man beim compilieren /P nutzt, erstellt er eine *.PPO Datei.
Hierin kann man sehen, was der Präprozessor aus einer *.PRG macht.
Fast alle Comandos werden über den Präprozessor auf Funktionen umgesetzt.
Gruß
Hubert
Benutzeravatar
Magic
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 343
Registriert: Mo, 11. Jul 2011 12:01

Re: Indexaufbau per INDEX ON

Beitrag von Magic »

brandelh hat geschrieben:wenn man beim compilieren /P nutzt, erstellt er eine *.PPO Datei.
Hierin kann man sehen, was der Präprozessor aus einer *.PRG macht.
Fast alle Comandos werden über den Präprozessor auf Funktionen umgesetzt.
Vielen Dank für den Hinweis. Diese Möglichkeit kannte ich noch nicht.
Das wird sicherlich auch an anderen Stellen hilfreich sein.
Ich kompilieren direkt aus dem VX. Hab dem Parameter noch nicht gesehen.
Vorhanden ist ein Parameter /profile. Muss aber nachlesen was dieser bewirkt.

Jetzt muss ich nur noch meinen Code ändern.
Gruß,
Magic
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9394
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 105 Mal
Danksagung erhalten: 364 Mal
Kontaktdaten:

Re: Indexaufbau per INDEX ON

Beitrag von Tom »

@Magic: Du kannst die Tabellen übrigens so umwandeln, dass sie (als Kopien) von Access verstanden werden. COPY TO ... VIA DBFNTX.
Herzlich,
Tom
Benutzeravatar
Magic
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 343
Registriert: Mo, 11. Jul 2011 12:01

Re: Indexaufbau per INDEX ON

Beitrag von Magic »

OK. Tom, ich glaube, das ist die Antwort auf meine andere Frage (?).

Aber davon mal unabhängig.
Das habe ich noch nicht in Betracht gezogen. Was passiert aber dann, wenn ich in der original Tabelle (also CDX mit TPF) Änderungen vornehme.
I.d.R. kommen neue Datensätze hinzu.
Dann musste ich den COPTY TO Befehl nochmals ausführen?
Eigentlich 'ne dumme Frage. Ist doch 'ne KOPIE!
Gruß,
Magic
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9394
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 105 Mal
Danksagung erhalten: 364 Mal
Kontaktdaten:

Re: Indexaufbau per INDEX ON

Beitrag von Tom »

Für eine "Live"-Verknüpfung musst Du mit DBFNTX arbeiten und die Beschränkungen beachten, die für dBaseIII gelten. Und, ja, ansonsten müsstest Du bei jeder Änderung am Original die Kopie aktualisieren bzw. erneut erzeugen. Aber das ist umständlich und fehleranfällig.
Herzlich,
Tom
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15710
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 73 Mal
Danksagung erhalten: 38 Mal
Kontaktdaten:

Re: Indexaufbau per INDEX ON

Beitrag von brandelh »

Hi,

wenn du das nicht nur einmal benötigst, wäre es besser wenn dein Programm bei jeder Änderungen gleich beide DBF Formate speichert.
Jedesmal ein COPY TO könnte von der Geschwindigkeit Probleme bereiten, auf jeden Fall wird es aber Zugriffsprobleme geben, sobald 2 Benutzer den Export starten.
Gruß
Hubert
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12913
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 46 Mal

Re: Indexaufbau per INDEX ON

Beitrag von AUGE_OHR »

Magic hat geschrieben:...Index (CDX) mit INDEX ON anzulegen
bevor du mit CDXDBE arbeiten kannst musst du die erst mal in der DBESYS einbinden.
Magic hat geschrieben:Das funktioniert schon alleine aufgrund des Syntaxfehler nicht.
das sind nicht nur "Schreib" Fehler sondern "Verständnis" Fehler.
a.) Ein Index Ausdruck ( IndexKey() ) muss für alle Datensätze die exakt gleiche Länge ergeben.
b.) ein SubIndex baut, wie der Name schon sagt auf einem "vorhandenen" Index auf
c.) ein Candidate Index könnte man als "Primärschlüssel" benutzten weil "eindeutig" ... aber man kann mehrere Candidate haben

also vergiss die "Schleife" und schreibe jeden einzelnen Indexausdruck separat und dann können wir noch mal darüber reden was mit deinen Index los ist.
gruss by OHR
Jimmy
Benutzeravatar
Magic
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 343
Registriert: Mo, 11. Jul 2011 12:01

Re: Indexaufbau per INDEX ON

Beitrag von Magic »

Guten Morgen,

Jimmy, ich verste nur noch Bahnhof ... :roll:
AUGE_OHR hat geschrieben:bevor du mit CDXDBE arbeiten kannst musst du die erst mal in der DBESYS einbinden.
Ich erfülle alle Voraussetzungen. Habe 'ne ADS und alles funtzt wie es soll.
AUGE_OHR hat geschrieben:das sind nicht nur "Schreib" Fehler sondern "Verständnis" Fehler.
a.) Ein Index Ausdruck ( IndexKey() ) muss für alle Datensätze die exakt gleiche Länge ergeben.
b.) ein SubIndex baut, wie der Name schon sagt auf einem "vorhandenen" Index auf
c.) ein Candidate Index könnte man als "Primärschlüssel" benutzten weil "eindeutig" ... aber man kann mehrere Candidate haben

also vergiss die "Schleife" und schreibe jeden einzelnen Indexausdruck separat und dann können wir noch mal darüber reden was mit deinen Index los ist.
???
Der Index hat bei mir immer die exakte Länge für alle Datensätze, etc.

Ich habe in einer DB die Struktur und die Indizes vorliegen.
Anhand der Daten baue ich mir eine (leere) Datenbank und den Index auf.
Funktioniert bisher einwandfrei. Und da ich CDX nutze und demnach mehrere Indizes in einer Datei habe mache ich dass also in einer Schleife. Bisher keinerlei Probleme.
Vielleicht verstehe ich aber auch etwas nicht.
Gruß,
Magic
Benutzeravatar
Rolf Ramacher
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 1931
Registriert: Do, 09. Nov 2006 10:33
Wohnort: Bergheim
Danksagung erhalten: 3 Mal
Kontaktdaten:

Re: Indexaufbau per INDEX ON

Beitrag von Rolf Ramacher »

Hallo,

ich gestalte meinen Indexaufbau so.

Code: Alles auswählen

If !File("SPStamm.Cdx")		// Artikelstamm
	lIndex:=.t.
   If !Netz_Use("SpStamm.Dbf",.t.)
		Quit
	EndIf
	oStatic1:caption:=(cText+"SPSTAMM")
	oStatic1:configure()
   Index on sa+liefnr+lartnr+artnr tag "spstamm" to "spstamm.cdx"
	Index on artnr tag "artikel" to "spstamm.cdx"
	Index on liefnr tag "liefnr" to "spstamm.cdx"
	Index on padr(alltrim(lartnr),16) tag "lartnr" to "spstamm.cdx"
	Index on lartnr tag "lartnrteil" to "spstamm.cdx"
	Index on ean tag "ean" to "spstamm.cdx"
	Index on wedat tag "wedatum" to "spstamm.cdx"
	Index on ss tag "ss" to "spstamm.cdx"
EndIf
Gruß Rolf

Mitglied der Gruppe XUG-Cologne
www.xug-cologne.de
Benutzeravatar
Magic
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 343
Registriert: Mo, 11. Jul 2011 12:01

Re: Indexaufbau per INDEX ON

Beitrag von Magic »

Rolf Ramacher hat geschrieben:ich gestalte meinen Indexaufbau so.
also genau so wie ich. Nur dass ich es in einer Schleife mache, weil bei mir die Infos aus einer DB kommen.
Gruß,
Magic
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12913
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 46 Mal

Re: Indexaufbau per INDEX ON

Beitrag von AUGE_OHR »

versuche es mal hiermit

Code: Alles auswählen

ordCondSet( ,  ,, , ,  , RECNO(), , , , , , ,  ) ;ordCreate("spstamm.cdx", "spstamm", "sa+liefnr+lartnr+artnr", _EarlyBoundCodeblock({|| sa+liefnr+lartnr+artnr}), , .F. )

ordCondSet( ,  ,, , ,  , RECNO(), , , , , , ,  ) ;ordCreate("spstamm.cdx", "spstamm", "sa+liefnr+lartnr+artnr", _EarlyBoundCodeblock({|| sa+liefnr+lartnr+artnr}), .T., .F. )

ordCondSet( ,  ,, , ,  , RECNO(), , , , .T., , ,  ) ;ordCreate("spstamm.cdx", "spstamm", "sa+liefnr+lartnr+artnr", _EarlyBoundCodeblock({|| sa+liefnr+lartnr+artnr}), , .F. )

ordCondSet( ,  ,, , ,  , RECNO(), , , , , .T., ,  ) ;ordCreate("spstamm.cdx", "spstamm", "sa+liefnr+lartnr+artnr", _EarlyBoundCodeblock({|| sa+liefnr+lartnr+artnr}), , .F. )

ordCondSet( ,  ,, , ,  , RECNO(), , , , , , .T.,  ) ;ordCreate("spstamm.cdx", "spstamm", "sa+liefnr+lartnr+artnr", _EarlyBoundCodeblock({|| sa+liefnr+lartnr+artnr}), , .F. )
siehe dir mal an wo die .T. stehen
gruss by OHR
Jimmy
Benutzeravatar
Magic
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 343
Registriert: Mo, 11. Jul 2011 12:01

Re: Indexaufbau per INDEX ON

Beitrag von Magic »

Tom hat geschrieben:Eben. OrdCreate hat entsprechende Parameter, wodurch sich das ganze in einer einzigen Zeile machen ließe, außerdem kann man auf bremsende Makros verzichten. Übrigens geht das sowieso - Dateinamen usw. einfach klammern:

Code: Alles auswählen

INDEX ON (cIndexKey) TAG (cIndexTag) TO (cIndexDatei) UNIQUE
ich habe den Grund noch nicht verstanden,
aber bei mir (in diesem Fall) funktioniert das so nicht.
Das Programm steigt an dieser Stelle ohne jegliche Fehlermeldung (auch keinerlei XPPERROR.LOG, etc.) aus.
Bricht an dieser Stelle einfach ab.
Gruß,
Magic
Benutzeravatar
Rolf Ramacher
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 1931
Registriert: Do, 09. Nov 2006 10:33
Wohnort: Bergheim
Danksagung erhalten: 3 Mal
Kontaktdaten:

Re: Indexaufbau per INDEX ON

Beitrag von Rolf Ramacher »

Hi Magic,

gibt es eine fatal.log ??
Gruß Rolf

Mitglied der Gruppe XUG-Cologne
www.xug-cologne.de
Benutzeravatar
Magic
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 343
Registriert: Mo, 11. Jul 2011 12:01

Re: Indexaufbau per INDEX ON

Beitrag von Magic »

Guten Morgen,
Rolf Ramacher hat geschrieben:gibt es eine fatal.log ??
nein. Es gibt nichts. Das programm bricht an der stelle einfach ab. Das Fenster wird ohne jegliche Meldung und *.log geschlossen. Mache ich es mit dem Makro-Operator läuft es problemlos.

Es ist aber auch an dieser Stelle kein "Flaschenhals" dadurch. Werde also hier keine Arbeit investieren um es unbeding anders zu machen.
Merkwürdig ist es aber schon.
Gruß,
Magic
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15710
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 73 Mal
Danksagung erhalten: 38 Mal
Kontaktdaten:

Re: Indexaufbau per INDEX ON

Beitrag von brandelh »

Magic hat geschrieben:Guten Morgen,
Rolf Ramacher hat geschrieben:gibt es eine fatal.log ??
nein. Es gibt nichts. Das programm bricht an der stelle einfach ab. Das Fenster wird ohne jegliche Meldung und *.log geschlossen. Mache ich es mit dem Makro-Operator läuft es problemlos.
Es ist aber auch an dieser Stelle kein "Flaschenhals" dadurch. Werde also hier keine Arbeit investieren um es unbeding anders zu machen.
Merkwürdig ist es aber schon.
Dass es keine Meldung gibt ist seltsam, kann es sein, dass dein Verzeichnis verstellt wurde ?
Diese LOG Dateien stehen nicht immer im EXE Verzeichnis, sondern im aktuellen Verzeichnis (curdir() z.B. ändert dieses).

Wenn es mit dem Makrooperator geht, dann enthält die Variable (cVar) vermutlich Quellcode (z.B. "upper(cFeld)+"...) und &(cVar) holt zuerst den Text aus der local und wandelt ihn dann um.

Mit XPP /P könntest du in er PPO Datei nachsehen, was Xbase++ aus deinem Code macht ;-)
Gruß
Hubert
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12913
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 46 Mal

Re: Indexaufbau per INDEX ON

Beitrag von AUGE_OHR »

brandelh hat geschrieben:Mit XPP /P könntest du in er PPO Datei nachsehen, was Xbase++ aus deinem Code macht ;-)
wie ich 4 Msg weiter oben als Beispiel gepostet habe.
wenn ich nicht genau weiss wo/wieviele "Komma" er haben will lasse ich die Befehle mittels /P "übersetzten" ;)
gruss by OHR
Jimmy
Benutzeravatar
Magic
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 343
Registriert: Mo, 11. Jul 2011 12:01

Re: Indexaufbau per INDEX ON

Beitrag von Magic »

Hi,

habe die .PPO Datei erzeugt.

Es geht ja um folgende Zeile:
In meiner .PRG steht:

Code: Alles auswählen

INDEX ON &cIndexKey TAG &cIndexTag TO &cIndexDatei
In der .PPO wird das übersetzt in:

Code: Alles auswählen

ordCondSet( ,  ,, , ,  , RECNO(), , , , , , ,  ) ;ordCreate(cIndexDatei, cIndexTag, cIndexKey, _EarlyBoundCodeblock({|| &cIndexKey}), , .F. )

Jetzt stelle ich in meiner .PRG die Notation um (statt &-Operator auf die Klammer)
In meiner .PRG steht nun:

Code: Alles auswählen

INDEX ON (cIndexKey) TAG (cIndexTag) TO (cIndexDatei)
In der .PPO finde ich dann folgendes:

Code: Alles auswählen

ordCondSet( ,  ,, , ,  , RECNO(), , , , , , ,  ) ;ordCreate((cIndexDatei), (cIndexTag), "(cIndexKey)", _EarlyBoundCodeblock({|| (cIndexKey)}), , .F. )


Anscheinend liegt es also an dem "(cIndexKey)"
habe dann in der .PRG geändert auf:

Code: Alles auswählen

INDEX ON &cIndexKey TAG (cIndexTag) TO (cIndexDatei)
finde dann in der .PPO

Code: Alles auswählen

ordCondSet( ,  ,, , ,  , RECNO(), , , , , , ,  ) ;ordCreate((cIndexDatei), (cIndexTag), cIndexKey, _EarlyBoundCodeblock({|| &cIndexKey}), , .F. )
ob da so in Ordnung ist? Auf den ersten Blick sollte es so sein.
Programmlauf ... Kein Abbruch, Ergebniss auch OK.

... nur den Unterscheid zwischen meiner ersten und der letzten Notation habe ich so richtig verstanden, wenn ich ehrlich bin #-o
Gruß,
Magic
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15710
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 73 Mal
Danksagung erhalten: 38 Mal
Kontaktdaten:

Re: Indexaufbau per INDEX ON

Beitrag von brandelh »

Magic hat geschrieben:... nur den Unterscheid zwischen meiner ersten und der letzten Notation habe ich so richtig verstanden, wenn ich ehrlich bin #-o
schön wenn du es verstanden hast ;-)
Ich vermute aber du meinst eher das Gegenteil ;-)

Die BEFEHLE interpretieren eine Quellcodezeile und müssen dort Feldnamen, Funktionen und Konstanten herausfiltern.
Das geht, solange keine Variablen benutzt werden. Local Variablen z.B. dürfen gar nicht mit &cLocalVar aufgerufen werden.
Nur Private Variablen stehen zur Laufzeit mit dem Namen zur Verfügung. In Clipper (vor 5.x) gab es nur PRIVATE oder PUBLIC, somit war diese Zeile kein Problem:

BEFEHL &cPrivateVar ....

zur Laufzeit wurde der Inhalt ausgewertet und notfalls auch code übersetzt.
Xbase++ kann damit gut umgehen, solange man auch PRIVATE verwendet, diese haben viele Nachteile (Performance, Nebenwirkungen etc.) und sind unerwünscht.
Mit einer LOCAL kann aber der obige Befehl nicht funktionieren, daher wurde die Syntax mit den () eingeführt.
Die Syntax (cLocalVar) zeigt dem Compiler, dass er im Code etwas vorsehen muss, das den Inhalt der Speicherzelle die zur Compilierungszeit cLocalVar geheißen hat weitergibt und nicht den Text "(cLocalVar)" - in anderen Sprachen würde man das wohl als ZEIGER oder POINTER bezeichnen.

In deinem Beispiel, scheint nun der alleinige INHALT nicht zu reichen, er muss zusätzlich noch interpretiert werden, dazu würde man &(cLocalVar) schreiben:

BEFEHL (cPrivateVar) .... // wertet den Inhalt aus und übergibt diesen als Text
BEFEHL &(cPrivateVar) .... // wertet den Inhalt aus und kompiliert diesen, der Inhalt müsste also CODE sein. z.b. "{|cFeld| upper(cFeld) }"

Allerdings ist das mit der Umsetzung solch komplexer Formen nicht ganz trivial und die Funktionen wie OrdCreate() sind in der Hilfe sauber dokumentiert.
Dort kann man als Parameter direkt die Variablen übergeben und spart sich den ganzen Macro-Ärger.

Daher verwende ich wann immer möglich direkt die Funktionen !
Gruß
Hubert
Benutzeravatar
Magic
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 343
Registriert: Mo, 11. Jul 2011 12:01

Re: Indexaufbau per INDEX ON

Beitrag von Magic »

brandelh hat geschrieben:schön wenn du es verstanden hast
Ich vermute aber du meinst eher das Gegenteil
RICHTIG :!: Habe da wohl was vergessen.
brandelh hat geschrieben:Das geht, solange keine Variablen benutzt werden. Local Variablen z.B. dürfen gar nicht mit &cLocalVar aufgerufen werden.
... und genau das verstehe ich an dem Konstrukt nicht. Denn alle 3 Variablen sind bei mir LOCAL :!: :?:
Ich glaube es muss noch ein wenig Zeit vergehen bis ich es vielleicht verstehen werde :roll:
Gruß,
Magic
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15710
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 73 Mal
Danksagung erhalten: 38 Mal
Kontaktdaten:

Re: Indexaufbau per INDEX ON

Beitrag von brandelh »

Ok, dann versuche ich es auch zu verstehen, wir werden es schon schaffen ;-)

der PPO Code ist der Code, der vom Präprozessor für den Compiler erzeugt wird.
ordCreate((cIndexDatei), (cIndexTag), "(cIndexKey)", _EarlyBoundCodeblock({|| (cIndexKey)}), , .F. )
ordCreate((cIndexDatei), (cIndexTag), cIndexKey, _EarlyBoundCodeblock({|| &cIndexKey}), , .F. )
laut Hilfe benötigt die Funktion ...

Code: Alles auswählen

OrdCreate( <cIndexFile> , [<cTagName>], <cIndexKey>, [<bIndexKey>], [<lUnique>], [<lAdditive>] )
Die Parameter die einfach Text beinhalten (cIndexFile, cTagName) machen beim Aufruf von (cLocalIndexFile) keine Probleme, da ein Text übergeben wird.
Der Parameter cIndexKey könnte einfach ein Feldname sein, der übergeben wurde: cIndexKey := "PLZ" -> Feld PLZ soll indiziert werden.
Die PRIVATE Variable cIndexKey würde den Inhalt "PLZ" haben und ist zur Laufzeit als Variable 'cIndexKey' bekannt !
- im ersten Beispiel als "(cIndexKey)" übergeben, wird in der Funktion daraus &"(cIndexKey)" => "PLZ" OK
- im zweiten Beispiel als Variable cIndexKey übergeben, wird in der Funktion daraus &cIndexKey => "PLZ" OK

Wenn nun eine LOCAL Variable cIndexKey verwendet wird, ändert sich das Verhalten.
Der Inhalt "PLZ" ist gleich, aber die Variable 'cIndexKey' gibt es zur Laufzeit nicht !
- im ersten Beispiel als "(cIndexKey)" übergeben, wird die Funktion versuchen daraus mit &"(cIndexKey)" die Variable 'cIndexKey' abzufragen.
Die gibt es nicht, also SOLLTE ein Laufzeitfehler "unbekannte Variable" ausgelöst werden ... (aus dem Gedächtnis ;-)) => Ende - hoffentlich mit XppError.log oder XppFatal.log
- im zweiten Beispiel wird die Adresse der Variablen cIndexKey übergeben, in der Funktion wird auf die Adresse zugegriffen und aus dem Inhalt der Speicherstelle gelesen => "PLZ" OK

so das deckt sich mit deinen Ergebnissen, wobei ich die Ausführungen zum Macrooperator ergänzen muss ...

Auch lokale Variblen dürfen (wie oben gesehen) mit &cLocalVar "bearbeitet" werden, nur darf man nicht erwarten, dass der Name von lokalen Variablen im Textstring zur Laufzeit auf die lokale Variable zugreift ! Der & Operator kompiliert Quellcode :!: mehr nicht ...

immer OK, solange das Feld existiert ;-)
cVar := "upper(name)" // name ist ein Feld ! cVar kann hier private oder local sein.
replace IndexName with &cVar => IndexName := upper(field->name)
das ginge zwar, aber hätte ein unerwünschtes Ergebnis ;-)
replace IndexName with (cVar) => IndexName := "upper(field->name)"
solange der Feldname in der PRIVATE cFeldName steht und das Feld existiert OK

Code: Alles auswählen

private cFeldName
cFeldName := "name"
cVar := "upper(cFeldName)"
replace IndexName with &cVar => IndexName := upper(field->name)
das jedoch geht nicht so

Code: Alles auswählen

local cFeldName
cFeldName := "name"
cVar := "upper(cFeldName)"
replace IndexName with &cVar => IndexName := "upper(field->name)" 
gleiches Ergebnis ...

Code: Alles auswählen

local cFeldName
cFeldName := "name"
cVar := "upper(cFeldName)"
replace IndexName with (cVar) => IndexName := "upper(field->name)" 
Solange es reicht, den Inhalt einer Variablen an den BEFEHL zu geben, reicht ein (cVar)
Wenn man als Inhalt CODE hat, der ausgewertet werden soll, dann muss &(cVar) oder &cVar verwendet werden.
Eine LOCAL Variable, darf nie im Code-Text vorkommen, denn diese wird zur Laufzeit nicht in den Inhalt übersetzt, sondern nur als Text interpretiert.
Man muss diese z.B. auflösen. Beispiel in Suchmasken:

Code: Alles auswählen

PRIVATE cSuchName, cSuchbedingung
cSuchName := "Müller"
cSuchName := alltrim(cSuchName)
cSuchbedingung := "{|| upper(Name) = upper(cSuchName)}"
...
if &(cSuchName) 
   ... gefunden ...
else
   ... 
aus altmodisch Clipper 4.x mach modern mit local ;-)

Code: Alles auswählen

local cSuchName, cSuchbedingung
cSuchName := "Müller"
cSuchbedingung := "{|| upper(Name) = upper(alltrim( ' "+cSuchName+" ' ))}" // => "{|| upper(Name) = upper(alltrim('Müller'))}"
...
if &(cSuchName) 
   ... gefunden ...
else
   ... 
*** Man beachte die ' vor und nach den " um die eingefügte Variable.
Es ist hilfreich diese Konstrukte als Text mit msgbox() anzuzeigen und zu prüfen ;-)
PS: die zusätzlichen Blanks zwischen " und ' sind nur zum besseren Sehen drin.
Gruß
Hubert
Benutzeravatar
Magic
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 343
Registriert: Mo, 11. Jul 2011 12:01

Re: Indexaufbau per INDEX ON

Beitrag von Magic »

=D> Vielen Dank für die ausfürliche Erläuterung =D>
brandelh hat geschrieben:Wenn man als Inhalt CODE hat, der ausgewertet werden soll, dann muss &(cVar) oder &cVar verwendet werden.
Das war jetzt das entscheidene, damit ich das entlich vertehen konnte. Jetzt muss ich es nur noch richtig verdauen.

Vielen Dank!
Gruß,
Magic
Antworten