extractBindVarTypes returns types based on the given query plan. This function is used to get bind var types for running our prepared tests only. A valid prepared query and execution messages must have the types defined.
(ctx *sql.Context, queryPlan sql.Node)
| 108 | // tests only. A valid prepared query and execution messages must have |
| 109 | // the types defined. |
| 110 | func extractBindVarTypes(ctx *sql.Context, queryPlan sql.Node) ([]uint32, error) { |
| 111 | inspectNode := queryPlan |
| 112 | |
| 113 | types := make(map[string]uint32) |
| 114 | var err error |
| 115 | var extractBindVars func(ctx *sql.Context, n sql.Node, expr sql.Expression) bool |
| 116 | extractBindVars = func(ctx *sql.Context, n sql.Node, expr sql.Expression) bool { |
| 117 | if err != nil { |
| 118 | return false |
| 119 | } |
| 120 | |
| 121 | switch e := expr.(type) { |
| 122 | // Subquery doesn't walk its Node child via Expressions, so we must walk it separately here |
| 123 | case *plan.Subquery: |
| 124 | transform.InspectExpressionsWithNode(ctx, e.Query, extractBindVars) |
| 125 | case *expression.BindVar: |
| 126 | var typOid uint32 |
| 127 | if doltgresType, ok := e.Type(ctx).(*pgtypes.DoltgresType); ok { |
| 128 | typOid = id.Cache().ToOID(doltgresType.ID.AsId()) |
| 129 | } else if _, ok := e.Type(ctx).(sql.DeferredType); ok { |
| 130 | // for a deferred type, we can make a guess to its type based on the containing node |
| 131 | switch n.(type) { |
| 132 | case *plan.Limit: |
| 133 | typOid = uint32(oid.T_int4) |
| 134 | case *plan.Offset: |
| 135 | typOid = uint32(oid.T_int4) |
| 136 | default: |
| 137 | typOid, err = VitessTypeToObjectID(e.Type(ctx)) |
| 138 | if err != nil { |
| 139 | err = errors.Errorf("could not determine OID for placeholder %s: %e", e.Name, err) |
| 140 | return false |
| 141 | } |
| 142 | } |
| 143 | } else { |
| 144 | // TODO: should remove usage non doltgres type |
| 145 | typOid, err = VitessTypeToObjectID(e.Type(ctx)) |
| 146 | if err != nil { |
| 147 | err = errors.Errorf("could not determine OID for placeholder %s: %e", e.Name, err) |
| 148 | return false |
| 149 | } |
| 150 | } |
| 151 | if existingOid, ok := types[e.Name]; ok { |
| 152 | err = checkCompatibleTypes(ctx, existingOid, typOid, e.Name) |
| 153 | } |
| 154 | types[e.Name] = typOid |
| 155 | case *pgexprs.ExplicitCast: |
| 156 | if bindVar, ok := e.Child().(*expression.BindVar); ok { |
| 157 | var typOid uint32 |
| 158 | if doltgresType, ok := bindVar.Type(ctx).(*pgtypes.DoltgresType); ok { |
| 159 | typOid = id.Cache().ToOID(doltgresType.ID.AsId()) |
| 160 | } else { |
| 161 | typOid, err = VitessTypeToObjectID(e.Type(ctx)) |
| 162 | if err != nil { |
| 163 | err = errors.Errorf("could not determine OID for placeholder %s: %e", bindVar.Name, err) |
| 164 | return false |
| 165 | } |
| 166 | } |
| 167 | if existingOid, ok := types[bindVar.Name]; ok { |
no test coverage detected