@@ -4109,6 +4109,10 @@ TableValueFunctionSourceNode* TableValueFunctionSourceNode::parseFunction(thread
41094109 node = FB_NEW_POOL (pool) UnlistFunctionSourceNode (pool);
41104110 break ;
41114111
4112+ case blr_table_value_fun_gen_series:
4113+ node = FB_NEW_POOL (pool) GenSeriesFunctionSourceNode (pool);
4114+ break ;
4115+
41124116 default :
41134117 PAR_syntax_error (csb, " blr_table_value_fun" );
41144118 }
@@ -4161,6 +4165,8 @@ void TableValueFunctionSourceNode::genBlr(DsqlCompilerScratch* dsqlScratch)
41614165
41624166 if (tableValueFunctionContext->funName == UnlistFunctionSourceNode::FUNC_NAME)
41634167 dsqlScratch->appendUChar (blr_table_value_fun_unlist);
4168+ else if (tableValueFunctionContext->funName == GenSeriesFunctionSourceNode::FUNC_NAME)
4169+ dsqlScratch->appendUChar (blr_table_value_fun_gen_series);
41644170 else
41654171 fb_assert (false );
41664172
@@ -4307,7 +4313,8 @@ void TableValueFunctionSourceNode::setDefaultNameField(DsqlCompilerScratch* /*ds
43074313
43084314 auto i = 0U ;
43094315
4310- if (nameFunc == UnlistFunctionSourceNode::FUNC_NAME)
4316+ if ((nameFunc == UnlistFunctionSourceNode::FUNC_NAME) ||
4317+ (nameFunc == GenSeriesFunctionSourceNode::FUNC_NAME))
43114318 {
43124319 dsql_fld* field = tableValueFunctionContext->outputField ;
43134320 if (field->fld_name .isEmpty ())
@@ -4320,6 +4327,8 @@ void TableValueFunctionSourceNode::setDefaultNameField(DsqlCompilerScratch* /*ds
43204327 fb_assert (false );
43214328}
43224329
4330+ // --------------------
4331+
43234332RecordSource* UnlistFunctionSourceNode::compile (thread_db* tdbb, Optimizer* opt,
43244333 bool /* innerSubStream*/ )
43254334{
@@ -4378,6 +4387,88 @@ dsql_fld* UnlistFunctionSourceNode::makeField(DsqlCompilerScratch* dsqlScratch)
43784387
43794388// --------------------
43804389
4390+ RecordSource* GenSeriesFunctionSourceNode::compile (thread_db* tdbb, Optimizer* opt,
4391+ bool /* innerSubStream*/ )
4392+ {
4393+ MemoryPool& pool = *tdbb->getDefaultPool ();
4394+ const auto csb = opt->getCompilerScratch ();
4395+ const auto alias = opt->makeAlias (stream);
4396+
4397+ return FB_NEW_POOL (pool) GenSeriesFunctionScan (csb, stream, alias, inputList);
4398+ }
4399+
4400+ dsql_fld* GenSeriesFunctionSourceNode::makeField (DsqlCompilerScratch* dsqlScratch)
4401+ {
4402+ if (inputList)
4403+ inputList = Node::doDsqlPass (dsqlScratch, inputList, false );
4404+
4405+ const auto startItem = inputList->items [0 ].getObject ();
4406+ startItem->setParameterType (
4407+ dsqlScratch, [](dsc* desc) { desc->makeInt64 (0 ); }, false );
4408+
4409+ const auto finishItem = inputList->items [1 ].getObject ();
4410+ finishItem->setParameterType (
4411+ dsqlScratch, [](dsc* desc) { desc->makeInt64 (0 ); }, false );
4412+
4413+ const auto stepItem = inputList->items [2 ].getObject ();
4414+ stepItem->setParameterType (
4415+ dsqlScratch, [](dsc* desc) { desc->makeInt64 (0 ); }, false );
4416+
4417+ dsc startDesc;
4418+ DsqlDescMaker::fromNode (dsqlScratch, &startDesc, startItem, true );
4419+ if (!startDesc.isExact () && !startDesc.isNull ())
4420+ status_exception::raise (Arg::Gds (isc_argmustbe_exact_function) << Arg::Str (getName ()));
4421+
4422+ dsc finishDesc;
4423+ DsqlDescMaker::fromNode (dsqlScratch, &finishDesc, finishItem, true );
4424+ if (!finishDesc.isExact () && !finishDesc.isNull ())
4425+ status_exception::raise (Arg::Gds (isc_argmustbe_exact_function) << Arg::Str (getName ()));
4426+
4427+ dsc stepDesc;
4428+ DsqlDescMaker::fromNode (dsqlScratch, &stepDesc, stepItem, true );
4429+ if (!stepDesc.isExact () && !stepDesc.isNull ())
4430+ status_exception::raise (Arg::Gds (isc_argmustbe_exact_function) << Arg::Str (getName ()));
4431+
4432+ // common scale
4433+ const auto scale = MIN (MIN (startDesc.dsc_scale , finishDesc.dsc_scale ), stepDesc.dsc_scale );
4434+ // common type
4435+ const auto dtype = MAX (MAX (startDesc.dsc_dtype , finishDesc.dsc_dtype ), stepDesc.dsc_dtype );
4436+
4437+ dsql_fld* field = dsqlField;
4438+
4439+ if (!field)
4440+ {
4441+ field = FB_NEW_POOL (dsqlScratch->getPool ()) dsql_fld (dsqlScratch->getPool ());
4442+
4443+ dsc desc;
4444+ if (dtype == dtype_int128)
4445+ desc.makeInt128 (scale);
4446+ else
4447+ desc.makeInt64 (scale);
4448+
4449+ MAKE_field (field, &desc);
4450+ field->fld_id = 0 ;
4451+ }
4452+
4453+ if (dsqlNameColumns.hasData ())
4454+ {
4455+ if (dsqlNameColumns.getCount () > 1 )
4456+ {
4457+ ERRD_post (Arg::Gds (isc_sqlerr) << Arg::Num (-104 ) << Arg::Gds (isc_dsql_command_err)
4458+ << Arg::Gds (isc_dsql_table_value_many_columns)
4459+ << Arg::Str (getName ())
4460+ << Arg::Num (1 ) << Arg::Num (dsqlNameColumns.getCount ()));
4461+ }
4462+
4463+ field->fld_name = dsqlNameColumns[0 ];
4464+ }
4465+
4466+ field->resolve (dsqlScratch);
4467+ return field;
4468+ }
4469+
4470+ // --------------------
4471+
43814472
43824473static RecordSourceNode* dsqlPassRelProc (DsqlCompilerScratch* dsqlScratch, RecordSourceNode* source)
43834474{
0 commit comments