本文整理匯總了Golang中github.com/cockroachdb/cockroach/sql/parser.FillArgs函數的典型用法代碼示例。如果您正苦於以下問題:Golang FillArgs函數的具體用法?Golang FillArgs怎麽用?Golang FillArgs使用的例子?那麽, 這裏精選的函數代碼示例或許可以為您提供幫助。
在下文中一共展示了FillArgs函數的10個代碼示例,這些例子默認根據受歡迎程度排序。您可以為喜歡或者感覺有用的代碼點讚,您的評價將有助於係統推薦出更棒的Golang代碼示例。
示例1: exec
// exec executes the request. Any error encountered is returned; it is
// the caller's responsibility to update the response.
func (s *Server) exec(req driver.Request) (driver.Response, error) {
var resp driver.Response
// Pick up current session state.
planner := planner{db: s.db}
if req.Session != nil {
// TODO(tschottdorf) will have to validate the Session information (for
// instance, whether access to the stored database is permitted).
if err := gogoproto.Unmarshal(req.Session, &planner.session); err != nil {
return resp, err
}
}
stmts, err := parser.Parse(req.Sql)
if err != nil {
return resp, err
}
for _, stmt := range stmts {
// Bind all the placeholder variables in the stmt to actual values.
if err := parser.FillArgs(stmt, parameters(req.Params)); err != nil {
return resp, err
}
var plan planNode
if plan, err = planner.makePlan(stmt); err != nil {
return resp, err
}
result := driver.Result{
Columns: plan.Columns(),
}
for plan.Next() {
values := plan.Values()
row := driver.Result_Row{}
row.Values = make([]driver.Datum, 0, len(values))
for _, val := range values {
switch vt := val.(type) {
case parser.DBool:
row.Values = append(row.Values, driver.Datum{BoolVal: (*bool)(&vt)})
case parser.DInt:
row.Values = append(row.Values, driver.Datum{IntVal: (*int64)(&vt)})
case parser.DFloat:
row.Values = append(row.Values, driver.Datum{FloatVal: (*float64)(&vt)})
case parser.DString:
row.Values = append(row.Values, driver.Datum{StringVal: (*string)(&vt)})
case parser.DNull:
row.Values = append(row.Values, driver.Datum{})
default:
return resp, util.Errorf("unsupported datum: %T", val)
}
}
result.Rows = append(result.Rows, row)
}
resp.Results = append(resp.Results, result)
}
// Update session state.
resp.Session, err = gogoproto.Marshal(&planner.session)
return resp, err
}
示例2: query
func (p *planner) query(sql string, args ...interface{}) (planNode, *roachpb.Error) {
stmt, err := parser.ParseOneTraditional(sql)
if err != nil {
return nil, roachpb.NewError(err)
}
if err := parser.FillArgs(stmt, golangParameters(args)); err != nil {
return nil, roachpb.NewError(err)
}
return p.makePlan(stmt, false)
}
示例3: execStmtInOpenTxn
// execStmtInOpenTxn executes one statement in the context
// of the planner's transaction (which is assumed to exist).
// It handles statements that affect the transaction state (BEGIN, COMMIT)
// and delegates everything else to `execStmt`.
// It binds placeholders.
//
// The current transaction might be committed/rolled back when this returns.
//
// Args:
// abortedMode: if set, we're in a transaction that has encountered errors, so we
// must reject the statement unless it's a COMMIT/ROLLBACK.
// implicitTxn: set if the current transaction was implicitly
// created by the system (i.e. the client sent the statement outside of
// a transaction).
// COMMIT/ROLLBACK statements are rejected if set. Also, the transaction
// might be auto-committed in this function.
// firstInTxn: set for the first statement in a transaction. Used
// so that nested BEGIN statements are caught.
// stmtTimestamp: Used as the statement_timestamp().
//
// Returns:
// - a Result
// - an error, if any. In case of error, the result returned also reflects this error.
func (e *Executor) execStmtInOpenTxn(
stmt parser.Statement, planMaker *planner,
implicitTxn bool,
firstInTxn bool,
stmtTimestamp parser.DTimestamp,
txnState *txnState) (Result, *roachpb.Error) {
if txnState.state() != openTransaction {
panic("execStmtInOpenTxn called outside of an open txn")
}
if planMaker.txn == nil {
panic("execStmtInOpenTxn called with the a txn not set on the planner")
}
planMaker.evalCtx.StmtTimestamp = stmtTimestamp
// TODO(cdo): Figure out how to not double count on retries.
e.updateStmtCounts(stmt)
switch stmt.(type) {
case *parser.BeginTransaction:
if !firstInTxn {
txnState.aborted = true
pErr := roachpb.NewError(errTransactionInProgress)
return Result{PErr: pErr}, pErr
}
case *parser.CommitTransaction, *parser.RollbackTransaction, *parser.SetTransaction:
if implicitTxn {
txnState.aborted = true
pErr := roachpb.NewError(errNoTransactionInProgress)
return Result{PErr: pErr}, pErr
}
}
// Bind all the placeholder variables in the stmt to actual values.
stmt, err := parser.FillArgs(stmt, &planMaker.params)
if err != nil {
txnState.aborted = true
pErr := roachpb.NewError(err)
return Result{PErr: pErr}, pErr
}
result, pErr := e.execStmt(stmt, planMaker, timeutil.Now(),
implicitTxn /* autoCommit */)
txnDone := planMaker.txn == nil
if pErr != nil {
result = Result{PErr: pErr}
txnState.aborted = true
}
if txnDone {
txnState.aborted = false
txnState.txn = nil
}
return result, pErr
}
示例4: execStmt
func (e *Executor) execStmt(stmt parser.Statement, planMaker *planner) (Result, *roachpb.Error) {
var result Result
switch stmt.(type) {
case *parser.BeginTransaction:
if planMaker.txn != nil {
return result, roachpb.NewError(errTransactionInProgress)
}
// Start a transaction here and not in planMaker to prevent begin
// transaction from being called within an auto-transaction below.
planMaker.setTxn(client.NewTxn(e.db), time.Now())
planMaker.txn.SetDebugName("sql", 0)
case *parser.CommitTransaction, *parser.RollbackTransaction:
if planMaker.txn == nil {
return result, roachpb.NewError(errNoTransactionInProgress)
} else if planMaker.txn.Proto.Status == roachpb.ABORTED {
// Reset to allow starting a new transaction.
planMaker.resetTxn()
return result, nil
}
case *parser.SetTransaction:
if planMaker.txn == nil {
return result, roachpb.NewError(errNoTransactionInProgress)
}
default:
if planMaker.txn != nil && planMaker.txn.Proto.Status == roachpb.ABORTED {
return result, roachpb.NewError(&roachpb.SqlTransactionAbortedError{})
}
}
// Bind all the placeholder variables in the stmt to actual values.
if err := parser.FillArgs(stmt, &planMaker.params); err != nil {
return result, roachpb.NewError(err)
}
// Create a function which both makes and executes the plan, populating
// result.
//
// TODO(pmattis): Should this be a separate function? Perhaps we should move
// some of the common code back out into execStmts and have execStmt contain
// only the body of this closure.
f := func(timestamp time.Time, autoCommit bool) *roachpb.Error {
planMaker.evalCtx.StmtTimestamp = parser.DTimestamp{Time: timestamp}
plan, pErr := planMaker.makePlan(stmt, autoCommit)
if pErr != nil {
return pErr
}
switch result.Type = stmt.StatementType(); result.Type {
case parser.RowsAffected:
for plan.Next() {
result.RowsAffected++
}
case parser.Rows:
result.Columns = plan.Columns()
for _, c := range result.Columns {
if err := checkResultDatum(c.Typ); err != nil {
return err
}
}
for plan.Next() {
// The plan.Values DTuple needs to be copied on each iteration.
values := plan.Values()
row := ResultRow{Values: make([]parser.Datum, 0, len(values))}
for _, val := range values {
if err := checkResultDatum(val); err != nil {
return err
}
row.Values = append(row.Values, val)
}
result.Rows = append(result.Rows, row)
}
}
return plan.PErr()
}
// If there is a pending transaction.
if planMaker.txn != nil {
pErr := f(time.Now(), false)
return result, pErr
}
if testingWaitForMetadata {
// We might need to verify metadata. Lock the system config so that
// no gossip updates sneak in under us.
// This lock does not change semantics. Even outside of tests, the
// planner is initialized with a static systemConfig, so locking
// the Executor's systemConfig cannot change the semantics of the
// SQL operation being performed under lock.
//
// The case of a multi-request transaction is not handled here,
// because those transactions outlive the verification callback.
// This can be addressed when we move to a connection-oriented
// protocol and server-side transactions.
e.systemConfigCond.L.Lock()
defer e.systemConfigCond.L.Unlock()
}
//.........這裏部分代碼省略.........
示例5: execStmt
func (s server) execStmt(stmt parser.Statement, params parameters, planMaker *planner) (driver.Result, error) {
var result driver.Result
if planMaker.txn == nil {
if _, ok := stmt.(*parser.BeginTransaction); ok {
// Start a transaction here and not in planMaker to prevent begin
// transaction from being called within an auto-transaction below.
planMaker.txn = client.NewTxn(s.db)
planMaker.txn.SetDebugName("sql", 0)
}
} else if planMaker.txn.Proto.Status == proto.ABORTED {
switch stmt.(type) {
case *parser.CommitTransaction, *parser.RollbackTransaction:
// Reset to allow starting a new transaction.
planMaker.txn = nil
return result, nil
default:
return result, errTransactionAborted
}
}
// Bind all the placeholder variables in the stmt to actual values.
if err := parser.FillArgs(stmt, params); err != nil {
return result, err
}
var plan planNode
// If there is a pending transaction.
if planMaker.txn != nil {
// Run in transaction planMaker.txn
var err error
if plan, err = planMaker.makePlan(stmt); err != nil {
return result, err
}
} else {
// No transaction. Run the command as a retryable block in an
// auto-transaction.
if err := s.db.Txn(func(txn *client.Txn) error {
planMaker.txn = txn
var err error
plan, err = planMaker.makePlan(stmt)
planMaker.txn = nil
return err
}); err != nil {
return result, err
}
}
result.Columns = plan.Columns()
for plan.Next() {
values := plan.Values()
row := driver.Result_Row{Values: make([]driver.Datum, 0, len(values))}
for _, val := range values {
if val == parser.DNull {
row.Values = append(row.Values, driver.Datum{})
} else {
switch vt := val.(type) {
case parser.DBool:
row.Values = append(row.Values, driver.Datum{BoolVal: (*bool)(&vt)})
case parser.DInt:
row.Values = append(row.Values, driver.Datum{IntVal: (*int64)(&vt)})
case parser.DFloat:
row.Values = append(row.Values, driver.Datum{FloatVal: (*float64)(&vt)})
case parser.DString:
row.Values = append(row.Values, driver.Datum{StringVal: (*string)(&vt)})
case parser.DDate:
s := vt.String()
row.Values = append(row.Values, driver.Datum{StringVal: &s})
case parser.DTimestamp:
s := vt.String()
row.Values = append(row.Values, driver.Datum{StringVal: &s})
case parser.DInterval:
s := vt.String()
row.Values = append(row.Values, driver.Datum{StringVal: &s})
default:
return result, util.Errorf("unsupported datum: %T", val)
}
}
}
result.Rows = append(result.Rows, row)
}
if err := plan.Err(); err != nil {
return result, err
}
return result, nil
}
示例6: execStmt
func (e *Executor) execStmt(stmt parser.Statement, params parameters, planMaker *planner) (driver.Response_Result, error) {
var result driver.Response_Result
switch stmt.(type) {
case *parser.BeginTransaction:
if planMaker.txn != nil {
return result, errTransactionInProgress
}
// Start a transaction here and not in planMaker to prevent begin
// transaction from being called within an auto-transaction below.
planMaker.setTxn(client.NewTxn(e.db), time.Now())
planMaker.txn.SetDebugName("sql", 0)
case *parser.CommitTransaction, *parser.RollbackTransaction:
if planMaker.txn == nil {
return result, errNoTransactionInProgress
} else if planMaker.txn.Proto.Status == roachpb.ABORTED {
// Reset to allow starting a new transaction.
planMaker.resetTxn()
return result, nil
}
case *parser.SetTransaction:
if planMaker.txn == nil {
return result, errNoTransactionInProgress
}
default:
if planMaker.txn != nil && planMaker.txn.Proto.Status == roachpb.ABORTED {
return result, errTransactionAborted
}
}
// Bind all the placeholder variables in the stmt to actual values.
if err := parser.FillArgs(stmt, params); err != nil {
return result, err
}
// Create a function which both makes and executes the plan, populating
// result.
//
// TODO(pmattis): Should this be a separate function? Perhaps we should move
// some of the common code back out into execStmts and have execStmt contain
// only the body of this closure.
f := func(timestamp time.Time) error {
planMaker.evalCtx.StmtTimestamp = parser.DTimestamp{Time: timestamp}
plan, err := planMaker.makePlan(stmt)
if err != nil {
return err
}
switch stmt.StatementType() {
case parser.DDL:
result.Union = &driver.Response_Result_DDL_{DDL: &driver.Response_Result_DDL{}}
case parser.RowsAffected:
resultRowsAffected := driver.Response_Result_RowsAffected{}
result.Union = &resultRowsAffected
for plan.Next() {
resultRowsAffected.RowsAffected++
}
case parser.Rows:
resultRows := &driver.Response_Result_Rows{
Columns: plan.Columns(),
}
result.Union = &driver.Response_Result_Rows_{
Rows: resultRows,
}
for plan.Next() {
values := plan.Values()
row := driver.Response_Result_Rows_Row{Values: make([]driver.Datum, 0, len(values))}
for _, val := range values {
if val == parser.DNull {
row.Values = append(row.Values, driver.Datum{})
continue
}
switch vt := val.(type) {
case parser.DBool:
row.Values = append(row.Values, driver.Datum{
Payload: &driver.Datum_BoolVal{BoolVal: bool(vt)},
})
case parser.DInt:
row.Values = append(row.Values, driver.Datum{
Payload: &driver.Datum_IntVal{IntVal: int64(vt)},
})
case parser.DFloat:
row.Values = append(row.Values, driver.Datum{
Payload: &driver.Datum_FloatVal{FloatVal: float64(vt)},
})
case parser.DBytes:
row.Values = append(row.Values, driver.Datum{
Payload: &driver.Datum_BytesVal{BytesVal: []byte(vt)},
})
case parser.DString:
row.Values = append(row.Values, driver.Datum{
Payload: &driver.Datum_StringVal{StringVal: string(vt)},
})
case parser.DDate:
row.Values = append(row.Values, driver.Datum{
Payload: &driver.Datum_DateVal{DateVal: int64(vt)},
})
case parser.DTimestamp:
//.........這裏部分代碼省略.........
示例7: execStmt
func (e Executor) execStmt(stmt parser.Statement, params parameters, planMaker *planner) (driver.Result, error) {
var result driver.Result
switch stmt.(type) {
case *parser.BeginTransaction:
if planMaker.txn != nil {
return result, errTransactionInProgress
}
// Start a transaction here and not in planMaker to prevent begin
// transaction from being called within an auto-transaction below.
planMaker.txn = client.NewTxn(e.db)
planMaker.txn.SetDebugName("sql", 0)
case *parser.CommitTransaction, *parser.RollbackTransaction:
if planMaker.txn != nil {
if planMaker.txn.Proto.Status == proto.ABORTED {
// Reset to allow starting a new transaction.
planMaker.txn = nil
return result, nil
}
} else {
return result, errNoTransactionInProgress
}
case *parser.SetTransaction:
if planMaker.txn == nil {
return result, errNoTransactionInProgress
}
default:
if planMaker.txn != nil && planMaker.txn.Proto.Status == proto.ABORTED {
return result, errTransactionAborted
}
}
// Bind all the placeholder variables in the stmt to actual values.
if err := parser.FillArgs(stmt, params); err != nil {
return result, err
}
// Create a function which both makes and executes the plan, populating
// result.
//
// TODO(pmattis): Should this be a separate function? Perhaps we should move
// some of the common code back out into execStmts and have execStmt contain
// only the body of this closure.
f := func() error {
plan, err := planMaker.makePlan(stmt)
if err != nil {
return err
}
result.Columns = plan.Columns()
for plan.Next() {
values := plan.Values()
row := driver.Result_Row{Values: make([]driver.Datum, 0, len(values))}
for _, val := range values {
if val == parser.DNull {
row.Values = append(row.Values, driver.Datum{})
} else {
switch vt := val.(type) {
case parser.DBool:
row.Values = append(row.Values, driver.Datum{
Payload: &driver.Datum_BoolVal{BoolVal: bool(vt)},
})
case parser.DInt:
row.Values = append(row.Values, driver.Datum{
Payload: &driver.Datum_IntVal{IntVal: int64(vt)},
})
case parser.DFloat:
row.Values = append(row.Values, driver.Datum{
Payload: &driver.Datum_FloatVal{FloatVal: float64(vt)},
})
case parser.DBytes:
row.Values = append(row.Values, driver.Datum{
Payload: &driver.Datum_BytesVal{BytesVal: []byte(vt)},
})
case parser.DString:
row.Values = append(row.Values, driver.Datum{
Payload: &driver.Datum_StringVal{StringVal: string(vt)},
})
case parser.DDate:
row.Values = append(row.Values, driver.Datum{
Payload: &driver.Datum_TimeVal{
TimeVal: &driver.Datum_Timestamp{
Sec: vt.Unix(),
Nsec: uint32(vt.Nanosecond()),
},
},
})
case parser.DTimestamp:
row.Values = append(row.Values, driver.Datum{
Payload: &driver.Datum_TimeVal{
TimeVal: &driver.Datum_Timestamp{
Sec: vt.Unix(),
Nsec: uint32(vt.Nanosecond()),
},
},
})
case parser.DInterval:
row.Values = append(row.Values, driver.Datum{
Payload: &driver.Datum_StringVal{StringVal: vt.String()},
})
default:
//.........這裏部分代碼省略.........
示例8: execStmtInOpenTxn
//.........這裏部分代碼省略.........
txnState.resetStateAndTxn(Aborted)
pErr := roachpb.NewError(errTransactionInProgress)
return Result{PErr: pErr}, pErr
}
case *parser.CommitTransaction:
if implicitTxn {
return e.noTransactionHelper(txnState)
}
// CommitTransaction is executed fully here; there's no planNode for it
// and the planner is not involved at all.
return commitSQLTransaction(txnState, planMaker, commit, e)
case *parser.ReleaseSavepoint:
if implicitTxn {
return e.noTransactionHelper(txnState)
}
if pErr := parser.ValidateRestartCheckpoint(s.Savepoint); pErr != nil {
return Result{PErr: pErr}, pErr
}
// ReleaseSavepoint is executed fully here; there's no planNode for it
// and the planner is not involved at all.
return commitSQLTransaction(txnState, planMaker, release, e)
case *parser.RollbackTransaction:
if implicitTxn {
return e.noTransactionHelper(txnState)
}
// RollbackTransaction is executed fully here; there's no planNode for it
// and the planner is not involved at all.
// Notice that we don't return any errors on rollback.
return rollbackSQLTransaction(txnState, planMaker), nil
case *parser.SetTransaction:
if implicitTxn {
return e.noTransactionHelper(txnState)
}
case *parser.Savepoint:
if implicitTxn {
return e.noTransactionHelper(txnState)
}
if pErr := parser.ValidateRestartCheckpoint(s.Name); pErr != nil {
return Result{PErr: pErr}, pErr
}
// We check if the transaction has "started" already by looking inside the txn proto.
// The executor should not be doing that. But it's also what the planner does for
// SET TRANSACTION ISOLATION ... It feels ever more wrong here.
// TODO(andrei): find a better way to track this running state.
// TODO(andrei): the check for retrying is a hack - we erroneously allow
// SAVEPOINT to be issued at any time during a retry, not just in the
// beginning. We should figure out how to track whether we started using the
// transaction during a retry.
if txnState.txn.Proto.IsInitialized() && !txnState.retrying {
pErr := roachpb.NewError(util.Errorf(
"SAVEPOINT %s needs to be the first statement in a transaction",
parser.RestartSavepointName))
return Result{PErr: pErr}, pErr
}
// Note that Savepoint doesn't have a corresponding plan node.
// This here is all the execution there is.
txnState.retryIntent = true
return Result{}, nil
case *parser.RollbackToSavepoint:
if pErr := parser.ValidateRestartCheckpoint(s.Savepoint); pErr != nil {
return Result{PErr: pErr}, pErr
}
// Can't restart if we didn't get an error first, which would've put the
// txn in a different state.
txnState.resetStateAndTxn(Aborted)
pErr := roachpb.NewError(errNotRetriable)
return Result{PErr: pErr}, pErr
}
// Bind all the placeholder variables in the stmt to actual values.
stmt, err := parser.FillArgs(stmt, &planMaker.params)
if err != nil {
txnState.resetStateAndTxn(Aborted)
pErr := roachpb.NewError(err)
return Result{PErr: pErr}, pErr
}
if txnState.tr != nil {
txnState.tr.LazyLog(stmt, true /* sensitive */)
}
result, pErr := e.execStmt(stmt, planMaker, timeutil.Now(),
implicitTxn /* autoCommit */)
if pErr != nil {
if txnState.tr != nil {
txnState.tr.LazyPrintf("ERROR: %v", pErr)
}
txnState.updateStateAndCleanupOnErr(pErr, e)
result = Result{PErr: pErr}
} else if txnState.tr != nil {
tResult := &traceResult{tag: result.PGTag, count: -1}
switch result.Type {
case parser.RowsAffected:
tResult.count = result.RowsAffected
case parser.Rows:
tResult.count = len(result.Rows)
}
txnState.tr.LazyLog(tResult, false)
}
return result, pErr
}
示例9: execStmt
func (e *Executor) execStmt(stmt parser.Statement, planMaker *planner) (driver.Response_Result, error) {
var result driver.Response_Result
switch stmt.(type) {
case *parser.BeginTransaction:
if planMaker.txn != nil {
return result, errTransactionInProgress
}
// Start a transaction here and not in planMaker to prevent begin
// transaction from being called within an auto-transaction below.
planMaker.setTxn(client.NewTxn(e.db), time.Now())
planMaker.txn.SetDebugName("sql", 0)
case *parser.CommitTransaction, *parser.RollbackTransaction:
if planMaker.txn == nil {
return result, errNoTransactionInProgress
} else if planMaker.txn.Proto.Status == roachpb.ABORTED {
// Reset to allow starting a new transaction.
planMaker.resetTxn()
return result, nil
}
case *parser.SetTransaction:
if planMaker.txn == nil {
return result, errNoTransactionInProgress
}
default:
if planMaker.txn != nil && planMaker.txn.Proto.Status == roachpb.ABORTED {
return result, errTransactionAborted
}
}
// Bind all the placeholder variables in the stmt to actual values.
if err := parser.FillArgs(stmt, &planMaker.params); err != nil {
return result, err
}
// Create a function which both makes and executes the plan, populating
// result.
//
// TODO(pmattis): Should this be a separate function? Perhaps we should move
// some of the common code back out into execStmts and have execStmt contain
// only the body of this closure.
f := func(timestamp time.Time) error {
planMaker.evalCtx.StmtTimestamp = parser.DTimestamp{Time: timestamp}
plan, err := planMaker.makePlan(stmt)
if err != nil {
return err
}
switch stmt.StatementType() {
case parser.DDL:
result.Union = &driver.Response_Result_DDL_{DDL: &driver.Response_Result_DDL{}}
case parser.RowsAffected:
resultRowsAffected := driver.Response_Result_RowsAffected{}
result.Union = &resultRowsAffected
for plan.Next() {
resultRowsAffected.RowsAffected++
}
case parser.Rows:
resultRows := &driver.Response_Result_Rows{
Columns: plan.Columns(),
}
result.Union = &driver.Response_Result_Rows_{
Rows: resultRows,
}
for plan.Next() {
values := plan.Values()
row := driver.Response_Result_Rows_Row{Values: make([]driver.Datum, 0, len(values))}
for _, val := range values {
if val == parser.DNull {
row.Values = append(row.Values, driver.Datum{})
continue
}
switch vt := val.(type) {
case parser.DBool:
row.Values = append(row.Values, driver.Datum{
Payload: &driver.Datum_BoolVal{BoolVal: bool(vt)},
})
case parser.DInt:
row.Values = append(row.Values, driver.Datum{
Payload: &driver.Datum_IntVal{IntVal: int64(vt)},
})
case parser.DFloat:
row.Values = append(row.Values, driver.Datum{
Payload: &driver.Datum_FloatVal{FloatVal: float64(vt)},
})
case parser.DBytes:
row.Values = append(row.Values, driver.Datum{
Payload: &driver.Datum_BytesVal{BytesVal: []byte(vt)},
})
case parser.DString:
row.Values = append(row.Values, driver.Datum{
Payload: &driver.Datum_StringVal{StringVal: string(vt)},
})
case parser.DDate:
row.Values = append(row.Values, driver.Datum{
Payload: &driver.Datum_DateVal{DateVal: int64(vt)},
})
case parser.DTimestamp:
//.........這裏部分代碼省略.........
示例10: exec
// exec executes the request. Any error encountered is returned; it is
// the caller's responsibility to update the response.
func (s *Server) exec(req driver.Request) (resp driver.Response, err error) {
// Pick up current session state.
// The request user is validated in ServeHTTP. Even in insecure mode,
// it is guaranteed not to be empty.
planMaker := planner{user: req.GetUser()}
defer func() {
// Update session state even if an error occurs.
if bytes, err := gogoproto.Marshal(&planMaker.session); err != nil {
// Marshaling a `Session` never errors (known from reading the code).
panic(err)
} else {
resp.Session = bytes
}
}()
if req.Session != nil {
// TODO(tschottdorf) will have to validate the Session information (for
// instance, whether access to the stored database is permitted).
if err = gogoproto.Unmarshal(req.Session, &planMaker.session); err != nil {
return
}
}
var stmts parser.StatementList
if stmts, err = parser.Parse(req.Sql); err != nil {
return
}
for _, stmt := range stmts {
// Bind all the placeholder variables in the stmt to actual values.
if err = parser.FillArgs(stmt, parameters(req.Params)); err != nil {
return
}
var plan planNode
if err = s.db.Txn(func(txn *client.Txn) error {
planMaker.txn = txn
plan, err = planMaker.makePlan(stmt)
planMaker.txn = nil
return err
}); err != nil {
return
}
result := driver.Result{
Columns: plan.Columns(),
}
for plan.Next() {
values := plan.Values()
row := driver.Result_Row{}
row.Values = make([]driver.Datum, 0, len(values))
for _, val := range values {
if val == parser.DNull {
row.Values = append(row.Values, driver.Datum{})
} else {
switch vt := val.(type) {
case parser.DBool:
row.Values = append(row.Values, driver.Datum{BoolVal: (*bool)(&vt)})
case parser.DInt:
row.Values = append(row.Values, driver.Datum{IntVal: (*int64)(&vt)})
case parser.DFloat:
row.Values = append(row.Values, driver.Datum{FloatVal: (*float64)(&vt)})
case parser.DString:
row.Values = append(row.Values, driver.Datum{StringVal: (*string)(&vt)})
default:
err = util.Errorf("unsupported datum: %T", val)
return
}
}
}
result.Rows = append(result.Rows, row)
}
if err = plan.Err(); err != nil {
return
}
resp.Results = append(resp.Results, result)
}
return
}