1 |
<?xml version="1.0" encoding="UTF-8"?> |
2 |
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1 plus MathML 2.0//EN" "http://www.w3.org/Math/DTD/mathml2/xhtml-math11-f.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><!--This file was converted to xhtml by LibreOffice - see http://cgit.freedesktop.org/libreoffice/core/tree/filter/source/xslt for the code.--><head profile="http://dublincore.org/documents/dcmi-terms/"><meta http-equiv="Content-Type" content="application/xhtml+xml; charset=utf-8"/><title xml:lang="en-US">- no title specified</title><meta name="DCTERMS.title" content="" xml:lang="en-US"/><meta name="DCTERMS.language" content="en-US" scheme="DCTERMS.RFC4646"/><meta name="DCTERMS.source" content="http://xml.openoffice.org/odf2xhtml"/><meta name="DCTERMS.creator" content="Tony Whyman"/><meta name="DCTERMS.issued" content="2011-04-21T17:35:42" scheme="DCTERMS.W3CDTF"/><meta name="DCTERMS.contributor" content="Tony Whyman"/><meta name="DCTERMS.modified" content="2015-02-23T10:54:09.431430480" scheme="DCTERMS.W3CDTF"/><meta name="DCTERMS.provenance" content="" xml:lang="en-US"/><meta name="DCTERMS.subject" content="," xml:lang="en-US"/><link rel="schema.DC" href="http://purl.org/dc/elements/1.1/" hreflang="en"/><link rel="schema.DCTERMS" href="http://purl.org/dc/terms/" hreflang="en"/><link rel="schema.DCTYPE" href="http://purl.org/dc/dcmitype/" hreflang="en"/><link rel="schema.DCAM" href="http://purl.org/dc/dcam/" hreflang="en"/><style type="text/css"> |
3 |
@page { } |
4 |
table { border-collapse:collapse; border-spacing:0; empty-cells:show } |
5 |
td, th { vertical-align:top; font-size:12pt;} |
6 |
h1, h2, h3, h4, h5, h6 { clear:both } |
7 |
ol, ul { margin:0; padding:0;} |
8 |
li { list-style: none; margin:0; padding:0;} |
9 |
<!-- "li span.odfLiEnd" - IE 7 issue--> |
10 |
li span. { clear: both; line-height:0; width:0; height:0; margin:0; padding:0; } |
11 |
span.footnodeNumber { padding-right:1em; } |
12 |
span.annotation_style_by_filter { font-size:95%; font-family:Arial; background-color:#fff000; margin:0; border:0; padding:0; } |
13 |
* { margin:0;} |
14 |
.Heading_20_2 { font-size:14pt; margin-bottom:0.0835in; margin-top:0.1665in; font-family:Arial; writing-mode:page; font-style:italic; font-weight:bold; } |
15 |
.P1 { font-size:12pt; margin-bottom:0.0835in; margin-top:0in; font-family:Times New Roman; writing-mode:page; margin-left:0.5in; margin-right:0in; text-indent:0in; } |
16 |
.P10 { font-size:12pt; font-family:Times New Roman; writing-mode:page; } |
17 |
.P2 { font-size:12pt; margin-bottom:0.0835in; margin-top:0in; font-family:Times New Roman; writing-mode:page; font-style:normal; } |
18 |
.P3 { font-size:10pt; margin-bottom:0.0835in; margin-top:0in; font-family:Courier New; writing-mode:page; } |
19 |
.P4 { font-size:12pt; margin-bottom:0.0835in; margin-top:0in; font-family:Times New Roman; writing-mode:page; } |
20 |
.P5 { font-size:12pt; font-family:Times New Roman; writing-mode:page; margin-top:0in; margin-bottom:0.1701in; } |
21 |
.P6 { font-size:12pt; font-family:Times New Roman; writing-mode:page; font-weight:bold; } |
22 |
.P7 { font-size:14pt; font-style:normal; font-weight:bold; margin-bottom:0.0835in; margin-top:0.1665in; font-family:Arial; writing-mode:page; } |
23 |
.P8 { font-size:12pt; margin-bottom:0.0835in; margin-top:0in; font-family:Times New Roman; writing-mode:page; } |
24 |
.P9 { font-size:115%; font-weight:bold; margin-bottom:0.0835in; margin-top:0.1665in; font-family:Arial; writing-mode:page; text-align:center ! important; } |
25 |
.Table_20_Contents { font-size:12pt; font-family:Times New Roman; writing-mode:page; } |
26 |
.Text_20_body { font-size:12pt; font-family:Times New Roman; writing-mode:page; margin-top:0in; margin-bottom:0.0835in; } |
27 |
.Table1 { margin-left:0in; margin-right:-0.0049in; float:none; } |
28 |
.Table1_A1 { padding:0.0382in; border-style:none; } |
29 |
.Bullet_20_Symbols { font-family:OpenSymbol; } |
30 |
.Internet_20_link { color:#000080; text-decoration:underline; } |
31 |
<!-- ODF styles with no properties representable as CSS --> |
32 |
.Table1.A .Table1.B .Numbering_20_Symbols .T1 { } |
33 |
</style></head><body dir="ltr" style="max-width:8.2681in;margin-top:0.7874in; margin-bottom:0.7874in; margin-left:0.7874in; margin-right:0.7874in; writing-mode:lr-tb; "><h1 class="P9"><a id="a__IBX_For_Lazarus__Firebird_Express_"><span/></a>IBX For Lazarus (Firebird Express)</h1><p class="Text_20_body">IBX for Lazarus is derived from the Open Source edition of IBX published by Borland/Inprise in 2000 under the InterBase Public License. This version has been brought up-to-date by MWA Software (<a href="http://www.mwasoftware.co.uk/" class="Internet_20_link">http://www.mwasoftware.co.uk</a>) and focused on the Firebird Database API for both Linux and Windows platforms (32 and 64-bit). It is released under the InterBase Public License for the original code and under the compatible Initial Developers Public License for new software. The Firebird Relational Database Management System can be downloaded from http://www.firebirdsql.org.</p><p class="Text_20_body">While the core of the product remains the original IBX software, this version includes a completely new set of property editors supporting SQL generation and testing using the Firebird Database engine direct from the IDE. These are intended to be a significant improvement on the Delphi Property Editors. IBSQLMonitor has also been re-organised in order to isolate the platform dependent aspects, allowing for the use of SV5 IPC for the Linux environment. The original Windows IPC is retained for the Windows environment. IBEvents has also been updated to ensure compatibility with Firebird Events.</p><p class="Text_20_body">The Database Interface unit (IBIntf) is now firmly focused on the Firebird 2 API for both 32-bit and 64-bit environments. </p><p class="Text_20_body">Support for generators has also been added compatible with the generator support added to IBX after the Open Source edition was published, supporting both “On New Record” and “On Post” generators.</p><h2 class="Heading_20_2"><a id="a__Minimum_Requirements"><span/></a>Minimum Requirements</h2><p class="P4"><span class="T1">IBX 1.2 requires at least Lazarus version 1.4 RC1 and version 2.6.4 </span> of the Free Pascal Compiler. </p><p class="Text_20_body">The Firebird 2.x client library must also be installed.</p><h2 class="Heading_20_2"><a id="a__Installation"><span/></a>Installation</h2><p class="Text_20_body">The Firebird Client Library should be installed on the system prior to installing into the Lazarus IDE. See the separate notes for using Firebird and IBX for Lazarus under Linux and Windows, respectively.</p><p class="Text_20_body">Installation into the Lazarus IDE is the same under both Linux and Windows. Unpack the source code archive into some suitable permanent location and open the “dclibx.lpk” package description file using the “Package->Open Package File” menu item to open the file.</p><p class="Text_20_body">When the Package Editor opens, click on “Use->Install”. Lazarus should now recompile itself and restart. Two new tabs should now be present on the Component Palette: “Firebird” and “Firebird Admin”. Respectively, these contain the IBX Database Access and Service API components.</p><p class="Text_20_body">If no IBX components are visible, then the most likely reason is that the Firebird Client Library has not been installed and/or cannot be located.</p><h2 class="Heading_20_2"><a id="a__Upgrading_from_an_Earlier_Version"><span/></a>Upgrading from an Earlier Version</h2><p class="Text_20_body">All you need to do is to unpack the archive and overwrite the existing IBX source code files. You must now rebuild lazarus using the “Tools->Build Lazarus with profile: Build All” menu item.</p><h2 class="Heading_20_2"><a id="a__Using_the_IBX_Components"><span/></a>Using the IBX Components</h2><p class="Text_20_body">The IBX components should behave identically to their Delphi equivalents and many online tutorials are available on how to use them. Some notes on their use are given below, and an example program is also provided. You should be aware of the following issues:</p><ol><li><p class="P8" style="margin-left:0cm;"><span class="Numbering_20_Symbols" style="display:block;float:left;min-width:0.635cm;">1.</span>The IBX components make use of the TThread component, and, as such require that multi-threading is enabled. Specifically, in the Linux environment, the “-dUseCThreads” option must be present in the “Compiler Options->Options->Custom Options” and set for every Lazarus project that uses them.<span class="odfLiEnd"/> </p></li><li><p class="P8" style="margin-left:0cm;"><span class="Numbering_20_Symbols" style="display:block;float:left;min-width:0.635cm;">2.</span>Prior to FPC 2.6.0, the TIntegerField type may cause problems when porting code from Delphi to Lazarus. <span class="odfLiEnd"/> </p></li><li><p class="P8" style="margin-left:0cm;"><span class="Numbering_20_Symbols" style="display:block;float:left;min-width:0.635cm;">3.</span>FMTBcd is not yet implemented by the Free Pascal Compiler. IBX for Lazarus thus uses the TFloatField type for extended floating point (64 bit) fields. This may cause problems where converting Delphi programs to Lazarus. The recommended approach is to change all TFmtBcdField types to TIBBcdFields. This will allow delphi forms to be converted to Lazarus. However, some of the conversions will not give the correct results. Typically, this will result in field values that appear to be of the order of several billion when the program is run. To resolve the problem, delete the field in the IDE Fields editor and then re-create it. The correct field type will then be used.<span class="odfLiEnd"/> </p></li></ol><p class="P1">Alternatively, all TFmtBcdField fields should be deleted prior to conversion and then recreated in the IDE.</p><h2 class="P7"><a id="a__The_IBX_Components"><span/></a>The IBX Components</h2><p class="P2">The purpose of IBX is to provide an implementation of the Delphi/Lazarus TDataset model, and hence a data source for Data Aware components, and doing so by making direct use of the Firebird API. There is no middleware involved and the intent is to maximise performance.</p><p class="P2">Firebird is an SQL database and a knowledge of SQL is generally necessary for all but basic use of IBX. IBX does not attempt to hide the SQL from the programmer. Indeed, it gives the programmer full use of SQL.</p><p class="P2">The following components are installed on the Firebird tab:</p><table border="0" cellspacing="0" cellpadding="0" class="Table1"><colgroup><col/><col/></colgroup><tr><td style="text-align:left;" class="Table1_A1"><p class="P6">TIBDatabase</p></td><td style="text-align:left;" class="Table1_A1"><p class="Table_20_Contents">Every project that uses IBX must have at least one TIBDatabase component. This is usually placed on a data module or the main form, and represents the connection to the database. Its properties identify the server on which the database is located, its name or pathname on that server, the login credentials, and the local character set when transliteration is required. It can also generate a login prompt for the user name and password, or support a user provided login form.</p></td></tr><tr><td style="text-align:left;" class="Table1_A1"><p class="P6">TIBTransaction</p></td><td style="text-align:left;" class="Table1_A1"><p class="Table_20_Contents">Every project that uses IBX must have at least one TIBTransaction component. Firebird is a transaction oriented database and all operations must take place in the context of a transaction. Its properties determine the transaction isolation (see Firebird documentation). A TIBTransaction is typically provided with the TIBDatabase and linked to it by the TIBDatabase DefaultTransaction property.</p></td></tr><tr><td style="text-align:left;" class="Table1_A1"><p class="P6">TIBQuery</p></td><td style="text-align:left;" class="Table1_A1"><p class="P5">This component is a descendent of TDataset and generates the dataset from the results of an SQL query (Select statement or a Stored Procedure that returns a results set). The SQL query used is given by its SQL property. This can be parameterised (see below) with the values of the parameters set before the query is executed. When the “active” property is set to true then the query is executed and the results set returned. When “active” is set to false, the results set is discarded.</p><p class="Table_20_Contents">Its properties must identify the database and the transaction used for executing the query.</p></td></tr><tr><td style="text-align:left;" class="Table1_A1"><p class="P6">TIBUpdateSQL</p></td><td style="text-align:left;" class="Table1_A1"><p class="Table_20_Contents">This component can be linked from one or more TIBQuery components and is used to support updateable queries. It provides SQL statements to:</p><ul><li><p class="P10" style="margin-left:0cm;"><span class="Bullet_20_Symbols" style="display:block;float:left;min-width:0.635cm;">•</span>Delete the current row in the results set<span class="odfLiEnd"/> </p></li><li><p class="P10" style="margin-left:0cm;"><span class="Bullet_20_Symbols" style="display:block;float:left;min-width:0.635cm;">•</span>Refresh (from the database) the current row in the results set<span class="odfLiEnd"/> </p></li><li><p class="P10" style="margin-left:0cm;"><span class="Bullet_20_Symbols" style="display:block;float:left;min-width:0.635cm;">•</span>Update the current row in the database to match the (modified) values in the database<span class="odfLiEnd"/> </p></li><li><p class="P10" style="margin-left:0cm;"><span class="Bullet_20_Symbols" style="display:block;float:left;min-width:0.635cm;">•</span>Insert a new row in the database.<span class="odfLiEnd"/> </p></li></ul></td></tr><tr><td style="text-align:left;" class="Table1_A1"><p class="P6">TIBDataSet</p></td><td style="text-align:left;" class="Table1_A1"><p class="P5">This is also a TDataset descendent and combiines the functionality of TIBQuery and TIBUpdateSQL into a single component.</p><p class="P5">Its properties must identify the database and the transaction used for executing the query.</p><p class="Table_20_Contents">You will normally want to use TIBDataset instead of a TIBQuery and TIBUpdateSQL pair. The main use of the latter combination is, for example, when a form uses a TIBQuery to provide a read only dataset, and a subclassed (inherited) form needs to update the dataset. The IBUpdateSQL can be added to the subclassed form to provide the update capability.</p></td></tr><tr><td style="text-align:left;" class="Table1_A1"><p class="P6">TIBStoredProc</p></td><td style="text-align:left;" class="Table1_A1"><p class="P5">This component is used to execute a stored procedure (on the Database Server). Usually one that does not generate a results set.</p><p class="Table_20_Contents">Its properties must identify the database and the transaction used for executing the query.</p></td></tr><tr><td style="text-align:left;" class="Table1_A1"><p class="P6">TIBSQL</p></td><td style="text-align:left;" class="Table1_A1"><p class="P5">This component is the basic SQL engine of IBX and is used internally by TIBQuery, TIBDataset and TIBStoredProc to perform SQL queries. It can be used directly by the programmer to effectively implement embedded SQL statements.</p><p class="P5">Its properties must identify the database and the transaction used for executing the query.</p><p class="Table_20_Contents">TIBSQL is essentially an object oriented encapsulation of the Firebird DSQL API. </p></td></tr><tr><td style="text-align:left;" class="Table1_A1"><p class="P6"> </p></td><td style="text-align:left;" class="Table1_A1"><p class="Table_20_Contents"> </p></td></tr><tr><td style="text-align:left;" class="Table1_A1"><p class="P6">TIBEvents</p></td><td style="text-align:left;" class="Table1_A1"><p class="P5">One very useful feature of the Firebird Database is its ability to generate asynchronous “events” from a Stored Procedure or Trigger and which can then be acted upon by any active client that is listening on the event. Database clients can thus act immediately on changes made by another client without needing to regularly query the database.</p><p class="P5">The TIBEvents component is used to register for and receive Firebird Events. Up to 16 events can be waited upon simultaneously. The name of each event to be listened to is set in the component's Events property. If you need to wait on more than 16 events, then additional TIBEvents components can be used.</p><p class="P5">The event notification is asynchronous and takes place at the end of the transaction in which the event was generated. A separate thread is created by TIBEvents to wait on the event notification. When the event occurs it calls the “OnEventAlert” event handler to report which event has been received. Note that the event handler is run in the context of the main thread and hence there is no need to worry about thread synchronisation.</p></td></tr><tr><td style="text-align:left;" class="Table1_A1"><p class="P6">TIBSQLMonitor</p></td><td style="text-align:left;" class="Table1_A1"><p class="P5">This component supports debugging and performance tuning by allowing one process to monitor the SQL function calls in the same or another process (on the same system).</p><p class="P5">The TIBDatabase trace flags determine which function calls can be traced with respect to its databae connection. However, a process only starts to broadcast its function calls after an explicit call to the IBSQLMonitor.EnableMonitoring procedure, and stops after a call to IBSQLMonitor.DisableMonitoring.</p><p class="P5">To receive SQL Function call traces, you need to place a TIBSQLMontor component on your form. The properties of this component can be set to filter the SQL function calls to what you are interested in. The OnSQL event handler is used to receive and process SQL function call trace events.</p><p class="P5">Note that the Windows implementation allows any process to monitor the SQL Trace events broadcast by another. The Linux implementation restricts monitoring to processes owned by the same user.</p></td></tr><tr><td style="text-align:left;" class="Table1_A1"><p class="P6">TIBTable</p></td><td style="text-align:left;" class="Table1_A1"><p class="P5">This component provides a simple TDataset descendent where the contents of the dataset are the same as a named Database Table. This component is useful for very simple novice applications, but TIBDataset should normally be preferred.</p></td></tr><tr><td style="text-align:left;" class="Table1_A1"><p class="P6">TIBExtract</p></td><td style="text-align:left;" class="Table1_A1"><p class="P5">This component allows the extract of database metadata. It is part of the original IBX and has been retained for compatibility. However, the Firebird isql utlitity should normally used for this purpose. No attempt has been made to bring this component up-to-date with respect to enhancements made to the Firebird SQL syntax.</p></td></tr><tr><td style="text-align:left;" class="Table1_A1"><p class="P6">TIBBatchMove</p></td><td style="text-align:left;" class="Table1_A1"><p class="P5">This component supports a table to table copy from a source IBX dataset to a TIBTable.</p></td></tr></table><p class="P2">The Firebird Admin tab provides the Service API components. These support various server side functions including user password maintenance and database backup/restore.</p><h2 class="P7"><a id="a__Using_the_Property_Editors"><span/></a>Using the Property Editors</h2><p class="P2">IBX for Lazarus comes with property and component editors for all IBX objects including those providing the service API. For the data access components (IBDataSet, IBQuery, IBSQLUpdate and IBSQL), the property and component editors provide assisted generation and testing of SQL statements using the Firebird Database Engine. For this to function correctly, a TIBDatabase component must be defined and linked to a live database. A default transaction must be present and linked to the TIBDatabase and the Database property must be set for each data access component, and pointing to the TIBDatabase component.</p><p class="P2">The editors follow the same basic scheme with a combo box in the left hand frame listing available tables and listboxes showing the columns and Primary Keys respectively for the currently selected table.</p><p class="P2">A “Generate SQL” button will cause a Select, Insert, Update or Delete Statement, as appropriate, to be generated for the currently selected table, and presented into the right hand editor window. If one or more columns are selected then the statement is restricted to those columns, otherwise all columns are included in the statement. Note that Update statements may be restricted to avoid updating the primary key values. If these are internal keys that are not visible to the user, then there is little value in including them in the update statement..</p><p class="P2">Double-clicking on a column name will cause that column name to be inserted in the SQL statement.</p><p class="P2">The “Test” button can be used to test the current SQL statement for correctness. The error generated by the database engine, if any, will be returned.</p><p class="Text_20_body">In typical use, the “Generate SQL” function provides an initial set of SQL statements that can be edited to suit the actual purpose. The “Test” function can be used to check correct syntax and avoids having to compile and run the program in order to test SQL syntax correctness.</p><h2 class="Heading_20_2"><a id="a__Notes_on_the_SQL_Syntax"><span/></a>Notes on the SQL Syntax</h2><p class="Text_20_body">The SQL statement syntax supported by IBX is the same as the SQL syntax supported by Firebird. Both the Data Manipulation Language (DML) and the Data Definition Language (DDL) can be used. However, there is one important difference and that is in the handling of parameterised queries.</p><p class="Text_20_body">In normal Firebird SQL, query parameters are represented by a '?' placeholder and are manipulated as positional parameters. IBX instead borrows from the Firebird Procedure and Trigger Language and uses named parameters, where a parameter name starts with a colon character and otherwise conforms with the requirements for a database column name. For example:</p><p class="P3">Select A.EMP_NO, A.FIRST_NAME, A.LAST_NAME, From EMPLOYEE A <br/>Where A.EMP_NO = :EMP_NO;</p><p class="Text_20_body">is a parameterised select query where “:EMP_NO” is a parameter.</p><p class="Text_20_body">For a select query, the parameter value must be specified before the query is activated. For example:</p><p class="P3">IBQuery1.ParamByName('EMP_NO').AsInteger := 1;<br/>IBQuery1.Active := true;</p><p class="Text_20_body">If a TIBQuery or TIBDataset with a parameterised Select query is activated without a parameter value assigned, and the query has a DataSource property set, the component will query the Dataset addressed by DataSource. If it has a field with the same name as the parameter (leading ':' omitted) then the current value of the field is taken as the parameter value. This allows master/detail relationships to be simply established by careful choice of parameter names.</p><p class="Text_20_body">In Update, Insert , Delete and Refresh queries, a different convention is used for determining parameter values. In the case, and before the query is executed, the parameter values are taken from the values of the dataset's own fields with the same name as the parameter. For example, an Insert query thus inserts a new record with the column values set to the current field values.</p><p class="P3">Insert into EMPLOYEE(EMP_NO,LAST_NAME) VALUES(:EMP_NO,:LAST_NAME);</p><p class="Text_20_body">In the Refresh, Update and Delete queries, a Where clause is normally given and this is usually specified to use the current values of the primary key fields, in order to select the current record. For example:</p><p class="P3">Delete from EMPLOYEE Where EMP_NO = :EMP_NO;</p><p class="Text_20_body">will delete the current record from the database.</p><p class="Text_20_body">One further convention is also very useful for Update queries. A parameter name may be prefixed with “:OLD_”. If so, the value it is set to is the value of the named field before any changes were made to it. This is important to allow a user to change the value of a field that is also a primary key. For example:</p><p class="P3">Update EMPLOYEE Set EMP_NO = :EMP_NO, LAST_NAME = :LAST_NAME<br/>Where EMP_NO = :OLD_EMP_NO;</p><p class="Text_20_body">allows change of both the employee's last name and the Employee Number. However, the Employee Number is also the primary key and it can only be changed if the original value is used in the where clause (to select the current record in the database), with the new value set in the main part of the Update statement.</p><h2 class="Heading_20_2"><a id="a__Transactions"><span/></a>Transactions</h2><p class="Text_20_body">Firebird is a transaction oriented database and all interactions with the database have to take place in the context of a transaction. At the end of a transaction, the transaction is either committed. That is all changes are made permanent, or they are rolled back and the state of the database restored to the state it was in before the transaction was started. Firebird allows multiple independent transactions to take place simultaneously and provides several possible isolation strategies in order to avoid the transactions interfering with each other.</p><p class="Text_20_body">In a simple application, you only need to include a single TIBTransaction component with your application. The first dataset to be activated implicitly starts the transaction and, if, when it is deactivated, no other datasets are active, it will automatically commit the transaction. When the database is closed, the default action of the TIBTransaction is to commit all changes.</p><p class="Text_20_body">In a more advanced application, you will want more control over committing or rolling back the transaction and TIBTransaction provides methods to start a transaction and to commit it or roll it back. In this case, it is usually advisable to explicitly start each transaction rather than relying on implicit starts as this avoids a dataset unexpectedly committing a transaction when it is closed. Commit and Rollback are then always under programmatic control.</p><p class="Text_20_body">Note that when a transaction ends, all datasets referencing the transaction are automatically deactivated. A new transaction has to be started and those datasets reactivated if they are to continue to be populated.</p></body></html> |