mirror of
https://github.com/neilotoole/sq.git
synced 2024-11-27 15:43:21 +03:00
parent
0841e7154f
commit
7c56377b40
@ -152,7 +152,7 @@ linters-settings:
|
||||
# Run `go tool vet help` to see all analyzers.
|
||||
# Default: []
|
||||
disable:
|
||||
- fieldalignment # too strict
|
||||
# - fieldalignment # too strict
|
||||
# Settings per analyzer.
|
||||
settings:
|
||||
shadow:
|
||||
@ -626,6 +626,7 @@ issues:
|
||||
linters: [ errorlint ]
|
||||
- path: "_test\\.go"
|
||||
linters:
|
||||
- govet
|
||||
- bodyclose
|
||||
- dupl
|
||||
- funlen
|
||||
|
3
Makefile
3
Makefile
@ -22,6 +22,9 @@ lint:
|
||||
.PHONY: gen
|
||||
gen:
|
||||
@go generate ./...
|
||||
@# Run betteralign on generated code
|
||||
@# https://github.com/dkorunic/betteralign
|
||||
@betteralign -apply ./libsq/ast/internal/slq &> /dev/null | true
|
||||
|
||||
.PHONY: fmt
|
||||
fmt:
|
||||
|
@ -34,7 +34,7 @@ var (
|
||||
)
|
||||
|
||||
// Info encapsulates Version, Commit and Timestamp.
|
||||
type Info struct {
|
||||
type Info struct { //nolint:govet // field alignment
|
||||
Version string `json:"version" yaml:"version"`
|
||||
Commit string `json:"commit,omitempty" yaml:"commit,omitempty"`
|
||||
Timestamp time.Time `json:"timestamp,omitempty" yaml:"timestamp,omitempty"`
|
||||
|
@ -31,9 +31,9 @@ func TestSmoke(t *testing.T) {
|
||||
// Execute a bunch of smoke test cases.
|
||||
|
||||
testCases := []struct {
|
||||
a []string
|
||||
// errBecause, if non-empty, indicates an error is expected.
|
||||
errBecause string
|
||||
a []string
|
||||
}{
|
||||
{a: []string{"ls"}},
|
||||
{a: []string{"ls", "-v"}},
|
||||
|
@ -230,7 +230,7 @@ func pingSource(ctx context.Context, dp driver.Provider, src *source.Source, tim
|
||||
}
|
||||
|
||||
type pingResult struct {
|
||||
err error
|
||||
src *source.Source
|
||||
duration time.Duration
|
||||
err error
|
||||
}
|
||||
|
@ -352,8 +352,8 @@ func parseTableHandleArgs(dp driver.Provider, coll *source.Collection, args []st
|
||||
// tblHandle represents a @HANDLE.TABLE, with the handle's associated
|
||||
// src and driver.
|
||||
type tblHandle struct {
|
||||
drvr driver.Driver
|
||||
src *source.Source
|
||||
handle string
|
||||
tbl string
|
||||
src *source.Source
|
||||
drvr driver.Driver
|
||||
}
|
||||
|
@ -677,6 +677,8 @@ func locCompParseLoc(loc string) (*parsedLoc, error) {
|
||||
// It can represent partial or fully constructed locations. The stage
|
||||
// of construction is noted in parsedLoc.stageDone.
|
||||
type parsedLoc struct {
|
||||
// du holds the parsed db url. This may be nil.
|
||||
du *dburl.URL
|
||||
// loc is the original unparsed location value.
|
||||
loc string
|
||||
|
||||
@ -700,14 +702,11 @@ type parsedLoc struct {
|
||||
// hostname is the hostname, if applicable.
|
||||
hostname string
|
||||
|
||||
// port is the port number, or 0 if not applicable.
|
||||
port int
|
||||
|
||||
// name is the database name.
|
||||
name string
|
||||
|
||||
// du holds the parsed db url. This may be nil.
|
||||
du *dburl.URL
|
||||
// port is the port number, or 0 if not applicable.
|
||||
port int
|
||||
}
|
||||
|
||||
// plocStage is an enum indicating what stage of construction
|
||||
@ -785,8 +784,8 @@ func locCompListFiles(ctx context.Context, toComplete string) []string {
|
||||
// elements of a location.
|
||||
type locHistory struct {
|
||||
coll *source.Collection
|
||||
typ drivertype.Type
|
||||
log *slog.Logger
|
||||
typ drivertype.Type
|
||||
}
|
||||
|
||||
func (h *locHistory) usernames() []string {
|
||||
|
@ -32,25 +32,24 @@ var _ config.Store = (*Store)(nil)
|
||||
// Store provides persistence of config via YAML file.
|
||||
// It implements config.Store.
|
||||
type Store struct {
|
||||
// Path is the location of the config file
|
||||
Path string
|
||||
|
||||
// PathOrigin is one of "flag", "env", or "default".
|
||||
PathOrigin string
|
||||
|
||||
// If HookLoad is non-nil, it is invoked by Load
|
||||
// on Path's bytes before the YAML is unmarshalled.
|
||||
// This allows expansion of variables etc.
|
||||
HookLoad func(data []byte) ([]byte, error)
|
||||
|
||||
// ExtPaths holds locations of potential ext config, both dirs and files (with suffix ".sq.yml")
|
||||
ExtPaths []string
|
||||
|
||||
// UpgradeRegistry holds upgrade funcs for upgrading the config file.
|
||||
UpgradeRegistry UpgradeRegistry
|
||||
|
||||
// OptionsRegistry holds options.
|
||||
OptionsRegistry *options.Registry
|
||||
// Path is the location of the config file
|
||||
Path string
|
||||
|
||||
// PathOrigin is one of "flag", "env", or "default".
|
||||
PathOrigin string
|
||||
|
||||
// ExtPaths holds locations of potential ext config, both dirs and files (with suffix ".sq.yml")
|
||||
ExtPaths []string
|
||||
}
|
||||
|
||||
// Lockfile implements Store.Lockfile.
|
||||
|
@ -24,13 +24,12 @@ import (
|
||||
|
||||
// Config contains parameters to control diff behavior.
|
||||
type Config struct {
|
||||
// Lines specifies the number of lines of context surrounding a diff.
|
||||
Lines int
|
||||
|
||||
// RecordWriterFn is a factory function that returns
|
||||
// an output.RecordWriter used to generate diff text
|
||||
// when comparing table data.
|
||||
RecordWriterFn output.NewRecordWriterFunc
|
||||
// Lines specifies the number of lines of context surrounding a diff.
|
||||
Lines int
|
||||
}
|
||||
|
||||
// Elements determines what source elements to compare.
|
||||
@ -53,9 +52,9 @@ type Elements struct {
|
||||
|
||||
// sourceData encapsulates data about a source.
|
||||
type sourceData struct {
|
||||
handle string
|
||||
src *source.Source
|
||||
srcMeta *metadata.Source
|
||||
handle string
|
||||
}
|
||||
|
||||
func (sd *sourceData) clone() *sourceData { //nolint:unused // REVISIT: no longer needed?
|
||||
@ -72,10 +71,10 @@ func (sd *sourceData) clone() *sourceData { //nolint:unused // REVISIT: no longe
|
||||
|
||||
// tableData encapsulates data about a table.
|
||||
type tableData struct {
|
||||
tblName string
|
||||
tblMeta *metadata.Table
|
||||
src *source.Source
|
||||
srcMeta *metadata.Source
|
||||
tblName string
|
||||
}
|
||||
|
||||
func (td *tableData) clone() *tableData { //nolint:unused // REVISIT: no longer needed?
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package diff computes differences between text files or strings.
|
||||
// Package udiff computes differences between text files or strings.
|
||||
package udiff
|
||||
|
||||
import (
|
||||
@ -13,8 +13,9 @@ import (
|
||||
|
||||
// An Edit describes the replacement of a portion of a text file.
|
||||
type Edit struct {
|
||||
Start, End int // byte offsets of the region to replace
|
||||
New string // the replacement
|
||||
Start int
|
||||
End int
|
||||
}
|
||||
|
||||
func (e Edit) String() string {
|
||||
|
@ -47,8 +47,8 @@ func ComputeEdits(before, after string) []diff.Edit {
|
||||
}
|
||||
|
||||
type operation struct {
|
||||
Kind diff.OpKind
|
||||
Content []string // content from b
|
||||
Kind diff.OpKind
|
||||
I1, I2 int // indices of the line in a
|
||||
J1 int // indices of the line in b, J2 implied by len(Content)
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ func diffASCII(before, after []byte) []Edit {
|
||||
// Convert from LCS diffs.
|
||||
res := make([]Edit, len(diffs))
|
||||
for i, d := range diffs {
|
||||
res[i] = Edit{d.Start, d.End, string(after[d.ReplStart:d.ReplEnd])}
|
||||
res[i] = Edit{Start: d.Start, End: d.End, New: string(after[d.ReplStart:d.ReplEnd])}
|
||||
}
|
||||
return res
|
||||
}
|
||||
@ -62,30 +62,30 @@ func diffRunes(before, after []rune) []Edit {
|
||||
utf8Len += runesLen(before[lastEnd:d.Start]) // text between edits
|
||||
start := utf8Len
|
||||
utf8Len += runesLen(before[d.Start:d.End]) // text deleted by this edit
|
||||
res[i] = Edit{start, utf8Len, string(after[d.ReplStart:d.ReplEnd])}
|
||||
res[i] = Edit{Start: start, End: utf8Len, New: string(after[d.ReplStart:d.ReplEnd])}
|
||||
lastEnd = d.End
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// runes is like []rune(string(bytes)) without the duplicate allocation.
|
||||
func runes(bytes []byte) []rune {
|
||||
n := utf8.RuneCount(bytes)
|
||||
runes := make([]rune, n)
|
||||
func runes(b []byte) []rune {
|
||||
n := utf8.RuneCount(b)
|
||||
rs := make([]rune, n)
|
||||
for i := 0; i < n; i++ {
|
||||
r, sz := utf8.DecodeRune(bytes)
|
||||
bytes = bytes[sz:]
|
||||
runes[i] = r
|
||||
r, sz := utf8.DecodeRune(b)
|
||||
b = b[sz:]
|
||||
rs[i] = r
|
||||
}
|
||||
return runes
|
||||
return rs
|
||||
}
|
||||
|
||||
// runesLen returns the length in bytes of the UTF-8 encoding of runes.
|
||||
func runesLen(runes []rune) (len int) {
|
||||
func runesLen(runes []rune) (length int) {
|
||||
for _, r := range runes {
|
||||
len += utf8.RuneLen(r)
|
||||
length += utf8.RuneLen(r)
|
||||
}
|
||||
return len
|
||||
return length
|
||||
}
|
||||
|
||||
// stringIsASCII reports whether s contains only ASCII.
|
||||
|
@ -15,12 +15,12 @@ import (
|
||||
// If the strings are equal, it returns the empty string.
|
||||
func Unified(oldLabel, newLabel, old, new string, numLines int) string {
|
||||
edits := Strings(old, new)
|
||||
unified, err := ToUnified(oldLabel, newLabel, old, edits, numLines)
|
||||
u, err := ToUnified(oldLabel, newLabel, old, edits, numLines)
|
||||
if err != nil {
|
||||
// Can't happen: edits are consistent.
|
||||
log.Fatalf("internal error in diff.Unified: %v", err)
|
||||
}
|
||||
return unified
|
||||
return u
|
||||
}
|
||||
|
||||
// ToUnified applies the edits to content and returns a unified diff.
|
||||
@ -46,22 +46,22 @@ type unified struct {
|
||||
|
||||
// Hunk represents a contiguous set of line edits to apply.
|
||||
type hunk struct {
|
||||
// The set of line based edits to apply.
|
||||
Lines []line
|
||||
// The line in the original source where the hunk starts.
|
||||
FromLine int
|
||||
// The line in the original source where the hunk finishes.
|
||||
ToLine int
|
||||
// The set of line based edits to apply.
|
||||
Lines []line
|
||||
}
|
||||
|
||||
// Line represents a single line operation to apply as part of a Hunk.
|
||||
type line struct {
|
||||
// Kind is the type of line this represents, deletion, insertion or copy.
|
||||
Kind OpKind
|
||||
// Content is the content of this line.
|
||||
// For deletion it is the line being removed, for all others it is the line
|
||||
// to put in the output.
|
||||
Content string
|
||||
// Kind is the type of line this represents, deletion, insertion or copy.
|
||||
Kind OpKind
|
||||
}
|
||||
|
||||
// OpKind is used to denote the type of operation a line represents.
|
||||
|
@ -21,11 +21,11 @@ import (
|
||||
//nolint:unused
|
||||
type recordDiff struct {
|
||||
td1, td2 *tableData
|
||||
header string
|
||||
diff string
|
||||
recMeta1, recMeta2 record.Meta
|
||||
rec1, rec2 record.Record
|
||||
row int
|
||||
header string
|
||||
diff string
|
||||
}
|
||||
|
||||
// findRecordDiff compares the row data in td1 and td2, returning
|
||||
|
@ -69,6 +69,7 @@ func renderTableMeta2YAML(showRowCounts bool, tm *metadata.Table) (string, error
|
||||
|
||||
// tableMeta hosts values of metadata.Table in the
|
||||
// structure that diff wants.
|
||||
//nolint:govet // field alignment
|
||||
type tableMeta struct {
|
||||
Name string `json:"name" yaml:"name"`
|
||||
FQName string `json:"name_fq,omitempty" yaml:"name_fq,omitempty"`
|
||||
|
@ -31,10 +31,11 @@ type RecordWriterAdapter struct {
|
||||
wg *sync.WaitGroup
|
||||
recCh chan record.Record
|
||||
errCh chan error
|
||||
errs []error
|
||||
written *atomic.Int64
|
||||
cancelFn context.CancelFunc
|
||||
|
||||
errs []error
|
||||
|
||||
// FlushAfterN indicates that the writer's Flush method
|
||||
// should be invoked after N invocations of WriteRecords.
|
||||
// A value of 0 will flush every time a record is written.
|
||||
|
@ -29,11 +29,11 @@ const (
|
||||
|
||||
// RecordWriter implements output.RecordWriter.
|
||||
type RecordWriter struct {
|
||||
mu sync.Mutex
|
||||
recMeta record.Meta
|
||||
cw *csv.Writer
|
||||
needsHeader bool
|
||||
pr *output.Printing
|
||||
recMeta record.Meta
|
||||
mu sync.Mutex
|
||||
needsHeader bool
|
||||
}
|
||||
|
||||
var (
|
||||
|
@ -18,9 +18,9 @@ func NewOpt(key, flag string, short rune, defaultVal Format,
|
||||
|
||||
// Opt is an options.Opt for format.Format.
|
||||
type Opt struct {
|
||||
options.BaseOpt
|
||||
defaultVal Format
|
||||
validFn func(Format) error
|
||||
defaultVal Format
|
||||
options.BaseOpt
|
||||
}
|
||||
|
||||
// Process implements options.Processor. It converts matching
|
||||
|
@ -23,11 +23,11 @@ import (
|
||||
|
||||
// RecordWriter implements output.RecordWriter.
|
||||
type recordWriter struct {
|
||||
mu sync.Mutex
|
||||
recMeta record.Meta
|
||||
pr *output.Printing
|
||||
out io.Writer
|
||||
pr *output.Printing
|
||||
buf *bytes.Buffer
|
||||
recMeta record.Meta
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
var _ output.NewRecordWriterFunc = NewRecordWriter
|
||||
|
@ -29,7 +29,7 @@ func (w *configWriter) CacheLocation(loc string) error {
|
||||
|
||||
// CacheStat implements output.ConfigWriter.
|
||||
func (w *configWriter) CacheStat(loc string, enabled bool, size int64) error {
|
||||
type cacheInfo struct {
|
||||
type cacheInfo struct { //nolint:govet // field alignment
|
||||
Location string `json:"location"`
|
||||
Enabled bool `json:"enabled"`
|
||||
Size *int64 `json:"size,omitempty"`
|
||||
|
@ -20,10 +20,10 @@ import (
|
||||
// without colorization (that is, in monochrome).
|
||||
type monoEncoder struct {
|
||||
formatDatetime func(time.Time) string
|
||||
formatDatetimeAsNumber bool
|
||||
formatDate func(time.Time) string
|
||||
formatDateAsNumber bool
|
||||
formatTime func(time.Time) string
|
||||
formatDatetimeAsNumber bool
|
||||
formatDateAsNumber bool
|
||||
formatTimeAsNumber bool
|
||||
}
|
||||
|
||||
@ -114,12 +114,12 @@ func (e monoEncoder) encodeAny(b []byte, v any) ([]byte, error) {
|
||||
// colorEncoder provides methods for encoding JSON values
|
||||
// with color.
|
||||
type colorEncoder struct {
|
||||
clrs internal.Colors
|
||||
formatDatetime func(time.Time) string
|
||||
formatDatetimeAsNumber bool
|
||||
formatDate func(time.Time) string
|
||||
formatDateAsNumber bool
|
||||
formatTime func(time.Time) string
|
||||
clrs internal.Colors
|
||||
formatDatetimeAsNumber bool
|
||||
formatDateAsNumber bool
|
||||
formatTimeAsNumber bool
|
||||
}
|
||||
|
||||
|
@ -22,9 +22,9 @@ type codec struct {
|
||||
}
|
||||
|
||||
type encoder struct {
|
||||
flags AppendFlags
|
||||
clrs internal.Colors
|
||||
indenter *Indenter
|
||||
clrs internal.Colors
|
||||
flags AppendFlags
|
||||
}
|
||||
type decoder struct{ flags ParseFlags }
|
||||
|
||||
@ -502,12 +502,12 @@ func constructEmbeddedStructPointerDecodeFunc(t reflect.Type, unexported bool, o
|
||||
|
||||
func appendStructFields(fields []structField, t reflect.Type, offset uintptr, seen map[reflect.Type]*structType, canAddr bool) []structField {
|
||||
type embeddedField struct {
|
||||
subtype *structType
|
||||
subfield *structField
|
||||
index int
|
||||
offset uintptr
|
||||
pointer bool
|
||||
unexported bool
|
||||
subtype *structType
|
||||
subfield *structField
|
||||
}
|
||||
|
||||
names := make(map[string]struct{})
|
||||
@ -915,25 +915,25 @@ type slice struct {
|
||||
}
|
||||
|
||||
type structType struct {
|
||||
fields []structField
|
||||
typ reflect.Type
|
||||
fieldsIndex map[string]*structField
|
||||
ficaseIndex map[string]*structField
|
||||
typ reflect.Type
|
||||
fields []structField
|
||||
inlined bool
|
||||
}
|
||||
|
||||
type structField struct {
|
||||
codec codec
|
||||
offset uintptr
|
||||
typ reflect.Type
|
||||
empty emptyFunc
|
||||
tag bool
|
||||
omitempty bool
|
||||
zero reflect.Value
|
||||
json string
|
||||
html string
|
||||
name string
|
||||
typ reflect.Type
|
||||
zero reflect.Value
|
||||
offset uintptr
|
||||
index int
|
||||
tag bool
|
||||
omitempty bool
|
||||
}
|
||||
|
||||
func unmarshalTypeError(b []byte, t reflect.Type) error {
|
||||
|
@ -931,10 +931,10 @@ func appendCompactEscapeHTML(dst, src []byte) []byte {
|
||||
// computed indentation. The AppendByte method appends a byte. All
|
||||
// methods are safe to use with a nil receiver.
|
||||
type Indenter struct {
|
||||
disabled bool
|
||||
Prefix string
|
||||
Indent string
|
||||
depth int
|
||||
disabled bool
|
||||
}
|
||||
|
||||
// NewIndenter returns a new Indenter instance. If prefix and
|
||||
|
@ -242,10 +242,10 @@ func Valid(data []byte) bool {
|
||||
// Decoder is documented at https://golang.org/pkg/encoding/json/#Decoder
|
||||
type Decoder struct {
|
||||
reader io.Reader
|
||||
err error
|
||||
buffer []byte
|
||||
remain []byte
|
||||
inputOffset int64
|
||||
err error
|
||||
flags ParseFlags
|
||||
}
|
||||
|
||||
@ -373,11 +373,11 @@ func (dec *Decoder) InputOffset() int64 {
|
||||
// Encoder is documented at https://golang.org/pkg/encoding/json/#Encoder
|
||||
type Encoder struct {
|
||||
writer io.Writer
|
||||
buffer *bytes.Buffer
|
||||
err error
|
||||
flags AppendFlags
|
||||
clrs internal.Colors
|
||||
buffer *bytes.Buffer
|
||||
indenter *Indenter
|
||||
clrs internal.Colors
|
||||
flags AppendFlags
|
||||
}
|
||||
|
||||
// NewEncoder is documented at https://golang.org/pkg/encoding/json/#NewEncoder
|
||||
|
@ -39,10 +39,8 @@ package json
|
||||
// }
|
||||
// }
|
||||
type Tokenizer struct {
|
||||
// When the tokenizer is positioned on a json delimiter this field is not
|
||||
// zero. In this case the possible values are '{', '}', '[', ']', ':', and
|
||||
// ','.
|
||||
Delim Delim
|
||||
// When the tokenizer has encountered invalid content this field is not nil.
|
||||
Err error
|
||||
|
||||
// This field contains the raw json token that the tokenizer is pointing at.
|
||||
// When Delim is not zero, this field is a single-element byte slice
|
||||
@ -50,23 +48,6 @@ type Tokenizer struct {
|
||||
// null, true, false, numbers, or quoted strings.
|
||||
Value RawValue
|
||||
|
||||
// When the tokenizer has encountered invalid content this field is not nil.
|
||||
Err error
|
||||
|
||||
// When the value is in an array or an object, this field contains the depth
|
||||
// at which it was found.
|
||||
Depth int
|
||||
|
||||
// When the value is in an array or an object, this field contains the
|
||||
// position at which it was found.
|
||||
Index int
|
||||
|
||||
// This field is true when the value is the key of an object.
|
||||
IsKey bool
|
||||
|
||||
// Tells whether the next value read from the tokenizer is a key.
|
||||
isKey bool
|
||||
|
||||
// json input for the tokenizer, pointing at data right after the last token
|
||||
// that was parsed.
|
||||
json []byte
|
||||
@ -75,6 +56,25 @@ type Tokenizer struct {
|
||||
// buffer is used as a AppendPre-allocated space to
|
||||
stack []state
|
||||
buffer [8]state
|
||||
|
||||
// When the value is in an array or an object, this field contains the depth
|
||||
// at which it was found.
|
||||
Depth int
|
||||
|
||||
// When the value is in an array or an object, this field contains the
|
||||
// position at which it was found.
|
||||
Index int
|
||||
|
||||
// When the tokenizer is positioned on a json delimiter this field is not
|
||||
// zero. In this case the possible values are '{', '}', '[', ']', ':', and
|
||||
// ','.
|
||||
Delim Delim
|
||||
|
||||
// This field is true when the value is the key of an object.
|
||||
IsKey bool
|
||||
|
||||
// Tells whether the next value read from the tokenizer is a key.
|
||||
isKey bool
|
||||
}
|
||||
|
||||
type state struct {
|
||||
|
@ -66,7 +66,7 @@ func (w *mdWriter) Catalogs(currentCatalog string, catalogs []string) error {
|
||||
if len(catalogs) == 0 {
|
||||
return nil
|
||||
}
|
||||
type cat struct {
|
||||
type cat struct { //nolint:govet // field alignment
|
||||
Name string `json:"catalog"`
|
||||
Active *bool `json:"active,omitempty"`
|
||||
}
|
||||
@ -89,7 +89,7 @@ func (w *mdWriter) Schemata(currentSchema string, schemas []*metadata.Schema) er
|
||||
|
||||
// We wrap each schema in a struct that has an "active" field,
|
||||
// because we need to show the current schema in the output.
|
||||
type wrapper struct {
|
||||
type wrapper struct { //nolint:govet // field alignment
|
||||
metadata.Schema `json:",omitempty,inline"`
|
||||
Active *bool `json:"active,omitempty"`
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ func (p pingWriter) Open(_ []*source.Source) error {
|
||||
|
||||
// Result implements output.PingWriter.
|
||||
func (p pingWriter) Result(src *source.Source, d time.Duration, err error) error {
|
||||
r := struct {
|
||||
r := struct { //nolint:govet // field alignment
|
||||
*source.Source
|
||||
Pong bool `json:"pong"`
|
||||
Duration time.Duration `json:"duration"`
|
||||
|
@ -42,22 +42,22 @@ func NewStdRecordWriter(out io.Writer, pr *output.Printing) output.RecordWriter
|
||||
|
||||
// stdWriter outputs records in standard JSON format.
|
||||
type stdWriter struct {
|
||||
mu sync.Mutex
|
||||
err error
|
||||
out io.Writer
|
||||
pr *output.Printing
|
||||
|
||||
// b is used as a buffer by writeRecord
|
||||
b []byte
|
||||
|
||||
// outBuf is used to hold output prior to flushing.
|
||||
outBuf *bytes.Buffer
|
||||
|
||||
recMeta record.Meta
|
||||
recsWritten bool
|
||||
|
||||
tpl *stdTemplate
|
||||
|
||||
// b is used as a buffer by writeRecord
|
||||
b []byte
|
||||
|
||||
recMeta record.Meta
|
||||
encodeFns []func(b []byte, v any) ([]byte, error)
|
||||
mu sync.Mutex
|
||||
recsWritten bool
|
||||
}
|
||||
|
||||
// Open implements output.RecordWriter.
|
||||
@ -294,11 +294,9 @@ func NewArrayRecordWriter(out io.Writer, pr *output.Printing) output.RecordWrite
|
||||
// surround the output of each encode func. Therefore there
|
||||
// are len(rec)+1 tpl elements.
|
||||
type lineRecordWriter struct {
|
||||
mu sync.Mutex
|
||||
err error
|
||||
out io.Writer
|
||||
pr *output.Printing
|
||||
recMeta record.Meta
|
||||
|
||||
// outBuf holds the output of the writer prior to flushing.
|
||||
outBuf *bytes.Buffer
|
||||
@ -307,11 +305,14 @@ type lineRecordWriter struct {
|
||||
// generating output.
|
||||
newTplFn func(record.Meta, *output.Printing) ([][]byte, error)
|
||||
|
||||
recMeta record.Meta
|
||||
|
||||
// tpl is a slice of []byte, where len(tpl) == len(recMeta) + 1.
|
||||
tpl [][]byte
|
||||
|
||||
// encodeFns holds an encoder func for each element of the record.
|
||||
encodeFns []func(b []byte, v any) ([]byte, error)
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
// Open implements output.RecordWriter.
|
||||
|
@ -23,11 +23,11 @@ import (
|
||||
|
||||
// RecordWriter implements output.RecordWriter.
|
||||
type RecordWriter struct {
|
||||
mu sync.Mutex
|
||||
recMeta record.Meta
|
||||
pr *output.Printing
|
||||
out io.Writer
|
||||
pr *output.Printing
|
||||
buf *bytes.Buffer
|
||||
recMeta record.Meta
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
var _ output.NewRecordWriterFunc = NewRecordWriter
|
||||
|
@ -13,7 +13,7 @@ import (
|
||||
|
||||
// VerboseOpt is a verbose realization of an options.Opt value.
|
||||
// This is used primarily to print metadata about the opt.
|
||||
type VerboseOpt struct {
|
||||
type VerboseOpt struct { //nolint:govet // field alignment
|
||||
Key string `json:"key"`
|
||||
Usage string `json:"usage"`
|
||||
Type string `json:"type"`
|
||||
|
@ -12,75 +12,18 @@ import (
|
||||
|
||||
// Printing describes color and pretty-printing options.
|
||||
type Printing struct {
|
||||
// monochrome is controlled by EnableColor.
|
||||
monochrome bool
|
||||
|
||||
// FlushThreshold is the size in bytes after which an output writer
|
||||
// should flush any internal buffer.
|
||||
FlushThreshold int
|
||||
|
||||
// ShowHeader indicates that a header (e.g. a header row) should
|
||||
// be printed where applicable.
|
||||
ShowHeader bool
|
||||
|
||||
// Verbose indicates that verbose output should be printed where
|
||||
// applicable.
|
||||
Verbose bool
|
||||
|
||||
// Compact indicates that output should not be pretty-printed.
|
||||
// Typically this means indentation, new lines, etc., but
|
||||
// varies by output format.
|
||||
Compact bool
|
||||
|
||||
// Indent is the indent string to use when pretty-printing,
|
||||
// typically two spaces.
|
||||
Indent string
|
||||
|
||||
// Redact indicates that sensitive fields (such as passwords)
|
||||
// should be redacted (hidden/masked).
|
||||
//
|
||||
// TODO: Redact is not being honored by the writers.
|
||||
Redact bool
|
||||
|
||||
// FormatDatetime formats a timestamp e.g. 2020-11-12T13:14:15Z.
|
||||
// Defaults to timez.DefaultDatetime.
|
||||
FormatDatetime func(time time.Time) string
|
||||
|
||||
// FormatDatetimeAsNumber indicates that datetime values should be
|
||||
// rendered as naked numbers (instead of as a string) if possible.
|
||||
// See cli.OptDatetimeFormatAsNumber.
|
||||
FormatDatetimeAsNumber bool
|
||||
|
||||
// FormatTime formats a time of day, e.g. 13:14:15.
|
||||
// Defaults to timez.DefaultTime.
|
||||
FormatTime func(time time.Time) string
|
||||
|
||||
// FormatTimeAsNumber indicates that time values should be
|
||||
// rendered as naked numbers (instead of as a string) if possible.
|
||||
// See cli.OptTimeFormatAsNumber.
|
||||
FormatTimeAsNumber bool
|
||||
|
||||
// FormatDate formats a date, e.g. 2020-11-12.
|
||||
// Defaults to timez.DefaultDate.
|
||||
FormatDate func(time time.Time) string
|
||||
|
||||
// FormatDateAsNumber indicates that date values should be
|
||||
// rendered as naked numbers (instead of as a string) if possible.
|
||||
// See cli.OptDateFormatAsNumber.
|
||||
FormatDateAsNumber bool
|
||||
|
||||
// ExcelDatetimeFormat is the format string for datetime values.
|
||||
// See excelw.OptDatetimeFormat.
|
||||
ExcelDatetimeFormat string
|
||||
|
||||
// ExcelDateFormat is the format string for date values.
|
||||
// See excelw.OptDateFormat.
|
||||
ExcelDateFormat string
|
||||
|
||||
// ExcelTimeFormat is the format string for time values.
|
||||
// See excelw.OptTimeFormat.
|
||||
ExcelTimeFormat string
|
||||
|
||||
// Active is the color for an active handle (or group, etc).
|
||||
Active *color.Color
|
||||
|
||||
@ -170,6 +113,63 @@ type Printing struct {
|
||||
|
||||
// Warning is the color for warning elements.
|
||||
Warning *color.Color
|
||||
|
||||
// Indent is the indent string to use when pretty-printing,
|
||||
// typically two spaces.
|
||||
Indent string
|
||||
|
||||
// ExcelDatetimeFormat is the format string for datetime values.
|
||||
// See excelw.OptDatetimeFormat.
|
||||
ExcelDatetimeFormat string
|
||||
|
||||
// ExcelDateFormat is the format string for date values.
|
||||
// See excelw.OptDateFormat.
|
||||
ExcelDateFormat string
|
||||
|
||||
// ExcelTimeFormat is the format string for time values.
|
||||
// See excelw.OptTimeFormat.
|
||||
ExcelTimeFormat string
|
||||
|
||||
// FlushThreshold is the size in bytes after which an output writer
|
||||
// should flush any internal buffer.
|
||||
FlushThreshold int
|
||||
|
||||
// monochrome is controlled by EnableColor.
|
||||
monochrome bool
|
||||
|
||||
// ShowHeader indicates that a header (e.g. a header row) should
|
||||
// be printed where applicable.
|
||||
ShowHeader bool
|
||||
|
||||
// Verbose indicates that verbose output should be printed where
|
||||
// applicable.
|
||||
Verbose bool
|
||||
|
||||
// Compact indicates that output should not be pretty-printed.
|
||||
// Typically this means indentation, new lines, etc., but
|
||||
// varies by output format.
|
||||
Compact bool
|
||||
|
||||
// Redact indicates that sensitive fields (such as passwords)
|
||||
// should be redacted (hidden/masked).
|
||||
//
|
||||
// TODO: Redact is not being honored by the writers.
|
||||
Redact bool
|
||||
|
||||
// FormatDatetimeAsNumber indicates that datetime values should be
|
||||
// rendered as naked numbers (instead of as a string) if possible.
|
||||
// See cli.OptDatetimeFormatAsNumber.
|
||||
FormatDatetimeAsNumber bool
|
||||
|
||||
// FormatTimeAsNumber indicates that time values should be
|
||||
// rendered as naked numbers (instead of as a string) if possible.
|
||||
// See cli.OptTimeFormatAsNumber.
|
||||
FormatTimeAsNumber bool
|
||||
|
||||
// FormatDateAsNumber indicates that date values should be
|
||||
// rendered as naked numbers (instead of as a string) if possible.
|
||||
// See cli.OptDateFormatAsNumber.
|
||||
FormatDateAsNumber bool
|
||||
}
|
||||
|
||||
// NewPrinting returns a Printing instance. Color and pretty-print
|
||||
|
@ -22,10 +22,10 @@ import (
|
||||
// written to the backing writer without any separator, or
|
||||
// encoding, etc.
|
||||
type recordWriter struct {
|
||||
mu sync.Mutex
|
||||
out io.Writer
|
||||
pr *output.Printing
|
||||
recMeta record.Meta
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
var _ output.NewRecordWriterFunc = NewRecordWriter
|
||||
|
@ -60,31 +60,31 @@ type Border struct {
|
||||
// Table struct
|
||||
type Table struct {
|
||||
out io.Writer
|
||||
rows [][]string
|
||||
lines [][][]string
|
||||
cs map[int]int
|
||||
rs map[int]int
|
||||
headers []string
|
||||
footers []string
|
||||
autoFmt bool
|
||||
autoWrap bool
|
||||
mW int
|
||||
colTrans map[int]textTransFunc
|
||||
cellTrans map[string]textTransFunc
|
||||
headerTrans textTransFunc
|
||||
pCenter string
|
||||
pRow string
|
||||
pColumn string
|
||||
rows [][]string
|
||||
lines [][][]string
|
||||
headers []string
|
||||
footers []string
|
||||
mW int
|
||||
tColumn int
|
||||
tRow int
|
||||
hAlign int
|
||||
fAlign int
|
||||
align int
|
||||
colSize int
|
||||
borders Border
|
||||
autoFmt bool
|
||||
autoWrap bool
|
||||
rowLine bool
|
||||
hdrLine bool
|
||||
hdrDisable bool
|
||||
borders Border
|
||||
colSize int
|
||||
colTrans map[int]textTransFunc
|
||||
cellTrans map[string]textTransFunc
|
||||
headerTrans textTransFunc
|
||||
}
|
||||
|
||||
// NewTable returns a new table that writes to writer.
|
||||
|
@ -12,11 +12,11 @@ import (
|
||||
)
|
||||
|
||||
type recordWriter struct {
|
||||
mu sync.Mutex
|
||||
tbl *table
|
||||
bar *progress.Bar
|
||||
recMeta record.Meta
|
||||
rowCount int
|
||||
bar *progress.Bar
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
// NewRecordWriter returns a RecordWriter for text table output.
|
||||
|
@ -31,11 +31,11 @@ import (
|
||||
|
||||
// table encapsulates our table implementation.
|
||||
type table struct {
|
||||
pr *output.Printing
|
||||
out io.Writer
|
||||
header bool
|
||||
pr *output.Printing
|
||||
|
||||
tblImpl *internal.Table
|
||||
header bool
|
||||
}
|
||||
|
||||
// renderResultCell renders a record value to a string.
|
||||
|
@ -25,17 +25,9 @@ import (
|
||||
)
|
||||
|
||||
type recordWriter struct {
|
||||
recMeta record.Meta
|
||||
mu sync.Mutex
|
||||
pr *output.Printing
|
||||
out io.Writer
|
||||
header bool
|
||||
pr *output.Printing
|
||||
xfile *excelize.File
|
||||
nextRow int
|
||||
timeStyle int
|
||||
dateStyle int
|
||||
datetimeStyle int
|
||||
headerStyle int
|
||||
|
||||
// mDecimalPlacesStyles maps decimal places to
|
||||
// the excelize style ID that should be used for that
|
||||
@ -47,6 +39,15 @@ type recordWriter struct {
|
||||
// The map should not be directly accessed; instead use
|
||||
// getDecimalStyle.
|
||||
mDecimalPlacesStyles map[int]int
|
||||
recMeta record.Meta
|
||||
nextRow int
|
||||
timeStyle int
|
||||
dateStyle int
|
||||
datetimeStyle int
|
||||
headerStyle int
|
||||
|
||||
mu sync.Mutex
|
||||
header bool
|
||||
}
|
||||
|
||||
var _ output.NewRecordWriterFunc = NewRecordWriter
|
||||
|
@ -26,23 +26,24 @@ type recordWriter struct {
|
||||
out io.Writer
|
||||
pr *output.Printing
|
||||
|
||||
recMeta record.Meta
|
||||
|
||||
// outBuf holds output prior to flushing.
|
||||
outBuf *bytes.Buffer
|
||||
|
||||
// recWritten indicates that at least one record has been written
|
||||
// to outBuf.
|
||||
recsWritten bool
|
||||
|
||||
elemColor *color.Color
|
||||
|
||||
tplRecStart string
|
||||
tplRecEnd string
|
||||
|
||||
recMeta record.Meta
|
||||
|
||||
tplFieldStart []string
|
||||
tplFieldEnd []string
|
||||
|
||||
fieldPrintFns []func(w io.Writer, a ...any)
|
||||
|
||||
// recWritten indicates that at least one record has been written
|
||||
// to outBuf.
|
||||
recsWritten bool
|
||||
}
|
||||
|
||||
const (
|
||||
|
@ -47,7 +47,7 @@ func (w *configWriter) CacheLocation(loc string) error {
|
||||
|
||||
// CacheStat implements output.ConfigWriter.
|
||||
func (w *configWriter) CacheStat(loc string, enabled bool, size int64) error {
|
||||
type cacheInfo struct {
|
||||
type cacheInfo struct { //nolint:govet // field alignment
|
||||
Location string `yaml:"location"`
|
||||
Enabled bool `yaml:"enabled"`
|
||||
Size *int64 `yaml:"size,omitempty"`
|
||||
|
@ -72,7 +72,7 @@ func (w *mdWriter) Catalogs(currentCatalog string, catalogs []string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type cat struct {
|
||||
type cat struct { //nolint:govet // field alignment
|
||||
Name string `yaml:"catalog"`
|
||||
Active *bool `yaml:"active,omitempty"`
|
||||
}
|
||||
@ -95,7 +95,7 @@ func (w *mdWriter) Schemata(currentSchema string, schemas []*metadata.Schema) er
|
||||
|
||||
// We wrap each schema in a struct that has an "active" field,
|
||||
// because we need to show the current schema in the output.
|
||||
type wrapper struct {
|
||||
type wrapper struct { //nolint:govet // field alignment
|
||||
metadata.Schema `yaml:",omitempty,inline"`
|
||||
Active *bool `yaml:"active,omitempty"`
|
||||
}
|
||||
|
@ -29,16 +29,16 @@ func NewRecordWriter(out io.Writer, pr *output.Printing) output.RecordWriter {
|
||||
}
|
||||
|
||||
type recordWriter struct {
|
||||
mu sync.Mutex
|
||||
out io.Writer
|
||||
pr *output.Printing
|
||||
recMeta record.Meta
|
||||
fieldNames []string
|
||||
buf *bytes.Buffer
|
||||
enc *goccy.Encoder
|
||||
null string
|
||||
recMeta record.Meta
|
||||
fieldNames []string
|
||||
clrs []*color.Color
|
||||
keys []string
|
||||
null string
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
// Open implements output.RecordWriter.
|
||||
|
@ -40,31 +40,26 @@ func FromContext(ctx context.Context) *Run {
|
||||
// to all cobra exec funcs. The Close method should be invoked when
|
||||
// the Run is no longer needed.
|
||||
type Run struct {
|
||||
// Stdin typically is os.Stdin, but can be changed for testing.
|
||||
Stdin *os.File
|
||||
|
||||
// Out is the output destination, typically os.Stdout.
|
||||
Out io.Writer
|
||||
|
||||
// ErrOut is the error output destination, typically os.Stderr.
|
||||
ErrOut io.Writer
|
||||
|
||||
// ConfigStore manages config persistence.
|
||||
ConfigStore config.Store
|
||||
|
||||
// Stdin typically is os.Stdin, but can be changed for testing.
|
||||
Stdin *os.File
|
||||
|
||||
// Cmd is the command instance provided by cobra for
|
||||
// the currently executing command. This field will
|
||||
// be set before the command's runFunc is invoked.
|
||||
Cmd *cobra.Command
|
||||
|
||||
// Args is the arg slice supplied by cobra for
|
||||
// the currently executing command. This field will
|
||||
// be set before the command's runFunc is invoked.
|
||||
Args []string
|
||||
|
||||
// Config is the run's config.
|
||||
Config *config.Config
|
||||
|
||||
// ConfigStore manages config persistence.
|
||||
ConfigStore config.Store
|
||||
|
||||
// OptionsRegistry is a registry of CLI options.Opt instances.
|
||||
OptionsRegistry *options.Registry
|
||||
|
||||
@ -90,6 +85,11 @@ type Run struct {
|
||||
// should be more-or-less the final cleanup action performed by the CLI,
|
||||
// and absolutely must happen after all other cleanup actions.
|
||||
LogCloser func() error
|
||||
|
||||
// Args is the arg slice supplied by cobra for
|
||||
// the currently executing command. This field will
|
||||
// be set before the command's runFunc is invoked.
|
||||
Args []string
|
||||
}
|
||||
|
||||
// Close should be invoked to dispose of any open resources
|
||||
|
@ -40,10 +40,10 @@ func (d *Provider) DriverFor(typ drivertype.Type) (driver.Driver, error) {
|
||||
|
||||
// Driver implements driver.Driver.
|
||||
type driveri struct {
|
||||
log *slog.Logger
|
||||
typ drivertype.Type
|
||||
ingester driver.GripOpenIngester
|
||||
log *slog.Logger
|
||||
files *files.Files
|
||||
typ drivertype.Type
|
||||
}
|
||||
|
||||
// DriverMetadata implements driver.Driver.
|
||||
|
@ -29,9 +29,12 @@ import (
|
||||
// at fromSrc is read via newRdrFn and the resulting records
|
||||
// are written to destGrip.
|
||||
type ingestJob struct {
|
||||
destGrip driver.Grip
|
||||
|
||||
fromSrc *source.Source
|
||||
newRdrFn files.NewReaderFunc
|
||||
destGrip driver.Grip
|
||||
|
||||
stmtCache map[string]*driver.StmtExecer
|
||||
|
||||
// sampleSize is the maximum number of values to
|
||||
// sample to determine the kind of an element.
|
||||
@ -43,8 +46,6 @@ type ingestJob struct {
|
||||
//
|
||||
// TODO: flatten should come from src.Options
|
||||
flatten bool
|
||||
|
||||
stmtCache map[string]*driver.StmtExecer
|
||||
}
|
||||
|
||||
// Close closes the ingestJob. In particular, it closes any cached statements.
|
||||
@ -144,19 +145,19 @@ type objectValueSet map[*entity]map[string]any
|
||||
|
||||
// processor process JSON objects.
|
||||
type processor struct {
|
||||
// if flattened is true, the JSON object will be flattened into a single table.
|
||||
flatten bool
|
||||
|
||||
root *entity
|
||||
importSchema *ingestSchema
|
||||
|
||||
colNamesOrdered []string
|
||||
|
||||
// schemaDirtyEntities tracks entities whose structure have been modified.
|
||||
schemaDirtyEntities map[*entity]struct{}
|
||||
|
||||
unwrittenObjVals []objectValueSet
|
||||
curObjVals objectValueSet
|
||||
|
||||
colNamesOrdered []string
|
||||
|
||||
unwrittenObjVals []objectValueSet
|
||||
// if flattened is true, the JSON object will be flattened into a single table.
|
||||
flatten bool
|
||||
}
|
||||
|
||||
func newProcessor(flatten bool) *processor {
|
||||
@ -409,11 +410,14 @@ func (p *processor) buildInsertionsFlat(schma *ingestSchema) ([]*insertion, erro
|
||||
|
||||
// entity models the structure of a JSON entity, either an object or an array.
|
||||
type entity struct {
|
||||
// isArray is true if the entity is an array, false if an object.
|
||||
isArray bool
|
||||
parent *entity
|
||||
|
||||
// detectors holds a kind detector for each non-entity field
|
||||
// of entity. That is, it holds a detector for each string or number
|
||||
// field etc, but not for an object or array field.
|
||||
detectors map[string]*kind.Detector
|
||||
|
||||
name string
|
||||
parent *entity
|
||||
children []*entity
|
||||
|
||||
// fieldName holds the names of each field. This includes simple
|
||||
@ -421,10 +425,8 @@ type entity struct {
|
||||
// object or array.
|
||||
fieldNames []string
|
||||
|
||||
// detectors holds a kind detector for each non-entity field
|
||||
// of entity. That is, it holds a detector for each string or number
|
||||
// field etc, but not for an object or array field.
|
||||
detectors map[string]*kind.Detector
|
||||
// isArray is true if the entity is an array, false if an object.
|
||||
isArray bool
|
||||
}
|
||||
|
||||
func (e *entity) String() string {
|
||||
@ -477,12 +479,12 @@ func walkEntity(ent *entity, visitFn func(*entity) error) error {
|
||||
// ingestSchema encapsulates the table definitions that
|
||||
// the JSON is ingested to.
|
||||
type ingestSchema struct {
|
||||
tblDefs []*schema.Table
|
||||
colMungeFns map[*schema.Column]kind.MungeFunc
|
||||
|
||||
// entityTbls is a mapping of entity to the table in which
|
||||
// the entity's fields will be inserted.
|
||||
entityTbls map[*entity]*schema.Table
|
||||
tblDefs []*schema.Table
|
||||
}
|
||||
|
||||
// execSchemaDelta executes the schema delta between curSchema and newSchema.
|
||||
|
@ -267,14 +267,18 @@ type objectsInArrayScanner struct {
|
||||
// unbounded.
|
||||
buf *buffer
|
||||
|
||||
// dec is the stdlib json decoder.
|
||||
dec *stdj.Decoder
|
||||
|
||||
// decBuf holds the value of dec.Buffered, which allows us
|
||||
// to look ahead at the upcoming decoder values.
|
||||
decBuf []byte
|
||||
|
||||
// bufOffset is the offset of buf's byte slice relative to the
|
||||
// entire input stream. This is necessary given that we trim
|
||||
// buf to prevent unbounded growth.
|
||||
bufOffset int
|
||||
|
||||
// dec is the stdlib json decoder.
|
||||
dec *stdj.Decoder
|
||||
|
||||
// curDecPos is the current position of the decoder in the
|
||||
// input stream.
|
||||
curDecPos int
|
||||
@ -283,10 +287,6 @@ type objectsInArrayScanner struct {
|
||||
// in the input stream.
|
||||
prevDecPos int
|
||||
|
||||
// decBuf holds the value of dec.Buffered, which allows us
|
||||
// to look ahead at the upcoming decoder values.
|
||||
decBuf []byte
|
||||
|
||||
// objCount is the count of objects processed by method next.
|
||||
objCount int
|
||||
}
|
||||
|
@ -57,10 +57,10 @@ func (d *Provider) DriverFor(typ drivertype.Type) (driver.Driver, error) {
|
||||
|
||||
// Driver implements driver.Driver.
|
||||
type driveri struct {
|
||||
typ drivertype.Type
|
||||
ingestFn ingestFunc
|
||||
ingester driver.GripOpenIngester
|
||||
ingestFn ingestFunc
|
||||
files *files.Files
|
||||
typ drivertype.Type
|
||||
}
|
||||
|
||||
// DriverMetadata implements driver.Driver.
|
||||
|
@ -436,11 +436,11 @@ type pgTable struct {
|
||||
tableSchema string
|
||||
tableName string
|
||||
tableType string
|
||||
isInsertable sqlz.NullBool // Use driver.NullBool because "YES", "NO" values
|
||||
rowCount int64
|
||||
size sql.NullInt64
|
||||
oid string
|
||||
comment sql.NullString
|
||||
size sql.NullInt64
|
||||
rowCount int64
|
||||
isInsertable sqlz.NullBool // Use driver.NullBool because "YES", "NO" values
|
||||
}
|
||||
|
||||
func tblMetaFromPgTable(pgt *pgTable) *metadata.Table {
|
||||
@ -475,30 +475,30 @@ type pgColumn struct {
|
||||
tableSchema string
|
||||
tableName string
|
||||
columnName string
|
||||
ordinalPosition int64
|
||||
columnDefault sql.NullString
|
||||
isNullable sqlz.NullBool
|
||||
dataType string
|
||||
udtCatalog string
|
||||
udtSchema string
|
||||
udtName string
|
||||
columnDefault sql.NullString
|
||||
domainCatalog sql.NullString
|
||||
domainSchema sql.NullString
|
||||
domainName sql.NullString
|
||||
isGenerated sql.NullString
|
||||
|
||||
// comment holds any column comment. Note that this field is
|
||||
// not part of the standard postgres infoschema, but is
|
||||
// separately fetched.
|
||||
comment sql.NullString
|
||||
characterMaximumLength sql.NullInt64
|
||||
characterOctetLength sql.NullInt64
|
||||
numericPrecision sql.NullInt64
|
||||
numericPrecisionRadix sql.NullInt64
|
||||
numericScale sql.NullInt64
|
||||
datetimePrecision sql.NullInt64
|
||||
domainCatalog sql.NullString
|
||||
domainSchema sql.NullString
|
||||
domainName sql.NullString
|
||||
udtCatalog string
|
||||
udtSchema string
|
||||
udtName string
|
||||
ordinalPosition int64
|
||||
isNullable sqlz.NullBool
|
||||
isIdentity sqlz.NullBool
|
||||
isGenerated sql.NullString
|
||||
isUpdatable sqlz.NullBool
|
||||
|
||||
// comment holds any column comment. Note that this field is
|
||||
// not part of the standard postgres infoschema, but is
|
||||
// separately fetched.
|
||||
comment sql.NullString
|
||||
}
|
||||
|
||||
// getPgColumns queries the column metadata for tblName.
|
||||
@ -674,7 +674,6 @@ type pgConstraint struct {
|
||||
tableSchema string
|
||||
tableName string
|
||||
columnName string
|
||||
ordinalPosition int64
|
||||
|
||||
constraintName sql.NullString
|
||||
constraintType sql.NullString
|
||||
@ -684,6 +683,7 @@ type pgConstraint struct {
|
||||
// a foreign-key constraint points to. This is null if this
|
||||
// constraint is not a foreign key.
|
||||
constraintFKeyTableName sql.NullString
|
||||
ordinalPosition int64
|
||||
}
|
||||
|
||||
// setTblMetaConstraints updates tblMeta with constraints found
|
||||
|
@ -21,6 +21,7 @@ import (
|
||||
|
||||
// grip implements driver.Grip.
|
||||
type grip struct {
|
||||
closeErr error
|
||||
log *slog.Logger
|
||||
db *sql.DB
|
||||
src *source.Source
|
||||
@ -30,7 +31,6 @@ type grip struct {
|
||||
// This is particularly relevant to sqlite, as calling Close multiple times
|
||||
// can cause problems on Windows.
|
||||
closeOnce sync.Once
|
||||
closeErr error
|
||||
}
|
||||
|
||||
// DB implements driver.Grip.
|
||||
|
@ -22,16 +22,16 @@ type SQLiteLexer struct {
|
||||
}
|
||||
|
||||
var SQLiteLexerLexerStaticData struct {
|
||||
once sync.Once
|
||||
PredictionContextCache *antlr.PredictionContextCache
|
||||
atn *antlr.ATN
|
||||
serializedATN []int32
|
||||
ChannelNames []string
|
||||
ModeNames []string
|
||||
LiteralNames []string
|
||||
SymbolicNames []string
|
||||
RuleNames []string
|
||||
PredictionContextCache *antlr.PredictionContextCache
|
||||
atn *antlr.ATN
|
||||
decisionToDFA []*antlr.DFA
|
||||
once sync.Once
|
||||
}
|
||||
|
||||
func sqlitelexerLexerInit() {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -108,10 +108,10 @@ var _ antlr.ErrorListener = (*antlrErrorListener)(nil)
|
||||
// TODO: this is a copy of the same-named type in libsq/ast/parser.go.
|
||||
// It should be moved to a common package.
|
||||
type antlrErrorListener struct {
|
||||
err error
|
||||
name string
|
||||
errs []string
|
||||
warnings []string
|
||||
err error
|
||||
}
|
||||
|
||||
// SyntaxError implements antlr.ErrorListener.
|
||||
|
@ -464,7 +464,7 @@ type constraintMeta struct {
|
||||
}
|
||||
|
||||
// columnMeta models column metadata from information schema.
|
||||
type columnMeta struct {
|
||||
type columnMeta struct { //nolint:govet // field alignment
|
||||
TableCatalog string `db:"TABLE_CATALOG"`
|
||||
TableSchema string `db:"TABLE_SCHEMA"`
|
||||
TableName string `db:"TABLE_NAME"`
|
||||
|
@ -47,7 +47,7 @@ func (d *DriverDef) String() string {
|
||||
}
|
||||
|
||||
// TableMapping describes how document data is mapped to a table.
|
||||
type TableMapping struct {
|
||||
type TableMapping struct { //nolint:govet // field alignment
|
||||
// Name is the table name.
|
||||
Name string `yaml:"table" json:"table"`
|
||||
|
||||
@ -168,7 +168,7 @@ func (t *TableMapping) RequiredCols() []*ColMapping {
|
||||
}
|
||||
|
||||
// ColMapping models a database table column.
|
||||
type ColMapping struct {
|
||||
type ColMapping struct { //nolint:govet // field alignment
|
||||
// Name is the column name.
|
||||
Name string `yaml:"col" json:"col"`
|
||||
|
||||
|
@ -60,12 +60,12 @@ func (p *Provider) Detectors() []files.TypeDetectFunc {
|
||||
|
||||
// Driver implements driver.Driver.
|
||||
type driveri struct {
|
||||
ingester driver.GripOpenIngester
|
||||
log *slog.Logger
|
||||
typ drivertype.Type
|
||||
def *DriverDef
|
||||
files *files.Files
|
||||
ingester driver.GripOpenIngester
|
||||
ingestFn IngestFunc
|
||||
typ drivertype.Type
|
||||
}
|
||||
|
||||
// DriverMetadata implements driver.Driver.
|
||||
|
@ -8,8 +8,8 @@ import (
|
||||
|
||||
// ArgNode implements the SQL "DISTINCT" clause.
|
||||
type ArgNode struct {
|
||||
baseNode
|
||||
key string
|
||||
baseNode
|
||||
}
|
||||
|
||||
// String returns a log/debug-friendly representation.
|
||||
|
@ -95,8 +95,8 @@ var _ Node = (*AST)(nil)
|
||||
// AST is the Abstract Syntax Tree. It is the root node of a SQL query/stmt.
|
||||
type AST struct {
|
||||
ctx *slq.QueryContext
|
||||
segs []*SegmentNode
|
||||
text string
|
||||
segs []*SegmentNode
|
||||
}
|
||||
|
||||
// ast implements ast.Node.
|
||||
|
@ -21,9 +21,9 @@ var (
|
||||
//
|
||||
// SELECT 1+2 AS "alias" FROM "actor"
|
||||
type ExprElementNode struct {
|
||||
baseNode
|
||||
alias string
|
||||
exprNode *ExprNode
|
||||
alias string
|
||||
baseNode
|
||||
}
|
||||
|
||||
// resultColumn implements ast.ResultColumn.
|
||||
|
@ -25,9 +25,9 @@ var (
|
||||
|
||||
// FuncNode models a function. For example, "COUNT()".
|
||||
type FuncNode struct {
|
||||
baseNode
|
||||
fnName string
|
||||
alias string
|
||||
baseNode
|
||||
proprietary bool
|
||||
}
|
||||
|
||||
|
@ -22,16 +22,16 @@ type SLQLexer struct {
|
||||
}
|
||||
|
||||
var SLQLexerLexerStaticData struct {
|
||||
once sync.Once
|
||||
PredictionContextCache *antlr.PredictionContextCache
|
||||
atn *antlr.ATN
|
||||
serializedATN []int32
|
||||
ChannelNames []string
|
||||
ModeNames []string
|
||||
LiteralNames []string
|
||||
SymbolicNames []string
|
||||
RuleNames []string
|
||||
PredictionContextCache *antlr.PredictionContextCache
|
||||
atn *antlr.ATN
|
||||
decisionToDFA []*antlr.DFA
|
||||
once sync.Once
|
||||
}
|
||||
|
||||
func slqlexerLexerInit() {
|
||||
|
@ -19,14 +19,14 @@ type SLQParser struct {
|
||||
}
|
||||
|
||||
var SLQParserStaticData struct {
|
||||
once sync.Once
|
||||
PredictionContextCache *antlr.PredictionContextCache
|
||||
atn *antlr.ATN
|
||||
serializedATN []int32
|
||||
LiteralNames []string
|
||||
SymbolicNames []string
|
||||
RuleNames []string
|
||||
PredictionContextCache *antlr.PredictionContextCache
|
||||
atn *antlr.ATN
|
||||
decisionToDFA []*antlr.DFA
|
||||
once sync.Once
|
||||
}
|
||||
|
||||
func slqParserInit() {
|
||||
@ -329,8 +329,8 @@ type IStmtListContext interface {
|
||||
}
|
||||
|
||||
type StmtListContext struct {
|
||||
antlr.BaseParserRuleContext
|
||||
parser antlr.Parser
|
||||
antlr.BaseParserRuleContext
|
||||
}
|
||||
|
||||
func NewEmptyStmtListContext() *StmtListContext {
|
||||
@ -574,8 +574,8 @@ type IQueryContext interface {
|
||||
}
|
||||
|
||||
type QueryContext struct {
|
||||
antlr.BaseParserRuleContext
|
||||
parser antlr.Parser
|
||||
antlr.BaseParserRuleContext
|
||||
}
|
||||
|
||||
func NewEmptyQueryContext() *QueryContext {
|
||||
@ -754,8 +754,8 @@ type ISegmentContext interface {
|
||||
}
|
||||
|
||||
type SegmentContext struct {
|
||||
antlr.BaseParserRuleContext
|
||||
parser antlr.Parser
|
||||
antlr.BaseParserRuleContext
|
||||
}
|
||||
|
||||
func NewEmptySegmentContext() *SegmentContext {
|
||||
@ -944,8 +944,8 @@ type IElementContext interface {
|
||||
}
|
||||
|
||||
type ElementContext struct {
|
||||
antlr.BaseParserRuleContext
|
||||
parser antlr.Parser
|
||||
antlr.BaseParserRuleContext
|
||||
}
|
||||
|
||||
func NewEmptyElementContext() *ElementContext {
|
||||
@ -1347,8 +1347,8 @@ type IFuncElementContext interface {
|
||||
}
|
||||
|
||||
type FuncElementContext struct {
|
||||
antlr.BaseParserRuleContext
|
||||
parser antlr.Parser
|
||||
antlr.BaseParserRuleContext
|
||||
}
|
||||
|
||||
func NewEmptyFuncElementContext() *FuncElementContext {
|
||||
@ -1499,8 +1499,8 @@ type IFuncContext interface {
|
||||
}
|
||||
|
||||
type FuncContext struct {
|
||||
antlr.BaseParserRuleContext
|
||||
parser antlr.Parser
|
||||
antlr.BaseParserRuleContext
|
||||
}
|
||||
|
||||
func NewEmptyFuncContext() *FuncContext {
|
||||
@ -1742,8 +1742,8 @@ type IFuncNameContext interface {
|
||||
}
|
||||
|
||||
type FuncNameContext struct {
|
||||
antlr.BaseParserRuleContext
|
||||
parser antlr.Parser
|
||||
antlr.BaseParserRuleContext
|
||||
}
|
||||
|
||||
func NewEmptyFuncNameContext() *FuncNameContext {
|
||||
@ -1858,8 +1858,8 @@ type IJoinContext interface {
|
||||
}
|
||||
|
||||
type JoinContext struct {
|
||||
antlr.BaseParserRuleContext
|
||||
parser antlr.Parser
|
||||
antlr.BaseParserRuleContext
|
||||
}
|
||||
|
||||
func NewEmptyJoinContext() *JoinContext {
|
||||
@ -2054,8 +2054,8 @@ type IJoinTableContext interface {
|
||||
}
|
||||
|
||||
type JoinTableContext struct {
|
||||
antlr.BaseParserRuleContext
|
||||
parser antlr.Parser
|
||||
antlr.BaseParserRuleContext
|
||||
}
|
||||
|
||||
func NewEmptyJoinTableContext() *JoinTableContext {
|
||||
@ -2210,8 +2210,8 @@ type IUniqueFuncContext interface {
|
||||
}
|
||||
|
||||
type UniqueFuncContext struct {
|
||||
antlr.BaseParserRuleContext
|
||||
parser antlr.Parser
|
||||
antlr.BaseParserRuleContext
|
||||
}
|
||||
|
||||
func NewEmptyUniqueFuncContext() *UniqueFuncContext {
|
||||
@ -2319,8 +2319,8 @@ type ICountFuncContext interface {
|
||||
}
|
||||
|
||||
type CountFuncContext struct {
|
||||
antlr.BaseParserRuleContext
|
||||
parser antlr.Parser
|
||||
antlr.BaseParserRuleContext
|
||||
}
|
||||
|
||||
func NewEmptyCountFuncContext() *CountFuncContext {
|
||||
@ -2520,8 +2520,8 @@ type IWhereContext interface {
|
||||
}
|
||||
|
||||
type WhereContext struct {
|
||||
antlr.BaseParserRuleContext
|
||||
parser antlr.Parser
|
||||
antlr.BaseParserRuleContext
|
||||
}
|
||||
|
||||
func NewEmptyWhereContext() *WhereContext {
|
||||
@ -2683,8 +2683,8 @@ type IGroupByTermContext interface {
|
||||
}
|
||||
|
||||
type GroupByTermContext struct {
|
||||
antlr.BaseParserRuleContext
|
||||
parser antlr.Parser
|
||||
antlr.BaseParserRuleContext
|
||||
}
|
||||
|
||||
func NewEmptyGroupByTermContext() *GroupByTermContext {
|
||||
@ -2839,8 +2839,8 @@ type IGroupByContext interface {
|
||||
}
|
||||
|
||||
type GroupByContext struct {
|
||||
antlr.BaseParserRuleContext
|
||||
parser antlr.Parser
|
||||
antlr.BaseParserRuleContext
|
||||
}
|
||||
|
||||
func NewEmptyGroupByContext() *GroupByContext {
|
||||
@ -3055,8 +3055,8 @@ type IHavingContext interface {
|
||||
}
|
||||
|
||||
type HavingContext struct {
|
||||
antlr.BaseParserRuleContext
|
||||
parser antlr.Parser
|
||||
antlr.BaseParserRuleContext
|
||||
}
|
||||
|
||||
func NewEmptyHavingContext() *HavingContext {
|
||||
@ -3205,8 +3205,8 @@ type IOrderByTermContext interface {
|
||||
}
|
||||
|
||||
type OrderByTermContext struct {
|
||||
antlr.BaseParserRuleContext
|
||||
parser antlr.Parser
|
||||
antlr.BaseParserRuleContext
|
||||
}
|
||||
|
||||
func NewEmptyOrderByTermContext() *OrderByTermContext {
|
||||
@ -3348,8 +3348,8 @@ type IOrderByContext interface {
|
||||
}
|
||||
|
||||
type OrderByContext struct {
|
||||
antlr.BaseParserRuleContext
|
||||
parser antlr.Parser
|
||||
antlr.BaseParserRuleContext
|
||||
}
|
||||
|
||||
func NewEmptyOrderByContext() *OrderByContext {
|
||||
@ -3562,8 +3562,8 @@ type ISelectorContext interface {
|
||||
}
|
||||
|
||||
type SelectorContext struct {
|
||||
antlr.BaseParserRuleContext
|
||||
parser antlr.Parser
|
||||
antlr.BaseParserRuleContext
|
||||
}
|
||||
|
||||
func NewEmptySelectorContext() *SelectorContext {
|
||||
@ -3689,8 +3689,8 @@ type ISelectorElementContext interface {
|
||||
}
|
||||
|
||||
type SelectorElementContext struct {
|
||||
antlr.BaseParserRuleContext
|
||||
parser antlr.Parser
|
||||
antlr.BaseParserRuleContext
|
||||
}
|
||||
|
||||
func NewEmptySelectorElementContext() *SelectorElementContext {
|
||||
@ -3840,8 +3840,8 @@ type IAliasContext interface {
|
||||
}
|
||||
|
||||
type AliasContext struct {
|
||||
antlr.BaseParserRuleContext
|
||||
parser antlr.Parser
|
||||
antlr.BaseParserRuleContext
|
||||
}
|
||||
|
||||
func NewEmptyAliasContext() *AliasContext {
|
||||
@ -3999,8 +3999,8 @@ type IArgContext interface {
|
||||
}
|
||||
|
||||
type ArgContext struct {
|
||||
antlr.BaseParserRuleContext
|
||||
parser antlr.Parser
|
||||
antlr.BaseParserRuleContext
|
||||
}
|
||||
|
||||
func NewEmptyArgContext() *ArgContext {
|
||||
@ -4106,8 +4106,8 @@ type IHandleTableContext interface {
|
||||
}
|
||||
|
||||
type HandleTableContext struct {
|
||||
antlr.BaseParserRuleContext
|
||||
parser antlr.Parser
|
||||
antlr.BaseParserRuleContext
|
||||
}
|
||||
|
||||
func NewEmptyHandleTableContext() *HandleTableContext {
|
||||
@ -4224,8 +4224,8 @@ type IHandleContext interface {
|
||||
}
|
||||
|
||||
type HandleContext struct {
|
||||
antlr.BaseParserRuleContext
|
||||
parser antlr.Parser
|
||||
antlr.BaseParserRuleContext
|
||||
}
|
||||
|
||||
func NewEmptyHandleContext() *HandleContext {
|
||||
@ -4333,8 +4333,8 @@ type IRowRangeContext interface {
|
||||
}
|
||||
|
||||
type RowRangeContext struct {
|
||||
antlr.BaseParserRuleContext
|
||||
parser antlr.Parser
|
||||
antlr.BaseParserRuleContext
|
||||
}
|
||||
|
||||
func NewEmptyRowRangeContext() *RowRangeContext {
|
||||
@ -4544,8 +4544,8 @@ type IExprElementContext interface {
|
||||
}
|
||||
|
||||
type ExprElementContext struct {
|
||||
antlr.BaseParserRuleContext
|
||||
parser antlr.Parser
|
||||
antlr.BaseParserRuleContext
|
||||
}
|
||||
|
||||
func NewEmptyExprElementContext() *ExprElementContext {
|
||||
@ -4704,8 +4704,8 @@ type IExprContext interface {
|
||||
}
|
||||
|
||||
type ExprContext struct {
|
||||
antlr.BaseParserRuleContext
|
||||
parser antlr.Parser
|
||||
antlr.BaseParserRuleContext
|
||||
}
|
||||
|
||||
func NewEmptyExprContext() *ExprContext {
|
||||
@ -5264,8 +5264,8 @@ type ILiteralContext interface {
|
||||
}
|
||||
|
||||
type LiteralContext struct {
|
||||
antlr.BaseParserRuleContext
|
||||
parser antlr.Parser
|
||||
antlr.BaseParserRuleContext
|
||||
}
|
||||
|
||||
func NewEmptyLiteralContext() *LiteralContext {
|
||||
@ -5383,8 +5383,8 @@ type IUnaryOperatorContext interface {
|
||||
}
|
||||
|
||||
type UnaryOperatorContext struct {
|
||||
antlr.BaseParserRuleContext
|
||||
parser antlr.Parser
|
||||
antlr.BaseParserRuleContext
|
||||
}
|
||||
|
||||
func NewEmptyUnaryOperatorContext() *UnaryOperatorContext {
|
||||
|
@ -129,14 +129,14 @@ var _ Node = (*JoinNode)(nil)
|
||||
|
||||
// JoinNode models a SQL JOIN node.
|
||||
type JoinNode struct {
|
||||
seg *SegmentNode
|
||||
ctx antlr.ParseTree
|
||||
text string
|
||||
jt jointype.Type
|
||||
jtVal string
|
||||
seg *SegmentNode
|
||||
predicateExpr *ExprNode
|
||||
|
||||
targetTbl *TblSelectorNode
|
||||
text string
|
||||
jt jointype.Type
|
||||
jtVal string
|
||||
}
|
||||
|
||||
// ast implements ast.Node.
|
||||
|
@ -16,8 +16,8 @@ const (
|
||||
|
||||
// LiteralNode is a leaf node representing a literal such as a number or a string.
|
||||
type LiteralNode struct {
|
||||
baseNode
|
||||
typ LiteralType
|
||||
baseNode
|
||||
}
|
||||
|
||||
// String returns a log/debug-friendly representation.
|
||||
|
@ -72,9 +72,9 @@ type ResultColumn interface {
|
||||
// baseNode is a base implementation of Node.
|
||||
type baseNode struct {
|
||||
parent Node
|
||||
children []Node
|
||||
ctx antlr.ParseTree
|
||||
text string
|
||||
children []Node
|
||||
}
|
||||
|
||||
// ast implements ast.Node.
|
||||
|
@ -71,8 +71,8 @@ const (
|
||||
|
||||
// OrderByTermNode is a child of OrderByNode.
|
||||
type OrderByTermNode struct {
|
||||
baseNode
|
||||
direction OrderByDirection
|
||||
baseNode
|
||||
}
|
||||
|
||||
// AddChild accepts a single child of type *SelectorNode.
|
||||
|
@ -41,11 +41,11 @@ func parseSLQ(log *slog.Logger, input string) (*slq.QueryContext, error) {
|
||||
var _ antlr.ErrorListener = (*antlrErrorListener)(nil)
|
||||
|
||||
type antlrErrorListener struct {
|
||||
err error
|
||||
log *slog.Logger
|
||||
name string
|
||||
errs []string
|
||||
warnings []string
|
||||
err error
|
||||
}
|
||||
|
||||
// SyntaxError implements antlr.ErrorListener.
|
||||
|
@ -14,9 +14,6 @@ type Context struct {
|
||||
// Renderer holds the rendering functions.
|
||||
Renderer *Renderer
|
||||
|
||||
// Dialect is the driver dialect.
|
||||
Dialect dialect.Dialect
|
||||
|
||||
// The args map contains predefined variables that are
|
||||
// substituted into the query. It may be empty or nil.
|
||||
Args map[string]string
|
||||
@ -25,6 +22,9 @@ type Context struct {
|
||||
// a SQL query. It may not be initialized until late in
|
||||
// the day.
|
||||
Fragments *Fragments
|
||||
|
||||
// Dialect is the driver dialect.
|
||||
Dialect dialect.Dialect
|
||||
}
|
||||
|
||||
// Renderer is a set of functions for rendering ast elements into SQL.
|
||||
@ -84,12 +84,12 @@ type Renderer struct {
|
||||
// empty string if n is nil.
|
||||
Distinct func(rc *Context, n *ast.UniqueNode) (string, error)
|
||||
|
||||
// Render renders f into a SQL query.
|
||||
Render func(rc *Context, f *Fragments) (string, error)
|
||||
|
||||
// PreRender is a set of hooks that are called before Render. It is a final
|
||||
// opportunity to customize f before rendering. It is nil by default.
|
||||
PreRender []func(rc *Context, f *Fragments) error
|
||||
|
||||
// Render renders f into a SQL query.
|
||||
Render func(rc *Context, f *Fragments) (string, error)
|
||||
}
|
||||
|
||||
// NewDefaultRenderer returns a Renderer that works for most SQL dialects.
|
||||
@ -121,6 +121,14 @@ func NewDefaultRenderer() *Renderer {
|
||||
// Fragments holds the fragments of a SQL query.
|
||||
// It is passed to Renderer.PreRender and Renderer.Render.
|
||||
type Fragments struct {
|
||||
Distinct string
|
||||
Columns string
|
||||
From string
|
||||
Where string
|
||||
GroupBy string
|
||||
Having string
|
||||
OrderBy string
|
||||
Range string
|
||||
// PreExecStmts are statements that are executed before the query.
|
||||
// These can be used for edge-case behavior, such as setting up
|
||||
// variables in the session.
|
||||
@ -132,15 +140,6 @@ type Fragments struct {
|
||||
//
|
||||
// See also: Fragments.PreExecStmts.
|
||||
PostExecStmts []string
|
||||
|
||||
Distinct string
|
||||
Columns string
|
||||
From string
|
||||
Where string
|
||||
GroupBy string
|
||||
Having string
|
||||
OrderBy string
|
||||
Range string
|
||||
}
|
||||
|
||||
// doRender renders the supplied fragments into a SQL query.
|
||||
|
@ -88,8 +88,6 @@ var (
|
||||
// generic selector will typically be replaced with a more specific
|
||||
// selector node such as TblSelectorNode or ColSelectorNode.
|
||||
type SelectorNode struct {
|
||||
baseNode
|
||||
|
||||
// alias is the (optional) alias part. For example, given ".first_name:given_name",
|
||||
// the alias value is "given_name". May be empty.
|
||||
alias string
|
||||
@ -104,6 +102,7 @@ type SelectorNode struct {
|
||||
// - .actor --> name1 = EMPTY
|
||||
// - .actor.first_name -> name1 = first_name
|
||||
name1 string
|
||||
baseNode
|
||||
}
|
||||
|
||||
// selector implements the ast.selector marker interface.
|
||||
@ -126,10 +125,10 @@ var _ Node = (*TblSelectorNode)(nil)
|
||||
// TblSelectorNode is a selector for a table, such as ".my_table"
|
||||
// or "@my_src.my_table".
|
||||
type TblSelectorNode struct {
|
||||
SelectorNode
|
||||
tbl tablefq.T
|
||||
|
||||
handle string
|
||||
tbl tablefq.T
|
||||
SelectorNode
|
||||
}
|
||||
|
||||
// newTblSelector creates a new TblSelectorNode from ctx.
|
||||
|
@ -22,8 +22,8 @@ func New() *Cleanup {
|
||||
// they are added.
|
||||
// Cleanup is safe for concurrent use.
|
||||
type Cleanup struct {
|
||||
mu sync.Mutex
|
||||
fns []func() error
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
// Len returns the count of cleanup funcs.
|
||||
|
@ -57,8 +57,8 @@ func Errorf(format string, args ...any) error {
|
||||
// errz is our error type that does the magic.
|
||||
type errz struct {
|
||||
error
|
||||
msg string
|
||||
*stack
|
||||
msg string
|
||||
}
|
||||
|
||||
// inner implements stackTracer.
|
||||
|
@ -208,9 +208,9 @@ func Errors(err error) []error {
|
||||
// multiErr formats to a semicolon delimited list of error messages with
|
||||
// %v and with a more readable multi-line format with %+v.
|
||||
type multiErr struct { //nolint:errname
|
||||
copyNeeded atomic.Bool
|
||||
errors []error
|
||||
*stack
|
||||
errors []error
|
||||
copyNeeded atomic.Bool
|
||||
}
|
||||
|
||||
// inner implements stackTracer.
|
||||
|
@ -470,10 +470,10 @@ func ReadCloserNotifier(rc io.ReadCloser, fn func(closeErr error)) io.ReadCloser
|
||||
}
|
||||
|
||||
type readCloserNotifier struct {
|
||||
once sync.Once
|
||||
closeErr error
|
||||
fn func(error)
|
||||
io.ReadCloser
|
||||
fn func(error)
|
||||
once sync.Once
|
||||
}
|
||||
|
||||
func (c *readCloserNotifier) Close() error {
|
||||
@ -493,10 +493,10 @@ func NewErrorAfterNReader(n int, err error) io.Reader {
|
||||
}
|
||||
|
||||
type errorAfterNReader struct {
|
||||
mu sync.Mutex
|
||||
err error
|
||||
afterN int
|
||||
count int
|
||||
err error
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
func (r *errorAfterNReader) Read(p []byte) (n int, err error) {
|
||||
|
@ -49,8 +49,7 @@ Color support on Windows can be added by using e.g. the [go-colorable] package.
|
||||
[zerolog.ConsoleWriter]: https://pkg.go.dev/github.com/rs/zerolog#ConsoleWriter
|
||||
[go-isatty]: https://pkg.go.dev/github.com/mattn/go-isatty
|
||||
[go-colorable]: https://pkg.go.dev/github.com/mattn/go-colorable
|
||||
*/
|
||||
package tint
|
||||
*/package tint
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@ -114,9 +113,6 @@ var (
|
||||
//
|
||||
// Options can be used as a drop-in replacement for slog.HandlerOptions.
|
||||
type Options struct {
|
||||
// Enable source code location (Default: false)
|
||||
AddSource bool
|
||||
|
||||
// Minimum level to log (Default: slog.LevelInfo)
|
||||
Level slog.Leveler
|
||||
|
||||
@ -127,6 +123,9 @@ type Options struct {
|
||||
// Time format (Default: time.StampMilli)
|
||||
TimeFormat string
|
||||
|
||||
// Enable source code location (Default: false)
|
||||
AddSource bool
|
||||
|
||||
// Disable color (Default: false)
|
||||
NoColor bool
|
||||
}
|
||||
@ -157,17 +156,18 @@ func NewHandler(w io.Writer, opts *Options) slog.Handler {
|
||||
|
||||
// handler implements a slog.Handler.
|
||||
type handler struct {
|
||||
w io.Writer
|
||||
|
||||
level slog.Leveler
|
||||
replaceAttr func([]string, slog.Attr) slog.Attr
|
||||
attrsPrefix string
|
||||
groupPrefix string
|
||||
timeFormat string
|
||||
groups []string
|
||||
|
||||
mu sync.Mutex
|
||||
w io.Writer
|
||||
|
||||
addSource bool
|
||||
level slog.Leveler
|
||||
replaceAttr func([]string, slog.Attr) slog.Attr
|
||||
timeFormat string
|
||||
noColor bool
|
||||
}
|
||||
|
||||
|
@ -28,8 +28,8 @@ func New() (*slog.Logger, *Buffer) {
|
||||
|
||||
// Buffer stores slog records that can be replayed via Buffer.Flush.
|
||||
type Buffer struct {
|
||||
mu sync.Mutex
|
||||
entries []entry
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
type entry struct {
|
||||
|
@ -98,10 +98,10 @@ type Opt interface {
|
||||
type BaseOpt struct {
|
||||
key string
|
||||
flag string
|
||||
short rune
|
||||
usage string
|
||||
help string
|
||||
tags []string
|
||||
short rune
|
||||
}
|
||||
|
||||
// NewBaseOpt returns a new BaseOpt. If flag is empty string, key is
|
||||
@ -207,9 +207,9 @@ func NewString(key, flag string, short rune, defaultVal string,
|
||||
|
||||
// String is an options.Opt for type string.
|
||||
type String struct {
|
||||
BaseOpt
|
||||
defaultVal string
|
||||
validFn func(string) error
|
||||
defaultVal string
|
||||
BaseOpt
|
||||
}
|
||||
|
||||
// GetAny implements options.Opt.
|
||||
|
@ -48,8 +48,8 @@ func FromContext(ctx context.Context) Options {
|
||||
|
||||
// Registry is a registry of Opt instances.
|
||||
type Registry struct {
|
||||
mu sync.Mutex
|
||||
opts []Opt
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
// Add adds opts to r. It panics if any element of opts is already registered.
|
||||
|
@ -202,20 +202,22 @@ func (rm Meta) LogValue() slog.Value {
|
||||
//
|
||||
// This is all a bit ugly.
|
||||
type ColumnTypeData struct {
|
||||
ScanType reflect.Type `json:"scan_type"`
|
||||
|
||||
Name string `json:"name"`
|
||||
|
||||
DatabaseTypeName string `json:"database_type_name"`
|
||||
Length int64 `json:"length"`
|
||||
Precision int64 `json:"precision"`
|
||||
Scale int64 `json:"scale"`
|
||||
|
||||
Kind kind.Kind `json:"kind"`
|
||||
|
||||
HasNullable bool `json:"has_nullable"`
|
||||
HasLength bool `json:"has_length"`
|
||||
HasPrecisionScale bool `json:"has_precision_scale"`
|
||||
|
||||
Nullable bool `json:"nullable"`
|
||||
Length int64 `json:"length"`
|
||||
DatabaseTypeName string `json:"database_type_name"`
|
||||
Precision int64 `json:"precision"`
|
||||
Scale int64 `json:"scale"`
|
||||
ScanType reflect.Type `json:"scan_type"`
|
||||
|
||||
Kind kind.Kind `json:"kind"`
|
||||
}
|
||||
|
||||
// NewColumnTypeData returns a new instance with field values
|
||||
|
@ -9,7 +9,7 @@ import (
|
||||
)
|
||||
|
||||
// Table models a database table definition.
|
||||
type Table struct {
|
||||
type Table struct { //nolint:govet // field alignment
|
||||
// Name is the table name.
|
||||
Name string `json:"name"`
|
||||
|
||||
@ -99,7 +99,7 @@ func (t *Table) FindCol(name string) (*Column, error) {
|
||||
}
|
||||
|
||||
// Column models a table column definition.
|
||||
type Column struct {
|
||||
type Column struct { //nolint:govet // field alignment
|
||||
Name string `json:"name"`
|
||||
Table *Table `json:"-"`
|
||||
Kind kind.Kind `json:"kind"`
|
||||
|
@ -8,9 +8,6 @@ import (
|
||||
|
||||
// Dialect holds driver-specific SQL dialect values and functions.
|
||||
type Dialect struct {
|
||||
// Type is the dialect's driver type.
|
||||
Type drivertype.Type `json:"type"`
|
||||
|
||||
// Placeholders returns a string a SQL placeholders string.
|
||||
// For example "(?, ?, ?)" or "($1, $2, $3), ($4, $5, $6)".
|
||||
Placeholders func(numCols, numRows int) string
|
||||
@ -20,21 +17,24 @@ type Dialect struct {
|
||||
// uses the double-quote rune (although MySQL uses backtick).
|
||||
Enquote func(string) string
|
||||
|
||||
// IntBool is true if BOOLEAN is handled as an INT by the DB driver.
|
||||
IntBool bool `json:"int_bool"`
|
||||
|
||||
// MaxBatchValues is the maximum number of values in a batch insert.
|
||||
MaxBatchValues int
|
||||
|
||||
// Ops is a map of overridden SLQ operator (e.g. "==" or "!=") to
|
||||
// its SQL rendering.
|
||||
Ops map[string]string
|
||||
|
||||
// Type is the dialect's driver type.
|
||||
Type drivertype.Type `json:"type"`
|
||||
|
||||
// Joins is the set of JOIN types (e.g. "RIGHT JOIN") that
|
||||
// the dialect supports. Not all drivers support each join type. For
|
||||
// example, MySQL doesn't support jointype.FullOuter.
|
||||
Joins []jointype.Type
|
||||
|
||||
// MaxBatchValues is the maximum number of values in a batch insert.
|
||||
MaxBatchValues int
|
||||
|
||||
// IntBool is true if BOOLEAN is handled as an INT by the DB driver.
|
||||
IntBool bool `json:"int_bool"`
|
||||
|
||||
// Catalog indicates that the database supports the catalog concept,
|
||||
// in addition to schema. For example, PostgreSQL supports catalog
|
||||
// and schema (sakila.public.actor), whereas MySQL only supports schema
|
||||
|
@ -32,11 +32,11 @@ type ScratchSrcFunc func(ctx context.Context, name string) (src *source.Source,
|
||||
// and then closed by Close. This may be a bad approach.
|
||||
type Grips struct {
|
||||
drvrs Provider
|
||||
mu sync.Mutex
|
||||
scratchSrcFn ScratchSrcFunc
|
||||
files *files.Files
|
||||
grips map[string]Grip
|
||||
clnup *cleanup.Cleanup
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
// NewGrips returns a Grips instances.
|
||||
@ -427,9 +427,9 @@ var _ Grip = (*cleanOnCloseGrip)(nil)
|
||||
// invocations of Close are no-ops and return the same error.
|
||||
type cleanOnCloseGrip struct {
|
||||
Grip
|
||||
once sync.Once
|
||||
closeErr error
|
||||
clnup *cleanup.Cleanup
|
||||
once sync.Once
|
||||
}
|
||||
|
||||
// Close implements Grip. It invokes the underlying Grip's Close
|
||||
|
@ -716,12 +716,12 @@ type columnRenameTemplateData struct {
|
||||
// Name is the original column name.
|
||||
Name string
|
||||
|
||||
// Index is the column index.
|
||||
Index int
|
||||
|
||||
// Alpha is the Excel-style alphabetical index, i.e. A, B, ..., Z, AA, AB.
|
||||
Alpha string
|
||||
|
||||
// Index is the column index.
|
||||
Index int
|
||||
|
||||
// Recurrence is the count of times this column name has already
|
||||
// appeared in the list of column names. If the column name is unique,
|
||||
// this value is zero.
|
||||
|
@ -22,9 +22,9 @@ func NewRegistry(log *slog.Logger) *Registry {
|
||||
// Registry provides access to driver implementations.
|
||||
type Registry struct {
|
||||
log *slog.Logger
|
||||
mu sync.Mutex
|
||||
providers map[drivertype.Type]Provider
|
||||
types []drivertype.Type
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
// AddProvider registers the provider for the specified driver type.
|
||||
|
@ -107,7 +107,17 @@ const XFromCache = "X-From-Stream"
|
||||
// Downloader encapsulates downloading a file from a URL, using a local
|
||||
// disk cache if possible.
|
||||
type Downloader struct {
|
||||
mu sync.Mutex
|
||||
// c is the HTTP client used to make requests.
|
||||
c *http.Client
|
||||
|
||||
// cache implements the on-disk cache. If nil, caching is disabled.
|
||||
// It will be created in dlDir.
|
||||
cache *cache
|
||||
|
||||
// dlStream is the streamcache.Stream that is returned Handler for an
|
||||
// active download. This field is used by Downloader.Filesize. It is
|
||||
// reset to nil on each call to Downloader.Get.
|
||||
dlStream *streamcache.Stream
|
||||
|
||||
// name is a user-friendly name, such as a source handle like @data.
|
||||
name string
|
||||
@ -116,28 +126,18 @@ type Downloader struct {
|
||||
// thus is guaranteed to be valid.
|
||||
url string
|
||||
|
||||
// c is the HTTP client used to make requests.
|
||||
c *http.Client
|
||||
// dlDir is the directory in which the download cache is stored.
|
||||
dlDir string
|
||||
|
||||
mu sync.Mutex
|
||||
|
||||
// continueOnError, if true, indicates that the downloader
|
||||
// should server the cached file if a refresh attempt fails.
|
||||
continueOnError bool
|
||||
|
||||
// dlDir is the directory in which the download cache is stored.
|
||||
dlDir string
|
||||
|
||||
// cache implements the on-disk cache. If nil, caching is disabled.
|
||||
// It will be created in dlDir.
|
||||
cache *cache
|
||||
|
||||
// markCachedResponses, if true, indicates that responses returned from the
|
||||
// cache will be given an extra header, X-From-cache.
|
||||
markCachedResponses bool
|
||||
|
||||
// dlStream is the streamcache.Stream that is returned Handler for an
|
||||
// active download. This field is used by Downloader.Filesize. It is
|
||||
// reset to nil on each call to Downloader.Get.
|
||||
dlStream *streamcache.Stream
|
||||
}
|
||||
|
||||
// New returns a new Downloader for url that caches downloads in dlDir..
|
||||
|
@ -39,7 +39,6 @@ type Handler struct {
|
||||
// callbacks it receives. This is used for testing.
|
||||
type SinkHandler struct {
|
||||
Handler
|
||||
mu sync.Mutex
|
||||
log *slog.Logger
|
||||
|
||||
// Errors records the errors received via Handler.Error.
|
||||
@ -50,6 +49,7 @@ type SinkHandler struct {
|
||||
|
||||
// Streams records the streams received via Handler.Uncached.
|
||||
Streams []*streamcache.Stream
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
// Reset resets the handler sinks. It also closes the source reader of
|
||||
|
@ -31,10 +31,7 @@ import (
|
||||
// a uniform mechanism for reading files, whether from local disk, stdin,
|
||||
// or remote HTTP.
|
||||
type Files struct {
|
||||
mu sync.Mutex
|
||||
log *slog.Logger
|
||||
cacheDir string
|
||||
tempDir string
|
||||
clnup *cleanup.Cleanup
|
||||
optRegistry *options.Registry
|
||||
|
||||
@ -66,9 +63,13 @@ type Files struct {
|
||||
// cfgLockFn is the lock func for sq's config.
|
||||
cfgLockFn lockfile.LockFunc
|
||||
|
||||
cacheDir string
|
||||
tempDir string
|
||||
|
||||
// detectFns is the set of functions that can detect
|
||||
// the type of a file.
|
||||
detectFns []TypeDetectFunc
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
// New returns a new Files instance. The caller must invoke Files.Close
|
||||
|
@ -26,8 +26,9 @@ import (
|
||||
// pipeline is used to execute a SLQ query,
|
||||
// and write the resulting records to a RecordWriter.
|
||||
type pipeline struct {
|
||||
// query is the SLQ query
|
||||
query string
|
||||
// targetGrip is the destination for the ultimate SQL query to
|
||||
// be executed against.
|
||||
targetGrip driver.Grip
|
||||
|
||||
// qc is the context in which the query is executed.
|
||||
qc *QueryContext
|
||||
@ -38,17 +39,16 @@ type pipeline struct {
|
||||
// based on the input query and other context.
|
||||
rc *render.Context
|
||||
|
||||
// tasks contains tasks that must be completed before targetSQL
|
||||
// is executed against targetGrip. Typically tasks is used to
|
||||
// set up the joindb before it is queried.
|
||||
tasks []tasker
|
||||
// query is the SLQ query
|
||||
query string
|
||||
|
||||
// targetSQL is the ultimate SQL query to be executed against targetGrip.
|
||||
targetSQL string
|
||||
|
||||
// targetGrip is the destination for the ultimate SQL query to
|
||||
// be executed against.
|
||||
targetGrip driver.Grip
|
||||
// tasks contains tasks that must be completed before targetSQL
|
||||
// is executed against targetGrip. Typically tasks is used to
|
||||
// set up the joindb before it is queried.
|
||||
tasks []tasker
|
||||
}
|
||||
|
||||
// newPipeline parses query, returning a pipeline prepared for
|
||||
|
@ -12,14 +12,14 @@ import (
|
||||
type queryModel struct {
|
||||
AST *ast.AST
|
||||
Table *ast.TblSelectorNode
|
||||
Joins []*ast.JoinNode
|
||||
Cols []ast.ResultColumn
|
||||
Range *ast.RowRangeNode
|
||||
Where *ast.WhereNode
|
||||
OrderBy *ast.OrderByNode
|
||||
GroupBy *ast.GroupByNode
|
||||
Having *ast.HavingNode
|
||||
Distinct *ast.UniqueNode
|
||||
Joins []*ast.JoinNode
|
||||
Cols []ast.ResultColumn
|
||||
}
|
||||
|
||||
func (qm *queryModel) String() string {
|
||||
|
@ -24,14 +24,14 @@ const (
|
||||
// Collection is a set of sources. Typically it is loaded from config
|
||||
// at a start of a run. Collection's methods are safe for concurrent use.
|
||||
type Collection struct {
|
||||
// data holds the set's data.
|
||||
data collData
|
||||
|
||||
// mu is the mutex used by exported methods. A method
|
||||
// should never call an exported method. Many exported methods
|
||||
// have an internal equivalent, e.g. "IsExistingGroup" and
|
||||
// "isExistingGroup", which should be used instead.
|
||||
mu sync.Mutex
|
||||
|
||||
// data holds the set's adata.
|
||||
data collData
|
||||
}
|
||||
|
||||
// collData holds Collection data for the purposes of serialization
|
||||
@ -886,7 +886,7 @@ func (c *Collection) tree(fromGroup string) (*Group, error) {
|
||||
}
|
||||
|
||||
// Group models the hierarchical group structure of a set.
|
||||
type Group struct {
|
||||
type Group struct { //nolint:govet // field alignment
|
||||
// Name is the group name. For the root group, this is source.RootGroup ("/").
|
||||
Name string `json:"name" yaml:"name"`
|
||||
|
||||
|
@ -159,9 +159,6 @@ type Fields struct {
|
||||
// Hostname is the Hostname, if applicable.
|
||||
Hostname string
|
||||
|
||||
// Port is the Port number or 0 if not applicable.
|
||||
Port int
|
||||
|
||||
// Name is the "source Name", e.g. "sakila". Typically this
|
||||
// is the database Name, but for a file location such
|
||||
// as "/path/to/things.xlsx" it would be "things".
|
||||
@ -173,6 +170,9 @@ type Fields struct {
|
||||
// DSN is the connection "data source Name" that can be used in a
|
||||
// call to sql.Open. Empty for non-SQL locations.
|
||||
DSN string
|
||||
|
||||
// Port is the Port number or 0 if not applicable.
|
||||
Port int
|
||||
}
|
||||
|
||||
// Parse parses a location string, returning a Fields instance representing
|
||||
|
@ -10,7 +10,7 @@ import (
|
||||
)
|
||||
|
||||
// Source holds metadata for a source.
|
||||
type Source struct {
|
||||
type Source struct { //nolint:govet // field alignment
|
||||
// Handle is the source handle.
|
||||
Handle string `json:"handle" yaml:"handle"`
|
||||
|
||||
@ -134,7 +134,7 @@ func (s *Source) String() string {
|
||||
}
|
||||
|
||||
// Table models table (or view) metadata.
|
||||
type Table struct {
|
||||
type Table struct { //nolint:govet // field alignment
|
||||
// Name is the table name, such as "actor".
|
||||
Name string `json:"name" yaml:"name"`
|
||||
|
||||
@ -222,7 +222,7 @@ func (t *Table) PKCols() []*Column {
|
||||
}
|
||||
|
||||
// Column models metadata for a particular column of a data source.
|
||||
type Column struct {
|
||||
type Column struct { //nolint:govet // field alignment
|
||||
Name string `json:"name" yaml:"name"`
|
||||
Position int64 `json:"position" yaml:"position"`
|
||||
PrimaryKey bool `json:"primary_key" yaml:"primary_key"`
|
||||
|
@ -51,7 +51,13 @@ func ReservedHandles() []string {
|
||||
var _ slog.LogValuer = (*Source)(nil)
|
||||
|
||||
// Source describes a data source.
|
||||
type Source struct {
|
||||
type Source struct { //nolint:govet
|
||||
// Note: We disable the govet linter because it wants to reorder
|
||||
// the fields to save a few bytes. However, for the purposes of
|
||||
// outputting Source to config files, we prefer this order.
|
||||
// We could probably implement a customer marshaler if struct
|
||||
// alignment becomes an issue.
|
||||
|
||||
// Handle is used to refer to a source, e.g. "@sakila".
|
||||
Handle string `yaml:"handle" json:"handle"`
|
||||
|
||||
|
@ -112,8 +112,6 @@ func KindScanType(knd kind.Kind) reflect.Type {
|
||||
// RecordSink is an impl of output.RecordWriter that
|
||||
// captures invocations of that interface.
|
||||
type RecordSink struct {
|
||||
mu sync.Mutex
|
||||
|
||||
// RecMeta holds the recMeta received via Open.
|
||||
RecMeta record.Meta
|
||||
|
||||
@ -125,6 +123,7 @@ type RecordSink struct {
|
||||
|
||||
// Flushed tracks the times Flush was invoked.
|
||||
Flushed []time.Time
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
// Result returns the first (and only) value returned from
|
||||
|
@ -87,24 +87,25 @@ func OptNoLog() Option {
|
||||
|
||||
// Helper encapsulates a test helper session.
|
||||
type Helper struct {
|
||||
mu sync.Mutex
|
||||
|
||||
T testing.TB
|
||||
|
||||
Context context.Context
|
||||
|
||||
registry *driver.Registry
|
||||
files *files.Files
|
||||
grips *driver.Grips
|
||||
run *run.Run
|
||||
|
||||
initOnce sync.Once
|
||||
|
||||
coll *source.Collection
|
||||
srcCache map[string]*source.Source
|
||||
|
||||
Context context.Context
|
||||
cancelFn context.CancelFunc
|
||||
|
||||
Cleanup *cleanup.Cleanup
|
||||
|
||||
initOnce sync.Once
|
||||
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
// New returns a new Helper. The helper's Close func will be
|
||||
|
Loading…
Reference in New Issue
Block a user