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
56DEFINE_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
67const char* const OLD_CONTEXT_NAME = "OLD";
68const char* const NEW_CONTEXT_NAME = "NEW";
69
70const int OLD_CONTEXT_VALUE = 0;
71const int NEW_CONTEXT_VALUE = 1;
72
73namespace 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
98namespace 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
111namespace Jrd {
112
113// blocks used to cache metadata
114
115// Database Block
116class dsql_dbb : public pool_alloc<dsql_type_dbb>
117{
118public:
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
169class dsql_rel : public pool_alloc<dsql_type_rel>
170{
171public:
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
188enum 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
196class TypeClause
197{
198public:
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
231public:
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
238public:
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
265class dsql_fld : public TypeClause
266{
267public:
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
278public:
279 void resolve(DsqlCompilerScratch* dsqlScratch, bool modifying = false)
280 {
281 DDL_resolve_intl_type(dsqlScratch, this, collate, modifying);
282 }
283
284public:
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
294enum 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
302class dsql_prc : public pool_alloc<dsql_type_prc>
303{
304public:
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
325enum 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
332class dsql_udf : public pool_alloc<dsql_type_udf>
333{
334public:
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
354enum 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
363class dsql_var : public Firebird::PermanentStorage
364{
365public:
366 enum Type
367 {
368 TYPE_INPUT,
369 TYPE_OUTPUT,
370 TYPE_LOCAL,
371 TYPE_HIDDEN
372 };
373
374public:
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
399class dsql_intlsym : public pool_alloc<dsql_type_intlsym>
400{
401public:
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
418enum intlsym_flags_vals {
419 INTLSYM_dropped = 1 // intlsym has been dropped
420};
421
422
423// Compiled statement - shared by multiple requests.
424class DsqlCompiledStatement : public Firebird::PermanentStorage
425{
426public:
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
442public:
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
459public:
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
507private:
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
522class dsql_req : public pool_alloc<dsql_type_req>
523{
524public:
525 static const unsigned FLAG_OPENED_CURSOR = 0x01;
526
527public:
528 explicit dsql_req(MemoryPool& pool);
529
530public:
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
560private:
561 MemoryPool& req_pool;
562
563public:
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
584protected:
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
596class DsqlDmlRequest : public dsql_req
597{
598public:
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
617private:
618 NestConst<StmtNode> node;
619};
620
621class DsqlDdlRequest : public dsql_req
622{
623public:
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
639private:
640 NestConst<DdlNode> node;
641 DsqlCompilerScratch* internalScratch;
642};
643
644class DsqlTransactionRequest : public dsql_req
645{
646public:
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
662private:
663 NestConst<TransactionNode> node;
664};
665
666//! Implicit (NATURAL and USING) joins
667class ImplicitJoin : public pool_alloc<dsql_type_imp_join>
668{
669public:
670 ValueExprNode* value;
671 dsql_ctx* visibleInContext;
672};
673
674struct 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
693class dsql_ctx : public pool_alloc<dsql_type_ctx>
694{
695public:
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
763const USHORT CTX_outer_join = 0x01; // reference is part of an outer join
764const USHORT CTX_system = 0x02; // Context generated by system (NEW/OLD in triggers, check-constraint, RETURNING)
765const USHORT CTX_null = 0x04; // Fields of the context should be resolved to NULL constant
766const USHORT CTX_returning = 0x08; // Context generated by RETURNING
767const USHORT CTX_recursive = 0x10; // Context has secondary number (ctx_recursive) generated for recursive UNION
768const USHORT CTX_view_with_check_store = 0x20; // Context of WITH CHECK OPTION view's store trigger
769const 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!
773class dsql_map : public pool_alloc<dsql_type_map>
774{
775public:
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
783class dsql_msg : public Firebird::PermanentStorage
784{
785public:
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
806class dsql_par : public Firebird::PermanentStorage
807{
808public:
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
844class CStrCmp
845{
846public:
847 static int greaterThan(const char* s1, const char* s2)
848 {
849 return strcmp(s1, s2) > 0;
850 }
851};
852
853typedef Firebird::SortedArray<const char*,
854 Firebird::EmptyStorage<const char*>, const char*,
855 Firebird::DefaultKeyValue<const char*>,
856 CStrCmp>
857 StrArray;
858
859class IntlString
860{
861public:
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
910private:
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
932extern unsigned DSQL_debug;
933#endif
934
935#endif // DSQL_DSQL_H
936