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 kontextu 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 posledního SQL příkazu

int 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 )
}