1 {*********************************************************}
3 { Zeos Database Objects }
4 { Interbase Database Connectivity Classes }
6 { Originally written by Sergey Merkuriev }
8 {*********************************************************}
10 {@********************************************************}
11 { Copyright (c) 1999-2012 Zeos Development Group }
13 { License Agreement: }
15 { This library is distributed in the hope that it will be }
16 { useful, but WITHOUT ANY WARRANTY; without even the }
17 { implied warranty of MERCHANTABILITY or FITNESS FOR }
18 { A PARTICULAR PURPOSE. See the GNU Lesser General }
19 { Public License for more details. }
21 { The source code of the ZEOS Libraries and packages are }
22 { distributed under the Library GNU General Public }
23 { License (see the file COPYING / COPYING.ZEOS) }
24 { with the following modification: }
25 { As a special exception, the copyright holders of this }
26 { library give you permission to link this library with }
27 { independent modules to produce an executable, }
28 { regardless of the license terms of these independent }
29 { modules, and to copy and distribute the resulting }
30 { executable under terms of your choice, provided that }
31 { you also meet, for each linked independent module, }
32 { the terms and conditions of the license of that module. }
33 { An independent module is a module which is not derived }
34 { from or based on this library. If you modify this }
35 { library, you may extend this exception to your version }
36 { of the library, but you are not obligated to do so. }
37 { If you do not wish to do so, delete this exception }
38 { statement from your version. }
41 { The project web site is located on: }
42 { http://zeos.firmos.at (FORUM) }
43 { http://sourceforge.net/p/zeoslib/tickets/ (BUGTRACKER)}
44 { svn://svn.code.sf.net/p/zeoslib/code-0/trunk (SVN) }
46 { http://www.sourceforge.net/projects/zeoslib. }
49 { Zeos Development Group. }
50 {********************************************************@}
52 unit ZDbcASAStatement;
58 uses Classes, {$IFDEF MSEgui}mclasses,{$ENDIF} SysUtils,
59 ZDbcIntfs, ZDbcStatement, ZDbcASA, ZDbcASAUtils, ZDbcASAResultSet,
60 ZPlainASADriver, ZCompatibility, ZDbcLogging, ZVariant, ZMessages;
64 {** Implements Generic ASA Statement. }
65 TZASAStatement = class(TZAbstractStatement)
69 FASAConnection: IZASAConnection;
71 FMoreResults: Boolean;
72 function InternalExecuteQuery(const SQL: RawByteString): IZResultSet;
74 constructor Create(Connection: IZConnection; Info: TStrings);
75 destructor Destroy; override;
77 procedure Close; override;
78 procedure Cancel; override;
79 function GetWarnings: EZSQLWarning; override;
80 procedure ClearWarnings; override;
81 function GetMoreResults: Boolean; override;
82 function ExecuteQuery(const SQL: RawByteString): IZResultSet; override;
83 function ExecuteUpdate(const SQL: RawByteString): Integer; override;
84 function Execute(const SQL: RawByteString): Boolean; override;
87 {** Implements Prepared SQL Statement. }
88 TZASAPreparedStatement = class(TZAbstractPreparedStatement)
92 FASAConnection: IZASAConnection;
93 FParamSQLData: IZASASQLDA;
95 FMoreResults: Boolean;
98 constructor Create(Connection: IZConnection; const SQL: string; Info: TStrings);
99 destructor Destroy; override;
101 procedure Close; override;
102 procedure Cancel; override;
103 function GetWarnings: EZSQLWarning; override;
104 procedure ClearWarnings; override;
105 function GetMoreResults: Boolean; override;
106 function ExecuteQuery(const SQL: RawByteString): IZResultSet; override;
107 function ExecuteUpdate(const SQL: RawByteString): Integer; override;
108 function Execute(const SQL: RawByteString): Boolean; override;
110 function ExecuteQueryPrepared: IZResultSet; override;
111 function ExecuteUpdatePrepared: Integer; override;
112 function ExecutePrepared: Boolean; override;
115 TZASACallableStatement = class(TZAbstractCallableStatement)
117 FCachedBlob: boolean;
119 FASAConnection: IZASAConnection;
120 FParamSQLData: IZASASQLDA;
121 FSQLData: IZASASQLDA;
122 FMoreResults: Boolean;
125 procedure FetchOutParams( Value: IZASASQLDA);
126 function GetProcedureSQL: RawByteString;
128 constructor Create(Connection: IZConnection; const SQL: string; Info: TStrings);
129 destructor Destroy; override;
131 procedure Close; override;
132 procedure Cancel; override;
133 function GetWarnings: EZSQLWarning; override;
134 procedure ClearWarnings; override;
135 function GetMoreResults: Boolean; override;
136 function ExecuteQuery(const SQL: RawByteString): IZResultSet; override;
137 function ExecuteUpdate(const SQL: RawByteString): Integer; override;
138 function Execute(const SQL: RawByteString): Boolean; override;
140 function ExecuteQueryPrepared: IZResultSet; override;
141 function ExecuteUpdatePrepared: Integer; override;
142 function ExecutePrepared: Boolean; override;
147 uses ZSysUtils, ZDbcUtils, ZPlainASAConstants;
151 function TZASAStatement.InternalExecuteQuery(const SQL: RawByteString): IZResultSet;
154 CursorOptions: SmallInt;
157 with FASAConnection do
160 GetPlainDriver.db_prepare_describe( GetDBHandle, nil, @FStmtNum,
161 PAnsiChar(ASQL), FSQLData.GetData, SQL_PREPARE_DESCRIBE_STMTNUM +
162 SQL_PREPARE_DESCRIBE_OUTPUT + SQL_PREPARE_DESCRIBE_VARRESULT, 0);
163 ZDbcASAUtils.CheckASAError(GetPlainDriver, GetDBHandle, lcExecute, LogSQL);
165 FMoreResults := GetDBHandle.sqlerrd[2] = 0;
166 if not FMoreResults then
168 if FSQLData.GetData^.sqld <= 0 then
174 if ( FSQLData.GetData^.sqld > FSQLData.GetData^.sqln) then
176 FSQLData.AllocateSQLDA( FSQLData.GetData^.sqld);
177 GetPlainDriver.db_describe( GetDBHandle, nil, @FStmtNum,
178 FSQLData.GetData, SQL_DESCRIBE_OUTPUT);
179 ZDbcASAUtils.CheckASAError( GetPlainDriver, GetDBHandle, lcExecute, LogSQL);
183 if ResultSetConcurrency = rcUpdatable then
184 CursorOptions := CUR_OPEN_DECLARE + CUR_UPDATE
186 CursorOptions := CUR_OPEN_DECLARE + CUR_READONLY;
187 if ResultSetType = rtScrollInsensitive then
188 CursorOptions := CursorOptions + CUR_INSENSITIVE;
189 Cursor := CursorName;
190 GetPlainDriver.db_open(GetDBHandle, PAnsiChar(Cursor), nil, @FStmtNum,
191 nil, FetchSize, 0, CursorOptions);
192 ZDbcASAUtils.CheckASAError( GetPlainDriver, GetDBHandle, lcExecute, LogSQL);
195 DescribeCursor( FASAConnection, FSQLData, Cursor, LogSQL);
197 LastUpdateCount := -1;
198 Result := GetCachedResultSet( LogSQL, Self,
199 TZASAResultSet.Create( Self, LogSQL, FStmtNum, Cursor, FSQLData, nil,
201 { Logging SQL Command }
202 DriverManager.LogMessage( lcExecute, GetPlainDriver.GetProtocol, LogSQL);
213 Constructs this object and assignes the main properties.
214 @param Connection a database connection object.
215 @param Handle a connection handle pointer.
216 @param Dialect a dialect Interbase SQL must be 1 or 2 or 3.
217 @param Info a statement parameters.
219 constructor TZASAStatement.Create(Connection: IZConnection;
222 inherited Create(Connection, Info);
224 FASAConnection := Connection as IZASAConnection;
225 FetchSize := BlockSize;
226 ResultSetConcurrency := rcUpdatable;
227 ResultSetType := rtScrollSensitive;
228 FCachedBlob := StrToBoolEx(DefineStatementParameter(Self, 'cashedblob', 'true'));
229 CursorName := AnsiString(RandomString(12));
230 FSQLData := TZASASQLDA.Create( FASAConnection.GetPlainDriver,
231 FASAConnection.GetDBHandle, CursorName, ConSettings);
234 destructor TZASAStatement.Destroy;
240 procedure TZASAStatement.Close;
244 FASAConnection.GetPlainDriver.db_close(FASAConnection.GetDBHandle, PAnsiChar(CursorName));
247 if FStmtNum <> 0 then
249 FASAConnection.GetPlainDriver.db_dropstmt( FASAConnection.GetDBHandle, nil,
256 procedure TZASAStatement.Cancel;
258 with FASAConnection do
260 GetPlainDriver.db_cancel_request( GetDBHandle);
261 ZDbcASAUtils.CheckASAError( GetPlainDriver, GetDBHandle, lcExecute);
265 function TZASAStatement.GetWarnings: EZSQLWarning;
267 Result := inherited GetWarnings;
270 procedure TZASAStatement.ClearWarnings;
275 function TZASAStatement.GetMoreResults: Boolean;
279 Result := FMoreResults;
282 with FASAConnection do
284 GetPlainDriver.db_resume(GetDBHandle, PAnsiChar(CursorName));
285 ZDbcASAUtils.CheckASAError( GetPlainDriver, GetDBHandle, lcExecute);
286 if GetDBHandle.sqlcode = SQLE_PROCEDURE_COMPLETE then
290 SQLData := TZASAResultSet(LastResultSet).SQLData;
291 DescribeCursor( FASAConnection, TZASASQLDA( SQLData), CursorName, '');
298 Executes an SQL statement that returns a single <code>ResultSet</code> object.
299 @param sql typically this is a static SQL <code>SELECT</code> statement
300 @return a <code>ResultSet</code> object that contains the data produced by the
301 given query; never <code>null</code>
303 function TZASAStatement.ExecuteQuery(const SQL: RawByteString): IZResultSet;
306 Result := InternalExecuteQuery(ASQL);
308 raise EZSQLException.Create( SCanNotRetrieveResultSetData)
312 Executes an SQL <code>INSERT</code>, <code>UPDATE</code> or
313 <code>DELETE</code> statement. In addition,
314 SQL statements that return nothing, such as SQL DDL statements,
317 @param sql an SQL <code>INSERT</code>, <code>UPDATE</code> or
318 <code>DELETE</code> statement or an SQL statement that returns nothing
319 @return either the row count for <code>INSERT</code>, <code>UPDATE</code>
320 or <code>DELETE</code> statements, or 0 for SQL statements that return nothing
323 function TZASAStatement.ExecuteUpdate(const SQL: RawByteString): Integer;
328 with FASAConnection do
330 GetPlainDriver.db_execute_imm(GetDBHandle, PAnsiChar(ASQL));
331 ZDbcASAUtils.CheckASAError( GetPlainDriver, GetDBHandle, lcExecute, LogSQL);
333 Result := GetDBHandle.sqlErrd[2];
334 LastUpdateCount := Result;
336 { Logging SQL Command }
337 DriverManager.LogMessage(lcExecute, GetPlainDriver.GetProtocol, LogSQL);
343 Executes an SQL statement that may return multiple results.
344 Under some (uncommon) situations a single SQL statement may return
345 multiple result sets and/or update counts. Normally you can ignore
346 this unless you are (1) executing a stored procedure that you know may
347 return multiple results or (2) you are dynamically executing an
348 unknown SQL string. The methods <code>execute</code>,
349 <code>getMoreResults</code>, <code>getResultSet</code>,
350 and <code>getUpdateCount</code> let you navigate through multiple results.
352 The <code>execute</code> method executes an SQL statement and indicates the
353 form of the first result. You can then use the methods
354 <code>getResultSet</code> or <code>getUpdateCount</code>
355 to retrieve the result, and <code>getMoreResults</code> to
356 move to any subsequent result(s).
358 @param sql any SQL statement
359 @return <code>true</code> if the next result is a <code>ResultSet</code> object;
360 <code>false</code> if it is an update count or there are no more results
365 function TZASAStatement.Execute(const SQL: RawByteString): Boolean;
368 LastResultSet := InternalExecuteQuery(ASQL);
369 Result := Assigned(LastResultSet);
374 { TZASAPreparedStatement }
377 Constructs this object and assignes the main properties.
378 @param Connection a database connection object.
379 @param Handle a connection handle pointer.
380 @param Dialect a dialect Interbase SQL must be 1 or 2 or 3.
381 @param Info a statement parameters.
383 constructor TZASAPreparedStatement.Create(Connection: IZConnection;
384 const SQL: string; Info: TStrings);
386 inherited Create(Connection, SQL, Info);
388 FASAConnection := Connection as IZASAConnection;
389 FetchSize := BlockSize;
390 ResultSetConcurrency := rcUpdatable;
391 ResultSetType := rtScrollSensitive;
392 FCachedBlob := StrToBoolEx(DefineStatementParameter(Self, 'cashedblob', 'true'));
393 CursorName := AnsiString(RandomString(12));
394 FParamSQLData := TZASASQLDA.Create( FASAConnection.GetPlainDriver,
395 FASAConnection.GetDBHandle, CursorName, ConSettings);
396 FSQLData := TZASASQLDA.Create( FASAConnection.GetPlainDriver,
397 FASAConnection.GetDBHandle, CursorName, ConSettings);
398 ASAPrepare( FASAConnection, FSQLData, FParamSQLData, ASQL, LogSQL, @FStmtNum, FPrepared,
402 destructor TZASAPreparedStatement.Destroy;
405 FParamSQLData := nil;
409 procedure TZASAPreparedStatement.Close;
413 FASAConnection.GetPlainDriver.db_close( FASAConnection.GetDBHandle, PAnsiChar(CursorName));
416 if FStmtNum <> 0 then
418 FASAConnection.GetPlainDriver.db_dropstmt( FASAConnection.GetDBHandle, nil, nil, @FStmtNum);
424 procedure TZASAPreparedStatement.Cancel;
426 with FASAConnection do
428 GetPlainDriver.db_cancel_request( GetDBHandle);
429 ZDbcASAUtils.CheckASAError( GetPlainDriver, GetDBHandle, lcExecute, SQL);
433 function TZASAPreparedStatement.GetWarnings: EZSQLWarning;
435 Result := inherited GetWarnings;
438 procedure TZASAPreparedStatement.ClearWarnings;
443 function TZASAPreparedStatement.GetMoreResults: Boolean;
445 Result := FMoreResults;
448 with FASAConnection do
450 GetPlainDriver.db_resume(GetDBHandle, PAnsiChar(CursorName));
451 ZDbcASAUtils.CheckASAError( GetPlainDriver, GetDBHandle, lcExecute);
452 if GetDBHandle.sqlcode = SQLE_PROCEDURE_COMPLETE then
455 DescribeCursor( FASAConnection, TZASASQLDA( FSQLData), CursorName, '');
461 Executes an SQL statement that may return multiple results.
462 Under some (uncommon) situations a single SQL statement may return
463 multiple result sets and/or update counts. Normally you can ignore
464 this unless you are (1) executing a stored procedure that you know may
465 return multiple results or (2) you are dynamically executing an
466 unknown SQL string. The methods <code>execute</code>,
467 <code>getMoreResults</code>, <code>getResultSet</code>,
468 and <code>getUpdateCount</code> let you navigate through multiple results.
470 The <code>execute</code> method executes an SQL statement and indicates the
471 form of the first result. You can then use the methods
472 <code>getResultSet</code> or <code>getUpdateCount</code>
473 to retrieve the result, and <code>getMoreResults</code> to
474 move to any subsequent result(s).
476 @param sql any SQL statement
477 @return <code>true</code> if the next result is a <code>ResultSet</code> object;
478 <code>false</code> if it is an update count or there are no more results
484 function TZASAPreparedStatement.Execute(const SQL: RawByteString): Boolean;
490 ASAPrepare( FASAConnection, FSQLData, FParamSQLData, ASQL, LogSQL, @FStmtNum, FPrepared,
493 Result := ExecutePrepared;
497 Executes any kind of SQL statement.
498 Some prepared statements return multiple results; the <code>execute</code>
499 method handles these complex statements as well as the simpler
500 form of statements handled by the methods <code>executeQuery</code>
501 and <code>executeUpdate</code>.
502 @see Statement#execute
504 function TZASAPreparedStatement.ExecutePrepared: Boolean;
506 if FMoreResults or ( FSQLData.GetData.sqld > 0) then
508 LastResultSet := ExecuteQueryPrepared;
513 ExecuteUpdatePrepared;
519 Executes an SQL statement that returns a single <code>ResultSet</code> object.
520 @param sql typically this is a static SQL <code>SELECT</code> statement
521 @return a <code>ResultSet</code> object that contains the data produced by the
522 given query; never <code>null</code>
524 function TZASAPreparedStatement.ExecuteQuery(const SQL: RawByteString): IZResultSet;
530 ASAPrepare( FASAConnection, FSQLData, FParamSQLData, ASQL, LogSQL, @FStmtNum,
531 FPrepared, FMoreResults);
533 Result := ExecuteQueryPrepared;
537 Executes the SQL query in this <code>PreparedStatement</code> object
538 and returns the result set generated by the query.
540 @return a <code>ResultSet</code> object that contains the data produced by the
541 query; never <code>null</code>
544 function TZASAPreparedStatement.ExecuteQueryPrepared: IZResultSet;
547 CursorOptions: SmallInt;
549 with FASAConnection do
551 PrepareParameters( GetPlainDriver, InParamValues, InParamTypes,
552 InParamCount, FParamSQLData, FASAConnection.GetConSettings);
553 if ResultSetConcurrency = rcUpdatable then
554 CursorOptions := CUR_OPEN_DECLARE + CUR_UPDATE
556 CursorOptions := CUR_OPEN_DECLARE + CUR_READONLY;
557 if ResultSetType = rtScrollInsensitive then
558 CursorOptions := CursorOptions + CUR_INSENSITIVE;
559 Cursor := CursorName;
560 GetPlainDriver.db_open(GetDBHandle, PAnsiChar(Cursor), nil, @FStmtNum,
561 FParamSQLData.GetData, FetchSize, 0, CursorOptions);
562 ZDbcASAUtils.CheckASAError( GetPlainDriver, GetDBHandle, lcExecute,
567 DescribeCursor( FASAConnection, TZASASQLDA( FSQLData), Cursor, '');
569 LastUpdateCount := -1;
570 Result := GetCachedResultSet( SQL, Self,
571 TZASAResultSet.Create( Self, SQL, FStmtNum, Cursor, FSQLData, nil,
574 { Logging SQL Command }
575 DriverManager.LogMessage( lcExecute, GetPlainDriver.GetProtocol, LogSQL);
588 Executes an SQL <code>INSERT</code>, <code>UPDATE</code> or
589 <code>DELETE</code> statement. In addition,
590 SQL statements that return nothing, such as SQL DDL statements,
593 @param sql an SQL <code>INSERT</code>, <code>UPDATE</code> or
594 <code>DELETE</code> statement or an SQL statement that returns nothing
595 @return either the row count for <code>INSERT</code>, <code>UPDATE</code>
596 or <code>DELETE</code> statements, or 0 for SQL statements that return nothing
598 function TZASAPreparedStatement.ExecuteUpdate(const SQL: RawByteString): Integer;
604 ASAPrepare( FASAConnection, FSQLData, FParamSQLData, ASQL, LogSQL, @FStmtNum,
605 FPrepared, FMoreResults);
607 Result := ExecuteUpdatePrepared;
611 Executes the SQL INSERT, UPDATE or DELETE statement
612 in this <code>PreparedStatement</code> object.
614 SQL statements that return nothing, such as SQL DDL statements,
617 @return either the row count for INSERT, UPDATE or DELETE statements;
618 or 0 for SQL statements that return nothing
621 function TZASAPreparedStatement.ExecuteUpdatePrepared: Integer;
624 with FASAConnection do
627 PrepareParameters( GetPlainDriver, InParamValues, InParamTypes,
628 InParamCount, FParamSQLData, FASAConnection.GetConSettings);
629 GetPlainDriver.db_execute_into( GetDBHandle, nil, nil, @FStmtNum,
630 FParamSQLData.GetData, nil);
631 ZDbcASAUtils.CheckASAError( GetPlainDriver, GetDBHandle, lcExecute, SQL,
632 SQLE_TOO_MANY_RECORDS);
634 Result := GetDBHandle.sqlErrd[2];
635 LastUpdateCount := Result;
637 { Logging SQL Command }
638 DriverManager.LogMessage(lcExecute, GetPlainDriver.GetProtocol, SQL);
644 { TZASACallableStatement }
647 Constructs this object and assignes the main properties.
648 @param Connection a database connection object.
649 @param Handle a connection handle pointer.
650 @param Info a statement parameters.
652 constructor TZASACallableStatement.Create(Connection: IZConnection;
653 const SQL: string; Info: TStrings);
655 inherited Create(Connection, SQL, Info);
657 FASAConnection := Connection as IZASAConnection;
658 FetchSize := BlockSize;
659 ResultSetConcurrency := rcUpdatable;
660 ResultSetType := rtScrollSensitive;
661 FCachedBlob := StrToBoolEx(DefineStatementParameter(Self, 'cashedblob', 'true'));
662 CursorName := AnsiString(RandomString(12));
663 FParamSQLData := TZASASQLDA.Create( FASAConnection.GetPlainDriver,
664 FASAConnection.GetDBHandle, CursorName, ConSettings);
665 FSQLData := TZASASQLDA.Create( FASAConnection.GetPlainDriver,
666 FASAConnection.GetDBHandle, CursorName, ConSettings);
669 destructor TZASACallableStatement.Destroy;
672 FParamSQLData := nil;
676 procedure TZASACallableStatement.Close;
680 FASAConnection.GetPlainDriver.db_close(FASAConnection.GetDBHandle, PAnsiChar(CursorName));
683 if FStmtNum <> 0 then
685 FASAConnection.GetPlainDriver.db_dropstmt( FASAConnection.GetDBHandle, nil,
692 procedure TZASACallableStatement.Cancel;
694 with FASAConnection do
696 GetPlainDriver.db_cancel_request( GetDBHandle);
697 ZDbcASAUtils.CheckASAError( GetPlainDriver, GetDBHandle, lcExecute, SQL);
701 function TZASACallableStatement.GetWarnings: EZSQLWarning;
703 Result := inherited GetWarnings;
706 procedure TZASACallableStatement.ClearWarnings;
711 function TZASACallableStatement.GetMoreResults: Boolean;
713 Result := FMoreResults;
716 with FASAConnection do
718 GetPlainDriver.db_resume(GetDBHandle, PAnsiChar(CursorName));
719 ZDbcASAUtils.CheckASAError( GetPlainDriver, GetDBHandle, lcExecute);
720 if GetDBHandle.sqlcode = SQLE_PROCEDURE_COMPLETE then
723 DescribeCursor( FASAConnection, TZASASQLDA( FSQLData), CursorName, '');
729 Executes an SQL statement that may return multiple results.
730 Under some (uncommon) situations a single SQL statement may return
731 multiple result sets and/or update counts. Normally you can ignore
732 this unless you are (1) executing a stored procedure that you know may
733 return multiple results or (2) you are dynamically executing an
734 unknown SQL string. The methods <code>execute</code>,
735 <code>getMoreResults</code>, <code>getResultSet</code>,
736 and <code>getUpdateCount</code> let you navigate through multiple results.
738 The <code>execute</code> method executes an SQL statement and indicates the
739 form of the first result. You can then use the methods
740 <code>getResultSet</code> or <code>getUpdateCount</code>
741 to retrieve the result, and <code>getMoreResults</code> to
742 move to any subsequent result(s).
744 @param sql any SQL statement
745 @return <code>true</code> if the next result is a <code>ResultSet</code> object;
746 <code>false</code> if it is an update count or there are no more results
752 function TZASACallableStatement.Execute(const SQL: RawByteString): Boolean;
754 ProcSQL: RawByteString;
757 ProcSQL := GetProcedureSQL;
758 if not FPrepared or ( ASQL <> ProcSQL) then
762 ASAPrepare( FASAConnection, FSQLData, FParamSQLData, ASQL, LogSQL, @FStmtNum,
763 FPrepared, FMoreResults);
765 Result := ExecutePrepared;
769 Executes any kind of SQL statement.
770 Some prepared statements return multiple results; the <code>execute</code>
771 method handles these complex statements as well as the simpler
772 form of statements handled by the methods <code>executeQuery</code>
773 and <code>executeUpdate</code>.
774 @see Statement#execute
776 function TZASACallableStatement.ExecutePrepared: Boolean;
778 if not FPrepared then
779 Result := Execute(ASQL)
782 if FMoreResults or ( ( FSQLData.GetData.sqld > 0) and
783 ( FSQLData.GetData.sqlVar[0].sqlInd^ and DT_PROCEDURE_OUT = 0)) then
785 LastResultSet := ExecuteQueryPrepared;
790 ExecuteUpdatePrepared;
797 Executes an SQL statement that returns a single <code>ResultSet</code> object.
798 @param sql typically this is a static SQL <code>SELECT</code> statement
799 @return a <code>ResultSet</code> object that contains the data produced by the
800 given query; never <code>null</code>
802 function TZASACallableStatement.ExecuteQuery(const SQL: RawByteString): IZResultSet;
804 ProcSQL: RawByteString;
807 ProcSQL := GetProcedureSQL;
808 if not FPrepared or ( ASQL <> ProcSQL) then
812 ASAPrepare( FASAConnection, FSQLData, FParamSQLData, ASQL, LogSQL, @FStmtNum,
813 FPrepared, FMoreResults);
815 Result := ExecuteQueryPrepared;
819 Executes the SQL query in this <code>PreparedStatement</code> object
820 and returns the result set generated by the query.
822 @return a <code>ResultSet</code> object that contains the data produced by the
823 query; never <code>null</code>
826 function TZASACallableStatement.ExecuteQueryPrepared: IZResultSet;
829 CursorOptions: SmallInt;
831 if not FPrepared then
832 Result := ExecuteQuery(ASQL)
835 with FASAConnection do
837 PrepareParameters( GetPlainDriver, InParamValues, InParamTypes,
838 InParamCount, FParamSQLData, FASAConnection.GetConSettings);
839 if ResultSetConcurrency = rcUpdatable then
840 CursorOptions := CUR_OPEN_DECLARE + CUR_UPDATE
842 CursorOptions := CUR_OPEN_DECLARE + CUR_READONLY;
843 if ResultSetType = rtScrollInsensitive then
844 CursorOptions := CursorOptions + CUR_INSENSITIVE;
845 Cursor := CursorName;
846 GetPlainDriver.db_open(GetDBHandle, PAnsiChar(Cursor), nil, @FStmtNum,
847 FParamSQLData.GetData, FetchSize, 0, CursorOptions);
848 ZDbcASAUtils.CheckASAError( GetPlainDriver, GetDBHandle, lcExecute, LogSQL);
852 DescribeCursor( FASAConnection, TZASASQLDA( FSQLData), Cursor, LogSQL);
854 LastUpdateCount := -1;
855 Result := GetCachedResultSet( LogSQL, Self,
856 TZASAResultSet.Create( Self, LogSQL, FStmtNum, Cursor, FSQLData, nil,
859 { Logging SQL Command }
860 DriverManager.LogMessage( lcExecute, GetPlainDriver.GetProtocol, LogSQL);
874 Executes an SQL <code>INSERT</code>, <code>UPDATE</code> or
875 <code>DELETE</code> statement. In addition,
876 SQL statements that return nothing, such as SQL DDL statements,
879 @param sql an SQL <code>INSERT</code>, <code>UPDATE</code> or
880 <code>DELETE</code> statement or an SQL statement that returns nothing
881 @return either the row count for <code>INSERT</code>, <code>UPDATE</code>
882 or <code>DELETE</code> statements, or 0 for SQL statements that return nothing
884 function TZASACallableStatement.ExecuteUpdate(const SQL: RawByteString): Integer;
886 ProcSQL: RawByteString;
889 ProcSQL := GetProcedureSQL;
890 if not FPrepared or ( ASQL <> ProcSQL) then
894 ASAPrepare( FASAConnection, FSQLData, FParamSQLData, ASQL, LogSQL, @FStmtNum,
895 FPrepared, FMoreResults);
897 Result := ExecuteUpdatePrepared;
901 Executes the SQL INSERT, UPDATE or DELETE statement
902 in this <code>PreparedStatement</code> object.
904 SQL statements that return nothing, such as SQL DDL statements,
907 @return either the row count for INSERT, UPDATE or DELETE statements;
908 or 0 for SQL statements that return nothing
910 function TZASACallableStatement.ExecuteUpdatePrepared: Integer;
912 if not FPrepared then
913 Result := ExecuteUpdate( SQL)
917 with FASAConnection do
920 PrepareParameters( GetPlainDriver, InParamValues, InParamTypes,
921 InParamCount, FParamSQLData, FASAConnection.GetConSettings);
922 GetPlainDriver.db_execute_into( GetDBHandle, nil, nil, @FStmtNum,
923 FParamSQLData.GetData, FSQLData.GetData);
924 ZDbcASAUtils.CheckASAError( GetPlainDriver, GetDBHandle, lcExecute, SQL);
926 Result := GetDBHandle.sqlErrd[2];
927 LastUpdateCount := Result;
928 { Fetch data and fill Output params }
929 FetchOutParams( FSQLData);
931 { Logging SQL Command }
932 DriverManager.LogMessage(lcExecute, GetPlainDriver.GetProtocol, SQL);
938 Set output parameters values from IZResultSQLDA.
939 @param Value a IZASASQLDA object.
941 procedure TZASACallableStatement.FetchOutParams( Value: IZASASQLDA);
949 SetOutParamCount(Value.GetFieldCount);
950 for I := 0 to Value.GetFieldCount-1 do
952 if Value.IsNull(I) then
953 DefVarManager.SetNull(Temp)
955 case Value.GetFieldSqlType(I) of
957 DefVarManager.SetAsBoolean(Temp, Value.GetBoolean(I));
959 DefVarManager.SetAsInteger(Temp, Value.GetByte(I));
961 DefVarManager.SetAsInteger(Temp, Value.GetShort(I));
963 DefVarManager.SetAsInteger(Temp, Value.GetInt(I));
965 DefVarManager.SetAsInteger(Temp, Value.GetLong(I));
967 DefVarManager.SetAsFloat(Temp, Value.GetFloat(I));
969 DefVarManager.SetAsFloat(Temp, Value.GetDouble(I));
971 DefVarManager.SetAsFloat(Temp, Value.GetBigDecimal(I));
973 DefVarManager.SetAsString(Temp, ZDbcString(Value.GetString(I)));
975 DefVarManager.SetAsUnicodeString(Temp, ZDbcUnicodeString(Value.GetString(I)));
977 DefVarManager.SetAsBytes( Temp, Value.GetBytes( I));
979 DefVarManager.SetAsDateTime(Temp, Value.GetDate(I));
981 DefVarManager.SetAsDateTime(Temp, Value.GetTime(I));
983 DefVarManager.SetAsDateTime(Temp, Value.GetTimestamp(I));
988 GetMem( P, PZASABlobStruct( Value.GetData.sqlvar[I].sqlData).untrunc_len);
989 Value.ReadBlobToMem( I, P, L);
990 TempBlob := TZASABlob.CreateWithData( P, L, GetConnection);
992 DefVarManager.SetAsInterface( Temp, TempBlob);
995 OutParamValues[I] := Temp;
1000 Create sql string for calling stored procedure.
1001 @param SelectProc indicate use <b>EXECUTE PROCEDURE</b> or
1002 <b>SELECT</b> staement
1003 @return a Stored Procedure SQL string
1005 function TZASACallableStatement.GetProcedureSql: RawByteString;
1007 function GenerateParamsStr(Count: integer): string;
1011 for I := 0 to Count - 1 do
1013 if Result <> '' then
1014 Result := Result + ',';
1015 Result := Result + '?';
1022 InParams := GenerateParamsStr( High( InParamValues) + 1);
1023 if InParams <> '' then
1024 InParams := '(' + InParams + ')';
1025 Result := ZPlainString('call ' + SQL + InParams);