1 | /* |
2 | * PROGRAM: Dynamic SQL runtime support |
3 | * MODULE: dsql.h |
4 | * DESCRIPTION: General Definitions for V4 DSQL module |
5 | * |
6 | * |
7 | * The contents of this file are subject to the Interbase Public |
8 | * License Version 1.0 (the "License"); you may not use this file |
9 | * except in compliance with the License. You may obtain a copy |
10 | * of the License at http://www.Inprise.com/IPL.html |
11 | * |
12 | * Software distributed under the License is distributed on an |
13 | * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express |
14 | * or implied. See the License for the specific language governing |
15 | * rights and limitations under the License. |
16 | * |
17 | * The Original Code was created by Inprise Corporation |
18 | * and its predecessors. Portions created by Inprise Corporation are |
19 | * Copyright (C) Inprise Corporation. |
20 | * |
21 | * All Rights Reserved. |
22 | * Contributor(s): ______________________________________. |
23 | * |
24 | * 2001.11.26 Claudio Valderrama: include udf_arguments and udf_flags |
25 | * in the udf struct, so we can load the arguments and check for |
26 | * collisions between dropping and redefining the udf concurrently. |
27 | * This closes SF Bug# 409769. |
28 | * 2002.10.29 Nickolay Samofatov: Added support for savepoints |
29 | * 2004.01.16 Vlad Horsun: added support for default parameters and |
30 | * EXECUTE BLOCK statement |
31 | * Adriano dos Santos Fernandes |
32 | */ |
33 | |
34 | #ifndef DSQL_DSQL_H |
35 | #define DSQL_DSQL_H |
36 | |
37 | #include "../jrd/RuntimeStatistics.h" |
38 | #include "../jrd/ntrace.h" |
39 | #include "../jrd/val.h" // Get rid of duplicated FUN_T enum. |
40 | #include "../jrd/Attachment.h" |
41 | #include "../dsql/BlrDebugWriter.h" |
42 | #include "../dsql/ddl_proto.h" |
43 | #include "../common/classes/array.h" |
44 | #include "../common/classes/GenericMap.h" |
45 | #include "../common/classes/MetaName.h" |
46 | #include "../common/classes/stack.h" |
47 | #include "../common/classes/auto.h" |
48 | #include "../common/classes/NestConst.h" |
49 | |
50 | #ifdef DEV_BUILD |
51 | // This macro enables DSQL tracing code |
52 | #define DSQL_DEBUG |
53 | #endif |
54 | |
55 | #ifdef DSQL_DEBUG |
56 | DEFINE_TRACE_ROUTINE(dsql_trace); |
57 | #endif |
58 | |
59 | // generic block used as header to all allocated structures |
60 | #include "../include/fb_blk.h" |
61 | |
62 | #include "../dsql/sym.h" |
63 | |
64 | #include "../jrd/EngineInterface.h" |
65 | |
66 | // Context aliases used in triggers |
67 | const char* const OLD_CONTEXT_NAME = "OLD" ; |
68 | const char* const NEW_CONTEXT_NAME = "NEW" ; |
69 | |
70 | const int OLD_CONTEXT_VALUE = 0; |
71 | const int NEW_CONTEXT_VALUE = 1; |
72 | |
73 | namespace Jrd |
74 | { |
75 | class Attachment; |
76 | class Database; |
77 | class DsqlCompilerScratch; |
78 | class DdlNode; |
79 | class RseNode; |
80 | class StmtNode; |
81 | class TransactionNode; |
82 | class ValueExprNode; |
83 | class ValueListNode; |
84 | class jrd_tra; |
85 | class jrd_req; |
86 | class blb; |
87 | struct bid; |
88 | |
89 | class dsql_ctx; |
90 | class dsql_msg; |
91 | class dsql_par; |
92 | class dsql_map; |
93 | class dsql_intlsym; |
94 | |
95 | typedef Firebird::Stack<dsql_ctx*> DsqlContextStack; |
96 | } |
97 | |
98 | namespace Firebird |
99 | { |
100 | class MetaName; |
101 | } |
102 | |
103 | //====================================================================== |
104 | // remaining node definitions for local processing |
105 | // |
106 | |
107 | /// Include definition of descriptor |
108 | |
109 | #include "../common/dsc.h" |
110 | |
111 | namespace Jrd { |
112 | |
113 | // blocks used to cache metadata |
114 | |
115 | // Database Block |
116 | class dsql_dbb : public pool_alloc<dsql_type_dbb> |
117 | { |
118 | public: |
119 | Firebird::GenericMap<Firebird::Pair<Firebird::Left< |
120 | Firebird::MetaName, class dsql_rel*> > > dbb_relations; // known relations in database |
121 | Firebird::GenericMap<Firebird::Pair<Firebird::Left< |
122 | Firebird::QualifiedName, class dsql_prc*> > > dbb_procedures; // known procedures in database |
123 | Firebird::GenericMap<Firebird::Pair<Firebird::Left< |
124 | Firebird::QualifiedName, class dsql_udf*> > > dbb_functions; // known functions in database |
125 | Firebird::GenericMap<Firebird::Pair<Firebird::Left< |
126 | Firebird::MetaName, class dsql_intlsym*> > > dbb_charsets; // known charsets in database |
127 | Firebird::GenericMap<Firebird::Pair<Firebird::Left< |
128 | Firebird::MetaName, class dsql_intlsym*> > > dbb_collations; // known collations in database |
129 | Firebird::GenericMap<Firebird::Pair<Firebird::NonPooled< |
130 | SSHORT, dsql_intlsym*> > > dbb_charsets_by_id; // charsets sorted by charset_id |
131 | Firebird::GenericMap<Firebird::Pair<Firebird::Left< |
132 | Firebird::string, class dsql_req*> > > dbb_cursors; // known cursors in database |
133 | |
134 | MemoryPool& dbb_pool; // The current pool for the dbb |
135 | Attachment* dbb_attachment; |
136 | Firebird::MetaName dbb_dfl_charset; |
137 | bool dbb_no_charset; |
138 | bool dbb_read_only; |
139 | USHORT dbb_db_SQL_dialect; |
140 | USHORT dbb_ods_version; // major ODS version number |
141 | USHORT dbb_minor_version; // minor ODS version number |
142 | |
143 | explicit dsql_dbb(MemoryPool& p) |
144 | : dbb_relations(p), |
145 | dbb_procedures(p), |
146 | dbb_functions(p), |
147 | dbb_charsets(p), |
148 | dbb_collations(p), |
149 | dbb_charsets_by_id(p), |
150 | dbb_cursors(p), |
151 | dbb_pool(p), |
152 | dbb_dfl_charset(p) |
153 | {} |
154 | |
155 | ~dsql_dbb(); |
156 | |
157 | MemoryPool* createPool() |
158 | { |
159 | return dbb_attachment->createPool(); |
160 | } |
161 | |
162 | void deletePool(MemoryPool* pool) |
163 | { |
164 | dbb_attachment->deletePool(pool); |
165 | } |
166 | }; |
167 | |
168 | //! Relation block |
169 | class dsql_rel : public pool_alloc<dsql_type_rel> |
170 | { |
171 | public: |
172 | explicit dsql_rel(MemoryPool& p) |
173 | : rel_name(p), |
174 | rel_owner(p) |
175 | { |
176 | } |
177 | |
178 | class dsql_fld* rel_fields; // Field block |
179 | //dsql_rel* rel_base_relation; // base relation for an updatable view |
180 | Firebird::MetaName rel_name; // Name of relation |
181 | Firebird::MetaName rel_owner; // Owner of relation |
182 | USHORT rel_id; // Relation id |
183 | USHORT rel_dbkey_length; |
184 | USHORT rel_flags; |
185 | }; |
186 | |
187 | // rel_flags bits |
188 | enum rel_flags_vals { |
189 | REL_new_relation = 1, // relation exists in sys tables, not committed yet |
190 | REL_dropped = 2, // relation has been dropped |
191 | REL_view = 4, // relation is a view |
192 | REL_external = 8, // relation is an external table |
193 | REL_creating = 16 // we are creating the bare relation in memory |
194 | }; |
195 | |
196 | class TypeClause |
197 | { |
198 | public: |
199 | TypeClause(MemoryPool& pool, const Firebird::MetaName& aCollate) |
200 | : dtype(dtype_unknown), |
201 | length(0), |
202 | scale(0), |
203 | subType(0), |
204 | segLength(0), |
205 | precision(0), |
206 | charLength(0), |
207 | charSetId(0), |
208 | collationId(0), |
209 | textType(0), |
210 | fullDomain(false), |
211 | notNull(false), |
212 | fieldSource(pool), |
213 | typeOfTable(pool), |
214 | typeOfName(pool), |
215 | collate(pool, aCollate), |
216 | charSet(pool), |
217 | subTypeName(pool, NULL), |
218 | flags(0), |
219 | elementDtype(0), |
220 | elementLength(0), |
221 | dimensions(0), |
222 | ranges(NULL), |
223 | explicitCollation(false) |
224 | { |
225 | } |
226 | |
227 | virtual ~TypeClause() |
228 | { |
229 | } |
230 | |
231 | public: |
232 | virtual void print(Firebird::string& text) const |
233 | { |
234 | text.printf("typeOfTable: '%s' typeOfName: '%s' notNull: %d fieldSource: '%s'" , |
235 | typeOfTable.c_str(), typeOfName.c_str(), notNull, fieldSource.c_str()); |
236 | } |
237 | |
238 | public: |
239 | USHORT dtype; |
240 | FLD_LENGTH length; |
241 | SSHORT scale; |
242 | SSHORT subType; |
243 | USHORT segLength; // Segment length for blobs |
244 | USHORT precision; // Precision for exact numeric types |
245 | USHORT charLength; // Length of field in characters |
246 | SSHORT charSetId; |
247 | SSHORT collationId; |
248 | SSHORT textType; |
249 | bool fullDomain; // Domain name without TYPE OF prefix |
250 | bool notNull; // NOT NULL was explicit specified |
251 | Firebird::MetaName fieldSource; |
252 | Firebird::MetaName typeOfTable; // TYPE OF table name |
253 | Firebird::MetaName typeOfName; // TYPE OF |
254 | Firebird::MetaName collate; |
255 | Firebird::MetaName charSet; // empty means not specified |
256 | Firebird::MetaName subTypeName; // Subtype name for later resolution |
257 | USHORT flags; |
258 | USHORT elementDtype; // Data type of array element |
259 | USHORT elementLength; // Length of array element |
260 | SSHORT dimensions; // Non-zero means array |
261 | ValueListNode* ranges; // ranges for multi dimension array |
262 | bool explicitCollation; // COLLATE was explicit specified |
263 | }; |
264 | |
265 | class dsql_fld : public TypeClause |
266 | { |
267 | public: |
268 | explicit dsql_fld(MemoryPool& p) |
269 | : TypeClause(p, NULL), |
270 | fld_next(NULL), |
271 | fld_relation(NULL), |
272 | fld_procedure(NULL), |
273 | fld_id(0), |
274 | fld_name(p) |
275 | { |
276 | } |
277 | |
278 | public: |
279 | void resolve(DsqlCompilerScratch* dsqlScratch, bool modifying = false) |
280 | { |
281 | DDL_resolve_intl_type(dsqlScratch, this, collate, modifying); |
282 | } |
283 | |
284 | public: |
285 | dsql_fld* fld_next; // Next field in relation |
286 | dsql_rel* fld_relation; // Parent relation |
287 | dsql_prc* fld_procedure; // Parent procedure |
288 | USHORT fld_id; // Field in in database |
289 | Firebird::MetaName fld_name; |
290 | }; |
291 | |
292 | // values used in fld_flags |
293 | |
294 | enum fld_flags_vals { |
295 | FLD_computed = 1, |
296 | FLD_national = 2, // field uses NATIONAL character set |
297 | FLD_nullable = 4, |
298 | FLD_system = 8 |
299 | }; |
300 | |
301 | //! Stored Procedure block |
302 | class dsql_prc : public pool_alloc<dsql_type_prc> |
303 | { |
304 | public: |
305 | explicit dsql_prc(MemoryPool& p) |
306 | : prc_name(p), |
307 | prc_owner(p) |
308 | { |
309 | } |
310 | |
311 | dsql_fld* prc_inputs; // Input parameters |
312 | dsql_fld* prc_outputs; // Output parameters |
313 | Firebird::QualifiedName prc_name; // Name of procedure |
314 | Firebird::MetaName prc_owner; // Owner of procedure |
315 | SSHORT prc_in_count; |
316 | SSHORT prc_def_count; // number of inputs with default values |
317 | SSHORT prc_out_count; |
318 | USHORT prc_id; // Procedure id |
319 | USHORT prc_flags; |
320 | bool prc_private; // Packaged private procedure |
321 | }; |
322 | |
323 | // prc_flags bits |
324 | |
325 | enum prc_flags_vals { |
326 | PRC_new_procedure = 1, // procedure is newly defined, not committed yet |
327 | PRC_dropped = 2, // procedure has been dropped |
328 | PRC_subproc = 4 // Sub procedure |
329 | }; |
330 | |
331 | //! User defined function block |
332 | class dsql_udf : public pool_alloc<dsql_type_udf> |
333 | { |
334 | public: |
335 | explicit dsql_udf(MemoryPool& p) |
336 | : udf_name(p), udf_arguments(p) |
337 | { |
338 | } |
339 | |
340 | USHORT udf_dtype; |
341 | SSHORT udf_scale; |
342 | SSHORT udf_sub_type; |
343 | USHORT udf_length; |
344 | SSHORT udf_character_set_id; |
345 | //USHORT udf_character_length; |
346 | USHORT udf_flags; |
347 | Firebird::QualifiedName udf_name; |
348 | Firebird::Array<dsc> udf_arguments; |
349 | bool udf_private; // Packaged private function |
350 | }; |
351 | |
352 | // udf_flags bits |
353 | |
354 | enum udf_flags_vals { |
355 | UDF_new_udf = 1, // udf is newly declared, not committed yet |
356 | UDF_dropped = 2, // udf has been dropped |
357 | UDF_subfunc = 4 // sub function |
358 | }; |
359 | |
360 | // Variables - input, output & local |
361 | |
362 | //! Variable block |
363 | class dsql_var : public Firebird::PermanentStorage |
364 | { |
365 | public: |
366 | enum Type |
367 | { |
368 | TYPE_INPUT, |
369 | TYPE_OUTPUT, |
370 | TYPE_LOCAL, |
371 | TYPE_HIDDEN |
372 | }; |
373 | |
374 | public: |
375 | explicit dsql_var(MemoryPool& p) |
376 | : PermanentStorage(p), |
377 | field(NULL), |
378 | type(TYPE_INPUT), |
379 | msgNumber(0), |
380 | msgItem(0), |
381 | number(0) |
382 | { |
383 | desc.clear(); |
384 | } |
385 | |
386 | dsql_fld* field; // Field on which variable is based |
387 | Type type; // Input, output, local or hidden variable |
388 | USHORT msgNumber; // Message number containing variable |
389 | USHORT msgItem; // Item number in message |
390 | USHORT number; // Local variable number |
391 | dsc desc; |
392 | }; |
393 | |
394 | |
395 | // Symbolic names for international text types |
396 | // (either collation or character set name) |
397 | |
398 | //! International symbol |
399 | class dsql_intlsym : public pool_alloc<dsql_type_intlsym> |
400 | { |
401 | public: |
402 | explicit dsql_intlsym(MemoryPool& p) |
403 | : intlsym_name(p) |
404 | { |
405 | } |
406 | |
407 | Firebird::MetaName intlsym_name; |
408 | USHORT intlsym_type; // what type of name |
409 | USHORT intlsym_flags; |
410 | SSHORT intlsym_ttype; // id of implementation |
411 | SSHORT intlsym_charset_id; |
412 | SSHORT intlsym_collate_id; |
413 | USHORT intlsym_bytes_per_char; |
414 | }; |
415 | |
416 | // values used in intlsym_flags |
417 | |
418 | enum intlsym_flags_vals { |
419 | INTLSYM_dropped = 1 // intlsym has been dropped |
420 | }; |
421 | |
422 | |
423 | // Compiled statement - shared by multiple requests. |
424 | class DsqlCompiledStatement : public Firebird::PermanentStorage |
425 | { |
426 | public: |
427 | enum Type // statement type |
428 | { |
429 | TYPE_SELECT, TYPE_SELECT_UPD, TYPE_INSERT, TYPE_DELETE, TYPE_UPDATE, TYPE_UPDATE_CURSOR, |
430 | TYPE_DELETE_CURSOR, TYPE_COMMIT, TYPE_ROLLBACK, TYPE_CREATE_DB, TYPE_DDL, TYPE_START_TRANS, |
431 | TYPE_EXEC_PROCEDURE, TYPE_COMMIT_RETAIN, TYPE_ROLLBACK_RETAIN, TYPE_SET_GENERATOR, |
432 | TYPE_SAVEPOINT, TYPE_EXEC_BLOCK, TYPE_SELECT_BLOCK |
433 | }; |
434 | |
435 | // Statement flags. |
436 | static const unsigned FLAG_ORPHAN = 0x01; |
437 | static const unsigned FLAG_NO_BATCH = 0x02; |
438 | //static const unsigned FLAG_BLR_VERSION4 = 0x04; |
439 | //static const unsigned FLAG_BLR_VERSION5 = 0x08; |
440 | static const unsigned FLAG_SELECTABLE = 0x10; |
441 | |
442 | public: |
443 | explicit DsqlCompiledStatement(MemoryPool& p) |
444 | : PermanentStorage(p), |
445 | type(TYPE_SELECT), |
446 | flags(0), |
447 | blrVersion(5), |
448 | sendMsg(NULL), |
449 | receiveMsg(NULL), |
450 | eof(NULL), |
451 | dbKey(NULL), |
452 | recVersion(NULL), |
453 | parentRecVersion(NULL), |
454 | parentDbKey(NULL), |
455 | parentRequest(NULL) |
456 | { |
457 | } |
458 | |
459 | public: |
460 | MemoryPool& getPool() { return PermanentStorage::getPool(); } |
461 | |
462 | Type getType() const { return type; } |
463 | void setType(Type value) { type = value; } |
464 | |
465 | ULONG getFlags() const { return flags; } |
466 | void setFlags(ULONG value) { flags = value; } |
467 | void addFlags(ULONG value) { flags |= value; } |
468 | |
469 | unsigned getBlrVersion() const { return blrVersion; } |
470 | void setBlrVersion(unsigned value) { blrVersion = value; } |
471 | |
472 | Firebird::RefStrPtr& getSqlText() { return sqlText; } |
473 | const Firebird::RefStrPtr& getSqlText() const { return sqlText; } |
474 | void setSqlText(Firebird::RefString* value) { sqlText = value; } |
475 | |
476 | dsql_msg* getSendMsg() { return sendMsg; } |
477 | const dsql_msg* getSendMsg() const { return sendMsg; } |
478 | void setSendMsg(dsql_msg* value) { sendMsg = value; } |
479 | |
480 | dsql_msg* getReceiveMsg() { return receiveMsg; } |
481 | const dsql_msg* getReceiveMsg() const { return receiveMsg; } |
482 | void setReceiveMsg(dsql_msg* value) { receiveMsg = value; } |
483 | |
484 | dsql_par* getEof() { return eof; } |
485 | const dsql_par* getEof() const { return eof; } |
486 | void setEof(dsql_par* value) { eof = value; } |
487 | |
488 | dsql_par* getDbKey() { return dbKey; } |
489 | const dsql_par* getDbKey() const { return dbKey; } |
490 | void setDbKey(dsql_par* value) { dbKey = value; } |
491 | |
492 | dsql_par* getRecVersion() { return recVersion; } |
493 | const dsql_par* getRecVersion() const { return recVersion; } |
494 | void setRecVersion(dsql_par* value) { recVersion = value; } |
495 | |
496 | dsql_par* getParentRecVersion() { return parentRecVersion; } |
497 | const dsql_par* getParentRecVersion() const { return parentRecVersion; } |
498 | void setParentRecVersion(dsql_par* value) { parentRecVersion = value; } |
499 | |
500 | dsql_par* getParentDbKey() { return parentDbKey; } |
501 | const dsql_par* getParentDbKey() const { return parentDbKey; } |
502 | void setParentDbKey(dsql_par* value) { parentDbKey = value; } |
503 | |
504 | dsql_req* getParentRequest() const { return parentRequest; } |
505 | void setParentRequest(dsql_req* value) { parentRequest = value; } |
506 | |
507 | private: |
508 | Type type; // Type of statement |
509 | ULONG flags; // generic flag |
510 | unsigned blrVersion; |
511 | Firebird::RefStrPtr sqlText; |
512 | dsql_msg* sendMsg; // Message to be sent to start request |
513 | dsql_msg* receiveMsg; // Per record message to be received |
514 | dsql_par* eof; // End of file parameter |
515 | dsql_par* dbKey; // Database key for current of |
516 | dsql_par* recVersion; // Record Version for current of |
517 | dsql_par* parentRecVersion; // parent record version |
518 | dsql_par* parentDbKey; // Parent database key for current of |
519 | dsql_req* parentRequest; // Source request, if cursor update |
520 | }; |
521 | |
522 | class dsql_req : public pool_alloc<dsql_type_req> |
523 | { |
524 | public: |
525 | static const unsigned FLAG_OPENED_CURSOR = 0x01; |
526 | |
527 | public: |
528 | explicit dsql_req(MemoryPool& pool); |
529 | |
530 | public: |
531 | MemoryPool& getPool() |
532 | { |
533 | return req_pool; |
534 | } |
535 | |
536 | jrd_tra* getTransaction() |
537 | { |
538 | return req_transaction; |
539 | } |
540 | |
541 | const DsqlCompiledStatement* getStatement() const |
542 | { |
543 | return statement; |
544 | } |
545 | |
546 | virtual void dsqlPass(thread_db* tdbb, DsqlCompilerScratch* scratch, |
547 | ntrace_result_t* traceResult) = 0; |
548 | |
549 | virtual void execute(thread_db* tdbb, jrd_tra** traHandle, |
550 | Firebird::IMessageMetadata* inMetadata, const UCHAR* inMsg, |
551 | Firebird::IMessageMetadata* outMetadata, UCHAR* outMsg, |
552 | bool singleton) = 0; |
553 | |
554 | virtual void setCursor(thread_db* tdbb, const TEXT* name); |
555 | |
556 | virtual bool fetch(thread_db* tdbb, UCHAR* buffer); |
557 | |
558 | static void destroy(thread_db* tdbb, dsql_req* request, bool drop); |
559 | |
560 | private: |
561 | MemoryPool& req_pool; |
562 | |
563 | public: |
564 | const DsqlCompiledStatement* statement; |
565 | Firebird::Array<DsqlCompiledStatement*> cursors; // Cursor update statements |
566 | |
567 | dsql_dbb* req_dbb; // DSQL attachment |
568 | jrd_tra* req_transaction; // JRD transaction |
569 | jrd_req* req_request; // JRD request |
570 | |
571 | unsigned req_flags; // flags |
572 | |
573 | Firebird::Array<UCHAR*> req_msg_buffers; |
574 | Firebird::string req_cursor; // Cursor name, if any |
575 | Firebird::GenericMap<Firebird::NonPooled<const dsql_par*, dsc> > req_user_descs; // SQLDA data type |
576 | |
577 | Firebird::AutoPtr<Jrd::RuntimeStatistics> req_fetch_baseline; // State of request performance counters when we reported it last time |
578 | SINT64 req_fetch_elapsed; // Number of clock ticks spent while fetching rows for this request since we reported it last time |
579 | SINT64 req_fetch_rowcount; // Total number of rows returned by this request |
580 | bool req_traced; // request is traced via TraceAPI |
581 | |
582 | JStatement* req_interface; |
583 | |
584 | protected: |
585 | // Request should never be destroyed using delete. |
586 | // It dies together with it's pool in release_request(). |
587 | ~dsql_req() |
588 | { |
589 | } |
590 | |
591 | // To avoid posix warning about missing public destructor declare |
592 | // MemoryPool as friend class. In fact IT releases request memory! |
593 | friend class Firebird::MemoryPool; |
594 | }; |
595 | |
596 | class DsqlDmlRequest : public dsql_req |
597 | { |
598 | public: |
599 | explicit DsqlDmlRequest(MemoryPool& pool, StmtNode* aNode) |
600 | : dsql_req(pool), |
601 | node(aNode) |
602 | { |
603 | } |
604 | |
605 | virtual void dsqlPass(thread_db* tdbb, DsqlCompilerScratch* scratch, |
606 | ntrace_result_t* traceResult); |
607 | |
608 | virtual void execute(thread_db* tdbb, jrd_tra** traHandle, |
609 | Firebird::IMessageMetadata* inMetadata, const UCHAR* inMsg, |
610 | Firebird::IMessageMetadata* outMetadata, UCHAR* outMsg, |
611 | bool singleton); |
612 | |
613 | virtual void setCursor(thread_db* tdbb, const TEXT* name); |
614 | |
615 | virtual bool fetch(thread_db* tdbb, UCHAR* buffer); |
616 | |
617 | private: |
618 | NestConst<StmtNode> node; |
619 | }; |
620 | |
621 | class DsqlDdlRequest : public dsql_req |
622 | { |
623 | public: |
624 | explicit DsqlDdlRequest(MemoryPool& pool, DdlNode* aNode) |
625 | : dsql_req(pool), |
626 | node(aNode), |
627 | internalScratch(NULL) |
628 | { |
629 | } |
630 | |
631 | virtual void dsqlPass(thread_db* tdbb, DsqlCompilerScratch* scratch, |
632 | ntrace_result_t* traceResult); |
633 | |
634 | virtual void execute(thread_db* tdbb, jrd_tra** traHandle, |
635 | Firebird::IMessageMetadata* inMetadata, const UCHAR* inMsg, |
636 | Firebird::IMessageMetadata* outMetadata, UCHAR* outMsg, |
637 | bool singleton); |
638 | |
639 | private: |
640 | NestConst<DdlNode> node; |
641 | DsqlCompilerScratch* internalScratch; |
642 | }; |
643 | |
644 | class DsqlTransactionRequest : public dsql_req |
645 | { |
646 | public: |
647 | explicit DsqlTransactionRequest(MemoryPool& pool, TransactionNode* aNode) |
648 | : dsql_req(pool), |
649 | node(aNode) |
650 | { |
651 | req_traced = false; |
652 | } |
653 | |
654 | virtual void dsqlPass(thread_db* tdbb, DsqlCompilerScratch* scratch, |
655 | ntrace_result_t* traceResult); |
656 | |
657 | virtual void execute(thread_db* tdbb, jrd_tra** traHandle, |
658 | Firebird::IMessageMetadata* inMetadata, const UCHAR* inMsg, |
659 | Firebird::IMessageMetadata* outMetadata, UCHAR* outMsg, |
660 | bool singleton); |
661 | |
662 | private: |
663 | NestConst<TransactionNode> node; |
664 | }; |
665 | |
666 | //! Implicit (NATURAL and USING) joins |
667 | class ImplicitJoin : public pool_alloc<dsql_type_imp_join> |
668 | { |
669 | public: |
670 | ValueExprNode* value; |
671 | dsql_ctx* visibleInContext; |
672 | }; |
673 | |
674 | struct PartitionMap |
675 | { |
676 | PartitionMap(ValueListNode* aPartition, ValueListNode* aOrder) |
677 | : partition(aPartition), |
678 | partitionRemapped(NULL), |
679 | order(aOrder), |
680 | map(NULL), |
681 | context(0) |
682 | { |
683 | } |
684 | |
685 | NestConst<ValueListNode> partition; |
686 | NestConst<ValueListNode> partitionRemapped; |
687 | NestConst<ValueListNode> order; |
688 | dsql_map* map; |
689 | USHORT context; |
690 | }; |
691 | |
692 | //! Context block used to create an instance of a relation reference |
693 | class dsql_ctx : public pool_alloc<dsql_type_ctx> |
694 | { |
695 | public: |
696 | explicit dsql_ctx(MemoryPool& p) |
697 | : ctx_alias(p), |
698 | ctx_internal_alias(p), |
699 | ctx_main_derived_contexts(p), |
700 | ctx_childs_derived_table(p), |
701 | ctx_imp_join(p), |
702 | ctx_win_maps(p) |
703 | { |
704 | } |
705 | |
706 | dsql_rel* ctx_relation; // Relation for context |
707 | dsql_prc* ctx_procedure; // Procedure for context |
708 | NestConst<ValueListNode> ctx_proc_inputs; // Procedure input parameters |
709 | dsql_map* ctx_map; // Maps for aggregates and unions |
710 | RseNode* ctx_rse; // Sub-rse for aggregates |
711 | dsql_ctx* ctx_parent; // Parent context for aggregates |
712 | USHORT ctx_context; // Context id |
713 | USHORT ctx_recursive; // Secondary context id for recursive UNION (nobody referred to this context) |
714 | USHORT ctx_scope_level; // Subquery level within this request |
715 | USHORT ctx_flags; // Various flag values |
716 | USHORT ctx_in_outer_join; // inOuterJoin when context was created |
717 | Firebird::string ctx_alias; // Context alias (can include concatenated derived table alias) |
718 | Firebird::string ctx_internal_alias; // Alias as specified in query |
719 | DsqlContextStack ctx_main_derived_contexts; // contexts used for blr_derived_expr |
720 | DsqlContextStack ctx_childs_derived_table; // Childs derived table context |
721 | Firebird::GenericMap<Firebird::Pair<Firebird::Left< |
722 | Firebird::MetaName, ImplicitJoin*> > > ctx_imp_join; // Map of USING fieldname to ImplicitJoin |
723 | Firebird::Array<PartitionMap*> ctx_win_maps; // Maps for window functions |
724 | |
725 | dsql_ctx& operator=(dsql_ctx& v) |
726 | { |
727 | ctx_relation = v.ctx_relation; |
728 | ctx_procedure = v.ctx_procedure; |
729 | ctx_proc_inputs = v.ctx_proc_inputs; |
730 | ctx_map = v.ctx_map; |
731 | ctx_rse = v.ctx_rse; |
732 | ctx_parent = v.ctx_parent; |
733 | ctx_alias = v.ctx_alias; |
734 | ctx_context = v.ctx_context; |
735 | ctx_recursive = v.ctx_recursive; |
736 | ctx_scope_level = v.ctx_scope_level; |
737 | ctx_flags = v.ctx_flags; |
738 | ctx_in_outer_join = v.ctx_in_outer_join; |
739 | ctx_main_derived_contexts.assign(v.ctx_main_derived_contexts); |
740 | ctx_childs_derived_table.assign(v.ctx_childs_derived_table); |
741 | ctx_imp_join.assign(v.ctx_imp_join); |
742 | ctx_win_maps.assign(v.ctx_win_maps); |
743 | |
744 | return *this; |
745 | } |
746 | |
747 | Firebird::string getObjectName() const |
748 | { |
749 | if (ctx_relation) |
750 | return ctx_relation->rel_name.c_str(); |
751 | if (ctx_procedure) |
752 | return ctx_procedure->prc_name.toString(); |
753 | return "" ; |
754 | } |
755 | |
756 | bool getImplicitJoinField(const Firebird::MetaName& name, NestConst<ValueExprNode>& node); |
757 | PartitionMap* getPartitionMap(DsqlCompilerScratch* dsqlScratch, |
758 | ValueListNode* partitionNode, ValueListNode* orderNode); |
759 | }; |
760 | |
761 | // Flag values for ctx_flags |
762 | |
763 | const USHORT CTX_outer_join = 0x01; // reference is part of an outer join |
764 | const USHORT CTX_system = 0x02; // Context generated by system (NEW/OLD in triggers, check-constraint, RETURNING) |
765 | const USHORT CTX_null = 0x04; // Fields of the context should be resolved to NULL constant |
766 | const USHORT CTX_returning = 0x08; // Context generated by RETURNING |
767 | const USHORT CTX_recursive = 0x10; // Context has secondary number (ctx_recursive) generated for recursive UNION |
768 | const USHORT CTX_view_with_check_store = 0x20; // Context of WITH CHECK OPTION view's store trigger |
769 | const USHORT CTX_view_with_check_modify = 0x40; // Context of WITH CHECK OPTION view's modify trigger |
770 | |
771 | //! Aggregate/union map block to map virtual fields to their base |
772 | //! TMN: NOTE! This datatype should definitely be renamed! |
773 | class dsql_map : public pool_alloc<dsql_type_map> |
774 | { |
775 | public: |
776 | dsql_map* map_next; // Next map in item |
777 | NestConst<ValueExprNode> map_node; // Value for map item |
778 | USHORT map_position; // Position in map |
779 | NestConst<PartitionMap> map_partition; // Partition |
780 | }; |
781 | |
782 | // Message block used in communicating with a running request |
783 | class dsql_msg : public Firebird::PermanentStorage |
784 | { |
785 | public: |
786 | explicit dsql_msg(MemoryPool& p) |
787 | : PermanentStorage(p), |
788 | msg_parameters(p), |
789 | msg_number(0), |
790 | msg_buffer_number(0), |
791 | msg_length(0), |
792 | msg_parameter(0), |
793 | msg_index(0) |
794 | { |
795 | } |
796 | |
797 | Firebird::Array<dsql_par*> msg_parameters; // Parameter list |
798 | USHORT msg_number; // Message number |
799 | USHORT msg_buffer_number; // Message buffer number (used instead of msg_number for blob msgs) |
800 | ULONG msg_length; // Message length |
801 | USHORT msg_parameter; // Next parameter number |
802 | USHORT msg_index; // Next index into SQLDA |
803 | }; |
804 | |
805 | // Parameter block used to describe a parameter of a message |
806 | class dsql_par : public Firebird::PermanentStorage |
807 | { |
808 | public: |
809 | explicit dsql_par(MemoryPool& p) |
810 | : PermanentStorage(p), |
811 | par_message(NULL), |
812 | par_null(NULL), |
813 | par_node(NULL), |
814 | par_dbkey_relname(p), |
815 | par_rec_version_relname(p), |
816 | par_name(p), |
817 | par_rel_name(p), |
818 | par_owner_name(p), |
819 | par_rel_alias(p), |
820 | par_alias(p), |
821 | par_parameter(0), |
822 | par_index(0), |
823 | par_is_text(false) |
824 | { |
825 | par_desc.clear(); |
826 | } |
827 | |
828 | dsql_msg* par_message; // Parent message |
829 | dsql_par* par_null; // Null parameter, if used |
830 | ValueExprNode* par_node; // Associated value node, if any |
831 | Firebird::MetaName par_dbkey_relname; // Context of internally requested dbkey |
832 | Firebird::MetaName par_rec_version_relname; // Context of internally requested rec. version |
833 | Firebird::MetaName par_name; // Parameter name, if any |
834 | Firebird::MetaName par_rel_name; // Relation name, if any |
835 | Firebird::MetaName par_owner_name; // Owner name, if any |
836 | Firebird::MetaName par_rel_alias; // Relation alias, if any |
837 | Firebird::MetaName par_alias; // Alias, if any |
838 | dsc par_desc; // Field data type |
839 | USHORT par_parameter; // BLR parameter number |
840 | USHORT par_index; // Index into SQLDA, if appropriate |
841 | bool par_is_text; // Parameter should be dtype_text (SQL_TEXT) externaly |
842 | }; |
843 | |
844 | class CStrCmp |
845 | { |
846 | public: |
847 | static int greaterThan(const char* s1, const char* s2) |
848 | { |
849 | return strcmp(s1, s2) > 0; |
850 | } |
851 | }; |
852 | |
853 | typedef Firebird::SortedArray<const char*, |
854 | Firebird::EmptyStorage<const char*>, const char*, |
855 | Firebird::DefaultKeyValue<const char*>, |
856 | CStrCmp> |
857 | StrArray; |
858 | |
859 | class IntlString |
860 | { |
861 | public: |
862 | IntlString(Firebird::MemoryPool& p, const Firebird::string& str, |
863 | const Firebird::MetaName& cs = NULL) |
864 | : charset(p, cs), |
865 | s(p, str) |
866 | { } |
867 | |
868 | explicit IntlString(const Firebird::string& str, const Firebird::MetaName& cs = NULL) |
869 | : charset(cs), |
870 | s(str) |
871 | { } |
872 | |
873 | IntlString(Firebird::MemoryPool& p, const IntlString& o) |
874 | : charset(p, o.charset), |
875 | s(p, o.s) |
876 | { } |
877 | |
878 | explicit IntlString(Firebird::MemoryPool& p) |
879 | : charset(p), |
880 | s(p) |
881 | { } |
882 | |
883 | Firebird::string toUtf8(DsqlCompilerScratch*) const; |
884 | |
885 | const Firebird::MetaName& getCharSet() const |
886 | { |
887 | return charset; |
888 | } |
889 | |
890 | void setCharSet(const Firebird::MetaName& value) |
891 | { |
892 | charset = value; |
893 | } |
894 | |
895 | const Firebird::string& getString() const |
896 | { |
897 | return s; |
898 | } |
899 | |
900 | bool hasData() const |
901 | { |
902 | return s.hasData(); |
903 | } |
904 | |
905 | bool isEmpty() const |
906 | { |
907 | return s.isEmpty(); |
908 | } |
909 | |
910 | private: |
911 | Firebird::MetaName charset; |
912 | Firebird::string s; |
913 | }; |
914 | |
915 | } // namespace |
916 | |
917 | /*! \var unsigned DSQL_debug |
918 | \brief Debug level |
919 | |
920 | 0 No output |
921 | 1 Display output tree in PASS1_statment |
922 | 2 Display input tree in PASS1_statment |
923 | 4 Display ddl BLR |
924 | 8 Display BLR |
925 | 16 Display PASS1_rse input tree |
926 | 32 Display SQL input string |
927 | 64 Display BLR in dsql/prepare |
928 | > 256 Display yacc parser output level = DSQL_level>>8 |
929 | */ |
930 | |
931 | #ifdef DSQL_DEBUG |
932 | extern unsigned DSQL_debug; |
933 | #endif |
934 | |
935 | #endif // DSQL_DSQL_H |
936 | |