| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224 |
- Program update;
- {*
- * PROGRAM: Object oriented API samples.
- * MODULE: 02.update.cpp
- * DESCRIPTION: Run once prepared statement with parameters
- * a few times, committing transaction after each run.
- * Learns how to prepare statement, manually define parameters
- * for it, execute that statement with different parameters
- * and perform non-default error processing.
- *
- * Example for the following interfaces:
- * IAttachment - database attachment
- * ITransaction - transaction
- * IStatement - SQL statement execution
- * IMessageMetadata - describe input and output data format
- * IMetadataBuilder - tool to modify/create metadata
- * IStatus - return state holder
- *
- * Note that all updates are rolled back in this version. (see *** later)
- *
- * Run something like this to build the program :
- *
- * fpc -Fu./common -Fu/opt/firebird/include/firebird -FUlib -oupdate 02.update.pas
- *
- * The contents of this file are subject to the Initial
- * Developer's Public License Version 1.0 (the "License");
- * you may not use this file except in compliance with the
- * License. You may obtain a copy of the License at
- * https://www.ibphoenix.com/about/firebird/idpl.
- *
- * Software distributed under the License is distributed AS IS,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied.
- * See the License for the specific language governing rights
- * and limitations under the License.
- *
- * The Original Code was created by Paul Reeves
- * for the Firebird Open Source RDBMS project.
- *
- * All Rights Reserved.
- * Contributor(s): ______________________________________.
- *
- *}
- {$mode Delphi}{$H+}
- Uses
- SysUtils,
- Firebird;
- Type
- Buffer = String [255];
- Var
- // master and status are required for all access to the API.
- // This is main interface of firebird, and the only one
- // for getting which there is special function in our API
- master: IMaster;
- // Status is used to return error description to user
- status: IStatus;
- // Provider is needed to start to work with database (or service)
- prov: IProvider;
- // declare pointers to required interfaces
- att: IAttachment;
- tra: ITransaction;
- // Interface executes prepared SQL statement
- stmt: IStatement;
- // Interfaces provides access to format of data in messages
- meta: IMessageMetadata;
- // Interface makes it possible to change format of data or define it yourself
- builder: IMetadataBuilder;
- Dept_Data: Array[0..4] Of String = ( '622', '100', '116', '900', '0' );
- Percent_data: Array[0..4] Of Double = ( 0.05, 1.00, 0.075, 0.10, 0 );
- i: Integer;
- InputBuffer: Buffer;
- len: Integer;
- PPercent_inc: PChar;
- PDept_no: PChar;
- Const
- UpdateString = 'UPDATE department SET budget = ? * budget + budget WHERE dept_no = ?';
- SQL_DIALECT_V6 = 3;
- SQL_DIALECT_CURRENT = SQL_DIALECT_V6;
- SQL_TEXT = 452; // CHAR
- SQL_DOUBLE = 480; // DOUBLE PRECISION
- Procedure PrintError( AMaster: IMaster; AStatus: IStatus );
- Var
- maxMessage: Integer;
- outMessage: PAnsiChar;
- Begin
- maxMessage := 256;
- outMessage := StrAlloc( maxMessage );
- AMaster.getUtilInterface.formatStatus( outMessage, maxMessage, AStatus );
- writeln( outMessage );
- StrDispose( outMessage );
- End;
- // Get the department and percent parameters for an example to run.
- Begin
- master := fb_get_master_interface;
- status := master.getStatus;
- Try
- // the main dispatcher is returned by a call to IMaster
- // no errors can occur - this function will always succeed
- prov := master.getDispatcher;
- // We assume that ISC_USER and ISC_PASSWORD env vars are set. Otherwise,
- // see code in 01.create for an example of setting the un/pw via the dpb.
- att := prov.attachDatabase( status, 'employee', 0, nil );
- writeln( 'Attached to database employee.fdb' );
- // start transaction
- tra := att.startTransaction( status, 0, nil );
- // prepare statement
- stmt := att.prepare( status, tra, 0, UpdateString, SQL_DIALECT_CURRENT, 0 );
- // build metadata
- // IMaster creates empty new metadata in builder
- builder := master.getMetadataBuilder( status, 2 );
- // set required info on fields
- builder.setType( status, 0, SQL_DOUBLE + 1 );
- builder.setType( status, 1, SQL_TEXT + 1 );
- builder.setLength( status, 1, 3 );
- // IMetadata should be ready
- meta := builder.getMetadata( status );
- // no need for builder any more
- builder.Release( );
- builder := nil;
- len := meta.getMessageLength( status );
- If ( len > sizeof( InputBuffer ) ) Then
- Raise Exception.Create( 'Input message length too big - cannot continue' )
- Else
- FillChar( InputBuffer, SizeOf( InputBuffer ), 0 );
- i := meta.getNullOffset( status, 0 );
- InputBuffer[i] := Char( 0 );
- i := meta.getNullOffset( status, 1 );
- InputBuffer[i] := Char( 0 );
- Try
- // locations of parameters in input message
- PPercent_inc := PChar( @InputBuffer [meta.getOffset( status, 0 )] );
- PDept_no := PChar( @InputBuffer [meta.getOffset( status, 1 )] );
- For i := 0 To length( Dept_Data ) - 1 Do Begin
- If ( Dept_Data [i] = '0' ) Or ( Percent_data [i] = 0 ) Then
- break;
- StrPCopy( PPercent_inc, Percent_data [i].ToString );
- StrPCopy( PDept_no, Dept_Data [i] );
- WriteLn( 'Increasing budget for department: ' + PDept_no + ' by ' + PPercent_inc + ' percent.' );
- Try
- stmt.Execute( status, tra, meta, @InputBuffer, nil, nil );
- // Save/Cancel each department's update independently.
- // *** Change to commitRetaining() to see changes
- // *** tra.commitRetaining(status);
- tra.rollbackRetaining( status );
- Except
- on E: FBException Do Begin
- PrintError( master, status );
- tra.rollbackRetaining( status );
- End;
- End;
- End;
- stmt.Free( status );
- stmt := nil;
- meta.Release;
- meta := nil;
- tra.commit( status );
- tra := nil;
- att.detach( status );
- att := nil;
- Except
- on E: FBException Do Begin
- PrintError( master, status );
- tra.rollbackRetaining( status );
- End;
- on E: Exception Do
- WriteLn( E.Message );
- End;
- Finally
- If assigned( meta ) Then
- meta.Release;
- If assigned( builder ) Then
- builder.Release;
- If assigned( stmt ) Then
- stmt.Release;
- If assigned( tra ) Then
- tra.Release;
- If assigned( att ) Then
- att.Release;
- prov.Release;
- status.dispose;
- End;
- End.
|