2001-05-23 15:26:42 +02:00
|
|
|
/*
|
|
|
|
* PROGRAM: Dynamic SQL runtime support
|
2003-10-05 08:27:16 +02:00
|
|
|
* MODULE: gen.cpp
|
2001-05-23 15:26:42 +02:00
|
|
|
* DESCRIPTION: Routines to generate BLR.
|
|
|
|
*
|
|
|
|
* The contents of this file are subject to the Interbase Public
|
|
|
|
* License Version 1.0 (the "License"); you may not use this file
|
|
|
|
* except in compliance with the License. You may obtain a copy
|
|
|
|
* of the License at http://www.Inprise.com/IPL.html
|
|
|
|
*
|
|
|
|
* Software distributed under the License is distributed on an
|
|
|
|
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
|
|
|
|
* or implied. See the License for the specific language governing
|
|
|
|
* rights and limitations under the License.
|
|
|
|
*
|
|
|
|
* The Original Code was created by Inprise Corporation
|
|
|
|
* and its predecessors. Portions created by Inprise Corporation are
|
|
|
|
* Copyright (C) Inprise Corporation.
|
|
|
|
*
|
|
|
|
* All Rights Reserved.
|
2002-06-29 08:56:51 +02:00
|
|
|
* Contributor(s): ______________________________________
|
|
|
|
* 2001.6.21 Claudio Valderrama: BREAK and SUBSTRING.
|
2002-09-28 16:04:35 +02:00
|
|
|
* 2001.07.28 John Bellardo: Added code to generate blr_skip.
|
|
|
|
* 2002.07.30 Arno Brinkman: Added code, procedures to generate COALESCE, CASE
|
|
|
|
* 2002.09.28 Dmitry Yemanov: Reworked internal_info stuff, enhanced
|
|
|
|
* exception handling in SPs/triggers,
|
|
|
|
* implemented ROWS_AFFECTED system variable
|
2002-10-29 21:20:44 +01:00
|
|
|
* 2002.10.21 Nickolay Samofatov: Added support for explicit pessimistic locks
|
|
|
|
* 2002.10.29 Nickolay Samofatov: Added support for savepoints
|
2003-11-02 13:28:30 +01:00
|
|
|
* 2003.10.05 Dmitry Yemanov: Added support for explicit cursors in PSQL
|
2008-09-27 11:51:53 +02:00
|
|
|
* 2004.01.16 Vlad Horsun: Added support for default parameters and
|
2004-01-16 11:43:21 +01:00
|
|
|
* EXECUTE BLOCK statement
|
2007-04-13 03:37:44 +02:00
|
|
|
* Adriano dos Santos Fernandes
|
2001-05-23 15:26:42 +02:00
|
|
|
*/
|
|
|
|
|
2001-07-30 01:43:24 +02:00
|
|
|
#include "firebird.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
#include <string.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "../dsql/dsql.h"
|
2008-02-28 14:48:16 +01:00
|
|
|
#include "../dsql/node.h"
|
2009-10-21 02:42:38 +02:00
|
|
|
#include "../dsql/DdlNodes.h"
|
2010-10-24 02:26:00 +02:00
|
|
|
#include "../dsql/ExprNodes.h"
|
2008-05-19 15:47:48 +02:00
|
|
|
#include "../dsql/StmtNodes.h"
|
2003-11-08 00:27:24 +01:00
|
|
|
#include "../jrd/ibase.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
#include "../jrd/align.h"
|
2005-05-28 00:45:31 +02:00
|
|
|
#include "../jrd/constants.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
#include "../jrd/intl.h"
|
2008-02-28 14:48:16 +01:00
|
|
|
#include "../jrd/jrd.h"
|
2006-07-20 11:57:04 +02:00
|
|
|
#include "../jrd/val.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
#include "../dsql/ddl_proto.h"
|
|
|
|
#include "../dsql/errd_proto.h"
|
|
|
|
#include "../dsql/gen_proto.h"
|
|
|
|
#include "../dsql/make_proto.h"
|
|
|
|
#include "../dsql/metd_proto.h"
|
2005-06-10 04:03:08 +02:00
|
|
|
#include "../dsql/utld_proto.h"
|
2005-05-28 00:45:31 +02:00
|
|
|
#include "../jrd/thread_proto.h"
|
2010-10-12 10:02:57 +02:00
|
|
|
#include "../common/dsc_proto.h"
|
|
|
|
#include "../yvalve/why_proto.h"
|
2001-07-30 01:43:24 +02:00
|
|
|
#include "gen/iberror.h"
|
2008-08-15 13:21:47 +02:00
|
|
|
#include "../common/StatusArg.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-02-28 14:48:16 +01:00
|
|
|
using namespace Jrd;
|
|
|
|
using namespace Dsql;
|
2008-08-15 13:21:47 +02:00
|
|
|
using namespace Firebird;
|
2008-02-28 14:48:16 +01:00
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
static void gen_aggregate(DsqlCompilerScratch*, const dsql_nod*);
|
|
|
|
static void gen_coalesce(DsqlCompilerScratch*, const dsql_nod*);
|
|
|
|
static void gen_error_condition(DsqlCompilerScratch*, const dsql_nod*);
|
|
|
|
static void gen_join_rse(DsqlCompilerScratch*, const dsql_nod*);
|
|
|
|
static void gen_map(DsqlCompilerScratch*, dsql_map*);
|
|
|
|
static void gen_plan(DsqlCompilerScratch*, const dsql_nod*);
|
|
|
|
static void gen_relation(DsqlCompilerScratch*, dsql_ctx*);
|
|
|
|
static void gen_searched_case(DsqlCompilerScratch*, const dsql_nod*);
|
2009-12-21 15:20:26 +01:00
|
|
|
static void gen_select(DsqlCompilerScratch*, dsql_nod*);
|
2009-12-20 22:01:10 +01:00
|
|
|
static void gen_simple_case(DsqlCompilerScratch*, const dsql_nod*);
|
|
|
|
static void gen_sort(DsqlCompilerScratch*, dsql_nod*);
|
|
|
|
static void gen_statement(DsqlCompilerScratch*, const dsql_nod*);
|
|
|
|
static void gen_table_lock(DsqlCompilerScratch*, const dsql_nod*, USHORT);
|
|
|
|
static void gen_union(DsqlCompilerScratch*, const dsql_nod*);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-02-12 20:28:13 +01:00
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
void GEN_hidden_variables(DsqlCompilerScratch* dsqlScratch, bool inExpression)
|
2008-08-15 18:32:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* G E N _ h i d d e n _ v a r i a b l e s
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Function
|
|
|
|
* Emit BLR for hidden variables.
|
|
|
|
*
|
|
|
|
**************************************/
|
2009-12-20 22:01:10 +01:00
|
|
|
if (dsqlScratch->hiddenVars.isEmpty())
|
2008-09-01 15:18:02 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
if (inExpression)
|
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_stmt_expr);
|
2009-12-20 22:01:10 +01:00
|
|
|
if (dsqlScratch->hiddenVars.getCount() > 1)
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_begin);
|
2008-09-01 15:18:02 +02:00
|
|
|
}
|
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
for (DsqlNodStack::const_iterator i(dsqlScratch->hiddenVars); i.hasData(); ++i)
|
2008-08-15 18:32:42 +02:00
|
|
|
{
|
2010-11-02 18:05:01 +01:00
|
|
|
const dsql_nod* varNod = i.object()->nod_arg[e_hidden_var_var];
|
|
|
|
const VariableNode* varNode = ExprNode::as<VariableNode>(varNod);
|
|
|
|
const dsql_var* var = varNode->dsqlVar;
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_dcl_variable);
|
|
|
|
dsqlScratch->appendUShort(var->var_variable_number);
|
2010-11-02 18:05:01 +01:00
|
|
|
GEN_descriptor(dsqlScratch, &varNode->varDesc, true);
|
2008-08-15 18:32:42 +02:00
|
|
|
}
|
2008-09-01 15:18:02 +02:00
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
if (inExpression && dsqlScratch->hiddenVars.getCount() > 1)
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_end);
|
2008-09-01 15:18:02 +02:00
|
|
|
|
|
|
|
// Clear it for GEN_expr not regenerate them.
|
2009-12-20 22:01:10 +01:00
|
|
|
dsqlScratch->hiddenVars.clear();
|
2008-08-15 18:32:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
GEN_expr
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
@brief Generate blr for an arbitrary expression.
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
@param dsqlScratch
|
2003-02-15 04:01:51 +01:00
|
|
|
@param node
|
|
|
|
|
|
|
|
**/
|
2009-12-20 22:01:10 +01:00
|
|
|
void GEN_expr(DsqlCompilerScratch* dsqlScratch, dsql_nod* node)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2008-07-02 11:46:44 +02:00
|
|
|
const dsql_ctx* context;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-01-06 06:53:34 +01:00
|
|
|
switch (node->nod_type)
|
|
|
|
{
|
2010-02-13 21:29:29 +01:00
|
|
|
case nod_class_exprnode:
|
|
|
|
{
|
2010-09-17 05:15:32 +02:00
|
|
|
ExprNode* exprNode = reinterpret_cast<ExprNode*>(node->nod_arg[0]);
|
|
|
|
exprNode->genBlr(dsqlScratch);
|
|
|
|
|
|
|
|
// Check whether the node we just processed is for a dialect 3
|
|
|
|
// operation which gives a different result than the corresponding
|
|
|
|
// operation in dialect 1. If it is, and if the client dialect is 2,
|
|
|
|
// issue a warning about the difference.
|
|
|
|
|
|
|
|
// ASF: Shouldn't we check nod_gen_id2 too?
|
|
|
|
|
|
|
|
if (exprNode->dsqlCompatDialectVerb &&
|
|
|
|
dsqlScratch->clientDialect == SQL_DIALECT_V6_TRANSITION)
|
|
|
|
{
|
|
|
|
dsc desc;
|
2010-11-01 01:42:12 +01:00
|
|
|
MAKE_desc(dsqlScratch, &desc, node);
|
2010-09-17 05:15:32 +02:00
|
|
|
|
|
|
|
if (desc.dsc_dtype == dtype_int64)
|
|
|
|
{
|
|
|
|
ERRD_post_warning(
|
|
|
|
Arg::Warning(isc_dsql_dialect_warning_expr) <<
|
|
|
|
Arg::Str(exprNode->dsqlCompatDialectVerb));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-02-13 21:29:29 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
case nod_alias:
|
2009-12-20 22:01:10 +01:00
|
|
|
GEN_expr(dsqlScratch, node->nod_arg[e_alias_value]);
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
case nod_aggregate:
|
2009-12-20 22:01:10 +01:00
|
|
|
gen_aggregate(dsqlScratch, node);
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
case nod_dom_value:
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_fid);
|
2010-06-22 02:53:35 +02:00
|
|
|
dsqlScratch->appendUChar(0); // Context
|
|
|
|
dsqlScratch->appendUShort(0); // Field id
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
case nod_join:
|
2009-12-20 22:01:10 +01:00
|
|
|
gen_join_rse(dsqlScratch, node);
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
case nod_relation:
|
2009-12-20 22:01:10 +01:00
|
|
|
gen_relation(dsqlScratch, (dsql_ctx*) node->nod_arg[e_rel_context]);
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
case nod_rse:
|
2010-02-22 17:00:49 +01:00
|
|
|
GEN_rse(dsqlScratch, node);
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
|
2003-08-15 01:34:37 +02:00
|
|
|
case nod_derived_table:
|
2010-02-22 17:00:49 +01:00
|
|
|
GEN_rse(dsqlScratch, node->nod_arg[e_derived_table_rse]);
|
2003-08-15 01:34:37 +02:00
|
|
|
return;
|
|
|
|
|
2008-09-27 11:51:53 +02:00
|
|
|
case nod_coalesce:
|
2009-12-20 22:01:10 +01:00
|
|
|
gen_coalesce(dsqlScratch, node);
|
2002-08-03 17:27:20 +02:00
|
|
|
return;
|
2008-09-27 11:51:53 +02:00
|
|
|
case nod_simple_case:
|
2009-12-20 22:01:10 +01:00
|
|
|
gen_simple_case(dsqlScratch, node);
|
2002-08-03 17:27:20 +02:00
|
|
|
return;
|
2008-09-27 11:51:53 +02:00
|
|
|
case nod_searched_case:
|
2009-12-20 22:01:10 +01:00
|
|
|
gen_searched_case(dsqlScratch, node);
|
2002-08-03 17:27:20 +02:00
|
|
|
return;
|
2008-07-03 09:12:36 +02:00
|
|
|
|
2008-08-20 03:54:45 +02:00
|
|
|
case nod_assign:
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_assignment);
|
2009-12-20 22:01:10 +01:00
|
|
|
GEN_expr(dsqlScratch, node->nod_arg[0]);
|
|
|
|
GEN_expr(dsqlScratch, node->nod_arg[1]);
|
2008-08-20 03:54:45 +02:00
|
|
|
return;
|
|
|
|
|
2008-09-01 15:18:02 +02:00
|
|
|
case nod_hidden_var:
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_stmt_expr);
|
2008-09-01 15:18:02 +02:00
|
|
|
|
|
|
|
// If it was not pre-declared, declare it now.
|
2009-12-20 22:01:10 +01:00
|
|
|
if (dsqlScratch->hiddenVars.hasData())
|
2008-09-01 15:18:02 +02:00
|
|
|
{
|
2010-11-02 18:05:01 +01:00
|
|
|
const VariableNode* varNode = ExprNode::as<VariableNode>(node->nod_arg[e_hidden_var_var]);
|
|
|
|
const dsql_var* var = varNode->dsqlVar;
|
2008-09-01 15:18:02 +02:00
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_begin);
|
|
|
|
dsqlScratch->appendUChar(blr_dcl_variable);
|
|
|
|
dsqlScratch->appendUShort(var->var_variable_number);
|
2010-11-02 18:05:01 +01:00
|
|
|
GEN_descriptor(dsqlScratch, &varNode->varDesc, true);
|
2008-09-01 15:18:02 +02:00
|
|
|
}
|
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_assignment);
|
2009-12-20 22:01:10 +01:00
|
|
|
GEN_expr(dsqlScratch, node->nod_arg[e_hidden_var_expr]);
|
|
|
|
GEN_expr(dsqlScratch, node->nod_arg[e_hidden_var_var]);
|
2008-09-01 15:18:02 +02:00
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
if (dsqlScratch->hiddenVars.hasData())
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_end);
|
2008-09-01 15:18:02 +02:00
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
GEN_expr(dsqlScratch, node->nod_arg[e_hidden_var_var]);
|
2008-09-01 15:18:02 +02:00
|
|
|
return;
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
default:
|
2008-08-15 13:21:47 +02:00
|
|
|
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-901) <<
|
|
|
|
Arg::Gds(isc_dsql_internal_err) <<
|
2008-09-27 11:51:53 +02:00
|
|
|
// expression evaluation not supported
|
|
|
|
Arg::Gds(isc_expression_eval_err) <<
|
|
|
|
Arg::Gds(isc_dsql_eval_unknode) << Arg::Num(node->nod_type));
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
GEN_port
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
@brief Generate a port from a message. Feel free to rearrange the
|
|
|
|
order of parameters.
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
@param dsqlScratch
|
2003-02-15 04:01:51 +01:00
|
|
|
@param message
|
|
|
|
|
|
|
|
**/
|
2009-12-20 22:01:10 +01:00
|
|
|
void GEN_port(DsqlCompilerScratch* dsqlScratch, dsql_msg* message)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2008-02-28 14:48:16 +01:00
|
|
|
thread_db* tdbb = JRD_get_thread_data();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_message);
|
|
|
|
dsqlScratch->appendUChar(message->msg_number);
|
|
|
|
dsqlScratch->appendUShort(message->msg_parameter);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2006-07-20 11:57:04 +02:00
|
|
|
ULONG offset = 0;
|
2009-12-19 19:50:38 +01:00
|
|
|
|
|
|
|
for (size_t i = 0; i < message->msg_parameters.getCount(); ++i)
|
2003-11-01 11:26:43 +01:00
|
|
|
{
|
2009-12-19 19:50:38 +01:00
|
|
|
dsql_par* parameter = message->msg_parameters[i];
|
|
|
|
|
|
|
|
parameter->par_parameter = (USHORT) i;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2007-07-08 10:43:30 +02:00
|
|
|
const USHORT fromCharSet = parameter->par_desc.getCharSet();
|
|
|
|
const USHORT toCharSet = (fromCharSet == CS_NONE || fromCharSet == CS_BINARY) ?
|
2009-10-21 02:42:38 +02:00
|
|
|
fromCharSet : tdbb->getCharSet();
|
2007-06-28 17:27:28 +02:00
|
|
|
|
|
|
|
if (parameter->par_desc.dsc_dtype <= dtype_any_text &&
|
2009-10-21 02:42:38 +02:00
|
|
|
tdbb->getCharSet() != CS_NONE && tdbb->getCharSet() != CS_BINARY)
|
2005-05-28 00:45:31 +02:00
|
|
|
{
|
2005-06-06 10:30:03 +02:00
|
|
|
USHORT adjust = 0;
|
2005-05-28 00:45:31 +02:00
|
|
|
if (parameter->par_desc.dsc_dtype == dtype_varying)
|
2005-06-06 10:30:03 +02:00
|
|
|
adjust = sizeof(USHORT);
|
2005-05-28 00:45:31 +02:00
|
|
|
else if (parameter->par_desc.dsc_dtype == dtype_cstring)
|
2005-06-06 10:30:03 +02:00
|
|
|
adjust = 1;
|
|
|
|
|
|
|
|
parameter->par_desc.dsc_length -= adjust;
|
2005-05-28 00:45:31 +02:00
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
const USHORT fromCharSetBPC = METD_get_charset_bpc(dsqlScratch->getTransaction(), fromCharSet);
|
|
|
|
const USHORT toCharSetBPC = METD_get_charset_bpc(dsqlScratch->getTransaction(), toCharSet);
|
2005-05-28 00:45:31 +02:00
|
|
|
|
2009-11-28 20:39:23 +01:00
|
|
|
parameter->par_desc.setTextType(INTL_CS_COLL_TO_TTYPE(toCharSet,
|
2006-01-15 19:11:31 +01:00
|
|
|
(fromCharSet == toCharSet ? INTL_GET_COLLATE(¶meter->par_desc) : 0)));
|
|
|
|
|
2005-05-28 00:45:31 +02:00
|
|
|
parameter->par_desc.dsc_length =
|
2005-06-10 04:03:08 +02:00
|
|
|
UTLD_char_length_to_byte_length(parameter->par_desc.dsc_length / fromCharSetBPC, toCharSetBPC);
|
2005-05-28 00:45:31 +02:00
|
|
|
|
2005-06-06 10:30:03 +02:00
|
|
|
parameter->par_desc.dsc_length += adjust;
|
2005-05-28 00:45:31 +02:00
|
|
|
}
|
2009-11-27 03:33:40 +01:00
|
|
|
else if (parameter->par_desc.dsc_dtype == dtype_blob &&
|
2007-07-08 10:43:30 +02:00
|
|
|
parameter->par_desc.dsc_sub_type == isc_blob_text &&
|
2009-10-21 02:42:38 +02:00
|
|
|
tdbb->getCharSet() != CS_NONE && tdbb->getCharSet() != CS_BINARY)
|
2007-06-28 17:27:28 +02:00
|
|
|
{
|
|
|
|
if (fromCharSet != toCharSet)
|
|
|
|
parameter->par_desc.setTextType(toCharSet);
|
|
|
|
}
|
2005-05-28 00:45:31 +02:00
|
|
|
|
2009-04-18 16:13:26 +02:00
|
|
|
// For older clients - generate an error should they try and
|
|
|
|
// access data types which did not exist in the older dialect
|
2009-12-20 22:01:10 +01:00
|
|
|
if (dsqlScratch->clientDialect <= SQL_DIALECT_V5)
|
2009-12-19 19:50:38 +01:00
|
|
|
{
|
2009-01-06 06:53:34 +01:00
|
|
|
switch (parameter->par_desc.dsc_dtype)
|
|
|
|
{
|
2009-04-18 16:13:26 +02:00
|
|
|
// In V6.0 - older clients, which we distinguish by
|
|
|
|
// their use of SQL DIALECT 0 or 1, are forbidden
|
|
|
|
// from selecting values of new datatypes
|
2003-02-10 20:57:57 +01:00
|
|
|
case dtype_sql_date:
|
|
|
|
case dtype_sql_time:
|
|
|
|
case dtype_int64:
|
2008-08-15 13:21:47 +02:00
|
|
|
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-804) <<
|
|
|
|
Arg::Gds(isc_dsql_datatype_err) <<
|
2009-01-06 06:53:34 +01:00
|
|
|
Arg::Gds(isc_sql_dialect_datatype_unsupport) <<
|
2009-12-20 22:01:10 +01:00
|
|
|
Arg::Num(dsqlScratch->clientDialect) <<
|
2009-01-06 06:53:34 +01:00
|
|
|
Arg::Str(DSC_dtype_tostring(parameter->par_desc.dsc_dtype)));
|
2003-02-10 20:57:57 +01:00
|
|
|
break;
|
|
|
|
default:
|
2008-09-27 11:51:53 +02:00
|
|
|
// No special action for other data types
|
2003-02-10 20:57:57 +01:00
|
|
|
break;
|
2004-11-07 11:38:13 +01:00
|
|
|
}
|
2009-12-19 19:50:38 +01:00
|
|
|
}
|
2009-01-07 10:30:57 +01:00
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
const USHORT align = type_alignments[parameter->par_desc.dsc_dtype];
|
2001-05-23 15:26:42 +02:00
|
|
|
if (align)
|
2006-07-20 11:57:04 +02:00
|
|
|
offset = FB_ALIGN(offset, align);
|
|
|
|
parameter->par_desc.dsc_address = (UCHAR*)(IPTR) offset;
|
|
|
|
offset += parameter->par_desc.dsc_length;
|
2009-12-20 22:01:10 +01:00
|
|
|
GEN_descriptor(dsqlScratch, ¶meter->par_desc, false);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2009-11-16 10:18:24 +01:00
|
|
|
if (offset > MAX_FORMAT_SIZE)
|
|
|
|
{
|
2008-08-15 13:21:47 +02:00
|
|
|
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-204) <<
|
|
|
|
Arg::Gds(isc_imp_exc) <<
|
|
|
|
Arg::Gds(isc_blktoobig));
|
2006-07-20 11:57:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
message->msg_length = (USHORT) offset;
|
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
dsqlScratch->ports.add(message);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
GEN_request
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
@brief Generate complete blr for a dsqlScratch.
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
@param dsqlScratch
|
2003-02-15 04:01:51 +01:00
|
|
|
@param node
|
|
|
|
|
|
|
|
**/
|
2010-06-15 18:07:58 +02:00
|
|
|
void GEN_request(DsqlCompilerScratch* scratch, dsql_nod* node)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2009-12-20 23:42:43 +01:00
|
|
|
DsqlCompiledStatement* statement = scratch->getStatement();
|
2009-12-20 22:01:10 +01:00
|
|
|
|
2009-12-23 01:57:08 +01:00
|
|
|
if (statement->getType() == DsqlCompiledStatement::TYPE_CREATE_DB ||
|
|
|
|
statement->getType() == DsqlCompiledStatement::TYPE_DDL)
|
2008-02-28 14:48:16 +01:00
|
|
|
{
|
2009-12-20 22:01:10 +01:00
|
|
|
DDL_generate(scratch, node);
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-12-23 01:57:08 +01:00
|
|
|
if (statement->getFlags() & DsqlCompiledStatement::FLAG_BLR_VERSION4)
|
2010-06-17 03:18:40 +02:00
|
|
|
scratch->appendUChar(blr_version4);
|
2001-05-23 15:26:42 +02:00
|
|
|
else
|
2010-06-17 03:18:40 +02:00
|
|
|
scratch->appendUChar(blr_version5);
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2009-12-23 01:57:08 +01:00
|
|
|
if (statement->getType() == DsqlCompiledStatement::TYPE_SAVEPOINT)
|
2002-10-29 21:20:44 +01:00
|
|
|
{
|
2009-12-20 23:42:43 +01:00
|
|
|
// Do not generate BEGIN..END block around savepoint statement
|
2002-10-29 21:20:44 +01:00
|
|
|
// to avoid breaking of savepoint logic
|
2009-12-22 16:36:10 +01:00
|
|
|
statement->setSendMsg(NULL);
|
|
|
|
statement->setReceiveMsg(NULL);
|
2009-12-20 22:01:10 +01:00
|
|
|
GEN_statement(scratch, node);
|
2008-09-27 11:51:53 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
scratch->appendUChar(blr_begin);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
GEN_hidden_variables(scratch, false);
|
2008-08-15 18:32:42 +02:00
|
|
|
|
2009-12-23 01:57:08 +01:00
|
|
|
switch (statement->getType())
|
2004-10-26 09:21:47 +02:00
|
|
|
{
|
2009-12-23 01:57:08 +01:00
|
|
|
case DsqlCompiledStatement::TYPE_SELECT:
|
|
|
|
case DsqlCompiledStatement::TYPE_SELECT_UPD:
|
2009-12-21 15:20:26 +01:00
|
|
|
gen_select(scratch, node);
|
2008-01-16 07:52:43 +01:00
|
|
|
break;
|
2009-12-23 01:57:08 +01:00
|
|
|
case DsqlCompiledStatement::TYPE_EXEC_BLOCK:
|
|
|
|
case DsqlCompiledStatement::TYPE_SELECT_BLOCK:
|
2009-12-20 22:01:10 +01:00
|
|
|
GEN_statement(scratch, node);
|
2008-01-16 07:52:43 +01:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
{
|
2009-12-22 16:36:10 +01:00
|
|
|
dsql_msg* message = statement->getSendMsg();
|
2008-01-16 07:52:43 +01:00
|
|
|
if (!message->msg_parameter)
|
2009-12-22 16:36:10 +01:00
|
|
|
statement->setSendMsg(NULL);
|
2009-11-16 10:18:24 +01:00
|
|
|
else
|
|
|
|
{
|
2009-12-20 22:01:10 +01:00
|
|
|
GEN_port(scratch, message);
|
2010-06-17 03:18:40 +02:00
|
|
|
scratch->appendUChar(blr_receive);
|
|
|
|
scratch->appendUChar(message->msg_number);
|
2008-01-16 07:52:43 +01:00
|
|
|
}
|
2009-12-22 16:36:10 +01:00
|
|
|
message = statement->getReceiveMsg();
|
2008-01-16 07:52:43 +01:00
|
|
|
if (!message->msg_parameter)
|
2009-12-22 16:36:10 +01:00
|
|
|
statement->setReceiveMsg(NULL);
|
2008-01-16 07:52:43 +01:00
|
|
|
else
|
2009-12-20 22:01:10 +01:00
|
|
|
GEN_port(scratch, message);
|
|
|
|
GEN_statement(scratch, node);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2008-09-27 11:51:53 +02:00
|
|
|
}
|
2010-06-17 03:18:40 +02:00
|
|
|
scratch->appendUChar(blr_end);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
scratch->appendUChar(blr_eoc);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
GEN_start_transaction
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
@brief Generate tpb for set transaction. Use blr string of dsqlScratch.
|
2003-02-15 04:01:51 +01:00
|
|
|
If a value is not specified, default is not STUFF'ed, let the
|
|
|
|
engine handle it.
|
|
|
|
Do not allow an option to be specified more than once.
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
@param dsqlScratch
|
2003-02-15 04:01:51 +01:00
|
|
|
@param tran_node
|
|
|
|
|
|
|
|
**/
|
2009-12-20 22:01:10 +01:00
|
|
|
void GEN_start_transaction( DsqlCompilerScratch* dsqlScratch, const dsql_nod* tran_node)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2003-11-01 11:26:43 +01:00
|
|
|
SSHORT count = tran_node->nod_count;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (!count)
|
|
|
|
return;
|
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
const dsql_nod* node = tran_node->nod_arg[0];
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (!node)
|
|
|
|
return;
|
|
|
|
|
2005-11-17 05:22:10 +01:00
|
|
|
// Find out isolation level - if specified. This is required for
|
|
|
|
// specifying the correct lock level in reserving clause.
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-08 00:27:24 +01:00
|
|
|
USHORT lock_level = isc_tpb_shared;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-01-07 10:30:57 +01:00
|
|
|
if (count = node->nod_count)
|
|
|
|
{
|
2009-11-16 10:18:24 +01:00
|
|
|
while (count--)
|
|
|
|
{
|
2003-11-01 11:26:43 +01:00
|
|
|
const dsql_nod* ptr = node->nod_arg[count];
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-06-06 04:25:35 +02:00
|
|
|
if (!ptr || ptr->nod_type != nod_isolation)
|
2001-05-23 15:26:42 +02:00
|
|
|
continue;
|
|
|
|
|
2009-01-06 06:53:34 +01:00
|
|
|
lock_level = (ptr->nod_flags & NOD_CONSISTENCY) ? isc_tpb_protected : isc_tpb_shared;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
bool sw_access = false, sw_wait = false, sw_isolation = false,
|
2005-11-17 05:22:10 +01:00
|
|
|
sw_reserve = false, sw_lock_timeout = false;
|
|
|
|
int misc_flags = 0;
|
2003-11-01 11:26:43 +01:00
|
|
|
|
2009-04-18 16:13:26 +02:00
|
|
|
// Stuff some version info.
|
2001-05-23 15:26:42 +02:00
|
|
|
if (count = node->nod_count)
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(isc_tpb_version1);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2005-11-17 05:22:10 +01:00
|
|
|
while (count--)
|
|
|
|
{
|
2003-11-01 11:26:43 +01:00
|
|
|
const dsql_nod* ptr = node->nod_arg[count];
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (!ptr)
|
|
|
|
continue;
|
|
|
|
|
2009-01-06 06:53:34 +01:00
|
|
|
switch (ptr->nod_type)
|
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
case nod_access:
|
|
|
|
if (sw_access)
|
2008-08-15 13:21:47 +02:00
|
|
|
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) <<
|
|
|
|
Arg::Gds(isc_dsql_dup_option));
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
sw_access = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
if (ptr->nod_flags & NOD_READ_ONLY)
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(isc_tpb_read);
|
2001-05-23 15:26:42 +02:00
|
|
|
else
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(isc_tpb_write);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case nod_wait:
|
|
|
|
if (sw_wait)
|
2008-08-15 13:21:47 +02:00
|
|
|
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) <<
|
|
|
|
Arg::Gds(isc_dsql_dup_option));
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
sw_wait = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
if (ptr->nod_flags & NOD_NO_WAIT)
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(isc_tpb_nowait);
|
2001-05-23 15:26:42 +02:00
|
|
|
else
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(isc_tpb_wait);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case nod_isolation:
|
|
|
|
if (sw_isolation)
|
2008-08-15 13:21:47 +02:00
|
|
|
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) <<
|
|
|
|
Arg::Gds(isc_dsql_dup_option));
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
sw_isolation = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (ptr->nod_flags & NOD_CONCURRENCY)
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(isc_tpb_concurrency);
|
2001-05-23 15:26:42 +02:00
|
|
|
else if (ptr->nod_flags & NOD_CONSISTENCY)
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(isc_tpb_consistency);
|
2009-11-16 10:18:24 +01:00
|
|
|
else
|
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(isc_tpb_read_committed);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-01-06 06:53:34 +01:00
|
|
|
if (ptr->nod_count && ptr->nod_arg[0] && ptr->nod_arg[0]->nod_type == nod_version)
|
2004-10-26 09:21:47 +02:00
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
if (ptr->nod_arg[0]->nod_flags & NOD_VERSION)
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(isc_tpb_rec_version);
|
2001-05-23 15:26:42 +02:00
|
|
|
else
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(isc_tpb_no_rec_version);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
else
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(isc_tpb_no_rec_version);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nod_reserve:
|
2003-11-01 11:26:43 +01:00
|
|
|
{
|
|
|
|
if (sw_reserve)
|
2008-08-15 13:21:47 +02:00
|
|
|
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) <<
|
|
|
|
Arg::Gds(isc_dsql_dup_option));
|
2003-11-01 11:26:43 +01:00
|
|
|
|
|
|
|
sw_reserve = true;
|
|
|
|
const dsql_nod* reserve = ptr->nod_arg[0];
|
|
|
|
|
2009-11-16 10:18:24 +01:00
|
|
|
if (reserve)
|
|
|
|
{
|
2003-11-01 11:26:43 +01:00
|
|
|
const dsql_nod* const* temp = reserve->nod_arg;
|
2009-01-06 06:53:34 +01:00
|
|
|
for (const dsql_nod* const* end = temp + reserve->nod_count; temp < end; temp++)
|
2003-11-01 11:26:43 +01:00
|
|
|
{
|
2009-12-20 22:01:10 +01:00
|
|
|
gen_table_lock(dsqlScratch, *temp, lock_level);
|
2003-11-01 11:26:43 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-01-07 10:30:57 +01:00
|
|
|
break;
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2005-11-17 05:22:10 +01:00
|
|
|
case nod_tra_misc:
|
|
|
|
if (misc_flags & ptr->nod_flags)
|
2008-08-15 13:21:47 +02:00
|
|
|
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) <<
|
|
|
|
Arg::Gds(isc_dsql_dup_option));
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2005-11-17 05:22:10 +01:00
|
|
|
misc_flags |= ptr->nod_flags;
|
|
|
|
if (ptr->nod_flags & NOD_NO_AUTO_UNDO)
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(isc_tpb_no_auto_undo);
|
2005-11-17 05:22:10 +01:00
|
|
|
else if (ptr->nod_flags & NOD_IGNORE_LIMBO)
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(isc_tpb_ignore_limbo);
|
2005-11-17 05:22:10 +01:00
|
|
|
else if (ptr->nod_flags & NOD_RESTART_REQUESTS)
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(isc_tpb_restart_requests);
|
2005-11-17 05:22:10 +01:00
|
|
|
break;
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2005-11-17 05:22:10 +01:00
|
|
|
case nod_lock_timeout:
|
|
|
|
if (sw_lock_timeout)
|
2008-08-15 13:21:47 +02:00
|
|
|
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) <<
|
|
|
|
Arg::Gds(isc_dsql_dup_option));
|
2005-11-17 05:22:10 +01:00
|
|
|
|
|
|
|
sw_lock_timeout = true;
|
2010-10-24 02:26:00 +02:00
|
|
|
if (ptr->nod_count == 1 && ExprNode::is<LiteralNode>(ptr->nod_arg[0]))
|
2005-11-17 05:22:10 +01:00
|
|
|
{
|
2010-10-24 02:26:00 +02:00
|
|
|
const int lck_timeout = (int) ExprNode::as<LiteralNode>(ptr->nod_arg[0])->getSlong();
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(isc_tpb_lock_timeout);
|
|
|
|
dsqlScratch->appendUChar(2);
|
|
|
|
dsqlScratch->appendUShort(lck_timeout);
|
2005-11-17 05:22:10 +01:00
|
|
|
}
|
|
|
|
break;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
default:
|
2008-08-15 13:21:47 +02:00
|
|
|
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) <<
|
|
|
|
Arg::Gds(isc_dsql_tran_err));
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
}
|
2010-06-17 03:18:40 +02:00
|
|
|
|
|
|
|
// Store DYN data in the statement.
|
2010-06-17 18:06:54 +02:00
|
|
|
dsqlScratch->getStatement()->setDdlData(dsqlScratch->getBlrData());
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
GEN_statement
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
@brief Generate blr for an arbitrary expression.
|
2006-05-31 20:02:34 +02:00
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
@param dsqlScratch
|
2003-02-15 04:01:51 +01:00
|
|
|
@param node
|
|
|
|
|
|
|
|
**/
|
2009-12-20 22:01:10 +01:00
|
|
|
void GEN_statement( DsqlCompilerScratch* dsqlScratch, dsql_nod* node)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2003-11-01 11:26:43 +01:00
|
|
|
dsql_nod* temp;
|
|
|
|
dsql_nod** ptr;
|
|
|
|
const dsql_nod* const* end;
|
2003-11-10 10:16:38 +01:00
|
|
|
dsql_str* string;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-01-06 06:53:34 +01:00
|
|
|
switch (node->nod_type)
|
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
case nod_assign:
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_assignment);
|
2009-12-20 22:01:10 +01:00
|
|
|
GEN_expr(dsqlScratch, node->nod_arg[0]);
|
|
|
|
GEN_expr(dsqlScratch, node->nod_arg[1]);
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
case nod_block:
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_block);
|
2009-12-20 22:01:10 +01:00
|
|
|
GEN_statement(dsqlScratch, node->nod_arg[e_blk_action]);
|
2009-11-16 10:18:24 +01:00
|
|
|
if (node->nod_count > 1)
|
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
temp = node->nod_arg[e_blk_errs];
|
2009-01-06 06:53:34 +01:00
|
|
|
for (ptr = temp->nod_arg, end = ptr + temp->nod_count; ptr < end; ptr++)
|
2003-11-01 11:26:43 +01:00
|
|
|
{
|
2009-12-20 22:01:10 +01:00
|
|
|
GEN_statement(dsqlScratch, *ptr);
|
2003-11-01 11:26:43 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_end);
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
|
2010-02-13 21:29:29 +01:00
|
|
|
case nod_class_stmtnode:
|
2009-11-16 10:18:24 +01:00
|
|
|
{
|
2010-02-13 21:29:29 +01:00
|
|
|
DmlNode* dmlNode = reinterpret_cast<DmlNode*>(node->nod_arg[0]);
|
2010-09-17 05:15:32 +02:00
|
|
|
dmlNode->genBlr(dsqlScratch);
|
2009-11-16 10:18:24 +01:00
|
|
|
}
|
2010-02-13 21:29:29 +01:00
|
|
|
return;
|
2008-01-16 07:52:43 +01:00
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
case nod_set_generator:
|
|
|
|
case nod_set_generator2:
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_set_generator);
|
2003-11-10 10:16:38 +01:00
|
|
|
string = (dsql_str*) node->nod_arg[e_gen_id_name];
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNullString(string->str_data);
|
2009-12-20 22:01:10 +01:00
|
|
|
GEN_expr(dsqlScratch, node->nod_arg[e_gen_id_value]);
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
case nod_list:
|
2008-08-15 18:32:42 +02:00
|
|
|
if (!(node->nod_flags & NOD_SIMPLE_LIST))
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_begin);
|
2009-01-06 06:53:34 +01:00
|
|
|
for (ptr = node->nod_arg, end = ptr + node->nod_count; ptr < end; ptr++)
|
2003-11-01 11:26:43 +01:00
|
|
|
{
|
2009-12-20 22:01:10 +01:00
|
|
|
GEN_statement(dsqlScratch, *ptr);
|
2003-11-01 11:26:43 +01:00
|
|
|
}
|
2008-08-15 18:32:42 +02:00
|
|
|
if (!(node->nod_flags & NOD_SIMPLE_LIST))
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_end);
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
|
2006-05-31 20:02:34 +02:00
|
|
|
case nod_erase:
|
|
|
|
case nod_erase_current:
|
2001-05-23 15:26:42 +02:00
|
|
|
case nod_modify:
|
|
|
|
case nod_modify_current:
|
2006-05-31 20:02:34 +02:00
|
|
|
case nod_store:
|
2009-12-20 22:01:10 +01:00
|
|
|
gen_statement(dsqlScratch, node);
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
case nod_on_error:
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_error_handler);
|
2001-05-23 15:26:42 +02:00
|
|
|
temp = node->nod_arg[e_err_errs];
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUShort(temp->nod_count);
|
2009-01-06 06:53:34 +01:00
|
|
|
for (ptr = temp->nod_arg, end = ptr + temp->nod_count; ptr < end; ptr++)
|
2003-11-01 11:26:43 +01:00
|
|
|
{
|
2009-12-20 22:01:10 +01:00
|
|
|
gen_error_condition(dsqlScratch, *ptr);
|
2003-11-01 11:26:43 +01:00
|
|
|
}
|
2009-12-20 22:01:10 +01:00
|
|
|
GEN_statement(dsqlScratch, node->nod_arg[e_err_action]);
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
|
2006-06-02 10:03:22 +02:00
|
|
|
case nod_breakleave:
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_leave);
|
|
|
|
dsqlScratch->appendUChar((int)(IPTR) node->nod_arg[e_breakleave_label]->nod_arg[e_label_number]);
|
2009-10-21 02:42:38 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
case nod_continue:
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_continue_loop);
|
|
|
|
dsqlScratch->appendUChar((int)(IPTR) node->nod_arg[e_continue_label]->nod_arg[e_label_number]);
|
2006-06-02 10:03:22 +02:00
|
|
|
return;
|
2002-12-18 16:01:50 +01:00
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
case nod_start_savepoint:
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_start_savepoint);
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
case nod_end_savepoint:
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_end_savepoint);
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
2003-06-10 15:40:19 +02:00
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
case nod_while:
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_label);
|
2010-06-22 02:53:35 +02:00
|
|
|
dsqlScratch->appendUChar((int)(IPTR) node->nod_arg[e_while_label]->nod_arg[e_label_number]);
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_loop);
|
|
|
|
dsqlScratch->appendUChar(blr_begin);
|
|
|
|
dsqlScratch->appendUChar(blr_if);
|
2009-12-20 22:01:10 +01:00
|
|
|
GEN_expr(dsqlScratch, node->nod_arg[e_while_cond]);
|
|
|
|
GEN_statement(dsqlScratch, node->nod_arg[e_while_action]);
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_leave);
|
2010-06-22 02:53:35 +02:00
|
|
|
dsqlScratch->appendUChar((int)(IPTR) node->nod_arg[e_while_label]->nod_arg[e_label_number]);
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_end);
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
case nod_sqlcode:
|
|
|
|
case nod_gdscode:
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_abort);
|
2009-12-20 22:01:10 +01:00
|
|
|
gen_error_condition(dsqlScratch, node);
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
|
2003-11-02 13:28:30 +01:00
|
|
|
case nod_cursor:
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_dcl_cursor);
|
2010-06-22 02:53:35 +02:00
|
|
|
dsqlScratch->appendUShort((int)(IPTR) node->nod_arg[e_cur_number]);
|
2009-10-31 07:17:49 +01:00
|
|
|
if (node->nod_arg[e_cur_scroll])
|
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_scrollable);
|
2009-10-31 07:17:49 +01:00
|
|
|
}
|
2010-02-22 17:00:49 +01:00
|
|
|
GEN_rse(dsqlScratch, node->nod_arg[e_cur_rse]);
|
2006-03-07 18:52:33 +01:00
|
|
|
temp = node->nod_arg[e_cur_rse]->nod_arg[e_rse_items];
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUShort(temp->nod_count);
|
2006-03-07 18:52:33 +01:00
|
|
|
ptr = temp->nod_arg;
|
|
|
|
end = ptr + temp->nod_count;
|
|
|
|
while (ptr < end) {
|
2009-12-20 22:01:10 +01:00
|
|
|
GEN_expr(dsqlScratch, *ptr++);
|
2006-03-07 18:52:33 +01:00
|
|
|
}
|
2003-11-02 13:28:30 +01:00
|
|
|
return;
|
|
|
|
|
2006-07-04 16:44:43 +02:00
|
|
|
case nod_src_info:
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->putDebugSrcInfo(node->nod_line, node->nod_column);
|
2009-12-20 22:01:10 +01:00
|
|
|
GEN_statement(dsqlScratch, node->nod_arg[e_src_info_stmt]);
|
2006-07-04 16:44:43 +02:00
|
|
|
return;
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
default:
|
2008-08-15 13:21:47 +02:00
|
|
|
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-901) <<
|
|
|
|
Arg::Gds(isc_dsql_internal_err) <<
|
|
|
|
// gen.c: node not supported
|
|
|
|
Arg::Gds(isc_node_err));
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
gen_aggregate
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
@brief Generate blr for a relation reference.
|
|
|
|
|
2008-09-27 11:51:53 +02:00
|
|
|
|
|
|
|
@param
|
|
|
|
@param
|
2003-02-15 04:01:51 +01:00
|
|
|
|
|
|
|
**/
|
2009-12-20 22:01:10 +01:00
|
|
|
static void gen_aggregate( DsqlCompilerScratch* dsqlScratch, const dsql_nod* node)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2009-10-21 02:42:38 +02:00
|
|
|
dsql_ctx* context = (dsql_ctx*) node->nod_arg[e_agg_context];
|
2010-01-19 18:18:13 +01:00
|
|
|
const bool window = (node->nod_flags & NOD_AGG_WINDOW);
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar((window ? blr_window : blr_aggregate));
|
2010-01-19 18:18:13 +01:00
|
|
|
|
2010-01-18 22:37:47 +01:00
|
|
|
if (!window)
|
2010-11-14 18:25:48 +01:00
|
|
|
GEN_stuff_context(dsqlScratch, context);
|
2010-01-19 18:18:13 +01:00
|
|
|
|
2010-02-22 17:00:49 +01:00
|
|
|
GEN_rse(dsqlScratch, node->nod_arg[e_agg_rse]);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-10-21 02:42:38 +02:00
|
|
|
// Handle PARTITION BY and GROUP BY clause
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-10-21 02:42:38 +02:00
|
|
|
if (window)
|
|
|
|
{
|
2010-01-21 19:33:18 +01:00
|
|
|
fb_assert(context->ctx_win_maps.hasData());
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(context->ctx_win_maps.getCount()); // number of windows
|
2010-01-18 22:37:47 +01:00
|
|
|
|
2010-01-21 19:33:18 +01:00
|
|
|
for (Array<PartitionMap*>::iterator i = context->ctx_win_maps.begin();
|
|
|
|
i != context->ctx_win_maps.end();
|
|
|
|
++i)
|
2010-01-18 22:37:47 +01:00
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_partition_by);
|
2010-01-18 22:37:47 +01:00
|
|
|
dsql_nod* partition = (*i)->partition;
|
|
|
|
dsql_nod* partitionRemapped = (*i)->partitionRemapped;
|
2010-01-23 04:02:53 +01:00
|
|
|
dsql_nod* order = (*i)->order;
|
2010-01-18 22:37:47 +01:00
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar((*i)->context);
|
2010-01-18 22:37:47 +01:00
|
|
|
|
|
|
|
if (partition)
|
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(partition->nod_count); // partition by expression count
|
2010-01-18 22:37:47 +01:00
|
|
|
|
|
|
|
dsql_nod** ptr = partition->nod_arg;
|
|
|
|
for (const dsql_nod* const* end = ptr + partition->nod_count; ptr < end; ++ptr)
|
|
|
|
GEN_expr(dsqlScratch, *ptr);
|
|
|
|
|
|
|
|
ptr = partitionRemapped->nod_arg;
|
|
|
|
for (const dsql_nod* const* end = ptr + partitionRemapped->nod_count; ptr < end; ++ptr)
|
|
|
|
GEN_expr(dsqlScratch, *ptr);
|
|
|
|
}
|
|
|
|
else
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(0); // partition by expression count
|
2010-01-18 22:37:47 +01:00
|
|
|
|
2010-01-23 04:02:53 +01:00
|
|
|
if (order)
|
|
|
|
gen_sort(dsqlScratch, order);
|
|
|
|
else
|
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_sort);
|
|
|
|
dsqlScratch->appendUChar(0);
|
2010-01-23 04:02:53 +01:00
|
|
|
}
|
|
|
|
|
2010-01-18 22:37:47 +01:00
|
|
|
gen_map(dsqlScratch, (*i)->map);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2009-10-21 02:42:38 +02:00
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_group_by);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-10-21 02:42:38 +02:00
|
|
|
dsql_nod* list = node->nod_arg[e_agg_group];
|
2009-11-16 10:18:24 +01:00
|
|
|
if (list != NULL)
|
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(list->nod_count);
|
2009-10-21 02:42:38 +02:00
|
|
|
dsql_nod** ptr = list->nod_arg;
|
|
|
|
for (const dsql_nod* const* end = ptr + list->nod_count; ptr < end; ptr++)
|
2009-12-20 22:01:10 +01:00
|
|
|
GEN_expr(dsqlScratch, *ptr);
|
2003-11-01 11:26:43 +01:00
|
|
|
}
|
2009-10-21 02:42:38 +02:00
|
|
|
else
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(0);
|
2010-01-19 18:18:13 +01:00
|
|
|
|
2010-01-21 19:33:18 +01:00
|
|
|
gen_map(dsqlScratch, context->ctx_map);
|
2010-01-18 22:37:47 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
gen_coalesce
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
@brief Generate BLR for coalesce function
|
2003-03-31 21:11:55 +02:00
|
|
|
|
|
|
|
Generate the blr values, begin with a cast and then :
|
|
|
|
|
|
|
|
blr_value_if
|
|
|
|
blr_missing
|
|
|
|
blr for expression 1
|
|
|
|
blr_value_if
|
|
|
|
blr_missing
|
2005-06-03 23:14:35 +02:00
|
|
|
blr for expression n-1
|
|
|
|
expression n
|
2003-03-31 21:11:55 +02:00
|
|
|
blr for expression n-1
|
2003-02-15 04:01:51 +01:00
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
@param dsqlScratch
|
2003-02-15 04:01:51 +01:00
|
|
|
@param node
|
|
|
|
|
|
|
|
**/
|
2009-12-20 22:01:10 +01:00
|
|
|
static void gen_coalesce( DsqlCompilerScratch* dsqlScratch, const dsql_nod* node)
|
2002-08-03 17:27:20 +02:00
|
|
|
{
|
2003-03-31 21:11:55 +02:00
|
|
|
// blr_value_if is used for building the coalesce function
|
2003-11-01 11:26:43 +01:00
|
|
|
dsql_nod* list = node->nod_arg[0];
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_cast);
|
2009-12-20 22:01:10 +01:00
|
|
|
GEN_descriptor(dsqlScratch, &node->nod_desc, true);
|
2003-11-01 11:26:43 +01:00
|
|
|
dsql_nod* const* ptr = list->nod_arg;
|
2009-01-06 06:53:34 +01:00
|
|
|
for (const dsql_nod* const* const end = ptr + (list->nod_count - 1); ptr < end; ptr++)
|
2002-08-03 17:27:20 +02:00
|
|
|
{
|
2003-03-31 21:11:55 +02:00
|
|
|
// IF (expression IS NULL) THEN
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_value_if);
|
|
|
|
dsqlScratch->appendUChar(blr_missing);
|
2009-12-20 22:01:10 +01:00
|
|
|
GEN_expr(dsqlScratch, *ptr);
|
2002-08-03 17:27:20 +02:00
|
|
|
}
|
2003-03-31 21:11:55 +02:00
|
|
|
// Return values
|
2009-12-20 22:01:10 +01:00
|
|
|
GEN_expr(dsqlScratch, *ptr);
|
2003-03-31 21:11:55 +02:00
|
|
|
list = node->nod_arg[1];
|
2003-11-01 11:26:43 +01:00
|
|
|
const dsql_nod* const* const begin = list->nod_arg;
|
|
|
|
ptr = list->nod_arg + list->nod_count;
|
2003-03-31 21:11:55 +02:00
|
|
|
// if all expressions are NULL return NULL
|
2003-11-01 11:26:43 +01:00
|
|
|
for (ptr--; ptr >= begin; ptr--)
|
2002-08-03 17:27:20 +02:00
|
|
|
{
|
2009-12-20 22:01:10 +01:00
|
|
|
GEN_expr(dsqlScratch, *ptr);
|
2002-08-03 17:27:20 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2008-08-15 18:32:42 +02:00
|
|
|
GEN_descriptor
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
@brief Generate a blr descriptor from an internal descriptor.
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
@param dsqlScratch
|
2003-02-15 04:01:51 +01:00
|
|
|
@param desc
|
|
|
|
@param texttype
|
|
|
|
|
|
|
|
**/
|
2009-12-20 22:01:10 +01:00
|
|
|
void GEN_descriptor( DsqlCompilerScratch* dsqlScratch, const dsc* desc, bool texttype)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2009-01-06 06:53:34 +01:00
|
|
|
switch (desc->dsc_dtype)
|
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
case dtype_text:
|
2009-11-16 10:18:24 +01:00
|
|
|
if (texttype || desc->dsc_ttype() == ttype_binary || desc->dsc_ttype() == ttype_none)
|
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_text2);
|
|
|
|
dsqlScratch->appendUShort(desc->dsc_ttype());
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2009-11-16 10:18:24 +01:00
|
|
|
else
|
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_text2); // automatic transliteration
|
|
|
|
dsqlScratch->appendUShort(ttype_dynamic);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUShort(desc->dsc_length);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_varying:
|
2009-11-16 10:18:24 +01:00
|
|
|
if (texttype || desc->dsc_ttype() == ttype_binary || desc->dsc_ttype() == ttype_none)
|
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_varying2);
|
|
|
|
dsqlScratch->appendUShort(desc->dsc_ttype());
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2009-11-16 10:18:24 +01:00
|
|
|
else
|
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_varying2); // automatic transliteration
|
|
|
|
dsqlScratch->appendUShort(ttype_dynamic);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUShort(desc->dsc_length - sizeof(USHORT));
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_short:
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_short);
|
|
|
|
dsqlScratch->appendUChar(desc->dsc_scale);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_long:
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_long);
|
|
|
|
dsqlScratch->appendUChar(desc->dsc_scale);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_quad:
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_quad);
|
|
|
|
dsqlScratch->appendUChar(desc->dsc_scale);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_int64:
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_int64);
|
|
|
|
dsqlScratch->appendUChar(desc->dsc_scale);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_real:
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_float);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_double:
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_double);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_sql_date:
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_sql_date);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_sql_time:
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_sql_time);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_timestamp:
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_timestamp);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_array:
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_quad);
|
|
|
|
dsqlScratch->appendUChar(0);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
2007-05-22 04:14:20 +02:00
|
|
|
case dtype_blob:
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_blob2);
|
|
|
|
dsqlScratch->appendUShort(desc->dsc_sub_type);
|
|
|
|
dsqlScratch->appendUShort(desc->getTextType());
|
2007-05-22 04:14:20 +02:00
|
|
|
break;
|
|
|
|
|
2010-12-18 03:17:06 +01:00
|
|
|
case dtype_boolean:
|
|
|
|
dsqlScratch->appendUChar(blr_bool);
|
|
|
|
break;
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
default:
|
2008-09-27 11:51:53 +02:00
|
|
|
// don't understand dtype
|
2008-08-15 13:21:47 +02:00
|
|
|
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-804) <<
|
|
|
|
Arg::Gds(isc_dsql_datatype_err));
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
gen_error_condition
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
@brief Generate blr for an error condtion
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
@param dsqlScratch
|
2003-02-15 04:01:51 +01:00
|
|
|
@param node
|
|
|
|
|
|
|
|
**/
|
2009-12-20 22:01:10 +01:00
|
|
|
static void gen_error_condition( DsqlCompilerScratch* dsqlScratch, const dsql_nod* node)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2003-11-10 10:16:38 +01:00
|
|
|
const dsql_str* string;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-01-06 06:53:34 +01:00
|
|
|
switch (node->nod_type)
|
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
case nod_sqlcode:
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_sql_code);
|
|
|
|
dsqlScratch->appendUShort((USHORT)(IPTR) node->nod_arg[0]);
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
case nod_gdscode:
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_gds_code);
|
2003-11-10 10:16:38 +01:00
|
|
|
string = (dsql_str*) node->nod_arg[0];
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNullString(string->str_data);
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
case nod_exception:
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_exception);
|
2003-11-10 10:16:38 +01:00
|
|
|
string = (dsql_str*) node->nod_arg[0];
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNullString(string->str_data);
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
case nod_default:
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_default_code);
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
default:
|
2003-11-04 00:59:24 +01:00
|
|
|
fb_assert(false);
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
gen_join_rse
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
@brief Generate a record selection expression
|
|
|
|
with an explicit join type.
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
@param dsqlScratch
|
2003-02-15 04:01:51 +01:00
|
|
|
@param rse
|
|
|
|
|
|
|
|
**/
|
2009-12-20 22:01:10 +01:00
|
|
|
static void gen_join_rse( DsqlCompilerScratch* dsqlScratch, const dsql_nod* rse)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_rs_stream);
|
|
|
|
dsqlScratch->appendUChar(2);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
GEN_expr(dsqlScratch, rse->nod_arg[e_join_left_rel]);
|
|
|
|
GEN_expr(dsqlScratch, rse->nod_arg[e_join_rght_rel]);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
const dsql_nod* node = rse->nod_arg[e_join_type];
|
2009-01-06 06:53:34 +01:00
|
|
|
if (node->nod_type != nod_join_inner)
|
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_join_type);
|
2001-05-23 15:26:42 +02:00
|
|
|
if (node->nod_type == nod_join_left)
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_left);
|
2001-05-23 15:26:42 +02:00
|
|
|
else if (node->nod_type == nod_join_right)
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_right);
|
2001-05-23 15:26:42 +02:00
|
|
|
else
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_full);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2004-10-13 20:37:53 +02:00
|
|
|
if (rse->nod_arg[e_join_boolean])
|
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_boolean);
|
2009-12-20 22:01:10 +01:00
|
|
|
GEN_expr(dsqlScratch, rse->nod_arg[e_join_boolean]);
|
2004-10-13 20:37:53 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_end);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
gen_map
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
@brief Generate a value map for a record selection expression.
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
@param dsqlScratch
|
2003-02-15 04:01:51 +01:00
|
|
|
@param map
|
|
|
|
|
|
|
|
**/
|
2009-12-20 22:01:10 +01:00
|
|
|
static void gen_map( DsqlCompilerScratch* dsqlScratch, dsql_map* map)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2003-11-01 11:26:43 +01:00
|
|
|
USHORT count = 0;
|
|
|
|
dsql_map* temp;
|
2001-05-23 15:26:42 +02:00
|
|
|
for (temp = map; temp; temp = temp->map_next)
|
2010-01-18 22:37:47 +01:00
|
|
|
++count;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_map);
|
|
|
|
dsqlScratch->appendUShort(count);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-11-16 10:18:24 +01:00
|
|
|
for (temp = map; temp; temp = temp->map_next)
|
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUShort(temp->map_position);
|
2009-12-20 22:01:10 +01:00
|
|
|
GEN_expr(dsqlScratch, temp->map_node);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-09 03:57:37 +02:00
|
|
|
// Generate a parameter reference.
|
|
|
|
void GEN_parameter( DsqlCompilerScratch* dsqlScratch, const dsql_par* parameter)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2003-11-01 11:26:43 +01:00
|
|
|
const dsql_msg* message = parameter->par_message;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-02-02 12:02:12 +01:00
|
|
|
const dsql_par* null = parameter->par_null;
|
2009-11-16 10:18:24 +01:00
|
|
|
if (null != NULL)
|
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_parameter2);
|
|
|
|
dsqlScratch->appendUChar(message->msg_number);
|
|
|
|
dsqlScratch->appendUShort(parameter->par_parameter);
|
|
|
|
dsqlScratch->appendUShort(null->par_parameter);
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_parameter);
|
|
|
|
dsqlScratch->appendUChar(message->msg_number);
|
|
|
|
dsqlScratch->appendUShort(parameter->par_parameter);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
gen_plan
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
@brief Generate blr for an access plan expression.
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
@param dsqlScratch
|
2003-02-15 04:01:51 +01:00
|
|
|
@param plan_expression
|
|
|
|
|
|
|
|
**/
|
2009-12-20 22:01:10 +01:00
|
|
|
static void gen_plan( DsqlCompilerScratch* dsqlScratch, const dsql_nod* plan_expression)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2009-04-18 16:13:26 +02:00
|
|
|
// stuff the join type
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-01-19 10:25:29 +01:00
|
|
|
const dsql_nod* list = plan_expression->nod_arg[0];
|
2009-11-16 10:18:24 +01:00
|
|
|
if (list->nod_count > 1)
|
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_join);
|
|
|
|
dsqlScratch->appendUChar(list->nod_count);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2009-04-18 16:13:26 +02:00
|
|
|
// stuff one or more plan items
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
const dsql_nod* const* ptr = list->nod_arg;
|
2009-01-06 06:53:34 +01:00
|
|
|
for (const dsql_nod* const* const end = ptr + list->nod_count; ptr < end; ptr++)
|
2003-11-01 11:26:43 +01:00
|
|
|
{
|
|
|
|
const dsql_nod* node = *ptr;
|
2009-11-16 10:18:24 +01:00
|
|
|
if (node->nod_type == nod_plan_expr)
|
|
|
|
{
|
2009-12-20 22:01:10 +01:00
|
|
|
gen_plan(dsqlScratch, node);
|
2001-05-23 15:26:42 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2008-09-27 11:51:53 +02:00
|
|
|
// if we're here, it must be a nod_plan_item
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_retrieve);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-04-18 16:13:26 +02:00
|
|
|
// stuff the relation--the relation id itself is redundant except
|
|
|
|
// when there is a need to differentiate the base tables of views
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
const dsql_nod* arg = node->nod_arg[0];
|
2009-12-20 22:01:10 +01:00
|
|
|
gen_relation(dsqlScratch, (dsql_ctx*) arg->nod_arg[e_rel_context]);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-09-27 11:51:53 +02:00
|
|
|
// now stuff the access method for this stream
|
2003-11-10 10:16:38 +01:00
|
|
|
const dsql_str* index_string;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
arg = node->nod_arg[1];
|
2009-01-06 06:53:34 +01:00
|
|
|
switch (arg->nod_type)
|
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
case nod_natural:
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_sequential);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case nod_index_order:
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_navigational);
|
2003-11-10 10:16:38 +01:00
|
|
|
index_string = (dsql_str*) arg->nod_arg[0];
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNullString(index_string->str_data);
|
2003-09-14 17:37:05 +02:00
|
|
|
if (!arg->nod_arg[1])
|
|
|
|
break;
|
|
|
|
// dimitr: FALL INTO, if the plan item is ORDER ... INDEX (...)
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
case nod_index:
|
2003-11-01 11:26:43 +01:00
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_indices);
|
2009-01-06 06:53:34 +01:00
|
|
|
arg = (arg->nod_type == nod_index) ? arg->nod_arg[0] : arg->nod_arg[1];
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(arg->nod_count);
|
2003-11-01 11:26:43 +01:00
|
|
|
const dsql_nod* const* ptr2 = arg->nod_arg;
|
2009-01-06 06:53:34 +01:00
|
|
|
for (const dsql_nod* const* const end2 = ptr2 + arg->nod_count; ptr2 < end2; ptr2++)
|
2003-11-01 11:26:43 +01:00
|
|
|
{
|
2003-11-10 10:16:38 +01:00
|
|
|
index_string = (dsql_str*) * ptr2;
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNullString(index_string->str_data);
|
2003-11-01 11:26:43 +01:00
|
|
|
}
|
|
|
|
break;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
2003-11-04 00:59:24 +01:00
|
|
|
fb_assert(false);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
gen_relation
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
@brief Generate blr for a relation reference.
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
@param dsqlScratch
|
2003-02-15 04:01:51 +01:00
|
|
|
@param context
|
|
|
|
|
|
|
|
**/
|
2009-12-20 22:01:10 +01:00
|
|
|
static void gen_relation( DsqlCompilerScratch* dsqlScratch, dsql_ctx* context)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2003-11-01 11:26:43 +01:00
|
|
|
const dsql_rel* relation = context->ctx_relation;
|
|
|
|
const dsql_prc* procedure = context->ctx_procedure;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-09-27 11:51:53 +02:00
|
|
|
// if this is a trigger or procedure, don't want relation id used
|
2009-01-06 06:53:34 +01:00
|
|
|
if (relation)
|
|
|
|
{
|
2009-12-20 22:01:10 +01:00
|
|
|
if (DDL_ids(dsqlScratch))
|
2009-11-16 10:18:24 +01:00
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(context->ctx_alias ? blr_rid2 : blr_rid);
|
|
|
|
dsqlScratch->appendUShort(relation->rel_id);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2009-11-16 10:18:24 +01:00
|
|
|
else
|
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(context->ctx_alias ? blr_relation2 : blr_relation);
|
|
|
|
dsqlScratch->appendMetaString(relation->rel_name.c_str());
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (context->ctx_alias)
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendMetaString(context->ctx_alias);
|
2007-05-27 00:08:13 +02:00
|
|
|
|
2010-11-14 18:25:48 +01:00
|
|
|
GEN_stuff_context(dsqlScratch, context);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2009-01-06 06:53:34 +01:00
|
|
|
else if (procedure)
|
|
|
|
{
|
2009-12-20 22:01:10 +01:00
|
|
|
if (DDL_ids(dsqlScratch))
|
2009-10-21 02:42:38 +02:00
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(context->ctx_alias ? blr_pid2 : blr_pid);
|
|
|
|
dsqlScratch->appendUShort(procedure->prc_id);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2009-10-21 02:42:38 +02:00
|
|
|
else
|
|
|
|
{
|
2010-01-27 05:32:27 +01:00
|
|
|
if (procedure->prc_name.package.hasData())
|
2009-10-21 02:42:38 +02:00
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(context->ctx_alias ? blr_procedure4 : blr_procedure3);
|
|
|
|
dsqlScratch->appendMetaString(procedure->prc_name.package.c_str());
|
|
|
|
dsqlScratch->appendMetaString(procedure->prc_name.identifier.c_str());
|
2009-10-21 02:42:38 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(context->ctx_alias ? blr_procedure2 : blr_procedure);
|
|
|
|
dsqlScratch->appendMetaString(procedure->prc_name.identifier.c_str());
|
2009-10-21 02:42:38 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2009-12-14 12:19:26 +01:00
|
|
|
|
|
|
|
if (context->ctx_alias)
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendMetaString(context->ctx_alias);
|
2009-12-14 12:19:26 +01:00
|
|
|
|
2010-11-14 18:25:48 +01:00
|
|
|
GEN_stuff_context(dsqlScratch, context);
|
2004-01-16 11:43:21 +01:00
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
dsql_nod* inputs = context->ctx_proc_inputs;
|
2009-11-16 10:18:24 +01:00
|
|
|
if (inputs)
|
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUShort(inputs->nod_count);
|
2004-01-16 11:43:21 +01:00
|
|
|
|
|
|
|
dsql_nod* const* ptr = inputs->nod_arg;
|
2009-01-06 06:53:34 +01:00
|
|
|
for (const dsql_nod* const* const end = ptr + inputs->nod_count; ptr < end; ptr++)
|
2003-11-01 11:26:43 +01:00
|
|
|
{
|
2009-12-20 22:01:10 +01:00
|
|
|
GEN_expr(dsqlScratch, *ptr);
|
2003-11-01 11:26:43 +01:00
|
|
|
}
|
2004-01-16 11:43:21 +01:00
|
|
|
}
|
|
|
|
else
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUShort(0);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2010-02-22 17:00:49 +01:00
|
|
|
GEN_rse
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
@brief Generate a record selection expression.
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
@param dsqlScratch
|
2003-02-15 04:01:51 +01:00
|
|
|
@param rse
|
|
|
|
|
|
|
|
**/
|
2010-02-22 17:00:49 +01:00
|
|
|
void GEN_rse( DsqlCompilerScratch* dsqlScratch, const dsql_nod* rse)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2005-09-10 09:15:24 +02:00
|
|
|
if (rse->nod_flags & NOD_SELECT_EXPR_SINGLETON)
|
2003-10-05 08:27:16 +02:00
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_singular);
|
2003-10-05 08:27:16 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_rse);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
dsql_nod* list = rse->nod_arg[e_rse_streams];
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-04-18 16:13:26 +02:00
|
|
|
// Handle source streams
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-11-16 10:18:24 +01:00
|
|
|
if (list->nod_type == nod_union)
|
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(1);
|
2009-12-20 22:01:10 +01:00
|
|
|
gen_union(dsqlScratch, rse);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2009-01-06 06:53:34 +01:00
|
|
|
else if (list->nod_type == nod_list)
|
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(list->nod_count);
|
2003-11-01 11:26:43 +01:00
|
|
|
dsql_nod* const* ptr = list->nod_arg;
|
2009-01-06 06:53:34 +01:00
|
|
|
for (const dsql_nod* const* const end = ptr + list->nod_count; ptr < end; ptr++)
|
2003-11-01 11:26:43 +01:00
|
|
|
{
|
|
|
|
dsql_nod* node = *ptr;
|
2009-01-06 06:53:34 +01:00
|
|
|
switch (node->nod_type)
|
2003-11-01 11:26:43 +01:00
|
|
|
{
|
2009-01-06 06:53:34 +01:00
|
|
|
case nod_relation:
|
|
|
|
case nod_aggregate:
|
|
|
|
case nod_join:
|
2009-12-20 22:01:10 +01:00
|
|
|
GEN_expr(dsqlScratch, node);
|
2009-01-06 06:53:34 +01:00
|
|
|
break;
|
|
|
|
case nod_derived_table:
|
2009-12-20 22:01:10 +01:00
|
|
|
GEN_expr(dsqlScratch, node->nod_arg[e_derived_table_rse]);
|
2009-01-06 06:53:34 +01:00
|
|
|
break;
|
2003-08-15 01:34:37 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
}
|
2009-11-16 10:18:24 +01:00
|
|
|
else
|
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(1);
|
2009-12-20 22:01:10 +01:00
|
|
|
GEN_expr(dsqlScratch, list);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2002-11-18 21:27:24 +01:00
|
|
|
if (rse->nod_arg[e_rse_lock])
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_writelock);
|
2003-08-13 13:09:57 +02:00
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
dsql_nod* node;
|
2003-08-13 13:09:57 +02:00
|
|
|
|
2009-11-16 10:18:24 +01:00
|
|
|
if ((node = rse->nod_arg[e_rse_first]) != NULL)
|
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_first);
|
2009-12-20 22:01:10 +01:00
|
|
|
GEN_expr(dsqlScratch, node);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2009-11-16 10:18:24 +01:00
|
|
|
if ((node = rse->nod_arg[e_rse_skip]) != NULL)
|
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_skip);
|
2010-01-20 08:34:31 +01:00
|
|
|
GEN_expr(dsqlScratch, node);
|
2006-06-02 10:03:22 +02:00
|
|
|
}
|
2002-06-29 08:56:51 +02:00
|
|
|
|
2009-11-16 10:18:24 +01:00
|
|
|
if ((node = rse->nod_arg[e_rse_boolean]) != NULL)
|
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_boolean);
|
2009-12-20 22:01:10 +01:00
|
|
|
GEN_expr(dsqlScratch, node);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if ((list = rse->nod_arg[e_rse_sort]) != NULL)
|
2010-01-20 08:34:31 +01:00
|
|
|
{
|
2009-12-20 22:01:10 +01:00
|
|
|
gen_sort(dsqlScratch, list);
|
2010-01-20 08:34:31 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-11-16 10:18:24 +01:00
|
|
|
if ((list = rse->nod_arg[e_rse_reduced]) != NULL)
|
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_project);
|
|
|
|
dsqlScratch->appendUChar(list->nod_count);
|
2003-11-01 11:26:43 +01:00
|
|
|
dsql_nod** ptr = list->nod_arg;
|
2009-01-06 06:53:34 +01:00
|
|
|
for (const dsql_nod* const* const end = ptr + list->nod_count; ptr < end; ptr++)
|
2003-11-01 11:26:43 +01:00
|
|
|
{
|
2009-12-20 22:01:10 +01:00
|
|
|
GEN_expr(dsqlScratch, *ptr);
|
2003-11-01 11:26:43 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2009-04-18 16:13:26 +02:00
|
|
|
// if the user specified an access plan to use, add it here
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-11-16 10:18:24 +01:00
|
|
|
if ((node = rse->nod_arg[e_rse_plan]) != NULL)
|
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_plan);
|
2009-12-20 22:01:10 +01:00
|
|
|
gen_plan(dsqlScratch, node);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_end);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
gen_searched_case
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
@brief Generate BLR for CASE function (searched)
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
@param dsqlScratch
|
2003-02-15 04:01:51 +01:00
|
|
|
@param node
|
|
|
|
|
|
|
|
**/
|
2009-12-20 22:01:10 +01:00
|
|
|
static void gen_searched_case( DsqlCompilerScratch* dsqlScratch, const dsql_nod* node)
|
2002-08-03 17:27:20 +02:00
|
|
|
{
|
2003-08-13 13:09:57 +02:00
|
|
|
// blr_value_if is used for building the case expression
|
2002-08-03 17:27:20 +02:00
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_cast);
|
2009-12-20 22:01:10 +01:00
|
|
|
GEN_descriptor(dsqlScratch, &node->nod_desc, true);
|
2009-01-06 06:53:34 +01:00
|
|
|
const SSHORT count = node->nod_arg[e_searched_case_search_conditions]->nod_count;
|
2003-11-01 11:26:43 +01:00
|
|
|
dsql_nod* boolean_list = node->nod_arg[e_searched_case_search_conditions];
|
|
|
|
dsql_nod* results_list = node->nod_arg[e_searched_case_results];
|
|
|
|
dsql_nod* const* bptr = boolean_list->nod_arg;
|
|
|
|
dsql_nod* const* rptr = results_list->nod_arg;
|
2009-01-06 06:53:34 +01:00
|
|
|
for (const dsql_nod* const* const end = bptr + count; bptr < end; bptr++, rptr++)
|
2002-08-03 17:27:20 +02:00
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_value_if);
|
2009-12-20 22:01:10 +01:00
|
|
|
GEN_expr(dsqlScratch, *bptr);
|
|
|
|
GEN_expr(dsqlScratch, *rptr);
|
2002-08-03 17:27:20 +02:00
|
|
|
}
|
2003-08-13 13:09:57 +02:00
|
|
|
// else_result
|
2009-12-20 22:01:10 +01:00
|
|
|
GEN_expr(dsqlScratch, node->nod_arg[e_searched_case_results]->nod_arg[count]);
|
2002-08-03 17:27:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
gen_select
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2010-06-15 18:07:58 +02:00
|
|
|
@brief Generate BLR for a SELECT statement.
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
@param dsqlScratch
|
2003-02-15 04:01:51 +01:00
|
|
|
@param rse
|
|
|
|
|
|
|
|
**/
|
2009-12-21 15:20:26 +01:00
|
|
|
static void gen_select(DsqlCompilerScratch* dsqlScratch, dsql_nod* rse)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2003-11-01 11:26:43 +01:00
|
|
|
dsql_ctx* context;
|
2005-09-02 07:30:16 +02:00
|
|
|
|
|
|
|
fb_assert(rse->nod_type == nod_rse);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-12-21 15:20:26 +01:00
|
|
|
DsqlCompiledStatement* statement = dsqlScratch->getStatement();
|
|
|
|
|
2009-04-18 16:13:26 +02:00
|
|
|
// Set up parameter for things in the select list
|
2005-09-02 07:30:16 +02:00
|
|
|
const dsql_nod* list = rse->nod_arg[e_rse_items];
|
2003-11-01 11:26:43 +01:00
|
|
|
dsql_nod* const* ptr = list->nod_arg;
|
2009-01-06 06:53:34 +01:00
|
|
|
for (const dsql_nod* const* const end = ptr + list->nod_count; ptr < end; ptr++)
|
2003-11-01 11:26:43 +01:00
|
|
|
{
|
2009-12-22 16:36:10 +01:00
|
|
|
dsql_par* parameter = MAKE_parameter(statement->getReceiveMsg(), true, true, 0, *ptr);
|
2005-09-02 07:30:16 +02:00
|
|
|
parameter->par_node = *ptr;
|
2010-11-01 01:42:12 +01:00
|
|
|
MAKE_desc(dsqlScratch, ¶meter->par_desc, *ptr);
|
2005-09-02 07:30:16 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-04-18 16:13:26 +02:00
|
|
|
// Set up parameter to handle EOF
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-12-22 16:36:10 +01:00
|
|
|
dsql_par* parameter_eof = MAKE_parameter(statement->getReceiveMsg(), false, false, 0, NULL);
|
|
|
|
statement->setEof(parameter_eof);
|
2005-09-02 07:30:16 +02:00
|
|
|
parameter_eof->par_desc.dsc_dtype = dtype_short;
|
|
|
|
parameter_eof->par_desc.dsc_scale = 0;
|
|
|
|
parameter_eof->par_desc.dsc_length = sizeof(SSHORT);
|
2003-08-13 13:09:57 +02:00
|
|
|
|
2009-04-18 16:13:26 +02:00
|
|
|
// Save DBKEYs for possible update later
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
list = rse->nod_arg[e_rse_streams];
|
|
|
|
|
2009-12-23 01:57:08 +01:00
|
|
|
GenericMap<NonPooled<dsql_par*, dsql_ctx*> > paramContexts(*getDefaultMemoryPool());
|
|
|
|
|
2009-01-06 06:53:34 +01:00
|
|
|
if (!rse->nod_arg[e_rse_reduced])
|
|
|
|
{
|
2006-08-17 14:08:49 +02:00
|
|
|
dsql_nod* const* ptr2 = list->nod_arg;
|
2009-01-06 06:53:34 +01:00
|
|
|
for (const dsql_nod* const* const end2 = ptr2 + list->nod_count; ptr2 < end2; ptr2++)
|
2003-11-01 11:26:43 +01:00
|
|
|
{
|
2006-08-17 14:08:49 +02:00
|
|
|
dsql_nod* item = *ptr2;
|
2009-01-06 06:53:34 +01:00
|
|
|
if (item && item->nod_type == nod_relation)
|
|
|
|
{
|
2003-11-01 11:26:43 +01:00
|
|
|
context = (dsql_ctx*) item->nod_arg[e_rel_context];
|
2009-11-16 10:18:24 +01:00
|
|
|
const dsql_rel* relation = context->ctx_relation;
|
|
|
|
if (relation)
|
2009-01-06 06:53:34 +01:00
|
|
|
{
|
2003-08-13 13:09:57 +02:00
|
|
|
// Set up dbkey
|
2009-12-22 16:36:10 +01:00
|
|
|
dsql_par* parameter = MAKE_parameter(statement->getReceiveMsg(), false,
|
2009-12-21 15:20:26 +01:00
|
|
|
false, 0, NULL);
|
2009-12-23 01:57:08 +01:00
|
|
|
|
2009-12-26 03:21:56 +01:00
|
|
|
parameter->par_dbkey_relname = relation->rel_name;
|
2009-12-23 01:57:08 +01:00
|
|
|
paramContexts.put(parameter, context);
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
parameter->par_desc.dsc_dtype = dtype_text;
|
2004-05-21 08:16:17 +02:00
|
|
|
parameter->par_desc.dsc_ttype() = ttype_binary;
|
2009-01-06 06:53:34 +01:00
|
|
|
parameter->par_desc.dsc_length = relation->rel_dbkey_length;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-08-13 13:09:57 +02:00
|
|
|
// Set up record version - for post v33 databases
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-12-22 16:36:10 +01:00
|
|
|
parameter = MAKE_parameter(statement->getReceiveMsg(), false, false, 0, NULL);
|
2009-12-26 03:21:56 +01:00
|
|
|
parameter->par_rec_version_relname = relation->rel_name;
|
2009-12-27 17:49:23 +01:00
|
|
|
paramContexts.put(parameter, context);
|
|
|
|
|
2005-09-10 09:15:24 +02:00
|
|
|
parameter->par_desc.dsc_dtype = dtype_text;
|
|
|
|
parameter->par_desc.dsc_ttype() = ttype_binary;
|
2009-01-06 06:53:34 +01:00
|
|
|
parameter->par_desc.dsc_length = relation->rel_dbkey_length / 2;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
}
|
2003-08-13 13:09:57 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2009-04-18 16:13:26 +02:00
|
|
|
// Generate definitions for the messages
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-12-22 16:36:10 +01:00
|
|
|
GEN_port(dsqlScratch, statement->getReceiveMsg());
|
|
|
|
dsql_msg* message = statement->getSendMsg();
|
2001-05-23 15:26:42 +02:00
|
|
|
if (message->msg_parameter)
|
2009-12-20 22:01:10 +01:00
|
|
|
GEN_port(dsqlScratch, message);
|
2001-05-23 15:26:42 +02:00
|
|
|
else
|
2009-12-22 16:36:10 +01:00
|
|
|
statement->setSendMsg(NULL);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-04-18 16:13:26 +02:00
|
|
|
// If there is a send message, build a RECEIVE
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-12-22 16:36:10 +01:00
|
|
|
if ((message = statement->getSendMsg()) != NULL)
|
2009-11-16 10:18:24 +01:00
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_receive);
|
|
|
|
dsqlScratch->appendUChar(message->msg_number);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2009-04-18 16:13:26 +02:00
|
|
|
// Generate FOR loop
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-12-22 16:36:10 +01:00
|
|
|
message = statement->getReceiveMsg();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_for);
|
|
|
|
dsqlScratch->appendUChar(blr_stall);
|
2010-02-22 17:00:49 +01:00
|
|
|
GEN_rse(dsqlScratch, rse);
|
2003-11-02 13:28:30 +01:00
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_send);
|
|
|
|
dsqlScratch->appendUChar(message->msg_number);
|
|
|
|
dsqlScratch->appendUChar(blr_begin);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-04-18 16:13:26 +02:00
|
|
|
// Build body of FOR loop
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2005-09-02 07:30:16 +02:00
|
|
|
SSHORT constant;
|
|
|
|
dsc constant_desc;
|
|
|
|
constant_desc.dsc_dtype = dtype_short;
|
|
|
|
constant_desc.dsc_scale = 0;
|
|
|
|
constant_desc.dsc_sub_type = 0;
|
|
|
|
constant_desc.dsc_flags = 0;
|
|
|
|
constant_desc.dsc_length = sizeof(SSHORT);
|
|
|
|
constant_desc.dsc_address = (UCHAR*) & constant;
|
|
|
|
|
2003-08-13 13:09:57 +02:00
|
|
|
// Add invalid usage here
|
2005-09-02 07:30:16 +02:00
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_assignment);
|
2001-05-23 15:26:42 +02:00
|
|
|
constant = 1;
|
2010-10-24 02:26:00 +02:00
|
|
|
LiteralNode::genConstant(dsqlScratch, &constant_desc, false);
|
2010-10-09 03:57:37 +02:00
|
|
|
GEN_parameter(dsqlScratch, statement->getEof());
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-12-19 19:50:38 +01:00
|
|
|
for (size_t i = 0; i < message->msg_parameters.getCount(); ++i)
|
2004-10-26 09:21:47 +02:00
|
|
|
{
|
2009-12-19 19:50:38 +01:00
|
|
|
dsql_par* parameter = message->msg_parameters[i];
|
|
|
|
|
2009-11-16 10:18:24 +01:00
|
|
|
if (parameter->par_node)
|
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_assignment);
|
2009-12-20 22:01:10 +01:00
|
|
|
GEN_expr(dsqlScratch, parameter->par_node);
|
2010-10-09 03:57:37 +02:00
|
|
|
GEN_parameter(dsqlScratch, parameter);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2009-12-23 01:57:08 +01:00
|
|
|
|
2009-12-26 03:21:56 +01:00
|
|
|
if (parameter->par_dbkey_relname.hasData() && paramContexts.get(parameter, context))
|
2009-11-16 10:18:24 +01:00
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_assignment);
|
|
|
|
dsqlScratch->appendUChar(blr_dbkey);
|
2010-11-14 18:25:48 +01:00
|
|
|
GEN_stuff_context(dsqlScratch, context);
|
2010-10-09 03:57:37 +02:00
|
|
|
GEN_parameter(dsqlScratch, parameter);
|
2009-12-26 03:21:56 +01:00
|
|
|
}
|
2009-12-23 01:57:08 +01:00
|
|
|
|
2009-12-26 03:21:56 +01:00
|
|
|
if (parameter->par_rec_version_relname.hasData() && paramContexts.get(parameter, context))
|
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_assignment);
|
|
|
|
dsqlScratch->appendUChar(blr_record_version);
|
2010-11-14 18:25:48 +01:00
|
|
|
GEN_stuff_context(dsqlScratch, context);
|
2010-10-09 03:57:37 +02:00
|
|
|
GEN_parameter(dsqlScratch, parameter);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_end);
|
|
|
|
dsqlScratch->appendUChar(blr_send);
|
|
|
|
dsqlScratch->appendUChar(message->msg_number);
|
|
|
|
dsqlScratch->appendUChar(blr_assignment);
|
2001-05-23 15:26:42 +02:00
|
|
|
constant = 0;
|
2010-10-24 02:26:00 +02:00
|
|
|
LiteralNode::genConstant(dsqlScratch, &constant_desc, false);
|
2010-10-09 03:57:37 +02:00
|
|
|
GEN_parameter(dsqlScratch, statement->getEof());
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
gen_simple_case
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
@brief Generate BLR for CASE function (simple)
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
@param dsqlScratch
|
2003-02-15 04:01:51 +01:00
|
|
|
@param node
|
|
|
|
|
|
|
|
**/
|
2009-12-20 22:01:10 +01:00
|
|
|
static void gen_simple_case( DsqlCompilerScratch* dsqlScratch, const dsql_nod* node)
|
2002-08-03 17:27:20 +02:00
|
|
|
{
|
2008-09-27 11:51:53 +02:00
|
|
|
// blr_value_if is used for building the case expression
|
2002-08-03 17:27:20 +02:00
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_cast);
|
2009-12-20 22:01:10 +01:00
|
|
|
GEN_descriptor(dsqlScratch, &node->nod_desc, true);
|
2008-08-26 12:28:58 +02:00
|
|
|
const SSHORT count = node->nod_arg[e_simple_case_when_operands]->nod_count;
|
2003-11-01 11:26:43 +01:00
|
|
|
dsql_nod* when_list = node->nod_arg[e_simple_case_when_operands];
|
|
|
|
dsql_nod* results_list = node->nod_arg[e_simple_case_results];
|
2003-08-13 13:09:57 +02:00
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
dsql_nod* const* wptr = when_list->nod_arg;
|
|
|
|
dsql_nod* const* rptr = results_list->nod_arg;
|
2009-01-06 06:53:34 +01:00
|
|
|
for (const dsql_nod* const* const end = wptr + count; wptr < end; wptr++, rptr++)
|
2002-08-03 17:27:20 +02:00
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_value_if);
|
|
|
|
dsqlScratch->appendUChar(blr_eql);
|
2009-08-06 04:32:56 +02:00
|
|
|
|
|
|
|
if (wptr == when_list->nod_arg || !node->nod_arg[e_simple_case_case_operand2])
|
2009-12-20 22:01:10 +01:00
|
|
|
GEN_expr(dsqlScratch, node->nod_arg[e_simple_case_case_operand]);
|
2009-08-06 04:32:56 +02:00
|
|
|
else
|
2009-12-20 22:01:10 +01:00
|
|
|
GEN_expr(dsqlScratch, node->nod_arg[e_simple_case_case_operand2]);
|
2009-08-06 04:32:56 +02:00
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
GEN_expr(dsqlScratch, *wptr);
|
|
|
|
GEN_expr(dsqlScratch, *rptr);
|
2002-08-03 17:27:20 +02:00
|
|
|
}
|
2008-09-27 11:51:53 +02:00
|
|
|
// else_result
|
2009-12-20 22:01:10 +01:00
|
|
|
GEN_expr(dsqlScratch, node->nod_arg[e_simple_case_results]->nod_arg[count]);
|
2002-08-03 17:27:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
gen_sort
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
@brief Generate a sort clause.
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
@param dsqlScratch
|
2003-02-15 04:01:51 +01:00
|
|
|
@param list
|
|
|
|
|
|
|
|
**/
|
2009-12-20 22:01:10 +01:00
|
|
|
static void gen_sort( DsqlCompilerScratch* dsqlScratch, dsql_nod* list)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_sort);
|
|
|
|
dsqlScratch->appendUChar(list->nod_count);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
dsql_nod* const* ptr = list->nod_arg;
|
2009-01-06 06:53:34 +01:00
|
|
|
for (const dsql_nod* const* const end = ptr + list->nod_count; ptr < end; ptr++)
|
2003-11-01 11:26:43 +01:00
|
|
|
{
|
2003-12-21 01:07:03 +01:00
|
|
|
dsql_nod* nulls_placement = (*ptr)->nod_arg[e_order_nulls];
|
2010-10-24 02:26:00 +02:00
|
|
|
|
2009-01-06 06:53:34 +01:00
|
|
|
if (nulls_placement)
|
|
|
|
{
|
2010-10-24 02:26:00 +02:00
|
|
|
switch (ExprNode::as<LiteralNode>(nulls_placement)->getSlong())
|
2009-01-06 06:53:34 +01:00
|
|
|
{
|
2003-12-21 01:07:03 +01:00
|
|
|
case NOD_NULLS_FIRST:
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_nullsfirst);
|
2003-12-21 01:07:03 +01:00
|
|
|
break;
|
|
|
|
case NOD_NULLS_LAST:
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_nullslast);
|
2003-12-21 01:07:03 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2002-09-10 20:28:23 +02:00
|
|
|
if ((*ptr)->nod_arg[e_order_flag])
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_descending);
|
2001-05-23 15:26:42 +02:00
|
|
|
else
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_ascending);
|
2009-12-20 22:01:10 +01:00
|
|
|
GEN_expr(dsqlScratch, (*ptr)->nod_arg[e_order_field]);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-31 20:02:34 +02:00
|
|
|
/**
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2006-05-31 20:02:34 +02:00
|
|
|
gen_statement
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2006-05-31 20:02:34 +02:00
|
|
|
@brief Generate BLR for DML statements.
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2006-05-31 20:02:34 +02:00
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
@param dsqlScratch
|
2006-05-31 20:02:34 +02:00
|
|
|
@param node
|
|
|
|
|
|
|
|
**/
|
2009-12-20 22:01:10 +01:00
|
|
|
static void gen_statement(DsqlCompilerScratch* dsqlScratch, const dsql_nod* node)
|
2006-05-31 20:02:34 +02:00
|
|
|
{
|
|
|
|
dsql_nod* rse = NULL;
|
2007-04-24 17:22:05 +02:00
|
|
|
const dsql_msg* message = NULL;
|
2010-06-10 04:03:03 +02:00
|
|
|
bool innerSend = dsqlScratch->flags & DsqlCompilerScratch::FLAG_UPDATE_OR_INSERT;
|
2010-06-30 10:55:16 +02:00
|
|
|
const bool merge = dsqlScratch->flags & DsqlCompilerScratch::FLAG_MERGE;
|
2006-05-31 20:02:34 +02:00
|
|
|
|
2009-01-06 06:53:34 +01:00
|
|
|
switch (node->nod_type)
|
|
|
|
{
|
2006-05-31 20:02:34 +02:00
|
|
|
case nod_store:
|
|
|
|
rse = node->nod_arg[e_sto_rse];
|
|
|
|
break;
|
|
|
|
case nod_modify:
|
|
|
|
rse = node->nod_arg[e_mod_rse];
|
|
|
|
break;
|
|
|
|
case nod_erase:
|
|
|
|
rse = node->nod_arg[e_era_rse];
|
|
|
|
break;
|
|
|
|
default:
|
2010-06-10 04:03:03 +02:00
|
|
|
innerSend = true;
|
2006-05-31 20:02:34 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2009-12-23 01:57:08 +01:00
|
|
|
if (dsqlScratch->getStatement()->getType() == DsqlCompiledStatement::TYPE_EXEC_PROCEDURE &&
|
2010-06-10 04:03:03 +02:00
|
|
|
!innerSend && !merge)
|
2007-04-24 17:22:05 +02:00
|
|
|
{
|
2009-12-22 16:36:10 +01:00
|
|
|
if ((message = dsqlScratch->getStatement()->getReceiveMsg()))
|
2007-04-24 17:22:05 +02:00
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_send);
|
|
|
|
dsqlScratch->appendUChar(message->msg_number);
|
2007-04-24 17:22:05 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-11-16 10:18:24 +01:00
|
|
|
if (rse)
|
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_for);
|
2009-12-20 22:01:10 +01:00
|
|
|
GEN_expr(dsqlScratch, rse);
|
2006-05-31 20:02:34 +02:00
|
|
|
}
|
|
|
|
|
2009-12-23 01:57:08 +01:00
|
|
|
if (dsqlScratch->getStatement()->getType() == DsqlCompiledStatement::TYPE_EXEC_PROCEDURE)
|
2007-04-24 17:22:05 +02:00
|
|
|
{
|
2009-12-22 16:36:10 +01:00
|
|
|
if ((message = dsqlScratch->getStatement()->getReceiveMsg()))
|
2007-04-24 17:22:05 +02:00
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_begin);
|
2007-04-24 17:22:05 +02:00
|
|
|
|
2010-06-10 04:03:03 +02:00
|
|
|
if (innerSend && !merge)
|
2007-04-24 17:22:05 +02:00
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_send);
|
|
|
|
dsqlScratch->appendUChar(message->msg_number);
|
2007-04-24 17:22:05 +02:00
|
|
|
}
|
2006-09-03 03:09:23 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-05-31 20:02:34 +02:00
|
|
|
dsql_nod* temp;
|
2008-07-02 11:46:44 +02:00
|
|
|
const dsql_ctx* context;
|
|
|
|
const dsql_str* name;
|
2006-05-31 20:02:34 +02:00
|
|
|
|
2009-01-06 06:53:34 +01:00
|
|
|
switch (node->nod_type)
|
|
|
|
{
|
2006-05-31 20:02:34 +02:00
|
|
|
case nod_store:
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(node->nod_arg[e_sto_return] ? blr_store2 : blr_store);
|
2009-12-20 22:01:10 +01:00
|
|
|
GEN_expr(dsqlScratch, node->nod_arg[e_sto_relation]);
|
|
|
|
GEN_statement(dsqlScratch, node->nod_arg[e_sto_statement]);
|
2006-08-19 17:49:28 +02:00
|
|
|
if (node->nod_arg[e_sto_return]) {
|
2009-12-20 22:01:10 +01:00
|
|
|
GEN_statement(dsqlScratch, node->nod_arg[e_sto_return]);
|
2006-05-31 20:02:34 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nod_modify:
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(node->nod_arg[e_mod_return] ? blr_modify2 : blr_modify);
|
2006-05-31 20:02:34 +02:00
|
|
|
temp = node->nod_arg[e_mod_source];
|
|
|
|
context = (dsql_ctx*) temp->nod_arg[e_rel_context];
|
2010-11-14 18:25:48 +01:00
|
|
|
GEN_stuff_context(dsqlScratch, context);
|
2006-05-31 20:02:34 +02:00
|
|
|
temp = node->nod_arg[e_mod_update];
|
|
|
|
context = (dsql_ctx*) temp->nod_arg[e_rel_context];
|
2010-11-14 18:25:48 +01:00
|
|
|
GEN_stuff_context(dsqlScratch, context);
|
2009-12-20 22:01:10 +01:00
|
|
|
GEN_statement(dsqlScratch, node->nod_arg[e_mod_statement]);
|
2006-08-19 17:49:28 +02:00
|
|
|
if (node->nod_arg[e_mod_return]) {
|
2009-12-20 22:01:10 +01:00
|
|
|
GEN_statement(dsqlScratch, node->nod_arg[e_mod_return]);
|
2006-05-31 20:02:34 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nod_modify_current:
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(node->nod_arg[e_mdc_return] ? blr_modify2 : blr_modify);
|
2006-05-31 20:02:34 +02:00
|
|
|
context = (dsql_ctx*) node->nod_arg[e_mdc_context];
|
2010-11-14 18:25:48 +01:00
|
|
|
GEN_stuff_context(dsqlScratch, context);
|
2006-05-31 20:02:34 +02:00
|
|
|
temp = node->nod_arg[e_mdc_update];
|
|
|
|
context = (dsql_ctx*) temp->nod_arg[e_rel_context];
|
2010-11-14 18:25:48 +01:00
|
|
|
GEN_stuff_context(dsqlScratch, context);
|
2009-12-20 22:01:10 +01:00
|
|
|
GEN_statement(dsqlScratch, node->nod_arg[e_mdc_statement]);
|
2006-08-19 20:18:31 +02:00
|
|
|
if (node->nod_arg[e_mdc_return]) {
|
2009-12-20 22:01:10 +01:00
|
|
|
GEN_statement(dsqlScratch, node->nod_arg[e_mdc_return]);
|
2006-05-31 20:02:34 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nod_erase:
|
|
|
|
temp = node->nod_arg[e_era_relation];
|
|
|
|
context = (dsql_ctx*) temp->nod_arg[e_rel_context];
|
2009-11-16 10:18:24 +01:00
|
|
|
if (node->nod_arg[e_era_return])
|
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_begin);
|
2009-12-20 22:01:10 +01:00
|
|
|
GEN_statement(dsqlScratch, node->nod_arg[e_era_return]);
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_erase);
|
2010-11-14 18:25:48 +01:00
|
|
|
GEN_stuff_context(dsqlScratch, context);
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_end);
|
2006-05-31 20:02:34 +02:00
|
|
|
}
|
2009-11-16 10:18:24 +01:00
|
|
|
else
|
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_erase);
|
2010-11-14 18:25:48 +01:00
|
|
|
GEN_stuff_context(dsqlScratch, context);
|
2006-05-31 20:02:34 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nod_erase_current:
|
|
|
|
context = (dsql_ctx*) node->nod_arg[e_erc_context];
|
2009-11-16 10:18:24 +01:00
|
|
|
if (node->nod_arg[e_erc_return])
|
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_begin);
|
2009-12-20 22:01:10 +01:00
|
|
|
GEN_statement(dsqlScratch, node->nod_arg[e_erc_return]);
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_erase);
|
2010-11-14 18:25:48 +01:00
|
|
|
GEN_stuff_context(dsqlScratch, context);
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_end);
|
2006-05-31 20:02:34 +02:00
|
|
|
}
|
2009-11-16 10:18:24 +01:00
|
|
|
else
|
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_erase);
|
2010-11-14 18:25:48 +01:00
|
|
|
GEN_stuff_context(dsqlScratch, context);
|
2006-05-31 20:02:34 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
fb_assert(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (message) {
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_end);
|
2006-05-31 20:02:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
gen_table_lock
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
@brief Generate tpb for table lock.
|
|
|
|
If lock level is specified, it overrrides the transaction lock level.
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
@param dsqlScratch
|
2003-02-15 04:01:51 +01:00
|
|
|
@param tbl_lock
|
|
|
|
@param lock_level
|
|
|
|
|
|
|
|
**/
|
2009-12-20 22:01:10 +01:00
|
|
|
static void gen_table_lock( DsqlCompilerScratch* dsqlScratch, const dsql_nod* tbl_lock, USHORT lock_level)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2008-06-03 08:14:59 +02:00
|
|
|
if (!tbl_lock || tbl_lock->nod_type != nod_table_lock)
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
const dsql_nod* tbl_names = tbl_lock->nod_arg[e_lock_tables];
|
2003-08-13 13:09:57 +02:00
|
|
|
SSHORT flags = 0;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (tbl_lock->nod_arg[e_lock_mode])
|
|
|
|
flags = tbl_lock->nod_arg[e_lock_mode]->nod_flags;
|
|
|
|
|
|
|
|
if (flags & NOD_PROTECTED)
|
2003-11-08 00:27:24 +01:00
|
|
|
lock_level = isc_tpb_protected;
|
2001-05-23 15:26:42 +02:00
|
|
|
else if (flags & NOD_SHARED)
|
2003-11-08 00:27:24 +01:00
|
|
|
lock_level = isc_tpb_shared;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-01-07 10:30:57 +01:00
|
|
|
const USHORT lock_mode = (flags & NOD_WRITE) ? isc_tpb_lock_write : isc_tpb_lock_read;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2006-06-02 10:03:22 +02:00
|
|
|
const dsql_nod* const* ptr = tbl_names->nod_arg;
|
2009-01-06 06:53:34 +01:00
|
|
|
for (const dsql_nod* const* const end = ptr + tbl_names->nod_count; ptr < end; ptr++)
|
2003-11-01 11:26:43 +01:00
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
if ((*ptr)->nod_type != nod_relation_name)
|
|
|
|
continue;
|
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(lock_mode);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-09-27 11:51:53 +02:00
|
|
|
// stuff table name
|
2003-11-10 10:16:38 +01:00
|
|
|
const dsql_str* temp = (dsql_str*) ((*ptr)->nod_arg[e_rln_name]);
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNullString(temp->str_data);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(lock_level);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
gen_union
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
@brief Generate a union of substreams.
|
2008-09-27 11:51:53 +02:00
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
@param dsqlScratch
|
2003-02-15 04:01:51 +01:00
|
|
|
@param union_node
|
|
|
|
|
|
|
|
**/
|
2009-12-20 22:01:10 +01:00
|
|
|
static void gen_union( DsqlCompilerScratch* dsqlScratch, const dsql_nod* union_node)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2010-11-14 18:25:48 +01:00
|
|
|
if (union_node->nod_arg[0]->nod_flags & NOD_UNION_RECURSIVE)
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_recurse);
|
2010-11-14 18:25:48 +01:00
|
|
|
else
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_union);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-04-18 16:13:26 +02:00
|
|
|
// Obtain the context for UNION from the first dsql_map* node
|
2003-11-01 11:26:43 +01:00
|
|
|
dsql_nod* items = union_node->nod_arg[e_rse_items];
|
|
|
|
dsql_nod* map_item = items->nod_arg[0];
|
2010-11-14 18:25:48 +01:00
|
|
|
|
2003-09-04 17:02:22 +02:00
|
|
|
// AB: First item could be a virtual field generated by derived table.
|
2010-11-14 18:25:48 +01:00
|
|
|
DerivedFieldNode* derivedField;
|
|
|
|
|
|
|
|
if ((derivedField = ExprNode::as<DerivedFieldNode>(map_item)))
|
|
|
|
map_item = derivedField->dsqlValue;
|
|
|
|
|
|
|
|
dsql_ctx* union_context = ExprNode::as<DsqlMapNode>(map_item)->context;
|
|
|
|
GEN_stuff_context(dsqlScratch, union_context);
|
2008-09-27 11:51:53 +02:00
|
|
|
// secondary context number must be present once in generated blr
|
2007-07-21 23:28:56 +02:00
|
|
|
union_context->ctx_flags &= ~CTX_recursive;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
dsql_nod* streams = union_node->nod_arg[e_rse_streams];
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(streams->nod_count); // number of substreams
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2006-06-02 10:03:22 +02:00
|
|
|
dsql_nod** ptr = streams->nod_arg;
|
2009-01-06 06:53:34 +01:00
|
|
|
for (const dsql_nod* const* const end = ptr + streams->nod_count; ptr < end; ptr++)
|
2003-11-01 11:26:43 +01:00
|
|
|
{
|
|
|
|
dsql_nod* sub_rse = *ptr;
|
2010-02-22 17:00:49 +01:00
|
|
|
GEN_rse(dsqlScratch, sub_rse);
|
2001-05-23 15:26:42 +02:00
|
|
|
items = sub_rse->nod_arg[e_rse_items];
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(blr_map);
|
|
|
|
dsqlScratch->appendUShort(items->nod_count);
|
2003-08-13 13:09:57 +02:00
|
|
|
USHORT count = 0;
|
2003-11-01 11:26:43 +01:00
|
|
|
dsql_nod** iptr = items->nod_arg;
|
2009-01-06 06:53:34 +01:00
|
|
|
for (const dsql_nod* const* const iend = iptr + items->nod_count; iptr < iend; iptr++)
|
2003-11-01 11:26:43 +01:00
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUShort(count);
|
2009-12-20 22:01:10 +01:00
|
|
|
GEN_expr(dsqlScratch, *iptr);
|
2001-05-23 15:26:42 +02:00
|
|
|
count++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-11-14 18:25:48 +01:00
|
|
|
// Write a context number into the BLR buffer. Check for possible overflow.
|
|
|
|
void GEN_stuff_context(DsqlCompilerScratch* dsqlScratch, const dsql_ctx* context)
|
2006-03-07 11:20:52 +01:00
|
|
|
{
|
2010-11-14 18:25:48 +01:00
|
|
|
if (context->ctx_context > MAX_UCHAR)
|
2008-08-15 13:21:47 +02:00
|
|
|
ERRD_post(Arg::Gds(isc_too_many_contexts));
|
2010-01-18 22:37:47 +01:00
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(context->ctx_context);
|
2007-07-21 23:28:56 +02:00
|
|
|
|
|
|
|
if (context->ctx_flags & CTX_recursive)
|
|
|
|
{
|
2010-11-14 18:25:48 +01:00
|
|
|
if (context->ctx_recursive > MAX_UCHAR)
|
2008-08-15 13:21:47 +02:00
|
|
|
ERRD_post(Arg::Gds(isc_too_many_contexts));
|
2010-11-14 18:25:48 +01:00
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(context->ctx_recursive);
|
2007-07-21 23:28:56 +02:00
|
|
|
}
|
2006-03-07 11:20:52 +01:00
|
|
|
}
|