Remote SQL

Installationsanweisung und Programmierhandbuch für C++


Einen kurzen Überblick gibt Ihnen die Kurzinformation.

Inhaltsverzeichnis

Überblick

Installation

Programmierumgebung

Beispielprogramm


Überblick

Einsatzbereich

Der Zweck des Produktes Remote SQL (RSQL) ist es, dem Programmierer von Anwendungen auf einem PC zu gestatten, über eine Netzwerkverbindung auf Daten einer HP NonStop SQL/MP Datenbank zuzugreifen.

Realisierung

RSQL ist eine Erweiterung von Remote ENSCRIBE. Es wurde in Client/Server Architektur realisiert. Dabei stellt das HP-NonStop-System die Server-Maschine dar und der PC den Client. Folglich enthält RSQL zwei wesentliche Komponenten:

Die Kommunikation zwischen diesen beiden Komponenten erfolgt mittels TCP/IP. Genaue Kenntnisse dieses Protokollstacks werden vom Programmierer jedoch nicht verlangt, da sämtliche Netzwerkzugriffe durch C++ Klassenbibliotheken verborgen werden. Im Gegenteil: der Anwendungsprogrammierer kann sich während der Entwicklung weitestgehend auf die eigentlichen SQL- und Datenbankproblematiken konzentrieren, ohne sich um Details der Transportschichten kümmern zu müssen.

Die folgende Graphik verdeutlicht das Zusammenspiel der einzelnen Komponenten am Beispiel eines Windows-Clients:


Der Server-Prozess auf dem NonStop-Server wird über den LISTNER-Prozess des TCP/IP gestartet, sobald ein Client-Programm (es können auch mehrere dieser Client-Systeme eingesetzt werden) dies erfordert, d.h. eine Verbindung (Connection) eröffnet.

Durch Aufruf der zugehörigen Klassenfunktionen kann das Anwendungsprogramm nun auf die SQL-Daten zugreifen, wobei die Klassenbibliothek die Aufträge über das TCP/IP-Netzwerk an den Serverprozess sendet. Dieser interpretiert die Aufträge und führt die entsprechenden SQL-Operationen aus.

Anschließend überträgt er die Antwortdaten an den PC. Diese werden nun dort in systemgerechte Datenformate konvertiert und dem aufrufenden Anwendungsprogramm bereitgestellt.

Zum Inhaltsverzeichnis 


Installation

Die Installation ist in zwei Teile gegliedert, entsprechend der Aufteilung in Server und Client. Sie sollten jeweils erfahren sein im Umgang mit dem jeweiligen System.


Serverseite

Die Programmdatei RSQLSRV sollte sich normalerweise im Volume $SYSTEM.RSQL befinden. Es sind jedoch auch andere Volumes möglich.

Dieses Serverprogramm wird von dem LISTNER-Prozess gestartet, welcher im Standardumfang des TCP/IP-Pakets von HP enthalten ist. Der Start erfolgt in dem Moment, in dem auf irgendeinem Client im Netz eine RSQL-Verbindung geöffnet wird. Dann nämlich wird eine TCP/IP-Verbindung zu demjenigen TCP-Port hergestellt, der für den RSQL-Dienst als 'well-known' Port definiert wurde (s.u.). Abhängig vom Inhalt der Textdatei PORTCONF (s.u.) startet der LISTNER nun den zugehörigen Serverprozess, in diesem Fall 'RSQLSRV'. Für jede Verbindung wird somit auch jeweils ein neuer Serverprozess kreiert.

Der Remote-SQL-Server überprüft in der Startphase die auf der PC-Seite bei dem entsprechenden Funktionsaufruf verwendete Benutzerkennung und das Passwort. Bei Erfolg wird dem Prozess die entsprechende User-ID zugeordnet.

Befolgen Sie bitte zur Installation die folgenden Schritte:

Schritt 1: Übertragen der Programmdatei RSQLSRV

Mittels eines Filetransferprogrammes (z.B. FTP, welches Bestandteil jedes TCP/IP-Softwarepakets ist) wird die ausführbare Objektdatei RSQLSRV auf das HP-NonStop-System übertragen, wobei im folgenden als Zieldateiname $SYSTEM.RSQL.RSQLSRV angenommen wird. Beachten Sie, dass die Übertragung im Binärmodus erfolgen muss. In FTP erreicht man dies durch Eingabe des Befehls 'bin' .

Schritt 2: Einrichten der Programmdatei RSQLSRV

An einem TACL-Bildschirm werden nun folgende Befehle eingegeben:

LOGON SUPER.SUPER
VOLUME $SYSTEM.RSQL
- hier befindet sich die Programmdatei

FUP ALTER RSQLSRV, CODE 100
- deklariert die Datei als ausführbares Programm

SQLCOMP /IN RSQLSRV/ CATALOG $DATA.SQL
- registriert das Programm bei NonStop-SQL

Im letzten Befehl ist statt '$DATA.SQL' ein beliebiger auf dem System gültiger SQL-Katalog anzugeben.

Schritt 3: Bearbeiten der Datei PORTCONF

Diese Datei befindet sich normalerweise in $SYSTEM.ZTCPIP.PORTCONF und sollte bereits existieren. Sie stellt die Verbindung zwischen den TCP-Portnummern und den Namen der Programmdateien her, die die entsprechenden Serverprogramme enthalten. Für RSQL ist hier folgende Zeile einzutragen:

741 $SYSTEM.RSQL.RSQLSRV -p150

Der Name der Programmdatei ist hierbei entsprechend der tatsächlichen Installation anzugeben. Die Portnummer können Sie selbst bestimmen. Beachten Sie dabei jedoch, dass Ports unter 1024 nur von Supervisor-Prozessen verwendet werden können, was hier jedoch der Fall ist. Clientprogramme wissen in diesem Fall, dass der Server "vertrauenswürdig" ist, da er nur von einem authorisierten Systemadministrator eingerichtet worden sein kann. Beachten Sie weiterhin, dass Ports oberhalb 1024 dynamisch von anderen Anwendungsprogrammen verwendet werden. Sie können daher nicht sicher sein, dass der konfigurierte Port später tatsächlich verfügbar ist. In den weiteren Beispielen wird die hier angegebene Portnummer 741 weiter verwendet werden.

Der Parameter -p150 legt die Prozesspriorität auf 150 fest. Der LISTNER läuft normalerweise mit einer hohen Priorität, die er auf nachgelagerte Prozesse überträgt. Dies ist bei komplexen SQL-Abfragen jedoch unter Umständen nicht gewünscht und kann hier beinflusst werden.

Schritt 4: Neustart des Listner-Prozesses

Nachdem die oben genannten Schritte durchgeführt wurden und damit alle benötigten Dateien auf dem HP-NonStop-System-System verfügbar sind, muss der Listner-Prozess neu gestartet werden, um die Änderungen wirksam zu machen. Ansonsten würden die Änderungen erst beim nächsten Systemstart aktiviert werden.

    1. Stoppen Sie den Listner-Prozess

    2. Starten Sie den Listner-Prozess erneut

Leider kann hier keine allgemeingültige Vorgehensweise angegeben werden, da diese Schritte auf nahezu jedem System anders erfolgen müssen. Als Hinweis kann dabei die Startup-Prozedur des TCP/IP-Systems dienen.

Damit ist die Installation der Serverseite abgeschlossen.

Zum Inhaltsverzeichnis


PC-Seite

Auf der PC-Seite sind bei der Installation von RSQL selbst keine Programme zu installieren, sondern lediglich einige Dateien, die im folgenden beschrieben werden. Diese Dateien werden vom Anwendungsentwickler verwendet, um eigene Anwendungsprogramme zu übersetzen und zu binden. Dies ist in Kapitel 3. detailiert beschrieben.

Die erwähnten Dateien werden nur auf dem PC benötigt, auf dem die Entwicklung, d.h. die Übersetzung Ihres Anwendungsprogrammes erfolgt. Das fertiggestellte Programm kann später auch auf anderen Systemen eingesetzt werden, ohne dass hierfür eine RSQL-spezifische Installation notwendig wäre.

Zunächst sind diese Dateien jedoch auf dem Entwicklungs-PC zu installieren:

Schritt 1: Anlegen eines Verzeichnisses zur Aufnahme der Dateien

Sie können hier ein beliebiges Verzeichnis wählen. Dieses kann sich sowohl auf der Festplatte des Entwicklungs-PCs, als auch auf einem über Netzwerk erreichbaren Fileserver befinden. In den folgenden Beispielen wird hier das Verzeichnis C:\RSQL verwendet.

Schritt 2: Kopieren der Dateien in das angelegte Verzeichnis

Kopieren Sie die folgenden Dateien von der Auslieferungsdiskette in das in Schritt 1 angelegte Verzeichnis:

NSSQL.H
RSQL.H
RSQLERR.H
RENSCRIB.H
RSQL.LIB

Damit ist die Installation der PC-Seite abgeschlossen. Wird die Source-Version der Bibliothek verwendet, sind statt der LIB-Datei die drei Dateien RSQLCS.H, RENSCRIB.C und RSQL.CPP zu installieren.

Zum Inhaltsverzeichnis


Programmierumgebung

Dieses Kapitel beschreibt die Programmierschnittstelle zu RSQL für den Programmierer von Anwendungsprogrammen, die auf NonStop-SQL/MP Daten über Netzwerk zugreifen sollen.


Einführung

RSQL verwendet zur Ausführung von Datenbankoperationen dynamische SQL-Anweisungen. Um solche SQL-Anweisungen in ein Anwendungsprogramm, welches auf einem Client-System laufen soll, aufzunehmen, stellt RSQL eine Bibliothek von Funktionen bzw. C++-Klassen zur Verfügung.

Die gesamte Netzwerkanbindung und die Realisierung des Client/Server-Systems werden in den Klassenbibliotheken (mit Ausnahme der Netzwerkadresse des HP-NonStop-Systems) verborgen.

Noch ein Wort für C++-Neulinge: die RSQL Klassenbibliotheken fordern keine tiefgehenden Kenntnisse der Programmiersprache C++. Wenn Sie bereits erfahren sind im Umgang mit C, so wird Ihnen die Verwendung von RSQL kaum Schwierigkeiten bereiten. Folgen Sie einfach den Beispielen. Auf der anderen Seite nimmt Ihnen C++ aber eine Menge Arbeit ab und sorgt unter anderem dafür, dass Ihre Programme zuverlässiger ablaufen.


Übersetzen, Binden, Starten unter Windows

Die vorliegende Version ist auf die Verwendung des Visual-C++ Compilers der Firma Microsoft ab Version 4.0 ausgelegt. In den folgenden Beispielen wird daher auf diesen Compiler und die zugehörige Entwicklungsumgebung Microsoft Developer Studio eingegangen.

Im folgenden wird davon ausgegangen, dass Sie den Umgang mit dem Microsoft Developer Studio bereits kennen. Daher wird nicht jeder Schritt im Einzelnen erläutert. Folgen Sie den folgenden Schritten, um ein neues Projekt mit Verwendung von RSQL anzulegen:


Zum Inhaltsverzeichnis


Programmierschnittstelle (API)

RSQL stellt dem Programmierer eine Bibliothek von C++-Klassen zur Verfügung, mit deren Hilfe er innerhalb seiner Anwendung

Dieser Abschnitt enthält zum einen die Referenz dieser API und andererseits einige Hinweise und Beispiele zu deren Anwendung.


Konzepte

Um RSQL innerhalb Ihrer Anwendung benutzen zu können, ist es erforderlich die Datei rsql.h mittels der Präprozessoranweisung #include in jede CPP-Datei einzubinden, in welcher Sie solche Funktionen verwenden möchten. In dieser Datei und in den durch diese ebenfalls eingebundenen Dateien befinden sich sämtliche Deklarationen und Definitionen der in RSQL verfügbaren Datentypen.

Bevor die einzelnen Daten- bzw. Klassentypen im Detail beschrieben werden, soll hier kurz ein Überblick geboten werden.

Ein typischer Programmablauf beginnt im allgemeinen mit dem Erzeugen eines Objektes vom Typ RSQL_Connection. Dies kann z.B. dadurch erfolgen, dass dieses Objekt als statische Variable oder aber als Auto-Variable einer Funktion definiert wird. Die erste Methodenfunktion, die Sie aufrufen ist Connect. Unter Angabe der Netzwerkadresse des HP-NonStop-Systems und einer dort gültigen Benutzerkennung wird eine Verbindung zu diesem Rechner hergestellt und ein dieser Verbindung zugehöriger RSQL-Serverprozess gestartet.

Ist die Verbindung einmal hergestellt, so können Sie weitere Methoden von RSQL_Connection verwenden, um Transaktionen zu steuern, einfache SQL-Befehle auszuführen, oder komplexere SQL-Anweisungen zu übersetzen. Letzeres geschieht mittels der Methode Prepare, der Sie den Text des SQL-Befehls übergeben. Diese erzeugt ein Objekt der Klasse RSQL_Statement. Dies ist auch die einzige zulässige Methode, ein solches Objekt zu erzeugen, da die Klasse keinen öffentlichen Konstruktor besitzt. Ein Statement ist auf diese Weise immer fest mit der erzeugenden Connection verbunden. Beim Entfernen der Connection werden somit auch immer alle zugehörigen Statements entfernt.

Nachdem das Objekt der Klasse RSQL_Statement erzeugt wurde und Sie einen Zeiger auf dieses Objekt erhalten haben, können Sie das Statement ausführen oder einen Cursor darauf deklarieren. Außerdem liefert Ihnen das Objekt Informationen über die Struktur der Ein- bzw. Ausgabedaten. Hierzu dienen die Klassen RSQL_DescriptorList und RSQL_Descriptor.

Das Deklarieren eines Cursors erfolgt mit Hilfe der Methode DeclareCursor, die einen Zeiger auf ein Objekt der Klasse RSQL_Cursor liefert. Dies ist vergleichbar mit der Erzeugung eines RSQL_Statements aus einer RSQL_Connection. Einen solchen Cursor können Sie nun mittels der Methodenfunktion Open öffnen und anschließend die Daten innerhalb einer Programmschleife lesen. Hierzu dient die Funktion Fetch.

Die Daten, die Fetch liefert werden in einen Speicherbereich abgelegt, dessen Adresse Sie angeben müssen, und den Sie reservieren müssen. Dies kann entweder dynamisch erfolgen, indem Sie die Größe und Strukturbeschreibung von RSQL_Statement erfragen oder Sie definieren eine C-Struktur, die einen solchen Speicherbereich beschreibt.

Die Daten in diesem Speicherbereich sind gemäß der Konventionen für C und für den in dem PC eingesetzten Prozessor ausgelegt. Die Konvertierung zwischen diesem Format und dem auf dem HP-NonStop-System von NonStop-SQL verwendeten erfolgt automatisch durch die RSQL-Bibliothek.

Zum Inhaltsverzeichnis


Datentypen

Wie bereits erläutert, werden beim Zugriff auf NonStop-SQL-Daten diese in C-konforme Datentypen auf dem PC konvertiert. Hier finden Sie eine Aufstellung der einzelnen Typen und wie Sie auf der PC-Seite gespeichert werden.
 


SQL-Datentyp

C-Datentyp

Bemerkung

CHAR(n)

char[n+1]

mit Leerzeichen aufgefüllt und mit Null-Byte abgeschlossen

VARCHAR(n)

char[n+1]

mit Null-Byte zur Längenbestimmung abgeschlossen

SMALLINT, 
NUMERIC(1-4, scale)

short

mit 10scale multipliziert

unsigned NUMERIC(1-4, scale)

unsigned short

mit 10scale multipliziert

INTEGER, 
NUMERIC(5-9, scale)

long

mit 10scale multipliziert

unsigned NUMERIC(5-9, scale)

unsigned long

mit 10scale multipliziert

LARGEINT, 
NUMERIC(10-18, scale)

longlong

mit 10scale multipliziert 
(longlong: s.u.)

REAL

float

Umwandlung kann nur näherungsweise erfolgen, dabei ist mit Ungenauigkeiten zu rechnen

DOUBLE

double

Umwandlung kann nur näherungsweise erfolgen, dabei ist mit Ungenauigkeiten zu rechnen

DECIMAL(n,m)

RSQL_Decimal[n+1]

wird als Ziffernstring gespeichert 
(RSQL_Decimal: s.u.)

DATETIME

RSQL_DateTime[n+1]

wird als Ziffernstring gespeichert 
(RSQL_DateTime: s.u.)

INTERVAL

RSQL_Interval[n+1]

wird als Ziffernstring gespeichert 
(RSQL_Interval: s.u.)

Nullindikator

RSQL_NullIndType

ist ungleich 0, wenn Nullwert vorliegt

 

Für einige Datentypen stehen keine Standardtypen in C bzw. C++ zur Verfügung. Für diese existieren folgende zusätzliche Vereinbarungen:

Zum Inhaltsverzeichnis


Fehlerbehandlung

Obwohl sicherlich unerwünscht, ist es jedoch möglich, dass die Ausführung einer Funktion der RSQL-Bibliothek fehlschlägt. Für diesem Fall stehen jedoch die im folgenden beschriebenen Diagnosefunktionen zur Verfügung.

Die meisten Funktionen liefern ein Ergebnis vom Typ RSQL_OkType, um anzuzeigen, ob die Ausführung erfolgreich war oder nicht. Dieser Typ ist wie folgt definiert:

enum RSQL_OkType { RSQL_NotOk=0, RSQL_Ok=1 };

Normalerweise wird RSQL_Ok zurückgegeben, im Fehlerfall jedoch RSQL_NotOk. Wenn dies der Fall ist, so kann mit der Funktion RSQL_Error der Fehlercode ermittelt werden.

RSQL_ErrorCode RSQL_Error();

Der Fehlercode wird als 16-bit Zahl dargestellt.

typedef short RSQL_ErrorCode;

Der Fehlercode kann dabei in verschiedenen Bereichen liegen, abhängig von der Fehlerursache, z.B.

Für den letzten Fall stehen symbolische Namen für die möglichen Fehlercodes zur Verfügung:

Einen Spezialfall stellt der Fehlercode 100 dar, wenn er von der SQL-Datenbank geliefert wurde. Dieser bedeutet, dass keine weiteren Daten mehr geholt werden können, da bereits alle Daten übertrgen wurden. Um diesen Fall zu überprüfen steht die Funktion RSQL_NoMoreData zur Verfügung.

int RSQL_NoMoreData();

Sie liefert 1, wenn der beschriebene Fall eingetreten ist und 0 sonst.

Meist ist es sinnvoll, eine genaue textuelle Beschreibung des Fehlers an den Programmanwender ausgeben zu können. Für diese Aufgabe existiert die Funktion RSQL_ErrorText, die einen Zeiger auf den Fehlertext liefert.

const char *RSQL_ErrorText();

Beachten Sie, dass der über den Zeiger referenzierte Speicherbereich nur vorübergehend den gültigen Fehlertext enthält. Wenn Sie diesen weiterhin zur Verfügung haben möchten, aber zwischendurch andere RSQL-Funktionen aufrufen müssen, so muss dieser Text in einen separaten Bereich kopiert werden.

Zum Inhaltsverzeichnis


Die Basisklassen

Dieser Abschnitt beschreibt die Funktion und die öffentlichen Komponenten, Daten und Methoden, der von RSQL zur Verfügung gestellten C++-Klassen.

Allgemeines zu Rückgabewerten:

Die meisten Funktionen liefern einen Rückgabewert vom Typ RSQL_OkType. Dieser kann zwei Werte annehmen (s. auch Abschnitt "Fehlerbehandlung"): RSQL_Ok, falls die Funktion erfolgreich ausgeführt werden konnte, andernfalls RSQL_NotOk. Da dies bei allen Funktionen gleich ist, wird darauf im folgenden nicht weiter eingegangen.

Eine Reihe anderer Funktionen liefern als Ergebnis einen Zeigertyp. In diesem Fall bedeutet die Rückgabe eines Nullzeigers, dass die Funktion nicht erfolgreich ausgeführt werden konnte.


RSQL_Connection

Objekte der Klasse RSQL_Connection dienen zur Verwaltung von Client/Server-Verbindungen zwischen dem PC und dem HP-NonStop-System.

RSQL_Connection()
Konstruktor. Initialisiert das Objekt, stellt aber noch keine Netzwerkverbindung her.

~RSQL_Connection()
Destruktor. Trennt die Netzwerkverbindung und löscht alle zugehörigen Statements und Cursor.

RSQL_OkType Connect(
const char *hostname, short port, const char *username, const char *password)
dient zum Herstellen einer Netzwerkverbindung. hostname ist ein gültiger Hostname bzw. eine IP-Adresse der Form a.b.c.d. port ist die TCP-Portnummer, die dem Server auf der NonStop-Seite zugewiesen wurde. (s. Installation der Serverseite). username ist ein auf dem HP-NonStop-System bekannter Benutzername. password ist das dem Benutzer zugehörige Kennwort.

PHOST econnex
enthält nach Herstellung der Netzwerkverbindung einen Zeiger auf die Verwaltungsstruktur der Remote-Enscribe-Verbindung. Eine detailierte Erläuterung des Datentyps PHOST finden Sie in der API-Beschreibung zu R-Enscribe.

RSQL_OkType Disconnect()
Trennt die Netzwerkverbindung und löscht alle zugehörigen Statements und Cursor.

RSQL_OkType LoadDefines(const char *commandOrFilename)
bewirkt die Ausführung von Befehlen zur Modifikation der DEFINEs auf der Serverseite. commandOrFilename kann entweder einen gültigen Befehl zur Änderung von Defines (Add, Alter, Delete) enthalten oder den Namen einer Guardian-Datei, die solche Befehle enthält. Andere TACL-Befehle, die in einer solchen Datei vorkommen werden ignoriert mit Ausnahme von OBEY (bzw. O).

RSQL_OkType BeginWork()
RSQL_OkType CommitWork()
RSQL_OkType RollbackWork()
dienen zur Transaktionskontrolle und entsprechen damit den gleichlautenden SQL-Befehlen.

RSQL_OkType ExecImmediate(const char *statement)
führt ein SQL-Statement direkt aus (entspricht EXECUTE IMMEDIATE). statement enthält ein gültiges SQL-Statement.

RSQL_Statement *Prepare(const char *name, const char *statement)
übersetzt ein SQL-Statement, dessen Text sich in statement und dessen Name sich in name befindet. Der Rückgabewert ist ein Zeiger auf ein mittels new-Operator erzeugtes Objekt vom Typ RSQL-Statement (s.u.). Wenn die Übersetzung auf Serverseite fehlschlägt, so wird kein Statement-Objekt angelegt und stattdessen ein Nullzeiger geliefert.

RSQL_Statement *FindStatement(const char *name)
sucht ein Statement-Objekt innerhalb einer Serververbindung. Es wird ein Zeiger auf dasjenige Objekt geliefert, welches beim Prepare (s.o.) mit dem gleichen Namen übersetzt wurde.

RSQL_Cursor *FindCursor(const char *cursorname)
sucht ein Cursor-Objekt innerhalb einer Serververbindung. Es wird ein Zeiger auf dasjenige Objekt geliefert, welches beim DeclareCursor (s. Abschnitt RSQL_Statement) mit dem gleichen Namen deklariert wurde.

Zum Inhaltsverzeichnis


RSQL_Statement

Objekte der Klasse RSQL_Statement dienen zur Verwaltung von SQL-Statements, die auf der Serverseite mittels PREPARE übersetzt wurden. Beachten Sie, dass es keinen öffentlichen Konstruktor gibt. RSQL_Statement-Objekte können nur mittels der Funktion RSQL_Connection::Prepare erzeugt werden.

Konstante

Statement-Typ

_SQL_STATEMENT_SELECT

select (cursor) statement

_SQL_STATEMENT_INSERT

insert statement

_SQL_STATEMENT_UPDATE

update statement

_SQL_STATEMENT_DELETE

delete statement

_SQL_STATEMENT_DDL

DDL statement

_SQL_STATEMENT_CONTROL

run-time control statement

_SQL_STATEMENT_DCL

lock, unlock, free resources

_SQL_STATEMENT_GET

get statements



RSQL_Connection *connection
enthält einen Zeiger auf das zugehörige RSQL_Connection-Objekt.

RSQL_DescriptorList *input
enthält einen Zeiger auf die Beschreibung der Eingabeparameter des übersetzen Statements. (siehe hierzu auch den Abschnitt RSQL_DescriptorList)

RSQL_OkType PrintDescription(int mode = 0, FILE *fp = 0)
gibt eine Beschreibung des übersetzen Statements in Textform auf die mittels fp referenzierte Datei aus. Wenn fp gleich 0 ist, so wird auf stdout ausgegeben. der Parameter mode bestimmt das Ausgabeformat: mode=0 gibt eine detailierte, lesbare Beschreibung aus. mode=1 druckt eine Beschreibung als C-Quellcode.

Zum Inhaltsverzeichnis


RSQL_Cursor

Objekte der Klasse RSQL_Cursor dienen zur Verwaltung von SQL-Cursors, die auf der Serverseite mittels DECLARE CURSOR für ein SELECT-Statement deklariert wurden. Beachten Sie, dass es keinen öffentlichen Konstruktor gibt. RSQL_Cursor-Objekte können nur mittels der Funktion RSQL_Statement::DeclareCursor erzeugt werden.

~RSQL_Cursor()
Destruktor. Schließt gleichzeitig den gegebenenfalls geöffneten Cursor.

char *name
dient zur Ermittlung des Namens des Cursors

RSQL_Statement *statement
enthält einen Zeiger auf das zugehörige RSQL_Statement-Objekt.

RSQL_OkType Open(const void *inbuf, int fFetchAhead = RSQL_NoFetchAhead)
öffnet den Cursor. inbuf zeigt dabei auf einen Speicherblock, der die Eingabeparameter enthält, die gemäß der Beschreibung der RSQL_DescriptorList *statement->input (s.o. und Abschnitt RSQL_Statement) aufgebaut ist. Wenn das Statement keine Eingabeparameter besitzt, so übergeben Sie hier einen Nullzeiger.

Der Parameter fFetchAhead bestimmt, ob bei der Übertragung der Daten bei jedem Aufruf der Funktion Fetch (s.u.) genau ein Datensatz mittels des SQL-Befehls FETCH auf der Serverseite gelesen werden soll, oder ob gleich eine größere Anzahl Datensätze geholt werden sollen, wobei dadurch der Aufwand der Datenkommunikation reduziert wird, was zu erheblichen Geschwindigkeitsvorteilen führen kann.

Wenn fFetchAhead= RSQL_NoFetchAhead, so wird jeweils nur ein Datensatz übertragen. Wenn fFetchAhead= RSQL_FetchAhead, so werden pro Datenübertragung mehrere Sätze gesendet.

Beachten Sie, dass Sie die Option RSQL_FetchAhead nicht verwenden können, wenn Sie den Cursor FOR UPDATE OF deklarieren.

OkType Fetch(void *outbuf)
liest den nächsten Datensatz eines geöffneten Cursors. outbuf zeigt dabei auf einen Speicherblock, der die Ausgabeparameter aufnimmt, die gemäß der Beschreibung der RSQL_DescriptorList *statement->output (s.o. und Abschnitt RSQL_Statement) konvertiert werden.

RSQL_OkType Close()
schliest den Cursor. Auch wenn es hierfür keinen entsprechenden SQL-Befehl gibt, so werden durch diese Funktion dennoch einige Speicherbereiche wieder freigegeben. Verwenden Sie diese Funktion, wenn Sie mit vielen Cursors arbeiten und Speicherplatzprobleme bekommen.

Zum Inhaltsverzeichnis


RSQL_DescriptorList

Objekte der Klasse RSQL_DescriptorList dienen der Beschreibung von Eingabe- bzw. Ausgabeparametern eines übersetzen Statements. Sie werden gewöhnlich beim Aufruf der Methodenfunktion RSQL_Statement::Prepare angelegt und stehen über die Zeiger RSQL_Statement::input bzw. RSQL_Statement::output zum Lesen zur Verfügung.

RSQL_DescriptorList enthält eine Liste der jeweiligen Parameter, die einzeln durch ihr jeweiliges RSQL_Descriptor-Objekt beschrieben werden.

RSQL_DescriptorList(int aCount, int afOutput)
Konstruktor. Legt eine neue Liste der Länge aCount an. afOutput ist ungleich null, wenn es sich um eine Liste von Ausgabeparametern handelt, und gleich null, wenn es sich um Eingabeparameter handelt.

~RSQL_DescriptorList()
Destruktor. Löscht gleichzeitig alle zugehörigen RSQL_Descriptor-Objekte.

int Count() const
liefert die Anzahl der enthaltenen RSQL_Descriptor-Objekte.

const RSQL_Descriptor *Descriptor(int position) const
liefert einen Zeiger auf das RSQL_Descriptor-Objekt an der Position position, die dabei zwischen 0 und Count()-1 liegen kann.

const RSQL_Descriptor& operator[](int position) const
liefert eine Referenz auf das RSQL_Descriptor-Objekt an der Position position, die dabei zwischen 0 und Count()-1 liegen kann.

size_t BufferSize() const
liefert die Gesamtgröße in Bytes des Speicherbereichs, der benötigt wird, um alle Parameterdaten der Liste auf der PC-Seite speichern zu können.

RSQL_DataBuffer *AllocBuffer() const
legt einen Datenspeicherbereich in passender Größe an, um alle Parameterdaten der Liste auf der PC-Seite speichern zu können. Der Rückgabewert ist ein Zeiger auf ein RSQL_DataBuffer-Objekt (s.u.).

RSQL_OkType PrintDescription(int mode = 0, FILE *fp = 0)
gibt eine Beschreibung der Parameterliste in Textform auf die mittels fp referenzierte Datei aus. Wenn fp gleich 0 ist, so wird auf stdout ausgegeben. der Parameter mode bestimmt das Ausgabeformat: mode=0 gibt eine detailierte, lesbare Beschreibung aus. mode=1 druckt eine Beschreibung als C-Quellcode.

Zum Inhaltsverzeichnis


RSQL_Descriptor

Objekte der Klasse RSQL_Descriptor dienen der Beschreibung einzelner Eingabe- bzw. Ausgabeparametern eines übersetzen Statements. Sie werden gewöhnlich beim Erzeugen von Objekten des Typs RSQL_DescriptorList erzeugt (s.o.).

char *name
Name des Parameters gemäß der SQL-Anweisung

char *ind_name
Name des Nullwert-Indikators gemäß der SQL-Anweisung. Dieser Zeiger ist gleich 0, wenn der Parameter keine Nullwerte enthalten darf.

size_t xmit_size
Größe des Parameters bei der Datenübertragung.

size_t xmit_offset
Offset des Parameters innerhalb des Datenblocks bei der Datenübertragung

size_t xmit_null_offset
Offset des Nullindikators innerhalb des Datenblocks bei der Datenübertragung

size_t alloc_size
Größe des Speicherbereichs, der benötigt wird, um den Parameter in C-Variable(n) zu speichern (z.B. data_size+1 bei Strings)

size_t alloc_align
erforderliche Ausrichtung des Speicherbereichs, der benötigt wird, um den Parameter in C-Variable(n) zu speichern.

size_t alloc_offs
Offset des Parameters innerhalb des Speicherbereichs, wenn dieser z.B. mittels der Funktion RSQL_DescriptorList::AllocBuffer angelegt wurde.

size_t null_offs
Offset des Nullindikators innerhalb des Speicherbereichs, wenn dieser z.B. mittels der Funktion RSQL_DescriptorList::AllocBuffer angelegt wurde.

short data_type
spezifiziert den SQL-Datentyp. Dieser Wert entspricht der Codierung, wie er auch von HP NonStop-SQL verwendet wird (s. dort). Die folgenden Konstanten sind möglich:

Konstante

Beschreibung

_SQLDT_ASCII_F

CHAR datatype

_SQLDT_ASCII_F_UP

CHAR datatype, UPSHIFTed

_SQLDT_DOUBLE_F

DOUBLE CHAR datatype

_SQLDT_ASCII_V

VARCHAR datatype

_SQLDT_ASCII_V_UP

VARCHAR datatype, UPSHIFted

_SQLDT_DOUBLE_V

DOUBLE VARCHAR datatype

_SQLDT_16BIT_S

16 bit signed binary number, 
SMALLINT, NUMERIC(1-4, <scale>)

_SQLDT_16BIT_U

16 bit unsigned binary number, 
unsigned NUMERIC(1-4, <scale>)

_SQLDT_32BIT_S

32 bit signed binary number, 
INTEGER, NUMERIC(5-9, <scale>)

_SQLDT_32BIT_U

32 bit unsigned binary number, 
unsigned NUMERIC(5-9, <scale>)

_SQLDT_64BIT_S

64 bit signed binary number, 
LARGEINT, NUMERIC(10-18,<scale>)

_SQLDT_REAL

32 bit FLOAT

_SQLDT_DOUBLE

64 bit FLOAT

_SQLDT_DEC_U

DECIMAL datatype: unsigned

_SQLDT_DEC_LSS

DECIMAL datatype: leading sign is separate

_SQLDT_DEC_LSE

DECIMAL datatype: leading sign is embedded

_SQLDT_DEC_TSS

DECIMAL datatype: trailing sign separate

_SQLDT_DEC_TSE

DECIMAL datatype: trailing sign embedded

_SQLDT_DATETIME

DATETIME datatype

_SQLDT_INT_Y_Y

INTERVAL YEAR TO YEAR

_SQLDT_INT_MO_MO

INTERVAL MONTH TO MONTH

_SQLDT_INT_Y_MO

INTERVAL YEAR TO MONTH

_SQLDT_INT_D_D

INTERVAL DAY TO DAY

_SQLDT_INT_H_H

INTERVAL HOUR TO HOUR

_SQLDT_INT_D_H

INTERVAL DAY TO HOUR

_SQLDT_INT_MI_MI

INTERVAL MINUTE TO MINUTE

_SQLDT_INT_H_MI

INTERVAL HOUR TO MINUTE

_SQLDT_INT_D_MI

INTERVAL DAY TO MINUTE

_SQLDT_INT_S_S

INTERVAL SECOND TO SECOND

_SQLDT_INT_MI_S

INTERVAL MINUTE TO SECOND

_SQLDT_INT_H_S

INTERVAL HOUR TO SECOND

_SQLDT_INT_D_S

INTERVAL DAY TO SECOND

_SQLDT_INT_F_F

INTERVAL FRACTION TO FRACTION

_SQLDT_INT_S_F

INTERVAL SECOND TO FRACTION

_SQLDT_INT_MI_F

INTERVAL MINUTE TO FRACTION

_SQLDT_INT_H_F

INTERVAL HOUR TO FRACTION

_SQLDT_INT_D_F

INTERVAL DAY TO FRACTION



Zum Inhaltsverzeichnis


RSQL_DataBuffer

Objekte der Klasse RSQL_DataBuffer werden zur Verwaltung dynamisch angelegter Speicherbereiche zur Aufnahme von Parameterdaten verwendet. Sie können sowohl separat, als auch mittels der Funktion RSQL_DescriptorList::AllocBuffer erzeugt werden.

Zum Inhaltsverzeichnis


Beispielprogramm

#include "rsql.h"
#include <stdio.h>

static void pe(const char *text)
{
    printf("%s. Error #%d\n%s\n",
               text,
               RSQL_Error(),
               RSQL_ErrorText() );
}

int main()
{
    RSQL_Connection NonStop;
    RSQL_OkType result;

    result = NonStop.Connect("prod01", 741, "USER.NAME", "MYPASS");
    if (result != RSQL_Ok)
    {
        pe("cannot connect");
        return 1;
    }

    NonStop.LoadDefines("ADD DEFINE =EMPL, FILE \ED.$DATA.SQLFILES.EMPL");

    RSQL_Statement *stmt;
    if (0 == (stmt = NonStop.Prepare(
              "mystmt",
              "SELECT * FROM =EMPL FOR BROWSE ACCESS"
    )))
    {
        pe("cannot prepare statement");
        return 1;
    }

    RSQL_Cursor *crsr;

    if (0 == (crsr = stmt->DeclareCursor("mycrsr")))
    {
        pe("cannot declare cursor");
        return 1;
    }

    if (crsr->Open(0, RSQL_FetchAhead) == RSQL_NotOk)
    {
        pe("cannot open");
        return 1;
    }

    struct mystmt_out
    {
        RSQL_Decimal EMPNUM[4+1];
        char FIRST_NAME[15+1];
        char LAST_NAME[20+1];
        RSQL_Decimal DEPTNUM[4+1];
        RSQL_Decimal JOBCODE[4+1];
        unsigned long SALARY;
    } d;

    int n = 0;

    while (crsr->Fetch(&d) == RSQL_Ok)
    {
        printf("#%3d: %s|%s|%s|%s|%s|%10ld\n",
                ++n,
                d.EMPNUM,
                d.FIRST_NAME,
                d.LAST_NAME,
                d.DEPTNUM,
                d.JOBCODE,
                d.SALARY);
    }

    if (!RSQL_NoMoreData())
    {
        pe("cannot fetch");
        return 1;
    }
    // Connection ist auto-Variable, wird automatisch entfernt
    // dabei werden auch der Cursor und das Statement gelöscht
    return 0;
}

Zum Inhaltsverzeichnis