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 ZDbcOracle;
00055
00056 interface
00057
00058 {$I ZDbc.inc}
00059
00060 uses
00061 {$IFNDEF VER130BELOW}
00062 Types,
00063 {$ENDIF}
00064 ZCompatibility, Classes, SysUtils, Contnrs, ZDbcIntfs, ZDbcConnection,
00065 ZPlainOracleDriver, ZDbcLogging, ZTokenizer, ZDbcGenericResolver,
00066 ZGenericSqlAnalyser;
00067
00068 type
00069
00070 {** Implements Oracle Database Driver. }
00071 TZOracleDriver = class(TZAbstractDriver)
00072 private
00073 FOracle9iPlainDriver: IZOraclePlainDriver;
00074 protected
00075 function GetPlainDriver(const Url: string): IZOraclePlainDriver;
00076 public
00077 constructor Create;
00078 function Connect(const Url: string; Info: TStrings): IZConnection; override;
00079
00080 function GetSupportedProtocols: TStringDynArray; override;
00081 function GetMajorVersion: Integer; override;
00082 function GetMinorVersion: Integer; override;
00083
00084 function GetTokenizer: IZTokenizer; override;
00085 function GetStatementAnalyser: IZStatementAnalyser; override;
00086 end;
00087
00088 {** Represents a Oracle specific connection interface. }
00089 IZOracleConnection = interface (IZConnection)
00090 ['{C7F36FDF-8A64-477B-A0EB-3E8AB7C09F8D}']
00091
00092 function GetPlainDriver: IZOraclePlainDriver;
00093 function GetConnectionHandle: POCIEnv;
00094 function GetContextHandle: POCISvcCtx;
00095 function GetErrorHandle: POCIError;
00096 function GetServerHandle: POCIServer;
00097 function GetSessionHandle: POCISession;
00098 function GetTransactionHandle: POCITrans;
00099 end;
00100
00101 {** Implements Oracle Database Connection. }
00102 TZOracleConnection = class(TZAbstractConnection, IZOracleConnection)
00103 private
00104 FCatalog: string;
00105 FPlainDriver: IZOraclePlainDriver;
00106 FHandle: POCIEnv;
00107 FContextHandle: POCISvcCtx;
00108 FErrorHandle: POCIError;
00109 FServerHandle: POCIServer;
00110 FSessionHandle: POCISession;
00111 FTransHandle: POCITrans;
00112 FClientCodePage: string;
00113
00114 protected
00115 procedure StartTransactionSupport;
00116
00117 public
00118 constructor Create(Driver: IZDriver; const Url: string;
00119 PlainDriver: IZOraclePlainDriver; const HostName: string; Port: Integer;
00120 const Database: string; const User: string; const Password: string; Info: TStrings);
00121 destructor Destroy; override;
00122
00123 function CreateRegularStatement(Info: TStrings): IZStatement; override;
00124 function CreatePreparedStatement(const SQL: string; Info: TStrings):
00125 IZPreparedStatement; override;
00126
00127 procedure Commit; override;
00128 procedure Rollback; override;
00129
00130 procedure Open; override;
00131 procedure Close; override;
00132
00133 procedure SetCatalog(const Catalog: string); override;
00134 function GetCatalog: string; override;
00135
00136 procedure SetTransactionIsolation(Level: TZTransactIsolationLevel); override;
00137 function CreateSequence(const Sequence: string; BlockSize: Integer): IZSequence; override;
00138
00139 function GetPlainDriver: IZOraclePlainDriver;
00140 function GetConnectionHandle: POCIEnv;
00141 function GetContextHandle: POCISvcCtx;
00142 function GetErrorHandle: POCIError;
00143 function GetServerHandle: POCIServer;
00144 function GetSessionHandle: POCISession;
00145 function GetTransactionHandle: POCITrans;
00146 end;
00147
00148 TZOracleSequence = class(TZAbstractSequence)
00149 public
00150 function GetCurrentValue: Int64; override;
00151 function GetCurrentValueSQL: String; override;
00152 function GetNextValue: Int64; override;
00153 function GetNextValueSQL: String; override;
00154 end;
00155
00156 {** Implements a specialized cached resolver for Oracle. }
00157 TZOracleCachedResolver = class(TZGenericCachedResolver)
00158 public
00159 function FormCalculateStatement(Columns: TObjectList): string; override;
00160 end;
00161
00162 var
00163 {** The common driver manager object. }
00164 OracleDriver: IZDriver;
00165
00166 implementation
00167
00168 uses
00169 ZMessages, ZSysUtils, ZDbcUtils, ZGenericSqlToken, ZDbcOracleStatement,
00170 ZDbcOracleUtils, ZDbcOracleMetadata, ZOracleToken, ZOracleAnalyser;
00171
00172 { TZOracleDriver }
00173
00174 {**
00175 Constructs this object with default properties.
00176 }
00177 constructor TZOracleDriver.Create;
00178 begin
00179 FOracle9iPlainDriver := TZOracle9iPlainDriver.Create;
00180 end;
00181
00182 {**
00183 Attempts to make a database connection to the given URL.
00184 The driver should return "null" if it realizes it is the wrong kind
00185 of driver to connect to the given URL. This will be common, as when
00186 the JDBC driver manager is asked to connect to a given URL it passes
00187 the URL to each loaded driver in turn.
00188
00189 <P>The driver should raise a SQLException if it is the right
00190 driver to connect to the given URL, but has trouble connecting to
00191 the database.
00192
00193 <P>The java.util.Properties argument can be used to passed arbitrary
00194 string tag/value pairs as connection arguments.
00195 Normally at least "user" and "password" properties should be
00196 included in the Properties.
00197
00198 @param url the URL of the database to which to connect
00199 @param info a list of arbitrary string tag/value pairs as
00200 connection arguments. Normally at least a "user" and
00201 "password" property should be included.
00202 @return a <code>Connection</code> object that represents a
00203 connection to the URL
00204 }
00205 function TZOracleDriver.Connect(const Url: string; Info: TStrings): IZConnection;
00206 var
00207 TempInfo: TStrings;
00208 HostName, Database, UserName, Password: string;
00209 Port: Integer;
00210 PlainDriver: IZOraclePlainDriver;
00211 begin
00212 TempInfo := TStringList.Create;
00213 try
00214 PlainDriver := GetPlainDriver(Url);
00215 ResolveDatabaseUrl(Url, Info, HostName, Port, Database,
00216 UserName, Password, TempInfo);
00217 Result := TZOracleConnection.Create(Self, Url, PlainDriver, HostName, Port,
00218 Database, UserName, Password, TempInfo);
00219 finally
00220 TempInfo.Free;
00221 end;
00222 end;
00223
00224 {**
00225 Gets the driver's major version number. Initially this should be 1.
00226 @return this driver's major version number
00227 }
00228 function TZOracleDriver.GetMajorVersion: Integer;
00229 begin
00230 Result := 1;
00231 end;
00232
00233 {**
00234 Gets the driver's minor version number. Initially this should be 0.
00235 @return this driver's minor version number
00236 }
00237 function TZOracleDriver.GetMinorVersion: Integer;
00238 begin
00239 Result := 0;
00240 end;
00241
00242 {**
00243 Gets a SQL syntax tokenizer.
00244 @returns a SQL syntax tokenizer object.
00245 }
00246 function TZOracleDriver.GetTokenizer: IZTokenizer;
00247 begin
00248 if Tokenizer = nil then
00249 Tokenizer := TZOracleTokenizer.Create;
00250 Result := Tokenizer;
00251 end;
00252
00253 {**
00254 Creates a statement analyser object.
00255 @returns a statement analyser object.
00256 }
00257 function TZOracleDriver.GetStatementAnalyser: IZStatementAnalyser;
00258 begin
00259 if Analyser = nil then
00260 Analyser := TZOracleStatementAnalyser.Create;
00261 Result := Analyser;
00262 end;
00263
00264 {**
00265 Get a name of the supported subprotocol.
00266 For example: oracle, oracle8 or postgresql72
00267 }
00268 function TZOracleDriver.GetSupportedProtocols: TStringDynArray;
00269 begin
00270 SetLength(Result, 2);
00271 Result[0] := 'oracle';
00272 Result[1] := FOracle9iPlainDriver.GetProtocol;
00273 end;
00274
00275 {**
00276 Gets plain driver for selected protocol.
00277 @param Url a database connection URL.
00278 @return a selected protocol.
00279 }
00280 function TZOracleDriver.GetPlainDriver(const Url: string): IZOraclePlainDriver;
00281 var
00282 Protocol: string;
00283 begin
00284 Protocol := ResolveConnectionProtocol(Url, GetSupportedProtocols);
00285 if Protocol = FOracle9iPlainDriver.GetProtocol then
00286 Result := FOracle9iPlainDriver
00287 else Result := FOracle9iPlainDriver;
00288 Result.Initialize;
00289 end;
00290
00291 { TZOracleConnection }
00292
00293 {**
00294 Constructs this object and assignes the main properties.
00295 @param Driver the parent ZDBC driver.
00296 @param PlainDriver a Oracle plain driver.
00297 @param HostName a name of the host.
00298 @param Port a port number (0 for default port).
00299 @param Database a name pof the database.
00300 @param User a user name.
00301 @param Password a user password.
00302 @param Info a string list with extra connection parameters.
00303 }
00304 constructor TZOracleConnection.Create(Driver: IZDriver; const Url: string;
00305 PlainDriver: IZOraclePlainDriver; const HostName: string; Port: Integer;
00306 const Database, User, Password: string; Info: TStrings);
00307 begin
00308 inherited Create(Driver, Url, HostName, Port, Database, User, Password, Info,
00309 TZOracleDatabaseMetadata.Create(Self, Url, Info));
00310
00311 { Sets a default properties }
00312 FPlainDriver := PlainDriver;
00313 FHandle := nil;
00314 if Self.Port = 0 then Self.Port := 1521;
00315 AutoCommit := True;
00316 TransactIsolationLevel := tiNone;
00317
00318 { Processes connection properties. }
00319 FClientCodePage := Trim(Info.Values['codepage']);
00320
00321 Open;
00322 end;
00323
00324 {**
00325 Destroys this object and cleanups the memory.
00326 }
00327 destructor TZOracleConnection.Destroy;
00328 begin
00329 if FHandle <> nil then
00330 begin
00331 FPlainDriver.HandleFree(FHandle, OCI_HTYPE_ENV);
00332 FHandle := nil;
00333 end;
00334
00335 inherited Destroy;
00336 end;
00337
00338 {**
00339 Opens a connection to database server with specified parameters.
00340 }
00341 procedure TZOracleConnection.Open;
00342 var
00343 Status: Integer;
00344 LogMessage: string;
00345
00346
00347
00348 procedure CleanupOnFail;
00349 begin
00350 FPlainDriver.HandleFree(FContextHandle, OCI_HTYPE_SVCCTX);
00351 FContextHandle := nil;
00352 FPlainDriver.HandleFree(FErrorHandle, OCI_HTYPE_ERROR);
00353 FErrorHandle := nil;
00354 FPlainDriver.HandleFree(FServerHandle, OCI_HTYPE_SERVER);
00355 FServerHandle := nil;
00356 end;
00357
00358 begin
00359 if not Closed then Exit;
00360
00361 LogMessage := Format('CONNECT TO "%s" AS USER "%s"', [Database, User]);
00362
00363 { Sets a default port number. }
00364 if Port = 0 then Port := 1521;
00365 { Sets connection timeout. }
00366
00367
00368 { Connect to Oracle database. }
00369 if FHandle = nil then
00370 FPlainDriver.EnvInit(FHandle, OCI_DEFAULT, 0, nil);
00371 FErrorHandle := nil;
00372 FPlainDriver.HandleAlloc(FHandle, FErrorHandle, OCI_HTYPE_ERROR, 0, nil);
00373 FServerHandle := nil;
00374 FPlainDriver.HandleAlloc(FHandle, FServerHandle, OCI_HTYPE_SERVER, 0, nil);
00375 FContextHandle := nil;
00376 FPlainDriver.HandleAlloc(FHandle, FContextHandle, OCI_HTYPE_SVCCTX, 0, nil);
00377
00378 Status := FPlainDriver.ServerAttach(FServerHandle, FErrorHandle,
00379 PChar(string(Database)), Length(Database), 0);
00380 try
00381 CheckOracleError(FPlainDriver, FErrorHandle, Status, lcConnect, LogMessage);
00382 except
00383 CleanupOnFail;
00384 raise;
00385 end;
00386
00387 FPlainDriver.AttrSet(FContextHandle, OCI_HTYPE_SVCCTX, FServerHandle, 0,
00388 OCI_ATTR_SERVER, FErrorHandle);
00389 FPlainDriver.HandleAlloc(FHandle, FSessionHandle, OCI_HTYPE_SESSION, 0, nil);
00390 FPlainDriver.AttrSet(FSessionHandle, OCI_HTYPE_SESSION, PChar(string(User)),
00391 Length(User), OCI_ATTR_USERNAME, FErrorHandle);
00392 FPlainDriver.AttrSet(FSessionHandle, OCI_HTYPE_SESSION, PChar(string(Password)),
00393 Length(Password), OCI_ATTR_PASSWORD, FErrorHandle);
00394 Status := FPlainDriver.SessionBegin(FContextHandle, FErrorHandle,
00395 FSessionHandle, OCI_CRED_RDBMS, OCI_DEFAULT);
00396 try
00397 CheckOracleError(FPlainDriver, FErrorHandle, Status, lcConnect, LogMessage);
00398 except
00399 CleanupOnFail;
00400 raise;
00401 end;
00402 FPlainDriver.AttrSet(FContextHandle, OCI_HTYPE_SVCCTX, FSessionHandle, 0,
00403 OCI_ATTR_SESSION, FErrorHandle);
00404
00405 DriverManager.LogMessage(lcConnect, FPlainDriver.GetProtocol, LogMessage);
00406
00407 (*
00408 { Sets a client codepage. }
00409 if FClientCodePage <> '' then
00410 begin
00411 SQL := PChar(Format('SET CHARACTER SET %s', [FClientCodePage]));
00412 FPlainDriver.ExecQuery(FHandle, SQL);
00413 CheckOracleError(FPlainDriver, FHandle, lcExecute, SQL);
00414 DriverManager.LogMessage(lcExecute, FPlainDriver.GetProtocol, SQL);
00415 end;
00416 *)
00417 StartTransactionSupport;
00418
00419 inherited Open;
00420 end;
00421
00422 {**
00423 Starts a transaction support.
00424 }
00425 procedure TZOracleConnection.StartTransactionSupport;
00426 var
00427 SQL: PChar;
00428 Status: Integer;
00429 Isolation: Integer;
00430 begin
00431 if TransactIsolationLevel = tiNone then
00432 begin
00433 SQL := 'SET TRANSACTION ISOLATION LEVEL DEFAULT';
00434 Isolation := OCI_DEFAULT;
00435 end
00436 else if TransactIsolationLevel = tiReadCommitted then
00437 begin
00438
00439
00440
00441
00442
00443 SQL := 'SET TRANSACTION ISOLATION LEVEL DEFAULT';
00444 Isolation := OCI_DEFAULT;
00445 end
00446 else if TransactIsolationLevel = tiRepeatableRead then
00447 begin
00448 SQL := 'SET TRANSACTION ISOLATION LEVEL READWRITE';
00449 Isolation := OCI_TRANS_READWRITE;
00450 end
00451 else if TransactIsolationLevel = tiSerializable then
00452 begin
00453 SQL := 'SET TRANSACTION ISOLATION LEVEL SERIALIZABLE';
00454 Isolation := OCI_TRANS_SERIALIZABLE;
00455 end
00456 else
00457 raise EZSQLException.Create(SIsolationIsNotSupported);
00458
00459 FTransHandle := nil;
00460 FPlainDriver.HandleAlloc(FHandle, FTransHandle, OCI_HTYPE_TRANS, 0, nil);
00461 FPlainDriver.AttrSet(FContextHandle, OCI_HTYPE_SVCCTX, FTransHandle, 0,
00462 OCI_ATTR_TRANS, FErrorHandle);
00463
00464 Status := FPlainDriver.TransStart(FContextHandle, FErrorHandle, 0, Isolation);
00465 CheckOracleError(FPlainDriver, FErrorHandle, Status, lcExecute, SQL);
00466
00467 DriverManager.LogMessage(lcExecute, FPlainDriver.GetProtocol, SQL);
00468 end;
00469
00470 {**
00471 Creates a <code>Statement</code> object for sending
00472 SQL statements to the database.
00473 SQL statements without parameters are normally
00474 executed using Statement objects. If the same SQL statement
00475 is executed many times, it is more efficient to use a
00476 <code>PreparedStatement</code> object.
00477 <P>
00478 Result sets created using the returned <code>Statement</code>
00479 object will by default have forward-only type and read-only concurrency.
00480
00481 @param Info a statement parameters.
00482 @return a new Statement object
00483 }
00484 function TZOracleConnection.CreateRegularStatement(Info: TStrings):
00485 IZStatement;
00486 begin
00487 if IsClosed then Open;
00488 Result := TZOracleStatement.Create(FPlainDriver, Self, Info);
00489 end;
00490
00491 {**
00492 Creates a <code>PreparedStatement</code> object for sending
00493 parameterized SQL statements to the database.
00494
00495 A SQL statement with or without IN parameters can be
00496 pre-compiled and stored in a PreparedStatement object. This
00497 object can then be used to efficiently execute this statement
00498 multiple times.
00499
00500 <P><B>Note:</B> This method is optimized for handling
00501 parametric SQL statements that benefit from precompilation. If
00502 the driver supports precompilation,
00503 the method <code>prepareStatement</code> will send
00504 the statement to the database for precompilation. Some drivers
00505 may not support precompilation. In this case, the statement may
00506 not be sent to the database until the <code>PreparedStatement</code> is
00507 executed. This has no direct effect on users; however, it does
00508 affect which method throws certain SQLExceptions.
00509
00510 Result sets created using the returned PreparedStatement will have
00511 forward-only type and read-only concurrency, by default.
00512
00513 @param sql a SQL statement that may contain one or more '?' IN
00514 parameter placeholders
00515 @param Info a statement parameters.
00516 @return a new PreparedStatement object containing the
00517 pre-compiled statement
00518 }
00519 function TZOracleConnection.CreatePreparedStatement(const SQL: string;
00520 Info: TStrings): IZPreparedStatement;
00521 begin
00522 if IsClosed then Open;
00523 Result := TZOraclePreparedStatement.Create(FPlainDriver, Self, SQL, Info);
00524 end;
00525
00526 {**
00527 Makes all changes made since the previous
00528 commit/rollback permanent and releases any database locks
00529 currently held by the Connection. This method should be
00530 used only when auto-commit mode has been disabled.
00531 @see #setAutoCommit
00532 }
00533 procedure TZOracleConnection.Commit;
00534 var
00535 Status: Integer;
00536 SQL: PChar;
00537 begin
00538 if not Closed then
00539 begin
00540 SQL := 'COMMIT';
00541
00542 Status := FPlainDriver.TransCommit(FContextHandle, FErrorHandle,
00543 OCI_DEFAULT);
00544 CheckOracleError(FPlainDriver, FErrorHandle, Status, lcExecute, SQL);
00545
00546 DriverManager.LogMessage(lcExecute, FPlainDriver.GetProtocol, SQL);
00547 end;
00548 end;
00549
00550 {**
00551 Drops all changes made since the previous
00552 commit/rollback and releases any database locks currently held
00553 by this Connection. This method should be used only when auto-
00554 commit has been disabled.
00555 @see #setAutoCommit
00556 }
00557 procedure TZOracleConnection.Rollback;
00558 var
00559 Status: Integer;
00560 SQL: PChar;
00561 begin
00562 if not Closed then
00563 begin
00564 SQL := 'ROLLBACK';
00565
00566 Status := FPlainDriver.TransRollback(FContextHandle, FErrorHandle,
00567 OCI_DEFAULT);
00568 CheckOracleError(FPlainDriver, FErrorHandle, Status, lcExecute, SQL);
00569
00570 DriverManager.LogMessage(lcExecute, FPlainDriver.GetProtocol, SQL);
00571 end;
00572 end;
00573
00574 {**
00575 Releases a Connection's database and JDBC resources
00576 immediately instead of waiting for
00577 them to be automatically released.
00578
00579 <P><B>Note:</B> A Connection is automatically closed when it is
00580 garbage collected. Certain fatal errors also result in a closed
00581 Connection.
00582 }
00583 procedure TZOracleConnection.Close;
00584 var
00585 Status: Integer;
00586 LogMessage: string;
00587 begin
00588 if not Closed then
00589 begin
00590 LogMessage := Format('DISCONNECT FROM "%s"', [Database]);
00591
00592 { Closes started transaction }
00593 Status := FPlainDriver.TransRollback(FContextHandle, FErrorHandle,
00594 OCI_DEFAULT);
00595 CheckOracleError(FPlainDriver, FErrorHandle, Status, lcDisconnect,
00596 LogMessage);
00597 FPlainDriver.HandleFree(FTransHandle, OCI_HTYPE_TRANS);
00598 FTransHandle := nil;
00599
00600 { Closes the session }
00601 Status := FPlainDriver.SessionEnd(FContextHandle, FErrorHandle,
00602 FSessionHandle, OCI_DEFAULT);
00603 CheckOracleError(FPlainDriver, FErrorHandle, Status, lcDisconnect,
00604 LogMessage);
00605
00606 { Detaches from the server }
00607 Status := FPlainDriver.ServerDetach(FServerHandle, FErrorHandle,
00608 OCI_DEFAULT);
00609 CheckOracleError(FPlainDriver, FErrorHandle, Status, lcDisconnect,
00610 LogMessage);
00611
00612 { Frees all handlers }
00613 FPlainDriver.HandleFree(FSessionHandle, OCI_HTYPE_SESSION);
00614 FSessionHandle := nil;
00615 FPlainDriver.HandleFree(FContextHandle, OCI_HTYPE_SVCCTX);
00616 FContextHandle := nil;
00617 FPlainDriver.HandleFree(FServerHandle, OCI_HTYPE_SERVER);
00618 FServerHandle := nil;
00619 FPlainDriver.HandleFree(FErrorHandle, OCI_HTYPE_ERROR);
00620 FErrorHandle := nil;
00621
00622 DriverManager.LogMessage(lcDisconnect, FPlainDriver.GetProtocol, LogMessage);
00623 end;
00624 inherited Close;
00625 end;
00626
00627 {**
00628 Gets a selected catalog name.
00629 @return a selected catalog name.
00630 }
00631 function TZOracleConnection.GetCatalog: string;
00632 begin
00633 Result := FCatalog;
00634 end;
00635
00636 {**
00637 Sets a new selected catalog name.
00638 @param Catalog a selected catalog name.
00639 }
00640 procedure TZOracleConnection.SetCatalog(const Catalog: string);
00641 begin
00642 FCatalog := Catalog;
00643 end;
00644
00645 {**
00646 Sets a new transact isolation level.
00647 @param Level a new transact isolation level.
00648 }
00649 procedure TZOracleConnection.SetTransactionIsolation(
00650 Level: TZTransactIsolationLevel);
00651 var
00652 Status: Integer;
00653 SQL: PChar;
00654 begin
00655 if TransactIsolationLevel <> Level then
00656 begin
00657 inherited SetTransactionIsolation(Level);
00658
00659 if not Closed then
00660 begin
00661 SQL := 'END TRANSACTION';
00662 Status := FPlainDriver.TransRollback(FContextHandle, FErrorHandle,
00663 OCI_DEFAULT);
00664 CheckOracleError(FPlainDriver, FErrorHandle, Status, lcExecute, SQL);
00665 FPlainDriver.HandleFree(FTransHandle, OCI_HTYPE_TRANS);
00666 FTransHandle := nil;
00667 DriverManager.LogMessage(lcExecute, FPlainDriver.GetProtocol, SQL);
00668
00669 StartTransactionSupport;
00670 end;
00671 end;
00672 end;
00673
00674 {**
00675 Creates a sequence generator object.
00676 @param Sequence a name of the sequence generator.
00677 @param BlockSize a number of unique keys requested in one trip to SQL server.
00678 @returns a created sequence object.
00679 }
00680 function TZOracleConnection.CreateSequence(const Sequence: string; BlockSize: Integer): IZSequence;
00681 begin
00682 Result := TZOracleSequence.Create(Self, Sequence, BlockSize);
00683 end;
00684 {**
00685 Gets a Oracle plain driver interface.
00686 @return a Oracle plain driver interface.
00687 }
00688 function TZOracleConnection.GetPlainDriver: IZOraclePlainDriver;
00689 begin
00690 Result := FPlainDriver;
00691 end;
00692
00693 {**
00694 Gets a reference to Oracle connection handle.
00695 @return a reference to Oracle connection handle.
00696 }
00697 function TZOracleConnection.GetConnectionHandle: POCIEnv;
00698 begin
00699 Result := FHandle;
00700 end;
00701
00702 {**
00703 Gets a reference to Oracle context handle.
00704 @return a reference to Oracle context handle.
00705 }
00706 function TZOracleConnection.GetContextHandle: POCISvcCtx;
00707 begin
00708 Result := FContextHandle;
00709 end;
00710
00711 {**
00712 Gets a reference to Oracle error handle.
00713 @return a reference to Oracle error handle.
00714 }
00715 function TZOracleConnection.GetErrorHandle: POCIError;
00716 begin
00717 Result := FErrorHandle;
00718 end;
00719
00720 {**
00721 Gets a reference to Oracle server handle.
00722 @return a reference to Oracle server handle.
00723 }
00724 function TZOracleConnection.GetServerHandle: POCIServer;
00725 begin
00726 Result := FServerHandle;
00727 end;
00728
00729 {**
00730 Gets a reference to Oracle session handle.
00731 @return a reference to Oracle session handle.
00732 }
00733 function TZOracleConnection.GetSessionHandle: POCISession;
00734 begin
00735 Result := FSessionHandle;
00736 end;
00737
00738 {**
00739 Gets a reference to Oracle transaction handle.
00740 @return a reference to Oracle transacton handle.
00741 }
00742 function TZOracleConnection.GetTransactionHandle: POCITrans;
00743 begin
00744 Result := FTransHandle;
00745 end;
00746
00747 { TZOracleSequence }
00748
00749 {**
00750 Gets the current unique key generated by this sequence.
00751 @param the last generated unique key.
00752 }
00753 function TZOracleSequence.GetCurrentValue: Int64;
00754 var
00755 Statement: IZStatement;
00756 ResultSet: IZResultSet;
00757 begin
00758 Statement := Connection.CreateStatement;
00759 ResultSet := Statement.ExecuteQuery(
00760 Format('SELECT %s.CURRVAL FROM DUAL', [Name]));
00761 if ResultSet.Next then
00762 Result := ResultSet.GetLong(1)
00763 else
00764 Result := inherited GetCurrentValue;
00765 ResultSet.Close;
00766 Statement.Close;
00767 end;
00768
00769 function TZOracleSequence.GetCurrentValueSQL: String;
00770 begin
00771 result:=Format('SELECT %s.CURRVAL FROM DUAL', [Name]);
00772 end;
00773
00774 {**
00775 Gets the next unique key generated by this sequence.
00776 @param the next generated unique key.
00777 }
00778 function TZOracleSequence.GetNextValue: Int64;
00779 var
00780 Statement: IZStatement;
00781 ResultSet: IZResultSet;
00782 begin
00783 Statement := Connection.CreateStatement;
00784 ResultSet := Statement.ExecuteQuery(
00785 Format('SELECT %s.NEXTVAL FROM DUAL', [Name]));
00786 if ResultSet.Next then
00787 Result := ResultSet.GetLong(1)
00788 else
00789 Result := inherited GetNextValue;
00790 ResultSet.Close;
00791 Statement.Close;
00792 end;
00793
00794
00795 function TZOracleSequence.GetNextValueSQL: String;
00796 begin
00797 result:=Format('SELECT %s.NEXTVAL FROM DUAL', [Name]);
00798 end;
00799
00800 { TZOracleCachedResolver }
00801
00802 {**
00803 Forms a where clause for SELECT statements to calculate default values.
00804 @param Columns a collection of key columns.
00805 @param OldRowAccessor an accessor object to old column values.
00806 }
00807 function TZOracleCachedResolver.FormCalculateStatement(
00808 Columns: TObjectList): string;
00809 var iPos: Integer;
00810 begin
00811 Result := inherited FormCalculateStatement(Columns);
00812 if Result <> '' then begin
00813 iPos := pos('FROM', uppercase(Result));
00814 if iPos > 0 then begin
00815 Result := copy(Result, 1, iPos+3) + ' DUAL';
00816 end
00817 else begin
00818 Result := Result + ' FROM DUAL';
00819 end;
00820 end;
00821 end;
00822
00823 initialization
00824 OracleDriver := TZOracleDriver.Create;
00825 DriverManager.RegisterDriver(OracleDriver);
00826 finalization
00827 if DriverManager <> nil then
00828 DriverManager.DeregisterDriver(OracleDriver);
00829 OracleDriver := nil;
00830 end.
00831