00001 {*********************************************************}
00002 { }
00003 { Zeos Database Objects }
00004 { DBLib Connectivity Classes }
00005 { }
00006 { Originally written by Janos Fegyverneki }
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 ZDbcDbLib;
00055
00056 interface
00057
00058 {$I ZDbc.inc}
00059
00060 uses
00061 {$IFNDEF VER130BELOW}
00062 Types,
00063 {$ENDIF}
00064 {$IFDEF VER130BELOW}
00065 {$IFDEF WIN32}
00066 Comobj,
00067 {$ENDIF}
00068 {$ENDIF}
00069 Classes, ZDbcConnection, ZDbcIntfs, ZCompatibility, ZDbcLogging,
00070 ZPlainDbLibDriver, ZTokenizer, ZGenericSqlAnalyser;
00071
00072 type
00073 {** Implements DBLib Database Driver. }
00074 TZDBLibDriver = class(TZAbstractDriver)
00075 private
00076 FMSSqlPlainDriver: IZDBLibPlainDriver;
00077 FSybasePlainDriver: IZDBLibPlainDriver;
00078 public
00079 constructor Create;
00080 function Connect(const Url: string; Info: TStrings): IZConnection; override;
00081
00082 function GetSupportedProtocols: TStringDynArray; override;
00083 function GetMajorVersion: Integer; override;
00084 function GetMinorVersion: Integer; override;
00085
00086 function GetTokenizer: IZTokenizer; override;
00087 function GetStatementAnalyser: IZStatementAnalyser; override;
00088 end;
00089
00090 {** Represents a DBLib specific connection interface. }
00091 IZDBLibConnection = interface (IZConnection)
00092 ['{6B0662A2-FF2A-4415-B6B0-AAC047EA0671}']
00093
00094 function GetPlainDriver: IZDBLibPlainDriver;
00095 function GetConnectionHandle: PDBPROCESS;
00096 procedure InternalExecuteStatement(const SQL: string);
00097 procedure CheckDBLibError(LogCategory: TZLoggingCategory; const LogMessage: string);
00098 end;
00099
00100 {** Implements a generic DBLib Connection. }
00101 TZDBLibConnection = class(TZAbstractConnection, IZDBLibConnection)
00102 private
00103 procedure ReStartTransactionSupport;
00104 procedure InternalSetTransactionIsolation(Level: TZTransactIsolationLevel);
00105 protected
00106 FPlainDriver: IZDBLibPlainDriver;
00107 FHandle: PDBPROCESS;
00108 procedure InternalExecuteStatement(const SQL: string); virtual;
00109 procedure InternalLogin; virtual;
00110 function GetPlainDriver: IZDBLibPlainDriver;
00111 function GetConnectionHandle: PDBPROCESS;
00112 procedure CheckDBLibError(LogCategory: TZLoggingCategory; const LogMessage: string); virtual;
00113 procedure StartTransaction; virtual;
00114 public
00115 constructor Create(Driver: IZDriver; const Url: string;
00116 PlainDriver: IZDBLibPlainDriver; const HostName: string; Port: Integer;
00117 const Database: string; const User: string; const Password: string; Info: TStrings);
00118
00119 destructor Destroy; override;
00120
00121 function CreateRegularStatement(Info: TStrings): IZStatement; override;
00122 function CreatePreparedStatement(const SQL: string; Info: TStrings):
00123 IZPreparedStatement; override;
00124 function CreateCallableStatement(const SQL: string; Info: TStrings):
00125 IZCallableStatement; override;
00126
00127 function NativeSQL(const SQL: string): string; override;
00128
00129 procedure SetAutoCommit(AutoCommit: Boolean); override;
00130 procedure SetTransactionIsolation(Level: TZTransactIsolationLevel); override;
00131
00132 procedure Commit; override;
00133 procedure Rollback; override;
00134
00135 procedure Open; override;
00136 procedure Close; override;
00137
00138 procedure SetReadOnly(ReadOnly: Boolean); override;
00139
00140 procedure SetCatalog(const Catalog: string); override;
00141 function GetCatalog: string; override;
00142
00143 function GetWarnings: EZSQLWarning; override;
00144 procedure ClearWarnings; override;
00145 end;
00146
00147 var
00148 {** The common driver manager object. }
00149 DBLibDriver: IZDriver;
00150
00151 implementation
00152
00153 uses
00154 SysUtils, ZSysUtils, ZMessages, ZDbcUtils, ZDbcDbLibStatement,
00155 ZDbcDbLibMsSqlMetadata, ZSybaseToken, ZSybaseAnalyser,
00156 ZDbcDbLibSybaseMetadata{$IFDEF FPC}, ZClasses{$ENDIF};
00157
00158 { TZDBLibDriver }
00159
00160 {**
00161 Constructs this object with default properties.
00162 }
00163 constructor TZDBLibDriver.Create;
00164 begin
00165 FMSSqlPlainDriver := TZDBLibMSSQL7PlainDriver.Create;
00166 FSybasePlainDriver := TZDBLibSybaseASE125PlainDriver.Create;
00167 end;
00168
00169 {**
00170 Get a name of the supported subprotocol.
00171 }
00172 function TZDBLibDriver.GetSupportedProtocols: TStringDynArray;
00173 begin
00174 SetLength(Result, 2);
00175 Result[0] := FSybasePlainDriver.GetProtocol;
00176 Result[1] := FMSSqlPlainDriver.GetProtocol;
00177 end;
00178
00179 {**
00180 Attempts to make a database connection to the given URL.
00181 }
00182 function TZDBLibDriver.Connect(const Url: string; Info: TStrings): IZConnection;
00183 var
00184 TempInfo: TStrings;
00185 HostName, Database, UserName, Password: string;
00186 Port: Integer;
00187 Protocol: string;
00188 PlainDriver: IZDBLibPlainDriver;
00189 begin
00190 TempInfo := TStringList.Create;
00191 try
00192 ResolveDatabaseUrl(Url, Info, HostName, Port, Database,
00193 UserName, Password, TempInfo);
00194 Protocol := ResolveConnectionProtocol(Url, GetSupportedProtocols);
00195 if Protocol = FMSSqlPlainDriver.GetProtocol then
00196 PlainDriver := FMSSqlPlainDriver;
00197 if Protocol = FSybasePlainDriver.GetProtocol then
00198 PlainDriver := FSybasePlainDriver;
00199 PlainDriver.Initialize;
00200 Result := TZDBLibConnection.Create(Self, Url, PlainDriver, HostName, Port,
00201 Database, UserName, Password, TempInfo);
00202 finally
00203 TempInfo.Free;
00204 end;
00205 end;
00206
00207 {**
00208 Gets the driver's major version number. Initially this should be 1.
00209 @return this driver's major version number
00210 }
00211 function TZDBLibDriver.GetMajorVersion: Integer;
00212 begin
00213 Result := 1;
00214 end;
00215
00216 {**
00217 Gets the driver's minor version number. Initially this should be 0.
00218 @return this driver's minor version number
00219 }
00220 function TZDBLibDriver.GetMinorVersion: Integer;
00221 begin
00222 Result := 0;
00223 end;
00224
00225 {**
00226 Gets a SQL syntax tokenizer.
00227 @returns a SQL syntax tokenizer object.
00228 }
00229 function TZDBLibDriver.GetTokenizer: IZTokenizer;
00230 begin
00231 if Tokenizer = nil then
00232 Tokenizer := TZSybaseTokenizer.Create;
00233 Result := Tokenizer;
00234 end;
00235
00236 {**
00237 Creates a statement analyser object.
00238 @returns a statement analyser object.
00239 }
00240 function TZDBLibDriver.GetStatementAnalyser: IZStatementAnalyser;
00241 begin
00242 if Analyser = nil then
00243 Analyser := TZSybaseStatementAnalyser.Create;
00244 Result := Analyser;
00245 end;
00246
00247 { TZDBLibConnection }
00248
00249 {**
00250 Constructs this object and assignes the main properties.
00251 @param Driver the parent ZDBC driver interface.
00252 @param HostName a name of the host.
00253 @param Port a port number (0 for default port).
00254 @param Database a name pof the database.
00255 @param User a user name.
00256 @param Password a user password.
00257 @param Info a string list with extra connection parameters.
00258 }
00259 constructor TZDBLibConnection.Create(Driver: IZDriver; const Url: string;
00260 PlainDriver: IZDBLibPlainDriver; const HostName: string; Port: Integer;
00261 const Database: string; const User: string; const Password: string; Info: TStrings);
00262 var
00263 Metadata: TContainedObject;
00264 begin
00265 FPlainDriver := PlainDriver;
00266 if FPlainDriver.GetProtocol = 'mssql' then
00267 Metadata := TZMsSqlDatabaseMetadata.Create(Self, Url, Info)
00268 else if FPlainDriver.GetProtocol = 'sybase' then
00269 Metadata := TZSybaseDatabaseMetadata.Create(Self, Url, Info)
00270 else Metadata := nil;
00271
00272 inherited Create(Driver, Url, HostName, Port, Database, User, Password, Info,
00273 Metadata);
00274
00275 FHandle := nil;
00276 end;
00277
00278 {**
00279 Destroys this object and cleanups the memory.
00280 }
00281 destructor TZDBLibConnection.Destroy;
00282 begin
00283 Close;
00284 inherited Destroy;
00285 end;
00286
00287 {**
00288 Executes simple statements internally.
00289 }
00290 procedure TZDBLibConnection.InternalExecuteStatement(const SQL: string);
00291 var
00292 LSQL: string;
00293 begin
00294 FHandle := GetConnectionHandle;
00295 if FPlainDriver.dbCancel(FHandle) <> DBSUCCEED then
00296 CheckDBLibError(lcExecute, SQL);
00297 if FPlainDriver.GetProtocol = 'mssql' then
00298 LSQL := StringReplace(Sql, '\'#13, '\\'#13, [rfReplaceAll])
00299 else
00300 LSQL := SQL;
00301 if FPlainDriver.dbcmd(FHandle, PChar(LSql)) <> DBSUCCEED then
00302 CheckDBLibError(lcExecute, LSQL);
00303 if FPlainDriver.dbsqlexec(FHandle) <> DBSUCCEED then
00304 CheckDBLibError(lcExecute, LSQL);
00305 repeat
00306 FPlainDriver.dbresults(FHandle);
00307 FPlainDriver.dbcanquery(FHandle);
00308 until FPlainDriver.dbmorecmds(FHandle) = DBFAIL;
00309 CheckDBLibError(lcExecute, LSQL);
00310 DriverManager.LogMessage(lcExecute, FPlainDriver.GetProtocol, LSQL);
00311 end;
00312
00313 {**
00314 Login procedure can be overriden for special settings.
00315 }
00316 procedure TZDBLibConnection.InternalLogin;
00317 var
00318 Loginrec: PLOGINREC;
00319 LogMessage: string;
00320 S: string;
00321 begin
00322 LogMessage := Format('CONNECT TO "%s"', [HostName]);
00323 LoginRec := FPLainDriver.dbLogin;
00324 try
00325
00326 S := Info.Values['workstation'];
00327 if S <> '' then
00328 FPlainDriver.dbSetLHost(LoginRec, PChar(S));
00329
00330 S := Info.Values['appname'];
00331 if S <> '' then
00332 FPlainDriver.dbSetLApp(LoginRec, PChar(S));
00333
00334 S := Info.Values['language'];
00335 if S <> '' then
00336 FPlainDriver.dbSetLNatLang(LoginRec, PChar(S));
00337
00338 S := Info.Values['timeout'];
00339 if S <> '' then
00340 FPlainDriver.dbSetLoginTime(StrToIntDef(S, 60));
00341
00342
00343 if FPlainDriver.GetProtocol = 'mssql' then
00344 begin
00345 if StrToBoolEx(Info.Values['NTAuth']) or StrToBoolEx(Info.Values['trusted'])
00346 or StrToBoolEx(Info.Values['secure']) then
00347 begin
00348 FPLainDriver.dbsetlsecure(LoginRec);
00349 LogMessage := LogMessage + ' USING WINDOWS AUTHENTICATION';
00350 end
00351 else
00352 begin
00353 FPLainDriver.dbsetluser(LoginRec, PChar(User));
00354 FPLainDriver.dbsetlpwd(LoginRec, PChar(Password));
00355 LogMessage := LogMessage + Format(' AS USER "%s"', [User]);
00356 end;
00357 end;
00358
00359
00360 if FPlainDriver.GetProtocol = 'sybase' then
00361 begin
00362 S := Info.Values['codepage'];
00363 if S <> '' then
00364 FPlainDriver.dbSetLCharSet(LoginRec, PChar(S));
00365
00366 FPLainDriver.dbsetluser(LoginRec, PChar(User));
00367 FPLainDriver.dbsetlpwd(LoginRec, PChar(Password));
00368 LogMessage := LogMessage + Format(' AS USER "%s"', [User]);
00369 end;
00370
00371 CheckDBLibError(lcConnect, LogMessage);
00372
00373 FHandle := FPLainDriver.dbOpen(LoginRec, PChar(HostName));
00374 CheckDBLibError(lcConnect, LogMessage);
00375 DriverManager.LogMessage(lcConnect, FPlainDriver.GetProtocol, LogMessage);
00376 finally
00377 FPLainDriver.dbLoginFree(LoginRec);
00378 end;
00379 end;
00380
00381 function TZDBLibConnection.GetPlainDriver: IZDBLibPlainDriver;
00382 begin
00383 Result := FPlainDriver;
00384 end;
00385
00386 function TZDBLibConnection.GetConnectionHandle: PDBPROCESS;
00387 begin
00388 if FPlainDriver.GetProtocol = 'mssql' then
00389 if FPlainDriver.dbDead(FHandle) then
00390 begin
00391
00392 Closed := True;
00393 Open;
00394 end;
00395 Result := FHandle;
00396 end;
00397
00398 procedure TZDBLibConnection.CheckDBLibError(LogCategory: TZLoggingCategory; const LogMessage: string);
00399 begin
00400 try
00401 FPlainDriver.CheckError;
00402 except
00403 on E: Exception do
00404 begin
00405 DriverManager.LogError(LogCategory, FPlainDriver.GetProtocol, LogMessage, 0, E.Message);
00406 raise;
00407 end;
00408 end;
00409 end;
00410
00411 {**
00412 Starts a transaction support.
00413 }
00414 procedure TZDBLibConnection.ReStartTransactionSupport;
00415 begin
00416 if Closed then Exit;
00417
00418 if not (AutoCommit or (GetTransactionIsolation = tiNone)) then
00419 StartTransaction;
00420 end;
00421
00422 {**
00423 Opens a connection to database server with specified parameters.
00424 }
00425 procedure TZDBLibConnection.Open;
00426 var
00427 LogMessage: string;
00428 begin
00429 if not Closed then Exit;
00430
00431 InternalLogin;
00432
00433 LogMessage := Format('USE %s', [Database]);
00434 if FPlainDriver.dbUse(FHandle, PChar(Database)) <> DBSUCCEED then
00435 CheckDBLibError(lcConnect, LogMessage);
00436 DriverManager.LogMessage(lcConnect, FPlainDriver.GetProtocol, LogMessage);
00437
00438 LogMessage := 'set textlimit=2147483647';
00439 if FPlainDriver.dbsetopt(FHandle, DBTEXTLIMIT, '2147483647') <> DBSUCCEED then
00440 CheckDBLibError(lcConnect, LogMessage);
00441 DriverManager.LogMessage(lcConnect, FPlainDriver.GetProtocol, LogMessage);
00442
00443 InternalExecuteStatement('set textsize 2147483647 set quoted_identifier on');
00444
00445 inherited Open;
00446
00447 InternalSetTransactionIsolation(GetTransactionIsolation);
00448 ReStartTransactionSupport;
00449 end;
00450
00451 {**
00452 Creates a <code>Statement</code> object for sending
00453 SQL statements to the database.
00454 SQL statements without parameters are normally
00455 executed using Statement objects. If the same SQL statement
00456 is executed many times, it is more efficient to use a
00457 <code>PreparedStatement</code> object.
00458 <P>
00459 Result sets created using the returned <code>Statement</code>
00460 object will by default have forward-only type and read-only concurrency.
00461
00462 @return a new Statement object
00463 }
00464 function TZDBLibConnection.CreateRegularStatement(Info: TStrings):
00465 IZStatement;
00466 begin
00467 if IsClosed then Open;
00468 Result := TZDBLibStatement.Create(Self, Info);
00469 end;
00470
00471 {**
00472 Creates a <code>PreparedStatement</code> object for sending
00473 parameterized SQL statements to the database.
00474
00475 A SQL statement with or without IN parameters can be
00476 pre-compiled and stored in a PreparedStatement object. This
00477 object can then be used to efficiently execute this statement
00478 multiple times.
00479
00480 <P><B>Note:</B> This method is optimized for handling
00481 parametric SQL statements that benefit from precompilation. If
00482 the driver supports precompilation,
00483 the method <code>prepareStatement</code> will send
00484 the statement to the database for precompilation. Some drivers
00485 may not support precompilation. In this case, the statement may
00486 not be sent to the database until the <code>PreparedStatement</code> is
00487 executed. This has no direct effect on users; however, it does
00488 affect which method throws certain SQLExceptions.
00489
00490 Result sets created using the returned PreparedStatement will have
00491 forward-only type and read-only concurrency, by default.
00492
00493 @param sql a SQL statement that may contain one or more '?' IN
00494 parameter placeholders
00495 @param Info a statement parameters.
00496 @return a new PreparedStatement object containing the
00497 pre-compiled statement
00498 }
00499 function TZDBLibConnection.CreatePreparedStatement(
00500 const SQL: string; Info: TStrings): IZPreparedStatement;
00501 begin
00502 if IsClosed then Open;
00503 Result := TZDBLibPreparedStatementEmulated.Create(Self, SQL, Info);
00504 end;
00505
00506 {**
00507 Creates a <code>CallableStatement</code> object for calling
00508 database stored procedures.
00509 The <code>CallableStatement</code> object provides
00510 methods for setting up its IN and OUT parameters, and
00511 methods for executing the call to a stored procedure.
00512
00513 <P><B>Note:</B> This method is optimized for handling stored
00514 procedure call statements. Some drivers may send the call
00515 statement to the database when the method <code>prepareCall</code>
00516 is done; others
00517 may wait until the <code>CallableStatement</code> object
00518 is executed. This has no
00519 direct effect on users; however, it does affect which method
00520 throws certain SQLExceptions.
00521
00522 Result sets created using the returned CallableStatement will have
00523 forward-only type and read-only concurrency, by default.
00524
00525 @param sql a SQL statement that may contain one or more '?'
00526 parameter placeholders. Typically this statement is a JDBC
00527 function call escape string.
00528 @param Info a statement parameters.
00529 @return a new CallableStatement object containing the
00530 pre-compiled SQL statement
00531 }
00532 function TZDBLibConnection.CreateCallableStatement(
00533 const SQL: string; Info: TStrings): IZCallableStatement;
00534 begin
00535 if IsClosed then Open;
00536 Result := TZDBLibCallableStatement.Create(Self, SQL, Info);
00537 end;
00538
00539 {**
00540 Converts the given SQL statement into the system's native SQL grammar.
00541 A driver may convert the JDBC sql grammar into its system's
00542 native SQL grammar prior to sending it; this method returns the
00543 native form of the statement that the driver would have sent.
00544
00545 @param sql a SQL statement that may contain one or more '?'
00546 parameter placeholders
00547 @return the native form of this statement
00548 }
00549 function TZDBLibConnection.NativeSQL(const SQL: string): string;
00550 begin
00551 Result := SQL;
00552 end;
00553
00554 {**
00555 Sets this connection's auto-commit mode.
00556 If a connection is in auto-commit mode, then all its SQL
00557 statements will be executed and committed as individual
00558 transactions. Otherwise, its SQL statements are grouped into
00559 transactions that are terminated by a call to either
00560 the method <code>commit</code> or the method <code>rollback</code>.
00561 By default, new connections are in auto-commit mode.
00562
00563 The commit occurs when the statement completes or the next
00564 execute occurs, whichever comes first. In the case of
00565 statements returning a ResultSet, the statement completes when
00566 the last row of the ResultSet has been retrieved or the
00567 ResultSet has been closed. In advanced cases, a single
00568 statement may return multiple results as well as output
00569 parameter values. In these cases the commit occurs when all results and
00570 output parameter values have been retrieved.
00571
00572 @param autoCommit true enables auto-commit; false disables auto-commit.
00573 }
00574 procedure TZDBLibConnection.SetAutoCommit(AutoCommit: Boolean);
00575 begin
00576 if GetAutoCommit = AutoCommit then Exit;
00577 if not Closed and AutoCommit then InternalExecuteStatement('commit');
00578 inherited;
00579 ReStartTransactionSupport;
00580 end;
00581
00582 procedure TZDBLibConnection.InternalSetTransactionIsolation(Level: TZTransactIsolationLevel);
00583 const
00584 IL: array[TZTransactIsolationLevel, 0..1] of string = (('READ COMMITTED', '1'), ('READ UNCOMMITTED', '0'), ('READ COMMITTED', '1'), ('REPEATABLE READ', '2'), ('SERIALIZABLE', '3'));
00585 var
00586 Index: Integer;
00587 S: string;
00588 begin
00589 Index := -1;
00590 if FPlainDriver.GetProtocol = 'mssql' then Index := 0;
00591 if FPlainDriver.GetProtocol = 'sybase' then Index := 1;
00592
00593 S := 'SET TRANSACTION ISOLATION LEVEL ' + IL[GetTransactionIsolation, Index];
00594 InternalExecuteStatement(S);
00595 end;
00596
00597 {**
00598 Attempts to change the transaction isolation level to the one given.
00599 The constants defined in the interface <code>Connection</code>
00600 are the possible transaction isolation levels.
00601
00602 <P><B>Note:</B> This method cannot be called while
00603 in the middle of a transaction.
00604
00605 @param level one of the TRANSACTION_* isolation values with the
00606 exception of TRANSACTION_NONE; some databases may not support other values
00607 @see DatabaseMetaData#supportsTransactionIsolationLevel
00608 }
00609 procedure TZDBLibConnection.SetTransactionIsolation(
00610 Level: TZTransactIsolationLevel);
00611 begin
00612 if GetTransactionIsolation = Level then Exit;
00613
00614 if not Closed and not AutoCommit and (GetTransactionIsolation <> tiNone) then
00615 InternalExecuteStatement('commit');
00616
00617 inherited;
00618
00619 if not Closed then
00620 InternalSetTransactionIsolation(Level);
00621
00622 RestartTransactionSupport;
00623 end;
00624
00625 {**
00626 Starts a new transaction. Used internally.
00627 }
00628 procedure TZDBLibConnection.StartTransaction;
00629 begin
00630 InternalExecuteStatement('begin transaction');
00631 end;
00632
00633 {**
00634 Makes all changes made since the previous
00635 commit/rollback permanent and releases any database locks
00636 currently held by the Connection. This method should be
00637 used only when auto-commit mode has been disabled.
00638 @see #setAutoCommit
00639 }
00640 procedure TZDBLibConnection.Commit;
00641 begin
00642 if AutoCommit then
00643 raise Exception.Create(SCannotUseCommit);
00644 InternalExecuteStatement('commit');
00645 StartTransaction;
00646 end;
00647
00648 {**
00649 Drops all changes made since the previous
00650 commit/rollback and releases any database locks currently held
00651 by this Connection. This method should be used only when auto-
00652 commit has been disabled.
00653 @see #setAutoCommit
00654 }
00655 procedure TZDBLibConnection.Rollback;
00656 begin
00657 if AutoCommit then
00658 raise Exception.Create(SCannotUseRollBack);
00659 InternalExecuteStatement('rollback');
00660 StartTransaction;
00661 end;
00662
00663 {**
00664 Releases a Connection's database and JDBC resources
00665 immediately instead of waiting for
00666 them to be automatically released.
00667
00668 <P><B>Note:</B> A Connection is automatically closed when it is
00669 garbage collected. Certain fatal errors also result in a closed
00670 Connection.
00671 }
00672 procedure TZDBLibConnection.Close;
00673 var
00674 LogMessage: string;
00675 begin
00676 if Closed then Exit;
00677
00678 if not FPlainDriver.dbDead(FHandle) then
00679 InternalExecuteStatement('if @@trancount > 0 rollback');
00680
00681 LogMessage := Format('CLOSE CONNECTION TO "%s" DATABASE "%s"', [HostName, Database]);
00682 if FPlainDriver.dbclose(FHandle) <> DBSUCCEED then
00683 CheckDBLibError(lcDisConnect, LogMessage);
00684 DriverManager.LogMessage(lcDisconnect, FPlainDriver.GetProtocol, LogMessage);
00685
00686 FHandle := nil;
00687 inherited;
00688 end;
00689
00690 {**
00691 Puts this connection in read-only mode as a hint to enable
00692 database optimizations.
00693
00694 <P><B>Note:</B> This method cannot be called while in the
00695 middle of a transaction.
00696
00697 @param readOnly true enables read-only mode; false disables
00698 read-only mode.
00699 }
00700 procedure TZDBLibConnection.SetReadOnly(ReadOnly: Boolean);
00701 begin
00702 { TODO -ofjanos -cAPI : I think it is not supported in this way }
00703 inherited;
00704 end;
00705
00706 {**
00707 Sets a catalog name in order to select
00708 a subspace of this Connection's database in which to work.
00709 If the driver does not support catalogs, it will
00710 silently ignore this request.
00711 }
00712 procedure TZDBLibConnection.SetCatalog(const Catalog: string);
00713 var
00714 LogMessage: string;
00715 begin
00716 if (Catalog <> '') and not Closed then
00717 begin
00718 LogMessage := Format('SET CATALOG %s', [Catalog]);
00719 if FPLainDriver.dbUse(FHandle, PChar(Catalog)) <> DBSUCCEED then
00720 CheckDBLibError(lcOther, LogMessage);
00721 DriverManager.LogMessage(lcOther, FPLainDriver.GetProtocol, LogMessage);
00722 end;
00723 end;
00724
00725 {**
00726 Returns the Connection's current catalog name.
00727 @return the current catalog name or null
00728 }
00729 function TZDBLibConnection.GetCatalog: string;
00730 begin
00731 Result := FPlainDriver.dbName(FHandle);
00732 CheckDBLibError(lcOther, 'GETCATALOG');
00733 end;
00734
00735 {**
00736 Returns the first warning reported by calls on this Connection.
00737 <P><B>Note:</B> Subsequent warnings will be chained to this
00738 SQLWarning.
00739 @return the first SQLWarning or null
00740 }
00741 function TZDBLibConnection.GetWarnings: EZSQLWarning;
00742 begin
00743 Result := nil;
00744 end;
00745
00746 {**
00747 Clears all warnings reported for this <code>Connection</code> object.
00748 After a call to this method, the method <code>getWarnings</code>
00749 returns null until a new warning is reported for this Connection.
00750 }
00751 procedure TZDBLibConnection.ClearWarnings;
00752 begin
00753 end;
00754
00755 initialization
00756 DBLibDriver := TZDBLibDriver.Create;
00757 DriverManager.RegisterDriver(DBLibDriver);
00758 finalization
00759 if Assigned(DriverManager) then
00760 DriverManager.DeregisterDriver(DBLibDriver);
00761 DBLibDriver := nil;
00762 end.