typeCheckSameTypedTupleExprs type checks a list of expressions, asserting that all are tuples which have the same type or nulls. The function expects the first provided expression to be a tuple, and will panic if it is not. However, it does not expect all other expressions are tuples or nulls, and w
( ctx context.Context, semaCtx *SemaContext, desired *types.T, exprs ...Expr, )
| 2265 | // provided, which will hint that type which the expressions should resolve to, |
| 2266 | // if possible. |
| 2267 | func typeCheckSameTypedTupleExprs( |
| 2268 | ctx context.Context, semaCtx *SemaContext, desired *types.T, exprs ...Expr, |
| 2269 | ) ([]TypedExpr, *types.T, error) { |
| 2270 | // Hold the resolved type expressions of the provided exprs, in order. |
| 2271 | // TODO(nvanbenschoten): Look into reducing allocations here. |
| 2272 | typedExprs := make([]TypedExpr, len(exprs)) |
| 2273 | |
| 2274 | // All other exprs must be tuples. |
| 2275 | first := exprs[0].(*Tuple) |
| 2276 | if err := checkAllExprsAreTuplesOrNulls(ctx, semaCtx, exprs[1:]); err != nil { |
| 2277 | return nil, nil, err |
| 2278 | } |
| 2279 | |
| 2280 | // All tuples must have the same length. |
| 2281 | firstLen := len(first.Exprs) |
| 2282 | if err := checkAllTuplesHaveLength(exprs[1:], firstLen); err != nil { |
| 2283 | return nil, nil, err |
| 2284 | } |
| 2285 | |
| 2286 | // All expressions within tuples at the same indexes must be the same type. |
| 2287 | resTypes := types.MakeTuple(make([]*types.T, firstLen)) |
| 2288 | sameTypeExprs := make([]Expr, 0, len(exprs)) |
| 2289 | // We will be skipping nulls, so we need to keep track at which indices in |
| 2290 | // exprs are the non-null tuples. |
| 2291 | sameTypeExprsIndices := make([]int, 0, len(exprs)) |
| 2292 | for elemIdx := range first.Exprs { |
| 2293 | sameTypeExprs = sameTypeExprs[:0] |
| 2294 | sameTypeExprsIndices = sameTypeExprsIndices[:0] |
| 2295 | for exprIdx, expr := range exprs { |
| 2296 | if expr == DNull { |
| 2297 | continue |
| 2298 | } |
| 2299 | sameTypeExprs = append(sameTypeExprs, expr.(*Tuple).Exprs[elemIdx]) |
| 2300 | sameTypeExprsIndices = append(sameTypeExprsIndices, exprIdx) |
| 2301 | } |
| 2302 | desiredElem := types.Any |
| 2303 | if len(desired.TupleContents()) > elemIdx { |
| 2304 | desiredElem = desired.TupleContents()[elemIdx] |
| 2305 | } |
| 2306 | typedSubExprs, resType, err := TypeCheckSameTypedExprs(ctx, semaCtx, desiredElem, sameTypeExprs...) |
| 2307 | if err != nil { |
| 2308 | return nil, nil, pgerror.Newf(pgcode.DatatypeMismatch, "tuples %s are not the same type: %v", Exprs(exprs), err) |
| 2309 | } |
| 2310 | for j, typedExpr := range typedSubExprs { |
| 2311 | tupleIdx := sameTypeExprsIndices[j] |
| 2312 | exprs[tupleIdx].(*Tuple).Exprs[elemIdx] = typedExpr |
| 2313 | } |
| 2314 | resTypes.TupleContents()[elemIdx] = resType |
| 2315 | } |
| 2316 | for tupleIdx, expr := range exprs { |
| 2317 | if expr != DNull { |
| 2318 | expr.(*Tuple).typ = resTypes |
| 2319 | } |
| 2320 | typedExprs[tupleIdx] = expr.(TypedExpr) |
| 2321 | } |
| 2322 | return typedExprs, resTypes, nil |
| 2323 | } |
| 2324 |
no test coverage detected