mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 04:43:03 +01:00
Refactor DSQL's nod_field
This commit is contained in:
parent
667caf5257
commit
4a9f98bed7
@ -7392,9 +7392,10 @@ void CreateAlterViewNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
|
||||
}
|
||||
|
||||
const dsql_fld* nameField = NULL;
|
||||
const FieldNode* fieldNameNode = ExprNode::as<FieldNode>(nameNode);
|
||||
|
||||
if (nameNode->nod_type == Dsql::nod_field)
|
||||
nameField = (dsql_fld*) nameNode->nod_arg[Dsql::e_fld_field];
|
||||
if (fieldNameNode)
|
||||
nameField = fieldNameNode->dsqlField;
|
||||
|
||||
const TEXT* fieldStr = NULL;
|
||||
|
||||
@ -7411,10 +7412,12 @@ void CreateAlterViewNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
|
||||
dsql_fld* field = 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];
|
||||
context = (dsql_ctx*) fieldNode->nod_arg[Dsql::e_fld_context];
|
||||
field = fieldNameNode->dsqlField;
|
||||
context = fieldNameNode->dsqlContext;
|
||||
}
|
||||
else
|
||||
updatable = false;
|
||||
@ -8064,8 +8067,8 @@ dsql_nod* CreateAlterViewNode::replaceFieldNames(dsql_nod* input, dsql_nod* sear
|
||||
if (replaceFields)
|
||||
replaceName = (dsql_str*) (*replace)->nod_arg[Dsql::e_fln_name];
|
||||
|
||||
const dsql_nod* fieldNode = *search;
|
||||
const dsql_fld* field = (dsql_fld*) fieldNode->nod_arg[Dsql::e_fld_field];
|
||||
const FieldNode* fieldNode = ExprNode::as<FieldNode>(*search);
|
||||
const dsql_fld* field = fieldNode->dsqlField;
|
||||
|
||||
if (field->fld_name == fieldName->str_data)
|
||||
{
|
||||
|
@ -4202,12 +4202,16 @@ static RegisterNode<FieldNode> regFieldNodeField(blr_field);
|
||||
|
||||
FieldNode::FieldNode(MemoryPool& pool)
|
||||
: TypedNode<ValueExprNode, ExprNode::TYPE_FIELD>(pool),
|
||||
dsqlContext(NULL),
|
||||
dsqlField(NULL),
|
||||
dsqlIndices(NULL),
|
||||
byId(false),
|
||||
fieldStream(0),
|
||||
fieldId(0),
|
||||
format(NULL),
|
||||
defaultValue(NULL)
|
||||
{
|
||||
dsqlDesc.clear();
|
||||
}
|
||||
|
||||
// Parse a field.
|
||||
@ -4383,40 +4387,191 @@ void FieldNode::print(string& text, Array<dsql_nod*>& nodes) const
|
||||
ExprNode::print(text, nodes);
|
||||
}
|
||||
|
||||
//// TODO: Implement FieldNode DSQL support.
|
||||
|
||||
ValueExprNode* FieldNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
|
||||
{
|
||||
// AB: nod_field is an already passed node.
|
||||
// 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 NULL;
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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
|
||||
{
|
||||
fb_assert(false);
|
||||
if (!ExprNode::dsqlMatch(other, ignoreMapCast))
|
||||
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,
|
||||
USHORT stream) /*const*/
|
||||
{
|
||||
const FieldNode* o = other->as<FieldNode>();
|
||||
// ASF: Why not test fieldStream == o->fieldStream?
|
||||
return o && fieldId == o->fieldId && o->fieldStream == stream;
|
||||
}
|
||||
|
||||
@ -5626,30 +5781,17 @@ void DsqlMapNode::setParameterName(dsql_par* parameter) const
|
||||
}
|
||||
|
||||
const char* nameAlias = NULL;
|
||||
const dsql_ctx* context = NULL;
|
||||
const dsql_fld* field;
|
||||
const FieldNode* fieldNode = NULL;
|
||||
const dsql_nod* alias;
|
||||
const dsql_str* str;
|
||||
|
||||
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:
|
||||
str = (dsql_str*) nestNode->nod_arg[Dsql::e_alias_alias];
|
||||
parameter->par_alias = str->str_data;
|
||||
alias = nestNode->nod_arg[Dsql::e_alias_value];
|
||||
|
||||
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];
|
||||
}
|
||||
fieldNode = ExprNode::as<FieldNode>(alias);
|
||||
break;
|
||||
|
||||
case Dsql::nod_class_exprnode:
|
||||
@ -5668,19 +5810,25 @@ void DsqlMapNode::setParameterName(dsql_par* parameter) const
|
||||
{
|
||||
parameter->par_alias = derivedField->name;
|
||||
alias = derivedField->dsqlValue;
|
||||
|
||||
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];
|
||||
}
|
||||
fieldNode = ExprNode::as<FieldNode>(alias);
|
||||
}
|
||||
else if ((fieldNode = ExprNode::as<FieldNode>(nestNode)))
|
||||
nameAlias = fieldNode->dsqlField->fld_name.c_str();
|
||||
|
||||
break;
|
||||
}
|
||||
} // 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)
|
||||
parameter->par_name = parameter->par_alias = nameAlias;
|
||||
|
||||
@ -5836,13 +5984,13 @@ bool DerivedFieldNode::dsqlFieldRemapper(FieldRemapper& visitor)
|
||||
void DerivedFieldNode::setParameterName(dsql_par* parameter) const
|
||||
{
|
||||
const dsql_ctx* context = NULL;
|
||||
const FieldNode* fieldNode;
|
||||
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 = field->fld_name.c_str();
|
||||
context = (dsql_ctx*) dsqlValue->nod_arg[Dsql::e_fld_context];
|
||||
parameter->par_name = fieldNode->dsqlField->fld_name.c_str();
|
||||
context = fieldNode->dsqlContext;
|
||||
}
|
||||
else if ((dbKeyNode = ExprNode::as<RecordKeyNode>(dsqlValue)))
|
||||
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
|
||||
// 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<RecordKeyNode>(dsqlValue) &&
|
||||
!ExprNode::is<DsqlMapNode>(dsqlValue))
|
||||
|
@ -437,6 +437,14 @@ public:
|
||||
|
||||
virtual void print(Firebird::string& text, Firebird::Array<dsql_nod*>& nodes) const;
|
||||
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 genBlr(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsc* desc);
|
||||
@ -478,6 +486,10 @@ public:
|
||||
virtual dsc* execute(thread_db* tdbb, jrd_req* request) const;
|
||||
|
||||
public:
|
||||
dsql_ctx* dsqlContext;
|
||||
dsql_fld* dsqlField;
|
||||
dsql_nod* dsqlIndices;
|
||||
dsc dsqlDesc;
|
||||
bool byId;
|
||||
USHORT fieldStream;
|
||||
USHORT fieldId;
|
||||
|
@ -67,7 +67,6 @@ 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_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_map(DsqlCompilerScratch*, dsql_map*);
|
||||
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
|
||||
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:
|
||||
gen_join_rse(dsqlScratch, node);
|
||||
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
|
||||
|
@ -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?
|
||||
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:
|
||||
MAKE_desc(dsqlScratch, desc, node->nod_arg[e_hidden_var_expr]);
|
||||
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(indices, dsql_type_nod);
|
||||
|
||||
dsql_nod* node = MAKE_node(nod_field, e_fld_count);
|
||||
node->nod_arg[e_fld_context] = (dsql_nod*) context;
|
||||
node->nod_arg[e_fld_field] = (dsql_nod*) field;
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
FieldNode* node = FB_NEW(*tdbb->getDefaultPool()) FieldNode(*tdbb->getDefaultPool());
|
||||
node->dsqlContext = context;
|
||||
node->dsqlField = field;
|
||||
|
||||
if (field->fld_dimensions)
|
||||
{
|
||||
if (indices)
|
||||
{
|
||||
node->nod_arg[e_fld_indices] = indices;
|
||||
MAKE_desc_from_field(&node->nod_desc, field);
|
||||
node->nod_desc.dsc_dtype = static_cast<UCHAR>(field->fld_element_dtype);
|
||||
node->nod_desc.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->dsqlIndices = indices;
|
||||
MAKE_desc_from_field(&node->dsqlDesc, field);
|
||||
node->dsqlDesc.dsc_dtype = static_cast<UCHAR>(field->fld_element_dtype);
|
||||
node->dsqlDesc.dsc_length = field->fld_element_length;
|
||||
|
||||
// node->dsqlDesc.dsc_scale = field->fld_scale;
|
||||
// node->dsqlDesc.dsc_sub_type = field->fld_sub_type;
|
||||
}
|
||||
else
|
||||
{
|
||||
node->nod_desc.dsc_dtype = dtype_array;
|
||||
node->nod_desc.dsc_length = sizeof(ISC_QUAD);
|
||||
node->nod_desc.dsc_scale = static_cast<SCHAR>(field->fld_scale);
|
||||
node->nod_desc.dsc_sub_type = field->fld_sub_type;
|
||||
node->dsqlDesc.dsc_dtype = dtype_array;
|
||||
node->dsqlDesc.dsc_length = sizeof(ISC_QUAD);
|
||||
node->dsqlDesc.dsc_scale = static_cast<SCHAR>(field->fld_scale);
|
||||
node->dsqlDesc.dsc_sub_type = field->fld_sub_type;
|
||||
}
|
||||
}
|
||||
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));
|
||||
}
|
||||
|
||||
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))
|
||||
{
|
||||
node->nod_desc.dsc_flags |= DSC_nullable;
|
||||
}
|
||||
node->dsqlDesc.dsc_flags |= DSC_nullable;
|
||||
|
||||
// UNICODE_FSS_HACK
|
||||
// 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 &&
|
||||
INTL_GET_CHARSET(&node->nod_desc) == CS_METADATA)
|
||||
if ((field->fld_flags & FLD_system) && node->dsqlDesc.dsc_dtype <= dtype_varying &&
|
||||
INTL_GET_CHARSET(&node->dsqlDesc) == CS_METADATA)
|
||||
{
|
||||
USHORT adjust = 0;
|
||||
|
||||
if (node->nod_desc.dsc_dtype == dtype_varying)
|
||||
if (node->dsqlDesc.dsc_dtype == dtype_varying)
|
||||
adjust = sizeof(USHORT);
|
||||
else if (node->nod_desc.dsc_dtype == dtype_cstring)
|
||||
else if (node->dsqlDesc.dsc_dtype == dtype_cstring)
|
||||
adjust = 1;
|
||||
|
||||
node->nod_desc.dsc_length -= adjust;
|
||||
node->nod_desc.dsc_length *= 3;
|
||||
node->nod_desc.dsc_length += adjust;
|
||||
node->dsqlDesc.dsc_length -= adjust;
|
||||
node->dsqlDesc.dsc_length *= 3;
|
||||
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);
|
||||
|
||||
const char* name_alias = NULL;
|
||||
const RecordKeyNode* dbKeyNode;
|
||||
const ValueExprNode* exprNode;
|
||||
|
||||
switch (item->nod_type)
|
||||
{
|
||||
@ -887,23 +877,15 @@ void MAKE_parameter_names(dsql_par* parameter, const dsql_nod* item)
|
||||
exprNode->setParameterName(parameter);
|
||||
}
|
||||
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:
|
||||
string = (dsql_str*) item->nod_arg[e_alias_alias];
|
||||
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];
|
||||
parameter->par_name = field->fld_name.c_str();
|
||||
context = (dsql_ctx*) alias->nod_arg[e_fld_context];
|
||||
exprNode->setParameterName(parameter);
|
||||
}
|
||||
else if ((dbKeyNode = ExprNode::as<RecordKeyNode>(alias)))
|
||||
dbKeyNode->setParameterName(parameter);
|
||||
|
||||
parameter->par_alias = string->str_data;
|
||||
break;
|
||||
@ -912,6 +894,7 @@ void MAKE_parameter_names(dsql_par* parameter, const dsql_nod* item)
|
||||
case nod_simple_case:
|
||||
name_alias = "CASE";
|
||||
break;
|
||||
|
||||
case nod_coalesce:
|
||||
name_alias = "COALESCE";
|
||||
break;
|
||||
@ -919,20 +902,4 @@ void MAKE_parameter_names(dsql_par* parameter, const dsql_nod* item)
|
||||
|
||||
if (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;
|
||||
}
|
||||
}
|
||||
|
@ -122,7 +122,6 @@ enum nod_t
|
||||
nod_flag,
|
||||
nod_join,
|
||||
nod_unique,
|
||||
nod_field,
|
||||
nod_dom_value,
|
||||
nod_field_name,
|
||||
nod_alias,
|
||||
@ -255,11 +254,6 @@ enum node_args {
|
||||
e_fpd_list = 0, // nod_for_update
|
||||
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_indices,
|
||||
e_ary_count,
|
||||
|
@ -391,14 +391,6 @@ bool AggregateFinder::internalVisit(const dsql_nod* node)
|
||||
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:
|
||||
return visitChildren(node);
|
||||
}
|
||||
@ -452,7 +444,6 @@ bool Aggregate2Finder::internalVisit(const dsql_nod* node)
|
||||
}
|
||||
|
||||
case nod_relation:
|
||||
case nod_field:
|
||||
return false;
|
||||
|
||||
default:
|
||||
@ -513,36 +504,6 @@ bool FieldFinder::internalVisit(const dsql_nod* node)
|
||||
case nod_relation:
|
||||
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:
|
||||
return visitChildren(node);
|
||||
}
|
||||
@ -596,28 +557,6 @@ bool InvalidReferenceFinder::internalVisit(const dsql_nod* node)
|
||||
invalid |= visit(&node->nod_arg[e_agg_rse]);
|
||||
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_unique:
|
||||
case nod_rse:
|
||||
@ -674,15 +613,6 @@ bool FieldRemapper::internalVisit(dsql_nod* node)
|
||||
|
||||
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:
|
||||
{
|
||||
AutoSetRestore<USHORT> autoCurrentLevel(¤tLevel, currentLevel + 1);
|
||||
@ -756,7 +686,6 @@ bool SubSelectFinder::internalVisit(const dsql_nod* node)
|
||||
|
||||
case nod_aggregate:
|
||||
|
||||
case nod_field:
|
||||
case nod_relation:
|
||||
case nod_field_name:
|
||||
return false;
|
||||
@ -1116,11 +1045,6 @@ dsql_nod* PASS1_node(DsqlCompilerScratch* dsqlScratch, dsql_nod* input)
|
||||
return pass1_variable(dsqlScratch, input);
|
||||
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:
|
||||
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)
|
||||
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 =
|
||||
reinterpret_cast<dsql_fld*>(elem1->nod_arg[e_fld_field])->fld_name;
|
||||
const Firebird::MetaName& n1 = fieldNode1->dsqlField->fld_name;
|
||||
|
||||
for (int j = i + 1; j < fields->nod_count; ++j)
|
||||
{
|
||||
@ -2223,18 +2148,19 @@ static void field_appears_once(const dsql_nod* fields, const dsql_nod* old_field
|
||||
if (elem2->nod_type == nod_assign && !is_insert)
|
||||
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 =
|
||||
reinterpret_cast<dsql_fld*>(elem2->nod_arg[e_fld_field])->fld_name;
|
||||
const Firebird::MetaName& n2 = fieldNode2->dsqlField->fld_name;
|
||||
|
||||
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;
|
||||
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(),
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -2585,19 +2511,6 @@ bool PASS1_node_match(const dsql_nod* node1, const dsql_nod* node2, bool ignore_
|
||||
}
|
||||
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:
|
||||
{
|
||||
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();
|
||||
|
||||
PASS1_make_context(dsqlScratch, input->nod_arg[e_blb_relation]);
|
||||
dsql_nod* field = pass1_field(dsqlScratch, input->nod_arg[e_blb_field], false, NULL);
|
||||
if (field->nod_desc.dsc_dtype != dtype_blob)
|
||||
FieldNode* field = ExprNode::as<FieldNode>(
|
||||
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) <<
|
||||
Arg::Gds(isc_dsql_blob_err));
|
||||
@ -2758,8 +2673,8 @@ static void pass1_blob( DsqlCompilerScratch* dsqlScratch, dsql_nod* input)
|
||||
blob->blb_segment = parameter;
|
||||
parameter->par_desc.dsc_dtype = dtype_text;
|
||||
parameter->par_desc.dsc_ttype() = ttype_binary;
|
||||
parameter->par_desc.dsc_length = ((dsql_fld*) field->nod_arg[e_fld_field])->fld_seg_length;
|
||||
DEV_BLKCHK(field->nod_arg[e_fld_field], dsql_type_fld);
|
||||
parameter->par_desc.dsc_length = field->dsqlField->fld_seg_length;
|
||||
DEV_BLKCHK(field->dsqlField, dsql_type_fld);
|
||||
|
||||
// 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
|
||||
@ -2773,7 +2688,7 @@ static void pass1_blob( DsqlCompilerScratch* dsqlScratch, dsql_nod* input)
|
||||
dsql_msg* temp_msg = (input->nod_type == nod_get_segment) ?
|
||||
blob->blb_open_in_msg : blob->blb_open_out_msg;
|
||||
blob->blb_blob_id = parameter = MAKE_parameter(temp_msg, true, true, 0, NULL);
|
||||
MAKE_desc(dsqlScratch, ¶meter->par_desc, field);
|
||||
field->make(dsqlScratch, ¶meter->par_desc);
|
||||
parameter->par_desc.dsc_dtype = dtype_quad;
|
||||
parameter->par_desc.dsc_scale = 0;
|
||||
|
||||
@ -4243,12 +4158,8 @@ static dsql_nod* pass1_group_by_list(DsqlCompilerScratch* dsqlScratch, dsql_nod*
|
||||
static dsql_nod* pass1_hidden_variable(DsqlCompilerScratch* dsqlScratch, dsql_nod*& expr)
|
||||
{
|
||||
// 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:
|
||||
return NULL;
|
||||
|
||||
case nod_class_exprnode:
|
||||
switch (ExprNode::fromLegacy(expr)->type)
|
||||
{
|
||||
case ExprNode::TYPE_CURRENT_DATE:
|
||||
@ -4256,6 +4167,7 @@ static dsql_nod* pass1_hidden_variable(DsqlCompilerScratch* dsqlScratch, dsql_no
|
||||
case ExprNode::TYPE_CURRENT_TIMESTAMP:
|
||||
case ExprNode::TYPE_CURRENT_ROLE:
|
||||
case ExprNode::TYPE_CURRENT_USER:
|
||||
case ExprNode::TYPE_FIELD:
|
||||
case ExprNode::TYPE_INTERNAL_INFO:
|
||||
case ExprNode::TYPE_LITERAL:
|
||||
case ExprNode::TYPE_NULL:
|
||||
@ -4264,7 +4176,6 @@ static dsql_nod* pass1_hidden_variable(DsqlCompilerScratch* dsqlScratch, dsql_no
|
||||
case ExprNode::TYPE_VARIABLE:
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
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 TEXT* tmp_name = NULL;
|
||||
const FieldNode* fieldNode;
|
||||
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_name = (temp2->nod_arg[e_fld_field] ?
|
||||
((dsql_fld*) temp2->nod_arg[e_fld_field])->fld_name.c_str() : NULL);
|
||||
tmp_ctx = fieldNode->dsqlContext;
|
||||
if (fieldNode->dsqlField)
|
||||
tmp_name = fieldNode->dsqlField->fld_name.c_str();
|
||||
}
|
||||
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;
|
||||
dsql_nod* item = j.object();
|
||||
FieldNode* fieldNode;
|
||||
DerivedFieldNode* derivedField;
|
||||
|
||||
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;
|
||||
break;
|
||||
|
||||
case nod_field:
|
||||
name = reinterpret_cast<dsql_fld*>(item->nod_arg[e_fld_field])->fld_name.c_str();
|
||||
break;
|
||||
|
||||
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();
|
||||
break;
|
||||
}
|
||||
@ -4865,6 +4776,7 @@ static dsql_nod* pass1_lookup_alias(DsqlCompilerScratch* dsqlScratch, const dsql
|
||||
{
|
||||
dsql_nod* matchingNode = NULL;
|
||||
dsql_nod* node = *ptr;
|
||||
FieldNode* fieldNode;
|
||||
DerivedFieldNode* derivedField;
|
||||
|
||||
switch (node->nod_type)
|
||||
@ -4878,16 +4790,13 @@ static dsql_nod* pass1_lookup_alias(DsqlCompilerScratch* dsqlScratch, const dsql
|
||||
}
|
||||
break;
|
||||
|
||||
case nod_field:
|
||||
default:
|
||||
if ((fieldNode = ExprNode::as<FieldNode>(node)))
|
||||
{
|
||||
const dsql_fld* field = (dsql_fld*) node->nod_arg[e_fld_field];
|
||||
if (field->fld_name == name->str_data)
|
||||
if (fieldNode->dsqlField->fld_name == name->str_data)
|
||||
matchingNode = node;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if ((derivedField = ExprNode::as<DerivedFieldNode>(node)))
|
||||
else if ((derivedField = ExprNode::as<DerivedFieldNode>(node)))
|
||||
{
|
||||
if (strcmp(derivedField->name.c_str(), name->str_data) == 0)
|
||||
matchingNode = node;
|
||||
@ -4907,16 +4816,14 @@ static dsql_nod* pass1_lookup_alias(DsqlCompilerScratch* dsqlScratch, const dsql
|
||||
buffer1[0] = 0;
|
||||
switch (returnNode->nod_type)
|
||||
{
|
||||
case nod_field:
|
||||
strcat(buffer1, "a field");
|
||||
break;
|
||||
|
||||
case nod_alias:
|
||||
strcat(buffer1, "an alias");
|
||||
break;
|
||||
|
||||
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");
|
||||
else
|
||||
strcat(buffer1, "an item");
|
||||
@ -4928,16 +4835,14 @@ static dsql_nod* pass1_lookup_alias(DsqlCompilerScratch* dsqlScratch, const dsql
|
||||
|
||||
switch (matchingNode->nod_type)
|
||||
{
|
||||
case nod_field:
|
||||
strcat(buffer2, "a field");
|
||||
break;
|
||||
|
||||
case nod_alias:
|
||||
strcat(buffer2, "an alias");
|
||||
break;
|
||||
|
||||
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");
|
||||
else
|
||||
strcat(buffer2, "an item");
|
||||
@ -4980,23 +4885,6 @@ static dsql_nod* pass1_make_derived_field(DsqlCompilerScratch* dsqlScratch, thre
|
||||
|
||||
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:
|
||||
{
|
||||
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;
|
||||
DsqlMapNode* mapNode;
|
||||
FieldNode* fieldNode;
|
||||
DerivedFieldNode* derivedField;
|
||||
|
||||
if ((subQueryNode = ExprNode::as<SubQueryNode>(select_item)))
|
||||
@ -5045,6 +4934,19 @@ static dsql_nod* pass1_make_derived_field(DsqlCompilerScratch* dsqlScratch, thre
|
||||
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)))
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
|
||||
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
|
||||
alias_node = MAKE_node(nod_alias, e_alias_count);
|
||||
// Copy fieldname to a new string.
|
||||
dsql_str* str_alias = FB_NEW_RPT(*tdbb->getDefaultPool(),
|
||||
sub_field->fld_name.length()) dsql_str;
|
||||
strcpy(str_alias->str_data, sub_field->fld_name.c_str());
|
||||
str_alias->str_length = sub_field->fld_name.length();
|
||||
fieldNode->dsqlField->fld_name.length()) dsql_str;
|
||||
strcpy(str_alias->str_data, fieldNode->dsqlField->fld_name.c_str());
|
||||
str_alias->str_length = fieldNode->dsqlField->fld_name.length();
|
||||
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);
|
||||
}
|
||||
|
||||
FieldNode* fieldNode;
|
||||
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;
|
||||
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);
|
||||
ctx = reinterpret_cast<ImplicitJoin*>(node->nod_arg[e_alias_imp_join])->visibleInContext;
|
||||
break;
|
||||
default:
|
||||
}
|
||||
else
|
||||
{
|
||||
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)
|
||||
return;
|
||||
|
||||
// Could it be something else ???
|
||||
fb_assert(fld_node->nod_type == nod_field);
|
||||
const FieldNode* fieldNode = ExprNode::as<FieldNode>(fld_node);
|
||||
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;
|
||||
|
||||
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>();
|
||||
dsql_par* parameter = paramNode->dsqlParameter;
|
||||
const dsql_fld* field = (dsql_fld*) fld_node->nod_arg[e_fld_field];
|
||||
DEV_BLKCHK(field, dsql_type_fld);
|
||||
parameter->par_name = field->fld_name.c_str();
|
||||
parameter->par_name = fieldNode->dsqlField->fld_name.c_str();
|
||||
parameter->par_rel_name = relation->rel_name.c_str();
|
||||
break;
|
||||
}
|
||||
@ -8790,20 +8694,6 @@ void DSQL_pretty(const dsql_nod* node, int column)
|
||||
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:
|
||||
trace_line("%sfield name: \"", buffer);
|
||||
string = (dsql_str*) node->nod_arg[e_fln_context];
|
||||
|
Loading…
Reference in New Issue
Block a user