ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/trunk/doc/readme.field+param.names
Revision: 19
Committed: Mon Jul 7 13:00:15 2014 UTC (9 years, 9 months ago) by tony
File size: 10528 byte(s)
Log Message:
Committing updates for Release R1-1-0

File Contents

# Content
1 IBX Field and Parameter Names
2 =============================
3
4 Column Names
5 ------------
6
7 Firebird identifiers are typically case insensitive and are converted to upper case when processed and reported. This translates into IBX always reporting upper case column names and matching column names to field names (e.g. in TDataSet.FieldByName) using a case insensitive match.
8
9 However, in SQL Dialect 3, Firebird introduced the ability to enclose identifiers in double qoutes. This is necessary if, for example, you want a column name that is the same as an SQL Reserved word. It also allows you to have case sensitive column names, or column names containing spaces.
10
11 For Example:
12
13 Create Table MY_TABLE (
14 "KeyField" Integer,
15 "GRANT" VarChar(32),
16 "My Column" Float
17 );
18
19 IBX could readily handle case sensitive column names and isn't bothered by SQL reserved words. However, it does have the problem that the Lazarus TDataSet model includes the ability to automatically generate TField properties and which are then added to the Form's list of properties. The name of the generated property is formed by concatenating the IBX object name with the column alias name.
20
21 Pascal identifiers are also case insensitive and this could cause problems if two column names differ only in the case of their letters: the generated property names will cause a compilation error. Neither can Pascal identifiers contain spaces.
22
23 IBX handles this by forcing all column names to upper case, regardless of how they are defined in SQL. It also replaces spaces by underscores. The identifiers given to Generated column properties are then both valid Pascal and unambiguous. However, it is still necessary to handle cases where two column names differ only in their case - forcing the column names to upper case will only result in a name clash.
24
25 On the other hand, column alias Names aren't always unique anyway. For example, in the SQL:
26
27 select sum(col1), sum(col2) from MyTable;
28
29 Firebird will generate the alias name "SUM" for both cases. It will also allow you to specify the same aliasname multiple times in the same statement.
30
31 IBX handles this by checking for non-unique aliasnames when the SQL is prepared and disambiguating the column names by adding a numerical suffix (starting from one) to each non-unique column name it finds after the first one. The same approach is used when non-unique column names result after forcing the column name to upper case.
32
33 For example, with a table defined as
34
35 Create Table MY_TABLE (
36 TableKey Integer not null,
37 "My Field" VarChar(32),
38 "MY Field" VarChar(32),
39 Primary Key(TableKey)
40 );
41
42 The column names used by IBX will be
43
44 TABLEKEY
45 MY_FIELD
46 MY_FIELD1
47
48 respectively.
49
50 IBQuery1.FieldByName('tableKey').AsInteger
51 IBQuery1.FieldByName('MY_FIELD').AsString
52 IBQuery1.FieldByName('my_field1').AsString
53
54 Are then all valid examples for accessing the column values using TIBQuery.FieldByName.
55
56 Parameter Names
57 ---------------
58
59 IBX supports both DSQL '?' and PSQL name style (e.g. :Param) parameters. In the latter case, these are case insensitive and can also be in a pseudo dialect 3 quoted format (e.g. :"MyParam"). Name based parameters need not be unique and when a non-unique parameter name is given in a call to ParamByName, each and every parameter with that name is set to the given value.
60
61 SQL Parameters defined using PSQL style names can then be set at run time using the ParamByName call. For example, if the select statement for a TIBQuery is
62
63 Select Col1, Col2 From MYTABLE Where Col3 = :ColValue;
64
65 Then, at run time, the parameter value can be set using
66
67 IBQuery1.ParamByName('COLVALUE').AsInteger := ...
68
69 or
70
71 IBQuery1.ParamByName('ColValue').AsInteger := ...
72
73 etc.
74
75 As with column names, parameter names are matched case insensitive.
76
77 Duplicate Parameter Names
78 -------------------------
79
80 Duplicate Parameter Names are supported by IBX and can be very useful. For example, an SQL Select Statement may be given as
81
82 Select Col1, Col2
83 From Table_A
84 Where Col3 = :arg1
85 UNION
86 Select Col4, Col5
87 From Table_B
88 Where Col6 = :arg1
89
90
91 In this case, "arg1" need only be set once. e.g.
92
93 IBQuery1.ParamByName('arg1').AsInteger := 3;
94
95 Both cases will be set to 3. This capability is particularly useful when using Master/Detail datasets linked by the Detail's DataSource property and the Detail is given by a query similar to the above.
96
97 OLD and NEW Parameters
98 ----------------------
99
100 These are typically used in Modify SQL statements (UPDATE) when a (e.g.) the primary key value is changed. In this case, the row to be updated needs to be selected by the original value of the primary key, while the column needs to be set to the new value. In order to support this capability, IBX allows parameter names to be prefixed by "OLD_" and "NEW_" where the former references the fields value when it was read from the dataset (i.e. before a call to TDataset.Edit), while the latter is the default and refers to the modified value set after a call to TDataset.Edit. For example, specify an Update SQL statement in the form:
101
102 UPDATE MYTABLE Set Key1 = :NEW_KEY1, COL2 = :COL2 Where Key1 = :OLD_KEY1;
103
104 to correctly handle database updates such as:
105
106 IBDataset1.Next;
107 IBDataset1.Edit;
108 IBDataset1.FieldByName('key1').AsInteger := <a new value>;
109 IBDataset1.Post;
110
111 Pseudo Dialect 3 Parameter Names (disabled by default)
112 --------------------------------
113
114 It is also possible to use a pseudo dialect 3 format parameter name e.g.
115
116 Select Col1, Col2 From MYTABLE Where Col3 = :"ColValue";
117
118 However, in this case, the double quotes are effectively ignored and the match is again made case insensitive. e.g.
119
120 IBQuery1.ParamByName('COLVALUE').AsInteger := ...
121
122 is a valid way to set the above parameter.
123
124
125 Enabling Support for Pseudo Dialect 3 Parameter Names
126 ------------------------------------------------------
127
128 Pseudo Dialect 3 quoted format parameter names are not believed to be very useful - but they do result in a significant client side processing overhead. The code to support these is now subject to conditional compilation and can hence be removed when not required. By default, pseudo dialect 3 format parameter names are disabled. To enable support, ALLOWDIALECT3PARAMNAMES should be defined when IBX is compiled. IBSQL.pas may be edited to make this change - see comments at this top of that file.
129
130 For example, to support an SQL statement in the format:
131
132 SELECT col1 From MYTABLE Where KeyID = :"MyKeyid";
133
134 and set using:
135
136 IBQuery1.ParamByName('"MyKeyid"').AsInteger := ...
137
138 you must define ALLOWDIALECT3PARAMNAMES at compilation time.
139
140 On the other hand, regardless of ALLOWDIALECT3PARAMNAMES
141
142 IBQuery1.ParamByName('MYKEYID').AsInteger := ...
143
144 will always work, even when double quotes are used in the SQL. Hence the limited utility of the format.
145
146 Disabling Case Insensitive Parameter Names
147 ------------------------------------------
148
149 Even when pseudo dialect 3 format parameter names are not supported, IBX still processes parameter names case insensitive. This does result in some additional overhead due to calls to "AnsiUpperCase". This can be avoided by undefining "UseCaseSensitiveParamName" - again in IBSQL.pas. In which case, with;
150
151 SELECT col1 From MYTABLE Where KeyID = :MyKeyid;
152
153 you can only set the input parameter with:
154
155 IBQuery1.ParamByName('MyKeyid').AsInteger := ...
156
157 i.e. the case of each character in the parameter name must match exactly.
158
159 Disabling Non-unique Parameter Name Support
160 -------------------------------------------
161
162 Non-unique parameter name support is generally very useful, However, it does impose an overhead each time a parameter is set as IBX has to pass through all the statement's parameters and check their names. When you know that all parameter names are unique and are using TIBSQL, this can be avoided by setting the TIBSQL.UniqueParamNames property to true at design time. This is a hint rather than a constraint and if set to true, IBX will simply not bother to check for more than one parameter with the same name - even if there is one.
163
164 Setting input parameter values by position
165 ------------------------------------------
166
167 Real speed freaks will probably want to use DSQL placeholders as these avoid all the overhead of name based lookups. To do this, you would will probably be using TIBSQL and have an SQL Statement in the form:
168
169 INSERT into MyTable (col1, col2) Values(?,?);
170
171 and set the input parameters positionally e.g.
172
173 IBSQL1.Params[0].AsInteger := ...
174 IBSQL1.Params[1].AsString := ...
175
176 Remember to set the "GenerateParamNames" property to true when doing this otherwise IBX will complain. In 1.1.0 onwards this is a published property.
177
178 Prior to 1.1.0, IBX would still check for other parameters with the same name(!) even when they were set positionally. This behaviour has been removed making this the fastest mode of use.
179
180 It is also possible to have mixed parameter naming e.g.
181
182 INSERT into MyTable (col1, col2) Values(:COL1,?);
183
184 You can then set the parameters using:
185
186 IBSQL1.ParamByName('col1').AsInteger := ...
187 IBSQL1.Params[1].AsString := ...
188
189 Note that the first DSQL format placeholder is index 1 as 'COL1' is index 0.
190
191 When you set TIBSQL.GenerateParamNames to true, each positional parameter is given a generated name in the format:
192
193 IBXParam<seqno>
194
195 where the <seqno> is incremented for each positional parameter, These are numbered from zero and named parameters are ignored when generating the sequence number. Thus in the above example, you could have set the positional parameter using:
196
197 IBSQL1.ParamByName('IBXParam0').AsString := ...
198
199 SQL Generation
200 --------------
201
202 IBX generates Firebird compliant SQL for you:
203
204 - when the "Generate SQL" button is clicked in a property editor.
205 - when a TIBTable is opened
206 - when a TIBStoredProc is executed.
207
208 The SQL generated for TIBTable and TIBStoredProc is not normally visible and the purpose of these objects is to hide the bother of SQL editing from users that are unfamiliar with SQL.
209
210 In all cases, the SQL is generated from the following rules:
211
212 a. Column Names are as specified in the Database Schema and, for Dialect 3 schemas, double quotes are used to delimit column names that contain spaces or are mixed or lower case or contain double quotes.
213
214 b. Parameter Names are always uppercase versions of the column name, if necessary disambiguated by adding a sequence number (starting from zero) to the end of the name. Any spaces or special characters are replaced by an underscore.
215
216 c. In update statements, parameter names in a "Where" clause are prefixed by "OLD_".
217
218
219
220
221
222
223
224
225