FastX SQL rozhraní
FastX server implementuje vlastní SQL rozhraní, které je k dispozici jak X modulům prostřednictvím xsql* operátorů, tak FastX pluginům, tedy rozšiřujícím dynamicky linkovaným knihovnám. FastX SQL se opírá o SQL drivery, což jsou normalizovaná rozhraní na jednotlivé typy zdrojů dat. Mají opět podobu dynamicky linkovaných knihoven, které se registrují v inicializačním bloku init|sql_drivers.
Logicky je FastXSQL rozděleno do dvou základních entit:
SQL connection a SQL cursor. SQL connection vytváří tzv. transaction scope, tedy spojení s SQL serverem z hlediska transakcí izolované od dalších spojení. SQL cursor je objekt v rámci SQL connection, který představuje kontext jednotlivého SQL příkazu. V rámci jednoho SQL spojení může existovat několik kurzorů. Jejich maximální počet je sice implementačně závislý, neměl by však být omezujícím faktorem ( Centura SQL Base podporuje 99 kurzorů/ spojení ). Ukončení transakce, tedy Commit() anebo Rollback() ovlivní všechny kurzory v rámci daného SQL spojení, neboť jsou v kontextu jediné transakce.Například
při otevření tabulkového editoru Freelance se vytvoří SQL spojení s implicitním kurzorem, kterým se vyvolá a obsluhuje SQL příkaz definující prohlížená data. Při ukládání dat tabulkového prohlížeče s různými změnami na více řádcích ( vkládání, editace, rušení ) se v rámci tohoto SQL spojení postupně přihlásí další až tři SQL kurzory pro příkazy INSERT, UPDATE a DELETE. Při úspěchu se nakonec volá Commit(), v opačném případě Rollback(). Tyto příkazy potvrdí/ odvolají změny provedené všemi SQL kurzory v rámci SQL spojení.Z program
átorského hlediska je FastXSQL implementováno jedinou třídou: cFastXSQL. Všechny její metody až na definované výjimky vrací 0 v případě úspěchu, v opačném případě číslo chyby.Běž
ící vlákno může vytvořit libovolný počet SQL spojení. Zpravidla však pracuje s jediným, neboť obsluhuje jedinou transakci.Členské proměnné třídy
cFastXSQL( PCHAR sConnectString, unsigned long setthread );
konstruktor vytvoří
nové SQL spojení a v případě úspěchu přihlásí implicitní SQL kurzor. Nenulový parametr setthread způsobí registraci spojení v seznamu autodestruktivních spojení. Tato spojení musí klient pravidelně notifikovat o své aktivitě, jinak je FastX automaticky zruší. Tento typ spojení využívají Freelance klienti. Smyslem je zrušit po stanovené době databázová spojení otevřená klientem, který již o sobě nedává vědět ( porucha SW, HW ).cFastXSQL( cFastXSQL * conn );
konstruktor vytvoří v konte
xtu zadaného SQL spojení nový SQL kurzor.int Prep( PCHAR command );
metoda připraví SQL příkaz k ( i opakovanému ) provedení metodou Exec()
int Ret( PCHAR cmdname );
metoda připraví SQL proceduru k ( i opakovanému ) provedení metodou Exec()
int Exec();
metoda vyvolá příkaz připravený některou z funkcí Prep(), Ret(), PrepAndExec()
int PrepAndExec( PCHAR command );
metoda vyvolá zadaný SQL příkaz
char *GetLastCommand();
metoda vrátí text posledního volaného SQL příkazu
int Commit();
metoda potvrzuje transakci
int Rollback();
metoda odvolává transakci
void ErrorInfo( int * errnum, int * errpos );
metoda vrací kód a případně pozici chyby v textu posledního SQL příkazu
void ErrorText( char * buffer, int buflen );
metoda vrací textový popis chyby posl
edního SQL příkazuint Bind( COLUMN_ORDER order, PCHAR buffer, int length, unsigned char bind_var_type );
metoda spojí parametr identifikovaný pořadím s konkrétní hodotou. Význam dalších parametrů definuje tabulka:
Buffer |
Length |
Bind_var_type |
LPSTR |
-1=spočti, jinak délka parametru |
BIND_STRING, BIND_VALUE Hodnota BIND_STRING říká, že parametrem je textový řetězec zapisovaný do sloupce typu CHAR anebo VARCHAR. Hodnota BIND_VALUE říká, že parametrem je textový řetězec zapisovaný do sloupce neznámého typu. SQL driver v tomto případě musí zajistit detekci typu ( např. DATE, TIMESTAMP apod. ) a případnou konverzi. |
LPLONG |
Ignored |
Hodnota BIND_LONG říká, že parametrem je ukazatel na int32 anebo long zapisovaný do sloupce typu INT, SMALLINT. |
LPDOUBLE |
Ignored |
Hodnota BIND_DOUBLE říká, že parametrem je ukazatel na double zapisovaný do sloupce typu DECIMAL, FLOAT, REAL apod. |
Ignored |
Ignored |
Hodnota BIND_NULL zapisuje do sloupce hodnotu NULL. |
int AutoInto();
metoda AutoInto() [ automatické
SQL INTO ] zpřístupňuje informace o datech přečtených předchozím SQL příkazem anebo procedurou. Pokud chcete číst data vybraná např. SELECT příkazem, volejte tuto metodu bezprostředně po Prep() anebo PrepAndExec(). Vytvoří a založí informace o čtených datech. Data jsou přístupná po volání Fetch() anebo FetchNext() metodami AutoIntoValue(), AutoIntoLong() a AutoIntoDouble().
char *AutoIntoValue( COLUMN_ORDER order );
metoda vrátí ukazatel na hodnotu příslušného výrazu. Hodnoty jsou platné v případě úspěšného předchozího volání metody
Fetch() anebo FetchNext().long AutoIntoLong( COLUMN_ORDER order );
metoda vrátí hodnotu příslušného výrazu jako
long.double AutoIntoDouble( COLUMN_ORDER order );
metoda vrátí hodnotu příslušného výrazu jako
double.int Fetch( long nRow );
metoda přečte z result setu zadaný řádek ( první = 0 ). Vrací 0 v případě úspěchu, 1 = END_OF_DATA, 2 = modified row, jinak kód chyby.
int FetchNext();
metoda přečte z result setu další řádek. Vrací 0 v případě úspěchu, 1 = END_OF_DATA, 2 =
modified row, jinak kód chyby.long LongRead( COLUMN_ORDER order, char * buffer, int buffer_size );
metoda přečte do bufferu nejvýše buffer_size bytů z výrazu typu
LONG VARCHAR. Je tedy obdobou AutoIntoValue() pro tento datový typ.int LongWriteBind( COLUMN_ORDER order );
metoda inicializuje parametr SQL příkazu pro zápis do sloupce typu
LONG VARCHAR. Je obdobou Bind() pro tento datový typ.int LongWrite( char * buffer, COLUMN_ORDER order, int buffer_size );
metoda zapíše data do parametru sloupce typu LONG VARCHAR.
int LongEnd();
metoda ukončí práci s
LONG VARCHAR parametrem anebo přečtenou hodnotou.long LongSize( COLUMN_ORDER order ); /* returns -1 on error */
metoda vrací velikost přečtené hodnoty typu
LONG VARCHAR.int SelectItemCount();
metoda vrací
počet sloupců vrácených předchozím příkazem Prep() anebo PrepAndExec()int SelectItemInfo( COLUMN_ORDER order, PDATATYPE pdt, PDATALEN pdl, PDATALEN pdec, char * labelBuffer = NULL );
metoda vrací informace o zadaném výrazu ( datový typ, délku, případně
počet desetinných míst, název sloupce/ text výrazu ).long CountResultSet();
metoda vrací počet řádek přečtených předchozím SQL příkazem
long CountModifiedRows();
metoda vrací počet řádek modifikovaných předchozím SQL příkazem
int PreserveContext( int on );
metoda nastaví/ vypne režim Cursor Context Preservation, ve kterém zůstávají připravené SQL příkazy v platnosti i po ukončení transakce pomocí COMMIT/ ROLLBACK
int ResultSetMode( int on );
metoda nastaví/ vypne režim, ve kterém lze náhodně číst řádky result setu funkcí
Fetch(), nikoli jen sekvenčně pomocí FetchNext().int SetIsolation( const char * level );
metoda nastaví úroveň izolace SQL spojení:
RL |
Release lock - uvolnit sdílené zámky po přečtení a odeslání dat klientovi . FastX server standardně pracuje s touto úrovní izolace, ostatní úrovně jsou k dispozici pro specifické požadavky konkrétní implementace. |
CS |
Cursor stability - držet sdílené zámky jen na kontextové řádce klienta |
RO |
Read Only |
RR |
Repeatable Read - držet sdílené zámky až do ukončení transakce |
~cFastXSQL()
destruktor
Příklad v jazyce C
N
ásledující příklad otevře spojení s implicitním kurzorem a další kurzor v kontextu spojení. Poté provede SELECT příkaz implicitním kurzorem a připraví UPDATE na druhém kurzoru. Pro každý řádek SELECTu provede UPDATE. Nakonec transakci potvrdí a odpojí se.#include <fastx.h> int fastXSQL() { cFastXSQL * conn, *cur; char name[64]; int id; // vytvorit spojeni a kurzor conn = new cFastXSQL( "MYDB/JOHN/DOVANI", 0 ); // pripojit dalsi kurzor v ramci spojeni cur = new new cFastXSQL( conn ); // nastavit result set mode ( zde neni nutno, ale jen pro ukazku ) conn->ResultSetMode( 1 ); // pripravit a vyvolat SQL SELECT prikaz conn->PrepAndExec( "SELECT ID,NAME FROM AUTHORS" ); // inicializovat cteni hodnot conn->AutoInto(); // pripravit SQL UPDATE prikaz na druhem kurzoru cur->Prep( "UPDATE AUTHORS SET NAME=:1 WHERE ID=:2" ); // pripojit parametry cur->Bind( 1, (PCHAR)name, -1, BIND_STRING ); cur->Bind( 2, (PCHAR)&id, -1, BIND_LONG ); while ( !conn->FetchNext() ) { // precist ID id = conn->AutoIntoLong( 1 ); // precist NAME strcpy( name, conn->AutoIntoValue( 2 ) ); // prevest na velka pismena strupr( name ); // vyvolat UPDATE cur->Exec(); } // potvrdit transakci ( bylo by mozne tez pomoci cur->Commit(), // obe varianty jsou identicke conn->Commit(); // (nejprve) zrusit kurzor delete cur; // zrusit spojeni delete conn; return 0; }
Ten samý příklad v jazyce X
long fastXSQL() { long conn, cur, id, fetch string name xsqllogin( 'MYDB', 'JOHN', 'DOVANI' ) // vytvorit spojeni a kurzor xsqlopenconn( conn, 0 ) // pripojit dalsi kurzor v ramci spojeni xsqlgetcur( cur, conn ) // nastavit result set mode ( zde neni nutno, ale jen pro ukazku ) xsqlresultset( conn, 1 ) // pripravit a vyvolat SQL SELECT prikaz xsqlprepandexec( conn, 'SELECT ID,NAME FROM AUTHORS' ) // inicializovat cteni hodnot xsqlinto( conn ) // pripravit SQL UPDATE prikaz na druhem kurzoru xsqlprep ( cur, 'UPDATE AUTHORS SET NAME=:1 WHERE ID=:2' ) // pripojit parametry xsqlbindstr( cur, 1, name ) xsqlbindlong( cur, 2, id ) xsqlfetchnext( conn, fetch ) while ( !fetch ) { // precist ID xsqlgetlong( conn, 1, id ) // precist NAME xsqlgetstring( conn, 2, name ) // prevest na velka pismena xstrupr( name ); // vyvolat UPDATE xsqlexec( cur ) } // potvrdit transakci ( bylo by mozne tez pomoci cur ), // obe varianty jsou identicke xsqlcommit( conn ) // (nejprve) zrusit kurzor xsqldisconn( cur ) // zrusit spojeni xsqldisconn( conn ) xret( 0 ) }