text:
// Copyright 2015 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: Peter Mattis (peter@cockroachlabs.com)

package parser

import (
	"bytes"
	"crypto/md5"
	"crypto/sha1"
	"crypto/sha256"
	"encoding/binary"
	"errors"
	"fmt"
	"math"
	"math/rand"
	"net"
	"regexp"
	"regexp/syntax"
	"strconv"
	"strings"
	"time"
	"unicode"
	"unicode/utf8"

	"gopkg.in/inf.v0"

	"github.com/cockroachdb/cockroach/pkg/build"
	"github.com/cockroachdb/cockroach/pkg/roachpb"
	"github.com/cockroachdb/cockroach/pkg/util/decimal"
	"github.com/cockroachdb/cockroach/pkg/util/duration"
	"github.com/cockroachdb/cockroach/pkg/util/encoding"
	"github.com/cockroachdb/cockroach/pkg/util/syncutil"
	"github.com/cockroachdb/cockroach/pkg/util/timeutil"
	"github.com/cockroachdb/cockroach/pkg/util/uuid"
)

var (
	errEmptyInputString = errors.New("the input string must not be empty")
	errAbsOfMinInt64    = errors.New("abs of min integer value (-9223372036854775808) not defined")
	errRoundTooLow      = errors.New("rounding would extend value by more than 2000 decimal digits")
	errArgTooBig        = errors.New("argument value is too large")
	errSqrtOfNegNumber  = errors.New("cannot take square root of a negative number")
	errLogOfNegNumber   = errors.New("cannot take logarithm of a negative number")
	errLogOfZero        = errors.New("cannot take logarithm of zero")
	errInsufficientArgs = errors.New("unknown signature: concat_ws()")
	errZeroIP           = errors.New("zero length IP")
)

// FunctionClass specifies the class of the builtin function.
type FunctionClass int

const (
	// NormalClass is a standard builtin function.
	NormalClass FunctionClass = iota
	// AggregateClass is a builtin aggregate function.
	AggregateClass
	// WindowClass is a builtin window function.
	WindowClass
)

// Avoid vet warning about unused enum value.
var _ = NormalClass

const (
	categoryIDGeneration = "ID Generation"
	categorySystemInfo   = "System Info"
	categoryDateAndTime  = "Date and Time"
	categoryString       = "String and Byte"
	categoryMath         = "Math and Numeric"
	categoryComparison   = "Comparison"
)

// Builtin is a built-in function.
type Builtin struct {
	Types      typeList
	ReturnType Type

	// When multiple overloads are eligible based on types even after all of of
	// the heuristics to pick one have been used, if one of the overloads is a
	// Builtin with the `preferredOverload` flag set to true it can be selected
	// rather than returning a no-such-method error.
	// This should generally be avoided -- avoiding introducing ambiguous
	// overloads in the first place is a much better solution -- and only done
	// after consultation with @knz @nvanbenschoten.
	preferredOverload bool

	// Set to true when a function potentially returns a different value
	// when called in the same statement with the same parameters.
	// e.g.: random(), clock_timestamp(). Some functions like now()
	// return the same value in the same statement, but different values
	// in separate statements, and should not be marked as impure.
	impure         bool
	class          FunctionClass
	category, Info string

	AggregateFunc func() AggregateFunc
	WindowFunc    func() WindowFunc
	fn            func(*EvalContext, DTuple) (Datum, error)
}

func (b Builtin) params() typeList {
	return b.Types
}

func (b Builtin) returnType() Type {
	return b.ReturnType
}

func (b Builtin) preferred() bool {
	return b.preferredOverload
}

func categorizeType(t Type) string {
	switch t {
	case TypeDate, TypeInterval, TypeTimestamp, TypeTimestampTZ:
		return categoryDateAndTime
	case TypeInt, TypeDecimal, TypeFloat:
		return categoryMath
	case TypeString, TypeBytes:
		return categoryString
	default:
		return strings.ToUpper(t.String())
	}
}

// Category is used to categorize a function (for documentation purposes).
func (b Builtin) Category() string {
	if b.category != "" {
		return b.category
	}
	if types, ok := b.Types.(ArgTypes); ok && len(types) == 1 {
		return categorizeType(types[0])
	}
	if b.ReturnType != nil {
		return categorizeType(b.ReturnType)
	}
	return ""
}

// Class returns the FunctionClass of this builtin.
func (b Builtin) Class() FunctionClass {
	return b.class
}

// Impure returns false if this builtin is a pure function of its inputs.
func (b Builtin) Impure() bool {
	return b.impure
}

// Signature returns a human-readable signature.
func (b Builtin) Signature() string {
	return fmt.Sprintf("(%s) -> %s", b.Types.String(), b.ReturnType)
}

func init() {
	initAggregateBuiltins()
	initWindowBuiltins()

	names := make([]string, 0, len(Builtins))
	funDefs = make(map[string]*FunctionDefinition)
	for name, def := range Builtins {
		fdef := &FunctionDefinition{Name: name, Definition: def}
		funDefs[name] = fdef
		names = append(names, name)
	}

	// We alias the builtins to uppercase to hasten the lookup in the
	// common case.
	for _, name := range names {
		uname := strings.ToUpper(name)
		def := Builtins[name]
		Builtins[uname] = def
		funDefs[uname] = funDefs[name]
	}
}

// Builtins contains the built-in functions indexed by name.
var Builtins = map[string][]Builtin{
	// Keep the list of functions sorted.

	// TODO(XisiHuang): support encoding, i.e., length(str, encoding).
	"length": {
		stringBuiltin1(func(s string) (Datum, error) {
			return NewDInt(DInt(utf8.RuneCountInString(s))), nil
		}, TypeInt),
		bytesBuiltin1(func(s string) (Datum, error) {
			return NewDInt(DInt(len(s))), nil
		}, TypeInt),
	},

	"octet_length": {
		stringBuiltin1(func(s string) (Datum, error) {
			return NewDInt(DInt(len(s))), nil
		}, TypeInt),
		bytesBuiltin1(func(s string) (Datum, error) {
			return NewDInt(DInt(len(s))), nil
		}, TypeInt),
	},

	// TODO(pmattis): What string functions should also support TypeBytes?

	"lower": {stringBuiltin1(func(s string) (Datum, error) {
		return NewDString(strings.ToLower(s)), nil
	}, TypeString)},

	"upper": {stringBuiltin1(func(s string) (Datum, error) {
		return NewDString(strings.ToUpper(s)), nil
	}, TypeString)},

	"substr":    substringImpls,
	"substring": substringImpls,

	// concat concatenates the text representations of all the arguments.
	// NULL arguments are ignored.
	"concat": {
		Builtin{
			Types:      VariadicType{TypeString},
			ReturnType: TypeString,
			fn: func(_ *EvalContext, args DTuple) (Datum, error) {
				var buffer bytes.Buffer
				for _, d := range args {
					if d == DNull {
						continue
					}
					buffer.WriteString(string(*d.(*DString)))
				}
				return NewDString(buffer.String()), nil
			},
		},
	},

	"concat_ws": {
		Builtin{
			Types:      VariadicType{TypeString},
			ReturnType: TypeString,
			fn: func(_ *EvalContext, args DTuple) (Datum, error) {
				if len(args) == 0 {
					return nil, errInsufficientArgs
				}
				if args[0] == DNull {
					return DNull, nil
				}
				sep := string(*args[0].(*DString))
				var buf bytes.Buffer
				prefix := ""
				for _, d := range args[1:] {
					if d == DNull {
						continue
					}
					// Note: we can't use the range index here because that
					// would break when the 2nd argument is NULL.
					buf.WriteString(prefix)
					prefix = sep
					buf.WriteString(string(*d.(*DString)))
				}
				return NewDString(buf.String()), nil
			},
		},
	},

	"to_uuid": {
		Builtin{
			Types:      ArgTypes{TypeString},
			ReturnType: TypeBytes,
			fn: func(_ *EvalContext, args DTuple) (Datum, error) {
				s := string(*args[0].(*DString))
				uv, err := uuid.FromString(s)
				if err != nil {
					return nil, err
				}
				return NewDBytes(DBytes(uv.GetBytes())), nil
			},
		},
	},

	"from_uuid": {
		Builtin{
			Types:      ArgTypes{TypeBytes},
			ReturnType: TypeString,
			fn: func(_ *EvalContext, args DTuple) (Datum, error) {
				b := []byte(*args[0].(*DBytes))
				uv, err := uuid.FromBytes(b)
				if err != nil {
					return nil, err
				}
				return NewDString(uv.String()), nil
			},
		},
	},

	"from_ip": {
		Builtin{
			Types:      ArgTypes{TypeBytes},
			ReturnType: TypeString,
			fn: func(_ *EvalContext, args DTuple) (Datum, error) {
				ipstr := args[0].(*DBytes)
				nboip := net.IP(*ipstr)
				sv := nboip.String()
				// if nboip has a length of 0, sv will be "<nil>"
				if sv == "<nil>" {
					return nil, errZeroIP
				}
				return NewDString(sv), nil
			},
		},
	},

	"to_ip": {
		Builtin{
			Types:      ArgTypes{TypeString},
			ReturnType: TypeBytes,
			fn: func(_ *EvalContext, args DTuple) (Datum, error) {
				ipdstr := args[0].(*DString)
				ip := net.ParseIP(string(*ipdstr))
				// If ipdstr could not be parsed to a valid IP,
				// ip will be nil.
				if ip == nil {
					return nil, fmt.Errorf("invalid IP format: %s", ipdstr)
				}
				return NewDBytes(DBytes(ip)), nil
			},
		},
	},

	"split_part": {
		Builtin{
			Types:      ArgTypes{TypeString, TypeString, TypeInt},
			ReturnType: TypeString,
			fn: func(_ *EvalContext, args DTuple) (Datum, error) {
				text := string(*args[0].(*DString))
				sep := string(*args[1].(*DString))
				field := int(*args[2].(*DInt))

				if field <= 0 {
					return nil, fmt.Errorf("field position %d must be greater than zero", field)
				}

				splits := strings.Split(text, sep)
				if field > len(splits) {
					return NewDString(""), nil
				}
				return NewDString(splits[field-1]), nil
			},
		},
	},

	"repeat": {
		Builtin{
			Types:      ArgTypes{TypeString, TypeInt},
			ReturnType: TypeString,
			fn: func(_ *EvalContext, args DTuple) (_ Datum, err error) {
				s := string(*args[0].(*DString))
				count := int(*args[1].(*DInt))
				if count < 0 {
					count = 0
				}
				// Repeat can overflow if len(s) * count is very large. The computation
				// for the limit about what make can allocate is not trivial, so it's most
				// accurate to detect it with a recover.
				defer func() {
					if r := recover(); r != nil {
						err = fmt.Errorf("%s", r)
					}
				}()
				return NewDString(strings.Repeat(s, count)), nil
			},
		},
	},

	"ascii": {stringBuiltin1(func(s string) (Datum, error) {
		for _, ch := range s {
			return NewDInt(DInt(ch)), nil
		}
		return nil, errEmptyInputString
	}, TypeInt)},

	"md5": {stringBuiltin1(func(s string) (Datum, error) {
		return NewDString(fmt.Sprintf("%x", md5.Sum([]byte(s)))), nil
	}, TypeString)},

	"sha1": {stringBuiltin1(func(s string) (Datum, error) {
		return NewDString(fmt.Sprintf("%x", sha1.Sum([]byte(s)))), nil
	}, TypeString)},

	"sha256": {stringBuiltin1(func(s string) (Datum, error) {
		return NewDString(fmt.Sprintf("%x", sha256.Sum256([]byte(s)))), nil
	}, TypeString)},

	"to_hex": {
		Builtin{
			Types:      ArgTypes{TypeInt},
			ReturnType: TypeString,
			fn: func(_ *EvalContext, args DTuple) (Datum, error) {
				return NewDString(fmt.Sprintf("%x", int64(*args[0].(*DInt)))), nil
			},
		},
	},

	// The SQL parser coerces POSITION to STRPOS.
	"strpos": {stringBuiltin2(func(s, substring string) (Datum, error) {
		index := strings.Index(s, substring)
		if index < 0 {
			return NewDInt(0), nil
		}

		return NewDInt(DInt(utf8.RuneCountInString(s[:index]) + 1)), nil
	}, TypeInt)},

	"overlay": {
		Builtin{
			Types:      ArgTypes{TypeString, TypeString, TypeInt},
			ReturnType: TypeString,
			fn: func(_ *EvalContext, args DTuple) (Datum, error) {
				s := string(*args[0].(*DString))
				to := string(*args[1].(*DString))
				pos := int(*args[2].(*DInt))
				size := utf8.RuneCountInString(to)
				return overlay(s, to, pos, size)
			},
		},
		Builtin{
			Types:      ArgTypes{TypeString, TypeString, TypeInt, TypeInt},
			ReturnType: TypeString,
			fn: func(_ *EvalContext, args DTuple) (Datum, error) {
				s := string(*args[0].(*DString))
				to := string(*args[1].(*DString))
				pos := int(*args[2].(*DInt))
				size := int(*args[3].(*DInt))
				return overlay(s, to, pos, size)
			},
		},
	},

	// The SQL parser coerces TRIM(...) and TRIM(BOTH ...) to BTRIM(...).
	"btrim": {
		stringBuiltin2(func(s, chars string) (Datum, error) {
			return NewDString(strings.Trim(s, chars)), nil
		}, TypeString),
		stringBuiltin1(func(s string) (Datum, error) {
			return NewDString(strings.TrimSpace(s)), nil
		}, TypeString),
	},

	// The SQL parser coerces TRIM(LEADING ...) to LTRIM(...).
	"ltrim": {
		stringBuiltin2(func(s, chars string) (Datum, error) {
			return NewDString(strings.TrimLeft(s, chars)), nil
		}, TypeString),
		stringBuiltin1(func(s string) (Datum, error) {
			return NewDString(strings.TrimLeftFunc(s, unicode.IsSpace)), nil
		}, TypeString),
	},

	// The SQL parser coerces TRIM(TRAILING ...) to RTRIM(...).
	"rtrim": {
		stringBuiltin2(func(s, chars string) (Datum, error) {
			return NewDString(strings.TrimRight(s, chars)), nil
		}, TypeString),
		stringBuiltin1(func(s string) (Datum, error) {
			return NewDString(strings.TrimRightFunc(s, unicode.IsSpace)), nil
		}, TypeString),
	},

	"reverse": {stringBuiltin1(func(s string) (Datum, error) {
		runes := []rune(s)
		for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
			runes[i], runes[j] = runes[j], runes[i]
		}
		return NewDString(string(runes)), nil
	}, TypeString)},

	"replace": {stringBuiltin3(
		"input", "from", "to",
		func(input, from, to string) (Datum, error) {
			return NewDString(strings.Replace(input, from, to, -1)), nil
		},
		TypeString,
		"Replace all occurrences of 'from' with 'to' in 'input'",
	)},

	"translate": {stringBuiltin3(
		"input", "from", "to",
		func(s, from, to string) (Datum, error) {
			const deletionRune = utf8.MaxRune + 1
			translation := make(map[rune]rune, len(from))
			for _, fromRune := range from {
				toRune, size := utf8.DecodeRuneInString(to)
				if toRune == utf8.RuneError {
					toRune = deletionRune
				} else {
					to = to[size:]
				}
				translation[fromRune] = toRune
			}

			runes := make([]rune, 0, len(s))
			for _, c := range s {
				if t, ok := translation[c]; ok {
					if t != deletionRune {
						runes = append(runes, t)
					}
				} else {
					runes = append(runes, c)
				}
			}
			return NewDString(string(runes)), nil
		}, TypeString, "")},

	"regexp_extract": {
		Builtin{
			Types:      ArgTypes{TypeString, TypeString},
			ReturnType: TypeString,
			fn: func(ctx *EvalContext, args DTuple) (Datum, error) {
				s := string(*args[0].(*DString))
				pattern := string(*args[1].(*DString))
				return regexpExtract(ctx, s, pattern, `\`)
			},
		},
	},

	"regexp_replace": {
		Builtin{
			Types:      ArgTypes{TypeString, TypeString, TypeString},
			ReturnType: TypeString,
			fn: func(ctx *EvalContext, args DTuple) (Datum, error) {
				s := string(*args[0].(*DString))
				pattern := string(*args[1].(*DString))
				to := string(*args[2].(*DString))
				return regexpReplace(ctx, s, pattern, to, "")
			},
		},
		Builtin{
			Types:      ArgTypes{TypeString, TypeString, TypeString, TypeString},
			ReturnType: TypeString,
			fn: func(ctx *EvalContext, args DTuple) (Datum, error) {
				s := string(*args[0].(*DString))
				pattern := string(*args[1].(*DString))
				to := string(*args[2].(*DString))
				sqlFlags := string(*args[3].(*DString))
				return regexpReplace(ctx, s, pattern, to, sqlFlags)
			},
		},
	},

	"initcap": {stringBuiltin1(func(s string) (Datum, error) {
		return NewDString(strings.Title(strings.ToLower(s))), nil
	}, TypeString)},

	"left": {
		Builtin{
			Types:      ArgTypes{TypeBytes, TypeInt},
			ReturnType: TypeBytes,
			fn: func(_ *EvalContext, args DTuple) (Datum, error) {
				bytes := []byte(*args[0].(*DBytes))
				n := int(*args[1].(*DInt))

				if n < -len(bytes) {
					n = 0
				} else if n < 0 {
					n = len(bytes) + n
				} else if n > len(bytes) {
					n = len(bytes)
				}
				return NewDBytes(DBytes(bytes[:n])), nil
			},
		},
		Builtin{
			Types:      ArgTypes{TypeString, TypeInt},
			ReturnType: TypeString,
			fn: func(_ *EvalContext, args DTuple) (Datum, error) {
				runes := []rune(string(*args[0].(*DString)))
				n := int(*args[1].(*DInt))

				if n < -len(runes) {
					n = 0
				} else if n < 0 {
					n = len(runes) + n
				} else if n > len(runes) {
					n = len(runes)
				}
				return NewDString(string(runes[:n])), nil
			},
		},
	},

	"right": {
		Builtin{
			Types:      ArgTypes{TypeBytes, TypeInt},
			ReturnType: TypeBytes,
			fn: func(_ *EvalContext, args DTuple) (Datum, error) {
				bytes := []byte(*args[0].(*DBytes))
				n := int(*args[1].(*DInt))

				if n < -len(bytes) {
					n = 0
				} else if n < 0 {
					n = len(bytes) + n
				} else if n > len(bytes) {
					n = len(bytes)
				}
				return NewDBytes(DBytes(bytes[len(bytes)-n:])), nil
			},
		},
		Builtin{
			Types:      ArgTypes{TypeString, TypeInt},
			ReturnType: TypeString,
			fn: func(_ *EvalContext, args DTuple) (Datum, error) {
				runes := []rune(string(*args[0].(*DString)))
				n := int(*args[1].(*DInt))

				if n < -len(runes) {
					n = 0
				} else if n < 0 {
					n = len(runes) + n
				} else if n > len(runes) {
					n = len(runes)
				}
				return NewDString(string(runes[len(runes)-n:])), nil
			},
		},
	},

	"random": {
		Builtin{
			Types:      ArgTypes{},
			ReturnType: TypeFloat,
			impure:     true,
			fn: func(_ *EvalContext, args DTuple) (Datum, error) {
				return NewDFloat(DFloat(rand.Float64())), nil
			},
		},
	},

	"experimental_unique_bytes": {
		Builtin{
			Types:      ArgTypes{},
			ReturnType: TypeBytes,
			category:   categoryIDGeneration,
			impure:     true,
			fn: func(ctx *EvalContext, args DTuple) (Datum, error) {
				return NewDBytes(generateUniqueBytes(ctx.NodeID)), nil
			},
		},
	},

	"unique_rowid": {
		Builtin{
			Types:      ArgTypes{},
			ReturnType: TypeInt,
			category:   categoryIDGeneration,
			impure:     true,
			fn: func(ctx *EvalContext, args DTuple) (Datum, error) {
				return NewDInt(generateUniqueInt(ctx.NodeID)), nil
			},
		},
	},

	"experimental_uuid_v4": {uuidV4Impl},
	"uuid_v4":              {uuidV4Impl},

	"greatest": {
		Builtin{
			Types:      AnyType{},
			ReturnType: TypeAny,
			category:   categoryComparison,
			fn: func(ctx *EvalContext, args DTuple) (Datum, error) {
				return pickFromTuple(ctx, true /* greatest */, args)
			},
		},
	},

	"least": {
		Builtin{
			Types:      AnyType{},
			ReturnType: TypeAny,
			category:   categoryComparison,
			fn: func(ctx *EvalContext, args DTuple) (Datum, error) {
				return pickFromTuple(ctx, false /* !greatest */, args)
			},
		},
	},

	// Timestamp/Date functions.

	"experimental_strftime": {
		Builtin{
			Types:      ArgTypes{TypeTimestamp, TypeString},
			ReturnType: TypeString,
			fn: func(_ *EvalContext, args DTuple) (Datum, error) {
				fromTime := args[0].(*DTimestamp).Time
				format := string(*args[1].(*DString))
				t, err := timeutil.Strftime(fromTime, format)
				if err != nil {
					return nil, err
				}
				return NewDString(t), nil
			},
		},
		Builtin{
			Types:      ArgTypes{TypeDate, TypeString},
			ReturnType: TypeString,
			fn: func(_ *EvalContext, args DTuple) (Datum, error) {
				fromTime := time.Unix(int64(*args[0].(*DDate))*secondsInDay, 0).UTC()
				format := string(*args[1].(*DString))
				t, err := timeutil.Strftime(fromTime, format)
				if err != nil {
					return nil, err
				}
				return NewDString(t), nil
			},
		},
		Builtin{
			Types:      ArgTypes{TypeTimestampTZ, TypeString},
			ReturnType: TypeString,
			fn: func(_ *EvalContext, args DTuple) (Datum, error) {
				fromTime := args[0].(*DTimestampTZ).Time
				format := string(*args[1].(*DString))
				t, err := timeutil.Strftime(fromTime, format)
				if err != nil {
					return nil, err
				}
				return NewDString(t), nil
			},
		},
	},

	"experimental_strptime": {
		Builtin{
			Types:      ArgTypes{TypeString, TypeString},
			ReturnType: TypeTimestampTZ,
			fn: func(_ *EvalContext, args DTuple) (Datum, error) {
				format := string(*args[0].(*DString))
				toParse := string(*args[1].(*DString))
				t, err := timeutil.Strptime(toParse, format)
				if err != nil {
					return nil, err
				}
				return MakeDTimestampTZ(t.UTC(), time.Microsecond), nil
			},
		},
	},

	"age": {
		Builtin{
			Types:      ArgTypes{TypeTimestampTZ},
			ReturnType: TypeInterval,
			fn: func(ctx *EvalContext, args DTuple) (Datum, error) {
				return timestampMinusBinOp.fn(ctx, ctx.GetTxnTimestamp(time.Microsecond), args[0])
			},
		},
		Builtin{
			Types:      ArgTypes{TypeTimestampTZ, TypeTimestampTZ},
			ReturnType: TypeInterval,
			fn: func(ctx *EvalContext, args DTuple) (Datum, error) {
				return timestampMinusBinOp.fn(ctx, args[0], args[1])
			},
		},
	},

	"current_date": {
		Builtin{
			Types:      ArgTypes{},
			ReturnType: TypeDate,
			fn: func(ctx *EvalContext, args DTuple) (Datum, error) {
				t := ctx.GetTxnTimestamp(time.Microsecond).Time
				return NewDDateFromTime(t, ctx.GetLocation()), nil
			},
		},
	},

	"now":                   txnTSImpl,
	"current_timestamp":     txnTSImpl,
	"transaction_timestamp": txnTSImpl,

	"statement_timestamp": {
		Builtin{
			Types:             ArgTypes{},
			ReturnType:        TypeTimestampTZ,
			preferredOverload: true,
			impure:            true,
			fn: func(ctx *EvalContext, args DTuple) (Datum, error) {
				return MakeDTimestampTZ(ctx.GetStmtTimestamp(), time.Microsecond), nil
			},
		},
		Builtin{
			Types:      ArgTypes{},
			ReturnType: TypeTimestamp,
			impure:     true,
			fn: func(ctx *EvalContext, args DTuple) (Datum, error) {
				return MakeDTimestamp(ctx.GetStmtTimestamp(), time.Microsecond), nil
			},
		},
	},

	"cluster_logical_timestamp": {
		Builtin{
			Types:      ArgTypes{},
			ReturnType: TypeDecimal,
			category:   categorySystemInfo,
			impure:     true,
			fn: func(ctx *EvalContext, args DTuple) (Datum, error) {
				return ctx.GetClusterTimestamp(), nil
			},
		},
	},

	"clock_timestamp": {
		Builtin{
			Types:             ArgTypes{},
			ReturnType:        TypeTimestampTZ,
			preferredOverload: true,
			impure:            true,
			fn: func(_ *EvalContext, args DTuple) (Datum, error) {
				return MakeDTimestampTZ(timeutil.Now(), time.Microsecond), nil
			},
		},
		Builtin{
			Types:      ArgTypes{},
			ReturnType: TypeTimestamp,
			impure:     true,
			fn: func(_ *EvalContext, args DTuple) (Datum, error) {
				return MakeDTimestamp(timeutil.Now(), time.Microsecond), nil
			},
		},
	},

	"extract": {
		Builtin{
			Types:      ArgTypes{TypeString, TypeTimestamp},
			ReturnType: TypeInt,
			category:   categoryDateAndTime,
			fn: func(_ *EvalContext, args DTuple) (Datum, error) {
				// extract timeSpan fromTime.
				fromTime := *args[1].(*DTimestamp)
				timeSpan := strings.ToLower(string(*args[0].(*DString)))
				switch timeSpan {
				case "year", "years":
					return NewDInt(DInt(fromTime.Year())), nil

				case "quarter":
					return NewDInt(DInt(fromTime.Month()/4 + 1)), nil

				case "month", "months":
					return NewDInt(DInt(fromTime.Month())), nil

				case "week", "weeks":
					_, week := fromTime.ISOWeek()
					return NewDInt(DInt(week)), nil

				case "day", "days":
					return NewDInt(DInt(fromTime.Day())), nil

				case "dayofweek", "dow":
					return NewDInt(DInt(fromTime.Weekday())), nil

				case "dayofyear", "doy":
					return NewDInt(DInt(fromTime.YearDay())), nil

				case "hour", "hours":
					return NewDInt(DInt(fromTime.Hour())), nil

				case "minute", "minutes":
					return NewDInt(DInt(fromTime.Minute())), nil

				case "second", "seconds":
					return NewDInt(DInt(fromTime.Second())), nil

				case "millisecond", "milliseconds":
					// This a PG extension not supported in MySQL.
					return NewDInt(DInt(fromTime.Nanosecond() / int(time.Millisecond))), nil

				case "microsecond", "microseconds":
					return NewDInt(DInt(fromTime.Nanosecond() / int(time.Microsecond))), nil

				case "epoch":
					return NewDInt(DInt(fromTime.Unix())), nil

				default:
					return nil, fmt.Errorf("unsupported timespan: %s", timeSpan)
				}
			},
		},
	},
	"extract_duration": {
		Builtin{
			Types:      ArgTypes{TypeString, TypeInterval},
			ReturnType: TypeInt,
			category:   categoryDateAndTime,
			fn: func(_ *EvalContext, args DTuple) (Datum, error) {
				// extract timeSpan fromTime.
				fromInterval := *args[1].(*DInterval)
				timeSpan := strings.ToLower(string(*args[0].(*DString)))
				switch timeSpan {
				case "hour", "hours":
					return NewDInt(DInt(fromInterval.Nanos / int64(time.Hour))), nil

				case "minute", "minutes":
					return NewDInt(DInt(fromInterval.Nanos / int64(time.Minute))), nil

				case "second", "seconds":
					return NewDInt(DInt(fromInterval.Nanos / int64(time.Second))), nil

				case "millisecond", "milliseconds":
					// This a PG extension not supported in MySQL.
					return NewDInt(DInt(fromInterval.Nanos / int64(time.Millisecond))), nil

				case "microsecond", "microseconds":
					return NewDInt(DInt(fromInterval.Nanos / int64(time.Microsecond))), nil

				default:
					return nil, fmt.Errorf("unsupported timespan: %s", timeSpan)
				}
			},
		},
	},

	// Math functions
	"abs": {
		floatBuiltin1(func(x float64) (Datum, error) {
			return NewDFloat(DFloat(math.Abs(x))), nil
		}),
		decimalBuiltin1(func(x *inf.Dec) (Datum, error) {
			dd := &DDecimal{}
			dd.Abs(x)
			return dd, nil
		}),
		Builtin{
			Types:      ArgTypes{TypeInt},
			ReturnType: TypeInt,
			fn: func(_ *EvalContext, args DTuple) (Datum, error) {
				x := *args[0].(*DInt)
				switch {
				case x == math.MinInt64:
					return nil, errAbsOfMinInt64
				case x < 0:
					return NewDInt(-x), nil
				}
				return args[0], nil
			},
		},
	},

	"acos": {
		floatBuiltin1(func(x float64) (Datum, error) {
			return NewDFloat(DFloat(math.Acos(x))), nil
		}),
	},

	"asin": {
		floatBuiltin1(func(x float64) (Datum, error) {
			return NewDFloat(DFloat(math.Asin(x))), nil
		}),
	},

	"atan": {
		floatBuiltin1(func(x float64) (Datum, error) {
			return NewDFloat(DFloat(math.Atan(x))), nil
		}),
	},

	"atan2": {
		floatBuiltin2(func(x, y float64) (Datum, error) {
			return NewDFloat(DFloat(math.Atan2(x, y))), nil
		}),
	},

	"cbrt": {
		floatBuiltin1(func(x float64) (Datum, error) {
			return NewDFloat(DFloat(math.Cbrt(x))), nil
		}),
		decimalBuiltin1(func(x *inf.Dec) (Datum, error) {
			dd := &DDecimal{}
			decimal.Cbrt(&dd.Dec, x, decimal.Precision)
			return dd, nil
		}),
	},

	"ceil":    ceilImpl,
	"ceiling": ceilImpl,

	"cos": {
		floatBuiltin1(func(x float64) (Datum, error) {
			return NewDFloat(DFloat(math.Cos(x))), nil
		}),
	},

	"cot": {
		floatBuiltin1(func(x float64) (Datum, error) {
			return NewDFloat(DFloat(1 / math.Tan(x))), nil
		}),
	},

	"degrees": {
		floatBuiltin1(func(x float64) (Datum, error) {
			return NewDFloat(DFloat(180.0 * x / math.Pi)), nil
		}),
	},

	"div": {
		floatBuiltin2(func(x, y float64) (Datum, error) {
			return NewDFloat(DFloat(math.Trunc(x / y))), nil
		}),
		decimalBuiltin2(func(x, y *inf.Dec) (Datum, error) {
			if y.Sign() == 0 {
				return nil, errDivByZero
			}
			dd := &DDecimal{}
			dd.QuoRound(x, y, 0, inf.RoundDown)
			return dd, nil
		}),
		{
			Types:      ArgTypes{TypeInt, TypeInt},
			ReturnType: TypeInt,
			fn: func(_ *EvalContext, args DTuple) (Datum, error) {
				y := *args[1].(*DInt)
				if y == 0 {
					return nil, errDivByZero
				}
				x := *args[0].(*DInt)
				return NewDInt(x / y), nil
			},
		},
	},

	"exp": {
		floatBuiltin1(func(x float64) (Datum, error) {
			return NewDFloat(DFloat(math.Exp(x))), nil
		}),
		decimalBuiltin1(func(x *inf.Dec) (Datum, error) {
			return expDecimal(x)
		}),
	},

	"floor": {
		floatBuiltin1(func(x float64) (Datum, error) {
			return NewDFloat(DFloat(math.Floor(x))), nil
		}),
		decimalBuiltin1(func(x *inf.Dec) (Datum, error) {
			dd := &DDecimal{}
			dd.Round(x, 0, inf.RoundFloor)
			return dd, nil
		}),
	},

	"ln": {
		floatBuiltin1(func(x float64) (Datum, error) {
			return NewDFloat(DFloat(math.Log(x))), nil
		}),
		decimalLogFn(decimal.Log),
	},

	"log": {
		floatBuiltin1(func(x float64) (Datum, error) {
			return NewDFloat(DFloat(math.Log10(x))), nil
		}),
		decimalLogFn(decimal.Log10),
	},

	"mod": {
		floatBuiltin2(func(x, y float64) (Datum, error) {
			return NewDFloat(DFloat(math.Mod(x, y))), nil
		}),
		decimalBuiltin2(func(x, y *inf.Dec) (Datum, error) {
			if y.Sign() == 0 {
				return nil, errZeroModulus
			}
			dd := &DDecimal{}
			decimal.Mod(&dd.Dec, x, y)
			return dd, nil
		}),
		Builtin{
			Types:      ArgTypes{TypeInt, TypeInt},
			ReturnType: TypeInt,
			fn: func(_ *EvalContext, args DTuple) (Datum, error) {
				y := *args[1].(*DInt)
				if y == 0 {
					return nil, errZeroModulus
				}
				x := *args[0].(*DInt)
				return NewDInt(x % y), nil
			},
		},
	},

	"pi": {
		Builtin{
			Types:      ArgTypes{},
			ReturnType: TypeFloat,
			fn: func(_ *EvalContext, args DTuple) (Datum, error) {
				return NewDFloat(math.Pi), nil
			},
		},
	},

	"pow":   powImpls,
	"power": powImpls,

	"radians": {
		floatBuiltin1(func(x float64) (Datum, error) {
			return NewDFloat(DFloat(x * math.Pi / 180.0)), nil
		}),
	},

	"round": {
		floatBuiltin1(func(x float64) (Datum, error) {
			return round(x, 0)
		}),
		decimalBuiltin1(func(x *inf.Dec) (Datum, error) {
			return roundDecimal(x, 0)
		}),
		Builtin{
			Types:      ArgTypes{TypeFloat, TypeInt},
			ReturnType: TypeFloat,
			fn: func(_ *EvalContext, args DTuple) (Datum, error) {
				return round(float64(*args[0].(*DFloat)), int64(*args[1].(*DInt)))
			},
		},
		Builtin{
			Types:      ArgTypes{TypeDecimal, TypeInt},
			ReturnType: TypeDecimal,
			fn: func(_ *EvalContext, args DTuple) (Datum, error) {
				scale := int64(*args[1].(*DInt))
				return roundDecimal(&args[0].(*DDecimal).Dec, scale)
			},
		},
	},

	"sin": {
		floatBuiltin1(func(x float64) (Datum, error) {
			return NewDFloat(DFloat(math.Sin(x))), nil
		}),
	},

	"sign": {
		floatBuiltin1(func(x float64) (Datum, error) {
			switch {
			case x < 0:
				return NewDFloat(-1), nil
			case x == 0:
				return NewDFloat(0), nil
			}
			return NewDFloat(1), nil
		}),
		decimalBuiltin1(func(x *inf.Dec) (Datum, error) {
			d := &DDecimal{}
			d.Dec.SetUnscaled(int64(x.Sign()))
			return d, nil
		}),
		Builtin{
			Types:      ArgTypes{TypeInt},
			ReturnType: TypeInt,
			fn: func(_ *EvalContext, args DTuple) (Datum, error) {
				x := *args[0].(*DInt)
				switch {
				case x < 0:
					return NewDInt(-1), nil
				case x == 0:
					return NewDInt(0), nil
				}
				return NewDInt(1), nil
			},
		},
	},

	"sqrt": {
		floatBuiltin1(func(x float64) (Datum, error) {
			if x < 0 {
				return nil, errSqrtOfNegNumber
			}
			return NewDFloat(DFloat(math.Sqrt(x))), nil
		}),
		decimalBuiltin1(func(x *inf.Dec) (Datum, error) {
			if x.Sign() < 0 {
				return nil, errSqrtOfNegNumber
			}
			dd := &DDecimal{}
			decimal.Sqrt(&dd.Dec, x, decimal.Precision)
			return dd, nil
		}),
	},

	"tan": {
		floatBuiltin1(func(x float64) (Datum, error) {
			return NewDFloat(DFloat(math.Tan(x))), nil
		}),
	},

	"trunc": {
		floatBuiltin1(func(x float64) (Datum, error) {
			return NewDFloat(DFloat(math.Trunc(x))), nil
		}),
		decimalBuiltin1(func(x *inf.Dec) (Datum, error) {
			dd := &DDecimal{}
			dd.Round(x, 0, inf.RoundDown)
			return dd, nil
		}),
	},

	// Array functions.

	"array_length": {
		Builtin{
			// TODO(nvanbenschoten): Make this work with all types of arrays.
			Types:      ArgTypes{TypeStringArray, TypeInt},
			ReturnType: TypeInt,
			category:   categorySystemInfo,
			fn: func(_ *EvalContext, args DTuple) (Datum, error) {
				arr := *args[0].(*DArray)
				dimen := *args[1].(*DInt)
				// We do not currently support multi-dimensional arrays.
				if dimen != 1 || arr.Len() == 0 {
					return DNull, nil
				}
				return NewDInt(DInt(arr.Len())), nil
			},
		},
	},

	"array_lower": {
		Builtin{
			// TODO(nvanbenschoten): Make this work with all types of arrays.
			Types:      ArgTypes{TypeStringArray, TypeInt},
			ReturnType: TypeInt,
			category:   categorySystemInfo,
			fn: func(_ *EvalContext, args DTuple) (Datum, error) {
				arr := *args[0].(*DArray)
				dimen := *args[1].(*DInt)
				// We do not currently support multi-dimensional arrays.
				if dimen != 1 || arr.Len() == 0 {
					return DNull, nil
				}
				return NewDInt(DInt(1)), nil
			},
		},
	},

	"array_upper": {
		Builtin{
			// TODO(nvanbenschoten): Make this work with all types of arrays.
			Types:      ArgTypes{TypeStringArray, TypeInt},
			ReturnType: TypeInt,
			category:   categorySystemInfo,
			fn: func(_ *EvalContext, args DTuple) (Datum, error) {
				arr := *args[0].(*DArray)
				dimen := *args[1].(*DInt)
				// We do not currently support multi-dimensional arrays.
				if dimen != 1 || arr.Len() == 0 {
					return DNull, nil
				}
				return NewDInt(DInt(arr.Len())), nil
			},
		},
	},

	// Metadata functions.

	"version": {
		Builtin{
			Types:      ArgTypes{},
			ReturnType: TypeString,
			category:   categorySystemInfo,
			fn: func(_ *EvalContext, args DTuple) (Datum, error) {
				return NewDString(build.GetInfo().Short()), nil
			},
		},
	},

	"current_schema": {
		Builtin{
			Types:      ArgTypes{},
			ReturnType: TypeString,
			category:   categorySystemInfo,
			fn: func(ctx *EvalContext, args DTuple) (Datum, error) {
				if len(ctx.Database) == 0 {
					return DNull, nil
				}
				return NewDString(ctx.Database), nil
			},
		},
	},

	// For now, schemas are the same as databases. So, current_schemas returns the
	// current database (if one has been set by the user) and, if the passed in
	// parameter is true, the session's database search path.
	"current_schemas": {
		Builtin{
			Types:      ArgTypes{TypeBool},
			ReturnType: TypeStringArray,
			category:   categorySystemInfo,
			fn: func(ctx *EvalContext, args DTuple) (Datum, error) {
				schemas := NewDArray(TypeString)
				showImplicitSchemas := args[0].(*DBool)
				if showImplicitSchemas == DBoolTrue {
					for _, p := range ctx.SearchPath {
						if err := schemas.Append(NewDString(p)); err != nil {
							return nil, err
						}
					}
				}
				if len(ctx.Database) != 0 {
					if err := schemas.Append(NewDString(ctx.Database)); err != nil {
						return nil, err
					}
				}
				return schemas, nil
			},
		},
	},

	"crdb_internal.force_retry": {
		Builtin{
			Types:      ArgTypes{TypeInterval},
			ReturnType: TypeInt,
			impure:     true,
			fn: func(ctx *EvalContext, args DTuple) (Datum, error) {
				minDuration := args[0].(*DInterval).Duration
				elapsed := duration.Duration{
					Nanos: int64(ctx.stmtTimestamp.Sub(ctx.txnTimestamp)),
				}
				if elapsed.Compare(minDuration) < 0 {
					return nil, roachpb.NewRetryableTxnError("forced by crdb_internal.force_retry()")
				}
				return NewDInt(0), nil
			},
		},
	},

	// pg_catalog functions.
	// See https://www.postgresql.org/docs/9.6/static/functions-info.html.

	// Postgres defines pg_get_expr as a function that "decompiles the internal form
	// of an expression", which is provided in the pg_node_tree type. In Cockroach's
	// pg_catalog implementation, we populate all pg_node_tree columns with the
	// corresponding expression as a string, which means that this function can simply
	// return the first argument directly. It also means we can ignore the second and
	// optional third argument.
	"pg_catalog.pg_get_expr": {
		Builtin{
			Types: NamedArgTypes{
				{"pg_node_tree", TypeString},
				{"relation_oid", TypeInt},
			},
			ReturnType: TypeString,
			fn: func(_ *EvalContext, args DTuple) (Datum, error) {
				return args[0], nil
			},
		},
		Builtin{
			Types: NamedArgTypes{
				{"pg_node_tree", TypeString},
				{"relation_oid", TypeInt},
				{"pretty_bool", TypeBool},
			},
			ReturnType: TypeString,
			fn: func(_ *EvalContext, args DTuple) (Datum, error) {
				return args[0], nil
			},
		},
	},

	"pg_catalog.pg_typeof": {
		// TODO(knz): This is a proof-of-concept until TypeAny works
		// properly.
		Builtin{
			Types:      ArgTypes{TypeInt},
			ReturnType: TypeString,
			fn: func(_ *EvalContext, args DTuple) (Datum, error) {
				return NewDString(args[0].ResolvedType().String()), nil
			},
		},
		Builtin{
			Types:      ArgTypes{TypeDecimal},
			ReturnType: TypeString,
			fn: func(_ *EvalContext, args DTuple) (Datum, error) {
				return NewDString(args[0].ResolvedType().String()), nil
			},
		},
		Builtin{
			Types:      ArgTypes{TypeString},
			ReturnType: TypeString,
			fn: func(_ *EvalContext, args DTuple) (Datum, error) {
				return NewDString(args[0].ResolvedType().String()), nil
			},
		},
	},
}

var substringImpls = []Builtin{
	{
		Types:      ArgTypes{TypeString, TypeInt},
		ReturnType: TypeString,
		fn: func(_ *EvalContext, args DTuple) (Datum, error) {
			runes := []rune(string(*args[0].(*DString)))
			// SQL strings are 1-indexed.
			start := int(*args[1].(*DInt)) - 1

			if start < 0 {
				start = 0
			} else if start > len(runes) {
				start = len(runes)
			}

			return NewDString(string(runes[start:])), nil
		},
	},
	{
		Types:      ArgTypes{TypeString, TypeInt, TypeInt},
		ReturnType: TypeString,
		fn: func(_ *EvalContext, args DTuple) (Datum, error) {
			runes := []rune(string(*args[0].(*DString)))
			// SQL strings are 1-indexed.
			start := int(*args[1].(*DInt)) - 1
			length := int(*args[2].(*DInt))

			if length < 0 {
				return nil, fmt.Errorf("negative substring length %d not allowed", length)
			}

			end := start + length
			// Check for integer overflow.
			if end < start {
				end = len(runes)
			} else if end < 0 {
				end = 0
			} else if end > len(runes) {
				end = len(runes)
			}

			if start < 0 {
				start = 0
			} else if start > len(runes) {
				start = len(runes)
			}

			return NewDString(string(runes[start:end])), nil
		},
	},
	{
		Types:      ArgTypes{TypeString, TypeString},
		ReturnType: TypeString,
		fn: func(ctx *EvalContext, args DTuple) (Datum, error) {
			s := string(*args[0].(*DString))
			pattern := string(*args[1].(*DString))
			return regexpExtract(ctx, s, pattern, `\`)
		},
	},
	{
		Types:      ArgTypes{TypeString, TypeString, TypeString},
		ReturnType: TypeString,
		fn: func(ctx *EvalContext, args DTuple) (Datum, error) {
			s := string(*args[0].(*DString))
			pattern := string(*args[1].(*DString))
			escape := string(*args[2].(*DString))
			return regexpExtract(ctx, s, pattern, escape)
		},
	},
}

var uuidV4Impl = Builtin{
	Types:      ArgTypes{},
	ReturnType: TypeBytes,
	category:   categoryIDGeneration,
	impure:     true,
	fn: func(_ *EvalContext, args DTuple) (Datum, error) {
		return NewDBytes(DBytes(uuid.MakeV4().GetBytes())), nil
	},
}

var ceilImpl = []Builtin{
	floatBuiltin1(func(x float64) (Datum, error) {
		return NewDFloat(DFloat(math.Ceil(x))), nil
	}),
	decimalBuiltin1(func(x *inf.Dec) (Datum, error) {
		dd := &DDecimal{}
		dd.Round(x, 0, inf.RoundCeil)
		return dd, nil
	}),
}

var txnTSImpl = []Builtin{
	{
		Types:             ArgTypes{},
		ReturnType:        TypeTimestampTZ,
		preferredOverload: true,
		impure:            true,
		fn: func(ctx *EvalContext, args DTuple) (Datum, error) {
			return ctx.GetTxnTimestamp(time.Microsecond), nil
		},
	},
	{
		Types:      ArgTypes{},
		ReturnType: TypeTimestamp,
		impure:     true,
		fn: func(ctx *EvalContext, args DTuple) (Datum, error) {
			return ctx.GetTxnTimestampNoZone(time.Microsecond), nil
		},
	},
}

var powImpls = []Builtin{
	floatBuiltin2(func(x, y float64) (Datum, error) {
		return NewDFloat(DFloat(math.Pow(x, y))), nil
	}),
	decimalBuiltin2(func(x, y *inf.Dec) (Datum, error) {
		dd := &DDecimal{}
		_, err := decimal.Pow(&dd.Dec, x, y, decimal.Precision)
		return dd, err
	}),
	{
		Types:      ArgTypes{TypeInt, TypeInt},
		ReturnType: TypeInt,
		fn: func(_ *EvalContext, args DTuple) (Datum, error) {
			x := int64(*args[0].(*DInt))
			y := int64(*args[1].(*DInt))
			return NewDInt(DInt(intPow(x, y))), nil
		},
	},
}

func decimalLogFn(logFn func(*inf.Dec, *inf.Dec, inf.Scale) (*inf.Dec, error)) Builtin {
	return decimalBuiltin1(func(x *inf.Dec) (Datum, error) {
		switch x.Sign() {
		case -1:
			return nil, errLogOfNegNumber
		case 0:
			return nil, errLogOfZero
		}
		dd := &DDecimal{}
		_, err := logFn(&dd.Dec, x, decimal.Precision)
		return dd, err
	})
}

func floatBuiltin1(f func(float64) (Datum, error)) Builtin {
	return Builtin{
		Types:      ArgTypes{TypeFloat},
		ReturnType: TypeFloat,
		fn: func(_ *EvalContext, args DTuple) (Datum, error) {
			return f(float64(*args[0].(*DFloat)))
		},
	}
}

func floatBuiltin2(f func(float64, float64) (Datum, error)) Builtin {
	return Builtin{
		Types:      ArgTypes{TypeFloat, TypeFloat},
		ReturnType: TypeFloat,
		fn: func(_ *EvalContext, args DTuple) (Datum, error) {
			return f(float64(*args[0].(*DFloat)),
				float64(*args[1].(*DFloat)))
		},
	}
}

func decimalBuiltin1(f func(*inf.Dec) (Datum, error)) Builtin {
	return Builtin{
		Types:      ArgTypes{TypeDecimal},
		ReturnType: TypeDecimal,
		fn: func(_ *EvalContext, args DTuple) (Datum, error) {
			dec := &args[0].(*DDecimal).Dec
			return f(dec)
		},
	}
}

func decimalBuiltin2(f func(*inf.Dec, *inf.Dec) (Datum, error)) Builtin {
	return Builtin{
		Types:      ArgTypes{TypeDecimal, TypeDecimal},
		ReturnType: TypeDecimal,
		fn: func(_ *EvalContext, args DTuple) (Datum, error) {
			dec1 := &args[0].(*DDecimal).Dec
			dec2 := &args[1].(*DDecimal).Dec
			return f(dec1, dec2)
		},
	}
}

func stringBuiltin1(f func(string) (Datum, error), returnType Type) Builtin {
	return Builtin{
		Types:      ArgTypes{TypeString},
		ReturnType: returnType,
		fn: func(_ *EvalContext, args DTuple) (Datum, error) {
			return f(string(*args[0].(*DString)))
		},
	}
}

func stringBuiltin2(f func(string, string) (Datum, error), returnType Type) Builtin {
	return Builtin{
		Types:      ArgTypes{TypeString, TypeString},
		ReturnType: returnType,
		category:   categorizeType(TypeString),
		fn: func(_ *EvalContext, args DTuple) (Datum, error) {
			return f(string(*args[0].(*DString)), string(*args[1].(*DString)))
		},
	}
}

func stringBuiltin3(
	a, b, c string, f func(string, string, string) (Datum, error), returnType Type, info string,
) Builtin {
	return Builtin{
		Types:      NamedArgTypes{{a, TypeString}, {b, TypeString}, {c, TypeString}},
		ReturnType: returnType,
		fn: func(_ *EvalContext, args DTuple) (Datum, error) {
			return f(string(*args[0].(*DString)), string(*args[1].(*DString)), string(*args[2].(*DString)))
		},
		Info: info,
	}
}

func bytesBuiltin1(f func(string) (Datum, error), returnType Type) Builtin {
	return Builtin{
		Types:      ArgTypes{TypeBytes},
		ReturnType: returnType,
		fn: func(_ *EvalContext, args DTuple) (Datum, error) {
			return f(string(*args[0].(*DBytes)))
		},
	}
}

type regexpEscapeKey struct {
	sqlPattern string
	sqlEscape  string
}

func (k regexpEscapeKey) pattern() (string, error) {
	pattern := k.sqlPattern
	if k.sqlEscape != `\` {
		pattern = strings.Replace(pattern, `\`, `\\`, -1)
		pattern = strings.Replace(pattern, k.sqlEscape, `\`, -1)
	}
	return pattern, nil
}

func regexpExtract(ctx *EvalContext, s, pattern, escape string) (Datum, error) {
	patternRe, err := ctx.ReCache.GetRegexp(regexpEscapeKey{pattern, escape})
	if err != nil {
		return nil, err
	}

	match := patternRe.FindStringSubmatch(s)
	if match == nil {
		return DNull, nil
	}

	if len(match) > 1 {
		return NewDString(match[1]), nil
	}
	return NewDString(match[0]), nil
}

type regexpFlagKey struct {
	sqlPattern string
	sqlFlags   string
}

func (k regexpFlagKey) pattern() (string, error) {
	return regexpEvalFlags(k.sqlPattern, k.sqlFlags)
}

var replaceSubRe = regexp.MustCompile(`\\[&1-9]`)

func regexpReplace(ctx *EvalContext, s, pattern, to, sqlFlags string) (Datum, error) {
	patternRe, err := ctx.ReCache.GetRegexp(regexpFlagKey{pattern, sqlFlags})
	if err != nil {
		return nil, err
	}

	matchCount := 1
	if strings.ContainsRune(sqlFlags, 'g') {
		matchCount = -1
	}

	replaceIndex := 0
	var newString bytes.Buffer

	// regexp.ReplaceAllStringFunc cannot be used here because it does not provide
	// access to regexp submatches for expansion in the replacement string.
	// regexp.ReplaceAllString cannot be used here because it does not allow
	// replacement of a specific number of matches, and does not expose the full
	// match for expansion in the replacement string.
	//
	// regexp.FindAllStringSubmatchIndex must therefore be used, which returns a 2D
	// int array. The outer array is iterated over with this for-range loop, and corresponds
	// to each match of the pattern in the string s. Inside each outer array is an int
	// array with index pairs. The first pair in a given match n ([n][0] & [n][1]) represents
	// the start and end index in s of the matched pattern. Subsequent pairs ([n][2] & [n][3],
	// and so on) represent the start and end index in s of matched subexpressions within the
	// pattern.
	for _, matchIndex := range patternRe.FindAllStringSubmatchIndex(s, matchCount) {
		start := matchIndex[0]
		end := matchIndex[1]

		// Add sections of s either before the first match or between matches.
		preMatch := s[replaceIndex:start]
		newString.WriteString(preMatch)

		// Add the replacement string for the current match.
		match := s[start:end]
		matchTo := replaceSubRe.ReplaceAllStringFunc(to, func(repl string) string {
			subRef := repl[len(repl)-1]
			if subRef == '&' {
				return match
			}

			sub, err := strconv.Atoi(string(subRef))
			if err != nil {
				panic(fmt.Sprintf("invalid integer submatch reference seen: %v", err))
			}
			if 2*sub >= len(matchIndex) {
				// regexpReplace expects references to "out-of-bounds" capture groups
				// to be ignored, so replace with an empty string.
				return ""
			}

			subStart := matchIndex[2*sub]
			subEnd := matchIndex[2*sub+1]
			return s[subStart:subEnd]
		})
		newString.WriteString(matchTo)

		replaceIndex = end
	}

	// Add the section of s past the final match.
	newString.WriteString(s[replaceIndex:])

	return NewDString(newString.String()), nil
}

var flagToByte = map[syntax.Flags]byte{
	syntax.FoldCase: 'i',
	syntax.DotNL:    's',
}

var flagToNotByte = map[syntax.Flags]byte{
	syntax.OneLine: 'm',
}

// regexpEvalFlags evaluates the provided Postgres regexp flags in
// accordance with their definitions provided at
// http://www.postgresql.org/docs/9.0/static/functions-matching.html#POSIX-EMBEDDED-OPTIONS-TABLE.
// It then returns an adjusted regexp pattern.
func regexpEvalFlags(pattern, sqlFlags string) (string, error) {
	flags := syntax.DotNL

	for _, sqlFlag := range sqlFlags {
		switch sqlFlag {
		case 'g':
			// Handled in `regexpReplace`.
		case 'i':
			flags |= syntax.FoldCase
		case 'c':
			flags &^= syntax.FoldCase
		case 's':
			flags |= syntax.DotNL
		case 'm', 'n':
			flags &^= syntax.DotNL
			flags |= syntax.OneLine
		case 'p':
			flags |= syntax.DotNL
			flags |= syntax.OneLine
		case 'w':
			flags |= syntax.DotNL
			flags &^= syntax.OneLine
		default:
			return "", fmt.Errorf("invalid regexp flag: %q", sqlFlag)
		}
	}

	var goFlags bytes.Buffer
	for flag, b := range flagToByte {
		if flags&flag != 0 {
			goFlags.WriteByte(b)
		}
	}
	for flag, b := range flagToNotByte {
		if flags&flag == 0 {
			goFlags.WriteByte(b)
		}
	}
	// Bytes() instead of String() to save an allocation.
	bs := goFlags.Bytes()
	if len(bs) == 0 {
		return pattern, nil
	}
	return fmt.Sprintf("(?%s:%s)", bs, pattern), nil
}

func overlay(s, to string, pos, size int) (Datum, error) {
	if pos < 1 {
		return nil, fmt.Errorf("non-positive substring length not allowed: %d", pos)
	}
	pos--

	runes := []rune(s)
	if pos > len(runes) {
		pos = len(runes)
	}
	after := pos + size
	if after < 0 {
		after = 0
	} else if after > len(runes) {
		after = len(runes)
	}
	return NewDString(string(runes[:pos]) + to + string(runes[after:])), nil
}

func round(x float64, n int64) (Datum, error) {
	pow := math.Pow(10, float64(n))

	if pow == 0 {
		// Rounding to so many digits on the left that we're underflowing.
		// Avoid a NaN below.
		return NewDFloat(DFloat(0)), nil
	}
	if math.Abs(x*pow) > 1e17 {
		// Rounding touches decimals below float precision; the operation
		// is a no-op.
		return NewDFloat(DFloat(x)), nil
	}

	v, frac := math.Modf(x * pow)
	// The following computation implements unbiased rounding, also
	// called bankers' rounding. It ensures that values that fall
	// exactly between two integers get equal chance to be rounded up or
	// down.
	if x > 0.0 {
		if frac > 0.5 || (frac == 0.5 && uint64(v)%2 != 0) {
			v += 1.0
		}
	} else {
		if frac < -0.5 || (frac == -0.5 && uint64(v)%2 != 0) {
			v -= 1.0
		}
	}

	return NewDFloat(DFloat(v / pow)), nil
}

const (
	scaleRatio = math.Ln2 / math.Ln10
)

func roundDecimal(x *inf.Dec, n int64) (Datum, error) {
	curScale := int64(x.Scale())

	if n > curScale+2000 {
		// If we let the decimal value grow too many decimals, the server
		// could explode (#8633).
		return nil, errRoundTooLow
	}

	dd := &DDecimal{}

	// We use WordLen(Bits())*8 instead of UnscaledBig().BitLen() here
	// as this is faster and we do not need an exact value for the
	// optimization below.
	upperCurDigits := encoding.WordLen(x.UnscaledBig().Bits()) * 8
	upperDigitsLeft := float64(curScale) - float64(upperCurDigits)*scaleRatio
	if n < int64(upperDigitsLeft)-1 {
		// This is an optimization. When the rounding scale is definitely
		// larger than the number, the result is 0, so we avoid
		// spending a lot of time in the division for nothing.
		return dd, nil
	}
	dd.Round(x, inf.Scale(n), inf.RoundHalfEven)
	return dd, nil
}

func expDecimal(x *inf.Dec) (Datum, error) {
	// The computation of Exp is separated in the decimal module by
	// computing the exponents on the left and right of the decimal
	// separator. The computation on the right is bounded by
	// decimal.Precision already; however if the value is too large on
	// the left the decimal value can grow too large in memory and slow
	// down / crash the entire server. So we prevent this from happening
	// and limit the argument to be ~1000 or less.
	curDigits := x.UnscaledBig().BitLen()
	binDigitsLeft := curDigits - int(float64(x.Scale())/scaleRatio)
	if binDigitsLeft > 10 /* 1024 */ {
		return nil, errArgTooBig
	}
	dd := &DDecimal{}
	decimal.Exp(&dd.Dec, x, decimal.Precision)
	return dd, nil
}

// Pick the greatest (or least value) from a tuple.
func pickFromTuple(ctx *EvalContext, greatest bool, args DTuple) (Datum, error) {
	g := args[0]
	// Pick a greater (or smaller) value.
	for _, d := range args[1:] {
		var eval Datum
		var err error
		if greatest {
			eval, err = evalComparison(ctx, LT, g, d)
		} else {
			eval, err = evalComparison(ctx, LT, d, g)
		}
		if err != nil {
			return nil, err
		}
		if eval == DBoolTrue ||
			(eval == DNull && g == DNull) {
			g = d
		}
	}
	return g, nil
}

func intPow(x, y int64) int64 {
	// Calculate x^y by squaring. See:
	// https://en.wikipedia.org/wiki/Exponentiation_by_squaring
	// special case 1: x == 0 (result 1 if y = 0, 0 otherwise)
	// special case 2: y < 0 (result 0)
	if y < 0 {
		return 0
	}
	var ret int64 = 1
	for y > 0 {
		if y&1 == 1 {
			ret *= x
		}
		x *= x
		y >>= 1
	}
	return ret
}

var uniqueBytesState struct {
	syncutil.Mutex
	nanos uint64
}

func generateUniqueBytes(nodeID roachpb.NodeID) DBytes {
	// Unique bytes are composed of the current time in nanoseconds and the
	// node-id. If the nanosecond value is the same on two consecutive calls to
	// timeutil.Now() the nanoseconds value is incremented. The node-id is varint
	// encoded. Since node-ids are allocated consecutively starting at 1, the
	// node-id field will consume 1 or 2 bytes for any reasonably sized cluster.
	//
	// TODO(pmattis): Do we have to worry about persisting the milliseconds value
	// periodically to avoid the clock ever going backwards (e.g. due to NTP
	// adjustment)?
	nanos := uint64(timeutil.Now().UnixNano())
	uniqueBytesState.Lock()
	if nanos <= uniqueBytesState.nanos {
		nanos = uniqueBytesState.nanos + 1
	}
	uniqueBytesState.nanos = nanos
	uniqueBytesState.Unlock()

	b := make([]byte, 0, 8+binary.MaxVarintLen32)
	b = encoding.EncodeUint64Ascending(b, nanos)
	// We use binary.PutUvarint instead of encoding.EncodeUvarint because the
	// former uses less space for values < 128 which is a common occurrence for
	// node IDs.
	n := binary.PutUvarint(b[len(b):len(b)+binary.MaxVarintLen32], uint64(nodeID))
	return DBytes(b[:len(b)+n])
}

var uniqueIntState struct {
	syncutil.Mutex
	timestamp uint64
}

var uniqueIntEpoch = time.Date(2015, time.January, 1, 0, 0, 0, 0, time.UTC).UnixNano()

func generateUniqueInt(nodeID roachpb.NodeID) DInt {
	// Unique ints are composed of the current time at a 10-microsecond
	// granularity and the node-id. The node-id is stored in the lower 15 bits of
	// the returned value and the timestamp is stored in the upper 48 bits. The
	// top-bit is left empty so that negative values are not returned. The 48-bit
	// timestamp field provides for 89 years of timestamps. We use a custom epoch
	// (Jan 1, 2015) in order to utilize the entire timestamp range.
	//
	// Note that generateUniqueInt() imposes a limit on node IDs while
	// generateUniqueBytes() does not.
	//
	// TODO(pmattis): Do we have to worry about persisting the milliseconds value
	// periodically to avoid the clock ever going backwards (e.g. due to NTP
	// adjustment)?
	const precision = uint64(10 * time.Microsecond)
	const nodeIDBits = 15

	nowNanos := timeutil.Now().UnixNano()
	// Paranoia: nowNanos should never be less than uniqueIntEpoch.
	if nowNanos < uniqueIntEpoch {
		nowNanos = uniqueIntEpoch
	}
	id := uint64(nowNanos-uniqueIntEpoch) / precision

	uniqueIntState.Lock()
	if id <= uniqueIntState.timestamp {
		id = uniqueIntState.timestamp + 1
	}
	uniqueIntState.timestamp = id
	uniqueIntState.Unlock()

	// We xor in the nodeID so that nodeIDs larger than 32K will flip bits in the
	// timestamp portion of the final value instead of always setting them.
	id = (id << nodeIDBits) ^ uint64(nodeID)
	return DInt(id)
}


text:
<?php

require_once './vendor/autoload.php';
require_once './vendor/ws/loewe/Woody/lib/winbinder.php';
require_once './vendor/ws/loewe/Woody/lib/fi/freeimage.inc.php';

use \ws\loewe\Utils\Autoload\Autoloader;
use \ws\loewe\Woody\Event\EventInfo;
use \ws\loewe\Woody\Event\EventFactory;
use \ws\loewe\Woody\Components\Component;

error_reporting(E_ALL | E_STRICT);

$autoloader = new Autoloader('./source/', 'php');

spl_autoload_register(array($autoloader, 'autoload'));

function globalWinBinderEventHandler($windowID, $id, $controlID = 0, $type = 0, $property = 0) {
  $eventInfo = new EventInfo($windowID, $id, Component::getComponentByID($controlID), $type, $property);

  foreach(EventFactory::createEvent($eventInfo) as $event) {
    if($event != null) {
      $event->dispatch();
    }
  }
}

$app = new ws\loewe\BattMan\App\BattManApplication();
$app->start();

redpajama_set_name: RedPajamaGithub


text:
import sys
import numpy as np
# ====================================================================
# Non-standard packages
# ====================================================================
import esbltaylor.esbltaylor as esbltaylorbuilt
import inverse_rayshooting.invraylocal as invraylocal
# ====================================================================
#   Functions
# ====================================================================
def binrot(theta, x_old, y_old):
    """Rotation by an angle alpha.

    :param theta: float, angle in radians.
    :param x_old: numpy array, x coodinate in the old frame.
    :param y_old: numpy array, y coodinate in the old frame.
    :return x_new: numpy array, x coodinate in the new frame.
    :return y_new: numpy array, y coodinate in the new frame.
    """
    cos_theta = np.cos(theta)
    sin_theta = np.sin(theta)
    x_new = x_old * cos_theta - y_old * sin_theta
    y_new = x_old * sin_theta + y_old * cos_theta
    return x_new, y_new
# --------------------------------------------------------------------
def lens_rotation(alpha0, s0, dalpha, ds, t, tb):
    """Compute the angle alpha and projected separation s for each
    time step due to the lens orbital motion.

    :param alpha0: angle alpha at date tb.
    :param s0: projected separation at date tb.
    :param dalpha: float, angular velocity at date tb
        (radians.year^-1).
    :param ds: change rate of separation (year^-1).
    :param t: list of dates.
    :param tb: time reference for linear development.
    :type alpha0: float
    :type s0: float
    :type dalpha: float
    :type ds: float
    :type t: numpy array
    :type tb: float
    :return: unpacked list of actual alpha and s values at each date.
    :rtype: numpy array, numpy array
    """
    Cte_yr_d = 365.25  # Julian year in days
    alpha = alpha0 - (t - tb) * dalpha / Cte_yr_d
    s = s0 + (t-tb) * ds / Cte_yr_d
    return alpha, s
# ----------------------------------------------------------------------
def critic_roots(s, q, phi):
    """Compute the critic curve. The conventions are :
    * the heaviest body is the origin;
    * the lightest body is at (-s, 0).

    :param s: projected separation in units of the Einstein radius
    :param q: mass ratio (q<1)
    :param phi: parameter to sample the critical curve
    :type s: float
    :type q: float
    :type phi: float
    :return: complex roots of the polynomial equation that gives the
    position of the critical curve
    :rtype: numpy array
    """
    coefs = [1, 2 * s, s ** 2 - np.exp(1j * phi),
             -2 * s * np.exp(1j * phi) / (1 + q),
             -(s ** 2 * np.exp(1j * phi) / (1 + q))]
    result = np.roots(coefs)
    del coefs
    return result
# --------------------------------------------------------------------
def magnifcalc(t, param, Ds=None, tb=None, **kwargs_method):
    # Compute the amplification
    kwargs = dict()
    kwargs.update({'params': param})
    kwargs.update({'dates': t})
    kwargs.update({'tb': tb})
    kwargs.update({'Ds': Ds})
    kwargs.update(kwargs_method)
    amp, flag = magnifcalc_wrap(**kwargs)
    return amp
# --------------------------------------------------------------------
def magnifcalc_wrap(**kwargs):

    try:
        params = kwargs['params']
    except KeyError:
        chat = "No parameters received in magnifcalc(...) from test_import."
        sys.exit(chat)
    try:
        t = kwargs['dates']
    except KeyError:
        chat = "No dates received in magnifcalc(...) from test_import."
        sys.exit(chat)
    try:
        tb = kwargs['tb']
    except KeyError:
        tb = params['t0']
    try:
        Ds = kwargs['Ds']
    except KeyError:
        Ds = dict({'N' : np.zeros(len(t)), 'E' : np.zeros(len(t))})
    try:
        err = float(kwargs['TriggerNextMethod'.lower()])
    except KeyError:
        err = 1e-3
    try:
        ray_sigma = float(kwargs['PrecisionGoalRayshooting'.lower()])
    except KeyError:
        ray_sigma = 1e-2
    try:
        ray_rect_pix = int(kwargs['LocalMarginRayshooting'.lower()])
    except KeyError:
        ray_rect_pix = 1

    t0 = params['t0']
    u0 = params['u0']
    tE = params['tE']
    rho = params['rho']
    gamma = params['gamma']
    q = params['q']
    piEN = params['piEN']
    piEE = params['piEE']
    alpha0 = params['alpha']
    s0 = params['s']
    dalpha = params['dadt']
    ds = params['dsdt']

    # Correction of the separation/angle due to lens orbital motion
    alpha, s = lens_rotation(alpha0, s0, dalpha, ds, t, tb)

    # Correction of the trajectory due to parallax
    DsN = Ds['N']
    DsE = Ds['E']
    tau = (t-t0)/tE + piEN * DsN + piEE * DsE
    beta = u0 + piEN * DsE - piEE * DsN
    x, y = binrot(alpha, tau, beta)

    # Center of mass to Cassan (2008)
    GL1 = s * q / (1 + q)
    x = x - GL1

    # Compute magnification using quadrupole, hexadecapole or inverse rayshooting
    flag = np.zeros(len(x), dtype='i4')
    magnification = np.zeros(len(x), dtype='f8')
    for i in range(4):
        rgs = np.where(flag == 0)
        s_curr = s[rgs]
        x_curr = x[rgs]
        y_curr = y[rgs]
        if i == 0:
            # print 'i=0', len(x_curr)
            degree = 0
            list = [[q, rho, gamma, degree, err, ray_sigma, ray_rect_pix], s_curr.tolist(), x_curr.tolist(), y_curr.tolist()]
            result = esbltaylorbuilt.magnifcalc(list)
            magnification_curr = np.array(result[0])
            flag_curr = np.array(result[1], dtype='i4')
            magnification[rgs] = magnification_curr
        if i == 1:
            # print 'i=1', len(x_curr)
            degree = 2
            list = [[q, rho, gamma, degree, err, ray_sigma, ray_rect_pix], s_curr.tolist(), x_curr.tolist(), y_curr.tolist()]
            result = esbltaylorbuilt.magnifcalc(list)
            magnification_curr = np.array(result[0])
            flag_curr = np.array(result[1], dtype='i4')
            flag[rgs] = flag_curr
            magnification[rgs] = magnification_curr
        if (i == 2) and len(x_curr)>0:
            # print 'i=2', len(x_curr)
            degree = 4
            list = [[q, rho, gamma, degree, err, ray_sigma, ray_rect_pix], s_curr.tolist(), x_curr.tolist(), y_curr.tolist()]
            result = esbltaylorbuilt.magnifcalc(list)
            magnification_curr = np.array(result[0])
            flag_curr = np.array(result[1], dtype='i4')
            flag[rgs] = flag_curr
            magnification[rgs] = magnification_curr
        if (i == 3) and len(x_curr)>0:
            # print 'i=3', len(x_curr)
            list = [[q, rho, gamma, degree, err, ray_sigma, ray_rect_pix], s_curr.tolist(), x_curr.tolist(), y_curr.tolist()]
            result = invraylocal.magnifcalc(list)
            magnification_curr = np.array(result[0])
            flag_curr = np.array(result[1], dtype='i4')
            flag[rgs] = flag_curr
            magnification[rgs] = magnification_curr

    del list
    del result
    del flag_curr
    del magnification_curr

    return magnification, flag

# ====================================================================
# Main function
# ====================================================================
if __name__=="__main__":
    print 'Please use with muLAn.'


text:
<?php

namespace Sylius\Behat\Context\Ui\Shop;

use Behat\Behat\Context\Context;
use Sylius\Behat\NotificationType;
use Sylius\Behat\Page\Shop\Account\AddressBook\CreatePageInterface;
use Sylius\Behat\Page\Shop\Account\AddressBook\IndexPageInterface;
use Sylius\Behat\Page\Shop\Account\AddressBook\UpdatePageInterface;
use Sylius\Behat\Page\SymfonyPageInterface;
use Sylius\Behat\Page\UnexpectedPageException;
use Sylius\Behat\Service\NotificationCheckerInterface;
use Sylius\Behat\Service\Resolver\CurrentPageResolverInterface;
use Sylius\Behat\Service\SharedStorageInterface;
use Sylius\Component\Core\Model\AddressInterface;
use Sylius\Component\Resource\Repository\RepositoryInterface;
use Webmozart\Assert\Assert;

/**
 * @author Anna Walasek <anna.walasek@lakion.com>
 * @author Jan Góralski <jan.goralski@lakion.com>
 */
final class AddressBookContext implements Context
{
    /**
     * @var SharedStorageInterface
     */
    private $sharedStorage;

    /**
     * @var RepositoryInterface
     */
    private $addressRepository;

    /**
     * @var IndexPageInterface
     */
    private $addressBookIndexPage;

    /**
     * @var CreatePageInterface
     */
    private $addressBookCreatePage;

    /**
     * @var UpdatePageInterface
     */
    private $addressBookUpdatePage;

    /**
     * @var CurrentPageResolverInterface
     */
    private $currentPageResolver;

    /**
     * @var NotificationCheckerInterface
     */
    private $notificationChecker;

    /**
     * @param SharedStorageInterface $sharedStorage
     * @param RepositoryInterface $addressRepository
     * @param IndexPageInterface $addressBookIndexPage
     * @param CreatePageInterface $addressBookCreatePage
     * @param UpdatePageInterface $addressBookUpdatePage
     * @param CurrentPageResolverInterface $currentPageResolver
     * @param NotificationCheckerInterface $notificationChecker
     */
    public function __construct(
        SharedStorageInterface $sharedStorage,
        RepositoryInterface $addressRepository,
        IndexPageInterface $addressBookIndexPage,
        CreatePageInterface $addressBookCreatePage,
        UpdatePageInterface $addressBookUpdatePage,
        CurrentPageResolverInterface $currentPageResolver,
        NotificationCheckerInterface $notificationChecker
    ) {
        $this->sharedStorage = $sharedStorage;
        $this->addressRepository = $addressRepository;
        $this->addressBookIndexPage = $addressBookIndexPage;
        $this->addressBookCreatePage = $addressBookCreatePage;
        $this->addressBookUpdatePage = $addressBookUpdatePage;
        $this->currentPageResolver = $currentPageResolver;
        $this->notificationChecker = $notificationChecker;
    }

    /**
     * @Given /^I am editing the address of "([^"]+)"$/
     */
    public function iEditAddressOf($fullName)
    {
        $this->sharedStorage->set('full_name', $fullName);

        $this->addressBookIndexPage->open();
        $this->addressBookIndexPage->editAddress($fullName);
    }

    /**
     * @Given my default address is of :fullName
     * @When I set the address of :fullName as default
     */
    public function iSetTheAddressOfAsDefault($fullName)
    {
        $this->sharedStorage->set('full_name', $fullName);

        $this->addressBookIndexPage->setAsDefault($fullName);
    }

    /**
     * @Given I want to add a new address to my address book
     */
    public function iWantToAddANewAddressToMyAddressBook()
    {
        $this->addressBookCreatePage->open();
    }

    /**
     * @Given I am browsing my address book
     * @When I browse my address book
     */
    public function iBrowseMyAddresses()
    {
        $this->addressBookIndexPage->open();
    }

    /**
     * @When I specify :provinceName as my province
     */
    public function iSpecifyAsMyProvince($provinceName)
    {
        $this->addressBookUpdatePage->specifyProvince($provinceName);
    }

    /**
     * @When I choose :provinceName as my province
     */
    public function iChooseAsMyProvince($provinceName)
    {
        $this->addressBookUpdatePage->selectProvince($provinceName);
    }

    /**
     * @When I choose :countryName as my country
     */
    public function iChooseAsMyCountry($countryName)
    {
        /** @var CreatePageInterface|UpdatePageInterface $currentPage */
        $currentPage = $this->getCurrentPage();
        $currentPage->selectCountry($countryName);
    }

    /**
     * @When /^I change the ([^"]+) to "([^"]+)"$/
     */
    public function iChangeMyTo($field, $value)
    {
        $this->addressBookUpdatePage->fillField($field, $value);
    }

    /**
     * @When /^I specify the (address as "([^"]+)", "([^"]+)", "([^"]+)", "([^"]+)", "([^"]+)", "([^"]+)")$/
     */
    public function iSpecifyTheAddressAs(AddressInterface $address)
    {
        $this->addressBookCreatePage->fillAddressData($address);
    }

    /**
     * @When I leave every field empty
     */
    public function iLeaveEveryFieldEmpty()
    {
        // Intentionally left empty
    }

    /**
     * @When I add it
     */
    public function iAddIt()
    {
        $this->addressBookCreatePage->addAddress();
    }

    /**
     * @When I save my changed address
     */
    public function iSaveChangedAddress()
    {
        $this->addressBookUpdatePage->saveChanges();
    }

    /**
     * @When I delete the :fullName address
     */
    public function iDeleteTheAddress($fullname)
    {
        $this->addressBookIndexPage->deleteAddress($fullname);
    }

    /**
     * @When /^I try to edit the address of "([^"]+)"$/
     */
    public function iTryToEdit($fullName)
    {
        $this->sharedStorage->set('full_name', $fullName);

        $address = $this->getAddressOf($fullName);

        $this->addressBookUpdatePage->tryToOpen(['id' => $address->getId()]);
    }

    /**
     * @Then /^it should contain "([^"]+)"$/
     */
    public function itShouldContain($value)
    {
        $fullName = $this->sharedStorage->get('full_name');

        $this->addressBookIndexPage->addressOfContains($fullName, $value);
    }

    /**
     * @Then there should( still) be a single address in my book
     */
    public function iShouldSeeASingleAddressInTheList()
    {
        $this->assertAddressesCountOnPage(1);
    }

    /**
     * @Then this address should be assigned to :fullName
     * @Then /^the address assigned to "([^"]+)" should (appear|be) in my book$/
     */
    public function thisAddressShouldHavePersonFirstNameAndLastName($fullName)
    {
        Assert::true(
            $this->addressBookIndexPage->hasAddressOf($fullName),
            sprintf('An address of "%s" should be on the list.', $fullName)
        );
    }

    /**
     * @Then I should still be on the address addition page
     */
    public function iShouldStillBeOnAddressAdditionPage()
    {
        Assert::true(
            $this->addressBookCreatePage->isOpen(),
            'The address creation page should be opened.'
        );
    }

    /**
     * @Then I should be notified that the province needs to be specified
     */
    public function iShouldBeNotifiedThatTheProvinceNeedsToBeSpecified()
    {
        Assert::true(
            $this->addressBookCreatePage->hasProvinceValidationMessage(),
            'Province validation messages should be visible.'
        );
    }

    /**
     * @Then /^I should be notified about (\d+) errors$/
     */
    public function iShouldBeNotifiedAboutErrors($expectedCount)
    {
        $actualCount = $this->addressBookCreatePage->countValidationMessages();

        Assert::same(
            (int) $expectedCount,
            $actualCount,
            sprintf('There should be %d validation messages, but %d has been found.', $expectedCount, $actualCount)
        );
    }

    /**
     * @Then there should be no addresses
     */
    public function thereShouldBeNoAddresses()
    {
        Assert::true(
            $this->addressBookIndexPage->hasNoAddresses(),
            'There should be no addresses on the list.'
        );
    }

    /**
     * @Then I should not see the address assigned to :fullName
     */
    public function iShouldNotSeeAddressOf($fullName)
    {
        Assert::false(
            $this->addressBookIndexPage->hasAddressOf($fullName),
            sprintf('The address of "%s" should not be on the list.', $fullName)
        );
    }

    /**
     * @Then /^I should(?:| still) have (\d+) address(?:|es) in my address book$/
     */
    public function iShouldHaveAddresses($count)
    {
        $this->addressBookIndexPage->open();

        $this->assertAddressesCountOnPage((int) $count);
    }

    /**
     * @Then I should be notified that the address has been successfully added
     */
    public function iShouldBeNotifiedThatAddressHasBeenSuccessfullyAdded()
    {
        $this->notificationChecker->checkNotification('Address has been successfully added.', NotificationType::success());
    }

    /**
     * @Then I should be notified that the address has been successfully deleted
     */
    public function iShouldBeNotifiedAboutSuccessfulDelete()
    {
        $this->notificationChecker->checkNotification('Address has been successfully deleted.', NotificationType::success());
    }

    /**
     * @Then I should be unable to edit their address
     */
    public function iShouldBeUnableToEditTheirAddress()
    {
        $address = $this->getAddressOf($this->sharedStorage->getLatestResource());

        Assert::false(
            $this->addressBookUpdatePage->isOpen(['id' => $address->getId()]),
            sprintf(
                'I should be unable to edit the address of "%s %s"',
                $address->getFirstName(),
                $address->getLastName()
            )
        );
    }

    /**
     * @Then I should be notified that the address has been successfully updated
     */
    public function iShouldBeNotifiedAboutSuccessfulUpdate()
    {
        $this->notificationChecker->checkNotification('Address has been successfully updated.', NotificationType::success());
    }

    /**
     * @Then I should be notified that the address has been set as default
     */
    public function iShouldBeNotifiedThatAddressHasBeenSetAsDefault()
    {
        $this->notificationChecker->checkNotification('Address has been set as default', NotificationType::success());
    }

    /**
     * @Then I should not have a default address
     */
    public function iShouldHaveNoDefaultAddress()
    {
        Assert::true(
            $this->addressBookIndexPage->hasNoDefaultAddress(),
            'There should be no default address.'
        );
    }

    /**
     * @Then /^the address of "([^"]+)" should be marked as my default$/
     * @Then /^(it) should be marked as my default address$/
     */
    public function itShouldBeMarkedAsMyDefaultAddress($fullName)
    {
        $actualFullName = $this->addressBookIndexPage->getFullNameOfDefaultAddress();

        Assert::same(
            $fullName,
            $actualFullName,
            sprintf('The default address should be of "%s", but is of "%s".', $fullName, $actualFullName)
        );
    }

    /**
     * @param string $fullName
     *
     * @return AddressInterface
     */
    private function getAddressOf($fullName)
    {
        list($firstName, $lastName) = explode(' ', $fullName);

        /** @var AddressInterface $address */
        $address = $this->addressRepository->findOneBy(['firstName' => $firstName, 'lastName' => $lastName]);
        Assert::notNull($address);

        return $address;
    }

    /**
     * @return SymfonyPageInterface
     */
    private function getCurrentPage()
    {
        return $this
            ->currentPageResolver
            ->getCurrentPageWithForm([
                $this->addressBookCreatePage,
                $this->addressBookUpdatePage
        ]);
    }

    /**
     * @param int $expectedCount
     *
     * @throws \InvalidArgumentException
     */
    private function assertAddressesCountOnPage($expectedCount)
    {
        $actualCount = $this->addressBookIndexPage->getAddressesCount();

        Assert::same(
            $expectedCount,
            $actualCount,
            sprintf(
                'There should be %d addresses on the list, but %d addresses has been found.',
                $expectedCount,
                $actualCount
            )
        );
    }
}


text:
<?php
class kategori_model extends MY_Model{
/*  public function selectAll()
   {
	$this->db->get('kategori');
   }

   public function ambil_data() {
        return $this->db->count_all("kategori");
   }
    public function get_kategori($limit, $start) {
    $this->db->limit($limit, $start);
    $query = $this->db->get("kategori");

    if ($query->num_rows() > 0) {
        foreach ($query->result() as $row) {
               $data[] = $row;
            }
            return $data;
        }
        return false;
   }*/
  protected $_table     = 'kategori';
  protected $_primary_key = 'id_kategori';

   function hapus_data($where, $table){
      $this->db->where($where);

      $this->db->delete($table);
    }

}
?>


text:
#include <string.h>
#include <assert.h>
#include "os/mynewt.h"
#include "modlog/modlog.h"
#include "bootutil/image.h"
#include "bootutil/bootutil.h"
#include "img_mgmt/img_mgmt.h"
#include "config/config.h"
#include "config/config_file.h"
#include "reboot/log_reboot.h"
#include "bsp/bsp.h"
#include "flash_map/flash_map.h"
#include "tinycbor/cbor.h"
#include "tinycbor/cbor_buf_writer.h"

uint16_t reboot_cnt;
static int8_t log_reboot_written;

static char *reboot_conf_get(int argc, char **argv, char *buf, int max_len);
static int reboot_conf_set(int argc, char **argv, char *val);
static int reboot_conf_export(void (*export_func)(char *name, char *val),
                              enum conf_export_tgt tgt);

struct conf_handler reboot_conf_handler = {
    .ch_name = "reboot",
    .ch_get = reboot_conf_get,
    .ch_set = reboot_conf_set,
    .ch_commit = NULL,
    .ch_export = reboot_conf_export
};

#if MYNEWT_VAL(REBOOT_LOG_FCB)
static struct fcb_log reboot_log_fcb;
static struct log reboot_log;
#if MYNEWT_VAL(LOG_FCB)
static struct flash_area reboot_sector;
#endif
#if MYNEWT_VAL(LOG_FCB2)
static struct flash_sector_range reboot_sector;
#endif
#endif

#if MYNEWT_VAL(REBOOT_LOG_CONSOLE)
static int
log_reboot_init_console(void)
{
    int rc;

    rc = modlog_register(LOG_MODULE_REBOOT, log_console_get(), LOG_SYSLEVEL,
                         NULL);
    if (rc != 0) {
        return rc;
    }

    return 0;

}
#endif

#if MYNEWT_VAL(REBOOT_LOG_FCB)
static int
log_reboot_init_fcb(void)
{
    const struct flash_area *ptr;
#if MYNEWT_VAL(LOG_FCB)
    struct fcb *fcbp;
#elif MYNEWT_VAL(LOG_FCB2)
    struct fcb2 *fcbp;
#endif
    int rc;

    if (flash_area_open(MYNEWT_VAL(REBOOT_LOG_FLASH_AREA), &ptr)) {
        return SYS_EUNKNOWN;
    }

    reboot_log_fcb.fl_entries = MYNEWT_VAL(REBOOT_LOG_ENTRY_COUNT);
    fcbp = &reboot_log_fcb.fl_fcb;
#if MYNEWT_VAL(LOG_FCB)
    reboot_sector = *ptr;
    fcbp->f_magic = 0x7EADBADF;
    fcbp->f_version = g_log_info.li_version;
    fcbp->f_sector_cnt = 1;
    fcbp->f_sectors = &reboot_sector;

    rc = fcb_init(fcbp);
    if (rc) {
        flash_area_erase(ptr, 0, ptr->fa_size);
        rc = fcb_init(fcbp);
        if (rc) {
            return rc;
        }
    }
#endif
#if MYNEWT_VAL(LOG_FCB2)
    fcbp->f_magic = 0x8EADBAE0;
    fcbp->f_version = g_log_info.li_version;
    fcbp->f_sector_cnt = 1;
    fcbp->f_range_cnt = 1;
    fcbp->f_ranges = &reboot_sector;
    reboot_sector.fsr_flash_area = *ptr;
    reboot_sector.fsr_sector_count = 1;
    reboot_sector.fsr_sector_size = ptr->fa_size;
    reboot_sector.fsr_align = flash_area_align(ptr);

    rc = fcb2_init(fcbp);
    if (rc) {
        flash_area_erase(ptr, 0, ptr->fa_size);
        rc = fcb2_init(fcbp);
        if (rc) {
            return rc;
        }
    }
#endif

    rc = log_register("reboot_log", &reboot_log, &log_fcb_handler,
                      &reboot_log_fcb, LOG_SYSLEVEL);
    if (rc != 0) {
        return rc;
    }

    rc = modlog_register(LOG_MODULE_REBOOT, &reboot_log, LOG_SYSLEVEL,
                         NULL);
    if (rc != 0) {
        return rc;
    }

    return 0;
}
#endif

static int
reboot_cnt_inc(void)
{
    char str[12];
    int rc;

    reboot_cnt++;
    rc = conf_save_one("reboot/reboot_cnt",
                       conf_str_from_value(CONF_INT16, &reboot_cnt,
                                           str, sizeof(str)));
    return rc;
}

/**
 * Logs reboot with the specified reason
 * @param reason for reboot
 * @return 0 on success; non-zero on failure
 */
static int
log_reboot_write(const struct log_reboot_info *info)
{
    struct image_version ver;
    uint8_t hash[32];
    char buf[MYNEWT_VAL(REBOOT_LOG_BUF_SIZE)];
    uint8_t cbor_enc_buf[MYNEWT_VAL(REBOOT_LOG_BUF_SIZE)];
    int off;
    int rc;
    int i;
    struct cbor_buf_writer writer;
    struct CborEncoder enc;
    struct CborEncoder map;
    size_t cbor_buf_len;
    uint32_t flags;
    uint8_t state_flags;

#if MYNEWT_VAL(REBOOT_LOG_FCB)
    {
        const struct flash_area *ptr;
        if (flash_area_open(MYNEWT_VAL(REBOOT_LOG_FLASH_AREA), &ptr)) {
            return 0;
        }
    }
#endif

    rc = img_mgmt_read_info(boot_current_slot, &ver, hash, &flags);
    if (rc != 0) {
        return rc;
    }

    memset(cbor_enc_buf, 0, sizeof cbor_enc_buf);

    cbor_buf_writer_init(&writer, cbor_enc_buf, sizeof cbor_enc_buf);
    cbor_encoder_init(&enc, &writer.enc, 0);
    rc = cbor_encoder_create_map(&enc, &map, CborIndefiniteLength);
    if (rc != 0) {
        return rc;
    }

    cbor_encode_text_stringz(&map, "rsn");
    cbor_encode_text_stringz(&map,log_reboot_reason_str(info->reason));

    cbor_encode_text_stringz(&map, "cnt");
    cbor_encode_int(&map, reboot_cnt);

    cbor_encode_text_stringz(&map, "img");
    snprintf(buf, sizeof buf, "%u.%u.%u.%u",
                  ver.iv_major, ver.iv_minor, ver.iv_revision,
                  (unsigned int)ver.iv_build_num);
    cbor_encode_text_stringz(&map, buf);

    cbor_encode_text_stringz(&map, "hash");
    off = 0;
    for (i = 0; i < sizeof hash; i++) {
        off += snprintf(buf + off, sizeof buf - off, "%02x",
                        (unsigned int)hash[i]);
    }
    cbor_encode_text_stringz(&map, buf);

    if (info->file != NULL) {
        cbor_encode_text_stringz(&map, "die");
        off  = 0;

        /* If die filename is longer than 1/3 of total allocated
         * buffer, then trim the filename from left. */
        if (strlen(info->file) > ((sizeof buf) / 3)) {
            off = strlen(info->file) - ((sizeof buf) / 3);
        }
        snprintf(buf, sizeof buf, "%s:%d",
                &info->file[off], info->line);
        cbor_encode_text_stringz(&map, buf);
    }

    if (info->pc != 0) {
        cbor_encode_text_stringz(&map, "pc");
        cbor_encode_int(&map, info->pc);
    }

    state_flags = img_mgmt_state_flags(boot_current_slot);
    cbor_encode_text_stringz(&map, "flags");
    off = 0;
    buf[0] = '\0';

    if (state_flags & IMG_MGMT_STATE_F_ACTIVE) {
        off += snprintf(buf + off, sizeof buf - off, "%s ", "active");
    }
    if (!(flags & IMAGE_F_NON_BOOTABLE)) {
        off += snprintf(buf + off, sizeof buf - off, "%s ", "bootable");
    }
    if (state_flags & IMG_MGMT_STATE_F_CONFIRMED) {
        off += snprintf(buf + off, sizeof buf - off, "%s ", "confirmed");
    }
    if (state_flags & IMG_MGMT_STATE_F_PENDING) {
        off += snprintf(buf + off, sizeof buf - off, "%s ", "pending");
    }
    if (off > 1) {
        buf[off - 1] = '\0';
    }
    cbor_encode_text_stringz(&map, buf);

    /* Find length of the CBOR encoded log entry. */
    cbor_buf_len = cbor_buf_writer_buffer_size(&writer, cbor_enc_buf) + 1;

    rc = cbor_encoder_close_container(&enc, &map);
    if (rc != 0) {
        return SYS_ENOMEM;
    }

    /* Log a CBOR encoded reboot record. */
    modlog_append(LOG_MODULE_REBOOT, LOG_LEVEL_CRITICAL, LOG_ETYPE_CBOR,
                  cbor_enc_buf, cbor_buf_len);

    return 0;
}

int
log_reboot(const struct log_reboot_info *info)
{
    int rc;

    /* Don't log a second reboot entry. */
    if (log_reboot_written) {
        return 0;
    }

    rc = log_reboot_write(info);
    if (rc != 0) {
        return rc;
    }

    if (info->reason != HAL_RESET_REQUESTED &&
        info->reason != HAL_RESET_DFU) {
        /* Record that we have written a reboot entry for the current boot.
         * Upon rebooting, we won't write a second entry.
         */
        log_reboot_written = 1;
        conf_save_one("reboot/written", "1");
    }

    return 0;
}

/**
 * Increments the reboot counter and writes an entry to the reboot log, if
 * necessary.  This function should be called from main() after config
 * settings have been loaded via conf_load().
 *
 * @param reason                The cause of the reboot.
 */
void
reboot_start(enum hal_reset_reason reason)
{
    struct log_reboot_info info;

    /* If an entry wasn't written before the previous reboot, write one now. */
    if (!log_reboot_written) {
        reboot_cnt_inc();

        info = (struct log_reboot_info) {
            .reason = reason,
            .file = NULL,
            .line = 0,
            .pc = 0,
        };
        log_reboot_write(&info);
    }

    /* Record that we haven't written a reboot entry for the current boot. */
    log_reboot_written = 0;
    conf_save_one("reboot/written", "0");
}

static char *
reboot_conf_get(int argc, char **argv, char *buf, int max_len)
{
    if (argc == 1) {
        if (!strcmp(argv[0], "reboot_cnt")) {
            return conf_str_from_value(CONF_INT16, &reboot_cnt, buf, max_len);
        } else if (!strcmp(argv[0], "written")) {
            return conf_str_from_value(CONF_BOOL, &log_reboot_written,
                                       buf, max_len);
        }
    }
    return NULL;
}

static int
reboot_conf_set(int argc, char **argv, char *val)
{
    if (argc == 1) {
        if (!strcmp(argv[0], "reboot_cnt")) {
            return CONF_VALUE_SET(val, CONF_INT16, reboot_cnt);
        } else if (!strcmp(argv[0], "written")) {
            return CONF_VALUE_SET(val, CONF_INT16, log_reboot_written);
        }
    }

    return OS_ENOENT;
}

static int
reboot_conf_export(void (*func)(char *name, char *val),
                   enum conf_export_tgt tgt)
{
    char str[12];

    if (tgt == CONF_EXPORT_SHOW) {
        func("reboot/reboot_cnt",
             conf_str_from_value(CONF_INT16, &reboot_cnt, str, sizeof str));
        func("reboot/written",
             conf_str_from_value(CONF_BOOL, &log_reboot_written, str,
                                 sizeof str));
    }
    return 0;
}

const char *
log_reboot_reason_str(enum hal_reset_reason reason)
{
    static char str_reason[MYNEWT_VAL(REBOOT_LOG_REBOOT_REASON_SIZE)];

    if (reason >= HAL_RESET_OTHER) {
        snprintf(str_reason,MYNEWT_VAL(REBOOT_LOG_REBOOT_REASON_SIZE),"OTHER: 0x%X",reason - HAL_RESET_OTHER);
        return str_reason;
    }

    switch (reason) {
    case HAL_RESET_POR:
        return "HARD";
        break;
    case HAL_RESET_PIN:
        return "RESET_PIN";
        break;
    case HAL_RESET_WATCHDOG:
        return "WDOG";
        break;
    case HAL_RESET_SOFT:
        return "SOFT";
        break;
    case HAL_RESET_BROWNOUT:
        return "BROWNOUT";
        break;
    case HAL_RESET_REQUESTED:
        return "REQUESTED";
        break;
    case HAL_RESET_SYS_OFF_INT:
        return "SYSTEM_OFF_INT";
        break;
    case HAL_RESET_DFU:
        return "DFU";
        break;
    default:
        snprintf(str_reason,MYNEWT_VAL(REBOOT_LOG_REBOOT_REASON_SIZE),"UNKNOWN %d",reason);
        return str_reason;
        break;
    }
}

void
log_reboot_pkg_init(void)
{
    int rc;

    /* Ensure this function only gets called by sysinit. */
    SYSINIT_ASSERT_ACTIVE();

    rc = conf_register(&reboot_conf_handler);
    SYSINIT_PANIC_ASSERT(rc == 0);

#if MYNEWT_VAL(REBOOT_LOG_FCB)
    rc = log_reboot_init_fcb();
    SYSINIT_PANIC_ASSERT(rc == 0);
#endif
#if MYNEWT_VAL(REBOOT_LOG_CONSOLE)
    rc = log_reboot_init_console();
    SYSINIT_PANIC_ASSERT(rc == 0);
#endif
}