Full Code of dinedal/textql for AI

master e6545d501ca9 cached
44 files
297.7 KB
99.8k tokens
518 symbols
1 requests
Download .txt
Showing preview only (311K chars total). Download the full file or copy to clipboard to get everything.
Repository: dinedal/textql
Branch: master
Commit: e6545d501ca9
Files: 44
Total size: 297.7 KB

Directory structure:
gitextract_eggpcwiz/

├── .SRCINFO
├── .gitignore
├── .travis.yml
├── Dockerfile
├── Dockerfile.alpine
├── LICENSE
├── Makefile
├── PKGBUILD
├── Readme.md
├── TODO.txt
├── VERSION
├── go.mod
├── go.sum
├── inputs/
│   ├── csv.go
│   ├── csv_test.go
│   └── input.go
├── man/
│   ├── textql.1
│   ├── textql.1.html
│   └── textql.1.ronn
├── outputs/
│   ├── csv.go
│   ├── output.go
│   └── pretty_csv.go
├── snapcraft.yaml
├── sqlparser/
│   ├── Makefile
│   ├── analyzer.go
│   ├── ast.go
│   ├── fuzz.go
│   ├── parsed_query.go
│   ├── sql.go
│   ├── sql.y
│   ├── sql_mod.go
│   ├── sqltypes/
│   │   ├── sqltypes.go
│   │   └── type_test.go
│   ├── token.go
│   ├── tracked_buffer.go
│   └── y.output
├── storage/
│   ├── sqlite.go
│   ├── sqlite_regexp.go
│   ├── sqlite_test.go
│   └── storage.go
├── test_util/
│   └── test_util.go
├── textql/
│   └── main.go
└── util/
    ├── file_helpers.go
    └── seperator_helpers.go

================================================
FILE CONTENTS
================================================

================================================
FILE: .SRCINFO
================================================
pkgbase = textql-git
	pkgdesc = Execute SQL against structured text like CSV or TSV
	pkgver = 2.0.3
	pkgrel = 1
	url = https://github.com/dinedal/textql
	arch = x86_64
	arch = i686
	license = MIT
	makedepends = git
	depends = go
	options = !strip
	options = !emptydirs

pkgname = textql-git



================================================
FILE: .gitignore
================================================
vendor/
glide
build/


================================================
FILE: .travis.yml
================================================
os: linux
arch:
 - amd64
 - ppc64le
language: go
sudo: false

go:
  - '1.13.x'

install: make


================================================
FILE: Dockerfile
================================================
FROM golang:1.10

# install sqlite3 for option "-console"
RUN apt-get update && apt-get install -y sqlite3

WORKDIR /go/src/app
COPY . .

RUN go get -d -v ./...
RUN go install -v ./...

WORKDIR /tmp

ENTRYPOINT ["textql"]


================================================
FILE: Dockerfile.alpine
================================================
FROM golang:1.10-alpine3.7 AS build

# "build-base" for gcc
RUN apk update && apk add git && apk add build-base
WORKDIR /go/src/app
COPY . .

RUN go get -d -v ./...
RUN go install -v ./...

FROM alpine:3.7
RUN apk add --update-cache sqlite
COPY --from=build /go/bin/textql /usr/bin
WORKDIR /tmp
ENTRYPOINT ["textql"]



================================================
FILE: LICENSE
================================================
MIT License
-----------

Copyright (c) 2014, Paul Bergeron

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

================================================
FILE: Makefile
================================================
.PHONY: all test clean man godep fast release install

all: textql

textql: test
	go build -ldflags "-X main.VERSION=`cat VERSION` -s" -o ./build/textql ./textql/main.go

fast:
	go build -i -ldflags "-X main.VERSION=`cat VERSION`-dev -s" -o ./build/textql ./textql/main.go

test:
	go test ./...

clean:
	rm -fr ./build

release: textql
	git tag -a `cat VERSION`
	git push origin `cat VERSION`

install: test
	go install -ldflags "-X main.VERSION=`cat VERSION` -s" ./textql/main.go

man:
	ronn man/textql.1.ronn


================================================
FILE: PKGBUILD
================================================
# Maintainer: Aniket-Pradhan aniket17133@iiitd.ac.in
# Owner/Cofntributer: Paul Bergeron https://github.com/dinedal

pkgname=textql-git
pkgver=2.0.3
pkgrel=1
pkgdesc="Execute SQL against structured text like CSV or TSV"
arch=('x86_64' 'i686')
url="https://github.com/dinedal/textql"
license=('MIT')
depends=('go')
makedepends=('git')
options=('!strip' '!emptydirs')
_gourl=github.com/dinedal/textql

build() {
  GOPATH="$srcdir" go get -v -u ${_gourl}/...
}

check() {
  echo $GOPATH
  echo $srcdir
  GOPATH="$GOPATH:$srcdir" go test -v ${_gourl}/...
}

package() {
  mkdir -p "$pkgdir/usr/bin"
  install -p -m755 "$srcdir/bin/"* "$pkgdir/usr/bin"

  mkdir -p "$pkgdir/$GOPATH"
  cp -Rv --preserve=timestamps "$srcdir/"{src,pkg} "$pkgdir/$GOPATH"

  for f in LICENSE COPYING LICENSE.* COPYING.*; do
    if [ -e "$srcdir/src/$_gourl/$f" ]; then
      install -Dm644 "$srcdir/src/$_gourl/$f" \
        "$pkgdir/usr/share/licenses/$pkgname/$f"
    fi
  done
}

# vim:set ts=2 sw=2 et:


================================================
FILE: Readme.md
================================================
# TextQL

[![Build Status](https://travis-ci.org/dinedal/textql.svg)](https://travis-ci.org/dinedal/textql) [![Go Report Card](http://goreportcard.com/badge/dinedal/textql)](http://goreportcard.com/report/dinedal/textql)

Allows you to easily execute SQL against structured text like CSV or TSV.

Example session:

![textql_usage_session](https://raw.github.com/dinedal/textql/master/textql_usage.gif)

## Major changes!

In the time since the initial release of textql, I've made some improvements as well as made the project much more modular. There've also been additional performance tweaks and added functionality, but this comes at the cost of breaking the original command-line flags and changing the install command.

### Changes since v1

Additions:

- Numeric values are automatically recognized in more cases.
- Date / Time / DateTime values are automatically recognized in reasonable formats. See [Time Strings](https://www.sqlite.org/lang_datefunc.html) for a list for accepted formats, and how to convert from other formats.
- Added join support! Multiple files / directories can be loaded by listing them at the end of the command.
- Directories are read by reading each file inside, and this is non-recursive.
- You can list as many files / directories as you like.
- Added flag '-output-file' to save output directly to a file.
- Added flag '-output-dlm' to modify the output delimiter.
- Added "short SQL" syntax.
  - For the case of a single table, the `FROM [table]` can be dropped from the query.
  - For simple selects, the `SELECT` keyword can be dropped from the query.
  - This means the v1 command `textql -sql "select * from tbl" -source some_file.csv` can be shortened to `textql -sql "*" some_file.csv`

Changes:

- The flag '-outputHeader' was renamed to '-output-header'.

Removals:

- Dropped the ability to override table names. This makes less sense after the automatic tablename generation based on filename, joins, and shorter SQL syntax changes.
- Removed '-source', any files / paths at the end of the command are used, as well as piped-in data.

Bug fixes:

- Writing to a directory no longer fails silently.

## Key differences between textql and sqlite importing

- sqlite import will not accept stdin, breaking unix pipes. textql will happily do so.
- textql supports quote-escaped delimiters, sqlite does not.
- textql leverages the sqlite in-memory database feature as much as possible and only touches disk if asked.

## Is it any good?

[Yes](https://news.ycombinator.com/item?id=3067434)

## Requirements

- Go 1.4 or later

## Install

**Latest release on Homebrew (OS X)**

```bash
brew install textql
```

**Build from source**

```bash
go get -u github.com/dinedal/textql/...
```

## Docker

First build the image.

```bash
docker build -t textql .
```

Now use that image mounting your current directory into the container.

```bash
docker run --rm -it -v $(pwd):/tmp textql [rest_of_command]
```

### Alias

You can add the following alias to your system to provide quick access to TextQL:

```bash
alias textql='docker run --rm -it -v $(pwd):/tmp textql '
```

## AUR

**Using an AUR-Helper**

```bash
yaourt textql-git
```

**Building from PKGBUILD**
First clone the repository.
```bash
makepkg -cs
```
Then install the package using pacman or your favorite Package Manager


## Usage

```bash
  textql [-console] [-save-to path path] [-output-file path] [-output-dlm delimter] [-output-header] [-pretty] [-quiet] [-header] [-dlm delimter] [-sql sql_statements] [path ...]

  -console
        After all statements are run, open SQLite3 REPL with this data
  -dlm string
        Input delimiter character between fields -dlm=tab for tab, -dlm=0x## to specify a character code in hex (default ",")
  -header
        Treat input files as having the first row as a header row
  -output-dlm string
        Output delimiter character between fields -output-dlm=tab for tab, -dlm=0x## to specify a character code in hex (default ",")
  -output-file file
        Filename to write output to, if empty no output is written (default "stdout")
  -output-header
        Display column names in output
  -quiet
        Suppress logging
  -pretty
        Pretty print output
  -save-to file
        SQLite3 db is left on disk at this file
  -sql string
        SQL Statement(s) to run on the data
  -version
        Print version and exit
```

## I want stdev, average, other functions

Just follow the install directions at [go-sqlite3-extension-functions](https://github.com/dinedal/go-sqlite3-extension-functions) and textql will automatically load this library.

Full function list:

- Math: acos, asin, atan, atn2, atan2, acosh, asinh, atanh, difference, degrees, radians, cos, sin, tan, cot, cosh, sinh, tanh, coth, exp, log, log10, power, sign, sqrt, square, ceil, floor, pi.
- String: replicate, charindex, leftstr, rightstr, ltrim, rtrim, trim, replace, reverse, proper, padl, padr, padc, strfilter.
- Aggregate: stdev, variance, mode, median, lower_quartile, upper_quartile

## License

New MIT License - Copyright (c) 2015, 2016 Paul Bergeron [http://pauldbergeron.com/](http://pauldbergeron.com/)

See LICENSE for details


================================================
FILE: TODO.txt
================================================
Install is really complex with vitess dep. Find a way to fix it?

~ go get -u github.com/dinedal/textql/...
# github.com/dinedal/textql/vendor/github.com/youtube/vitess/data/test/bson_test
go/src/github.com/dinedal/textql/vendor/github.com/youtube/vitess/data/test/bson_test/input_int.go:7: MyType redeclared in this block
    previous declaration at go/src/github.com/dinedal/textql/vendor/github.com/youtube/vitess/data/test/bson_test/input_custom.go:7
go/src/github.com/dinedal/textql/vendor/github.com/youtube/vitess/data/test/bson_test/input_map.go:7: MyType redeclared in this block
    previous declaration at go/src/github.com/dinedal/textql/vendor/github.com/youtube/vitess/data/test/bson_test/input_int.go:7
go/src/github.com/dinedal/textql/vendor/github.com/youtube/vitess/data/test/bson_test/input_mixed.go:11: MyType redeclared in this block
    previous declaration at go/src/github.com/dinedal/textql/vendor/github.com/youtube/vitess/data/test/bson_test/input_map.go:7
go/src/github.com/dinedal/textql/vendor/github.com/youtube/vitess/data/test/bson_test/input_private.go:7: MyType redeclared in this block
    previous declaration at go/src/github.com/dinedal/textql/vendor/github.com/youtube/vitess/data/test/bson_test/input_mixed.go:11
go/src/github.com/dinedal/textql/vendor/github.com/youtube/vitess/data/test/bson_test/input_ptr.go:7: MyType redeclared in this block
    previous declaration at go/src/github.com/dinedal/textql/vendor/github.com/youtube/vitess/data/test/bson_test/input_private.go:7
go/src/github.com/dinedal/textql/vendor/github.com/youtube/vitess/data/test/bson_test/input_simple.go:9: MyType redeclared in this block
    previous declaration at go/src/github.com/dinedal/textql/vendor/github.com/youtube/vitess/data/test/bson_test/input_ptr.go:7
go/src/github.com/dinedal/textql/vendor/github.com/youtube/vitess/data/test/bson_test/input_slice.go:7: MyType redeclared in this block
    previous declaration at go/src/github.com/dinedal/textql/vendor/github.com/youtube/vitess/data/test/bson_test/input_simple.go:9
go/src/github.com/dinedal/textql/vendor/github.com/youtube/vitess/data/test/bson_test/input_tag.go:7: MyType redeclared in this block
    previous declaration at go/src/github.com/dinedal/textql/vendor/github.com/youtube/vitess/data/test/bson_test/input_slice.go:7
go/src/github.com/dinedal/textql/vendor/github.com/youtube/vitess/data/test/bson_test/output_int.go:29: (*MyType).UnmarshalBson redeclared in this block
    previous declaration at go/src/github.com/dinedal/textql/vendor/github.com/youtube/vitess/data/test/bson_test/output_custom.go:42
go/src/github.com/dinedal/textql/vendor/github.com/youtube/vitess/data/test/bson_test/output_map.go:18: (*MyType).MarshalBson redeclared in this block
    previous declaration at go/src/github.com/dinedal/textql/vendor/github.com/youtube/vitess/data/test/bson_test/output_custom.go:19
go/src/github.com/dinedal/textql/vendor/github.com/youtube/vitess/data/test/bson_test/output_map.go:18: too many errors
# pkg-config --cflags gomysql
Package gomysql was not found in the pkg-config search path.
Perhaps you should add the directory containing `gomysql.pc'
to the PKG_CONFIG_PATH environment variable
No package 'gomysql' found
pkg-config: exit status 1
# launchpad.net/gozk/zookeeper
go/src/launchpad.net/gozk/zookeeper/zk.go:15:10: fatal error: 'zookeeper.h' file not found
#include <zookeeper.h>
         ^
1 error generated.
# github.com/youtube/vitess/go/stats/influxdbbackend
go/src/github.com/youtube/vitess/go/stats/influxdbbackend/influxdb_backend.go:40: undefined: client.ClientConfig
go/src/github.com/youtube/vitess/go/stats/influxdbbackend/influxdb_backend.go:60: undefined: client.Series
go/src/github.com/youtube/vitess/go/stats/influxdbbackend/influxdb_backend.go:62: undefined: client.Series
go/src/github.com/youtube/vitess/go/stats/influxdbbackend/influxdb_backend.go:73: backend.client.WriteSeries undefined (type *client.Client has no field or method WriteSeries)
# github.com/youtube/vitess/go/terminal
go/src/github.com/youtube/vitess/go/terminal/tty.go:16: undefined: syscall.TCGETS
# pkg-config --cflags gomysql
Package gomysql was not found in the pkg-config search path.
Perhaps you should add the directory containing `gomysql.pc'
to the PKG_CONFIG_PATH environment variable
No package 'gomysql' found
pkg-config: exit status 1
# github.com/dinedal/textql/vendor/github.com/youtube/vitess/go/stats/influxdbbackend
go/src/github.com/dinedal/textql/vendor/github.com/youtube/vitess/go/stats/influxdbbackend/influxdb_backend.go:40: undefined: client.ClientConfig
go/src/github.com/dinedal/textql/vendor/github.com/youtube/vitess/go/stats/influxdbbackend/influxdb_backend.go:60: undefined: client.Series
go/src/github.com/dinedal/textql/vendor/github.com/youtube/vitess/go/stats/influxdbbackend/influxdb_backend.go:62: undefined: client.Series
go/src/github.com/dinedal/textql/vendor/github.com/youtube/vitess/go/stats/influxdbbackend/influxdb_backend.go:73: backend.client.WriteSeries undefined (type *client.Client has no field or method WriteSeries)
# github.com/dinedal/textql/vendor/github.com/youtube/vitess/go/terminal
go/src/github.com/dinedal/textql/vendor/github.com/youtube/vitess/go/terminal/tty.go:16: undefined: syscall.TCGETS
# github.com/dinedal/textql/vendor/github.com/youtube/vitess/third_party/go/launchpad.net/gozk/zookeeper
go/src/github.com/dinedal/textql/vendor/github.com/youtube/vitess/third_party/go/launchpad.net/gozk/zookeeper/zk.go:15:10: fatal error: 'zookeeper.h' file not found
#include <zookeeper.h>
         ^
1 error generated.



Fix all the below:


Gofmt formats Go programs. We run gofmt -s on your code, where -s is for the "simplify" command

/github.com/dinedal/textql/outputs/csv.go
/github.com/dinedal/textql/storage/sqlite_test.go

Gocyclo calculates cyclomatic complexities of functions in Go source code. The cyclomatic complexity of a function is calculated according to the following rules: 1 is the base complexity of a function +1 for each 'if', 'for', 'case', '&&' or '||'

/github.com/dinedal/textql/cmd/textql.go
Line 106: 24 main main repos/src/github.com/dinedal/textql/cmd/textql.go:106:1
/github.com/dinedal/textql/sqlparser/parsed_query.go
Line 53: 18 sqlparser EncodeValue repos/src/github.com/dinedal/textql/sqlparser/parsed_query.go:53:1
/github.com/dinedal/textql/sqlparser/sql.go
/github.com/dinedal/textql/sqlparser/token.go
Line 141: 31 sqlparser (*Tokenizer).Scan repos/src/github.com/dinedal/textql/sqlparser/token.go:141:1
Line 297: 16 sqlparser (*Tokenizer).scanNumber repos/src/github.com/dinedal/textql/sqlparser/token.go:297:1
/github.com/dinedal/textql/sqlparser/tracked_buffer.go
Line 40: 18 sqlparser (*TrackedBuffer).Myprintf repos/src/github.com/dinedal/textql/sqlparser/tracked_buffer.go:40:1
gofmt
89%
golint
10%
Golint is a linter for Go source code.

/github.com/dinedal/textql/cmd/textql.go
Line 18: exported type CommandLineOptions should have comment or be unexported
Line 32: exported var VERSION should have comment or be unexported
Line 34: exported function NewCommandLineOptions should have comment or be unexported
Line 52: exported method CommandLineOptions.GetCommands should have comment or be unexported
Line 52: receiver name should be a reflection of its identity; don't use generic names such as "me", "this", or "self"
Line 56: exported method CommandLineOptions.GetSourceFiles should have comment or be unexported
Line 56: receiver name should be a reflection of its identity; don't use generic names such as "me", "this", or "self"
Line 60: exported method CommandLineOptions.GetDelimiter should have comment or be unexported
Line 60: receiver name should be a reflection of its identity; don't use generic names such as "me", "this", or "self"
Line 64: exported method CommandLineOptions.GetHeader should have comment or be unexported
Line 64: receiver name should be a reflection of its identity; don't use generic names such as "me", "this", or "self"
Line 68: exported method CommandLineOptions.GetOutputHeader should have comment or be unexported
Line 68: receiver name should be a reflection of its identity; don't use generic names such as "me", "this", or "self"
Line 72: exported method CommandLineOptions.GetOutputDelimiter should have comment or be unexported
Line 72: receiver name should be a reflection of its identity; don't use generic names such as "me", "this", or "self"
Line 76: exported method CommandLineOptions.GetOutputFile should have comment or be unexported
Line 76: receiver name should be a reflection of its identity; don't use generic names such as "me", "this", or "self"
Line 80: exported method CommandLineOptions.GetSaveTo should have comment or be unexported
Line 80: receiver name should be a reflection of its identity; don't use generic names such as "me", "this", or "self"
Line 84: exported method CommandLineOptions.GetConsole should have comment or be unexported
Line 84: receiver name should be a reflection of its identity; don't use generic names such as "me", "this", or "self"
Line 88: exported method CommandLineOptions.GetVersion should have comment or be unexported
Line 88: receiver name should be a reflection of its identity; don't use generic names such as "me", "this", or "self"
Line 92: exported method CommandLineOptions.GetQuiet should have comment or be unexported
Line 92: receiver name should be a reflection of its identity; don't use generic names such as "me", "this", or "self"
Line 96: exported method CommandLineOptions.Usage should have comment or be unexported
Line 96: receiver name should be a reflection of its identity; don't use generic names such as "me", "this", or "self"
Line 133: can probably use "var inputSources []string" instead
/github.com/dinedal/textql/inputs/csv.go
Line 21: exported type CSVInputOptions should have comment or be unexported
Line 27: exported function NewCSVInput should have comment or be unexported
Line 27: exported func NewCSVInput returns unexported type *inputs.csvInput, which can be annoying to use
Line 49: receiver name should be a reflection of its identity; don't use generic names such as "me", "this", or "self"
Line 53: receiver name should be a reflection of its identity; don't use generic names such as "me", "this", or "self"
Line 57: receiver name should be a reflection of its identity; don't use generic names such as "me", "this", or "self"
Line 84: receiver name should be a reflection of its identity; don't use generic names such as "me", "this", or "self"
Line 106: receiver name should be a reflection of its identity; don't use generic names such as "me", "this", or "self"
/github.com/dinedal/textql/inputs/input.go
Line 3: exported type Input should have comment or be unexported
/github.com/dinedal/textql/outputs/csv.go
Line 18: exported type CSVOutputOptions should have comment or be unexported
Line 24: exported function NewCSVOutput should have comment or be unexported
Line 24: exported func NewCSVOutput returns unexported type *outputs.csvOutput, which can be annoying to use
Line 35: receiver name should be a reflection of its identity; don't use generic names such as "me", "this", or "self"
Line 53: should omit 2nd value from range; this loop is equivalent to `for i := range ...`
/github.com/dinedal/textql/outputs/output.go
Line 5: exported type Output should have comment or be unexported
/github.com/dinedal/textql/sqlparser/analyzer.go
Line 50: comment on exported function HasINClause should be of the form "HasINClause ..."
/github.com/dinedal/textql/sqlparser/ast.go
Line 56: exported method Union.IStatement should have comment or be unexported
Line 57: exported method Select.IStatement should have comment or be unexported
Line 58: exported method Insert.IStatement should have comment or be unexported
Line 59: exported method Update.IStatement should have comment or be unexported
Line 60: exported method Delete.IStatement should have comment or be unexported
Line 61: exported method Set.IStatement should have comment or be unexported
Line 62: exported method DDL.IStatement should have comment or be unexported
Line 63: exported method Other.IStatement should have comment or be unexported
Line 73: exported method Select.ISelectStatement should have comment or be unexported
Line 74: exported method Union.ISelectStatement should have comment or be unexported
Line 92: don't use ALL_CAPS in Go names; use CamelCase
Line 97: don't use ALL_CAPS in Go names; use CamelCase
Line 98: don't use ALL_CAPS in Go names; use CamelCase
Line 101: exported method Select.Format should have comment or be unexported
Line 117: don't use ALL_CAPS in Go names; use CamelCase
Line 118: don't use ALL_CAPS in Go names; use CamelCase
Line 119: don't use ALL_CAPS in Go names; use CamelCase
Line 120: don't use ALL_CAPS in Go names; use CamelCase
Line 121: don't use ALL_CAPS in Go names; use CamelCase
Line 124: exported method Union.Format should have comment or be unexported
Line 137: exported method Insert.Format should have comment or be unexported
Line 149: exported method Select.IInsertRows should have comment or be unexported
Line 150: exported method Union.IInsertRows should have comment or be unexported
Line 151: exported method Values.IInsertRows should have comment or be unexported
Line 163: exported method Update.Format should have comment or be unexported
Line 178: exported method Delete.Format should have comment or be unexported
Line 190: exported method Set.Format should have comment or be unexported
Line 204: don't use ALL_CAPS in Go names; use CamelCase
Line 204: exported const AST_CREATE should have comment (or a comment on this block) or be unexported
Line 205: don't use ALL_CAPS in Go names; use CamelCase
Line 206: don't use ALL_CAPS in Go names; use CamelCase
Line 207: don't use ALL_CAPS in Go names; use CamelCase
Line 210: exported method DDL.Format should have comment or be unexported
Line 226: exported method Other.Format should have comment or be unexported
Line 233: exported method Comments.Format should have comment or be unexported
Line 242: exported method SelectExprs.Format should have comment or be unexported
Line 256: exported method StarExpr.ISelectExpr should have comment or be unexported
Line 257: exported method NonStarExpr.ISelectExpr should have comment or be unexported
Line 264: exported method StarExpr.Format should have comment or be unexported
Line 277: exported method NonStarExpr.Format should have comment or be unexported
Line 290: exported method Columns.Format should have comment or be unexported
Line 300: exported method TableExprs.Format should have comment or be unexported
Line 314: exported method AliasedTableExpr.ITableExpr should have comment or be unexported
Line 315: exported method ParenTableExpr.ITableExpr should have comment or be unexported
Line 316: exported method JoinTableExpr.ITableExpr should have comment or be unexported
Line 326: exported method AliasedTableExpr.Format should have comment or be unexported
Line 343: exported method TableName.ISimpleTableExpr should have comment or be unexported
Line 344: exported method Subquery.ISimpleTableExpr should have comment or be unexported
Line 351: exported method TableName.Format should have comment or be unexported
Line 364: exported method ParenTableExpr.Format should have comment or be unexported
Line 378: don't use ALL_CAPS in Go names; use CamelCase
Line 379: don't use ALL_CAPS in Go names; use CamelCase
Line 380: don't use ALL_CAPS in Go names; use CamelCase
Line 381: don't use ALL_CAPS in Go names; use CamelCase
Line 382: don't use ALL_CAPS in Go names; use CamelCase
Line 383: don't use ALL_CAPS in Go names; use CamelCase
Line 386: exported method JoinTableExpr.Format should have comment or be unexported
Line 400: don't use ALL_CAPS in Go names; use CamelCase
Line 400: exported const AST_USE should have comment (or a comment on this block) or be unexported
Line 401: don't use ALL_CAPS in Go names; use CamelCase
Line 402: don't use ALL_CAPS in Go names; use CamelCase
Line 405: exported method IndexHints.Format should have comment or be unexported
Line 423: don't use ALL_CAPS in Go names; use CamelCase
Line 424: don't use ALL_CAPS in Go names; use CamelCase
Line 436: exported method Where.Format should have comment or be unexported
Line 451: don't use ALL_CAPS in Go names; use CamelCase
Line 463: exported method From.Format should have comment or be unexported
Line 476: exported method AndExpr.IExpr should have comment or be unexported
Line 477: exported method OrExpr.IExpr should have comment or be unexported
Line 478: exported method NotExpr.IExpr should have comment or be unexported
Line 479: exported method ParenBoolExpr.IExpr should have comment or be unexported
Line 480: exported method ComparisonExpr.IExpr should have comment or be unexported
Line 481: exported method RangeCond.IExpr should have comment or be unexported
Line 482: exported method NullCheck.IExpr should have comment or be unexported
Line 483: exported method ExistsExpr.IExpr should have comment or be unexported
Line 484: exported method KeyrangeExpr.IExpr should have comment or be unexported
Line 485: exported method StrVal.IExpr should have comment or be unexported
Line 486: exported method NumVal.IExpr should have comment or be unexported
Line 487: exported method ValArg.IExpr should have comment or be unexported
Line 488: exported method NullVal.IExpr should have comment or be unexported
Line 489: exported method ColName.IExpr should have comment or be unexported
Line 490: exported method ValTuple.IExpr should have comment or be unexported
Line 491: exported method Subquery.IExpr should have comment or be unexported
Line 492: exported method ListArg.IExpr should have comment or be unexported
Line 493: exported method BinaryExpr.IExpr should have comment or be unexported
Line 494: exported method UnaryExpr.IExpr should have comment or be unexported
Line 495: exported method FuncExpr.IExpr should have comment or be unexported
Line 496: exported method CaseExpr.IExpr should have comment or be unexported
Line 504: exported method AndExpr.IBoolExpr should have comment or be unexported
Line 505: exported method OrExpr.IBoolExpr should have comment or be unexported
Line 506: exported method NotExpr.IBoolExpr should have comment or be unexported
Line 507: exported method ParenBoolExpr.IBoolExpr should have comment or be unexported
Line 508: exported method ComparisonExpr.IBoolExpr should have comment or be unexported
Line 509: exported method RangeCond.IBoolExpr should have comment or be unexported
Line 510: exported method NullCheck.IBoolExpr should have comment or be unexported
Line 511: exported method ExistsExpr.IBoolExpr should have comment or be unexported
Line 512: exported method KeyrangeExpr.IBoolExpr should have comment or be unexported
Line 519: exported method AndExpr.Format should have comment or be unexported
Line 528: exported method OrExpr.Format should have comment or be unexported
Line 537: exported method NotExpr.Format should have comment or be unexported
Line 546: exported method ParenBoolExpr.Format should have comment or be unexported
Line 558: don't use ALL_CAPS in Go names; use CamelCase
Line 559: don't use ALL_CAPS in Go names; use CamelCase
Line 560: don't use ALL_CAPS in Go names; use CamelCase
Line 561: don't use ALL_CAPS in Go names; use CamelCase
Line 562: don't use ALL_CAPS in Go names; use CamelCase
Line 563: don't use ALL_CAPS in Go names; use CamelCase
Line 564: don't use ALL_CAPS in Go names; use CamelCase
Line 565: don't use ALL_CAPS in Go names; use CamelCase
Line 566: don't use ALL_CAPS in Go names; use CamelCase
Line 567: don't use ALL_CAPS in Go names; use CamelCase
Line 568: don't use ALL_CAPS in Go names; use CamelCase
Line 571: exported method ComparisonExpr.Format should have comment or be unexported
Line 584: don't use ALL_CAPS in Go names; use CamelCase
Line 585: don't use ALL_CAPS in Go names; use CamelCase
Line 588: exported method RangeCond.Format should have comment or be unexported
Line 600: don't use ALL_CAPS in Go names; use CamelCase
Line 601: don't use ALL_CAPS in Go names; use CamelCase
Line 604: exported method NullCheck.Format should have comment or be unexported
Line 613: exported method ExistsExpr.Format should have comment or be unexported
Line 622: exported method KeyrangeExpr.Format should have comment or be unexported
Line 632: exported method StrVal.IValExpr should have comment or be unexported
Line 633: exported method NumVal.IValExpr should have comment or be unexported
Line 634: exported method ValArg.IValExpr should have comment or be unexported
Line 635: exported method NullVal.IValExpr should have comment or be unexported
Line 636: exported method ColName.IValExpr should have comment or be unexported
Line 637: exported method ValTuple.IValExpr should have comment or be unexported
Line 638: exported method Subquery.IValExpr should have comment or be unexported
Line 639: exported method ListArg.IValExpr should have comment or be unexported
Line 640: exported method BinaryExpr.IValExpr should have comment or be unexported
Line 641: exported method UnaryExpr.IValExpr should have comment or be unexported
Line 642: exported method FuncExpr.IValExpr should have comment or be unexported
Line 643: exported method CaseExpr.IValExpr should have comment or be unexported
Line 648: exported method StrVal.Format should have comment or be unexported
Line 656: exported method NumVal.Format should have comment or be unexported
Line 663: exported method ValArg.Format should have comment or be unexported
Line 670: exported method NullVal.Format should have comment or be unexported
Line 679: exported method ColName.Format should have comment or be unexported
Line 702: exported method ValTuple.IColTuple should have comment or be unexported
Line 703: exported method Subquery.IColTuple should have comment or be unexported
Line 704: exported method ListArg.IColTuple should have comment or be unexported
Line 709: exported method ValTuple.Format should have comment or be unexported
Line 717: exported method ValExprs.Format should have comment or be unexported
Line 730: exported method Subquery.Format should have comment or be unexported
Line 737: exported method ListArg.Format should have comment or be unexported
Line 749: don't use ALL_CAPS in Go names; use CamelCase
Line 750: don't use ALL_CAPS in Go names; use CamelCase
Line 751: don't use ALL_CAPS in Go names; use CamelCase
Line 752: don't use ALL_CAPS in Go names; use CamelCase
Line 753: don't use ALL_CAPS in Go names; use CamelCase
Line 754: don't use ALL_CAPS in Go names; use CamelCase
Line 755: don't use ALL_CAPS in Go names; use CamelCase
Line 756: don't use ALL_CAPS in Go names; use CamelCase
Line 759: exported method BinaryExpr.Format should have comment or be unexported
Line 771: don't use ALL_CAPS in Go names; use CamelCase
Line 772: don't use ALL_CAPS in Go names; use CamelCase
Line 773: don't use ALL_CAPS in Go names; use CamelCase
Line 776: exported method UnaryExpr.Format should have comment or be unexported
Line 787: exported method FuncExpr.Format should have comment or be unexported
Line 815: exported method FuncExpr.IsAggregate should have comment or be unexported
Line 826: exported method CaseExpr.Format should have comment or be unexported
Line 846: exported method When.Format should have comment or be unexported
Line 853: exported method GroupBy.Format should have comment or be unexported
Line 864: exported method OrderBy.Format should have comment or be unexported
Line 880: don't use ALL_CAPS in Go names; use CamelCase
Line 881: don't use ALL_CAPS in Go names; use CamelCase
Line 884: exported method Order.Format should have comment or be unexported
Line 893: exported method Limit.Format should have comment or be unexported
Line 950: exported method Values.Format should have comment or be unexported
Line 964: exported method ValTuple.IRowTuple should have comment or be unexported
Line 965: exported method Subquery.IRowTuple should have comment or be unexported
Line 970: exported method UpdateExprs.Format should have comment or be unexported
Line 984: exported method UpdateExpr.Format should have comment or be unexported
Line 991: exported method OnDup.Format should have comment or be unexported
/github.com/dinedal/textql/sqlparser/parsed_query.go
Line 20: exported type ParsedQuery should have comment or be unexported
Line 25: exported type EncoderFunc should have comment or be unexported
Line 27: exported method ParsedQuery.GenerateQuery should have comment or be unexported
Line 49: exported method ParsedQuery.MarshalJSON should have comment or be unexported
Line 53: exported function EncodeValue should have comment or be unexported
Line 102: exported type TupleEqualityList should have comment or be unexported
Line 107: exported method TupleEqualityList.Encode should have comment or be unexported
Line 156: exported function FetchBindVar should have comment or be unexported
/github.com/dinedal/textql/sqlparser/sql.go
/github.com/dinedal/textql/sqlparser/token.go
Line 15: exported const EOFCHAR should have comment or be unexported
Line 172: if block ends with a return statement, so drop this else and outdent its block
Line 190: if block ends with a return statement, so drop this else and outdent its block
Line 214: if block ends with a return statement, so drop this else and outdent its block
Line 221: if block ends with a return statement, so drop this else and outdent its block
Line 249: var keywordId should be keywordID
Line 417: exported method Tokenizer.ConsumeNext should have comment or be unexported
/github.com/dinedal/textql/sqlparser/tracked_buffer.go
Line 25: exported function NewTrackedBuffer should have comment or be unexported
Line 101: exported method TrackedBuffer.ParsedQuery should have comment or be unexported
Line 105: exported method TrackedBuffer.HasBindVars should have comment or be unexported
/github.com/dinedal/textql/storage/sqlite.go
Line 20: struct field connId should be connID
Line 24: exported type SQLite3Options should have comment or be unexported
Line 27: should omit type []*sqlite3.SQLiteConn from declaration of var sqlite3conn; it will be inferred from the right-hand side
Line 28: should omit type *regexp.Regexp from declaration of var allWhiteSpace; it will be inferred from the right-hand side
Line 29: should omit type *regexp.Regexp from declaration of var tableNameCheckRegEx; it will be inferred from the right-hand side
Line 42: exported function NewSQLite3Storage should have comment or be unexported
Line 42: exported func NewSQLite3Storage returns unexported type *storage.sqlite3Storage, which can be annoying to use
Line 52: receiver name should be a reflection of its identity; don't use generic names such as "me", "this", or "self"
Line 69: receiver name should be a reflection of its identity; don't use generic names such as "me", "this", or "self"
Line 97: receiver name should be a reflection of its identity; don't use generic names such as "me", "this", or "self"
Line 135: receiver name should be a reflection of its identity; don't use generic names such as "me", "this", or "self"
Line 160: receiver name should be a reflection of its identity; don't use generic names such as "me", "this", or "self"
Line 165: can probably use "var vals []interface{}" instead
Line 184: receiver name should be a reflection of its identity; don't use generic names such as "me", "this", or "self"
Line 199: receiver name should be a reflection of its identity; don't use generic names such as "me", "this", or "self"
Line 207: var backupConnId should be backupConnID
Line 234: receiver name should be a reflection of its identity; don't use generic names such as "me", "this", or "self"
/github.com/dinedal/textql/storage/sqlite_test.go
Line 188: should omit 2nd value from range; this loop is equivalent to `for i := range ...`
/github.com/dinedal/textql/storage/storage.go
Line 9: exported type Storage should have comment or be unexported
/github.com/dinedal/textql/test_util/test_util.go
Line 1: don't use an underscore in package name
Line 8: exported function OpenFileFromString should have comment or be unexported
/github.com/dinedal/textql/util/file_helpers.go
Line 12: exported function IsPathDir should have comment or be unexported
Line 30: exported function OpenFileOrStdDev should have comment or be unexported
Line 65: exported function CleanPath should have comment or be unexported
Line 94: exported function RewindFile should have comment or be unexported
Line 102: exported function IsThereDataOnStdin should have comment or be unexported
Line 111: if block ends with a return statement, so drop this else and outdent its block
Line 116: exported function AllFilesInDirectory should have comment or be unexported
Line 119: can probably use "var result []string" instead
/github.com/dinedal/textql/util/seperator_helpers.go
Line 10: exported function DetermineSeparator should have comment or be unexported


================================================
FILE: VERSION
================================================
2.0.3


================================================
FILE: go.mod
================================================
module github.com/dinedal/textql

go 1.13

require (
	github.com/mattn/go-runewidth v0.0.2 // indirect
	github.com/mattn/go-sqlite3 v2.0.3+incompatible
	github.com/olekukonko/tablewriter v0.0.0-20180506121414-d4647c9c7a84
)


================================================
FILE: go.sum
================================================
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712 h1:aaQcKT9WumO6JEJcRyTqFVq4XUZiUcKR2/GI31TOcz8=
github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mattn/go-runewidth v0.0.2 h1:UnlwIPBGaTZfPQ6T1IGzPI0EkYAQmT9fAEJ/poFC63o=
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-sqlite3 v1.9.0 h1:pDRiWfl+++eC2FEFRy6jXmQlvp4Yh3z1MJKg4UeYM/4=
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U=
github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/olekukonko/tablewriter v0.0.0-20180506121414-d4647c9c7a84 h1:fiKJgB4JDUd43CApkmCeTSQlWjtTtABrU2qsgbuP0BI=
github.com/olekukonko/tablewriter v0.0.0-20180506121414-d4647c9c7a84/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446 h1:/NRJ5vAYoqz+7sG51ubIDHXeWO8DlTSrToPu6q11ziA=
github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
gitlab.com/cznic/ebnf2y v1.0.0/go.mod h1:jx14dqOldV2pRvSi8HASTB/k5fkIv2TwjYAp5py0MTs=
gitlab.com/cznic/golex v1.0.0/go.mod h1:vkWdDgqbbThjRHoOLU7yNPgMxaubAkwnvF/4zeG8cvU=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/exp v0.0.0-20190411193353-0480eff6dd7c/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee h1:WG0RUwxtNT4qqaXX3DPA8zHFNm/D9xaBpxzHt1WcA/E=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20200130224948-02f1738cbe39 h1:5ERHXLQfA0b8cHOwaOfWaaGekrA4+Ka/N74zilLnsIk=
golang.org/x/tools v0.0.0-20200130224948-02f1738cbe39/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200131211209-ecb101ed6550 h1:3Kc3/T5DQ/majKzDmb+0NzmbXFhKLaeDTp3KqVPV5Eo=
golang.org/x/tools/gopls v0.3.0 h1:l9KKK1/n6CIbfgaUvHBWAvCfOxcl1N+KSOK79OlPIao=
golang.org/x/tools/gopls v0.3.0/go.mod h1:vvBkm7WBjHNudDeK7Sg7HeR+sKt6yp5TD/4NQaTZzRs=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbOeHJjicWYPqR9bpxqxYG2pA=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
modernc.org/b v1.0.0 h1:vpvqeyp17ddcQWF29Czawql4lDdABCDRbXRAS4+aF2o=
modernc.org/b v1.0.0/go.mod h1:uZWcZfRj1BpYzfN9JTerzlNUnnPsV9O2ZA8JsRcubNg=
modernc.org/db v1.0.0 h1:2c6NdCfaLnshSvY7OU09cyAY0gYXUZj4lmg5ItHyucg=
modernc.org/db v1.0.0/go.mod h1:kYD/cO29L/29RM0hXYl4i3+Q5VojL31kTUVpVJDw0s8=
modernc.org/ebnfutil v1.0.0/go.mod h1:+2n/OnQXoild9pzrPa/2wmVtR+ufWjB/0fYkc0BV9sc=
modernc.org/file v1.0.0 h1:9/PdvjVxd5+LcWUQIfapAWRGOkDLK90rloa8s/au06A=
modernc.org/file v1.0.0/go.mod h1:uqEokAEn1u6e+J45e54dsEA/pw4o7zLrA2GwyntZzjw=
modernc.org/fileutil v1.0.0 h1:Z1AFLZwl6BO8A5NldQg/xTSjGLetp+1Ubvl4alfGx8w=
modernc.org/fileutil v1.0.0/go.mod h1:JHsWpkrk/CnVV1H/eGlFf85BEpfkrp56ro8nojIq9Q8=
modernc.org/golex v1.0.0 h1:wWpDlbK8ejRfSyi0frMyhilD3JBvtcx2AdGDnU+JtsE=
modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk=
modernc.org/internal v1.0.0 h1:XMDsFDcBDsibbBnHB2xzljZ+B1yrOVLEFkKL2u15Glw=
modernc.org/internal v1.0.0/go.mod h1:VUD/+JAkhCpvkUitlEOnhpVxCgsBI90oTzSCRcqQVSM=
modernc.org/lex v1.0.0/go.mod h1:G6rxMTy3cH2iA0iXL/HRRv4Znu8MK4higxph/lE7ypk=
modernc.org/lexer v1.0.0/go.mod h1:F/Dld0YKYdZCLQ7bD0USbWL4YKCyTDRDHiDTOs0q0vk=
modernc.org/lldb v1.0.0 h1:6vjDJxQEfhlOLwl4bhpwIz00uyFK4EmSYcbwqwbynsc=
modernc.org/lldb v1.0.0/go.mod h1:jcRvJGWfCGodDZz8BPwiKMJxGJngQ/5DrRapkQnLob8=
modernc.org/mathutil v1.0.0 h1:93vKjrJopTPrtTNpZ8XIovER7iCIH1QU7wNbOQXC60I=
modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k=
modernc.org/ql v1.0.1 h1:pwGOhUbl75KRiGEUUotORpnBlI0whDEb/koIqZOGI7k=
modernc.org/ql v1.0.1/go.mod h1:Fj1ylcVyzcu/fgWZTrvBO9j/aEUg/ixLFnGtmzh7quI=
modernc.org/sortutil v1.0.0 h1:SUTM1sCR0Ldpv7dbB/KCPC2zHHsZ1KrSkhmGmmV22CQ=
modernc.org/sortutil v1.0.0/go.mod h1:1QO0q8IlIlmjBIwm6t/7sof874+xCfZouyqZMLIAtxM=
modernc.org/strutil v1.0.0 h1:XVFtQwFVwc02Wk+0L/Z/zDDXO81r5Lhe6iMKmGX3KhE=
modernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs=
modernc.org/zappy v1.0.0 h1:dPVaP+3ueIUv4guk8PuZ2wiUGcJ1WUVvIheeSSTD0yk=
modernc.org/zappy v1.0.0/go.mod h1:hHe+oGahLVII/aTTyWK/b53VDHMAGCBYYeZ9sn83HC4=
mvdan.cc/xurls/v2 v2.1.0 h1:KaMb5GLhlcSX+e+qhbRJODnUUBvlw01jt4yrjFIHAuA=
mvdan.cc/xurls/v2 v2.1.0/go.mod h1:5GrSd9rOnKOpZaji1OZLYL/yeAAtGDlo/cFe+8K5n8E=


================================================
FILE: inputs/csv.go
================================================
package inputs

import (
	"encoding/csv"
	"io"
	"log"
	"os"
	"path/filepath"
	"strconv"
)

// CSVInput represents a record producing input from a CSV formatted file or pipe.
type CSVInput struct {
	options         *CSVInputOptions
	reader          *csv.Reader
	firstRow        []string
	header          []string
	minOutputLength int
	name            string
}

// CSVInputOptions options are passed to the underlying encoding/csv reader.
type CSVInputOptions struct {
	// HasHeader when true, will treat the first row as a header row.
	HasHeader bool
	// Separator is the rune that fields are delimited by.
	Separator rune
	// ReadFrom is where the data will be read from.
	ReadFrom io.Reader
}

// NewCSVInput sets up a new CSVInput, the first row is read when this is run.
// If there is a problem with reading the first row, the error is returned.
// Otherwise, the returned csvInput can be reliably consumed with ReadRecord()
// until ReadRecord() returns nil.
func NewCSVInput(opts *CSVInputOptions) (*CSVInput, error) {
	csvInput := &CSVInput{
		options: opts,
		reader:  csv.NewReader(opts.ReadFrom),
	}
	csvInput.firstRow = nil

	csvInput.reader.FieldsPerRecord = -1
	csvInput.reader.Comma = csvInput.options.Separator
	csvInput.reader.LazyQuotes = true

	headerErr := csvInput.readHeader()

	if headerErr != nil {
		return nil, headerErr
	}

	if asFile, ok := csvInput.options.ReadFrom.(*os.File); ok {
		csvInput.name = filepath.Base(asFile.Name())
	} else {
		csvInput.name = "pipe"
	}

	return csvInput, nil
}

// Name returns the name of the CSV being read.
// By default, either the base filename or 'pipe' if it is a unix pipe
func (csvInput *CSVInput) Name() string {
	return csvInput.name
}

// SetName overrides the name of the CSV
func (csvInput *CSVInput) SetName(name string) {
	csvInput.name = name
}

// ReadRecord reads a single record from the CSV. Always returns successfully.
// If the record is empty, an empty []string is returned.
// Record expand to match the current row size, adding blank fields as needed.
// Records never return less then the number of fields in the first row.
// Returns nil on EOF
// In the event of a parse error due to an invalid record, it is logged, and
// an empty []string is returned with the number of fields in the first row,
// as if the record were empty.
//
// In general, this is a very tolerant of problems CSV reader.
func (csvInput *CSVInput) ReadRecord() []string {
	var row []string
	var fileErr error

	if csvInput.firstRow != nil {
		row = csvInput.firstRow
		csvInput.firstRow = nil
		return row
	}

	row, fileErr = csvInput.reader.Read()
	emptysToAppend := csvInput.minOutputLength - len(row)
	if fileErr == io.EOF {
		return nil
	} else if parseErr, ok := fileErr.(*csv.ParseError); ok {
		log.Println(parseErr)
		emptysToAppend = csvInput.minOutputLength
	}

	if emptysToAppend > 0 {
		for counter := 0; counter < emptysToAppend; counter++ {
			row = append(row, "")
		}
	}

	return row
}

func (csvInput *CSVInput) readHeader() error {
	var readErr error

	csvInput.firstRow, readErr = csvInput.reader.Read()

	if readErr != nil {
		log.Fatalln(readErr)
		return readErr
	}

	csvInput.minOutputLength = len(csvInput.firstRow)

	if csvInput.options.HasHeader {
		csvInput.header = csvInput.firstRow
		csvInput.firstRow = nil
	} else {
		csvInput.header = make([]string, csvInput.minOutputLength)
		for i := 0; i < len(csvInput.firstRow); i++ {
			csvInput.header[i] = "c" + strconv.Itoa(i)
		}
	}

	return nil
}

// Header returns the header of the csvInput. Either the first row if a header
// set in the options, or c#, where # is the column number, starting with 0.
func (csvInput *CSVInput) Header() []string {
	return csvInput.header
}


================================================
FILE: inputs/csv_test.go
================================================
package inputs

import (
	"os"
	"strings"

	"reflect"
	"testing"

	"github.com/dinedal/textql/test_util"
)

var (
	simple = `a,b,c
1,2,3
4,5,6`

	bad = `a,b,c
1,2,
4,5,6
7,8


9,,10
11,12,13,14
"foo,bar","boo,\"far",","
'foo,bar','"','"'
"test
",multi-line
`
)

func TestCSVInputFakesHeader(t *testing.T) {
	fp := test_util.OpenFileFromString(simple)
	defer fp.Close()
	defer os.Remove(fp.Name())

	opts := &CSVInputOptions{
		HasHeader: false,
		Separator: ',',
		ReadFrom:  fp,
	}

	input, _ := NewCSVInput(opts)
	expected := []string{"c0", "c1", "c2"}

	if !reflect.DeepEqual(input.Header(), expected) {
		t.Errorf("Header() = %v, want %v", input.Header(), expected)
	}
}

func TestCSVInputReadsHeader(t *testing.T) {
	fp := test_util.OpenFileFromString(simple)
	defer fp.Close()
	defer os.Remove(fp.Name())

	opts := &CSVInputOptions{
		HasHeader: true,
		Separator: ',',
		ReadFrom:  fp,
	}

	input, _ := NewCSVInput(opts)
	expected := []string{"a", "b", "c"}

	if !reflect.DeepEqual(input.Header(), expected) {
		t.Errorf("Header() = %v, want %v", input.Header(), expected)
	}
}

func TestCSVInputReadsSimple(t *testing.T) {
	fp := test_util.OpenFileFromString(simple)
	defer fp.Close()
	defer os.Remove(fp.Name())

	opts := &CSVInputOptions{
		HasHeader: true,
		Separator: ',',
		ReadFrom:  fp,
	}

	input, _ := NewCSVInput(opts)
	expected := make([][]string, len(strings.Split(simple, "\n"))-1)
	expected[0] = []string{"1", "2", "3"}
	expected[1] = []string{"4", "5", "6"}

	for counter := 0; counter < len(expected); counter++ {
		row := input.ReadRecord()
		if !reflect.DeepEqual(row, expected[counter]) {
			t.Errorf("ReadRecord() = %v, want %v", row, expected[counter])
		}
	}
}

func TestCSVInputReadsBad(t *testing.T) {
	fp := test_util.OpenFileFromString(bad)
	defer fp.Close()
	defer os.Remove(fp.Name())

	opts := &CSVInputOptions{
		HasHeader: true,
		Separator: ',',
		ReadFrom:  fp,
	}

	input, _ := NewCSVInput(opts)
	expected := make([][]string, len(strings.Split(bad, "\n"))-1)
	expected[0] = []string{"1", "2", ""}
	expected[1] = []string{"4", "5", "6"}
	expected[2] = []string{"7", "8", ""}
	expected[3] = []string{"9", "", "10"}
	expected[4] = []string{"11", "12", "13", "14"}
	expected[5] = []string{"foo,bar", `boo,\"far`, ","}
	expected[6] = []string{`'foo`, `bar'`, `'"'`, `'"'`}
	expected[7] = []string{"test\n", "multi-line", ""}

	for counter := 0; counter < len(expected); counter++ {
		row := input.ReadRecord()
		if !reflect.DeepEqual(row, expected[counter]) {
			t.Errorf("ReadRecord() = %v, want %v", row, expected[counter])
		}
	}
}

func TestCSVInputHasAName(t *testing.T) {
	fp := test_util.OpenFileFromString(simple)
	defer fp.Close()
	defer os.Remove(fp.Name())

	opts := &CSVInputOptions{
		HasHeader: true,
		Separator: ',',
		ReadFrom:  fp,
	}

	input, _ := NewCSVInput(opts)
	expected := fp.Name()

	if !reflect.DeepEqual(input.Name(), expected) {
		t.Errorf("Name() = %v, want %v", input.Name(), expected)
	}
}


================================================
FILE: inputs/input.go
================================================
package inputs

// Input is how TextQL reads from data sources.
// To be an input, an implementor must return tabular data.
// How data is manipulated into the tabular structure is left to the implementor.
// Inputs are expected to return in a row by row fashion.
type Input interface {
	// ReadRecord should return nil on the end of data, or a single record.
	// Recoverable errors should represent themselves as empty sets.
	// Unrecoverable errors should return nil.
	ReadRecord() []string
	// Header should return metadata naming the columns in the table.
	Header() []string
	// Name should return a reasonable name for the data set, prehaps the file name.
	Name() string
	// SetName allows users of the dataset to supply their own name if needed.
	SetName(string)
}


================================================
FILE: man/textql.1
================================================
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
.TH "TEXTQL" "1" "December 2015" "" ""
.
.SH "NAME"
\fBtextql\fR \- execute queries on structured text
.
.SH "SYNOPSIS"
\fBtextql\fR [\fI\-save\-to path\fR] [\fI\-output\-file path\fR] [\fI\-output\-dlm delimter\fR] [\fI\-output\-header\fR] [\fI\-header\fR] [\fI\-dlm delimter\fR] [\fI\-source path\fR] [\fI\-sql sql_statements\fR] [\fI\-quiet\fR] [\fIpath\fR\.\.\.]
.
.br
\fBtextql\fR \fI\-console\fR \fIpath\fR\.\.\.
.
.br
.
.SH "DESCRIPTION"
\fBtextql\fR executes given statements in SQL on structured texts and returns the result\. SQL statements accepted by \fBtextql\fR are ANSI SQL compatible, and are executed against the data in the order provided\. No transformations are applied to the text files but are instead applied to a temporary view of the data\. Statements that insert data or modify the existing data will only have their effects visible in the output\.
.
.P
The argument list of the end is expected to be a list of paths which may or may not be specific files\. Each path is traversed for files that are then loaded as part of the database that \fBtextql\fR creates internally, and files are loaded without traversal\. Paths provided are not recursed\.
.
.P
Each statement is then executed against \fBtextql\fR\'s internal database and the result, if any, is printed\. \fBINSERT\fR, \fBUPDATE\fR, \fBDELETE\fR or other side effecting statements do not effect the text files given as input, but instead modify the database internal to \fBtextql\fR\. Their result may be viewed via the output, presisting the database as is with \fB\-save\-to\fR or in a SQLite REPL with \fB\-\-console\fR
.
.P
With no arguements, \fBtextql\fR will print a brief overview of it\'s usage\.
.
.SH "FILES"
Structured text accepted by textql is any text file in a tabular format where each row of the table is on a single line, and each column is a section of the line delimited by a single character which is consistent throughout the file\. A common structured text format is CSV (RFC4180)\.
.
.SH "OPTIONS"
.
.TP
\fB\-console\fR
After all statements are run, open SQLite3 REPL with this data
.
.TP
\fB\-dlm string\fR
Input delimiter character between fields \-dlm=tab for tab, \-dlm=0x## to specify a character code in hex (default ",")
.
.TP
\fB\-header\fR
Treat input files as having the first row as a header row
.
.TP
\fB\-output\-dlm string\fR
Output delimiter character between fields \-output\-dlm=tab for tab, \-dlm=0x## to specify a character code in hex (default ",")
.
.TP
\fB\-output\-file file\fR
Filename to write output to, if empty no output is written (default "stdout")
.
.TP
\fB\-output\-header\fR
Display column names in output
.
.TP
\fB\-quiet\fR
Surpress logging
.
.TP
\fB\-pretty\fR
Pretty print output
.
.TP
\fB\-save\-to file\fR
SQLite3 db is left on disk at this file
.
.TP
\fB\-sql string\fR
SQL Statement(s) to run on the data
.
.TP
\fB\-version\fR
Print version and exit
.
.SH "COPYRIGHT"
textql is Copyright (C) 2015, 2016 Paul Bergeron \fIhttp://pauldbergeron\.com/\fR


================================================
FILE: man/textql.1.html
================================================
<!DOCTYPE html>
<html>
<head>
  <meta http-equiv='content-type' value='text/html;charset=utf8'>
  <meta name='generator' value='Ronn/v0.7.3 (http://github.com/rtomayko/ronn/tree/0.7.3)'>
  <title>textql(1) - execute queries on structured text</title>
  <style type='text/css' media='all'>
  /* style: man */
  body#manpage {margin:0}
  .mp {max-width:100ex;padding:0 9ex 1ex 4ex}
  .mp p,.mp pre,.mp ul,.mp ol,.mp dl {margin:0 0 20px 0}
  .mp h2 {margin:10px 0 0 0}
  .mp > p,.mp > pre,.mp > ul,.mp > ol,.mp > dl {margin-left:8ex}
  .mp h3 {margin:0 0 0 4ex}
  .mp dt {margin:0;clear:left}
  .mp dt.flush {float:left;width:8ex}
  .mp dd {margin:0 0 0 9ex}
  .mp h1,.mp h2,.mp h3,.mp h4 {clear:left}
  .mp pre {margin-bottom:20px}
  .mp pre+h2,.mp pre+h3 {margin-top:22px}
  .mp h2+pre,.mp h3+pre {margin-top:5px}
  .mp img {display:block;margin:auto}
  .mp h1.man-title {display:none}
  .mp,.mp code,.mp pre,.mp tt,.mp kbd,.mp samp,.mp h3,.mp h4 {font-family:monospace;font-size:14px;line-height:1.42857142857143}
  .mp h2 {font-size:16px;line-height:1.25}
  .mp h1 {font-size:20px;line-height:2}
  .mp {text-align:justify;background:#fff}
  .mp,.mp code,.mp pre,.mp pre code,.mp tt,.mp kbd,.mp samp {color:#131211}
  .mp h1,.mp h2,.mp h3,.mp h4 {color:#030201}
  .mp u {text-decoration:underline}
  .mp code,.mp strong,.mp b {font-weight:bold;color:#131211}
  .mp em,.mp var {font-style:italic;color:#232221;text-decoration:none}
  .mp a,.mp a:link,.mp a:hover,.mp a code,.mp a pre,.mp a tt,.mp a kbd,.mp a samp {color:#0000ff}
  .mp b.man-ref {font-weight:normal;color:#434241}
  .mp pre {padding:0 4ex}
  .mp pre code {font-weight:normal;color:#434241}
  .mp h2+pre,h3+pre {padding-left:0}
  ol.man-decor,ol.man-decor li {margin:3px 0 10px 0;padding:0;float:left;width:33%;list-style-type:none;text-transform:uppercase;color:#999;letter-spacing:1px}
  ol.man-decor {width:100%}
  ol.man-decor li.tl {text-align:left}
  ol.man-decor li.tc {text-align:center;letter-spacing:4px}
  ol.man-decor li.tr {text-align:right;float:right}
  </style>
</head>
<!--
  The following styles are deprecated and will be removed at some point:
  div#man, div#man ol.man, div#man ol.head, div#man ol.man.

  The .man-page, .man-decor, .man-head, .man-foot, .man-title, and
  .man-navigation should be used instead.
-->
<body id='manpage'>
  <div class='mp' id='man'>

  <div class='man-navigation' style='display:none'>
    <a href="#NAME">NAME</a>
    <a href="#SYNOPSIS">SYNOPSIS</a>
    <a href="#DESCRIPTION">DESCRIPTION</a>
    <a href="#FILES">FILES</a>
    <a href="#OPTIONS">OPTIONS</a>
    <a href="#COPYRIGHT">COPYRIGHT</a>
  </div>

  <ol class='man-decor man-head man head'>
    <li class='tl'>textql(1)</li>
    <li class='tc'></li>
    <li class='tr'>textql(1)</li>
  </ol>

  <h2 id="NAME">NAME</h2>
<p class="man-name">
  <code>textql</code> - <span class="man-whatis">execute queries on structured text</span>
</p>

<h2 id="SYNOPSIS">SYNOPSIS</h2>

<p><code>textql</code> [<var>-save-to path</var>] [<var>-output-file path</var>] [<var>-output-dlm delimter</var>] [<var>-output-header</var>] [<var>-header</var>] [<var>-dlm delimter</var>] [<var>-source path</var>] [<var>-sql sql_statements</var>] [<var>-quiet</var>] [<var>path</var>...]<br />
<code>textql</code> <var>-console</var> <var>path</var>...<br /></p>

<h2 id="DESCRIPTION">DESCRIPTION</h2>

<p><strong>textql</strong> executes given statements in SQL on structured texts and returns the result.
SQL statements accepted by <code>textql</code> are ANSI SQL compatible, and are executed against
the data in the order provided. No transformations are applied to the text files
but are instead applied to a temporary view of the data. Statements that insert data
or modify the existing data will only have their effects visible in the output.</p>

<p>The argument list of the end is expected to be a list of paths which may or may not
be specific files. Each path is traversed for files that are then loaded as part of
the database that <code>textql</code> creates internally, and files are loaded without traversal.
Paths provided are not recursed.</p>

<p>Each statement is then executed against <code>textql</code>'s internal database and the result, if
any, is printed. <strong>INSERT</strong>, <strong>UPDATE</strong>, <strong>DELETE</strong> or other side effecting statements
do not effect the text files given as input, but instead modify the database
internal to <code>textql</code>. Their result may be viewed via the output, presisting the
database as is with <code>-save-to</code> or in a SQLite REPL with <code>--console</code></p>

<p>With no arguements, <code>textql</code> will print a brief overview of it's usage.</p>

<h2 id="FILES">FILES</h2>

<p>Structured text accepted by textql is any text file in a tabular format
where each row of the table is on a single line, and each column is a section of the
line delimited by a single character which is consistent throughout the file. A
common structured text format is CSV (RFC4180).</p>

<h2 id="OPTIONS">OPTIONS</h2>

<dl>
<dt><code>-console</code></dt><dd>After all statements are run, open SQLite3 REPL with this data</dd>
<dt><code>-dlm string</code></dt><dd>Input delimiter character between fields -dlm=tab for tab, -dlm=0x## to specify a character code in hex (default ",")</dd>
<dt class="flush"><code>-header</code></dt><dd>Treat input files as having the first row as a header row</dd>
<dt><code>-output-dlm string</code></dt><dd>Output delimiter character between fields -output-dlm=tab for tab, -dlm=0x## to specify a character code in hex (default ",")</dd>
<dt><code>-output-file file</code></dt><dd>Filename to write output to, if empty no output is written (default "stdout")</dd>
<dt><code>-output-header</code></dt><dd>Display column names in output</dd>
<dt class="flush"><code>-quiet</code></dt><dd>Surpress logging</dd>
<dt class="flush"><code>-pretty</code></dt><dd>Pretty print output</dd>
<dt><code>-save-to file</code></dt><dd>SQLite3 db is left on disk at this file</dd>
<dt><code>-sql string</code></dt><dd>SQL Statement(s) to run on the data</dd>
<dt><code>-version</code></dt><dd>Print version and exit</dd>
</dl>


<h2 id="COPYRIGHT">COPYRIGHT</h2>

<p>textql is Copyright (C) 2015, 2016 Paul Bergeron
<a href="http://pauldbergeron.com/" data-bare-link="true">http://pauldbergeron.com/</a></p>


  <ol class='man-decor man-foot man foot'>
    <li class='tl'></li>
    <li class='tc'>December 2015</li>
    <li class='tr'>textql(1)</li>
  </ol>

  </div>
</body>
</html>


================================================
FILE: man/textql.1.ronn
================================================
textql(1) -- execute queries on structured text
===============================================

## SYNOPSIS

`textql` [<-save-to path>] [<-output-file path>] [<-output-dlm delimter>] [<-output-header>] [<-header>] [<-dlm delimter>] [<-source path>] [<-sql sql_statements>] [<-quiet>] [<path>...]<br>
`textql` <-console> <path>...<br>

## DESCRIPTION

**textql** executes given statements in SQL on structured texts and returns the result.
SQL statements accepted by `textql` are ANSI SQL compatible, and are executed against
the data in the order provided. No transformations are applied to the text files
but are instead applied to a temporary view of the data. Statements that insert data
or modify the existing data will only have their effects visible in the output.

The argument list of the end is expected to be a list of paths which may or may not
be specific files. Each path is traversed for files that are then loaded as part of
the database that `textql` creates internally, and files are loaded without traversal.
Paths provided are not recursed.

Each statement is then executed against `textql`'s internal database and the result, if
any, is printed. **INSERT**, **UPDATE**, **DELETE** or other side effecting statements
do not effect the text files given as input, but instead modify the database
internal to `textql`. Their result may be viewed via the output, presisting the
database as is with `-save-to` or in a SQLite REPL with `--console`

With no arguements, `textql` will print a brief overview of it's usage.

## FILES

Structured text accepted by textql is any text file in a tabular format
where each row of the table is on a single line, and each column is a section of the
line delimited by a single character which is consistent throughout the file. A
common structured text format is CSV (RFC4180).

## OPTIONS

  * `-console`:
    After all statements are run, open SQLite3 REPL with this data
  * `-dlm string`:
    Input delimiter character between fields -dlm=tab for tab, -dlm=0x## to specify a character code in hex (default ",")
  * `-header`:
    Treat input files as having the first row as a header row
  * `-output-dlm string`:
    Output delimiter character between fields -output-dlm=tab for tab, -dlm=0x## to specify a character code in hex (default ",")
  * `-output-file file`:
    Filename to write output to, if empty no output is written (default "stdout")
  * `-output-header`:
    Display column names in output
  * `-quiet`:
    Surpress logging
  * `-pretty`:
    Pretty print output
  * `-save-to file`:
    SQLite3 db is left on disk at this file
  * `-sql string`:
    SQL Statement(s) to run on the data
  * `-version`:
    Print version and exit


## COPYRIGHT

textql is Copyright (C) 2015, 2016 Paul Bergeron
<http://pauldbergeron.com/>

================================================
FILE: outputs/csv.go
================================================
package outputs

import (
	"database/sql"
	"encoding/csv"
	"io"
	"log"
)

// CSVOutput represents a TextQL output that transforms sql.Rows into CSV formatted
// string data using encoding/csv
type CSVOutput struct {
	options         *CSVOutputOptions
	writer          *csv.Writer
	firstRow        []string
	header          []string
	minOutputLength int
}

// CSVOutputOptions define options that are passed to encoding/csv for formatting
// the output in specific ways.
type CSVOutputOptions struct {
	// WriteHeader determines if a header row based on the column names should be written.
	WriteHeader bool
	// Separator is the rune used to delimit fields.
	Separator rune
	// WriteTo is where the formatted data will be written to.
	WriteTo io.Writer
}

// NewCSVOutput returns a new CSVOutput configured per the options provided.
func NewCSVOutput(opts *CSVOutputOptions) *CSVOutput {
	csvOutput := &CSVOutput{
		options: opts,
		writer:  csv.NewWriter(opts.WriteTo),
	}

	csvOutput.writer.Comma = csvOutput.options.Separator

	return csvOutput
}

// Show writes the sql.Rows given to the destination in CSV format.
func (csvOutput *CSVOutput) Show(rows *sql.Rows) {
	cols, colsErr := rows.Columns()

	if colsErr != nil {
		log.Fatalln(colsErr)
	}

	if csvOutput.options.WriteHeader && len(cols) > 0 {
		if err := csvOutput.writer.Write(cols); err != nil {
			log.Fatalln(err)
		}
	}

	rawResult := make([][]byte, len(cols))
	result := make([]string, len(cols))

	dest := make([]interface{}, len(cols))

	for i := range cols {
		dest[i] = &rawResult[i]
	}

	for rows.Next() {
		rows.Scan(dest...)

		for i, raw := range rawResult {
			result[i] = string(raw)
		}

		writeErr := csvOutput.writer.Write(result)

		if writeErr != nil {
			log.Fatalln(writeErr)
		}
	}

	csvOutput.writer.Flush()
	rows.Close()
}


================================================
FILE: outputs/output.go
================================================
package outputs

import "database/sql"

// Output implementors should accept sql.Rows and transform them
// however they need to in order to represent them in their specific format.
type Output interface {
	// Show should display/write the sql.Rows to the implmentor's destination and format.
	Show(*sql.Rows)
}


================================================
FILE: outputs/pretty_csv.go
================================================
package outputs

import (
	"database/sql"
	"io"
	"log"

	"github.com/olekukonko/tablewriter"
)

// PrettyCSVOutput represents a TextQL output that transforms sql.Rows into pretty tables
type PrettyCSVOutput struct {
	options         *PrettyCSVOutputOptions
	writer          *tablewriter.Table
	firstRow        []string
	header          []string
	minOutputLength int
}

// PrettyCSVOutputOptions define options that are passed to tablewriter for formatting
// the output in specific ways.
type PrettyCSVOutputOptions struct {
	// WriteHeader determines if a header row based on the column names should be written.
	WriteHeader bool
	// WriteTo is where the formatted data will be written to.
	WriteTo io.Writer
}

// NewPrettyCSVOutput returns a new PrettyCSVOutput configured per the options provided.
func NewPrettyCSVOutput(opts *PrettyCSVOutputOptions) *PrettyCSVOutput {
	prettyCsvOutput := &PrettyCSVOutput{
		options: opts,
		writer:  tablewriter.NewWriter(opts.WriteTo),
	}

	return prettyCsvOutput
}

// Show writes the sql.Rows given to the destination in tablewriter basic format.
func (prettyCsvOutput *PrettyCSVOutput) Show(rows *sql.Rows) {
	cols, colsErr := rows.Columns()

	if colsErr != nil {
		log.Fatalln(colsErr)
	}

	if prettyCsvOutput.options.WriteHeader {
		prettyCsvOutput.writer.SetHeader(cols)
		prettyCsvOutput.writer.SetHeaderLine(true)
		prettyCsvOutput.writer.SetAutoFormatHeaders(false)
	}

	rawResult := make([][]byte, len(cols))
	result := make([]string, len(cols))

	dest := make([]interface{}, len(cols))

	for i := range cols {
		dest[i] = &rawResult[i]
	}

	for rows.Next() {
		rows.Scan(dest...)

		for i, raw := range rawResult {
			result[i] = string(raw)
		}

		prettyCsvOutput.writer.Append(result)
	}

	if len(cols) > 0 {
		prettyCsvOutput.writer.Render()
	}
	rows.Close()
}


================================================
FILE: snapcraft.yaml
================================================
name: textql
version: '1.0'
summary: Execute SQL against structured text like CSV or TSV 
description: |
  Execute SQL against structured text like CSV or TSV.
grade: stable
confinement: strict
base: core18
parts:
  textql:
    plugin: go
    source: https://github.com/dinedal/textql.git
    go-importpath: github.com/dinedal/textql
    build-packages:
      - build-essential
apps:
  textql:
    command: bin/textql
    plugs:
      - home


================================================
FILE: sqlparser/Makefile
================================================

MAKEFLAGS = -s

sql.go: sql.y
	go tool yacc -o sql.go sql.y
	gofmt -w sql.go

clean:
	rm -f y.output sql.go


================================================
FILE: sqlparser/analyzer.go
================================================
// Copyright 2012, Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package sqlparser

// analyzer.go contains utility analysis functions.

import (
	"fmt"

	"github.com/dinedal/textql/sqlparser/sqltypes"
)

// GetTableName returns the table name from the SimpleTableExpr
// only if it's a simple expression. Otherwise, it returns "".
func GetTableName(node SimpleTableExpr) string {
	if n, ok := node.(*TableName); ok && n.Qualifier == nil {
		return string(n.Name)
	}
	// sub-select or '.' expression
	return ""
}

// GetColName returns the column name, only if
// it's a simple expression. Otherwise, it returns "".
func GetColName(node Expr) string {
	if n, ok := node.(*ColName); ok {
		return string(n.Name)
	}
	return ""
}

// IsColName returns true if the ValExpr is a *ColName.
func IsColName(node ValExpr) bool {
	_, ok := node.(*ColName)
	return ok
}

// IsValue returns true if the ValExpr is a string, number or value arg.
// NULL is not considered to be a value.
func IsValue(node ValExpr) bool {
	switch node.(type) {
	case StrVal, NumVal, ValArg:
		return true
	}
	return false
}

// HasINCaluse returns true if any of the conditions has an IN clause.
func HasINClause(conditions []BoolExpr) bool {
	for _, node := range conditions {
		if c, ok := node.(*ComparisonExpr); ok && c.Operator == AST_IN {
			return true
		}
	}
	return false
}

// IsSimpleTuple returns true if the ValExpr is a ValTuple that
// contains simple values or if it's a list arg.
func IsSimpleTuple(node ValExpr) bool {
	switch vals := node.(type) {
	case ValTuple:
		for _, n := range vals {
			if !IsValue(n) {
				return false
			}
		}
		return true
	case ListArg:
		return true
	}
	// It's a subquery
	return false
}

// AsInterface converts the ValExpr to an interface. It converts
// ValTuple to []interface{}, ValArg to string, StrVal to sqltypes.String,
// NumVal to sqltypes.Numeric, NullVal to nil.
// Otherwise, it returns an error.
func AsInterface(node ValExpr) (interface{}, error) {
	switch node := node.(type) {
	case ValTuple:
		vals := make([]interface{}, 0, len(node))
		for _, val := range node {
			v, err := AsInterface(val)
			if err != nil {
				return nil, err
			}
			vals = append(vals, v)
		}
		return vals, nil
	case ValArg:
		return string(node), nil
	case ListArg:
		return string(node), nil
	case StrVal:
		return sqltypes.MakeString(node), nil
	case NumVal:
		n, err := sqltypes.BuildNumeric(string(node))
		if err != nil {
			return nil, fmt.Errorf("type mismatch: %s", err)
		}
		return n, nil
	case *NullVal:
		return nil, nil
	}
	return nil, fmt.Errorf("unexpected node %v", node)
}

// StringIn is a convenience function that returns
// true if str matches any of the values.
func StringIn(str string, values ...string) bool {
	for _, val := range values {
		if str == val {
			return true
		}
	}
	return false
}


================================================
FILE: sqlparser/ast.go
================================================
// Copyright 2012, Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package sqlparser

import (
	"errors"
	"fmt"
	"strconv"

	"github.com/dinedal/textql/sqlparser/sqltypes"
)

// Instructions for creating new types: If a type
// needs to satisfy an interface, declare that function
// along with that interface. This will help users
// identify the list of types to which they can assert
// those interfaces.
// If the member of a type has a string with a predefined
// list of values, declare those values as const following
// the type.
// For interfaces that define dummy functions to consolidate
// a set of types, define the function as ITypeName.
// This will help avoid name collisions.

// Parse parses the sql and returns a Statement, which
// is the AST representation of the query.
func Parse(sql string) (Statement, error) {
	tokenizer := NewStringTokenizer(sql)
	if yyParse(tokenizer) != 0 {
		return nil, errors.New(tokenizer.LastError)
	}
	return tokenizer.ParseTree, nil
}

// SQLNode defines the interface for all nodes
// generated by the parser.
type SQLNode interface {
	Format(buf *TrackedBuffer)
}

// String returns a string representation of an SQLNode.
func String(node SQLNode) string {
	buf := NewTrackedBuffer(nil)
	buf.Myprintf("%v", node)
	return buf.String()
}

// Statement represents a statement.
type Statement interface {
	IStatement()
	SQLNode
}

func (*Union) IStatement()  {}
func (*Select) IStatement() {}
func (*Insert) IStatement() {}
func (*Update) IStatement() {}
func (*Delete) IStatement() {}
func (*Set) IStatement()    {}
func (*DDL) IStatement()    {}
func (*Other) IStatement()  {}

// SelectStatement any SELECT statement.
type SelectStatement interface {
	ISelectStatement()
	IStatement()
	IInsertRows()
	SQLNode
}

func (*Select) ISelectStatement() {}
func (*Union) ISelectStatement()  {}

// Select represents a SELECT statement.
type Select struct {
	Comments    Comments
	Distinct    string
	SelectExprs SelectExprs
	From        *From
	Where       *Where
	GroupBy     GroupBy
	Having      *Where
	OrderBy     OrderBy
	Limit       *Limit
	Lock        string
}

// Select.Distinct
const (
	AST_DISTINCT = "distinct "
)

// Select.Lock
const (
	AST_FOR_UPDATE = " for update"
	AST_SHARE_MODE = " lock in share mode"
)

func (node *Select) Format(buf *TrackedBuffer) {
	buf.Myprintf("select %v%s%v from %v%v%v%v%v%v%s",
		node.Comments, node.Distinct, node.SelectExprs,
		node.From, node.Where,
		node.GroupBy, node.Having, node.OrderBy,
		node.Limit, node.Lock)
}

// Union represents a UNION statement.
type Union struct {
	Type        string
	Left, Right SelectStatement
}

// Union.Type
const (
	AST_UNION     = "union"
	AST_UNION_ALL = "union all"
	AST_SET_MINUS = "minus"
	AST_EXCEPT    = "except"
	AST_INTERSECT = "intersect"
)

func (node *Union) Format(buf *TrackedBuffer) {
	buf.Myprintf("%v %s %v", node.Left, node.Type, node.Right)
}

// Insert represents an INSERT statement.
type Insert struct {
	Comments Comments
	Table    *TableName
	Columns  Columns
	Rows     InsertRows
	OnDup    OnDup
}

func (node *Insert) Format(buf *TrackedBuffer) {
	buf.Myprintf("insert %vinto %v%v %v%v",
		node.Comments,
		node.Table, node.Columns, node.Rows, node.OnDup)
}

// InsertRows represents the rows for an INSERT statement.
type InsertRows interface {
	IInsertRows()
	SQLNode
}

func (*Select) IInsertRows() {}
func (*Union) IInsertRows()  {}
func (Values) IInsertRows()  {}

// Update represents an UPDATE statement.
type Update struct {
	Comments Comments
	Table    *TableName
	Exprs    UpdateExprs
	Where    *Where
	OrderBy  OrderBy
	Limit    *Limit
}

func (node *Update) Format(buf *TrackedBuffer) {
	buf.Myprintf("update %v%v set %v%v%v%v",
		node.Comments, node.Table,
		node.Exprs, node.Where, node.OrderBy, node.Limit)
}

// Delete represents a DELETE statement.
type Delete struct {
	Comments Comments
	Table    *TableName
	Where    *Where
	OrderBy  OrderBy
	Limit    *Limit
}

func (node *Delete) Format(buf *TrackedBuffer) {
	buf.Myprintf("delete %vfrom %v%v%v%v",
		node.Comments,
		node.Table, node.Where, node.OrderBy, node.Limit)
}

// Set represents a SET statement.
type Set struct {
	Comments Comments
	Exprs    UpdateExprs
}

func (node *Set) Format(buf *TrackedBuffer) {
	buf.Myprintf("set %v%v", node.Comments, node.Exprs)
}

// DDL represents a CREATE, ALTER, DROP or RENAME statement.
// Table is set for AST_ALTER, AST_DROP, AST_RENAME.
// NewName is set for AST_ALTER, AST_CREATE, AST_RENAME.
type DDL struct {
	Action  string
	Table   []byte
	NewName []byte
}

const (
	AST_CREATE = "create"
	AST_ALTER  = "alter"
	AST_DROP   = "drop"
	AST_RENAME = "rename"
)

func (node *DDL) Format(buf *TrackedBuffer) {
	switch node.Action {
	case AST_CREATE:
		buf.Myprintf("%s table %s", node.Action, node.NewName)
	case AST_RENAME:
		buf.Myprintf("%s table %s %s", node.Action, node.Table, node.NewName)
	default:
		buf.Myprintf("%s table %s", node.Action, node.Table)
	}
}

// Other represents a SHOW, DESCRIBE, or EXPLAIN statement.
// It should be used only as an indicator. It does not contain
// the full AST for the statement.
type Other struct{}

func (node *Other) Format(buf *TrackedBuffer) {
	buf.WriteString("other")
}

// Comments represents a list of comments.
type Comments [][]byte

func (node Comments) Format(buf *TrackedBuffer) {
	for _, c := range node {
		buf.Myprintf("%s ", c)
	}
}

// SelectExprs represents SELECT expressions.
type SelectExprs []SelectExpr

func (node SelectExprs) Format(buf *TrackedBuffer) {
	var prefix string
	for _, n := range node {
		buf.Myprintf("%s%v", prefix, n)
		prefix = ", "
	}
}

// SelectExpr represents a SELECT expression.
type SelectExpr interface {
	ISelectExpr()
	SQLNode
}

func (*StarExpr) ISelectExpr()    {}
func (*NonStarExpr) ISelectExpr() {}

// StarExpr defines a '*' or 'table.*' expression.
type StarExpr struct {
	TableName []byte
}

func (node *StarExpr) Format(buf *TrackedBuffer) {
	if node.TableName != nil {
		buf.Myprintf("%s.", node.TableName)
	}
	buf.Myprintf("*")
}

// NonStarExpr defines a non-'*' select expr.
type NonStarExpr struct {
	Expr Expr
	As   []byte
}

func (node *NonStarExpr) Format(buf *TrackedBuffer) {
	buf.Myprintf("%v", node.Expr)
	if node.As != nil {
		buf.Myprintf(" as %s", node.As)
	}
}

// Columns represents an insert column list.
// The syntax for Columns is a subset of SelectExprs.
// So, it's castable to a SelectExprs and can be analyzed
// as such.
type Columns []SelectExpr

func (node Columns) Format(buf *TrackedBuffer) {
	if node == nil {
		return
	}
	buf.Myprintf("(%v)", SelectExprs(node))
}

// TableExprs represents a list of table expressions.
type TableExprs []TableExpr

func (node TableExprs) Format(buf *TrackedBuffer) {
	var prefix string
	for _, n := range node {
		buf.Myprintf("%s%v", prefix, n)
		prefix = ", "
	}
}

// TableExpr represents a table expression.
type TableExpr interface {
	ITableExpr()
	SQLNode
}

func (*AliasedTableExpr) ITableExpr() {}
func (*ParenTableExpr) ITableExpr()   {}
func (*JoinTableExpr) ITableExpr()    {}

// AliasedTableExpr represents a table expression
// coupled with an optional alias or index hint.
type AliasedTableExpr struct {
	Expr  SimpleTableExpr
	As    []byte
	Hints *IndexHints
}

func (node *AliasedTableExpr) Format(buf *TrackedBuffer) {
	buf.Myprintf("%v", node.Expr)
	if node.As != nil {
		buf.Myprintf(" as %s", node.As)
	}
	if node.Hints != nil {
		// Hint node provides the space padding.
		buf.Myprintf("%v", node.Hints)
	}
}

// SimpleTableExpr represents a simple table expression.
type SimpleTableExpr interface {
	ISimpleTableExpr()
	SQLNode
}

func (*TableName) ISimpleTableExpr() {}
func (*Subquery) ISimpleTableExpr()  {}

// TableName represents a table  name.
type TableName struct {
	Name, Qualifier []byte
}

func (node *TableName) Format(buf *TrackedBuffer) {
	if node.Qualifier != nil {
		escape(buf, node.Qualifier)
		buf.Myprintf(".")
	}
	escape(buf, node.Name)
}

// ParenTableExpr represents a parenthesized TableExpr.
type ParenTableExpr struct {
	Expr TableExpr
}

func (node *ParenTableExpr) Format(buf *TrackedBuffer) {
	buf.Myprintf("(%v)", node.Expr)
}

// JoinTableExpr represents a TableExpr that's a JOIN operation.
type JoinTableExpr struct {
	LeftExpr  TableExpr
	Join      string
	RightExpr TableExpr
	On        BoolExpr
}

// JoinTableExpr.Join
const (
	AST_JOIN          = "join"
	AST_STRAIGHT_JOIN = "straight_join"
	AST_LEFT_JOIN     = "left join"
	AST_RIGHT_JOIN    = "right join"
	AST_CROSS_JOIN    = "cross join"
	AST_NATURAL_JOIN  = "natural join"
)

func (node *JoinTableExpr) Format(buf *TrackedBuffer) {
	buf.Myprintf("%v %s %v", node.LeftExpr, node.Join, node.RightExpr)
	if node.On != nil {
		buf.Myprintf(" on %v", node.On)
	}
}

// IndexHints represents a list of index hints.
type IndexHints struct {
	Type    string
	Indexes [][]byte
}

const (
	AST_USE    = "use"
	AST_IGNORE = "ignore"
	AST_FORCE  = "force"
)

func (node *IndexHints) Format(buf *TrackedBuffer) {
	buf.Myprintf(" %s index ", node.Type)
	prefix := "("
	for _, n := range node.Indexes {
		buf.Myprintf("%s%s", prefix, n)
		prefix = ", "
	}
	buf.Myprintf(")")
}

// Where represents a WHERE or HAVING clause.
type Where struct {
	Type string
	Expr BoolExpr
}

// Where.Type
const (
	AST_WHERE  = "where"
	AST_HAVING = "having"
)

// NewWhere creates a WHERE or HAVING clause out
// of a BoolExpr. If the expression is nil, it returns nil.
func NewWhere(typ string, expr BoolExpr) *Where {
	if expr == nil {
		return nil
	}
	return &Where{Type: typ, Expr: expr}
}

func (node *Where) Format(buf *TrackedBuffer) {
	if node == nil || node.Expr == nil {
		return
	}
	buf.Myprintf(" %s %v", node.Type, node.Expr)
}

// From represents a FROM clause
type From struct {
	Type string
	Expr TableExprs
}

// From.Type
const (
	AST_FROM = "from"
)

// NewFrom creates a FROM clause
// of a table list expression. If the expression is nil, it returns nil.
func NewFrom(typ string, expr TableExprs) *From {
	if expr == nil {
		return nil
	}
	return &From{Type: typ, Expr: expr}
}

func (node *From) Format(buf *TrackedBuffer) {
	if node == nil || node.Expr == nil {
		return
	}
	buf.Myprintf("%v", node.Expr)
}

// Expr represents an expression.
type Expr interface {
	IExpr()
	SQLNode
}

func (*AndExpr) IExpr()        {}
func (*OrExpr) IExpr()         {}
func (*NotExpr) IExpr()        {}
func (*ParenBoolExpr) IExpr()  {}
func (*ComparisonExpr) IExpr() {}
func (*RangeCond) IExpr()      {}
func (*NullCheck) IExpr()      {}
func (*ExistsExpr) IExpr()     {}
func (*KeyrangeExpr) IExpr()   {}
func (StrVal) IExpr()          {}
func (NumVal) IExpr()          {}
func (ValArg) IExpr()          {}
func (*NullVal) IExpr()        {}
func (*ColName) IExpr()        {}
func (ValTuple) IExpr()        {}
func (*Subquery) IExpr()       {}
func (ListArg) IExpr()         {}
func (*BinaryExpr) IExpr()     {}
func (*UnaryExpr) IExpr()      {}
func (*FuncExpr) IExpr()       {}
func (*CaseExpr) IExpr()       {}

// BoolExpr represents a boolean expression.
type BoolExpr interface {
	IBoolExpr()
	Expr
}

func (*AndExpr) IBoolExpr()        {}
func (*OrExpr) IBoolExpr()         {}
func (*NotExpr) IBoolExpr()        {}
func (*ParenBoolExpr) IBoolExpr()  {}
func (*ComparisonExpr) IBoolExpr() {}
func (*RangeCond) IBoolExpr()      {}
func (*NullCheck) IBoolExpr()      {}
func (*ExistsExpr) IBoolExpr()     {}
func (*KeyrangeExpr) IBoolExpr()   {}

// AndExpr represents an AND expression.
type AndExpr struct {
	Left, Right BoolExpr
}

func (node *AndExpr) Format(buf *TrackedBuffer) {
	buf.Myprintf("%v and %v", node.Left, node.Right)
}

// OrExpr represents an OR expression.
type OrExpr struct {
	Left, Right BoolExpr
}

func (node *OrExpr) Format(buf *TrackedBuffer) {
	buf.Myprintf("%v or %v", node.Left, node.Right)
}

// NotExpr represents a NOT expression.
type NotExpr struct {
	Expr BoolExpr
}

func (node *NotExpr) Format(buf *TrackedBuffer) {
	buf.Myprintf("not %v", node.Expr)
}

// ParenBoolExpr represents a parenthesized boolean expression.
type ParenBoolExpr struct {
	Expr BoolExpr
}

func (node *ParenBoolExpr) Format(buf *TrackedBuffer) {
	buf.Myprintf("(%v)", node.Expr)
}

// ComparisonExpr represents a two-value comparison expression.
type ComparisonExpr struct {
	Operator    string
	Left, Right ValExpr
}

// ComparisonExpr.Operator
const (
	AST_EQ       = "="
	AST_LT       = "<"
	AST_GT       = ">"
	AST_LE       = "<="
	AST_GE       = ">="
	AST_NE       = "!="
	AST_NSE      = "<=>"
	AST_IN       = "in"
	AST_NOT_IN   = "not in"
	AST_LIKE     = "like"
	AST_NOT_LIKE = "not like"
)

func (node *ComparisonExpr) Format(buf *TrackedBuffer) {
	buf.Myprintf("%v %s %v", node.Left, node.Operator, node.Right)
}

// RangeCond represents a BETWEEN or a NOT BETWEEN expression.
type RangeCond struct {
	Operator string
	Left     ValExpr
	From, To ValExpr
}

// RangeCond.Operator
const (
	AST_BETWEEN     = "between"
	AST_NOT_BETWEEN = "not between"
)

func (node *RangeCond) Format(buf *TrackedBuffer) {
	buf.Myprintf("%v %s %v and %v", node.Left, node.Operator, node.From, node.To)
}

// NullCheck represents an IS NULL or an IS NOT NULL expression.
type NullCheck struct {
	Operator string
	Expr     ValExpr
}

// NullCheck.Operator
const (
	AST_IS_NULL     = "is null"
	AST_IS_NOT_NULL = "is not null"
)

func (node *NullCheck) Format(buf *TrackedBuffer) {
	buf.Myprintf("%v %s", node.Expr, node.Operator)
}

// ExistsExpr represents an EXISTS expression.
type ExistsExpr struct {
	Subquery *Subquery
}

func (node *ExistsExpr) Format(buf *TrackedBuffer) {
	buf.Myprintf("exists %v", node.Subquery)
}

// KeyrangeExpr represents a KEYRANGE expression.
type KeyrangeExpr struct {
	Start, End ValExpr
}

func (node *KeyrangeExpr) Format(buf *TrackedBuffer) {
	buf.Myprintf("keyrange(%v, %v)", node.Start, node.End)
}

// ValExpr represents a value expression.
type ValExpr interface {
	IValExpr()
	Expr
}

func (StrVal) IValExpr()      {}
func (NumVal) IValExpr()      {}
func (ValArg) IValExpr()      {}
func (*NullVal) IValExpr()    {}
func (*ColName) IValExpr()    {}
func (ValTuple) IValExpr()    {}
func (*Subquery) IValExpr()   {}
func (ListArg) IValExpr()     {}
func (*BinaryExpr) IValExpr() {}
func (*UnaryExpr) IValExpr()  {}
func (*FuncExpr) IValExpr()   {}
func (*CaseExpr) IValExpr()   {}

// StrVal represents a string value.
type StrVal []byte

func (node StrVal) Format(buf *TrackedBuffer) {
	s := sqltypes.MakeString([]byte(node))
	s.EncodeSql(buf)
}

// NumVal represents a number.
type NumVal []byte

func (node NumVal) Format(buf *TrackedBuffer) {
	buf.Myprintf("%s", []byte(node))
}

// ValArg represents a named bind var argument.
type ValArg []byte

func (node ValArg) Format(buf *TrackedBuffer) {
	buf.WriteArg(string(node))
}

// NullVal represents a NULL value.
type NullVal struct{}

func (node *NullVal) Format(buf *TrackedBuffer) {
	buf.Myprintf("null")
}

// ColName represents a column name.
type ColName struct {
	Name, Qualifier []byte
}

func (node *ColName) Format(buf *TrackedBuffer) {
	if node.Qualifier != nil {
		escape(buf, node.Qualifier)
		buf.Myprintf(".")
	}
	escape(buf, node.Name)
}

func escape(buf *TrackedBuffer, name []byte) {
	if _, ok := keywords[string(name)]; ok {
		buf.Myprintf("`%s`", name)
	} else {
		buf.Myprintf("%s", name)
	}
}

// ColTuple represents a list of column values.
// It can be ValTuple, Subquery, ListArg.
type ColTuple interface {
	IColTuple()
	ValExpr
}

func (ValTuple) IColTuple()  {}
func (*Subquery) IColTuple() {}
func (ListArg) IColTuple()   {}

// ValTuple represents a tuple of actual values.
type ValTuple ValExprs

func (node ValTuple) Format(buf *TrackedBuffer) {
	buf.Myprintf("(%v)", ValExprs(node))
}

// ValExprs represents a list of value expressions.
// It's not a valid expression because it's not parenthesized.
type ValExprs []ValExpr

func (node ValExprs) Format(buf *TrackedBuffer) {
	var prefix string
	for _, n := range node {
		buf.Myprintf("%s%v", prefix, n)
		prefix = ", "
	}
}

// Subquery represents a subquery.
type Subquery struct {
	Select SelectStatement
}

func (node *Subquery) Format(buf *TrackedBuffer) {
	buf.Myprintf("(%v)", node.Select)
}

// ListArg represents a named list argument.
type ListArg []byte

func (node ListArg) Format(buf *TrackedBuffer) {
	buf.WriteArg(string(node))
}

// BinaryExpr represents a binary value expression.
type BinaryExpr struct {
	Operator    byte
	Left, Right Expr
}

// BinaryExpr.Operator
const (
	AST_BITAND = '&'
	AST_BITOR  = '|'
	AST_BITXOR = '^'
	AST_PLUS   = '+'
	AST_MINUS  = '-'
	AST_MULT   = '*'
	AST_DIV    = '/'
	AST_MOD    = '%'
)

func (node *BinaryExpr) Format(buf *TrackedBuffer) {
	buf.Myprintf("%v%c%v", node.Left, node.Operator, node.Right)
}

// UnaryExpr represents a unary value expression.
type UnaryExpr struct {
	Operator byte
	Expr     Expr
}

// UnaryExpr.Operator
const (
	AST_UPLUS  = '+'
	AST_UMINUS = '-'
	AST_TILDA  = '~'
)

func (node *UnaryExpr) Format(buf *TrackedBuffer) {
	buf.Myprintf("%c%v", node.Operator, node.Expr)
}

// FuncExpr represents a function call.
type FuncExpr struct {
	Name     []byte
	Distinct bool
	Exprs    SelectExprs
}

func (node *FuncExpr) Format(buf *TrackedBuffer) {
	var distinct string
	if node.Distinct {
		distinct = "distinct "
	}
	buf.Myprintf("%s(%s%v)", node.Name, distinct, node.Exprs)
}

// Aggregates is a map of all aggregate functions.
var Aggregates = map[string]bool{
	"avg":          true,
	"bit_and":      true,
	"bit_or":       true,
	"bit_xor":      true,
	"count":        true,
	"group_concat": true,
	"max":          true,
	"min":          true,
	"std":          true,
	"stddev_pop":   true,
	"stddev_samp":  true,
	"stddev":       true,
	"sum":          true,
	"var_pop":      true,
	"var_samp":     true,
	"variance":     true,
}

func (node *FuncExpr) IsAggregate() bool {
	return Aggregates[string(node.Name)]
}

// CaseExpr represents a CASE expression.
type CaseExpr struct {
	Expr  ValExpr
	Whens []*When
	Else  ValExpr
}

func (node *CaseExpr) Format(buf *TrackedBuffer) {
	buf.Myprintf("case ")
	if node.Expr != nil {
		buf.Myprintf("%v ", node.Expr)
	}
	for _, when := range node.Whens {
		buf.Myprintf("%v ", when)
	}
	if node.Else != nil {
		buf.Myprintf("else %v ", node.Else)
	}
	buf.Myprintf("end")
}

// When represents a WHEN sub-expression.
type When struct {
	Cond BoolExpr
	Val  ValExpr
}

func (node *When) Format(buf *TrackedBuffer) {
	buf.Myprintf("when %v then %v", node.Cond, node.Val)
}

// GroupBy represents a GROUP BY clause.
type GroupBy []ValExpr

func (node GroupBy) Format(buf *TrackedBuffer) {
	prefix := " group by "
	for _, n := range node {
		buf.Myprintf("%s%v", prefix, n)
		prefix = ", "
	}
}

// OrderBy represents an ORDER By clause.
type OrderBy []*Order

func (node OrderBy) Format(buf *TrackedBuffer) {
	prefix := " order by "
	for _, n := range node {
		buf.Myprintf("%s%v", prefix, n)
		prefix = ", "
	}
}

// Order represents an ordering expression.
type Order struct {
	Expr      ValExpr
	Direction string
}

// Order.Direction
const (
	AST_ASC  = "asc"
	AST_DESC = "desc"
)

func (node *Order) Format(buf *TrackedBuffer) {
	buf.Myprintf("%v %s", node.Expr, node.Direction)
}

// Limit represents a LIMIT clause.
type Limit struct {
	Offset, Rowcount ValExpr
}

func (node *Limit) Format(buf *TrackedBuffer) {
	if node == nil {
		return
	}
	buf.Myprintf(" limit ")
	if node.Offset != nil {
		buf.Myprintf("%v, ", node.Offset)
	}
	buf.Myprintf("%v", node.Rowcount)
}

// Limits returns the values of the LIMIT clause as interfaces.
// The returned values can be nil for absent field, string for
// bind variable names, or int64 for an actual number.
// Otherwise, it's an error.
func (node *Limit) Limits() (offset, rowcount interface{}, err error) {
	if node == nil {
		return nil, nil, nil
	}
	switch v := node.Offset.(type) {
	case NumVal:
		o, err := strconv.ParseInt(string(v), 0, 64)
		if err != nil {
			return nil, nil, err
		}
		if o < 0 {
			return nil, nil, fmt.Errorf("negative offset: %d", o)
		}
		offset = o
	case ValArg:
		offset = string(v)
	case nil:
		// pass
	default:
		return nil, nil, fmt.Errorf("unexpected node for offset: %+v", v)
	}
	switch v := node.Rowcount.(type) {
	case NumVal:
		rc, err := strconv.ParseInt(string(v), 0, 64)
		if err != nil {
			return nil, nil, err
		}
		if rc < 0 {
			return nil, nil, fmt.Errorf("negative limit: %d", rc)
		}
		rowcount = rc
	case ValArg:
		rowcount = string(v)
	default:
		return nil, nil, fmt.Errorf("unexpected node for rowcount: %+v", v)
	}
	return offset, rowcount, nil
}

// Values represents a VALUES clause.
type Values []RowTuple

func (node Values) Format(buf *TrackedBuffer) {
	prefix := "values "
	for _, n := range node {
		buf.Myprintf("%s%v", prefix, n)
		prefix = ", "
	}
}

// RowTuple represents a row of values. It can be ValTuple, Subquery.
type RowTuple interface {
	IRowTuple()
	ValExpr
}

func (ValTuple) IRowTuple()  {}
func (*Subquery) IRowTuple() {}

// UpdateExprs represents a list of update expressions.
type UpdateExprs []*UpdateExpr

func (node UpdateExprs) Format(buf *TrackedBuffer) {
	var prefix string
	for _, n := range node {
		buf.Myprintf("%s%v", prefix, n)
		prefix = ", "
	}
}

// UpdateExpr represents an update expression.
type UpdateExpr struct {
	Name *ColName
	Expr ValExpr
}

func (node *UpdateExpr) Format(buf *TrackedBuffer) {
	buf.Myprintf("%v = %v", node.Name, node.Expr)
}

// OnDup represents an ON DUPLICATE KEY clause.
type OnDup UpdateExprs

func (node OnDup) Format(buf *TrackedBuffer) {
	if node == nil {
		return
	}
	buf.Myprintf(" on duplicate key update %v", UpdateExprs(node))
}


================================================
FILE: sqlparser/fuzz.go
================================================
package sqlparser

func Fuzz(data []byte) int {
	_, err := Parse(string(data))
	if err != nil {
		return 0
	}
	return 1
}


================================================
FILE: sqlparser/parsed_query.go
================================================
// Copyright 2012, Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package sqlparser

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"

	"github.com/dinedal/textql/sqlparser/sqltypes"
)

type bindLocation struct {
	offset, length int
}

type ParsedQuery struct {
	Query         string
	bindLocations []bindLocation
}

type EncoderFunc func(value interface{}) ([]byte, error)

func (pq *ParsedQuery) GenerateQuery(bindVariables map[string]interface{}) ([]byte, error) {
	if len(pq.bindLocations) == 0 {
		return []byte(pq.Query), nil
	}
	buf := bytes.NewBuffer(make([]byte, 0, len(pq.Query)))
	current := 0
	for _, loc := range pq.bindLocations {
		buf.WriteString(pq.Query[current:loc.offset])
		name := pq.Query[loc.offset : loc.offset+loc.length]
		supplied, _, err := FetchBindVar(name, bindVariables)
		if err != nil {
			return nil, err
		}
		if err := EncodeValue(buf, supplied); err != nil {
			return nil, err
		}
		current = loc.offset + loc.length
	}
	buf.WriteString(pq.Query[current:])
	return buf.Bytes(), nil
}

func (pq *ParsedQuery) MarshalJSON() ([]byte, error) {
	return json.Marshal(pq.Query)
}

func EncodeValue(buf *bytes.Buffer, value interface{}) error {
	switch bindVal := value.(type) {
	case nil:
		buf.WriteString("null")
	case []sqltypes.Value:
		for i := 0; i < len(bindVal); i++ {
			if i != 0 {
				buf.WriteString(", ")
			}
			if err := EncodeValue(buf, bindVal[i]); err != nil {
				return err
			}
		}
	case [][]sqltypes.Value:
		for i := 0; i < len(bindVal); i++ {
			if i != 0 {
				buf.WriteString(", ")
			}
			buf.WriteByte('(')
			if err := EncodeValue(buf, bindVal[i]); err != nil {
				return err
			}
			buf.WriteByte(')')
		}
	case []interface{}:
		buf.WriteByte('(')
		for i, v := range bindVal {
			if i != 0 {
				buf.WriteString(", ")
			}
			if err := EncodeValue(buf, v); err != nil {
				return err
			}
		}
		buf.WriteByte(')')
	case TupleEqualityList:
		if err := bindVal.Encode(buf); err != nil {
			return err
		}
	default:
		v, err := sqltypes.BuildValue(bindVal)
		if err != nil {
			return err
		}
		v.EncodeSql(buf)
	}
	return nil
}

type TupleEqualityList struct {
	Columns []string
	Rows    [][]sqltypes.Value
}

func (tpl *TupleEqualityList) Encode(buf *bytes.Buffer) error {
	if len(tpl.Rows) == 0 {
		return errors.New("cannot encode with 0 rows")
	}
	if len(tpl.Columns) == 1 {
		return tpl.encodeAsIN(buf)
	}
	return tpl.encodeAsEquality(buf)
}

func (tpl *TupleEqualityList) encodeAsIN(buf *bytes.Buffer) error {
	buf.WriteString(tpl.Columns[0])
	buf.WriteString(" in (")
	for i, r := range tpl.Rows {
		if len(r) != 1 {
			return errors.New("values don't match column count")
		}
		if i != 0 {
			buf.WriteString(", ")
		}
		if err := EncodeValue(buf, r); err != nil {
			return err
		}
	}
	buf.WriteByte(')')
	return nil
}

func (tpl *TupleEqualityList) encodeAsEquality(buf *bytes.Buffer) error {
	for i, r := range tpl.Rows {
		if i != 0 {
			buf.WriteString(" or ")
		}
		buf.WriteString("(")
		for j, c := range tpl.Columns {
			if j != 0 {
				buf.WriteString(" and ")
			}
			buf.WriteString(c)
			buf.WriteString(" = ")
			if err := EncodeValue(buf, r[j]); err != nil {
				return err
			}
		}
		buf.WriteByte(')')
	}
	return nil
}

func FetchBindVar(name string, bindVariables map[string]interface{}) (val interface{}, isList bool, err error) {
	name = name[1:]
	if name[0] == ':' {
		name = name[1:]
		isList = true
	}
	supplied, ok := bindVariables[name]
	if !ok {
		return nil, false, fmt.Errorf("missing bind var %s", name)
	}
	list, gotList := supplied.([]interface{})
	if isList {
		if !gotList {
			return nil, false, fmt.Errorf("unexpected list arg type %T for key %s", supplied, name)
		}
		if len(list) == 0 {
			return nil, false, fmt.Errorf("empty list supplied for %s", name)
		}
		return list, true, nil
	}
	if gotList {
		return nil, false, fmt.Errorf("unexpected arg type %T for key %s", supplied, name)
	}
	return supplied, false, nil
}


================================================
FILE: sqlparser/sql.go
================================================
//line sql.y:6
package sqlparser

import __yyfmt__ "fmt"

//line sql.y:6
import "bytes"

func SetParseTree(yylex interface{}, stmt Statement) {
	yylex.(*Tokenizer).ParseTree = stmt
}

func SetAllowComments(yylex interface{}, allow bool) {
	yylex.(*Tokenizer).AllowComments = allow
}

func ForceEOF(yylex interface{}) {
	yylex.(*Tokenizer).ForceEOF = true
}

var (
	SHARE        = []byte("share")
	MODE         = []byte("mode")
	IF_BYTES     = []byte("if")
	VALUES_BYTES = []byte("values")
)

//line sql.y:31
type yySymType struct {
	yys         int
	empty       struct{}
	statement   Statement
	selStmt     SelectStatement
	byt         byte
	bytes       []byte
	bytes2      [][]byte
	str         string
	selectExprs SelectExprs
	selectExpr  SelectExpr
	columns     Columns
	colName     *ColName
	tableExprs  TableExprs
	tableExpr   TableExpr
	smTableExpr SimpleTableExpr
	tableName   *TableName
	indexHints  *IndexHints
	expr        Expr
	boolExpr    BoolExpr
	valExpr     ValExpr
	colTuple    ColTuple
	valExprs    ValExprs
	values      Values
	rowTuple    RowTuple
	subquery    *Subquery
	caseExpr    *CaseExpr
	whens       []*When
	when        *When
	orderBy     OrderBy
	order       *Order
	limit       *Limit
	insRows     InsertRows
	updateExprs UpdateExprs
	updateExpr  *UpdateExpr
}

const LEX_ERROR = 57346
const SELECT = 57347
const INSERT = 57348
const UPDATE = 57349
const DELETE = 57350
const FROM = 57351
const WHERE = 57352
const GROUP = 57353
const HAVING = 57354
const ORDER = 57355
const BY = 57356
const LIMIT = 57357
const FOR = 57358
const ALL = 57359
const DISTINCT = 57360
const AS = 57361
const EXISTS = 57362
const IN = 57363
const IS = 57364
const LIKE = 57365
const BETWEEN = 57366
const NULL = 57367
const ASC = 57368
const DESC = 57369
const VALUES = 57370
const INTO = 57371
const DUPLICATE = 57372
const KEY = 57373
const DEFAULT = 57374
const SET = 57375
const LOCK = 57376
const KEYRANGE = 57377
const ID = 57378
const STRING = 57379
const NUMBER = 57380
const VALUE_ARG = 57381
const LIST_ARG = 57382
const COMMENT = 57383
const LE = 57384
const GE = 57385
const NE = 57386
const NULL_SAFE_EQUAL = 57387
const UNION = 57388
const MINUS = 57389
const EXCEPT = 57390
const INTERSECT = 57391
const JOIN = 57392
const STRAIGHT_JOIN = 57393
const LEFT = 57394
const RIGHT = 57395
const INNER = 57396
const OUTER = 57397
const CROSS = 57398
const NATURAL = 57399
const USE = 57400
const FORCE = 57401
const ON = 57402
const OR = 57403
const AND = 57404
const NOT = 57405
const UNARY = 57406
const CASE = 57407
const WHEN = 57408
const THEN = 57409
const ELSE = 57410
const END = 57411
const CREATE = 57412
const ALTER = 57413
const DROP = 57414
const RENAME = 57415
const ANALYZE = 57416
const TABLE = 57417
const INDEX = 57418
const VIEW = 57419
const TO = 57420
const IGNORE = 57421
const IF = 57422
const UNIQUE = 57423
const USING = 57424
const SHOW = 57425
const DESCRIBE = 57426
const EXPLAIN = 57427

var yyToknames = []string{
	"LEX_ERROR",
	"SELECT",
	"INSERT",
	"UPDATE",
	"DELETE",
	"FROM",
	"WHERE",
	"GROUP",
	"HAVING",
	"ORDER",
	"BY",
	"LIMIT",
	"FOR",
	"ALL",
	"DISTINCT",
	"AS",
	"EXISTS",
	"IN",
	"IS",
	"LIKE",
	"BETWEEN",
	"NULL",
	"ASC",
	"DESC",
	"VALUES",
	"INTO",
	"DUPLICATE",
	"KEY",
	"DEFAULT",
	"SET",
	"LOCK",
	"KEYRANGE",
	"ID",
	"STRING",
	"NUMBER",
	"VALUE_ARG",
	"LIST_ARG",
	"COMMENT",
	"LE",
	"GE",
	"NE",
	"NULL_SAFE_EQUAL",
	"'('",
	"'='",
	"'<'",
	"'>'",
	"'~'",
	"UNION",
	"MINUS",
	"EXCEPT",
	"INTERSECT",
	"','",
	"JOIN",
	"STRAIGHT_JOIN",
	"LEFT",
	"RIGHT",
	"INNER",
	"OUTER",
	"CROSS",
	"NATURAL",
	"USE",
	"FORCE",
	"ON",
	"OR",
	"AND",
	"NOT",
	"'&'",
	"'|'",
	"'^'",
	"'+'",
	"'-'",
	"'*'",
	"'/'",
	"'%'",
	"'.'",
	"UNARY",
	"CASE",
	"WHEN",
	"THEN",
	"ELSE",
	"END",
	"CREATE",
	"ALTER",
	"DROP",
	"RENAME",
	"ANALYZE",
	"TABLE",
	"INDEX",
	"VIEW",
	"TO",
	"IGNORE",
	"IF",
	"UNIQUE",
	"USING",
	"SHOW",
	"DESCRIBE",
	"EXPLAIN",
}
var yyStatenames = []string{}

const yyEofCode = 1
const yyErrCode = 2
const yyMaxDepth = 200

//line yacctab:1
var yyExca = []int{
	-1, 1,
	1, -1,
	-2, 0,
}

const yyNprod = 207
const yyPrivate = 57344

var yyTokenNames []string
var yyStates []string

const yyLast = 678

var yyAct = []int{

	51, 122, 141, 363, 359, 342, 49, 48, 83, 314,
	366, 280, 126, 334, 225, 159, 142, 42, 43, 125,
	3, 163, 205, 174, 332, 60, 47, 90, 138, 381,
	381, 37, 31, 32, 33, 34, 84, 85, 99, 98,
	268, 94, 15, 17, 18, 19, 153, 146, 127, 381,
	86, 340, 128, 91, 196, 29, 320, 91, 91, 219,
	71, 196, 73, 121, 124, 76, 74, 77, 136, 330,
	20, 144, 194, 38, 148, 383, 382, 150, 143, 329,
	132, 154, 195, 328, 147, 230, 231, 232, 233, 234,
	43, 235, 236, 43, 149, 380, 168, 339, 170, 302,
	299, 82, 173, 251, 249, 181, 182, 197, 185, 186,
	187, 188, 189, 190, 191, 192, 171, 172, 167, 304,
	157, 78, 21, 22, 24, 23, 25, 176, 293, 295,
	297, 198, 43, 43, 206, 26, 27, 28, 79, 80,
	81, 206, 183, 255, 241, 99, 98, 152, 215, 109,
	110, 111, 112, 113, 214, 209, 223, 216, 294, 218,
	306, 203, 200, 202, 193, 161, 207, 97, 96, 210,
	274, 111, 112, 113, 99, 98, 98, 198, 227, 211,
	335, 244, 245, 327, 325, 224, 184, 240, 242, 272,
	335, 167, 316, 275, 170, 222, 287, 326, 248, 291,
	285, 288, 243, 43, 176, 286, 290, 169, 160, 144,
	289, 260, 144, 211, 264, 373, 143, 354, 196, 143,
	252, 228, 265, 212, 256, 92, 262, 254, 263, 155,
	129, 352, 278, 250, 258, 230, 231, 232, 233, 234,
	279, 235, 236, 271, 273, 270, 166, 259, 301, 351,
	283, 284, 15, 211, 167, 167, 165, 305, 350, 144,
	144, 310, 31, 32, 33, 34, 143, 312, 177, 317,
	134, 91, 133, 131, 175, 130, 313, 309, 318, 303,
	158, 239, 96, 166, 198, 123, 346, 345, 298, 95,
	322, 59, 296, 165, 321, 324, 277, 276, 238, 323,
	261, 220, 331, 56, 57, 58, 96, 217, 333, 213,
	139, 156, 151, 16, 364, 337, 208, 370, 353, 15,
	137, 247, 379, 341, 338, 266, 29, 178, 348, 179,
	180, 221, 365, 347, 87, 343, 344, 282, 315, 281,
	226, 144, 308, 349, 160, 357, 360, 356, 355, 88,
	140, 367, 367, 367, 361, 384, 378, 362, 15, 36,
	267, 371, 368, 369, 72, 319, 269, 75, 377, 145,
	311, 257, 374, 358, 385, 360, 375, 376, 386, 35,
	388, 387, 389, 253, 201, 144, 54, 390, 135, 391,
	204, 59, 143, 53, 65, 50, 52, 67, 68, 69,
	70, 55, 41, 56, 57, 58, 336, 307, 100, 44,
	292, 164, 46, 229, 162, 40, 63, 237, 93, 30,
	106, 107, 108, 109, 110, 111, 112, 113, 89, 14,
	13, 12, 11, 10, 9, 45, 8, 7, 6, 61,
	62, 39, 5, 4, 2, 1, 66, 54, 0, 0,
	0, 0, 59, 0, 0, 65, 0, 0, 0, 0,
	0, 64, 55, 41, 56, 57, 58, 199, 0, 372,
	0, 0, 0, 46, 0, 0, 0, 63, 0, 0,
	0, 0, 0, 15, 106, 107, 108, 109, 110, 111,
	112, 113, 0, 0, 0, 0, 45, 0, 54, 0,
	61, 62, 39, 59, 0, 0, 65, 66, 0, 0,
	0, 0, 0, 55, 123, 56, 57, 58, 54, 0,
	0, 0, 64, 59, 46, 0, 65, 0, 63, 0,
	0, 0, 0, 55, 123, 56, 57, 58, 0, 0,
	0, 0, 0, 15, 46, 0, 0, 45, 63, 0,
	0, 61, 62, 0, 0, 0, 0, 0, 66, 0,
	0, 0, 0, 59, 0, 0, 65, 45, 0, 0,
	0, 61, 62, 64, 123, 56, 57, 58, 66, 0,
	0, 0, 0, 59, 129, 0, 65, 0, 63, 0,
	0, 0, 0, 64, 123, 56, 57, 58, 0, 0,
	0, 0, 0, 0, 129, 0, 0, 0, 63, 0,
	0, 61, 62, 101, 105, 103, 104, 300, 66, 106,
	107, 108, 109, 110, 111, 112, 113, 0, 0, 0,
	0, 61, 62, 64, 117, 118, 119, 120, 66, 114,
	115, 116, 246, 0, 106, 107, 108, 109, 110, 111,
	112, 113, 0, 64, 0, 0, 0, 0, 0, 0,
	0, 102, 106, 107, 108, 109, 110, 111, 112, 113,
	106, 107, 108, 109, 110, 111, 112, 113,
}
var yyPact = []int{

	37, -1000, -1000, 211, -1000, -1000, -1000, -1000, -1000, -1000,
	-1000, -1000, -1000, -1000, -1000, -1000, 427, -1000, -1000, -1000,
	-1000, -30, -27, 31, 48, 11, -1000, -1000, -1000, -1000,
	353, 317, -1000, -1000, -1000, 308, -1000, 216, -1000, -1000,
	270, 89, 107, 592, -1000, 498, 478, -1000, -1000, -1000,
	558, 229, 227, -1000, 226, 224, -1000, -1000, -1000, -1000,
	-1000, -1000, -1000, -1000, -1000, -1000, 558, 291, 274, 341,
	249, -48, -7, 246, -1000, 4, 246, -1000, 276, -49,
	246, -49, 275, -1000, -1000, -1000, -1000, -1000, 427, 239,
	334, 427, 210, -1000, -1000, 246, -1000, 132, 498, 498,
	558, 228, 306, 558, 558, 117, 558, 558, 558, 558,
	558, 558, 558, 558, -1000, -1000, -1000, -1000, -1000, -1000,
	-1000, -1000, 592, 86, -29, -19, 6, 592, -1000, 538,
	366, 427, -1000, 353, 266, 53, 600, 274, 283, 77,
	274, 158, -1000, 176, -1000, 273, 85, 246, -1000, 271,
	-1000, -34, 265, 311, 129, 246, -1000, 216, -1000, 329,
	498, -1000, 166, 179, 262, 247, 66, -1000, -1000, -1000,
	-1000, -1000, 108, 600, -1000, 538, -1000, -1000, 228, 558,
	558, 600, 574, -1000, 296, 76, 76, 76, 96, 96,
	-1000, -1000, -1000, 246, -1000, -1000, 558, -1000, 600, -1000,
	3, 427, 2, 165, 60, -1000, 498, 201, 249, 264,
	334, 249, 558, -1000, 305, -57, -1000, 157, -1000, 261,
	-1000, -1000, 260, -1000, 334, 327, 323, 107, 210, 210,
	-1000, -1000, 144, 140, 154, 150, 143, 64, -1000, 256,
	29, 252, -1, -1000, 600, 549, 558, -1000, 600, -1000,
	-2, -1000, 266, 35, -1000, 558, 78, 314, 249, 249,
	198, -1000, 325, -1000, 600, -1000, -1000, 126, 246, -1000,
	-37, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 329,
	325, 498, 558, 179, 118, -1000, 141, -1000, 127, -1000,
	-1000, -1000, -1000, -8, -12, -22, -1000, -1000, -1000, -1000,
	558, 600, -1000, -77, -1000, 600, 558, 114, 184, 211,
	124, -4, -1000, 325, 320, 322, 251, -1000, -1000, 250,
	-1000, 327, 320, 107, 163, 498, -1000, -1000, 212, 203,
	185, 600, -1000, 600, -1000, 288, 162, -1000, -1000, -1000,
	249, 320, -1000, 558, 558, -1000, -1000, 325, 298, 107,
	246, 246, 246, 286, 184, -1000, -1000, 414, 160, -1000,
	350, -1000, 320, -1000, 349, 301, -6, -1000, -25, -26,
	348, -1000, 558, 558, -1000, -1000, -1000, 298, -1000, 246,
	-1000, 246, -1000, -1000, 249, 600, -1000, -1000, 246, -1000,
	158, -1000,
}
var yyPgo = []int{

	0, 445, 444, 19, 443, 442, 438, 437, 436, 434,
	433, 432, 431, 430, 429, 379, 428, 419, 313, 31,
	73, 418, 417, 415, 414, 21, 27, 413, 411, 28,
	410, 10, 15, 17, 409, 408, 407, 26, 1, 23,
	12, 406, 6, 396, 25, 395, 7, 393, 390, 22,
	388, 383, 14, 11, 9, 373, 4, 372, 5, 3,
	371, 370, 13, 2, 16, 147, 369, 367, 366, 365,
	364, 360, 0, 8, 359,
}
var yyR1 = []int{

	0, 1, 2, 2, 2, 2, 2, 2, 2, 2,
	2, 2, 2, 2, 4, 3, 3, 5, 5, 6,
	7, 8, 9, 9, 9, 10, 10, 10, 11, 12,
	12, 12, 13, 14, 14, 14, 74, 15, 16, 16,
	17, 17, 17, 17, 17, 18, 18, 19, 19, 20,
	20, 20, 23, 23, 21, 21, 21, 24, 24, 25,
	25, 25, 25, 22, 22, 22, 27, 27, 27, 27,
	27, 27, 27, 27, 27, 28, 28, 28, 29, 29,
	30, 30, 30, 30, 31, 31, 26, 26, 32, 32,
	33, 33, 33, 33, 33, 34, 34, 34, 34, 34,
	34, 34, 34, 34, 34, 34, 35, 35, 35, 35,
	35, 35, 35, 39, 39, 39, 44, 40, 40, 38,
	38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
	38, 38, 38, 38, 38, 38, 43, 43, 45, 45,
	45, 47, 50, 50, 48, 48, 49, 51, 51, 46,
	46, 37, 37, 37, 37, 52, 52, 53, 53, 54,
	54, 55, 55, 56, 57, 57, 57, 58, 58, 58,
	59, 59, 59, 60, 60, 61, 61, 62, 62, 36,
	36, 41, 41, 42, 42, 63, 63, 64, 65, 65,
	66, 66, 67, 67, 68, 68, 68, 68, 68, 69,
	69, 70, 70, 71, 71, 72, 73,
}
var yyR2 = []int{

	0, 1, 1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 9, 11, 3, 7, 7, 8,
	7, 3, 5, 8, 4, 6, 7, 4, 5, 4,
	5, 5, 3, 2, 2, 2, 0, 2, 0, 2,
	1, 2, 1, 1, 1, 0, 1, 1, 3, 1,
	2, 3, 1, 1, 0, 1, 2, 1, 3, 3,
	3, 3, 5, 0, 1, 2, 1, 1, 2, 3,
	2, 3, 2, 2, 2, 1, 3, 1, 1, 3,
	0, 5, 5, 5, 1, 3, 0, 2, 0, 2,
	1, 3, 3, 2, 3, 3, 3, 4, 3, 4,
	5, 6, 3, 4, 2, 6, 1, 1, 1, 1,
	1, 1, 1, 3, 1, 1, 3, 1, 3, 1,
	1, 1, 3, 3, 3, 3, 3, 3, 3, 3,
	2, 3, 4, 5, 4, 1, 1, 1, 1, 1,
	1, 5, 0, 1, 1, 2, 4, 0, 2, 1,
	3, 1, 1, 1, 1, 0, 3, 0, 2, 0,
	3, 1, 3, 2, 0, 1, 1, 0, 2, 4,
	0, 2, 4, 0, 3, 1, 3, 0, 5, 2,
	1, 1, 3, 3, 1, 1, 3, 3, 0, 2,
	0, 3, 0, 1, 1, 1, 1, 1, 1, 0,
	1, 0, 1, 0, 2, 1, 0,
}
var yyChk = []int{

	-1000, -1, -2, -3, -4, -5, -6, -7, -8, -9,
	-10, -11, -12, -13, -14, 5, -18, 6, 7, 8,
	33, 85, 86, 88, 87, 89, 98, 99, 100, 18,
	-17, 51, 52, 53, 54, -15, -74, -19, -20, 75,
	-23, 36, -33, -38, -34, 69, 46, -37, -46, -42,
	-45, -72, -43, -47, 20, 35, 37, 38, 39, 25,
	-44, 73, 74, 50, 95, 28, 80, -15, -15, -15,
	-15, 90, -70, 92, 96, -67, 92, 94, 90, 90,
	91, 92, 90, -73, -73, -73, -3, 17, -18, -16,
	-26, 55, 9, -21, -72, 19, 36, 78, 68, 67,
	-35, 21, 69, 23, 24, 22, 70, 71, 72, 73,
	74, 75, 76, 77, 47, 48, 49, 42, 43, 44,
	45, -33, -38, 36, -33, -3, -40, -38, -38, 46,
	46, 46, -44, 46, 46, -50, -38, 29, -29, 36,
	9, -63, -64, -46, -72, -66, 95, 91, -72, 90,
	-72, 36, -65, 95, -72, -65, 36, -19, 41, -32,
	10, -20, -24, -25, -28, 46, 36, -44, -72, 75,
	-72, -33, -33, -38, -39, 46, -44, 40, 21, 23,
	24, -38, -38, 25, 69, -38, -38, -38, -38, -38,
	-38, -38, -38, 78, 101, 101, 55, 101, -38, 101,
	-19, 18, -19, -37, -48, -49, 81, -29, 33, 78,
	-29, 55, 47, 36, 69, -72, -73, 36, -73, 93,
	36, 20, 66, -72, -26, -52, 11, -33, 55, -27,
	56, 57, 58, 59, 60, 62, 63, -22, 36, 19,
	-25, 78, -40, -39, -38, -38, 68, 25, -38, 101,
	-19, 101, 55, -51, -49, 83, -33, -60, 33, 46,
	-63, 36, -32, -64, -38, -73, 20, -71, 97, -68,
	88, 86, 32, 87, 13, 36, 36, 36, -73, -32,
	-53, 12, 14, -25, -25, 56, 61, 56, 61, 56,
	56, 56, -30, 64, 94, 65, 36, 101, 36, 101,
	68, -38, 101, -37, 84, -38, 82, -36, 28, -3,
	-63, -61, -46, -32, -54, 13, 66, -72, -73, -69,
	93, -52, -54, -33, -40, 66, 56, 56, 91, 91,
	91, -38, 101, -38, -62, 66, -41, -42, -62, 101,
	55, -54, -58, 15, 14, 36, 36, -53, -58, -33,
	46, 46, 46, 30, 55, -46, -58, -38, -55, -56,
	-38, -73, -54, -59, 16, 34, -31, -72, -31, -31,
	31, -42, 55, 55, -57, 26, 27, -58, 7, 21,
	101, 55, 101, 101, 7, -38, -56, -59, -72, -72,
	-63, -72,
}
var yyDef = []int{

	45, -2, 1, 2, 3, 4, 5, 6, 7, 8,
	9, 10, 11, 12, 13, 36, 0, 36, 36, 36,
	36, 201, 192, 0, 0, 0, 206, 206, 206, 46,
	0, 40, 42, 43, 44, 45, 38, 86, 47, 49,
	54, 205, 52, 53, 90, 0, 0, 119, 120, 121,
	0, 149, 0, 135, 0, 0, 151, 152, 153, 154,
	184, 138, 139, 140, 136, 137, 142, 0, 0, 0,
	0, 190, 0, 0, 202, 0, 0, 193, 0, 188,
	0, 188, 0, 33, 34, 35, 16, 41, 0, 37,
	88, 0, 0, 50, 55, 0, 205, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 106, 107, 108, 109, 110, 111,
	112, 93, 0, 205, 0, 0, 0, 117, 130, 0,
	0, 0, 104, 0, 0, 0, 143, 0, 0, 78,
	0, 21, 185, 0, 149, 0, 0, 0, 206, 0,
	206, 0, 0, 0, 0, 0, 32, 86, 39, 155,
	0, 48, 87, 57, 63, 0, 75, 77, 56, 51,
	150, 91, 92, 95, 96, 0, 114, 115, 0, 0,
	0, 98, 0, 102, 0, 122, 123, 124, 125, 126,
	127, 128, 129, 0, 94, 116, 0, 183, 117, 131,
	0, 0, 0, 0, 147, 144, 0, 173, 0, 0,
	88, 0, 0, 206, 0, 203, 24, 0, 27, 0,
	29, 189, 0, 206, 88, 157, 0, 89, 0, 0,
	66, 67, 0, 0, 0, 0, 0, 80, 64, 0,
	0, 0, 0, 97, 99, 0, 0, 103, 118, 132,
	0, 134, 0, 0, 145, 0, 0, 0, 0, 0,
	88, 79, 159, 186, 187, 22, 191, 0, 0, 206,
	199, 194, 195, 196, 197, 198, 28, 30, 31, 155,
	159, 0, 0, 58, 61, 68, 0, 70, 0, 72,
	73, 74, 59, 0, 0, 0, 65, 60, 76, 113,
	0, 100, 133, 0, 141, 148, 0, 177, 0, 180,
	177, 0, 175, 159, 167, 0, 0, 204, 25, 0,
	200, 157, 167, 158, 156, 0, 69, 71, 0, 0,
	0, 101, 105, 146, 17, 0, 179, 181, 18, 174,
	0, 167, 20, 0, 0, 206, 26, 159, 170, 62,
	0, 0, 0, 0, 0, 176, 19, 168, 160, 161,
	164, 23, 167, 14, 0, 0, 0, 84, 0, 0,
	0, 182, 0, 0, 163, 165, 166, 170, 171, 0,
	81, 0, 82, 83, 0, 169, 162, 15, 0, 85,
	178, 172,
}
var yyTok1 = []int{

	1, 3, 3, 3, 3, 3, 3, 3, 3, 3,
	3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
	3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
	3, 3, 3, 3, 3, 3, 3, 77, 70, 3,
	46, 101, 75, 73, 55, 74, 78, 76, 3, 3,
	3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
	48, 47, 49, 3, 3, 3, 3, 3, 3, 3,
	3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
	3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
	3, 3, 3, 3, 72, 3, 3, 3, 3, 3,
	3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
	3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
	3, 3, 3, 3, 71, 3, 50,
}
var yyTok2 = []int{

	2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
	12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
	22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
	32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
	42, 43, 44, 45, 51, 52, 53, 54, 56, 57,
	58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
	68, 69, 79, 80, 81, 82, 83, 84, 85, 86,
	87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
	97, 98, 99, 100,
}
var yyTok3 = []int{
	0,
}

//line yaccpar:1

/*	parser for yacc output	*/

var yyDebug = 0

type yyLexer interface {
	Lex(lval *yySymType) int
	Error(s string)
}

const yyFlag = -1000

func yyTokname(c int) string {
	// 4 is TOKSTART above
	if c >= 4 && c-4 < len(yyToknames) {
		if yyToknames[c-4] != "" {
			return yyToknames[c-4]
		}
	}
	return __yyfmt__.Sprintf("tok-%v", c)
}

func yyStatname(s int) string {
	if s >= 0 && s < len(yyStatenames) {
		if yyStatenames[s] != "" {
			return yyStatenames[s]
		}
	}
	return __yyfmt__.Sprintf("state-%v", s)
}

func yylex1(lex yyLexer, lval *yySymType) int {
	c := 0
	char := lex.Lex(lval)
	if char <= 0 {
		c = yyTok1[0]
		goto out
	}
	if char < len(yyTok1) {
		c = yyTok1[char]
		goto out
	}
	if char >= yyPrivate {
		if char < yyPrivate+len(yyTok2) {
			c = yyTok2[char-yyPrivate]
			goto out
		}
	}
	for i := 0; i < len(yyTok3); i += 2 {
		c = yyTok3[i+0]
		if c == char {
			c = yyTok3[i+1]
			goto out
		}
	}

out:
	if c == 0 {
		c = yyTok2[1] /* unknown char */
	}
	if yyDebug >= 3 {
		__yyfmt__.Printf("lex %s(%d)\n", yyTokname(c), uint(char))
	}
	return c
}

func yyParse(yylex yyLexer) int {
	var yyn int
	var yylval yySymType
	var yyVAL yySymType
	yyS := make([]yySymType, yyMaxDepth)

	Nerrs := 0   /* number of errors */
	Errflag := 0 /* error recovery flag */
	yystate := 0
	yychar := -1
	yyp := -1
	goto yystack

ret0:
	return 0

ret1:
	return 1

yystack:
	/* put a state and value onto the stack */
	if yyDebug >= 4 {
		__yyfmt__.Printf("char %v in %v\n", yyTokname(yychar), yyStatname(yystate))
	}

	yyp++
	if yyp >= len(yyS) {
		nyys := make([]yySymType, len(yyS)*2)
		copy(nyys, yyS)
		yyS = nyys
	}
	yyS[yyp] = yyVAL
	yyS[yyp].yys = yystate

yynewstate:
	yyn = yyPact[yystate]
	if yyn <= yyFlag {
		goto yydefault /* simple state */
	}
	if yychar < 0 {
		yychar = yylex1(yylex, &yylval)
	}
	yyn += yychar
	if yyn < 0 || yyn >= yyLast {
		goto yydefault
	}
	yyn = yyAct[yyn]
	if yyChk[yyn] == yychar { /* valid shift */
		yychar = -1
		yyVAL = yylval
		yystate = yyn
		if Errflag > 0 {
			Errflag--
		}
		goto yystack
	}

yydefault:
	/* default state action */
	yyn = yyDef[yystate]
	if yyn == -2 {
		if yychar < 0 {
			yychar = yylex1(yylex, &yylval)
		}

		/* look through exception table */
		xi := 0
		for {
			if yyExca[xi+0] == -1 && yyExca[xi+1] == yystate {
				break
			}
			xi += 2
		}
		for xi += 2; ; xi += 2 {
			yyn = yyExca[xi+0]
			if yyn < 0 || yyn == yychar {
				break
			}
		}
		yyn = yyExca[xi+1]
		if yyn < 0 {
			goto ret0
		}
	}
	if yyn == 0 {
		/* error ... attempt to resume parsing */
		switch Errflag {
		case 0: /* brand new error */
			yylex.Error("syntax error")
			Nerrs++
			if yyDebug >= 1 {
				__yyfmt__.Printf("%s", yyStatname(yystate))
				__yyfmt__.Printf(" saw %s\n", yyTokname(yychar))
			}
			fallthrough

		case 1, 2: /* incompletely recovered error ... try again */
			Errflag = 3

			/* find a state where "error" is a legal shift action */
			for yyp >= 0 {
				yyn = yyPact[yyS[yyp].yys] + yyErrCode
				if yyn >= 0 && yyn < yyLast {
					yystate = yyAct[yyn] /* simulate a shift of "error" */
					if yyChk[yystate] == yyErrCode {
						goto yystack
					}
				}

				/* the current p has no shift on "error", pop stack */
				if yyDebug >= 2 {
					__yyfmt__.Printf("error recovery pops state %d\n", yyS[yyp].yys)
				}
				yyp--
			}
			/* there is no state on the stack with an error shift ... abort */
			goto ret1

		case 3: /* no shift yet; clobber input char */
			if yyDebug >= 2 {
				__yyfmt__.Printf("error recovery discards %s\n", yyTokname(yychar))
			}
			if yychar == yyEofCode {
				goto ret1
			}
			yychar = -1
			goto yynewstate /* try again in the same state */
		}
	}

	/* reduction by production yyn */
	if yyDebug >= 2 {
		__yyfmt__.Printf("reduce %v in:\n\t%v\n", yyn, yyStatname(yystate))
	}

	yynt := yyn
	yypt := yyp
	_ = yypt // guard against "declared and not used"

	yyp -= yyR2[yyn]
	yyVAL = yyS[yyp+1]

	/* consult goto table to find next state */
	yyn = yyR1[yyn]
	yyg := yyPgo[yyn]
	yyj := yyg + yyS[yyp].yys + 1

	if yyj >= yyLast {
		yystate = yyAct[yyg]
	} else {
		yystate = yyAct[yyj]
		if yyChk[yystate] != -yyn {
			yystate = yyAct[yyg]
		}
	}
	// dummy call; replaced with literal code
	switch yynt {

	case 1:
		//line sql.y:154
		{
			SetParseTree(yylex, yyS[yypt-0].statement)
		}
	case 2:
		//line sql.y:160
		{
			yyVAL.statement = yyS[yypt-0].selStmt
		}
	case 3:
		//line sql.y:164
		{
			yyVAL.statement = yyS[yypt-0].selStmt
		}
	case 4:
		yyVAL.statement = yyS[yypt-0].statement
	case 5:
		yyVAL.statement = yyS[yypt-0].statement
	case 6:
		yyVAL.statement = yyS[yypt-0].statement
	case 7:
		yyVAL.statement = yyS[yypt-0].statement
	case 8:
		yyVAL.statement = yyS[yypt-0].statement
	case 9:
		yyVAL.statement = yyS[yypt-0].statement
	case 10:
		yyVAL.statement = yyS[yypt-0].statement
	case 11:
		yyVAL.statement = yyS[yypt-0].statement
	case 12:
		yyVAL.statement = yyS[yypt-0].statement
	case 13:
		yyVAL.statement = yyS[yypt-0].statement
	case 14:
		//line sql.y:180
		{
			yyVAL.selStmt = &Select{Comments: nil, Distinct: yyS[yypt-8].str, SelectExprs: yyS[yypt-7].selectExprs, From: NewFrom(AST_FROM, yyS[yypt-6].tableExprs), Where: NewWhere(AST_WHERE, yyS[yypt-5].boolExpr), GroupBy: GroupBy(yyS[yypt-4].valExprs), Having: NewWhere(AST_HAVING, yyS[yypt-3].boolExpr), OrderBy: yyS[yypt-2].orderBy, Limit: yyS[yypt-1].limit, Lock: yyS[yypt-0].str}
		}
	case 15:
		//line sql.y:186
		{
			yyVAL.selStmt = &Select{Comments: Comments(yyS[yypt-9].bytes2), Distinct: yyS[yypt-8].str, SelectExprs: yyS[yypt-7].selectExprs, From: NewFrom(AST_FROM, yyS[yypt-6].tableExprs), Where: NewWhere(AST_WHERE, yyS[yypt-5].boolExpr), GroupBy: GroupBy(yyS[yypt-4].valExprs), Having: NewWhere(AST_HAVING, yyS[yypt-3].boolExpr), OrderBy: yyS[yypt-2].orderBy, Limit: yyS[yypt-1].limit, Lock: yyS[yypt-0].str}
		}
	case 16:
		//line sql.y:190
		{
			yyVAL.selStmt = &Union{Type: yyS[yypt-1].str, Left: yyS[yypt-2].selStmt, Right: yyS[yypt-0].selStmt}
		}
	case 17:
		//line sql.y:196
		{
			yyVAL.statement = &Insert{Comments: Comments(yyS[yypt-5].bytes2), Table: yyS[yypt-3].tableName, Columns: yyS[yypt-2].columns, Rows: yyS[yypt-1].insRows, OnDup: OnDup(yyS[yypt-0].updateExprs)}
		}
	case 18:
		//line sql.y:200
		{
			cols := make(Columns, 0, len(yyS[yypt-1].updateExprs))
			vals := make(ValTuple, 0, len(yyS[yypt-1].updateExprs))
			for _, col := range yyS[yypt-1].updateExprs {
				cols = append(cols, &NonStarExpr{Expr: col.Name})
				vals = append(vals, col.Expr)
			}
			yyVAL.statement = &Insert{Comments: Comments(yyS[yypt-5].bytes2), Table: yyS[yypt-3].tableName, Columns: cols, Rows: Values{vals}, OnDup: OnDup(yyS[yypt-0].updateExprs)}
		}
	case 19:
		//line sql.y:212
		{
			yyVAL.statement = &Update{Comments: Comments(yyS[yypt-6].bytes2), Table: yyS[yypt-5].tableName, Exprs: yyS[yypt-3].updateExprs, Where: NewWhere(AST_WHERE, yyS[yypt-2].boolExpr), OrderBy: yyS[yypt-1].orderBy, Limit: yyS[yypt-0].limit}
		}
	case 20:
		//line sql.y:218
		{
			yyVAL.statement = &Delete{Comments: Comments(yyS[yypt-5].bytes2), Table: yyS[yypt-3].tableName, Where: NewWhere(AST_WHERE, yyS[yypt-2].boolExpr), OrderBy: yyS[yypt-1].orderBy, Limit: yyS[yypt-0].limit}
		}
	case 21:
		//line sql.y:224
		{
			yyVAL.statement = &Set{Comments: Comments(yyS[yypt-1].bytes2), Exprs: yyS[yypt-0].updateExprs}
		}
	case 22:
		//line sql.y:230
		{
			yyVAL.statement = &DDL{Action: AST_CREATE, NewName: yyS[yypt-1].bytes}
		}
	case 23:
		//line sql.y:234
		{
			// Change this to an alter statement
			yyVAL.statement = &DDL{Action: AST_ALTER, Table: yyS[yypt-1].bytes, NewName: yyS[yypt-1].bytes}
		}
	case 24:
		//line sql.y:239
		{
			yyVAL.statement = &DDL{Action: AST_CREATE, NewName: yyS[yypt-1].bytes}
		}
	case 25:
		//line sql.y:245
		{
			yyVAL.statement = &DDL{Action: AST_ALTER, Table: yyS[yypt-2].bytes, NewName: yyS[yypt-2].bytes}
		}
	case 26:
		//line sql.y:249
		{
			// Change this to a rename statement
			yyVAL.statement = &DDL{Action: AST_RENAME, Table: yyS[yypt-3].bytes, NewName: yyS[yypt-0].bytes}
		}
	case 27:
		//line sql.y:254
		{
			yyVAL.statement = &DDL{Action: AST_ALTER, Table: yyS[yypt-1].bytes, NewName: yyS[yypt-1].bytes}
		}
	case 28:
		//line sql.y:260
		{
			yyVAL.statement = &DDL{Action: AST_RENAME, Table: yyS[yypt-2].bytes, NewName: yyS[yypt-0].bytes}
		}
	case 29:
		//line sql.y:266
		{
			yyVAL.statement = &DDL{Action: AST_DROP, Table: yyS[yypt-0].bytes}
		}
	case 30:
		//line sql.y:270
		{
			// Change this to an alter statement
			yyVAL.statement = &DDL{Action: AST_ALTER, Table: yyS[yypt-0].bytes, NewName: yyS[yypt-0].bytes}
		}
	case 31:
		//line sql.y:275
		{
			yyVAL.statement = &DDL{Action: AST_DROP, Table: yyS[yypt-1].bytes}
		}
	case 32:
		//line sql.y:281
		{
			yyVAL.statement = &DDL{Action: AST_ALTER, Table: yyS[yypt-0].bytes, NewName: yyS[yypt-0].bytes}
		}
	case 33:
		//line sql.y:287
		{
			yyVAL.statement = &Other{}
		}
	case 34:
		//line sql.y:291
		{
			yyVAL.statement = &Other{}
		}
	case 35:
		//line sql.y:295
		{
			yyVAL.statement = &Other{}
		}
	case 36:
		//line sql.y:300
		{
			SetAllowComments(yylex, true)
		}
	case 37:
		//line sql.y:304
		{
			yyVAL.bytes2 = yyS[yypt-0].bytes2
			SetAllowComments(yylex, false)
		}
	case 38:
		//line sql.y:310
		{
			yyVAL.bytes2 = nil
		}
	case 39:
		//line sql.y:314
		{
			yyVAL.bytes2 = append(yyS[yypt-1].bytes2, yyS[yypt-0].bytes)
		}
	case 40:
		//line sql.y:320
		{
			yyVAL.str = AST_UNION
		}
	case 41:
		//line sql.y:324
		{
			yyVAL.str = AST_UNION_ALL
		}
	case 42:
		//line sql.y:328
		{
			yyVAL.str = AST_SET_MINUS
		}
	case 43:
		//line sql.y:332
		{
			yyVAL.str = AST_EXCEPT
		}
	case 44:
		//line sql.y:336
		{
			yyVAL.str = AST_INTERSECT
		}
	case 45:
		//line sql.y:341
		{
			yyVAL.str = ""
		}
	case 46:
		//line sql.y:345
		{
			yyVAL.str = AST_DISTINCT
		}
	case 47:
		//line sql.y:351
		{
			yyVAL.selectExprs = SelectExprs{yyS[yypt-0].selectExpr}
		}
	case 48:
		//line sql.y:355
		{
			yyVAL.selectExprs = append(yyVAL.selectExprs, yyS[yypt-0].selectExpr)
		}
	case 49:
		//line sql.y:361
		{
			yyVAL.selectExpr = &StarExpr{}
		}
	case 50:
		//line sql.y:365
		{
			yyVAL.selectExpr = &NonStarExpr{Expr: yyS[yypt-1].expr, As: yyS[yypt-0].bytes}
		}
	case 51:
		//line sql.y:369
		{
			yyVAL.selectExpr = &StarExpr{TableName: yyS[yypt-2].bytes}
		}
	case 52:
		//line sql.y:375
		{
			yyVAL.expr = yyS[yypt-0].boolExpr
		}
	case 53:
		//line sql.y:379
		{
			yyVAL.expr = yyS[yypt-0].valExpr
		}
	case 54:
		//line sql.y:384
		{
			yyVAL.bytes = nil
		}
	case 55:
		//line sql.y:388
		{
			yyVAL.bytes = yyS[yypt-0].bytes
		}
	case 56:
		//line sql.y:392
		{
			yyVAL.bytes = yyS[yypt-0].bytes
		}
	case 57:
		//line sql.y:398
		{
			yyVAL.tableExprs = TableExprs{yyS[yypt-0].tableExpr}
		}
	case 58:
		//line sql.y:402
		{
			yyVAL.tableExprs = append(yyVAL.tableExprs, yyS[yypt-0].tableExpr)
		}
	case 59:
		//line sql.y:408
		{
			yyVAL.tableExpr = &AliasedTableExpr{Expr: yyS[yypt-2].smTableExpr, As: yyS[yypt-1].bytes, Hints: yyS[yypt-0].indexHints}
		}
	case 60:
		//line sql.y:412
		{
			yyVAL.tableExpr = &ParenTableExpr{Expr: yyS[yypt-1].tableExpr}
		}
	case 61:
		//line sql.y:416
		{
			yyVAL.tableExpr = &JoinTableExpr{LeftExpr: yyS[yypt-2].tableExpr, Join: yyS[yypt-1].str, RightExpr: yyS[yypt-0].tableExpr}
		}
	case 62:
		//line sql.y:420
		{
			yyVAL.tableExpr = &JoinTableExpr{LeftExpr: yyS[yypt-4].tableExpr, Join: yyS[yypt-3].str, RightExpr: yyS[yypt-2].tableExpr, On: yyS[yypt-0].boolExpr}
		}
	case 63:
		//line sql.y:425
		{
			yyVAL.bytes = nil
		}
	case 64:
		//line sql.y:429
		{
			yyVAL.bytes = yyS[yypt-0].bytes
		}
	case 65:
		//line sql.y:433
		{
			yyVAL.bytes = yyS[yypt-0].bytes
		}
	case 66:
		//line sql.y:439
		{
			yyVAL.str = AST_JOIN
		}
	case 67:
		//line sql.y:443
		{
			yyVAL.str = AST_STRAIGHT_JOIN
		}
	case 68:
		//line sql.y:447
		{
			yyVAL.str = AST_LEFT_JOIN
		}
	case 69:
		//line sql.y:451
		{
			yyVAL.str = AST_LEFT_JOIN
		}
	case 70:
		//line sql.y:455
		{
			yyVAL.str = AST_RIGHT_JOIN
		}
	case 71:
		//line sql.y:459
		{
			yyVAL.str = AST_RIGHT_JOIN
		}
	case 72:
		//line sql.y:463
		{
			yyVAL.str = AST_JOIN
		}
	case 73:
		//line sql.y:467
		{
			yyVAL.str = AST_CROSS_JOIN
		}
	case 74:
		//line sql.y:471
		{
			yyVAL.str = AST_NATURAL_JOIN
		}
	case 75:
		//line sql.y:477
		{
			yyVAL.smTableExpr = &TableName{Name: yyS[yypt-0].bytes}
		}
	case 76:
		//line sql.y:481
		{
			yyVAL.smTableExpr = &TableName{Qualifier: yyS[yypt-2].bytes, Name: yyS[yypt-0].bytes}
		}
	case 77:
		//line sql.y:485
		{
			yyVAL.smTableExpr = yyS[yypt-0].subquery
		}
	case 78:
		//line sql.y:491
		{
			yyVAL.tableName = &TableName{Name: yyS[yypt-0].bytes}
		}
	case 79:
		//line sql.y:495
		{
			yyVAL.tableName = &TableName{Qualifier: yyS[yypt-2].bytes, Name: yyS[yypt-0].bytes}
		}
	case 80:
		//line sql.y:500
		{
			yyVAL.indexHints = nil
		}
	case 81:
		//line sql.y:504
		{
			yyVAL.indexHints = &IndexHints{Type: AST_USE, Indexes: yyS[yypt-1].bytes2}
		}
	case 82:
		//line sql.y:508
		{
			yyVAL.indexHints = &IndexHints{Type: AST_IGNORE, Indexes: yyS[yypt-1].bytes2}
		}
	case 83:
		//line sql.y:512
		{
			yyVAL.indexHints = &IndexHints{Type: AST_FORCE, Indexes: yyS[yypt-1].bytes2}
		}
	case 84:
		//line sql.y:518
		{
			yyVAL.bytes2 = [][]byte{yyS[yypt-0].bytes}
		}
	case 85:
		//line sql.y:522
		{
			yyVAL.bytes2 = append(yyS[yypt-2].bytes2, yyS[yypt-0].bytes)
		}
	case 86:
		//line sql.y:527
		{
			yyVAL.tableExprs = nil
		}
	case 87:
		//line sql.y:531
		{
			yyVAL.tableExprs = yyS[yypt-0].tableExprs
		}
	case 88:
		//line sql.y:537
		{
			yyVAL.boolExpr = nil
		}
	case 89:
		//line sql.y:541
		{
			yyVAL.boolExpr = yyS[yypt-0].boolExpr
		}
	case 90:
		yyVAL.boolExpr = yyS[yypt-0].boolExpr
	case 91:
		//line sql.y:548
		{
			yyVAL.boolExpr = &AndExpr{Left: yyS[yypt-2].boolExpr, Right: yyS[yypt-0].boolExpr}
		}
	case 92:
		//line sql.y:552
		{
			yyVAL.boolExpr = &OrExpr{Left: yyS[yypt-2].boolExpr, Right: yyS[yypt-0].boolExpr}
		}
	case 93:
		//line sql.y:556
		{
			yyVAL.boolExpr = &NotExpr{Expr: yyS[yypt-0].boolExpr}
		}
	case 94:
		//line sql.y:560
		{
			yyVAL.boolExpr = &ParenBoolExpr{Expr: yyS[yypt-1].boolExpr}
		}
	case 95:
		//line sql.y:566
		{
			yyVAL.boolExpr = &ComparisonExpr{Left: yyS[yypt-2].valExpr, Operator: yyS[yypt-1].str, Right: yyS[yypt-0].valExpr}
		}
	case 96:
		//line sql.y:570
		{
			yyVAL.boolExpr = &ComparisonExpr{Left: yyS[yypt-2].valExpr, Operator: AST_IN, Right: yyS[yypt-0].colTuple}
		}
	case 97:
		//line sql.y:574
		{
			yyVAL.boolExpr = &ComparisonExpr{Left: yyS[yypt-3].valExpr, Operator: AST_NOT_IN, Right: yyS[yypt-0].colTuple}
		}
	case 98:
		//line sql.y:578
		{
			yyVAL.boolExpr = &ComparisonExpr{Left: yyS[yypt-2].valExpr, Operator: AST_LIKE, Right: yyS[yypt-0].valExpr}
		}
	case 99:
		//line sql.y:582
		{
			yyVAL.boolExpr = &ComparisonExpr{Left: yyS[yypt-3].valExpr, Operator: AST_NOT_LIKE, Right: yyS[yypt-0].valExpr}
		}
	case 100:
		//line sql.y:586
		{
			yyVAL.boolExpr = &RangeCond{Left: yyS[yypt-4].valExpr, Operator: AST_BETWEEN, From: yyS[yypt-2].valExpr, To: yyS[yypt-0].valExpr}
		}
	case 101:
		//line sql.y:590
		{
			yyVAL.boolExpr = &RangeCond{Left: yyS[yypt-5].valExpr, Operator: AST_NOT_BETWEEN, From: yyS[yypt-2].valExpr, To: yyS[yypt-0].valExpr}
		}
	case 102:
		//line sql.y:594
		{
			yyVAL.boolExpr = &NullCheck{Operator: AST_IS_NULL, Expr: yyS[yypt-2].valExpr}
		}
	case 103:
		//line sql.y:598
		{
			yyVAL.boolExpr = &NullCheck{Operator: AST_IS_NOT_NULL, Expr: yyS[yypt-3].valExpr}
		}
	case 104:
		//line sql.y:602
		{
			yyVAL.boolExpr = &ExistsExpr{Subquery: yyS[yypt-0].subquery}
		}
	case 105:
		//line sql.y:606
		{
			yyVAL.boolExpr = &KeyrangeExpr{Start: yyS[yypt-3].valExpr, End: yyS[yypt-1].valExpr}
		}
	case 106:
		//line sql.y:612
		{
			yyVAL.str = AST_EQ
		}
	case 107:
		//line sql.y:616
		{
			yyVAL.str = AST_LT
		}
	case 108:
		//line sql.y:620
		{
			yyVAL.str = AST_GT
		}
	case 109:
		//line sql.y:624
		{
			yyVAL.str = AST_LE
		}
	case 110:
		//line sql.y:628
		{
			yyVAL.str = AST_GE
		}
	case 111:
		//line sql.y:632
		{
			yyVAL.str = AST_NE
		}
	case 112:
		//line sql.y:636
		{
			yyVAL.str = AST_NSE
		}
	case 113:
		//line sql.y:642
		{
			yyVAL.colTuple = ValTuple(yyS[yypt-1].valExprs)
		}
	case 114:
		//line sql.y:646
		{
			yyVAL.colTuple = yyS[yypt-0].subquery
		}
	case 115:
		//line sql.y:650
		{
			yyVAL.colTuple = ListArg(yyS[yypt-0].bytes)
		}
	case 116:
		//line sql.y:656
		{
			yyVAL.subquery = &Subquery{yyS[yypt-1].selStmt}
		}
	case 117:
		//line sql.y:662
		{
			yyVAL.valExprs = ValExprs{yyS[yypt-0].valExpr}
		}
	case 118:
		//line sql.y:666
		{
			yyVAL.valExprs = append(yyS[yypt-2].valExprs, yyS[yypt-0].valExpr)
		}
	case 119:
		//line sql.y:672
		{
			yyVAL.valExpr = yyS[yypt-0].valExpr
		}
	case 120:
		//line sql.y:676
		{
			yyVAL.valExpr = yyS[yypt-0].colName
		}
	case 121:
		//line sql.y:680
		{
			yyVAL.valExpr = yyS[yypt-0].rowTuple
		}
	case 122:
		//line sql.y:684
		{
			yyVAL.valExpr = &BinaryExpr{Left: yyS[yypt-2].valExpr, Operator: AST_BITAND, Right: yyS[yypt-0].valExpr}
		}
	case 123:
		//line sql.y:688
		{
			yyVAL.valExpr = &BinaryExpr{Left: yyS[yypt-2].valExpr, Operator: AST_BITOR, Right: yyS[yypt-0].valExpr}
		}
	case 124:
		//line sql.y:692
		{
			yyVAL.valExpr = &BinaryExpr{Left: yyS[yypt-2].valExpr, Operator: AST_BITXOR, Right: yyS[yypt-0].valExpr}
		}
	case 125:
		//line sql.y:696
		{
			yyVAL.valExpr = &BinaryExpr{Left: yyS[yypt-2].valExpr, Operator: AST_PLUS, Right: yyS[yypt-0].valExpr}
		}
	case 126:
		//line sql.y:700
		{
			yyVAL.valExpr = &BinaryExpr{Left: yyS[yypt-2].valExpr, Operator: AST_MINUS, Right: yyS[yypt-0].valExpr}
		}
	case 127:
		//line sql.y:704
		{
			yyVAL.valExpr = &BinaryExpr{Left: yyS[yypt-2].valExpr, Operator: AST_MULT, Right: yyS[yypt-0].valExpr}
		}
	case 128:
		//line sql.y:708
		{
			yyVAL.valExpr = &BinaryExpr{Left: yyS[yypt-2].valExpr, Operator: AST_DIV, Right: yyS[yypt-0].valExpr}
		}
	case 129:
		//line sql.y:712
		{
			yyVAL.valExpr = &BinaryExpr{Left: yyS[yypt-2].valExpr, Operator: AST_MOD, Right: yyS[yypt-0].valExpr}
		}
	case 130:
		//line sql.y:716
		{
			if num, ok := yyS[yypt-0].valExpr.(NumVal); ok {
				switch yyS[yypt-1].byt {
				case '-':
					yyVAL.valExpr = append(NumVal("-"), num...)
				case '+':
					yyVAL.valExpr = num
				default:
					yyVAL.valExpr = &UnaryExpr{Operator: yyS[yypt-1].byt, Expr: yyS[yypt-0].valExpr}
				}
			} else {
				yyVAL.valExpr = &UnaryExpr{Operator: yyS[yypt-1].byt, Expr: yyS[yypt-0].valExpr}
			}
		}
	case 131:
		//line sql.y:731
		{
			yyVAL.valExpr = &FuncExpr{Name: yyS[yypt-2].bytes}
		}
	case 132:
		//line sql.y:735
		{
			yyVAL.valExpr = &FuncExpr{Name: yyS[yypt-3].bytes, Exprs: yyS[yypt-1].selectExprs}
		}
	case 133:
		//line sql.y:739
		{
			yyVAL.valExpr = &FuncExpr{Name: yyS[yypt-4].bytes, Distinct: true, Exprs: yyS[yypt-1].selectExprs}
		}
	case 134:
		//line sql.y:743
		{
			yyVAL.valExpr = &FuncExpr{Name: yyS[yypt-3].bytes, Exprs: yyS[yypt-1].selectExprs}
		}
	case 135:
		//line sql.y:747
		{
			yyVAL.valExpr = yyS[yypt-0].caseExpr
		}
	case 136:
		//line sql.y:753
		{
			yyVAL.bytes = IF_BYTES
		}
	case 137:
		//line sql.y:757
		{
			yyVAL.bytes = VALUES_BYTES
		}
	case 138:
		//line sql.y:763
		{
			yyVAL.byt = AST_UPLUS
		}
	case 139:
		//line sql.y:767
		{
			yyVAL.byt = AST_UMINUS
		}
	case 140:
		//line sql.y:771
		{
			yyVAL.byt = AST_TILDA
		}
	case 141:
		//line sql.y:777
		{
			yyVAL.caseExpr = &CaseExpr{Expr: yyS[yypt-3].valExpr, Whens: yyS[yypt-2].whens, Else: yyS[yypt-1].valExpr}
		}
	case 142:
		//line sql.y:782
		{
			yyVAL.valExpr = nil
		}
	case 143:
		//line sql.y:786
		{
			yyVAL.valExpr = yyS[yypt-0].valExpr
		}
	case 144:
		//line sql.y:792
		{
			yyVAL.whens = []*When{yyS[yypt-0].when}
		}
	case 145:
		//line sql.y:796
		{
			yyVAL.whens = append(yyS[yypt-1].whens, yyS[yypt-0].when)
		}
	case 146:
		//line sql.y:802
		{
			yyVAL.when = &When{Cond: yyS[yypt-2].boolExpr, Val: yyS[yypt-0].valExpr}
		}
	case 147:
		//line sql.y:807
		{
			yyVAL.valExpr = nil
		}
	case 148:
		//line sql.y:811
		{
			yyVAL.valExpr = yyS[yypt-0].valExpr
		}
	case 149:
		//line sql.y:817
		{
			yyVAL.colName = &ColName{Name: yyS[yypt-0].bytes}
		}
	case 150:
		//line sql.y:821
		{
			yyVAL.colName = &ColName{Qualifier: yyS[yypt-2].bytes, Name: yyS[yypt-0].bytes}
		}
	case 151:
		//line sql.y:827
		{
			yyVAL.valExpr = StrVal(yyS[yypt-0].bytes)
		}
	case 152:
		//line sql.y:831
		{
			yyVAL.valExpr = NumVal(yyS[yypt-0].bytes)
		}
	case 153:
		//line sql.y:835
		{
			yyVAL.valExpr = ValArg(yyS[yypt-0].bytes)
		}
	case 154:
		//line sql.y:839
		{
			yyVAL.valExpr = &NullVal{}
		}
	case 155:
		//line sql.y:844
		{
			yyVAL.valExprs = nil
		}
	case 156:
		//line sql.y:848
		{
			yyVAL.valExprs = yyS[yypt-0].valExprs
		}
	case 157:
		//line sql.y:853
		{
			yyVAL.boolExpr = nil
		}
	case 158:
		//line sql.y:857
		{
			yyVAL.boolExpr = yyS[yypt-0].boolExpr
		}
	case 159:
		//line sql.y:862
		{
			yyVAL.orderBy = nil
		}
	case 160:
		//line sql.y:866
		{
			yyVAL.orderBy = yyS[yypt-0].orderBy
		}
	case 161:
		//line sql.y:872
		{
			yyVAL.orderBy = OrderBy{yyS[yypt-0].order}
		}
	case 162:
		//line sql.y:876
		{
			yyVAL.orderBy = append(yyS[yypt-2].orderBy, yyS[yypt-0].order)
		}
	case 163:
		//line sql.y:882
		{
			yyVAL.order = &Order{Expr: yyS[yypt-1].valExpr, Direction: yyS[yypt-0].str}
		}
	case 164:
		//line sql.y:887
		{
			yyVAL.str = AST_ASC
		}
	case 165:
		//line sql.y:891
		{
			yyVAL.str = AST_ASC
		}
	case 166:
		//line sql.y:895
		{
			yyVAL.str = AST_DESC
		}
	case 167:
		//line sql.y:900
		{
			yyVAL.limit = nil
		}
	case 168:
		//line sql.y:904
		{
			yyVAL.limit = &Limit{Rowcount: yyS[yypt-0].valExpr}
		}
	case 169:
		//line sql.y:908
		{
			yyVAL.limit = &Limit{Offset: yyS[yypt-2].valExpr, Rowcount: yyS[yypt-0].valExpr}
		}
	case 170:
		//line sql.y:913
		{
			yyVAL.str = ""
		}
	case 171:
		//line sql.y:917
		{
			yyVAL.str = AST_FOR_UPDATE
		}
	case 172:
		//line sql.y:921
		{
			if !bytes.Equal(yyS[yypt-1].bytes, SHARE) {
				yylex.Error("expecting share")
				return 1
			}
			if !bytes.Equal(yyS[yypt-0].bytes, MODE) {
				yylex.Error("expecting mode")
				return 1
			}
			yyVAL.str = AST_SHARE_MODE
		}
	case 173:
		//line sql.y:934
		{
			yyVAL.columns = nil
		}
	case 174:
		//line sql.y:938
		{
			yyVAL.columns = yyS[yypt-1].columns
		}
	case 175:
		//line sql.y:944
		{
			yyVAL.columns = Columns{&NonStarExpr{Expr: yyS[yypt-0].colName}}
		}
	case 176:
		//line sql.y:948
		{
			yyVAL.columns = append(yyVAL.columns, &NonStarExpr{Expr: yyS[yypt-0].colName})
		}
	case 177:
		//line sql.y:953
		{
			yyVAL.updateExprs = nil
		}
	case 178:
		//line sql.y:957
		{
			yyVAL.updateExprs = yyS[yypt-0].updateExprs
		}
	case 179:
		//line sql.y:963
		{
			yyVAL.insRows = yyS[yypt-0].values
		}
	case 180:
		//line sql.y:967
		{
			yyVAL.insRows = yyS[yypt-0].selStmt
		}
	case 181:
		//line sql.y:973
		{
			yyVAL.values = Values{yyS[yypt-0].rowTuple}
		}
	case 182:
		//line sql.y:977
		{
			yyVAL.values = append(yyS[yypt-2].values, yyS[yypt-0].rowTuple)
		}
	case 183:
		//line sql.y:983
		{
			yyVAL.rowTuple = ValTuple(yyS[yypt-1].valExprs)
		}
	case 184:
		//line sql.y:987
		{
			yyVAL.rowTuple = yyS[yypt-0].subquery
		}
	case 185:
		//line sql.y:993
		{
			yyVAL.updateExprs = UpdateExprs{yyS[yypt-0].updateExpr}
		}
	case 186:
		//line sql.y:997
		{
			yyVAL.updateExprs = append(yyS[yypt-2].updateExprs, yyS[yypt-0].updateExpr)
		}
	case 187:
		//line sql.y:1003
		{
			yyVAL.updateExpr = &UpdateExpr{Name: yyS[yypt-2].colName, Expr: yyS[yypt-0].valExpr}
		}
	case 188:
		//line sql.y:1008
		{
			yyVAL.empty = struct{}{}
		}
	case 189:
		//line sql.y:1010
		{
			yyVAL.empty = struct{}{}
		}
	case 190:
		//line sql.y:1013
		{
			yyVAL.empty = struct{}{}
		}
	case 191:
		//line sql.y:1015
		{
			yyVAL.empty = struct{}{}
		}
	case 192:
		//line sql.y:1018
		{
			yyVAL.empty = struct{}{}
		}
	case 193:
		//line sql.y:1020
		{
			yyVAL.empty = struct{}{}
		}
	case 194:
		//line sql.y:1024
		{
			yyVAL.empty = struct{}{}
		}
	case 195:
		//line sql.y:1026
		{
			yyVAL.empty = struct{}{}
		}
	case 196:
		//line sql.y:1028
		{
			yyVAL.empty = struct{}{}
		}
	case 197:
		//line sql.y:1030
		{
			yyVAL.empty = struct{}{}
		}
	case 198:
		//line sql.y:1032
		{
			yyVAL.empty = struct{}{}
		}
	case 199:
		//line sql.y:1035
		{
			yyVAL.empty = struct{}{}
		}
	case 200:
		//line sql.y:1037
		{
			yyVAL.empty = struct{}{}
		}
	case 201:
		//line sql.y:1040
		{
			yyVAL.empty = struct{}{}
		}
	case 202:
		//line sql.y:1042
		{
			yyVAL.empty = struct{}{}
		}
	case 203:
		//line sql.y:1045
		{
			yyVAL.empty = struct{}{}
		}
	case 204:
		//line sql.y:1047
		{
			yyVAL.empty = struct{}{}
		}
	case 205:
		//line sql.y:1051
		{
			yyVAL.bytes = yyS[yypt-0].bytes
		}
	case 206:
		//line sql.y:1056
		{
			ForceEOF(yylex)
		}
	}
	goto yystack /* stack new state and value */
}


================================================
FILE: sqlparser/sql.y
================================================
// Copyright 2012, Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

%{
package sqlparser

import "bytes"

func SetParseTree(yylex interface{}, stmt Statement) {
  yylex.(*Tokenizer).ParseTree = stmt
}

func SetAllowComments(yylex interface{}, allow bool) {
  yylex.(*Tokenizer).AllowComments = allow
}

func ForceEOF(yylex interface{}) {
  yylex.(*Tokenizer).ForceEOF = true
}

var (
  SHARE =        []byte("share")
  MODE  =        []byte("mode")
  IF_BYTES =     []byte("if")
  VALUES_BYTES = []byte("values")
)

%}

%union {
  empty       struct{}
  statement   Statement
  selStmt     SelectStatement
  byt         byte
  bytes       []byte
  bytes2      [][]byte
  str         string
  selectExprs SelectExprs
  selectExpr  SelectExpr
  columns     Columns
  colName     *ColName
  tableExprs  TableExprs
  tableExpr   TableExpr
  smTableExpr SimpleTableExpr
  tableName   *TableName
  indexHints  *IndexHints
  expr        Expr
  boolExpr    BoolExpr
  valExpr     ValExpr
  colTuple    ColTuple
  valExprs    ValExprs
  values      Values
  rowTuple    RowTuple
  subquery    *Subquery
  caseExpr    *CaseExpr
  whens       []*When
  when        *When
  orderBy     OrderBy
  order       *Order
  limit       *Limit
  insRows     InsertRows
  updateExprs UpdateExprs
  updateExpr  *UpdateExpr
}

%token LEX_ERROR
%token <empty> SELECT INSERT UPDATE DELETE FROM WHERE GROUP HAVING ORDER BY LIMIT FOR
%token <empty> ALL DISTINCT AS EXISTS IN IS LIKE BETWEEN NULL ASC DESC VALUES INTO DUPLICATE KEY DEFAULT SET LOCK KEYRANGE
%token <bytes> ID STRING NUMBER VALUE_ARG LIST_ARG COMMENT
%token <empty> LE GE NE NULL_SAFE_EQUAL
%token <empty> '(' '=' '<' '>' '~'

%left <empty> UNION MINUS EXCEPT INTERSECT
%left <empty> ','
%left <empty> JOIN STRAIGHT_JOIN LEFT RIGHT INNER OUTER CROSS NATURAL USE FORCE
%left <empty> ON
%left <empty> OR
%left <empty> AND
%right <empty> NOT
%left <empty> '&' '|' '^'
%left <empty> '+' '-'
%left <empty> '*' '/' '%'
%nonassoc <empty> '.'
%left <empty> UNARY
%right <empty> CASE, WHEN, THEN, ELSE
%left <empty> END

// DDL Tokens
%token <empty> CREATE ALTER DROP RENAME ANALYZE
%token <empty> TABLE INDEX VIEW TO IGNORE IF UNIQUE USING
%token <empty> SHOW DESCRIBE EXPLAIN

%start any_command

%type <statement> command
%type <selStmt> select_statement
%type <selStmt> missing_select_statement
%type <statement> insert_statement update_statement delete_statement set_statement
%type <statement> create_statement alter_statement rename_statement drop_statement
%type <statement> analyze_statement other_statement
%type <bytes2> comment_opt comment_list
%type <str> union_op
%type <str> distinct_opt
%type <selectExprs> select_expression_list
%type <selectExpr> select_expression
%type <bytes> as_lower_opt as_opt
%type <expr> expression
%type <tableExprs> table_expression_list
%type <tableExpr> table_expression
%type <tableExprs> from_expression_list_opt
%type <str> join_type
%type <smTableExpr> simple_table_expression
%type <tableName> dml_table_expression
%type <indexHints> index_hint_list
%type <bytes2> index_list
%type <boolExpr> where_expression_opt
%type <boolExpr> boolean_expression condition
%type <str> compare
%type <insRows> row_list
%type <valExpr> value value_expression
%type <colTuple> col_tuple
%type <valExprs> value_expression_list
%type <values> tuple_list
%type <rowTuple> row_tuple
%type <bytes> keyword_as_func
%type <subquery> subquery
%type <byt> unary_operator
%type <colName> column_name
%type <caseExpr> case_expression
%type <whens> when_expression_list
%type <when> when_expression
%type <valExpr> value_expression_opt else_expression_opt
%type <valExprs> group_by_opt
%type <boolExpr> having_opt
%type <orderBy> order_by_opt order_list
%type <order> order
%type <str> asc_desc_opt
%type <limit> limit_opt
%type <str> lock_opt
%type <columns> column_list_opt column_list
%type <updateExprs> on_dup_opt
%type <updateExprs> update_list
%type <updateExpr> update_expression
%type <empty> exists_opt not_exists_opt ignore_opt non_rename_operation to_opt constraint_opt using_opt
%type <bytes> sql_id
%type <empty> force_eof


%%

any_command:
  command
  {
    SetParseTree(yylex, $1)
  }

command:
  select_statement
  {
    $$ = $1
  }
| missing_select_statement
  {
    $$ = $1
  }
| insert_statement
| update_statement
| delete_statement
| set_statement
| create_statement
| alter_statement
| rename_statement
| drop_statement
| analyze_statement
| other_statement

missing_select_statement:
  distinct_opt select_expression_list from_expression_list_opt where_expression_opt group_by_opt having_opt order_by_opt limit_opt lock_opt
  {
    $$ = &Select{Comments: nil, Distinct: $1, SelectExprs: $2, From: NewFrom(AST_FROM, $3), Where: NewWhere(AST_WHERE, $4), GroupBy: GroupBy($5), Having: NewWhere(AST_HAVING, $6), OrderBy: $7, Limit: $8, Lock: $9}
  }

select_statement:
  SELECT comment_opt distinct_opt select_expression_list from_expression_list_opt where_expression_opt group_by_opt having_opt order_by_opt limit_opt lock_opt
  {
    $$ = &Select{Comments: Comments($2), Distinct: $3, SelectExprs: $4, From: NewFrom(AST_FROM, $5), Where: NewWhere(AST_WHERE, $6), GroupBy: GroupBy($7), Having: NewWhere(AST_HAVING, $8), OrderBy: $9, Limit: $10, Lock: $11}
  }
| select_statement union_op select_statement %prec UNION
  {
    $$ = &Union{Type: $2, Left: $1, Right: $3}
  }

insert_statement:
  INSERT comment_opt INTO dml_table_expression column_list_opt row_list on_dup_opt
  {
    $$ = &Insert{Comments: Comments($2), Table: $4, Columns: $5, Rows: $6, OnDup: OnDup($7)}
  }
| INSERT comment_opt INTO dml_table_expression SET update_list on_dup_opt
  {
    cols := make(Columns, 0, len($6))
    vals := make(ValTuple, 0, len($6))
    for _, col := range $6 {
      cols = append(cols, &NonStarExpr{Expr: col.Name})
      vals = append(vals, col.Expr)
    }
    $$ = &Insert{Comments: Comments($2), Table: $4, Columns: cols, Rows: Values{vals}, OnDup: OnDup($7)}
  }

update_statement:
  UPDATE comment_opt dml_table_expression SET update_list where_expression_opt order_by_opt limit_opt
  {
    $$ = &Update{Comments: Comments($2), Table: $3, Exprs: $5, Where: NewWhere(AST_WHERE, $6), OrderBy: $7, Limit: $8}
  }

delete_statement:
  DELETE comment_opt FROM dml_table_expression where_expression_opt order_by_opt limit_opt
  {
    $$ = &Delete{Comments: Comments($2), Table: $4, Where: NewWhere(AST_WHERE, $5), OrderBy: $6, Limit: $7}
  }

set_statement:
  SET comment_opt update_list
  {
    $$ = &Set{Comments: Comments($2), Exprs: $3}
  }

create_statement:
  CREATE TABLE not_exists_opt ID force_eof
  {
    $$ = &DDL{Action: AST_CREATE, NewName: $4}
  }
| CREATE constraint_opt INDEX sql_id using_opt ON ID force_eof
  {
    // Change this to an alter statement
    $$ = &DDL{Action: AST_ALTER, Table: $7, NewName: $7}
  }
| CREATE VIEW sql_id force_eof
  {
    $$ = &DDL{Action: AST_CREATE, NewName: $3}
  }

alter_statement:
  ALTER ignore_opt TABLE ID non_rename_operation force_eof
  {
    $$ = &DDL{Action: AST_ALTER, Table: $4, NewName: $4}
  }
| ALTER ignore_opt TABLE ID RENAME to_opt ID
  {
    // Change this to a rename statement
    $$ = &DDL{Action: AST_RENAME, Table: $4, NewName: $7}
  }
| ALTER VIEW sql_id force_eof
  {
    $$ = &DDL{Action: AST_ALTER, Table: $3, NewName: $3}
  }

rename_statement:
  RENAME TABLE ID TO ID
  {
    $$ = &DDL{Action: AST_RENAME, Table: $3, NewName: $5}
  }

drop_statement:
  DROP TABLE exists_opt ID
  {
    $$ = &DDL{Action: AST_DROP, Table: $4}
  }
| DROP INDEX sql_id ON ID
  {
    // Change this to an alter statement
    $$ = &DDL{Action: AST_ALTER, Table: $5, NewName: $5}
  }
| DROP VIEW exists_opt sql_id force_eof
  {
    $$ = &DDL{Action: AST_DROP, Table: $4}
  }

analyze_statement:
  ANALYZE TABLE ID
  {
    $$ = &DDL{Action: AST_ALTER, Table: $3, NewName: $3}
  }

other_statement:
  SHOW force_eof
  {
    $$ = &Other{}
  }
| DESCRIBE force_eof
  {
    $$ = &Other{}
  }
| EXPLAIN force_eof
  {
    $$ = &Other{}
  }

comment_opt:
  {
    SetAllowComments(yylex, true)
  }
  comment_list
  {
    $$ = $2
    SetAllowComments(yylex, false)
  }

comment_list:
  {
    $$ = nil
  }
| comment_list COMMENT
  {
    $$ = append($1, $2)
  }

union_op:
  UNION
  {
    $$ = AST_UNION
  }
| UNION ALL
  {
    $$ = AST_UNION_ALL
  }
| MINUS
  {
    $$ = AST_SET_MINUS
  }
| EXCEPT
  {
    $$ = AST_EXCEPT
  }
| INTERSECT
  {
    $$ = AST_INTERSECT
  }

distinct_opt:
  {
    $$ = ""
  }
| DISTINCT
  {
    $$ = AST_DISTINCT
  }

select_expression_list:
  select_expression
  {
    $$ = SelectExprs{$1}
  }
| select_expression_list ',' select_expression
  {
    $$ = append($$, $3)
  }

select_expression:
  '*'
  {
    $$ = &StarExpr{}
  }
| expression as_lower_opt
  {
    $$ = &NonStarExpr{Expr: $1, As: $2}
  }
| ID '.' '*'
  {
    $$ = &StarExpr{TableName: $1}
  }

expression:
  boolean_expression
  {
    $$ = $1
  }
| value_expression
  {
    $$ = $1
  }

as_lower_opt:
  {
    $$ = nil
  }
| sql_id
  {
    $$ = $1
  }
| AS sql_id
  {
    $$ = $2
  }

table_expression_list:
  table_expression
  {
    $$ = TableExprs{$1}
  }
| table_expression_list ',' table_expression
  {
    $$ = append($$, $3)
  }

table_expression:
  simple_table_expression as_opt index_hint_list
  {
    $$ = &AliasedTableExpr{Expr:$1, As: $2, Hints: $3}
  }
| '(' table_expression ')'
  {
    $$ = &ParenTableExpr{Expr: $2}
  }
| table_expression join_type table_expression %prec JOIN
  {
    $$ = &JoinTableExpr{LeftExpr: $1, Join: $2, RightExpr: $3}
  }
| table_expression join_type table_expression ON boolean_expression %prec JOIN
  {
    $$ = &JoinTableExpr{LeftExpr: $1, Join: $2, RightExpr: $3, On: $5}
  }

as_opt:
  {
    $$ = nil
  }
| ID
  {
    $$ = $1
  }
| AS ID
  {
    $$ = $2
  }

join_type:
  JOIN
  {
    $$ = AST_JOIN
  }
| STRAIGHT_JOIN
  {
    $$ = AST_STRAIGHT_JOIN
  }
| LEFT JOIN
  {
    $$ = AST_LEFT_JOIN
  }
| LEFT OUTER JOIN
  {
    $$ = AST_LEFT_JOIN
  }
| RIGHT JOIN
  {
    $$ = AST_RIGHT_JOIN
  }
| RIGHT OUTER JOIN
  {
    $$ = AST_RIGHT_JOIN
  }
| INNER JOIN
  {
    $$ = AST_JOIN
  }
| CROSS JOIN
  {
    $$ = AST_CROSS_JOIN
  }
| NATURAL JOIN
  {
    $$ = AST_NATURAL_JOIN
  }

simple_table_expression:
ID
  {
    $$ = &TableName{Name: $1}
  }
| ID '.' ID
  {
    $$ = &TableName{Qualifier: $1, Name: $3}
  }
| subquery
  {
    $$ = $1
  }

dml_table_expression:
ID
  {
    $$ = &TableName{Name: $1}
  }
| ID '.' ID
  {
    $$ = &TableName{Qualifier: $1, Name: $3}
  }

index_hint_list:
  {
    $$ = nil
  }
| USE INDEX '(' index_list ')'
  {
    $$ = &IndexHints{Type: AST_USE, Indexes: $4}
  }
| IGNORE INDEX '(' index_list ')'
  {
    $$ = &IndexHints{Type: AST_IGNORE, Indexes: $4}
  }
| FORCE INDEX '(' index_list ')'
  {
    $$ = &IndexHints{Type: AST_FORCE, Indexes: $4}
  }

index_list:
  sql_id
  {
    $$ = [][]byte{$1}
  }
| index_list ',' sql_id
  {
    $$ = append($1, $3)
  }

from_expression_list_opt:
  {
    $$ = nil
  }
| FROM table_expression_list
  {
    $$ = $2
  }


where_expression_opt:
  {
    $$ = nil
  }
| WHERE boolean_expression
  {
    $$ = $2
  }

boolean_expression:
  condition
| boolean_expression AND boolean_expression
  {
    $$ = &AndExpr{Left: $1, Right: $3}
  }
| boolean_expression OR boolean_expression
  {
    $$ = &OrExpr{Left: $1, Right: $3}
  }
| NOT boolean_expression
  {
    $$ = &NotExpr{Expr: $2}
  }
| '(' boolean_expression ')'
  {
    $$ = &ParenBoolExpr{Expr: $2}
  }

condition:
  value_expression compare value_expression
  {
    $$ = &ComparisonExpr{Left: $1, Operator: $2, Right: $3}
  }
| value_expression IN col_tuple
  {
    $$ = &ComparisonExpr{Left: $1, Operator: AST_IN, Right: $3}
  }
| value_expression NOT IN col_tuple
  {
    $$ = &ComparisonExpr{Left: $1, Operator: AST_NOT_IN, Right: $4}
  }
| value_expression LIKE value_expression
  {
    $$ = &ComparisonExpr{Left: $1, Operator: AST_LIKE, Right: $3}
  }
| value_expression NOT LIKE value_expression
  {
    $$ = &ComparisonExpr{Left: $1, Operator: AST_NOT_LIKE, Right: $4}
  }
| value_expression BETWEEN value_expression AND value_expression
  {
    $$ = &RangeCond{Left: $1, Operator: AST_BETWEEN, From: $3, To: $5}
  }
| value_expression NOT BETWEEN value_expression AND value_expression
  {
    $$ = &RangeCond{Left: $1, Operator: AST_NOT_BETWEEN, From: $4, To: $6}
  }
| value_expression IS NULL
  {
    $$ = &NullCheck{Operator: AST_IS_NULL, Expr: $1}
  }
| value_expression IS NOT NULL
  {
    $$ = &NullCheck{Operator: AST_IS_NOT_NULL, Expr: $1}
  }
| EXISTS subquery
  {
    $$ = &ExistsExpr{Subquery: $2}
  }
| KEYRANGE '(' value ',' value ')'
  {
    $$ = &KeyrangeExpr{Start: $3, End: $5}
  }

compare:
  '='
  {
    $$ = AST_EQ
  }
| '<'
  {
    $$ = AST_LT
  }
| '>'
  {
    $$ = AST_GT
  }
| LE
  {
    $$ = AST_LE
  }
| GE
  {
    $$ = AST_GE
  }
| NE
  {
    $$ = AST_NE
  }
| NULL_SAFE_EQUAL
  {
    $$ = AST_NSE
  }

col_tuple:
  '(' value_expression_list ')'
  {
    $$ = ValTuple($2)
  }
| subquery
  {
    $$ = $1
  }
| LIST_ARG
  {
    $$ = ListArg($1)
  }

subquery:
  '(' select_statement ')'
  {
    $$ = &Subquery{$2}
  }

value_expression_list:
  value_expression
  {
    $$ = ValExprs{$1}
  }
| value_expression_list ',' value_expression
  {
    $$ = append($1, $3)
  }

value_expression:
  value
  {
    $$ = $1
  }
| column_name
  {
    $$ = $1
  }
| row_tuple
  {
    $$ = $1
  }
| value_expression '&' value_expression
  {
    $$ = &BinaryExpr{Left: $1, Operator: AST_BITAND, Right: $3}
  }
| value_expression '|' value_expression
  {
    $$ = &BinaryExpr{Left: $1, Operator: AST_BITOR, Right: $3}
  }
| value_expression '^' value_expression
  {
    $$ = &BinaryExpr{Left: $1, Operator: AST_BITXOR, Right: $3}
  }
| value_expression '+' value_expression
  {
    $$ = &BinaryExpr{Left: $1, Operator: AST_PLUS, Right: $3}
  }
| value_expression '-' value_expression
  {
    $$ = &BinaryExpr{Left: $1, Operator: AST_MINUS, Right: $3}
  }
| value_expression '*' value_expression
  {
    $$ = &BinaryExpr{Left: $1, Operator: AST_MULT, Right: $3}
  }
| value_expression '/' value_expression
  {
    $$ = &BinaryExpr{Left: $1, Operator: AST_DIV, Right: $3}
  }
| value_expression '%' value_expression
  {
    $$ = &BinaryExpr{Left: $1, Operator: AST_MOD, Right: $3}
  }
| unary_operator value_expression %prec UNARY
  {
    if num, ok := $2.(NumVal); ok {
      switch $1 {
      case '-':
        $$ = append(NumVal("-"), num...)
      case '+':
        $$ = num
      default:
        $$ = &UnaryExpr{Operator: $1, Expr: $2}
      }
    } else {
      $$ = &UnaryExpr{Operator: $1, Expr: $2}
    }
  }
| sql_id '(' ')'
  {
    $$ = &FuncExpr{Name: $1}
  }
| sql_id '(' select_expression_list ')'
  {
    $$ = &FuncExpr{Name: $1, Exprs: $3}
  }
| sql_id '(' DISTINCT select_expression_list ')'
  {
    $$ = &FuncExpr{Name: $1, Distinct: true, Exprs: $4}
  }
| keyword_as_func '(' select_expression_list ')'
  {
    $$ = &FuncExpr{Name: $1, Exprs: $3}
  }
| case_expression
  {
    $$ = $1
  }

keyword_as_func:
  IF
  {
    $$ = IF_BYTES
  }
| VALUES
  {
    $$ = VALUES_BYTES
  }

unary_operator:
  '+'
  {
    $$ = AST_UPLUS
  }
| '-'
  {
    $$ = AST_UMINUS
  }
| '~'
  {
    $$ = AST_TILDA
  }

case_expression:
  CASE value_expression_opt when_expression_list else_expression_opt END
  {
    $$ = &CaseExpr{Expr: $2, Whens: $3, Else: $4}
  }

value_expression_opt:
  {
    $$ = nil
  }
| value_expression
  {
    $$ = $1
  }

when_expression_list:
  when_expression
  {
    $$ = []*When{$1}
  }
| when_expression_list when_expression
  {
    $$ = append($1, $2)
  }

when_expression:
  WHEN boolean_expression THEN value_expression
  {
    $$ = &When{Cond: $2, Val: $4}
  }

else_expression_opt:
  {
    $$ = nil
  }
| ELSE value_expression
  {
    $$ = $2
  }

column_name:
  sql_id
  {
    $$ = &ColName{Name: $1}
  }
| ID '.' sql_id
  {
    $$ = &ColName{Qualifier: $1, Name: $3}
  }

value:
  STRING
  {
    $$ = StrVal($1)
  }
| NUMBER
  {
    $$ = NumVal($1)
  }
| VALUE_ARG
  {
    $$ = ValArg($1)
  }
| NULL
  {
    $$ = &NullVal{}
  }

group_by_opt:
  {
    $$ = nil
  }
| GROUP BY value_expression_list
  {
    $$ = $3
  }

having_opt:
  {
    $$ = nil
  }
| HAVING boolean_expression
  {
    $$ = $2
  }

order_by_opt:
  {
    $$ = nil
  }
| ORDER BY order_list
  {
    $$ = $3
  }

order_list:
  order
  {
    $$ = OrderBy{$1}
  }
| order_list ',' order
  {
    $$ = append($1, $3)
  }

order:
  value_expression asc_desc_opt
  {
    $$ = &Order{Expr: $1, Direction: $2}
  }

asc_desc_opt:
  {
    $$ = AST_ASC
  }
| ASC
  {
    $$ = AST_ASC
  }
| DESC
  {
    $$ = AST_DESC
  }

limit_opt:
  {
    $$ = nil
  }
| LIMIT value_expression
  {
    $$ = &Limit{Rowcount: $2}
  }
| LIMIT value_expression ',' value_expression
  {
    $$ = &Limit{Offset: $2, Rowcount: $4}
  }

lock_opt:
  {
    $$ = ""
  }
| FOR UPDATE
  {
    $$ = AST_FOR_UPDATE
  }
| LOCK IN sql_id sql_id
  {
    if !bytes.Equal($3, SHARE) {
      yylex.Error("expecting share")
      return 1
    }
    if !bytes.Equal($4, MODE) {
      yylex.Error("expecting mode")
      return 1
    }
    $$ = AST_SHARE_MODE
  }

column_list_opt:
  {
    $$ = nil
  }
| '(' column_list ')'
  {
    $$ = $2
  }

column_list:
  column_name
  {
    $$ = Columns{&NonStarExpr{Expr: $1}}
  }
| column_list ',' column_name
  {
    $$ = append($$, &NonStarExpr{Expr: $3})
  }

on_dup_opt:
  {
    $$ = nil
  }
| ON DUPLICATE KEY UPDATE update_list
  {
    $$ = $5
  }

row_list:
  VALUES tuple_list
  {
    $$ = $2
  }
| select_statement
  {
    $$ = $1
  }

tuple_list:
  row_tuple
  {
    $$ = Values{$1}
  }
| tuple_list ',' row_tuple
  {
    $$ = append($1, $3)
  }

row_tuple:
  '(' value_expression_list ')'
  {
    $$ = ValTuple($2)
  }
| subquery
  {
    $$ = $1
  }

update_list:
  update_expression
  {
    $$ = UpdateExprs{$1}
  }
| update_list ',' update_expression
  {
    $$ = append($1, $3)
  }

update_expression:
  column_name '=' value_expression
  {
    $$ = &UpdateExpr{Name: $1, Expr: $3} 
  }

exists_opt:
  { $$ = struct{}{} }
| IF EXISTS
  { $$ = struct{}{} }

not_exists_opt:
  { $$ = struct{}{} }
| IF NOT EXISTS
  { $$ = struct{}{} }

ignore_opt:
  { $$ = struct{}{} }
| IGNORE
  { $$ = struct{}{} }

non_rename_operation:
  ALTER
  { $$ = struct{}{} }
| DEFAULT
  { $$ = struct{}{} }
| DROP
  { $$ = struct{}{} }
| ORDER
  { $$ = struct{}{} }
| ID
  { $$ = struct{}{} }

to_opt:
  { $$ = struct{}{} }
| TO
  { $$ = struct{}{} }

constraint_opt:
  { $$ = struct{}{} }
| UNIQUE
  { $$ = struct{}{} }

using_opt:
  { $$ = struct{}{} }
| USING sql_id
  { $$ = struct{}{} }

sql_id:
  ID
  {
    $$ = $1
  }

force_eof:
{
  ForceEOF(yylex)
}


================================================
FILE: sqlparser/sql_mod.go
================================================
package sqlparser

// Magicify runs the SQL passed in, and a table name, throught a customized
// TextQL SQL Parser. This provides the following functionality:
//  - Queries that do not start with SELECT are implictly mapped to SELECT statements
//  - Queries that are missing a FROM, have the FROM inserted with tableName
func Magicify(sql string, tableName string) string {
	if tableName == "" {
		return sql
	}

	statement, err := Parse(sql)

	if err != nil {
		return sql
	}

	switch statement := statement.(type) {
	case *Select:
		replaceFromInSelect(statement, tableName)
		return generateQuery(statement)
	default:
		return sql
	}
}

func replaceFromInSelect(statement *Select, tableName string) {
	if statement.From == nil {
		tableName := &TableName{[]byte("[" + tableName + "]"), nil}
		aliasedTableExpr := AliasedTableExpr{tableName, nil, nil}
		tableExprs := TableExprs{&aliasedTableExpr}
		statement.From = &From{Type: AST_FROM, Expr: tableExprs}
	} else {
		for _, expr := range statement.From.Expr {
			switch expr := expr.(type) {
			case *AliasedTableExpr:
				switch subQuery := expr.Expr.(type) {
				case *Subquery:
					switch selectSubQuery := subQuery.Select.(type) {
					case *Select:
						replaceFromInSelect(selectSubQuery, tableName)
					default:
						return
					}
				default:
					return
				}
			default:
				return
			}
		}
	}
}

func generateQuery(statement Statement) string {
	buf := NewTrackedBuffer(nil)
	statement.Format(buf)
	return buf.String()
}


================================================
FILE: sqlparser/sqltypes/sqltypes.go
================================================
// Copyright 2012, Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package sqltypes implements interfaces and types that represent SQL values.
package sqltypes

import (
	"encoding/base64"
	"encoding/gob"
	"encoding/json"
	"fmt"
	"reflect"
	"strconv"
	"time"
	"unsafe"
)

var (
	NULL       = Value{}
	DONTESCAPE = byte(255)
	nullstr    = []byte("null")
)

// BinWriter interface is used for encoding values.
// Types like bytes.Buffer conform to this interface.
// We expect the writer objects to be in-memory buffers.
// So, we don't expect the write operations to fail.
type BinWriter interface {
	Write([]byte) (int, error)
	WriteByte(byte) error
}

// Value can store any SQL value. NULL is stored as nil.
type Value struct {
	Inner InnerValue
}

// Numeric represents non-fractional SQL number.
type Numeric []byte

// Fractional represents fractional types like float and decimal
// It's functionally equivalent to Numeric other than how it's constructed
type Fractional []byte

// String represents any SQL type that needs to be represented using quotes.
type String []byte

// MakeNumeric makes a Numeric from a []byte without validation.
func MakeNumeric(b []byte) Value {
	return Value{Numeric(b)}
}

// MakeFractional makes a Fractional value from a []byte without validation.
func MakeFractional(b []byte) Value {
	return Value{Fractional(b)}
}

// MakeString makes a String value from a []byte.
func MakeString(b []byte) Value {
	return Value{String(b)}
}

// Raw returns the raw bytes. All types are currently implemented as []byte.
func (v Value) Raw() []byte {
	if v.Inner == nil {
		return nil
	}
	return v.Inner.raw()
}

// String returns the raw value as a string
func (v Value) String() string {
	if v.Inner == nil {
		return ""
	}
	return toString(v.Inner.raw())
}

// String force casts a []byte to a string.
// USE AT YOUR OWN RISK
func toString(b []byte) (s string) {
	if len(b) == 0 {
		return ""
	}
	pbytes := (*reflect.SliceHeader)(unsafe.Pointer(&b))
	pstring := (*reflect.StringHeader)(unsafe.Pointer(&s))
	pstring.Data = pbytes.Data
	pstring.Len = pbytes.Len
	return
}

// ParseInt64 will parse a Numeric value into an int64
func (v Value) ParseInt64() (val int64, err error) {
	if v.Inner == nil {
		return 0, fmt.Errorf("value is null")
	}
	n, ok := v.Inner.(Numeric)
	if !ok {
		return 0, fmt.Errorf("value is not Numeric")
	}
	return strconv.ParseInt(string(n.raw()), 10, 64)
}

// ParseUint64 will parse a Numeric value into a uint64
func (v Value) ParseUint64() (val uint64, err error) {
	if v.Inner == nil {
		return 0, fmt.Errorf("value is null")
	}
	n, ok := v.Inner.(Numeric)
	if !ok {
		return 0, fmt.Errorf("value is not Numeric")
	}
	return strconv.ParseUint(string(n.raw()), 10, 64)
}

// ParseFloat64 will parse a Fractional value into an float64
func (v Value) ParseFloat64() (val float64, err error) {
	if v.Inner == nil {
		return 0, fmt.Errorf("value is null")
	}
	n, ok := v.Inner.(Fractional)
	if !ok {
		return 0, fmt.Errorf("value is not Fractional")
	}
	return strconv.ParseFloat(string(n.raw()), 64)
}

// EncodeSql encodes the value into an SQL statement. Can be binary.
func (v Value) EncodeSql(b BinWriter) {
	if v.Inner == nil {
		if _, err := b.Write(nullstr); err != nil {
			panic(err)
		}
	} else {
		v.Inner.encodeSql(b)
	}
}

// EncodeAscii encodes the value using 7-bit clean ascii bytes.
func (v Value) EncodeAscii(b BinWriter) {
	if v.Inner == nil {
		if _, err := b.Write(nullstr); err != nil {
			panic(err)
		}
	} else {
		v.Inner.encodeAscii(b)
	}
}

func (v Value) IsNull() bool {
	return v.Inner == nil
}

func (v Value) IsNumeric() (ok bool) {
	if v.Inner != nil {
		_, ok = v.Inner.(Numeric)
	}
	return ok
}

func (v Value) IsFractional() (ok bool) {
	if v.Inner != nil {
		_, ok = v.Inner.(Fractional)
	}
	return ok
}

func (v Value) IsString() (ok bool) {
	if v.Inner != nil {
		_, ok = v.Inner.(String)
	}
	return ok
}

// MarshalJSON should only be used for testing.
// It's not a complete implementation.
func (v Value) MarshalJSON() ([]byte, error) {
	return json.Marshal(v.Inner)
}

// UnmarshalJSON should only be used for testing.
// It's not a complete implementation.
func (v *Value) UnmarshalJSON(b []byte) error {
	if len(b) == 0 {
		return fmt.Errorf("error unmarshaling empty bytes")
	}
	var val interface{}
	var err error
	switch b[0] {
	case '-':
		var ival int64
		err = json.Unmarshal(b, &ival)
		val = ival
	case '"':
		var bval []byte
		err = json.Unmarshal(b, &bval)
		val = bval
	case 'n': // null
		err = json.Unmarshal(b, &val)
	default:
		var uval uint64
		err = json.Unmarshal(b, &uval)
		val = uval
	}
	if err != nil {
		return err
	}
	*v, err = BuildValue(val)
	return err
}

// InnerValue defines methods that need to be supported by all non-null value types.
type InnerValue interface {
	raw() []byte
	encodeSql(BinWriter)
	encodeAscii(BinWriter)
}

func BuildValue(goval interface{}) (v Value, err error) {
	switch bindVal := goval.(type) {
	case nil:
		// no op
	case int:
		v = Value{Numeric(strconv.AppendInt(nil, int64(bindVal), 10))}
	case int32:
		v = Value{Numeric(strconv.AppendInt(nil, int64(bindVal), 10))}
	case int64:
		v = Value{Numeric(strconv.AppendInt(nil, int64(bindVal), 10))}
	case uint:
		v = Value{Numeric(strconv.AppendUint(nil, uint64(bindVal), 10))}
	case uint32:
		v = Value{Numeric(strconv.AppendUint(nil, uint64(bindVal), 10))}
	case uint64:
		v = Value{Numeric(strconv.AppendUint(nil, uint64(bindVal), 10))}
	case float64:
		v = Value{Fractional(strconv.AppendFloat(nil, bindVal, 'f', -1, 64))}
	case string:
		v = Value{String([]byte(bindVal))}
	case []byte:
		v = Value{String(bindVal)}
	case time.Time:
		v = Value{String([]byte(bindVal.Format("2006-01-02 15:04:05")))}
	case Numeric, Fractional, String:
		v = Value{bindVal.(InnerValue)}
	case Value:
		v = bindVal
	default:
		return Value{}, fmt.Errorf("unsupported bind variable type %T: %v", goval, goval)
	}
	return v, nil
}

// BuildNumeric builds a Numeric type that represents any whole number.
// It normalizes the representation to ensure 1:1 mapping between the
// number and its representation.
func BuildNumeric(val string) (n Value, err error) {
	if val[0] == '-' || val[0] == '+' {
		signed, err := strconv.ParseInt(val, 0, 64)
		if err != nil {
			return Value{}, err
		}
		n = Value{Numeric(strconv.AppendInt(nil, signed, 10))}
	} else {
		unsigned, err := strconv.ParseUint(val, 0, 64)
		if err != nil {
			return Value{}, err
		}
		n = Value{Numeric(strconv.AppendUint(nil, unsigned, 10))}
	}
	return n, nil
}

func (n Numeric) raw() []byte {
	return []byte(n)
}

func (n Numeric) encodeSql(b BinWriter) {
	if _, err := b.Write(n.raw()); err != nil {
		panic(err)
	}
}

func (n Numeric) encodeAscii(b BinWriter) {
	if _, err := b.Write(n.raw()); err != nil {
		panic(err)
	}
}

func (n Numeric) MarshalJSON() ([]byte, error) {
	return n.raw(), nil
}

func (f Fractional) raw() []byte {
	return []byte(f)
}

func (f Fractional) encodeSql(b BinWriter) {
	if _, err := b.Write(f.raw()); err != nil {
		panic(err)
	}
}

func (f Fractional) encodeAscii(b BinWriter) {
	if _, err := b.Write(f.raw()); err != nil {
		panic(err)
	}
}

func (s String) MarshalJSON() ([]byte, error) {
	return json.Marshal(string(s.raw()))
}

func (s String) raw() []byte {
	return []byte(s)
}

func (s String) encodeSql(b BinWriter) {
	writebyte(b, '\'')
	for _, ch := range s.raw() {
		if encodedChar := SqlEncodeMap[ch]; encodedChar == DONTESCAPE {
			writebyte(b, ch)
		} else {
			writebyte(b, '\\')
			writebyte(b, encodedChar)
		}
	}
	writebyte(b, '\'')
}

func (s String) encodeAscii(b BinWriter) {
	writebyte(b, '\'')
	encoder := base64.NewEncoder(base64.StdEncoding, b)
	encoder.Write(s.raw())
	encoder.Close()
	writebyte(b, '\'')
}

func writebyte(b BinWriter, c byte) {
	if err := b.WriteByte(c); err != nil {
		panic(err)
	}
}

// SqlEncodeMap specifies how to escape binary data with '\'.
// Complies to http://dev.mysql.com/doc/refman/5.1/en/string-syntax.html
var SqlEncodeMap [256]byte

// SqlDecodeMap is the reverse of SqlEncodeMap
var SqlDecodeMap [256]byte

var encodeRef = map[byte]byte{
	'\x00': '0',
	'\'':   '\'',
	'"':    '"',
	'\b':   'b',
	'\n':   'n',
	'\r':   'r',
	'\t':   't',
	26:     'Z', // ctl-Z
	'\\':   '\\',
}

func init() {
	for i := range SqlEncodeMap {
		SqlEncodeMap[i] = DONTESCAPE
		SqlDecodeMap[i] = DONTESCAPE
	}
	for i := range SqlEncodeMap {
		if to, ok := encodeRef[byte(i)]; ok {
			SqlEncodeMap[byte(i)] = to
			SqlDecodeMap[to] = byte(i)
		}
	}
	gob.Register(Numeric(nil))
	gob.Register(Fractional(nil))
	gob.Register(String(nil))
}


================================================
FILE: sqlparser/sqltypes/type_test.go
================================================
// Copyright 2012, Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package sqltypes

import (
	"bytes"
	"testing"
	"time"
)

func TestNull(t *testing.T) {
	n := Value{}
	if !n.IsNull() {
		t.Errorf("value is not null")
	}
	if n.String() != "" {
		t.Errorf("Expecting '', got %s", n.String())
	}
	b := bytes.NewBuffer(nil)
	n.EncodeSql(b)
	if b.String() != "null" {
		t.Errorf("Expecting null, got %s", b.String())
	}
	n.EncodeAscii(b)
	if b.String() != "nullnull" {
		t.Errorf("Expecting nullnull, got %s", b.String())
	}
	js, err := n.MarshalJSON()
	if err != nil {
		t.Errorf("Unexpected error: %s", err)
	}
	if string(js) != "null" {
		t.Errorf("Expecting null, received %s", js)
	}
}

func TestNumeric(t *testing.T) {
	n := Value{Numeric([]byte("1234"))}
	b := bytes.NewBuffer(nil)
	n.EncodeSql(b)
	if b.String() != "1234" {
		t.Errorf("Expecting 1234, got %s", b.String())
	}
	n.EncodeAscii(b)
	if b.String() != "12341234" {
		t.Errorf("Expecting 12341234, got %s", b.String())
	}
	js, err := n.MarshalJSON()
	if err != nil {
		t.Errorf("Unexpected error: %s", err)
	}
	if string(js) != "1234" {
		t.Errorf("Expecting 1234, received %s", js)
	}
}

func TestTime(t *testing.T) {
	date := time.Date(1999, 1, 2, 3, 4, 5, 0, time.UTC)
	v, _ := BuildValue(date)
	if !v.IsString() || v.String() != "1999-01-02 03:04:05" {
		t.Errorf("Expecting 1999-01-02 03:04:05, got %s", v.String())
	}

	b := &bytes.Buffer{}
	v.EncodeSql(b)
	if b.String() != "'1999-01-02 03:04:05'" {
		t.Errorf("Expecting '1999-01-02 03:04:05', got %s", b.String())
	}
}

const (
	INVALIDNEG = "-9223372036854775809"
	MINNEG     = "-9223372036854775808"
	MAXPOS     = "18446744073709551615"
	INVALIDPOS = "18446744073709551616"
	NEGFLOAT   = "1.234"
	POSFLOAT   = "-1.234"
)

func TestBuildNumeric(t *testing.T) {
	var n Value
	var err error
	n, err = BuildNumeric(MINNEG)
	if err != nil {
		t.Errorf("Unexpected error: %s", err)
	}
	if n.String() != MINNEG {
		t.Errorf("Expecting %v, received %s", MINNEG, n.Raw())
	}
	n, err = BuildNumeric(MAXPOS)
	if err != nil {
		t.Errorf("Unexpected error: %s", err)
	}
	if n.String() != MAXPOS {
		t.Errorf("Expecting %v, received %s", MAXPOS, n.Raw())
	}
	n, err = BuildNumeric("0xA")
	if err != nil {
		t.Errorf("Unexpected error: %s", err)
	}
	if n.String() != "10" {
		t.Errorf("Expecting %v, received %s", 10, n.Raw())
	}
	n, err = BuildNumeric("012")
	if err != nil {
		t.Errorf("Unexpected error: %s", err)
	}
	if string(n.Raw()) != "10" {
		t.Errorf("Expecting %v, received %s", 10, n.Raw())
	}
	if n, err = BuildNumeric(INVALIDNEG); err == nil {
		t.Errorf("Expecting error")
	}
	if n, err = BuildNumeric(INVALIDPOS); err == nil {
		t.Errorf("Expecting error")
	}
	if n, err = BuildNumeric(NEGFLOAT); err == nil {
		t.Errorf("Expecting error")
	}
	if n, err = BuildNumeric(POSFLOAT); err == nil {
		t.Errorf("Expecting error")
	}
}

const (
	HARDSQL     = "\x00'\"\b\n\r\t\x1A\\"
	HARDESCAPED = "'\\0\\'\\\"\\b\\n\\r\\t\\Z\\\\'"
	HARDASCII   = "'ACciCAoNCRpc'"
)

func TestString(t *testing.T) {
	s := Value{String([]byte(HARDSQL))}
	b := bytes.NewBuffer(nil)
	s.EncodeSql(b)
	if b.String() != HARDESCAPED {
		t.Errorf("Expecting %s, received %s", HARDESCAPED, b.String())
	}
	b = bytes.NewBuffer(nil)
	s.EncodeAscii(b)
	if b.String() != HARDASCII {
		t.Errorf("Expecting %s, received %#v", HARDASCII, b.String())
	}
	s = Value{String([]byte("ab\x01cd"))}
	js, err := s.MarshalJSON()
	if err != nil {
		t.Errorf("Unexpected error: %s", err)
	}
	if got, want := string(js), "\"ab\\u0001cd\""; got != want {
		t.Errorf("%#v.MarshalJSON() = %#v, want %#v", s, got, want)
	}
}

func TestBuildValue(t *testing.T) {
	v, err := BuildValue(nil)
	if err != nil {
		t.Errorf("%v", err)
	}
	if !v.IsNull() {
		t.Errorf("Expecting null")
	}
	n64, err := v.ParseUint64()
	if err == nil || err.Error() != "value is null" {
		t.Errorf("%v", err)
	}
	v, err = BuildValue(int(-1))
	if err != nil {
		t.Errorf("%v", err)
	}
	if !v.IsNumeric() || v.String() != "-1" {
		t.Errorf("Expecting -1, received %T: %s", v.Inner, v.String())
	}
	v, err = BuildValue(int32(-1))
	if err != nil {
		t.Errorf("%v", err)
	}
	if !v.IsNumeric() || v.String() != "-1" {
		t.Errorf("Expecting -1, received %T: %s", v.Inner, v.String())
	}
	v, err = BuildValue(int64(-1))
	if err != nil {
		t.Errorf("%v", err)
	}
	if !v.IsNumeric() || v.String() != "-1" {
		t.Errorf("Expecting -1, received %T: %s", v.Inner, v.String())
	}
	n64, err = v.ParseUint64()
	if err == nil {
		t.Errorf("-1 shouldn't convert into uint64")
	}
	i64, err := v.ParseInt64()
	if i64 != -1 {
		t.Errorf("want -1, got %d", i64)
	}
	if err != nil {
		t.Errorf("%v", err)
	}
	v, err = BuildValue(uint(1))
	if err != nil {
		t.Errorf("%v", err)
	}
	if !v.IsNumeric() || v.String() != "1" {
		t.Errorf("Expecting 1, received %T: %s", v.Inner, v.String())
	}
	v, err = BuildValue(uint32(1))
	if err != nil {
		t.Errorf("%v", err)
	}
	if !v.IsNumeric() || v.String() != "1" {
		t.Errorf("Expecting 1, received %T: %s", v.Inner, v.String())
	}
	v, err = BuildValue(uint64(1))
	if err != nil {
		t.Errorf("%v", err)
	}
	n64, err = v.ParseUint64()
	if err != nil {
		t.Errorf("%v", err)
	}
	if n64 != 1 {
		t.Errorf("Expecting 1, got %v", n64)
	}
	if !v.IsNumeric() || v.String() != "1" {
		t.Errorf("Expecting 1, received %T: %s", v.Inner, v.String())
	}
	v, err = BuildValue(1.23)
	if err != nil {
		t.Errorf("%v", err)
	}
	if !v.IsFractional() || v.String() != "1.23" {
		t.Errorf("Expecting 1.23, received %T: %s", v.Inner, v.String())
	}
	n64, err = v.ParseUint64()
	if err == nil {
		t.Errorf("1.23 shouldn't convert into uint64")
	}
	v, err = BuildValue("abcd")
	if err != nil {
		t.Errorf("%v", err)
	}
	if !v.IsString() || v.String() != "abcd" {
		t.Errorf("Expecting abcd, received %T: %s", v.Inner, v.String())
	}
	v, err = BuildValue([]byte("abcd"))
	if err != nil {
		t.Errorf("%v", err)
	}
	if !v.IsString() || v.String() != "abcd" {
		t.Errorf("Expecting abcd, received %T: %s", v.Inner, v.String())
	}
	n64, err = v.ParseUint64()
	if err == nil || err.Error() != "value is not Numeric" {
		t.Errorf("%v", err)
	}
	v, err = BuildValue(time.Date(2012, time.February, 24, 23, 19, 43, 10, time.UTC))
	if err != nil {
		t.Errorf("%v", err)
	}
	if !v.IsString() || v.String() != "2012-02-24 23:19:43" {
		t.Errorf("Expecting 2012-02-24 23:19:43, received %T: %s", v.Inner, v.String())
	}
	v, err = BuildValue(Numeric([]byte("123")))
	if err != nil {
		t.Errorf("%v", err)
	}
	if !v.IsNumeric() || v.String() != "123" {
		t.Errorf("Expecting 123, received %T: %s", v.Inner, v.String())
	}
	v, err = BuildValue(Fractional([]byte("12.3")))
	if err != nil {
		t.Errorf("%v", err)
	}
	if !v.IsFractional() || v.String() != "12.3" {
		t.Errorf("Expecting 12.3, received %T: %s", v.Inner, v.String())
	}
	v, err = BuildValue(String([]byte("abc")))
	if err != nil {
		t.Errorf("%v", err)
	}
	if !v.IsString() || v.String() != "abc" {
		t.Errorf("Expecting abc, received %T: %s", v.Inner, v.String())
	}
	v, err = BuildValue(float32(1.23))
	if err == nil {
		t.Errorf("Did not receive error")
	}
	v1 := Value{String([]byte("ab"))}
	v, err = BuildValue(v1)
	if err != nil {
		t.Errorf("%v", err)
	}
	if !v.IsString() || v.String() != "ab" {
		t.Errorf("Expecting ab, received %T: %s", v.Inner, v.String())
	}
	v, err = BuildValue(float32(1.23))
	if err == nil {
		t.Errorf("Did not receive error")
	}
}

// Ensure DONTESCAPE is not escaped
func TestEncode(t *testing.T) {
	if SqlEncodeMap[DONTESCAPE] != DONTESCAPE {
		t.Errorf("Encode fail: %v", SqlEncodeMap[DONTESCAPE])
	}
	if SqlDecodeMap[DONTESCAPE] != DONTESCAPE {
		t.Errorf("Decode fail: %v", SqlDecodeMap[DONTESCAPE])
	}
}


================================================
FILE: sqlparser/token.go
================================================
// Copyright 2012, Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package sqlparser

import (
	"bytes"
	"fmt"
	"strings"

	"github.com/dinedal/textql/sqlparser/sqltypes"
)

const EOFCHAR = 0x100

// Tokenizer is the struct used to generate SQL
// tokens for the parser.
type Tokenizer struct {
	InStream      *strings.Reader
	AllowComments bool
	ForceEOF      bool
	lastChar      uint16
	Position      int
	errorToken    []byte
	LastError     string
	posVarIndex   int
	ParseTree     Statement
}

// NewStringTokenizer creates a new Tokenizer for the
// sql string.
func NewStringTokenizer(sql string) *Tokenizer {
	return &Tokenizer{InStream: strings.NewReader(sql)}
}

var keywords = map[string]int{
	"all":           ALL,
	"alter":         ALTER,
	"analyze":       ANALYZE,
	"and":           AND,
	"as":            AS,
	"asc":           ASC,
	"between":       BETWEEN,
	"by":            BY,
	"case":          CASE,
	"create":        CREATE,
	"cross":         CROSS,
	"default":       DEFAULT,
	"delete":        DELETE,
	"desc":          DESC,
	"describe":      DESCRIBE,
	"distinct":      DISTINCT,
	"drop":          DROP,
	"duplicate":     DUPLICATE,
	"else":          ELSE,
	"end":           END,
	"except":        EXCEPT,
	"exists":        EXISTS,
	"explain":       EXPLAIN,
	"for":           FOR,
	"force":         FORCE,
	"from":          FROM,
	"group":         GROUP,
	"having":        HAVING,
	"if":            IF,
	"ignore":        IGNORE,
	"in":            IN,
	"index":         INDEX,
	"inner":         INNER,
	"insert":        INSERT,
	"intersect":     INTERSECT,
	"into":          INTO,
	"is":            IS,
	"join":          JOIN,
	"key":           KEY,
	"keyrange":      KEYRANGE,
	"left":          LEFT,
	"like":          LIKE,
	"limit":         LIMIT,
	"lock":          LOCK,
	"minus":         MINUS,
	"natural":       NATURAL,
	"not":           NOT,
	"null":          NULL,
	"on":            ON,
	"or":            OR,
	"order":         ORDER,
	"outer":         OUTER,
	"rename":        RENAME,
	"right":         RIGHT,
	"select":        SELECT,
	"set":           SET,
	"show":          SHOW,
	"straight_join": STRAIGHT_JOIN,
	"table":         TABLE,
	"then":          THEN,
	"to":            TO,
	"union":         UNION,
	"unique":        UNIQUE,
	"update":        UPDATE,
	"use":           USE,
	"using":         USING,
	"values":        VALUES,
	"view":          VIEW,
	"when":          WHEN,
	"where":         WHERE,
}

// Lex returns the next token form the Tokenizer.
// This function is used by go yacc.
func (tkn *Tokenizer) Lex(lval *yySymType) int {
	typ, val := tkn.Scan()
	for typ == COMMENT {
		if tkn.AllowComments {
			break
		}
		typ, val = tkn.Scan()
	}
	switch typ {
	case ID, STRING, NUMBER, VALUE_ARG, LIST_ARG, COMMENT:
		lval.bytes = val
	}
	tkn.errorToken = val
	return typ
}

// Error is called by go yacc if there's a parsing error.
func (tkn *Tokenizer) Error(err string) {
	buf := bytes.NewBuffer(make([]byte, 0, 32))
	if tkn.errorToken != nil {
		fmt.Fprintf(buf, "%s at position %v near %s", err, tkn.Position, tkn.errorToken)
	} else {
		fmt.Fprintf(buf, "%s at position %v", err, tkn.Position)
	}
	tkn.LastError = buf.String()
}

// Scan scans the tokenizer for the next token and returns
// the token type and an optional value.
func (tkn *Tokenizer) Scan() (int, []byte) {
	if tkn.ForceEOF {
		return 0, nil
	}

	if tkn.lastChar == 0 {
		tkn.next()
	}
	tkn.skipBlank()
	switch ch := tkn.lastChar; {
	case isLetter(ch):
		return tkn.scanIdentifier()
	case isDigit(ch):
		return tkn.scanNumber(false)
	case ch == ':':
		return tkn.scanBindVar()
	default:
		tkn.next()
		switch ch {
		case EOFCHAR:
			return 0, nil
		case '=', ',', ';', '(', ')', '+', '*', '%', '&', '|', '^', '~':
			return int(ch), nil
		case '?':
			tkn.posVarIndex++
			buf := new(bytes.Buffer)
			fmt.Fprintf(buf, ":v%d", tkn.posVarIndex)
			return VALUE_ARG, buf.Bytes()
		case '.':
			if isDigit(tkn.lastChar) {
				return tkn.scanNumber(true)
			} else {
				return int(ch), nil
			}
		case '/':
			switch tkn.lastChar {
			case '/':
				tkn.next()
				return tkn.scanCommentType1("//")
			case '*':
				tkn.next()
				return tkn.scanCommentType2()
			default:
				return int(ch), nil
			}
		case '-':
			if tkn.lastChar == '-' {
				tkn.next()
				return tkn.scanCommentType1("--")
			} else {
				return int(ch), nil
			}
		case '<':
			switch tkn.lastChar {
			case '>':
				tkn.next()
				return NE, nil
			case '=':
				tkn.next()
				switch tkn.lastChar {
				case '>':
					tkn.next()
					return NULL_SAFE_EQUAL, nil
				default:
					return LE, nil
				}
			default:
				return int(ch), nil
			}
		case '>':
			if tkn.lastChar == '=' {
				tkn.next()
				return GE, nil
			} else {
				return int(ch), nil
			}
		case '!':
			if tkn.lastChar == '=' {
				tkn.next()
				return NE, nil
			} else {
				return LEX_ERROR, []byte("!")
			}
		case '\'', '"':
			return tkn.scanString(ch, STRING)
		case '`':
			return tkn.scanLiteralIdentifier()
		default:
			return LEX_ERROR, []byte{byte(ch)}
		}
	}
}

func (tkn *Tokenizer) skipBlank() {
	ch := tkn.lastChar
	for ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t' {
		tkn.next()
		ch = tkn.lastChar
	}
}

func (tkn *Tokenizer) scanIdentifier() (int, []byte) {
	buffer := bytes.NewBuffer(make([]byte, 0, 8))
	buffer.WriteByte(byte(tkn.lastChar))
	for tkn.next(); isLetter(tkn.lastChar) || isDigit(tkn.lastChar); tkn.next() {
		buffer.WriteByte(byte(tkn.lastChar))
	}
	lowered := bytes.ToLower(buffer.Bytes())
	if keywordId, found := keywords[string(lowered)]; found {
		return keywordId, lowered
	}
	return ID, buffer.Bytes()
}

func (tkn *Tokenizer) scanLiteralIdentifier() (int, []byte) {
	buffer := bytes.NewBuffer(make([]byte, 0, 8))
	buffer.WriteByte(byte(tkn.lastChar))
	if !isLetter(tkn.lastChar) {
		return LEX_ERROR, buffer.Bytes()
	}
	for tkn.next(); isLetter(tkn.lastChar) || isDigit(tkn.lastChar); tkn.next() {
		buffer.WriteByte(byte(tkn.lastChar))
	}
	if tkn.lastChar != '`' {
		return LEX_ERROR, buffer.Bytes()
	}
	tkn.next()
	return ID, buffer.Bytes()
}

func (tkn *Tokenizer) scanBindVar() (int, []byte) {
	buffer := bytes.NewBuffer(make([]byte, 0, 8))
	buffer.WriteByte(byte(tkn.lastChar))
	token := VALUE_ARG
	tkn.next()
	if tkn.lastChar == ':' {
		token = LIST_ARG
		buffer.WriteByte(byte(tkn.lastChar))
		tkn.next()
	}
	if !isLetter(tkn.lastChar) {
		return LEX_ERROR, buffer.Bytes()
	}
	for isLetter(tkn.lastChar) || isDigit(tkn.lastChar) || tkn.lastChar == '.' {
		buffer.WriteByte(byte(tkn.lastChar))
		tkn.next()
	}
	return token, buffer.Bytes()
}

func (tkn *Tokenizer) scanMantissa(base int, buffer *bytes.Buffer) {
	for digitVal(tkn.lastChar) < base {
		tkn.ConsumeNext(buffer)
	}
}

func (tkn *Tokenizer) scanNumber(seenDecimalPoint bool) (int, []byte) {
	buffer := bytes.NewBuffer(make([]byte, 0, 8))
	if seenDecimalPoint {
		buffer.WriteByte('.')
		tkn.scanMantissa(10, buffer)
		goto exponent
	}

	if tkn.lastChar == '0' {
		// int or float
		tkn.ConsumeNext(buffer)
		if tkn.lastChar == 'x' || tkn.lastChar == 'X' {
			// hexadecimal int
			tkn.ConsumeNext(buffer)
			tkn.scanMantissa(16, buffer)
		} else {
			// octal int or float
			seenDecimalDigit := false
			tkn.scanMantissa(8, buffer)
			if tkn.lastChar == '8' || tkn.lastChar == '9' {
				// illegal octal int or float
				seenDecimalDigit = true
				tkn.scanMantissa(10, buffer)
			}
			if tkn.lastChar == '.' || tkn.lastChar == 'e' || tkn.lastChar == 'E' {
				goto fraction
			}
			// octal int
			if seenDecimalDigit {
				return LEX_ERROR, buffer.Bytes()
			}
		}
		goto exit
	}

	// decimal int or float
	tkn.scanMantissa(10, buffer)

fraction:
	if tkn.lastChar == '.' {
		tkn.ConsumeNext(buffer)
		tkn.scanMantissa(10, buffer)
	}

exponent:
	if tkn.lastChar == 'e' || tkn.lastChar == 'E' {
		tkn.ConsumeNext(buffer)
		if tkn.lastChar == '+' || tkn.lastChar == '-' {
			tkn.ConsumeNext(buffer)
		}
		tkn.scanMantissa(10, buffer)
	}

exit:
	return NUMBER, buffer.Bytes()
}

func (tkn *Tokenizer) scanString(delim uint16, typ int) (int, []byte) {
	buffer := bytes.NewBuffer(make([]byte, 0, 8))
	for {
		ch := tkn.lastChar
		tkn.next()
		if ch == delim {
			if tkn.lastChar == delim {
				tkn.next()
			} else {
				break
			}
		} else if ch == '\\' {
			if tkn.lastChar == EOFCHAR {
				return LEX_ERROR, buffer.Bytes()
			}
			if decodedChar := sqltypes.SqlDecodeMap[byte(tkn.lastChar)]; decodedChar == sqltypes.DONTESCAPE {
				ch = tkn.lastChar
			} else {
				ch = uint16(decodedChar)
			}
			tkn.next()
		}
		if ch == EOFCHAR {
			return LEX_ERROR, buffer.Bytes()
		}
		buffer.WriteByte(byte(ch))
	}
	return typ, buffer.Bytes()
}

func (tkn *Tokenizer) scanCommentType1(prefix string) (int, []byte) {
	buffer := bytes.NewBuffer(make([]byte, 0, 8))
	buffer.WriteString(prefix)
	for tkn.lastChar != EOFCHAR {
		if tkn.lastChar == '\n' {
			tkn.ConsumeNext(buffer)
			break
		}
		tkn.ConsumeNext(buffer)
	}
	return COMMENT, buffer.Bytes()
}

func (tkn *Tokenizer) scanCommentType2() (int, []byte) {
	buffer := bytes.NewBuffer(make([]byte, 0, 8))
	buffer.WriteString("/*")
	for {
		if tkn.lastChar == '*' {
			tkn.ConsumeNext(buffer)
			if tkn.lastChar == '/' {
				tkn.ConsumeNext(buffer)
				break
			}
			continue
		}
		if tkn.lastChar == EOFCHAR {
			return LEX_ERROR, buffer.Bytes()
		}
		tkn.ConsumeNext(buffer)
	}
	return COMMENT, buffer.Bytes()
}

func (tkn *Tokenizer) ConsumeNext(buffer *bytes.Buffer) {
	if tkn.lastChar == EOFCHAR {
		// This should never happen.
		panic("unexpected EOF")
	}
	buffer.WriteByte(byte(tkn.lastChar))
	tkn.next()
}

func (tkn *Tokenizer) next() {
	if ch, err := tkn.InStream.ReadByte(); err != nil {
		// Only EOF is possible.
		tkn.lastChar = EOFCHAR
	} else {
		tkn.lastChar = uint16(ch)
	}
	tkn.Position++
}

func isLetter(ch uint16) bool {
	return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' || ch == '@'
}

func digitVal(ch uint16) int {
	switch {
	case '0' <= ch && ch <= '9':
		return int(ch) - '0'
	case 'a' <= ch && ch <= 'f':
		return int(ch) - 'a' + 10
	case 'A' <= ch && ch <= 'F':
		return int(ch) - 'A' + 10
	}
	return 16 // larger than any legal digit val
}

func isDigit(ch uint16) bool {
	return '0' <= ch && ch <= '9'
}


================================================
FILE: sqlparser/tracked_buffer.go
================================================
// Copyright 2012, Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package sqlparser

import (
	"bytes"
	"fmt"
)

// TrackedBuffer is used to rebuild a query from the ast.
// bindLocations keeps track of locations in the buffer that
// use bind variables for efficient future substitutions.
// nodeFormatter is the formatting function the buffer will
// use to format a node. By default(nil), it's FormatNode.
// But you can supply a different formatting function if you
// want to generate a query that's different from the default.
type TrackedBuffer struct {
	*bytes.Buffer
	bindLocations []bindLocation
	nodeFormatter func(buf *TrackedBuffer, node SQLNode)
}

func NewTrackedBuffer(nodeFormatter func(buf *TrackedBuffer, node SQLNode)) *TrackedBuffer {
	buf := &TrackedBuffer{
		Buffer:        bytes.NewBuffer(make([]byte, 0, 128)),
		bindLocations: make([]bindLocation, 0, 4),
		nodeFormatter: nodeFormatter,
	}
	return buf
}

// Myprintf mimics fmt.Fprintf(buf, ...), but limited to Node(%v),
// Node.Value(%s) and string(%s). It also allows a %a for a value argument, in
// which case it adds tracking info for future substitutions.
//
// The name must be something other than the usual Printf() to avoid "go vet"
// warnings due to our custom format specifiers.
func (buf *TrackedBuffer) Myprintf(format string, values ...interface{}) {
	end := len(format)
	fieldnum := 0
	for i := 0; i < end; {
		lasti := i
		for i < end && format[i] != '%' {
			i++
		}
		if i > lasti {
			buf.WriteString(format[lasti:i])
		}
		if i >= end {
			break
		}
		i++ // '%'
		switch format[i] {
		case 'c':
			switch v := values[fieldnum].(type) {
			case byte:
				buf.WriteByte(v)
			case rune:
				buf.WriteRune(v)
			default:
				panic(fmt.Sprintf("unexpected type %T", v))
			}
		case 's':
			switch v := values[fieldnum].(type) {
			case []byte:
				buf.Write(v)
			case string:
				buf.WriteString(v)
			default:
				panic(fmt.Sprintf("unexpected type %T", v))
			}
		case 'v':
			node := values[fieldnum].(SQLNode)
			if buf.nodeFormatter == nil {
				node.Format(buf)
			} else {
				buf.nodeFormatter(buf, node)
			}
		case 'a':
			buf.WriteArg(values[fieldnum].(string))
		default:
			panic("unexpected")
		}
		fieldnum++
		i++
	}
}

// WriteArg writes a value argument into the buffer. arg should not contain
// the ':' prefix. It also adds tracking info for future substitutions.
func (buf *TrackedBuffer) WriteArg(arg string) {
	buf.bindLocations = append(buf.bindLocations, bindLocation{
		offset: buf.Len(),
		length: len(arg),
	})
	buf.WriteString(arg)
}

func (buf *TrackedBuffer) ParsedQuery() *ParsedQuery {
	return &ParsedQuery{Query: buf.String(), bindLocations: buf.bindLocations}
}

func (buf *TrackedBuffer) HasBindVars() bool {
	return len(buf.bindLocations) != 0
}


================================================
FILE: sqlparser/y.output
================================================

state 0
	$accept: .any_command $end 
	distinct_opt: .    (45)

	SELECT  shift 15
	INSERT  shift 17
	UPDATE  shift 18
	DELETE  shift 19
	DISTINCT  shift 29
	SET  shift 20
	CREATE  shift 21
	ALTER  shift 22
	DROP  shift 24
	RENAME  shift 23
	ANALYZE  shift 25
	SHOW  shift 26
	DESCRIBE  shift 27
	EXPLAIN  shift 28
	.  reduce 45 (src line 340)

	any_command  goto 1
	command  goto 2
	select_statement  goto 3
	missing_select_statement  goto 4
	insert_statement  goto 5
	update_statement  goto 6
	delete_statement  goto 7
	set_statement  goto 8
	create_statement  goto 9
	alter_statement  goto 10
	rename_statement  goto 11
	drop_statement  goto 12
	analyze_statement  goto 13
	other_statement  goto 14
	distinct_opt  goto 16

state 1
	$accept:  any_command.$end 

	$end  accept
	.  error


state 2
	any_command:  command.    (1)

	.  reduce 1 (src line 152)


state 3
	command:  select_statement.    (2)
	select_statement:  select_statement.union_op select_statement 

	UNION  shift 31
	MINUS  shift 32
	EXCEPT  shift 33
	INTERSECT  shift 34
	.  reduce 2 (src line 158)

	union_op  goto 30

state 4
	command:  missing_select_statement.    (3)

	.  reduce 3 (src line 163)


state 5
	command:  insert_statement.    (4)

	.  reduce 4 (src line 167)


state 6
	command:  update_statement.    (5)

	.  reduce 5 (src line 168)


state 7
	command:  delete_statement.    (6)

	.  reduce 6 (src line 169)


state 8
	command:  set_statement.    (7)

	.  reduce 7 (src line 170)


state 9
	command:  create_statement.    (8)

	.  reduce 8 (src line 171)


state 10
	command:  alter_statement.    (9)

	.  reduce 9 (src line 172)


state 11
	command:  rename_statement.    (10)

	.  reduce 10 (src line 173)


state 12
	command:  drop_statement.    (11)

	.  reduce 11 (src line 174)


state 13
	command:  analyze_statement.    (12)

	.  reduce 12 (src line 175)


state 14
	command:  other_statement.    (13)

	.  reduce 13 (src line 176)


state 15
	select_statement:  SELECT.comment_opt distinct_opt select_expression_list from_expression_list_opt where_expression_opt group_by_opt having_opt order_by_opt limit_opt lock_opt 
	$$36: .    (36)

	.  reduce 36 (src line 299)

	comment_opt  goto 35
	$$36  goto 36

state 16
	missing_select_statement:  distinct_opt.select_expression_list from_expression_list_opt where_expression_opt group_by_opt having_opt order_by_opt limit_opt lock_opt 

	EXISTS  shift 54
	NULL  shift 59
	VALUES  shift 65
	KEYRANGE  shift 55
	ID  shift 41
	STRING  shift 56
	NUMBER  shift 57
	VALUE_ARG  shift 58
	'('  shift 46
	'~'  shift 63
	NOT  shift 45
	'+'  shift 61
	'-'  shift 62
	'*'  shift 39
	CASE  shift 66
	IF  shift 64
	.  error

	select_expression_list  goto 37
	select_expression  goto 38
	expression  goto 40
	boolean_expression  goto 42
	condition  goto 44
	value  goto 47
	value_expression  goto 43
	row_tuple  goto 49
	keyword_as_func  goto 52
	subquery  goto 60
	unary_operator  goto 50
	column_name  goto 48
	case_expression  goto 53
	sql_id  goto 51

state 17
	insert_statement:  INSERT.comment_opt INTO dml_table_expression column_list_opt row_list on_dup_opt 
	insert_statement:  INSERT.comment_opt INTO dml_table_expression SET update_list on_dup_opt 
	$$36: .    (36)

	.  reduce 36 (src line 299)

	comment_opt  goto 67
	$$36  goto 36

state 18
	update_statement:  UPDATE.comment_opt dml_table_expression SET update_list where_expression_opt order_by_opt limit_opt 
	$$36: .    (36)

	.  reduce 36 (src line 299)

	comment_opt  goto 68
	$$36  goto 36

state 19
	delete_statement:  DELETE.comment_opt FROM dml_table_expression where_expression_opt order_by_opt limit_opt 
	$$36: .    (36)

	.  reduce 36 (src line 299)

	comment_opt  goto 69
	$$36  goto 36

state 20
	set_statement:  SET.comment_opt update_list 
	$$36: .    (36)

	.  reduce 36 (src line 299)

	comment_opt  goto 70
	$$36  goto 36

state 21
	create_statement:  CREATE.TABLE not_exists_opt ID force_eof 
	create_statement:  CREATE.constraint_opt INDEX sql_id using_opt ON ID force_eof 
	create_statement:  CREATE.VIEW sql_id force_eof 
	constraint_opt: .    (201)

	TABLE  shift 71
	VIEW  shift 73
	UNIQUE  shift 74
	.  reduce 201 (src line 1039)

	constraint_opt  goto 72

state 22
	alter_statement:  ALTER.ignore_opt TABLE ID non_rename_operation force_eof 
	alter_statement:  ALTER.ignore_opt TABLE ID RENAME to_opt ID 
	alter_statement:  ALTER.VIEW sql_id force_eof 
	ignore_opt: .    (192)

	VIEW  shift 76
	IGNORE  shift 77
	.  reduce 192 (src line 1017)

	ignore_opt  goto 75

state 23
	rename_statement:  RENAME.TABLE ID TO ID 

	TABLE  shift 78
	.  error


state 24
	drop_statement:  DROP.TABLE exists_opt ID 
	drop_statement:  DROP.INDEX sql_id ON ID 
	drop_statement:  DROP.VIEW exists_opt sql_id force_eof 

	TABLE  shift 79
	INDEX  shift 80
	VIEW  shift 81
	.  error


state 25
	analyze_statement:  ANALYZE.TABLE ID 

	TABLE  shift 82
	.  error


state 26
	other_statement:  SHOW.force_eof 
	force_eof: .    (206)

	.  reduce 206 (src line 1055)

	force_eof  goto 83

state 27
	other_statement:  DESCRIBE.force_eof 
	force_eof: .    (206)

	.  reduce 206 (src line 1055)

	force_eof  goto 84

state 28
	other_statement:  EXPLAIN.force_eof 
	force_eof: .    (206)

	.  reduce 206 (src line 1055)

	force_eof  goto 85

state 29
	distinct_opt:  DISTINCT.    (46)

	.  reduce 46 (src line 344)


state 30
	select_statement:  select_statement union_op.select_statement 

	SELECT  shift 15
	.  error

	select_statement  goto 86

state 31
	union_op:  UNION.    (40)
	union_op:  UNION.ALL 

	ALL  shift 87
	.  reduce 40 (src line 318)


state 32
	union_op:  MINUS.    (42)

	.  reduce 42 (src line 327)


state 33
	union_op:  EXCEPT.    (43)

	.  reduce 43 (src line 331)


state 34
	union_op:  INTERSECT.    (44)

	.  reduce 44 (src line 335)


state 35
	select_statement:  SELECT comment_opt.distinct_opt select_expression_list from_expression_list_opt where_expression_opt group_by_opt having_opt order_by_opt limit_opt lock_opt 
	distinct_opt: .    (45)

	DISTINCT  shift 29
	.  reduce 45 (src line 340)

	distinct_opt  goto 8
Download .txt
gitextract_eggpcwiz/

├── .SRCINFO
├── .gitignore
├── .travis.yml
├── Dockerfile
├── Dockerfile.alpine
├── LICENSE
├── Makefile
├── PKGBUILD
├── Readme.md
├── TODO.txt
├── VERSION
├── go.mod
├── go.sum
├── inputs/
│   ├── csv.go
│   ├── csv_test.go
│   └── input.go
├── man/
│   ├── textql.1
│   ├── textql.1.html
│   └── textql.1.ronn
├── outputs/
│   ├── csv.go
│   ├── output.go
│   └── pretty_csv.go
├── snapcraft.yaml
├── sqlparser/
│   ├── Makefile
│   ├── analyzer.go
│   ├── ast.go
│   ├── fuzz.go
│   ├── parsed_query.go
│   ├── sql.go
│   ├── sql.y
│   ├── sql_mod.go
│   ├── sqltypes/
│   │   ├── sqltypes.go
│   │   └── type_test.go
│   ├── token.go
│   ├── tracked_buffer.go
│   └── y.output
├── storage/
│   ├── sqlite.go
│   ├── sqlite_regexp.go
│   ├── sqlite_test.go
│   └── storage.go
├── test_util/
│   └── test_util.go
├── textql/
│   └── main.go
└── util/
    ├── file_helpers.go
    └── seperator_helpers.go
Download .txt
SYMBOL INDEX (518 symbols across 24 files)

FILE: inputs/csv.go
  type CSVInput (line 13) | type CSVInput struct
    method Name (line 64) | func (csvInput *CSVInput) Name() string {
    method SetName (line 69) | func (csvInput *CSVInput) SetName(name string) {
    method ReadRecord (line 83) | func (csvInput *CSVInput) ReadRecord() []string {
    method readHeader (line 111) | func (csvInput *CSVInput) readHeader() error {
    method Header (line 138) | func (csvInput *CSVInput) Header() []string {
  type CSVInputOptions (line 23) | type CSVInputOptions struct
  function NewCSVInput (line 36) | func NewCSVInput(opts *CSVInputOptions) (*CSVInput, error) {

FILE: inputs/csv_test.go
  function TestCSVInputFakesHeader (line 33) | func TestCSVInputFakesHeader(t *testing.T) {
  function TestCSVInputReadsHeader (line 52) | func TestCSVInputReadsHeader(t *testing.T) {
  function TestCSVInputReadsSimple (line 71) | func TestCSVInputReadsSimple(t *testing.T) {
  function TestCSVInputReadsBad (line 95) | func TestCSVInputReadsBad(t *testing.T) {
  function TestCSVInputHasAName (line 125) | func TestCSVInputHasAName(t *testing.T) {

FILE: inputs/input.go
  type Input (line 7) | type Input interface

FILE: outputs/csv.go
  type CSVOutput (line 12) | type CSVOutput struct
    method Show (line 44) | func (csvOutput *CSVOutput) Show(rows *sql.Rows) {
  type CSVOutputOptions (line 22) | type CSVOutputOptions struct
  function NewCSVOutput (line 32) | func NewCSVOutput(opts *CSVOutputOptions) *CSVOutput {

FILE: outputs/output.go
  type Output (line 7) | type Output interface

FILE: outputs/pretty_csv.go
  type PrettyCSVOutput (line 12) | type PrettyCSVOutput struct
    method Show (line 40) | func (prettyCsvOutput *PrettyCSVOutput) Show(rows *sql.Rows) {
  type PrettyCSVOutputOptions (line 22) | type PrettyCSVOutputOptions struct
  function NewPrettyCSVOutput (line 30) | func NewPrettyCSVOutput(opts *PrettyCSVOutputOptions) *PrettyCSVOutput {

FILE: sqlparser/analyzer.go
  function GetTableName (line 17) | func GetTableName(node SimpleTableExpr) string {
  function GetColName (line 27) | func GetColName(node Expr) string {
  function IsColName (line 35) | func IsColName(node ValExpr) bool {
  function IsValue (line 42) | func IsValue(node ValExpr) bool {
  function HasINClause (line 51) | func HasINClause(conditions []BoolExpr) bool {
  function IsSimpleTuple (line 62) | func IsSimpleTuple(node ValExpr) bool {
  function AsInterface (line 82) | func AsInterface(node ValExpr) (interface{}, error) {
  function StringIn (line 114) | func StringIn(str string, values ...string) bool {

FILE: sqlparser/ast.go
  function Parse (line 29) | func Parse(sql string) (Statement, error) {
  type SQLNode (line 39) | type SQLNode interface
  function String (line 44) | func String(node SQLNode) string {
  type Statement (line 51) | type Statement interface
  type SelectStatement (line 66) | type SelectStatement interface
  type Select (line 77) | type Select struct
    method IStatement (line 57) | func (*Select) IStatement() {}
    method ISelectStatement (line 73) | func (*Select) ISelectStatement() {}
    method Format (line 101) | func (node *Select) Format(buf *TrackedBuffer) {
    method IInsertRows (line 149) | func (*Select) IInsertRows() {}
  constant AST_DISTINCT (line 92) | AST_DISTINCT = "distinct "
  constant AST_FOR_UPDATE (line 97) | AST_FOR_UPDATE = " for update"
  constant AST_SHARE_MODE (line 98) | AST_SHARE_MODE = " lock in share mode"
  type Union (line 110) | type Union struct
    method IStatement (line 56) | func (*Union) IStatement()  {}
    method ISelectStatement (line 74) | func (*Union) ISelectStatement()  {}
    method Format (line 124) | func (node *Union) Format(buf *TrackedBuffer) {
    method IInsertRows (line 150) | func (*Union) IInsertRows()  {}
  constant AST_UNION (line 117) | AST_UNION     = "union"
  constant AST_UNION_ALL (line 118) | AST_UNION_ALL = "union all"
  constant AST_SET_MINUS (line 119) | AST_SET_MINUS = "minus"
  constant AST_EXCEPT (line 120) | AST_EXCEPT    = "except"
  constant AST_INTERSECT (line 121) | AST_INTERSECT = "intersect"
  type Insert (line 129) | type Insert struct
    method IStatement (line 58) | func (*Insert) IStatement() {}
    method Format (line 137) | func (node *Insert) Format(buf *TrackedBuffer) {
  type InsertRows (line 144) | type InsertRows interface
  type Update (line 154) | type Update struct
    method IStatement (line 59) | func (*Update) IStatement() {}
    method Format (line 163) | func (node *Update) Format(buf *TrackedBuffer) {
  type Delete (line 170) | type Delete struct
    method IStatement (line 60) | func (*Delete) IStatement() {}
    method Format (line 178) | func (node *Delete) Format(buf *TrackedBuffer) {
  type Set (line 185) | type Set struct
    method IStatement (line 61) | func (*Set) IStatement()    {}
    method Format (line 190) | func (node *Set) Format(buf *TrackedBuffer) {
  type DDL (line 197) | type DDL struct
    method IStatement (line 62) | func (*DDL) IStatement()    {}
    method Format (line 210) | func (node *DDL) Format(buf *TrackedBuffer) {
  constant AST_CREATE (line 204) | AST_CREATE = "create"
  constant AST_ALTER (line 205) | AST_ALTER  = "alter"
  constant AST_DROP (line 206) | AST_DROP   = "drop"
  constant AST_RENAME (line 207) | AST_RENAME = "rename"
  type Other (line 224) | type Other struct
    method IStatement (line 63) | func (*Other) IStatement()  {}
    method Format (line 226) | func (node *Other) Format(buf *TrackedBuffer) {
  type Comments (line 231) | type Comments
    method Format (line 233) | func (node Comments) Format(buf *TrackedBuffer) {
  type SelectExprs (line 240) | type SelectExprs
    method Format (line 242) | func (node SelectExprs) Format(buf *TrackedBuffer) {
  type SelectExpr (line 251) | type SelectExpr interface
  type StarExpr (line 260) | type StarExpr struct
    method ISelectExpr (line 256) | func (*StarExpr) ISelectExpr()    {}
    method Format (line 264) | func (node *StarExpr) Format(buf *TrackedBuffer) {
  type NonStarExpr (line 272) | type NonStarExpr struct
    method ISelectExpr (line 257) | func (*NonStarExpr) ISelectExpr() {}
    method Format (line 277) | func (node *NonStarExpr) Format(buf *TrackedBuffer) {
  type Columns (line 288) | type Columns
    method Format (line 290) | func (node Columns) Format(buf *TrackedBuffer) {
  type TableExprs (line 298) | type TableExprs
    method Format (line 300) | func (node TableExprs) Format(buf *TrackedBuffer) {
  type TableExpr (line 309) | type TableExpr interface
  type AliasedTableExpr (line 320) | type AliasedTableExpr struct
    method ITableExpr (line 314) | func (*AliasedTableExpr) ITableExpr() {}
    method Format (line 326) | func (node *AliasedTableExpr) Format(buf *TrackedBuffer) {
  type SimpleTableExpr (line 338) | type SimpleTableExpr interface
  type TableName (line 347) | type TableName struct
    method ISimpleTableExpr (line 343) | func (*TableName) ISimpleTableExpr() {}
    method Format (line 351) | func (node *TableName) Format(buf *TrackedBuffer) {
  type ParenTableExpr (line 360) | type ParenTableExpr struct
    method ITableExpr (line 315) | func (*ParenTableExpr) ITableExpr()   {}
    method Format (line 364) | func (node *ParenTableExpr) Format(buf *TrackedBuffer) {
  type JoinTableExpr (line 369) | type JoinTableExpr struct
    method ITableExpr (line 316) | func (*JoinTableExpr) ITableExpr()    {}
    method Format (line 386) | func (node *JoinTableExpr) Format(buf *TrackedBuffer) {
  constant AST_JOIN (line 378) | AST_JOIN          = "join"
  constant AST_STRAIGHT_JOIN (line 379) | AST_STRAIGHT_JOIN = "straight_join"
  constant AST_LEFT_JOIN (line 380) | AST_LEFT_JOIN     = "left join"
  constant AST_RIGHT_JOIN (line 381) | AST_RIGHT_JOIN    = "right join"
  constant AST_CROSS_JOIN (line 382) | AST_CROSS_JOIN    = "cross join"
  constant AST_NATURAL_JOIN (line 383) | AST_NATURAL_JOIN  = "natural join"
  type IndexHints (line 394) | type IndexHints struct
    method Format (line 405) | func (node *IndexHints) Format(buf *TrackedBuffer) {
  constant AST_USE (line 400) | AST_USE    = "use"
  constant AST_IGNORE (line 401) | AST_IGNORE = "ignore"
  constant AST_FORCE (line 402) | AST_FORCE  = "force"
  type Where (line 416) | type Where struct
    method Format (line 436) | func (node *Where) Format(buf *TrackedBuffer) {
  constant AST_WHERE (line 423) | AST_WHERE  = "where"
  constant AST_HAVING (line 424) | AST_HAVING = "having"
  function NewWhere (line 429) | func NewWhere(typ string, expr BoolExpr) *Where {
  type From (line 444) | type From struct
    method Format (line 463) | func (node *From) Format(buf *TrackedBuffer) {
  constant AST_FROM (line 451) | AST_FROM = "from"
  function NewFrom (line 456) | func NewFrom(typ string, expr TableExprs) *From {
  type Expr (line 471) | type Expr interface
  type BoolExpr (line 499) | type BoolExpr interface
  type AndExpr (line 515) | type AndExpr struct
    method IExpr (line 476) | func (*AndExpr) IExpr()        {}
    method IBoolExpr (line 504) | func (*AndExpr) IBoolExpr()        {}
    method Format (line 519) | func (node *AndExpr) Format(buf *TrackedBuffer) {
  type OrExpr (line 524) | type OrExpr struct
    method IExpr (line 477) | func (*OrExpr) IExpr()         {}
    method IBoolExpr (line 505) | func (*OrExpr) IBoolExpr()         {}
    method Format (line 528) | func (node *OrExpr) Format(buf *TrackedBuffer) {
  type NotExpr (line 533) | type NotExpr struct
    method IExpr (line 478) | func (*NotExpr) IExpr()        {}
    method IBoolExpr (line 506) | func (*NotExpr) IBoolExpr()        {}
    method Format (line 537) | func (node *NotExpr) Format(buf *TrackedBuffer) {
  type ParenBoolExpr (line 542) | type ParenBoolExpr struct
    method IExpr (line 479) | func (*ParenBoolExpr) IExpr()  {}
    method IBoolExpr (line 507) | func (*ParenBoolExpr) IBoolExpr()  {}
    method Format (line 546) | func (node *ParenBoolExpr) Format(buf *TrackedBuffer) {
  type ComparisonExpr (line 551) | type ComparisonExpr struct
    method IExpr (line 480) | func (*ComparisonExpr) IExpr() {}
    method IBoolExpr (line 508) | func (*ComparisonExpr) IBoolExpr() {}
    method Format (line 571) | func (node *ComparisonExpr) Format(buf *TrackedBuffer) {
  constant AST_EQ (line 558) | AST_EQ       = "="
  constant AST_LT (line 559) | AST_LT       = "<"
  constant AST_GT (line 560) | AST_GT       = ">"
  constant AST_LE (line 561) | AST_LE       = "<="
  constant AST_GE (line 562) | AST_GE       = ">="
  constant AST_NE (line 563) | AST_NE       = "!="
  constant AST_NSE (line 564) | AST_NSE      = "<=>"
  constant AST_IN (line 565) | AST_IN       = "in"
  constant AST_NOT_IN (line 566) | AST_NOT_IN   = "not in"
  constant AST_LIKE (line 567) | AST_LIKE     = "like"
  constant AST_NOT_LIKE (line 568) | AST_NOT_LIKE = "not like"
  type RangeCond (line 576) | type RangeCond struct
    method IExpr (line 481) | func (*RangeCond) IExpr()      {}
    method IBoolExpr (line 509) | func (*RangeCond) IBoolExpr()      {}
    method Format (line 588) | func (node *RangeCond) Format(buf *TrackedBuffer) {
  constant AST_BETWEEN (line 584) | AST_BETWEEN     = "between"
  constant AST_NOT_BETWEEN (line 585) | AST_NOT_BETWEEN = "not between"
  type NullCheck (line 593) | type NullCheck struct
    method IExpr (line 482) | func (*NullCheck) IExpr()      {}
    method IBoolExpr (line 510) | func (*NullCheck) IBoolExpr()      {}
    method Format (line 604) | func (node *NullCheck) Format(buf *TrackedBuffer) {
  constant AST_IS_NULL (line 600) | AST_IS_NULL     = "is null"
  constant AST_IS_NOT_NULL (line 601) | AST_IS_NOT_NULL = "is not null"
  type ExistsExpr (line 609) | type ExistsExpr struct
    method IExpr (line 483) | func (*ExistsExpr) IExpr()     {}
    method IBoolExpr (line 511) | func (*ExistsExpr) IBoolExpr()     {}
    method Format (line 613) | func (node *ExistsExpr) Format(buf *TrackedBuffer) {
  type KeyrangeExpr (line 618) | type KeyrangeExpr struct
    method IExpr (line 484) | func (*KeyrangeExpr) IExpr()   {}
    method IBoolExpr (line 512) | func (*KeyrangeExpr) IBoolExpr()   {}
    method Format (line 622) | func (node *KeyrangeExpr) Format(buf *TrackedBuffer) {
  type ValExpr (line 627) | type ValExpr interface
  type StrVal (line 646) | type StrVal
    method IExpr (line 485) | func (StrVal) IExpr()          {}
    method IValExpr (line 632) | func (StrVal) IValExpr()      {}
    method Format (line 648) | func (node StrVal) Format(buf *TrackedBuffer) {
  type NumVal (line 654) | type NumVal
    method IExpr (line 486) | func (NumVal) IExpr()          {}
    method IValExpr (line 633) | func (NumVal) IValExpr()      {}
    method Format (line 656) | func (node NumVal) Format(buf *TrackedBuffer) {
  type ValArg (line 661) | type ValArg
    method IExpr (line 487) | func (ValArg) IExpr()          {}
    method IValExpr (line 634) | func (ValArg) IValExpr()      {}
    method Format (line 663) | func (node ValArg) Format(buf *TrackedBuffer) {
  type NullVal (line 668) | type NullVal struct
    method IExpr (line 488) | func (*NullVal) IExpr()        {}
    method IValExpr (line 635) | func (*NullVal) IValExpr()    {}
    method Format (line 670) | func (node *NullVal) Format(buf *TrackedBuffer) {
  type ColName (line 675) | type ColName struct
    method IExpr (line 489) | func (*ColName) IExpr()        {}
    method IValExpr (line 636) | func (*ColName) IValExpr()    {}
    method Format (line 679) | func (node *ColName) Format(buf *TrackedBuffer) {
  function escape (line 687) | func escape(buf *TrackedBuffer, name []byte) {
  type ColTuple (line 697) | type ColTuple interface
  type ValTuple (line 707) | type ValTuple
    method IExpr (line 490) | func (ValTuple) IExpr()        {}
    method IValExpr (line 637) | func (ValTuple) IValExpr()    {}
    method IColTuple (line 702) | func (ValTuple) IColTuple()  {}
    method Format (line 709) | func (node ValTuple) Format(buf *TrackedBuffer) {
    method IRowTuple (line 964) | func (ValTuple) IRowTuple()  {}
  type ValExprs (line 715) | type ValExprs
    method Format (line 717) | func (node ValExprs) Format(buf *TrackedBuffer) {
  type Subquery (line 726) | type Subquery struct
    method ISimpleTableExpr (line 344) | func (*Subquery) ISimpleTableExpr()  {}
    method IExpr (line 491) | func (*Subquery) IExpr()       {}
    method IValExpr (line 638) | func (*Subquery) IValExpr()   {}
    method IColTuple (line 703) | func (*Subquery) IColTuple() {}
    method Format (line 730) | func (node *Subquery) Format(buf *TrackedBuffer) {
    method IRowTuple (line 965) | func (*Subquery) IRowTuple() {}
  type ListArg (line 735) | type ListArg
    method IExpr (line 492) | func (ListArg) IExpr()         {}
    method IValExpr (line 639) | func (ListArg) IValExpr()     {}
    method IColTuple (line 704) | func (ListArg) IColTuple()   {}
    method Format (line 737) | func (node ListArg) Format(buf *TrackedBuffer) {
  type BinaryExpr (line 742) | type BinaryExpr struct
    method IExpr (line 493) | func (*BinaryExpr) IExpr()     {}
    method IValExpr (line 640) | func (*BinaryExpr) IValExpr() {}
    method Format (line 759) | func (node *BinaryExpr) Format(buf *TrackedBuffer) {
  constant AST_BITAND (line 749) | AST_BITAND = '&'
  constant AST_BITOR (line 750) | AST_BITOR  = '|'
  constant AST_BITXOR (line 751) | AST_BITXOR = '^'
  constant AST_PLUS (line 752) | AST_PLUS   = '+'
  constant AST_MINUS (line 753) | AST_MINUS  = '-'
  constant AST_MULT (line 754) | AST_MULT   = '*'
  constant AST_DIV (line 755) | AST_DIV    = '/'
  constant AST_MOD (line 756) | AST_MOD    = '%'
  type UnaryExpr (line 764) | type UnaryExpr struct
    method IExpr (line 494) | func (*UnaryExpr) IExpr()      {}
    method IValExpr (line 641) | func (*UnaryExpr) IValExpr()  {}
    method Format (line 776) | func (node *UnaryExpr) Format(buf *TrackedBuffer) {
  constant AST_UPLUS (line 771) | AST_UPLUS  = '+'
  constant AST_UMINUS (line 772) | AST_UMINUS = '-'
  constant AST_TILDA (line 773) | AST_TILDA  = '~'
  type FuncExpr (line 781) | type FuncExpr struct
    method IExpr (line 495) | func (*FuncExpr) IExpr()       {}
    method IValExpr (line 642) | func (*FuncExpr) IValExpr()   {}
    method Format (line 787) | func (node *FuncExpr) Format(buf *TrackedBuffer) {
    method IsAggregate (line 815) | func (node *FuncExpr) IsAggregate() bool {
  type CaseExpr (line 820) | type CaseExpr struct
    method IExpr (line 496) | func (*CaseExpr) IExpr()       {}
    method IValExpr (line 643) | func (*CaseExpr) IValExpr()   {}
    method Format (line 826) | func (node *CaseExpr) Format(buf *TrackedBuffer) {
  type When (line 841) | type When struct
    method Format (line 846) | func (node *When) Format(buf *TrackedBuffer) {
  type GroupBy (line 851) | type GroupBy
    method Format (line 853) | func (node GroupBy) Format(buf *TrackedBuffer) {
  type OrderBy (line 862) | type OrderBy
    method Format (line 864) | func (node OrderBy) Format(buf *TrackedBuffer) {
  type Order (line 873) | type Order struct
    method Format (line 884) | func (node *Order) Format(buf *TrackedBuffer) {
  constant AST_ASC (line 880) | AST_ASC  = "asc"
  constant AST_DESC (line 881) | AST_DESC = "desc"
  type Limit (line 889) | type Limit struct
    method Format (line 893) | func (node *Limit) Format(buf *TrackedBuffer) {
    method Limits (line 908) | func (node *Limit) Limits() (offset, rowcount interface{}, err error) {
  type Values (line 948) | type Values
    method IInsertRows (line 151) | func (Values) IInsertRows()  {}
    method Format (line 950) | func (node Values) Format(buf *TrackedBuffer) {
  type RowTuple (line 959) | type RowTuple interface
  type UpdateExprs (line 968) | type UpdateExprs
    method Format (line 970) | func (node UpdateExprs) Format(buf *TrackedBuffer) {
  type UpdateExpr (line 979) | type UpdateExpr struct
    method Format (line 984) | func (node *UpdateExpr) Format(buf *TrackedBuffer) {
  type OnDup (line 989) | type OnDup
    method Format (line 991) | func (node OnDup) Format(buf *TrackedBuffer) {

FILE: sqlparser/fuzz.go
  function Fuzz (line 3) | func Fuzz(data []byte) int {

FILE: sqlparser/parsed_query.go
  type bindLocation (line 16) | type bindLocation struct
  type ParsedQuery (line 20) | type ParsedQuery struct
    method GenerateQuery (line 27) | func (pq *ParsedQuery) GenerateQuery(bindVariables map[string]interfac...
    method MarshalJSON (line 49) | func (pq *ParsedQuery) MarshalJSON() ([]byte, error) {
  type EncoderFunc (line 25) | type EncoderFunc
  function EncodeValue (line 53) | func EncodeValue(buf *bytes.Buffer, value interface{}) error {
  type TupleEqualityList (line 102) | type TupleEqualityList struct
    method Encode (line 107) | func (tpl *TupleEqualityList) Encode(buf *bytes.Buffer) error {
    method encodeAsIN (line 117) | func (tpl *TupleEqualityList) encodeAsIN(buf *bytes.Buffer) error {
    method encodeAsEquality (line 135) | func (tpl *TupleEqualityList) encodeAsEquality(buf *bytes.Buffer) error {
  function FetchBindVar (line 156) | func FetchBindVar(name string, bindVariables map[string]interface{}) (va...

FILE: sqlparser/sql.go
  function SetParseTree (line 9) | func SetParseTree(yylex interface{}, stmt Statement) {
  function SetAllowComments (line 13) | func SetAllowComments(yylex interface{}, allow bool) {
  function ForceEOF (line 17) | func ForceEOF(yylex interface{}) {
  type yySymType (line 29) | type yySymType struct
  constant LEX_ERROR (line 66) | LEX_ERROR = 57346
  constant SELECT (line 67) | SELECT = 57347
  constant INSERT (line 68) | INSERT = 57348
  constant UPDATE (line 69) | UPDATE = 57349
  constant DELETE (line 70) | DELETE = 57350
  constant FROM (line 71) | FROM = 57351
  constant WHERE (line 72) | WHERE = 57352
  constant GROUP (line 73) | GROUP = 57353
  constant HAVING (line 74) | HAVING = 57354
  constant ORDER (line 75) | ORDER = 57355
  constant BY (line 76) | BY = 57356
  constant LIMIT (line 77) | LIMIT = 57357
  constant FOR (line 78) | FOR = 57358
  constant ALL (line 79) | ALL = 57359
  constant DISTINCT (line 80) | DISTINCT = 57360
  constant AS (line 81) | AS = 57361
  constant EXISTS (line 82) | EXISTS = 57362
  constant IN (line 83) | IN = 57363
  constant IS (line 84) | IS = 57364
  constant LIKE (line 85) | LIKE = 57365
  constant BETWEEN (line 86) | BETWEEN = 57366
  constant NULL (line 87) | NULL = 57367
  constant ASC (line 88) | ASC = 57368
  constant DESC (line 89) | DESC = 57369
  constant VALUES (line 90) | VALUES = 57370
  constant INTO (line 91) | INTO = 57371
  constant DUPLICATE (line 92) | DUPLICATE = 57372
  constant KEY (line 93) | KEY = 57373
  constant DEFAULT (line 94) | DEFAULT = 57374
  constant SET (line 95) | SET = 57375
  constant LOCK (line 96) | LOCK = 57376
  constant KEYRANGE (line 97) | KEYRANGE = 57377
  constant ID (line 98) | ID = 57378
  constant STRING (line 99) | STRING = 57379
  constant NUMBER (line 100) | NUMBER = 57380
  constant VALUE_ARG (line 101) | VALUE_ARG = 57381
  constant LIST_ARG (line 102) | LIST_ARG = 57382
  constant COMMENT (line 103) | COMMENT = 57383
  constant LE (line 104) | LE = 57384
  constant GE (line 105) | GE = 57385
  constant NE (line 106) | NE = 57386
  constant NULL_SAFE_EQUAL (line 107) | NULL_SAFE_EQUAL = 57387
  constant UNION (line 108) | UNION = 57388
  constant MINUS (line 109) | MINUS = 57389
  constant EXCEPT (line 110) | EXCEPT = 57390
  constant INTERSECT (line 111) | INTERSECT = 57391
  constant JOIN (line 112) | JOIN = 57392
  constant STRAIGHT_JOIN (line 113) | STRAIGHT_JOIN = 57393
  constant LEFT (line 114) | LEFT = 57394
  constant RIGHT (line 115) | RIGHT = 57395
  constant INNER (line 116) | INNER = 57396
  constant OUTER (line 117) | OUTER = 57397
  constant CROSS (line 118) | CROSS = 57398
  constant NATURAL (line 119) | NATURAL = 57399
  constant USE (line 120) | USE = 57400
  constant FORCE (line 121) | FORCE = 57401
  constant ON (line 122) | ON = 57402
  constant OR (line 123) | OR = 57403
  constant AND (line 124) | AND = 57404
  constant NOT (line 125) | NOT = 57405
  constant UNARY (line 126) | UNARY = 57406
  constant CASE (line 127) | CASE = 57407
  constant WHEN (line 128) | WHEN = 57408
  constant THEN (line 129) | THEN = 57409
  constant ELSE (line 130) | ELSE = 57410
  constant END (line 131) | END = 57411
  constant CREATE (line 132) | CREATE = 57412
  constant ALTER (line 133) | ALTER = 57413
  constant DROP (line 134) | DROP = 57414
  constant RENAME (line 135) | RENAME = 57415
  constant ANALYZE (line 136) | ANALYZE = 57416
  constant TABLE (line 137) | TABLE = 57417
  constant INDEX (line 138) | INDEX = 57418
  constant VIEW (line 139) | VIEW = 57419
  constant TO (line 140) | TO = 57420
  constant IGNORE (line 141) | IGNORE = 57421
  constant IF (line 142) | IF = 57422
  constant UNIQUE (line 143) | UNIQUE = 57423
  constant USING (line 144) | USING = 57424
  constant SHOW (line 145) | SHOW = 57425
  constant DESCRIBE (line 146) | DESCRIBE = 57426
  constant EXPLAIN (line 147) | EXPLAIN = 57427
  constant yyEofCode (line 250) | yyEofCode = 1
  constant yyErrCode (line 251) | yyErrCode = 2
  constant yyMaxDepth (line 252) | yyMaxDepth = 200
  constant yyNprod (line 261) | yyNprod = 207
  constant yyPrivate (line 262) | yyPrivate = 57344
  constant yyLast (line 267) | yyLast = 678
  type yyLexer (line 566) | type yyLexer interface
  constant yyFlag (line 571) | yyFlag = -1000
  function yyTokname (line 573) | func yyTokname(c int) string {
  function yyStatname (line 583) | func yyStatname(s int) string {
  function yylex1 (line 592) | func yylex1(lex yyLexer, lval *yySymType) int {
  function yyParse (line 627) | func yyParse(yylex yyLexer) int {

FILE: sqlparser/sql_mod.go
  function Magicify (line 7) | func Magicify(sql string, tableName string) string {
  function replaceFromInSelect (line 27) | func replaceFromInSelect(statement *Select, tableName string) {
  function generateQuery (line 55) | func generateQuery(statement Statement) string {

FILE: sqlparser/sqltypes/sqltypes.go
  type BinWriter (line 29) | type BinWriter interface
  type Value (line 35) | type Value struct
    method Raw (line 65) | func (v Value) Raw() []byte {
    method String (line 73) | func (v Value) String() string {
    method ParseInt64 (line 94) | func (v Value) ParseInt64() (val int64, err error) {
    method ParseUint64 (line 106) | func (v Value) ParseUint64() (val uint64, err error) {
    method ParseFloat64 (line 118) | func (v Value) ParseFloat64() (val float64, err error) {
    method EncodeSql (line 130) | func (v Value) EncodeSql(b BinWriter) {
    method EncodeAscii (line 141) | func (v Value) EncodeAscii(b BinWriter) {
    method IsNull (line 151) | func (v Value) IsNull() bool {
    method IsNumeric (line 155) | func (v Value) IsNumeric() (ok bool) {
    method IsFractional (line 162) | func (v Value) IsFractional() (ok bool) {
    method IsString (line 169) | func (v Value) IsString() (ok bool) {
    method MarshalJSON (line 178) | func (v Value) MarshalJSON() ([]byte, error) {
    method UnmarshalJSON (line 184) | func (v *Value) UnmarshalJSON(b []byte) error {
  type Numeric (line 40) | type Numeric
    method raw (line 274) | func (n Numeric) raw() []byte {
    method encodeSql (line 278) | func (n Numeric) encodeSql(b BinWriter) {
    method encodeAscii (line 284) | func (n Numeric) encodeAscii(b BinWriter) {
    method MarshalJSON (line 290) | func (n Numeric) MarshalJSON() ([]byte, error) {
  type Fractional (line 44) | type Fractional
    method raw (line 294) | func (f Fractional) raw() []byte {
    method encodeSql (line 298) | func (f Fractional) encodeSql(b BinWriter) {
    method encodeAscii (line 304) | func (f Fractional) encodeAscii(b BinWriter) {
  type String (line 47) | type String
    method MarshalJSON (line 310) | func (s String) MarshalJSON() ([]byte, error) {
    method raw (line 314) | func (s String) raw() []byte {
    method encodeSql (line 318) | func (s String) encodeSql(b BinWriter) {
    method encodeAscii (line 331) | func (s String) encodeAscii(b BinWriter) {
  function MakeNumeric (line 50) | func MakeNumeric(b []byte) Value {
  function MakeFractional (line 55) | func MakeFractional(b []byte) Value {
  function MakeString (line 60) | func MakeString(b []byte) Value {
  function toString (line 82) | func toString(b []byte) (s string) {
  type InnerValue (line 214) | type InnerValue interface
  function BuildValue (line 220) | func BuildValue(goval interface{}) (v Value, err error) {
  function BuildNumeric (line 257) | func BuildNumeric(val string) (n Value, err error) {
  function writebyte (line 339) | func writebyte(b BinWriter, c byte) {
  function init (line 364) | func init() {

FILE: sqlparser/sqltypes/type_test.go
  function TestNull (line 13) | func TestNull(t *testing.T) {
  function TestNumeric (line 39) | func TestNumeric(t *testing.T) {
  function TestTime (line 59) | func TestTime(t *testing.T) {
  constant INVALIDNEG (line 74) | INVALIDNEG = "-9223372036854775809"
  constant MINNEG (line 75) | MINNEG     = "-9223372036854775808"
  constant MAXPOS (line 76) | MAXPOS     = "18446744073709551615"
  constant INVALIDPOS (line 77) | INVALIDPOS = "18446744073709551616"
  constant NEGFLOAT (line 78) | NEGFLOAT   = "1.234"
  constant POSFLOAT (line 79) | POSFLOAT   = "-1.234"
  function TestBuildNumeric (line 82) | func TestBuildNumeric(t *testing.T) {
  constant HARDSQL (line 128) | HARDSQL     = "\x00'\"\b\n\r\t\x1A\\"
  constant HARDESCAPED (line 129) | HARDESCAPED = "'\\0\\'\\\"\\b\\n\\r\\t\\Z\\\\'"
  constant HARDASCII (line 130) | HARDASCII   = "'ACciCAoNCRpc'"
  function TestString (line 133) | func TestString(t *testing.T) {
  function TestBuildValue (line 155) | func TestBuildValue(t *testing.T) {
  function TestEncode (line 303) | func TestEncode(t *testing.T) {

FILE: sqlparser/token.go
  constant EOFCHAR (line 15) | EOFCHAR = 0x100
  type Tokenizer (line 19) | type Tokenizer struct
    method Lex (line 112) | func (tkn *Tokenizer) Lex(lval *yySymType) int {
    method Error (line 129) | func (tkn *Tokenizer) Error(err string) {
    method Scan (line 141) | func (tkn *Tokenizer) Scan() (int, []byte) {
    method skipBlank (line 234) | func (tkn *Tokenizer) skipBlank() {
    method scanIdentifier (line 242) | func (tkn *Tokenizer) scanIdentifier() (int, []byte) {
    method scanLiteralIdentifier (line 255) | func (tkn *Tokenizer) scanLiteralIdentifier() (int, []byte) {
    method scanBindVar (line 271) | func (tkn *Tokenizer) scanBindVar() (int, []byte) {
    method scanMantissa (line 291) | func (tkn *Tokenizer) scanMantissa(base int, buffer *bytes.Buffer) {
    method scanNumber (line 297) | func (tkn *Tokenizer) scanNumber(seenDecimalPoint bool) (int, []byte) {
    method scanString (line 354) | func (tkn *Tokenizer) scanString(delim uint16, typ int) (int, []byte) {
    method scanCommentType1 (line 384) | func (tkn *Tokenizer) scanCommentType1(prefix string) (int, []byte) {
    method scanCommentType2 (line 397) | func (tkn *Tokenizer) scanCommentType2() (int, []byte) {
    method ConsumeNext (line 417) | func (tkn *Tokenizer) ConsumeNext(buffer *bytes.Buffer) {
    method next (line 426) | func (tkn *Tokenizer) next() {
  function NewStringTokenizer (line 33) | func NewStringTokenizer(sql string) *Tokenizer {
  function isLetter (line 436) | func isLetter(ch uint16) bool {
  function digitVal (line 440) | func digitVal(ch uint16) int {
  function isDigit (line 452) | func isDigit(ch uint16) bool {

FILE: sqlparser/tracked_buffer.go
  type TrackedBuffer (line 19) | type TrackedBuffer struct
    method Myprintf (line 40) | func (buf *TrackedBuffer) Myprintf(format string, values ...interface{...
    method WriteArg (line 93) | func (buf *TrackedBuffer) WriteArg(arg string) {
    method ParsedQuery (line 101) | func (buf *TrackedBuffer) ParsedQuery() *ParsedQuery {
    method HasBindVars (line 105) | func (buf *TrackedBuffer) HasBindVars() bool {
  function NewTrackedBuffer (line 25) | func NewTrackedBuffer(nodeFormatter func(buf *TrackedBuffer, node SQLNod...

FILE: storage/sqlite.go
  type SQLite3Storage (line 19) | type SQLite3Storage struct
    method open (line 76) | func (sqlite3Storage *SQLite3Storage) open() {
    method LoadInput (line 95) | func (sqlite3Storage *SQLite3Storage) LoadInput(input inputs.Input) {
    method createTable (line 123) | func (sqlite3Storage *SQLite3Storage) createTable(tableName string, co...
    method createLoadStmt (line 159) | func (sqlite3Storage *SQLite3Storage) createLoadStmt(tableName string,...
    method loadRow (line 184) | func (sqlite3Storage *SQLite3Storage) loadRow(tableName string, colCou...
    method ExecuteSQLString (line 211) | func (sqlite3Storage *SQLite3Storage) ExecuteSQLString(sqlQuery string...
    method Exec (line 229) | func (sqlite3Storage *SQLite3Storage) Exec(sqlQuery string) (sql.Resul...
    method SaveTo (line 245) | func (sqlite3Storage *SQLite3Storage) SaveTo(path string) error {
    method Close (line 281) | func (sqlite3Storage *SQLite3Storage) Close() {
  type SQLite3Options (line 27) | type SQLite3Options struct
  type entrypoint (line 36) | type entrypoint struct
  function init (line 47) | func init() {
  function NewSQLite3StorageWithDefaults (line 61) | func NewSQLite3StorageWithDefaults() *SQLite3Storage {
  function NewSQLite3Storage (line 66) | func NewSQLite3Storage(opts *SQLite3Options) *SQLite3Storage {

FILE: storage/sqlite_regexp.go
  function regExp (line 5) | func regExp(re, s string) (bool, error) {

FILE: storage/sqlite_test.go
  function NewTestCSVInput (line 25) | func NewTestCSVInput() (input inputs.Input, fp *os.File) {
  function TestSQLiteStorageLoadInput (line 38) | func TestSQLiteStorageLoadInput(t *testing.T) {
  function TestSQLiteStorageSaveTo (line 48) | func TestSQLiteStorageSaveTo(t *testing.T) {
  function TestSQLiteStorageExecuteSQLStringNormalSQL (line 93) | func TestSQLiteStorageExecuteSQLStringNormalSQL(t *testing.T) {
  function TestSQLiteStorageExecuteSQLStringMissingSelect (line 130) | func TestSQLiteStorageExecuteSQLStringMissingSelect(t *testing.T) {
  function LoadTestDataAndExecuteQuery (line 167) | func LoadTestDataAndExecuteQuery(t *testing.T, testData string, sqlStrin...
  function TestSQLiteStorageExecuteSQLStringMissingFromOuterQuery (line 222) | func TestSQLiteStorageExecuteSQLStringMissingFromOuterQuery(t *testing.T) {
  function TestSQLiteStorageExecuteSQLStringMissingFromSubQuery (line 235) | func TestSQLiteStorageExecuteSQLStringMissingFromSubQuery(t *testing.T) {
  function TestWhitespaceLoadsAsNull (line 248) | func TestWhitespaceLoadsAsNull(t *testing.T) {
  function TestSQLiteStorageExec (line 314) | func TestSQLiteStorageExec(t *testing.T) {

FILE: storage/storage.go
  type Storage (line 14) | type Storage interface

FILE: test_util/test_util.go
  function OpenFileFromString (line 8) | func OpenFileFromString(contents string) *os.File {

FILE: textql/main.go
  type commandLineOptions (line 18) | type commandLineOptions struct
    method GetStatements (line 57) | func (clo *commandLineOptions) GetStatements() (string, *error) {
    method GetSourceFiles (line 73) | func (clo *commandLineOptions) GetSourceFiles() []string {
    method GetDelimiter (line 77) | func (clo *commandLineOptions) GetDelimiter() string {
    method GetHeader (line 81) | func (clo *commandLineOptions) GetHeader() bool {
    method GetOutputHeader (line 85) | func (clo *commandLineOptions) GetOutputHeader() bool {
    method GetOutputDelimiter (line 89) | func (clo *commandLineOptions) GetOutputDelimiter() string {
    method GetOutputFile (line 93) | func (clo *commandLineOptions) GetOutputFile() string {
    method GetSaveTo (line 97) | func (clo *commandLineOptions) GetSaveTo() string {
    method GetConsole (line 101) | func (clo *commandLineOptions) GetConsole() bool {
    method GetVersion (line 105) | func (clo *commandLineOptions) GetVersion() bool {
    method GetQuiet (line 109) | func (clo *commandLineOptions) GetQuiet() bool {
    method GetPretty (line 113) | func (clo *commandLineOptions) GetPretty() bool {
    method Usage (line 117) | func (clo *commandLineOptions) Usage() {
  function newCommandLineOptions (line 37) | func newCommandLineOptions() *commandLineOptions {
  function handleSemiColon (line 127) | func handleSemiColon(sqlStrings *[]string) []string {
  function main (line 151) | func main() {

FILE: util/file_helpers.go
  function IsPathDir (line 12) | func IsPathDir(path string) bool {
  function OpenFileOrStdDev (line 30) | func OpenFileOrStdDev(path string, write bool) *os.File {
  function CleanPath (line 65) | func CleanPath(path string) string {
  function RewindFile (line 94) | func RewindFile(fileHandle *os.File) {
  function IsThereDataOnStdin (line 102) | func IsThereDataOnStdin() bool {
  function AllFilesInDirectory (line 116) | func AllFilesInDirectory(path string) []string {

FILE: util/seperator_helpers.go
  function DetermineSeparator (line 10) | func DetermineSeparator(delimiter string) rune {
Condensed preview — 44 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (331K chars).
[
  {
    "path": ".SRCINFO",
    "chars": 292,
    "preview": "pkgbase = textql-git\n\tpkgdesc = Execute SQL against structured text like CSV or TSV\n\tpkgver = 2.0.3\n\tpkgrel = 1\n\turl = h"
  },
  {
    "path": ".gitignore",
    "chars": 21,
    "preview": "vendor/\nglide\nbuild/\n"
  },
  {
    "path": ".travis.yml",
    "chars": 94,
    "preview": "os: linux\narch:\n - amd64\n - ppc64le\nlanguage: go\nsudo: false\n\ngo:\n  - '1.13.x'\n\ninstall: make\n"
  },
  {
    "path": "Dockerfile",
    "chars": 222,
    "preview": "FROM golang:1.10\n\n# install sqlite3 for option \"-console\"\nRUN apt-get update && apt-get install -y sqlite3\n\nWORKDIR /go/"
  },
  {
    "path": "Dockerfile.alpine",
    "chars": 318,
    "preview": "FROM golang:1.10-alpine3.7 AS build\n\n# \"build-base\" for gcc\nRUN apk update && apk add git && apk add build-base\nWORKDIR "
  },
  {
    "path": "LICENSE",
    "chars": 1082,
    "preview": "MIT License\n-----------\n\nCopyright (c) 2014, Paul Bergeron\n\nPermission is hereby granted, free of charge, to any person "
  },
  {
    "path": "Makefile",
    "chars": 511,
    "preview": ".PHONY: all test clean man godep fast release install\n\nall: textql\n\ntextql: test\n\tgo build -ldflags \"-X main.VERSION=`ca"
  },
  {
    "path": "PKGBUILD",
    "chars": 982,
    "preview": "# Maintainer: Aniket-Pradhan aniket17133@iiitd.ac.in\n# Owner/Cofntributer: Paul Bergeron https://github.com/dinedal\n\npkg"
  },
  {
    "path": "Readme.md",
    "chars": 5175,
    "preview": "# TextQL\n\n[![Build Status](https://travis-ci.org/dinedal/textql.svg)](https://travis-ci.org/dinedal/textql) [![Go Report"
  },
  {
    "path": "TODO.txt",
    "chars": 29005,
    "preview": "Install is really complex with vitess dep. Find a way to fix it?\n\n~ go get -u github.com/dinedal/textql/...\n# github.com"
  },
  {
    "path": "VERSION",
    "chars": 6,
    "preview": "2.0.3\n"
  },
  {
    "path": "go.mod",
    "chars": 224,
    "preview": "module github.com/dinedal/textql\n\ngo 1.13\n\nrequire (\n\tgithub.com/mattn/go-runewidth v0.0.2 // indirect\n\tgithub.com/mattn"
  },
  {
    "path": "go.sum",
    "chars": 8352,
    "preview": "github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=\ngithub.com/BurntSushi/toml v0.3.1/go.m"
  },
  {
    "path": "inputs/csv.go",
    "chars": 3718,
    "preview": "package inputs\n\nimport (\n\t\"encoding/csv\"\n\t\"io\"\n\t\"log\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strconv\"\n)\n\n// CSVInput represents a reco"
  },
  {
    "path": "inputs/csv_test.go",
    "chars": 2960,
    "preview": "package inputs\n\nimport (\n\t\"os\"\n\t\"strings\"\n\n\t\"reflect\"\n\t\"testing\"\n\n\t\"github.com/dinedal/textql/test_util\"\n)\n\nvar (\n\tsimpl"
  },
  {
    "path": "inputs/input.go",
    "chars": 771,
    "preview": "package inputs\n\n// Input is how TextQL reads from data sources.\n// To be an input, an implementor must return tabular da"
  },
  {
    "path": "man/textql.1",
    "chars": 3082,
    "preview": ".\\\" generated with Ronn/v0.7.3\n.\\\" http://github.com/rtomayko/ronn/tree/0.7.3\n.\n.TH \"TEXTQL\" \"1\" \"December 2015\" \"\" \"\"\n."
  },
  {
    "path": "man/textql.1.html",
    "chars": 6529,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n  <meta http-equiv='content-type' value='text/html;charset=utf8'>\n  <meta name='generator'"
  },
  {
    "path": "man/textql.1.ronn",
    "chars": 2798,
    "preview": "textql(1) -- execute queries on structured text\n===============================================\n\n## SYNOPSIS\n\n`textql` ["
  },
  {
    "path": "outputs/csv.go",
    "chars": 1810,
    "preview": "package outputs\n\nimport (\n\t\"database/sql\"\n\t\"encoding/csv\"\n\t\"io\"\n\t\"log\"\n)\n\n// CSVOutput represents a TextQL output that t"
  },
  {
    "path": "outputs/output.go",
    "chars": 312,
    "preview": "package outputs\n\nimport \"database/sql\"\n\n// Output implementors should accept sql.Rows and transform them\n// however they"
  },
  {
    "path": "outputs/pretty_csv.go",
    "chars": 1817,
    "preview": "package outputs\n\nimport (\n\t\"database/sql\"\n\t\"io\"\n\t\"log\"\n\n\t\"github.com/olekukonko/tablewriter\"\n)\n\n// PrettyCSVOutput repre"
  },
  {
    "path": "snapcraft.yaml",
    "chars": 442,
    "preview": "name: textql\nversion: '1.0'\nsummary: Execute SQL against structured text like CSV or TSV \ndescription: |\n  Execute SQL a"
  },
  {
    "path": "sqlparser/Makefile",
    "chars": 109,
    "preview": "\nMAKEFLAGS = -s\n\nsql.go: sql.y\n\tgo tool yacc -o sql.go sql.y\n\tgofmt -w sql.go\n\nclean:\n\trm -f y.output sql.go\n"
  },
  {
    "path": "sqlparser/analyzer.go",
    "chars": 2929,
    "preview": "// Copyright 2012, Google Inc. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license tha"
  },
  {
    "path": "sqlparser/ast.go",
    "chars": 21658,
    "preview": "// Copyright 2012, Google Inc. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license tha"
  },
  {
    "path": "sqlparser/fuzz.go",
    "chars": 122,
    "preview": "package sqlparser\n\nfunc Fuzz(data []byte) int {\n\t_, err := Parse(string(data))\n\tif err != nil {\n\t\treturn 0\n\t}\n\treturn 1\n"
  },
  {
    "path": "sqlparser/parsed_query.go",
    "chars": 4025,
    "preview": "// Copyright 2012, Google Inc. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license tha"
  },
  {
    "path": "sqlparser/sql.go",
    "chars": 40565,
    "preview": "//line sql.y:6\npackage sqlparser\n\nimport __yyfmt__ \"fmt\"\n\n//line sql.y:6\nimport \"bytes\"\n\nfunc SetParseTree(yylex interfa"
  },
  {
    "path": "sqlparser/sql.y",
    "chars": 18626,
    "preview": "// Copyright 2012, Google Inc. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license tha"
  },
  {
    "path": "sqlparser/sql_mod.go",
    "chars": 1492,
    "preview": "package sqlparser\n\n// Magicify runs the SQL passed in, and a table name, throught a customized\n// TextQL SQL Parser. Thi"
  },
  {
    "path": "sqlparser/sqltypes/sqltypes.go",
    "chars": 8660,
    "preview": "// Copyright 2012, Google Inc. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license tha"
  },
  {
    "path": "sqlparser/sqltypes/type_test.go",
    "chars": 7718,
    "preview": "// Copyright 2012, Google Inc. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license tha"
  },
  {
    "path": "sqlparser/token.go",
    "chars": 10269,
    "preview": "// Copyright 2012, Google Inc. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license tha"
  },
  {
    "path": "sqlparser/tracked_buffer.go",
    "chars": 2871,
    "preview": "// Copyright 2012, Google Inc. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license tha"
  },
  {
    "path": "sqlparser/y.output",
    "chars": 89270,
    "preview": "\nstate 0\n\t$accept: .any_command $end \n\tdistinct_opt: .    (45)\n\n\tSELECT  shift 15\n\tINSERT  shift 17\n\tUPDATE  shift 18\n\tD"
  },
  {
    "path": "storage/sqlite.go",
    "chars": 6872,
    "preview": "package storage\n\nimport (\n\t\"bytes\"\n\t\"database/sql\"\n\t\"path\"\n\t\"strings\"\n\n\t\"log\"\n\t\"regexp\"\n\n\t\"github.com/dinedal/textql/inp"
  },
  {
    "path": "storage/sqlite_regexp.go",
    "chars": 112,
    "preview": "package storage\n\nimport \"regexp\"\n\nfunc regExp(re, s string) (bool, error) {\n\treturn regexp.MatchString(re, s)\n}\n"
  },
  {
    "path": "storage/sqlite_test.go",
    "chars": 7118,
    "preview": "package storage\n\nimport (\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"os\"\n\t\"os/exec\"\n\t\"testing\"\n\n\t\"github.com/dinedal/textql/inputs\"\n\t\"github."
  },
  {
    "path": "storage/storage.go",
    "chars": 1074,
    "preview": "package storage\n\nimport (\n\t\"database/sql\"\n\n\t\"github.com/dinedal/textql/inputs\"\n)\n\n// Storage implentors are expected to "
  },
  {
    "path": "test_util/test_util.go",
    "chars": 191,
    "preview": "package test_util\n\nimport (\n\t\"io/ioutil\"\n\t\"os\"\n)\n\nfunc OpenFileFromString(contents string) *os.File {\n\tf, _ := ioutil.Te"
  },
  {
    "path": "textql/main.go",
    "chars": 8174,
    "preview": "package main\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"log\"\n\t\"os\"\n\t\"os/exec\"\n\t\"strings\"\n\n\t\"github.com/dinedal/textql/input"
  },
  {
    "path": "util/file_helpers.go",
    "chars": 1999,
    "preview": "package util\n\nimport (\n\t\"io/ioutil\"\n\t\"log\"\n\t\"os\"\n\t\"os/user\"\n\t\"path/filepath\"\n\t\"strings\"\n)\n\nfunc IsPathDir(path string) b"
  },
  {
    "path": "util/seperator_helpers.go",
    "chars": 477,
    "preview": "package util\n\nimport (\n\t\"encoding/hex\"\n\t\"log\"\n\t\"strings\"\n\t\"unicode/utf8\"\n)\n\nfunc DetermineSeparator(delimiter string) ru"
  }
]

About this extraction

This page contains the full source code of the dinedal/textql GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 44 files (297.7 KB), approximately 99.8k tokens, and a symbol index with 518 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!