00001 {*********************************************************}
00002 { }
00003 { Zeos Database Objects }
00004 { Oracle Database Connectivity Classes }
00005 { }
00006 { Originally written by Sergey Seroukhov }
00007 { }
00008 {*********************************************************}
00009
00010 {@********************************************************}
00011 { Copyright (c) 1999-2006 Zeos Development Group }
00012 { }
00013 { License Agreement: }
00014 { }
00015 { This library is distributed in the hope that it will be }
00016 { useful, but WITHOUT ANY WARRANTY; without even the }
00017 { implied warranty of MERCHANTABILITY or FITNESS FOR }
00018 { A PARTICULAR PURPOSE. See the GNU Lesser General }
00019 { Public License for more details. }
00020 { }
00021 { The source code of the ZEOS Libraries and packages are }
00022 { distributed under the Library GNU General Public }
00023 { License (see the file COPYING / COPYING.ZEOS) }
00024 { with the following modification: }
00025 { As a special exception, the copyright holders of this }
00026 { library give you permission to link this library with }
00027 { independent modules to produce an executable, }
00028 { regardless of the license terms of these independent }
00029 { modules, and to copy and distribute the resulting }
00030 { executable under terms of your choice, provided that }
00031 { you also meet, for each linked independent module, }
00032 { the terms and conditions of the license of that module. }
00033 { An independent module is a module which is not derived }
00034 { from or based on this library. If you modify this }
00035 { library, you may extend this exception to your version }
00036 { of the library, but you are not obligated to do so. }
00037 { If you do not wish to do so, delete this exception }
00038 { statement from your version. }
00039 { }
00040 { }
00041 { The project web site is located on: }
00042 { http:
00043 { http:
00044 { svn:
00045 { }
00046 { http:
00047 { http:
00048 { }
00049 { }
00050 { }
00051 { Zeos Development Group. }
00052 {********************************************************@}
00053
00054 unit ZDbcOracleStatement;
00055
00056 interface
00057
00058 {$I ZDbc.inc}
00059
00060 uses
00061 Classes, SysUtils, ZSysUtils, ZDbcIntfs, ZDbcStatement, ZDbcLogging,
00062 ZPlainOracleDriver, ZCompatibility, ZVariant, ZDbcOracleUtils;
00063
00064 type
00065
00066 {** Defines a Oracle specific statement. }
00067 IZOracleStatement = interface(IZStatement)
00068 ['{8644E5B6-1E0F-493F-B6AC-40D70CCEA13A}']
00069
00070 function GetStatementHandle: POCIStmt;
00071 end;
00072
00073 {** Implements Generic Oracle Statement. }
00074 TZOracleStatement = class(TZAbstractStatement, IZOracleStatement)
00075 private
00076 FPlainDriver: IZOraclePlainDriver;
00077
00078 public
00079 constructor Create(PlainDriver: IZOraclePlainDriver;
00080 Connection: IZConnection; Info: TStrings);
00081 destructor Destroy; override;
00082
00083 function ExecuteQuery(const SQL: string): IZResultSet; override;
00084 function ExecuteUpdate(const SQL: string): Integer; override;
00085 function Execute(const SQL: string): Boolean; override;
00086
00087 function GetStatementHandle: POCIStmt;
00088 end;
00089
00090 {** Implements Prepared SQL Statement. }
00091 TZOraclePreparedStatement = class(TZAbstractPreparedStatement)
00092 private
00093 FPrepared: Boolean;
00094 FHandle: POCIStmt;
00095 FErrorHandle: POCIError;
00096 FPlainDriver: IZOraclePlainDriver;
00097 FOracleSQL: string;
00098 FExecStatement: IZStatement;
00099 FLastStatement: IZStatement;
00100 FInVars: PZSQLVars;
00101
00102 procedure SetLastStatement(LastStatement: IZStatement);
00103 function GetExecStatement: IZStatement;
00104 function ConvertToOracleSQLQuery(SQL: string): string;
00105
00106 protected
00107 property Prepared: Boolean read FPrepared write FPrepared;
00108 property Handle: POCIStmt read FHandle write FHandle;
00109 property ErrorHandle: POCIError read FErrorHandle write FErrorHandle;
00110 property OracleSQL: string read FOracleSQL write FOracleSQL;
00111 property ExecStatement: IZStatement read FExecStatement write FExecStatement;
00112 property LastStatement: IZStatement read FLastStatement write SetLastStatement;
00113 property InVars: PZSQLVars read FInVars write FInVars;
00114
00115 procedure Prepare; virtual;
00116
00117 public
00118 constructor Create(PlainDriver: IZOraclePlainDriver;
00119 Connection: IZConnection; const SQL: string; Info: TStrings);
00120 destructor Destroy; override;
00121
00122 procedure Close; override;
00123
00124 function ExecuteQuery(const SQL: string): IZResultSet; override;
00125 function ExecuteUpdate(const SQL: string): Integer; override;
00126 function Execute(const SQL: string): Boolean; override;
00127
00128 function ExecuteQueryPrepared: IZResultSet; override;
00129 function ExecuteUpdatePrepared: Integer; override;
00130 function ExecutePrepared: Boolean; override;
00131
00132 function GetStatementHandle: POCIStmt;
00133 end;
00134
00135 implementation
00136
00137 uses
00138 ZTokenizer;
00139
00140 { TZOracleStatement }
00141
00142 {**
00143 Constructs this object and assignes the main properties.
00144 @param PlainDriver a Oracle plain driver.
00145 @param Connection a database connection object.
00146 @param Info a statement parameters.
00147 @param Handle a connection handle pointer.
00148 }
00149 constructor TZOracleStatement.Create(PlainDriver: IZOraclePlainDriver;
00150 Connection: IZConnection; Info: TStrings);
00151 begin
00152 inherited Create(Connection, Info);
00153 FPlainDriver := PlainDriver;
00154 ResultSetType := rtForwardOnly;
00155 end;
00156
00157 {**
00158 Destroys this object and cleanups the memory.
00159 }
00160 destructor TZOracleStatement.Destroy;
00161 begin
00162 inherited Destroy;
00163 end;
00164
00165 {**
00166 Executes an SQL statement that returns a single <code>ResultSet</code> object.
00167 @param sql typically this is a static SQL <code>SELECT</code> statement
00168 @return a <code>ResultSet</code> object that contains the data produced by the
00169 given query; never <code>null</code>
00170 }
00171 function TZOracleStatement.ExecuteQuery(const SQL: string): IZResultSet;
00172 var
00173 Handle: POCIStmt;
00174 ErrorHandle: POCIError;
00175 begin
00176 AllocateOracleStatementHandles(FPlainDriver, Connection, Handle, ErrorHandle);
00177
00178 try
00179 PrepareOracleStatement(FPlainDriver, SQL, Handle, ErrorHandle);
00180 Result := CreateOracleResultSet(FPlainDriver, Self, SQL,
00181 Handle, ErrorHandle);
00182 except
00183 FreeOracleStatementHandles(FPlainDriver, Handle, ErrorHandle);
00184 raise;
00185 end;
00186
00187 DriverManager.LogMessage(lcExecute, FPlainDriver.GetProtocol, SQL);
00188 end;
00189
00190 {**
00191 Executes an SQL <code>INSERT</code>, <code>UPDATE</code> or
00192 <code>DELETE</code> statement. In addition,
00193 SQL statements that return nothing, such as SQL DDL statements,
00194 can be executed.
00195
00196 @param sql an SQL <code>INSERT</code>, <code>UPDATE</code> or
00197 <code>DELETE</code> statement or an SQL statement that returns nothing
00198 @return either the row count for <code>INSERT</code>, <code>UPDATE</code>
00199 or <code>DELETE</code> statements, or 0 for SQL statements that return nothing
00200 }
00201 function TZOracleStatement.ExecuteUpdate(const SQL: string): Integer;
00202 var
00203 Handle: POCIStmt;
00204 ErrorHandle: POCIError;
00205 begin
00206 AllocateOracleStatementHandles(FPlainDriver, Connection, Handle, ErrorHandle);
00207
00208 try
00209 PrepareOracleStatement(FPlainDriver, SQL, Handle, ErrorHandle);
00210 ExecuteOracleStatement(FPlainDriver, Connection, SQL, Handle, ErrorHandle);
00211 Result := GetOracleUpdateCount(FPlainDriver, Handle, ErrorHandle);
00212 finally
00213 FreeOracleStatementHandles(FPlainDriver, Handle, ErrorHandle);
00214 end;
00215
00216 DriverManager.LogMessage(lcExecute, FPlainDriver.GetProtocol, SQL);
00217
00218 { Autocommit statement. }
00219 if Connection.GetAutoCommit then
00220 Connection.Commit;
00221 end;
00222
00223 {**
00224 Executes an SQL statement that may return multiple results.
00225 Under some (uncommon) situations a single SQL statement may return
00226 multiple result sets and/or update counts. Normally you can ignore
00227 this unless you are (1) executing a stored procedure that you know may
00228 return multiple results or (2) you are dynamically executing an
00229 unknown SQL string. The methods <code>execute</code>,
00230 <code>getMoreResults</code>, <code>getResultSet</code>,
00231 and <code>getUpdateCount</code> let you navigate through multiple results.
00232
00233 The <code>execute</code> method executes an SQL statement and indicates the
00234 form of the first result. You can then use the methods
00235 <code>getResultSet</code> or <code>getUpdateCount</code>
00236 to retrieve the result, and <code>getMoreResults</code> to
00237 move to any subsequent result(s).
00238
00239 @param sql any SQL statement
00240 @return <code>true</code> if the next result is a <code>ResultSet</code> object;
00241 <code>false</code> if it is an update count or there are no more results
00242 }
00243 function TZOracleStatement.Execute(const SQL: string): Boolean;
00244 var
00245 Handle: POCIStmt;
00246 ErrorHandle: POCIError;
00247 StatementType: ub2;
00248 begin
00249 Result := False;
00250 AllocateOracleStatementHandles(FPlainDriver, Connection, Handle, ErrorHandle);
00251
00252 try
00253 PrepareOracleStatement(FPlainDriver, SQL, Handle, ErrorHandle);
00254
00255 StatementType := 0;
00256 FPlainDriver.AttrGet(Handle, OCI_HTYPE_STMT, @StatementType, nil,
00257 OCI_ATTR_STMT_TYPE, ErrorHandle);
00258
00259 if StatementType = OCI_STMT_SELECT then
00260 begin
00261 LastResultSet := CreateOracleResultSet(FPlainDriver, Self,
00262 SQL, Handle, ErrorHandle);
00263 Result := LastResultSet <> nil;
00264 end
00265 else
00266 begin
00267 ExecuteOracleStatement(FPlainDriver, Connection, SQL,
00268 Handle, ErrorHandle);
00269 LastUpdateCount := GetOracleUpdateCount(FPlainDriver, Handle, ErrorHandle);
00270 end;
00271 finally
00272 if not Result then
00273 begin
00274 FreeOracleStatementHandles(FPlainDriver, Handle, ErrorHandle);
00275 end;
00276 end;
00277
00278 DriverManager.LogMessage(lcExecute, FPlainDriver.GetProtocol, SQL);
00279
00280 { Autocommit statement. }
00281 if not Result and Connection.GetAutoCommit then
00282 Connection.Commit;
00283 end;
00284
00285 {**
00286 Gets statement handle.
00287 @return statement handle.
00288 }
00289 function TZOracleStatement.GetStatementHandle: POCIStmt;
00290 begin
00291 Result := nil;
00292 end;
00293
00294 { TZOraclePreparedStatement }
00295
00296 {**
00297 Constructs this object and assignes the main properties.
00298 @param PlainDriver a Oracle plain driver.
00299 @param Connection a database connection object.
00300 @param Info a statement parameters.
00301 @param Handle a connection handle pointer.
00302 }
00303 constructor TZOraclePreparedStatement.Create(
00304 PlainDriver: IZOraclePlainDriver; Connection: IZConnection;
00305 const SQL: string; Info: TStrings);
00306 begin
00307 inherited Create(Connection, SQL, Info);
00308 FPlainDriver := PlainDriver;
00309 ResultSetType := rtForwardOnly;
00310 FOracleSQL := ConvertToOracleSQLQuery(SQL);
00311 FPrepared := False;
00312 end;
00313
00314 {**
00315 Destroys this object and cleanups the memory.
00316 }
00317 destructor TZOraclePreparedStatement.Destroy;
00318 begin
00319 inherited Destroy;
00320 end;
00321
00322 {**
00323 Sets a reference to the last statement.
00324 @param LastStatement the last statement interface.
00325 }
00326 procedure TZOraclePreparedStatement.SetLastStatement(
00327 LastStatement: IZStatement);
00328 begin
00329 if FLastStatement <> nil then
00330 FLastStatement.Close;
00331 FLastStatement := LastStatement;
00332 end;
00333
00334 {**
00335 Creates a temporary statement which executes queries.
00336 @param Info a statement parameters.
00337 @return a created statement object.
00338 }
00339 function TZOraclePreparedStatement.GetExecStatement: IZStatement;
00340 begin
00341 if ExecStatement = nil then
00342 begin
00343 ExecStatement := TZOracleStatement.Create(FPlainDriver, Connection, Info);
00344
00345 ExecStatement.SetMaxFieldSize(GetMaxFieldSize);
00346 ExecStatement.SetMaxRows(GetMaxRows);
00347 ExecStatement.SetEscapeProcessing(EscapeProcessing);
00348 ExecStatement.SetQueryTimeout(GetQueryTimeout);
00349 ExecStatement.SetCursorName(CursorName);
00350
00351 ExecStatement.SetFetchDirection(GetFetchDirection);
00352 ExecStatement.SetFetchSize(GetFetchSize);
00353 ExecStatement.SetResultSetConcurrency(GetResultSetConcurrency);
00354 ExecStatement.SetResultSetType(GetResultSetType);
00355 end;
00356 Result := ExecStatement;
00357 end;
00358
00359 {**
00360 Converts an SQL query into Oracle format.
00361 @param SQL a query with parameters defined with '?'
00362 @returns a query with parameters in Oracle format ':pN'.
00363 }
00364 function TZOraclePreparedStatement.ConvertToOracleSQLQuery(SQL: string): string;
00365 var
00366 I, N: Integer;
00367 Tokens: TStrings;
00368 begin
00369 if Pos('?', SQL) > 0 then
00370 begin
00371 Tokens := Connection.GetDriver.GetTokenizer.
00372 TokenizeBufferToList(SQL, [toUnifyWhitespaces]);
00373 try
00374 Result := '';
00375 N := 0;
00376 for I := 0 to Tokens.Count - 1 do
00377 begin
00378 if Tokens[I] = '?' then
00379 begin
00380 Inc(N);
00381 Result := Result + ':P' + IntToStr(N);
00382 end else
00383 Result := Result + Tokens[I];
00384 end;
00385 finally
00386 Tokens.Free;
00387 end;
00388 end else
00389 Result := SQL;
00390 end;
00391
00392 {**
00393 Closes this statement and frees all resources.
00394 }
00395 procedure TZOraclePreparedStatement.Close;
00396 begin
00397 inherited Close;
00398 if LastStatement <> nil then
00399 begin
00400 FLastStatement.Close;
00401 FLastStatement := nil;
00402 end;
00403 FreeOracleStatementHandles(FPlainDriver, FHandle, FErrorHandle);
00404 FreeOracleSQLVars(FPlainDriver, FInVars);
00405 end;
00406
00407 {**
00408 Executes an SQL statement that may return multiple results.
00409 Under some (uncommon) situations a single SQL statement may return
00410 multiple result sets and/or update counts. Normally you can ignore
00411 this unless you are (1) executing a stored procedure that you know may
00412 return multiple results or (2) you are dynamically executing an
00413 unknown SQL string. The methods <code>execute</code>,
00414 <code>getMoreResults</code>, <code>getResultSet</code>,
00415 and <code>getUpdateCount</code> let you navigate through multiple results.
00416
00417 The <code>execute</code> method executes an SQL statement and indicates the
00418 form of the first result. You can then use the methods
00419 <code>getResultSet</code> or <code>getUpdateCount</code>
00420 to retrieve the result, and <code>getMoreResults</code> to
00421 move to any subsequent result(s).
00422
00423 @param sql any SQL statement
00424 @return <code>true</code> if the next result is a <code>ResultSet</code> object;
00425 <code>false</code> if it is an update count or there are no more results
00426 }
00427 function TZOraclePreparedStatement.Execute(const SQL: string): Boolean;
00428 begin
00429 LastStatement := GetExecStatement;
00430 Result := LastStatement.Execute(SQL);
00431 if Result then
00432 LastResultSet := LastStatement.GetResultSet
00433 else
00434 LastUpdateCount := LastStatement.GetUpdateCount;
00435 end;
00436
00437 {**
00438 Executes an SQL statement that returns a single <code>ResultSet</code> object.
00439 @param sql typically this is a static SQL <code>SELECT</code> statement
00440 @return a <code>ResultSet</code> object that contains the data produced by the
00441 given query; never <code>null</code>
00442 }
00443 function TZOraclePreparedStatement.ExecuteQuery(const SQL: string): IZResultSet;
00444 begin
00445 Result := GetExecStatement.ExecuteQuery(SQL);
00446 end;
00447
00448 {**
00449 Executes an SQL <code>INSERT</code>, <code>UPDATE</code> or
00450 <code>DELETE</code> statement. In addition,
00451 SQL statements that return nothing, such as SQL DDL statements,
00452 can be executed.
00453
00454 @param sql an SQL <code>INSERT</code>, <code>UPDATE</code> or
00455 <code>DELETE</code> statement or an SQL statement that returns nothing
00456 @return either the row count for <code>INSERT</code>, <code>UPDATE</code>
00457 or <code>DELETE</code> statements, or 0 for SQL statements that return nothing
00458 }
00459 function TZOraclePreparedStatement.ExecuteUpdate(const SQL: string): Integer;
00460 begin
00461 Result := GetExecStatement.ExecuteUpdate(SQL);
00462 LastUpdateCount := Result;
00463 end;
00464
00465 {**
00466 Prepares an SQL statement
00467 }
00468 procedure TZOraclePreparedStatement.Prepare;
00469 var
00470 I: Integer;
00471 Status: Integer;
00472 TypeCode: ub2;
00473 CurrentVar: PZSQLVar;
00474 begin
00475 if not Prepared then
00476 begin
00477 { Allocates statement handles. }
00478 if (FHandle = nil) or (FErrorHandle = nil) then
00479 begin
00480 AllocateOracleStatementHandles(FPlainDriver, Connection,
00481 FHandle, FErrorHandle);
00482 end;
00483
00484 PrepareOracleStatement(FPlainDriver, OracleSQL, Handle, ErrorHandle);
00485 AllocateOracleSQLVars(FInVars, InParamCount);
00486 InVars^.ActualNum := InParamCount;
00487
00488 for I := 0 to InParamCount - 1 do
00489 begin
00490 CurrentVar := @FInVars.Variables[I + 1];
00491 CurrentVar.Handle := nil;
00492
00493 { Artificially define Oracle internal type. }
00494 if InParamTypes[I] = stBinaryStream then
00495 TypeCode := SQLT_BLOB
00496 else if InParamTypes[I] = stAsciiStream then
00497 TypeCode := SQLT_CLOB
00498 else TypeCode := SQLT_STR;
00499
00500 InitializeOracleVar(FPlainDriver, Connection, CurrentVar,
00501 InParamTypes[I], TypeCode, 1024);
00502
00503 Status := FPlainDriver.BindByPos(FHandle, CurrentVar.BindHandle,
00504 FErrorHandle, I + 1, CurrentVar.Data, CurrentVar.Length,
00505 CurrentVar.TypeCode, @CurrentVar.Indicator, nil, nil, 0, nil,
00506 OCI_DEFAULT);
00507 CheckOracleError(FPlainDriver, FErrorHandle, Status, lcExecute, SQL);
00508 end;
00509
00510 DriverManager.LogMessage(lcExecute, FPlainDriver.GetProtocol, SQL);
00511 Prepared := True;
00512 end;
00513 end;
00514
00515 {**
00516 Executes the SQL query in this <code>PreparedStatement</code> object
00517 and returns the result set generated by the query.
00518
00519 @return a <code>ResultSet</code> object that contains the data produced by the
00520 query; never <code>null</code>
00521 }
00522 function TZOraclePreparedStatement.ExecutePrepared: Boolean;
00523 var
00524 StatementType: ub2;
00525 begin
00526 Result := False;
00527
00528 { Prepares a statement. }
00529 if not Prepared then
00530 Prepare;
00531
00532 { Loads binded variables with values. }
00533 LoadOracleVars(FPlainDriver, Connection, ErrorHandle,
00534 FInVars, InParamValues);
00535
00536 StatementType := 0;
00537 FPlainDriver.AttrGet(Handle, OCI_HTYPE_STMT, @StatementType, nil,
00538 OCI_ATTR_STMT_TYPE, ErrorHandle);
00539
00540 if StatementType = OCI_STMT_SELECT then
00541 begin
00542 { Executes the statement and gets a resultset. }
00543 LastResultSet := CreateOracleResultSet(FPlainDriver, Self,
00544 SQL, Handle, ErrorHandle);
00545 Result := LastResultSet <> nil;
00546 end
00547 else
00548 begin
00549 { Executes the statement and gets a result. }
00550 ExecuteOracleStatement(FPlainDriver, Connection, OracleSQL,
00551 Handle, ErrorHandle);
00552 LastUpdateCount := GetOracleUpdateCount(FPlainDriver, Handle, ErrorHandle);
00553 end;
00554
00555 DriverManager.LogMessage(lcExecute, FPlainDriver.GetProtocol, OracleSQL);
00556
00557 { Unloads binded variables with values. }
00558 UnloadOracleVars(FInVars);
00559
00560 { Autocommit statement. }
00561 if not Result and Connection.GetAutoCommit then
00562 Connection.Commit;
00563 end;
00564
00565 {**
00566 Executes the SQL query in this <code>PreparedStatement</code> object
00567 and returns the result set generated by the query.
00568
00569 @return a <code>ResultSet</code> object that contains the data produced by the
00570 query; never <code>null</code>
00571 }
00572 function TZOraclePreparedStatement.ExecuteQueryPrepared: IZResultSet;
00573 begin
00574 { Prepares a statement. }
00575 if not Prepared then
00576 Prepare;
00577
00578 { Loads binded variables with values. }
00579 LoadOracleVars(FPlainDriver, Connection, ErrorHandle,
00580 FInVars, InParamValues);
00581
00582 { Executes the statement and gets a resultset. }
00583 Result := CreateOracleResultSet(FPlainDriver, Self, SQL,
00584 Handle, ErrorHandle);
00585
00586 DriverManager.LogMessage(lcExecute, FPlainDriver.GetProtocol, SQL);
00587
00588 { Unloads binded variables with values. }
00589 UnloadOracleVars(FInVars);
00590 end;
00591
00592 {**
00593 Executes the SQL INSERT, UPDATE or DELETE statement
00594 in this <code>PreparedStatement</code> object.
00595 In addition,
00596 SQL statements that return nothing, such as SQL DDL statements,
00597 can be executed.
00598
00599 @return either the row count for INSERT, UPDATE or DELETE statements;
00600 or 0 for SQL statements that return nothing
00601 }
00602 function TZOraclePreparedStatement.ExecuteUpdatePrepared: Integer;
00603 var
00604 StatementType: ub2;
00605 ResultSet: IZResultSet;
00606 begin
00607 { Prepares a statement. }
00608 if not Prepared then
00609 Prepare;
00610
00611 { Loads binded variables with values. }
00612 LoadOracleVars(FPlainDriver, Connection, ErrorHandle,
00613 FInVars, InParamValues);
00614
00615 StatementType := 0;
00616 FPlainDriver.AttrGet(Handle, OCI_HTYPE_STMT, @StatementType, nil,
00617 OCI_ATTR_STMT_TYPE, ErrorHandle);
00618
00619 if StatementType = OCI_STMT_SELECT then
00620 begin
00621 { Executes the statement and gets a resultset. }
00622 ResultSet := CreateOracleResultSet(FPlainDriver, Self,
00623 SQL, Handle, ErrorHandle);
00624 try
00625 while ResultSet.Next do;
00626 LastUpdateCount := ResultSet.GetRow;
00627 finally
00628 ResultSet.Close;
00629 end;
00630 end
00631 else
00632 begin
00633 { Executes the statement and gets a result. }
00634 ExecuteOracleStatement(FPlainDriver, Connection, OracleSQL,
00635 Handle, ErrorHandle);
00636 LastUpdateCount := GetOracleUpdateCount(FPlainDriver, Handle, ErrorHandle);
00637 end;
00638 Result := LastUpdateCount;
00639
00640 DriverManager.LogMessage(lcExecute, FPlainDriver.GetProtocol, OracleSQL);
00641
00642 { Unloads binded variables with values. }
00643 UnloadOracleVars(FInVars);
00644
00645 { Autocommit statement. }
00646 if Connection.GetAutoCommit then
00647 Connection.Commit;
00648 end;
00649
00650 {**
00651 Gets statement handle.
00652 @return statement handle.
00653 }
00654 function TZOraclePreparedStatement.GetStatementHandle: POCIStmt;
00655 begin
00656 Result := FHandle;
00657 end;
00658
00659 end.