8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-02-02 08:40:39 +01:00

Implemented #7046: Make ability to add comment to mapping ('COMMENT ON MAPPING ... IS ...')

This commit is contained in:
AlexPeshkoff 2022-07-01 18:19:53 +03:00
parent 65efac2a56
commit c3b172d4e2
6 changed files with 91 additions and 9 deletions

View File

@ -158,6 +158,7 @@ basic_type:
- PACKAGE
- USER (ability to store comment depends upon user management plugin)
- SECURITY CLASS (not implemented because Borland hid them).
- [GLOBAL] MAPPING
5) Allow setting and dropping default values from table fields.

View File

@ -10500,6 +10500,7 @@ string MappingNode::internalPrint(NodePrinter& printer) const
NODE_PRINT(printer, fromType);
NODE_PRINT(printer, from);
NODE_PRINT(printer, to);
NODE_PRINT(printer, comment);
NODE_PRINT(printer, op);
NODE_PRINT(printer, mode);
NODE_PRINT(printer, global);
@ -10558,10 +10559,22 @@ void MappingNode::runInSecurityDb(SecDbContext* secDbContext)
case MAP_RPL:
ddl = "CREATE OR ALTER MAPPING ";
break;
case MAP_COMMENT:
ddl = "COMMENT ON MAPPING ";
break;
}
addItem(ddl, name.c_str());
if (op == MAP_COMMENT)
{
ddl += " IS ";
if (comment)
addItem(ddl, comment->c_str(), '\'');
else
ddl += "NULL";
}
addItem(ddl, name.c_str());
if (op != MAP_DROP)
else if (op != MAP_DROP)
{
ddl += " USING ";
switch (mode)
@ -10654,6 +10667,7 @@ void MappingNode::runInSecurityDb(SecDbContext* secDbContext)
(Arg::Gds(isc_map_already_exists) << name).raise();
break;
case MAP_COMMENT:
case MAP_MOD:
case MAP_DROP:
if (!hasLine)
@ -10676,6 +10690,10 @@ void MappingNode::runInSecurityDb(SecDbContext* secDbContext)
Field<Varying> f2(full, 255);
Field<Varying> nm2(full, MAX_SQL_IDENTIFIER_LEN);
Message cmnt;
Field<Varying> c3(cmnt, MAX_VARY_COLUMN_SIZE);
Field<Varying> nm3(cmnt, MAX_SQL_IDENTIFIER_LEN);
toType = role ? 1 : 0;
if (to)
t = to->c_str();
@ -10688,7 +10706,9 @@ void MappingNode::runInSecurityDb(SecDbContext* secDbContext)
type2 = fromType->c_str();
if (from)
f2 = fromUtf8.c_str();
nm2 = name.c_str();
if (comment)
c3 = comment->c_str();
nm3 = nm2 = name.c_str();
Message* msg = NULL;
const char* sql = NULL;
@ -10707,6 +10727,11 @@ void MappingNode::runInSecurityDb(SecDbContext* secDbContext)
"where RDB$MAP_NAME = ?";
msg = &full;
break;
case MAP_COMMENT:
sql = "update RDB$AUTH_MAPPING set RDB$DESCRIPTION = ? "
"where RDB$MAP_NAME = ?";
msg = &cmnt;
break;
case MAP_DROP:
sql = "delete from RDBAUTH_MAPPING where RDB$MAP_NAME = ?";
msg = &msgCheck;
@ -10751,7 +10776,7 @@ void MappingNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd
// run all statements under savepoint control
AutoSavePoint savePoint(tdbb, transaction);
fb_assert(op == MAP_DROP || fromType);
fb_assert(op == MAP_DROP || op == MAP_COMMENT || fromType);
short plugNull = plugin ? FALSE : TRUE;
short dbNull = db ? FALSE : TRUE;
@ -10807,6 +10832,17 @@ void MappingNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd
END_MODIFY
break;
case MAP_COMMENT:
MODIFY M
M.RDB$DESCRIPTION.NULL = !(comment && comment->hasData());
if (!M.RDB$DESCRIPTION.NULL)
{
AutoBlb b(tdbb, blb::create(tdbb, transaction, &M.RDB$DESCRIPTION));
b->BLB_put_data(tdbb, (const UCHAR*)(comment->c_str()), comment->length());
}
END_MODIFY
break;
case MAP_DROP:
ddlTriggerAction = DDL_TRIGGER_DROP_MAPPING;
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, ddlTriggerAction,
@ -10870,16 +10906,18 @@ void MappingNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd
case MAP_MOD:
case MAP_DROP:
case MAP_COMMENT:
if (!found)
(Arg::Gds(isc_map_not_exists) << name).raise();
break;
}
fb_assert(ddlTriggerAction > 0);
fb_assert(ddlTriggerAction > 0 || op == MAP_COMMENT);
if (ddlTriggerAction > 0)
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, ddlTriggerAction, name, NULL);
DFW_post_work(transaction, dfw_clear_cache, NULL, Mapping::MAPPING_CACHE);
if (op != MAP_COMMENT)
DFW_post_work(transaction, dfw_clear_cache, NULL, Mapping::MAPPING_CACHE);
savePoint.release(); // everything is ok
}

View File

@ -2066,7 +2066,7 @@ private:
class MappingNode : public DdlNode, private ExecInSecurityDb
{
public:
enum OP {MAP_ADD, MAP_MOD, MAP_RPL, MAP_DROP};
enum OP {MAP_ADD, MAP_MOD, MAP_RPL, MAP_DROP, MAP_COMMENT};
MappingNode(MemoryPool& p, OP o, const MetaName& nm)
: DdlNode(p),
@ -2077,6 +2077,7 @@ public:
fromType(NULL),
from(NULL),
to(NULL),
comment(NULL),
op(o),
mode('#'),
global(false),
@ -2096,7 +2097,8 @@ protected:
{
statusVector << Firebird::Arg::Gds(isc_dsql_mapping_failed) << name <<
(op == MAP_ADD ? "CREATE" : op == MAP_MOD ?
"ALTER" : op == MAP_RPL ? "CREATE OR ALTER" : "DROP");
"ALTER" : op == MAP_RPL ? "CREATE OR ALTER" : op == MAP_DROP ?
"DROP" : "COMMENT ON");
}
void runInSecurityDb(SecDbContext* secDbContext);
@ -2111,6 +2113,7 @@ public:
MetaName* fromType;
IntlString* from;
MetaName* to;
Firebird::string* comment;
OP op;
char mode; // * - any source, P - plugin, M - mapping, S - any serverwide plugin
bool global;

View File

@ -5651,6 +5651,8 @@ comment
{ $$ = newNode<CommentOnNode>($3, *$4, "", *$6); }
| comment_on_user
{ $$ = $1; }
| comment_on_mapping
{ $$ = $1; }
;
%type <createAlterUserNode> comment_on_user
@ -7307,6 +7309,28 @@ drop_map_clause($global)
}
;
%type <mappingNode> comment_on_mapping
comment_on_mapping
: COMMENT ON MAPPING map_comment(false)
{
$$ = $4;
}
| COMMENT ON GLOBAL MAPPING map_comment(true)
{
$$ = $5;
}
;
%type <mappingNode> map_comment(<boolVal>)
map_comment($global)
: map_name IS ddl_desc
{
$$ = newNode<MappingNode>(MappingNode::MAP_COMMENT, *$1);
$$->global = $global;
$$->comment = $3;
}
;
%type <mappingNode> map_clause(<mappingOp>)
map_clause($op)
: map_name

View File

@ -1725,10 +1725,11 @@ RecordBuffer* MappingList::getList(thread_db* tdbb, jrd_rel* relation)
Field<Varying> from(mMap, 255);
Field<SSHORT> role(mMap);
Field<Varying> to(mMap, MAX_SQL_IDENTIFIER_SIZE);
Field<ISC_QUAD> desc(mMap);
curs = att->openCursor(&st, tra, 0,
"SELECT RDB$MAP_NAME, RDB$MAP_USING, RDB$MAP_PLUGIN, RDB$MAP_DB, "
" RDB$MAP_FROM_TYPE, RDB$MAP_FROM, RDB$MAP_TO_TYPE, RDB$MAP_TO "
" RDB$MAP_FROM_TYPE, RDB$MAP_FROM, RDB$MAP_TO_TYPE, RDB$MAP_TO, RDB$DESCRIPTION "
"FROM RDB$AUTH_MAPPING",
3, nullptr, nullptr, mMap.getMetadata(), nullptr, 0);
if (st->getState() & IStatus::STATE_ERRORS)
@ -1798,6 +1799,20 @@ RecordBuffer* MappingList::getList(thread_db* tdbb, jrd_rel* relation)
DumpField(f_sec_map_to, VALUE_STRING, to->len, to->data));
}
if (!desc.null)
{
RefPtr<IBlob> blb(REF_NO_INCR, att->openBlob(&st, tra, &desc, 0, nullptr));
check("IAttachment::openBlob", &st);
string buf;
const FB_SIZE_T FLD_LIMIT = MAX_COLUMN_SIZE;
unsigned length = 0;
blb->getSegment(&st, FLD_LIMIT, buf.getBuffer(FLD_LIMIT), &length);
check("IBlob::getSegment", &st);
putField(tdbb, record,
DumpField(f_sec_map_comment, VALUE_STRING, length, buf.c_str()));
}
buffer->store(record);
}
check("IResultSet::fetchNext", &st);

View File

@ -685,6 +685,7 @@ RELATION(nam_sec_global_auth_mapping, rel_global_auth_mapping, ODS_12_0, rel_vir
FIELD(f_sec_map_from, nam_sec_map_from, fld_map_from, 0, ODS_12_0)
FIELD(f_sec_map_to_type, nam_sec_map_to_type, fld_obj_type, 0, ODS_12_0)
FIELD(f_sec_map_to, nam_sec_map_to, fld_map_to, 0, ODS_12_0)
FIELD(f_sec_map_comment, nam_sec_description, fld_description, 0, ODS_13_1)
END_RELATION
// Relation 47 (RDB$DB_CREATORS)