Skip to content

Commit 84d9f20

Browse files
committed
support INT128 datatype
1 parent 328eb39 commit 84d9f20

File tree

6 files changed

+120
-41
lines changed

6 files changed

+120
-41
lines changed

doc/sql.extensions/README.generate_series.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,20 @@ The interval and the step between series values ​​are defined by the user.
1313
## Arguments
1414

1515
* `start` - The first value in the interval. `start` is specified as a variable, a literal, or a scalar expression of type
16-
`smallint`, `integer`, `bigint` or `numeric(18, x)`.
16+
`SMALLINT`, `INTEGER`, `BIGINT`, `INT128` or `NUMERIC/DECIMAL`.
1717

1818
* `finish` - The last value in the interval. `finish` is specified as a variable, a literal, or a scalar expression of
19-
type `smallint`, `integer`, `bigint` or `numeric(18, x)`. The series stops once the last generated step value exceeds
20-
the `finish` value.
19+
type `SMALLINT`, `INTEGER`, `BIGINT`, `INT128` or `NUMERIC/DECIMAL`. The series stops once the last generated step value
20+
exceeds the `finish` value.
2121

2222
* `step` - Indicates the number of values to increment or decrement between steps in the series. `step` is an expression
23-
of type `smallint`, `integer`, `bigint` or `numeric(18, x)`. `step` can be either negative or positive, but can't be zero (0). This
24-
argument is optional. The default value for `step` is 1.
23+
of type `SMALLINT`, `INTEGER`, `BIGINT`, `INT128` or `NUMERIC/DECIMAL`.
24+
`step` can be either negative or positive, but can't be zero (0). This argument is optional. The default value for `step` is 1.
2525

2626
## Returning type
2727

28-
The function `GENERATE_SERIES` returns a set with `BIGINT` or `NUMERIC(18, x)` column, where the scale is
29-
determined by the maximum of the scales of the function arguments.
28+
The function `GENERATE_SERIES` returns a set with `BIGINT`, `INT128` or `NUMERIC(18, x)/NUMERIC(38, x)` column,
29+
where the scale is determined by the maximum of the scales of the function arguments.
3030

3131
## Rules
3232

src/include/firebird/impl/msg/jrd.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -999,3 +999,4 @@ FB_IMPL_MSG(JRD, 996, invalid_name, -901, "HY", "000", "Invalid name: @1")
999999
FB_IMPL_MSG(JRD, 997, invalid_unqualified_name_list, -901, "HY", "000", "Invalid list of unqualified names: @1")
10001000
FB_IMPL_MSG(JRD, 998, no_user_att_while_restore, -901, "HY", "000", "User attachments are not allowed for the database being restored")
10011001
FB_IMPL_MSG(JRD, 999, genseq_stepmustbe_nonzero, -833, "42", "000", "Argument STEP must be different than zero for function @1")
1002+
FB_IMPL_MSG(JRD, 1000, argmustbe_exact_function, -833, "42", "000", "Arguments for @1 function must be exact numeric types")

src/include/gen/Firebird.pas

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5845,6 +5845,7 @@ IProfilerStatsImpl = class(IProfilerStats)
58455845
isc_invalid_unqualified_name_list = 335545317;
58465846
isc_no_user_att_while_restore = 335545318;
58475847
isc_genseq_stepmustbe_nonzero = 335545319;
5848+
isc_argmustbe_exact_function = 335545320;
58485849
isc_gfix_db_name = 335740929;
58495850
isc_gfix_invalid_sw = 335740930;
58505851
isc_gfix_incmp_sw = 335740932;

src/jrd/RecordSourceNodes.cpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4415,15 +4415,26 @@ dsql_fld* GenSeriesFunctionSourceNode::makeField(DsqlCompilerScratch* dsqlScratc
44154415

44164416
dsc startDesc;
44174417
DsqlDescMaker::fromNode(dsqlScratch, &startDesc, startItem, true);
4418+
if (!startDesc.isExact() && !startDesc.isNull()) {
4419+
status_exception::raise(Arg::Gds(isc_argmustbe_exact_function) << Arg::Str(getName()));
4420+
}
44184421

44194422
dsc finishDesc;
44204423
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+
}
44214427

44224428
dsc stepDesc;
44234429
DsqlDescMaker::fromNode(dsqlScratch, &stepDesc, stepItem, true);
4430+
if (!stepDesc.isExact() && !stepDesc.isNull()) {
4431+
status_exception::raise(Arg::Gds(isc_argmustbe_exact_function) << Arg::Str(getName()));
4432+
}
44244433

44254434
// common scale
44264435
const auto scale = MIN(MIN(startDesc.dsc_scale, finishDesc.dsc_scale), stepDesc.dsc_scale);
4436+
// common type
4437+
const auto dtype = MAX(MAX(startDesc.dsc_dtype, finishDesc.dsc_dtype), stepDesc.dsc_dtype);
44274438

44284439
dsql_fld* field = dsqlField;
44294440

@@ -4432,7 +4443,12 @@ dsql_fld* GenSeriesFunctionSourceNode::makeField(DsqlCompilerScratch* dsqlScratc
44324443
field = FB_NEW_POOL(dsqlScratch->getPool()) dsql_fld(dsqlScratch->getPool());
44334444

44344445
dsc desc;
4435-
desc.makeInt64(scale);
4446+
if (dtype == dtype_int128) {
4447+
desc.makeInt128(scale);
4448+
}
4449+
else {
4450+
desc.makeInt64(scale);
4451+
}
44364452
MAKE_field(field, &desc);
44374453
field->fld_id = 0;
44384454
}

src/jrd/recsrc/RecordSource.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#define JRD_RECORD_SOURCE_H
2525

2626
#include <optional>
27+
#include <variant>
2728
#include "../common/classes/array.h"
2829
#include "../common/classes/objects_array.h"
2930
#include "../common/classes/NestConst.h"
@@ -1627,10 +1628,11 @@ namespace Jrd
16271628

16281629
struct Impure : public TableValueFunctionScan::Impure
16291630
{
1630-
SINT64 m_start;
1631-
SINT64 m_finish;
1632-
SINT64 m_step;
1633-
SINT64 m_result;
1631+
std::variant<SINT64, Firebird::Int128> m_start;
1632+
std::variant<SINT64, Firebird::Int128> m_finish;
1633+
std::variant<SINT64, Firebird::Int128> m_step;
1634+
std::variant<SINT64, Firebird::Int128> m_result;
1635+
UCHAR m_dtype;
16341636
SCHAR m_scale;
16351637
};
16361638

src/jrd/recsrc/TableValueFunctionScan.cpp

Lines changed: 88 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -405,32 +405,60 @@ void GenSeriesFunctionScan::internalOpen(thread_db* tdbb) const
405405
return;
406406
}
407407

408-
// common scale
409-
const auto scale = MIN(MIN(startDesc->dsc_scale, finishDesc->dsc_scale), stepDesc->dsc_scale);
408+
const auto impure = request->getImpure<Impure>(m_impure);
409+
impure->m_recordBuffer = nullptr;
410410

411-
const auto start = MOV_get_int64(tdbb, startDesc, scale);
412-
const auto finish = MOV_get_int64(tdbb, finishDesc, scale);
413-
const auto step = MOV_get_int64(tdbb, stepDesc, scale);
411+
// common scale
412+
impure->m_scale = MIN(MIN(startDesc->dsc_scale, finishDesc->dsc_scale), stepDesc->dsc_scale);
413+
// common type
414+
impure->m_dtype = MAX(MAX(startDesc->dsc_dtype, finishDesc->dsc_dtype), stepDesc->dsc_dtype);
414415

415-
// validate parameter value
416-
if (((step > 0) && (start > finish)) ||
417-
((step < 0) && (start < finish)))
416+
if (impure->m_dtype != dtype_int128)
418417
{
419-
rpb->rpb_number.setValid(false);
420-
return;
418+
const auto start = MOV_get_int64(tdbb, startDesc, impure->m_scale);
419+
const auto finish = MOV_get_int64(tdbb, finishDesc, impure->m_scale);
420+
const auto step = MOV_get_int64(tdbb, stepDesc, impure->m_scale);
421+
422+
if (step == 0)
423+
status_exception::raise(Arg::Gds(isc_genseq_stepmustbe_nonzero) << Arg::Str(m_name));
424+
425+
// validate parameter value
426+
if (((step > 0) && (start > finish)) ||
427+
((step < 0) && (start < finish)))
428+
{
429+
rpb->rpb_number.setValid(false);
430+
return;
431+
}
432+
433+
impure->m_start = start;
434+
impure->m_finish = finish;
435+
impure->m_step = step;
421436
}
437+
else {
438+
const auto start = MOV_get_int128(tdbb, startDesc, impure->m_scale);
439+
const auto finish = MOV_get_int128(tdbb, finishDesc, impure->m_scale);
440+
const auto step = MOV_get_int128(tdbb, stepDesc, impure->m_scale);
422441

423-
if (step == 0)
424-
status_exception::raise(Arg::Gds(isc_genseq_stepmustbe_nonzero) << Arg::Str(m_name));
442+
if (step.sign() == 0)
443+
status_exception::raise(Arg::Gds(isc_genseq_stepmustbe_nonzero) << Arg::Str(m_name));
425444

426-
const auto impure = request->getImpure<Impure>(m_impure);
445+
// validate parameter value
446+
if (((step.sign() > 0) && (start.compare(finish) > 0)) ||
447+
((step.sign() < 0) && (start.compare(finish) < 0)))
448+
{
449+
rpb->rpb_number.setValid(false);
450+
return;
451+
}
452+
453+
impure->m_start = start;
454+
impure->m_finish = finish;
455+
impure->m_step = step;
456+
}
457+
458+
427459
impure->irsb_flags |= irsb_open;
428-
impure->m_recordBuffer = nullptr;
429-
impure->m_start = start;
430-
impure->m_finish = finish;
431-
impure->m_step = step;
432-
impure->m_result = start;
433-
impure->m_scale = scale;
460+
impure->m_result = impure->m_start;
461+
434462

435463
VIO_record(tdbb, rpb, m_format, &pool);
436464
}
@@ -465,7 +493,8 @@ bool GenSeriesFunctionScan::internalGetRecord(thread_db* tdbb) const
465493

466494
rpb->rpb_number.increment();
467495

468-
if (nextBuffer(tdbb)) {
496+
if (nextBuffer(tdbb))
497+
{
469498
rpb->rpb_number.setValid(true);
470499
return true;
471500
}
@@ -479,20 +508,50 @@ bool GenSeriesFunctionScan::nextBuffer(thread_db* tdbb) const
479508
const auto request = tdbb->getRequest();
480509
const auto impure = request->getImpure<Impure>(m_impure);
481510

482-
if (((impure->m_step > 0) && (impure->m_result <= impure->m_finish)) ||
483-
((impure->m_step < 0) && (impure->m_result >= impure->m_finish)))
511+
if (impure->m_dtype != dtype_int128)
484512
{
485-
Record* const record = request->req_rpb[m_stream].rpb_record;
513+
auto result = std::get<SINT64>(impure->m_result);
514+
const auto finish = std::get<SINT64>(impure->m_finish);
515+
const auto step = std::get<SINT64>(impure->m_step);
516+
517+
if (((step > 0) && (result <= finish)) ||
518+
((step < 0) && (result >= finish)))
519+
{
520+
Record* const record = request->req_rpb[m_stream].rpb_record;
486521

487-
auto toDesc = m_format->fmt_desc.begin();
522+
auto toDesc = m_format->fmt_desc.begin();
488523

489-
dsc fromDesc;
490-
fromDesc.makeInt64(impure->m_scale, &impure->m_result);
491-
assignParameter(tdbb, &fromDesc, toDesc, 0, record);
524+
dsc fromDesc;
525+
fromDesc.makeInt64(impure->m_scale, &result);
526+
assignParameter(tdbb, &fromDesc, toDesc, 0, record);
492527

493-
impure->m_result += impure->m_step;
528+
result += step;
529+
impure->m_result = result;
494530

495-
return true;
531+
return true;
532+
}
533+
}
534+
else {
535+
auto result = std::get<Firebird::Int128>(impure->m_result);
536+
const auto finish = std::get<Firebird::Int128>(impure->m_finish);
537+
const auto step = std::get<Firebird::Int128>(impure->m_step);
538+
539+
if (((step.sign() > 0) && (result.compare(finish) <= 0)) ||
540+
((step.sign() < 0) && (result.compare(finish) >= 0)))
541+
{
542+
Record* const record = request->req_rpb[m_stream].rpb_record;
543+
544+
auto toDesc = m_format->fmt_desc.begin();
545+
546+
dsc fromDesc;
547+
fromDesc.makeInt128(impure->m_scale, &result);
548+
assignParameter(tdbb, &fromDesc, toDesc, 0, record);
549+
550+
result = result.add(step);
551+
impure->m_result = result;
552+
553+
return true;
554+
}
496555
}
497556

498557
return false;

0 commit comments

Comments
 (0)