zeoslib  UNKNOWN
 All Files
ZDbcAdoStatement.pas
Go to the documentation of this file.
1 {*********************************************************}
2 { }
3 { Zeos Database Objects }
4 { ADO Statement Classes }
5 { }
6 { Originally written by Janos Fegyverneki }
7 { }
8 {*********************************************************}
9 
10 {@********************************************************}
11 { Copyright (c) 1999-2012 Zeos Development Group }
12 { }
13 { License Agreement: }
14 { }
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. }
20 { }
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. }
39 { }
40 { }
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) }
45 { }
46 { http://www.sourceforge.net/projects/zeoslib. }
47 { }
48 { }
49 { Zeos Development Group. }
50 {********************************************************@}
51 
52 unit ZDbcAdoStatement;
53 
54 interface
55 
56 {$I ZDbc.inc}
57 
58 uses
59  Types, Classes, SysUtils, ZCompatibility, ZClasses, ZSysUtils, ZCollections,
60  ZDbcIntfs, ZPlainDriver, ZDbcStatement, ZDbcAdo, ZPlainAdoDriver, ZPlainAdo,
61  ZVariant, ZDbcAdoUtils;
62 
63 type
64  {** Implements Generic ADO Statement. }
65  TZAdoStatement = class(TZAbstractStatement)
66  protected
67  AdoRecordSet: ZPlainAdo.RecordSet;
68  public
69  function ExecuteQuery(const SQL: ZWideString): IZResultSet; override;
70  function ExecuteUpdate(const SQL: ZWideString): Integer; override;
71  function Execute(const SQL: ZWideString): Boolean; override;
72 
73  function ExecuteQuery(const SQL: RawByteString): IZResultSet; override;
74  function ExecuteUpdate(const SQL: RawByteString): Integer; override;
75  function Execute(const SQL: RawByteString): Boolean; override;
76 
77  function GetMoreResults: Boolean; override;
78  end;
79 
80  {** Implements Prepared ADO Statement. }
81  TZAdoPreparedStatement = class(TZAbstractPreparedStatement)
82  private
83  AdoRecordSet: ZPlainAdo.RecordSet;
84  FAdoCommand: ZPlainAdo.Command;
85  protected
86  procedure PrepareInParameters; override;
87  procedure BindInParameters; override;
88  public
89  constructor Create(Connection: IZConnection; const SQL: string; Info: TStrings);
90  destructor Destroy; override;
91 
92  function ExecuteQueryPrepared: IZResultSet; override;
93  function ExecuteUpdatePrepared: Integer; override;
94  function ExecutePrepared: Boolean; override;
95 
96  function GetMoreResults: Boolean; override;
97  procedure Unprepare; override;
98  end;
99 
100  {** Implements Callable ADO Statement. }
101  TZAdoCallableStatement = class(TZAbstractCallableStatement)
102  private
103  AdoRecordSet: ZPlainAdo.RecordSet;
104  FAdoCommand: ZPlainAdo.Command;
105  FDirectionTypes: TDirectionTypes;
106  protected
107  function GetOutParam(ParameterIndex: Integer): TZVariant; override;
108  procedure PrepareInParameters; override;
109  procedure BindInParameters; override;
110  public
111  constructor Create(Connection: IZConnection;
112  SQL: string; Info: TStrings);
113  function ExecuteQueryPrepared: IZResultSet; override;
114  function ExecuteUpdatePrepared: Integer; override;
115  function ExecutePrepared: Boolean; override;
116 
117  procedure RegisterParamType(ParameterIndex: Integer; ParamType: Integer); override;
118  function GetMoreResults: Boolean; override;
119  procedure Unprepare; override;
120  end;
121 
122 implementation
123 
124 uses
125 {$IFNDEF FPC}
126  Variants,
127 {$ENDIF}
128  OleDB, ComObj,
129  {$IFDEF WITH_TOBJECTLIST_INLINE} System.Contnrs{$ELSE} Contnrs{$ENDIF},
130  {$IFNDEF UNICODE}ZEncoding,{$ENDIF}
131  ZDbcLogging, ZDbcCachedResultSet, ZDbcResultSet, ZDbcAdoResultSet,
132  ZDbcMetadata, ZDbcResultSetMetadata, ZDbcUtils;
133 
134 function TZAdoStatement.ExecuteQuery(const SQL: ZWideString): IZResultSet;
135 var
136  RC: OleVariant;
137  function GetMoreResults(var RS: IZResultSet): Boolean;
138  begin
139  if Assigned(AdoRecordSet) then
140  begin
141  AdoRecordSet := AdoRecordSet.NextRecordset(RC);
142  RS := GetCurrentResultSet(AdoRecordSet, (Connection as IZAdoConnection), Self,
143  SQL, ConSettings, ResultSetConcurrency);
144  Result := Assigned(RS);
145  LastUpdateCount := RC;
146  end
147  else Result := False;
148  end;
149 begin
150  {$IFDEF UNICODE}
151  WSQL := SQL;
152  {$ENDIF}
153  Result := nil;
154  LastUpdateCount := -1;
155  if IsSelect(SSQL) then
156  begin
157  AdoRecordSet := CoRecordSet.Create;
158  AdoRecordSet.MaxRecords := MaxRows;
159  AdoRecordSet.Open(SQL, (Connection as IZAdoConnection).GetAdoConnection,
160  adOpenStatic, adLockOptimistic, adAsyncFetch);
161  end
162  else
163  AdoRecordSet := (Connection as IZAdoConnection).GetAdoConnection.Execute(WSQL, RC, adExecuteNoRecords);
164  Result := GetCurrentResultSet(AdoRecordSet, (Connection as IZAdoConnection), Self,
165  SSQL, ConSettings, ResultSetConcurrency);
166  if not Assigned(Result) then
167  while (not GetMoreResults(Result)) and (LastUpdateCount > -1) do ;
168 end;
169 
170 function TZAdoStatement.ExecuteUpdate(const SQL: ZWideString): Integer;
171 var
172  RC: OleVariant;
173 begin
174  LastResultSet := nil;
175  LastUpdateCount := -1;
176  {$IFDEF UNICODE}
177  WSQL := SQL;
178  {$ENDIF}
179  try
180  (Connection as IZAdoConnection).GetAdoConnection.Execute(WSQL, RC, adExecuteNoRecords);
181  Result := RC;
182  LastUpdateCount := Result;
183  DriverManager.LogMessage(lcExecute, Connection.GetIZPlainDriver.GetProtocol, LogSQL);
184  except
185  on E: Exception do
186  begin
187  DriverManager.LogError(lcExecute, Connection.GetIZPlainDriver.GetProtocol, LogSQL, 0, E.Message);
188  raise;
189  end;
190  end
191 end;
192 
193 function TZAdoStatement.Execute(const SQL: ZWideString): Boolean;
194 var
195  RC: OleVariant;
196 begin
197  {$IFDEF UNICODE}
198  WSQL := SQL;
199  {$ENDIF}
200  LastResultSet := nil;
201  LastUpdateCount := -1;
202  try
203  if IsSelect(SSQL) then
204  begin
205  AdoRecordSet := CoRecordSet.Create;
206  AdoRecordSet.MaxRecords := MaxRows;
207  AdoRecordSet.Open(SQL, (Connection as IZAdoConnection).GetAdoConnection,
208  adOpenStatic, adLockOptimistic, adAsyncFetch);
209  end
210  else
211  AdoRecordSet := (Connection as IZAdoConnection).GetAdoConnection.Execute(WSQL, RC, adExecuteNoRecords);
212  LastResultSet := GetCurrentResultSet(AdoRecordSet, (Connection as IZAdoConnection), Self,
213  LogSQL, ConSettings, ResultSetConcurrency);
214  Result := Assigned(LastResultSet);
215  LastUpdateCount := RC;
216  DriverManager.LogMessage(lcExecute, Connection.GetIZPlainDriver.GetProtocol, LogSQL);
217  except
218  on E: Exception do
219  begin
220  DriverManager.LogError(lcExecute, Connection.GetIZPlainDriver.GetProtocol, LogSQL, 0, E.Message);
221  raise;
222  end;
223  end
224 end;
225 
226 function TZAdoStatement.ExecuteQuery(const SQL: RawByteString): IZResultSet;
227 begin
228  if ASQL <> SQL then
229  ASQL := SQL;
230  Result := ExecuteQuery(WSQL);
231 end;
232 
233 function TZAdoStatement.ExecuteUpdate(const SQL: RawByteString): Integer;
234 begin
235  if ASQL <> SQL then
236  ASQL := SQL;
237  Result := ExecuteUpdate(WSQL);
238 end;
239 
240 function TZAdoStatement.Execute(const SQL: RawByteString): Boolean;
241 begin
242  if ASQL <> SQL then
243  ASQL := SQL;
244  Result := Execute(WSQL);
245 end;
246 
247 function TZAdoStatement.GetMoreResults: Boolean;
248 var
249  RC: OleVariant;
250 begin
251  Result := False;
252  LastResultSet := nil;
253  LastUpdateCount := -1;
254  if Assigned(AdoRecordSet) then
255  begin
256  AdoRecordSet := AdoRecordSet.NextRecordset(RC);
257  LastResultSet := GetCurrentResultSet(AdoRecordSet, (Connection as IZAdoConnection), Self,
258  SSQL, ConSettings, ResultSetConcurrency);
259  Result := Assigned(LastResultSet);
260  LastUpdateCount := RC;
261  end;
262 end;
263 
264 { TZAdoPreparedStatement }
265 
266 constructor TZAdoPreparedStatement.Create(Connection: IZConnection;
267  const SQL: string; Info: TStrings);
268 begin
269  FAdoCommand := CoCommand.Create;
270  inherited Create(Connection, SQL, Info);
271  FAdoCommand.CommandText := WSQL;
272  FAdoCommand._Set_ActiveConnection((Connection as IZAdoConnection).GetAdoConnection);
273 end;
274 
275 destructor TZAdoPreparedStatement.Destroy;
276 begin
277  AdoRecordSet := nil;
278  inherited;
279  FAdoCommand := nil;
280 end;
281 
282 procedure TZAdoPreparedStatement.PrepareInParameters;
283 begin
284  if InParamCount > 0 then
285  RefreshParameters(FAdoCommand);
286  FAdoCommand.Prepared := True;
287 end;
288 
289 procedure TZAdoPreparedStatement.BindInParameters;
290 var I: Integer;
291 begin
292  if InParamCount = 0 then
293  Exit
294  else
295  for i := 0 to InParamCount-1 do
296  if DefVarManager.IsNull(InParamValues[i]) then
297  if (InParamDefaultValues[i] <> '') and (UpperCase(InParamDefaultValues[i]) <> 'NULL') and
298  StrToBoolEx(DefineStatementParameter(Self, 'defaults', 'true')) then
299  begin
300  DefVarManager.SetAsString(InParamValues[i], InParamDefaultValues[i]);
301  ADOSetInParam(FAdoCommand, (Connection as IZAdoConnection), InParamCount, I+1, InParamTypes[i], InParamValues[i], adParamInput)
302  end
303  else
304  ADOSetInParam(FAdoCommand, (Connection as IZAdoConnection), InParamCount, I+1, InParamTypes[i], NullVariant, adParamInput)
305  else
306  ADOSetInParam(FAdoCommand, (Connection as IZAdoConnection), InParamCount, I+1, InParamTypes[i], InParamValues[i], adParamInput);
307 end;
308 
309 {**
310  Executes the SQL query in this <code>PreparedStatement</code> object
311  and returns the result set generated by the query.
312 
313  @return a <code>ResultSet</code> object that contains the data produced by the
314  query; never <code>null</code>
315 }
316 function TZAdoPreparedStatement.ExecuteQueryPrepared: IZResultSet;
317 begin
318  if not ExecutePrepared then
319  while (not GetMoreResults) and (LastUpdateCount > -1) do ;
320  Result := LastResultSet;
321 end;
322 
323 {**
324  Executes the SQL INSERT, UPDATE or DELETE statement
325  in this <code>PreparedStatement</code> object.
326  In addition,
327  SQL statements that return nothing, such as SQL DDL statements,
328  can be executed.
329 
330  @return either the row count for INSERT, UPDATE or DELETE statements;
331  or 0 for SQL statements that return nothing
332 }
333 function TZAdoPreparedStatement.ExecuteUpdatePrepared: Integer;
334 begin
335  ExecutePrepared;
336  Result := LastUpdateCount;
337 end;
338 
339 {**
340  Executes any kind of SQL statement.
341  Some prepared statements return multiple results; the <code>execute</code>
342  method handles these complex statements as well as the simpler
343  form of statements handled by the methods <code>executeQuery</code>
344  and <code>executeUpdate</code>.
345  @see Statement#execute
346 }
347 function TZAdoPreparedStatement.ExecutePrepared: Boolean;
348 var
349  RC: OleVariant;
350 begin
351  LastResultSet := nil;
352  LastUpdateCount := -1;
353 
354  Prepare;
355  BindInParameters;
356  try
357  if IsSelect(SQL) then
358  begin
359  AdoRecordSet := CoRecordSet.Create;
360  AdoRecordSet.MaxRecords := MaxRows;
361  AdoRecordSet._Set_ActiveConnection(FAdoCommand.Get_ActiveConnection);
362  AdoRecordSet.Open(FAdoCommand, EmptyParam, adOpenForwardOnly, adLockOptimistic, adAsyncFetch);
363  end
364  else
365  AdoRecordSet := FAdoCommand.Execute(RC, EmptyParam, -1{, adExecuteNoRecords});
366  LastResultSet := GetCurrentResultSet(AdoRecordSet, (Connection as IZAdoConnection), Self,
367  SQL, ConSettings, ResultSetConcurrency);
368  LastUpdateCount := RC;
369  Result := Assigned(LastResultSet);
370  DriverManager.LogMessage(lcExecute, Connection.GetIZPlainDriver.GetProtocol, SQL);
371  except
372  on E: Exception do
373  begin
374  DriverManager.LogError(lcExecute, Connection.GetIZPlainDriver.GetProtocol, SQL, 0, E.Message);
375  raise;
376  end;
377  end
378 end;
379 
380 function TZAdoPreparedStatement.GetMoreResults: Boolean;
381 var
382  RC: OleVariant;
383 begin
384  Result := False;
385  LastResultSet := nil;
386  LastUpdateCount := -1;
387  if Assigned(AdoRecordSet) then
388  begin
389  AdoRecordSet := AdoRecordSet.NextRecordset(RC);
390  LastResultSet := GetCurrentResultSet(AdoRecordSet, (Connection as IZAdoConnection), Self,
391  SQL, ConSettings, ResultSetConcurrency);
392  Result := Assigned(LastResultSet);
393  LastUpdateCount := RC;
394  end;
395 end;
396 
397 procedure TZAdoPreparedStatement.Unprepare;
398 begin
399  if FAdoCommand.Prepared then
400  FAdoCommand.Prepared := False;
401  inherited;
402 end;
403 
404 { TZAdoCallableStatement }
405 
406 constructor TZAdoCallableStatement.Create(Connection: IZConnection;
407  SQL: string; Info: TStrings);
408 begin
409  inherited Create(Connection, SQL, Info);
410  FAdoCommand := CoCommand.Create;
411  FAdoCommand.CommandText := WSQL;
412  FAdoCommand._Set_ActiveConnection((Connection as IZAdoConnection).GetAdoConnection);
413  FAdoCommand.CommandType := adCmdStoredProc;
414 end;
415 
416 function TZAdoCallableStatement.ExecuteQueryPrepared: IZResultSet;
417 var
418  I: Integer;
419  ColumnInfo: TZColumnInfo;
420  ColumnsInfo: TObjectList;
421  RS: TZVirtualResultSet;
422  IndexAlign: TIntegerDynArray;
423  P: Pointer;
424  Stream: TStream;
425 begin
426  ExecutePrepared;
427  SetLength(IndexAlign, 0);
428  ColumnsInfo := TObjectList.Create(True);
429  Stream := nil;
430  try
431  for I := 0 to FAdoCommand.Parameters.Count -1 do
432  if FAdoCommand.Parameters.Item[i].Direction in [adParamOutput,
433  adParamInputOutput, adParamReturnValue] then
434  begin
435  SetLength(IndexAlign, Length(IndexAlign)+1);
436  ColumnInfo := TZColumnInfo.Create;
437  with ColumnInfo do
438  begin
439  ColumnLabel := FAdoCommand.Parameters.Item[i].Name;
440  ColumnType := ConvertAdoToSqlType(FAdoCommand.Parameters.Item[I].Type_, ConSettings.CPType);
441  ColumnDisplaySize := FAdoCommand.Parameters.Item[I].Precision;
442  Precision := FAdoCommand.Parameters.Item[I].Precision;
443  IndexAlign[High(IndexAlign)] := I;
444  end;
445  ColumnsInfo.Add(ColumnInfo);
446  end;
447 
448  RS := TZVirtualResultSet.CreateWithColumns(ColumnsInfo, '', ConSettings);
449  with RS do
450  begin
451  SetType(rtScrollInsensitive);
452  SetConcurrency(rcReadOnly);
453  RS.MoveToInsertRow;
454  for i := 1 to ColumnsInfo.Count do
455  case TZColumnInfo(ColumnsInfo[i-1]).ColumnType of
456  stBoolean:
457  RS.UpdateBoolean(i, FAdoCommand.Parameters.Item[IndexAlign[i-1]].Value);
458  stByte, stShort, stInteger, stLong:
459  RS.UpdateInt(i, FAdoCommand.Parameters.Item[IndexAlign[i-1]].Value);
460  stFloat, stDouble, stBigDecimal:
461  RS.UpdateFloat(i, FAdoCommand.Parameters.Item[IndexAlign[i-1]].Value);
462  stString:
463  RS.UpdateString(i, FAdoCommand.Parameters.Item[IndexAlign[i-1]].Value);
464  stAsciiStream:
465  begin
466  Stream := TStringStream.Create(AnsiString(FAdoCommand.Parameters.Item[IndexAlign[i-1]].Value));
467  RS.UpdateAsciiStream(I, Stream);
468  Stream.Free;
469  end;
470  stUnicodeString:
471  RS.UpdateUnicodeString(i, FAdoCommand.Parameters.Item[IndexAlign[i-1]].Value);
472  stUnicodeStream:
473  begin
474  Stream := WideStringStream(WideString(FAdoCommand.Parameters.Item[IndexAlign[i-1]].Value));
475  RS.UpdateUnicodeStream(I, Stream);
476  FreeAndNil(Stream);
477  end;
478  stBytes:
479  RS.UpdateBytes(i, FAdoCommand.Parameters.Item[IndexAlign[i-1]].Value);
480  stDate:
481  RS.UpdateDate(i, FAdoCommand.Parameters.Item[IndexAlign[i-1]].Value);
482  stTime:
483  RS.UpdateTime(i, FAdoCommand.Parameters.Item[IndexAlign[i-1]].Value);
484  stTimestamp:
485  RS.UpdateTimestamp(i, FAdoCommand.Parameters.Item[IndexAlign[i-1]].Value);
486  stBinaryStream:
487  begin
488  if VarIsStr(FAdoCommand.Parameters.Item[IndexAlign[i-1]].Value) then
489  begin
490  Stream := TStringStream.Create(AnsiString(FAdoCommand.Parameters.Item[IndexAlign[i-1]].Value));
491  RS.UpdateBinaryStream(I, Stream);
492  FreeAndNil(Stream);
493  end
494  else
495  if VarIsArray(FAdoCommand.Parameters.Item[IndexAlign[i-1]].Value) then
496  begin
497  P := VarArrayLock(FAdoCommand.Parameters.Item[IndexAlign[i-1]].Value);
498  try
499  Stream := TMemoryStream.Create;
500  Stream.Size := VarArrayHighBound(FAdoCommand.Parameters.Item[IndexAlign[i-1]].Value, 1)+1;
501  System.Move(P^, TMemoryStream(Stream).Memory^, Stream.Size);
502  RS.UpdateBinaryStream(I, Stream);
503  FreeAndNil(Stream);
504  finally
505  VarArrayUnLock(FAdoCommand.Parameters.Item[IndexAlign[i-1]].Value);
506  end;
507  end;
508  end
509  else
510  RS.UpdateNull(i);
511  end;
512  RS.InsertRow;
513  end;
514  Result := RS;
515  finally
516  ColumnsInfo.Free;
517  if Assigned(Stream) then Stream.Free;
518 
519  end;
520 end;
521 
522 {**
523  Executes the SQL INSERT, UPDATE or DELETE statement
524  in this <code>PreparedStatement</code> object.
525  In addition,
526  SQL statements that return nothing, such as SQL DDL statements,
527  can be executed.
528 
529  @return either the row count for INSERT, UPDATE or DELETE statements;
530  or 0 for SQL statements that return nothing
531 }
532 function TZAdoCallableStatement.ExecuteUpdatePrepared: Integer;
533 begin
534  ExecutePrepared;
535  Result := LastUpdateCount;
536 end;
537 
538 {**
539  Executes any kind of SQL statement.
540  Some prepared statements return multiple results; the <code>execute</code>
541  method handles these complex statements as well as the simpler
542  form of statements handled by the methods <code>executeQuery</code>
543  and <code>executeUpdate</code>.
544  @see Statement#execute
545 }
546 function TZAdoCallableStatement.ExecutePrepared: Boolean;
547 var
548  RC: OleVariant;
549 begin
550  LastResultSet := nil;
551  LastUpdateCount := -1;
552  if Not Prepared then Prepare;
553 
554  BindInParameters;
555  try
556  if IsSelect(SQL) then
557  begin
558  AdoRecordSet := CoRecordSet.Create;
559  AdoRecordSet.MaxRecords := MaxRows;
560  AdoRecordSet._Set_ActiveConnection(FAdoCommand.Get_ActiveConnection);
561  AdoRecordSet.Open(FAdoCommand, EmptyParam, adOpenForwardOnly, adLockOptimistic, adAsyncFetch);
562  end
563  else
564  AdoRecordSet := FAdoCommand.Execute(RC, EmptyParam, -1{, adExecuteNoRecords});
565  LastResultSet := GetCurrentResultSet(AdoRecordSet, (Connection as IZAdoConnection), Self,
566  SQL, ConSettings, ResultSetConcurrency);
567  LastUpdateCount := RC;
568  Result := Assigned(LastResultSet);
569  DriverManager.LogMessage(lcExecute, Connection.GetIZPlainDriver.GetProtocol, SQL);
570  except
571  on E: Exception do
572  begin
573  DriverManager.LogError(lcExecute, Connection.GetIZPlainDriver.GetProtocol, SQL, 0, E.Message);
574  raise;
575  end;
576  end
577 end;
578 
579 procedure TZAdoCallableStatement.RegisterParamType(ParameterIndex: Integer;
580  ParamType: Integer);
581 begin
582  inherited RegisterParamType(ParameterIndex, ParamType);
583  if Length(FDirectionTypes) < ParameterIndex then
584  SetLength(FDirectionTypes, ParameterIndex);
585 
586  case Self.FDBParamTypes[ParameterIndex-1] of
587  1: //ptInput
588  FDirectionTypes[ParameterIndex-1] := adParamInput;
589  2: //ptOut
590  FDirectionTypes[ParameterIndex-1] := adParamOutput;
591  3: //ptInputOutput
592  FDirectionTypes[ParameterIndex-1] := adParamInputOutput;
593  4: //ptResult
594  FDirectionTypes[ParameterIndex-1] := adParamReturnValue;
595  else
596  //ptUnknown
597  FDirectionTypes[ParameterIndex-1] := adParamUnknown;
598  end;
599 end;
600 
601 function TZAdoCallableStatement.GetMoreResults: Boolean;
602 var
603  RC: OleVariant;
604 begin
605  Result := False;
606  LastResultSet := nil;
607  LastUpdateCount := -1;
608  if Assigned(AdoRecordSet) then
609  begin
610  AdoRecordSet := AdoRecordSet.NextRecordset(RC);
611  LastResultSet := GetCurrentResultSet(AdoRecordSet, (Connection as IZAdoConnection), Self,
612  SQL, ConSettings, ResultSetConcurrency);
613  Result := Assigned(LastResultSet);
614  LastUpdateCount := RC;
615  end;
616 end;
617 
618 procedure TZAdoCallableStatement.Unprepare;
619 begin
620  if FAdoCommand.Prepared then
621  FAdoCommand.Prepared := False;
622  inherited;
623 end;
624 
625 function TZAdoCallableStatement.GetOutParam(ParameterIndex: Integer): TZVariant;
626 var
627  Temp: Variant;
628  V: Variant;
629  P: Pointer;
630  TempBlob: IZBLob;
631 begin
632 
633  if ParameterIndex > OutParamCount then
634  Result := NullVariant
635  else
636  begin
637  Temp := FAdoCommand.Parameters.Item[ParameterIndex - 1].Value;
638 
639  case ConvertAdoToSqlType(FAdoCommand.Parameters.Item[ParameterIndex - 1].Type_,
640  ConSettings.CPType) of
641  stBoolean:
642  DefVarManager.SetAsBoolean(Result, Temp);
643  stByte, stShort, stInteger, stLong:
644  DefVarManager.SetAsInteger(Result, Temp);
645  stFloat, stDouble, stBigDecimal:
646  DefVarManager.SetAsFloat(Result, Temp);
647  stString, stAsciiStream:
648  DefVarManager.SetAsString(Result, Temp);
649  stUnicodeString, stUnicodeStream:
650  DefVarManager.SetAsUnicodeString(Result, Temp);
651  stBytes:
652  DefVarManager.SetAsBytes(Result, VarToBytes(Temp));
653  stDate, stTime, stTimestamp:
654  DefVarManager.SetAsDateTime(Result, Temp);
655  stBinaryStream:
656  begin
657  if VarIsStr(V) then
658  begin
659  TempBlob := TZAbstractBlob.CreateWithStream(nil, GetConnection);
660  TempBlob.SetString(AnsiString(V));
661  end
662  else
663  if VarIsArray(V) then
664  begin
665  P := VarArrayLock(V);
666  try
667  TempBlob := TZAbstractBlob.CreateWithData(P, VarArrayHighBound(V, 1)+1, GetConnection);
668  finally
669  VarArrayUnLock(V);
670  end;
671  end;
672  DefVarManager.SetAsInterface(Result, TempBlob);
673  TempBlob := nil;
674  end
675  else
676  DefVarManager.SetNull(Result);
677  end;
678  end;
679 
680  LastWasNull := DefVarManager.IsNull(Result) or VarIsNull(Temp) or VarIsClear(Temp);
681 end;
682 
683 procedure TZAdoCallableStatement.PrepareInParameters;
684 begin
685  if InParamCount > 0 then
686  RefreshParameters(FAdoCommand, @FDirectionTypes);
687  FAdoCommand.Prepared := True;
688 end;
689 
690 procedure TZAdoCallableStatement.BindInParameters;
691 var
692  I: Integer;
693 begin
694  if InParamCount = 0 then
695  Exit
696  else
697  for i := 0 to InParamCount-1 do
698  if FDBParamTypes[i] in [1,3] then //ptInput, ptInputOutput
699  if DefVarManager.IsNull(InParamValues[i]) then
700  if (InParamDefaultValues[i] <> '') and (UpperCase(InParamDefaultValues[i]) <> 'NULL') and
701  StrToBoolEx(DefineStatementParameter(Self, 'defaults', 'true')) then
702  begin
703  DefVarManager.SetAsString(InParamValues[i], InParamDefaultValues[i]);
704  ADOSetInParam(FAdoCommand, (Connection as IZAdoConnection), InParamCount, I+1, InParamTypes[i], InParamValues[i], adParamInput)
705  end
706  else
707  ADOSetInParam(FAdoCommand, (Connection as IZAdoConnection), InParamCount, I+1, InParamTypes[i], NullVariant, FDirectionTypes[i])
708  else
709  ADOSetInParam(FAdoCommand, (Connection as IZAdoConnection), InParamCount, I+1, InParamTypes[i], InParamValues[i], FDirectionTypes[i])
710  else
711  ADOSetInParam(FAdoCommand, (Connection as IZAdoConnection), InParamCount, I+1, InParamTypes[i], NullVariant, FDirectionTypes[i]);
712 end;
713 
714 end.
715 
716 
717