Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions enginetest/queries/trigger_queries.go
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,50 @@ create trigger insert_into_a
after insert on a
for each row replace into c
select d.x+2, 0 from d join b using (x)
where d.x = new.x`,
"insert into a (x,z) values (2,2)",
},
Query: "select x, y from c order by 1",
Expected: []sql.Row{
{4, 0},
},
},
{
Name: "trigger insert projection group by index error",
SetUpScript: []string{
"create table a (x int primary key, y int default 1, z int)",
"create table b (x int primary key)",
"create table c (x int primary key, y tinyint)",
"create table d (x int primary key)",
"insert into b values (1), (2)",
"insert into d values (1), (2)",
`
create trigger insert_into_a
after insert on a
for each row replace into c
select max(d.x + new.x), 0 from d join b using (x)
where d.x = new.x`,
"insert into a (x,z) values (2,2)",
},
Query: "select x, y from c order by 1",
Expected: []sql.Row{
{4, 0},
},
},
{
Name: "trigger insert projection window index error",
SetUpScript: []string{
"create table a (x int primary key, y int default 1, z int)",
"create table b (x int primary key)",
"create table c (x int primary key, y tinyint)",
"create table d (x int primary key)",
"insert into b values (1), (2)",
"insert into d values (1), (2)",
`
create trigger insert_into_a
after insert on a
for each row replace into c
select first_value(d.x + new.x) over (partition by (x) order by x), 0 from d join b using (x)
where d.x = new.x`,
"insert into a (x,z) values (2,2)",
},
Expand Down
43 changes: 42 additions & 1 deletion sql/analyzer/fix_exec_indexes.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ func assignExecIndexes(ctx *sql.Context, a *Analyzer, n sql.Node, scope *plan.Sc
if !scope.IsEmpty() {
// triggers
s.triggerScope = true
s.insertSourceScope = scope.InInsertSource()
s.addSchema(scope.Schema())
s = s.push()
}
Expand Down Expand Up @@ -161,7 +162,33 @@ type idxScope struct {
children []sql.Node
expressions []sql.Expression
checks sql.CheckConstraints
triggerScope bool

triggerScope bool
insertSourceScope bool
}

func (s *idxScope) inTrigger() bool {
if s == nil {
return false
}
for _, ps := range s.parentScopes {
if ps.inTrigger() {
return true
}
}
return s.triggerScope
}

func (s *idxScope) inInsertSource() bool {
if s == nil {
return false
}
for _, ps := range s.parentScopes {
if ps.inInsertSource() {
return true
}
}
return s.insertSourceScope
}

func (s *idxScope) addSchema(sch sql.Schema) {
Expand Down Expand Up @@ -535,6 +562,20 @@ func (s *idxScope) visitSelf(n sql.Node) error {
n.DestSch[colIdx].Default = newDef.(*sql.ColumnDefaultValue)
}
default:
// Group By and Window functions already account for the new/old columns present from triggers
// This means that when indexing the Projections, we should not include the trigger scope(s), which are
// within s.parentScopes.
if proj, isProj := n.(*plan.Project); isProj {
switch proj.Child.(type) {
case *plan.GroupBy, *plan.Window:
if s.inTrigger() && s.inInsertSource() {
for _, e := range proj.Expressions() {
s.expressions = append(s.expressions, fixExprToScope(e, s.childScopes...))
}
return nil
}
}
}
if ne, ok := n.(sql.Expressioner); ok {
scope := append(s.parentScopes, s.childScopes...)
for _, e := range ne.Expressions() {
Expand Down
6 changes: 4 additions & 2 deletions sql/analyzer/inserts.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ import (
func resolveInsertRows(ctx *sql.Context, a *Analyzer, n sql.Node, scope *plan.Scope, sel RuleSelector, qFlags *sql.QueryFlags) (sql.Node, transform.TreeIdentity, error) {
if _, ok := n.(*plan.TriggerExecutor); ok {
return n, transform.SameTree, nil
} else if _, ok := n.(*plan.CreateProcedure); ok {
}
if _, ok := n.(*plan.CreateProcedure); ok {
return n, transform.SameTree, nil
}
// We capture all INSERTs along the tree, such as those inside of block statements.
Expand All @@ -50,14 +51,15 @@ func resolveInsertRows(ctx *sql.Context, a *Analyzer, n sql.Node, scope *plan.Sc

source := insert.Source
// TriggerExecutor has already been analyzed
if _, ok := insert.Source.(*plan.TriggerExecutor); !ok && !insert.LiteralValueSource {
if _, isTrigExec := insert.Source.(*plan.TriggerExecutor); !isTrigExec && !insert.LiteralValueSource {
// Analyze the source of the insert independently
if _, ok := insert.Source.(*plan.Values); ok {
scope = scope.NewScope(plan.NewProject(
expression.SchemaToGetFields(insert.Source.Schema()[:len(insert.ColumnNames)], sql.ColSet{}),
plan.NewSubqueryAlias("dummy", "", insert.Source),
))
}
scope.SetInInsertSource(true)
source, _, err = a.analyzeWithSelector(ctx, insert.Source, scope, SelectAllBatches, newInsertSourceSelector(sel), qFlags)
if err != nil {
return nil, transform.SameTree, err
Expand Down
45 changes: 26 additions & 19 deletions sql/plan/scope.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,20 +44,8 @@ type Scope struct {
inLateralJoin bool
joinSiblings []sql.Node
JoinTrees []string
}

func (s *Scope) SetJoin(b bool) {
if s == nil {
return
}
s.inJoin = b
}

func (s *Scope) SetLateralJoin(b bool) {
if s == nil {
return
}
s.inLateralJoin = b
inInsertSource bool
}

func (s *Scope) IsEmpty() bool {
Expand Down Expand Up @@ -318,18 +306,37 @@ func (s *Scope) Schema() sql.Schema {
return schema
}

func (s *Scope) InJoin() bool {
func (s *Scope) SetJoin(b bool) {
if s == nil {
return
}
s.inJoin = b
}

func (s *Scope) SetLateralJoin(b bool) {
if s == nil {
return false
return
}
return s.inJoin
s.inLateralJoin = b
}

func (s *Scope) InLateralJoin() bool {
func (s *Scope) SetInInsertSource(b bool) {
if s == nil {
return false
return
}
return s.inLateralJoin
s.inInsertSource = b
}

func (s *Scope) InJoin() bool {
return s != nil && s.inJoin
}

func (s *Scope) InLateralJoin() bool {
return s != nil && s.inLateralJoin
}

func (s *Scope) InInsertSource() bool {
return s != nil && s.inInsertSource
}

func (s *Scope) JoinSiblings() []sql.Node {
Expand Down
1 change: 1 addition & 0 deletions sql/rowexec/show.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ func (b *BaseBuilder) buildDescribeQuery(ctx *sql.Context, n *plan.DescribeQuery
var rows []sql.Row
if n.Format.Plan {
formatString := sql.Describe(n.Child, n.Format)
formatString = strings.Replace(formatString, "\r", "", -1)
for _, l := range strings.Split(formatString, "\n") {
if strings.TrimSpace(l) != "" {
rows = append(rows, sql.NewRow(l))
Expand Down