2015-12-18 24 views
6

Ich bin ein COBOL-Programmierer, und mein neuestes Projekt ist es, eine COBOL-Anwendung mit einer SQLite3-Datenbank zu verbinden.Wie schreibe ich SQLite Callback in COBOL

Ich habe this guide verfolgt, und ihre Lösung ist genau das, was ich in meiner COBOL-Anwendung benötigen würde. Es ist mir gelungen, Daten zu erstellen, zu verbinden, Daten einzufügen und die Datenbank zu schließen, aber das Problem tritt auf, wenn ich versuche, Daten aus der Datenbank auszuwählen.

Im Tutorial verwenden sie einen Callback mit Doppelzeigern.

static int callback(void *NotUsed, int argc, char **argv, char **azColName){ 
    int i; 
    for(i=0; i<argc; i++){ 
     printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL"); 
    } 
    printf("\n"); 
    return 0; 
} 

Meine Lösung in COBOL wird wie folgt

WORKING-STORAGE SECTION. 
    *----------------------------------------------------------------* 

    01 sqlite3-db   pointer. 
    01 err_msg   pointer. 
    01 sqlite    pointer. 
    01 res    pointer. 

    01 notused   pointer. 
    01 argc    pic 99 comp-5. 
    01 argv    pointer. 
    01 azColName   pointer. 
    01 Writefunction-Ptr procedure-pointer. 

    procedure division. 
      set Writefunction-Ptr to entry "sqlite-callback". 

      *>Random code. 

      call "sqlite3_exec" using 
      by value sqlite3-db 
      by reference sqlQuery 
      by value Writefunction-Ptr 
      by value 0 
      by reference err_msg 
      returning rc 
      end-call 

      *>Random code. 

    stop run. 

    entry "sqlite-callback" using 
      by value notused 
      by value argc 
      by reference argv 
      by reference azColName. 

     display argc 

     goback. 
    Entry-Termination. 

Der Rückruf funktioniert, weil es die Anzahl der Zeilen aufgerufen wird, die aus der Datenbank, und die ganze Zahl argc enthält die Anzahl der Spalten, die die zurückgegeben Tabelle enthält.

Die Frage ist:

Doppelzeiger in COBOL, wie sind sie vertreten? In meiner Lösung deklariere ich einen Zeiger und rufe den Callback mit "by reference" auf den Zeiger. Wissen Sie nicht, ob dies der richtige Weg ist, Doppelzeiger in COBOL darzustellen?

Wie zeige ich den Inhalt von azColName und argv an und nicht nur die Speicheradresse, auf die der Zeiger zeigt?

Ich versuchte jetzt, SET ADDRESS OF zu verwenden, aber ich bekomme es immer noch nicht zur Arbeit. Muss etwas sein, das ich vermisst habe. Meine Lösung ist im Moment wie folgt aussieht:

WORKING-STORAGE SECTION. 
01 argv pointer. 

Linkage Section. 
01 link-area pic x. 

procedure division using link-area. 

*> RANDOM CODE 

    set address of link-area to argv 
    call "sqlite3_exec" using 
     by value sqlite3-db 
     by reference z"SELECT * FROM Cars" 
     by value Writefunction-Ptr 
     by value 0 
     by reference err_msg 
     returning rc 
     end-call 

*> RANDOM CODE 


entry "sqlite-callback" using 
    by value notused 
    by value argc 
    by reference argv 
    by reference azColName. 

    display argc. 

    if address of link-area not = null 
    display "Contents of new argv: " link-area 
    else 
    display "empty" 
    end-if 

    goback. 

Entry-Termination. 

Das Ergebnis, das ich bekommen ist, dass die if-Anweisung immer falsch ist, so dass die Zeichenfolge „leer“ angezeigt wird. Aber immer noch wird argc auf die Anzahl der Spalten in der Tabelle gesetzt.

Die Arbeitslösung:

WORKING-STORAGE SECTION. 

    01 argv. 
     03 firstColumn pointer. 
     03 secondColumn pointer. 
     03 thirdColumn pointer. 

    01 azColName   pointer. 
    01 argc    pic 99 comp-5. 
    01 notused   pointer. 

    01 Writefunction-Ptr procedure-pointer. 

    *----------------------------------------------------------------- 
    Linkage Section. 

    01 Cars_Id  pic 9(2). 
    01 Cars_Name  pic X(20). 
    01 Cars_Price pic 9(10). 
    /----------------------------------------------------------------- 
    procedure division. 

    //code  

    set Writefunction-Ptr to entry "sqlite-callback". 

      initialize sqlQuery 
      move z"SELECT * FROM Cars;" to sqlQuery 


      call "sqlite3_exec" using 
      by value sqlite3-db 
      by reference sqlQuery 
      by value Writefunction-Ptr 
      by value 0 
      by reference err_msg 
      returning rc 
      end-call 

    //code 

    stop run. 



    entry "sqlite-callback" using 
      by value notused 
      by value argc 
      by reference argv 
      by reference azColName. 

     set address of Cars_Id to firstColumn 
     set address of Cars_Name to secondColumn 
     set address of Cars_Price to thirdColumn 


     display Cars_Id "|" Cars_Name "|" Cars_Price 

     goback. 
    Entry-Termination. 
+1

Welche COBOL verwenden Sie? Kompiliert das ohne LINKAGE SECTION? Sehen Sie sich SET ADDRESS von x TO your-pointer an, wobei x in der LINKAGE SECTION definiert ist und die gewünschte Größe und den Typ hat. Dadurch können Sie auf die Daten zugreifen, auf die der Zeiger zeigt. –

+0

Marcus verwendet einen MicroFocus ServerExpress Compiler. – Anders

Antwort

3

Wir müssen wirklich den Compiler wissen Sie verwenden.

Ihre SET-Anweisung ist an der falschen Stelle. argv hat nur eine Adresse, wenn der ENTRY aufgerufen wird. Bevor der Eintrag aufgerufen wird, ist es eine binäre Null oder irgendein unvorhersehbarer Müll.

Wenn Sie das SET nach dem ENTRY verschieben, sollten Sie den Wert von LINK-AREA verwenden können. argv wird immer noch nur eine Adresse sein, aber LINK-AREA (bitte geben Sie ihm einen besseren Namen) wird auf diese Adresse zeigen, also definieren Sie es als argv, und LINK-AREA kann verwendet werden, um den eigentlichen Inhalt zu erhalten von argv.


Bei Verwendung von BY REFERENCE der Compiler Code, um einen Zeiger mit der Adresse des Datenelements passieren erzeugt.

Auf dem PROCEDURE DIVISION USING oder ENTRY USING sollte das Element auch durch Verweisung sein und der Compiler generiert Code, um Ihre LINKAGE-SECTION-Definition auf die übergebene Adresse zuzuordnen.

Das ist ähnlich, wenn Sie BY CONTENT verwenden, aber der Compiler nimmt eine Kopie der Daten in Ihrem Programm und übergibt einen Zeiger, der stattdessen verweist.Bei der Verwendung der PROCEDURE DIVISION oder ENTRY, die immer noch als BY REFERENCE definiert ist.

Mit "übergibt" der Compiler den tatsächlichen Wert, obwohl es Grenzwerte gibt, entweder die im Standard oder Erweiterungen des Standards mit Ihrem tatsächlichen Compiler angegebenen. Die USING der PROCEDURE DIVISION oder ENTRY sollte auch BY VALUE angeben.

Auf alle USINGs, die durch REFERENCE/CONTENT/VALUE weitergegeben werden, müssen Sie BY überhaupt nicht angeben, wenn alle gleich sind und Sie möchten, dass es nach REFERENCE der Standardwert ist.

Wenn Sie einen POINTER (USAGE POINTER) "übergeben", können Sie auf die Daten zugreifen, auf die mit SET ADDRESS OF verwiesen wird. Die SET ADRESSE des Artikels muss in der LINKAGE SECTION sein.

Sie können auch einen impliziten Zeiger mit SET ADDRESS OF verwenden. SET-Adresse eines TO ADDRESS OF b die in der LINKAGE SECTION an die Adresse b abgebildet Adresse ändern, ein Element, das irgendwo in Ihrem Programm definiert ist DATA DIVISION (jeder Abschnitt außer den FILE SECTION). TO-Zeiger-name

Wenn Sie wollen, dass die Daten darauf zu durch einen Zeiger, definieren Sie ein Element, um zu sehen, die die richtige Größe und Art und Verwendung SET ADDRESS OF Element hat.

Der Zeiger kann natürlich auf ein einfaches Datenelement oder eine Gruppe Daten-Element (eine Struktur) verweist.

Alle Artikel in der LINKAGE SECTION muss eine Adresse haben, bevor sie referenziert werden. Jene auf einem USING werden vom Compiler adressierbar gemacht (und der Compiler geht davon aus, dass die korrekte Anzahl von Adressen/Items übergeben wird). Alle anderen LINKAGE SECTION-Elemente müssen über eine Adressierbarkeit verfügen, die durch SET ADDRESS OF festgelegt wurde, oder indem ADDRESS OF in USING an CALL übergeben wird und das CALLed-Programm die Adresse festgelegt hat.

+0

Vielen Dank. Der Rückruf funktioniert jetzt. –