ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/trunk/fbintf/client/3.0/FB30Array.pas
Revision: 309
Committed: Tue Jul 21 08:00:42 2020 UTC (3 years, 9 months ago) by tony
Content type: text/x-pascal
File size: 10632 byte(s)
Log Message:
Fixes Merged

File Contents

# User Rev Content
1 tony 45 (*
2     * Firebird Interface (fbintf). The fbintf components provide a set of
3     * Pascal language bindings for the Firebird API.
4     *
5     * The contents of this file are subject to the Initial Developer's
6     * Public License Version 1.0 (the "License"); you may not use this
7     * file except in compliance with the License. You may obtain a copy
8     * of the License here:
9     *
10     * http://www.firebirdsql.org/index.php?op=doc&id=idpl
11     *
12     * Software distributed under the License is distributed on an "AS
13     * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
14     * implied. See the License for the specific language governing rights
15     * and limitations under the License.
16     *
17     * The Initial Developer of the Original Code is Tony Whyman.
18     *
19     * The Original Code is (C) 2016 Tony Whyman, MWA Software
20     * (http://www.mwasoftware.co.uk).
21     *
22     * All Rights Reserved.
23     *
24     * Contributor(s): ______________________________________.
25     *
26     *)
27     unit FB30Array;
28 tony 56 {$IFDEF MSWINDOWS}
29     {$DEFINE WINDOWS}
30     {$ENDIF}
31 tony 45
32     {$IFDEF FPC}
33 tony 56 {$mode delphi}
34 tony 45 {$codepage UTF8}
35     {$interfaces COM}
36     {$ENDIF}
37    
38     interface
39    
40     uses
41     Classes, SysUtils, Firebird, IB, FBArray, IBHeader, FB30Attachment, FBClientAPI,
42 tony 263 FB30Transaction, FBParamBlock, FB30ClientAPI;
43 tony 45
44     type
45    
46 tony 56 ISDLItem = interface(IParameterBlockItem)
47     ['{a34b6064-5ae9-4fc1-85c3-f145f069b607}']
48 tony 45 procedure addByte(aValue: byte);
49 tony 308 procedure addShortInt(aValue: ShortInt);
50 tony 45 procedure addShortInteger(aValue: integer);
51     procedure SetAsShortInteger(aValue: integer);
52     procedure SetAsTinyInteger(aValue: integer);
53     end;
54    
55 tony 56 ISDL = interface(IParameterBlock<ISDLItem>)
56     ['{52ae1f5f-657b-4b14-81aa-7b3658454f4c}']
57 tony 45 end;
58    
59     { TFB30ArrayMetaData }
60    
61     TFB30ArrayMetaData = class(TFBArrayMetaData,IArrayMetaData)
62     private
63     FCodePage: TSystemCodePage;
64 tony 309 FCharSetWidth: integer;
65 tony 45 protected
66     procedure LoadMetaData(aAttachment: IAttachment; aTransaction: ITransaction;
67 tony 56 relationName, columnName: AnsiString); override;
68 tony 45 public
69     function GetCharSetID: cardinal; override;
70     function GetCodePage: TSystemCodePage; override;
71 tony 309 function GetCharSetWidth: integer; override;
72 tony 45 end;
73    
74     { TFB30Array }
75    
76     TFB30Array = class(TFBArray,IArray)
77     private
78     FAttachmentIntf: Firebird.IAttachment;
79     FTransactionIntf: Firebird.ITransaction;
80 tony 263 FFirebird30ClientAPI: TFB30ClientAPI;
81 tony 45 FSDL: ISDL;
82     protected
83     procedure AllocateBuffer; override;
84     procedure InternalGetSlice; override;
85     procedure InternalPutSlice(Force: boolean); override;
86     public
87     constructor Create(aAttachment: TFB30Attachment; aTransaction: TFB30Transaction; aField: IArrayMetaData); overload;
88     constructor Create(aAttachment: TFB30Attachment; aTransaction: TFB30Transaction; aField: IArrayMetaData; ArrayID: TISC_QUAD); overload;
89     end;
90    
91     TSDLItem = class(TParamBlockItem,ISDLItem);
92    
93     { TSDLBlock }
94    
95 tony 56 TSDLBlock = class (TCustomParamBlock<TSDLItem,ISDLItem>, ISDL)
96 tony 45 public
97 tony 263 constructor Create(api: TFBClientAPI);
98 tony 45 end;
99    
100     implementation
101    
102 tony 263 uses FBAttachment, FB30Statement;
103 tony 45
104     const
105     sGetArrayMetaData = 'Select F.RDB$FIELD_LENGTH, F.RDB$FIELD_SCALE, F.RDB$FIELD_TYPE, '+
106     'F.RDB$DIMENSIONS, FD.RDB$DIMENSION, FD.RDB$LOWER_BOUND, FD.RDB$UPPER_BOUND, '+
107     'F.RDB$CHARACTER_SET_ID '+
108     'From RDB$FIELDS F JOIN RDB$RELATION_FIELDS RF '+
109     'On F.RDB$FIELD_NAME = RF.RDB$FIELD_SOURCE JOIN RDB$FIELD_DIMENSIONS FD '+
110     'On FD.RDB$FIELD_NAME = F.RDB$FIELD_NAME ' +
111 tony 113 'Where RF.RDB$RELATION_NAME = ? and RF.RDB$FIELD_NAME = ? ' +
112     'UNION '+
113     'Select F.RDB$FIELD_LENGTH, F.RDB$FIELD_SCALE, F.RDB$FIELD_TYPE, '+
114     'F.RDB$DIMENSIONS, FD.RDB$DIMENSION, FD.RDB$LOWER_BOUND, FD.RDB$UPPER_BOUND, '+
115     'F.RDB$CHARACTER_SET_ID '+
116     'From RDB$FIELDS F JOIN RDB$PROCEDURE_PARAMETERS PP '+
117     'On F.RDB$FIELD_NAME = PP.RDB$FIELD_SOURCE JOIN RDB$FIELD_DIMENSIONS FD '+
118     'On FD.RDB$FIELD_NAME = F.RDB$FIELD_NAME ' +
119     'Where PP.RDB$PROCEDURE_NAME = ? and PP.RDB$PARAMETER_NAME = ? '+
120     'Order by 5 asc';
121 tony 45
122    
123     { TFB30ArrayMetaData }
124    
125     {Assemble the array descriptor from the System Tables}
126    
127     procedure TFB30ArrayMetaData.LoadMetaData(aAttachment: IAttachment;
128 tony 56 aTransaction: ITransaction; relationName, columnName: AnsiString);
129 tony 45 var stmt: IStatement;
130 tony 47 CharWidth: integer;
131 tony 45 begin
132 tony 263 CharWidth := 0;
133 tony 45 RelationName := AnsiUpperCase(RelationName);
134     ColumnName := AnsiUpperCase(ColumnName);
135     stmt := TFB30Statement.Create(aAttachment as TFB30Attachment,aTransaction,
136     sGetArrayMetaData ,aAttachment.GetSQLDialect);
137     with stmt do
138     begin
139     SQLParams[0].AsString := RelationName;
140     SQLParams[1].AsString := ColumnName;
141 tony 113 SQLParams[2].AsString := RelationName;
142     SQLParams[3].AsString := ColumnName;
143 tony 45 with OpenCursor do
144     if FetchNext then
145     begin
146     FillChar(FArrayDesc.array_desc_field_name,sizeof(FArrayDesc.array_desc_field_name),' ');
147 tony 47 FillChar(FArrayDesc.array_desc_relation_name,sizeof(FArrayDesc.array_desc_relation_name),' ');
148 tony 45 Move(columnName[1],FArrayDesc.array_desc_field_name,Length(columnName));
149     Move(relationName[1],FArrayDesc.array_desc_relation_name,length(relationName));
150     FArrayDesc.array_desc_length := Data[0].AsInteger;
151 tony 56 FArrayDesc.array_desc_scale := Data[1].AsInteger;
152 tony 45 FArrayDesc.array_desc_dtype := Data[2].AsInteger;
153     FArrayDesc.array_desc_dimensions := Data[3].AsInteger;
154     FArrayDesc.array_desc_flags := 0; {row major}
155     FCharSetID := Data[7].AsInteger;
156     if (FCharSetID > 1) and (aAttachment as TFB30Attachment).HasDefaultCharSet then
157     FCharSetID := (aAttachment as TFB30Attachment).CharSetID;
158     FCodePage := CP_NONE;
159 tony 60 FAttachment.CharSetID2CodePage(FCharSetID,FCodePage);
160 tony 309 FCharSetWidth := 1;
161     FAttachment.CharSetWidth(FCharSetID,FCharSetWidth);
162 tony 47 if (FArrayDesc.array_desc_dtype in [blr_text,blr_cstring, blr_varying]) and
163     (FCharSetID = 0) then {This really shouldn't be necessary - but it is :(}
164     with aAttachment as TFBAttachment do
165     begin
166 tony 60 if HasDefaultCharSet and FAttachment.CharSetWidth(CharSetID,CharWidth) then
167 tony 56 FArrayDesc.array_desc_length := FArrayDesc.array_desc_length * CharWidth;
168 tony 47 end;
169 tony 45 repeat
170     with FArrayDesc.array_desc_bounds[Data[4].AsInteger] do
171     begin
172     array_bound_lower := Data[5].AsInteger;
173     array_bound_upper := Data[6].AsInteger;
174     end;
175     until not FetchNext;
176     end;
177     end;
178     end;
179    
180     function TFB30ArrayMetaData.GetCharSetID: cardinal;
181     begin
182     Result := FCharSetID;
183     end;
184    
185     function TFB30ArrayMetaData.GetCodePage: TSystemCodePage;
186     begin
187     Result := FCodePage;
188     end;
189    
190 tony 309 function TFB30ArrayMetaData.GetCharSetWidth: integer;
191     begin
192     Result := FCharSetWidth;
193     end;
194    
195 tony 45 { TFB30Array }
196    
197     procedure TFB30Array.AllocateBuffer;
198    
199     procedure AddVarInteger(aValue: integer);
200     begin
201     if (aValue >= -128) and (aValue <= 127) then
202     FSDL.Add(isc_sdl_tiny_integer).SetAsTinyInteger(aValue)
203     else
204     if (aValue >= -32768) and (aValue <= 32767) then
205     FSDL.Add(isc_sdl_short_integer).SetAsShortInteger(aValue)
206     else
207     FSDL.Add(isc_sdl_long_integer).SetAsInteger(aValue);
208     end;
209    
210     var i: integer;
211     SDLItem: ISDLItem;
212     begin
213     inherited AllocateBuffer;
214     {Now set up the SDL}
215    
216 tony 263 FSDL := TSDLBlock.Create(FFirebird30ClientAPI);
217 tony 45 with GetArrayDesc^ do
218     {The following is based on gen_SDL from Firebird src/dsql/array.cpp}
219     begin
220     SDLItem := FSDL.Add(isc_sdl_struct);
221     SDLItem.SetAsByte(array_desc_dtype);
222    
223     case array_desc_dtype of
224     blr_short,blr_long,
225     blr_int64,blr_quad:
226 tony 308 SDLItem.addShortInt(byte(array_desc_scale));
227 tony 45
228     blr_text,blr_cstring, blr_varying:
229     SDLItem.addShortInteger(array_desc_length);
230     end;
231    
232 tony 47 FSDL.Add(isc_sdl_relation).SetAsString(array_desc_relation_name);
233     FSDL.Add(isc_sdl_field).SetAsString(array_desc_field_name);
234 tony 45
235     for i := 0 to array_desc_dimensions - 1 do
236     begin
237     if array_desc_bounds[i].array_bound_lower = 1 then
238     FSDL.Add(isc_sdl_do1).SetAsTinyInteger(i)
239     else
240     begin
241     FSDL.Add(isc_sdl_do2).SetAsTinyInteger(i);
242     AddVarInteger(array_desc_bounds[i].array_bound_lower);
243     end;
244     AddVarInteger(array_desc_bounds[i].array_bound_upper);
245     end;
246    
247     SDLItem := FSDL.Add(isc_sdl_element);
248     SDLItem.AddByte(1);
249     SDLItem := FSDL.Add(isc_sdl_scalar);
250     SDLItem.AddByte(0);
251     SDLItem.AddByte(array_desc_dimensions);
252     for i := 0 to array_desc_dimensions - 1 do
253     begin
254     SDLItem := FSDL.Add(isc_sdl_variable);
255     SDLItem.AddByte(i);
256     end;
257     FSDL.Add(isc_sdl_eoc);
258     end;
259     end;
260    
261     procedure TFB30Array.InternalGetSlice;
262     begin
263 tony 263 with FFirebird30ClientAPI do
264 tony 45 begin
265     FAttachmentIntf.getSlice(StatusIntf,FTransactionIntf,
266     @FArrayID,
267     (FSDL as TSDLBlock).getDataLength,
268     BytePtr((FSDL as TSDLBlock).getBuffer),
269     0,nil,
270     FBufSize,BytePtr(FBuffer)
271     );
272     Check4DataBaseError;
273     end;
274     SignalActivity;
275     end;
276    
277     procedure TFB30Array.InternalPutSlice(Force: boolean);
278     begin
279 tony 263 with FFirebird30ClientAPI do
280 tony 45 begin
281     FAttachmentIntf.putSlice(StatusIntf,FTransactionIntf, @FArrayID,
282     (FSDL as TSDLBlock).getDataLength,
283     BytePtr((FSDL as TSDLBlock).getBuffer),
284     0,nil,
285     FBufSize,BytePtr(FBuffer)
286     );
287     if not Force then
288     Check4DataBaseError;
289     end;
290     SignalActivity;
291     end;
292    
293     constructor TFB30Array.Create(aAttachment: TFB30Attachment;
294     aTransaction: TFB30Transaction; aField: IArrayMetaData);
295     begin
296     inherited Create(aAttachment,aTransaction,aField);
297     FAttachmentIntf := aAttachment.AttachmentIntf;
298     FTransactionIntf := aTransaction.TransactionIntf;
299 tony 263 FFirebird30ClientAPI := aAttachment.Firebird30ClientAPI;
300 tony 45 end;
301    
302     constructor TFB30Array.Create(aAttachment: TFB30Attachment;
303     aTransaction: TFB30Transaction; aField: IArrayMetaData; ArrayID: TISC_QUAD);
304     begin
305     inherited Create(aAttachment,aTransaction,aField,ArrayID);
306     FAttachmentIntf := aAttachment.AttachmentIntf;
307     FTransactionIntf := aTransaction.TransactionIntf;
308 tony 263 FFirebird30ClientAPI := aAttachment.Firebird30ClientAPI;
309 tony 45 end;
310    
311     { TSDLBlock }
312    
313 tony 263 constructor TSDLBlock.Create(api: TFBClientAPI);
314 tony 45 begin
315 tony 263 inherited Create(api);
316 tony 45 FDataLength := 1;
317 tony 56 FBuffer^ := isc_sdl_version1;
318 tony 45 end;
319    
320     end.
321