func (iter *Iter) Scan(dest ...interface{}) bool {
	if iter.err != nil {
		return false
	}
	if iter.pos >= iter.numRows {
		if iter.next != nil {
			*iter = *iter.next.fetch()
			return iter.Scan(dest...)
		}
		return false
	}
	if iter.next != nil && iter.pos == iter.next.pos {
		go iter.next.fetch()
	}
	if len(dest) != iter.meta.actualColCount {
		iter.err = fmt.Errorf("gocql: not enough columns to scan into: have %d want %d", len(dest), iter.meta.actualColCount)
		return false
	}
	i := 0
	for c := range iter.meta.columns {
		col := &iter.meta.columns[c]
		colBytes, err := iter.readColumn()
		if err != nil {
			iter.err = err
			return false
		}
		if dest[i] == nil {
			i++
			continue
		}
		switch col.TypeInfo.Type() {
		case TypeTuple:
			tuple := col.TypeInfo.(TupleTypeInfo)
			count := len(tuple.Elems)
			iter.err = Unmarshal(col.TypeInfo, colBytes, dest[i:i+count])
			i += count
		default:
			iter.err = Unmarshal(col.TypeInfo, colBytes, dest[i])
			i++
		}
		if iter.err != nil {
			return false
		}
	}
	iter.pos++
	return true
}
Scan consumes the next row of the iterator and copies the columns of the
current row into the values pointed at by dest. Use nil as a dest value
to skip the corresponding column. Scan might send additional queries
to the database to retrieve the next set of rows if paging was enabled.

Scan returns true if the row was successfully unmarshaled or false if the
end of the result set was reached or if an error occurred. Close should
be called afterwards to retrieve any potential errors.
package gocql
import (
	"bytes"
	"encoding/binary"
	"errors"
	"fmt"
	"golang.org/x/net/context"
	"io"
	"net"
	"strconv"
	"strings"
	"sync"
	"sync/atomic"
	"time"
	"unicode"
	"github.com/gocql/gocql/internal/lru"
)
type Session struct {
	cons                Consistency
	pageSize            int
	prefetch            float64
	routingKeyInfoCache routingKeyInfoLRU
	schemaDescriber     *schemaDescriber
	trace               Tracer
	hostSource          *ringDescriber
	stmtsLRU            *preparedLRU
	connCfg *ConnConfig
	executor *queryExecutor
	pool     *policyConnPool
	policy   HostSelectionPolicy
	ring     ring
	metadata clusterMetadata
	mu sync.RWMutex
	control *controlConn
	nodeEvents   *eventDeouncer
	schemaEvents *eventDeouncer
	hosts           []HostInfo
	useSystemSchema bool
	cfg ClusterConfig
	closeMu  sync.RWMutex
	isClosed bool
}
func addrsToHosts(addrs []string, defaultPort int) ([]*HostInfo, error) {
	hosts := make([]*HostInfo, len(addrs))
	for i, hostport := range addrs {
		addr, portStr, err := net.SplitHostPort(JoinHostPort(hostport, defaultPort))
		if err != nil {
			return nil, fmt.Errorf("NewSession: unable to parse hostport of addr %q: %v", hostport, err)
		}
		port, err := strconv.Atoi(portStr)
		if err != nil {
			return nil, fmt.Errorf("NewSession: invalid port for hostport of addr %q: %v", hostport, err)
		}
		hosts[i] = &HostInfo{peer: addr, port: port, state: NodeUp}
	}
	return hosts, nil
}
func NewSession(cfg ClusterConfig) (*Session, error) {
	if len(cfg.Hosts) < 1 {
		return nil, ErrNoHosts
	}
	s := &Session{
		cons:     cfg.Consistency,
		prefetch: 0.25,
		cfg:      cfg,
		pageSize: cfg.PageSize,
		stmtsLRU: &preparedLRU{lru: lru.New(cfg.MaxPreparedStmts)},
	}
	connCfg, err := connConfig(s)
	if err != nil {
		s.Close()
		return nil, fmt.Errorf("gocql: unable to create session: %v", err)
	}
	s.connCfg = connCfg
	s.nodeEvents = newEventDeouncer("NodeEvents", s.handleNodeEvent)
	s.schemaEvents = newEventDeouncer("SchemaEvents", s.handleSchemaEvent)
	s.routingKeyInfoCache.lru = lru.New(cfg.MaxRoutingKeyInfo)
	s.hostSource = &ringDescriber{
		session:   s,
		closeChan: make(chan bool),
	}
	pool := cfg.PoolConfig.buildPool(s)
	if cfg.PoolConfig.HostSelectionPolicy == nil {
		cfg.PoolConfig.HostSelectionPolicy = RoundRobinHostPolicy()
	}
	s.pool = pool
	s.policy = cfg.PoolConfig.HostSelectionPolicy
	s.executor = &queryExecutor{
		pool:   pool,
		policy: cfg.PoolConfig.HostSelectionPolicy,
	}
	var hosts []*HostInfo
	if !cfg.disableControlConn {
		s.control = createControlConn(s)
		if err := s.control.connect(cfg.Hosts); err != nil {
			s.Close()
			return nil, fmt.Errorf("gocql: unable to create session: %v", err)
		}
		localHasRPCAddr, _ := checkSystemLocal(s.control)
		s.hostSource.localHasRpcAddr = localHasRPCAddr
		var err error
		if cfg.DisableInitialHostLookup {
			hosts, err = addrsToHosts(cfg.Hosts, cfg.Port)
		} else {
			hosts, _, err = s.hostSource.GetHosts()
		}
		if err != nil {
			s.Close()
			return nil, fmt.Errorf("gocql: unable to create session: %v", err)
		}
	} else {
		hosts, err = addrsToHosts(cfg.Hosts, cfg.Port)
	}
	for _, host := range hosts {
		if s.cfg.HostFilter == nil || s.cfg.HostFilter.Accept(host) {
			if existingHost, ok := s.ring.addHostIfMissing(host); ok {
				existingHost.update(host)
			}
			s.handleNodeUp(net.ParseIP(host.Peer()), host.Port(), false)
		}
	}
	if s.pool.Size() == 0 {
		s.Close()
		return nil, ErrNoConnectionsStarted
	}
	s.useSystemSchema = hosts[0].Version().Major >= 3
	return s, nil
}
func (s *Session) SetConsistency(cons Consistency) {
	s.mu.Lock()
	s.cons = cons
	s.mu.Unlock()
}
func (s *Session) SetPageSize(n int) {
	s.mu.Lock()
	s.pageSize = n
	s.mu.Unlock()
}
func (s *Session) SetPrefetch(p float64) {
	s.mu.Lock()
	s.prefetch = p
	s.mu.Unlock()
}
func (s *Session) SetTrace(trace Tracer) {
	s.mu.Lock()
	s.trace = trace
	s.mu.Unlock()
}
func (s *Session) Query(stmt string, values ...interface{}) *Query {
	s.mu.RLock()
	qry := &Query{stmt: stmt, values: values, cons: s.cons,
		session: s, pageSize: s.pageSize, trace: s.trace,
		prefetch: s.prefetch, rt: s.cfg.RetryPolicy, serialCons: s.cfg.SerialConsistency,
		defaultTimestamp: s.cfg.DefaultTimestamp,
	}
	s.mu.RUnlock()
	return qry
}
type QueryInfo struct {
	Id          []byte
	Args        []ColumnInfo
	Rval        []ColumnInfo
	PKeyColumns []int
}
func (s *Session) Bind(stmt string, b func(q *QueryInfo) ([]interface{}, error)) *Query {
	s.mu.RLock()
	qry := &Query{stmt: stmt, binding: b, cons: s.cons,
		session: s, pageSize: s.pageSize, trace: s.trace,
		prefetch: s.prefetch, rt: s.cfg.RetryPolicy}
	s.mu.RUnlock()
	return qry
}
func (s *Session) Close() {
	s.closeMu.Lock()
	defer s.closeMu.Unlock()
	if s.isClosed {
		return
	}
	s.isClosed = true
	if s.pool != nil {
		s.pool.Close()
	}
	if s.hostSource != nil {
		close(s.hostSource.closeChan)
	}
	if s.control != nil {
		s.control.close()
	}
	if s.nodeEvents != nil {
		s.nodeEvents.stop()
	}
	if s.schemaEvents != nil {
		s.schemaEvents.stop()
	}
}
func (s *Session) Closed() bool {
	s.closeMu.RLock()
	closed := s.isClosed
	s.closeMu.RUnlock()
	return closed
}
func (s *Session) executeQuery(qry *Query) *Iter {
	if s.Closed() {
		return &Iter{err: ErrSessionClosed}
	}
	iter, err := s.executor.executeQuery(qry)
	if err != nil {
		return &Iter{err: err}
	}
	if iter == nil {
		panic("nil iter")
	}
	return iter
}
func (s *Session) KeyspaceMetadata(keyspace string) (*KeyspaceMetadata, error) {
	if s.Closed() {
		return nil, ErrSessionClosed
	}
	if keyspace == "" {
		return nil, ErrNoKeyspace
	}
	s.mu.Lock()
	if s.schemaDescriber == nil {
		s.schemaDescriber = newSchemaDescriber(s)
	}
	s.mu.Unlock()
	return s.schemaDescriber.getSchema(keyspace)
}
func (s *Session) getConn() *Conn {
	hosts := s.ring.allHosts()
	var conn *Conn
	for _, host := range hosts {
		if !host.IsUp() {
			continue
		}
		pool, ok := s.pool.getPool(host.Peer())
		if !ok {
			continue
		}
		conn = pool.Pick()
		if conn != nil {
			return conn
		}
	}
	return nil
}
func (s *Session) routingKeyInfo(ctx context.Context, stmt string) (*routingKeyInfo, error) {
	s.routingKeyInfoCache.mu.Lock()
	entry, cached := s.routingKeyInfoCache.lru.Get(stmt)
	if cached {
		s.routingKeyInfoCache.mu.Unlock()
		inflight := entry.(*inflightCachedEntry)
		inflight.wg.Wait()
		if inflight.err != nil {
			return nil, inflight.err
		}
		key, _ := inflight.value.(*routingKeyInfo)
		return key, nil
	}
	inflight := new(inflightCachedEntry)
	inflight.wg.Add(1)
	defer inflight.wg.Done()
	s.routingKeyInfoCache.lru.Add(stmt, inflight)
	s.routingKeyInfoCache.mu.Unlock()
	var (
		info         *preparedStatment
		partitionKey []*ColumnMetadata
	)
	conn := s.getConn()
	if conn == nil {
		inflight.err = errors.New("gocql: unable to fetch preapred info: no connection avilable")
		return nil, inflight.err
	}
	info, inflight.err = conn.prepareStatement(ctx, stmt, nil)
	if inflight.err != nil {
		s.routingKeyInfoCache.Remove(stmt)
		return nil, inflight.err
	}
	if info.request.colCount == 0 {
		return nil, nil
	}
	if len(info.request.pkeyColumns) > 0 {
		types := make([]TypeInfo, len(info.request.pkeyColumns))
		for i, col := range info.request.pkeyColumns {
			types[i] = info.request.columns[col].TypeInfo
		}
		routingKeyInfo := &routingKeyInfo{
			indexes: info.request.pkeyColumns,
			types:   types,
		}
		inflight.value = routingKeyInfo
		return routingKeyInfo, nil
	}
	table := info.request.columns[0].Table
	var keyspaceMetadata *KeyspaceMetadata
	keyspaceMetadata, inflight.err = s.KeyspaceMetadata(info.request.columns[0].Keyspace)
	if inflight.err != nil {
		s.routingKeyInfoCache.Remove(stmt)
		return nil, inflight.err
	}
	tableMetadata, found := keyspaceMetadata.Tables[table]
	if !found {
		inflight.err = ErrNoMetadata
		s.routingKeyInfoCache.Remove(stmt)
		return nil, inflight.err
	}
	partitionKey = tableMetadata.PartitionKey
	size := len(partitionKey)
	routingKeyInfo := &routingKeyInfo{
		indexes: make([]int, size),
		types:   make([]TypeInfo, size),
	}
	for keyIndex, keyColumn := range partitionKey {
		routingKeyInfo.indexes[keyIndex] = -1
		for argIndex, boundColumn := range info.request.columns {
			if keyColumn.Name == boundColumn.Name {
				routingKeyInfo.indexes[keyIndex] = argIndex
				routingKeyInfo.types[keyIndex] = boundColumn.TypeInfo
				break
			}
		}
		if routingKeyInfo.indexes[keyIndex] == -1 {
			return nil, nil
		}
	}
	inflight.value = routingKeyInfo
	return routingKeyInfo, nil
}
func (b *Batch) execute(conn *Conn) *Iter {
	return conn.executeBatch(b)
}
func (s *Session) executeBatch(batch *Batch) *Iter {
	if s.Closed() {
		return &Iter{err: ErrSessionClosed}
	}
	if batch.Size() > BatchSizeMaximum {
		return &Iter{err: ErrTooManyStmts}
	}
	iter, err := s.executor.executeQuery(batch)
	if err != nil {
		return &Iter{err: err}
	}
	return iter
}
func (s *Session) ExecuteBatch(batch *Batch) error {
	iter := s.executeBatch(batch)
	return iter.Close()
}
func (s *Session) ExecuteBatchCAS(batch *Batch, dest ...interface{}) (applied bool, iter *Iter, err error) {
	iter = s.executeBatch(batch)
	if err := iter.checkErrAndNotFound(); err != nil {
		iter.Close()
		return false, nil, err
	}
	if len(iter.Columns()) > 1 {
		dest = append([]interface{}{&applied}, dest...)
		iter.Scan(dest...)
	} else {
		iter.Scan(&applied)
	}
	return applied, iter, nil
}
func (s *Session) MapExecuteBatchCAS(batch *Batch, dest map[string]interface{}) (applied bool, iter *Iter, err error) {
	iter = s.executeBatch(batch)
	if err := iter.checkErrAndNotFound(); err != nil {
		iter.Close()
		return false, nil, err
	}
	iter.MapScan(dest)
	applied = dest["[applied]"].(bool)
	delete(dest, "[applied]")
	return applied, iter, iter.err
}
func (s *Session) connect(addr string, errorHandler ConnErrorHandler, host *HostInfo) (*Conn, error) {
	return Connect(host, addr, s.connCfg, errorHandler, s)
}
type Query struct {
	stmt                  string
	values                []interface{}
	cons                  Consistency
	pageSize              int
	routingKey            []byte
	routingKeyBuffer      []byte
	pageState             []byte
	prefetch              float64
	trace                 Tracer
	session               *Session
	rt                    RetryPolicy
	binding               func(q *QueryInfo) ([]interface{}, error)
	attempts              int
	totalLatency          int64
	serialCons            SerialConsistency
	defaultTimestamp      bool
	defaultTimestampValue int64
	disableSkipMetadata   bool
	context               context.Context
	disableAutoPage bool
}
func (q Query) String() string {
	return fmt.Sprintf("[query statement=%q values=%+v consistency=%s]", q.stmt, q.values, q.cons)
}
func (q *Query) Attempts() int {
	return q.attempts
}
func (q *Query) Latency() int64 {
	if q.attempts > 0 {
		return q.totalLatency / int64(q.attempts)
	}
	return 0
}
func (q *Query) Consistency(c Consistency) *Query {
	q.cons = c
	return q
}
func (q *Query) GetConsistency() Consistency {
	return q.cons
}
func (q *Query) Trace(trace Tracer) *Query {
	q.trace = trace
	return q
}
func (q *Query) PageSize(n int) *Query {
	q.pageSize = n
	return q
}
func (q *Query) DefaultTimestamp(enable bool) *Query {
	q.defaultTimestamp = enable
	return q
}
func (q *Query) WithTimestamp(timestamp int64) *Query {
	q.DefaultTimestamp(true)
	q.defaultTimestampValue = timestamp
	return q
}
func (q *Query) RoutingKey(routingKey []byte) *Query {
	q.routingKey = routingKey
	return q
}
func (q *Query) WithContext(ctx context.Context) *Query {
	q.context = ctx
	return q
}
func (q *Query) execute(conn *Conn) *Iter {
	return conn.executeQuery(q)
}
func (q *Query) attempt(d time.Duration) {
	q.attempts++
	q.totalLatency += d.Nanoseconds()
}
func (q *Query) retryPolicy() RetryPolicy {
	return q.rt
}
func (q *Query) GetRoutingKey() ([]byte, error) {
	if q.routingKey != nil {
		return q.routingKey, nil
	} else if q.binding != nil && len(q.values) == 0 {
		return nil, nil
	}
	routingKeyInfo, err := q.session.routingKeyInfo(q.context, q.stmt)
	if err != nil {
		return nil, err
	}
	if routingKeyInfo == nil {
		return nil, nil
	}
	if len(routingKeyInfo.indexes) == 1 {
		routingKey, err := Marshal(
			routingKeyInfo.types[0],
			q.values[routingKeyInfo.indexes[0]],
		)
		if err != nil {
			return nil, err
		}
		return routingKey, nil
	}
	if q.routingKeyBuffer == nil {
		q.routingKeyBuffer = make([]byte, 0, 256)
	}
	buf := bytes.NewBuffer(q.routingKeyBuffer)
	for i := range routingKeyInfo.indexes {
		encoded, err := Marshal(
			routingKeyInfo.types[i],
			q.values[routingKeyInfo.indexes[i]],
		)
		if err != nil {
			return nil, err
		}
		lenBuf := []byte{0x00, 0x00}
		binary.BigEndian.PutUint16(lenBuf, uint16(len(encoded)))
		buf.Write(lenBuf)
		buf.Write(encoded)
		buf.WriteByte(0x00)
	}
	routingKey := buf.Bytes()
	return routingKey, nil
}
func (q *Query) shouldPrepare() bool {
	stmt := strings.TrimLeftFunc(strings.TrimRightFunc(q.stmt, func(r rune) bool {
		return unicode.IsSpace(r) || r == ';'
	}), unicode.IsSpace)
	var stmtType string
	if n := strings.IndexFunc(stmt, unicode.IsSpace); n >= 0 {
		stmtType = strings.ToLower(stmt[:n])
	}
	if stmtType == "begin" {
		if n := strings.LastIndexFunc(stmt, unicode.IsSpace); n >= 0 {
			stmtType = strings.ToLower(stmt[n+1:])
		}
	}
	switch stmtType {
	case "select", "insert", "update", "delete", "batch":
		return true
	}
	return false
}
func (q *Query) Prefetch(p float64) *Query {
	q.prefetch = p
	return q
}
func (q *Query) RetryPolicy(r RetryPolicy) *Query {
	q.rt = r
	return q
}
func (q *Query) Bind(v ...interface{}) *Query {
	q.values = v
	return q
}
func (q *Query) SerialConsistency(cons SerialConsistency) *Query {
	q.serialCons = cons
	return q
}
func (q *Query) PageState(state []byte) *Query {
	q.pageState = state
	q.disableAutoPage = true
	return q
}
func (q *Query) NoSkipMetadata() *Query {
	q.disableSkipMetadata = true
	return q
}
func (q *Query) Exec() error {
	return q.Iter().Close()
}
func isUseStatement(stmt string) bool {
	if len(stmt) < 3 {
		return false
	}
	return strings.ToLower(stmt[0:3]) == "use"
}
func (q *Query) Iter() *Iter {
	if isUseStatement(q.stmt) {
		return &Iter{err: ErrUseStmt}
	}
	return q.session.executeQuery(q)
}
func (q *Query) MapScan(m map[string]interface{}) error {
	iter := q.Iter()
	if err := iter.checkErrAndNotFound(); err != nil {
		return err
	}
	iter.MapScan(m)
	return iter.Close()
}
func (q *Query) Scan(dest ...interface{}) error {
	iter := q.Iter()
	if err := iter.checkErrAndNotFound(); err != nil {
		return err
	}
	iter.Scan(dest...)
	return iter.Close()
}
func (q *Query) ScanCAS(dest ...interface{}) (applied bool, err error) {
	q.disableSkipMetadata = true
	iter := q.Iter()
	if err := iter.checkErrAndNotFound(); err != nil {
		return false, err
	}
	if len(iter.Columns()) > 1 {
		dest = append([]interface{}{&applied}, dest...)
		iter.Scan(dest...)
	} else {
		iter.Scan(&applied)
	}
	return applied, iter.Close()
}
func (q *Query) MapScanCAS(dest map[string]interface{}) (applied bool, err error) {
	q.disableSkipMetadata = true
	iter := q.Iter()
	if err := iter.checkErrAndNotFound(); err != nil {
		return false, err
	}
	iter.MapScan(dest)
	applied = dest["[applied]"].(bool)
	delete(dest, "[applied]")
	return applied, iter.Close()
}
type Iter struct {
	err     error
	pos     int
	meta    resultMetadata
	numRows int
	next    *nextIter
	host    *HostInfo
	framer *framer
	closed int32
}
func (iter *Iter) Host() *HostInfo {
	return iter.host
}
func (iter *Iter) Columns() []ColumnInfo {
	return iter.meta.columns
}
func (iter *Iter) readColumn() ([]byte, error) {
	return iter.framer.readBytesInternal()
}