8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-23 14:03:07 +01:00

Refactor DSQL's nod_field

This commit is contained in:
asfernandes 2010-12-19 21:42:32 +00:00
parent 667caf5257
commit 4a9f98bed7
7 changed files with 332 additions and 392 deletions

View File

@ -7392,9 +7392,10 @@ void CreateAlterViewNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
} }
const dsql_fld* nameField = NULL; const dsql_fld* nameField = NULL;
const FieldNode* fieldNameNode = ExprNode::as<FieldNode>(nameNode);
if (nameNode->nod_type == Dsql::nod_field) if (fieldNameNode)
nameField = (dsql_fld*) nameNode->nod_arg[Dsql::e_fld_field]; nameField = fieldNameNode->dsqlField;
const TEXT* fieldStr = NULL; const TEXT* fieldStr = NULL;
@ -7411,10 +7412,12 @@ void CreateAlterViewNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
dsql_fld* field = NULL; dsql_fld* field = NULL;
const dsql_ctx* context = NULL; const dsql_ctx* context = NULL;
if (fieldNode->nod_type == Dsql::nod_field) fieldNameNode = ExprNode::as<FieldNode>(fieldNode);
if (fieldNameNode)
{ {
field = (dsql_fld*) fieldNode->nod_arg[Dsql::e_fld_field]; field = fieldNameNode->dsqlField;
context = (dsql_ctx*) fieldNode->nod_arg[Dsql::e_fld_context]; context = fieldNameNode->dsqlContext;
} }
else else
updatable = false; updatable = false;
@ -8064,8 +8067,8 @@ dsql_nod* CreateAlterViewNode::replaceFieldNames(dsql_nod* input, dsql_nod* sear
if (replaceFields) if (replaceFields)
replaceName = (dsql_str*) (*replace)->nod_arg[Dsql::e_fln_name]; replaceName = (dsql_str*) (*replace)->nod_arg[Dsql::e_fln_name];
const dsql_nod* fieldNode = *search; const FieldNode* fieldNode = ExprNode::as<FieldNode>(*search);
const dsql_fld* field = (dsql_fld*) fieldNode->nod_arg[Dsql::e_fld_field]; const dsql_fld* field = fieldNode->dsqlField;
if (field->fld_name == fieldName->str_data) if (field->fld_name == fieldName->str_data)
{ {

View File

@ -4202,12 +4202,16 @@ static RegisterNode<FieldNode> regFieldNodeField(blr_field);
FieldNode::FieldNode(MemoryPool& pool) FieldNode::FieldNode(MemoryPool& pool)
: TypedNode<ValueExprNode, ExprNode::TYPE_FIELD>(pool), : TypedNode<ValueExprNode, ExprNode::TYPE_FIELD>(pool),
dsqlContext(NULL),
dsqlField(NULL),
dsqlIndices(NULL),
byId(false), byId(false),
fieldStream(0), fieldStream(0),
fieldId(0), fieldId(0),
format(NULL), format(NULL),
defaultValue(NULL) defaultValue(NULL)
{ {
dsqlDesc.clear();
} }
// Parse a field. // Parse a field.
@ -4383,40 +4387,191 @@ void FieldNode::print(string& text, Array<dsql_nod*>& nodes) const
ExprNode::print(text, nodes); ExprNode::print(text, nodes);
} }
//// TODO: Implement FieldNode DSQL support.
ValueExprNode* FieldNode::dsqlPass(DsqlCompilerScratch* dsqlScratch) ValueExprNode* FieldNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
{ {
fb_assert(false); // AB: nod_field is an already passed node.
return NULL; // This could be done in expand_select_list.
return this;
}
bool FieldNode::dsqlAggregateFinder(AggregateFinder& visitor)
{
if (visitor.deepestLevel < dsqlContext->ctx_scope_level)
visitor.deepestLevel = dsqlContext->ctx_scope_level;
return false;
}
bool FieldNode::dsqlAggregate2Finder(Aggregate2Finder& visitor)
{
return false;
}
bool FieldNode::dsqlInvalidReferenceFinder(InvalidReferenceFinder& visitor)
{
// Wouldn't it be better to call an error from this point where return is true?
// Then we could give the fieldname that's making the trouble.
// If we come here then this field is used inside a aggregate-function. The
// ctx_scope_level gives the info how deep the context is inside the statement.
// If the context-scope-level from this field is lower or the same as the scope-level
// from the given context then it is an invalid field.
if (dsqlContext->ctx_scope_level == visitor.context->ctx_scope_level)
{
// Return true (invalid) if this field isn't inside the GROUP BY clause, that
// should already been seen in the match_node test in that routine start.
return true;
}
return false;
}
bool FieldNode::dsqlSubSelectFinder(SubSelectFinder& visitor)
{
return false;
}
bool FieldNode::dsqlFieldFinder(FieldFinder& visitor)
{
visitor.field = true;
switch (visitor.matchType)
{
case FIELD_MATCH_TYPE_EQUAL:
return dsqlContext->ctx_scope_level == visitor.checkScopeLevel;
case FIELD_MATCH_TYPE_LOWER:
return dsqlContext->ctx_scope_level < visitor.checkScopeLevel;
case FIELD_MATCH_TYPE_LOWER_EQUAL:
return dsqlContext->ctx_scope_level <= visitor.checkScopeLevel;
///case FIELD_MATCH_TYPE_HIGHER:
/// return dsqlContext->ctx_scope_level > visitor.checkScopeLevel;
///case FIELD_MATCH_TYPE_HIGHER_EQUAL:
/// return dsqlContext->ctx_scope_level >= visitor.checkScopeLevel;
default:
fb_assert(false);
}
return false;
}
bool FieldNode::dsqlFieldRemapper(FieldRemapper& visitor)
{
if (dsqlContext->ctx_scope_level == visitor.context->ctx_scope_level)
{
visitor.replaceNode(PASS1_post_map(visitor.dsqlScratch, this, visitor.context,
visitor.partitionNode, visitor.orderNode));
}
return false;
} }
void FieldNode::setParameterName(dsql_par* parameter) const void FieldNode::setParameterName(dsql_par* parameter) const
{ {
fb_assert(false); parameter->par_name = parameter->par_alias = dsqlField->fld_name.c_str();
if (dsqlContext->ctx_relation)
{
parameter->par_rel_name = dsqlContext->ctx_relation->rel_name.c_str();
parameter->par_owner_name = dsqlContext->ctx_relation->rel_owner.c_str();
}
else if (dsqlContext->ctx_procedure)
{
parameter->par_rel_name = dsqlContext->ctx_procedure->prc_name.identifier.c_str();
parameter->par_owner_name = dsqlContext->ctx_procedure->prc_owner.c_str();
}
parameter->par_rel_alias = dsqlContext->ctx_alias;
} }
// Generate blr for a field - field id's are preferred but not for trigger or view blr.
void FieldNode::genBlr(DsqlCompilerScratch* dsqlScratch) void FieldNode::genBlr(DsqlCompilerScratch* dsqlScratch)
{ {
fb_assert(false); // For older clients - generate an error should they try and
// access data types which did not exist in the older dialect.
if (dsqlScratch->clientDialect <= SQL_DIALECT_V5)
{
switch (dsqlField->fld_dtype)
{
case dtype_sql_date:
case dtype_sql_time:
case dtype_int64:
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-804) <<
Arg::Gds(isc_dsql_datatype_err) <<
Arg::Gds(isc_sql_dialect_datatype_unsupport) <<
Arg::Num(dsqlScratch->clientDialect) <<
Arg::Str(DSC_dtype_tostring(static_cast<UCHAR>(dsqlField->fld_dtype))));
break;
default:
// No special action for other data types
break;
}
}
if (dsqlIndices)
dsqlScratch->appendUChar(blr_index);
if (DDL_ids(dsqlScratch))
{
dsqlScratch->appendUChar(blr_fid);
GEN_stuff_context(dsqlScratch, dsqlContext);
dsqlScratch->appendUShort(dsqlField->fld_id);
}
else
{
dsqlScratch->appendUChar(blr_field);
GEN_stuff_context(dsqlScratch, dsqlContext);
dsqlScratch->appendMetaString(dsqlField->fld_name.c_str());
}
if (dsqlIndices)
{
dsqlScratch->appendUChar(dsqlIndices->nod_count);
dsql_nod** ptr = dsqlIndices->nod_arg;
for (const dsql_nod* const* end = ptr + dsqlIndices->nod_count; ptr != end; ++ptr)
GEN_expr(dsqlScratch, *ptr);
}
} }
void FieldNode::make(DsqlCompilerScratch* /*dsqlScratch*/, dsc* desc) void FieldNode::make(DsqlCompilerScratch* /*dsqlScratch*/, dsc* desc)
{ {
fb_assert(false); if (dsqlDesc.dsc_dtype)
*desc = dsqlDesc;
else
{
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-203) <<
Arg::Gds(isc_dsql_field_ref));
}
} }
bool FieldNode::dsqlMatch(const ExprNode* other, bool ignoreMapCast) const bool FieldNode::dsqlMatch(const ExprNode* other, bool ignoreMapCast) const
{ {
fb_assert(false); if (!ExprNode::dsqlMatch(other, ignoreMapCast))
return false; return false;
const FieldNode* o = other->as<FieldNode>();
fb_assert(o)
if (dsqlField != o->dsqlField || dsqlContext != o->dsqlContext)
return false;
if (dsqlIndices || o->dsqlIndices)
return PASS1_node_match(dsqlIndices, o->dsqlIndices, ignoreMapCast);
return true;
} }
bool FieldNode::expressionEqual(thread_db* tdbb, CompilerScratch* csb, /*const*/ ExprNode* other, bool FieldNode::expressionEqual(thread_db* tdbb, CompilerScratch* csb, /*const*/ ExprNode* other,
USHORT stream) /*const*/ USHORT stream) /*const*/
{ {
const FieldNode* o = other->as<FieldNode>(); const FieldNode* o = other->as<FieldNode>();
// ASF: Why not test fieldStream == o->fieldStream?
return o && fieldId == o->fieldId && o->fieldStream == stream; return o && fieldId == o->fieldId && o->fieldStream == stream;
} }
@ -5626,30 +5781,17 @@ void DsqlMapNode::setParameterName(dsql_par* parameter) const
} }
const char* nameAlias = NULL; const char* nameAlias = NULL;
const dsql_ctx* context = NULL; const FieldNode* fieldNode = NULL;
const dsql_fld* field;
const dsql_nod* alias; const dsql_nod* alias;
const dsql_str* str; const dsql_str* str;
switch (nestNode->nod_type) switch (nestNode->nod_type)
{ {
case Dsql::nod_field:
field = (dsql_fld*) nestNode->nod_arg[Dsql::e_fld_field];
nameAlias = field->fld_name.c_str();
context = (dsql_ctx*) nestNode->nod_arg[Dsql::e_fld_context];
break;
case Dsql::nod_alias: case Dsql::nod_alias:
str = (dsql_str*) nestNode->nod_arg[Dsql::e_alias_alias]; str = (dsql_str*) nestNode->nod_arg[Dsql::e_alias_alias];
parameter->par_alias = str->str_data; parameter->par_alias = str->str_data;
alias = nestNode->nod_arg[Dsql::e_alias_value]; alias = nestNode->nod_arg[Dsql::e_alias_value];
fieldNode = ExprNode::as<FieldNode>(alias);
if (alias->nod_type == Dsql::nod_field)
{
field = (dsql_fld*) alias->nod_arg[Dsql::e_fld_field];
parameter->par_name = field->fld_name.c_str();
context = (dsql_ctx*) alias->nod_arg[Dsql::e_fld_context];
}
break; break;
case Dsql::nod_class_exprnode: case Dsql::nod_class_exprnode:
@ -5668,19 +5810,25 @@ void DsqlMapNode::setParameterName(dsql_par* parameter) const
{ {
parameter->par_alias = derivedField->name; parameter->par_alias = derivedField->name;
alias = derivedField->dsqlValue; alias = derivedField->dsqlValue;
fieldNode = ExprNode::as<FieldNode>(alias);
if (alias->nod_type == Dsql::nod_field)
{
field = (dsql_fld*) alias->nod_arg[Dsql::e_fld_field];
parameter->par_name = field->fld_name.c_str();
context = (dsql_ctx*) alias->nod_arg[Dsql::e_fld_context];
}
} }
else if ((fieldNode = ExprNode::as<FieldNode>(nestNode)))
nameAlias = fieldNode->dsqlField->fld_name.c_str();
break; break;
} }
} // switch(nestNode->nod_type) } // switch(nestNode->nod_type)
const dsql_ctx* context = NULL;
const dsql_fld* field;
if (fieldNode)
{
context = fieldNode->dsqlContext;
field = fieldNode->dsqlField;
parameter->par_name = field->fld_name.c_str();
}
if (nameAlias) if (nameAlias)
parameter->par_name = parameter->par_alias = nameAlias; parameter->par_name = parameter->par_alias = nameAlias;
@ -5836,13 +5984,13 @@ bool DerivedFieldNode::dsqlFieldRemapper(FieldRemapper& visitor)
void DerivedFieldNode::setParameterName(dsql_par* parameter) const void DerivedFieldNode::setParameterName(dsql_par* parameter) const
{ {
const dsql_ctx* context = NULL; const dsql_ctx* context = NULL;
const FieldNode* fieldNode;
const RecordKeyNode* dbKeyNode; const RecordKeyNode* dbKeyNode;
if (dsqlValue->nod_type == Dsql::nod_field) if ((fieldNode = ExprNode::as<FieldNode>(dsqlValue)))
{ {
dsql_fld* field = (dsql_fld*) dsqlValue->nod_arg[Dsql::e_fld_field]; parameter->par_name = fieldNode->dsqlField->fld_name.c_str();
parameter->par_name = field->fld_name.c_str(); context = fieldNode->dsqlContext;
context = (dsql_ctx*) dsqlValue->nod_arg[Dsql::e_fld_context];
} }
else if ((dbKeyNode = ExprNode::as<RecordKeyNode>(dsqlValue))) else if ((dbKeyNode = ExprNode::as<RecordKeyNode>(dsqlValue)))
dbKeyNode->setParameterName(parameter); dbKeyNode->setParameterName(parameter);
@ -5872,7 +6020,7 @@ void DerivedFieldNode::genBlr(DsqlCompilerScratch* dsqlScratch)
// a set (ORed) of contexts. If any of them are in a valid position the expression is // a set (ORed) of contexts. If any of them are in a valid position the expression is
// evaluated, otherwise a NULL will be returned. This is fix for CORE-1246. // evaluated, otherwise a NULL will be returned. This is fix for CORE-1246.
if (dsqlValue->nod_type != Dsql::nod_field && if (!ExprNode::is<FieldNode>(dsqlValue) &&
!ExprNode::is<DerivedFieldNode>(dsqlValue) && !ExprNode::is<DerivedFieldNode>(dsqlValue) &&
!ExprNode::is<RecordKeyNode>(dsqlValue) && !ExprNode::is<RecordKeyNode>(dsqlValue) &&
!ExprNode::is<DsqlMapNode>(dsqlValue)) !ExprNode::is<DsqlMapNode>(dsqlValue))

View File

@ -437,6 +437,14 @@ public:
virtual void print(Firebird::string& text, Firebird::Array<dsql_nod*>& nodes) const; virtual void print(Firebird::string& text, Firebird::Array<dsql_nod*>& nodes) const;
virtual ValueExprNode* dsqlPass(DsqlCompilerScratch* dsqlScratch); virtual ValueExprNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
virtual bool dsqlAggregateFinder(AggregateFinder& visitor);
virtual bool dsqlAggregate2Finder(Aggregate2Finder& visitor);
virtual bool dsqlInvalidReferenceFinder(InvalidReferenceFinder& visitor);
virtual bool dsqlSubSelectFinder(SubSelectFinder& visitor);
virtual bool dsqlFieldFinder(FieldFinder& visitor);
virtual bool dsqlFieldRemapper(FieldRemapper& visitor);
virtual void setParameterName(dsql_par* parameter) const; virtual void setParameterName(dsql_par* parameter) const;
virtual void genBlr(DsqlCompilerScratch* dsqlScratch); virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
virtual void make(DsqlCompilerScratch* dsqlScratch, dsc* desc); virtual void make(DsqlCompilerScratch* dsqlScratch, dsc* desc);
@ -478,6 +486,10 @@ public:
virtual dsc* execute(thread_db* tdbb, jrd_req* request) const; virtual dsc* execute(thread_db* tdbb, jrd_req* request) const;
public: public:
dsql_ctx* dsqlContext;
dsql_fld* dsqlField;
dsql_nod* dsqlIndices;
dsc dsqlDesc;
bool byId; bool byId;
USHORT fieldStream; USHORT fieldStream;
USHORT fieldId; USHORT fieldId;

View File

@ -67,7 +67,6 @@ static void gen_aggregate(DsqlCompilerScratch*, const dsql_nod*);
static void gen_coalesce(DsqlCompilerScratch*, const dsql_nod*); static void gen_coalesce(DsqlCompilerScratch*, const dsql_nod*);
static void gen_error_condition(DsqlCompilerScratch*, const dsql_nod*); static void gen_error_condition(DsqlCompilerScratch*, const dsql_nod*);
static void gen_exec_stmt(DsqlCompilerScratch* dsqlScratch, const dsql_nod* node); static void gen_exec_stmt(DsqlCompilerScratch* dsqlScratch, const dsql_nod* node);
static void gen_field(DsqlCompilerScratch*, const dsql_ctx*, const dsql_fld*, dsql_nod*);
static void gen_join_rse(DsqlCompilerScratch*, const dsql_nod*); static void gen_join_rse(DsqlCompilerScratch*, const dsql_nod*);
static void gen_map(DsqlCompilerScratch*, dsql_map*); static void gen_map(DsqlCompilerScratch*, dsql_map*);
static inline void gen_optional_expr(DsqlCompilerScratch*, const UCHAR code, dsql_nod*); static inline void gen_optional_expr(DsqlCompilerScratch*, const UCHAR code, dsql_nod*);
@ -182,13 +181,6 @@ void GEN_expr(DsqlCompilerScratch* dsqlScratch, dsql_nod* node)
dsqlScratch->appendUShort(0); // Field id dsqlScratch->appendUShort(0); // Field id
return; return;
case nod_field:
gen_field(dsqlScratch,
(dsql_ctx*) node->nod_arg[e_fld_context],
(dsql_fld*) node->nod_arg[e_fld_field],
node->nod_arg[e_fld_indices]);
return;
case nod_join: case nod_join:
gen_join_rse(dsqlScratch, node); gen_join_rse(dsqlScratch, node);
return; return;
@ -1242,72 +1234,6 @@ static void gen_exec_stmt(DsqlCompilerScratch* dsqlScratch, const dsql_nod* node
} }
/**
gen_field
@brief Generate blr for a field - field id's
are preferred but not for trigger or view blr.
@param dsqlScratch
@param context
@param field
@param indices
**/
static void gen_field( DsqlCompilerScratch* dsqlScratch, const dsql_ctx* context,
const dsql_fld* field, dsql_nod* indices)
{
// For older clients - generate an error should they try and
// access data types which did not exist in the older dialect
if (dsqlScratch->clientDialect <= SQL_DIALECT_V5)
{
switch (field->fld_dtype)
{
case dtype_sql_date:
case dtype_sql_time:
case dtype_int64:
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-804) <<
Arg::Gds(isc_dsql_datatype_err) <<
Arg::Gds(isc_sql_dialect_datatype_unsupport) <<
Arg::Num(dsqlScratch->clientDialect) <<
Arg::Str(DSC_dtype_tostring(static_cast<UCHAR>(field->fld_dtype))));
break;
default:
// No special action for other data types
break;
}
}
if (indices)
dsqlScratch->appendUChar(blr_index);
if (DDL_ids(dsqlScratch))
{
dsqlScratch->appendUChar(blr_fid);
GEN_stuff_context(dsqlScratch, context);
dsqlScratch->appendUShort(field->fld_id);
}
else
{
dsqlScratch->appendUChar(blr_field);
GEN_stuff_context(dsqlScratch, context);
dsqlScratch->appendMetaString(field->fld_name.c_str());
}
if (indices)
{
dsqlScratch->appendUChar(indices->nod_count);
dsql_nod** ptr = indices->nod_arg;
for (const dsql_nod* const* end = ptr + indices->nod_count; ptr < end; ptr++)
{
GEN_expr(dsqlScratch, *ptr);
}
}
}
/** /**
gen_join_rse gen_join_rse

View File

@ -422,18 +422,6 @@ void MAKE_desc(DsqlCompilerScratch* dsqlScratch, dsc* desc, dsql_nod* node)
desc->dsc_flags = 0; // Can first/skip accept NULL in the future? desc->dsc_flags = 0; // Can first/skip accept NULL in the future?
return; return;
case nod_field:
if (node->nod_desc.dsc_dtype)
{
*desc = node->nod_desc;
}
else
{
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-203) <<
Arg::Gds(isc_dsql_field_ref));
}
return;
case nod_hidden_var: case nod_hidden_var:
MAKE_desc(dsqlScratch, desc, node->nod_arg[e_hidden_var_expr]); MAKE_desc(dsqlScratch, desc, node->nod_arg[e_hidden_var_expr]);
return; return;
@ -541,28 +529,29 @@ dsql_nod* MAKE_field(dsql_ctx* context, dsql_fld* field, dsql_nod* indices)
DEV_BLKCHK(field, dsql_type_fld); DEV_BLKCHK(field, dsql_type_fld);
DEV_BLKCHK(indices, dsql_type_nod); DEV_BLKCHK(indices, dsql_type_nod);
dsql_nod* node = MAKE_node(nod_field, e_fld_count); thread_db* tdbb = JRD_get_thread_data();
node->nod_arg[e_fld_context] = (dsql_nod*) context; FieldNode* node = FB_NEW(*tdbb->getDefaultPool()) FieldNode(*tdbb->getDefaultPool());
node->nod_arg[e_fld_field] = (dsql_nod*) field; node->dsqlContext = context;
node->dsqlField = field;
if (field->fld_dimensions) if (field->fld_dimensions)
{ {
if (indices) if (indices)
{ {
node->nod_arg[e_fld_indices] = indices; node->dsqlIndices = indices;
MAKE_desc_from_field(&node->nod_desc, field); MAKE_desc_from_field(&node->dsqlDesc, field);
node->nod_desc.dsc_dtype = static_cast<UCHAR>(field->fld_element_dtype); node->dsqlDesc.dsc_dtype = static_cast<UCHAR>(field->fld_element_dtype);
node->nod_desc.dsc_length = field->fld_element_length; node->dsqlDesc.dsc_length = field->fld_element_length;
// node->nod_desc.dsc_scale = field->fld_scale;
// node->nod_desc.dsc_sub_type = field->fld_sub_type;
// node->dsqlDesc.dsc_scale = field->fld_scale;
// node->dsqlDesc.dsc_sub_type = field->fld_sub_type;
} }
else else
{ {
node->nod_desc.dsc_dtype = dtype_array; node->dsqlDesc.dsc_dtype = dtype_array;
node->nod_desc.dsc_length = sizeof(ISC_QUAD); node->dsqlDesc.dsc_length = sizeof(ISC_QUAD);
node->nod_desc.dsc_scale = static_cast<SCHAR>(field->fld_scale); node->dsqlDesc.dsc_scale = static_cast<SCHAR>(field->fld_scale);
node->nod_desc.dsc_sub_type = field->fld_sub_type; node->dsqlDesc.dsc_sub_type = field->fld_sub_type;
} }
} }
else else
@ -573,32 +562,33 @@ dsql_nod* MAKE_field(dsql_ctx* context, dsql_fld* field, dsql_nod* indices)
Arg::Gds(isc_dsql_only_can_subscript_array) << Arg::Str(field->fld_name)); Arg::Gds(isc_dsql_only_can_subscript_array) << Arg::Str(field->fld_name));
} }
MAKE_desc_from_field(&node->nod_desc, field); MAKE_desc_from_field(&node->dsqlDesc, field);
} }
if ((field->fld_flags & FLD_nullable) || (context->ctx_flags & CTX_outer_join)) if ((field->fld_flags & FLD_nullable) || (context->ctx_flags & CTX_outer_join))
{ node->dsqlDesc.dsc_flags |= DSC_nullable;
node->nod_desc.dsc_flags |= DSC_nullable;
}
// UNICODE_FSS_HACK // UNICODE_FSS_HACK
// check if the field is a system domain and the type is CHAR/VARCHAR CHARACTER SET UNICODE_FSS // check if the field is a system domain and the type is CHAR/VARCHAR CHARACTER SET UNICODE_FSS
if ((field->fld_flags & FLD_system) && node->nod_desc.dsc_dtype <= dtype_varying && if ((field->fld_flags & FLD_system) && node->dsqlDesc.dsc_dtype <= dtype_varying &&
INTL_GET_CHARSET(&node->nod_desc) == CS_METADATA) INTL_GET_CHARSET(&node->dsqlDesc) == CS_METADATA)
{ {
USHORT adjust = 0; USHORT adjust = 0;
if (node->nod_desc.dsc_dtype == dtype_varying) if (node->dsqlDesc.dsc_dtype == dtype_varying)
adjust = sizeof(USHORT); adjust = sizeof(USHORT);
else if (node->nod_desc.dsc_dtype == dtype_cstring) else if (node->dsqlDesc.dsc_dtype == dtype_cstring)
adjust = 1; adjust = 1;
node->nod_desc.dsc_length -= adjust; node->dsqlDesc.dsc_length -= adjust;
node->nod_desc.dsc_length *= 3; node->dsqlDesc.dsc_length *= 3;
node->nod_desc.dsc_length += adjust; node->dsqlDesc.dsc_length += adjust;
} }
return node; dsql_nod* nod = MAKE_node(nod_class_exprnode, 1);
nod->nod_arg[0] = reinterpret_cast<dsql_nod*>(node);
return nod;
} }
@ -876,7 +866,7 @@ void MAKE_parameter_names(dsql_par* parameter, const dsql_nod* item)
fb_assert(parameter && item); fb_assert(parameter && item);
const char* name_alias = NULL; const char* name_alias = NULL;
const RecordKeyNode* dbKeyNode; const ValueExprNode* exprNode;
switch (item->nod_type) switch (item->nod_type)
{ {
@ -887,23 +877,15 @@ void MAKE_parameter_names(dsql_par* parameter, const dsql_nod* item)
exprNode->setParameterName(parameter); exprNode->setParameterName(parameter);
} }
break; break;
case nod_field:
field = (dsql_fld*) item->nod_arg[e_fld_field];
name_alias = field->fld_name.c_str();
context = (dsql_ctx*) item->nod_arg[e_fld_context];
break;
case nod_alias: case nod_alias:
string = (dsql_str*) item->nod_arg[e_alias_alias]; string = (dsql_str*) item->nod_arg[e_alias_alias];
alias = item->nod_arg[e_alias_value]; alias = item->nod_arg[e_alias_value];
if (alias->nod_type == nod_field) if ((exprNode = ExprNode::as<RecordKeyNode>(alias)) ||
(exprNode = ExprNode::as<FieldNode>(alias)))
{ {
field = (dsql_fld*) alias->nod_arg[e_fld_field]; exprNode->setParameterName(parameter);
parameter->par_name = field->fld_name.c_str();
context = (dsql_ctx*) alias->nod_arg[e_fld_context];
} }
else if ((dbKeyNode = ExprNode::as<RecordKeyNode>(alias)))
dbKeyNode->setParameterName(parameter);
parameter->par_alias = string->str_data; parameter->par_alias = string->str_data;
break; break;
@ -912,6 +894,7 @@ void MAKE_parameter_names(dsql_par* parameter, const dsql_nod* item)
case nod_simple_case: case nod_simple_case:
name_alias = "CASE"; name_alias = "CASE";
break; break;
case nod_coalesce: case nod_coalesce:
name_alias = "COALESCE"; name_alias = "COALESCE";
break; break;
@ -919,20 +902,4 @@ void MAKE_parameter_names(dsql_par* parameter, const dsql_nod* item)
if (name_alias) if (name_alias)
parameter->par_name = parameter->par_alias = name_alias; parameter->par_name = parameter->par_alias = name_alias;
if (context)
{
if (context->ctx_relation)
{
parameter->par_rel_name = context->ctx_relation->rel_name.c_str();
parameter->par_owner_name = context->ctx_relation->rel_owner.c_str();
}
else if (context->ctx_procedure)
{
parameter->par_rel_name = context->ctx_procedure->prc_name.identifier.c_str();
parameter->par_owner_name = context->ctx_procedure->prc_owner.c_str();
}
parameter->par_rel_alias = context->ctx_alias;
}
} }

View File

@ -122,7 +122,6 @@ enum nod_t
nod_flag, nod_flag,
nod_join, nod_join,
nod_unique, nod_unique,
nod_field,
nod_dom_value, nod_dom_value,
nod_field_name, nod_field_name,
nod_alias, nod_alias,
@ -255,11 +254,6 @@ enum node_args {
e_fpd_list = 0, // nod_for_update e_fpd_list = 0, // nod_for_update
e_fpd_count, e_fpd_count,
e_fld_context = 0, // nod_field
e_fld_field,
e_fld_indices,
e_fld_count,
e_ary_array = 0, // nod_array e_ary_array = 0, // nod_array
e_ary_indices, e_ary_indices,
e_ary_count, e_ary_count,

View File

@ -391,14 +391,6 @@ bool AggregateFinder::internalVisit(const dsql_nod* node)
return aggregate; return aggregate;
} }
case nod_field:
{
const dsql_ctx* localContext = reinterpret_cast<dsql_ctx*>(node->nod_arg[e_fld_context]);
if (deepestLevel < localContext->ctx_scope_level)
deepestLevel = localContext->ctx_scope_level;
return false;
}
default: default:
return visitChildren(node); return visitChildren(node);
} }
@ -452,7 +444,6 @@ bool Aggregate2Finder::internalVisit(const dsql_nod* node)
} }
case nod_relation: case nod_relation:
case nod_field:
return false; return false;
default: default:
@ -513,36 +504,6 @@ bool FieldFinder::internalVisit(const dsql_nod* node)
case nod_relation: case nod_relation:
return false; return false;
case nod_field:
{
const dsql_ctx* field_context = (dsql_ctx*) node->nod_arg[e_fld_context];
DEV_BLKCHK(field_context, dsql_type_ctx);
field = true;
switch (matchType)
{
case FIELD_MATCH_TYPE_EQUAL:
return field_context->ctx_scope_level == checkScopeLevel;
case FIELD_MATCH_TYPE_LOWER:
return field_context->ctx_scope_level < checkScopeLevel;
case FIELD_MATCH_TYPE_LOWER_EQUAL:
return field_context->ctx_scope_level <= checkScopeLevel;
///case FIELD_MATCH_TYPE_HIGHER:
/// return field_context->ctx_scope_level > checkScopeLevel;
///case FIELD_MATCH_TYPE_HIGHER_EQUAL:
/// return field_context->ctx_scope_level >= checkScopeLevel;
default:
fb_assert(false);
}
break;
}
default: default:
return visitChildren(node); return visitChildren(node);
} }
@ -596,28 +557,6 @@ bool InvalidReferenceFinder::internalVisit(const dsql_nod* node)
invalid |= visit(&node->nod_arg[e_agg_rse]); invalid |= visit(&node->nod_arg[e_agg_rse]);
break; break;
case nod_field:
{
const dsql_ctx* localContext = reinterpret_cast<dsql_ctx*>(node->nod_arg[e_fld_context]);
// Wouldn't it be better to call an error from this point where return is true?
// Then we could give the fieldname that's making the trouble.
// If we come here then this field is used inside a aggregate-function. The
// ctx_scope_level gives the info how deep the context is inside the statement.
// If the context-scope-level from this field is lower or the same as the scope-level
// from the given context then it is an invalid field.
if (localContext->ctx_scope_level == context->ctx_scope_level)
{
// Return true (invalid) if this field isn't inside the GROUP BY clause, that
// should already been seen in the match_node test in that routine start.
invalid = true;
}
break;
}
case nod_coalesce: case nod_coalesce:
///case nod_unique: ///case nod_unique:
case nod_rse: case nod_rse:
@ -674,15 +613,6 @@ bool FieldRemapper::internalVisit(dsql_nod* node)
switch (node->nod_type) switch (node->nod_type)
{ {
case nod_field:
{
const dsql_ctx* localContext = reinterpret_cast<dsql_ctx*>(node->nod_arg[e_fld_context]);
if (localContext->ctx_scope_level == context->ctx_scope_level)
replaceNode(PASS1_post_map(dsqlScratch, node, context, partitionNode, orderNode));
break;
}
case nod_rse: case nod_rse:
{ {
AutoSetRestore<USHORT> autoCurrentLevel(&currentLevel, currentLevel + 1); AutoSetRestore<USHORT> autoCurrentLevel(&currentLevel, currentLevel + 1);
@ -756,7 +686,6 @@ bool SubSelectFinder::internalVisit(const dsql_nod* node)
case nod_aggregate: case nod_aggregate:
case nod_field:
case nod_relation: case nod_relation:
case nod_field_name: case nod_field_name:
return false; return false;
@ -1116,11 +1045,6 @@ dsql_nod* PASS1_node(DsqlCompilerScratch* dsqlScratch, dsql_nod* input)
return pass1_variable(dsqlScratch, input); return pass1_variable(dsqlScratch, input);
return pass1_field(dsqlScratch, input, false, NULL); return pass1_field(dsqlScratch, input, false, NULL);
case nod_field:
// AB: nod_field is an already passed node.
// This could be done in expand_select_list.
return input;
case nod_array: case nod_array:
if (dsqlScratch->isPsql()) if (dsqlScratch->isPsql())
{ {
@ -2212,10 +2136,11 @@ static void field_appears_once(const dsql_nod* fields, const dsql_nod* old_field
if (elem1->nod_type == nod_assign && !is_insert) if (elem1->nod_type == nod_assign && !is_insert)
elem1 = elem1->nod_arg[e_asgn_field]; elem1 = elem1->nod_arg[e_asgn_field];
if (elem1->nod_type == nod_field) const FieldNode* fieldNode1 = ExprNode::as<FieldNode>(elem1);
if (fieldNode1)
{ {
const Firebird::MetaName& n1 = const Firebird::MetaName& n1 = fieldNode1->dsqlField->fld_name;
reinterpret_cast<dsql_fld*>(elem1->nod_arg[e_fld_field])->fld_name;
for (int j = i + 1; j < fields->nod_count; ++j) for (int j = i + 1; j < fields->nod_count; ++j)
{ {
@ -2223,19 +2148,20 @@ static void field_appears_once(const dsql_nod* fields, const dsql_nod* old_field
if (elem2->nod_type == nod_assign && !is_insert) if (elem2->nod_type == nod_assign && !is_insert)
elem2 = elem2->nod_arg[e_asgn_field]; elem2 = elem2->nod_arg[e_asgn_field];
if (elem2->nod_type == nod_field) const FieldNode* fieldNode2 = ExprNode::as<FieldNode>(elem2);
if (fieldNode2)
{ {
const Firebird::MetaName& n2 = const Firebird::MetaName& n2 = fieldNode2->dsqlField->fld_name;
reinterpret_cast<dsql_fld*>(elem2->nod_arg[e_fld_field])->fld_name;
if (n1 == n2) if (n1 == n2)
{ {
const dsql_ctx* tmp_ctx = (dsql_ctx*) elem2->nod_arg[e_fld_context]; const dsql_ctx* tmp_ctx = fieldNode2->dsqlContext;
const dsql_rel* bad_rel = tmp_ctx ? tmp_ctx->ctx_relation : 0; const dsql_rel* bad_rel = tmp_ctx ? tmp_ctx->ctx_relation : 0;
field_duplication(bad_rel ? bad_rel->rel_name.c_str() : 0, field_duplication((bad_rel ? bad_rel->rel_name.c_str() : 0),
n2.c_str(), n2.c_str(),
is_insert ? old_fields->nod_arg[j]: old_fields->nod_arg[j]->nod_arg[1], (is_insert ? old_fields->nod_arg[j] : old_fields->nod_arg[j]->nod_arg[1]),
dsqlScratch); dsqlScratch);
} }
} }
} }
@ -2585,19 +2511,6 @@ bool PASS1_node_match(const dsql_nod* node1, const dsql_nod* node2, bool ignore_
} }
return true; return true;
case nod_field:
if (node1->nod_arg[e_fld_field] != node2->nod_arg[e_fld_field] ||
node1->nod_arg[e_fld_context] != node2->nod_arg[e_fld_context])
{
return false;
}
if (node1->nod_arg[e_fld_indices] || node2->nod_arg[e_fld_indices])
{
return PASS1_node_match(node1->nod_arg[e_fld_indices],
node2->nod_arg[e_fld_indices], ignore_map_cast);
}
return true;
case nod_derived_table: case nod_derived_table:
{ {
const dsql_ctx* ctx1 = (dsql_ctx*) node1->nod_arg[e_derived_table_context]; const dsql_ctx* ctx1 = (dsql_ctx*) node1->nod_arg[e_derived_table_context];
@ -2735,8 +2648,10 @@ static void pass1_blob( DsqlCompilerScratch* dsqlScratch, dsql_nod* input)
thread_db* tdbb = JRD_get_thread_data(); thread_db* tdbb = JRD_get_thread_data();
PASS1_make_context(dsqlScratch, input->nod_arg[e_blb_relation]); PASS1_make_context(dsqlScratch, input->nod_arg[e_blb_relation]);
dsql_nod* field = pass1_field(dsqlScratch, input->nod_arg[e_blb_field], false, NULL); FieldNode* field = ExprNode::as<FieldNode>(
if (field->nod_desc.dsc_dtype != dtype_blob) pass1_field(dsqlScratch, input->nod_arg[e_blb_field], false, NULL));
if (field->dsqlDesc.dsc_dtype != dtype_blob)
{ {
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-206) << ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-206) <<
Arg::Gds(isc_dsql_blob_err)); Arg::Gds(isc_dsql_blob_err));
@ -2758,8 +2673,8 @@ static void pass1_blob( DsqlCompilerScratch* dsqlScratch, dsql_nod* input)
blob->blb_segment = parameter; blob->blb_segment = parameter;
parameter->par_desc.dsc_dtype = dtype_text; parameter->par_desc.dsc_dtype = dtype_text;
parameter->par_desc.dsc_ttype() = ttype_binary; parameter->par_desc.dsc_ttype() = ttype_binary;
parameter->par_desc.dsc_length = ((dsql_fld*) field->nod_arg[e_fld_field])->fld_seg_length; parameter->par_desc.dsc_length = field->dsqlField->fld_seg_length;
DEV_BLKCHK(field->nod_arg[e_fld_field], dsql_type_fld); DEV_BLKCHK(field->dsqlField, dsql_type_fld);
// The Null indicator is used to pass back the segment length, // The Null indicator is used to pass back the segment length,
// set DSC_nullable so that the SQL_type is set to SQL_TEXT+1 instead // set DSC_nullable so that the SQL_type is set to SQL_TEXT+1 instead
@ -2773,7 +2688,7 @@ static void pass1_blob( DsqlCompilerScratch* dsqlScratch, dsql_nod* input)
dsql_msg* temp_msg = (input->nod_type == nod_get_segment) ? dsql_msg* temp_msg = (input->nod_type == nod_get_segment) ?
blob->blb_open_in_msg : blob->blb_open_out_msg; blob->blb_open_in_msg : blob->blb_open_out_msg;
blob->blb_blob_id = parameter = MAKE_parameter(temp_msg, true, true, 0, NULL); blob->blb_blob_id = parameter = MAKE_parameter(temp_msg, true, true, 0, NULL);
MAKE_desc(dsqlScratch, &parameter->par_desc, field); field->make(dsqlScratch, &parameter->par_desc);
parameter->par_desc.dsc_dtype = dtype_quad; parameter->par_desc.dsc_dtype = dtype_quad;
parameter->par_desc.dsc_scale = 0; parameter->par_desc.dsc_scale = 0;
@ -4243,28 +4158,24 @@ static dsql_nod* pass1_group_by_list(DsqlCompilerScratch* dsqlScratch, dsql_nod*
static dsql_nod* pass1_hidden_variable(DsqlCompilerScratch* dsqlScratch, dsql_nod*& expr) static dsql_nod* pass1_hidden_variable(DsqlCompilerScratch* dsqlScratch, dsql_nod*& expr)
{ {
// For some node types, it's better to not create temporary value. // For some node types, it's better to not create temporary value.
switch (expr->nod_type) if (expr->nod_type == nod_class_exprnode)
{ {
case nod_field: switch (ExprNode::fromLegacy(expr)->type)
return NULL; {
case ExprNode::TYPE_CURRENT_DATE:
case nod_class_exprnode: case ExprNode::TYPE_CURRENT_TIME:
switch (ExprNode::fromLegacy(expr)->type) case ExprNode::TYPE_CURRENT_TIMESTAMP:
{ case ExprNode::TYPE_CURRENT_ROLE:
case ExprNode::TYPE_CURRENT_DATE: case ExprNode::TYPE_CURRENT_USER:
case ExprNode::TYPE_CURRENT_TIME: case ExprNode::TYPE_FIELD:
case ExprNode::TYPE_CURRENT_TIMESTAMP: case ExprNode::TYPE_INTERNAL_INFO:
case ExprNode::TYPE_CURRENT_ROLE: case ExprNode::TYPE_LITERAL:
case ExprNode::TYPE_CURRENT_USER: case ExprNode::TYPE_NULL:
case ExprNode::TYPE_INTERNAL_INFO: case ExprNode::TYPE_PARAMETER:
case ExprNode::TYPE_LITERAL: case ExprNode::TYPE_RECORD_KEY:
case ExprNode::TYPE_NULL: case ExprNode::TYPE_VARIABLE:
case ExprNode::TYPE_PARAMETER: return NULL;
case ExprNode::TYPE_RECORD_KEY: }
case ExprNode::TYPE_VARIABLE:
return NULL;
}
break;
} }
VariableNode* var = MAKE_variable(NULL, "", VAR_local, 0, 0, dsqlScratch->hiddenVarsNumber++); VariableNode* var = MAKE_variable(NULL, "", VAR_local, 0, 0, dsqlScratch->hiddenVarsNumber++);
@ -4349,13 +4260,14 @@ static dsql_nod* pass1_insert( DsqlCompilerScratch* dsqlScratch, dsql_nod* input
const dsql_ctx* tmp_ctx = NULL; const dsql_ctx* tmp_ctx = NULL;
const TEXT* tmp_name = NULL; const TEXT* tmp_name = NULL;
const FieldNode* fieldNode;
const DerivedFieldNode* derivedField; const DerivedFieldNode* derivedField;
if (temp2->nod_type == nod_field) if ((fieldNode = ExprNode::as<FieldNode>(temp2)))
{ {
tmp_ctx = (dsql_ctx*) temp2->nod_arg[e_fld_context]; tmp_ctx = fieldNode->dsqlContext;
tmp_name = (temp2->nod_arg[e_fld_field] ? if (fieldNode->dsqlField)
((dsql_fld*) temp2->nod_arg[e_fld_field])->fld_name.c_str() : NULL); tmp_name = fieldNode->dsqlField->fld_name.c_str();
} }
else if ((derivedField = ExprNode::as<DerivedFieldNode>(temp2))) else if ((derivedField = ExprNode::as<DerivedFieldNode>(temp2)))
{ {
@ -4543,6 +4455,7 @@ static dsql_nod* pass1_join(DsqlCompilerScratch* dsqlScratch, dsql_nod* input)
{ {
const TEXT* name = NULL; const TEXT* name = NULL;
dsql_nod* item = j.object(); dsql_nod* item = j.object();
FieldNode* fieldNode;
DerivedFieldNode* derivedField; DerivedFieldNode* derivedField;
switch (item->nod_type) switch (item->nod_type)
@ -4551,12 +4464,10 @@ static dsql_nod* pass1_join(DsqlCompilerScratch* dsqlScratch, dsql_nod* input)
name = reinterpret_cast<dsql_str*>(item->nod_arg[e_alias_alias])->str_data; name = reinterpret_cast<dsql_str*>(item->nod_arg[e_alias_alias])->str_data;
break; break;
case nod_field:
name = reinterpret_cast<dsql_fld*>(item->nod_arg[e_fld_field])->fld_name.c_str();
break;
default: default:
if ((derivedField = ExprNode::as<DerivedFieldNode>(item))) if ((fieldNode = ExprNode::as<FieldNode>(item)))
name = fieldNode->dsqlField->fld_name.c_str();
else if ((derivedField = ExprNode::as<DerivedFieldNode>(item)))
name = derivedField->name.c_str(); name = derivedField->name.c_str();
break; break;
} }
@ -4865,6 +4776,7 @@ static dsql_nod* pass1_lookup_alias(DsqlCompilerScratch* dsqlScratch, const dsql
{ {
dsql_nod* matchingNode = NULL; dsql_nod* matchingNode = NULL;
dsql_nod* node = *ptr; dsql_nod* node = *ptr;
FieldNode* fieldNode;
DerivedFieldNode* derivedField; DerivedFieldNode* derivedField;
switch (node->nod_type) switch (node->nod_type)
@ -4878,16 +4790,13 @@ static dsql_nod* pass1_lookup_alias(DsqlCompilerScratch* dsqlScratch, const dsql
} }
break; break;
case nod_field: default:
if ((fieldNode = ExprNode::as<FieldNode>(node)))
{ {
const dsql_fld* field = (dsql_fld*) node->nod_arg[e_fld_field]; if (fieldNode->dsqlField->fld_name == name->str_data)
if (field->fld_name == name->str_data)
matchingNode = node; matchingNode = node;
} }
break; else if ((derivedField = ExprNode::as<DerivedFieldNode>(node)))
default:
if ((derivedField = ExprNode::as<DerivedFieldNode>(node)))
{ {
if (strcmp(derivedField->name.c_str(), name->str_data) == 0) if (strcmp(derivedField->name.c_str(), name->str_data) == 0)
matchingNode = node; matchingNode = node;
@ -4907,16 +4816,14 @@ static dsql_nod* pass1_lookup_alias(DsqlCompilerScratch* dsqlScratch, const dsql
buffer1[0] = 0; buffer1[0] = 0;
switch (returnNode->nod_type) switch (returnNode->nod_type)
{ {
case nod_field:
strcat(buffer1, "a field");
break;
case nod_alias: case nod_alias:
strcat(buffer1, "an alias"); strcat(buffer1, "an alias");
break; break;
default: default:
if ((derivedField = ExprNode::as<DerivedFieldNode>(returnNode))) if (ExprNode::is<FieldNode>(returnNode))
strcat(buffer1, "a field");
else if (ExprNode::is<DerivedFieldNode>(returnNode))
strcat(buffer1, "a derived field"); strcat(buffer1, "a derived field");
else else
strcat(buffer1, "an item"); strcat(buffer1, "an item");
@ -4928,16 +4835,14 @@ static dsql_nod* pass1_lookup_alias(DsqlCompilerScratch* dsqlScratch, const dsql
switch (matchingNode->nod_type) switch (matchingNode->nod_type)
{ {
case nod_field:
strcat(buffer2, "a field");
break;
case nod_alias: case nod_alias:
strcat(buffer2, "an alias"); strcat(buffer2, "an alias");
break; break;
default: default:
if ((derivedField = ExprNode::as<DerivedFieldNode>(matchingNode))) if (ExprNode::is<FieldNode>(matchingNode))
strcat(buffer2, "a field");
else if (ExprNode::is<DerivedFieldNode>(matchingNode))
strcat(buffer2, "a derived field"); strcat(buffer2, "a derived field");
else else
strcat(buffer2, "an item"); strcat(buffer2, "an item");
@ -4980,23 +4885,6 @@ static dsql_nod* pass1_make_derived_field(DsqlCompilerScratch* dsqlScratch, thre
switch (select_item->nod_type) switch (select_item->nod_type)
{ {
case nod_field:
{
const dsql_fld* field = (dsql_fld*) select_item->nod_arg[e_fld_field];
DEV_BLKCHK(field, dsql_type_fld);
// Create a derived field and hook in.
DerivedFieldNode* newField = FB_NEW(pool) DerivedFieldNode(pool, field->fld_name,
dsqlScratch->scopeLevel, select_item);
dsql_nod* nod = MAKE_node(nod_class_exprnode, 1);
nod->nod_arg[0] = reinterpret_cast<dsql_nod*>(newField);
nod->nod_desc = select_item->nod_desc;
return nod;
}
case nod_alias: case nod_alias:
{ {
const dsql_str* alias_alias = (dsql_str*) select_item->nod_arg[e_alias_alias]; const dsql_str* alias_alias = (dsql_str*) select_item->nod_arg[e_alias_alias];
@ -5017,6 +4905,7 @@ static dsql_nod* pass1_make_derived_field(DsqlCompilerScratch* dsqlScratch, thre
{ {
SubQueryNode* subQueryNode; SubQueryNode* subQueryNode;
DsqlMapNode* mapNode; DsqlMapNode* mapNode;
FieldNode* fieldNode;
DerivedFieldNode* derivedField; DerivedFieldNode* derivedField;
if ((subQueryNode = ExprNode::as<SubQueryNode>(select_item))) if ((subQueryNode = ExprNode::as<SubQueryNode>(select_item)))
@ -5045,6 +4934,19 @@ static dsql_nod* pass1_make_derived_field(DsqlCompilerScratch* dsqlScratch, thre
return derived_field; return derived_field;
} }
} }
else if ((fieldNode = ExprNode::as<FieldNode>(select_item)))
{
// Create a derived field and hook in.
DerivedFieldNode* newField = FB_NEW(pool) DerivedFieldNode(pool,
fieldNode->dsqlField->fld_name, dsqlScratch->scopeLevel, select_item);
dsql_nod* nod = MAKE_node(nod_class_exprnode, 1);
nod->nod_arg[0] = reinterpret_cast<dsql_nod*>(newField);
nod->nod_desc = fieldNode->dsqlDesc;
return nod;
}
else if ((derivedField = ExprNode::as<DerivedFieldNode>(select_item))) else if ((derivedField = ExprNode::as<DerivedFieldNode>(select_item)))
{ {
// Create a derived field that points to a derived field. // Create a derived field that points to a derived field.
@ -7086,16 +6988,17 @@ static void pass1_union_auto_cast(DsqlCompilerScratch* dsqlScratch, dsql_nod* in
name_node = mapNode->map->map_node; name_node = mapNode->map->map_node;
} }
if (name_node->nod_type == nod_field) const FieldNode* fieldNode;
if ((fieldNode = ExprNode::as<FieldNode>(name_node)))
{ {
dsql_fld* sub_field = (dsql_fld*) name_node->nod_arg[e_fld_field];
// Create new node for alias and copy fieldname // Create new node for alias and copy fieldname
alias_node = MAKE_node(nod_alias, e_alias_count); alias_node = MAKE_node(nod_alias, e_alias_count);
// Copy fieldname to a new string. // Copy fieldname to a new string.
dsql_str* str_alias = FB_NEW_RPT(*tdbb->getDefaultPool(), dsql_str* str_alias = FB_NEW_RPT(*tdbb->getDefaultPool(),
sub_field->fld_name.length()) dsql_str; fieldNode->dsqlField->fld_name.length()) dsql_str;
strcpy(str_alias->str_data, sub_field->fld_name.c_str()); strcpy(str_alias->str_data, fieldNode->dsqlField->fld_name.c_str());
str_alias->str_length = sub_field->fld_name.length(); str_alias->str_length = fieldNode->dsqlField->fld_name.length();
alias_node->nod_arg[e_alias_alias] = (dsql_nod*) str_alias; alias_node->nod_arg[e_alias_alias] = (dsql_nod*) str_alias;
} }
} }
@ -7965,24 +7868,27 @@ static dsql_nod* resolve_using_field(DsqlCompilerScratch* dsqlScratch, dsql_str*
PASS1_field_unknown(qualifier.c_str(), name->str_data, flawedNode); PASS1_field_unknown(qualifier.c_str(), name->str_data, flawedNode);
} }
FieldNode* fieldNode;
DerivedFieldNode* derivedField; DerivedFieldNode* derivedField;
if ((derivedField = ExprNode::as<DerivedFieldNode>(node))) if ((fieldNode = ExprNode::as<FieldNode>(node)))
{
ctx = fieldNode->dsqlContext;
return node;
}
else if ((derivedField = ExprNode::as<DerivedFieldNode>(node)))
{ {
ctx = derivedField->context; ctx = derivedField->context;
return node; return node;
} }
switch (node->nod_type) if (node->nod_type == nod_alias)
{ {
case nod_field:
ctx = reinterpret_cast<dsql_ctx*>(node->nod_arg[e_fln_context]);
break;
case nod_alias:
fb_assert(node->nod_count >= (int) e_alias_imp_join - 1); fb_assert(node->nod_count >= (int) e_alias_imp_join - 1);
ctx = reinterpret_cast<ImplicitJoin*>(node->nod_arg[e_alias_imp_join])->visibleInContext; ctx = reinterpret_cast<ImplicitJoin*>(node->nod_arg[e_alias_imp_join])->visibleInContext;
break; }
default: else
{
fb_assert(false); fb_assert(false);
} }
@ -8107,10 +8013,10 @@ static void set_parameter_name( dsql_nod* par_node, const dsql_nod* fld_node, co
if (!par_node) if (!par_node)
return; return;
// Could it be something else ??? const FieldNode* fieldNode = ExprNode::as<FieldNode>(fld_node);
fb_assert(fld_node->nod_type == nod_field); fb_assert(fieldNode); // Could it be something else ???
if (fld_node->nod_desc.dsc_dtype != dtype_array) if (fieldNode->dsqlDesc.dsc_dtype != dtype_array)
return; return;
switch (par_node->nod_type) switch (par_node->nod_type)
@ -8141,9 +8047,7 @@ static void set_parameter_name( dsql_nod* par_node, const dsql_nod* fld_node, co
{ {
ParameterNode* paramNode = exprNode->as<ParameterNode>(); ParameterNode* paramNode = exprNode->as<ParameterNode>();
dsql_par* parameter = paramNode->dsqlParameter; dsql_par* parameter = paramNode->dsqlParameter;
const dsql_fld* field = (dsql_fld*) fld_node->nod_arg[e_fld_field]; parameter->par_name = fieldNode->dsqlField->fld_name.c_str();
DEV_BLKCHK(field, dsql_type_fld);
parameter->par_name = field->fld_name.c_str();
parameter->par_rel_name = relation->rel_name.c_str(); parameter->par_rel_name = relation->rel_name.c_str();
break; break;
} }
@ -8790,20 +8694,6 @@ void DSQL_pretty(const dsql_nod* node, int column)
return; return;
} }
case nod_field:
{
const dsql_ctx* context = (dsql_ctx*) node->nod_arg[e_fld_context];
const dsql_rel* relation = context->ctx_relation;
const dsql_prc* procedure = context->ctx_procedure;
const dsql_fld* field = (dsql_fld*) node->nod_arg[e_fld_field];
trace_line("%sfield %s.%s, context %d\n", buffer,
(relation != NULL ?
relation->rel_name.c_str() :
(procedure != NULL ? procedure->prc_name.toString().c_str() : "unknown_db_object")),
field->fld_name.c_str(), context->ctx_context);
return;
}
case nod_field_name: case nod_field_name:
trace_line("%sfield name: \"", buffer); trace_line("%sfield name: \"", buffer);
string = (dsql_str*) node->nod_arg[e_fln_context]; string = (dsql_str*) node->nod_arg[e_fln_context];