mirror of
https://github.com/open-policy-agent/opa.git
synced 2026-08-12 19:32:48 -06:00
4ab2ac0c61
* server: port compile API Also adds e2e tests: These include coverage for ucast in the prisma setting, and thus require some JS runtime. * e2e: selectively skip e2e Compile API tests ...for macos runs, and for the go-compat suites. * server: accept timer_rego_external_resolve_ns metrics with value 0 When running the tests in a loop for a while, I would see values of 0ns for this metric. However, comparing with its non-zero values, which are often 41 or 42ns, it seems like this is just not happening in this code path. So if "almost nothing" actually goes below 1ns, it's OK. * e2e: split dep-heavy e2e tests into their own go module * Makefile: export DOCKER_RUNNING (make e2e read it) --------- Co-authored-by: Philip Conrad <philip@chariot-chaser.net> Signed-off-by: Stephan Renatus <stephan.renatus@gmail.com>
126 lines
2.6 KiB
Go
126 lines
2.6 KiB
Go
// Copyright 2018 Huan Du. All rights reserved.
|
|
// Licensed under the MIT license that can be found in the LICENSE file.
|
|
|
|
package sqlbuilder
|
|
|
|
import (
|
|
"reflect"
|
|
"strings"
|
|
)
|
|
|
|
// Escape replaces `$` with `$$` in ident.
|
|
func Escape(ident string) string {
|
|
return strings.Replace(ident, "$", "$$", -1)
|
|
}
|
|
|
|
// EscapeAll replaces `$` with `$$` in all strings of ident.
|
|
func EscapeAll(ident ...string) []string {
|
|
escaped := make([]string, 0, len(ident))
|
|
|
|
for _, i := range ident {
|
|
escaped = append(escaped, Escape(i))
|
|
}
|
|
|
|
return escaped
|
|
}
|
|
|
|
// Flatten recursively extracts values in slices and returns
|
|
// a flattened []interface{} with all values.
|
|
// If slices is not a slice, return `[]interface{}{slices}`.
|
|
func Flatten(slices interface{}) (flattened []interface{}) {
|
|
v := reflect.ValueOf(slices)
|
|
slices, flattened = flatten(v)
|
|
|
|
if slices != nil {
|
|
return []interface{}{slices}
|
|
}
|
|
|
|
return flattened
|
|
}
|
|
|
|
func flatten(v reflect.Value) (elem interface{}, flattened []interface{}) {
|
|
k := v.Kind()
|
|
|
|
for k == reflect.Interface {
|
|
v = v.Elem()
|
|
k = v.Kind()
|
|
}
|
|
|
|
if k != reflect.Slice && k != reflect.Array {
|
|
if !v.IsValid() || !v.CanInterface() {
|
|
return
|
|
}
|
|
|
|
elem = v.Interface()
|
|
return elem, nil
|
|
}
|
|
|
|
for i, l := 0, v.Len(); i < l; i++ {
|
|
e, f := flatten(v.Index(i))
|
|
|
|
if e == nil {
|
|
flattened = append(flattened, f...)
|
|
} else {
|
|
flattened = append(flattened, e)
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
type rawArgs struct {
|
|
expr string
|
|
}
|
|
|
|
// Raw marks the expr as a raw value which will not be added to args.
|
|
func Raw(expr string) interface{} {
|
|
return rawArgs{expr}
|
|
}
|
|
|
|
type listArgs struct {
|
|
args []interface{}
|
|
isTuple bool
|
|
}
|
|
|
|
// List marks arg as a list of data.
|
|
// If arg is `[]int{1, 2, 3}`, it will be compiled to `?, ?, ?` with args `[1 2 3]`.
|
|
func List(arg interface{}) interface{} {
|
|
return listArgs{
|
|
args: Flatten(arg),
|
|
}
|
|
}
|
|
|
|
// Tuple wraps values into a tuple and can be used as a single value.
|
|
func Tuple(values ...interface{}) interface{} {
|
|
return listArgs{
|
|
args: values,
|
|
isTuple: true,
|
|
}
|
|
}
|
|
|
|
// TupleNames joins names with tuple format.
|
|
// The names is not escaped. Use `EscapeAll` to escape them if necessary.
|
|
func TupleNames(names ...string) string {
|
|
buf := newStringBuilder()
|
|
buf.WriteRune('(')
|
|
buf.WriteStrings(names, ", ")
|
|
buf.WriteRune(')')
|
|
|
|
return buf.String()
|
|
}
|
|
|
|
type namedArgs struct {
|
|
name string
|
|
arg interface{}
|
|
}
|
|
|
|
// Named creates a named argument.
|
|
// Unlike `sql.Named`, this named argument works only with `Build` or `BuildNamed` for convenience
|
|
// and will be replaced to a `?` after `Compile`.
|
|
func Named(name string, arg interface{}) interface{} {
|
|
return namedArgs{
|
|
name: name,
|
|
arg: arg,
|
|
}
|
|
}
|