<commit_before>package main

/*
 * Copyright 2014 Albert P. Tobey <atobey@datastax.com> @AlTobey
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import (
	"encoding/json"
	"fmt"
	"github.com/gocql/gocql"
	"log"
	"net/http"
)

type Grid struct {
	GameId    gocql.UUID `json:"game_id"`   // timeuuid
	TurnId    int        `json:"turn_id"`   // turn number
	OffsetMs  float64    `json:"offset_ms"` // time offset from beginning of game (ms)
	TurnMs    float64    `json:"turn_ms"`   // time elapsed between turns
	Player    string     `json:"player"`    // arbitrary string, player name
	Score     float32    `json:"score"`     // score at the end of the turn
	TileVal   int        `json:"tile_val"`  // the new tile value put on the board
	TileIdx   int        `json:"tile_idx"`  // index on the grid where the new tile was placed
	Direction string     `json:"dir"`       // up down left right init
	State     []int      `json:"state"`     // every value in the grid
}

type Game []Grid

func (g *Grid) Save(cass *gocql.Session) error {
	// update the index on every insert because why not
	err := cass.Query(`INSERT INTO player_game (player, game_id) VALUES (?,?)`, g.Player, g.GameId).Exec()
	if err != nil {
		return err
	}

	query := `INSERT INTO grids (game_id, turn_id, offset_ms, turn_ms, player, score, tile_val, tile_idx, direction, state) VALUES (?,?,?,?,?,?,?,?,?,?)`
	return cass.Query(query, g.GameId, g.TurnId, g.OffsetMs, g.TurnMs, g.Player, g.Score, g.TileVal, g.TileIdx, g.Direction, g.State).Exec()
}

func GetGame(cass *gocql.Session, id gocql.UUID) (list Game, err error) {
	list = make(Game, 0)

	query := `SELECT game_id, turn_id, offset_ms, turn_ms, player, score, tile_val, tile_idx, direction, state FROM grids WHERE game_id=?`
	iq := cass.Query(query, id).Iter()

	for {
		g := Grid{}
		ok := iq.Scan(&g.GameId, &g.TurnId, &g.OffsetMs, &g.TurnMs, &g.Player, &g.Score, &g.TileVal, &g.TileIdx, &g.Direction, &g.State)
		if ok {
			list = append(list, g)
		} else {
			break
		}
	}
	if err = iq.Close(); err != nil {
		log.Printf("Error during Cassandra query: %s", err)
	}

	return list, err
}

func GridHandler(w http.ResponseWriter, r *http.Request) {
	g := Grid{}
	dec := json.NewDecoder(r.Body)
	err := dec.Decode(&g)
	if err != nil {
		log.Printf("PUT invalid json data: %s", err)
		http.Error(w, fmt.Sprintf("PUT invalid json data: %s", err), 500)
	}

	switch r.Method {
	case "PUT":
		err := g.Save(cass)
		if err != nil {
			log.Printf("Write to Cassandra failed: %s", err)
			http.Error(w, "Write to Cassandra failed!", 500)
		}
	default:
		http.Error(w, fmt.Sprintf("method '%s' not implemented", r.Method), 500)
		return
	}
}
<commit_msg>add a TTL on player_game inserts<commit_after>package main

/*
 * Copyright 2014 Albert P. Tobey <atobey@datastax.com> @AlTobey
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import (
	"encoding/json"
	"fmt"
	"github.com/gocql/gocql"
	"log"
	"net/http"
)

type Grid struct {
	GameId    gocql.UUID `json:"game_id"`   // timeuuid
	TurnId    int        `json:"turn_id"`   // turn number
	OffsetMs  float64    `json:"offset_ms"` // time offset from beginning of game (ms)
	TurnMs    float64    `json:"turn_ms"`   // time elapsed between turns
	Player    string     `json:"player"`    // arbitrary string, player name
	Score     float32    `json:"score"`     // score at the end of the turn
	TileVal   int        `json:"tile_val"`  // the new tile value put on the board
	TileIdx   int        `json:"tile_idx"`  // index on the grid where the new tile was placed
	Direction string     `json:"dir"`       // up down left right init
	State     []int      `json:"state"`     // every value in the grid
}

type Game []Grid

func (g *Grid) Save(cass *gocql.Session) error {
	// update the index on every insert because why not
	// TTL 600 - any games older than 10 minutes are irrelevant
	pgquery := `INSERT INTO player_game (player, game_id) VALUES (?,?) USING TTL 600`
	err := cass.Query(pgquery, g.Player, g.GameId).Exec()
	if err != nil {
		return err
	}

	gquery := `INSERT INTO grids (game_id, turn_id, offset_ms, turn_ms, player, score, tile_val, tile_idx, direction, state) VALUES (?,?,?,?,?,?,?,?,?,?)`
	return cass.Query(gquery, g.GameId, g.TurnId, g.OffsetMs, g.TurnMs, g.Player, g.Score, g.TileVal, g.TileIdx, g.Direction, g.State).Exec()
}

func GetGame(cass *gocql.Session, id gocql.UUID) (list Game, err error) {
	list = make(Game, 0)

	query := `SELECT game_id, turn_id, offset_ms, turn_ms, player, score, tile_val, tile_idx, direction, state FROM grids WHERE game_id=?`
	iq := cass.Query(query, id).Iter()

	for {
		g := Grid{}
		ok := iq.Scan(&g.GameId, &g.TurnId, &g.OffsetMs, &g.TurnMs, &g.Player, &g.Score, &g.TileVal, &g.TileIdx, &g.Direction, &g.State)
		if ok {
			list = append(list, g)
		} else {
			break
		}
	}
	if err = iq.Close(); err != nil {
		log.Printf("Error during Cassandra query: %s", err)
	}

	return list, err
}

func GridHandler(w http.ResponseWriter, r *http.Request) {
	g := Grid{}
	dec := json.NewDecoder(r.Body)
	err := dec.Decode(&g)
	if err != nil {
		log.Printf("PUT invalid json data: %s", err)
		http.Error(w, fmt.Sprintf("PUT invalid json data: %s", err), 500)
	}

	switch r.Method {
	case "PUT":
		err := g.Save(cass)
		if err != nil {
			log.Printf("Write to Cassandra failed: %s", err)
			http.Error(w, "Write to Cassandra failed!", 500)
		}
	default:
		http.Error(w, fmt.Sprintf("method '%s' not implemented", r.Method), 500)
		return
	}
}
<|endoftext|>


<commit_before>package types

import (
	"fmt"
	"net/url"
)

// Reference to indexed item
type Reference struct {
	ParentHash string `json:"parent_hash"`
	Name       string `json:"name"`
}

// String shows the name
func (r *Reference) String() string {
	return r.Name
}

// References represents a list of references
type References []Reference

// Contains returns true of a given reference exists, false when it doesn't
func (references References) Contains(newRef *Reference) bool {
	for _, r := range references {
		if r.ParentHash == newRef.ParentHash {
			return true
		}
	}

	return false
}

// ReferencedResource is a resource with zero or more references to it.
type ReferencedResource struct {
	*Resource
	References
}

// GatewayPath returns the path for requesting a resource from an IPFS gateway.
// If a reference is available, it is used to generate the filename to facilitate content
// type detection (e.g. /ipfs/<parent_hash>/my_file.jpg instead of /ipfs/<file_hash>/).
func (r ReferencedResource) GatewayPath() string {
	if len(r.References) > 0 && r.References[0].Name != "" {
		// Named reference, use it for generating path
		return fmt.Sprintf("/ipfs/%s/%s", r.References[0].ParentHash, url.PathEscape(r.References[0].Name))
	}

	return fmt.Sprintf("/ipfs/%s", r.ID)
}
<commit_msg>Remove legacy references.<commit_after><|endoftext|>


<commit_before>package types

import (
	"database/sql"
	"database/sql/driver"
	"encoding/json"
	"reflect"
	"strconv"
	"time"

	"gopkg.in/pg.v4/internal"
)

var (
	scannerType      = reflect.TypeOf(new(sql.Scanner)).Elem()
	driverValuerType = reflect.TypeOf(new(driver.Valuer)).Elem()
)

var (
	timeType = reflect.TypeOf((*time.Time)(nil)).Elem()
)

type ScannerFunc func(reflect.Value, []byte) error

var valueScanners []ScannerFunc

func init() {
	valueScanners = []ScannerFunc{
		reflect.Bool:          scanBoolValue,
		reflect.Int:           scanIntValue,
		reflect.Int8:          scanIntValue,
		reflect.Int16:         scanIntValue,
		reflect.Int32:         scanIntValue,
		reflect.Int64:         scanIntValue,
		reflect.Uint:          scanUintValue,
		reflect.Uint8:         scanUintValue,
		reflect.Uint16:        scanUintValue,
		reflect.Uint32:        scanUintValue,
		reflect.Uint64:        scanUintValue,
		reflect.Uintptr:       nil,
		reflect.Float32:       scanFloatValue,
		reflect.Float64:       scanFloatValue,
		reflect.Complex64:     nil,
		reflect.Complex128:    nil,
		reflect.Array:         nil,
		reflect.Chan:          nil,
		reflect.Func:          nil,
		reflect.Interface:     scanIfaceValue,
		reflect.Map:           scanJSONValue,
		reflect.Ptr:           nil,
		reflect.Slice:         scanJSONValue,
		reflect.String:        scanStringValue,
		reflect.Struct:        scanJSONValue,
		reflect.UnsafePointer: nil,
	}
}

func Scanner(typ reflect.Type) ScannerFunc {
	return scanner(typ, false)
}

func scanner(typ reflect.Type, pgArray bool) ScannerFunc {
	if typ == timeType {
		return scanTimeValue
	}

	if typ.Implements(scannerType) {
		return scanSQLScannerValue
	}
	if reflect.PtrTo(typ).Implements(scannerType) {
		return scanSQLScannerAddrValue
	}

	kind := typ.Kind()
	switch kind {
	case reflect.Ptr:
		return ptrScannerFunc(typ)
	case reflect.Slice:
		if typ.Elem().Kind() == reflect.Uint8 {
			return scanBytesValue
		}
		if pgArray {
			return ArrayScanner(typ)
		}
	}
	return valueScanners[kind]
}

func ptrScannerFunc(typ reflect.Type) ScannerFunc {
	scanner := Scanner(typ.Elem())
	return func(v reflect.Value, b []byte) error {
		if scanner == nil {
			return internal.Errorf("pg: Scan(unsupported %s)", v.Type())
		}
		if b == nil {
			if v.IsNil() {
				return nil
			}
			if !v.CanSet() {
				return internal.Errorf("pg: Scan(non-pointer %s)", v.Type())
			}
			v.Set(reflect.Zero(v.Type()))
			return nil
		}
		if v.IsNil() {
			if !v.CanSet() {
				return internal.Errorf("pg: Scan(non-pointer %s)", v.Type())
			}
			v.Set(reflect.New(v.Type().Elem()))
		}
		return scanner(v.Elem(), b)
	}
}

func scanIfaceValue(v reflect.Value, b []byte) error {
	if v.IsNil() {
		return internal.Errorf("pg: Scan(nil)")
	}
	return ScanValue(v.Elem(), b)
}

func IsSQLScanner(typ reflect.Type) bool {
	if typ.Implements(scannerType) {
		return true
	}
	if reflect.PtrTo(typ).Implements(scannerType) {
		return true
	}
	return false
}

func ScanValue(v reflect.Value, b []byte) error {
	if !v.IsValid() {
		return internal.Errorf("pg: Scan(nil)")
	}

	scanner := Scanner(v.Type())
	if scanner != nil {
		return scanner(v, b)
	}

	if v.Kind() == reflect.Interface {
		return internal.Errorf("pg: Scan(nil)")
	}
	return internal.Errorf("pg: Scan(unsupported %s)", v.Type())
}

func scanBoolValue(v reflect.Value, b []byte) error {
	if !v.CanSet() {
		return internal.Errorf("pg: Scan(non-pointer %s)", v.Type())
	}
	if b == nil {
		v.SetBool(false)
		return nil
	}
	v.SetBool(len(b) == 1 && (b[0] == 't' || b[0] == '1'))
	return nil
}

func scanIntValue(v reflect.Value, b []byte) error {
	if !v.CanSet() {
		return internal.Errorf("pg: Scan(non-pointer %s)", v.Type())
	}
	if b == nil {
		v.SetInt(0)
		return nil
	}
	n, err := strconv.ParseInt(internal.BytesToString(b), 10, 64)
	if err != nil {
		return err
	}
	v.SetInt(n)
	return nil
}

func scanUintValue(v reflect.Value, b []byte) error {
	if !v.CanSet() {
		return internal.Errorf("pg: Scan(non-pointer %s)", v.Type())
	}
	if b == nil {
		v.SetUint(0)
		return nil
	}
	n, err := strconv.ParseUint(internal.BytesToString(b), 10, 64)
	if err != nil {
		return err
	}
	v.SetUint(n)
	return nil
}

func scanFloatValue(v reflect.Value, b []byte) error {
	if !v.CanSet() {
		return internal.Errorf("pg: Scan(non-pointer %s)", v.Type())
	}
	if b == nil {
		v.SetFloat(0)
		return nil
	}
	n, err := strconv.ParseFloat(internal.BytesToString(b), 64)
	if err != nil {
		return err
	}
	v.SetFloat(n)
	return nil
}

func scanStringValue(v reflect.Value, b []byte) error {
	if !v.CanSet() {
		return internal.Errorf("pg: Scan(non-pointer %s)", v.Type())
	}
	v.SetString(string(b))
	return nil
}

func scanJSONValue(v reflect.Value, b []byte) error {
	if !v.CanSet() {
		return internal.Errorf("pg: Scan(non-pointer %s)", v.Type())
	}
	if b == nil {
		v.Set(reflect.New(v.Type()).Elem())
		return nil
	}
	return json.Unmarshal(b, v.Addr().Interface())
}

var zeroTimeValue = reflect.ValueOf(time.Time{})

func scanTimeValue(v reflect.Value, b []byte) error {
	if !v.CanSet() {
		return internal.Errorf("pg: Scan(non-pointer %s)", v.Type())
	}
	if b == nil {
		v.Set(zeroTimeValue)
		return nil
	}
	tm, err := ParseTime(b)
	if err != nil {
		return err
	}
	v.Set(reflect.ValueOf(tm))
	return nil
}

func scanBytesValue(v reflect.Value, b []byte) error {
	if !v.CanSet() {
		return internal.Errorf("pg: Scan(non-pointer %s)", v.Type())
	}
	if b == nil {
		v.SetBytes(nil)
		return nil
	}
	bs, err := scanBytes(b)
	if err != nil {
		return err
	}
	v.SetBytes(bs)
	return nil
}

func scanSQLScannerValue(v reflect.Value, b []byte) error {
	if b == nil {
		if v.IsNil() {
			return nil
		}
		return scanSQLScanner(v.Interface().(sql.Scanner), nil)
	}
	if v.IsNil() {
		v.Set(reflect.New(v.Type().Elem()))
	}
	return scanSQLScanner(v.Interface().(sql.Scanner), b)
}

func scanSQLScannerAddrValue(v reflect.Value, b []byte) error {
	if !v.CanAddr() {
		return internal.Errorf("pg: Scan(non-pointer %s)", v.Type())
	}
	return scanSQLScanner(v.Addr().Interface().(sql.Scanner), b)
}
<commit_msg>types: scan nil interface as JSONB.<commit_after>package types

import (
	"database/sql"
	"database/sql/driver"
	"encoding/json"
	"reflect"
	"strconv"
	"time"

	"gopkg.in/pg.v4/internal"
)

var (
	scannerType      = reflect.TypeOf(new(sql.Scanner)).Elem()
	driverValuerType = reflect.TypeOf(new(driver.Valuer)).Elem()
)

var (
	timeType = reflect.TypeOf((*time.Time)(nil)).Elem()
)

type ScannerFunc func(reflect.Value, []byte) error

var valueScanners []ScannerFunc

func init() {
	valueScanners = []ScannerFunc{
		reflect.Bool:          scanBoolValue,
		reflect.Int:           scanIntValue,
		reflect.Int8:          scanIntValue,
		reflect.Int16:         scanIntValue,
		reflect.Int32:         scanIntValue,
		reflect.Int64:         scanIntValue,
		reflect.Uint:          scanUintValue,
		reflect.Uint8:         scanUintValue,
		reflect.Uint16:        scanUintValue,
		reflect.Uint32:        scanUintValue,
		reflect.Uint64:        scanUintValue,
		reflect.Uintptr:       nil,
		reflect.Float32:       scanFloatValue,
		reflect.Float64:       scanFloatValue,
		reflect.Complex64:     nil,
		reflect.Complex128:    nil,
		reflect.Array:         nil,
		reflect.Chan:          nil,
		reflect.Func:          nil,
		reflect.Interface:     scanIfaceValue,
		reflect.Map:           scanJSONValue,
		reflect.Ptr:           nil,
		reflect.Slice:         scanJSONValue,
		reflect.String:        scanStringValue,
		reflect.Struct:        scanJSONValue,
		reflect.UnsafePointer: nil,
	}
}

func Scanner(typ reflect.Type) ScannerFunc {
	return scanner(typ, false)
}

func scanner(typ reflect.Type, pgArray bool) ScannerFunc {
	if typ == timeType {
		return scanTimeValue
	}

	if typ.Implements(scannerType) {
		return scanSQLScannerValue
	}
	if reflect.PtrTo(typ).Implements(scannerType) {
		return scanSQLScannerAddrValue
	}

	kind := typ.Kind()
	switch kind {
	case reflect.Ptr:
		return ptrScannerFunc(typ)
	case reflect.Slice:
		if typ.Elem().Kind() == reflect.Uint8 {
			return scanBytesValue
		}
		if pgArray {
			return ArrayScanner(typ)
		}
	}
	return valueScanners[kind]
}

func ptrScannerFunc(typ reflect.Type) ScannerFunc {
	scanner := Scanner(typ.Elem())
	return func(v reflect.Value, b []byte) error {
		if scanner == nil {
			return internal.Errorf("pg: Scan(unsupported %s)", v.Type())
		}
		if b == nil {
			if v.IsNil() {
				return nil
			}
			if !v.CanSet() {
				return internal.Errorf("pg: Scan(non-pointer %s)", v.Type())
			}
			v.Set(reflect.Zero(v.Type()))
			return nil
		}
		if v.IsNil() {
			if !v.CanSet() {
				return internal.Errorf("pg: Scan(non-pointer %s)", v.Type())
			}
			v.Set(reflect.New(v.Type().Elem()))
		}
		return scanner(v.Elem(), b)
	}
}

func scanIfaceValue(v reflect.Value, b []byte) error {
	if v.IsNil() {
		return scanJSONValue(v, b)
	}
	return ScanValue(v.Elem(), b)
}

func IsSQLScanner(typ reflect.Type) bool {
	if typ.Implements(scannerType) {
		return true
	}
	if reflect.PtrTo(typ).Implements(scannerType) {
		return true
	}
	return false
}

func ScanValue(v reflect.Value, b []byte) error {
	if !v.IsValid() {
		return internal.Errorf("pg: Scan(nil)")
	}

	scanner := Scanner(v.Type())
	if scanner != nil {
		return scanner(v, b)
	}

	if v.Kind() == reflect.Interface {
		return internal.Errorf("pg: Scan(nil)")
	}
	return internal.Errorf("pg: Scan(unsupported %s)", v.Type())
}

func scanBoolValue(v reflect.Value, b []byte) error {
	if !v.CanSet() {
		return internal.Errorf("pg: Scan(non-pointer %s)", v.Type())
	}
	if b == nil {
		v.SetBool(false)
		return nil
	}
	v.SetBool(len(b) == 1 && (b[0] == 't' || b[0] == '1'))
	return nil
}

func scanIntValue(v reflect.Value, b []byte) error {
	if !v.CanSet() {
		return internal.Errorf("pg: Scan(non-pointer %s)", v.Type())
	}
	if b == nil {
		v.SetInt(0)
		return nil
	}
	n, err := strconv.ParseInt(internal.BytesToString(b), 10, 64)
	if err != nil {
		return err
	}
	v.SetInt(n)
	return nil
}

func scanUintValue(v reflect.Value, b []byte) error {
	if !v.CanSet() {
		return internal.Errorf("pg: Scan(non-pointer %s)", v.Type())
	}
	if b == nil {
		v.SetUint(0)
		return nil
	}
	n, err := strconv.ParseUint(internal.BytesToString(b), 10, 64)
	if err != nil {
		return err
	}
	v.SetUint(n)
	return nil
}

func scanFloatValue(v reflect.Value, b []byte) error {
	if !v.CanSet() {
		return internal.Errorf("pg: Scan(non-pointer %s)", v.Type())
	}
	if b == nil {
		v.SetFloat(0)
		return nil
	}
	n, err := strconv.ParseFloat(internal.BytesToString(b), 64)
	if err != nil {
		return err
	}
	v.SetFloat(n)
	return nil
}

func scanStringValue(v reflect.Value, b []byte) error {
	if !v.CanSet() {
		return internal.Errorf("pg: Scan(non-pointer %s)", v.Type())
	}
	v.SetString(string(b))
	return nil
}

func scanJSONValue(v reflect.Value, b []byte) error {
	if !v.CanSet() {
		return internal.Errorf("pg: Scan(non-pointer %s)", v.Type())
	}
	if b == nil {
		v.Set(reflect.New(v.Type()).Elem())
		return nil
	}
	return json.Unmarshal(b, v.Addr().Interface())
}

var zeroTimeValue = reflect.ValueOf(time.Time{})

func scanTimeValue(v reflect.Value, b []byte) error {
	if !v.CanSet() {
		return internal.Errorf("pg: Scan(non-pointer %s)", v.Type())
	}
	if b == nil {
		v.Set(zeroTimeValue)
		return nil
	}
	tm, err := ParseTime(b)
	if err != nil {
		return err
	}
	v.Set(reflect.ValueOf(tm))
	return nil
}

func scanBytesValue(v reflect.Value, b []byte) error {
	if !v.CanSet() {
		return internal.Errorf("pg: Scan(non-pointer %s)", v.Type())
	}
	if b == nil {
		v.SetBytes(nil)
		return nil
	}
	bs, err := scanBytes(b)
	if err != nil {
		return err
	}
	v.SetBytes(bs)
	return nil
}

func scanSQLScannerValue(v reflect.Value, b []byte) error {
	if b == nil {
		if v.IsNil() {
			return nil
		}
		return scanSQLScanner(v.Interface().(sql.Scanner), nil)
	}
	if v.IsNil() {
		v.Set(reflect.New(v.Type().Elem()))
	}
	return scanSQLScanner(v.Interface().(sql.Scanner), b)
}

func scanSQLScannerAddrValue(v reflect.Value, b []byte) error {
	if !v.CanAddr() {
		return internal.Errorf("pg: Scan(non-pointer %s)", v.Type())
	}
	return scanSQLScanner(v.Addr().Interface().(sql.Scanner), b)
}
<|endoftext|>


<commit_before>package query

import (
	"fmt"

	"github.com/mithrandie/csvq/lib/cmd"
	"github.com/mithrandie/csvq/lib/parser"
	"github.com/mithrandie/csvq/lib/ternary"
)

type Procedure struct {
	Filter    *Filter
	ReturnVal parser.Primary
}

func NewProcedure() *Procedure {
	return &Procedure{
		Filter: NewEmptyFilter(),
	}
}

func (proc *Procedure) NewChildProcedure() *Procedure {
	return &Procedure{
		Filter: proc.Filter.CreateChildScope(),
	}
}

func (proc *Procedure) ExecuteChild(statements []parser.Statement) (StatementFlow, error) {
	child := proc.NewChildProcedure()
	f, err := child.Execute(statements)
	return f, err
}

func (proc *Procedure) Execute(statements []parser.Statement) (StatementFlow, error) {
	flow := TERMINATE

	for _, stmt := range statements {
		f, err := proc.ExecuteStatement(stmt)
		if err != nil {
			return f, err
		}
		if f != TERMINATE {
			flow = f
			break
		}
	}
	return flow, nil
}

func (proc *Procedure) ExecuteStatement(stmt parser.Statement) (StatementFlow, error) {
	flow := TERMINATE

	var err error

	var results []Result
	var view *View
	var views []*View
	var printstr string

	switch stmt.(type) {
	case parser.SetFlag:
		err = SetFlag(stmt.(parser.SetFlag))
	case parser.VariableDeclaration:
		err = proc.Filter.VariablesList.Declare(stmt.(parser.VariableDeclaration), proc.Filter)
	case parser.VariableSubstitution:
		_, err = proc.Filter.Evaluate(stmt.(parser.QueryExpression))
	case parser.DisposeVariable:
		err = proc.Filter.VariablesList.Dispose(stmt.(parser.DisposeVariable).Variable)
	case parser.CursorDeclaration:
		err = proc.Filter.CursorsList.Declare(stmt.(parser.CursorDeclaration))
	case parser.OpenCursor:
		err = proc.Filter.CursorsList.Open(stmt.(parser.OpenCursor).Cursor, proc.Filter)
	case parser.CloseCursor:
		err = proc.Filter.CursorsList.Close(stmt.(parser.CloseCursor).Cursor)
	case parser.DisposeCursor:
		err = proc.Filter.CursorsList.Dispose(stmt.(parser.DisposeCursor).Cursor)
	case parser.FetchCursor:
		fetch := stmt.(parser.FetchCursor)
		_, err = FetchCursor(fetch.Cursor, fetch.Position, fetch.Variables, proc.Filter)
	case parser.TableDeclaration:
		err = DeclareTable(stmt.(parser.TableDeclaration), proc.Filter)
	case parser.DisposeTable:
		err = proc.Filter.TempViewsList.Dispose(stmt.(parser.DisposeTable).Table)
	case parser.FunctionDeclaration:
		err = proc.Filter.FunctionsList.Declare(stmt.(parser.FunctionDeclaration))
	case parser.AggregateDeclaration:
		err = proc.Filter.FunctionsList.DeclareAggregate(stmt.(parser.AggregateDeclaration))
	case parser.SelectQuery:
		if view, err = Select(stmt.(parser.SelectQuery), proc.Filter); err == nil {
			flags := cmd.GetFlags()
			var viewstr string
			var lineBreak = cmd.LF
			if 0 < len(flags.OutFile) {
				lineBreak = flags.LineBreak
			}
			viewstr, err = EncodeView(view, flags.Format, flags.WriteDelimiter, flags.WithoutHeader, flags.WriteEncoding, lineBreak)
			if err == nil {
				if 0 < len(flags.OutFile) {
					AddSelectLog(viewstr)
				} else {
					Log(viewstr, false)
				}
			}
		}
	case parser.InsertQuery:
		if view, err = Insert(stmt.(parser.InsertQuery), proc.Filter); err == nil {
			results = []Result{
				{
					Type:          INSERT,
					FileInfo:      view.FileInfo,
					OperatedCount: view.OperatedRecords,
				},
			}
			Log(fmt.Sprintf("%s inserted on %q.", FormatCount(view.OperatedRecords, "record"), view.FileInfo.Path), cmd.GetFlags().Silent)

			view.OperatedRecords = 0
		}
	case parser.UpdateQuery:
		if views, err = Update(stmt.(parser.UpdateQuery), proc.Filter); err == nil {
			results = make([]Result, len(views))
			for i, v := range views {
				results[i] = Result{
					Type:          UPDATE,
					FileInfo:      v.FileInfo,
					OperatedCount: v.OperatedRecords,
				}
				Log(fmt.Sprintf("%s updated on %q.", FormatCount(v.OperatedRecords, "record"), v.FileInfo.Path), cmd.GetFlags().Silent)

				v.OperatedRecords = 0
			}
		}
	case parser.DeleteQuery:
		if views, err = Delete(stmt.(parser.DeleteQuery), proc.Filter); err == nil {
			results = make([]Result, len(views))
			for i, v := range views {
				results[i] = Result{
					Type:          DELETE,
					FileInfo:      v.FileInfo,
					OperatedCount: v.OperatedRecords,
				}
				Log(fmt.Sprintf("%s deleted on %q.", FormatCount(v.OperatedRecords, "record"), v.FileInfo.Path), cmd.GetFlags().Silent)

				v.OperatedRecords = 0
			}
		}
	case parser.CreateTable:
		if view, err = CreateTable(stmt.(parser.CreateTable), proc.Filter); err == nil {
			results = []Result{
				{
					Type:     CREATE_TABLE,
					FileInfo: view.FileInfo,
				},
			}
			Log(fmt.Sprintf("file %q is created.", view.FileInfo.Path), cmd.GetFlags().Silent)

			view.OperatedRecords = 0
		}
	case parser.AddColumns:
		if view, err = AddColumns(stmt.(parser.AddColumns), proc.Filter); err == nil {
			results = []Result{
				{
					Type:          ADD_COLUMNS,
					FileInfo:      view.FileInfo,
					OperatedCount: view.OperatedFields,
				},
			}
			Log(fmt.Sprintf("%s added on %q.", FormatCount(view.OperatedFields, "field"), view.FileInfo.Path), cmd.GetFlags().Silent)

			view.OperatedRecords = 0
		}
	case parser.DropColumns:
		if view, err = DropColumns(stmt.(parser.DropColumns), proc.Filter); err == nil {
			results = []Result{
				{
					Type:          DROP_COLUMNS,
					FileInfo:      view.FileInfo,
					OperatedCount: view.OperatedFields,
				},
			}
			Log(fmt.Sprintf("%s dropped on %q.", FormatCount(view.OperatedFields, "field"), view.FileInfo.Path), cmd.GetFlags().Silent)

			view.OperatedRecords = 0
		}
	case parser.RenameColumn:
		if view, err = RenameColumn(stmt.(parser.RenameColumn), proc.Filter); err == nil {
			results = []Result{
				{
					Type:          RENAME_COLUMN,
					FileInfo:      view.FileInfo,
					OperatedCount: view.OperatedFields,
				},
			}
			Log(fmt.Sprintf("%s renamed on %q.", FormatCount(view.OperatedFields, "field"), view.FileInfo.Path), cmd.GetFlags().Silent)

			view.OperatedRecords = 0
		}
	case parser.TransactionControl:
		switch stmt.(parser.TransactionControl).Token {
		case parser.COMMIT:
			err = proc.Commit(stmt.(parser.Expression))
		case parser.ROLLBACK:
			proc.Rollback()
		}
	case parser.FlowControl:
		switch stmt.(parser.FlowControl).Token {
		case parser.CONTINUE:
			flow = CONTINUE
		case parser.BREAK:
			flow = BREAK
		}
	case parser.Exit:
		ex := stmt.(parser.Exit)
		code := 0
		if ex.Code != nil {
			code = int(ex.Code.(parser.Integer).Value())
		}
		if 0 < code {
			flow = ERROR
			err = NewExit(code)
		} else {
			flow = EXIT
		}
	case parser.Return:
		var ret parser.Primary
		if ret, err = proc.Filter.Evaluate(stmt.(parser.Return).Value); err == nil {
			proc.ReturnVal = ret
			flow = RETURN
		}
	case parser.If:
		flow, err = proc.IfStmt(stmt.(parser.If))
	case parser.Case:
		flow, err = proc.Case(stmt.(parser.Case))
	case parser.While:
		flow, err = proc.While(stmt.(parser.While))
	case parser.WhileInCursor:
		flow, err = proc.WhileInCursor(stmt.(parser.WhileInCursor))
	case parser.Print:
		if printstr, err = Print(stmt.(parser.Print), proc.Filter); err == nil {
			Log(printstr, cmd.GetFlags().Silent)
		}
	case parser.Function:
		_, err = proc.Filter.Evaluate(stmt.(parser.Function))
	case parser.Printf:
		if printstr, err = Printf(stmt.(parser.Printf), proc.Filter); err == nil {
			Log(printstr, cmd.GetFlags().Silent)
		}
	case parser.Source:
		var externalStatements []parser.Statement
		source := stmt.(parser.Source)
		if externalStatements, err = Source(source, proc.Filter); err == nil {
			flow, err = proc.Execute(externalStatements)
		}
	case parser.Trigger:
		trigger := stmt.(parser.Trigger)
		switch trigger.Token {
		case parser.ERROR:
			var message string
			if trigger.Message != nil {
				if pt, ok := trigger.Message.(parser.PrimitiveType); ok && trigger.Code == nil && pt.IsInteger() {
					trigger.Code = pt.Value
				} else {
					var p parser.Primary
					if p, err = proc.Filter.Evaluate(trigger.Message); err == nil {
						if s := parser.PrimaryToString(p); !parser.IsNull(s) {
							message = s.(parser.String).Value()
						}
					}
				}
			}
			if err == nil {
				err = NewUserTriggeredError(trigger, message)
			}
		}
	}

	if results != nil {
		Results = append(Results, results...)
	}

	if err != nil {
		flow = ERROR
	}
	return flow, err
}

func (proc *Procedure) IfStmt(stmt parser.If) (StatementFlow, error) {
	stmts := make([]parser.ElseIf, len(stmt.ElseIf)+1)
	stmts[0] = parser.ElseIf{
		Condition:  stmt.Condition,
		Statements: stmt.Statements,
	}
	for i, v := range stmt.ElseIf {
		stmts[i+1] = v.(parser.ElseIf)
	}

	for _, v := range stmts {
		p, err := proc.Filter.Evaluate(v.Condition)
		if err != nil {
			return ERROR, err
		}
		if p.Ternary() == ternary.TRUE {
			return proc.ExecuteChild(v.Statements)
		}
	}

	if stmt.Else != nil {
		return proc.ExecuteChild(stmt.Else.(parser.Else).Statements)
	}
	return TERMINATE, nil
}

func (proc *Procedure) Case(stmt parser.Case) (StatementFlow, error) {
	var value parser.Primary
	var err error
	if stmt.Value != nil {
		value, err = proc.Filter.Evaluate(stmt.Value)
		if err != nil {
			return ERROR, err
		}
	}

	for _, v := range stmt.When {
		when := v.(parser.CaseWhen)
		var t ternary.Value

		cond, err := proc.Filter.Evaluate(when.Condition)
		if err != nil {
			return ERROR, err
		}

		if value == nil {
			t = cond.Ternary()
		} else {
			t = EqualTo(value, cond)
		}

		if t == ternary.TRUE {
			return proc.ExecuteChild(when.Statements)
		}
	}

	if stmt.Else == nil {
		return TERMINATE, nil
	}
	return proc.ExecuteChild(stmt.Else.(parser.CaseElse).Statements)
}

func (proc *Procedure) While(stmt parser.While) (StatementFlow, error) {
	for {
		p, err := proc.Filter.Evaluate(stmt.Condition)
		if err != nil {
			return ERROR, err
		}
		if p.Ternary() != ternary.TRUE {
			break
		}
		f, err := proc.ExecuteChild(stmt.Statements)
		if err != nil {
			return ERROR, err
		}

		if f == BREAK {
			return TERMINATE, nil
		}
		if f == EXIT {
			return EXIT, nil
		}
	}
	return TERMINATE, nil
}

func (proc *Procedure) WhileInCursor(stmt parser.WhileInCursor) (StatementFlow, error) {
	for {
		success, err := FetchCursor(stmt.Cursor, nil, stmt.Variables, proc.Filter)
		if err != nil {
			return ERROR, err
		}
		if !success {
			break
		}

		f, err := proc.ExecuteChild(stmt.Statements)
		if err != nil {
			return ERROR, err
		}

		if f == BREAK {
			return TERMINATE, nil
		}
		if f == EXIT {
			return EXIT, nil
		}
	}

	return TERMINATE, nil
}

func (proc *Procedure) Commit(expr parser.Expression) error {
	var createFiles = map[string]*FileInfo{}
	var updateFiles = map[string]*FileInfo{}

	for _, result := range Results {
		if result.FileInfo != nil {
			switch result.Type {
			case CREATE_TABLE:
				createFiles[result.FileInfo.Path] = result.FileInfo
			default:
				if !result.FileInfo.IsTemporary && 0 < result.OperatedCount {
					if _, ok := createFiles[result.FileInfo.Path]; !ok {
						if _, ok := updateFiles[result.FileInfo.Path]; !ok {
							updateFiles[result.FileInfo.Path] = result.FileInfo
						}
					}
				}
			}
		}
	}

	var modified bool

	if 0 < len(createFiles) {
		for filename, fileinfo := range createFiles {
			view, _ := ViewCache.Get(parser.Identifier{Literal: filename})
			viewstr, err := EncodeView(view, cmd.CSV, fileinfo.Delimiter, false, fileinfo.Encoding, fileinfo.LineBreak)
			if err != nil {
				return err
			}

			if err = cmd.CreateFile(filename, viewstr); err != nil {
				if expr == nil {
					return NewAutoCommitError(err.Error())
				}
				return NewWriteFileError(expr, err.Error())
			}
			Log(fmt.Sprintf("Commit: file %q is created.", filename), cmd.GetFlags().Silent)
			if !modified {
				modified = true
			}
		}
	}

	if 0 < len(updateFiles) {
		for filename, fileinfo := range updateFiles {
			view, _ := ViewCache.Get(parser.Identifier{Literal: filename})
			viewstr, err := EncodeView(view, cmd.CSV, fileinfo.Delimiter, fileinfo.NoHeader, fileinfo.Encoding, fileinfo.LineBreak)
			if err != nil {
				return err
			}

			if err = cmd.UpdateFile(filename, viewstr); err != nil {
				if expr == nil {
					return NewAutoCommitError(err.Error())
				}
				return NewWriteFileError(expr, err.Error())
			}
			Log(fmt.Sprintf("Commit: file %q is updated.", filename), cmd.GetFlags().Silent)
			if !modified {
				modified = true
			}
		}
	}

	Results = []Result{}
	ViewCache.Clear()

	return nil
}

func (proc *Procedure) Rollback() {
	Results = []Result{}
	ViewCache.Clear()
	proc.Filter.TempViewsList.Rollback()

	Log("Rolled back.", cmd.GetFlags().Silent)
	return
}
<commit_msg>Fix a bug of silent option.<commit_after>package query

import (
	"fmt"

	"github.com/mithrandie/csvq/lib/cmd"
	"github.com/mithrandie/csvq/lib/parser"
	"github.com/mithrandie/csvq/lib/ternary"
)

type Procedure struct {
	Filter    *Filter
	ReturnVal parser.Primary
}

func NewProcedure() *Procedure {
	return &Procedure{
		Filter: NewEmptyFilter(),
	}
}

func (proc *Procedure) NewChildProcedure() *Procedure {
	return &Procedure{
		Filter: proc.Filter.CreateChildScope(),
	}
}

func (proc *Procedure) ExecuteChild(statements []parser.Statement) (StatementFlow, error) {
	child := proc.NewChildProcedure()
	f, err := child.Execute(statements)
	return f, err
}

func (proc *Procedure) Execute(statements []parser.Statement) (StatementFlow, error) {
	flow := TERMINATE

	for _, stmt := range statements {
		f, err := proc.ExecuteStatement(stmt)
		if err != nil {
			return f, err
		}
		if f != TERMINATE {
			flow = f
			break
		}
	}
	return flow, nil
}

func (proc *Procedure) ExecuteStatement(stmt parser.Statement) (StatementFlow, error) {
	flow := TERMINATE

	var err error

	var results []Result
	var view *View
	var views []*View
	var printstr string

	switch stmt.(type) {
	case parser.SetFlag:
		err = SetFlag(stmt.(parser.SetFlag))
	case parser.VariableDeclaration:
		err = proc.Filter.VariablesList.Declare(stmt.(parser.VariableDeclaration), proc.Filter)
	case parser.VariableSubstitution:
		_, err = proc.Filter.Evaluate(stmt.(parser.QueryExpression))
	case parser.DisposeVariable:
		err = proc.Filter.VariablesList.Dispose(stmt.(parser.DisposeVariable).Variable)
	case parser.CursorDeclaration:
		err = proc.Filter.CursorsList.Declare(stmt.(parser.CursorDeclaration))
	case parser.OpenCursor:
		err = proc.Filter.CursorsList.Open(stmt.(parser.OpenCursor).Cursor, proc.Filter)
	case parser.CloseCursor:
		err = proc.Filter.CursorsList.Close(stmt.(parser.CloseCursor).Cursor)
	case parser.DisposeCursor:
		err = proc.Filter.CursorsList.Dispose(stmt.(parser.DisposeCursor).Cursor)
	case parser.FetchCursor:
		fetch := stmt.(parser.FetchCursor)
		_, err = FetchCursor(fetch.Cursor, fetch.Position, fetch.Variables, proc.Filter)
	case parser.TableDeclaration:
		err = DeclareTable(stmt.(parser.TableDeclaration), proc.Filter)
	case parser.DisposeTable:
		err = proc.Filter.TempViewsList.Dispose(stmt.(parser.DisposeTable).Table)
	case parser.FunctionDeclaration:
		err = proc.Filter.FunctionsList.Declare(stmt.(parser.FunctionDeclaration))
	case parser.AggregateDeclaration:
		err = proc.Filter.FunctionsList.DeclareAggregate(stmt.(parser.AggregateDeclaration))
	case parser.SelectQuery:
		if view, err = Select(stmt.(parser.SelectQuery), proc.Filter); err == nil {
			flags := cmd.GetFlags()
			var viewstr string
			var lineBreak = cmd.LF
			if 0 < len(flags.OutFile) {
				lineBreak = flags.LineBreak
			}
			viewstr, err = EncodeView(view, flags.Format, flags.WriteDelimiter, flags.WithoutHeader, flags.WriteEncoding, lineBreak)
			if err == nil {
				if 0 < len(flags.OutFile) {
					AddSelectLog(viewstr)
				} else {
					Log(viewstr, false)
				}
			}
		}
	case parser.InsertQuery:
		if view, err = Insert(stmt.(parser.InsertQuery), proc.Filter); err == nil {
			results = []Result{
				{
					Type:          INSERT,
					FileInfo:      view.FileInfo,
					OperatedCount: view.OperatedRecords,
				},
			}
			Log(fmt.Sprintf("%s inserted on %q.", FormatCount(view.OperatedRecords, "record"), view.FileInfo.Path), cmd.GetFlags().Silent)

			view.OperatedRecords = 0
		}
	case parser.UpdateQuery:
		if views, err = Update(stmt.(parser.UpdateQuery), proc.Filter); err == nil {
			results = make([]Result, len(views))
			for i, v := range views {
				results[i] = Result{
					Type:          UPDATE,
					FileInfo:      v.FileInfo,
					OperatedCount: v.OperatedRecords,
				}
				Log(fmt.Sprintf("%s updated on %q.", FormatCount(v.OperatedRecords, "record"), v.FileInfo.Path), cmd.GetFlags().Silent)

				v.OperatedRecords = 0
			}
		}
	case parser.DeleteQuery:
		if views, err = Delete(stmt.(parser.DeleteQuery), proc.Filter); err == nil {
			results = make([]Result, len(views))
			for i, v := range views {
				results[i] = Result{
					Type:          DELETE,
					FileInfo:      v.FileInfo,
					OperatedCount: v.OperatedRecords,
				}
				Log(fmt.Sprintf("%s deleted on %q.", FormatCount(v.OperatedRecords, "record"), v.FileInfo.Path), cmd.GetFlags().Silent)

				v.OperatedRecords = 0
			}
		}
	case parser.CreateTable:
		if view, err = CreateTable(stmt.(parser.CreateTable), proc.Filter); err == nil {
			results = []Result{
				{
					Type:     CREATE_TABLE,
					FileInfo: view.FileInfo,
				},
			}
			Log(fmt.Sprintf("file %q is created.", view.FileInfo.Path), cmd.GetFlags().Silent)

			view.OperatedRecords = 0
		}
	case parser.AddColumns:
		if view, err = AddColumns(stmt.(parser.AddColumns), proc.Filter); err == nil {
			results = []Result{
				{
					Type:          ADD_COLUMNS,
					FileInfo:      view.FileInfo,
					OperatedCount: view.OperatedFields,
				},
			}
			Log(fmt.Sprintf("%s added on %q.", FormatCount(view.OperatedFields, "field"), view.FileInfo.Path), cmd.GetFlags().Silent)

			view.OperatedRecords = 0
		}
	case parser.DropColumns:
		if view, err = DropColumns(stmt.(parser.DropColumns), proc.Filter); err == nil {
			results = []Result{
				{
					Type:          DROP_COLUMNS,
					FileInfo:      view.FileInfo,
					OperatedCount: view.OperatedFields,
				},
			}
			Log(fmt.Sprintf("%s dropped on %q.", FormatCount(view.OperatedFields, "field"), view.FileInfo.Path), cmd.GetFlags().Silent)

			view.OperatedRecords = 0
		}
	case parser.RenameColumn:
		if view, err = RenameColumn(stmt.(parser.RenameColumn), proc.Filter); err == nil {
			results = []Result{
				{
					Type:          RENAME_COLUMN,
					FileInfo:      view.FileInfo,
					OperatedCount: view.OperatedFields,
				},
			}
			Log(fmt.Sprintf("%s renamed on %q.", FormatCount(view.OperatedFields, "field"), view.FileInfo.Path), cmd.GetFlags().Silent)

			view.OperatedRecords = 0
		}
	case parser.TransactionControl:
		switch stmt.(parser.TransactionControl).Token {
		case parser.COMMIT:
			err = proc.Commit(stmt.(parser.Expression))
		case parser.ROLLBACK:
			proc.Rollback()
		}
	case parser.FlowControl:
		switch stmt.(parser.FlowControl).Token {
		case parser.CONTINUE:
			flow = CONTINUE
		case parser.BREAK:
			flow = BREAK
		}
	case parser.Exit:
		ex := stmt.(parser.Exit)
		code := 0
		if ex.Code != nil {
			code = int(ex.Code.(parser.Integer).Value())
		}
		if 0 < code {
			flow = ERROR
			err = NewExit(code)
		} else {
			flow = EXIT
		}
	case parser.Return:
		var ret parser.Primary
		if ret, err = proc.Filter.Evaluate(stmt.(parser.Return).Value); err == nil {
			proc.ReturnVal = ret
			flow = RETURN
		}
	case parser.If:
		flow, err = proc.IfStmt(stmt.(parser.If))
	case parser.Case:
		flow, err = proc.Case(stmt.(parser.Case))
	case parser.While:
		flow, err = proc.While(stmt.(parser.While))
	case parser.WhileInCursor:
		flow, err = proc.WhileInCursor(stmt.(parser.WhileInCursor))
	case parser.Print:
		if printstr, err = Print(stmt.(parser.Print), proc.Filter); err == nil {
			Log(printstr, false)
		}
	case parser.Function:
		_, err = proc.Filter.Evaluate(stmt.(parser.Function))
	case parser.Printf:
		if printstr, err = Printf(stmt.(parser.Printf), proc.Filter); err == nil {
			Log(printstr, false)
		}
	case parser.Source:
		var externalStatements []parser.Statement
		source := stmt.(parser.Source)
		if externalStatements, err = Source(source, proc.Filter); err == nil {
			flow, err = proc.Execute(externalStatements)
		}
	case parser.Trigger:
		trigger := stmt.(parser.Trigger)
		switch trigger.Token {
		case parser.ERROR:
			var message string
			if trigger.Message != nil {
				if pt, ok := trigger.Message.(parser.PrimitiveType); ok && trigger.Code == nil && pt.IsInteger() {
					trigger.Code = pt.Value
				} else {
					var p parser.Primary
					if p, err = proc.Filter.Evaluate(trigger.Message); err == nil {
						if s := parser.PrimaryToString(p); !parser.IsNull(s) {
							message = s.(parser.String).Value()
						}
					}
				}
			}
			if err == nil {
				err = NewUserTriggeredError(trigger, message)
			}
		}
	}

	if results != nil {
		Results = append(Results, results...)
	}

	if err != nil {
		flow = ERROR
	}
	return flow, err
}

func (proc *Procedure) IfStmt(stmt parser.If) (StatementFlow, error) {
	stmts := make([]parser.ElseIf, len(stmt.ElseIf)+1)
	stmts[0] = parser.ElseIf{
		Condition:  stmt.Condition,
		Statements: stmt.Statements,
	}
	for i, v := range stmt.ElseIf {
		stmts[i+1] = v.(parser.ElseIf)
	}

	for _, v := range stmts {
		p, err := proc.Filter.Evaluate(v.Condition)
		if err != nil {
			return ERROR, err
		}
		if p.Ternary() == ternary.TRUE {
			return proc.ExecuteChild(v.Statements)
		}
	}

	if stmt.Else != nil {
		return proc.ExecuteChild(stmt.Else.(parser.Else).Statements)
	}
	return TERMINATE, nil
}

func (proc *Procedure) Case(stmt parser.Case) (StatementFlow, error) {
	var value parser.Primary
	var err error
	if stmt.Value != nil {
		value, err = proc.Filter.Evaluate(stmt.Value)
		if err != nil {
			return ERROR, err
		}
	}

	for _, v := range stmt.When {
		when := v.(parser.CaseWhen)
		var t ternary.Value

		cond, err := proc.Filter.Evaluate(when.Condition)
		if err != nil {
			return ERROR, err
		}

		if value == nil {
			t = cond.Ternary()
		} else {
			t = EqualTo(value, cond)
		}

		if t == ternary.TRUE {
			return proc.ExecuteChild(when.Statements)
		}
	}

	if stmt.Else == nil {
		return TERMINATE, nil
	}
	return proc.ExecuteChild(stmt.Else.(parser.CaseElse).Statements)
}

func (proc *Procedure) While(stmt parser.While) (StatementFlow, error) {
	for {
		p, err := proc.Filter.Evaluate(stmt.Condition)
		if err != nil {
			return ERROR, err
		}
		if p.Ternary() != ternary.TRUE {
			break
		}
		f, err := proc.ExecuteChild(stmt.Statements)
		if err != nil {
			return ERROR, err
		}

		if f == BREAK {
			return TERMINATE, nil
		}
		if f == EXIT {
			return EXIT, nil
		}
	}
	return TERMINATE, nil
}

func (proc *Procedure) WhileInCursor(stmt parser.WhileInCursor) (StatementFlow, error) {
	for {
		success, err := FetchCursor(stmt.Cursor, nil, stmt.Variables, proc.Filter)
		if err != nil {
			return ERROR, err
		}
		if !success {
			break
		}

		f, err := proc.ExecuteChild(stmt.Statements)
		if err != nil {
			return ERROR, err
		}

		if f == BREAK {
			return TERMINATE, nil
		}
		if f == EXIT {
			return EXIT, nil
		}
	}

	return TERMINATE, nil
}

func (proc *Procedure) Commit(expr parser.Expression) error {
	var createFiles = map[string]*FileInfo{}
	var updateFiles = map[string]*FileInfo{}

	for _, result := range Results {
		if result.FileInfo != nil {
			switch result.Type {
			case CREATE_TABLE:
				createFiles[result.FileInfo.Path] = result.FileInfo
			default:
				if !result.FileInfo.IsTemporary && 0 < result.OperatedCount {
					if _, ok := createFiles[result.FileInfo.Path]; !ok {
						if _, ok := updateFiles[result.FileInfo.Path]; !ok {
							updateFiles[result.FileInfo.Path] = result.FileInfo
						}
					}
				}
			}
		}
	}

	var modified bool

	if 0 < len(createFiles) {
		for filename, fileinfo := range createFiles {
			view, _ := ViewCache.Get(parser.Identifier{Literal: filename})
			viewstr, err := EncodeView(view, cmd.CSV, fileinfo.Delimiter, false, fileinfo.Encoding, fileinfo.LineBreak)
			if err != nil {
				return err
			}

			if err = cmd.CreateFile(filename, viewstr); err != nil {
				if expr == nil {
					return NewAutoCommitError(err.Error())
				}
				return NewWriteFileError(expr, err.Error())
			}
			Log(fmt.Sprintf("Commit: file %q is created.", filename), cmd.GetFlags().Silent)
			if !modified {
				modified = true
			}
		}
	}

	if 0 < len(updateFiles) {
		for filename, fileinfo := range updateFiles {
			view, _ := ViewCache.Get(parser.Identifier{Literal: filename})
			viewstr, err := EncodeView(view, cmd.CSV, fileinfo.Delimiter, fileinfo.NoHeader, fileinfo.Encoding, fileinfo.LineBreak)
			if err != nil {
				return err
			}

			if err = cmd.UpdateFile(filename, viewstr); err != nil {
				if expr == nil {
					return NewAutoCommitError(err.Error())
				}
				return NewWriteFileError(expr, err.Error())
			}
			Log(fmt.Sprintf("Commit: file %q is updated.", filename), cmd.GetFlags().Silent)
			if !modified {
				modified = true
			}
		}
	}

	Results = []Result{}
	ViewCache.Clear()

	return nil
}

func (proc *Procedure) Rollback() {
	Results = []Result{}
	ViewCache.Clear()
	proc.Filter.TempViewsList.Rollback()

	Log("Rolled back.", cmd.GetFlags().Silent)
	return
}
<|endoftext|>


<commit_before>package util

import (
	"sync"
)

type BufferPool struct {
	pool sync.Pool
}

func NewBufferPool() *BufferPool {
	return &BufferPool{pool: sync.Pool{
		New: func() interface{} { return make([]byte, 0) },
	}}
}

func (b *BufferPool) Get() []byte {
	return b.pool.Get().([]byte)
}

func (b *BufferPool) Put(buf []byte) {
	b.pool.Put(buf[:0])
}

// BufferPool33 is a pool that returns cap=33 len=0 byte slices
type BufferPool33 struct {
	pool sync.Pool
}

func NewBufferPool33() *BufferPool33 {
	return &BufferPool33{pool: sync.Pool{
		New: func() interface{} { return make([]byte, 0, 33) },
	}}
}

func (b *BufferPool33) Get() []byte {
	return b.pool.Get().([]byte)
}

func (b *BufferPool33) Put(buf []byte) {
	b.pool.Put(buf[:0])
}
<commit_msg>go fmt<commit_after>package util

import (
	"sync"
)

type BufferPool struct {
	pool sync.Pool
}

func NewBufferPool() *BufferPool {
	return &BufferPool{pool: sync.Pool{
		New: func() interface{} { return make([]byte, 0) },
	}}
}

func (b *BufferPool) Get() []byte {
	return b.pool.Get().([]byte)
}

func (b *BufferPool) Put(buf []byte) {
	b.pool.Put(buf[:0])
}

// BufferPool33 is a pool that returns cap=33 len=0 byte slices
type BufferPool33 struct {
	pool sync.Pool
}

func NewBufferPool33() *BufferPool33 {
	return &BufferPool33{pool: sync.Pool{
		New: func() interface{} { return make([]byte, 0, 33) },
	}}
}

func (b *BufferPool33) Get() []byte {
	return b.pool.Get().([]byte)
}

func (b *BufferPool33) Put(buf []byte) {
	b.pool.Put(buf[:0])
}
<|endoftext|>


<commit_before>// Copyright 2016 The Cockroach Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied. See the License for the specific language governing
// permissions and limitations under the License.
//
// Author: Raphael 'kena' Poss (knz@cockroachlabs.com)

package envutil

import (
	"bytes"
	"fmt"
	"os"
	"runtime"
	"strconv"
	"strings"
	"time"

	"github.com/cockroachdb/cockroach/util/humanizeutil"
	"github.com/cockroachdb/cockroach/util/log"
)

type envVarInfo struct {
	consumer string
	present  bool
	value    string
}

var envVarRegistry map[string]envVarInfo

func init() {
	ClearEnvCache()
}

// VarName returns the name of the environment variable
// corresponding to a configuration key or command-line flag name.
func VarName(name string) string {
	return "COCKROACH_" + strings.ToUpper(strings.Replace(name, "-", "_", -1))
}

// getEnv retrieves an environment variable, keeps track of where
// it was accessed, and checks that each environment variable is accessed
// from at most one place.
// The bookkeeping enables a report of all influential environment
// variables with "cockroach debug env". To keep this report useful,
// all relevant environment variables should be read during start up.
func getEnv(name string) (string, bool) {
	_, consumer, _, _ := runtime.Caller(2)
	varName := VarName(name)
	if f, ok := envVarRegistry[varName]; ok {
		if f.consumer != consumer {
			panic("environment variable " + varName + " already used from " + f.consumer)
		}
		return f.value, f.present
	}
	v, found := os.LookupEnv(varName)
	envVarRegistry[varName] = envVarInfo{consumer: consumer, present: found, value: v}
	return v, found
}

// ClearEnvCache clears saved environment values so that
// a new read access the environment again. (Used for testing)
func ClearEnvCache() {
	envVarRegistry = make(map[string]envVarInfo)
}

// GetEnvReport dumps all configuration variables that may have been
// used and their value.
func GetEnvReport() string {
	var b bytes.Buffer
	for k, v := range envVarRegistry {
		if v.present {
			fmt.Fprintf(&b, "%s = %s # %s\n", k, v.value, v.consumer)
		} else {
			fmt.Fprintf(&b, "# %s is not set (read from %s)\n", k, v.consumer)
		}
	}
	return b.String()
}

// GetShellCommand returns a complete command to run with a prefix of the command line.
func GetShellCommand(cmd string) []string {
	if runtime.GOOS == "windows" {
		if shell := os.Getenv("COMSPEC"); len(shell) > 0 {
			return []string{shell, "/C", cmd}
		}
		return []string{`C:\Windows\system32\cmd.exe`, "/C", cmd}
	}
	if shell := os.Getenv("SHELL"); len(shell) > 0 {
		return []string{shell, "-c", cmd}
	}

	return []string{"/bin/sh", "-c", cmd}
}

// EnvOrDefaultString returns the value set by the specified
// environment variable, if any, otherwise the specified default
// value.
func EnvOrDefaultString(name string, value string) string {
	if v, present := getEnv(name); present {
		return v
	}
	return value
}

// EnvOrDefaultBool returns the value set by the specified environment
// variable, if any, otherwise the specified default value.
func EnvOrDefaultBool(name string, value bool) bool {
	if str, present := getEnv(name); present {
		v, err := strconv.ParseBool(str)
		if err != nil {
			log.Errorf("error parsing %s: %s", VarName(name), err)
			return value
		}
		return v
	}
	return value
}

// EnvOrDefaultInt returns the value set by the specified environment
// variable, if any, otherwise the specified default value.
func EnvOrDefaultInt(name string, value int) int {
	if str, present := getEnv(name); present {
		v, err := strconv.ParseInt(str, 0, 0)
		if err != nil {
			log.Errorf("error parsing %s: %s", VarName(name), err)
			return value
		}
		return int(v)
	}
	return value
}

// EnvOrDefaultInt64 returns the value set by the specified environment
// variable, if any, otherwise the specified default value.
func EnvOrDefaultInt64(name string, value int64) int64 {
	if str, present := getEnv(name); present {
		v, err := strconv.ParseInt(str, 0, 64)
		if err != nil {
			log.Errorf("error parsing %s: %s", VarName(name), err)
			return value
		}
		return v
	}
	return value
}

// EnvOrDefaultBytes returns the value set by the specified environment
// variable, if any, otherwise the specified default value.
func EnvOrDefaultBytes(name string, value int64) int64 {
	if str, present := getEnv(name); present {
		v, err := humanizeutil.ParseBytes(str)
		if err != nil {
			log.Errorf("error parsing %s: %s", VarName(name), err)
			return value
		}
		return v
	}
	return value
}

// EnvOrDefaultDuration returns the value set by the specified environment
// variable, if any, otherwise the specified default value.
func EnvOrDefaultDuration(name string, value time.Duration) time.Duration {
	if str, present := getEnv(name); present {
		v, err := time.ParseDuration(str)
		if err != nil {
			log.Errorf("error parsing %s: %s", VarName(name), err)
			return value
		}
		return v
	}
	return value
}
<commit_msg>envutil: silence unused warnings<commit_after>// Copyright 2016 The Cockroach Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied. See the License for the specific language governing
// permissions and limitations under the License.
//
// Author: Raphael 'kena' Poss (knz@cockroachlabs.com)

package envutil

import (
	"bytes"
	"fmt"
	"os"
	"runtime"
	"strconv"
	"strings"
	"time"

	"github.com/cockroachdb/cockroach/util/humanizeutil"
	"github.com/cockroachdb/cockroach/util/log"
)

type envVarInfo struct {
	consumer string
	present  bool
	value    string
}

var envVarRegistry map[string]envVarInfo

func init() {
	ClearEnvCache()
	// Silence unused warnings.
	var _ = EnvOrDefaultBytes("", 0)
	var _ = EnvOrDefaultInt("", 0)
}

// VarName returns the name of the environment variable
// corresponding to a configuration key or command-line flag name.
func VarName(name string) string {
	return "COCKROACH_" + strings.ToUpper(strings.Replace(name, "-", "_", -1))
}

// getEnv retrieves an environment variable, keeps track of where
// it was accessed, and checks that each environment variable is accessed
// from at most one place.
// The bookkeeping enables a report of all influential environment
// variables with "cockroach debug env". To keep this report useful,
// all relevant environment variables should be read during start up.
func getEnv(name string) (string, bool) {
	_, consumer, _, _ := runtime.Caller(2)
	varName := VarName(name)
	if f, ok := envVarRegistry[varName]; ok {
		if f.consumer != consumer {
			panic("environment variable " + varName + " already used from " + f.consumer)
		}
		return f.value, f.present
	}
	v, found := os.LookupEnv(varName)
	envVarRegistry[varName] = envVarInfo{consumer: consumer, present: found, value: v}
	return v, found
}

// ClearEnvCache clears saved environment values so that
// a new read access the environment again. (Used for testing)
func ClearEnvCache() {
	envVarRegistry = make(map[string]envVarInfo)
}

// GetEnvReport dumps all configuration variables that may have been
// used and their value.
func GetEnvReport() string {
	var b bytes.Buffer
	for k, v := range envVarRegistry {
		if v.present {
			fmt.Fprintf(&b, "%s = %s # %s\n", k, v.value, v.consumer)
		} else {
			fmt.Fprintf(&b, "# %s is not set (read from %s)\n", k, v.consumer)
		}
	}
	return b.String()
}

// GetShellCommand returns a complete command to run with a prefix of the command line.
func GetShellCommand(cmd string) []string {
	if runtime.GOOS == "windows" {
		if shell := os.Getenv("COMSPEC"); len(shell) > 0 {
			return []string{shell, "/C", cmd}
		}
		return []string{`C:\Windows\system32\cmd.exe`, "/C", cmd}
	}
	if shell := os.Getenv("SHELL"); len(shell) > 0 {
		return []string{shell, "-c", cmd}
	}

	return []string{"/bin/sh", "-c", cmd}
}

// EnvOrDefaultString returns the value set by the specified
// environment variable, if any, otherwise the specified default
// value.
func EnvOrDefaultString(name string, value string) string {
	if v, present := getEnv(name); present {
		return v
	}
	return value
}

// EnvOrDefaultBool returns the value set by the specified environment
// variable, if any, otherwise the specified default value.
func EnvOrDefaultBool(name string, value bool) bool {
	if str, present := getEnv(name); present {
		v, err := strconv.ParseBool(str)
		if err != nil {
			log.Errorf("error parsing %s: %s", VarName(name), err)
			return value
		}
		return v
	}
	return value
}

// EnvOrDefaultInt returns the value set by the specified environment
// variable, if any, otherwise the specified default value.
func EnvOrDefaultInt(name string, value int) int {
	if str, present := getEnv(name); present {
		v, err := strconv.ParseInt(str, 0, 0)
		if err != nil {
			log.Errorf("error parsing %s: %s", VarName(name), err)
			return value
		}
		return int(v)
	}
	return value
}

// EnvOrDefaultInt64 returns the value set by the specified environment
// variable, if any, otherwise the specified default value.
func EnvOrDefaultInt64(name string, value int64) int64 {
	if str, present := getEnv(name); present {
		v, err := strconv.ParseInt(str, 0, 64)
		if err != nil {
			log.Errorf("error parsing %s: %s", VarName(name), err)
			return value
		}
		return v
	}
	return value
}

// EnvOrDefaultBytes returns the value set by the specified environment
// variable, if any, otherwise the specified default value.
func EnvOrDefaultBytes(name string, value int64) int64 {
	if str, present := getEnv(name); present {
		v, err := humanizeutil.ParseBytes(str)
		if err != nil {
			log.Errorf("error parsing %s: %s", VarName(name), err)
			return value
		}
		return v
	}
	return value
}

// EnvOrDefaultDuration returns the value set by the specified environment
// variable, if any, otherwise the specified default value.
func EnvOrDefaultDuration(name string, value time.Duration) time.Duration {
	if str, present := getEnv(name); present {
		v, err := time.ParseDuration(str)
		if err != nil {
			log.Errorf("error parsing %s: %s", VarName(name), err)
			return value
		}
		return v
	}
	return value
}
<|endoftext|>


<commit_before>/*
  Go Language Raspberry Pi Interface
  (c) Copyright David Thorpe 2016-2018
  All Rights Reserved

  Documentation http://djthorpe.github.io/gopi/
  For Licensing and Usage information, please see LICENSE.md
*/

// Merge multiple incoming events into a single outgoing event channel
package event

import (
	"fmt"
	"reflect"

	"github.com/djthorpe/gopi"
)

////////////////////////////////////////////////////////////////////////////////
// TYPES

// EventMerger represents a way to merge events
type EventMerger struct {
	change chan struct{}
	in     []<-chan gopi.Event
	out    chan<- gopi.Event
}

////////////////////////////////////////////////////////////////////////////////
// NEW

// Create an event merger object and start listening on
// incoming channels
func NewEventMerger(channels ...<-chan gopi.Event) *EventMerger {
	this := new(EventMerger)
	this.change = make(chan struct{})
	this.in = make([]<-chan gopi.Event, len(channels))
	this.out = make(chan<- gopi.Event)
	for i := range channels {
		this.in[i] = channels[i]
	}

	//  Start merger in background
	go this.mergeInBackground()

	return this
}

////////////////////////////////////////////////////////////////////////////////
// PUBLIC METHODS

// Channel returns the output channel
func (this *EventMerger) Channel() chan<- gopi.Event {
	return this.out
}

// Add an input channel
func (this *EventMerger) Add(new_channel <-chan gopi.Event) {
	this.in = append(this.in, new_channel)
	// Signal change
	this.change <- struct{}{}
}

////////////////////////////////////////////////////////////////////////////////
// PRIVATE METHODS

func (this *EventMerger) cases() []reflect.SelectCase {
	cases := make([]reflect.SelectCase, 1, len(this.in)+1)
	// Add the change channel
	cases[0] = reflect.SelectCase{
		Dir:  reflect.SelectRecv,
		Chan: reflect.ValueOf(this.change),
	}
	// Add the remaining channels - ignoring nil channels
	// which have been closed
	for i := range this.in {
		if this.in[i] != nil {
			cases = append(cases, reflect.SelectCase{
				Dir:  reflect.SelectRecv,
				Chan: reflect.ValueOf(this.in[i]),
			})
		}
	}
	// TODO: return nil if all channels closed
	return cases
}

func (this *EventMerger) mergeInBackground() {
	// Continue loop until all in channels are closed
	cases := this.cases()
	for {
		// select - TODO: Cache the cases structure, we don't want to rebuild
		// it everytime a message is received
		chosen, v, ok := reflect.Select(cases)
		if chosen == 0 {
			// We need to reload the cases. If zero then end
			if cases = this.cases(); len(cases) == 0 {
				fmt.Println("FINISHED")
				close(this.out)
				close(this.change)
				return
			} else {
				fmt.Println("RELOAD")
				continue
			}
		} else if ok {
			this.out <- v.Interface().(gopi.Event)
		} else {
			// TODO: Remove channel from list of cases
			fmt.Printf("reflect.Select failed on channel %v\n", chosen-1)
		}
	}
}
<commit_msg>Updated the channel merge code<commit_after>/*
	Go Language Raspberry Pi Interface
	(c) Copyright David Thorpe 2016-2018
	All Rights Reserved

	Documentation http://djthorpe.github.io/gopi/
	For Licensing and Usage information, please see LICENSE.md
*/

// Merge multiple incoming events into one, and fan out to subscribers
package event

import (
	"reflect"

	// Frameworks
	"github.com/djthorpe/gopi"
)

////////////////////////////////////////////////////////////////////////////////
// TYPES

// EventMerger represents a way to merge events
type EventMerger interface {
	gopi.Publisher

	// Add a channel for merging
	Add(<-chan gopi.Event)

	// Close the event merger
	Close()
}

type merger struct {
	// change indicates that the cases need to be reloaded and done
	// indicates the background task is done
	change chan struct{}
	done   chan struct{}

	// all the channels which are being merged
	in []<-chan gopi.Event

	// the pubsub object for fanning out emitted events
	pubsub *PubSub
}

////////////////////////////////////////////////////////////////////////////////
// NEW AND CLOSE

// Create an event merger object and start listening on incoming channels
func NewEventMerger(channels ...<-chan gopi.Event) EventMerger {
	this := new(merger)
	this.change = make(chan struct{})
	this.done = make(chan struct{})
	this.in = make([]<-chan gopi.Event, len(channels))
	this.pubsub = NewPubSub(len(channels))

	// Obtain the channels
	for i := range channels {
		this.in[i] = channels[i]
	}

	// Start merger in background
	go this.mergeInBackground()

	return this
}

////////////////////////////////////////////////////////////////////////////////
// PUBLISHER INTERFACE IMPLEMENTATION

func (this *merger) Subscribe() <-chan gopi.Event {
	return this.pubsub.Subscribe()
}

func (this *merger) Unsubscribe(subscriber <-chan gopi.Event) {
	this.pubsub.Unsubscribe(subscriber)
}

func (this *merger) Emit(evt gopi.Event) {
	this.pubsub.Emit(evt)
}

////////////////////////////////////////////////////////////////////////////////
// EVENTMERGER INTERFACE IMPLEMENTATION

// Add an input channel
func (this *merger) Add(new_channel <-chan gopi.Event) {
	this.in = append(this.in, new_channel)
	// Signal change
	this.change <- gopi.DONE
}

// Close channels and release resources
func (this *merger) Close() {

	// Close the pubsub object
	this.pubsub.Close()
	this.pubsub = nil

	// Empty channels array to be only the change channel and close it
	this.in = this.in[0:1]
	// Close change channel to indicate done
	close(this.change)
	// Wait for done signal
	<-this.done
}

////////////////////////////////////////////////////////////////////////////////
// PRIVATE METHODS

func (this *merger) cases() []reflect.SelectCase {
	cases := make([]reflect.SelectCase, 1, len(this.in)+1)
	// Add the change channel
	cases[0] = reflect.SelectCase{
		Dir:  reflect.SelectRecv,
		Chan: reflect.ValueOf(this.change),
	}
	// Add the remaining channels - ignoring nil channels
	// which have been closed
	for i := range this.in {
		if this.in[i] != nil {
			cases = append(cases, reflect.SelectCase{
				Dir:  reflect.SelectRecv,
				Chan: reflect.ValueOf(this.in[i]),
			})
		}
	}
	// TODO: return nil if all channels closed
	return cases
}

func (this *merger) mergeInBackground() {
	// Continue loop until all in channels are closed
	cases := this.cases()
FOR_LOOP:
	for {
		// Deal with zero cases condition
		if len(cases) == 0 {
			break FOR_LOOP
		}
		// select cases
		i, v, ok := reflect.Select(cases)
		if i == 0 {
			// We need to reload the cases. If zero then end
			if cases = this.cases(); ok == false {
				break FOR_LOOP
			} else {
				// Reload
				continue
			}
		} else if ok {
			this.Emit(v.Interface().(gopi.Event))
		} else {
			// Remove channel from list of cases
			cases = append(cases[:i], cases[i+1:]...)
		}
	}
	// Indicate the background thread is done
	this.done <- gopi.DONE
}
<|endoftext|>


<commit_before>package colonycore

import (
	"github.com/eaciit/dbox"
	"github.com/eaciit/orm/v1"
	"os"
	"path/filepath"
)

type MapChart struct {
	orm.ModelBase
	ID        string `json:"_id"`
	ChartName string `json:"chartName"`
	FileName  string `json:"fileName"`
}

type Chart struct {
	orm.ModelBase
	ID                string          `json:"_id"`
	Outsiders         *Outsiders      `json:"outsiders"`
	Title             string          `json:"title"`
	DataSourceID      string          `json:"dataSourceID"`
	ChartArea         *ChartArea      `json:"chartArea"`
	dataSource        *DataSources    `json:"dataSource"`
	Legend            *Legend         `json:"legend"`
	SeriesDefaultType string          `json:"seriesDefaultType"`
	Series            *Series         `json:"series"`
	ValueAxis         *ValueAxis      `json:"valueAxis"`
	CategoryAxis      []*CategoryAxis `json:"categoryAxis"`
	Tooltip           *Tooltip        `json:"tooltip"`
}

type Outsiders struct {
	WidthMode           string `json:"widthMode"`
	HeightMode          string `json:"heightMode"`
	ValueAxisUseMaxMode bool   `json:"valueAxisUseMaxMode"`
	ValueAxisUseMinMode bool   `json:"valueAxisUseMinMode"`
}

type ChartArea struct {
	Height int `json:"height"`
	Width  int `json:"width"`
}

type DataSources struct {
	data []string
}

type Legend struct {
	Visible bool `json:"visible"`
}

type Series struct {
	Field string `json:"field"`
	Name  string `json:"name"`
	Types bool   `json:"types"`
}

type ValueAxis struct {
	Max            int  `json:"max"`
	Min            int  `json:"min"`
	Types          bool `json:"types"`
	Line           bool `json:"line"`
	MinorGridLines bool `json:"minorGridLines"`
	LabelsRotation int  `json:"labelsRotation"`
}

type CategoryAxis struct {
	Field string `json:"field"`
}

type Tooltip struct {
	Visible  bool   `json:"visible"`
	Template string `json:"template"`
}

func (mc *MapChart) TableName() string {
	return filepath.Join("widget", "mapcharts")
}

func (mc *MapChart) RecordID() interface{} {
	return mc.ID
}

func (mc *MapChart) Get(search string) ([]MapChart, error) {
	var query *dbox.Filter

	if search != "" {
		query = dbox.Contains("_id", search)
	}

	mapchart := []MapChart{}
	cursor, err := Find(new(MapChart), query)
	if err != nil {
		return mapchart, err
	}

	err = cursor.Fetch(&mapchart, 0, false)
	if err != nil {
		return mapchart, err
	}
	defer cursor.Close()
	return mapchart, nil
}

func (mc *MapChart) Delete() error {
	if err := Delete(mc); err != nil {
		return err
	}
	return nil
}

func (c *Chart) TableName() string {
	return filepath.Join("widget", "chart", c.ID)
}

func (c *Chart) RecordID() interface{} {
	return c.ID
}

func (c *Chart) GetById() error {
	if err := Get(c, c.ID); err != nil {
		return err
	}
	return nil
}

func (c *Chart) Save() error {
	newChart := MapChart{}
	mapchart, err := newChart.Get("")
	if err != nil {
		return err
	}

	var isUpdate bool

	for _, eachRaw := range mapchart {
		if eachRaw.FileName == c.ID+".json" {
			eachRaw.ChartName = c.Title
			isUpdate = true
			newChart = eachRaw
		}
	}

	if !isUpdate {
		newChart.ID = c.ID
		newChart.FileName = c.ID + ".json"
		newChart.ChartName = c.Title
	}

	if err := Save(&newChart); err != nil {
		return err
	}

	if err := Save(c); err != nil {
		return err
	}
	return nil
}

func (c *Chart) Remove() error {
	_file := filepath.Join(ConfigPath, "widget", "chart", c.ID+".json")
	if err := os.Remove(_file); err != nil {
		return err
	}
	return nil
}
<commit_msg>Revert "update widget chart model"<commit_after>package colonycore

import (
	"github.com/eaciit/dbox"
	"github.com/eaciit/orm/v1"
	"os"
	"path/filepath"
)

type MapGrid struct {
	orm.ModelBase
	ID       string `json:"_id"`
	GridName string `json:"gridName"`
	FileName string `json:"fileName"`
}

type Grid struct {
	orm.ModelBase
	ID           string             `json:"_id"`
	Title        string             `json:"title"`
	DataSourceID string             `json:"dataSourceID"`
	Aggregate    []*AggregateColumn `json:"aggregate"`
	Outsider     *Outsider          `json:"outsider"`
	PageSize     int                `json:"pageSize"`
	Groupable    bool               `json:"groupable"`
	Sortable     bool               `json:"sortable"`
	Filterable   bool               `json:"filterable"`
	Pageable     *Pageable          `json:"pageable"`
	Columns      []*Column          `json:"columns"`
	ColumnMenu   bool               `json:"columnMenu"`
	Toolbar      []string           `json:"toolbar"`
	Pdf          *ExportGrid        `json:"pdf"`
	Excel        *ExportGrid        `json:"excel"`
}

type AggregateColumn struct {
	Field     string `json:"field"`
	Aggregate string `json:"aggregate"`
}

type Outsider struct {
	VisiblePDF   bool `json:"visiblePDF"`
	VisibleExcel bool `json:"visibleExcel"`
}

type Pageable struct {
	Refresh     bool `json:"refresh"`
	PageSize    bool `json:"pageSize"`
	ButtonCount int  `json:"buttonCount"`
}

type ExportGrid struct {
	AllPages bool   `json:"allPages"`
	FileName string `json:"fileName"`
}

type Column struct {
	Template         string            `json:"template"`
	Field            string            `json:"field"`
	Title            string            `json:"title"`
	Format           string            `json:"format"`
	Width            string            `json:"width"`
	Menu             bool              `json:"menu"`
	HeaderTemplate   string            `json:"headerTemplate"`
	HeaderAttributes *HeaderAttributes `json:"headerAttributes"`
	FooterTemplate   string            `json:"footerTemplate"`
}

type HeaderAttributes struct {
	Class string `json:"class"`
	Style string `json:"style"`
}

func (mg *MapGrid) TableName() string {
	return filepath.Join("widget", "mapgrids")
}

func (mg *MapGrid) RecordID() interface{} {
	return mg.ID
}

func (mg *MapGrid) Get(search string) ([]MapGrid, error) {
	var query *dbox.Filter

	if search != "" {
		query = dbox.Contains("_id", search)
	}

	mapgrid := []MapGrid{}
	cursor, err := Find(new(MapGrid), query)
	if err != nil {
		return mapgrid, err
	}

	err = cursor.Fetch(&mapgrid, 0, false)
	if err != nil {
		return mapgrid, err
	}
	defer cursor.Close()
	return mapgrid, nil
}

func (mg *MapGrid) Delete() error {
	if err := Delete(mg); err != nil {
		return err
	}
	return nil
}

func (g *Grid) TableName() string {
	return filepath.Join("widget", "grid", g.ID)
}

func (g *Grid) RecordID() interface{} {
	return g.ID
}

func (g *Grid) GetById() error {
	if err := Get(g, g.ID); err != nil {
		return err
	}
	return nil
}

func (g *Grid) Save() error {
	newGrid := MapGrid{}
	mapgrid, err := newGrid.Get("")
	if err != nil {
		return err
	}

	var isUpdate bool

	for _, eachRaw := range mapgrid {
		if eachRaw.FileName == g.ID+".json" {
			eachRaw.GridName = g.Title
			isUpdate = true
			newGrid = eachRaw
		}
	}

	if !isUpdate {
		newGrid.ID = g.ID
		newGrid.FileName = g.ID + ".json"
		newGrid.GridName = g.Title
	}

	if err := Save(&newGrid); err != nil {
		return err
	}

	if err := Save(g); err != nil {
		return err
	}
	return nil
}

func (g *Grid) Remove() error {
	_file := filepath.Join(ConfigPath, "widget", "grid", g.ID+".json")
	if err := os.Remove(_file); err != nil {
		return err
	}
	return nil
}
<|endoftext|>


<commit_before>// Copyright 2016 Keybase Inc. All rights reserved.
// Use of this source code is governed by a BSD
// license that can be found in the LICENSE file.

package libfs

import (
	"runtime"
	"strings"
	"sync"
	"time"

	keybase1 "github.com/keybase/client/go/libkb"
	"github.com/keybase/client/go/logger"
	"github.com/keybase/kbfs/libkbfs"
	"golang.org/x/net/context"
)

// Special files in root directory.
const (
	HumanErrorFileName      = "kbfs.error.txt"
	HumanNoLoginFileName    = "kbfs.nologin.txt"
	failureDisplayThreshold = 5 * time.Second
)

// RemoteStatus is for maintaining status of various remote connections like keybase
// service and md-server.
type RemoteStatus struct {
	sync.Mutex
	failingServices   map[string]error
	extraFileName     string
	extraFileContents []byte
	failingSince      time.Time
}

// Init a RemoteStatus and register it with libkbfs.
func (r *RemoteStatus) Init(ctx context.Context, log logger.Logger, config libkbfs.Config) {
	r.failingServices = map[string]error{}
	// A time in the far past that is not IsZero
	r.failingSince.Add(time.Second)
	go r.loop(ctx, log, config)
}

func (r *RemoteStatus) loop(ctx context.Context, log logger.Logger, config libkbfs.Config) {
	for {
		tctx, cancel := context.WithTimeout(ctx, 1*time.Second)
		st, ch, err := config.KBFSOps().Status(tctx)
		// No deferring inside loops, and no panics either here.
		cancel()
		if err != nil {
			log.Warning("KBFS Status failed: %v,%v", st, err)
		}
		r.update(st)
		// Block on the channel or shutdown.
		select {
		case <-ctx.Done():
			return
		case <-ch:
		}
	}
}

func (r *RemoteStatus) update(st libkbfs.KBFSStatus) {
	r.Lock()
	defer r.Unlock()

	r.failingServices = st.FailingServices

	// Select the file name:
	// + Default to an empty name
	// + If all errors are LoginRequiredError then display the nologin filename
	// + If there are any other errors use the generic error file name,
	//   implemented by breaking out of the loop if such an error is encountered.
	fname := ""
	for _, err := range r.failingServices {
		if isNotLoggedInError(err) {
			fname = HumanNoLoginFileName
		} else {
			fname = HumanErrorFileName
			break
		}
	}
	isZeroTime := r.failingSince.IsZero()
	if len(r.failingServices) > 0 {
		if isZeroTime {
			r.failingSince = time.Now()
		}
	} else if !isZeroTime {
		r.failingSince = time.Time{}
	}
	r.extraFileName = fname
	r.extraFileContents = nil
}

func isNotLoggedInError(err error) bool {
	_, ok := err.(keybase1.LoginRequiredError)
	return ok
}

var newline = func() string {
	if runtime.GOOS == "windows" {
		return "\r\n"
	}
	return "\n"
}()

// ExtraFileName returns the extra file name or an empty string for none.
func (r *RemoteStatus) ExtraFileName() string {
	r.Lock()
	defer r.Unlock()

	if r.extraFileName == "" || time.Since(r.failingSince) < failureDisplayThreshold {
		return ""
	}

	return r.extraFileName
}

// ExtraFileNameAndSize returns the extra file name or an empty string for none and the size of the extra file.
func (r *RemoteStatus) ExtraFileNameAndSize() (string, int64) {
	r.Lock()
	defer r.Unlock()

	if r.extraFileName == "" || time.Since(r.failingSince) > failureDisplayThreshold {
		return "", 0
	}

	return r.extraFileName, int64(len(r.humanReadableBytesLocked()))
}

// humanReadableBytesNeedsLock should be called with lock already held.
func (r *RemoteStatus) humanReadableBytesLocked() []byte {
	if r.extraFileContents != nil {
		return r.extraFileContents
	}

	var ss []string
	needLogin := false
	for service, err := range r.failingServices {
		switch err.(type) {
		case *keybase1.LoginRequiredError:
			needLogin = true
		default:
			ss = append(ss, service+": "+err.Error())
		}
	}

	if len(ss) == 0 {
		if needLogin {
			ss = append(ss, "Not logged in")
		} else {
			ss = append(ss, "Everything appears ok")
		}
	}
	ss = append(ss, "")

	res := []byte(strings.Join(ss, newline))
	r.extraFileContents = res
	return res
}

// NewSpecialReadFunc implements a special read file that contains human readable
// current status.
func (r *RemoteStatus) NewSpecialReadFunc(ctx context.Context) ([]byte, time.Time, error) {
	r.Lock()
	defer r.Unlock()

	return r.humanReadableBytesLocked(), time.Time{}, nil
}
<commit_msg>libfs: fix RemoteStatus.ExtraFileNameAndSize<commit_after>// Copyright 2016 Keybase Inc. All rights reserved.
// Use of this source code is governed by a BSD
// license that can be found in the LICENSE file.

package libfs

import (
	"runtime"
	"strings"
	"sync"
	"time"

	keybase1 "github.com/keybase/client/go/libkb"
	"github.com/keybase/client/go/logger"
	"github.com/keybase/kbfs/libkbfs"
	"golang.org/x/net/context"
)

// Special files in root directory.
const (
	HumanErrorFileName      = "kbfs.error.txt"
	HumanNoLoginFileName    = "kbfs.nologin.txt"
	failureDisplayThreshold = 5 * time.Second
)

// RemoteStatus is for maintaining status of various remote connections like keybase
// service and md-server.
type RemoteStatus struct {
	sync.Mutex
	failingServices   map[string]error
	extraFileName     string
	extraFileContents []byte
	failingSince      time.Time
}

// Init a RemoteStatus and register it with libkbfs.
func (r *RemoteStatus) Init(ctx context.Context, log logger.Logger, config libkbfs.Config) {
	r.failingServices = map[string]error{}
	// A time in the far past that is not IsZero
	r.failingSince.Add(time.Second)
	go r.loop(ctx, log, config)
}

func (r *RemoteStatus) loop(ctx context.Context, log logger.Logger, config libkbfs.Config) {
	for {
		tctx, cancel := context.WithTimeout(ctx, 1*time.Second)
		st, ch, err := config.KBFSOps().Status(tctx)
		// No deferring inside loops, and no panics either here.
		cancel()
		if err != nil {
			log.Warning("KBFS Status failed: %v,%v", st, err)
		}
		r.update(st)
		// Block on the channel or shutdown.
		select {
		case <-ctx.Done():
			return
		case <-ch:
		}
	}
}

func (r *RemoteStatus) update(st libkbfs.KBFSStatus) {
	r.Lock()
	defer r.Unlock()

	r.failingServices = st.FailingServices

	// Select the file name:
	// + Default to an empty name
	// + If all errors are LoginRequiredError then display the nologin filename
	// + If there are any other errors use the generic error file name,
	//   implemented by breaking out of the loop if such an error is encountered.
	fname := ""
	for _, err := range r.failingServices {
		if isNotLoggedInError(err) {
			fname = HumanNoLoginFileName
		} else {
			fname = HumanErrorFileName
			break
		}
	}
	isZeroTime := r.failingSince.IsZero()
	if len(r.failingServices) > 0 {
		if isZeroTime {
			r.failingSince = time.Now()
		}
	} else if !isZeroTime {
		r.failingSince = time.Time{}
	}
	r.extraFileName = fname
	r.extraFileContents = nil
}

func isNotLoggedInError(err error) bool {
	_, ok := err.(keybase1.LoginRequiredError)
	return ok
}

var newline = func() string {
	if runtime.GOOS == "windows" {
		return "\r\n"
	}
	return "\n"
}()

// ExtraFileName returns the extra file name or an empty string for none.
func (r *RemoteStatus) ExtraFileName() string {
	r.Lock()
	defer r.Unlock()

	if r.extraFileName == "" || time.Since(r.failingSince) < failureDisplayThreshold {
		return ""
	}

	return r.extraFileName
}

// ExtraFileNameAndSize returns the extra file name or an empty string for none and the size of the extra file.
func (r *RemoteStatus) ExtraFileNameAndSize() (string, int64) {
	r.Lock()
	defer r.Unlock()

	if r.extraFileName == "" || time.Since(r.failingSince) < failureDisplayThreshold {
		return "", 0
	}

	return r.extraFileName, int64(len(r.humanReadableBytesLocked()))
}

// humanReadableBytesNeedsLock should be called with lock already held.
func (r *RemoteStatus) humanReadableBytesLocked() []byte {
	if r.extraFileContents != nil {
		return r.extraFileContents
	}

	var ss []string
	needLogin := false
	for service, err := range r.failingServices {
		switch err.(type) {
		case *keybase1.LoginRequiredError:
			needLogin = true
		default:
			ss = append(ss, service+": "+err.Error())
		}
	}

	if len(ss) == 0 {
		if needLogin {
			ss = append(ss, "Not logged in")
		} else {
			ss = append(ss, "Everything appears ok")
		}
	}
	ss = append(ss, "")

	res := []byte(strings.Join(ss, newline))
	r.extraFileContents = res
	return res
}

// NewSpecialReadFunc implements a special read file that contains human readable
// current status.
func (r *RemoteStatus) NewSpecialReadFunc(ctx context.Context) ([]byte, time.Time, error) {
	r.Lock()
	defer r.Unlock()

	return r.humanReadableBytesLocked(), time.Time{}, nil
}
<|endoftext|>


<commit_before>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package math

// Ldexp is the inverse of Frexp.
// It returns frac × 2**exp.
//
// Special cases are:
//	Ldexp(±0, exp) = ±0
//	Ldexp(±Inf, exp) = ±Inf
//	Ldexp(NaN, exp) = NaN

//extern ldexp
func libc_ldexp(float64, int) float64

func Ldexp(frac float64, exp int) float64 {
	return libc_ldexp(frac, exp)
}

func ldexp(frac float64, exp int) float64 {
	// special cases
	switch {
	case frac == 0:
		return frac // correctly return -0
	case IsInf(frac, 0) || IsNaN(frac):
		return frac
	}
	frac, e := normalize(frac)
	exp += e
	x := Float64bits(frac)
	exp += int(x>>shift)&mask - bias
	if exp < -1074 {
		return Copysign(0, frac) // underflow
	}
	if exp > 1023 { // overflow
		if frac < 0 {
			return Inf(-1)
		}
		return Inf(1)
	}
	var m float64 = 1
	if exp < -1022 { // denormal
		exp += 52
		m = 1.0 / (1 << 52) // 2**-52
	}
	x &^= mask << shift
	x |= uint64(exp+bias) << shift
	return m * Float64frombits(x)
}
<commit_msg>math: Work around bug in Solaris 9 implementation of ldexp.<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package math

// Ldexp is the inverse of Frexp.
// It returns frac × 2**exp.
//
// Special cases are:
//	Ldexp(±0, exp) = ±0
//	Ldexp(±Inf, exp) = ±Inf
//	Ldexp(NaN, exp) = NaN

//extern ldexp
func libc_ldexp(float64, int) float64

func Ldexp(frac float64, exp int) float64 {
	r := libc_ldexp(frac, exp)

	// Work around a bug in the implementation of ldexp on Solaris
	// 9.  If multiplying a negative number by 2 raised to a
	// negative exponent underflows, we want to return negative
	// zero, but the Solaris 9 implementation returns positive
	// zero.  This workaround can be removed when and if we no
	// longer care about Solaris 9.
	if r == 0 && frac < 0 && exp < 0 {
		r = Copysign(0, frac)
	}
	return r
}

func ldexp(frac float64, exp int) float64 {
	// special cases
	switch {
	case frac == 0:
		return frac // correctly return -0
	case IsInf(frac, 0) || IsNaN(frac):
		return frac
	}
	frac, e := normalize(frac)
	exp += e
	x := Float64bits(frac)
	exp += int(x>>shift)&mask - bias
	if exp < -1074 {
		return Copysign(0, frac) // underflow
	}
	if exp > 1023 { // overflow
		if frac < 0 {
			return Inf(-1)
		}
		return Inf(1)
	}
	var m float64 = 1
	if exp < -1022 { // denormal
		exp += 52
		m = 1.0 / (1 << 52) // 2**-52
	}
	x &^= mask << shift
	x |= uint64(exp+bias) << shift
	return m * Float64frombits(x)
}
<|endoftext|>


<commit_before>/****************************************************************************
 * Copyright (c) 2013, Scott Ferguson
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the software nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY SCOTT FERGUSON ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL SCOTT FERGUSON BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ****************************************************************************/

package goat

import (
	"encoding/gob"
	"github.com/gorilla/mux"
	"github.com/gorilla/sessions"
	"labix.org/v2/mgo"
	"labix.org/v2/mgo/bson"
	"net"
	"net/http"
	"net/url"
	"strconv"
)

const (
	GET    = 1 << 0
	POST   = 1 << 1
	PUT    = 1 << 2
	DELETE = 1 << 3

	methodGet    = "GET"
	methodPost   = "POST"
	methodPut    = "PUT"
	methodDelete = "DELETE"
)

type Goat struct {
	Router       *mux.Router
	routes       map[string]*route
	middleware   []Middleware
	dbsession    *mgo.Session
	dbname       string
	sessionstore sessions.Store
	listener     *net.TCPListener
}

type Handler func(http.ResponseWriter, *http.Request, *Context) error

type route struct {
	*Goat
	path        string
	name        string
	handler     Handler
	interceptor Interceptor
}

func (r route) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	var c *Context
	var err error

	if c, err = NewContext(); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
	defer c.Close()

	// Execute Middleware
	for _, m := range r.middleware {
		m(req, c)
	}

	// Execute the handler
	if r.handler != nil {
		err = r.handler(w, req, c)
	} else if r.interceptor != nil {
		rh := r.interceptor(w, req, c)
		err = rh(w, req, c)
	}

	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

func methodList(methods int) (r []string) {
	if methods&GET == GET {
		r = append(r, methodGet)
	}

	if methods&POST == POST {
		r = append(r, methodPost)
	}

	if methods&PUT == PUT {
		r = append(r, methodPut)
	}

	if methods&DELETE == DELETE {
		r = append(r, methodDelete)
	}

	return
}

func NewGoat() *Goat {
	// Initialize session store
	gob.Register(bson.ObjectId(""))
	s := sessions.NewCookieStore([]byte("sevenbyelevensecretbomberboy"))
	r := mux.NewRouter()

	http.Handle("/", r)

	return &Goat{
		Router:       r,
		sessionstore: s,
		routes:       make(map[string]*route),
	}
}

func (g *Goat) RegisterRoute(path, name string, method int, handler interface{}) {
	// Initialize the HTTP router
	r := new(route)
	r.Goat = g
	r.path = path
	r.name = name

	if g.routes[r.name] != nil {
		return
	}

	g.routes[r.name] = r

	if h, ok := handler.(func(http.ResponseWriter, *http.Request, *Context) error); ok {
		r.handler = h
	} else if h, ok := handler.(Handler); ok {
		r.handler = h
	} else if i, ok := handler.(Interceptor); ok {
		r.interceptor = i
	} else if h, ok := handler.(http.Handler); ok {
		g.Router.Handle(path, h)
		return
	} else {
		panic("Unknown handler passed to RegisterRoute")
	}

	methods := methodList(method)
	g.Router.Handle(path, r).Methods(methods...).Name(r.name)
}

func (g *Goat) CloneDB() *mgo.Database {
	return g.dbsession.Clone().DB(g.dbname)
}

func (g *Goat) RegisterStaticFileHandler(remote, local string) {
	// Static file handler
	http.Handle(remote, http.FileServer(http.Dir(local)))
}

func (g *Goat) RegisterMiddleware(m Middleware) {
	g.middleware = append(g.middleware, m)
}

func (g *Goat) Reverse(root string, params ...string) (*url.URL, error) {
	return g.Router.Get(root).URL(params...)
}

func (g *Goat) ListenAndServe(port string) error {
	p := 8080

	if port != "" {
		p, _ = strconv.Atoi(port)
	}

	server := &http.Server{}

	g.listener, _ = net.ListenTCP("tcp", &net.TCPAddr{
		Port: p,
	})

	return server.Serve(g.listener)
}

func (g *Goat) Close() {
	g.listener.Close()
}
<commit_msg>Don't use the default servemux<commit_after>/****************************************************************************
 * Copyright (c) 2013, Scott Ferguson
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the software nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY SCOTT FERGUSON ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL SCOTT FERGUSON BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ****************************************************************************/

package goat

import (
	"encoding/gob"
	"github.com/gorilla/mux"
	"github.com/gorilla/sessions"
	"labix.org/v2/mgo"
	"labix.org/v2/mgo/bson"
	"net"
	"net/http"
	"net/url"
	"strconv"
)

const (
	GET    = 1 << 0
	POST   = 1 << 1
	PUT    = 1 << 2
	DELETE = 1 << 3

	methodGet    = "GET"
	methodPost   = "POST"
	methodPut    = "PUT"
	methodDelete = "DELETE"
)

type Goat struct {
	Router       *mux.Router
	routes       map[string]*route
	middleware   []Middleware
	dbsession    *mgo.Session
	dbname       string
	sessionstore sessions.Store
	listener     *net.TCPListener
	servemux     *http.ServeMux
}

type Handler func(http.ResponseWriter, *http.Request, *Context) error

type route struct {
	*Goat
	path        string
	name        string
	handler     Handler
	interceptor Interceptor
}

func (r route) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	var c *Context
	var err error

	if c, err = NewContext(); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
	defer c.Close()

	// Execute Middleware
	for _, m := range r.middleware {
		m(req, c)
	}

	// Execute the handler
	if r.handler != nil {
		err = r.handler(w, req, c)
	} else if r.interceptor != nil {
		rh := r.interceptor(w, req, c)
		err = rh(w, req, c)
	}

	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

func methodList(methods int) (r []string) {
	if methods&GET == GET {
		r = append(r, methodGet)
	}

	if methods&POST == POST {
		r = append(r, methodPost)
	}

	if methods&PUT == PUT {
		r = append(r, methodPut)
	}

	if methods&DELETE == DELETE {
		r = append(r, methodDelete)
	}

	return
}

func NewGoat() *Goat {
	// Initialize session store
	gob.Register(bson.ObjectId(""))
	s := sessions.NewCookieStore([]byte("sevenbyelevensecretbomberboy"))
	r := mux.NewRouter()

	mx := http.NewServeMux()
	mx.Handle("/", r)

	return &Goat{
		Router:       r,
		sessionstore: s,
		routes:       make(map[string]*route),
		servemux:     mx,
	}
}

func (g *Goat) RegisterRoute(path, name string, method int, handler interface{}) {
	// Initialize the HTTP router
	r := new(route)
	r.Goat = g
	r.path = path
	r.name = name

	if g.routes[r.name] != nil {
		return
	}

	g.routes[r.name] = r

	if h, ok := handler.(func(http.ResponseWriter, *http.Request, *Context) error); ok {
		r.handler = h
	} else if h, ok := handler.(Handler); ok {
		r.handler = h
	} else if i, ok := handler.(Interceptor); ok {
		r.interceptor = i
	} else if h, ok := handler.(http.Handler); ok {
		g.Router.Handle(path, h)
		return
	} else {
		panic("Unknown handler passed to RegisterRoute")
	}

	methods := methodList(method)
	g.Router.Handle(path, r).Methods(methods...).Name(r.name)
}

func (g *Goat) CloneDB() *mgo.Database {
	return g.dbsession.Clone().DB(g.dbname)
}

func (g *Goat) RegisterStaticFileHandler(remote, local string) {
	// Static file handler
	http.Handle(remote, http.FileServer(http.Dir(local)))
}

func (g *Goat) RegisterMiddleware(m Middleware) {
	g.middleware = append(g.middleware, m)
}

func (g *Goat) Reverse(root string, params ...string) (*url.URL, error) {
	return g.Router.Get(root).URL(params...)
}

func (g *Goat) ListenAndServe(port string) error {
	p := 8080

	if port != "" {
		p, _ = strconv.Atoi(port)
	}

	server := &http.Server{
		Handler: g.servemux,
	}

	g.listener, _ = net.ListenTCP("tcp", &net.TCPAddr{
		Port: p,
	})

	return server.Serve(g.listener)
}

func (g *Goat) Close() {
	g.listener.Close()
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"errors"
	"fmt"
	"os"
	"regexp"
	"strconv"
	"strings"
)

// Evaluate an expression
func eval(e interface{}) interface{} {
	switch e := e.(type) {
	case bool, uint64, float64:
		return e
	case string:
		return e
	case []string:
		switch e[0] {
		case "quote": // (quote exp)
			return e[1:]
		case "if": // (if test then else?)
			test := e[1]
			then := e[2]
			else_ := e[3]
			if eval(test).(bool) {
				return eval(then)
			} else {
				return eval(else_)
			}
			// case "def": // (def var exp)
			// case "fn":
			// case "set!": // (set! var exp)
		}
	}
	return e
}

// Read a Scheme expression from a string.
func read(s string) ([]interface{}, error) {
	return (read_from(tokenize(s)))
}

// Converts a string into an array of tokens.
func tokenize(s string) []string {
	return regexp.MustCompile(`\s+`).Split(
		strings.Replace(strings.Replace(s, "(", " ( ", -1), ")", " ) ", -1), -1)
}

// Read an expression from a sequence of tokens.
func read_from(tokens []string) ([]interface{}, error) {
	var token string
	if len(tokens) == 0 {
		return nil, errors.New("unexpected EOF while reading")
	}
	token, tokens = tokens[len(tokens)-1], tokens[:len(tokens)-1]
	switch token {
	case "(":
		l := make([]interface{}, 0)
		for tokens[0] != ")" {
			token, _ := read_from(tokens) // TODO handle err
			l = append(l, token)
		}
		tokens = tokens[:len(tokens)-1]
		return l, nil
	case ")":
		return nil, errors.New("unexpected )")
	}
	return []interface{}{atom(token)}, nil
}

// Bools, ints, and floats are converted; every other token is a symbol.
func atom(s string) interface{} {
	if b, err := strconv.ParseBool(s); (s == "true" || s == "false") && err != nil {
		return b
	}
	if i, err := strconv.ParseUint(s, 0, 64); err != nil {
		return i
	}
	if f, err := strconv.ParseFloat(s, 64); err != nil {
		return f
	}
	return s
}

func prompt() {
	fmt.Print(">>> ")
}

func main() {
	//env := &Env{}

	scanner := bufio.NewScanner(os.Stdin)
	for prompt(); scanner.Scan(); prompt() {
		in := scanner.Text()
		fmt.Println(in)
		parsed, _ := read(in) // TODO handle err
		fmt.Println(eval(parsed))
	}
	if err := scanner.Err(); err != nil {
		fmt.Fprintln(os.Stderr, "reading standard input:", err)
	}
}
<commit_msg>incremental progress<commit_after>package main

import (
	"bufio"
	"errors"
	"fmt"
	"os"
	"regexp"
	"strconv"
	"strings"
)

// Evaluate an expression
func eval(e interface{}) interface{} {
	fmt.Printf("[eval] expression: %v (%T)\n", e, e)
	switch e := e.(type) {
	case string:
		// TODO lookup in env
		return e
	case bool, uint64, float64:
		return e
	case []interface{}:
		switch e[0] {
		case "quote": // (quote exp)
			return e[1:]
		case "if": // (if test then else?)
			test := e[1]
			then := e[2]
			else_ := e[3]
			if eval(test).(bool) {
				return eval(then)
			} else {
				return eval(else_)
			}
			// case "def": // (def var exp)
			// case "fn":
			// case "set!": // (set! var exp)
		}
	}
	return e
}

// Read a Scheme expression from a string.
func read(s string) (interface{}, error) {
	return (read_from(tokenize(s)))
}

// Converts a string into an array of tokens.
func tokenize(s string) []string {
	return regexp.MustCompile(`\s+`).Split(
		strings.Replace(strings.Replace(s, "(", " ( ", -1), ")", " ) ", -1), -1)
}

// Read an expression from a sequence of tokens.
func read_from(tokens []string) (interface{}, error) {
	var token string
	if len(tokens) == 0 {
		return nil, errors.New("unexpected EOF while reading")
	}
	token, tokens = tokens[len(tokens)-1], tokens[:len(tokens)-1]
	switch token {
	case "(":
		L := []interface{}{}
		for tokens[0] != ")" {
			token, _ := read_from(tokens) // TODO handle err
			L = append(L, token)
		}
		tokens = tokens[:len(tokens)-1]
		return L, nil
	case ")":
		return nil, errors.New("unexpected )")
	}
	return atom(token), nil
}

// Bools, ints, and floats are converted; every other token is a symbol.
func atom(s string) interface{} {
	if f, err := strconv.ParseFloat(s, 64); (strings.IndexAny(s, "0123456789") >= 0) && err != nil {
		return f
	}
	if i, err := strconv.ParseUint(s, 0, 64); (strings.IndexAny(s, "0123456789") >= 0) && err != nil {
		return i
	}
	if b, err := strconv.ParseBool(s); (s == "true" || s == "false") && err != nil {
		return b
	}
	return s
}

func prompt() {
	fmt.Print(">>> ")
}

func main() {
	//env := &Env{}

	scanner := bufio.NewScanner(os.Stdin)
	for prompt(); scanner.Scan(); prompt() {
		in := scanner.Text()
		fmt.Println(in)
		parsed, _ := read(in) // TODO handle err
		fmt.Println(eval(parsed))
	}
	if err := scanner.Err(); err != nil {
		fmt.Fprintln(os.Stderr, "reading standard input:", err)
	}
}
<|endoftext|>