github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/opt/props/verify.go (about) 1 // Copyright 2018 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 // +build race 12 13 package props 14 15 import ( 16 "github.com/cockroachdb/cockroach/pkg/util/log" 17 "github.com/cockroachdb/errors" 18 ) 19 20 // Verify runs consistency checks against the shared properties, in order to 21 // ensure that they conform to several invariants: 22 // 23 // 1. The properties must have been built. 24 // 2. If HasCorrelatedSubquery is true, then HasSubquery must be true as well. 25 // 3. If Mutate is true, then CanHaveSideEffects must also be true. 26 // 27 func (s *Shared) Verify() { 28 if !s.Populated { 29 panic(errors.AssertionFailedf("properties are not populated")) 30 } 31 if s.HasCorrelatedSubquery && !s.HasSubquery { 32 panic(errors.AssertionFailedf("HasSubquery cannot be false if HasCorrelatedSubquery is true")) 33 } 34 if s.CanMutate && !s.CanHaveSideEffects { 35 panic(errors.AssertionFailedf("CanHaveSideEffects cannot be false if CanMutate is true")) 36 } 37 } 38 39 // Verify runs consistency checks against the relational properties, in order to 40 // ensure that they conform to several invariants: 41 // 42 // 1. Functional dependencies are internally consistent. 43 // 2. Not null columns are a subset of output columns. 44 // 3. Outer columns do not intersect output columns. 45 // 4. If functional dependencies indicate that the relation can have at most 46 // one row, then the cardinality reflects that as well. 47 // 48 func (r *Relational) Verify() { 49 r.Shared.Verify() 50 r.FuncDeps.Verify() 51 52 if !r.NotNullCols.SubsetOf(r.OutputCols) { 53 panic(errors.AssertionFailedf("not null cols %s not a subset of output cols %s", 54 log.Safe(r.NotNullCols), log.Safe(r.OutputCols))) 55 } 56 if r.OuterCols.Intersects(r.OutputCols) { 57 panic(errors.AssertionFailedf("outer cols %s intersect output cols %s", 58 log.Safe(r.OuterCols), log.Safe(r.OutputCols))) 59 } 60 if r.FuncDeps.HasMax1Row() { 61 if r.Cardinality.Max > 1 { 62 panic(errors.AssertionFailedf( 63 "max cardinality must be <= 1 if FDs have max 1 row: %s", r.Cardinality)) 64 } 65 } 66 if r.IsAvailable(PruneCols) { 67 if !r.Rule.PruneCols.SubsetOf(r.OutputCols) { 68 panic(errors.AssertionFailedf("prune cols %s must be a subset of output cols %s", 69 log.Safe(r.Rule.PruneCols), log.Safe(r.OutputCols))) 70 } 71 } 72 } 73 74 // VerifyAgainst checks that the two properties don't contradict each other. 75 // Used for testing (e.g. to cross-check derived properties from expressions in 76 // the same group). 77 func (r *Relational) VerifyAgainst(other *Relational) { 78 if !r.OutputCols.Equals(other.OutputCols) { 79 panic(errors.AssertionFailedf("output cols mismatch: %s vs %s", log.Safe(r.OutputCols), log.Safe(other.OutputCols))) 80 } 81 82 if r.Cardinality.Max < other.Cardinality.Min || 83 r.Cardinality.Min > other.Cardinality.Max { 84 panic(errors.AssertionFailedf("cardinality mismatch: %s vs %s", log.Safe(r.Cardinality), log.Safe(other.Cardinality))) 85 } 86 87 // NotNullCols, FuncDeps are best effort, so they might differ. 88 // OuterCols, CanHaveSideEffects, and HasPlaceholder might differ if a 89 // subexpression containing them was elided. 90 } 91 92 // Verify runs consistency checks against the relational properties, in order to 93 // ensure that they conform to several invariants: 94 // 95 // 1. Functional dependencies are internally consistent. 96 // 97 func (s *Scalar) Verify() { 98 s.Shared.Verify() 99 s.FuncDeps.Verify() 100 }