ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/trunk/fbintf/examples/SelectInto/UdrSelectInto.pas
Revision: 402
Committed: Mon Aug 1 10:07:24 2022 UTC (2 years, 4 months ago) by tony
Content type: text/x-pascal
File size: 5422 byte(s)
Log Message:
IBX Release 2.5.0

File Contents

# Content
1 unit UdrSelectInto;
2
3 {
4 create or alter procedure select_into (
5 select_statement blob sub_type 1 not null,
6 table_name varchar(63) not null,
7 table_type varchar(25) not null -- 'global temporary preserve', 'global temporary[ delete]', <empty string> for standard table
8 ) returns (
9 status varchar(100)
10 )
11 external name 'selectinto!select_into'
12 engine udr;
13 }
14
15 interface
16
17 uses Classes, SysUtils, IB, FBUDRController, FBUDRIntf;
18
19 type
20 TSelectInto = class(TFBUDRExecuteProcedure)
21 public
22 procedure Execute(context: IFBUDRExternalContext;
23 ProcMetadata: IFBUDRProcMetadata;
24 InputParams: IFBUDRInputParams;
25 OutputData: IFBUDROutputData); override;
26 end;
27
28
29 implementation
30
31 uses StrUtils, IBUtils;
32
33 function SQLType2Name(SQLType: Cardinal) : AnsiString;
34 begin
35 case SQLType of
36 SQL_VARYING: Result := 'VARCHAR';
37 SQL_TEXT: Result := 'CHAR';
38 SQL_DOUBLE: Result := 'DOUBLE PRECISION';
39 SQL_FLOAT: Result := 'FLOAT';
40 SQL_LONG: Result := 'INTEGER';
41 SQL_SHORT: Result := 'SMALLINT';
42 SQL_TIMESTAMP: Result := 'TIMESTAMP';
43 SQL_TIMESTAMP_TZ: Result := 'TIMESTAMP WITH TIMEZONE';
44 SQL_TIMESTAMP_TZ_EX: Result := 'TIMESTAMP WITH TIMEZONE';
45 SQL_BLOB: Result := 'BLOB';
46 SQL_D_FLOAT: Result := 'FLOAT';
47 SQL_TYPE_TIME: Result := 'TIME';
48 SQL_TYPE_DATE: Result := 'DATE';
49 SQL_INT64: Result := 'BIGINT';
50 SQL_TIME_TZ: Result := 'TIME WITH TIMEZONE';
51 SQL_TIME_TZ_EX: Result := 'TIME WITH TIMEZONE';
52 SQL_DEC16: Result := 'DECFLOAT(16)';
53 SQL_DEC34: Result := 'DECFLOAT(34)';
54 SQL_INT128: Result := 'INT128';
55 SQL_NULL: Result := 'VARCHAR(1)';
56 SQL_BOOLEAN: Result := 'BOOLEAN';
57 else
58 Result := 'UNKNOWN';
59 end
60 end;
61
62 function Fld2SQLTypeDef(SQLType: Cardinal; SubType: Integer; Size: Cardinal; Scale: Integer; CharSetClause: String) : AnsiString;
63 var
64 TypeDef: AnsiString;
65 begin
66 TypeDef := SQLType2Name(SQLType);
67
68 if Scale < 0 then
69 case SQLType of
70 SQL_SHORT: TypeDef := format('NUMERIC(4,%d)', [-Scale]);
71 SQL_LONG: TypeDef := format('NUMERIC(9,%d)', [-Scale]);
72 SQL_DOUBLE: TypeDef := format('NUMERIC(15,%d)', [-Scale]);
73 SQL_INT64: TypeDef := format('NUMERIC(18,%d)', [-Scale]);
74 SQL_INT128: TypeDef := format('NUMERIC(35,%d)', [-Scale]);
75 end
76 else
77 case SQLType of
78 SQL_VARYING,
79 SQL_TEXT: TypeDef := format(TypeDef + '(%d) %s', [Size, CharSetClause]);
80 SQL_BLOB: TypeDef := format(TypeDef + ' SUB_TYPE %d %s', [SubType, CharSetClause]);
81 end;
82 Result := TypeDef;
83 end;
84
85 procedure TSelectInto.Execute(context: IFBUDRExternalContext; ProcMetadata: IFBUDRProcMetadata; InputParams: IFBUDRInputParams; OutputData: IFBUDROutputData);
86 var
87 Statement: IStatement;
88 TX2: ITransaction;
89 Dialect, DefaultCharSetID, i: Integer;
90 SelectSQL, TableName, TableType: AnsiString;
91 TypeDef, TypeDefs, CharSetClause, Command, CommitAction, SQL: AnsiString;
92 begin
93 TypeDefs := '';
94 with context do
95 begin
96 // prepare and analyse select_statement and create DDL of target table columns
97 SelectSQL := InputParams.ByName('select_statement').AsString;
98 Dialect := GetAttachment.GetSQLDialect;
99 DefaultCharSetID := context.GetAttachment.getCharSetID;
100 CharSetClause := '';
101
102 Statement := GetAttachment.Prepare(GetTransaction, SelectSQL);
103 with Statement.MetaData do
104 begin
105 for i := 0 to Count -1 do
106 begin
107 with ColMetaData[i] do
108 begin
109 case GetSQLType of SQL_VARYING,
110 SQL_TEXT,
111 SQL_BLOB: if (DefaultCharSetID <> getCharSetID) then
112 CharSetClause := 'CHARACTER SET ' + GetAttachment.GetCharsetName(getCharSetID);
113 end;
114 TypeDef := Fld2SQLTypeDef(GetSQLType, SQLSubtype, Size, Scale, CharSetClause);
115 TypeDefs := TypeDefs + ','#13#10 + QuoteIdentifierIfNeeded(Dialect, Name) + ' ' + TypeDef;
116 end;
117 end;
118 Delete(TypeDefs, 1, 1);
119 end;
120
121 // create target table DDL
122 TableName := InputParams.ByName('table_name').AsString;
123 TableType := UpperCase(InputParams.ByName('table_type').AsString);
124
125 // default: recreate standard table
126 Command := 'RECREATE ';
127
128 // global temporary?
129 CommitAction := '';
130 if AnsiContainsStr(TableType, 'GLOBAL TEMPORARY') then
131 begin
132 Command := Command + 'GLOBAL TEMPORARY';
133 if AnsiContainsStr(TableType, 'PRESERVE') then
134 CommitAction := 'ON COMMIT PRESERVE ROWS';
135 end;
136
137 // create target table within own TX, needs to be committed separately
138 SQL := SQL + format('%s TABLE %s (%s) %s', [Command, TableName, TypeDefs, CommitAction]);
139 TX2 := GetAttachment.StartTransaction([isc_tpb_write, isc_tpb_nowait, isc_tpb_read_committed], taCommit);
140 GetAttachment.ExecImmediate(TX2, SQL);
141 TX2.Commit();
142
143 // fill target table
144 SQL := format('INSERT INTO %s %s;', [TableName, SelectSQL]);
145 GetAttachment.ExecImmediate(GetTransaction, SQL);
146 end;
147 OutputData.ByName('status').AsString := 'ok';
148 end;
149
150 initialization
151
152 FBRegisterUDRProcedure('select_into', TSelectInto);
153
154 end.

Properties

Name Value
svn:eol-style native