Code: Select all
#FB_Client = 1
Global sLibrary.s
Global EndOfLine.s
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Windows
sLibrary.s = "fbclient.dll"
EndOfLine = Chr(13) + Chr(10)
CompilerCase #PB_OS_Linux
sLibrary.s = "libfbclient.so"
EndOfLine = Chr(10) ;need to check this out
CompilerCase #PB_OS_MacOS
sLibrary.s = "Firebird.framework"
EndOfLine = Chr(10) ;need to check this out
CompilerEndSelect
lresult = OpenLibrary(#FB_Client,sLibrary)
If Not lresult
MessageRequester("Error","Library not found",0)
End
EndIf
Prototype.i isc_attach_database(*StatusVector,dbNameLength.w,*dbName,*dbHandle,DPBSize.w,*DPB)
Global fb_attach.isc_attach_database = GetFunction(#FB_Client,"isc_attach_database")
Prototype.i isc_detach_database(*StatusVector,*dbHandle)
Global fb_detach.isc_detach_database = GetFunction(#FB_Client,"isc_detach_database")
PrototypeC.i isc_start_transaction(*StatusVector,*TransactionHandle,Count.w,*dbHandle,TPBLength.w,*TPB)
Global fb_start.isc_start_transaction = GetFunction(#FB_Client,"isc_start_transaction")
Prototype.i isc_rollback_transaction(*StatusVector,*TransactionHandle)
Global fb_rollback.isc_rollback_transaction = GetFunction(#FB_Client,"isc_rollback_transaction")
Prototype.i isc_commit_transaction(*StatusVector,*TransactionHandle)
Global fb_commit.isc_commit_transaction = GetFunction(#FB_Client,"isc_commit_transaction")
Prototype.i isc_dsql_alloc_statement2(*StatusVector,*dbHandle,*QueryHandle)
Global fb_allocate.isc_dsql_alloc_statement2 = GetFunction(#FB_Client,"isc_dsql_alloc_statement2")
Prototype.i isc_dsql_prepare(*StatusVector,*TransactionHandle,*QueryHandle,SQLlength.w,*SQLstring,Dialect.w,*XSQLDA)
Global fb_prepare.isc_dsql_prepare = GetFunction(#FB_Client,"isc_dsql_prepare")
Prototype.i isc_dsql_describe(*StatusVector,*QueryHandle,da_version.w,*XSQLDA)
Global fb_describe.isc_dsql_describe = GetFunction(#FB_Client,"isc_dsql_describe")
Prototype.i fb_interpret(*Buffer,SizeOfBuffer.i,*PtrToStatusVector)
Global fb_error.fb_interpret = GetFunction(#FB_Client,"fb_interpret")
Prototype.i isc_sqlcode(*StatusVector)
Global fb_sqlcode.isc_sqlcode = GetFunction(#FB_Client,"isc_sqlcode")
Prototype.i isc_sql_interpret(SQLCode.w,*Buffer,SizeOfBuffer.w)
Global fb_sql_error.isc_sql_interpret = GetFunction(#FB_Client,"isc_sql_interprete")
Prototype.i isc_dsql_fetch(*StatusVector,*QueryHandle,da_version.w,*XSQLDA)
Global fb_fetch.isc_dsql_fetch = GetFunction(#FB_Client,"isc_dsql_fetch")
Prototype.i isc_dsql_free_statement(*StatusVector,*QueryHandle,free_option.w)
Global fb_free.isc_dsql_free_statement = GetFunction(#FB_Client,"isc_dsql_free_statement")
Prototype.i isc_dsql_execute_immediate(*StatusVector,*dbHandle,*TransactionHandle,SQL_length.w,*SQLstring,Dialect.w,*XSQLDA)
Global fb_execute_immediate.isc_dsql_execute_immediate = GetFunction(#FB_Client,"isc_dsql_execute_immediate")
Prototype.i isc_dsql_execute(*StatusVector,*TransactionHandle,*QueryHandle,da_version.w,*XSQLDA)
Global fb_execute.isc_dsql_execute = GetFunction(#FB_Client,"isc_dsql_execute")
Global fb_LastErrorMessage.s
;data type constants
#SQL_ARRAY = 540
#SQL_BLOB = 520
#SQL_DATE = 510
#SQL_DOUBLE = 480
#SQL_D_FLOAT = 530
#SQL_FLOAT = 482
#SQL_INT64 = 580
#SQL_LONG = 496
#SQL_QUAD = 550
#SQL_SHORT = 500
#SQL_TEXT = 452
#SQL_TIMESTAMP = 510
#SQL_TYPE_DATE = 570
#SQL_TYPE_TIME = 560
#SQL_VARYING = 448
;some other required constants
;database parameter buffer constants
#isc_dpb_version1 = 1
#isc_dpb_user_name = 28
#isc_dpb_password = 29
#isc_dpb_sql_dialect = 63
;transaction parameter buffer constants
#isc_tpb_concurrency = 2
#isc_tpb_version3 = 3
#isc_tpb_wait = 6
#isc_tpb_write = 9
#DSQL_CLOSE = 1
#DSQL_DROP = 2
#SQLDA_VERSION1 = 1
#SQL_DIALECT_V5 = 1
#SQL_DIALECT_V6 = 3
Structure ISC_STATUS ;used for retrieveing error messages
vector.i[20]
EndStructure
Procedure fb_InterpretDatabaseError(*sv)
fb_LastErrorMessage = ""
lSQLCode.w = fb_sqlcode(*sv)
If lSQLCode <> 0
fb_LastErrorMessage = "SQL Code: " + Str(lSQLCode)
*Mem = AllocateMemory(1000)
fb_sql_error(lSQLCode,*Mem,1000)
fb_LastErrorMessage = fb_LastErrorMessage + EndOfLine + PeekS(*Mem,1000,#PB_UTF8)
FreeMemory(*Mem)
EndIf
If fb_LastErrorMessage <> "":fb_LastErrorMessage = fb_LastErrorMessage + EndOfLine + EndOfLine:EndIf
lresult = 1
While lresult <> 0
*Mem = AllocateMemory(1000)
lresult = fb_error(*Mem,1000,@*sv)
fb_LastErrorMessage = fb_LastErrorMessage + PeekS(*Mem,1000,#PB_UTF8)
FreeMemory(*Mem)
Wend
EndProcedure
Procedure.i fb_OpenDatabase(DatabaseAlias.s,Username.s,Password.s)
lAlias.w = StringByteLength(DatabaseAlias,#PB_UTF8)
*dbAlias = AllocateMemory(lAlias)
PokeS(*dbAlias,DatabaseAlias,lAlias,#PB_UTF8)
sParam.s = Chr(#isc_dpb_version1)
lUN.w = StringByteLength(Username,#PB_UTF8)
If lUN > 0:sParam = sParam + Chr(#isc_dpb_user_name) + Chr(lUN) + Username:EndIf
lPWD.w = StringByteLength(Password,#PB_UTF8)
If lPWD > 0:sParam = sParam + Chr(#isc_dpb_password) + Chr(lPWD) + Password:EndIf
lUN = StringByteLength(sParam,#PB_UTF8)
*dbParam = AllocateMemory(lUN)
PokeS(*dbParam,sParam,lUN,#PB_UTF8)
lHandle = #Null
lresult = fb_attach(@sv.ISC_STATUS,lAlias,*dbAlias,@lHandle,lUN,*dbParam)
FreeMemory(*dbAlias)
FreeMemory(*dbParam)
If lresult = 0
ProcedureReturn lHandle
Else
fb_InterpretDatabaseError(@sv)
ProcedureReturn -1
EndIf
EndProcedure
Procedure.i fb_CloseDatabase(dbHandle)
lresult = fb_detach(@sv.ISC_STATUS,@dbHandle)
If lresult = 0
ProcedureReturn lresult
Else
fb_InterpretDatabaseError(@sv)
ProcedureReturn -1
EndIf
EndProcedure
Procedure.i fb_StartTransaction(dbHandle)
*TPB = AllocateMemory(4)
PokeB(*TPB,#isc_tpb_version3)
PokeB(*TPB + 1,#isc_tpb_write)
PokeB(*TPB + 2,#isc_tpb_concurrency)
PokeB(*TPB + 3,#isc_tpb_wait)
TransactionID = #Null
lResult = fb_start(@sv.ISC_STATUS,@TransactionID,1,@dbHandle,4,*TPB)
FreeMemory(*TPB)
If lResult = 0
ProcedureReturn TransactionID
Else
fb_InterpretDatabaseError(@sv)
ProcedureReturn -1
EndIf
EndProcedure
Procedure.i fb_CommitTransaction(TransactionID)
lresult = fb_commit(@sv.ISC_STATUS,@TransactionID)
If lresult = 0
ProcedureReturn lresult
Else
fb_InterpretDatabaseError(@sv)
ProcedureReturn -1
EndIf
EndProcedure
Procedure.i fb_RollbackTransaction(TransactionID)
lresult = fb_rollback(@sv.ISC_STATUS,@TransactionID)
If lresult = 0
ProcedureReturn lresult
Else
fb_InterpretDatabaseError(@sv)
ProcedureReturn -1
EndIf
EndProcedure
Procedure.i fb_SQLExecute(dbHandle,TransactionID,SQLString.s)
lSQL = StringByteLength(SQLString,#PB_UTF8)
*SQL = AllocateMemory(lSQL)
PokeS(*SQL,SQLString,lSQL,#PB_UTF8)
lResult = fb_execute_immediate(@sv.ISC_STATUS,@dbHandle,@TransactionID,lSQL,*SQL,#SQL_DIALECT_V6,#Null)
FreeMemory(*SQL)
If lResult = 0
ProcedureReturn #True
Else
fb_InterpretDatabaseError(@sv)
ProcedureReturn #False
EndIf
EndProcedure
;start the test
;Employees is an alias I've set up for the Employees example database that installs with Firebird
db = fb_OpenDatabase("Employees","SYSDBA","masterkey")
If db = -1
MessageRequester("Error",fb_LastErrormessage,0)
End
Else
MessageRequester("Cool #1!","Connected - handle: " + Str(db),0)
lTransID = fb_StartTransaction(db)
If lTransID = -1
MessageRequester("Error",fb_LastErrormessage,0)
Else
MessageRequester("Cool #2!","Started a transaction - handle: " + Str(lTransID),0)
If fb_SQLExecute(db,lTransID,"UPDATE COUNTRY SET CURRENCY = 'Euros' WHERE COUNTRY = 'France';")
fb_CommitTransaction(lTransID)
MessageRequester("Cool #3!","Record updated",0)
Else
fb_RollbackTransaction(lTransID)
MessageRequester("Error",fb_LastErrormessage,0)
EndIf
EndIf
fb_CloseDatabase(dbHandle)
EndIf
CloseLibrary(#FB_Client)
She-who-must-be-obeyed has just summoned me to do DIY
