// Prepare returns the result types of the given statement. pinfo may // contain partial type information for placeholders. Prepare will // populate the missing types. The column result types are returned (or // nil if there are no results). func (e *Executor) Prepare( query string, session *Session, pinfo parser.PlaceholderTypes, ) ([]ResultColumn, error) { if log.V(2) { log.Infof(session.Ctx(), "preparing: %s", query) } else if traceSQL { log.Tracef(session.Ctx(), "preparing: %s", query) } stmt, err := parser.ParseOne(query, parser.Syntax(session.Syntax)) if err != nil { return nil, err } if err = pinfo.ProcessPlaceholderAnnotations(stmt); err != nil { return nil, err } protoTS, err := isAsOf(&session.planner, stmt, e.ctx.Clock.Now()) if err != nil { return nil, err } session.planner.resetForBatch(e) session.planner.semaCtx.Placeholders.SetTypes(pinfo) session.planner.evalCtx.PrepareOnly = true // Prepare needs a transaction because it needs to retrieve db/table // descriptors for type checking. txn := client.NewTxn(session.Ctx(), *e.ctx.DB) txn.Proto.Isolation = session.DefaultIsolationLevel session.planner.setTxn(txn) defer session.planner.setTxn(nil) if protoTS != nil { session.planner.asOf = true defer func() { session.planner.asOf = false }() setTxnTimestamps(txn, *protoTS) } plan, err := session.planner.prepare(stmt) if err != nil { return nil, err } if plan == nil { return nil, nil } cols := plan.Columns() for _, c := range cols { if err := checkResultDatum(c.Typ); err != nil { return nil, err } } return cols, nil }
// Prepare returns the result types of the given statement. pinfo may // contain partial type information for placeholders. Prepare will // populate the missing types. The column result types are returned (or // nil if there are no results). func (e *Executor) Prepare( ctx context.Context, query string, session *Session, pinfo parser.PlaceholderTypes, ) ([]ResultColumn, error) { stmt, err := parser.ParseOne(query, parser.Syntax(session.Syntax)) if err != nil { return nil, err } if err = pinfo.ProcessPlaceholderAnnotations(stmt); err != nil { return nil, err } session.planner.resetForBatch(e) session.planner.semaCtx.Placeholders.SetTypes(pinfo) session.planner.evalCtx.PrepareOnly = true // Prepare needs a transaction because it needs to retrieve db/table // descriptors for type checking. txn := client.NewTxn(ctx, *e.ctx.DB) txn.Proto.Isolation = session.DefaultIsolationLevel session.planner.setTxn(txn) defer session.planner.setTxn(nil) plan, err := session.planner.prepare(stmt) if err != nil { return nil, err } if plan == nil { return nil, nil } cols := plan.Columns() for _, c := range cols { if err := checkResultDatum(c.Typ); err != nil { return nil, err } } return cols, nil }