8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-22 20:03:02 +01:00

Replace Nullable by std::optional.

This commit is contained in:
Adriano dos Santos Fernandes 2023-09-18 20:27:14 -03:00
parent bf72356edb
commit c170e4b089
30 changed files with 498 additions and 329 deletions

View File

@ -1318,7 +1318,7 @@ int gbak(Firebird::UtilSvc* uSvc)
errNum = IN_SW_BURP_S; errNum = IN_SW_BURP_S;
else if (tdgbl->gbl_sw_no_reserve) else if (tdgbl->gbl_sw_no_reserve)
errNum = IN_SW_BURP_US; errNum = IN_SW_BURP_US;
else if (tdgbl->gbl_sw_replica.isAssigned()) else if (tdgbl->gbl_sw_replica.has_value())
errNum = IN_SW_BURP_REPLICA; errNum = IN_SW_BURP_REPLICA;
if (errNum != IN_SW_BURP_0) if (errNum != IN_SW_BURP_0)

View File

@ -29,6 +29,7 @@
#ifndef BURP_BURP_H #ifndef BURP_BURP_H
#define BURP_BURP_H #define BURP_BURP_H
#include <optional>
#include <stdio.h> #include <stdio.h>
#include "ibase.h" #include "ibase.h"
#include "firebird/Interface.h" #include "firebird/Interface.h"
@ -1033,7 +1034,7 @@ public:
ULONG io_buffer_size; ULONG io_buffer_size;
redirect_vals sw_redirect; redirect_vals sw_redirect;
bool burp_throw; bool burp_throw;
Nullable<ReplicaMode> gbl_sw_replica; std::optional<ReplicaMode> gbl_sw_replica;
UCHAR* blk_io_ptr; UCHAR* blk_io_ptr;
int blk_io_cnt; int blk_io_cnt;

View File

@ -27,6 +27,7 @@
*/ */
#include "firebird.h" #include "firebird.h"
#include <optional>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
@ -577,8 +578,8 @@ int RESTORE_restore (const TEXT* file_name, const TEXT* database_name)
dpb.insertByte(isc_dpb_force_write, tdgbl->hdr_forced_writes ? 1 : 0); dpb.insertByte(isc_dpb_force_write, tdgbl->hdr_forced_writes ? 1 : 0);
// set up the replica mode, if needed // set up the replica mode, if needed
if (tdgbl->gbl_sw_replica.isAssigned()) if (tdgbl->gbl_sw_replica.has_value())
dpb.insertByte(isc_dpb_set_db_replica, tdgbl->gbl_sw_replica.value); dpb.insertByte(isc_dpb_set_db_replica, tdgbl->gbl_sw_replica.value());
Firebird::IAttachment* db_handle = provider->attachDatabase(&tdgbl->status_vector, database_name, Firebird::IAttachment* db_handle = provider->attachDatabase(&tdgbl->status_vector, database_name,
dpb.getBufferLength(), dpb.getBuffer()); dpb.getBufferLength(), dpb.getBuffer());
@ -860,7 +861,7 @@ void create_database(BurpGlobals* tdgbl, Firebird::IProvider* provider, const TE
bool forced_writes = true; // turned on by default bool forced_writes = true; // turned on by default
ULONG page_buffers = 0; ULONG page_buffers = 0;
USHORT SQL_dialect = 0; USHORT SQL_dialect = 0;
Nullable<ReplicaMode> replica_mode; std::optional<ReplicaMode> replica_mode;
tdgbl->gbl_database_file_name = file_name; tdgbl->gbl_database_file_name = file_name;
@ -949,7 +950,7 @@ void create_database(BurpGlobals* tdgbl, Firebird::IProvider* provider, const TE
tdgbl->gbl_sw_mode_val = db_read_only; tdgbl->gbl_sw_mode_val = db_read_only;
} }
if (!tdgbl->gbl_sw_replica.isAssigned()) if (!tdgbl->gbl_sw_replica.has_value())
tdgbl->gbl_sw_replica = replica_mode; tdgbl->gbl_sw_replica = replica_mode;
if (tdgbl->gbl_sw_page_buffers) if (tdgbl->gbl_sw_page_buffers)

View File

@ -133,32 +133,32 @@ unsigned StatementMetadata::buildInfoFlags(unsigned itemsLength, const UCHAR* it
// Get statement type. // Get statement type.
unsigned StatementMetadata::getType() unsigned StatementMetadata::getType()
{ {
if (!type.specified) if (!type.has_value())
{ {
UCHAR info[] = {isc_info_sql_stmt_type}; UCHAR info[] = {isc_info_sql_stmt_type};
UCHAR result[16]; UCHAR result[16];
getAndParse(sizeof(info), info, sizeof(result), result); getAndParse(sizeof(info), info, sizeof(result), result);
fb_assert(type.specified); fb_assert(type.has_value());
} }
return type.value; return type.value();
} }
unsigned StatementMetadata::getFlags() unsigned StatementMetadata::getFlags()
{ {
if (!flags.specified) if (!flags.has_value())
{ {
UCHAR info[] = {isc_info_sql_stmt_flags}; UCHAR info[] = {isc_info_sql_stmt_flags};
UCHAR result[16]; UCHAR result[16];
getAndParse(sizeof(info), info, sizeof(result), result); getAndParse(sizeof(info), info, sizeof(result), result);
fb_assert(flags.specified); fb_assert(flags.has_value());
} }
return flags.value; return flags.value();
} }
// Get statement plan. // Get statement plan.
@ -228,7 +228,7 @@ ISC_UINT64 StatementMetadata::getAffectedRecords()
// Reset the object to its initial state. // Reset the object to its initial state.
void StatementMetadata::clear() void StatementMetadata::clear()
{ {
type.specified = false; type.reset();
legacyPlan = detailedPlan = ""; legacyPlan = detailedPlan = "";
inputParameters->items.clear(); inputParameters->items.clear();
outputParameters->items.clear(); outputParameters->items.clear();
@ -432,14 +432,14 @@ bool StatementMetadata::fillFromCache(unsigned itemsLength, const UCHAR* items,
if (((itemsLength == 1 && items[0] == isc_info_sql_stmt_type) || if (((itemsLength == 1 && items[0] == isc_info_sql_stmt_type) ||
(itemsLength == 2 && items[0] == isc_info_sql_stmt_type && (itemsLength == 2 && items[0] == isc_info_sql_stmt_type &&
(items[1] == isc_info_end || items[1] == 0))) && (items[1] == isc_info_end || items[1] == 0))) &&
type.specified) type.has_value())
{ {
if (bufferLength >= 8) if (bufferLength >= 8)
{ {
*buffer++ = isc_info_sql_stmt_type; *buffer++ = isc_info_sql_stmt_type;
put_vax_short(buffer, 4); put_vax_short(buffer, 4);
buffer += 2; buffer += 2;
put_vax_long(buffer, type.value); put_vax_long(buffer, type.value());
buffer += 4; buffer += 4;
*buffer = isc_info_end; *buffer = isc_info_end;
} }

View File

@ -25,6 +25,7 @@
#ifndef COMMON_STATEMENT_METADATA_H #ifndef COMMON_STATEMENT_METADATA_H
#define COMMON_STATEMENT_METADATA_H #define COMMON_STATEMENT_METADATA_H
#include <optional>
#include "firebird/Interface.h" #include "firebird/Interface.h"
#include "iberror.h" #include "iberror.h"
#include "../common/classes/Nullable.h" #include "../common/classes/Nullable.h"
@ -82,7 +83,7 @@ private:
private: private:
IStatement* statement; IStatement* statement;
Nullable<unsigned> type, flags; std::optional<unsigned> type, flags;
string legacyPlan, detailedPlan; string legacyPlan, detailedPlan;
RefPtr<Parameters> inputParameters, outputParameters; RefPtr<Parameters> inputParameters, outputParameters;
}; };

View File

@ -341,7 +341,7 @@ void defineComputed(DsqlCompilerScratch* dsqlScratch, RelationSourceNode* relati
fb_assert(field->scale <= MAX_SCHAR); fb_assert(field->scale <= MAX_SCHAR);
saveDesc.dsc_scale = (SCHAR) field->scale; saveDesc.dsc_scale = (SCHAR) field->scale;
saveDesc.dsc_sub_type = field->subType; saveDesc.dsc_sub_type = field->subType;
saveCharSetIdSpecified = field->charSetId.specified; saveCharSetIdSpecified = field->charSetId.has_value();
field->dtype = 0; field->dtype = 0;
field->length = 0; field->length = 0;
@ -376,8 +376,7 @@ void defineComputed(DsqlCompilerScratch* dsqlScratch, RelationSourceNode* relati
if (field->dtype <= dtype_any_text) if (field->dtype <= dtype_any_text)
{ {
field->charSetId = DSC_GET_CHARSET(&saveDesc); field->charSetId = saveCharSetIdSpecified ? std::optional{DSC_GET_CHARSET(&saveDesc)} : std::nullopt;
field->charSetId.specified = saveCharSetIdSpecified;
field->collationId = DSC_GET_COLLATE(&saveDesc); field->collationId = DSC_GET_COLLATE(&saveDesc);
} }
else else
@ -396,7 +395,7 @@ void defineComputed(DsqlCompilerScratch* dsqlScratch, RelationSourceNode* relati
field->collationId = DSC_GET_COLLATE(&desc); field->collationId = DSC_GET_COLLATE(&desc);
const USHORT adjust = field->dtype == dtype_varying ? sizeof(USHORT) : 0; const USHORT adjust = field->dtype == dtype_varying ? sizeof(USHORT) : 0;
const USHORT bpc = METD_get_charset_bpc(dsqlScratch->getTransaction(), field->charSetId.value); const USHORT bpc = METD_get_charset_bpc(dsqlScratch->getTransaction(), field->charSetId.value_or(CS_NONE));
field->charLength = (field->length - adjust) / bpc; field->charLength = (field->length - adjust) / bpc;
} }
else if (field->dtype == dtype_blob) else if (field->dtype == dtype_blob)
@ -845,7 +844,7 @@ static void updateRdbFields(const TypeClause* type,
if (type->subType == isc_blob_text) if (type->subType == isc_blob_text)
{ {
characterSetIdNull = FALSE; characterSetIdNull = FALSE;
characterSetId = type->charSetId.value; characterSetId = type->charSetId.value_or(CS_NONE);
collationIdNull = FALSE; collationIdNull = FALSE;
collationId = type->collationId; collationId = type->collationId;
@ -872,7 +871,7 @@ static void updateRdbFields(const TypeClause* type,
} }
characterSetIdNull = FALSE; characterSetIdNull = FALSE;
characterSetId = type->charSetId.value; characterSetId = type->charSetId.value_or(CS_NONE);
collationIdNull = FALSE; collationIdNull = FALSE;
collationId = type->collationId; collationId = type->collationId;
@ -1605,7 +1604,7 @@ void CommentOnNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
return; return;
} }
Nullable<string> description; std::optional<string> description;
if (text.hasData()) if (text.hasData())
description = text; description = text;
@ -1916,7 +1915,7 @@ bool CreateAlterFunctionNode::executeAlter(thread_db* tdbb, DsqlCompilerScratch*
// CVC: This is case of "returns <type> [by value|reference]". // CVC: This is case of "returns <type> [by value|reference]".
// Some data types can not be returned as value. // Some data types can not be returned as value.
if (returnType->udfMechanism.value == FUN_value && if (returnType->udfMechanism.value() == FUN_value &&
(field->dtype == dtype_text || field->dtype == dtype_varying || (field->dtype == dtype_text || field->dtype == dtype_varying ||
field->dtype == dtype_cstring || field->dtype == dtype_blob || field->dtype == dtype_cstring || field->dtype == dtype_blob ||
field->dtype == dtype_timestamp)) field->dtype == dtype_timestamp))
@ -1969,8 +1968,8 @@ bool CreateAlterFunctionNode::executeAlter(thread_db* tdbb, DsqlCompilerScratch*
// We'll verify that SCALAR_ARRAY can't be used as a return type. // We'll verify that SCALAR_ARRAY can't be used as a return type.
// The support for SCALAR_ARRAY is only for input parameters. // The support for SCALAR_ARRAY is only for input parameters.
if (parameters[udfReturnPos - 1]->udfMechanism.specified && if (parameters[udfReturnPos - 1]->udfMechanism.has_value() &&
parameters[udfReturnPos - 1]->udfMechanism.value == FUN_scalar_array) parameters[udfReturnPos - 1]->udfMechanism.value() == FUN_scalar_array)
{ {
status_exception::raise( status_exception::raise(
Arg::Gds(isc_sqlerr) << Arg::Num(-607) << Arg::Gds(isc_sqlerr) << Arg::Num(-607) <<
@ -2232,12 +2231,12 @@ void CreateAlterFunctionNode::storeArgument(thread_db* tdbb, DsqlCompilerScratch
{ {
// CVC: I need to test returning blobs by descriptor before allowing the // CVC: I need to test returning blobs by descriptor before allowing the
// change there. For now, I ignore the return type specification. // change there. For now, I ignore the return type specification.
const bool freeIt = parameter->udfMechanism.value < 0; const bool freeIt = parameter->udfMechanism.value() < 0;
ARG.RDB$MECHANISM = (SSHORT) ((freeIt ? -1 : 1) * FUN_blob_struct); ARG.RDB$MECHANISM = (SSHORT) ((freeIt ? -1 : 1) * FUN_blob_struct);
// If we have the FREE_IT set then the blob has to be freed on return. // If we have the FREE_IT set then the blob has to be freed on return.
} }
else if (parameter->udfMechanism.specified) else if (parameter->udfMechanism.has_value())
ARG.RDB$MECHANISM = (SSHORT) parameter->udfMechanism.value; ARG.RDB$MECHANISM = (SSHORT) parameter->udfMechanism.value();
else if (type->dtype == dtype_blob) else if (type->dtype == dtype_blob)
ARG.RDB$MECHANISM = (SSHORT) FUN_blob_struct; ARG.RDB$MECHANISM = (SSHORT) FUN_blob_struct;
else else
@ -3354,10 +3353,10 @@ void TriggerDefinition::store(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
TRG.RDB$RELATION_NAME.NULL = relationName.isEmpty(); TRG.RDB$RELATION_NAME.NULL = relationName.isEmpty();
strcpy(TRG.RDB$RELATION_NAME, relationName.c_str()); strcpy(TRG.RDB$RELATION_NAME, relationName.c_str());
fb_assert(type.specified); fb_assert(type.has_value());
TRG.RDB$TRIGGER_TYPE = type.value; TRG.RDB$TRIGGER_TYPE = type.value();
TRG.RDB$TRIGGER_SEQUENCE = (!position.specified ? 0 : position.value); TRG.RDB$TRIGGER_SEQUENCE = position.value_or(0);
TRG.RDB$TRIGGER_INACTIVE = (!active.specified ? 0 : (USHORT) !active.value); TRG.RDB$TRIGGER_INACTIVE = (!active.specified ? 0 : (USHORT) !active.value);
} }
END_STORE END_STORE
@ -3377,7 +3376,7 @@ bool TriggerDefinition::modify(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch
TRG IN RDB$TRIGGERS TRG IN RDB$TRIGGERS
WITH TRG.RDB$TRIGGER_NAME EQ name.c_str() WITH TRG.RDB$TRIGGER_NAME EQ name.c_str()
{ {
if (type.specified && type.value != (FB_UINT64) TRG.RDB$TRIGGER_TYPE && if (type.has_value() && type != (FB_UINT64) TRG.RDB$TRIGGER_TYPE &&
TRG.RDB$RELATION_NAME.NULL) TRG.RDB$RELATION_NAME.NULL)
{ {
status_exception::raise( status_exception::raise(
@ -3424,11 +3423,11 @@ bool TriggerDefinition::modify(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch
if (relationName.hasData()) if (relationName.hasData())
strcpy(TRG.RDB$RELATION_NAME, relationName.c_str()); strcpy(TRG.RDB$RELATION_NAME, relationName.c_str());
if (type.specified) if (type.has_value())
TRG.RDB$TRIGGER_TYPE = type.value; TRG.RDB$TRIGGER_TYPE = type.value();
if (position.specified) if (position.has_value())
TRG.RDB$TRIGGER_SEQUENCE = position.value; TRG.RDB$TRIGGER_SEQUENCE = position.value();
if (active.specified) if (active.specified)
TRG.RDB$TRIGGER_INACTIVE = (USHORT) !active.value; TRG.RDB$TRIGGER_INACTIVE = (USHORT) !active.value;
@ -3465,12 +3464,12 @@ bool TriggerDefinition::modify(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch
attachment->storeMetaDataBlob(tdbb, transaction, &TRG.RDB$TRIGGER_SOURCE, source); attachment->storeMetaDataBlob(tdbb, transaction, &TRG.RDB$TRIGGER_SOURCE, source);
} }
if (ssDefiner.specified) if (ssDefiner.has_value())
{ {
if (ssDefiner.value != SS_DROP) if (ssDefiner.value() != SS_DROP)
{ {
TRG.RDB$SQL_SECURITY.NULL = FALSE; TRG.RDB$SQL_SECURITY.NULL = FALSE;
TRG.RDB$SQL_SECURITY = ssDefiner.value == SS_DEFINER ? FB_TRUE : FB_FALSE; TRG.RDB$SQL_SECURITY = ssDefiner.value() == SS_DEFINER ? FB_TRUE : FB_FALSE;
} }
else else
TRG.RDB$SQL_SECURITY.NULL = TRUE; TRG.RDB$SQL_SECURITY.NULL = TRUE;
@ -3509,14 +3508,14 @@ DdlNode* CreateAlterTriggerNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
{ {
dsqlScratch->flags |= (DsqlCompilerScratch::FLAG_BLOCK | DsqlCompilerScratch::FLAG_TRIGGER); dsqlScratch->flags |= (DsqlCompilerScratch::FLAG_BLOCK | DsqlCompilerScratch::FLAG_TRIGGER);
if (type.specified) if (type.has_value())
{ {
if (create && // ALTER TRIGGER doesn't accept table name if (create && // ALTER TRIGGER doesn't accept table name
((relationName.hasData() && ((relationName.hasData() &&
(type.value & (unsigned) TRIGGER_TYPE_MASK) != (unsigned) TRIGGER_TYPE_DML) || (type.value() & (unsigned) TRIGGER_TYPE_MASK) != (unsigned) TRIGGER_TYPE_DML) ||
(relationName.isEmpty() && (relationName.isEmpty() &&
(type.value & (unsigned) TRIGGER_TYPE_MASK) != (unsigned) TRIGGER_TYPE_DB && (type.value() & (unsigned) TRIGGER_TYPE_MASK) != (unsigned) TRIGGER_TYPE_DB &&
(type.value & (unsigned) TRIGGER_TYPE_MASK) != (unsigned) TRIGGER_TYPE_DDL))) (type.value() & (unsigned) TRIGGER_TYPE_MASK) != (unsigned) TRIGGER_TYPE_DDL)))
{ {
status_exception::raise( status_exception::raise(
Arg::Gds(isc_dsql_command_err) << Arg::Gds(isc_dsql_command_err) <<
@ -3524,7 +3523,7 @@ DdlNode* CreateAlterTriggerNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
} }
} }
if (create && ssDefiner.specified && ssDefiner.value == TriggerDefinition::SS_DROP) if (create && ssDefiner.has_value() && ssDefiner.value() == TriggerDefinition::SS_DROP)
status_exception::raise(Arg::Gds(isc_dsql_command_err) << Arg::Gds(isc_dsql_invalid_drop_ss_clause)); status_exception::raise(Arg::Gds(isc_dsql_command_err) << Arg::Gds(isc_dsql_invalid_drop_ss_clause));
return DdlNode::dsqlPass(dsqlScratch); return DdlNode::dsqlPass(dsqlScratch);
@ -3540,7 +3539,7 @@ void CreateAlterTriggerNode::checkPermission(thread_db* tdbb, jrd_tra* transacti
TRG IN RDB$TRIGGERS TRG IN RDB$TRIGGERS
WITH TRG.RDB$TRIGGER_NAME EQ name.c_str() WITH TRG.RDB$TRIGGER_NAME EQ name.c_str()
{ {
if (!type.specified && !TRG.RDB$TRIGGER_TYPE.NULL) if (!type.has_value() && !TRG.RDB$TRIGGER_TYPE.NULL)
type = TRG.RDB$TRIGGER_TYPE; type = TRG.RDB$TRIGGER_TYPE;
if (relationName.isEmpty() && !TRG.RDB$RELATION_NAME.NULL) if (relationName.isEmpty() && !TRG.RDB$RELATION_NAME.NULL)
@ -3548,7 +3547,7 @@ void CreateAlterTriggerNode::checkPermission(thread_db* tdbb, jrd_tra* transacti
} }
END_FOR END_FOR
if (!type.specified) if (!type.has_value())
status_exception::raise(Arg::Gds(isc_dyn_trig_not_found) << Arg::Str(name)); status_exception::raise(Arg::Gds(isc_dyn_trig_not_found) << Arg::Str(name));
} }
@ -3637,7 +3636,7 @@ void CreateAlterTriggerNode::compile(thread_db* /*tdbb*/, DsqlCompilerScratch* d
const string temp = relationNode->alias; // always empty? const string temp = relationNode->alias; // always empty?
if (hasOldContext(type.value)) if (hasOldContext(type.value()))
{ {
relationNode->alias = OLD_CONTEXT_NAME; relationNode->alias = OLD_CONTEXT_NAME;
dsql_ctx* oldContext = PASS1_make_context(dsqlScratch, relationNode); dsql_ctx* oldContext = PASS1_make_context(dsqlScratch, relationNode);
@ -3646,7 +3645,7 @@ void CreateAlterTriggerNode::compile(thread_db* /*tdbb*/, DsqlCompilerScratch* d
else else
dsqlScratch->contextNumber++; dsqlScratch->contextNumber++;
if (hasNewContext(type.value)) if (hasNewContext(type.value()))
{ {
relationNode->alias = NEW_CONTEXT_NAME; relationNode->alias = NEW_CONTEXT_NAME;
dsql_ctx* newContext = PASS1_make_context(dsqlScratch, relationNode); dsql_ctx* newContext = PASS1_make_context(dsqlScratch, relationNode);
@ -5078,7 +5077,7 @@ void AlterDomainNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
} }
DSC_make_descriptor(&newDom.dyn_dsc, blr_dtypes[type->dtype], type->scale, DSC_make_descriptor(&newDom.dyn_dsc, blr_dtypes[type->dtype], type->scale,
typeLength, type->subType, type->charSetId.value, type->collationId); typeLength, type->subType, type->charSetId.value_or(CS_NONE), type->collationId);
newDom.dyn_fld_name = name; newDom.dyn_fld_name = name;
newDom.dyn_charbytelen = typeLength; newDom.dyn_charbytelen = typeLength;
@ -5643,11 +5642,11 @@ void CreateAlterSequenceNode::executeCreate(thread_db* tdbb, DsqlCompilerScratch
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_CREATE_SEQUENCE, executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_CREATE_SEQUENCE,
name, NULL); name, NULL);
const SINT64 val = value.orElse(1); const SINT64 val = value.value_or(1);
SLONG initialStep = 1; SLONG initialStep = 1;
if (step.specified) if (step.has_value())
{ {
initialStep = step.value; initialStep = step.value();
if (initialStep == 0) if (initialStep == 0)
status_exception::raise(Arg::Gds(isc_dyn_cant_use_zero_increment) << Arg::Str(name)); status_exception::raise(Arg::Gds(isc_dyn_cant_use_zero_increment) << Arg::Str(name));
} }
@ -5681,11 +5680,11 @@ bool CreateAlterSequenceNode::executeAlter(thread_db* tdbb, DsqlCompilerScratch*
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_ALTER_SEQUENCE, executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_ALTER_SEQUENCE,
name, NULL); name, NULL);
fb_assert(restartSpecified && value.specified); fb_assert(restartSpecified && value.has_value());
const SINT64 val = value.specified ? value.value : 0; const SINT64 val = value.value_or(0);
if (step.specified) if (step.has_value())
{ {
const SLONG newStep = step.value; const SLONG newStep = step.value();
if (newStep == 0) if (newStep == 0)
status_exception::raise(Arg::Gds(isc_dyn_cant_use_zero_increment) << Arg::Str(name)); status_exception::raise(Arg::Gds(isc_dyn_cant_use_zero_increment) << Arg::Str(name));
@ -5724,9 +5723,9 @@ bool CreateAlterSequenceNode::executeAlter(thread_db* tdbb, DsqlCompilerScratch*
const SLONG id = X.RDB$GENERATOR_ID; const SLONG id = X.RDB$GENERATOR_ID;
if (step.specified) if (step.has_value())
{ {
const SLONG newStep = step.value; const SLONG newStep = step.value();
if (newStep == 0) if (newStep == 0)
status_exception::raise(Arg::Gds(isc_dyn_cant_use_zero_increment) << Arg::Str(name)); status_exception::raise(Arg::Gds(isc_dyn_cant_use_zero_increment) << Arg::Str(name));
@ -5741,7 +5740,7 @@ bool CreateAlterSequenceNode::executeAlter(thread_db* tdbb, DsqlCompilerScratch*
if (restartSpecified) if (restartSpecified)
{ {
const SINT64 oldValue = !X.RDB$INITIAL_VALUE.NULL ? X.RDB$INITIAL_VALUE : 0; const SINT64 oldValue = !X.RDB$INITIAL_VALUE.NULL ? X.RDB$INITIAL_VALUE : 0;
const SINT64 newValue = value.specified ? value.value : oldValue; const SINT64 newValue = value.value_or(oldValue);
transaction->getGenIdCache()->put(id, transaction->getGenIdCache()->put(id,
newValue - (!X.RDB$GENERATOR_INCREMENT.NULL ? X.RDB$GENERATOR_INCREMENT : 1)); newValue - (!X.RDB$GENERATOR_INCREMENT.NULL ? X.RDB$GENERATOR_INCREMENT : 1));
@ -5947,16 +5946,16 @@ void RelationNode::FieldDefinition::modify(thread_db* tdbb, jrd_tra* transaction
RFR.RDB$BASE_FIELD.NULL = TRUE; RFR.RDB$BASE_FIELD.NULL = TRUE;
///RFR.RDB$UPDATE_FLAG.NULL = TRUE; ///RFR.RDB$UPDATE_FLAG.NULL = TRUE;
if (collationId.specified) if (collationId.has_value())
{ {
RFR.RDB$COLLATION_ID.NULL = FALSE; RFR.RDB$COLLATION_ID.NULL = FALSE;
RFR.RDB$COLLATION_ID = collationId.value; RFR.RDB$COLLATION_ID = collationId.value();
} }
SLONG fieldPos = -1; SLONG fieldPos = -1;
if (position.specified) if (position.has_value())
fieldPos = position.value; fieldPos = position.value();
else else
{ {
DYN_UTIL_generate_field_position(tdbb, relationName, &fieldPos); DYN_UTIL_generate_field_position(tdbb, relationName, &fieldPos);
@ -5976,14 +5975,14 @@ void RelationNode::FieldDefinition::modify(thread_db* tdbb, jrd_tra* transaction
strcpy(RFR.RDB$BASE_FIELD, baseField.c_str()); strcpy(RFR.RDB$BASE_FIELD, baseField.c_str());
} }
if (viewContext.specified) if (viewContext.has_value())
{ {
fb_assert(baseField.hasData()); fb_assert(baseField.hasData());
RFR.RDB$VIEW_CONTEXT.NULL = FALSE; RFR.RDB$VIEW_CONTEXT.NULL = FALSE;
RFR.RDB$VIEW_CONTEXT = viewContext.value; RFR.RDB$VIEW_CONTEXT = viewContext.value();
DYN_UTIL_find_field_source(tdbb, transaction, relationName, viewContext.value, DYN_UTIL_find_field_source(tdbb, transaction, relationName, viewContext.value(),
baseField.c_str(), RFR.RDB$FIELD_SOURCE); baseField.c_str(), RFR.RDB$FIELD_SOURCE);
} }
END_MODIFY END_MODIFY
@ -6017,10 +6016,10 @@ void RelationNode::FieldDefinition::store(thread_db* tdbb, jrd_tra* transaction)
RFR.RDB$BASE_FIELD.NULL = TRUE; RFR.RDB$BASE_FIELD.NULL = TRUE;
///RFR.RDB$UPDATE_FLAG.NULL = TRUE; ///RFR.RDB$UPDATE_FLAG.NULL = TRUE;
if (collationId.specified) if (collationId.has_value())
{ {
RFR.RDB$COLLATION_ID.NULL = FALSE; RFR.RDB$COLLATION_ID.NULL = FALSE;
RFR.RDB$COLLATION_ID = collationId.value; RFR.RDB$COLLATION_ID = collationId.value();
} }
if (identitySequence.hasData()) if (identitySequence.hasData())
@ -6029,7 +6028,7 @@ void RelationNode::FieldDefinition::store(thread_db* tdbb, jrd_tra* transaction)
strcpy(RFR.RDB$GENERATOR_NAME, identitySequence.c_str()); strcpy(RFR.RDB$GENERATOR_NAME, identitySequence.c_str());
RFR.RDB$IDENTITY_TYPE.NULL = FALSE; RFR.RDB$IDENTITY_TYPE.NULL = FALSE;
RFR.RDB$IDENTITY_TYPE = identityType.value; RFR.RDB$IDENTITY_TYPE = identityType.value();
} }
if (notNullFlag.specified) if (notNullFlag.specified)
@ -6053,8 +6052,8 @@ void RelationNode::FieldDefinition::store(thread_db* tdbb, jrd_tra* transaction)
SLONG fieldPos = -1; SLONG fieldPos = -1;
if (position.specified) if (position.has_value())
fieldPos = position.value; fieldPos = position.value();
else else
{ {
DYN_UTIL_generate_field_position(tdbb, relationName, &fieldPos); DYN_UTIL_generate_field_position(tdbb, relationName, &fieldPos);
@ -6074,14 +6073,14 @@ void RelationNode::FieldDefinition::store(thread_db* tdbb, jrd_tra* transaction)
strcpy(RFR.RDB$BASE_FIELD, baseField.c_str()); strcpy(RFR.RDB$BASE_FIELD, baseField.c_str());
} }
if (viewContext.specified) if (viewContext.has_value())
{ {
fb_assert(baseField.hasData()); fb_assert(baseField.hasData());
RFR.RDB$VIEW_CONTEXT.NULL = FALSE; RFR.RDB$VIEW_CONTEXT.NULL = FALSE;
RFR.RDB$VIEW_CONTEXT = viewContext.value; RFR.RDB$VIEW_CONTEXT = viewContext.value();
DYN_UTIL_find_field_source(tdbb, transaction, relationName, viewContext.value, DYN_UTIL_find_field_source(tdbb, transaction, relationName, viewContext.value(),
baseField.c_str(), RFR.RDB$FIELD_SOURCE); baseField.c_str(), RFR.RDB$FIELD_SOURCE);
} }
} }
@ -6357,7 +6356,7 @@ void RelationNode::defineField(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch
if (clause->identityOptions) if (clause->identityOptions)
{ {
if (clause->identityOptions->increment.orElse(1) == 0) if (clause->identityOptions->increment.value_or(1) == 0)
{ {
status_exception::raise(Arg::Gds(isc_dyn_cant_use_zero_inc_ident) << status_exception::raise(Arg::Gds(isc_dyn_cant_use_zero_inc_ident) <<
Arg::Str(field->fld_name) << Arg::Str(field->fld_name) <<
@ -6378,8 +6377,8 @@ void RelationNode::defineField(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch
CreateAlterSequenceNode::store(tdbb, transaction, fieldDefinition.identitySequence, CreateAlterSequenceNode::store(tdbb, transaction, fieldDefinition.identitySequence,
fb_sysflag_identity_generator, fb_sysflag_identity_generator,
clause->identityOptions->startValue.orElse(1), clause->identityOptions->startValue.value_or(1),
clause->identityOptions->increment.orElse(1)); clause->identityOptions->increment.value_or(1));
} }
BlrDebugWriter::BlrData defaultValue; BlrDebugWriter::BlrData defaultValue;
@ -7341,9 +7340,9 @@ void CreateRelationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScrat
DYN_UTIL_check_unique_name(tdbb, transaction, name, obj_relation); DYN_UTIL_check_unique_name(tdbb, transaction, name, obj_relation);
fb_assert(relationType.specified); fb_assert(relationType.has_value());
checkRelationTempScope(tdbb, transaction, name, relationType.value); checkRelationTempScope(tdbb, transaction, name, relationType.value());
AutoCacheRequest request(tdbb, drq_s_rels2, DYN_REQUESTS); AutoCacheRequest request(tdbb, drq_s_rels2, DYN_REQUESTS);
@ -7353,7 +7352,7 @@ void CreateRelationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScrat
strcpy(REL.RDB$RELATION_NAME, name.c_str()); strcpy(REL.RDB$RELATION_NAME, name.c_str());
REL.RDB$SYSTEM_FLAG = 0; REL.RDB$SYSTEM_FLAG = 0;
REL.RDB$FLAGS = REL_sql; REL.RDB$FLAGS = REL_sql;
REL.RDB$RELATION_TYPE = relationType.value; REL.RDB$RELATION_TYPE = relationType.value();
if (ssDefiner.specified) if (ssDefiner.specified)
{ {
@ -8041,23 +8040,23 @@ void AlterRelationNode::modifyField(thread_db* tdbb, DsqlCompilerScratch* dsqlSc
{ {
const SINT64 val = const SINT64 val =
clause->identityOptions->startValue clause->identityOptions->startValue
.orElse(!GEN.RDB$INITIAL_VALUE.NULL ? GEN.RDB$INITIAL_VALUE : 0) - .value_or(!GEN.RDB$INITIAL_VALUE.NULL ? GEN.RDB$INITIAL_VALUE : 0) -
clause->identityOptions->increment clause->identityOptions->increment
.orElse(!GEN.RDB$GENERATOR_INCREMENT.NULL ? GEN.RDB$GENERATOR_INCREMENT : 1); .value_or(!GEN.RDB$GENERATOR_INCREMENT.NULL ? GEN.RDB$GENERATOR_INCREMENT : 1);
transaction->getGenIdCache()->put(id, val); transaction->getGenIdCache()->put(id, val);
} }
if (clause->identityOptions->type.specified) if (clause->identityOptions->type.has_value())
{ {
MODIFY RFR MODIFY RFR
RFR.RDB$IDENTITY_TYPE = clause->identityOptions->type.value; RFR.RDB$IDENTITY_TYPE = clause->identityOptions->type.value();
END_MODIFY END_MODIFY
} }
if (clause->identityOptions->increment.specified) if (clause->identityOptions->increment.has_value())
{ {
if (clause->identityOptions->increment.value == 0) if (clause->identityOptions->increment.value() == 0)
{ {
status_exception::raise(Arg::Gds(isc_dyn_cant_use_zero_inc_ident) << status_exception::raise(Arg::Gds(isc_dyn_cant_use_zero_inc_ident) <<
Arg::Str(field->fld_name) << Arg::Str(field->fld_name) <<
@ -8065,7 +8064,7 @@ void AlterRelationNode::modifyField(thread_db* tdbb, DsqlCompilerScratch* dsqlSc
} }
MET_update_generator_increment(tdbb, id, MET_update_generator_increment(tdbb, id,
clause->identityOptions->increment.value); clause->identityOptions->increment.value());
} }
dsc desc; dsc desc;
@ -9014,7 +9013,7 @@ void CreateAlterViewNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
const USHORT adjust = const USHORT adjust =
(desc.dsc_dtype == dtype_varying) ? sizeof(USHORT) : 0; (desc.dsc_dtype == dtype_varying) ? sizeof(USHORT) : 0;
const USHORT bpc = const USHORT bpc =
METD_get_charset_bpc(dsqlScratch->getTransaction(), newField.charSetId.value); METD_get_charset_bpc(dsqlScratch->getTransaction(), newField.charSetId.value_or(CS_NONE));
newField.charLength = (newField.length - adjust) / bpc; newField.charLength = (newField.length - adjust) / bpc;
} }
@ -10182,7 +10181,6 @@ string CreateShadowNode::internalPrint(NodePrinter& printer) const
NODE_PRINT(printer, number); NODE_PRINT(printer, number);
NODE_PRINT(printer, manual); NODE_PRINT(printer, manual);
NODE_PRINT(printer, conditional); NODE_PRINT(printer, conditional);
NODE_PRINT(printer, firstLength);
NODE_PRINT(printer, files); NODE_PRINT(printer, files);
return "CreateShadowNode"; return "CreateShadowNode";

View File

@ -23,6 +23,7 @@
#ifndef DSQL_DDL_NODES_H #ifndef DSQL_DDL_NODES_H
#define DSQL_DDL_NODES_H #define DSQL_DDL_NODES_H
#include <optional>
#include "firebird/impl/blr.h" #include "firebird/impl/blr.h"
#include "../jrd/dyn.h" #include "../jrd/dyn.h"
#include "../common/msg_encode.h" #include "../common/msg_encode.h"
@ -174,7 +175,7 @@ public:
NestConst<dsql_fld> type; NestConst<dsql_fld> type;
NestConst<ValueSourceClause> defaultClause; NestConst<ValueSourceClause> defaultClause;
NestConst<ValueExprNode> parameterExpr; NestConst<ValueExprNode> parameterExpr;
Nullable<int> udfMechanism; std::optional<int> udfMechanism;
}; };
@ -696,16 +697,16 @@ protected:
public: public:
MetaName name; MetaName name;
MetaName relationName; MetaName relationName;
Nullable<FB_UINT64> type; std::optional<FB_UINT64> type;
Nullable<bool> active; Nullable<bool> active;
Nullable<int> position; std::optional<int> position;
NestConst<ExternalClause> external; NestConst<ExternalClause> external;
Firebird::string source; Firebird::string source;
Firebird::ByteChunk blrData; Firebird::ByteChunk blrData;
Firebird::ByteChunk debugData; Firebird::ByteChunk debugData;
USHORT systemFlag; USHORT systemFlag;
bool fkTrigger; bool fkTrigger;
Nullable<SqlSecurity> ssDefiner; std::optional<SqlSecurity> ssDefiner;
}; };
@ -1116,7 +1117,6 @@ public:
Arg::Num(this->column)); Arg::Num(this->column));
} }
*/ */
value.specified = false;
} }
static SSHORT store(thread_db* tdbb, jrd_tra* transaction, const MetaName& name, static SSHORT store(thread_db* tdbb, jrd_tra* transaction, const MetaName& name,
@ -1147,8 +1147,8 @@ public:
bool legacy; bool legacy;
bool restartSpecified; bool restartSpecified;
const MetaName name; const MetaName name;
BaseNullable<SINT64> value; std::optional<SINT64> value;
Nullable<SLONG> step; std::optional<SLONG> step;
}; };
@ -1210,13 +1210,13 @@ public:
MetaName relationName; MetaName relationName;
MetaName fieldSource; MetaName fieldSource;
MetaName identitySequence; MetaName identitySequence;
Nullable<IdentityType> identityType; std::optional<IdentityType> identityType;
Nullable<USHORT> collationId; std::optional<USHORT> collationId;
Nullable<bool> notNullFlag; // true = NOT NULL / false = NULL Nullable<bool> notNullFlag; // true = NOT NULL / false = NULL
Nullable<USHORT> position; std::optional<USHORT> position;
Firebird::string defaultSource; Firebird::string defaultSource;
Firebird::ByteChunk defaultValue; Firebird::ByteChunk defaultValue;
Nullable<USHORT> viewContext; std::optional<USHORT> viewContext;
MetaName baseField; MetaName baseField;
}; };
@ -1386,9 +1386,9 @@ public:
{ {
} }
Nullable<IdentityType> type; std::optional<IdentityType> type;
Nullable<SINT64> startValue; std::optional<SINT64> startValue;
Nullable<SLONG> increment; std::optional<SLONG> increment;
bool restart; // used in ALTER bool restart; // used in ALTER
}; };
@ -1562,8 +1562,7 @@ public:
CreateRelationNode(MemoryPool& p, RelationSourceNode* aDsqlNode, CreateRelationNode(MemoryPool& p, RelationSourceNode* aDsqlNode,
const Firebird::string* aExternalFile = NULL) const Firebird::string* aExternalFile = NULL)
: RelationNode(p, aDsqlNode), : RelationNode(p, aDsqlNode),
externalFile(aExternalFile), externalFile(aExternalFile)
relationType(rel_persistent)
{ {
} }
@ -1583,7 +1582,7 @@ private:
public: public:
const Firebird::string* externalFile; const Firebird::string* externalFile;
Nullable<rel_t> relationType; std::optional<rel_t> relationType = rel_persistent;
bool preserveRowsOpt; bool preserveRowsOpt;
bool deleteRowsOpt; bool deleteRowsOpt;
}; };
@ -1977,7 +1976,6 @@ public:
SSHORT number; SSHORT number;
bool manual; bool manual;
bool conditional; bool conditional;
Nullable<SLONG> firstLength;
Firebird::Array<NestConst<DbFileClause> > files; Firebird::Array<NestConst<DbFileClause> > files;
}; };
@ -2468,14 +2466,4 @@ public:
} // namespace } // namespace
template <>
class NullableClear<Jrd::TriggerDefinition::SqlSecurity> // TriggerDefinition::SqlSecurity especialization for NullableClear
{
public:
static void clear(Jrd::TriggerDefinition::SqlSecurity& v)
{
v = Jrd::TriggerDefinition::SS_INVOKER;
}
};
#endif // DSQL_DDL_NODES_H #endif // DSQL_DDL_NODES_H

View File

@ -2802,7 +2802,7 @@ dsc* ArithmeticNode::addSqlTime(thread_db* tdbb, const dsc* desc, impure_value*
bool op1_is_time = op1_desc->isTime(); bool op1_is_time = op1_desc->isTime();
bool op2_is_time = op2_desc->isTime(); bool op2_is_time = op2_desc->isTime();
Nullable<USHORT> op1_tz, op2_tz; std::optional<USHORT> op1_tz, op2_tz;
if (op1_desc->dsc_dtype == dtype_sql_time_tz) if (op1_desc->dsc_dtype == dtype_sql_time_tz)
op1_tz = ((ISC_TIME_TZ*) op1_desc->dsc_address)->time_zone; op1_tz = ((ISC_TIME_TZ*) op1_desc->dsc_address)->time_zone;
@ -2813,14 +2813,14 @@ dsc* ArithmeticNode::addSqlTime(thread_db* tdbb, const dsc* desc, impure_value*
dsc op1_tz_desc, op2_tz_desc; dsc op1_tz_desc, op2_tz_desc;
ISC_TIME_TZ op1_time_tz, op2_time_tz; ISC_TIME_TZ op1_time_tz, op2_time_tz;
if (op1_desc->dsc_dtype == dtype_sql_time && op2_is_time && op2_tz.specified) if (op1_desc->dsc_dtype == dtype_sql_time && op2_is_time && op2_tz.has_value())
{ {
op1_tz_desc.makeTimeTz(&op1_time_tz); op1_tz_desc.makeTimeTz(&op1_time_tz);
MOV_move(tdbb, const_cast<dsc*>(op1_desc), &op1_tz_desc); MOV_move(tdbb, const_cast<dsc*>(op1_desc), &op1_tz_desc);
op1_desc = &op1_tz_desc; op1_desc = &op1_tz_desc;
} }
if (op2_desc->dsc_dtype == dtype_sql_time && op1_is_time && op1_tz.specified) if (op2_desc->dsc_dtype == dtype_sql_time && op1_is_time && op1_tz.has_value())
{ {
op2_tz_desc.makeTimeTz(&op2_time_tz); op2_tz_desc.makeTimeTz(&op2_time_tz);
MOV_move(tdbb, const_cast<dsc*>(op2_desc), &op2_tz_desc); MOV_move(tdbb, const_cast<dsc*>(op2_desc), &op2_tz_desc);
@ -2888,18 +2888,18 @@ dsc* ArithmeticNode::addSqlTime(thread_db* tdbb, const dsc* desc, impure_value*
value->vlu_misc.vlu_sql_time_tz.utc_time = d2; value->vlu_misc.vlu_sql_time_tz.utc_time = d2;
result->dsc_dtype = op1_tz.specified || op2_tz.specified ? dtype_sql_time_tz : dtype_sql_time; result->dsc_dtype = op1_tz.has_value() || op2_tz.has_value() ? dtype_sql_time_tz : dtype_sql_time;
result->dsc_length = type_lengths[result->dsc_dtype]; result->dsc_length = type_lengths[result->dsc_dtype];
result->dsc_scale = 0; result->dsc_scale = 0;
result->dsc_sub_type = 0; result->dsc_sub_type = 0;
result->dsc_address = (UCHAR*) &value->vlu_misc.vlu_sql_time_tz; result->dsc_address = (UCHAR*) &value->vlu_misc.vlu_sql_time_tz;
fb_assert(!(op1_tz.specified && op2_tz.specified)); fb_assert(!(op1_tz.has_value() && op2_tz.has_value()));
if (op1_tz.specified) if (op1_tz.has_value())
value->vlu_misc.vlu_sql_time_tz.time_zone = op1_tz.value; value->vlu_misc.vlu_sql_time_tz.time_zone = op1_tz.value();
else if (op2_tz.specified) else if (op2_tz.has_value())
value->vlu_misc.vlu_sql_time_tz.time_zone = op2_tz.value; value->vlu_misc.vlu_sql_time_tz.time_zone = op2_tz.value();
return result; return result;
} }
@ -2917,7 +2917,7 @@ dsc* ArithmeticNode::addTimeStamp(thread_db* tdbb, const dsc* desc, impure_value
const dsc* op1_desc = &value->vlu_desc; const dsc* op1_desc = &value->vlu_desc;
const dsc* op2_desc = desc; const dsc* op2_desc = desc;
Nullable<USHORT> op1_tz, op2_tz; std::optional<USHORT> op1_tz, op2_tz;
if (op1_desc->dsc_dtype == dtype_sql_time_tz) if (op1_desc->dsc_dtype == dtype_sql_time_tz)
op1_tz = ((ISC_TIME_TZ*) op1_desc->dsc_address)->time_zone; op1_tz = ((ISC_TIME_TZ*) op1_desc->dsc_address)->time_zone;
@ -2934,7 +2934,7 @@ dsc* ArithmeticNode::addTimeStamp(thread_db* tdbb, const dsc* desc, impure_value
ISC_TIME_TZ op1_time_tz, op2_time_tz; ISC_TIME_TZ op1_time_tz, op2_time_tz;
if ((op1_desc->dsc_dtype == dtype_sql_time || op1_desc->dsc_dtype == dtype_timestamp) && if ((op1_desc->dsc_dtype == dtype_sql_time || op1_desc->dsc_dtype == dtype_timestamp) &&
op2_desc->isDateTime() && op2_tz.specified) op2_desc->isDateTime() && op2_tz.has_value())
{ {
if (op1_desc->dsc_dtype == dtype_sql_time) if (op1_desc->dsc_dtype == dtype_sql_time)
op1_tz_desc.makeTimeTz(&op1_time_tz); op1_tz_desc.makeTimeTz(&op1_time_tz);
@ -2946,7 +2946,7 @@ dsc* ArithmeticNode::addTimeStamp(thread_db* tdbb, const dsc* desc, impure_value
} }
if ((op2_desc->dsc_dtype == dtype_sql_time || op2_desc->dsc_dtype == dtype_timestamp) && if ((op2_desc->dsc_dtype == dtype_sql_time || op2_desc->dsc_dtype == dtype_timestamp) &&
op1_desc->isDateTime() && op1_tz.specified) op1_desc->isDateTime() && op1_tz.has_value())
{ {
if (op2_desc->dsc_dtype == dtype_sql_time) if (op2_desc->dsc_dtype == dtype_sql_time)
op2_tz_desc.makeTimeTz(&op2_time_tz); op2_tz_desc.makeTimeTz(&op2_time_tz);
@ -3122,18 +3122,18 @@ dsc* ArithmeticNode::addTimeStamp(thread_db* tdbb, const dsc* desc, impure_value
ERR_post(Arg::Gds(isc_datetime_range_exceeded)); ERR_post(Arg::Gds(isc_datetime_range_exceeded));
} }
fb_assert(!(op1_tz.specified && op2_tz.specified)); fb_assert(!(op1_tz.has_value() && op2_tz.has_value()));
result->dsc_dtype = op1_tz.specified || op2_tz.specified ? dtype_timestamp_tz : dtype_timestamp; result->dsc_dtype = op1_tz.has_value() || op2_tz.has_value() ? dtype_timestamp_tz : dtype_timestamp;
result->dsc_length = type_lengths[result->dsc_dtype]; result->dsc_length = type_lengths[result->dsc_dtype];
result->dsc_scale = 0; result->dsc_scale = 0;
result->dsc_sub_type = 0; result->dsc_sub_type = 0;
result->dsc_address = (UCHAR*) &value->vlu_misc.vlu_timestamp_tz; result->dsc_address = (UCHAR*) &value->vlu_misc.vlu_timestamp_tz;
if (op1_tz.specified) if (op1_tz.has_value())
value->vlu_misc.vlu_timestamp_tz.time_zone = op1_tz.value; value->vlu_misc.vlu_timestamp_tz.time_zone = op1_tz.value();
else if (op2_tz.specified) else if (op2_tz.has_value())
value->vlu_misc.vlu_timestamp_tz.time_zone = op2_tz.value; value->vlu_misc.vlu_timestamp_tz.time_zone = op2_tz.value();
return result; return result;
} }
@ -5180,7 +5180,7 @@ ValueExprNode* DerivedExprNode::copy(thread_db* tdbb, NodeCopier& copier) const
i = copier.remap[i]; i = copier.remap[i];
} }
fb_assert(!cursorNumber.specified); fb_assert(!cursorNumber.has_value());
return node; return node;
} }
@ -5230,8 +5230,8 @@ ValueExprNode* DerivedExprNode::pass2(thread_db* tdbb, CompilerScratch* csb)
dsc* DerivedExprNode::execute(thread_db* tdbb, Request* request) const dsc* DerivedExprNode::execute(thread_db* tdbb, Request* request) const
{ {
if (cursorNumber.specified) if (cursorNumber.has_value())
request->req_cursors[cursorNumber.value]->checkState(request); request->req_cursors[cursorNumber.value()]->checkState(request);
dsc* value = NULL; dsc* value = NULL;
@ -6652,7 +6652,7 @@ ValueExprNode* FieldNode::copy(thread_db* tdbb, NodeCopier& copier) const
stream = copier.remap[stream]; stream = copier.remap[stream];
} }
fb_assert(!cursorNumber.specified); fb_assert(!cursorNumber.has_value());
return PAR_gen_field(tdbb, stream, fldId, byId); return PAR_gen_field(tdbb, stream, fldId, byId);
} }
@ -6910,8 +6910,8 @@ dsc* FieldNode::execute(thread_db* tdbb, Request* request) const
{ {
impure_value* const impure = request->getImpure<impure_value>(impureOffset); impure_value* const impure = request->getImpure<impure_value>(impureOffset);
if (cursorNumber.specified) if (cursorNumber.has_value())
request->req_cursors[cursorNumber.value]->checkState(request); request->req_cursors[cursorNumber.value()]->checkState(request);
record_param& rpb = request->req_rpb[fieldStream]; record_param& rpb = request->req_rpb[fieldStream];
Record* record = rpb.rpb_record; Record* record = rpb.rpb_record;

View File

@ -23,6 +23,7 @@
#ifndef DSQL_EXPR_NODES_H #ifndef DSQL_EXPR_NODES_H
#define DSQL_EXPR_NODES_H #define DSQL_EXPR_NODES_H
#include <optional>
#include "firebird/impl/blr.h" #include "firebird/impl/blr.h"
#include "../dsql/Nodes.h" #include "../dsql/Nodes.h"
#include "../dsql/NodePrinter.h" #include "../dsql/NodePrinter.h"
@ -683,7 +684,7 @@ public:
public: public:
NestConst<ValueExprNode> arg; NestConst<ValueExprNode> arg;
Firebird::Array<StreamType> internalStreamList; Firebird::Array<StreamType> internalStreamList;
Nullable<USHORT> cursorNumber; std::optional<USHORT> cursorNumber;
}; };
@ -825,7 +826,7 @@ public:
NestConst<ValueListNode> dsqlIndices; NestConst<ValueListNode> dsqlIndices;
const Format* format; const Format* format;
const StreamType fieldStream; const StreamType fieldStream;
Nullable<USHORT> cursorNumber; std::optional<USHORT> cursorNumber;
const USHORT fieldId; const USHORT fieldId;
const bool byId; const bool byId;
bool dsqlCursorField; bool dsqlCursorField;

View File

@ -23,6 +23,7 @@
#ifndef DSQL_NODE_PRINTER_H #ifndef DSQL_NODE_PRINTER_H
#define DSQL_NODE_PRINTER_H #define DSQL_NODE_PRINTER_H
#include <optional>
#include "../dsql/Nodes.h" #include "../dsql/Nodes.h"
#define NODE_PRINT(var, property) var.print(STRINGIZE(property), property) #define NODE_PRINT(var, property) var.print(STRINGIZE(property), property)
@ -272,6 +273,13 @@ public:
print(s, nullable.value); print(s, nullable.value);
} }
template <typename T>
void print(const Firebird::string& s, const std::optional<T>& optional)
{
if (optional.has_value())
print(s, optional.value());
}
template <typename T> template <typename T>
void print(const Firebird::string&, const Firebird::Pair<T>&) void print(const Firebird::string&, const Firebird::Pair<T>&)
{ {

View File

@ -23,6 +23,7 @@
#ifndef DSQL_PARSER_H #ifndef DSQL_PARSER_H
#define DSQL_PARSER_H #define DSQL_PARSER_H
#include <optional>
#include "../dsql/dsql.h" #include "../dsql/dsql.h"
#include "../dsql/DdlNodes.h" #include "../dsql/DdlNodes.h"
#include "../dsql/BoolNodes.h" #include "../dsql/BoolNodes.h"
@ -250,6 +251,13 @@ private:
clause = value; clause = value;
} }
template <typename T>
void setClause(std::optional<T>& clause, const char* duplicateMsg, const T& value)
{
checkDuplicateClause(clause, duplicateMsg);
clause = value;
}
template <typename T> template <typename T>
void setClause(BaseNullable<T>& clause, const char* duplicateMsg, const BaseNullable<T>& value) void setClause(BaseNullable<T>& clause, const char* duplicateMsg, const BaseNullable<T>& value)
{ {
@ -260,6 +268,16 @@ private:
} }
} }
template <typename T>
void setClause(std::optional<T>& clause, const char* duplicateMsg, const std::optional<T>& value)
{
if (value.has_value())
{
checkDuplicateClause(clause, duplicateMsg);
clause = value.value();
}
}
template <typename T1, typename T2> template <typename T1, typename T2>
void setClause(NestConst<T1>& clause, const char* duplicateMsg, const T2& value) void setClause(NestConst<T1>& clause, const char* duplicateMsg, const T2& value)
{ {
@ -312,6 +330,12 @@ private:
return clause.specified; return clause.specified;
} }
template <typename T>
bool isDuplicateClause(const std::optional<T>& clause)
{
return clause.has_value();
}
template <typename T> template <typename T>
bool isDuplicateClause(const Firebird::Array<T>& clause) bool isDuplicateClause(const Firebird::Array<T>& clause)
{ {

View File

@ -77,7 +77,7 @@ static dsql_par* dsqlFindDbKey(const DsqlDmlStatement*, const RelationSourceNode
static dsql_par* dsqlFindRecordVersion(const DsqlDmlStatement*, const RelationSourceNode*); static dsql_par* dsqlFindRecordVersion(const DsqlDmlStatement*, const RelationSourceNode*);
static void dsqlGenEofAssignment(DsqlCompilerScratch* dsqlScratch, SSHORT value); static void dsqlGenEofAssignment(DsqlCompilerScratch* dsqlScratch, SSHORT value);
static void dsqlGenReturning(DsqlCompilerScratch* dsqlScratch, ReturningClause* returning, static void dsqlGenReturning(DsqlCompilerScratch* dsqlScratch, ReturningClause* returning,
Nullable<USHORT> localTableNumber); std::optional<USHORT> localTableNumber);
static void dsqlGenReturningLocalTableCursor(DsqlCompilerScratch* dsqlScratch, ReturningClause* returning, static void dsqlGenReturningLocalTableCursor(DsqlCompilerScratch* dsqlScratch, ReturningClause* returning,
USHORT localTableNumber); USHORT localTableNumber);
static void dsqlGenReturningLocalTableDecl(DsqlCompilerScratch* dsqlScratch, USHORT tableNumber); static void dsqlGenReturningLocalTableDecl(DsqlCompilerScratch* dsqlScratch, USHORT tableNumber);
@ -111,7 +111,7 @@ static void postTriggerAccess(CompilerScratch* csb, jrd_rel* ownerRelation,
static void preModifyEraseTriggers(thread_db* tdbb, TrigVector** trigs, static void preModifyEraseTriggers(thread_db* tdbb, TrigVector** trigs,
StmtNode::WhichTrigger whichTrig, record_param* rpb, record_param* rec, TriggerAction op); StmtNode::WhichTrigger whichTrig, record_param* rpb, record_param* rec, TriggerAction op);
static void preprocessAssignments(thread_db* tdbb, CompilerScratch* csb, static void preprocessAssignments(thread_db* tdbb, CompilerScratch* csb,
StreamType stream, CompoundStmtNode* compoundNode, const Nullable<OverrideClause>* insertOverride); StreamType stream, CompoundStmtNode* compoundNode, const std::optional<OverrideClause>* insertOverride);
static void restartRequest(const Request* request, jrd_tra* transaction); static void restartRequest(const Request* request, jrd_tra* transaction);
static void validateExpressions(thread_db* tdbb, const Array<ValidateInfo>& validations); static void validateExpressions(thread_db* tdbb, const Array<ValidateInfo>& validations);
@ -207,7 +207,7 @@ void AssignmentNode::validateTarget(CompilerScratch* csb, const ValueExprNode* t
// Assignment to cursor fields are always prohibited. // Assignment to cursor fields are always prohibited.
// But we cannot detect FOR cursors here. They are treated in dsqlPass. // But we cannot detect FOR cursors here. They are treated in dsqlPass.
else if (fieldNode->cursorNumber.specified) else if (fieldNode->cursorNumber.has_value())
error = true; error = true;
if (error) if (error)
@ -1637,7 +1637,7 @@ DeclareSubFuncNode* DeclareSubFuncNode::dsqlPass(DsqlCompilerScratch* dsqlScratc
dsqlFunction->udf_scale = returnType->scale; dsqlFunction->udf_scale = returnType->scale;
dsqlFunction->udf_sub_type = returnType->subType; dsqlFunction->udf_sub_type = returnType->subType;
dsqlFunction->udf_length = returnType->length; dsqlFunction->udf_length = returnType->length;
dsqlFunction->udf_character_set_id = returnType->charSetId.value; dsqlFunction->udf_character_set_id = returnType->charSetId.value_or(CS_NONE);
if (dsqlDeterministic) if (dsqlDeterministic)
dsqlSignature.flags |= Signature::FLAG_DETERMINISTIC; dsqlSignature.flags |= Signature::FLAG_DETERMINISTIC;
@ -2358,7 +2358,7 @@ string EraseNode::internalPrint(NodePrinter& printer) const
void EraseNode::genBlr(DsqlCompilerScratch* dsqlScratch) void EraseNode::genBlr(DsqlCompilerScratch* dsqlScratch)
{ {
Nullable<USHORT> tableNumber; std::optional<USHORT> tableNumber;
if (dsqlReturning && !dsqlScratch->isPsql()) if (dsqlReturning && !dsqlScratch->isPsql())
{ {
@ -2367,7 +2367,7 @@ void EraseNode::genBlr(DsqlCompilerScratch* dsqlScratch)
dsqlScratch->appendUChar(blr_begin); dsqlScratch->appendUChar(blr_begin);
tableNumber = dsqlScratch->localTableNumber++; tableNumber = dsqlScratch->localTableNumber++;
dsqlGenReturningLocalTableDecl(dsqlScratch, tableNumber.value); dsqlGenReturningLocalTableDecl(dsqlScratch, tableNumber.value());
} }
else else
{ {
@ -2403,7 +2403,7 @@ void EraseNode::genBlr(DsqlCompilerScratch* dsqlScratch)
if (!dsqlScratch->isPsql() && dsqlCursorName.isEmpty()) if (!dsqlScratch->isPsql() && dsqlCursorName.isEmpty())
{ {
dsqlGenReturningLocalTableCursor(dsqlScratch, dsqlReturning, tableNumber.value); dsqlGenReturningLocalTableCursor(dsqlScratch, dsqlReturning, tableNumber.value());
dsqlScratch->appendUChar(blr_end); dsqlScratch->appendUChar(blr_end);
} }
@ -6164,14 +6164,14 @@ string MergeNode::internalPrint(NodePrinter& printer) const
void MergeNode::genBlr(DsqlCompilerScratch* dsqlScratch) void MergeNode::genBlr(DsqlCompilerScratch* dsqlScratch)
{ {
Nullable<USHORT> tableNumber; std::optional<USHORT> tableNumber;
if (returning && !dsqlScratch->isPsql()) if (returning && !dsqlScratch->isPsql())
{ {
dsqlScratch->appendUChar(blr_begin); dsqlScratch->appendUChar(blr_begin);
tableNumber = dsqlScratch->localTableNumber++; tableNumber = dsqlScratch->localTableNumber++;
dsqlGenReturningLocalTableDecl(dsqlScratch, tableNumber.value); dsqlGenReturningLocalTableDecl(dsqlScratch, tableNumber.value());
} }
// Put src info for blr_for. // Put src info for blr_for.
@ -6311,10 +6311,10 @@ void MergeNode::genBlr(DsqlCompilerScratch* dsqlScratch)
} }
} }
dsqlScratch->appendUChar(notMatched->overrideClause.specified ? blr_store3 : (returning ? blr_store2 : blr_store)); dsqlScratch->appendUChar(notMatched->overrideClause.has_value() ? blr_store3 : (returning ? blr_store2 : blr_store));
if (notMatched->overrideClause.specified) if (notMatched->overrideClause.has_value())
dsqlScratch->appendUChar(UCHAR(notMatched->overrideClause.value)); dsqlScratch->appendUChar(UCHAR(notMatched->overrideClause.value()));
GEN_expr(dsqlScratch, notMatched->storeRelation); GEN_expr(dsqlScratch, notMatched->storeRelation);
@ -6332,7 +6332,7 @@ void MergeNode::genBlr(DsqlCompilerScratch* dsqlScratch)
if (returning) if (returning)
dsqlGenReturning(dsqlScratch, notMatched->processedReturning, tableNumber); dsqlGenReturning(dsqlScratch, notMatched->processedReturning, tableNumber);
else if (notMatched->overrideClause.specified) else if (notMatched->overrideClause.has_value())
dsqlScratch->appendUChar(blr_null); dsqlScratch->appendUChar(blr_null);
if (notMatched->condition && isLast) if (notMatched->condition && isLast)
@ -6414,7 +6414,7 @@ void MergeNode::genBlr(DsqlCompilerScratch* dsqlScratch)
if (returning && !dsqlScratch->isPsql()) if (returning && !dsqlScratch->isPsql())
{ {
dsqlGenReturningLocalTableCursor(dsqlScratch, returning, tableNumber.value); dsqlGenReturningLocalTableCursor(dsqlScratch, returning, tableNumber.value());
dsqlScratch->appendUChar(blr_end); dsqlScratch->appendUChar(blr_end);
} }
@ -6635,7 +6635,7 @@ StmtNode* ModifyNode::internalDsqlPass(DsqlCompilerScratch* dsqlScratch, bool up
if (dsqlReturning && !dsqlScratch->isPsql() && dsqlCursorName.isEmpty()) if (dsqlReturning && !dsqlScratch->isPsql() && dsqlCursorName.isEmpty())
{ {
node->dsqlReturningLocalTableNumber = updateOrInsert ? node->dsqlReturningLocalTableNumber = updateOrInsert ?
dsqlReturningLocalTableNumber.value : dsqlReturningLocalTableNumber.value() :
dsqlScratch->localTableNumber++; dsqlScratch->localTableNumber++;
} }
@ -6824,7 +6824,7 @@ void ModifyNode::genBlr(DsqlCompilerScratch* dsqlScratch)
if (dsqlReturning && !dsqlScratch->isPsql()) if (dsqlReturning && !dsqlScratch->isPsql())
{ {
if (dsqlCursorName.isEmpty()) if (dsqlCursorName.isEmpty())
dsqlGenReturningLocalTableDecl(dsqlScratch, dsqlReturningLocalTableNumber.value); dsqlGenReturningLocalTableDecl(dsqlScratch, dsqlReturningLocalTableNumber.value());
else else
{ {
dsqlScratch->appendUChar(blr_send); dsqlScratch->appendUChar(blr_send);
@ -6869,7 +6869,7 @@ void ModifyNode::genBlr(DsqlCompilerScratch* dsqlScratch)
!(dsqlScratch->flags & DsqlCompilerScratch::FLAG_UPDATE_OR_INSERT) && !(dsqlScratch->flags & DsqlCompilerScratch::FLAG_UPDATE_OR_INSERT) &&
dsqlCursorName.isEmpty()) dsqlCursorName.isEmpty())
{ {
dsqlGenReturningLocalTableCursor(dsqlScratch, dsqlReturning, dsqlReturningLocalTableNumber.value); dsqlGenReturningLocalTableCursor(dsqlScratch, dsqlReturning, dsqlReturningLocalTableNumber.value());
} }
} }
} }
@ -7600,7 +7600,7 @@ DmlNode* StoreNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* cs
{ {
node->overrideClause = static_cast<OverrideClause>(csb->csb_blr_reader.getByte()); node->overrideClause = static_cast<OverrideClause>(csb->csb_blr_reader.getByte());
switch (node->overrideClause.value) switch (node->overrideClause.value())
{ {
case OverrideClause::USER_VALUE: case OverrideClause::USER_VALUE:
case OverrideClause::SYSTEM_VALUE: case OverrideClause::SYSTEM_VALUE:
@ -7851,7 +7851,7 @@ void StoreNode::genBlr(DsqlCompilerScratch* dsqlScratch)
if (dsqlReturning && !dsqlScratch->isPsql()) if (dsqlReturning && !dsqlScratch->isPsql())
{ {
if (dsqlRse) if (dsqlRse)
dsqlGenReturningLocalTableDecl(dsqlScratch, dsqlReturningLocalTableNumber.value); dsqlGenReturningLocalTableDecl(dsqlScratch, dsqlReturningLocalTableNumber.value());
else if (!(dsqlScratch->flags & DsqlCompilerScratch::FLAG_UPDATE_OR_INSERT)) else if (!(dsqlScratch->flags & DsqlCompilerScratch::FLAG_UPDATE_OR_INSERT))
{ {
dsqlScratch->appendUChar(blr_send); dsqlScratch->appendUChar(blr_send);
@ -7866,10 +7866,10 @@ void StoreNode::genBlr(DsqlCompilerScratch* dsqlScratch)
GEN_expr(dsqlScratch, dsqlRse); GEN_expr(dsqlScratch, dsqlRse);
} }
dsqlScratch->appendUChar(overrideClause.specified ? blr_store3 : (dsqlReturning ? blr_store2 : blr_store)); dsqlScratch->appendUChar(overrideClause.has_value() ? blr_store3 : (dsqlReturning ? blr_store2 : blr_store));
if (overrideClause.specified) if (overrideClause.has_value())
dsqlScratch->appendUChar(UCHAR(overrideClause.value)); dsqlScratch->appendUChar(UCHAR(overrideClause.value()));
GEN_expr(dsqlScratch, target); GEN_expr(dsqlScratch, target);
@ -7879,15 +7879,15 @@ void StoreNode::genBlr(DsqlCompilerScratch* dsqlScratch)
{ {
dsqlGenReturning(dsqlScratch, dsqlReturning, dsqlReturningLocalTableNumber); dsqlGenReturning(dsqlScratch, dsqlReturning, dsqlReturningLocalTableNumber);
if (dsqlReturningLocalTableNumber.isAssigned()) if (dsqlReturningLocalTableNumber.has_value())
{ {
if (dsqlScratch->flags & DsqlCompilerScratch::FLAG_UPDATE_OR_INSERT) if (dsqlScratch->flags & DsqlCompilerScratch::FLAG_UPDATE_OR_INSERT)
dsqlScratch->appendUChar(blr_end); // close blr_if (blr_eql, blr_internal_info) dsqlScratch->appendUChar(blr_end); // close blr_if (blr_eql, blr_internal_info)
dsqlGenReturningLocalTableCursor(dsqlScratch, dsqlReturning, dsqlReturningLocalTableNumber.value); dsqlGenReturningLocalTableCursor(dsqlScratch, dsqlReturning, dsqlReturningLocalTableNumber.value());
} }
} }
else if (overrideClause.specified) else if (overrideClause.has_value())
dsqlScratch->appendUChar(blr_null); dsqlScratch->appendUChar(blr_null);
} }
@ -9013,8 +9013,7 @@ SetTransactionNode* SetTransactionNode::dsqlPass(DsqlCompilerScratch* dsqlScratc
// Find out isolation level - if specified. This is required for // Find out isolation level - if specified. This is required for
// specifying the correct lock level in reserving clause. // specifying the correct lock level in reserving clause.
const USHORT lockLevel = isoLevel.specified && isoLevel.value == ISO_LEVEL_CONSISTENCY ? const USHORT lockLevel = isoLevel == ISO_LEVEL_CONSISTENCY ? isc_tpb_protected : isc_tpb_shared;
isc_tpb_protected : isc_tpb_shared;
// Stuff some version info. // Stuff some version info.
dsqlScratch->appendUChar(isc_tpb_version1); dsqlScratch->appendUChar(isc_tpb_version1);
@ -9025,23 +9024,23 @@ SetTransactionNode* SetTransactionNode::dsqlPass(DsqlCompilerScratch* dsqlScratc
if (wait.specified) if (wait.specified)
dsqlScratch->appendUChar(wait.value ? isc_tpb_wait : isc_tpb_nowait); dsqlScratch->appendUChar(wait.value ? isc_tpb_wait : isc_tpb_nowait);
if (isoLevel.specified) if (isoLevel.has_value())
{ {
if (isoLevel.value == ISO_LEVEL_CONCURRENCY) if (isoLevel == ISO_LEVEL_CONCURRENCY)
dsqlScratch->appendUChar(isc_tpb_concurrency); dsqlScratch->appendUChar(isc_tpb_concurrency);
else if (isoLevel.value == ISO_LEVEL_CONSISTENCY) else if (isoLevel == ISO_LEVEL_CONSISTENCY)
dsqlScratch->appendUChar(isc_tpb_consistency); dsqlScratch->appendUChar(isc_tpb_consistency);
else else
{ {
dsqlScratch->appendUChar(isc_tpb_read_committed); dsqlScratch->appendUChar(isc_tpb_read_committed);
if (isoLevel.value == ISO_LEVEL_READ_COMMITTED_READ_CONSISTENCY) if (isoLevel == ISO_LEVEL_READ_COMMITTED_READ_CONSISTENCY)
dsqlScratch->appendUChar(isc_tpb_read_consistency); dsqlScratch->appendUChar(isc_tpb_read_consistency);
else if (isoLevel.value == ISO_LEVEL_READ_COMMITTED_REC_VERSION) else if (isoLevel == ISO_LEVEL_READ_COMMITTED_REC_VERSION)
dsqlScratch->appendUChar(isc_tpb_rec_version); dsqlScratch->appendUChar(isc_tpb_rec_version);
else else
{ {
fb_assert(isoLevel.value == ISO_LEVEL_READ_COMMITTED_NO_REC_VERSION); fb_assert(isoLevel == ISO_LEVEL_READ_COMMITTED_NO_REC_VERSION);
dsqlScratch->appendUChar(isc_tpb_no_rec_version); dsqlScratch->appendUChar(isc_tpb_no_rec_version);
} }
} }
@ -9059,22 +9058,22 @@ SetTransactionNode* SetTransactionNode::dsqlPass(DsqlCompilerScratch* dsqlScratc
if (autoCommit.specified) if (autoCommit.specified)
dsqlScratch->appendUChar(isc_tpb_autocommit); dsqlScratch->appendUChar(isc_tpb_autocommit);
if (lockTimeout.specified) if (lockTimeout.has_value())
{ {
dsqlScratch->appendUChar(isc_tpb_lock_timeout); dsqlScratch->appendUChar(isc_tpb_lock_timeout);
dsqlScratch->appendUChar(2); dsqlScratch->appendUChar(2);
dsqlScratch->appendUShort(lockTimeout.value); dsqlScratch->appendUShort(lockTimeout.value());
} }
for (RestrictionOption** i = reserveList.begin(); i != reserveList.end(); ++i) for (RestrictionOption** i = reserveList.begin(); i != reserveList.end(); ++i)
genTableLock(dsqlScratch, **i, lockLevel); genTableLock(dsqlScratch, **i, lockLevel);
if (atSnapshotNumber.specified) if (atSnapshotNumber.has_value())
{ {
dsqlScratch->appendUChar(isc_tpb_at_snapshot_number); dsqlScratch->appendUChar(isc_tpb_at_snapshot_number);
static_assert(sizeof(CommitNumber) == sizeof(FB_UINT64), "sizeof(CommitNumber) == sizeof(FB_UINT64)"); static_assert(sizeof(CommitNumber) == sizeof(FB_UINT64), "sizeof(CommitNumber) == sizeof(FB_UINT64)");
dsqlScratch->appendUChar(sizeof(CommitNumber)); dsqlScratch->appendUChar(sizeof(CommitNumber));
dsqlScratch->appendUInt64(atSnapshotNumber.value); dsqlScratch->appendUInt64(atSnapshotNumber.value());
} }
if (dsqlScratch->getBlrData().getCount() > 1) // 1 -> isc_tpb_version1 if (dsqlScratch->getBlrData().getCount() > 1) // 1 -> isc_tpb_version1
@ -9643,7 +9642,7 @@ void UpdateOrInsertNode::genBlr(DsqlCompilerScratch* dsqlScratch)
storeNode->genBlr(dsqlScratch); storeNode->genBlr(dsqlScratch);
// StoreNode::genBlr closes our blr_if when RETURNING in DSQL is used. // StoreNode::genBlr closes our blr_if when RETURNING in DSQL is used.
if (storeNode->dsqlReturningLocalTableNumber.isUnknown()) if (!storeNode->dsqlReturningLocalTableNumber.has_value())
dsqlScratch->appendUChar(blr_end); // blr_if dsqlScratch->appendUChar(blr_end); // blr_if
dsqlScratch->appendUChar(blr_end); dsqlScratch->appendUChar(blr_end);
@ -9908,16 +9907,16 @@ static void dsqlGenEofAssignment(DsqlCompilerScratch* dsqlScratch, SSHORT value)
} }
static void dsqlGenReturning(DsqlCompilerScratch* dsqlScratch, ReturningClause* returning, static void dsqlGenReturning(DsqlCompilerScratch* dsqlScratch, ReturningClause* returning,
Nullable<USHORT> localTableNumber) std::optional<USHORT> localTableNumber)
{ {
if (localTableNumber.isAssigned()) if (localTableNumber.has_value())
{ {
const USHORT localStoreContext = dsqlScratch->contextNumber++; const USHORT localStoreContext = dsqlScratch->contextNumber++;
dsqlScratch->appendUChar(blr_store); dsqlScratch->appendUChar(blr_store);
dsqlScratch->putBlrMarkers(StmtNode::MARK_AVOID_COUNTERS); dsqlScratch->putBlrMarkers(StmtNode::MARK_AVOID_COUNTERS);
dsqlScratch->appendUChar(blr_local_table_id); dsqlScratch->appendUChar(blr_local_table_id);
dsqlScratch->appendUShort(localTableNumber.value); dsqlScratch->appendUShort(localTableNumber.value());
dsqlScratch->appendMetaString(""); // alias dsqlScratch->appendMetaString(""); // alias
GEN_stuff_context_number(dsqlScratch, localStoreContext); GEN_stuff_context_number(dsqlScratch, localStoreContext);
@ -11025,7 +11024,7 @@ static void preModifyEraseTriggers(thread_db* tdbb, TrigVector** trigs,
// 1. Remove assignments of DEFAULT to computed fields. // 1. Remove assignments of DEFAULT to computed fields.
// 2. Remove assignments to identity column when OVERRIDING USER VALUE is specified in INSERT. // 2. Remove assignments to identity column when OVERRIDING USER VALUE is specified in INSERT.
static void preprocessAssignments(thread_db* tdbb, CompilerScratch* csb, static void preprocessAssignments(thread_db* tdbb, CompilerScratch* csb,
StreamType stream, CompoundStmtNode* compoundNode, const Nullable<OverrideClause>* insertOverride) StreamType stream, CompoundStmtNode* compoundNode, const std::optional<OverrideClause>* insertOverride)
{ {
if (!compoundNode) if (!compoundNode)
return; return;
@ -11036,7 +11035,7 @@ static void preprocessAssignments(thread_db* tdbb, CompilerScratch* csb,
if (!relation) if (!relation)
return; return;
Nullable<IdentityType> identityType; std::optional<IdentityType> identityType;
for (FB_SIZE_T i = compoundNode->statements.getCount(); i--; ) for (FB_SIZE_T i = compoundNode->statements.getCount(); i--; )
{ {
@ -11058,9 +11057,9 @@ static void preprocessAssignments(thread_db* tdbb, CompilerScratch* csb,
if (assignToField->fieldStream == stream && if (assignToField->fieldStream == stream &&
(fld = MET_get_field(relation, fieldId))) (fld = MET_get_field(relation, fieldId)))
{ {
if (insertOverride && fld->fld_identity_type.specified) if (insertOverride && fld->fld_identity_type.has_value())
{ {
if (insertOverride->specified || !nodeIs<DefaultNode>(assignFrom)) if (insertOverride->has_value() || !nodeIs<DefaultNode>(assignFrom))
identityType = fld->fld_identity_type; identityType = fld->fld_identity_type;
if (*insertOverride == OverrideClause::USER_VALUE) if (*insertOverride == OverrideClause::USER_VALUE)
@ -11096,9 +11095,9 @@ static void preprocessAssignments(thread_db* tdbb, CompilerScratch* csb,
if (!insertOverride) if (!insertOverride)
return; return;
if (insertOverride->specified) if (insertOverride->has_value())
{ {
if (!identityType.specified) if (!identityType.has_value())
ERR_post(Arg::Gds(isc_overriding_without_identity) << relation->rel_name); ERR_post(Arg::Gds(isc_overriding_without_identity) << relation->rel_name);
if (identityType == IDENT_TYPE_BY_DEFAULT && *insertOverride == OverrideClause::SYSTEM_VALUE) if (identityType == IDENT_TYPE_BY_DEFAULT && *insertOverride == OverrideClause::SYSTEM_VALUE)

View File

@ -23,6 +23,7 @@
#ifndef DSQL_STMT_NODES_H #ifndef DSQL_STMT_NODES_H
#define DSQL_STMT_NODES_H #define DSQL_STMT_NODES_H
#include <optional>
#include "../jrd/MetaName.h" #include "../jrd/MetaName.h"
#include "firebird/impl/blr.h" #include "firebird/impl/blr.h"
#include "../jrd/Function.h" #include "../jrd/Function.h"
@ -1072,7 +1073,7 @@ public:
Firebird::Array<NestConst<FieldNode>> fields; Firebird::Array<NestConst<FieldNode>> fields;
NestConst<ValueListNode> values; NestConst<ValueListNode> values;
NestConst<BoolExprNode> condition; NestConst<BoolExprNode> condition;
Nullable<OverrideClause> overrideClause; std::optional<OverrideClause> overrideClause;
NestConst<Jrd::RecordSourceNode> storeRelation; NestConst<Jrd::RecordSourceNode> storeRelation;
NestValueArray processedFields; NestValueArray processedFields;
@ -1188,7 +1189,7 @@ public:
StreamType newStream = 0; StreamType newStream = 0;
unsigned marks = 0; // see StmtNode::IUD_MARK_xxx unsigned marks = 0; // see StmtNode::IUD_MARK_xxx
USHORT dsqlRseFlags = 0; USHORT dsqlRseFlags = 0;
Nullable<USHORT> dsqlReturningLocalTableNumber; std::optional<USHORT> dsqlReturningLocalTableNumber;
}; };
@ -1315,8 +1316,8 @@ public:
NestConst<StmtNode> subStore; NestConst<StmtNode> subStore;
Firebird::Array<ValidateInfo> validations; Firebird::Array<ValidateInfo> validations;
unsigned marks; unsigned marks;
Nullable<USHORT> dsqlReturningLocalTableNumber; std::optional<USHORT> dsqlReturningLocalTableNumber;
Nullable<OverrideClause> overrideClause; std::optional<OverrideClause> overrideClause;
}; };
@ -1621,9 +1622,9 @@ private:
public: public:
Firebird::Array<RestrictionOption*> reserveList; Firebird::Array<RestrictionOption*> reserveList;
Firebird::UCharBuffer tpb; Firebird::UCharBuffer tpb;
Nullable<CommitNumber> atSnapshotNumber; std::optional<CommitNumber> atSnapshotNumber;
Nullable<unsigned> isoLevel; std::optional<unsigned> isoLevel;
Nullable<USHORT> lockTimeout; std::optional<USHORT> lockTimeout;
Nullable<bool> readOnly; Nullable<bool> readOnly;
Nullable<bool> wait; Nullable<bool> wait;
Nullable<bool> noAutoUndo; Nullable<bool> noAutoUndo;
@ -2001,7 +2002,7 @@ public:
NestConst<ValueListNode> order; NestConst<ValueListNode> order;
NestConst<RowsClause> rows; NestConst<RowsClause> rows;
NestConst<ReturningClause> returning; NestConst<ReturningClause> returning;
Nullable<OverrideClause> overrideClause; std::optional<OverrideClause> overrideClause;
NestConst<StoreNode> storeNode; NestConst<StoreNode> storeNode;
NestConst<ModifyNode> modifyNode; NestConst<ModifyNode> modifyNode;
Firebird::Array<NestConst<AssignmentNode>> varAssignments; Firebird::Array<NestConst<AssignmentNode>> varAssignments;

View File

@ -17,6 +17,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <optional>
#include "../dsql/Nodes.h" #include "../dsql/Nodes.h"
#include "../dsql/AggNodes.h" #include "../dsql/AggNodes.h"
#include "../dsql/DdlNodes.h" #include "../dsql/DdlNodes.h"

View File

@ -211,7 +211,7 @@ void DDL_resolve_intl_type(DsqlCompilerScratch* dsqlScratch, dsql_fld* field,
if (field->dtype <= dtype_any_text || if (field->dtype <= dtype_any_text ||
(field->dtype == dtype_blob && field->subType == isc_blob_text)) (field->dtype == dtype_blob && field->subType == isc_blob_text))
{ {
field->charSet = METD_get_charset_name(dsqlScratch->getTransaction(), field->charSetId.value); field->charSet = METD_get_charset_name(dsqlScratch->getTransaction(), field->charSetId.value_or(CS_NONE));
} }
} }
@ -269,7 +269,7 @@ void DDL_resolve_intl_type(DsqlCompilerScratch* dsqlScratch, dsql_fld* field,
return; return;
} }
if (field->charSetId.specified && collation_name.isEmpty()) if (field->charSetId.has_value() && collation_name.isEmpty())
{ {
// This field has already been resolved once, and the collation // This field has already been resolved once, and the collation
// hasn't changed. Therefore, no need to do it again. // hasn't changed. Therefore, no need to do it again.
@ -296,7 +296,7 @@ void DDL_resolve_intl_type(DsqlCompilerScratch* dsqlScratch, dsql_fld* field,
if (afield) if (afield)
{ {
field->charSetId = afield->charSetId; field->charSetId = afield->charSetId;
bpc = METD_get_charset_bpc(dsqlScratch->getTransaction(), field->charSetId.value); bpc = METD_get_charset_bpc(dsqlScratch->getTransaction(), field->charSetId.value_or(CS_NONE));
field->collationId = afield->collationId; field->collationId = afield->collationId;
field->textType = afield->textType; field->textType = afield->textType;
@ -310,7 +310,7 @@ void DDL_resolve_intl_type(DsqlCompilerScratch* dsqlScratch, dsql_fld* field,
} }
} }
if (!(field->charSet.hasData() || field->charSetId.specified || // set if a domain if (!(field->charSet.hasData() || field->charSetId.has_value() || // set if a domain
(field->flags & FLD_national))) (field->flags & FLD_national)))
{ {
// Attach the database default character set, if not otherwise specified // Attach the database default character set, if not otherwise specified
@ -371,7 +371,7 @@ void DDL_resolve_intl_type(DsqlCompilerScratch* dsqlScratch, dsql_fld* field,
if (collation_name.hasData()) if (collation_name.hasData())
{ {
const dsql_intlsym* resolved_collation = METD_get_collation(dsqlScratch->getTransaction(), const dsql_intlsym* resolved_collation = METD_get_collation(dsqlScratch->getTransaction(),
collation_name, field->charSetId.value); collation_name, field->charSetId.value_or(CS_NONE));
if (!resolved_collation) if (!resolved_collation)
{ {
@ -382,7 +382,7 @@ void DDL_resolve_intl_type(DsqlCompilerScratch* dsqlScratch, dsql_fld* field,
else else
{ {
charSetName = METD_get_charset_name(dsqlScratch->getTransaction(), charSetName = METD_get_charset_name(dsqlScratch->getTransaction(),
field->charSetId.value); field->charSetId.value_or(CS_NONE));
} }
// Specified collation not found // Specified collation not found
@ -396,8 +396,8 @@ void DDL_resolve_intl_type(DsqlCompilerScratch* dsqlScratch, dsql_fld* field,
resolved_type = resolved_collation; resolved_type = resolved_collation;
if ((field->charSetId.value != resolved_type->intlsym_charset_id) && if ((field->charSetId.value_or(CS_NONE) != resolved_type->intlsym_charset_id) &&
(field->charSetId.value != ttype_dynamic)) (field->charSetId.value_or(CS_NONE) != ttype_dynamic))
{ {
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-204) << ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-204) <<
Arg::Gds(isc_dsql_datatype_err) << Arg::Gds(isc_dsql_datatype_err) <<

View File

@ -226,7 +226,7 @@ public:
USHORT segLength = 0; // Segment length for blobs USHORT segLength = 0; // Segment length for blobs
USHORT precision = 0; // Precision for exact numeric types USHORT precision = 0; // Precision for exact numeric types
USHORT charLength = 0; // Length of field in characters USHORT charLength = 0; // Length of field in characters
Nullable<SSHORT> charSetId; std::optional<SSHORT> charSetId;
SSHORT collationId = 0; SSHORT collationId = 0;
SSHORT textType = 0; SSHORT textType = 0;
bool fullDomain = false; // Domain name without TYPE OF prefix bool fullDomain = false; // Domain name without TYPE OF prefix
@ -725,19 +725,19 @@ struct SignatureParameter
MetaName charSetName; MetaName charSetName;
MetaName collationName; MetaName collationName;
MetaName subTypeName; MetaName subTypeName;
Nullable<SSHORT> collationId; std::optional<SSHORT> collationId;
Nullable<SSHORT> nullFlag; std::optional<SSHORT> nullFlag;
SSHORT mechanism = 0; SSHORT mechanism = 0;
Nullable<SSHORT> fieldLength; std::optional<SSHORT> fieldLength;
Nullable<SSHORT> fieldScale; std::optional<SSHORT> fieldScale;
Nullable<SSHORT> fieldType; std::optional<SSHORT> fieldType;
Nullable<SSHORT> fieldSubType; std::optional<SSHORT> fieldSubType;
Nullable<SSHORT> fieldSegmentLength; std::optional<SSHORT> fieldSegmentLength;
Nullable<SSHORT> fieldNullFlag; std::optional<SSHORT> fieldNullFlag;
Nullable<SSHORT> fieldCharLength; std::optional<SSHORT> fieldCharLength;
Nullable<SSHORT> fieldCollationId; std::optional<SSHORT> fieldCollationId;
Nullable<SSHORT> fieldCharSetId; std::optional<SSHORT> fieldCharSetId;
Nullable<SSHORT> fieldPrecision; std::optional<SSHORT> fieldPrecision;
bool operator >(const SignatureParameter& o) const bool operator >(const SignatureParameter& o) const
{ {
@ -755,19 +755,19 @@ struct SignatureParameter
fieldName == o.fieldName && fieldName == o.fieldName &&
relationName == o.relationName && relationName == o.relationName &&
collationId == o.collationId && collationId == o.collationId &&
nullFlag.orElse(FALSE) == o.nullFlag.orElse(FALSE) && nullFlag.value_or(FALSE) == o.nullFlag.value_or(FALSE) &&
mechanism == o.mechanism && mechanism == o.mechanism &&
fieldLength == o.fieldLength && fieldLength == o.fieldLength &&
fieldScale == o.fieldScale && fieldScale == o.fieldScale &&
fieldType == o.fieldType && fieldType == o.fieldType &&
fieldSubType.orElse(0) == o.fieldSubType.orElse(0) && fieldSubType.value_or(0) == o.fieldSubType.value_or(0) &&
fieldSegmentLength == o.fieldSegmentLength && fieldSegmentLength == o.fieldSegmentLength &&
fieldNullFlag.orElse(FALSE) == o.fieldNullFlag.orElse(FALSE) && fieldNullFlag.value_or(FALSE) == o.fieldNullFlag.value_or(FALSE) &&
fieldCharLength == o.fieldCharLength && fieldCharLength == o.fieldCharLength &&
charSetName == o.charSetName && charSetName == o.charSetName &&
collationName == o.collationName && collationName == o.collationName &&
subTypeName == o.subTypeName && subTypeName == o.subTypeName &&
fieldCollationId.orElse(0) == o.fieldCollationId.orElse(0) && fieldCollationId.value_or(0) == o.fieldCollationId.value_or(0) &&
fieldCharSetId == o.fieldCharSetId && fieldCharSetId == o.fieldCharSetId &&
fieldPrecision == o.fieldPrecision; fieldPrecision == o.fieldPrecision;
} }

View File

@ -69,14 +69,14 @@ void DsqlDescMaker::fromElement(dsc* desc, const TypeClause* field)
{ {
composeDesc(desc, composeDesc(desc,
field->elementDtype, field->scale, field->subType, field->elementLength, field->elementDtype, field->scale, field->subType, field->elementLength,
field->charSetId.value, field->collationId, field->flags & FLD_nullable); field->charSetId.value_or(CS_NONE), field->collationId, field->flags & FLD_nullable);
} }
void DsqlDescMaker::fromField(dsc* desc, const TypeClause* field) void DsqlDescMaker::fromField(dsc* desc, const TypeClause* field)
{ {
composeDesc(desc, composeDesc(desc,
field->dtype, field->scale, field->subType, field->length, field->dtype, field->scale, field->subType, field->length,
field->charSetId.value, field->collationId, field->flags & FLD_nullable); field->charSetId.value_or(CS_NONE), field->collationId, field->flags & FLD_nullable);
} }
void DsqlDescMaker::fromList(DsqlCompilerScratch* scratch, dsc* desc, void DsqlDescMaker::fromList(DsqlCompilerScratch* scratch, dsc* desc,

View File

@ -561,7 +561,7 @@ bool METD_get_domain(jrd_tra* transaction, TypeClause* field, const MetaName& na
field->subType = FLX.RDB$FIELD_SUB_TYPE; field->subType = FLX.RDB$FIELD_SUB_TYPE;
field->dimensions = FLX.RDB$DIMENSIONS.NULL ? 0 : FLX.RDB$DIMENSIONS; field->dimensions = FLX.RDB$DIMENSIONS.NULL ? 0 : FLX.RDB$DIMENSIONS;
field->charSetId = Nullable<SSHORT>::empty(); field->charSetId = std::nullopt;
if (!FLX.RDB$CHARACTER_SET_ID.NULL) if (!FLX.RDB$CHARACTER_SET_ID.NULL)
field->charSetId = FLX.RDB$CHARACTER_SET_ID; field->charSetId = FLX.RDB$CHARACTER_SET_ID;
field->collationId = 0; field->collationId = 0;

View File

@ -727,23 +727,24 @@ using namespace Firebird;
%nonassoc ALTER %nonassoc ALTER
%nonassoc COLUMN %nonassoc COLUMN
%union %union YYSTYPE
{ {
BaseNullable<int> nullableIntVal; YYSTYPE()
{}
std::optional<int> nullableIntVal;
BaseNullable<bool> nullableBoolVal; BaseNullable<bool> nullableBoolVal;
BaseNullable<Jrd::TriggerDefinition::SqlSecurity> nullableSqlSecurityVal; std::optional<Jrd::TriggerDefinition::SqlSecurity> nullableSqlSecurityVal;
BaseNullable<Jrd::OverrideClause> nullableOverrideClause; std::optional<Jrd::OverrideClause> nullableOverrideClause;
struct { bool first; bool second; } boolPair; struct { bool first; bool second; } boolPair;
bool boolVal; bool boolVal;
int intVal; int intVal;
unsigned uintVal; unsigned uintVal;
SLONG int32Val; SLONG int32Val;
BaseNullable<SLONG> nullableInt32Val;
SINT64 int64Val; SINT64 int64Val;
FB_UINT64 uint64Val; FB_UINT64 uint64Val;
BaseNullable<SINT64> nullableInt64Val; std::optional<SINT64> nullableInt64Val;
BaseNullable<BaseNullable<SINT64> > nullableNullableInt64Val; std::optional<FB_UINT64> nullableUint64Val;
BaseNullable<FB_UINT64> nullableUint64Val;
Jrd::ScaledNumber scaledNumber; Jrd::ScaledNumber scaledNumber;
UCHAR blrOp; UCHAR blrOp;
Jrd::OrderNode::NullsPlacement nullsPlacement; Jrd::OrderNode::NullsPlacement nullsPlacement;
@ -1449,10 +1450,10 @@ arg_desc($parameters)
%type <nullableIntVal> param_mechanism %type <nullableIntVal> param_mechanism
param_mechanism param_mechanism
: /* nothing */ { $$ = Nullable<int>::empty(); } // Beware: This means FUN_reference or FUN_blob_struct. : /* nothing */ { $$ = std::nullopt; } // Beware: This means FUN_reference or FUN_blob_struct.
| BY DESCRIPTOR { $$ = Nullable<int>::val(FUN_descriptor); } | BY DESCRIPTOR { $$ = FUN_descriptor; }
| BY SCALAR_ARRAY { $$ = Nullable<int>::val(FUN_scalar_array); } | BY SCALAR_ARRAY { $$ = FUN_scalar_array; }
| NULL { $$ = Nullable<int>::val(FUN_ref_with_null); } | NULL { $$ = FUN_ref_with_null; }
; ;
%type return_value1(<createAlterFunctionNode>) %type return_value1(<createAlterFunctionNode>)
@ -1852,7 +1853,7 @@ replace_sequence_clause
replace_sequence_options($2) replace_sequence_options($2)
{ {
// Remove this to implement CORE-5137 // Remove this to implement CORE-5137
if (!$2->restartSpecified && !$2->step.specified) if (!$2->restartSpecified && !$2->step.has_value())
yyerrorIncompleteCmd(YYPOSNARG(3)); yyerrorIncompleteCmd(YYPOSNARG(3));
$$ = $2; $$ = $2;
} }
@ -1885,7 +1886,7 @@ alter_sequence_clause
} }
alter_sequence_options($2) alter_sequence_options($2)
{ {
if (!$2->restartSpecified && !$2->value.specified && !$2->step.specified) if (!$2->restartSpecified && !$2->value.has_value() && !$2->step.has_value())
yyerrorIncompleteCmd(YYPOSNARG(3)); yyerrorIncompleteCmd(YYPOSNARG(3));
$$ = $2; $$ = $2;
} }
@ -1913,8 +1914,8 @@ restart_option($seqNode)
%type <nullableInt64Val> with_opt %type <nullableInt64Val> with_opt
with_opt with_opt
: /* Nothign */ { $$ = BaseNullable<SINT64>::empty(); } : /* Nothign */ { $$ = std::nullopt; }
| WITH sequence_value { $$ = BaseNullable<SINT64>::val($2); } | WITH sequence_value { $$ = $2; }
; ;
%type <createAlterSequenceNode> set_generator_clause %type <createAlterSequenceNode> set_generator_clause
@ -1926,7 +1927,7 @@ set_generator_clause
node->alter = true; node->alter = true;
node->legacy = true; node->legacy = true;
node->restartSpecified = true; node->restartSpecified = true;
node->value = BaseNullable<SINT64>::val($5); node->value = $5;
$$ = node; $$ = node;
} }
; ;
@ -2278,12 +2279,12 @@ gtt_table_clause
: simple_table_name : simple_table_name
{ {
$<createRelationNode>$ = newNode<CreateRelationNode>($1); $<createRelationNode>$ = newNode<CreateRelationNode>($1);
$<createRelationNode>$->relationType = Nullable<rel_t>::empty(); $<createRelationNode>$->relationType = std::nullopt;
} }
'(' table_elements($2) ')' gtt_ops($2) '(' table_elements($2) ')' gtt_ops($2)
{ {
$$ = $2; $$ = $2;
if (!$$->relationType.specified) if (!$$->relationType.has_value())
$$->relationType = rel_global_temp_delete; $$->relationType = rel_global_temp_delete;
} }
; ;
@ -4025,8 +4026,8 @@ trigger_type_suffix
%type <nullableIntVal> trigger_position %type <nullableIntVal> trigger_position
trigger_position trigger_position
: /* nothing */ { $$ = Nullable<int>::empty(); } : /* nothing */ { $$ = std::nullopt; }
| POSITION nonneg_short_integer { $$ = Nullable<int>::val($2); } | POSITION nonneg_short_integer { $$ = $2; }
; ;
// ALTER statement // ALTER statement
@ -4594,21 +4595,21 @@ alter_trigger_clause
%type <nullableUint64Val> trigger_type_opt %type <nullableUint64Val> trigger_type_opt
trigger_type_opt // we do not allow alter database triggers, hence we do not use trigger_type here trigger_type_opt // we do not allow alter database triggers, hence we do not use trigger_type here
: trigger_type_prefix trigger_type_suffix : trigger_type_prefix trigger_type_suffix
{ $$ = Nullable<FB_UINT64>::val($1 + $2 - 1); } { $$ = $1 + $2 - 1; }
| |
{ $$ = Nullable<FB_UINT64>::empty(); } { $$ = std::nullopt; }
; ;
%type <nullableSqlSecurityVal> trg_sql_security_clause %type <nullableSqlSecurityVal> trg_sql_security_clause
trg_sql_security_clause trg_sql_security_clause
: // nothing : // nothing
{ $$ = Nullable<TriggerDefinition::SqlSecurity>::empty(); } { $$ = std::nullopt; }
| SQL SECURITY DEFINER | SQL SECURITY DEFINER
{ $$ = Nullable<TriggerDefinition::SqlSecurity>::val(TriggerDefinition::SS_DEFINER); } { $$ = TriggerDefinition::SS_DEFINER; }
| SQL SECURITY INVOKER | SQL SECURITY INVOKER
{ $$ = Nullable<TriggerDefinition::SqlSecurity>::val(TriggerDefinition::SS_INVOKER); } { $$ = TriggerDefinition::SS_INVOKER; }
| DROP SQL SECURITY | DROP SQL SECURITY
{ $$ = Nullable<TriggerDefinition::SqlSecurity>::val(TriggerDefinition::SS_DROP); } { $$ = TriggerDefinition::SS_DROP; }
; ;
// DROP metadata operations // DROP metadata operations
@ -6619,9 +6620,9 @@ insert_start
%type <nullableOverrideClause> override_opt %type <nullableOverrideClause> override_opt
override_opt override_opt
: /* nothing */ { $$ = Nullable<OverrideClause>::empty(); } : /* nothing */ { $$ = std::nullopt; }
| OVERRIDING USER VALUE { $$ = Nullable<OverrideClause>::val(OverrideClause::USER_VALUE); } | OVERRIDING USER VALUE { $$ = OverrideClause::USER_VALUE; }
| OVERRIDING SYSTEM VALUE { $$ = Nullable<OverrideClause>::val(OverrideClause::SYSTEM_VALUE); } | OVERRIDING SYSTEM VALUE { $$ = OverrideClause::SYSTEM_VALUE; }
; ;
%type <valueListNode> value_or_default_list %type <valueListNode> value_or_default_list

View File

@ -173,6 +173,54 @@ void PreparedStatement::Builder::moveFromResultSet(thread_db* tdbb, ResultSet* r
{ {
for (Array<OutputSlot>::const_iterator i = outputSlots.begin(); i != outputSlots.end(); ++i) for (Array<OutputSlot>::const_iterator i = outputSlots.begin(); i != outputSlots.end(); ++i)
{ {
if (i->isOptional)
{
const bool isNull = rs->isNull(i->number);
switch (i->type)
{
case TYPE_SSHORT:
*(std::optional<SSHORT>*) i->address = isNull ?
std::nullopt : std::optional{rs->getSmallInt(tdbb, i->number)};
break;
case TYPE_SLONG:
*(std::optional<SLONG>*) i->address = isNull ?
std::nullopt : std::optional{rs->getInt(tdbb, i->number)};
break;
case TYPE_SINT64:
*(std::optional<SINT64>*) i->address = isNull ?
std::nullopt : std::optional{rs->getBigInt(tdbb, i->number)};
break;
case TYPE_DOUBLE:
*(std::optional<double>*) i->address = isNull ?
std::nullopt : std::optional{rs->getDouble(tdbb, i->number)};
break;
case TYPE_STRING:
*(std::optional<string>*) i->address = isNull ?
std::nullopt : std::optional{rs->getString(tdbb, i->number)};
break;
case TYPE_METANAME:
*(std::optional<MetaName>*) i->address = isNull ?
std::nullopt : std::optional{rs->getMetaName(tdbb, i->number)};
break;
case TYPE_METASTRING:
*(std::optional<MetaString>*) i->address = isNull ?
std::nullopt : std::optional{rs->getMetaString(tdbb, i->number)};
break;
default:
fb_assert(false);
}
continue;
}
switch (i->type) switch (i->type)
{ {
case TYPE_SSHORT: case TYPE_SSHORT:
@ -192,11 +240,8 @@ void PreparedStatement::Builder::moveFromResultSet(thread_db* tdbb, ResultSet* r
break; break;
case TYPE_STRING: case TYPE_STRING:
{ *(string*) i->address = rs->getString(tdbb, i->number);
AbstractString* str = (AbstractString*) i->address;
str->replace(0, str->length(), rs->getString(tdbb, i->number));
break; break;
}
case TYPE_METANAME: case TYPE_METANAME:
*(MetaName*) i->address = rs->getMetaName(tdbb, i->number); *(MetaName*) i->address = rs->getMetaName(tdbb, i->number);
@ -209,9 +254,6 @@ void PreparedStatement::Builder::moveFromResultSet(thread_db* tdbb, ResultSet* r
default: default:
fb_assert(false); fb_assert(false);
} }
if (i->specifiedAddress && rs->isNull(i->number))
*i->specifiedAddress = false;
} }
} }
@ -221,8 +263,70 @@ void PreparedStatement::Builder::moveToStatement(thread_db* tdbb, PreparedStatem
{ {
for (Array<InputSlot>::const_iterator i = inputSlots.begin(); i != inputSlots.end(); ++i) for (Array<InputSlot>::const_iterator i = inputSlots.begin(); i != inputSlots.end(); ++i)
{ {
if (i->specifiedAddress && !*i->specifiedAddress) if (i->isOptional)
{ {
switch (i->type)
{
case TYPE_SSHORT:
if (const auto optional = (std::optional<SSHORT>*) i->address; optional->has_value())
{
stmt->setSmallInt(tdbb, i->number, optional->value());
continue;
}
break;
case TYPE_SLONG:
if (const auto optional = (std::optional<SLONG>*) i->address; optional->has_value())
{
stmt->setInt(tdbb, i->number, optional->value());
continue;
}
break;
case TYPE_SINT64:
if (const auto optional = (std::optional<SINT64>*) i->address; optional->has_value())
{
stmt->setBigInt(tdbb, i->number, optional->value());
continue;
}
break;
case TYPE_DOUBLE:
if (const auto optional = (std::optional<double>*) i->address; optional->has_value())
{
stmt->setDouble(tdbb, i->number, optional->value());
continue;
}
break;
case TYPE_STRING:
if (const auto optional = (std::optional<string>*) i->address; optional->has_value())
{
stmt->setString(tdbb, i->number, optional->value());
continue;
}
break;
case TYPE_METANAME:
if (const auto optional = (std::optional<MetaName>*) i->address; optional->has_value())
{
stmt->setMetaName(tdbb, i->number, optional->value());
continue;
}
break;
case TYPE_METASTRING:
if (const auto optional = (std::optional<MetaString>*) i->address; optional->has_value())
{
stmt->setMetaString(tdbb, i->number, optional->value());
continue;
}
break;
default:
fb_assert(false);
}
stmt->setNull(i->number); stmt->setNull(i->number);
continue; continue;
} }
@ -246,7 +350,7 @@ void PreparedStatement::Builder::moveToStatement(thread_db* tdbb, PreparedStatem
break; break;
case TYPE_STRING: case TYPE_STRING:
stmt->setString(tdbb, i->number, *(AbstractString*) i->address); stmt->setString(tdbb, i->number, *(string*) i->address);
break; break;
case TYPE_METANAME: case TYPE_METANAME:

View File

@ -24,6 +24,8 @@
#define JRD_PREPARED_STATEMENT_H #define JRD_PREPARED_STATEMENT_H
#include "firebird.h" #include "firebird.h"
#include <utility>
#include <optional>
#include "../common/dsc.h" #include "../common/dsc.h"
#include "../common/MsgMetadata.h" #include "../common/MsgMetadata.h"
#include "../jrd/intl.h" #include "../jrd/intl.h"
@ -33,7 +35,6 @@
#include "../common/classes/fb_string.h" #include "../common/classes/fb_string.h"
#include "../common/classes/MetaString.h" #include "../common/classes/MetaString.h"
#include "../jrd/MetaName.h" #include "../jrd/MetaName.h"
#include "../common/classes/Nullable.h"
namespace Jrd { namespace Jrd {
@ -45,6 +46,9 @@ class dsql_msg;
class ResultSet; class ResultSet;
template <typename T>
struct PreparedStatementTypeDiscriminator {};
class PreparedStatement : public Firebird::PermanentStorage class PreparedStatement : public Firebird::PermanentStorage
{ {
friend class ResultSet; friend class ResultSet;
@ -52,7 +56,7 @@ friend class ResultSet;
public: public:
class Builder class Builder
{ {
private: public:
enum Type enum Type
{ {
TYPE_SSHORT, TYPE_SSHORT,
@ -83,7 +87,7 @@ public:
Type type; Type type;
unsigned number; unsigned number;
const void* address; const void* address;
const bool* specifiedAddress; bool isOptional;
}; };
struct OutputSlot struct OutputSlot
@ -91,7 +95,7 @@ public:
Type type; Type type;
unsigned number; unsigned number;
void* address; void* address;
bool* specifiedAddress; bool isOptional;
}; };
public: public:
@ -103,16 +107,15 @@ public:
public: public:
// Output variables. // Output variables.
template <typename T> OutputParam operator ()(const char* chunk, Nullable<T>& param) template <typename T> OutputParam operator ()(const char* chunk, std::optional<T>& param)
{ {
OutputParam ret = (*this)(chunk, param.value); addOutput(PreparedStatementTypeDiscriminator<T>::TYPE, &param, true, outputSlots);
outputSlots[outputSlots.getCount() - 1].specifiedAddress = &param.specified; return OutputParam(chunk, outputSlots.getCount() - 1);
return ret;
} }
template <typename T> OutputParam operator ()(const char* chunk, T& param) template <typename T> OutputParam operator ()(const char* chunk, T& param)
{ {
addOutput(getType(param), &param, outputSlots); addOutput(PreparedStatementTypeDiscriminator<T>::TYPE, &param, false, outputSlots);
return OutputParam(chunk, outputSlots.getCount() - 1); return OutputParam(chunk, outputSlots.getCount() - 1);
} }
@ -134,16 +137,16 @@ public:
return *this; return *this;
} }
template <typename T> Builder& operator <<(const Nullable<T>& param) template <typename T> Builder& operator <<(const std::optional<T>& param)
{ {
*this << param.value; addInput(PreparedStatementTypeDiscriminator<T>::TYPE, &param, true, inputSlots);
inputSlots[inputSlots.getCount() - 1].specifiedAddress = &param.specified; text += "?";
return *this; return *this;
} }
template <typename T> Builder& operator <<(const T& param) template <typename T> Builder& operator <<(const T& param)
{ {
addInput(getType(param), &param, inputSlots); addInput(PreparedStatementTypeDiscriminator<T>::TYPE, &param, false, inputSlots);
text += "?"; text += "?";
return *this; return *this;
} }
@ -158,32 +161,23 @@ public:
void moveToStatement(thread_db* tdbb, PreparedStatement* stmt) const; void moveToStatement(thread_db* tdbb, PreparedStatement* stmt) const;
private: private:
// Make the C++ template engine return the constant for each type. void addInput(Type type, const void* address, bool isOptional, Firebird::Array<InputSlot>& slots)
static Type getType(SSHORT) { return TYPE_SSHORT; }
static Type getType(SLONG) { return TYPE_SLONG; }
static Type getType(SINT64) { return TYPE_SINT64; }
static Type getType(double) { return TYPE_DOUBLE; }
static Type getType(const Firebird::AbstractString&) { return TYPE_STRING; }
static Type getType(const MetaName&) { return TYPE_METANAME; }
static Type getType(const Firebird::MetaString&) { return TYPE_METASTRING; }
void addInput(Type type, const void* address, Firebird::Array<InputSlot>& slots)
{ {
InputSlot slot; InputSlot slot;
slot.type = type; slot.type = type;
slot.number = (unsigned) slots.getCount() + 1; slot.number = (unsigned) slots.getCount() + 1;
slot.address = address; slot.address = address;
slot.specifiedAddress = NULL; slot.isOptional = isOptional;
slots.add(slot); slots.add(slot);
} }
void addOutput(Type type, void* address, Firebird::Array<OutputSlot>& slots) void addOutput(Type type, void* address, bool isOptional, Firebird::Array<OutputSlot>& slots)
{ {
OutputSlot slot; OutputSlot slot;
slot.type = type; slot.type = type;
slot.number = (unsigned) slots.getCount() + 1; slot.number = (unsigned) slots.getCount() + 1;
slot.address = address; slot.address = address;
slot.specifiedAddress = NULL; slot.isOptional = isOptional;
slots.add(slot); slots.add(slot);
} }
@ -324,7 +318,7 @@ public:
setDesc(tdbb, param, desc); setDesc(tdbb, param, desc);
} }
void setString(thread_db* tdbb, unsigned param, const Firebird::AbstractString& value) void setString(thread_db* tdbb, unsigned param, const Firebird::string& value)
{ {
fb_assert(param > 0); fb_assert(param > 0);
@ -378,6 +372,50 @@ private:
typedef Firebird::AutoPtr<PreparedStatement> AutoPreparedStatement; typedef Firebird::AutoPtr<PreparedStatement> AutoPreparedStatement;
// PreparedStatementTypeDiscriminator specializations.
template <>
struct PreparedStatementTypeDiscriminator<SSHORT>
{
static constexpr PreparedStatement::Builder::Type TYPE = PreparedStatement::Builder::TYPE_SSHORT;
};
template <>
struct PreparedStatementTypeDiscriminator<SLONG>
{
static constexpr PreparedStatement::Builder::Type TYPE = PreparedStatement::Builder::TYPE_SLONG;
};
template <>
struct PreparedStatementTypeDiscriminator<SINT64>
{
static constexpr PreparedStatement::Builder::Type TYPE = PreparedStatement::Builder::TYPE_SINT64;
};
template <>
struct PreparedStatementTypeDiscriminator<double>
{
static constexpr PreparedStatement::Builder::Type TYPE = PreparedStatement::Builder::TYPE_DOUBLE;
};
template <>
struct PreparedStatementTypeDiscriminator<Firebird::string>
{
static constexpr PreparedStatement::Builder::Type TYPE = PreparedStatement::Builder::TYPE_STRING;
};
template <>
struct PreparedStatementTypeDiscriminator<MetaName>
{
static constexpr PreparedStatement::Builder::Type TYPE = PreparedStatement::Builder::TYPE_METANAME;
};
template <>
struct PreparedStatementTypeDiscriminator<Firebird::MetaString>
{
static constexpr PreparedStatement::Builder::Type TYPE = PreparedStatement::Builder::TYPE_METASTRING;
};
} // namespace } // namespace

View File

@ -335,8 +335,8 @@ void ProfilerPackage::startSessionFunction(ThrowStatusExceptionWrapper* /*status
} }
const string description(in->description.str, in->descriptionNull ? 0 : in->description.length); const string description(in->description.str, in->descriptionNull ? 0 : in->description.length);
const Nullable<SLONG> flushInterval(in->flushIntervalNull ? const std::optional<SLONG> flushInterval(in->flushIntervalNull ?
Nullable<SLONG>() : Nullable<SLONG>(in->flushInterval)); std::nullopt : std::optional{in->flushInterval});
const PathName pluginName(in->pluginName.str, in->pluginNameNull ? 0 : in->pluginName.length); const PathName pluginName(in->pluginName.str, in->pluginNameNull ? 0 : in->pluginName.length);
const string pluginOptions(in->pluginOptions.str, in->pluginOptionsNull ? 0 : in->pluginOptions.length); const string pluginOptions(in->pluginOptions.str, in->pluginOptionsNull ? 0 : in->pluginOptions.length);
@ -398,11 +398,11 @@ int ProfilerManager::blockingAst(void* astObject)
return 0; return 0;
} }
SINT64 ProfilerManager::startSession(thread_db* tdbb, Nullable<SLONG> flushInterval, SINT64 ProfilerManager::startSession(thread_db* tdbb, std::optional<SLONG> flushInterval,
const PathName& pluginName, const string& description, const string& options) const PathName& pluginName, const string& description, const string& options)
{ {
if (flushInterval.isAssigned()) if (flushInterval.has_value())
checkFlushInterval(flushInterval.value); checkFlushInterval(flushInterval.value());
AutoSetRestore<bool> pauseProfiler(&paused, true); AutoSetRestore<bool> pauseProfiler(&paused, true);
@ -460,8 +460,8 @@ SINT64 ProfilerManager::startSession(thread_db* tdbb, Nullable<SLONG> flushInter
paused = false; paused = false;
if (flushInterval.isAssigned()) if (flushInterval.has_value())
setFlushInterval(flushInterval.value); setFlushInterval(flushInterval.value());
return currentSession->pluginSession->getId(); return currentSession->pluginSession->getId();
} }
@ -1038,8 +1038,8 @@ void ProfilerListener::processCommand(thread_db* tdbb)
const string description(in->description.str, const string description(in->description.str,
in->descriptionNull ? 0 : in->description.length); in->descriptionNull ? 0 : in->description.length);
const Nullable<SLONG> flushInterval(in->flushIntervalNull ? const std::optional<SLONG> flushInterval(in->flushIntervalNull ?
Nullable<SLONG>() : Nullable<SLONG>(in->flushInterval)); std::nullopt : std::optional{in->flushInterval});
const PathName pluginName(in->pluginName.str, const PathName pluginName(in->pluginName.str,
in->pluginNameNull ? 0 : in->pluginName.length); in->pluginNameNull ? 0 : in->pluginName.length);
const string pluginOptions(in->pluginOptions.str, const string pluginOptions(in->pluginOptions.str,

View File

@ -25,6 +25,7 @@
#include "firebird.h" #include "firebird.h"
#include "firebird/Message.h" #include "firebird/Message.h"
#include <optional>
#include "../common/PerformanceStopWatch.h" #include "../common/PerformanceStopWatch.h"
#include "../common/classes/auto.h" #include "../common/classes/auto.h"
#include "../common/classes/fb_string.h" #include "../common/classes/fb_string.h"
@ -187,7 +188,7 @@ public:
void operator=(const ProfilerManager&) = delete; void operator=(const ProfilerManager&) = delete;
public: public:
SINT64 startSession(thread_db* tdbb, Nullable<SLONG> flushInterval, SINT64 startSession(thread_db* tdbb, std::optional<SLONG> flushInterval,
const Firebird::PathName& pluginName, const Firebird::string& description, const Firebird::string& options); const Firebird::PathName& pluginName, const Firebird::string& description, const Firebird::string& options);
void prepareCursor(thread_db* tdbb, Request* request, const Select* select); void prepareCursor(thread_db* tdbb, Request* request, const Select* select);

View File

@ -22,6 +22,7 @@
#ifndef JRD_RELATION_H #ifndef JRD_RELATION_H
#define JRD_RELATION_H #define JRD_RELATION_H
#include <optional>
#include "../jrd/jrd.h" #include "../jrd/jrd.h"
#include "../jrd/btr.h" #include "../jrd/btr.h"
#include "../jrd/lck.h" #include "../jrd/lck.h"
@ -490,7 +491,7 @@ public:
MetaName fld_security_name; // security class name for field MetaName fld_security_name; // security class name for field
MetaName fld_generator_name; // identity generator name MetaName fld_generator_name; // identity generator name
MetaNamePair fld_source_rel_field; // Relation/field source name MetaNamePair fld_source_rel_field; // Relation/field source name
Nullable<IdentityType> fld_identity_type; std::optional<IdentityType> fld_identity_type;
USHORT fld_flags; USHORT fld_flags;
public: public:

View File

@ -1039,10 +1039,10 @@ namespace
dependencies.push(dependency); dependencies.push(dependency);
} }
if (parameter->prm_text_type.isAssigned()) if (parameter->prm_text_type.has_value())
{ {
CompilerScratch::Dependency dependency(obj_collation); CompilerScratch::Dependency dependency(obj_collation);
dependency.number = parameter->prm_text_type.value; dependency.number = parameter->prm_text_type.value();
dependencies.push(dependency); dependencies.push(dependency);
} }
} }

View File

@ -32,6 +32,7 @@
#ifndef JRD_EXE_H #ifndef JRD_EXE_H
#define JRD_EXE_H #define JRD_EXE_H
#include <optional>
#include "../jrd/blb.h" #include "../jrd/blb.h"
#include "../jrd/Relation.h" #include "../jrd/Relation.h"
#include "../common/classes/array.h" #include "../common/classes/array.h"
@ -610,7 +611,7 @@ public:
void activate(bool subStream = false); void activate(bool subStream = false);
void deactivate(); void deactivate();
Nullable<USHORT> csb_cursor_number; // Cursor number for this stream std::optional<USHORT> csb_cursor_number; // Cursor number for this stream
StreamType csb_stream; // Map user context to internal stream StreamType csb_stream; // Map user context to internal stream
StreamType csb_view_stream; // stream number for view relation, below StreamType csb_view_stream; // stream number for view relation, below
USHORT csb_flags; USHORT csb_flags;

View File

@ -223,7 +223,8 @@ namespace
return formatNumber; return formatNumber;
} }
bool getCharsetByTextType(SSHORT& charSet, const USHORT subType) template <typename T>
bool getCharsetByTextType(T& charSet, const USHORT subType)
{ {
switch (subType) switch (subType)
{ {
@ -1169,10 +1170,7 @@ void INI_init_dsql(thread_db* tdbb, dsql_dbb* database)
} }
if (DTYPE_IS_TEXT(gfield->gfld_dtype)) if (DTYPE_IS_TEXT(gfield->gfld_dtype))
{ getCharsetByTextType(field->charSetId, gfield->gfld_sub_type);
if (getCharsetByTextType(field->charSetId.value, gfield->gfld_sub_type))
field->charSetId.specified = true;
}
if (gfield->gfld_nullable) if (gfield->gfld_nullable)
field->flags |= FLD_nullable; field->flags |= FLD_nullable;

View File

@ -291,7 +291,7 @@ public:
MetaName prm_field_source; MetaName prm_field_source;
MetaName prm_type_of_column; MetaName prm_type_of_column;
MetaName prm_type_of_table; MetaName prm_type_of_table;
Nullable<USHORT> prm_text_type; std::optional<USHORT> prm_text_type;
FUN_T prm_fun_mechanism; FUN_T prm_fun_mechanism;
public: public:

View File

@ -4290,7 +4290,7 @@ void MET_scan_relation(thread_db* tdbb, jrd_rel* relation)
case RSR_field_generator_name: case RSR_field_generator_name:
field->fld_generator_name = (const TEXT*) p; field->fld_generator_name = (const TEXT*) p;
if (!field->fld_identity_type.specified) if (!field->fld_identity_type.has_value())
field->fld_identity_type = IDENT_TYPE_BY_DEFAULT; field->fld_identity_type = IDENT_TYPE_BY_DEFAULT;
break; break;

View File

@ -22,6 +22,7 @@
#include "firebird.h" #include "firebird.h"
#include "firebird/Message.h" #include "firebird/Message.h"
#include <optional>
#include "../common/Int128.h" #include "../common/Int128.h"
#include "../common/classes/ImplementHelper.h" #include "../common/classes/ImplementHelper.h"
#include "../common/classes/auto.h" #include "../common/classes/auto.h"
@ -29,7 +30,6 @@
#include "../common/classes/fb_string.h" #include "../common/classes/fb_string.h"
#include "../common/classes/GenericMap.h" #include "../common/classes/GenericMap.h"
#include "../common/classes/MetaString.h" #include "../common/classes/MetaString.h"
#include "../common/classes/Nullable.h"
#include "../common/classes/objects_array.h" #include "../common/classes/objects_array.h"
#include "../common/classes/stack.h" #include "../common/classes/stack.h"
#include "../common/status.h" #include "../common/status.h"
@ -105,7 +105,7 @@ struct Cursor
struct RecordSource struct RecordSource
{ {
Nullable<ULONG> parentId; std::optional<ULONG> parentId;
unsigned level; unsigned level;
string accessPath{defaultPool()}; string accessPath{defaultPool()};
}; };
@ -137,8 +137,8 @@ struct Request
SINT64 callerStatementId = 0; SINT64 callerStatementId = 0;
SINT64 callerRequestId = 0; SINT64 callerRequestId = 0;
ISC_TIMESTAMP_TZ startTimestamp; ISC_TIMESTAMP_TZ startTimestamp;
Nullable<ISC_TIMESTAMP_TZ> finishTimestamp; std::optional<ISC_TIMESTAMP_TZ> finishTimestamp;
Nullable<FB_UINT64> totalElapsedTicks; std::optional<FB_UINT64> totalElapsedTicks;
NonPooledMap<CursorRecSourceKey, RecordSourceStats> recordSourcesStats{defaultPool()}; NonPooledMap<CursorRecSourceKey, RecordSourceStats> recordSourcesStats{defaultPool()};
NonPooledMap<LineColumnKey, Stats> psqlStats{defaultPool()}; NonPooledMap<LineColumnKey, Stats> psqlStats{defaultPool()};
}; };
@ -226,7 +226,7 @@ public:
NonPooledMap<SINT64, Request> requests{defaultPool()}; NonPooledMap<SINT64, Request> requests{defaultPool()};
SINT64 id; SINT64 id;
ISC_TIMESTAMP_TZ startTimestamp; ISC_TIMESTAMP_TZ startTimestamp;
Nullable<ISC_TIMESTAMP_TZ> finishTimestamp; std::optional<ISC_TIMESTAMP_TZ> finishTimestamp;
string description{defaultPool()}; string description{defaultPool()};
bool detailedRequests = false; bool detailedRequests = false;
bool dirty = true; bool dirty = true;
@ -649,8 +649,9 @@ void ProfilerPlugin::flush(ThrowStatusExceptionWrapper* status)
sessionMessage->startTimestampNull = FB_FALSE; sessionMessage->startTimestampNull = FB_FALSE;
sessionMessage->startTimestamp = session->startTimestamp; sessionMessage->startTimestamp = session->startTimestamp;
sessionMessage->finishTimestampNull = session->finishTimestamp.isUnknown(); sessionMessage->finishTimestampNull = !session->finishTimestamp.has_value();
sessionMessage->finishTimestamp = session->finishTimestamp.value; if (session->finishTimestamp.has_value())
sessionMessage->finishTimestamp = session->finishTimestamp.value();
sessionStmt->execute(status, transaction, sessionMessage.getMetadata(), sessionStmt->execute(status, transaction, sessionMessage.getMetadata(),
sessionMessage.getData(), nullptr, nullptr); sessionMessage.getData(), nullptr, nullptr);
@ -772,8 +773,8 @@ void ProfilerPlugin::flush(ThrowStatusExceptionWrapper* status)
recSrcMessage->recordSourceIdNull = FB_FALSE; recSrcMessage->recordSourceIdNull = FB_FALSE;
recSrcMessage->recordSourceId = recSourceId; recSrcMessage->recordSourceId = recSourceId;
recSrcMessage->parentRecordSourceIdNull = !recSrc.parentId.specified; recSrcMessage->parentRecordSourceIdNull = !recSrc.parentId.has_value();
recSrcMessage->parentRecordSourceId = recSrc.parentId.value; recSrcMessage->parentRecordSourceId = recSrc.parentId.value_or(0);
recSrcMessage->levelNull = FB_FALSE; recSrcMessage->levelNull = FB_FALSE;
recSrcMessage->level = recSrc.level; recSrcMessage->level = recSrc.level;
@ -839,15 +840,16 @@ void ProfilerPlugin::flush(ThrowStatusExceptionWrapper* status)
requestMessage->startTimestampNull = FB_FALSE; requestMessage->startTimestampNull = FB_FALSE;
requestMessage->startTimestamp = profileRequest.startTimestamp; requestMessage->startTimestamp = profileRequest.startTimestamp;
requestMessage->finishTimestampNull = profileRequest.finishTimestamp.isUnknown(); requestMessage->finishTimestampNull = !profileRequest.finishTimestamp.has_value();
requestMessage->finishTimestamp = profileRequest.finishTimestamp.value; if (profileRequest.finishTimestamp.has_value())
requestMessage->finishTimestamp = profileRequest.finishTimestamp.value();
requestMessage->totalElapsedTimeNull = profileRequest.totalElapsedTicks.isUnknown(); requestMessage->totalElapsedTimeNull = !profileRequest.totalElapsedTicks.has_value();
requestMessage->totalElapsedTime = ticksToNanoseconds(profileRequest.totalElapsedTicks.value); requestMessage->totalElapsedTime = ticksToNanoseconds(profileRequest.totalElapsedTicks.value_or(0));
addBatch(requestBatch, requestBatchSize, requestMessage); addBatch(requestBatch, requestBatchSize, requestMessage);
if (profileRequest.finishTimestamp.isAssigned()) if (profileRequest.finishTimestamp.has_value())
finishedRequests.add(requestIt->first); finishedRequests.add(requestIt->first);
profileRequest.dirty = false; profileRequest.dirty = false;
@ -937,7 +939,7 @@ void ProfilerPlugin::flush(ThrowStatusExceptionWrapper* status)
} }
} }
if (session->finishTimestamp.isUnknown()) if (!session->finishTimestamp.has_value())
{ {
session->statements.clear(); session->statements.clear();
session->recordSources.clear(); session->recordSources.clear();