From 9f36dad095cef8e5c523ec3a257ac8a6a7efc29a Mon Sep 17 00:00:00 2001 From: Chengxiong Ruan Date: Tue, 20 Sep 2022 17:34:00 -0400 Subject: [PATCH] sql: add eventlog for UDF relevant statements Backport addresses #86058. Release note: None Release justification: low risk GA blocker --- docs/generated/eventlog.md | 119 +++++++++++++++ pkg/sql/alter_function.go | 65 +++++++- pkg/sql/create_function.go | 15 +- pkg/sql/drop_function.go | 12 +- pkg/sql/logictest/testdata/logic_test/udf | 101 +++++++++++++ pkg/util/log/eventpb/ddl_events.proto | 36 +++++ .../eventpb/eventlog_channels_generated.go | 15 ++ pkg/util/log/eventpb/json_encode_generated.go | 142 ++++++++++++++++++ pkg/util/log/eventpb/privilege_events.proto | 10 ++ 9 files changed, 506 insertions(+), 9 deletions(-) diff --git a/docs/generated/eventlog.md b/docs/generated/eventlog.md index 670a8a3b2e02..f3c502769681 100644 --- a/docs/generated/eventlog.md +++ b/docs/generated/eventlog.md @@ -614,6 +614,30 @@ An event of type `alter_database_survival_goal` is recorded when the survival go | `SurvivalGoal` | The new survival goal | yes | +#### Common fields + +| Field | Description | Sensitive | +|--|--|--| +| `Timestamp` | The timestamp of the event. Expressed as nanoseconds since the Unix epoch. | no | +| `EventType` | The type of the event. | no | +| `Statement` | A normalized copy of the SQL statement that triggered the event. The statement string contains a mix of sensitive and non-sensitive details (it is redactable). | partially | +| `Tag` | The statement tag. This is separate from the statement string, since the statement string can contain sensitive information. The tag is guaranteed not to. | no | +| `User` | The user account that triggered the event. The special usernames `root` and `node` are not considered sensitive. | depends | +| `DescriptorID` | The primary object descriptor affected by the operation. Set to zero for operations that don't affect descriptors. | no | +| `ApplicationName` | The application name for the session where the event was emitted. This is included in the event to ease filtering of logging output by application. | no | +| `PlaceholderValues` | The mapping of SQL placeholders to their values, for prepared statements. | yes | + +### `alter_function_options` + +An event of type `alter_function_options` is recorded when a user-defined function's options are +altered. + + +| Field | Description | Sensitive | +|--|--|--| +| `FunctionName` | Name of the affected function. | yes | + + #### Common fields | Field | Description | Sensitive | @@ -934,6 +958,30 @@ An event of type `create_database` is recorded when a database is created. | `DatabaseName` | The name of the new database. | yes | +#### Common fields + +| Field | Description | Sensitive | +|--|--|--| +| `Timestamp` | The timestamp of the event. Expressed as nanoseconds since the Unix epoch. | no | +| `EventType` | The type of the event. | no | +| `Statement` | A normalized copy of the SQL statement that triggered the event. The statement string contains a mix of sensitive and non-sensitive details (it is redactable). | partially | +| `Tag` | The statement tag. This is separate from the statement string, since the statement string can contain sensitive information. The tag is guaranteed not to. | no | +| `User` | The user account that triggered the event. The special usernames `root` and `node` are not considered sensitive. | depends | +| `DescriptorID` | The primary object descriptor affected by the operation. Set to zero for operations that don't affect descriptors. | no | +| `ApplicationName` | The application name for the session where the event was emitted. This is included in the event to ease filtering of logging output by application. | no | +| `PlaceholderValues` | The mapping of SQL placeholders to their values, for prepared statements. | yes | + +### `create_function` + +An event of type `create_function` is recorded when a user-defined function is created. + + +| Field | Description | Sensitive | +|--|--|--| +| `FunctionName` | Name of the created function. | yes | +| `IsReplace` | If the new function is a replace of an existing function. | no | + + #### Common fields | Field | Description | Sensitive | @@ -1131,6 +1179,29 @@ An event of type `drop_database` is recorded when a database is dropped. | `DroppedSchemaObjects` | The names of the schemas dropped by a cascade operation. | yes | +#### Common fields + +| Field | Description | Sensitive | +|--|--|--| +| `Timestamp` | The timestamp of the event. Expressed as nanoseconds since the Unix epoch. | no | +| `EventType` | The type of the event. | no | +| `Statement` | A normalized copy of the SQL statement that triggered the event. The statement string contains a mix of sensitive and non-sensitive details (it is redactable). | partially | +| `Tag` | The statement tag. This is separate from the statement string, since the statement string can contain sensitive information. The tag is guaranteed not to. | no | +| `User` | The user account that triggered the event. The special usernames `root` and `node` are not considered sensitive. | depends | +| `DescriptorID` | The primary object descriptor affected by the operation. Set to zero for operations that don't affect descriptors. | no | +| `ApplicationName` | The application name for the session where the event was emitted. This is included in the event to ease filtering of logging output by application. | no | +| `PlaceholderValues` | The mapping of SQL placeholders to their values, for prepared statements. | yes | + +### `drop_function` + +An event of type `drop_function` is recorded when a user-defined function is dropped. + + +| Field | Description | Sensitive | +|--|--|--| +| `FunctionName` | Name of the created function. | yes | + + #### Common fields | Field | Description | Sensitive | @@ -1356,6 +1427,30 @@ An event of type `rename_database` is recorded when a database is renamed. | `NewDatabaseName` | The new name of the affected database. | yes | +#### Common fields + +| Field | Description | Sensitive | +|--|--|--| +| `Timestamp` | The timestamp of the event. Expressed as nanoseconds since the Unix epoch. | no | +| `EventType` | The type of the event. | no | +| `Statement` | A normalized copy of the SQL statement that triggered the event. The statement string contains a mix of sensitive and non-sensitive details (it is redactable). | partially | +| `Tag` | The statement tag. This is separate from the statement string, since the statement string can contain sensitive information. The tag is guaranteed not to. | no | +| `User` | The user account that triggered the event. The special usernames `root` and `node` are not considered sensitive. | depends | +| `DescriptorID` | The primary object descriptor affected by the operation. Set to zero for operations that don't affect descriptors. | no | +| `ApplicationName` | The application name for the session where the event was emitted. This is included in the event to ease filtering of logging output by application. | no | +| `PlaceholderValues` | The mapping of SQL placeholders to their values, for prepared statements. | yes | + +### `rename_function` + +An event of type `rename_function` is recorded when a user-defined function is renamed. + + +| Field | Description | Sensitive | +|--|--|--| +| `FunctionName` | The old name of the affected function. | yes | +| `NewFunctionName` | The new name of the affected function. | yes | + + #### Common fields | Field | Description | Sensitive | @@ -1699,6 +1794,30 @@ An event of type `alter_default_privileges` is recorded when default privileges | `GrantedPrivileges` | The privileges being granted to the grantee. | no | | `RevokedPrivileges` | The privileges being revoked from the grantee. | no | +### `alter_function_owner` + +AlterTableOwner is recorded when the owner of a user-defined function is changed. + + +| Field | Description | Sensitive | +|--|--|--| +| `FunctionName` | The name of the affected user-defined function. | yes | +| `Owner` | The name of the new owner. | yes | + + +#### Common fields + +| Field | Description | Sensitive | +|--|--|--| +| `Timestamp` | The timestamp of the event. Expressed as nanoseconds since the Unix epoch. | no | +| `EventType` | The type of the event. | no | +| `Statement` | A normalized copy of the SQL statement that triggered the event. The statement string contains a mix of sensitive and non-sensitive details (it is redactable). | partially | +| `Tag` | The statement tag. This is separate from the statement string, since the statement string can contain sensitive information. The tag is guaranteed not to. | no | +| `User` | The user account that triggered the event. The special usernames `root` and `node` are not considered sensitive. | depends | +| `DescriptorID` | The primary object descriptor affected by the operation. Set to zero for operations that don't affect descriptors. | no | +| `ApplicationName` | The application name for the session where the event was emitted. This is included in the event to ease filtering of logging output by application. | no | +| `PlaceholderValues` | The mapping of SQL placeholders to their values, for prepared statements. | yes | + ### `alter_schema_owner` An event of type `alter_schema_owner` is recorded when a schema's owner is changed. diff --git a/pkg/sql/alter_function.go b/pkg/sql/alter_function.go index 21be2ea71c9e..525359ed3791 100644 --- a/pkg/sql/alter_function.go +++ b/pkg/sql/alter_function.go @@ -24,6 +24,7 @@ import ( "github.com/cockroachdb/cockroach/pkg/sql/sem/tree" "github.com/cockroachdb/cockroach/pkg/sql/types" "github.com/cockroachdb/cockroach/pkg/util/errorutil/unimplemented" + "github.com/cockroachdb/cockroach/pkg/util/log/eventpb" ) type alterFunctionOptionsNode struct { @@ -86,7 +87,18 @@ func (n *alterFunctionOptionsNode) startExec(params runParams) error { return err } - return params.p.writeFuncSchemaChange(params.ctx, fnDesc) + if err := params.p.writeFuncSchemaChange(params.ctx, fnDesc); err != nil { + return err + } + + fnName, err := params.p.getQualifiedFunctionName(params.ctx, fnDesc) + if err != nil { + return err + } + event := eventpb.AlterFunctionOptions{ + FunctionName: fnName.FQString(), + } + return params.p.logEvent(params.ctx, fnDesc.GetID(), &event) } func (n *alterFunctionOptionsNode) Next(params runParams) (bool, error) { return false, nil } @@ -116,6 +128,10 @@ func (n *alterFunctionRenameNode) startExec(params runParams) error { if err != nil { return err } + oldFnName, err := params.p.getQualifiedFunctionName(params.ctx, fnDesc) + if err != nil { + return err + } scDesc, err := params.p.Descriptors().GetMutableSchemaByID( params.ctx, params.p.txn, fnDesc.GetParentSchemaID(), tree.SchemaLookupFlags{Required: true}, @@ -145,7 +161,19 @@ func (n *alterFunctionRenameNode) startExec(params runParams) error { return err } - return params.p.writeSchemaDescChange(params.ctx, scDesc, "alter function name") + if err := params.p.writeSchemaDescChange(params.ctx, scDesc, "alter function name"); err != nil { + return err + } + + newFnName, err := params.p.getQualifiedFunctionName(params.ctx, fnDesc) + if err != nil { + return err + } + event := eventpb.RenameFunction{ + FunctionName: oldFnName.FQString(), + NewFunctionName: newFnName.FQString(), + } + return params.p.logEvent(params.ctx, fnDesc.GetID(), &event) } func (n *alterFunctionRenameNode) Next(params runParams) (bool, error) { return false, nil } @@ -193,7 +221,19 @@ func (n *alterFunctionSetOwnerNode) startExec(params runParams) error { } fnDesc.GetPrivileges().SetOwner(newOwner) - return params.p.writeFuncSchemaChange(params.ctx, fnDesc) + if err := params.p.writeFuncSchemaChange(params.ctx, fnDesc); err != nil { + return err + } + + fnName, err := params.p.getQualifiedFunctionName(params.ctx, fnDesc) + if err != nil { + return err + } + event := eventpb.AlterFunctionOwner{ + FunctionName: fnName.FQString(), + Owner: newOwner.Normalized(), + } + return params.p.logEvent(params.ctx, fnDesc.GetID(), &event) } func (n *alterFunctionSetOwnerNode) Next(params runParams) (bool, error) { return false, nil } @@ -223,6 +263,10 @@ func (n *alterFunctionSetSchemaNode) startExec(params runParams) error { if err != nil { return err } + oldFnName, err := params.p.getQualifiedFunctionName(params.ctx, fnDesc) + if err != nil { + return err + } // Functions cannot be resolved across db, so just use current db name to get // the descriptor. db, err := params.p.Descriptors().GetMutableDatabaseByName( @@ -298,7 +342,20 @@ func (n *alterFunctionSetSchemaNode) startExec(params runParams) error { return err } fnDesc.SetParentSchemaID(targetSc.GetID()) - return params.p.writeFuncSchemaChange(params.ctx, fnDesc) + if err := params.p.writeFuncSchemaChange(params.ctx, fnDesc); err != nil { + return err + } + + newFnName, err := params.p.getQualifiedFunctionName(params.ctx, fnDesc) + if err != nil { + return err + } + event := eventpb.SetSchema{ + DescriptorName: oldFnName.FQString(), + NewDescriptorName: newFnName.FQString(), + DescriptorType: string(fnDesc.DescriptorType()), + } + return params.p.logEvent(params.ctx, fnDesc.GetID(), &event) } func (n *alterFunctionSetSchemaNode) Next(params runParams) (bool, error) { return false, nil } diff --git a/pkg/sql/create_function.go b/pkg/sql/create_function.go index 21b06df1e1c0..048da1f16080 100644 --- a/pkg/sql/create_function.go +++ b/pkg/sql/create_function.go @@ -30,6 +30,7 @@ import ( "github.com/cockroachdb/cockroach/pkg/sql/sem/tree" "github.com/cockroachdb/cockroach/pkg/sql/types" "github.com/cockroachdb/cockroach/pkg/util/errorutil/unimplemented" + "github.com/cockroachdb/cockroach/pkg/util/log/eventpb" ) type createFunctionNode struct { @@ -81,10 +82,20 @@ func (n *createFunctionNode) startExec(params runParams) error { return err } + fnName := tree.MakeQualifiedFunctionName(n.dbDesc.GetName(), n.scDesc.GetName(), n.cf.FuncName.String()) + event := eventpb.CreateFunction{ + FunctionName: fnName.FQString(), + IsReplace: !isNew, + } if isNew { - return n.createNewFunction(udfMutableDesc, mutScDesc, params) + err = n.createNewFunction(udfMutableDesc, mutScDesc, params) + } else { + err = n.replaceFunction(udfMutableDesc, params) + } + if err != nil { + return err } - return n.replaceFunction(udfMutableDesc, params) + return params.p.logEvent(params.ctx, udfMutableDesc.GetID(), &event) }() }) diff --git a/pkg/sql/drop_function.go b/pkg/sql/drop_function.go index 3f726044fb5d..60f0c7e96e49 100644 --- a/pkg/sql/drop_function.go +++ b/pkg/sql/drop_function.go @@ -22,6 +22,7 @@ import ( "github.com/cockroachdb/cockroach/pkg/sql/sem/tree" "github.com/cockroachdb/cockroach/pkg/util" "github.com/cockroachdb/cockroach/pkg/util/errorutil/unimplemented" + "github.com/cockroachdb/cockroach/pkg/util/log/eventpb" "github.com/cockroachdb/errors" ) @@ -126,8 +127,8 @@ func (p *planner) matchUDF( } if !ol.IsUDF { return nil, errors.Errorf( - "cannot drop function %s because it is required by the database system", - ol.Signature(true /*Simplify*/), + "cannot drop function %s%s because it is required by the database system", + fnDef.Name, ol.Signature(true /*Simplify*/), ) } return &ol, nil @@ -229,7 +230,12 @@ func (p *planner) dropFunctionImpl(ctx context.Context, fnMutable *funcdesc.Muta // Mark the UDF as dropped. fnMutable.SetDropped() - return p.writeFuncSchemaChange(ctx, fnMutable) + if err := p.writeFuncSchemaChange(ctx, fnMutable); err != nil { + return err + } + fnName := tree.MakeQualifiedFunctionName(p.CurrentDatabase(), scDesc.GetName(), fnMutable.GetName()) + event := eventpb.DropFunction{FunctionName: fnName.FQString()} + return p.logEvent(ctx, fnMutable.GetID(), &event) } func (p *planner) writeFuncDesc(ctx context.Context, funcDesc *funcdesc.Mutable) error { diff --git a/pkg/sql/logictest/testdata/logic_test/udf b/pkg/sql/logictest/testdata/logic_test/udf index 488bbe0eff4a..cd32bbe5143c 100644 --- a/pkg/sql/logictest/testdata/logic_test/udf +++ b/pkg/sql/logictest/testdata/logic_test/udf @@ -1500,6 +1500,107 @@ SELECT f() statement ok SET DATABASE = test; +subtest event_logging + +statement ok +CREATE USER u_test_event; +CREATE SCHEMA sc_test_event; +DELETE FROM system.eventlog; + +statement ok +CREATE FUNCTION f_test_log() RETURNS INT LANGUAGE SQL AS $$ SELECT 1 $$; + +query TTTT retry +WITH tmp AS ( + SELECT "eventType" AS etype, info::JSONB AS info_json + FROM system.eventlog + WHERE "eventType" = 'create_function' +) +SELECT etype, info_json->'DescriptorID', info_json->'FunctionName', info_json->'Statement' FROM tmp; +---- +create_function 203 "test.public.f_test_log" "CREATE FUNCTION test.public.f_test_log()\n\tRETURNS INT8\n\tLANGUAGE SQL\n\tAS $$SELECT 1;$$" + +statement ok +CREATE OR REPLACE FUNCTION f_test_log() RETURNS INT LANGUAGE SQL AS $$ SELECT 2 $$; + +query TTTT retry +WITH tmp AS ( + SELECT "eventType" AS etype, info::JSONB AS info_json + FROM system.eventlog + WHERE "eventType" = 'create_function' +) +SELECT etype, info_json->'DescriptorID', info_json->'FunctionName', info_json->'Statement' FROM tmp; +---- +create_function 203 "test.public.f_test_log" "CREATE FUNCTION test.public.f_test_log()\n\tRETURNS INT8\n\tLANGUAGE SQL\n\tAS $$SELECT 1;$$" +create_function 203 "test.public.f_test_log" "CREATE OR REPLACE FUNCTION test.public.f_test_log()\n\tRETURNS INT8\n\tLANGUAGE SQL\n\tAS $$SELECT 2;$$" + +statement ok +ALTER FUNCTION f_test_log RENAME TO f_test_log_new; + +query TTTTT retry +WITH tmp AS ( + SELECT "eventType" AS etype, info::JSONB AS info_json + FROM system.eventlog + WHERE "eventType" = 'rename_function' +) +SELECT etype, info_json->'DescriptorID', info_json->'FunctionName', info_json->'NewFunctionName', info_json->'Statement' FROM tmp; +---- +rename_function 203 "test.public.f_test_log" "test.public.f_test_log_new" "ALTER FUNCTION \"\".\"\".f_test_log RENAME TO f_test_log_new" + +statement ok +ALTER FUNCTION f_test_log_new RENAME TO f_test_log; + +statement ok +ALTER FUNCTION f_test_log OWNER TO u_test_event; + +query TTTTT retry +WITH tmp AS ( + SELECT "eventType" AS etype, info::JSONB AS info_json + FROM system.eventlog + WHERE "eventType" = 'alter_function_owner' +) +SELECT etype, info_json->'DescriptorID', info_json->'FunctionName', info_json->'Owner', info_json->'Statement' FROM tmp; +---- +alter_function_owner 203 "test.public.f_test_log" "u_test_event" "ALTER FUNCTION \"\".\"\".f_test_log OWNER TO u_test_event" + +statement ok +ALTER FUNCTION f_test_log SET SCHEMA sc_test_event; + +query TTTTT retry +WITH tmp AS ( + SELECT "eventType" AS etype, info::JSONB AS info_json + FROM system.eventlog + WHERE "eventType" = 'set_schema' +) +SELECT etype, info_json->'DescriptorID', info_json->'DescriptorName', info_json->'NewDescriptorName', info_json->'Statement' FROM tmp; +---- +set_schema 203 "test.public.f_test_log" "test.sc_test_event.f_test_log" "ALTER FUNCTION \"\".\"\".f_test_log SET SCHEMA sc_test_event" + +statement ok +ALTER FUNCTION sc_test_event.f_test_log SET SCHEMA public; +ALTER FUNCTION f_test_log IMMUTABLE; +DROP FUNCTION f_test_log; + +query TTTT retry +WITH tmp AS ( + SELECT "eventType" AS etype, info::JSONB AS info_json + FROM system.eventlog + WHERE "eventType" = 'alter_function_options' +) +SELECT etype, info_json->'DescriptorID', info_json->'FunctionName', info_json->'Statement' FROM tmp; +---- +alter_function_options 203 "test.public.f_test_log" "ALTER FUNCTION \"\".\"\".f_test_log IMMUTABLE" + +query TTTT retry +WITH tmp AS ( + SELECT "eventType" AS etype, info::JSONB AS info_json + FROM system.eventlog + WHERE "eventType" = 'drop_function' +) +SELECT etype, info_json->'DescriptorID', info_json->'FunctionName', info_json->'Statement' FROM tmp; +---- +drop_function 203 "test.public.f_test_log" "DROP FUNCTION \"\".\"\".f_test_log" + subtest execution statement ok diff --git a/pkg/util/log/eventpb/ddl_events.proto b/pkg/util/log/eventpb/ddl_events.proto index 1ae8439745ad..9eeeb46f000f 100644 --- a/pkg/util/log/eventpb/ddl_events.proto +++ b/pkg/util/log/eventpb/ddl_events.proto @@ -560,3 +560,39 @@ message AlterDatabaseSetZoneConfigExtension { CommonZoneConfigDetails config = 3 [(gogoproto.nullable) = false, (gogoproto.jsontag) = "", (gogoproto.embed) = true]; } +// CreateFunction is recorded when a user-defined function is created. +message CreateFunction { + CommonEventDetails common = 1 [(gogoproto.nullable) = false, (gogoproto.jsontag) = "", (gogoproto.embed) = true]; + CommonSQLEventDetails sql = 2 [(gogoproto.nullable) = false, (gogoproto.jsontag) = "", (gogoproto.embed) = true]; + // Name of the created function. + string function_name = 3 [(gogoproto.jsontag) = ",omitempty"]; + // If the new function is a replace of an existing function. + bool is_replace = 4 [(gogoproto.jsontag) = ",omitempty"]; +} + +// DropFunction is recorded when a user-defined function is dropped. +message DropFunction { + CommonEventDetails common = 1 [(gogoproto.nullable) = false, (gogoproto.jsontag) = "", (gogoproto.embed) = true]; + CommonSQLEventDetails sql = 2 [(gogoproto.nullable) = false, (gogoproto.jsontag) = "", (gogoproto.embed) = true]; + // Name of the created function. + string function_name = 3 [(gogoproto.jsontag) = ",omitempty"]; +} + +// RenameFunction is recorded when a user-defined function is renamed. +message RenameFunction { + CommonEventDetails common = 1 [(gogoproto.nullable) = false, (gogoproto.jsontag) = "", (gogoproto.embed) = true]; + CommonSQLEventDetails sql = 2 [(gogoproto.nullable) = false, (gogoproto.jsontag) = "", (gogoproto.embed) = true]; + // The old name of the affected function. + string function_name = 3 [(gogoproto.jsontag) = ",omitempty"]; + // The new name of the affected function. + string new_function_name = 4 [(gogoproto.jsontag) = ",omitempty"]; +} + +// AlterFunctionOptions is recorded when a user-defined function's options are +// altered. +message AlterFunctionOptions { + CommonEventDetails common = 1 [(gogoproto.nullable) = false, (gogoproto.jsontag) = "", (gogoproto.embed) = true]; + CommonSQLEventDetails sql = 2 [(gogoproto.nullable) = false, (gogoproto.jsontag) = "", (gogoproto.embed) = true]; + // Name of the affected function. + string function_name = 3 [(gogoproto.jsontag) = ",omitempty"]; +} diff --git a/pkg/util/log/eventpb/eventlog_channels_generated.go b/pkg/util/log/eventpb/eventlog_channels_generated.go index 3e6ae8996aa8..5c63f78204dc 100644 --- a/pkg/util/log/eventpb/eventlog_channels_generated.go +++ b/pkg/util/log/eventpb/eventlog_channels_generated.go @@ -72,6 +72,9 @@ func (m *AlterDatabaseSetZoneConfigExtension) LoggingChannel() logpb.Channel { // LoggingChannel implements the EventPayload interface. func (m *AlterDatabaseSurvivalGoal) LoggingChannel() logpb.Channel { return logpb.Channel_SQL_SCHEMA } +// LoggingChannel implements the EventPayload interface. +func (m *AlterFunctionOptions) LoggingChannel() logpb.Channel { return logpb.Channel_SQL_SCHEMA } + // LoggingChannel implements the EventPayload interface. func (m *AlterIndex) LoggingChannel() logpb.Channel { return logpb.Channel_SQL_SCHEMA } @@ -111,6 +114,9 @@ func (m *ConvertToSchema) LoggingChannel() logpb.Channel { return logpb.Channel_ // LoggingChannel implements the EventPayload interface. func (m *CreateDatabase) LoggingChannel() logpb.Channel { return logpb.Channel_SQL_SCHEMA } +// LoggingChannel implements the EventPayload interface. +func (m *CreateFunction) LoggingChannel() logpb.Channel { return logpb.Channel_SQL_SCHEMA } + // LoggingChannel implements the EventPayload interface. func (m *CreateIndex) LoggingChannel() logpb.Channel { return logpb.Channel_SQL_SCHEMA } @@ -135,6 +141,9 @@ func (m *CreateView) LoggingChannel() logpb.Channel { return logpb.Channel_SQL_S // LoggingChannel implements the EventPayload interface. func (m *DropDatabase) LoggingChannel() logpb.Channel { return logpb.Channel_SQL_SCHEMA } +// LoggingChannel implements the EventPayload interface. +func (m *DropFunction) LoggingChannel() logpb.Channel { return logpb.Channel_SQL_SCHEMA } + // LoggingChannel implements the EventPayload interface. func (m *DropIndex) LoggingChannel() logpb.Channel { return logpb.Channel_SQL_SCHEMA } @@ -165,6 +174,9 @@ func (m *ForceDeleteTableDataEntry) LoggingChannel() logpb.Channel { return logp // LoggingChannel implements the EventPayload interface. func (m *RenameDatabase) LoggingChannel() logpb.Channel { return logpb.Channel_SQL_SCHEMA } +// LoggingChannel implements the EventPayload interface. +func (m *RenameFunction) LoggingChannel() logpb.Channel { return logpb.Channel_SQL_SCHEMA } + // LoggingChannel implements the EventPayload interface. func (m *RenameSchema) LoggingChannel() logpb.Channel { return logpb.Channel_SQL_SCHEMA } @@ -201,6 +213,9 @@ func (m *AlterDatabaseOwner) LoggingChannel() logpb.Channel { return logpb.Chann // LoggingChannel implements the EventPayload interface. func (m *AlterDefaultPrivileges) LoggingChannel() logpb.Channel { return logpb.Channel_PRIVILEGES } +// LoggingChannel implements the EventPayload interface. +func (m *AlterFunctionOwner) LoggingChannel() logpb.Channel { return logpb.Channel_PRIVILEGES } + // LoggingChannel implements the EventPayload interface. func (m *AlterSchemaOwner) LoggingChannel() logpb.Channel { return logpb.Channel_PRIVILEGES } diff --git a/pkg/util/log/eventpb/json_encode_generated.go b/pkg/util/log/eventpb/json_encode_generated.go index 46b5057e4f21..0b29f208e3da 100644 --- a/pkg/util/log/eventpb/json_encode_generated.go +++ b/pkg/util/log/eventpb/json_encode_generated.go @@ -299,6 +299,62 @@ func (m *AlterDefaultPrivileges) AppendJSONFields(printComma bool, b redact.Reda return printComma, b } +// AppendJSONFields implements the EventPayload interface. +func (m *AlterFunctionOptions) AppendJSONFields(printComma bool, b redact.RedactableBytes) (bool, redact.RedactableBytes) { + + printComma, b = m.CommonEventDetails.AppendJSONFields(printComma, b) + + printComma, b = m.CommonSQLEventDetails.AppendJSONFields(printComma, b) + + if m.FunctionName != "" { + if printComma { + b = append(b, ',') + } + printComma = true + b = append(b, "\"FunctionName\":\""...) + b = append(b, redact.StartMarker()...) + b = redact.RedactableBytes(jsonbytes.EncodeString([]byte(b), string(redact.EscapeMarkers([]byte(m.FunctionName))))) + b = append(b, redact.EndMarker()...) + b = append(b, '"') + } + + return printComma, b +} + +// AppendJSONFields implements the EventPayload interface. +func (m *AlterFunctionOwner) AppendJSONFields(printComma bool, b redact.RedactableBytes) (bool, redact.RedactableBytes) { + + printComma, b = m.CommonEventDetails.AppendJSONFields(printComma, b) + + printComma, b = m.CommonSQLEventDetails.AppendJSONFields(printComma, b) + + if m.FunctionName != "" { + if printComma { + b = append(b, ',') + } + printComma = true + b = append(b, "\"FunctionName\":\""...) + b = append(b, redact.StartMarker()...) + b = redact.RedactableBytes(jsonbytes.EncodeString([]byte(b), string(redact.EscapeMarkers([]byte(m.FunctionName))))) + b = append(b, redact.EndMarker()...) + b = append(b, '"') + } + + if m.Owner != "" { + if printComma { + b = append(b, ',') + } + printComma = true + b = append(b, "\"Owner\":\""...) + b = append(b, redact.StartMarker()...) + b = redact.RedactableBytes(jsonbytes.EncodeString([]byte(b), string(redact.EscapeMarkers([]byte(m.Owner))))) + b = append(b, redact.EndMarker()...) + b = append(b, '"') + } + + return printComma, b +} + // AppendJSONFields implements the EventPayload interface. func (m *AlterIndex) AppendJSONFields(printComma bool, b redact.RedactableBytes) (bool, redact.RedactableBytes) { @@ -2109,6 +2165,36 @@ func (m *CreateDatabase) AppendJSONFields(printComma bool, b redact.RedactableBy return printComma, b } +// AppendJSONFields implements the EventPayload interface. +func (m *CreateFunction) AppendJSONFields(printComma bool, b redact.RedactableBytes) (bool, redact.RedactableBytes) { + + printComma, b = m.CommonEventDetails.AppendJSONFields(printComma, b) + + printComma, b = m.CommonSQLEventDetails.AppendJSONFields(printComma, b) + + if m.FunctionName != "" { + if printComma { + b = append(b, ',') + } + printComma = true + b = append(b, "\"FunctionName\":\""...) + b = append(b, redact.StartMarker()...) + b = redact.RedactableBytes(jsonbytes.EncodeString([]byte(b), string(redact.EscapeMarkers([]byte(m.FunctionName))))) + b = append(b, redact.EndMarker()...) + b = append(b, '"') + } + + if m.IsReplace { + if printComma { + b = append(b, ',') + } + printComma = true + b = append(b, "\"IsReplace\":true"...) + } + + return printComma, b +} + // AppendJSONFields implements the EventPayload interface. func (m *CreateIndex) AppendJSONFields(printComma bool, b redact.RedactableBytes) (bool, redact.RedactableBytes) { @@ -2511,6 +2597,28 @@ func (m *DropDatabase) AppendJSONFields(printComma bool, b redact.RedactableByte return printComma, b } +// AppendJSONFields implements the EventPayload interface. +func (m *DropFunction) AppendJSONFields(printComma bool, b redact.RedactableBytes) (bool, redact.RedactableBytes) { + + printComma, b = m.CommonEventDetails.AppendJSONFields(printComma, b) + + printComma, b = m.CommonSQLEventDetails.AppendJSONFields(printComma, b) + + if m.FunctionName != "" { + if printComma { + b = append(b, ',') + } + printComma = true + b = append(b, "\"FunctionName\":\""...) + b = append(b, redact.StartMarker()...) + b = redact.RedactableBytes(jsonbytes.EncodeString([]byte(b), string(redact.EscapeMarkers([]byte(m.FunctionName))))) + b = append(b, redact.EndMarker()...) + b = append(b, '"') + } + + return printComma, b +} + // AppendJSONFields implements the EventPayload interface. func (m *DropIndex) AppendJSONFields(printComma bool, b redact.RedactableBytes) (bool, redact.RedactableBytes) { @@ -3272,6 +3380,40 @@ func (m *RenameDatabase) AppendJSONFields(printComma bool, b redact.RedactableBy return printComma, b } +// AppendJSONFields implements the EventPayload interface. +func (m *RenameFunction) AppendJSONFields(printComma bool, b redact.RedactableBytes) (bool, redact.RedactableBytes) { + + printComma, b = m.CommonEventDetails.AppendJSONFields(printComma, b) + + printComma, b = m.CommonSQLEventDetails.AppendJSONFields(printComma, b) + + if m.FunctionName != "" { + if printComma { + b = append(b, ',') + } + printComma = true + b = append(b, "\"FunctionName\":\""...) + b = append(b, redact.StartMarker()...) + b = redact.RedactableBytes(jsonbytes.EncodeString([]byte(b), string(redact.EscapeMarkers([]byte(m.FunctionName))))) + b = append(b, redact.EndMarker()...) + b = append(b, '"') + } + + if m.NewFunctionName != "" { + if printComma { + b = append(b, ',') + } + printComma = true + b = append(b, "\"NewFunctionName\":\""...) + b = append(b, redact.StartMarker()...) + b = redact.RedactableBytes(jsonbytes.EncodeString([]byte(b), string(redact.EscapeMarkers([]byte(m.NewFunctionName))))) + b = append(b, redact.EndMarker()...) + b = append(b, '"') + } + + return printComma, b +} + // AppendJSONFields implements the EventPayload interface. func (m *RenameSchema) AppendJSONFields(printComma bool, b redact.RedactableBytes) (bool, redact.RedactableBytes) { diff --git a/pkg/util/log/eventpb/privilege_events.proto b/pkg/util/log/eventpb/privilege_events.proto index 30bacfe7c503..3e7ee64a9b63 100644 --- a/pkg/util/log/eventpb/privilege_events.proto +++ b/pkg/util/log/eventpb/privilege_events.proto @@ -132,6 +132,16 @@ message AlterTableOwner { string owner = 4 [(gogoproto.jsontag) = ",omitempty"]; } +// AlterTableOwner is recorded when the owner of a user-defined function is changed. +message AlterFunctionOwner { + CommonEventDetails common = 1 [(gogoproto.nullable) = false, (gogoproto.jsontag) = "", (gogoproto.embed) = true]; + CommonSQLEventDetails sql = 2 [(gogoproto.nullable) = false, (gogoproto.jsontag) = "", (gogoproto.embed) = true]; + // The name of the affected user-defined function. + string function_name = 3 [(gogoproto.jsontag) = ",omitempty"]; + // The name of the new owner. + string owner = 5 [(gogoproto.jsontag) = ",omitempty"]; +} + // AlterDefaultPrivileges is recorded when default privileges are changed. message AlterDefaultPrivileges { CommonEventDetails common = 1 [(gogoproto.nullable) = false, (gogoproto.jsontag) = "", (gogoproto.embed) = true];