[
  {
    "path": ".SRCINFO",
    "content": "pkgbase = textql-git\n\tpkgdesc = Execute SQL against structured text like CSV or TSV\n\tpkgver = 2.0.3\n\tpkgrel = 1\n\turl = https://github.com/dinedal/textql\n\tarch = x86_64\n\tarch = i686\n\tlicense = MIT\n\tmakedepends = git\n\tdepends = go\n\toptions = !strip\n\toptions = !emptydirs\n\npkgname = textql-git\n\n"
  },
  {
    "path": ".gitignore",
    "content": "vendor/\nglide\nbuild/\n"
  },
  {
    "path": ".travis.yml",
    "content": "os: linux\narch:\n - amd64\n - ppc64le\nlanguage: go\nsudo: false\n\ngo:\n  - '1.13.x'\n\ninstall: make\n"
  },
  {
    "path": "Dockerfile",
    "content": "FROM golang:1.10\n\n# install sqlite3 for option \"-console\"\nRUN apt-get update && apt-get install -y sqlite3\n\nWORKDIR /go/src/app\nCOPY . .\n\nRUN go get -d -v ./...\nRUN go install -v ./...\n\nWORKDIR /tmp\n\nENTRYPOINT [\"textql\"]\n"
  },
  {
    "path": "Dockerfile.alpine",
    "content": "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 /go/src/app\nCOPY . .\n\nRUN go get -d -v ./...\nRUN go install -v ./...\n\nFROM alpine:3.7\nRUN apk add --update-cache sqlite\nCOPY --from=build /go/bin/textql /usr/bin\nWORKDIR /tmp\nENTRYPOINT [\"textql\"]\n\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n-----------\n\nCopyright (c) 2014, Paul Bergeron\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE."
  },
  {
    "path": "Makefile",
    "content": ".PHONY: all test clean man godep fast release install\n\nall: textql\n\ntextql: test\n\tgo build -ldflags \"-X main.VERSION=`cat VERSION` -s\" -o ./build/textql ./textql/main.go\n\nfast:\n\tgo build -i -ldflags \"-X main.VERSION=`cat VERSION`-dev -s\" -o ./build/textql ./textql/main.go\n\ntest:\n\tgo test ./...\n\nclean:\n\trm -fr ./build\n\nrelease: textql\n\tgit tag -a `cat VERSION`\n\tgit push origin `cat VERSION`\n\ninstall: test\n\tgo install -ldflags \"-X main.VERSION=`cat VERSION` -s\" ./textql/main.go\n\nman:\n\tronn man/textql.1.ronn\n"
  },
  {
    "path": "PKGBUILD",
    "content": "# Maintainer: Aniket-Pradhan aniket17133@iiitd.ac.in\n# Owner/Cofntributer: Paul Bergeron https://github.com/dinedal\n\npkgname=textql-git\npkgver=2.0.3\npkgrel=1\npkgdesc=\"Execute SQL against structured text like CSV or TSV\"\narch=('x86_64' 'i686')\nurl=\"https://github.com/dinedal/textql\"\nlicense=('MIT')\ndepends=('go')\nmakedepends=('git')\noptions=('!strip' '!emptydirs')\n_gourl=github.com/dinedal/textql\n\nbuild() {\n  GOPATH=\"$srcdir\" go get -v -u ${_gourl}/...\n}\n\ncheck() {\n  echo $GOPATH\n  echo $srcdir\n  GOPATH=\"$GOPATH:$srcdir\" go test -v ${_gourl}/...\n}\n\npackage() {\n  mkdir -p \"$pkgdir/usr/bin\"\n  install -p -m755 \"$srcdir/bin/\"* \"$pkgdir/usr/bin\"\n\n  mkdir -p \"$pkgdir/$GOPATH\"\n  cp -Rv --preserve=timestamps \"$srcdir/\"{src,pkg} \"$pkgdir/$GOPATH\"\n\n  for f in LICENSE COPYING LICENSE.* COPYING.*; do\n    if [ -e \"$srcdir/src/$_gourl/$f\" ]; then\n      install -Dm644 \"$srcdir/src/$_gourl/$f\" \\\n        \"$pkgdir/usr/share/licenses/$pkgname/$f\"\n    fi\n  done\n}\n\n# vim:set ts=2 sw=2 et:\n"
  },
  {
    "path": "Readme.md",
    "content": "# TextQL\n\n[![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)\n\nAllows you to easily execute SQL against structured text like CSV or TSV.\n\nExample session:\n\n![textql_usage_session](https://raw.github.com/dinedal/textql/master/textql_usage.gif)\n\n## Major changes!\n\nIn 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.\n\n### Changes since v1\n\nAdditions:\n\n- Numeric values are automatically recognized in more cases.\n- 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.\n- Added join support! Multiple files / directories can be loaded by listing them at the end of the command.\n- Directories are read by reading each file inside, and this is non-recursive.\n- You can list as many files / directories as you like.\n- Added flag '-output-file' to save output directly to a file.\n- Added flag '-output-dlm' to modify the output delimiter.\n- Added \"short SQL\" syntax.\n  - For the case of a single table, the `FROM [table]` can be dropped from the query.\n  - For simple selects, the `SELECT` keyword can be dropped from the query.\n  - This means the v1 command `textql -sql \"select * from tbl\" -source some_file.csv` can be shortened to `textql -sql \"*\" some_file.csv`\n\nChanges:\n\n- The flag '-outputHeader' was renamed to '-output-header'.\n\nRemovals:\n\n- 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.\n- Removed '-source', any files / paths at the end of the command are used, as well as piped-in data.\n\nBug fixes:\n\n- Writing to a directory no longer fails silently.\n\n## Key differences between textql and sqlite importing\n\n- sqlite import will not accept stdin, breaking unix pipes. textql will happily do so.\n- textql supports quote-escaped delimiters, sqlite does not.\n- textql leverages the sqlite in-memory database feature as much as possible and only touches disk if asked.\n\n## Is it any good?\n\n[Yes](https://news.ycombinator.com/item?id=3067434)\n\n## Requirements\n\n- Go 1.4 or later\n\n## Install\n\n**Latest release on Homebrew (OS X)**\n\n```bash\nbrew install textql\n```\n\n**Build from source**\n\n```bash\ngo get -u github.com/dinedal/textql/...\n```\n\n## Docker\n\nFirst build the image.\n\n```bash\ndocker build -t textql .\n```\n\nNow use that image mounting your current directory into the container.\n\n```bash\ndocker run --rm -it -v $(pwd):/tmp textql [rest_of_command]\n```\n\n### Alias\n\nYou can add the following alias to your system to provide quick access to TextQL:\n\n```bash\nalias textql='docker run --rm -it -v $(pwd):/tmp textql '\n```\n\n## AUR\n\n**Using an AUR-Helper**\n\n```bash\nyaourt textql-git\n```\n\n**Building from PKGBUILD**\nFirst clone the repository.\n```bash\nmakepkg -cs\n```\nThen install the package using pacman or your favorite Package Manager\n\n\n## Usage\n\n```bash\n  textql [-console] [-save-to path path] [-output-file path] [-output-dlm delimter] [-output-header] [-pretty] [-quiet] [-header] [-dlm delimter] [-sql sql_statements] [path ...]\n\n  -console\n        After all statements are run, open SQLite3 REPL with this data\n  -dlm string\n        Input delimiter character between fields -dlm=tab for tab, -dlm=0x## to specify a character code in hex (default \",\")\n  -header\n        Treat input files as having the first row as a header row\n  -output-dlm string\n        Output delimiter character between fields -output-dlm=tab for tab, -dlm=0x## to specify a character code in hex (default \",\")\n  -output-file file\n        Filename to write output to, if empty no output is written (default \"stdout\")\n  -output-header\n        Display column names in output\n  -quiet\n        Suppress logging\n  -pretty\n        Pretty print output\n  -save-to file\n        SQLite3 db is left on disk at this file\n  -sql string\n        SQL Statement(s) to run on the data\n  -version\n        Print version and exit\n```\n\n## I want stdev, average, other functions\n\nJust follow the install directions at [go-sqlite3-extension-functions](https://github.com/dinedal/go-sqlite3-extension-functions) and textql will automatically load this library.\n\nFull function list:\n\n- 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.\n- String: replicate, charindex, leftstr, rightstr, ltrim, rtrim, trim, replace, reverse, proper, padl, padr, padc, strfilter.\n- Aggregate: stdev, variance, mode, median, lower_quartile, upper_quartile\n\n## License\n\nNew MIT License - Copyright (c) 2015, 2016 Paul Bergeron [http://pauldbergeron.com/](http://pauldbergeron.com/)\n\nSee LICENSE for details\n"
  },
  {
    "path": "TODO.txt",
    "content": "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/dinedal/textql/vendor/github.com/youtube/vitess/data/test/bson_test\ngo/src/github.com/dinedal/textql/vendor/github.com/youtube/vitess/data/test/bson_test/input_int.go:7: MyType redeclared in this block\n    previous declaration at go/src/github.com/dinedal/textql/vendor/github.com/youtube/vitess/data/test/bson_test/input_custom.go:7\ngo/src/github.com/dinedal/textql/vendor/github.com/youtube/vitess/data/test/bson_test/input_map.go:7: MyType redeclared in this block\n    previous declaration at go/src/github.com/dinedal/textql/vendor/github.com/youtube/vitess/data/test/bson_test/input_int.go:7\ngo/src/github.com/dinedal/textql/vendor/github.com/youtube/vitess/data/test/bson_test/input_mixed.go:11: MyType redeclared in this block\n    previous declaration at go/src/github.com/dinedal/textql/vendor/github.com/youtube/vitess/data/test/bson_test/input_map.go:7\ngo/src/github.com/dinedal/textql/vendor/github.com/youtube/vitess/data/test/bson_test/input_private.go:7: MyType redeclared in this block\n    previous declaration at go/src/github.com/dinedal/textql/vendor/github.com/youtube/vitess/data/test/bson_test/input_mixed.go:11\ngo/src/github.com/dinedal/textql/vendor/github.com/youtube/vitess/data/test/bson_test/input_ptr.go:7: MyType redeclared in this block\n    previous declaration at go/src/github.com/dinedal/textql/vendor/github.com/youtube/vitess/data/test/bson_test/input_private.go:7\ngo/src/github.com/dinedal/textql/vendor/github.com/youtube/vitess/data/test/bson_test/input_simple.go:9: MyType redeclared in this block\n    previous declaration at go/src/github.com/dinedal/textql/vendor/github.com/youtube/vitess/data/test/bson_test/input_ptr.go:7\ngo/src/github.com/dinedal/textql/vendor/github.com/youtube/vitess/data/test/bson_test/input_slice.go:7: MyType redeclared in this block\n    previous declaration at go/src/github.com/dinedal/textql/vendor/github.com/youtube/vitess/data/test/bson_test/input_simple.go:9\ngo/src/github.com/dinedal/textql/vendor/github.com/youtube/vitess/data/test/bson_test/input_tag.go:7: MyType redeclared in this block\n    previous declaration at go/src/github.com/dinedal/textql/vendor/github.com/youtube/vitess/data/test/bson_test/input_slice.go:7\ngo/src/github.com/dinedal/textql/vendor/github.com/youtube/vitess/data/test/bson_test/output_int.go:29: (*MyType).UnmarshalBson redeclared in this block\n    previous declaration at go/src/github.com/dinedal/textql/vendor/github.com/youtube/vitess/data/test/bson_test/output_custom.go:42\ngo/src/github.com/dinedal/textql/vendor/github.com/youtube/vitess/data/test/bson_test/output_map.go:18: (*MyType).MarshalBson redeclared in this block\n    previous declaration at go/src/github.com/dinedal/textql/vendor/github.com/youtube/vitess/data/test/bson_test/output_custom.go:19\ngo/src/github.com/dinedal/textql/vendor/github.com/youtube/vitess/data/test/bson_test/output_map.go:18: too many errors\n# pkg-config --cflags gomysql\nPackage gomysql was not found in the pkg-config search path.\nPerhaps you should add the directory containing `gomysql.pc'\nto the PKG_CONFIG_PATH environment variable\nNo package 'gomysql' found\npkg-config: exit status 1\n# launchpad.net/gozk/zookeeper\ngo/src/launchpad.net/gozk/zookeeper/zk.go:15:10: fatal error: 'zookeeper.h' file not found\n#include <zookeeper.h>\n         ^\n1 error generated.\n# github.com/youtube/vitess/go/stats/influxdbbackend\ngo/src/github.com/youtube/vitess/go/stats/influxdbbackend/influxdb_backend.go:40: undefined: client.ClientConfig\ngo/src/github.com/youtube/vitess/go/stats/influxdbbackend/influxdb_backend.go:60: undefined: client.Series\ngo/src/github.com/youtube/vitess/go/stats/influxdbbackend/influxdb_backend.go:62: undefined: client.Series\ngo/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)\n# github.com/youtube/vitess/go/terminal\ngo/src/github.com/youtube/vitess/go/terminal/tty.go:16: undefined: syscall.TCGETS\n# pkg-config --cflags gomysql\nPackage gomysql was not found in the pkg-config search path.\nPerhaps you should add the directory containing `gomysql.pc'\nto the PKG_CONFIG_PATH environment variable\nNo package 'gomysql' found\npkg-config: exit status 1\n# github.com/dinedal/textql/vendor/github.com/youtube/vitess/go/stats/influxdbbackend\ngo/src/github.com/dinedal/textql/vendor/github.com/youtube/vitess/go/stats/influxdbbackend/influxdb_backend.go:40: undefined: client.ClientConfig\ngo/src/github.com/dinedal/textql/vendor/github.com/youtube/vitess/go/stats/influxdbbackend/influxdb_backend.go:60: undefined: client.Series\ngo/src/github.com/dinedal/textql/vendor/github.com/youtube/vitess/go/stats/influxdbbackend/influxdb_backend.go:62: undefined: client.Series\ngo/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)\n# github.com/dinedal/textql/vendor/github.com/youtube/vitess/go/terminal\ngo/src/github.com/dinedal/textql/vendor/github.com/youtube/vitess/go/terminal/tty.go:16: undefined: syscall.TCGETS\n# github.com/dinedal/textql/vendor/github.com/youtube/vitess/third_party/go/launchpad.net/gozk/zookeeper\ngo/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\n#include <zookeeper.h>\n         ^\n1 error generated.\n\n\n\nFix all the below:\n\n\nGofmt formats Go programs. We run gofmt -s on your code, where -s is for the \"simplify\" command\n\n/github.com/dinedal/textql/outputs/csv.go\n/github.com/dinedal/textql/storage/sqlite_test.go\n\nGocyclo 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 '||'\n\n/github.com/dinedal/textql/cmd/textql.go\nLine 106: 24 main main repos/src/github.com/dinedal/textql/cmd/textql.go:106:1\n/github.com/dinedal/textql/sqlparser/parsed_query.go\nLine 53: 18 sqlparser EncodeValue repos/src/github.com/dinedal/textql/sqlparser/parsed_query.go:53:1\n/github.com/dinedal/textql/sqlparser/sql.go\n/github.com/dinedal/textql/sqlparser/token.go\nLine 141: 31 sqlparser (*Tokenizer).Scan repos/src/github.com/dinedal/textql/sqlparser/token.go:141:1\nLine 297: 16 sqlparser (*Tokenizer).scanNumber repos/src/github.com/dinedal/textql/sqlparser/token.go:297:1\n/github.com/dinedal/textql/sqlparser/tracked_buffer.go\nLine 40: 18 sqlparser (*TrackedBuffer).Myprintf repos/src/github.com/dinedal/textql/sqlparser/tracked_buffer.go:40:1\ngofmt\n89%\ngolint\n10%\nGolint is a linter for Go source code.\n\n/github.com/dinedal/textql/cmd/textql.go\nLine 18: exported type CommandLineOptions should have comment or be unexported\nLine 32: exported var VERSION should have comment or be unexported\nLine 34: exported function NewCommandLineOptions should have comment or be unexported\nLine 52: exported method CommandLineOptions.GetCommands should have comment or be unexported\nLine 52: receiver name should be a reflection of its identity; don't use generic names such as \"me\", \"this\", or \"self\"\nLine 56: exported method CommandLineOptions.GetSourceFiles should have comment or be unexported\nLine 56: receiver name should be a reflection of its identity; don't use generic names such as \"me\", \"this\", or \"self\"\nLine 60: exported method CommandLineOptions.GetDelimiter should have comment or be unexported\nLine 60: receiver name should be a reflection of its identity; don't use generic names such as \"me\", \"this\", or \"self\"\nLine 64: exported method CommandLineOptions.GetHeader should have comment or be unexported\nLine 64: receiver name should be a reflection of its identity; don't use generic names such as \"me\", \"this\", or \"self\"\nLine 68: exported method CommandLineOptions.GetOutputHeader should have comment or be unexported\nLine 68: receiver name should be a reflection of its identity; don't use generic names such as \"me\", \"this\", or \"self\"\nLine 72: exported method CommandLineOptions.GetOutputDelimiter should have comment or be unexported\nLine 72: receiver name should be a reflection of its identity; don't use generic names such as \"me\", \"this\", or \"self\"\nLine 76: exported method CommandLineOptions.GetOutputFile should have comment or be unexported\nLine 76: receiver name should be a reflection of its identity; don't use generic names such as \"me\", \"this\", or \"self\"\nLine 80: exported method CommandLineOptions.GetSaveTo should have comment or be unexported\nLine 80: receiver name should be a reflection of its identity; don't use generic names such as \"me\", \"this\", or \"self\"\nLine 84: exported method CommandLineOptions.GetConsole should have comment or be unexported\nLine 84: receiver name should be a reflection of its identity; don't use generic names such as \"me\", \"this\", or \"self\"\nLine 88: exported method CommandLineOptions.GetVersion should have comment or be unexported\nLine 88: receiver name should be a reflection of its identity; don't use generic names such as \"me\", \"this\", or \"self\"\nLine 92: exported method CommandLineOptions.GetQuiet should have comment or be unexported\nLine 92: receiver name should be a reflection of its identity; don't use generic names such as \"me\", \"this\", or \"self\"\nLine 96: exported method CommandLineOptions.Usage should have comment or be unexported\nLine 96: receiver name should be a reflection of its identity; don't use generic names such as \"me\", \"this\", or \"self\"\nLine 133: can probably use \"var inputSources []string\" instead\n/github.com/dinedal/textql/inputs/csv.go\nLine 21: exported type CSVInputOptions should have comment or be unexported\nLine 27: exported function NewCSVInput should have comment or be unexported\nLine 27: exported func NewCSVInput returns unexported type *inputs.csvInput, which can be annoying to use\nLine 49: receiver name should be a reflection of its identity; don't use generic names such as \"me\", \"this\", or \"self\"\nLine 53: receiver name should be a reflection of its identity; don't use generic names such as \"me\", \"this\", or \"self\"\nLine 57: receiver name should be a reflection of its identity; don't use generic names such as \"me\", \"this\", or \"self\"\nLine 84: receiver name should be a reflection of its identity; don't use generic names such as \"me\", \"this\", or \"self\"\nLine 106: receiver name should be a reflection of its identity; don't use generic names such as \"me\", \"this\", or \"self\"\n/github.com/dinedal/textql/inputs/input.go\nLine 3: exported type Input should have comment or be unexported\n/github.com/dinedal/textql/outputs/csv.go\nLine 18: exported type CSVOutputOptions should have comment or be unexported\nLine 24: exported function NewCSVOutput should have comment or be unexported\nLine 24: exported func NewCSVOutput returns unexported type *outputs.csvOutput, which can be annoying to use\nLine 35: receiver name should be a reflection of its identity; don't use generic names such as \"me\", \"this\", or \"self\"\nLine 53: should omit 2nd value from range; this loop is equivalent to `for i := range ...`\n/github.com/dinedal/textql/outputs/output.go\nLine 5: exported type Output should have comment or be unexported\n/github.com/dinedal/textql/sqlparser/analyzer.go\nLine 50: comment on exported function HasINClause should be of the form \"HasINClause ...\"\n/github.com/dinedal/textql/sqlparser/ast.go\nLine 56: exported method Union.IStatement should have comment or be unexported\nLine 57: exported method Select.IStatement should have comment or be unexported\nLine 58: exported method Insert.IStatement should have comment or be unexported\nLine 59: exported method Update.IStatement should have comment or be unexported\nLine 60: exported method Delete.IStatement should have comment or be unexported\nLine 61: exported method Set.IStatement should have comment or be unexported\nLine 62: exported method DDL.IStatement should have comment or be unexported\nLine 63: exported method Other.IStatement should have comment or be unexported\nLine 73: exported method Select.ISelectStatement should have comment or be unexported\nLine 74: exported method Union.ISelectStatement should have comment or be unexported\nLine 92: don't use ALL_CAPS in Go names; use CamelCase\nLine 97: don't use ALL_CAPS in Go names; use CamelCase\nLine 98: don't use ALL_CAPS in Go names; use CamelCase\nLine 101: exported method Select.Format should have comment or be unexported\nLine 117: don't use ALL_CAPS in Go names; use CamelCase\nLine 118: don't use ALL_CAPS in Go names; use CamelCase\nLine 119: don't use ALL_CAPS in Go names; use CamelCase\nLine 120: don't use ALL_CAPS in Go names; use CamelCase\nLine 121: don't use ALL_CAPS in Go names; use CamelCase\nLine 124: exported method Union.Format should have comment or be unexported\nLine 137: exported method Insert.Format should have comment or be unexported\nLine 149: exported method Select.IInsertRows should have comment or be unexported\nLine 150: exported method Union.IInsertRows should have comment or be unexported\nLine 151: exported method Values.IInsertRows should have comment or be unexported\nLine 163: exported method Update.Format should have comment or be unexported\nLine 178: exported method Delete.Format should have comment or be unexported\nLine 190: exported method Set.Format should have comment or be unexported\nLine 204: don't use ALL_CAPS in Go names; use CamelCase\nLine 204: exported const AST_CREATE should have comment (or a comment on this block) or be unexported\nLine 205: don't use ALL_CAPS in Go names; use CamelCase\nLine 206: don't use ALL_CAPS in Go names; use CamelCase\nLine 207: don't use ALL_CAPS in Go names; use CamelCase\nLine 210: exported method DDL.Format should have comment or be unexported\nLine 226: exported method Other.Format should have comment or be unexported\nLine 233: exported method Comments.Format should have comment or be unexported\nLine 242: exported method SelectExprs.Format should have comment or be unexported\nLine 256: exported method StarExpr.ISelectExpr should have comment or be unexported\nLine 257: exported method NonStarExpr.ISelectExpr should have comment or be unexported\nLine 264: exported method StarExpr.Format should have comment or be unexported\nLine 277: exported method NonStarExpr.Format should have comment or be unexported\nLine 290: exported method Columns.Format should have comment or be unexported\nLine 300: exported method TableExprs.Format should have comment or be unexported\nLine 314: exported method AliasedTableExpr.ITableExpr should have comment or be unexported\nLine 315: exported method ParenTableExpr.ITableExpr should have comment or be unexported\nLine 316: exported method JoinTableExpr.ITableExpr should have comment or be unexported\nLine 326: exported method AliasedTableExpr.Format should have comment or be unexported\nLine 343: exported method TableName.ISimpleTableExpr should have comment or be unexported\nLine 344: exported method Subquery.ISimpleTableExpr should have comment or be unexported\nLine 351: exported method TableName.Format should have comment or be unexported\nLine 364: exported method ParenTableExpr.Format should have comment or be unexported\nLine 378: don't use ALL_CAPS in Go names; use CamelCase\nLine 379: don't use ALL_CAPS in Go names; use CamelCase\nLine 380: don't use ALL_CAPS in Go names; use CamelCase\nLine 381: don't use ALL_CAPS in Go names; use CamelCase\nLine 382: don't use ALL_CAPS in Go names; use CamelCase\nLine 383: don't use ALL_CAPS in Go names; use CamelCase\nLine 386: exported method JoinTableExpr.Format should have comment or be unexported\nLine 400: don't use ALL_CAPS in Go names; use CamelCase\nLine 400: exported const AST_USE should have comment (or a comment on this block) or be unexported\nLine 401: don't use ALL_CAPS in Go names; use CamelCase\nLine 402: don't use ALL_CAPS in Go names; use CamelCase\nLine 405: exported method IndexHints.Format should have comment or be unexported\nLine 423: don't use ALL_CAPS in Go names; use CamelCase\nLine 424: don't use ALL_CAPS in Go names; use CamelCase\nLine 436: exported method Where.Format should have comment or be unexported\nLine 451: don't use ALL_CAPS in Go names; use CamelCase\nLine 463: exported method From.Format should have comment or be unexported\nLine 476: exported method AndExpr.IExpr should have comment or be unexported\nLine 477: exported method OrExpr.IExpr should have comment or be unexported\nLine 478: exported method NotExpr.IExpr should have comment or be unexported\nLine 479: exported method ParenBoolExpr.IExpr should have comment or be unexported\nLine 480: exported method ComparisonExpr.IExpr should have comment or be unexported\nLine 481: exported method RangeCond.IExpr should have comment or be unexported\nLine 482: exported method NullCheck.IExpr should have comment or be unexported\nLine 483: exported method ExistsExpr.IExpr should have comment or be unexported\nLine 484: exported method KeyrangeExpr.IExpr should have comment or be unexported\nLine 485: exported method StrVal.IExpr should have comment or be unexported\nLine 486: exported method NumVal.IExpr should have comment or be unexported\nLine 487: exported method ValArg.IExpr should have comment or be unexported\nLine 488: exported method NullVal.IExpr should have comment or be unexported\nLine 489: exported method ColName.IExpr should have comment or be unexported\nLine 490: exported method ValTuple.IExpr should have comment or be unexported\nLine 491: exported method Subquery.IExpr should have comment or be unexported\nLine 492: exported method ListArg.IExpr should have comment or be unexported\nLine 493: exported method BinaryExpr.IExpr should have comment or be unexported\nLine 494: exported method UnaryExpr.IExpr should have comment or be unexported\nLine 495: exported method FuncExpr.IExpr should have comment or be unexported\nLine 496: exported method CaseExpr.IExpr should have comment or be unexported\nLine 504: exported method AndExpr.IBoolExpr should have comment or be unexported\nLine 505: exported method OrExpr.IBoolExpr should have comment or be unexported\nLine 506: exported method NotExpr.IBoolExpr should have comment or be unexported\nLine 507: exported method ParenBoolExpr.IBoolExpr should have comment or be unexported\nLine 508: exported method ComparisonExpr.IBoolExpr should have comment or be unexported\nLine 509: exported method RangeCond.IBoolExpr should have comment or be unexported\nLine 510: exported method NullCheck.IBoolExpr should have comment or be unexported\nLine 511: exported method ExistsExpr.IBoolExpr should have comment or be unexported\nLine 512: exported method KeyrangeExpr.IBoolExpr should have comment or be unexported\nLine 519: exported method AndExpr.Format should have comment or be unexported\nLine 528: exported method OrExpr.Format should have comment or be unexported\nLine 537: exported method NotExpr.Format should have comment or be unexported\nLine 546: exported method ParenBoolExpr.Format should have comment or be unexported\nLine 558: don't use ALL_CAPS in Go names; use CamelCase\nLine 559: don't use ALL_CAPS in Go names; use CamelCase\nLine 560: don't use ALL_CAPS in Go names; use CamelCase\nLine 561: don't use ALL_CAPS in Go names; use CamelCase\nLine 562: don't use ALL_CAPS in Go names; use CamelCase\nLine 563: don't use ALL_CAPS in Go names; use CamelCase\nLine 564: don't use ALL_CAPS in Go names; use CamelCase\nLine 565: don't use ALL_CAPS in Go names; use CamelCase\nLine 566: don't use ALL_CAPS in Go names; use CamelCase\nLine 567: don't use ALL_CAPS in Go names; use CamelCase\nLine 568: don't use ALL_CAPS in Go names; use CamelCase\nLine 571: exported method ComparisonExpr.Format should have comment or be unexported\nLine 584: don't use ALL_CAPS in Go names; use CamelCase\nLine 585: don't use ALL_CAPS in Go names; use CamelCase\nLine 588: exported method RangeCond.Format should have comment or be unexported\nLine 600: don't use ALL_CAPS in Go names; use CamelCase\nLine 601: don't use ALL_CAPS in Go names; use CamelCase\nLine 604: exported method NullCheck.Format should have comment or be unexported\nLine 613: exported method ExistsExpr.Format should have comment or be unexported\nLine 622: exported method KeyrangeExpr.Format should have comment or be unexported\nLine 632: exported method StrVal.IValExpr should have comment or be unexported\nLine 633: exported method NumVal.IValExpr should have comment or be unexported\nLine 634: exported method ValArg.IValExpr should have comment or be unexported\nLine 635: exported method NullVal.IValExpr should have comment or be unexported\nLine 636: exported method ColName.IValExpr should have comment or be unexported\nLine 637: exported method ValTuple.IValExpr should have comment or be unexported\nLine 638: exported method Subquery.IValExpr should have comment or be unexported\nLine 639: exported method ListArg.IValExpr should have comment or be unexported\nLine 640: exported method BinaryExpr.IValExpr should have comment or be unexported\nLine 641: exported method UnaryExpr.IValExpr should have comment or be unexported\nLine 642: exported method FuncExpr.IValExpr should have comment or be unexported\nLine 643: exported method CaseExpr.IValExpr should have comment or be unexported\nLine 648: exported method StrVal.Format should have comment or be unexported\nLine 656: exported method NumVal.Format should have comment or be unexported\nLine 663: exported method ValArg.Format should have comment or be unexported\nLine 670: exported method NullVal.Format should have comment or be unexported\nLine 679: exported method ColName.Format should have comment or be unexported\nLine 702: exported method ValTuple.IColTuple should have comment or be unexported\nLine 703: exported method Subquery.IColTuple should have comment or be unexported\nLine 704: exported method ListArg.IColTuple should have comment or be unexported\nLine 709: exported method ValTuple.Format should have comment or be unexported\nLine 717: exported method ValExprs.Format should have comment or be unexported\nLine 730: exported method Subquery.Format should have comment or be unexported\nLine 737: exported method ListArg.Format should have comment or be unexported\nLine 749: don't use ALL_CAPS in Go names; use CamelCase\nLine 750: don't use ALL_CAPS in Go names; use CamelCase\nLine 751: don't use ALL_CAPS in Go names; use CamelCase\nLine 752: don't use ALL_CAPS in Go names; use CamelCase\nLine 753: don't use ALL_CAPS in Go names; use CamelCase\nLine 754: don't use ALL_CAPS in Go names; use CamelCase\nLine 755: don't use ALL_CAPS in Go names; use CamelCase\nLine 756: don't use ALL_CAPS in Go names; use CamelCase\nLine 759: exported method BinaryExpr.Format should have comment or be unexported\nLine 771: don't use ALL_CAPS in Go names; use CamelCase\nLine 772: don't use ALL_CAPS in Go names; use CamelCase\nLine 773: don't use ALL_CAPS in Go names; use CamelCase\nLine 776: exported method UnaryExpr.Format should have comment or be unexported\nLine 787: exported method FuncExpr.Format should have comment or be unexported\nLine 815: exported method FuncExpr.IsAggregate should have comment or be unexported\nLine 826: exported method CaseExpr.Format should have comment or be unexported\nLine 846: exported method When.Format should have comment or be unexported\nLine 853: exported method GroupBy.Format should have comment or be unexported\nLine 864: exported method OrderBy.Format should have comment or be unexported\nLine 880: don't use ALL_CAPS in Go names; use CamelCase\nLine 881: don't use ALL_CAPS in Go names; use CamelCase\nLine 884: exported method Order.Format should have comment or be unexported\nLine 893: exported method Limit.Format should have comment or be unexported\nLine 950: exported method Values.Format should have comment or be unexported\nLine 964: exported method ValTuple.IRowTuple should have comment or be unexported\nLine 965: exported method Subquery.IRowTuple should have comment or be unexported\nLine 970: exported method UpdateExprs.Format should have comment or be unexported\nLine 984: exported method UpdateExpr.Format should have comment or be unexported\nLine 991: exported method OnDup.Format should have comment or be unexported\n/github.com/dinedal/textql/sqlparser/parsed_query.go\nLine 20: exported type ParsedQuery should have comment or be unexported\nLine 25: exported type EncoderFunc should have comment or be unexported\nLine 27: exported method ParsedQuery.GenerateQuery should have comment or be unexported\nLine 49: exported method ParsedQuery.MarshalJSON should have comment or be unexported\nLine 53: exported function EncodeValue should have comment or be unexported\nLine 102: exported type TupleEqualityList should have comment or be unexported\nLine 107: exported method TupleEqualityList.Encode should have comment or be unexported\nLine 156: exported function FetchBindVar should have comment or be unexported\n/github.com/dinedal/textql/sqlparser/sql.go\n/github.com/dinedal/textql/sqlparser/token.go\nLine 15: exported const EOFCHAR should have comment or be unexported\nLine 172: if block ends with a return statement, so drop this else and outdent its block\nLine 190: if block ends with a return statement, so drop this else and outdent its block\nLine 214: if block ends with a return statement, so drop this else and outdent its block\nLine 221: if block ends with a return statement, so drop this else and outdent its block\nLine 249: var keywordId should be keywordID\nLine 417: exported method Tokenizer.ConsumeNext should have comment or be unexported\n/github.com/dinedal/textql/sqlparser/tracked_buffer.go\nLine 25: exported function NewTrackedBuffer should have comment or be unexported\nLine 101: exported method TrackedBuffer.ParsedQuery should have comment or be unexported\nLine 105: exported method TrackedBuffer.HasBindVars should have comment or be unexported\n/github.com/dinedal/textql/storage/sqlite.go\nLine 20: struct field connId should be connID\nLine 24: exported type SQLite3Options should have comment or be unexported\nLine 27: should omit type []*sqlite3.SQLiteConn from declaration of var sqlite3conn; it will be inferred from the right-hand side\nLine 28: should omit type *regexp.Regexp from declaration of var allWhiteSpace; it will be inferred from the right-hand side\nLine 29: should omit type *regexp.Regexp from declaration of var tableNameCheckRegEx; it will be inferred from the right-hand side\nLine 42: exported function NewSQLite3Storage should have comment or be unexported\nLine 42: exported func NewSQLite3Storage returns unexported type *storage.sqlite3Storage, which can be annoying to use\nLine 52: receiver name should be a reflection of its identity; don't use generic names such as \"me\", \"this\", or \"self\"\nLine 69: receiver name should be a reflection of its identity; don't use generic names such as \"me\", \"this\", or \"self\"\nLine 97: receiver name should be a reflection of its identity; don't use generic names such as \"me\", \"this\", or \"self\"\nLine 135: receiver name should be a reflection of its identity; don't use generic names such as \"me\", \"this\", or \"self\"\nLine 160: receiver name should be a reflection of its identity; don't use generic names such as \"me\", \"this\", or \"self\"\nLine 165: can probably use \"var vals []interface{}\" instead\nLine 184: receiver name should be a reflection of its identity; don't use generic names such as \"me\", \"this\", or \"self\"\nLine 199: receiver name should be a reflection of its identity; don't use generic names such as \"me\", \"this\", or \"self\"\nLine 207: var backupConnId should be backupConnID\nLine 234: receiver name should be a reflection of its identity; don't use generic names such as \"me\", \"this\", or \"self\"\n/github.com/dinedal/textql/storage/sqlite_test.go\nLine 188: should omit 2nd value from range; this loop is equivalent to `for i := range ...`\n/github.com/dinedal/textql/storage/storage.go\nLine 9: exported type Storage should have comment or be unexported\n/github.com/dinedal/textql/test_util/test_util.go\nLine 1: don't use an underscore in package name\nLine 8: exported function OpenFileFromString should have comment or be unexported\n/github.com/dinedal/textql/util/file_helpers.go\nLine 12: exported function IsPathDir should have comment or be unexported\nLine 30: exported function OpenFileOrStdDev should have comment or be unexported\nLine 65: exported function CleanPath should have comment or be unexported\nLine 94: exported function RewindFile should have comment or be unexported\nLine 102: exported function IsThereDataOnStdin should have comment or be unexported\nLine 111: if block ends with a return statement, so drop this else and outdent its block\nLine 116: exported function AllFilesInDirectory should have comment or be unexported\nLine 119: can probably use \"var result []string\" instead\n/github.com/dinedal/textql/util/seperator_helpers.go\nLine 10: exported function DetermineSeparator should have comment or be unexported\n"
  },
  {
    "path": "VERSION",
    "content": "2.0.3\n"
  },
  {
    "path": "go.mod",
    "content": "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/go-sqlite3 v2.0.3+incompatible\n\tgithub.com/olekukonko/tablewriter v0.0.0-20180506121414-d4647c9c7a84\n)\n"
  },
  {
    "path": "go.sum",
    "content": "github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=\ngithub.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=\ngithub.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=\ngithub.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712 h1:aaQcKT9WumO6JEJcRyTqFVq4XUZiUcKR2/GI31TOcz8=\ngithub.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=\ngithub.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=\ngithub.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=\ngithub.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=\ngithub.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=\ngithub.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=\ngithub.com/mattn/go-runewidth v0.0.2 h1:UnlwIPBGaTZfPQ6T1IGzPI0EkYAQmT9fAEJ/poFC63o=\ngithub.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=\ngithub.com/mattn/go-sqlite3 v1.9.0 h1:pDRiWfl+++eC2FEFRy6jXmQlvp4Yh3z1MJKg4UeYM/4=\ngithub.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=\ngithub.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U=\ngithub.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=\ngithub.com/olekukonko/tablewriter v0.0.0-20180506121414-d4647c9c7a84 h1:fiKJgB4JDUd43CApkmCeTSQlWjtTtABrU2qsgbuP0BI=\ngithub.com/olekukonko/tablewriter v0.0.0-20180506121414-d4647c9c7a84/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=\ngithub.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=\ngithub.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446 h1:/NRJ5vAYoqz+7sG51ubIDHXeWO8DlTSrToPu6q11ziA=\ngithub.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M=\ngithub.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=\ngithub.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=\ngithub.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=\ngithub.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=\ngithub.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=\ngitlab.com/cznic/ebnf2y v1.0.0/go.mod h1:jx14dqOldV2pRvSi8HASTB/k5fkIv2TwjYAp5py0MTs=\ngitlab.com/cznic/golex v1.0.0/go.mod h1:vkWdDgqbbThjRHoOLU7yNPgMxaubAkwnvF/4zeG8cvU=\ngolang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=\ngolang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=\ngolang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=\ngolang.org/x/exp v0.0.0-20190411193353-0480eff6dd7c/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=\ngolang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=\ngolang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=\ngolang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=\ngolang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee h1:WG0RUwxtNT4qqaXX3DPA8zHFNm/D9xaBpxzHt1WcA/E=\ngolang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=\ngolang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=\ngolang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=\ngolang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=\ngolang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=\ngolang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=\ngolang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=\ngolang.org/x/tools v0.0.0-20200130224948-02f1738cbe39 h1:5ERHXLQfA0b8cHOwaOfWaaGekrA4+Ka/N74zilLnsIk=\ngolang.org/x/tools v0.0.0-20200130224948-02f1738cbe39/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=\ngolang.org/x/tools v0.0.0-20200131211209-ecb101ed6550 h1:3Kc3/T5DQ/majKzDmb+0NzmbXFhKLaeDTp3KqVPV5Eo=\ngolang.org/x/tools/gopls v0.3.0 h1:l9KKK1/n6CIbfgaUvHBWAvCfOxcl1N+KSOK79OlPIao=\ngolang.org/x/tools/gopls v0.3.0/go.mod h1:vvBkm7WBjHNudDeK7Sg7HeR+sKt6yp5TD/4NQaTZzRs=\ngolang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbOeHJjicWYPqR9bpxqxYG2pA=\ngolang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=\ngopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\nhonnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=\nhonnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=\nmodernc.org/b v1.0.0 h1:vpvqeyp17ddcQWF29Czawql4lDdABCDRbXRAS4+aF2o=\nmodernc.org/b v1.0.0/go.mod h1:uZWcZfRj1BpYzfN9JTerzlNUnnPsV9O2ZA8JsRcubNg=\nmodernc.org/db v1.0.0 h1:2c6NdCfaLnshSvY7OU09cyAY0gYXUZj4lmg5ItHyucg=\nmodernc.org/db v1.0.0/go.mod h1:kYD/cO29L/29RM0hXYl4i3+Q5VojL31kTUVpVJDw0s8=\nmodernc.org/ebnfutil v1.0.0/go.mod h1:+2n/OnQXoild9pzrPa/2wmVtR+ufWjB/0fYkc0BV9sc=\nmodernc.org/file v1.0.0 h1:9/PdvjVxd5+LcWUQIfapAWRGOkDLK90rloa8s/au06A=\nmodernc.org/file v1.0.0/go.mod h1:uqEokAEn1u6e+J45e54dsEA/pw4o7zLrA2GwyntZzjw=\nmodernc.org/fileutil v1.0.0 h1:Z1AFLZwl6BO8A5NldQg/xTSjGLetp+1Ubvl4alfGx8w=\nmodernc.org/fileutil v1.0.0/go.mod h1:JHsWpkrk/CnVV1H/eGlFf85BEpfkrp56ro8nojIq9Q8=\nmodernc.org/golex v1.0.0 h1:wWpDlbK8ejRfSyi0frMyhilD3JBvtcx2AdGDnU+JtsE=\nmodernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk=\nmodernc.org/internal v1.0.0 h1:XMDsFDcBDsibbBnHB2xzljZ+B1yrOVLEFkKL2u15Glw=\nmodernc.org/internal v1.0.0/go.mod h1:VUD/+JAkhCpvkUitlEOnhpVxCgsBI90oTzSCRcqQVSM=\nmodernc.org/lex v1.0.0/go.mod h1:G6rxMTy3cH2iA0iXL/HRRv4Znu8MK4higxph/lE7ypk=\nmodernc.org/lexer v1.0.0/go.mod h1:F/Dld0YKYdZCLQ7bD0USbWL4YKCyTDRDHiDTOs0q0vk=\nmodernc.org/lldb v1.0.0 h1:6vjDJxQEfhlOLwl4bhpwIz00uyFK4EmSYcbwqwbynsc=\nmodernc.org/lldb v1.0.0/go.mod h1:jcRvJGWfCGodDZz8BPwiKMJxGJngQ/5DrRapkQnLob8=\nmodernc.org/mathutil v1.0.0 h1:93vKjrJopTPrtTNpZ8XIovER7iCIH1QU7wNbOQXC60I=\nmodernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k=\nmodernc.org/ql v1.0.1 h1:pwGOhUbl75KRiGEUUotORpnBlI0whDEb/koIqZOGI7k=\nmodernc.org/ql v1.0.1/go.mod h1:Fj1ylcVyzcu/fgWZTrvBO9j/aEUg/ixLFnGtmzh7quI=\nmodernc.org/sortutil v1.0.0 h1:SUTM1sCR0Ldpv7dbB/KCPC2zHHsZ1KrSkhmGmmV22CQ=\nmodernc.org/sortutil v1.0.0/go.mod h1:1QO0q8IlIlmjBIwm6t/7sof874+xCfZouyqZMLIAtxM=\nmodernc.org/strutil v1.0.0 h1:XVFtQwFVwc02Wk+0L/Z/zDDXO81r5Lhe6iMKmGX3KhE=\nmodernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs=\nmodernc.org/zappy v1.0.0 h1:dPVaP+3ueIUv4guk8PuZ2wiUGcJ1WUVvIheeSSTD0yk=\nmodernc.org/zappy v1.0.0/go.mod h1:hHe+oGahLVII/aTTyWK/b53VDHMAGCBYYeZ9sn83HC4=\nmvdan.cc/xurls/v2 v2.1.0 h1:KaMb5GLhlcSX+e+qhbRJODnUUBvlw01jt4yrjFIHAuA=\nmvdan.cc/xurls/v2 v2.1.0/go.mod h1:5GrSd9rOnKOpZaji1OZLYL/yeAAtGDlo/cFe+8K5n8E=\n"
  },
  {
    "path": "inputs/csv.go",
    "content": "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 record producing input from a CSV formatted file or pipe.\ntype CSVInput struct {\n\toptions         *CSVInputOptions\n\treader          *csv.Reader\n\tfirstRow        []string\n\theader          []string\n\tminOutputLength int\n\tname            string\n}\n\n// CSVInputOptions options are passed to the underlying encoding/csv reader.\ntype CSVInputOptions struct {\n\t// HasHeader when true, will treat the first row as a header row.\n\tHasHeader bool\n\t// Separator is the rune that fields are delimited by.\n\tSeparator rune\n\t// ReadFrom is where the data will be read from.\n\tReadFrom io.Reader\n}\n\n// NewCSVInput sets up a new CSVInput, the first row is read when this is run.\n// If there is a problem with reading the first row, the error is returned.\n// Otherwise, the returned csvInput can be reliably consumed with ReadRecord()\n// until ReadRecord() returns nil.\nfunc NewCSVInput(opts *CSVInputOptions) (*CSVInput, error) {\n\tcsvInput := &CSVInput{\n\t\toptions: opts,\n\t\treader:  csv.NewReader(opts.ReadFrom),\n\t}\n\tcsvInput.firstRow = nil\n\n\tcsvInput.reader.FieldsPerRecord = -1\n\tcsvInput.reader.Comma = csvInput.options.Separator\n\tcsvInput.reader.LazyQuotes = true\n\n\theaderErr := csvInput.readHeader()\n\n\tif headerErr != nil {\n\t\treturn nil, headerErr\n\t}\n\n\tif asFile, ok := csvInput.options.ReadFrom.(*os.File); ok {\n\t\tcsvInput.name = filepath.Base(asFile.Name())\n\t} else {\n\t\tcsvInput.name = \"pipe\"\n\t}\n\n\treturn csvInput, nil\n}\n\n// Name returns the name of the CSV being read.\n// By default, either the base filename or 'pipe' if it is a unix pipe\nfunc (csvInput *CSVInput) Name() string {\n\treturn csvInput.name\n}\n\n// SetName overrides the name of the CSV\nfunc (csvInput *CSVInput) SetName(name string) {\n\tcsvInput.name = name\n}\n\n// ReadRecord reads a single record from the CSV. Always returns successfully.\n// If the record is empty, an empty []string is returned.\n// Record expand to match the current row size, adding blank fields as needed.\n// Records never return less then the number of fields in the first row.\n// Returns nil on EOF\n// In the event of a parse error due to an invalid record, it is logged, and\n// an empty []string is returned with the number of fields in the first row,\n// as if the record were empty.\n//\n// In general, this is a very tolerant of problems CSV reader.\nfunc (csvInput *CSVInput) ReadRecord() []string {\n\tvar row []string\n\tvar fileErr error\n\n\tif csvInput.firstRow != nil {\n\t\trow = csvInput.firstRow\n\t\tcsvInput.firstRow = nil\n\t\treturn row\n\t}\n\n\trow, fileErr = csvInput.reader.Read()\n\temptysToAppend := csvInput.minOutputLength - len(row)\n\tif fileErr == io.EOF {\n\t\treturn nil\n\t} else if parseErr, ok := fileErr.(*csv.ParseError); ok {\n\t\tlog.Println(parseErr)\n\t\temptysToAppend = csvInput.minOutputLength\n\t}\n\n\tif emptysToAppend > 0 {\n\t\tfor counter := 0; counter < emptysToAppend; counter++ {\n\t\t\trow = append(row, \"\")\n\t\t}\n\t}\n\n\treturn row\n}\n\nfunc (csvInput *CSVInput) readHeader() error {\n\tvar readErr error\n\n\tcsvInput.firstRow, readErr = csvInput.reader.Read()\n\n\tif readErr != nil {\n\t\tlog.Fatalln(readErr)\n\t\treturn readErr\n\t}\n\n\tcsvInput.minOutputLength = len(csvInput.firstRow)\n\n\tif csvInput.options.HasHeader {\n\t\tcsvInput.header = csvInput.firstRow\n\t\tcsvInput.firstRow = nil\n\t} else {\n\t\tcsvInput.header = make([]string, csvInput.minOutputLength)\n\t\tfor i := 0; i < len(csvInput.firstRow); i++ {\n\t\t\tcsvInput.header[i] = \"c\" + strconv.Itoa(i)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// Header returns the header of the csvInput. Either the first row if a header\n// set in the options, or c#, where # is the column number, starting with 0.\nfunc (csvInput *CSVInput) Header() []string {\n\treturn csvInput.header\n}\n"
  },
  {
    "path": "inputs/csv_test.go",
    "content": "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\tsimple = `a,b,c\n1,2,3\n4,5,6`\n\n\tbad = `a,b,c\n1,2,\n4,5,6\n7,8\n\n\n9,,10\n11,12,13,14\n\"foo,bar\",\"boo,\\\"far\",\",\"\n'foo,bar','\"','\"'\n\"test\n\",multi-line\n`\n)\n\nfunc TestCSVInputFakesHeader(t *testing.T) {\n\tfp := test_util.OpenFileFromString(simple)\n\tdefer fp.Close()\n\tdefer os.Remove(fp.Name())\n\n\topts := &CSVInputOptions{\n\t\tHasHeader: false,\n\t\tSeparator: ',',\n\t\tReadFrom:  fp,\n\t}\n\n\tinput, _ := NewCSVInput(opts)\n\texpected := []string{\"c0\", \"c1\", \"c2\"}\n\n\tif !reflect.DeepEqual(input.Header(), expected) {\n\t\tt.Errorf(\"Header() = %v, want %v\", input.Header(), expected)\n\t}\n}\n\nfunc TestCSVInputReadsHeader(t *testing.T) {\n\tfp := test_util.OpenFileFromString(simple)\n\tdefer fp.Close()\n\tdefer os.Remove(fp.Name())\n\n\topts := &CSVInputOptions{\n\t\tHasHeader: true,\n\t\tSeparator: ',',\n\t\tReadFrom:  fp,\n\t}\n\n\tinput, _ := NewCSVInput(opts)\n\texpected := []string{\"a\", \"b\", \"c\"}\n\n\tif !reflect.DeepEqual(input.Header(), expected) {\n\t\tt.Errorf(\"Header() = %v, want %v\", input.Header(), expected)\n\t}\n}\n\nfunc TestCSVInputReadsSimple(t *testing.T) {\n\tfp := test_util.OpenFileFromString(simple)\n\tdefer fp.Close()\n\tdefer os.Remove(fp.Name())\n\n\topts := &CSVInputOptions{\n\t\tHasHeader: true,\n\t\tSeparator: ',',\n\t\tReadFrom:  fp,\n\t}\n\n\tinput, _ := NewCSVInput(opts)\n\texpected := make([][]string, len(strings.Split(simple, \"\\n\"))-1)\n\texpected[0] = []string{\"1\", \"2\", \"3\"}\n\texpected[1] = []string{\"4\", \"5\", \"6\"}\n\n\tfor counter := 0; counter < len(expected); counter++ {\n\t\trow := input.ReadRecord()\n\t\tif !reflect.DeepEqual(row, expected[counter]) {\n\t\t\tt.Errorf(\"ReadRecord() = %v, want %v\", row, expected[counter])\n\t\t}\n\t}\n}\n\nfunc TestCSVInputReadsBad(t *testing.T) {\n\tfp := test_util.OpenFileFromString(bad)\n\tdefer fp.Close()\n\tdefer os.Remove(fp.Name())\n\n\topts := &CSVInputOptions{\n\t\tHasHeader: true,\n\t\tSeparator: ',',\n\t\tReadFrom:  fp,\n\t}\n\n\tinput, _ := NewCSVInput(opts)\n\texpected := make([][]string, len(strings.Split(bad, \"\\n\"))-1)\n\texpected[0] = []string{\"1\", \"2\", \"\"}\n\texpected[1] = []string{\"4\", \"5\", \"6\"}\n\texpected[2] = []string{\"7\", \"8\", \"\"}\n\texpected[3] = []string{\"9\", \"\", \"10\"}\n\texpected[4] = []string{\"11\", \"12\", \"13\", \"14\"}\n\texpected[5] = []string{\"foo,bar\", `boo,\\\"far`, \",\"}\n\texpected[6] = []string{`'foo`, `bar'`, `'\"'`, `'\"'`}\n\texpected[7] = []string{\"test\\n\", \"multi-line\", \"\"}\n\n\tfor counter := 0; counter < len(expected); counter++ {\n\t\trow := input.ReadRecord()\n\t\tif !reflect.DeepEqual(row, expected[counter]) {\n\t\t\tt.Errorf(\"ReadRecord() = %v, want %v\", row, expected[counter])\n\t\t}\n\t}\n}\n\nfunc TestCSVInputHasAName(t *testing.T) {\n\tfp := test_util.OpenFileFromString(simple)\n\tdefer fp.Close()\n\tdefer os.Remove(fp.Name())\n\n\topts := &CSVInputOptions{\n\t\tHasHeader: true,\n\t\tSeparator: ',',\n\t\tReadFrom:  fp,\n\t}\n\n\tinput, _ := NewCSVInput(opts)\n\texpected := fp.Name()\n\n\tif !reflect.DeepEqual(input.Name(), expected) {\n\t\tt.Errorf(\"Name() = %v, want %v\", input.Name(), expected)\n\t}\n}\n"
  },
  {
    "path": "inputs/input.go",
    "content": "package inputs\n\n// Input is how TextQL reads from data sources.\n// To be an input, an implementor must return tabular data.\n// How data is manipulated into the tabular structure is left to the implementor.\n// Inputs are expected to return in a row by row fashion.\ntype Input interface {\n\t// ReadRecord should return nil on the end of data, or a single record.\n\t// Recoverable errors should represent themselves as empty sets.\n\t// Unrecoverable errors should return nil.\n\tReadRecord() []string\n\t// Header should return metadata naming the columns in the table.\n\tHeader() []string\n\t// Name should return a reasonable name for the data set, prehaps the file name.\n\tName() string\n\t// SetName allows users of the dataset to supply their own name if needed.\n\tSetName(string)\n}\n"
  },
  {
    "path": "man/textql.1",
    "content": ".\\\" generated with Ronn/v0.7.3\n.\\\" http://github.com/rtomayko/ronn/tree/0.7.3\n.\n.TH \"TEXTQL\" \"1\" \"December 2015\" \"\" \"\"\n.\n.SH \"NAME\"\n\\fBtextql\\fR \\- execute queries on structured text\n.\n.SH \"SYNOPSIS\"\n\\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\\.\\.\\.]\n.\n.br\n\\fBtextql\\fR \\fI\\-console\\fR \\fIpath\\fR\\.\\.\\.\n.\n.br\n.\n.SH \"DESCRIPTION\"\n\\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\\.\n.\n.P\nThe 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\\.\n.\n.P\nEach 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\n.\n.P\nWith no arguements, \\fBtextql\\fR will print a brief overview of it\\'s usage\\.\n.\n.SH \"FILES\"\nStructured 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)\\.\n.\n.SH \"OPTIONS\"\n.\n.TP\n\\fB\\-console\\fR\nAfter all statements are run, open SQLite3 REPL with this data\n.\n.TP\n\\fB\\-dlm string\\fR\nInput delimiter character between fields \\-dlm=tab for tab, \\-dlm=0x## to specify a character code in hex (default \",\")\n.\n.TP\n\\fB\\-header\\fR\nTreat input files as having the first row as a header row\n.\n.TP\n\\fB\\-output\\-dlm string\\fR\nOutput delimiter character between fields \\-output\\-dlm=tab for tab, \\-dlm=0x## to specify a character code in hex (default \",\")\n.\n.TP\n\\fB\\-output\\-file file\\fR\nFilename to write output to, if empty no output is written (default \"stdout\")\n.\n.TP\n\\fB\\-output\\-header\\fR\nDisplay column names in output\n.\n.TP\n\\fB\\-quiet\\fR\nSurpress logging\n.\n.TP\n\\fB\\-pretty\\fR\nPretty print output\n.\n.TP\n\\fB\\-save\\-to file\\fR\nSQLite3 db is left on disk at this file\n.\n.TP\n\\fB\\-sql string\\fR\nSQL Statement(s) to run on the data\n.\n.TP\n\\fB\\-version\\fR\nPrint version and exit\n.\n.SH \"COPYRIGHT\"\ntextql is Copyright (C) 2015, 2016 Paul Bergeron \\fIhttp://pauldbergeron\\.com/\\fR\n"
  },
  {
    "path": "man/textql.1.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <meta http-equiv='content-type' value='text/html;charset=utf8'>\n  <meta name='generator' value='Ronn/v0.7.3 (http://github.com/rtomayko/ronn/tree/0.7.3)'>\n  <title>textql(1) - execute queries on structured text</title>\n  <style type='text/css' media='all'>\n  /* style: man */\n  body#manpage {margin:0}\n  .mp {max-width:100ex;padding:0 9ex 1ex 4ex}\n  .mp p,.mp pre,.mp ul,.mp ol,.mp dl {margin:0 0 20px 0}\n  .mp h2 {margin:10px 0 0 0}\n  .mp > p,.mp > pre,.mp > ul,.mp > ol,.mp > dl {margin-left:8ex}\n  .mp h3 {margin:0 0 0 4ex}\n  .mp dt {margin:0;clear:left}\n  .mp dt.flush {float:left;width:8ex}\n  .mp dd {margin:0 0 0 9ex}\n  .mp h1,.mp h2,.mp h3,.mp h4 {clear:left}\n  .mp pre {margin-bottom:20px}\n  .mp pre+h2,.mp pre+h3 {margin-top:22px}\n  .mp h2+pre,.mp h3+pre {margin-top:5px}\n  .mp img {display:block;margin:auto}\n  .mp h1.man-title {display:none}\n  .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}\n  .mp h2 {font-size:16px;line-height:1.25}\n  .mp h1 {font-size:20px;line-height:2}\n  .mp {text-align:justify;background:#fff}\n  .mp,.mp code,.mp pre,.mp pre code,.mp tt,.mp kbd,.mp samp {color:#131211}\n  .mp h1,.mp h2,.mp h3,.mp h4 {color:#030201}\n  .mp u {text-decoration:underline}\n  .mp code,.mp strong,.mp b {font-weight:bold;color:#131211}\n  .mp em,.mp var {font-style:italic;color:#232221;text-decoration:none}\n  .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}\n  .mp b.man-ref {font-weight:normal;color:#434241}\n  .mp pre {padding:0 4ex}\n  .mp pre code {font-weight:normal;color:#434241}\n  .mp h2+pre,h3+pre {padding-left:0}\n  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}\n  ol.man-decor {width:100%}\n  ol.man-decor li.tl {text-align:left}\n  ol.man-decor li.tc {text-align:center;letter-spacing:4px}\n  ol.man-decor li.tr {text-align:right;float:right}\n  </style>\n</head>\n<!--\n  The following styles are deprecated and will be removed at some point:\n  div#man, div#man ol.man, div#man ol.head, div#man ol.man.\n\n  The .man-page, .man-decor, .man-head, .man-foot, .man-title, and\n  .man-navigation should be used instead.\n-->\n<body id='manpage'>\n  <div class='mp' id='man'>\n\n  <div class='man-navigation' style='display:none'>\n    <a href=\"#NAME\">NAME</a>\n    <a href=\"#SYNOPSIS\">SYNOPSIS</a>\n    <a href=\"#DESCRIPTION\">DESCRIPTION</a>\n    <a href=\"#FILES\">FILES</a>\n    <a href=\"#OPTIONS\">OPTIONS</a>\n    <a href=\"#COPYRIGHT\">COPYRIGHT</a>\n  </div>\n\n  <ol class='man-decor man-head man head'>\n    <li class='tl'>textql(1)</li>\n    <li class='tc'></li>\n    <li class='tr'>textql(1)</li>\n  </ol>\n\n  <h2 id=\"NAME\">NAME</h2>\n<p class=\"man-name\">\n  <code>textql</code> - <span class=\"man-whatis\">execute queries on structured text</span>\n</p>\n\n<h2 id=\"SYNOPSIS\">SYNOPSIS</h2>\n\n<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 />\n<code>textql</code> <var>-console</var> <var>path</var>...<br /></p>\n\n<h2 id=\"DESCRIPTION\">DESCRIPTION</h2>\n\n<p><strong>textql</strong> executes given statements in SQL on structured texts and returns the result.\nSQL statements accepted by <code>textql</code> are ANSI SQL compatible, and are executed against\nthe data in the order provided. No transformations are applied to the text files\nbut are instead applied to a temporary view of the data. Statements that insert data\nor modify the existing data will only have their effects visible in the output.</p>\n\n<p>The argument list of the end is expected to be a list of paths which may or may not\nbe specific files. Each path is traversed for files that are then loaded as part of\nthe database that <code>textql</code> creates internally, and files are loaded without traversal.\nPaths provided are not recursed.</p>\n\n<p>Each statement is then executed against <code>textql</code>'s internal database and the result, if\nany, is printed. <strong>INSERT</strong>, <strong>UPDATE</strong>, <strong>DELETE</strong> or other side effecting statements\ndo not effect the text files given as input, but instead modify the database\ninternal to <code>textql</code>. Their result may be viewed via the output, presisting the\ndatabase as is with <code>-save-to</code> or in a SQLite REPL with <code>--console</code></p>\n\n<p>With no arguements, <code>textql</code> will print a brief overview of it's usage.</p>\n\n<h2 id=\"FILES\">FILES</h2>\n\n<p>Structured text accepted by textql is any text file in a tabular format\nwhere each row of the table is on a single line, and each column is a section of the\nline delimited by a single character which is consistent throughout the file. A\ncommon structured text format is CSV (RFC4180).</p>\n\n<h2 id=\"OPTIONS\">OPTIONS</h2>\n\n<dl>\n<dt><code>-console</code></dt><dd>After all statements are run, open SQLite3 REPL with this data</dd>\n<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>\n<dt class=\"flush\"><code>-header</code></dt><dd>Treat input files as having the first row as a header row</dd>\n<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>\n<dt><code>-output-file file</code></dt><dd>Filename to write output to, if empty no output is written (default \"stdout\")</dd>\n<dt><code>-output-header</code></dt><dd>Display column names in output</dd>\n<dt class=\"flush\"><code>-quiet</code></dt><dd>Surpress logging</dd>\n<dt class=\"flush\"><code>-pretty</code></dt><dd>Pretty print output</dd>\n<dt><code>-save-to file</code></dt><dd>SQLite3 db is left on disk at this file</dd>\n<dt><code>-sql string</code></dt><dd>SQL Statement(s) to run on the data</dd>\n<dt><code>-version</code></dt><dd>Print version and exit</dd>\n</dl>\n\n\n<h2 id=\"COPYRIGHT\">COPYRIGHT</h2>\n\n<p>textql is Copyright (C) 2015, 2016 Paul Bergeron\n<a href=\"http://pauldbergeron.com/\" data-bare-link=\"true\">http://pauldbergeron.com/</a></p>\n\n\n  <ol class='man-decor man-foot man foot'>\n    <li class='tl'></li>\n    <li class='tc'>December 2015</li>\n    <li class='tr'>textql(1)</li>\n  </ol>\n\n  </div>\n</body>\n</html>\n"
  },
  {
    "path": "man/textql.1.ronn",
    "content": "textql(1) -- execute queries on structured text\n===============================================\n\n## SYNOPSIS\n\n`textql` [<-save-to path>] [<-output-file path>] [<-output-dlm delimter>] [<-output-header>] [<-header>] [<-dlm delimter>] [<-source path>] [<-sql sql_statements>] [<-quiet>] [<path>...]<br>\n`textql` <-console> <path>...<br>\n\n## DESCRIPTION\n\n**textql** executes given statements in SQL on structured texts and returns the result.\nSQL statements accepted by `textql` are ANSI SQL compatible, and are executed against\nthe data in the order provided. No transformations are applied to the text files\nbut are instead applied to a temporary view of the data. Statements that insert data\nor modify the existing data will only have their effects visible in the output.\n\nThe argument list of the end is expected to be a list of paths which may or may not\nbe specific files. Each path is traversed for files that are then loaded as part of\nthe database that `textql` creates internally, and files are loaded without traversal.\nPaths provided are not recursed.\n\nEach statement is then executed against `textql`'s internal database and the result, if\nany, is printed. **INSERT**, **UPDATE**, **DELETE** or other side effecting statements\ndo not effect the text files given as input, but instead modify the database\ninternal to `textql`. Their result may be viewed via the output, presisting the\ndatabase as is with `-save-to` or in a SQLite REPL with `--console`\n\nWith no arguements, `textql` will print a brief overview of it's usage.\n\n## FILES\n\nStructured text accepted by textql is any text file in a tabular format\nwhere each row of the table is on a single line, and each column is a section of the\nline delimited by a single character which is consistent throughout the file. A\ncommon structured text format is CSV (RFC4180).\n\n## OPTIONS\n\n  * `-console`:\n    After all statements are run, open SQLite3 REPL with this data\n  * `-dlm string`:\n    Input delimiter character between fields -dlm=tab for tab, -dlm=0x## to specify a character code in hex (default \",\")\n  * `-header`:\n    Treat input files as having the first row as a header row\n  * `-output-dlm string`:\n    Output delimiter character between fields -output-dlm=tab for tab, -dlm=0x## to specify a character code in hex (default \",\")\n  * `-output-file file`:\n    Filename to write output to, if empty no output is written (default \"stdout\")\n  * `-output-header`:\n    Display column names in output\n  * `-quiet`:\n    Surpress logging\n  * `-pretty`:\n    Pretty print output\n  * `-save-to file`:\n    SQLite3 db is left on disk at this file\n  * `-sql string`:\n    SQL Statement(s) to run on the data\n  * `-version`:\n    Print version and exit\n\n\n## COPYRIGHT\n\ntextql is Copyright (C) 2015, 2016 Paul Bergeron\n<http://pauldbergeron.com/>"
  },
  {
    "path": "outputs/csv.go",
    "content": "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 transforms sql.Rows into CSV formatted\n// string data using encoding/csv\ntype CSVOutput struct {\n\toptions         *CSVOutputOptions\n\twriter          *csv.Writer\n\tfirstRow        []string\n\theader          []string\n\tminOutputLength int\n}\n\n// CSVOutputOptions define options that are passed to encoding/csv for formatting\n// the output in specific ways.\ntype CSVOutputOptions struct {\n\t// WriteHeader determines if a header row based on the column names should be written.\n\tWriteHeader bool\n\t// Separator is the rune used to delimit fields.\n\tSeparator rune\n\t// WriteTo is where the formatted data will be written to.\n\tWriteTo io.Writer\n}\n\n// NewCSVOutput returns a new CSVOutput configured per the options provided.\nfunc NewCSVOutput(opts *CSVOutputOptions) *CSVOutput {\n\tcsvOutput := &CSVOutput{\n\t\toptions: opts,\n\t\twriter:  csv.NewWriter(opts.WriteTo),\n\t}\n\n\tcsvOutput.writer.Comma = csvOutput.options.Separator\n\n\treturn csvOutput\n}\n\n// Show writes the sql.Rows given to the destination in CSV format.\nfunc (csvOutput *CSVOutput) Show(rows *sql.Rows) {\n\tcols, colsErr := rows.Columns()\n\n\tif colsErr != nil {\n\t\tlog.Fatalln(colsErr)\n\t}\n\n\tif csvOutput.options.WriteHeader && len(cols) > 0 {\n\t\tif err := csvOutput.writer.Write(cols); err != nil {\n\t\t\tlog.Fatalln(err)\n\t\t}\n\t}\n\n\trawResult := make([][]byte, len(cols))\n\tresult := make([]string, len(cols))\n\n\tdest := make([]interface{}, len(cols))\n\n\tfor i := range cols {\n\t\tdest[i] = &rawResult[i]\n\t}\n\n\tfor rows.Next() {\n\t\trows.Scan(dest...)\n\n\t\tfor i, raw := range rawResult {\n\t\t\tresult[i] = string(raw)\n\t\t}\n\n\t\twriteErr := csvOutput.writer.Write(result)\n\n\t\tif writeErr != nil {\n\t\t\tlog.Fatalln(writeErr)\n\t\t}\n\t}\n\n\tcsvOutput.writer.Flush()\n\trows.Close()\n}\n"
  },
  {
    "path": "outputs/output.go",
    "content": "package outputs\n\nimport \"database/sql\"\n\n// Output implementors should accept sql.Rows and transform them\n// however they need to in order to represent them in their specific format.\ntype Output interface {\n\t// Show should display/write the sql.Rows to the implmentor's destination and format.\n\tShow(*sql.Rows)\n}\n"
  },
  {
    "path": "outputs/pretty_csv.go",
    "content": "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 represents a TextQL output that transforms sql.Rows into pretty tables\ntype PrettyCSVOutput struct {\n\toptions         *PrettyCSVOutputOptions\n\twriter          *tablewriter.Table\n\tfirstRow        []string\n\theader          []string\n\tminOutputLength int\n}\n\n// PrettyCSVOutputOptions define options that are passed to tablewriter for formatting\n// the output in specific ways.\ntype PrettyCSVOutputOptions struct {\n\t// WriteHeader determines if a header row based on the column names should be written.\n\tWriteHeader bool\n\t// WriteTo is where the formatted data will be written to.\n\tWriteTo io.Writer\n}\n\n// NewPrettyCSVOutput returns a new PrettyCSVOutput configured per the options provided.\nfunc NewPrettyCSVOutput(opts *PrettyCSVOutputOptions) *PrettyCSVOutput {\n\tprettyCsvOutput := &PrettyCSVOutput{\n\t\toptions: opts,\n\t\twriter:  tablewriter.NewWriter(opts.WriteTo),\n\t}\n\n\treturn prettyCsvOutput\n}\n\n// Show writes the sql.Rows given to the destination in tablewriter basic format.\nfunc (prettyCsvOutput *PrettyCSVOutput) Show(rows *sql.Rows) {\n\tcols, colsErr := rows.Columns()\n\n\tif colsErr != nil {\n\t\tlog.Fatalln(colsErr)\n\t}\n\n\tif prettyCsvOutput.options.WriteHeader {\n\t\tprettyCsvOutput.writer.SetHeader(cols)\n\t\tprettyCsvOutput.writer.SetHeaderLine(true)\n\t\tprettyCsvOutput.writer.SetAutoFormatHeaders(false)\n\t}\n\n\trawResult := make([][]byte, len(cols))\n\tresult := make([]string, len(cols))\n\n\tdest := make([]interface{}, len(cols))\n\n\tfor i := range cols {\n\t\tdest[i] = &rawResult[i]\n\t}\n\n\tfor rows.Next() {\n\t\trows.Scan(dest...)\n\n\t\tfor i, raw := range rawResult {\n\t\t\tresult[i] = string(raw)\n\t\t}\n\n\t\tprettyCsvOutput.writer.Append(result)\n\t}\n\n\tif len(cols) > 0 {\n\t\tprettyCsvOutput.writer.Render()\n\t}\n\trows.Close()\n}\n"
  },
  {
    "path": "snapcraft.yaml",
    "content": "name: textql\nversion: '1.0'\nsummary: Execute SQL against structured text like CSV or TSV \ndescription: |\n  Execute SQL against structured text like CSV or TSV.\ngrade: stable\nconfinement: strict\nbase: core18\nparts:\n  textql:\n    plugin: go\n    source: https://github.com/dinedal/textql.git\n    go-importpath: github.com/dinedal/textql\n    build-packages:\n      - build-essential\napps:\n  textql:\n    command: bin/textql\n    plugs:\n      - home\n"
  },
  {
    "path": "sqlparser/Makefile",
    "content": "\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",
    "content": "// Copyright 2012, Google Inc. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage sqlparser\n\n// analyzer.go contains utility analysis functions.\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/dinedal/textql/sqlparser/sqltypes\"\n)\n\n// GetTableName returns the table name from the SimpleTableExpr\n// only if it's a simple expression. Otherwise, it returns \"\".\nfunc GetTableName(node SimpleTableExpr) string {\n\tif n, ok := node.(*TableName); ok && n.Qualifier == nil {\n\t\treturn string(n.Name)\n\t}\n\t// sub-select or '.' expression\n\treturn \"\"\n}\n\n// GetColName returns the column name, only if\n// it's a simple expression. Otherwise, it returns \"\".\nfunc GetColName(node Expr) string {\n\tif n, ok := node.(*ColName); ok {\n\t\treturn string(n.Name)\n\t}\n\treturn \"\"\n}\n\n// IsColName returns true if the ValExpr is a *ColName.\nfunc IsColName(node ValExpr) bool {\n\t_, ok := node.(*ColName)\n\treturn ok\n}\n\n// IsValue returns true if the ValExpr is a string, number or value arg.\n// NULL is not considered to be a value.\nfunc IsValue(node ValExpr) bool {\n\tswitch node.(type) {\n\tcase StrVal, NumVal, ValArg:\n\t\treturn true\n\t}\n\treturn false\n}\n\n// HasINCaluse returns true if any of the conditions has an IN clause.\nfunc HasINClause(conditions []BoolExpr) bool {\n\tfor _, node := range conditions {\n\t\tif c, ok := node.(*ComparisonExpr); ok && c.Operator == AST_IN {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// IsSimpleTuple returns true if the ValExpr is a ValTuple that\n// contains simple values or if it's a list arg.\nfunc IsSimpleTuple(node ValExpr) bool {\n\tswitch vals := node.(type) {\n\tcase ValTuple:\n\t\tfor _, n := range vals {\n\t\t\tif !IsValue(n) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\treturn true\n\tcase ListArg:\n\t\treturn true\n\t}\n\t// It's a subquery\n\treturn false\n}\n\n// AsInterface converts the ValExpr to an interface. It converts\n// ValTuple to []interface{}, ValArg to string, StrVal to sqltypes.String,\n// NumVal to sqltypes.Numeric, NullVal to nil.\n// Otherwise, it returns an error.\nfunc AsInterface(node ValExpr) (interface{}, error) {\n\tswitch node := node.(type) {\n\tcase ValTuple:\n\t\tvals := make([]interface{}, 0, len(node))\n\t\tfor _, val := range node {\n\t\t\tv, err := AsInterface(val)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tvals = append(vals, v)\n\t\t}\n\t\treturn vals, nil\n\tcase ValArg:\n\t\treturn string(node), nil\n\tcase ListArg:\n\t\treturn string(node), nil\n\tcase StrVal:\n\t\treturn sqltypes.MakeString(node), nil\n\tcase NumVal:\n\t\tn, err := sqltypes.BuildNumeric(string(node))\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"type mismatch: %s\", err)\n\t\t}\n\t\treturn n, nil\n\tcase *NullVal:\n\t\treturn nil, nil\n\t}\n\treturn nil, fmt.Errorf(\"unexpected node %v\", node)\n}\n\n// StringIn is a convenience function that returns\n// true if str matches any of the values.\nfunc StringIn(str string, values ...string) bool {\n\tfor _, val := range values {\n\t\tif str == val {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n"
  },
  {
    "path": "sqlparser/ast.go",
    "content": "// Copyright 2012, Google Inc. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage sqlparser\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"strconv\"\n\n\t\"github.com/dinedal/textql/sqlparser/sqltypes\"\n)\n\n// Instructions for creating new types: If a type\n// needs to satisfy an interface, declare that function\n// along with that interface. This will help users\n// identify the list of types to which they can assert\n// those interfaces.\n// If the member of a type has a string with a predefined\n// list of values, declare those values as const following\n// the type.\n// For interfaces that define dummy functions to consolidate\n// a set of types, define the function as ITypeName.\n// This will help avoid name collisions.\n\n// Parse parses the sql and returns a Statement, which\n// is the AST representation of the query.\nfunc Parse(sql string) (Statement, error) {\n\ttokenizer := NewStringTokenizer(sql)\n\tif yyParse(tokenizer) != 0 {\n\t\treturn nil, errors.New(tokenizer.LastError)\n\t}\n\treturn tokenizer.ParseTree, nil\n}\n\n// SQLNode defines the interface for all nodes\n// generated by the parser.\ntype SQLNode interface {\n\tFormat(buf *TrackedBuffer)\n}\n\n// String returns a string representation of an SQLNode.\nfunc String(node SQLNode) string {\n\tbuf := NewTrackedBuffer(nil)\n\tbuf.Myprintf(\"%v\", node)\n\treturn buf.String()\n}\n\n// Statement represents a statement.\ntype Statement interface {\n\tIStatement()\n\tSQLNode\n}\n\nfunc (*Union) IStatement()  {}\nfunc (*Select) IStatement() {}\nfunc (*Insert) IStatement() {}\nfunc (*Update) IStatement() {}\nfunc (*Delete) IStatement() {}\nfunc (*Set) IStatement()    {}\nfunc (*DDL) IStatement()    {}\nfunc (*Other) IStatement()  {}\n\n// SelectStatement any SELECT statement.\ntype SelectStatement interface {\n\tISelectStatement()\n\tIStatement()\n\tIInsertRows()\n\tSQLNode\n}\n\nfunc (*Select) ISelectStatement() {}\nfunc (*Union) ISelectStatement()  {}\n\n// Select represents a SELECT statement.\ntype Select struct {\n\tComments    Comments\n\tDistinct    string\n\tSelectExprs SelectExprs\n\tFrom        *From\n\tWhere       *Where\n\tGroupBy     GroupBy\n\tHaving      *Where\n\tOrderBy     OrderBy\n\tLimit       *Limit\n\tLock        string\n}\n\n// Select.Distinct\nconst (\n\tAST_DISTINCT = \"distinct \"\n)\n\n// Select.Lock\nconst (\n\tAST_FOR_UPDATE = \" for update\"\n\tAST_SHARE_MODE = \" lock in share mode\"\n)\n\nfunc (node *Select) Format(buf *TrackedBuffer) {\n\tbuf.Myprintf(\"select %v%s%v from %v%v%v%v%v%v%s\",\n\t\tnode.Comments, node.Distinct, node.SelectExprs,\n\t\tnode.From, node.Where,\n\t\tnode.GroupBy, node.Having, node.OrderBy,\n\t\tnode.Limit, node.Lock)\n}\n\n// Union represents a UNION statement.\ntype Union struct {\n\tType        string\n\tLeft, Right SelectStatement\n}\n\n// Union.Type\nconst (\n\tAST_UNION     = \"union\"\n\tAST_UNION_ALL = \"union all\"\n\tAST_SET_MINUS = \"minus\"\n\tAST_EXCEPT    = \"except\"\n\tAST_INTERSECT = \"intersect\"\n)\n\nfunc (node *Union) Format(buf *TrackedBuffer) {\n\tbuf.Myprintf(\"%v %s %v\", node.Left, node.Type, node.Right)\n}\n\n// Insert represents an INSERT statement.\ntype Insert struct {\n\tComments Comments\n\tTable    *TableName\n\tColumns  Columns\n\tRows     InsertRows\n\tOnDup    OnDup\n}\n\nfunc (node *Insert) Format(buf *TrackedBuffer) {\n\tbuf.Myprintf(\"insert %vinto %v%v %v%v\",\n\t\tnode.Comments,\n\t\tnode.Table, node.Columns, node.Rows, node.OnDup)\n}\n\n// InsertRows represents the rows for an INSERT statement.\ntype InsertRows interface {\n\tIInsertRows()\n\tSQLNode\n}\n\nfunc (*Select) IInsertRows() {}\nfunc (*Union) IInsertRows()  {}\nfunc (Values) IInsertRows()  {}\n\n// Update represents an UPDATE statement.\ntype Update struct {\n\tComments Comments\n\tTable    *TableName\n\tExprs    UpdateExprs\n\tWhere    *Where\n\tOrderBy  OrderBy\n\tLimit    *Limit\n}\n\nfunc (node *Update) Format(buf *TrackedBuffer) {\n\tbuf.Myprintf(\"update %v%v set %v%v%v%v\",\n\t\tnode.Comments, node.Table,\n\t\tnode.Exprs, node.Where, node.OrderBy, node.Limit)\n}\n\n// Delete represents a DELETE statement.\ntype Delete struct {\n\tComments Comments\n\tTable    *TableName\n\tWhere    *Where\n\tOrderBy  OrderBy\n\tLimit    *Limit\n}\n\nfunc (node *Delete) Format(buf *TrackedBuffer) {\n\tbuf.Myprintf(\"delete %vfrom %v%v%v%v\",\n\t\tnode.Comments,\n\t\tnode.Table, node.Where, node.OrderBy, node.Limit)\n}\n\n// Set represents a SET statement.\ntype Set struct {\n\tComments Comments\n\tExprs    UpdateExprs\n}\n\nfunc (node *Set) Format(buf *TrackedBuffer) {\n\tbuf.Myprintf(\"set %v%v\", node.Comments, node.Exprs)\n}\n\n// DDL represents a CREATE, ALTER, DROP or RENAME statement.\n// Table is set for AST_ALTER, AST_DROP, AST_RENAME.\n// NewName is set for AST_ALTER, AST_CREATE, AST_RENAME.\ntype DDL struct {\n\tAction  string\n\tTable   []byte\n\tNewName []byte\n}\n\nconst (\n\tAST_CREATE = \"create\"\n\tAST_ALTER  = \"alter\"\n\tAST_DROP   = \"drop\"\n\tAST_RENAME = \"rename\"\n)\n\nfunc (node *DDL) Format(buf *TrackedBuffer) {\n\tswitch node.Action {\n\tcase AST_CREATE:\n\t\tbuf.Myprintf(\"%s table %s\", node.Action, node.NewName)\n\tcase AST_RENAME:\n\t\tbuf.Myprintf(\"%s table %s %s\", node.Action, node.Table, node.NewName)\n\tdefault:\n\t\tbuf.Myprintf(\"%s table %s\", node.Action, node.Table)\n\t}\n}\n\n// Other represents a SHOW, DESCRIBE, or EXPLAIN statement.\n// It should be used only as an indicator. It does not contain\n// the full AST for the statement.\ntype Other struct{}\n\nfunc (node *Other) Format(buf *TrackedBuffer) {\n\tbuf.WriteString(\"other\")\n}\n\n// Comments represents a list of comments.\ntype Comments [][]byte\n\nfunc (node Comments) Format(buf *TrackedBuffer) {\n\tfor _, c := range node {\n\t\tbuf.Myprintf(\"%s \", c)\n\t}\n}\n\n// SelectExprs represents SELECT expressions.\ntype SelectExprs []SelectExpr\n\nfunc (node SelectExprs) Format(buf *TrackedBuffer) {\n\tvar prefix string\n\tfor _, n := range node {\n\t\tbuf.Myprintf(\"%s%v\", prefix, n)\n\t\tprefix = \", \"\n\t}\n}\n\n// SelectExpr represents a SELECT expression.\ntype SelectExpr interface {\n\tISelectExpr()\n\tSQLNode\n}\n\nfunc (*StarExpr) ISelectExpr()    {}\nfunc (*NonStarExpr) ISelectExpr() {}\n\n// StarExpr defines a '*' or 'table.*' expression.\ntype StarExpr struct {\n\tTableName []byte\n}\n\nfunc (node *StarExpr) Format(buf *TrackedBuffer) {\n\tif node.TableName != nil {\n\t\tbuf.Myprintf(\"%s.\", node.TableName)\n\t}\n\tbuf.Myprintf(\"*\")\n}\n\n// NonStarExpr defines a non-'*' select expr.\ntype NonStarExpr struct {\n\tExpr Expr\n\tAs   []byte\n}\n\nfunc (node *NonStarExpr) Format(buf *TrackedBuffer) {\n\tbuf.Myprintf(\"%v\", node.Expr)\n\tif node.As != nil {\n\t\tbuf.Myprintf(\" as %s\", node.As)\n\t}\n}\n\n// Columns represents an insert column list.\n// The syntax for Columns is a subset of SelectExprs.\n// So, it's castable to a SelectExprs and can be analyzed\n// as such.\ntype Columns []SelectExpr\n\nfunc (node Columns) Format(buf *TrackedBuffer) {\n\tif node == nil {\n\t\treturn\n\t}\n\tbuf.Myprintf(\"(%v)\", SelectExprs(node))\n}\n\n// TableExprs represents a list of table expressions.\ntype TableExprs []TableExpr\n\nfunc (node TableExprs) Format(buf *TrackedBuffer) {\n\tvar prefix string\n\tfor _, n := range node {\n\t\tbuf.Myprintf(\"%s%v\", prefix, n)\n\t\tprefix = \", \"\n\t}\n}\n\n// TableExpr represents a table expression.\ntype TableExpr interface {\n\tITableExpr()\n\tSQLNode\n}\n\nfunc (*AliasedTableExpr) ITableExpr() {}\nfunc (*ParenTableExpr) ITableExpr()   {}\nfunc (*JoinTableExpr) ITableExpr()    {}\n\n// AliasedTableExpr represents a table expression\n// coupled with an optional alias or index hint.\ntype AliasedTableExpr struct {\n\tExpr  SimpleTableExpr\n\tAs    []byte\n\tHints *IndexHints\n}\n\nfunc (node *AliasedTableExpr) Format(buf *TrackedBuffer) {\n\tbuf.Myprintf(\"%v\", node.Expr)\n\tif node.As != nil {\n\t\tbuf.Myprintf(\" as %s\", node.As)\n\t}\n\tif node.Hints != nil {\n\t\t// Hint node provides the space padding.\n\t\tbuf.Myprintf(\"%v\", node.Hints)\n\t}\n}\n\n// SimpleTableExpr represents a simple table expression.\ntype SimpleTableExpr interface {\n\tISimpleTableExpr()\n\tSQLNode\n}\n\nfunc (*TableName) ISimpleTableExpr() {}\nfunc (*Subquery) ISimpleTableExpr()  {}\n\n// TableName represents a table  name.\ntype TableName struct {\n\tName, Qualifier []byte\n}\n\nfunc (node *TableName) Format(buf *TrackedBuffer) {\n\tif node.Qualifier != nil {\n\t\tescape(buf, node.Qualifier)\n\t\tbuf.Myprintf(\".\")\n\t}\n\tescape(buf, node.Name)\n}\n\n// ParenTableExpr represents a parenthesized TableExpr.\ntype ParenTableExpr struct {\n\tExpr TableExpr\n}\n\nfunc (node *ParenTableExpr) Format(buf *TrackedBuffer) {\n\tbuf.Myprintf(\"(%v)\", node.Expr)\n}\n\n// JoinTableExpr represents a TableExpr that's a JOIN operation.\ntype JoinTableExpr struct {\n\tLeftExpr  TableExpr\n\tJoin      string\n\tRightExpr TableExpr\n\tOn        BoolExpr\n}\n\n// JoinTableExpr.Join\nconst (\n\tAST_JOIN          = \"join\"\n\tAST_STRAIGHT_JOIN = \"straight_join\"\n\tAST_LEFT_JOIN     = \"left join\"\n\tAST_RIGHT_JOIN    = \"right join\"\n\tAST_CROSS_JOIN    = \"cross join\"\n\tAST_NATURAL_JOIN  = \"natural join\"\n)\n\nfunc (node *JoinTableExpr) Format(buf *TrackedBuffer) {\n\tbuf.Myprintf(\"%v %s %v\", node.LeftExpr, node.Join, node.RightExpr)\n\tif node.On != nil {\n\t\tbuf.Myprintf(\" on %v\", node.On)\n\t}\n}\n\n// IndexHints represents a list of index hints.\ntype IndexHints struct {\n\tType    string\n\tIndexes [][]byte\n}\n\nconst (\n\tAST_USE    = \"use\"\n\tAST_IGNORE = \"ignore\"\n\tAST_FORCE  = \"force\"\n)\n\nfunc (node *IndexHints) Format(buf *TrackedBuffer) {\n\tbuf.Myprintf(\" %s index \", node.Type)\n\tprefix := \"(\"\n\tfor _, n := range node.Indexes {\n\t\tbuf.Myprintf(\"%s%s\", prefix, n)\n\t\tprefix = \", \"\n\t}\n\tbuf.Myprintf(\")\")\n}\n\n// Where represents a WHERE or HAVING clause.\ntype Where struct {\n\tType string\n\tExpr BoolExpr\n}\n\n// Where.Type\nconst (\n\tAST_WHERE  = \"where\"\n\tAST_HAVING = \"having\"\n)\n\n// NewWhere creates a WHERE or HAVING clause out\n// of a BoolExpr. If the expression is nil, it returns nil.\nfunc NewWhere(typ string, expr BoolExpr) *Where {\n\tif expr == nil {\n\t\treturn nil\n\t}\n\treturn &Where{Type: typ, Expr: expr}\n}\n\nfunc (node *Where) Format(buf *TrackedBuffer) {\n\tif node == nil || node.Expr == nil {\n\t\treturn\n\t}\n\tbuf.Myprintf(\" %s %v\", node.Type, node.Expr)\n}\n\n// From represents a FROM clause\ntype From struct {\n\tType string\n\tExpr TableExprs\n}\n\n// From.Type\nconst (\n\tAST_FROM = \"from\"\n)\n\n// NewFrom creates a FROM clause\n// of a table list expression. If the expression is nil, it returns nil.\nfunc NewFrom(typ string, expr TableExprs) *From {\n\tif expr == nil {\n\t\treturn nil\n\t}\n\treturn &From{Type: typ, Expr: expr}\n}\n\nfunc (node *From) Format(buf *TrackedBuffer) {\n\tif node == nil || node.Expr == nil {\n\t\treturn\n\t}\n\tbuf.Myprintf(\"%v\", node.Expr)\n}\n\n// Expr represents an expression.\ntype Expr interface {\n\tIExpr()\n\tSQLNode\n}\n\nfunc (*AndExpr) IExpr()        {}\nfunc (*OrExpr) IExpr()         {}\nfunc (*NotExpr) IExpr()        {}\nfunc (*ParenBoolExpr) IExpr()  {}\nfunc (*ComparisonExpr) IExpr() {}\nfunc (*RangeCond) IExpr()      {}\nfunc (*NullCheck) IExpr()      {}\nfunc (*ExistsExpr) IExpr()     {}\nfunc (*KeyrangeExpr) IExpr()   {}\nfunc (StrVal) IExpr()          {}\nfunc (NumVal) IExpr()          {}\nfunc (ValArg) IExpr()          {}\nfunc (*NullVal) IExpr()        {}\nfunc (*ColName) IExpr()        {}\nfunc (ValTuple) IExpr()        {}\nfunc (*Subquery) IExpr()       {}\nfunc (ListArg) IExpr()         {}\nfunc (*BinaryExpr) IExpr()     {}\nfunc (*UnaryExpr) IExpr()      {}\nfunc (*FuncExpr) IExpr()       {}\nfunc (*CaseExpr) IExpr()       {}\n\n// BoolExpr represents a boolean expression.\ntype BoolExpr interface {\n\tIBoolExpr()\n\tExpr\n}\n\nfunc (*AndExpr) IBoolExpr()        {}\nfunc (*OrExpr) IBoolExpr()         {}\nfunc (*NotExpr) IBoolExpr()        {}\nfunc (*ParenBoolExpr) IBoolExpr()  {}\nfunc (*ComparisonExpr) IBoolExpr() {}\nfunc (*RangeCond) IBoolExpr()      {}\nfunc (*NullCheck) IBoolExpr()      {}\nfunc (*ExistsExpr) IBoolExpr()     {}\nfunc (*KeyrangeExpr) IBoolExpr()   {}\n\n// AndExpr represents an AND expression.\ntype AndExpr struct {\n\tLeft, Right BoolExpr\n}\n\nfunc (node *AndExpr) Format(buf *TrackedBuffer) {\n\tbuf.Myprintf(\"%v and %v\", node.Left, node.Right)\n}\n\n// OrExpr represents an OR expression.\ntype OrExpr struct {\n\tLeft, Right BoolExpr\n}\n\nfunc (node *OrExpr) Format(buf *TrackedBuffer) {\n\tbuf.Myprintf(\"%v or %v\", node.Left, node.Right)\n}\n\n// NotExpr represents a NOT expression.\ntype NotExpr struct {\n\tExpr BoolExpr\n}\n\nfunc (node *NotExpr) Format(buf *TrackedBuffer) {\n\tbuf.Myprintf(\"not %v\", node.Expr)\n}\n\n// ParenBoolExpr represents a parenthesized boolean expression.\ntype ParenBoolExpr struct {\n\tExpr BoolExpr\n}\n\nfunc (node *ParenBoolExpr) Format(buf *TrackedBuffer) {\n\tbuf.Myprintf(\"(%v)\", node.Expr)\n}\n\n// ComparisonExpr represents a two-value comparison expression.\ntype ComparisonExpr struct {\n\tOperator    string\n\tLeft, Right ValExpr\n}\n\n// ComparisonExpr.Operator\nconst (\n\tAST_EQ       = \"=\"\n\tAST_LT       = \"<\"\n\tAST_GT       = \">\"\n\tAST_LE       = \"<=\"\n\tAST_GE       = \">=\"\n\tAST_NE       = \"!=\"\n\tAST_NSE      = \"<=>\"\n\tAST_IN       = \"in\"\n\tAST_NOT_IN   = \"not in\"\n\tAST_LIKE     = \"like\"\n\tAST_NOT_LIKE = \"not like\"\n)\n\nfunc (node *ComparisonExpr) Format(buf *TrackedBuffer) {\n\tbuf.Myprintf(\"%v %s %v\", node.Left, node.Operator, node.Right)\n}\n\n// RangeCond represents a BETWEEN or a NOT BETWEEN expression.\ntype RangeCond struct {\n\tOperator string\n\tLeft     ValExpr\n\tFrom, To ValExpr\n}\n\n// RangeCond.Operator\nconst (\n\tAST_BETWEEN     = \"between\"\n\tAST_NOT_BETWEEN = \"not between\"\n)\n\nfunc (node *RangeCond) Format(buf *TrackedBuffer) {\n\tbuf.Myprintf(\"%v %s %v and %v\", node.Left, node.Operator, node.From, node.To)\n}\n\n// NullCheck represents an IS NULL or an IS NOT NULL expression.\ntype NullCheck struct {\n\tOperator string\n\tExpr     ValExpr\n}\n\n// NullCheck.Operator\nconst (\n\tAST_IS_NULL     = \"is null\"\n\tAST_IS_NOT_NULL = \"is not null\"\n)\n\nfunc (node *NullCheck) Format(buf *TrackedBuffer) {\n\tbuf.Myprintf(\"%v %s\", node.Expr, node.Operator)\n}\n\n// ExistsExpr represents an EXISTS expression.\ntype ExistsExpr struct {\n\tSubquery *Subquery\n}\n\nfunc (node *ExistsExpr) Format(buf *TrackedBuffer) {\n\tbuf.Myprintf(\"exists %v\", node.Subquery)\n}\n\n// KeyrangeExpr represents a KEYRANGE expression.\ntype KeyrangeExpr struct {\n\tStart, End ValExpr\n}\n\nfunc (node *KeyrangeExpr) Format(buf *TrackedBuffer) {\n\tbuf.Myprintf(\"keyrange(%v, %v)\", node.Start, node.End)\n}\n\n// ValExpr represents a value expression.\ntype ValExpr interface {\n\tIValExpr()\n\tExpr\n}\n\nfunc (StrVal) IValExpr()      {}\nfunc (NumVal) IValExpr()      {}\nfunc (ValArg) IValExpr()      {}\nfunc (*NullVal) IValExpr()    {}\nfunc (*ColName) IValExpr()    {}\nfunc (ValTuple) IValExpr()    {}\nfunc (*Subquery) IValExpr()   {}\nfunc (ListArg) IValExpr()     {}\nfunc (*BinaryExpr) IValExpr() {}\nfunc (*UnaryExpr) IValExpr()  {}\nfunc (*FuncExpr) IValExpr()   {}\nfunc (*CaseExpr) IValExpr()   {}\n\n// StrVal represents a string value.\ntype StrVal []byte\n\nfunc (node StrVal) Format(buf *TrackedBuffer) {\n\ts := sqltypes.MakeString([]byte(node))\n\ts.EncodeSql(buf)\n}\n\n// NumVal represents a number.\ntype NumVal []byte\n\nfunc (node NumVal) Format(buf *TrackedBuffer) {\n\tbuf.Myprintf(\"%s\", []byte(node))\n}\n\n// ValArg represents a named bind var argument.\ntype ValArg []byte\n\nfunc (node ValArg) Format(buf *TrackedBuffer) {\n\tbuf.WriteArg(string(node))\n}\n\n// NullVal represents a NULL value.\ntype NullVal struct{}\n\nfunc (node *NullVal) Format(buf *TrackedBuffer) {\n\tbuf.Myprintf(\"null\")\n}\n\n// ColName represents a column name.\ntype ColName struct {\n\tName, Qualifier []byte\n}\n\nfunc (node *ColName) Format(buf *TrackedBuffer) {\n\tif node.Qualifier != nil {\n\t\tescape(buf, node.Qualifier)\n\t\tbuf.Myprintf(\".\")\n\t}\n\tescape(buf, node.Name)\n}\n\nfunc escape(buf *TrackedBuffer, name []byte) {\n\tif _, ok := keywords[string(name)]; ok {\n\t\tbuf.Myprintf(\"`%s`\", name)\n\t} else {\n\t\tbuf.Myprintf(\"%s\", name)\n\t}\n}\n\n// ColTuple represents a list of column values.\n// It can be ValTuple, Subquery, ListArg.\ntype ColTuple interface {\n\tIColTuple()\n\tValExpr\n}\n\nfunc (ValTuple) IColTuple()  {}\nfunc (*Subquery) IColTuple() {}\nfunc (ListArg) IColTuple()   {}\n\n// ValTuple represents a tuple of actual values.\ntype ValTuple ValExprs\n\nfunc (node ValTuple) Format(buf *TrackedBuffer) {\n\tbuf.Myprintf(\"(%v)\", ValExprs(node))\n}\n\n// ValExprs represents a list of value expressions.\n// It's not a valid expression because it's not parenthesized.\ntype ValExprs []ValExpr\n\nfunc (node ValExprs) Format(buf *TrackedBuffer) {\n\tvar prefix string\n\tfor _, n := range node {\n\t\tbuf.Myprintf(\"%s%v\", prefix, n)\n\t\tprefix = \", \"\n\t}\n}\n\n// Subquery represents a subquery.\ntype Subquery struct {\n\tSelect SelectStatement\n}\n\nfunc (node *Subquery) Format(buf *TrackedBuffer) {\n\tbuf.Myprintf(\"(%v)\", node.Select)\n}\n\n// ListArg represents a named list argument.\ntype ListArg []byte\n\nfunc (node ListArg) Format(buf *TrackedBuffer) {\n\tbuf.WriteArg(string(node))\n}\n\n// BinaryExpr represents a binary value expression.\ntype BinaryExpr struct {\n\tOperator    byte\n\tLeft, Right Expr\n}\n\n// BinaryExpr.Operator\nconst (\n\tAST_BITAND = '&'\n\tAST_BITOR  = '|'\n\tAST_BITXOR = '^'\n\tAST_PLUS   = '+'\n\tAST_MINUS  = '-'\n\tAST_MULT   = '*'\n\tAST_DIV    = '/'\n\tAST_MOD    = '%'\n)\n\nfunc (node *BinaryExpr) Format(buf *TrackedBuffer) {\n\tbuf.Myprintf(\"%v%c%v\", node.Left, node.Operator, node.Right)\n}\n\n// UnaryExpr represents a unary value expression.\ntype UnaryExpr struct {\n\tOperator byte\n\tExpr     Expr\n}\n\n// UnaryExpr.Operator\nconst (\n\tAST_UPLUS  = '+'\n\tAST_UMINUS = '-'\n\tAST_TILDA  = '~'\n)\n\nfunc (node *UnaryExpr) Format(buf *TrackedBuffer) {\n\tbuf.Myprintf(\"%c%v\", node.Operator, node.Expr)\n}\n\n// FuncExpr represents a function call.\ntype FuncExpr struct {\n\tName     []byte\n\tDistinct bool\n\tExprs    SelectExprs\n}\n\nfunc (node *FuncExpr) Format(buf *TrackedBuffer) {\n\tvar distinct string\n\tif node.Distinct {\n\t\tdistinct = \"distinct \"\n\t}\n\tbuf.Myprintf(\"%s(%s%v)\", node.Name, distinct, node.Exprs)\n}\n\n// Aggregates is a map of all aggregate functions.\nvar Aggregates = map[string]bool{\n\t\"avg\":          true,\n\t\"bit_and\":      true,\n\t\"bit_or\":       true,\n\t\"bit_xor\":      true,\n\t\"count\":        true,\n\t\"group_concat\": true,\n\t\"max\":          true,\n\t\"min\":          true,\n\t\"std\":          true,\n\t\"stddev_pop\":   true,\n\t\"stddev_samp\":  true,\n\t\"stddev\":       true,\n\t\"sum\":          true,\n\t\"var_pop\":      true,\n\t\"var_samp\":     true,\n\t\"variance\":     true,\n}\n\nfunc (node *FuncExpr) IsAggregate() bool {\n\treturn Aggregates[string(node.Name)]\n}\n\n// CaseExpr represents a CASE expression.\ntype CaseExpr struct {\n\tExpr  ValExpr\n\tWhens []*When\n\tElse  ValExpr\n}\n\nfunc (node *CaseExpr) Format(buf *TrackedBuffer) {\n\tbuf.Myprintf(\"case \")\n\tif node.Expr != nil {\n\t\tbuf.Myprintf(\"%v \", node.Expr)\n\t}\n\tfor _, when := range node.Whens {\n\t\tbuf.Myprintf(\"%v \", when)\n\t}\n\tif node.Else != nil {\n\t\tbuf.Myprintf(\"else %v \", node.Else)\n\t}\n\tbuf.Myprintf(\"end\")\n}\n\n// When represents a WHEN sub-expression.\ntype When struct {\n\tCond BoolExpr\n\tVal  ValExpr\n}\n\nfunc (node *When) Format(buf *TrackedBuffer) {\n\tbuf.Myprintf(\"when %v then %v\", node.Cond, node.Val)\n}\n\n// GroupBy represents a GROUP BY clause.\ntype GroupBy []ValExpr\n\nfunc (node GroupBy) Format(buf *TrackedBuffer) {\n\tprefix := \" group by \"\n\tfor _, n := range node {\n\t\tbuf.Myprintf(\"%s%v\", prefix, n)\n\t\tprefix = \", \"\n\t}\n}\n\n// OrderBy represents an ORDER By clause.\ntype OrderBy []*Order\n\nfunc (node OrderBy) Format(buf *TrackedBuffer) {\n\tprefix := \" order by \"\n\tfor _, n := range node {\n\t\tbuf.Myprintf(\"%s%v\", prefix, n)\n\t\tprefix = \", \"\n\t}\n}\n\n// Order represents an ordering expression.\ntype Order struct {\n\tExpr      ValExpr\n\tDirection string\n}\n\n// Order.Direction\nconst (\n\tAST_ASC  = \"asc\"\n\tAST_DESC = \"desc\"\n)\n\nfunc (node *Order) Format(buf *TrackedBuffer) {\n\tbuf.Myprintf(\"%v %s\", node.Expr, node.Direction)\n}\n\n// Limit represents a LIMIT clause.\ntype Limit struct {\n\tOffset, Rowcount ValExpr\n}\n\nfunc (node *Limit) Format(buf *TrackedBuffer) {\n\tif node == nil {\n\t\treturn\n\t}\n\tbuf.Myprintf(\" limit \")\n\tif node.Offset != nil {\n\t\tbuf.Myprintf(\"%v, \", node.Offset)\n\t}\n\tbuf.Myprintf(\"%v\", node.Rowcount)\n}\n\n// Limits returns the values of the LIMIT clause as interfaces.\n// The returned values can be nil for absent field, string for\n// bind variable names, or int64 for an actual number.\n// Otherwise, it's an error.\nfunc (node *Limit) Limits() (offset, rowcount interface{}, err error) {\n\tif node == nil {\n\t\treturn nil, nil, nil\n\t}\n\tswitch v := node.Offset.(type) {\n\tcase NumVal:\n\t\to, err := strconv.ParseInt(string(v), 0, 64)\n\t\tif err != nil {\n\t\t\treturn nil, nil, err\n\t\t}\n\t\tif o < 0 {\n\t\t\treturn nil, nil, fmt.Errorf(\"negative offset: %d\", o)\n\t\t}\n\t\toffset = o\n\tcase ValArg:\n\t\toffset = string(v)\n\tcase nil:\n\t\t// pass\n\tdefault:\n\t\treturn nil, nil, fmt.Errorf(\"unexpected node for offset: %+v\", v)\n\t}\n\tswitch v := node.Rowcount.(type) {\n\tcase NumVal:\n\t\trc, err := strconv.ParseInt(string(v), 0, 64)\n\t\tif err != nil {\n\t\t\treturn nil, nil, err\n\t\t}\n\t\tif rc < 0 {\n\t\t\treturn nil, nil, fmt.Errorf(\"negative limit: %d\", rc)\n\t\t}\n\t\trowcount = rc\n\tcase ValArg:\n\t\trowcount = string(v)\n\tdefault:\n\t\treturn nil, nil, fmt.Errorf(\"unexpected node for rowcount: %+v\", v)\n\t}\n\treturn offset, rowcount, nil\n}\n\n// Values represents a VALUES clause.\ntype Values []RowTuple\n\nfunc (node Values) Format(buf *TrackedBuffer) {\n\tprefix := \"values \"\n\tfor _, n := range node {\n\t\tbuf.Myprintf(\"%s%v\", prefix, n)\n\t\tprefix = \", \"\n\t}\n}\n\n// RowTuple represents a row of values. It can be ValTuple, Subquery.\ntype RowTuple interface {\n\tIRowTuple()\n\tValExpr\n}\n\nfunc (ValTuple) IRowTuple()  {}\nfunc (*Subquery) IRowTuple() {}\n\n// UpdateExprs represents a list of update expressions.\ntype UpdateExprs []*UpdateExpr\n\nfunc (node UpdateExprs) Format(buf *TrackedBuffer) {\n\tvar prefix string\n\tfor _, n := range node {\n\t\tbuf.Myprintf(\"%s%v\", prefix, n)\n\t\tprefix = \", \"\n\t}\n}\n\n// UpdateExpr represents an update expression.\ntype UpdateExpr struct {\n\tName *ColName\n\tExpr ValExpr\n}\n\nfunc (node *UpdateExpr) Format(buf *TrackedBuffer) {\n\tbuf.Myprintf(\"%v = %v\", node.Name, node.Expr)\n}\n\n// OnDup represents an ON DUPLICATE KEY clause.\ntype OnDup UpdateExprs\n\nfunc (node OnDup) Format(buf *TrackedBuffer) {\n\tif node == nil {\n\t\treturn\n\t}\n\tbuf.Myprintf(\" on duplicate key update %v\", UpdateExprs(node))\n}\n"
  },
  {
    "path": "sqlparser/fuzz.go",
    "content": "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}\n"
  },
  {
    "path": "sqlparser/parsed_query.go",
    "content": "// Copyright 2012, Google Inc. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage sqlparser\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\n\t\"github.com/dinedal/textql/sqlparser/sqltypes\"\n)\n\ntype bindLocation struct {\n\toffset, length int\n}\n\ntype ParsedQuery struct {\n\tQuery         string\n\tbindLocations []bindLocation\n}\n\ntype EncoderFunc func(value interface{}) ([]byte, error)\n\nfunc (pq *ParsedQuery) GenerateQuery(bindVariables map[string]interface{}) ([]byte, error) {\n\tif len(pq.bindLocations) == 0 {\n\t\treturn []byte(pq.Query), nil\n\t}\n\tbuf := bytes.NewBuffer(make([]byte, 0, len(pq.Query)))\n\tcurrent := 0\n\tfor _, loc := range pq.bindLocations {\n\t\tbuf.WriteString(pq.Query[current:loc.offset])\n\t\tname := pq.Query[loc.offset : loc.offset+loc.length]\n\t\tsupplied, _, err := FetchBindVar(name, bindVariables)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif err := EncodeValue(buf, supplied); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tcurrent = loc.offset + loc.length\n\t}\n\tbuf.WriteString(pq.Query[current:])\n\treturn buf.Bytes(), nil\n}\n\nfunc (pq *ParsedQuery) MarshalJSON() ([]byte, error) {\n\treturn json.Marshal(pq.Query)\n}\n\nfunc EncodeValue(buf *bytes.Buffer, value interface{}) error {\n\tswitch bindVal := value.(type) {\n\tcase nil:\n\t\tbuf.WriteString(\"null\")\n\tcase []sqltypes.Value:\n\t\tfor i := 0; i < len(bindVal); i++ {\n\t\t\tif i != 0 {\n\t\t\t\tbuf.WriteString(\", \")\n\t\t\t}\n\t\t\tif err := EncodeValue(buf, bindVal[i]); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\tcase [][]sqltypes.Value:\n\t\tfor i := 0; i < len(bindVal); i++ {\n\t\t\tif i != 0 {\n\t\t\t\tbuf.WriteString(\", \")\n\t\t\t}\n\t\t\tbuf.WriteByte('(')\n\t\t\tif err := EncodeValue(buf, bindVal[i]); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tbuf.WriteByte(')')\n\t\t}\n\tcase []interface{}:\n\t\tbuf.WriteByte('(')\n\t\tfor i, v := range bindVal {\n\t\t\tif i != 0 {\n\t\t\t\tbuf.WriteString(\", \")\n\t\t\t}\n\t\t\tif err := EncodeValue(buf, v); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t\tbuf.WriteByte(')')\n\tcase TupleEqualityList:\n\t\tif err := bindVal.Encode(buf); err != nil {\n\t\t\treturn err\n\t\t}\n\tdefault:\n\t\tv, err := sqltypes.BuildValue(bindVal)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tv.EncodeSql(buf)\n\t}\n\treturn nil\n}\n\ntype TupleEqualityList struct {\n\tColumns []string\n\tRows    [][]sqltypes.Value\n}\n\nfunc (tpl *TupleEqualityList) Encode(buf *bytes.Buffer) error {\n\tif len(tpl.Rows) == 0 {\n\t\treturn errors.New(\"cannot encode with 0 rows\")\n\t}\n\tif len(tpl.Columns) == 1 {\n\t\treturn tpl.encodeAsIN(buf)\n\t}\n\treturn tpl.encodeAsEquality(buf)\n}\n\nfunc (tpl *TupleEqualityList) encodeAsIN(buf *bytes.Buffer) error {\n\tbuf.WriteString(tpl.Columns[0])\n\tbuf.WriteString(\" in (\")\n\tfor i, r := range tpl.Rows {\n\t\tif len(r) != 1 {\n\t\t\treturn errors.New(\"values don't match column count\")\n\t\t}\n\t\tif i != 0 {\n\t\t\tbuf.WriteString(\", \")\n\t\t}\n\t\tif err := EncodeValue(buf, r); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\tbuf.WriteByte(')')\n\treturn nil\n}\n\nfunc (tpl *TupleEqualityList) encodeAsEquality(buf *bytes.Buffer) error {\n\tfor i, r := range tpl.Rows {\n\t\tif i != 0 {\n\t\t\tbuf.WriteString(\" or \")\n\t\t}\n\t\tbuf.WriteString(\"(\")\n\t\tfor j, c := range tpl.Columns {\n\t\t\tif j != 0 {\n\t\t\t\tbuf.WriteString(\" and \")\n\t\t\t}\n\t\t\tbuf.WriteString(c)\n\t\t\tbuf.WriteString(\" = \")\n\t\t\tif err := EncodeValue(buf, r[j]); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t\tbuf.WriteByte(')')\n\t}\n\treturn nil\n}\n\nfunc FetchBindVar(name string, bindVariables map[string]interface{}) (val interface{}, isList bool, err error) {\n\tname = name[1:]\n\tif name[0] == ':' {\n\t\tname = name[1:]\n\t\tisList = true\n\t}\n\tsupplied, ok := bindVariables[name]\n\tif !ok {\n\t\treturn nil, false, fmt.Errorf(\"missing bind var %s\", name)\n\t}\n\tlist, gotList := supplied.([]interface{})\n\tif isList {\n\t\tif !gotList {\n\t\t\treturn nil, false, fmt.Errorf(\"unexpected list arg type %T for key %s\", supplied, name)\n\t\t}\n\t\tif len(list) == 0 {\n\t\t\treturn nil, false, fmt.Errorf(\"empty list supplied for %s\", name)\n\t\t}\n\t\treturn list, true, nil\n\t}\n\tif gotList {\n\t\treturn nil, false, fmt.Errorf(\"unexpected arg type %T for key %s\", supplied, name)\n\t}\n\treturn supplied, false, nil\n}\n"
  },
  {
    "path": "sqlparser/sql.go",
    "content": "//line sql.y:6\npackage sqlparser\n\nimport __yyfmt__ \"fmt\"\n\n//line sql.y:6\nimport \"bytes\"\n\nfunc SetParseTree(yylex interface{}, stmt Statement) {\n\tyylex.(*Tokenizer).ParseTree = stmt\n}\n\nfunc SetAllowComments(yylex interface{}, allow bool) {\n\tyylex.(*Tokenizer).AllowComments = allow\n}\n\nfunc ForceEOF(yylex interface{}) {\n\tyylex.(*Tokenizer).ForceEOF = true\n}\n\nvar (\n\tSHARE        = []byte(\"share\")\n\tMODE         = []byte(\"mode\")\n\tIF_BYTES     = []byte(\"if\")\n\tVALUES_BYTES = []byte(\"values\")\n)\n\n//line sql.y:31\ntype yySymType struct {\n\tyys         int\n\tempty       struct{}\n\tstatement   Statement\n\tselStmt     SelectStatement\n\tbyt         byte\n\tbytes       []byte\n\tbytes2      [][]byte\n\tstr         string\n\tselectExprs SelectExprs\n\tselectExpr  SelectExpr\n\tcolumns     Columns\n\tcolName     *ColName\n\ttableExprs  TableExprs\n\ttableExpr   TableExpr\n\tsmTableExpr SimpleTableExpr\n\ttableName   *TableName\n\tindexHints  *IndexHints\n\texpr        Expr\n\tboolExpr    BoolExpr\n\tvalExpr     ValExpr\n\tcolTuple    ColTuple\n\tvalExprs    ValExprs\n\tvalues      Values\n\trowTuple    RowTuple\n\tsubquery    *Subquery\n\tcaseExpr    *CaseExpr\n\twhens       []*When\n\twhen        *When\n\torderBy     OrderBy\n\torder       *Order\n\tlimit       *Limit\n\tinsRows     InsertRows\n\tupdateExprs UpdateExprs\n\tupdateExpr  *UpdateExpr\n}\n\nconst LEX_ERROR = 57346\nconst SELECT = 57347\nconst INSERT = 57348\nconst UPDATE = 57349\nconst DELETE = 57350\nconst FROM = 57351\nconst WHERE = 57352\nconst GROUP = 57353\nconst HAVING = 57354\nconst ORDER = 57355\nconst BY = 57356\nconst LIMIT = 57357\nconst FOR = 57358\nconst ALL = 57359\nconst DISTINCT = 57360\nconst AS = 57361\nconst EXISTS = 57362\nconst IN = 57363\nconst IS = 57364\nconst LIKE = 57365\nconst BETWEEN = 57366\nconst NULL = 57367\nconst ASC = 57368\nconst DESC = 57369\nconst VALUES = 57370\nconst INTO = 57371\nconst DUPLICATE = 57372\nconst KEY = 57373\nconst DEFAULT = 57374\nconst SET = 57375\nconst LOCK = 57376\nconst KEYRANGE = 57377\nconst ID = 57378\nconst STRING = 57379\nconst NUMBER = 57380\nconst VALUE_ARG = 57381\nconst LIST_ARG = 57382\nconst COMMENT = 57383\nconst LE = 57384\nconst GE = 57385\nconst NE = 57386\nconst NULL_SAFE_EQUAL = 57387\nconst UNION = 57388\nconst MINUS = 57389\nconst EXCEPT = 57390\nconst INTERSECT = 57391\nconst JOIN = 57392\nconst STRAIGHT_JOIN = 57393\nconst LEFT = 57394\nconst RIGHT = 57395\nconst INNER = 57396\nconst OUTER = 57397\nconst CROSS = 57398\nconst NATURAL = 57399\nconst USE = 57400\nconst FORCE = 57401\nconst ON = 57402\nconst OR = 57403\nconst AND = 57404\nconst NOT = 57405\nconst UNARY = 57406\nconst CASE = 57407\nconst WHEN = 57408\nconst THEN = 57409\nconst ELSE = 57410\nconst END = 57411\nconst CREATE = 57412\nconst ALTER = 57413\nconst DROP = 57414\nconst RENAME = 57415\nconst ANALYZE = 57416\nconst TABLE = 57417\nconst INDEX = 57418\nconst VIEW = 57419\nconst TO = 57420\nconst IGNORE = 57421\nconst IF = 57422\nconst UNIQUE = 57423\nconst USING = 57424\nconst SHOW = 57425\nconst DESCRIBE = 57426\nconst EXPLAIN = 57427\n\nvar yyToknames = []string{\n\t\"LEX_ERROR\",\n\t\"SELECT\",\n\t\"INSERT\",\n\t\"UPDATE\",\n\t\"DELETE\",\n\t\"FROM\",\n\t\"WHERE\",\n\t\"GROUP\",\n\t\"HAVING\",\n\t\"ORDER\",\n\t\"BY\",\n\t\"LIMIT\",\n\t\"FOR\",\n\t\"ALL\",\n\t\"DISTINCT\",\n\t\"AS\",\n\t\"EXISTS\",\n\t\"IN\",\n\t\"IS\",\n\t\"LIKE\",\n\t\"BETWEEN\",\n\t\"NULL\",\n\t\"ASC\",\n\t\"DESC\",\n\t\"VALUES\",\n\t\"INTO\",\n\t\"DUPLICATE\",\n\t\"KEY\",\n\t\"DEFAULT\",\n\t\"SET\",\n\t\"LOCK\",\n\t\"KEYRANGE\",\n\t\"ID\",\n\t\"STRING\",\n\t\"NUMBER\",\n\t\"VALUE_ARG\",\n\t\"LIST_ARG\",\n\t\"COMMENT\",\n\t\"LE\",\n\t\"GE\",\n\t\"NE\",\n\t\"NULL_SAFE_EQUAL\",\n\t\"'('\",\n\t\"'='\",\n\t\"'<'\",\n\t\"'>'\",\n\t\"'~'\",\n\t\"UNION\",\n\t\"MINUS\",\n\t\"EXCEPT\",\n\t\"INTERSECT\",\n\t\"','\",\n\t\"JOIN\",\n\t\"STRAIGHT_JOIN\",\n\t\"LEFT\",\n\t\"RIGHT\",\n\t\"INNER\",\n\t\"OUTER\",\n\t\"CROSS\",\n\t\"NATURAL\",\n\t\"USE\",\n\t\"FORCE\",\n\t\"ON\",\n\t\"OR\",\n\t\"AND\",\n\t\"NOT\",\n\t\"'&'\",\n\t\"'|'\",\n\t\"'^'\",\n\t\"'+'\",\n\t\"'-'\",\n\t\"'*'\",\n\t\"'/'\",\n\t\"'%'\",\n\t\"'.'\",\n\t\"UNARY\",\n\t\"CASE\",\n\t\"WHEN\",\n\t\"THEN\",\n\t\"ELSE\",\n\t\"END\",\n\t\"CREATE\",\n\t\"ALTER\",\n\t\"DROP\",\n\t\"RENAME\",\n\t\"ANALYZE\",\n\t\"TABLE\",\n\t\"INDEX\",\n\t\"VIEW\",\n\t\"TO\",\n\t\"IGNORE\",\n\t\"IF\",\n\t\"UNIQUE\",\n\t\"USING\",\n\t\"SHOW\",\n\t\"DESCRIBE\",\n\t\"EXPLAIN\",\n}\nvar yyStatenames = []string{}\n\nconst yyEofCode = 1\nconst yyErrCode = 2\nconst yyMaxDepth = 200\n\n//line yacctab:1\nvar yyExca = []int{\n\t-1, 1,\n\t1, -1,\n\t-2, 0,\n}\n\nconst yyNprod = 207\nconst yyPrivate = 57344\n\nvar yyTokenNames []string\nvar yyStates []string\n\nconst yyLast = 678\n\nvar yyAct = []int{\n\n\t51, 122, 141, 363, 359, 342, 49, 48, 83, 314,\n\t366, 280, 126, 334, 225, 159, 142, 42, 43, 125,\n\t3, 163, 205, 174, 332, 60, 47, 90, 138, 381,\n\t381, 37, 31, 32, 33, 34, 84, 85, 99, 98,\n\t268, 94, 15, 17, 18, 19, 153, 146, 127, 381,\n\t86, 340, 128, 91, 196, 29, 320, 91, 91, 219,\n\t71, 196, 73, 121, 124, 76, 74, 77, 136, 330,\n\t20, 144, 194, 38, 148, 383, 382, 150, 143, 329,\n\t132, 154, 195, 328, 147, 230, 231, 232, 233, 234,\n\t43, 235, 236, 43, 149, 380, 168, 339, 170, 302,\n\t299, 82, 173, 251, 249, 181, 182, 197, 185, 186,\n\t187, 188, 189, 190, 191, 192, 171, 172, 167, 304,\n\t157, 78, 21, 22, 24, 23, 25, 176, 293, 295,\n\t297, 198, 43, 43, 206, 26, 27, 28, 79, 80,\n\t81, 206, 183, 255, 241, 99, 98, 152, 215, 109,\n\t110, 111, 112, 113, 214, 209, 223, 216, 294, 218,\n\t306, 203, 200, 202, 193, 161, 207, 97, 96, 210,\n\t274, 111, 112, 113, 99, 98, 98, 198, 227, 211,\n\t335, 244, 245, 327, 325, 224, 184, 240, 242, 272,\n\t335, 167, 316, 275, 170, 222, 287, 326, 248, 291,\n\t285, 288, 243, 43, 176, 286, 290, 169, 160, 144,\n\t289, 260, 144, 211, 264, 373, 143, 354, 196, 143,\n\t252, 228, 265, 212, 256, 92, 262, 254, 263, 155,\n\t129, 352, 278, 250, 258, 230, 231, 232, 233, 234,\n\t279, 235, 236, 271, 273, 270, 166, 259, 301, 351,\n\t283, 284, 15, 211, 167, 167, 165, 305, 350, 144,\n\t144, 310, 31, 32, 33, 34, 143, 312, 177, 317,\n\t134, 91, 133, 131, 175, 130, 313, 309, 318, 303,\n\t158, 239, 96, 166, 198, 123, 346, 345, 298, 95,\n\t322, 59, 296, 165, 321, 324, 277, 276, 238, 323,\n\t261, 220, 331, 56, 57, 58, 96, 217, 333, 213,\n\t139, 156, 151, 16, 364, 337, 208, 370, 353, 15,\n\t137, 247, 379, 341, 338, 266, 29, 178, 348, 179,\n\t180, 221, 365, 347, 87, 343, 344, 282, 315, 281,\n\t226, 144, 308, 349, 160, 357, 360, 356, 355, 88,\n\t140, 367, 367, 367, 361, 384, 378, 362, 15, 36,\n\t267, 371, 368, 369, 72, 319, 269, 75, 377, 145,\n\t311, 257, 374, 358, 385, 360, 375, 376, 386, 35,\n\t388, 387, 389, 253, 201, 144, 54, 390, 135, 391,\n\t204, 59, 143, 53, 65, 50, 52, 67, 68, 69,\n\t70, 55, 41, 56, 57, 58, 336, 307, 100, 44,\n\t292, 164, 46, 229, 162, 40, 63, 237, 93, 30,\n\t106, 107, 108, 109, 110, 111, 112, 113, 89, 14,\n\t13, 12, 11, 10, 9, 45, 8, 7, 6, 61,\n\t62, 39, 5, 4, 2, 1, 66, 54, 0, 0,\n\t0, 0, 59, 0, 0, 65, 0, 0, 0, 0,\n\t0, 64, 55, 41, 56, 57, 58, 199, 0, 372,\n\t0, 0, 0, 46, 0, 0, 0, 63, 0, 0,\n\t0, 0, 0, 15, 106, 107, 108, 109, 110, 111,\n\t112, 113, 0, 0, 0, 0, 45, 0, 54, 0,\n\t61, 62, 39, 59, 0, 0, 65, 66, 0, 0,\n\t0, 0, 0, 55, 123, 56, 57, 58, 54, 0,\n\t0, 0, 64, 59, 46, 0, 65, 0, 63, 0,\n\t0, 0, 0, 55, 123, 56, 57, 58, 0, 0,\n\t0, 0, 0, 15, 46, 0, 0, 45, 63, 0,\n\t0, 61, 62, 0, 0, 0, 0, 0, 66, 0,\n\t0, 0, 0, 59, 0, 0, 65, 45, 0, 0,\n\t0, 61, 62, 64, 123, 56, 57, 58, 66, 0,\n\t0, 0, 0, 59, 129, 0, 65, 0, 63, 0,\n\t0, 0, 0, 64, 123, 56, 57, 58, 0, 0,\n\t0, 0, 0, 0, 129, 0, 0, 0, 63, 0,\n\t0, 61, 62, 101, 105, 103, 104, 300, 66, 106,\n\t107, 108, 109, 110, 111, 112, 113, 0, 0, 0,\n\t0, 61, 62, 64, 117, 118, 119, 120, 66, 114,\n\t115, 116, 246, 0, 106, 107, 108, 109, 110, 111,\n\t112, 113, 0, 64, 0, 0, 0, 0, 0, 0,\n\t0, 102, 106, 107, 108, 109, 110, 111, 112, 113,\n\t106, 107, 108, 109, 110, 111, 112, 113,\n}\nvar yyPact = []int{\n\n\t37, -1000, -1000, 211, -1000, -1000, -1000, -1000, -1000, -1000,\n\t-1000, -1000, -1000, -1000, -1000, -1000, 427, -1000, -1000, -1000,\n\t-1000, -30, -27, 31, 48, 11, -1000, -1000, -1000, -1000,\n\t353, 317, -1000, -1000, -1000, 308, -1000, 216, -1000, -1000,\n\t270, 89, 107, 592, -1000, 498, 478, -1000, -1000, -1000,\n\t558, 229, 227, -1000, 226, 224, -1000, -1000, -1000, -1000,\n\t-1000, -1000, -1000, -1000, -1000, -1000, 558, 291, 274, 341,\n\t249, -48, -7, 246, -1000, 4, 246, -1000, 276, -49,\n\t246, -49, 275, -1000, -1000, -1000, -1000, -1000, 427, 239,\n\t334, 427, 210, -1000, -1000, 246, -1000, 132, 498, 498,\n\t558, 228, 306, 558, 558, 117, 558, 558, 558, 558,\n\t558, 558, 558, 558, -1000, -1000, -1000, -1000, -1000, -1000,\n\t-1000, -1000, 592, 86, -29, -19, 6, 592, -1000, 538,\n\t366, 427, -1000, 353, 266, 53, 600, 274, 283, 77,\n\t274, 158, -1000, 176, -1000, 273, 85, 246, -1000, 271,\n\t-1000, -34, 265, 311, 129, 246, -1000, 216, -1000, 329,\n\t498, -1000, 166, 179, 262, 247, 66, -1000, -1000, -1000,\n\t-1000, -1000, 108, 600, -1000, 538, -1000, -1000, 228, 558,\n\t558, 600, 574, -1000, 296, 76, 76, 76, 96, 96,\n\t-1000, -1000, -1000, 246, -1000, -1000, 558, -1000, 600, -1000,\n\t3, 427, 2, 165, 60, -1000, 498, 201, 249, 264,\n\t334, 249, 558, -1000, 305, -57, -1000, 157, -1000, 261,\n\t-1000, -1000, 260, -1000, 334, 327, 323, 107, 210, 210,\n\t-1000, -1000, 144, 140, 154, 150, 143, 64, -1000, 256,\n\t29, 252, -1, -1000, 600, 549, 558, -1000, 600, -1000,\n\t-2, -1000, 266, 35, -1000, 558, 78, 314, 249, 249,\n\t198, -1000, 325, -1000, 600, -1000, -1000, 126, 246, -1000,\n\t-37, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 329,\n\t325, 498, 558, 179, 118, -1000, 141, -1000, 127, -1000,\n\t-1000, -1000, -1000, -8, -12, -22, -1000, -1000, -1000, -1000,\n\t558, 600, -1000, -77, -1000, 600, 558, 114, 184, 211,\n\t124, -4, -1000, 325, 320, 322, 251, -1000, -1000, 250,\n\t-1000, 327, 320, 107, 163, 498, -1000, -1000, 212, 203,\n\t185, 600, -1000, 600, -1000, 288, 162, -1000, -1000, -1000,\n\t249, 320, -1000, 558, 558, -1000, -1000, 325, 298, 107,\n\t246, 246, 246, 286, 184, -1000, -1000, 414, 160, -1000,\n\t350, -1000, 320, -1000, 349, 301, -6, -1000, -25, -26,\n\t348, -1000, 558, 558, -1000, -1000, -1000, 298, -1000, 246,\n\t-1000, 246, -1000, -1000, 249, 600, -1000, -1000, 246, -1000,\n\t158, -1000,\n}\nvar yyPgo = []int{\n\n\t0, 445, 444, 19, 443, 442, 438, 437, 436, 434,\n\t433, 432, 431, 430, 429, 379, 428, 419, 313, 31,\n\t73, 418, 417, 415, 414, 21, 27, 413, 411, 28,\n\t410, 10, 15, 17, 409, 408, 407, 26, 1, 23,\n\t12, 406, 6, 396, 25, 395, 7, 393, 390, 22,\n\t388, 383, 14, 11, 9, 373, 4, 372, 5, 3,\n\t371, 370, 13, 2, 16, 147, 369, 367, 366, 365,\n\t364, 360, 0, 8, 359,\n}\nvar yyR1 = []int{\n\n\t0, 1, 2, 2, 2, 2, 2, 2, 2, 2,\n\t2, 2, 2, 2, 4, 3, 3, 5, 5, 6,\n\t7, 8, 9, 9, 9, 10, 10, 10, 11, 12,\n\t12, 12, 13, 14, 14, 14, 74, 15, 16, 16,\n\t17, 17, 17, 17, 17, 18, 18, 19, 19, 20,\n\t20, 20, 23, 23, 21, 21, 21, 24, 24, 25,\n\t25, 25, 25, 22, 22, 22, 27, 27, 27, 27,\n\t27, 27, 27, 27, 27, 28, 28, 28, 29, 29,\n\t30, 30, 30, 30, 31, 31, 26, 26, 32, 32,\n\t33, 33, 33, 33, 33, 34, 34, 34, 34, 34,\n\t34, 34, 34, 34, 34, 34, 35, 35, 35, 35,\n\t35, 35, 35, 39, 39, 39, 44, 40, 40, 38,\n\t38, 38, 38, 38, 38, 38, 38, 38, 38, 38,\n\t38, 38, 38, 38, 38, 38, 43, 43, 45, 45,\n\t45, 47, 50, 50, 48, 48, 49, 51, 51, 46,\n\t46, 37, 37, 37, 37, 52, 52, 53, 53, 54,\n\t54, 55, 55, 56, 57, 57, 57, 58, 58, 58,\n\t59, 59, 59, 60, 60, 61, 61, 62, 62, 36,\n\t36, 41, 41, 42, 42, 63, 63, 64, 65, 65,\n\t66, 66, 67, 67, 68, 68, 68, 68, 68, 69,\n\t69, 70, 70, 71, 71, 72, 73,\n}\nvar yyR2 = []int{\n\n\t0, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n\t1, 1, 1, 1, 9, 11, 3, 7, 7, 8,\n\t7, 3, 5, 8, 4, 6, 7, 4, 5, 4,\n\t5, 5, 3, 2, 2, 2, 0, 2, 0, 2,\n\t1, 2, 1, 1, 1, 0, 1, 1, 3, 1,\n\t2, 3, 1, 1, 0, 1, 2, 1, 3, 3,\n\t3, 3, 5, 0, 1, 2, 1, 1, 2, 3,\n\t2, 3, 2, 2, 2, 1, 3, 1, 1, 3,\n\t0, 5, 5, 5, 1, 3, 0, 2, 0, 2,\n\t1, 3, 3, 2, 3, 3, 3, 4, 3, 4,\n\t5, 6, 3, 4, 2, 6, 1, 1, 1, 1,\n\t1, 1, 1, 3, 1, 1, 3, 1, 3, 1,\n\t1, 1, 3, 3, 3, 3, 3, 3, 3, 3,\n\t2, 3, 4, 5, 4, 1, 1, 1, 1, 1,\n\t1, 5, 0, 1, 1, 2, 4, 0, 2, 1,\n\t3, 1, 1, 1, 1, 0, 3, 0, 2, 0,\n\t3, 1, 3, 2, 0, 1, 1, 0, 2, 4,\n\t0, 2, 4, 0, 3, 1, 3, 0, 5, 2,\n\t1, 1, 3, 3, 1, 1, 3, 3, 0, 2,\n\t0, 3, 0, 1, 1, 1, 1, 1, 1, 0,\n\t1, 0, 1, 0, 2, 1, 0,\n}\nvar yyChk = []int{\n\n\t-1000, -1, -2, -3, -4, -5, -6, -7, -8, -9,\n\t-10, -11, -12, -13, -14, 5, -18, 6, 7, 8,\n\t33, 85, 86, 88, 87, 89, 98, 99, 100, 18,\n\t-17, 51, 52, 53, 54, -15, -74, -19, -20, 75,\n\t-23, 36, -33, -38, -34, 69, 46, -37, -46, -42,\n\t-45, -72, -43, -47, 20, 35, 37, 38, 39, 25,\n\t-44, 73, 74, 50, 95, 28, 80, -15, -15, -15,\n\t-15, 90, -70, 92, 96, -67, 92, 94, 90, 90,\n\t91, 92, 90, -73, -73, -73, -3, 17, -18, -16,\n\t-26, 55, 9, -21, -72, 19, 36, 78, 68, 67,\n\t-35, 21, 69, 23, 24, 22, 70, 71, 72, 73,\n\t74, 75, 76, 77, 47, 48, 49, 42, 43, 44,\n\t45, -33, -38, 36, -33, -3, -40, -38, -38, 46,\n\t46, 46, -44, 46, 46, -50, -38, 29, -29, 36,\n\t9, -63, -64, -46, -72, -66, 95, 91, -72, 90,\n\t-72, 36, -65, 95, -72, -65, 36, -19, 41, -32,\n\t10, -20, -24, -25, -28, 46, 36, -44, -72, 75,\n\t-72, -33, -33, -38, -39, 46, -44, 40, 21, 23,\n\t24, -38, -38, 25, 69, -38, -38, -38, -38, -38,\n\t-38, -38, -38, 78, 101, 101, 55, 101, -38, 101,\n\t-19, 18, -19, -37, -48, -49, 81, -29, 33, 78,\n\t-29, 55, 47, 36, 69, -72, -73, 36, -73, 93,\n\t36, 20, 66, -72, -26, -52, 11, -33, 55, -27,\n\t56, 57, 58, 59, 60, 62, 63, -22, 36, 19,\n\t-25, 78, -40, -39, -38, -38, 68, 25, -38, 101,\n\t-19, 101, 55, -51, -49, 83, -33, -60, 33, 46,\n\t-63, 36, -32, -64, -38, -73, 20, -71, 97, -68,\n\t88, 86, 32, 87, 13, 36, 36, 36, -73, -32,\n\t-53, 12, 14, -25, -25, 56, 61, 56, 61, 56,\n\t56, 56, -30, 64, 94, 65, 36, 101, 36, 101,\n\t68, -38, 101, -37, 84, -38, 82, -36, 28, -3,\n\t-63, -61, -46, -32, -54, 13, 66, -72, -73, -69,\n\t93, -52, -54, -33, -40, 66, 56, 56, 91, 91,\n\t91, -38, 101, -38, -62, 66, -41, -42, -62, 101,\n\t55, -54, -58, 15, 14, 36, 36, -53, -58, -33,\n\t46, 46, 46, 30, 55, -46, -58, -38, -55, -56,\n\t-38, -73, -54, -59, 16, 34, -31, -72, -31, -31,\n\t31, -42, 55, 55, -57, 26, 27, -58, 7, 21,\n\t101, 55, 101, 101, 7, -38, -56, -59, -72, -72,\n\t-63, -72,\n}\nvar yyDef = []int{\n\n\t45, -2, 1, 2, 3, 4, 5, 6, 7, 8,\n\t9, 10, 11, 12, 13, 36, 0, 36, 36, 36,\n\t36, 201, 192, 0, 0, 0, 206, 206, 206, 46,\n\t0, 40, 42, 43, 44, 45, 38, 86, 47, 49,\n\t54, 205, 52, 53, 90, 0, 0, 119, 120, 121,\n\t0, 149, 0, 135, 0, 0, 151, 152, 153, 154,\n\t184, 138, 139, 140, 136, 137, 142, 0, 0, 0,\n\t0, 190, 0, 0, 202, 0, 0, 193, 0, 188,\n\t0, 188, 0, 33, 34, 35, 16, 41, 0, 37,\n\t88, 0, 0, 50, 55, 0, 205, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 106, 107, 108, 109, 110, 111,\n\t112, 93, 0, 205, 0, 0, 0, 117, 130, 0,\n\t0, 0, 104, 0, 0, 0, 143, 0, 0, 78,\n\t0, 21, 185, 0, 149, 0, 0, 0, 206, 0,\n\t206, 0, 0, 0, 0, 0, 32, 86, 39, 155,\n\t0, 48, 87, 57, 63, 0, 75, 77, 56, 51,\n\t150, 91, 92, 95, 96, 0, 114, 115, 0, 0,\n\t0, 98, 0, 102, 0, 122, 123, 124, 125, 126,\n\t127, 128, 129, 0, 94, 116, 0, 183, 117, 131,\n\t0, 0, 0, 0, 147, 144, 0, 173, 0, 0,\n\t88, 0, 0, 206, 0, 203, 24, 0, 27, 0,\n\t29, 189, 0, 206, 88, 157, 0, 89, 0, 0,\n\t66, 67, 0, 0, 0, 0, 0, 80, 64, 0,\n\t0, 0, 0, 97, 99, 0, 0, 103, 118, 132,\n\t0, 134, 0, 0, 145, 0, 0, 0, 0, 0,\n\t88, 79, 159, 186, 187, 22, 191, 0, 0, 206,\n\t199, 194, 195, 196, 197, 198, 28, 30, 31, 155,\n\t159, 0, 0, 58, 61, 68, 0, 70, 0, 72,\n\t73, 74, 59, 0, 0, 0, 65, 60, 76, 113,\n\t0, 100, 133, 0, 141, 148, 0, 177, 0, 180,\n\t177, 0, 175, 159, 167, 0, 0, 204, 25, 0,\n\t200, 157, 167, 158, 156, 0, 69, 71, 0, 0,\n\t0, 101, 105, 146, 17, 0, 179, 181, 18, 174,\n\t0, 167, 20, 0, 0, 206, 26, 159, 170, 62,\n\t0, 0, 0, 0, 0, 176, 19, 168, 160, 161,\n\t164, 23, 167, 14, 0, 0, 0, 84, 0, 0,\n\t0, 182, 0, 0, 163, 165, 166, 170, 171, 0,\n\t81, 0, 82, 83, 0, 169, 162, 15, 0, 85,\n\t178, 172,\n}\nvar yyTok1 = []int{\n\n\t1, 3, 3, 3, 3, 3, 3, 3, 3, 3,\n\t3, 3, 3, 3, 3, 3, 3, 3, 3, 3,\n\t3, 3, 3, 3, 3, 3, 3, 3, 3, 3,\n\t3, 3, 3, 3, 3, 3, 3, 77, 70, 3,\n\t46, 101, 75, 73, 55, 74, 78, 76, 3, 3,\n\t3, 3, 3, 3, 3, 3, 3, 3, 3, 3,\n\t48, 47, 49, 3, 3, 3, 3, 3, 3, 3,\n\t3, 3, 3, 3, 3, 3, 3, 3, 3, 3,\n\t3, 3, 3, 3, 3, 3, 3, 3, 3, 3,\n\t3, 3, 3, 3, 72, 3, 3, 3, 3, 3,\n\t3, 3, 3, 3, 3, 3, 3, 3, 3, 3,\n\t3, 3, 3, 3, 3, 3, 3, 3, 3, 3,\n\t3, 3, 3, 3, 71, 3, 50,\n}\nvar yyTok2 = []int{\n\n\t2, 3, 4, 5, 6, 7, 8, 9, 10, 11,\n\t12, 13, 14, 15, 16, 17, 18, 19, 20, 21,\n\t22, 23, 24, 25, 26, 27, 28, 29, 30, 31,\n\t32, 33, 34, 35, 36, 37, 38, 39, 40, 41,\n\t42, 43, 44, 45, 51, 52, 53, 54, 56, 57,\n\t58, 59, 60, 61, 62, 63, 64, 65, 66, 67,\n\t68, 69, 79, 80, 81, 82, 83, 84, 85, 86,\n\t87, 88, 89, 90, 91, 92, 93, 94, 95, 96,\n\t97, 98, 99, 100,\n}\nvar yyTok3 = []int{\n\t0,\n}\n\n//line yaccpar:1\n\n/*\tparser for yacc output\t*/\n\nvar yyDebug = 0\n\ntype yyLexer interface {\n\tLex(lval *yySymType) int\n\tError(s string)\n}\n\nconst yyFlag = -1000\n\nfunc yyTokname(c int) string {\n\t// 4 is TOKSTART above\n\tif c >= 4 && c-4 < len(yyToknames) {\n\t\tif yyToknames[c-4] != \"\" {\n\t\t\treturn yyToknames[c-4]\n\t\t}\n\t}\n\treturn __yyfmt__.Sprintf(\"tok-%v\", c)\n}\n\nfunc yyStatname(s int) string {\n\tif s >= 0 && s < len(yyStatenames) {\n\t\tif yyStatenames[s] != \"\" {\n\t\t\treturn yyStatenames[s]\n\t\t}\n\t}\n\treturn __yyfmt__.Sprintf(\"state-%v\", s)\n}\n\nfunc yylex1(lex yyLexer, lval *yySymType) int {\n\tc := 0\n\tchar := lex.Lex(lval)\n\tif char <= 0 {\n\t\tc = yyTok1[0]\n\t\tgoto out\n\t}\n\tif char < len(yyTok1) {\n\t\tc = yyTok1[char]\n\t\tgoto out\n\t}\n\tif char >= yyPrivate {\n\t\tif char < yyPrivate+len(yyTok2) {\n\t\t\tc = yyTok2[char-yyPrivate]\n\t\t\tgoto out\n\t\t}\n\t}\n\tfor i := 0; i < len(yyTok3); i += 2 {\n\t\tc = yyTok3[i+0]\n\t\tif c == char {\n\t\t\tc = yyTok3[i+1]\n\t\t\tgoto out\n\t\t}\n\t}\n\nout:\n\tif c == 0 {\n\t\tc = yyTok2[1] /* unknown char */\n\t}\n\tif yyDebug >= 3 {\n\t\t__yyfmt__.Printf(\"lex %s(%d)\\n\", yyTokname(c), uint(char))\n\t}\n\treturn c\n}\n\nfunc yyParse(yylex yyLexer) int {\n\tvar yyn int\n\tvar yylval yySymType\n\tvar yyVAL yySymType\n\tyyS := make([]yySymType, yyMaxDepth)\n\n\tNerrs := 0   /* number of errors */\n\tErrflag := 0 /* error recovery flag */\n\tyystate := 0\n\tyychar := -1\n\tyyp := -1\n\tgoto yystack\n\nret0:\n\treturn 0\n\nret1:\n\treturn 1\n\nyystack:\n\t/* put a state and value onto the stack */\n\tif yyDebug >= 4 {\n\t\t__yyfmt__.Printf(\"char %v in %v\\n\", yyTokname(yychar), yyStatname(yystate))\n\t}\n\n\tyyp++\n\tif yyp >= len(yyS) {\n\t\tnyys := make([]yySymType, len(yyS)*2)\n\t\tcopy(nyys, yyS)\n\t\tyyS = nyys\n\t}\n\tyyS[yyp] = yyVAL\n\tyyS[yyp].yys = yystate\n\nyynewstate:\n\tyyn = yyPact[yystate]\n\tif yyn <= yyFlag {\n\t\tgoto yydefault /* simple state */\n\t}\n\tif yychar < 0 {\n\t\tyychar = yylex1(yylex, &yylval)\n\t}\n\tyyn += yychar\n\tif yyn < 0 || yyn >= yyLast {\n\t\tgoto yydefault\n\t}\n\tyyn = yyAct[yyn]\n\tif yyChk[yyn] == yychar { /* valid shift */\n\t\tyychar = -1\n\t\tyyVAL = yylval\n\t\tyystate = yyn\n\t\tif Errflag > 0 {\n\t\t\tErrflag--\n\t\t}\n\t\tgoto yystack\n\t}\n\nyydefault:\n\t/* default state action */\n\tyyn = yyDef[yystate]\n\tif yyn == -2 {\n\t\tif yychar < 0 {\n\t\t\tyychar = yylex1(yylex, &yylval)\n\t\t}\n\n\t\t/* look through exception table */\n\t\txi := 0\n\t\tfor {\n\t\t\tif yyExca[xi+0] == -1 && yyExca[xi+1] == yystate {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\txi += 2\n\t\t}\n\t\tfor xi += 2; ; xi += 2 {\n\t\t\tyyn = yyExca[xi+0]\n\t\t\tif yyn < 0 || yyn == yychar {\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tyyn = yyExca[xi+1]\n\t\tif yyn < 0 {\n\t\t\tgoto ret0\n\t\t}\n\t}\n\tif yyn == 0 {\n\t\t/* error ... attempt to resume parsing */\n\t\tswitch Errflag {\n\t\tcase 0: /* brand new error */\n\t\t\tyylex.Error(\"syntax error\")\n\t\t\tNerrs++\n\t\t\tif yyDebug >= 1 {\n\t\t\t\t__yyfmt__.Printf(\"%s\", yyStatname(yystate))\n\t\t\t\t__yyfmt__.Printf(\" saw %s\\n\", yyTokname(yychar))\n\t\t\t}\n\t\t\tfallthrough\n\n\t\tcase 1, 2: /* incompletely recovered error ... try again */\n\t\t\tErrflag = 3\n\n\t\t\t/* find a state where \"error\" is a legal shift action */\n\t\t\tfor yyp >= 0 {\n\t\t\t\tyyn = yyPact[yyS[yyp].yys] + yyErrCode\n\t\t\t\tif yyn >= 0 && yyn < yyLast {\n\t\t\t\t\tyystate = yyAct[yyn] /* simulate a shift of \"error\" */\n\t\t\t\t\tif yyChk[yystate] == yyErrCode {\n\t\t\t\t\t\tgoto yystack\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/* the current p has no shift on \"error\", pop stack */\n\t\t\t\tif yyDebug >= 2 {\n\t\t\t\t\t__yyfmt__.Printf(\"error recovery pops state %d\\n\", yyS[yyp].yys)\n\t\t\t\t}\n\t\t\t\tyyp--\n\t\t\t}\n\t\t\t/* there is no state on the stack with an error shift ... abort */\n\t\t\tgoto ret1\n\n\t\tcase 3: /* no shift yet; clobber input char */\n\t\t\tif yyDebug >= 2 {\n\t\t\t\t__yyfmt__.Printf(\"error recovery discards %s\\n\", yyTokname(yychar))\n\t\t\t}\n\t\t\tif yychar == yyEofCode {\n\t\t\t\tgoto ret1\n\t\t\t}\n\t\t\tyychar = -1\n\t\t\tgoto yynewstate /* try again in the same state */\n\t\t}\n\t}\n\n\t/* reduction by production yyn */\n\tif yyDebug >= 2 {\n\t\t__yyfmt__.Printf(\"reduce %v in:\\n\\t%v\\n\", yyn, yyStatname(yystate))\n\t}\n\n\tyynt := yyn\n\tyypt := yyp\n\t_ = yypt // guard against \"declared and not used\"\n\n\tyyp -= yyR2[yyn]\n\tyyVAL = yyS[yyp+1]\n\n\t/* consult goto table to find next state */\n\tyyn = yyR1[yyn]\n\tyyg := yyPgo[yyn]\n\tyyj := yyg + yyS[yyp].yys + 1\n\n\tif yyj >= yyLast {\n\t\tyystate = yyAct[yyg]\n\t} else {\n\t\tyystate = yyAct[yyj]\n\t\tif yyChk[yystate] != -yyn {\n\t\t\tyystate = yyAct[yyg]\n\t\t}\n\t}\n\t// dummy call; replaced with literal code\n\tswitch yynt {\n\n\tcase 1:\n\t\t//line sql.y:154\n\t\t{\n\t\t\tSetParseTree(yylex, yyS[yypt-0].statement)\n\t\t}\n\tcase 2:\n\t\t//line sql.y:160\n\t\t{\n\t\t\tyyVAL.statement = yyS[yypt-0].selStmt\n\t\t}\n\tcase 3:\n\t\t//line sql.y:164\n\t\t{\n\t\t\tyyVAL.statement = yyS[yypt-0].selStmt\n\t\t}\n\tcase 4:\n\t\tyyVAL.statement = yyS[yypt-0].statement\n\tcase 5:\n\t\tyyVAL.statement = yyS[yypt-0].statement\n\tcase 6:\n\t\tyyVAL.statement = yyS[yypt-0].statement\n\tcase 7:\n\t\tyyVAL.statement = yyS[yypt-0].statement\n\tcase 8:\n\t\tyyVAL.statement = yyS[yypt-0].statement\n\tcase 9:\n\t\tyyVAL.statement = yyS[yypt-0].statement\n\tcase 10:\n\t\tyyVAL.statement = yyS[yypt-0].statement\n\tcase 11:\n\t\tyyVAL.statement = yyS[yypt-0].statement\n\tcase 12:\n\t\tyyVAL.statement = yyS[yypt-0].statement\n\tcase 13:\n\t\tyyVAL.statement = yyS[yypt-0].statement\n\tcase 14:\n\t\t//line sql.y:180\n\t\t{\n\t\t\tyyVAL.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}\n\t\t}\n\tcase 15:\n\t\t//line sql.y:186\n\t\t{\n\t\t\tyyVAL.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}\n\t\t}\n\tcase 16:\n\t\t//line sql.y:190\n\t\t{\n\t\t\tyyVAL.selStmt = &Union{Type: yyS[yypt-1].str, Left: yyS[yypt-2].selStmt, Right: yyS[yypt-0].selStmt}\n\t\t}\n\tcase 17:\n\t\t//line sql.y:196\n\t\t{\n\t\t\tyyVAL.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)}\n\t\t}\n\tcase 18:\n\t\t//line sql.y:200\n\t\t{\n\t\t\tcols := make(Columns, 0, len(yyS[yypt-1].updateExprs))\n\t\t\tvals := make(ValTuple, 0, len(yyS[yypt-1].updateExprs))\n\t\t\tfor _, col := range yyS[yypt-1].updateExprs {\n\t\t\t\tcols = append(cols, &NonStarExpr{Expr: col.Name})\n\t\t\t\tvals = append(vals, col.Expr)\n\t\t\t}\n\t\t\tyyVAL.statement = &Insert{Comments: Comments(yyS[yypt-5].bytes2), Table: yyS[yypt-3].tableName, Columns: cols, Rows: Values{vals}, OnDup: OnDup(yyS[yypt-0].updateExprs)}\n\t\t}\n\tcase 19:\n\t\t//line sql.y:212\n\t\t{\n\t\t\tyyVAL.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}\n\t\t}\n\tcase 20:\n\t\t//line sql.y:218\n\t\t{\n\t\t\tyyVAL.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}\n\t\t}\n\tcase 21:\n\t\t//line sql.y:224\n\t\t{\n\t\t\tyyVAL.statement = &Set{Comments: Comments(yyS[yypt-1].bytes2), Exprs: yyS[yypt-0].updateExprs}\n\t\t}\n\tcase 22:\n\t\t//line sql.y:230\n\t\t{\n\t\t\tyyVAL.statement = &DDL{Action: AST_CREATE, NewName: yyS[yypt-1].bytes}\n\t\t}\n\tcase 23:\n\t\t//line sql.y:234\n\t\t{\n\t\t\t// Change this to an alter statement\n\t\t\tyyVAL.statement = &DDL{Action: AST_ALTER, Table: yyS[yypt-1].bytes, NewName: yyS[yypt-1].bytes}\n\t\t}\n\tcase 24:\n\t\t//line sql.y:239\n\t\t{\n\t\t\tyyVAL.statement = &DDL{Action: AST_CREATE, NewName: yyS[yypt-1].bytes}\n\t\t}\n\tcase 25:\n\t\t//line sql.y:245\n\t\t{\n\t\t\tyyVAL.statement = &DDL{Action: AST_ALTER, Table: yyS[yypt-2].bytes, NewName: yyS[yypt-2].bytes}\n\t\t}\n\tcase 26:\n\t\t//line sql.y:249\n\t\t{\n\t\t\t// Change this to a rename statement\n\t\t\tyyVAL.statement = &DDL{Action: AST_RENAME, Table: yyS[yypt-3].bytes, NewName: yyS[yypt-0].bytes}\n\t\t}\n\tcase 27:\n\t\t//line sql.y:254\n\t\t{\n\t\t\tyyVAL.statement = &DDL{Action: AST_ALTER, Table: yyS[yypt-1].bytes, NewName: yyS[yypt-1].bytes}\n\t\t}\n\tcase 28:\n\t\t//line sql.y:260\n\t\t{\n\t\t\tyyVAL.statement = &DDL{Action: AST_RENAME, Table: yyS[yypt-2].bytes, NewName: yyS[yypt-0].bytes}\n\t\t}\n\tcase 29:\n\t\t//line sql.y:266\n\t\t{\n\t\t\tyyVAL.statement = &DDL{Action: AST_DROP, Table: yyS[yypt-0].bytes}\n\t\t}\n\tcase 30:\n\t\t//line sql.y:270\n\t\t{\n\t\t\t// Change this to an alter statement\n\t\t\tyyVAL.statement = &DDL{Action: AST_ALTER, Table: yyS[yypt-0].bytes, NewName: yyS[yypt-0].bytes}\n\t\t}\n\tcase 31:\n\t\t//line sql.y:275\n\t\t{\n\t\t\tyyVAL.statement = &DDL{Action: AST_DROP, Table: yyS[yypt-1].bytes}\n\t\t}\n\tcase 32:\n\t\t//line sql.y:281\n\t\t{\n\t\t\tyyVAL.statement = &DDL{Action: AST_ALTER, Table: yyS[yypt-0].bytes, NewName: yyS[yypt-0].bytes}\n\t\t}\n\tcase 33:\n\t\t//line sql.y:287\n\t\t{\n\t\t\tyyVAL.statement = &Other{}\n\t\t}\n\tcase 34:\n\t\t//line sql.y:291\n\t\t{\n\t\t\tyyVAL.statement = &Other{}\n\t\t}\n\tcase 35:\n\t\t//line sql.y:295\n\t\t{\n\t\t\tyyVAL.statement = &Other{}\n\t\t}\n\tcase 36:\n\t\t//line sql.y:300\n\t\t{\n\t\t\tSetAllowComments(yylex, true)\n\t\t}\n\tcase 37:\n\t\t//line sql.y:304\n\t\t{\n\t\t\tyyVAL.bytes2 = yyS[yypt-0].bytes2\n\t\t\tSetAllowComments(yylex, false)\n\t\t}\n\tcase 38:\n\t\t//line sql.y:310\n\t\t{\n\t\t\tyyVAL.bytes2 = nil\n\t\t}\n\tcase 39:\n\t\t//line sql.y:314\n\t\t{\n\t\t\tyyVAL.bytes2 = append(yyS[yypt-1].bytes2, yyS[yypt-0].bytes)\n\t\t}\n\tcase 40:\n\t\t//line sql.y:320\n\t\t{\n\t\t\tyyVAL.str = AST_UNION\n\t\t}\n\tcase 41:\n\t\t//line sql.y:324\n\t\t{\n\t\t\tyyVAL.str = AST_UNION_ALL\n\t\t}\n\tcase 42:\n\t\t//line sql.y:328\n\t\t{\n\t\t\tyyVAL.str = AST_SET_MINUS\n\t\t}\n\tcase 43:\n\t\t//line sql.y:332\n\t\t{\n\t\t\tyyVAL.str = AST_EXCEPT\n\t\t}\n\tcase 44:\n\t\t//line sql.y:336\n\t\t{\n\t\t\tyyVAL.str = AST_INTERSECT\n\t\t}\n\tcase 45:\n\t\t//line sql.y:341\n\t\t{\n\t\t\tyyVAL.str = \"\"\n\t\t}\n\tcase 46:\n\t\t//line sql.y:345\n\t\t{\n\t\t\tyyVAL.str = AST_DISTINCT\n\t\t}\n\tcase 47:\n\t\t//line sql.y:351\n\t\t{\n\t\t\tyyVAL.selectExprs = SelectExprs{yyS[yypt-0].selectExpr}\n\t\t}\n\tcase 48:\n\t\t//line sql.y:355\n\t\t{\n\t\t\tyyVAL.selectExprs = append(yyVAL.selectExprs, yyS[yypt-0].selectExpr)\n\t\t}\n\tcase 49:\n\t\t//line sql.y:361\n\t\t{\n\t\t\tyyVAL.selectExpr = &StarExpr{}\n\t\t}\n\tcase 50:\n\t\t//line sql.y:365\n\t\t{\n\t\t\tyyVAL.selectExpr = &NonStarExpr{Expr: yyS[yypt-1].expr, As: yyS[yypt-0].bytes}\n\t\t}\n\tcase 51:\n\t\t//line sql.y:369\n\t\t{\n\t\t\tyyVAL.selectExpr = &StarExpr{TableName: yyS[yypt-2].bytes}\n\t\t}\n\tcase 52:\n\t\t//line sql.y:375\n\t\t{\n\t\t\tyyVAL.expr = yyS[yypt-0].boolExpr\n\t\t}\n\tcase 53:\n\t\t//line sql.y:379\n\t\t{\n\t\t\tyyVAL.expr = yyS[yypt-0].valExpr\n\t\t}\n\tcase 54:\n\t\t//line sql.y:384\n\t\t{\n\t\t\tyyVAL.bytes = nil\n\t\t}\n\tcase 55:\n\t\t//line sql.y:388\n\t\t{\n\t\t\tyyVAL.bytes = yyS[yypt-0].bytes\n\t\t}\n\tcase 56:\n\t\t//line sql.y:392\n\t\t{\n\t\t\tyyVAL.bytes = yyS[yypt-0].bytes\n\t\t}\n\tcase 57:\n\t\t//line sql.y:398\n\t\t{\n\t\t\tyyVAL.tableExprs = TableExprs{yyS[yypt-0].tableExpr}\n\t\t}\n\tcase 58:\n\t\t//line sql.y:402\n\t\t{\n\t\t\tyyVAL.tableExprs = append(yyVAL.tableExprs, yyS[yypt-0].tableExpr)\n\t\t}\n\tcase 59:\n\t\t//line sql.y:408\n\t\t{\n\t\t\tyyVAL.tableExpr = &AliasedTableExpr{Expr: yyS[yypt-2].smTableExpr, As: yyS[yypt-1].bytes, Hints: yyS[yypt-0].indexHints}\n\t\t}\n\tcase 60:\n\t\t//line sql.y:412\n\t\t{\n\t\t\tyyVAL.tableExpr = &ParenTableExpr{Expr: yyS[yypt-1].tableExpr}\n\t\t}\n\tcase 61:\n\t\t//line sql.y:416\n\t\t{\n\t\t\tyyVAL.tableExpr = &JoinTableExpr{LeftExpr: yyS[yypt-2].tableExpr, Join: yyS[yypt-1].str, RightExpr: yyS[yypt-0].tableExpr}\n\t\t}\n\tcase 62:\n\t\t//line sql.y:420\n\t\t{\n\t\t\tyyVAL.tableExpr = &JoinTableExpr{LeftExpr: yyS[yypt-4].tableExpr, Join: yyS[yypt-3].str, RightExpr: yyS[yypt-2].tableExpr, On: yyS[yypt-0].boolExpr}\n\t\t}\n\tcase 63:\n\t\t//line sql.y:425\n\t\t{\n\t\t\tyyVAL.bytes = nil\n\t\t}\n\tcase 64:\n\t\t//line sql.y:429\n\t\t{\n\t\t\tyyVAL.bytes = yyS[yypt-0].bytes\n\t\t}\n\tcase 65:\n\t\t//line sql.y:433\n\t\t{\n\t\t\tyyVAL.bytes = yyS[yypt-0].bytes\n\t\t}\n\tcase 66:\n\t\t//line sql.y:439\n\t\t{\n\t\t\tyyVAL.str = AST_JOIN\n\t\t}\n\tcase 67:\n\t\t//line sql.y:443\n\t\t{\n\t\t\tyyVAL.str = AST_STRAIGHT_JOIN\n\t\t}\n\tcase 68:\n\t\t//line sql.y:447\n\t\t{\n\t\t\tyyVAL.str = AST_LEFT_JOIN\n\t\t}\n\tcase 69:\n\t\t//line sql.y:451\n\t\t{\n\t\t\tyyVAL.str = AST_LEFT_JOIN\n\t\t}\n\tcase 70:\n\t\t//line sql.y:455\n\t\t{\n\t\t\tyyVAL.str = AST_RIGHT_JOIN\n\t\t}\n\tcase 71:\n\t\t//line sql.y:459\n\t\t{\n\t\t\tyyVAL.str = AST_RIGHT_JOIN\n\t\t}\n\tcase 72:\n\t\t//line sql.y:463\n\t\t{\n\t\t\tyyVAL.str = AST_JOIN\n\t\t}\n\tcase 73:\n\t\t//line sql.y:467\n\t\t{\n\t\t\tyyVAL.str = AST_CROSS_JOIN\n\t\t}\n\tcase 74:\n\t\t//line sql.y:471\n\t\t{\n\t\t\tyyVAL.str = AST_NATURAL_JOIN\n\t\t}\n\tcase 75:\n\t\t//line sql.y:477\n\t\t{\n\t\t\tyyVAL.smTableExpr = &TableName{Name: yyS[yypt-0].bytes}\n\t\t}\n\tcase 76:\n\t\t//line sql.y:481\n\t\t{\n\t\t\tyyVAL.smTableExpr = &TableName{Qualifier: yyS[yypt-2].bytes, Name: yyS[yypt-0].bytes}\n\t\t}\n\tcase 77:\n\t\t//line sql.y:485\n\t\t{\n\t\t\tyyVAL.smTableExpr = yyS[yypt-0].subquery\n\t\t}\n\tcase 78:\n\t\t//line sql.y:491\n\t\t{\n\t\t\tyyVAL.tableName = &TableName{Name: yyS[yypt-0].bytes}\n\t\t}\n\tcase 79:\n\t\t//line sql.y:495\n\t\t{\n\t\t\tyyVAL.tableName = &TableName{Qualifier: yyS[yypt-2].bytes, Name: yyS[yypt-0].bytes}\n\t\t}\n\tcase 80:\n\t\t//line sql.y:500\n\t\t{\n\t\t\tyyVAL.indexHints = nil\n\t\t}\n\tcase 81:\n\t\t//line sql.y:504\n\t\t{\n\t\t\tyyVAL.indexHints = &IndexHints{Type: AST_USE, Indexes: yyS[yypt-1].bytes2}\n\t\t}\n\tcase 82:\n\t\t//line sql.y:508\n\t\t{\n\t\t\tyyVAL.indexHints = &IndexHints{Type: AST_IGNORE, Indexes: yyS[yypt-1].bytes2}\n\t\t}\n\tcase 83:\n\t\t//line sql.y:512\n\t\t{\n\t\t\tyyVAL.indexHints = &IndexHints{Type: AST_FORCE, Indexes: yyS[yypt-1].bytes2}\n\t\t}\n\tcase 84:\n\t\t//line sql.y:518\n\t\t{\n\t\t\tyyVAL.bytes2 = [][]byte{yyS[yypt-0].bytes}\n\t\t}\n\tcase 85:\n\t\t//line sql.y:522\n\t\t{\n\t\t\tyyVAL.bytes2 = append(yyS[yypt-2].bytes2, yyS[yypt-0].bytes)\n\t\t}\n\tcase 86:\n\t\t//line sql.y:527\n\t\t{\n\t\t\tyyVAL.tableExprs = nil\n\t\t}\n\tcase 87:\n\t\t//line sql.y:531\n\t\t{\n\t\t\tyyVAL.tableExprs = yyS[yypt-0].tableExprs\n\t\t}\n\tcase 88:\n\t\t//line sql.y:537\n\t\t{\n\t\t\tyyVAL.boolExpr = nil\n\t\t}\n\tcase 89:\n\t\t//line sql.y:541\n\t\t{\n\t\t\tyyVAL.boolExpr = yyS[yypt-0].boolExpr\n\t\t}\n\tcase 90:\n\t\tyyVAL.boolExpr = yyS[yypt-0].boolExpr\n\tcase 91:\n\t\t//line sql.y:548\n\t\t{\n\t\t\tyyVAL.boolExpr = &AndExpr{Left: yyS[yypt-2].boolExpr, Right: yyS[yypt-0].boolExpr}\n\t\t}\n\tcase 92:\n\t\t//line sql.y:552\n\t\t{\n\t\t\tyyVAL.boolExpr = &OrExpr{Left: yyS[yypt-2].boolExpr, Right: yyS[yypt-0].boolExpr}\n\t\t}\n\tcase 93:\n\t\t//line sql.y:556\n\t\t{\n\t\t\tyyVAL.boolExpr = &NotExpr{Expr: yyS[yypt-0].boolExpr}\n\t\t}\n\tcase 94:\n\t\t//line sql.y:560\n\t\t{\n\t\t\tyyVAL.boolExpr = &ParenBoolExpr{Expr: yyS[yypt-1].boolExpr}\n\t\t}\n\tcase 95:\n\t\t//line sql.y:566\n\t\t{\n\t\t\tyyVAL.boolExpr = &ComparisonExpr{Left: yyS[yypt-2].valExpr, Operator: yyS[yypt-1].str, Right: yyS[yypt-0].valExpr}\n\t\t}\n\tcase 96:\n\t\t//line sql.y:570\n\t\t{\n\t\t\tyyVAL.boolExpr = &ComparisonExpr{Left: yyS[yypt-2].valExpr, Operator: AST_IN, Right: yyS[yypt-0].colTuple}\n\t\t}\n\tcase 97:\n\t\t//line sql.y:574\n\t\t{\n\t\t\tyyVAL.boolExpr = &ComparisonExpr{Left: yyS[yypt-3].valExpr, Operator: AST_NOT_IN, Right: yyS[yypt-0].colTuple}\n\t\t}\n\tcase 98:\n\t\t//line sql.y:578\n\t\t{\n\t\t\tyyVAL.boolExpr = &ComparisonExpr{Left: yyS[yypt-2].valExpr, Operator: AST_LIKE, Right: yyS[yypt-0].valExpr}\n\t\t}\n\tcase 99:\n\t\t//line sql.y:582\n\t\t{\n\t\t\tyyVAL.boolExpr = &ComparisonExpr{Left: yyS[yypt-3].valExpr, Operator: AST_NOT_LIKE, Right: yyS[yypt-0].valExpr}\n\t\t}\n\tcase 100:\n\t\t//line sql.y:586\n\t\t{\n\t\t\tyyVAL.boolExpr = &RangeCond{Left: yyS[yypt-4].valExpr, Operator: AST_BETWEEN, From: yyS[yypt-2].valExpr, To: yyS[yypt-0].valExpr}\n\t\t}\n\tcase 101:\n\t\t//line sql.y:590\n\t\t{\n\t\t\tyyVAL.boolExpr = &RangeCond{Left: yyS[yypt-5].valExpr, Operator: AST_NOT_BETWEEN, From: yyS[yypt-2].valExpr, To: yyS[yypt-0].valExpr}\n\t\t}\n\tcase 102:\n\t\t//line sql.y:594\n\t\t{\n\t\t\tyyVAL.boolExpr = &NullCheck{Operator: AST_IS_NULL, Expr: yyS[yypt-2].valExpr}\n\t\t}\n\tcase 103:\n\t\t//line sql.y:598\n\t\t{\n\t\t\tyyVAL.boolExpr = &NullCheck{Operator: AST_IS_NOT_NULL, Expr: yyS[yypt-3].valExpr}\n\t\t}\n\tcase 104:\n\t\t//line sql.y:602\n\t\t{\n\t\t\tyyVAL.boolExpr = &ExistsExpr{Subquery: yyS[yypt-0].subquery}\n\t\t}\n\tcase 105:\n\t\t//line sql.y:606\n\t\t{\n\t\t\tyyVAL.boolExpr = &KeyrangeExpr{Start: yyS[yypt-3].valExpr, End: yyS[yypt-1].valExpr}\n\t\t}\n\tcase 106:\n\t\t//line sql.y:612\n\t\t{\n\t\t\tyyVAL.str = AST_EQ\n\t\t}\n\tcase 107:\n\t\t//line sql.y:616\n\t\t{\n\t\t\tyyVAL.str = AST_LT\n\t\t}\n\tcase 108:\n\t\t//line sql.y:620\n\t\t{\n\t\t\tyyVAL.str = AST_GT\n\t\t}\n\tcase 109:\n\t\t//line sql.y:624\n\t\t{\n\t\t\tyyVAL.str = AST_LE\n\t\t}\n\tcase 110:\n\t\t//line sql.y:628\n\t\t{\n\t\t\tyyVAL.str = AST_GE\n\t\t}\n\tcase 111:\n\t\t//line sql.y:632\n\t\t{\n\t\t\tyyVAL.str = AST_NE\n\t\t}\n\tcase 112:\n\t\t//line sql.y:636\n\t\t{\n\t\t\tyyVAL.str = AST_NSE\n\t\t}\n\tcase 113:\n\t\t//line sql.y:642\n\t\t{\n\t\t\tyyVAL.colTuple = ValTuple(yyS[yypt-1].valExprs)\n\t\t}\n\tcase 114:\n\t\t//line sql.y:646\n\t\t{\n\t\t\tyyVAL.colTuple = yyS[yypt-0].subquery\n\t\t}\n\tcase 115:\n\t\t//line sql.y:650\n\t\t{\n\t\t\tyyVAL.colTuple = ListArg(yyS[yypt-0].bytes)\n\t\t}\n\tcase 116:\n\t\t//line sql.y:656\n\t\t{\n\t\t\tyyVAL.subquery = &Subquery{yyS[yypt-1].selStmt}\n\t\t}\n\tcase 117:\n\t\t//line sql.y:662\n\t\t{\n\t\t\tyyVAL.valExprs = ValExprs{yyS[yypt-0].valExpr}\n\t\t}\n\tcase 118:\n\t\t//line sql.y:666\n\t\t{\n\t\t\tyyVAL.valExprs = append(yyS[yypt-2].valExprs, yyS[yypt-0].valExpr)\n\t\t}\n\tcase 119:\n\t\t//line sql.y:672\n\t\t{\n\t\t\tyyVAL.valExpr = yyS[yypt-0].valExpr\n\t\t}\n\tcase 120:\n\t\t//line sql.y:676\n\t\t{\n\t\t\tyyVAL.valExpr = yyS[yypt-0].colName\n\t\t}\n\tcase 121:\n\t\t//line sql.y:680\n\t\t{\n\t\t\tyyVAL.valExpr = yyS[yypt-0].rowTuple\n\t\t}\n\tcase 122:\n\t\t//line sql.y:684\n\t\t{\n\t\t\tyyVAL.valExpr = &BinaryExpr{Left: yyS[yypt-2].valExpr, Operator: AST_BITAND, Right: yyS[yypt-0].valExpr}\n\t\t}\n\tcase 123:\n\t\t//line sql.y:688\n\t\t{\n\t\t\tyyVAL.valExpr = &BinaryExpr{Left: yyS[yypt-2].valExpr, Operator: AST_BITOR, Right: yyS[yypt-0].valExpr}\n\t\t}\n\tcase 124:\n\t\t//line sql.y:692\n\t\t{\n\t\t\tyyVAL.valExpr = &BinaryExpr{Left: yyS[yypt-2].valExpr, Operator: AST_BITXOR, Right: yyS[yypt-0].valExpr}\n\t\t}\n\tcase 125:\n\t\t//line sql.y:696\n\t\t{\n\t\t\tyyVAL.valExpr = &BinaryExpr{Left: yyS[yypt-2].valExpr, Operator: AST_PLUS, Right: yyS[yypt-0].valExpr}\n\t\t}\n\tcase 126:\n\t\t//line sql.y:700\n\t\t{\n\t\t\tyyVAL.valExpr = &BinaryExpr{Left: yyS[yypt-2].valExpr, Operator: AST_MINUS, Right: yyS[yypt-0].valExpr}\n\t\t}\n\tcase 127:\n\t\t//line sql.y:704\n\t\t{\n\t\t\tyyVAL.valExpr = &BinaryExpr{Left: yyS[yypt-2].valExpr, Operator: AST_MULT, Right: yyS[yypt-0].valExpr}\n\t\t}\n\tcase 128:\n\t\t//line sql.y:708\n\t\t{\n\t\t\tyyVAL.valExpr = &BinaryExpr{Left: yyS[yypt-2].valExpr, Operator: AST_DIV, Right: yyS[yypt-0].valExpr}\n\t\t}\n\tcase 129:\n\t\t//line sql.y:712\n\t\t{\n\t\t\tyyVAL.valExpr = &BinaryExpr{Left: yyS[yypt-2].valExpr, Operator: AST_MOD, Right: yyS[yypt-0].valExpr}\n\t\t}\n\tcase 130:\n\t\t//line sql.y:716\n\t\t{\n\t\t\tif num, ok := yyS[yypt-0].valExpr.(NumVal); ok {\n\t\t\t\tswitch yyS[yypt-1].byt {\n\t\t\t\tcase '-':\n\t\t\t\t\tyyVAL.valExpr = append(NumVal(\"-\"), num...)\n\t\t\t\tcase '+':\n\t\t\t\t\tyyVAL.valExpr = num\n\t\t\t\tdefault:\n\t\t\t\t\tyyVAL.valExpr = &UnaryExpr{Operator: yyS[yypt-1].byt, Expr: yyS[yypt-0].valExpr}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tyyVAL.valExpr = &UnaryExpr{Operator: yyS[yypt-1].byt, Expr: yyS[yypt-0].valExpr}\n\t\t\t}\n\t\t}\n\tcase 131:\n\t\t//line sql.y:731\n\t\t{\n\t\t\tyyVAL.valExpr = &FuncExpr{Name: yyS[yypt-2].bytes}\n\t\t}\n\tcase 132:\n\t\t//line sql.y:735\n\t\t{\n\t\t\tyyVAL.valExpr = &FuncExpr{Name: yyS[yypt-3].bytes, Exprs: yyS[yypt-1].selectExprs}\n\t\t}\n\tcase 133:\n\t\t//line sql.y:739\n\t\t{\n\t\t\tyyVAL.valExpr = &FuncExpr{Name: yyS[yypt-4].bytes, Distinct: true, Exprs: yyS[yypt-1].selectExprs}\n\t\t}\n\tcase 134:\n\t\t//line sql.y:743\n\t\t{\n\t\t\tyyVAL.valExpr = &FuncExpr{Name: yyS[yypt-3].bytes, Exprs: yyS[yypt-1].selectExprs}\n\t\t}\n\tcase 135:\n\t\t//line sql.y:747\n\t\t{\n\t\t\tyyVAL.valExpr = yyS[yypt-0].caseExpr\n\t\t}\n\tcase 136:\n\t\t//line sql.y:753\n\t\t{\n\t\t\tyyVAL.bytes = IF_BYTES\n\t\t}\n\tcase 137:\n\t\t//line sql.y:757\n\t\t{\n\t\t\tyyVAL.bytes = VALUES_BYTES\n\t\t}\n\tcase 138:\n\t\t//line sql.y:763\n\t\t{\n\t\t\tyyVAL.byt = AST_UPLUS\n\t\t}\n\tcase 139:\n\t\t//line sql.y:767\n\t\t{\n\t\t\tyyVAL.byt = AST_UMINUS\n\t\t}\n\tcase 140:\n\t\t//line sql.y:771\n\t\t{\n\t\t\tyyVAL.byt = AST_TILDA\n\t\t}\n\tcase 141:\n\t\t//line sql.y:777\n\t\t{\n\t\t\tyyVAL.caseExpr = &CaseExpr{Expr: yyS[yypt-3].valExpr, Whens: yyS[yypt-2].whens, Else: yyS[yypt-1].valExpr}\n\t\t}\n\tcase 142:\n\t\t//line sql.y:782\n\t\t{\n\t\t\tyyVAL.valExpr = nil\n\t\t}\n\tcase 143:\n\t\t//line sql.y:786\n\t\t{\n\t\t\tyyVAL.valExpr = yyS[yypt-0].valExpr\n\t\t}\n\tcase 144:\n\t\t//line sql.y:792\n\t\t{\n\t\t\tyyVAL.whens = []*When{yyS[yypt-0].when}\n\t\t}\n\tcase 145:\n\t\t//line sql.y:796\n\t\t{\n\t\t\tyyVAL.whens = append(yyS[yypt-1].whens, yyS[yypt-0].when)\n\t\t}\n\tcase 146:\n\t\t//line sql.y:802\n\t\t{\n\t\t\tyyVAL.when = &When{Cond: yyS[yypt-2].boolExpr, Val: yyS[yypt-0].valExpr}\n\t\t}\n\tcase 147:\n\t\t//line sql.y:807\n\t\t{\n\t\t\tyyVAL.valExpr = nil\n\t\t}\n\tcase 148:\n\t\t//line sql.y:811\n\t\t{\n\t\t\tyyVAL.valExpr = yyS[yypt-0].valExpr\n\t\t}\n\tcase 149:\n\t\t//line sql.y:817\n\t\t{\n\t\t\tyyVAL.colName = &ColName{Name: yyS[yypt-0].bytes}\n\t\t}\n\tcase 150:\n\t\t//line sql.y:821\n\t\t{\n\t\t\tyyVAL.colName = &ColName{Qualifier: yyS[yypt-2].bytes, Name: yyS[yypt-0].bytes}\n\t\t}\n\tcase 151:\n\t\t//line sql.y:827\n\t\t{\n\t\t\tyyVAL.valExpr = StrVal(yyS[yypt-0].bytes)\n\t\t}\n\tcase 152:\n\t\t//line sql.y:831\n\t\t{\n\t\t\tyyVAL.valExpr = NumVal(yyS[yypt-0].bytes)\n\t\t}\n\tcase 153:\n\t\t//line sql.y:835\n\t\t{\n\t\t\tyyVAL.valExpr = ValArg(yyS[yypt-0].bytes)\n\t\t}\n\tcase 154:\n\t\t//line sql.y:839\n\t\t{\n\t\t\tyyVAL.valExpr = &NullVal{}\n\t\t}\n\tcase 155:\n\t\t//line sql.y:844\n\t\t{\n\t\t\tyyVAL.valExprs = nil\n\t\t}\n\tcase 156:\n\t\t//line sql.y:848\n\t\t{\n\t\t\tyyVAL.valExprs = yyS[yypt-0].valExprs\n\t\t}\n\tcase 157:\n\t\t//line sql.y:853\n\t\t{\n\t\t\tyyVAL.boolExpr = nil\n\t\t}\n\tcase 158:\n\t\t//line sql.y:857\n\t\t{\n\t\t\tyyVAL.boolExpr = yyS[yypt-0].boolExpr\n\t\t}\n\tcase 159:\n\t\t//line sql.y:862\n\t\t{\n\t\t\tyyVAL.orderBy = nil\n\t\t}\n\tcase 160:\n\t\t//line sql.y:866\n\t\t{\n\t\t\tyyVAL.orderBy = yyS[yypt-0].orderBy\n\t\t}\n\tcase 161:\n\t\t//line sql.y:872\n\t\t{\n\t\t\tyyVAL.orderBy = OrderBy{yyS[yypt-0].order}\n\t\t}\n\tcase 162:\n\t\t//line sql.y:876\n\t\t{\n\t\t\tyyVAL.orderBy = append(yyS[yypt-2].orderBy, yyS[yypt-0].order)\n\t\t}\n\tcase 163:\n\t\t//line sql.y:882\n\t\t{\n\t\t\tyyVAL.order = &Order{Expr: yyS[yypt-1].valExpr, Direction: yyS[yypt-0].str}\n\t\t}\n\tcase 164:\n\t\t//line sql.y:887\n\t\t{\n\t\t\tyyVAL.str = AST_ASC\n\t\t}\n\tcase 165:\n\t\t//line sql.y:891\n\t\t{\n\t\t\tyyVAL.str = AST_ASC\n\t\t}\n\tcase 166:\n\t\t//line sql.y:895\n\t\t{\n\t\t\tyyVAL.str = AST_DESC\n\t\t}\n\tcase 167:\n\t\t//line sql.y:900\n\t\t{\n\t\t\tyyVAL.limit = nil\n\t\t}\n\tcase 168:\n\t\t//line sql.y:904\n\t\t{\n\t\t\tyyVAL.limit = &Limit{Rowcount: yyS[yypt-0].valExpr}\n\t\t}\n\tcase 169:\n\t\t//line sql.y:908\n\t\t{\n\t\t\tyyVAL.limit = &Limit{Offset: yyS[yypt-2].valExpr, Rowcount: yyS[yypt-0].valExpr}\n\t\t}\n\tcase 170:\n\t\t//line sql.y:913\n\t\t{\n\t\t\tyyVAL.str = \"\"\n\t\t}\n\tcase 171:\n\t\t//line sql.y:917\n\t\t{\n\t\t\tyyVAL.str = AST_FOR_UPDATE\n\t\t}\n\tcase 172:\n\t\t//line sql.y:921\n\t\t{\n\t\t\tif !bytes.Equal(yyS[yypt-1].bytes, SHARE) {\n\t\t\t\tyylex.Error(\"expecting share\")\n\t\t\t\treturn 1\n\t\t\t}\n\t\t\tif !bytes.Equal(yyS[yypt-0].bytes, MODE) {\n\t\t\t\tyylex.Error(\"expecting mode\")\n\t\t\t\treturn 1\n\t\t\t}\n\t\t\tyyVAL.str = AST_SHARE_MODE\n\t\t}\n\tcase 173:\n\t\t//line sql.y:934\n\t\t{\n\t\t\tyyVAL.columns = nil\n\t\t}\n\tcase 174:\n\t\t//line sql.y:938\n\t\t{\n\t\t\tyyVAL.columns = yyS[yypt-1].columns\n\t\t}\n\tcase 175:\n\t\t//line sql.y:944\n\t\t{\n\t\t\tyyVAL.columns = Columns{&NonStarExpr{Expr: yyS[yypt-0].colName}}\n\t\t}\n\tcase 176:\n\t\t//line sql.y:948\n\t\t{\n\t\t\tyyVAL.columns = append(yyVAL.columns, &NonStarExpr{Expr: yyS[yypt-0].colName})\n\t\t}\n\tcase 177:\n\t\t//line sql.y:953\n\t\t{\n\t\t\tyyVAL.updateExprs = nil\n\t\t}\n\tcase 178:\n\t\t//line sql.y:957\n\t\t{\n\t\t\tyyVAL.updateExprs = yyS[yypt-0].updateExprs\n\t\t}\n\tcase 179:\n\t\t//line sql.y:963\n\t\t{\n\t\t\tyyVAL.insRows = yyS[yypt-0].values\n\t\t}\n\tcase 180:\n\t\t//line sql.y:967\n\t\t{\n\t\t\tyyVAL.insRows = yyS[yypt-0].selStmt\n\t\t}\n\tcase 181:\n\t\t//line sql.y:973\n\t\t{\n\t\t\tyyVAL.values = Values{yyS[yypt-0].rowTuple}\n\t\t}\n\tcase 182:\n\t\t//line sql.y:977\n\t\t{\n\t\t\tyyVAL.values = append(yyS[yypt-2].values, yyS[yypt-0].rowTuple)\n\t\t}\n\tcase 183:\n\t\t//line sql.y:983\n\t\t{\n\t\t\tyyVAL.rowTuple = ValTuple(yyS[yypt-1].valExprs)\n\t\t}\n\tcase 184:\n\t\t//line sql.y:987\n\t\t{\n\t\t\tyyVAL.rowTuple = yyS[yypt-0].subquery\n\t\t}\n\tcase 185:\n\t\t//line sql.y:993\n\t\t{\n\t\t\tyyVAL.updateExprs = UpdateExprs{yyS[yypt-0].updateExpr}\n\t\t}\n\tcase 186:\n\t\t//line sql.y:997\n\t\t{\n\t\t\tyyVAL.updateExprs = append(yyS[yypt-2].updateExprs, yyS[yypt-0].updateExpr)\n\t\t}\n\tcase 187:\n\t\t//line sql.y:1003\n\t\t{\n\t\t\tyyVAL.updateExpr = &UpdateExpr{Name: yyS[yypt-2].colName, Expr: yyS[yypt-0].valExpr}\n\t\t}\n\tcase 188:\n\t\t//line sql.y:1008\n\t\t{\n\t\t\tyyVAL.empty = struct{}{}\n\t\t}\n\tcase 189:\n\t\t//line sql.y:1010\n\t\t{\n\t\t\tyyVAL.empty = struct{}{}\n\t\t}\n\tcase 190:\n\t\t//line sql.y:1013\n\t\t{\n\t\t\tyyVAL.empty = struct{}{}\n\t\t}\n\tcase 191:\n\t\t//line sql.y:1015\n\t\t{\n\t\t\tyyVAL.empty = struct{}{}\n\t\t}\n\tcase 192:\n\t\t//line sql.y:1018\n\t\t{\n\t\t\tyyVAL.empty = struct{}{}\n\t\t}\n\tcase 193:\n\t\t//line sql.y:1020\n\t\t{\n\t\t\tyyVAL.empty = struct{}{}\n\t\t}\n\tcase 194:\n\t\t//line sql.y:1024\n\t\t{\n\t\t\tyyVAL.empty = struct{}{}\n\t\t}\n\tcase 195:\n\t\t//line sql.y:1026\n\t\t{\n\t\t\tyyVAL.empty = struct{}{}\n\t\t}\n\tcase 196:\n\t\t//line sql.y:1028\n\t\t{\n\t\t\tyyVAL.empty = struct{}{}\n\t\t}\n\tcase 197:\n\t\t//line sql.y:1030\n\t\t{\n\t\t\tyyVAL.empty = struct{}{}\n\t\t}\n\tcase 198:\n\t\t//line sql.y:1032\n\t\t{\n\t\t\tyyVAL.empty = struct{}{}\n\t\t}\n\tcase 199:\n\t\t//line sql.y:1035\n\t\t{\n\t\t\tyyVAL.empty = struct{}{}\n\t\t}\n\tcase 200:\n\t\t//line sql.y:1037\n\t\t{\n\t\t\tyyVAL.empty = struct{}{}\n\t\t}\n\tcase 201:\n\t\t//line sql.y:1040\n\t\t{\n\t\t\tyyVAL.empty = struct{}{}\n\t\t}\n\tcase 202:\n\t\t//line sql.y:1042\n\t\t{\n\t\t\tyyVAL.empty = struct{}{}\n\t\t}\n\tcase 203:\n\t\t//line sql.y:1045\n\t\t{\n\t\t\tyyVAL.empty = struct{}{}\n\t\t}\n\tcase 204:\n\t\t//line sql.y:1047\n\t\t{\n\t\t\tyyVAL.empty = struct{}{}\n\t\t}\n\tcase 205:\n\t\t//line sql.y:1051\n\t\t{\n\t\t\tyyVAL.bytes = yyS[yypt-0].bytes\n\t\t}\n\tcase 206:\n\t\t//line sql.y:1056\n\t\t{\n\t\t\tForceEOF(yylex)\n\t\t}\n\t}\n\tgoto yystack /* stack new state and value */\n}\n"
  },
  {
    "path": "sqlparser/sql.y",
    "content": "// Copyright 2012, Google Inc. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n%{\npackage sqlparser\n\nimport \"bytes\"\n\nfunc SetParseTree(yylex interface{}, stmt Statement) {\n  yylex.(*Tokenizer).ParseTree = stmt\n}\n\nfunc SetAllowComments(yylex interface{}, allow bool) {\n  yylex.(*Tokenizer).AllowComments = allow\n}\n\nfunc ForceEOF(yylex interface{}) {\n  yylex.(*Tokenizer).ForceEOF = true\n}\n\nvar (\n  SHARE =        []byte(\"share\")\n  MODE  =        []byte(\"mode\")\n  IF_BYTES =     []byte(\"if\")\n  VALUES_BYTES = []byte(\"values\")\n)\n\n%}\n\n%union {\n  empty       struct{}\n  statement   Statement\n  selStmt     SelectStatement\n  byt         byte\n  bytes       []byte\n  bytes2      [][]byte\n  str         string\n  selectExprs SelectExprs\n  selectExpr  SelectExpr\n  columns     Columns\n  colName     *ColName\n  tableExprs  TableExprs\n  tableExpr   TableExpr\n  smTableExpr SimpleTableExpr\n  tableName   *TableName\n  indexHints  *IndexHints\n  expr        Expr\n  boolExpr    BoolExpr\n  valExpr     ValExpr\n  colTuple    ColTuple\n  valExprs    ValExprs\n  values      Values\n  rowTuple    RowTuple\n  subquery    *Subquery\n  caseExpr    *CaseExpr\n  whens       []*When\n  when        *When\n  orderBy     OrderBy\n  order       *Order\n  limit       *Limit\n  insRows     InsertRows\n  updateExprs UpdateExprs\n  updateExpr  *UpdateExpr\n}\n\n%token LEX_ERROR\n%token <empty> SELECT INSERT UPDATE DELETE FROM WHERE GROUP HAVING ORDER BY LIMIT FOR\n%token <empty> ALL DISTINCT AS EXISTS IN IS LIKE BETWEEN NULL ASC DESC VALUES INTO DUPLICATE KEY DEFAULT SET LOCK KEYRANGE\n%token <bytes> ID STRING NUMBER VALUE_ARG LIST_ARG COMMENT\n%token <empty> LE GE NE NULL_SAFE_EQUAL\n%token <empty> '(' '=' '<' '>' '~'\n\n%left <empty> UNION MINUS EXCEPT INTERSECT\n%left <empty> ','\n%left <empty> JOIN STRAIGHT_JOIN LEFT RIGHT INNER OUTER CROSS NATURAL USE FORCE\n%left <empty> ON\n%left <empty> OR\n%left <empty> AND\n%right <empty> NOT\n%left <empty> '&' '|' '^'\n%left <empty> '+' '-'\n%left <empty> '*' '/' '%'\n%nonassoc <empty> '.'\n%left <empty> UNARY\n%right <empty> CASE, WHEN, THEN, ELSE\n%left <empty> END\n\n// DDL Tokens\n%token <empty> CREATE ALTER DROP RENAME ANALYZE\n%token <empty> TABLE INDEX VIEW TO IGNORE IF UNIQUE USING\n%token <empty> SHOW DESCRIBE EXPLAIN\n\n%start any_command\n\n%type <statement> command\n%type <selStmt> select_statement\n%type <selStmt> missing_select_statement\n%type <statement> insert_statement update_statement delete_statement set_statement\n%type <statement> create_statement alter_statement rename_statement drop_statement\n%type <statement> analyze_statement other_statement\n%type <bytes2> comment_opt comment_list\n%type <str> union_op\n%type <str> distinct_opt\n%type <selectExprs> select_expression_list\n%type <selectExpr> select_expression\n%type <bytes> as_lower_opt as_opt\n%type <expr> expression\n%type <tableExprs> table_expression_list\n%type <tableExpr> table_expression\n%type <tableExprs> from_expression_list_opt\n%type <str> join_type\n%type <smTableExpr> simple_table_expression\n%type <tableName> dml_table_expression\n%type <indexHints> index_hint_list\n%type <bytes2> index_list\n%type <boolExpr> where_expression_opt\n%type <boolExpr> boolean_expression condition\n%type <str> compare\n%type <insRows> row_list\n%type <valExpr> value value_expression\n%type <colTuple> col_tuple\n%type <valExprs> value_expression_list\n%type <values> tuple_list\n%type <rowTuple> row_tuple\n%type <bytes> keyword_as_func\n%type <subquery> subquery\n%type <byt> unary_operator\n%type <colName> column_name\n%type <caseExpr> case_expression\n%type <whens> when_expression_list\n%type <when> when_expression\n%type <valExpr> value_expression_opt else_expression_opt\n%type <valExprs> group_by_opt\n%type <boolExpr> having_opt\n%type <orderBy> order_by_opt order_list\n%type <order> order\n%type <str> asc_desc_opt\n%type <limit> limit_opt\n%type <str> lock_opt\n%type <columns> column_list_opt column_list\n%type <updateExprs> on_dup_opt\n%type <updateExprs> update_list\n%type <updateExpr> update_expression\n%type <empty> exists_opt not_exists_opt ignore_opt non_rename_operation to_opt constraint_opt using_opt\n%type <bytes> sql_id\n%type <empty> force_eof\n\n\n%%\n\nany_command:\n  command\n  {\n    SetParseTree(yylex, $1)\n  }\n\ncommand:\n  select_statement\n  {\n    $$ = $1\n  }\n| missing_select_statement\n  {\n    $$ = $1\n  }\n| insert_statement\n| update_statement\n| delete_statement\n| set_statement\n| create_statement\n| alter_statement\n| rename_statement\n| drop_statement\n| analyze_statement\n| other_statement\n\nmissing_select_statement:\n  distinct_opt select_expression_list from_expression_list_opt where_expression_opt group_by_opt having_opt order_by_opt limit_opt lock_opt\n  {\n    $$ = &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}\n  }\n\nselect_statement:\n  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\n  {\n    $$ = &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}\n  }\n| select_statement union_op select_statement %prec UNION\n  {\n    $$ = &Union{Type: $2, Left: $1, Right: $3}\n  }\n\ninsert_statement:\n  INSERT comment_opt INTO dml_table_expression column_list_opt row_list on_dup_opt\n  {\n    $$ = &Insert{Comments: Comments($2), Table: $4, Columns: $5, Rows: $6, OnDup: OnDup($7)}\n  }\n| INSERT comment_opt INTO dml_table_expression SET update_list on_dup_opt\n  {\n    cols := make(Columns, 0, len($6))\n    vals := make(ValTuple, 0, len($6))\n    for _, col := range $6 {\n      cols = append(cols, &NonStarExpr{Expr: col.Name})\n      vals = append(vals, col.Expr)\n    }\n    $$ = &Insert{Comments: Comments($2), Table: $4, Columns: cols, Rows: Values{vals}, OnDup: OnDup($7)}\n  }\n\nupdate_statement:\n  UPDATE comment_opt dml_table_expression SET update_list where_expression_opt order_by_opt limit_opt\n  {\n    $$ = &Update{Comments: Comments($2), Table: $3, Exprs: $5, Where: NewWhere(AST_WHERE, $6), OrderBy: $7, Limit: $8}\n  }\n\ndelete_statement:\n  DELETE comment_opt FROM dml_table_expression where_expression_opt order_by_opt limit_opt\n  {\n    $$ = &Delete{Comments: Comments($2), Table: $4, Where: NewWhere(AST_WHERE, $5), OrderBy: $6, Limit: $7}\n  }\n\nset_statement:\n  SET comment_opt update_list\n  {\n    $$ = &Set{Comments: Comments($2), Exprs: $3}\n  }\n\ncreate_statement:\n  CREATE TABLE not_exists_opt ID force_eof\n  {\n    $$ = &DDL{Action: AST_CREATE, NewName: $4}\n  }\n| CREATE constraint_opt INDEX sql_id using_opt ON ID force_eof\n  {\n    // Change this to an alter statement\n    $$ = &DDL{Action: AST_ALTER, Table: $7, NewName: $7}\n  }\n| CREATE VIEW sql_id force_eof\n  {\n    $$ = &DDL{Action: AST_CREATE, NewName: $3}\n  }\n\nalter_statement:\n  ALTER ignore_opt TABLE ID non_rename_operation force_eof\n  {\n    $$ = &DDL{Action: AST_ALTER, Table: $4, NewName: $4}\n  }\n| ALTER ignore_opt TABLE ID RENAME to_opt ID\n  {\n    // Change this to a rename statement\n    $$ = &DDL{Action: AST_RENAME, Table: $4, NewName: $7}\n  }\n| ALTER VIEW sql_id force_eof\n  {\n    $$ = &DDL{Action: AST_ALTER, Table: $3, NewName: $3}\n  }\n\nrename_statement:\n  RENAME TABLE ID TO ID\n  {\n    $$ = &DDL{Action: AST_RENAME, Table: $3, NewName: $5}\n  }\n\ndrop_statement:\n  DROP TABLE exists_opt ID\n  {\n    $$ = &DDL{Action: AST_DROP, Table: $4}\n  }\n| DROP INDEX sql_id ON ID\n  {\n    // Change this to an alter statement\n    $$ = &DDL{Action: AST_ALTER, Table: $5, NewName: $5}\n  }\n| DROP VIEW exists_opt sql_id force_eof\n  {\n    $$ = &DDL{Action: AST_DROP, Table: $4}\n  }\n\nanalyze_statement:\n  ANALYZE TABLE ID\n  {\n    $$ = &DDL{Action: AST_ALTER, Table: $3, NewName: $3}\n  }\n\nother_statement:\n  SHOW force_eof\n  {\n    $$ = &Other{}\n  }\n| DESCRIBE force_eof\n  {\n    $$ = &Other{}\n  }\n| EXPLAIN force_eof\n  {\n    $$ = &Other{}\n  }\n\ncomment_opt:\n  {\n    SetAllowComments(yylex, true)\n  }\n  comment_list\n  {\n    $$ = $2\n    SetAllowComments(yylex, false)\n  }\n\ncomment_list:\n  {\n    $$ = nil\n  }\n| comment_list COMMENT\n  {\n    $$ = append($1, $2)\n  }\n\nunion_op:\n  UNION\n  {\n    $$ = AST_UNION\n  }\n| UNION ALL\n  {\n    $$ = AST_UNION_ALL\n  }\n| MINUS\n  {\n    $$ = AST_SET_MINUS\n  }\n| EXCEPT\n  {\n    $$ = AST_EXCEPT\n  }\n| INTERSECT\n  {\n    $$ = AST_INTERSECT\n  }\n\ndistinct_opt:\n  {\n    $$ = \"\"\n  }\n| DISTINCT\n  {\n    $$ = AST_DISTINCT\n  }\n\nselect_expression_list:\n  select_expression\n  {\n    $$ = SelectExprs{$1}\n  }\n| select_expression_list ',' select_expression\n  {\n    $$ = append($$, $3)\n  }\n\nselect_expression:\n  '*'\n  {\n    $$ = &StarExpr{}\n  }\n| expression as_lower_opt\n  {\n    $$ = &NonStarExpr{Expr: $1, As: $2}\n  }\n| ID '.' '*'\n  {\n    $$ = &StarExpr{TableName: $1}\n  }\n\nexpression:\n  boolean_expression\n  {\n    $$ = $1\n  }\n| value_expression\n  {\n    $$ = $1\n  }\n\nas_lower_opt:\n  {\n    $$ = nil\n  }\n| sql_id\n  {\n    $$ = $1\n  }\n| AS sql_id\n  {\n    $$ = $2\n  }\n\ntable_expression_list:\n  table_expression\n  {\n    $$ = TableExprs{$1}\n  }\n| table_expression_list ',' table_expression\n  {\n    $$ = append($$, $3)\n  }\n\ntable_expression:\n  simple_table_expression as_opt index_hint_list\n  {\n    $$ = &AliasedTableExpr{Expr:$1, As: $2, Hints: $3}\n  }\n| '(' table_expression ')'\n  {\n    $$ = &ParenTableExpr{Expr: $2}\n  }\n| table_expression join_type table_expression %prec JOIN\n  {\n    $$ = &JoinTableExpr{LeftExpr: $1, Join: $2, RightExpr: $3}\n  }\n| table_expression join_type table_expression ON boolean_expression %prec JOIN\n  {\n    $$ = &JoinTableExpr{LeftExpr: $1, Join: $2, RightExpr: $3, On: $5}\n  }\n\nas_opt:\n  {\n    $$ = nil\n  }\n| ID\n  {\n    $$ = $1\n  }\n| AS ID\n  {\n    $$ = $2\n  }\n\njoin_type:\n  JOIN\n  {\n    $$ = AST_JOIN\n  }\n| STRAIGHT_JOIN\n  {\n    $$ = AST_STRAIGHT_JOIN\n  }\n| LEFT JOIN\n  {\n    $$ = AST_LEFT_JOIN\n  }\n| LEFT OUTER JOIN\n  {\n    $$ = AST_LEFT_JOIN\n  }\n| RIGHT JOIN\n  {\n    $$ = AST_RIGHT_JOIN\n  }\n| RIGHT OUTER JOIN\n  {\n    $$ = AST_RIGHT_JOIN\n  }\n| INNER JOIN\n  {\n    $$ = AST_JOIN\n  }\n| CROSS JOIN\n  {\n    $$ = AST_CROSS_JOIN\n  }\n| NATURAL JOIN\n  {\n    $$ = AST_NATURAL_JOIN\n  }\n\nsimple_table_expression:\nID\n  {\n    $$ = &TableName{Name: $1}\n  }\n| ID '.' ID\n  {\n    $$ = &TableName{Qualifier: $1, Name: $3}\n  }\n| subquery\n  {\n    $$ = $1\n  }\n\ndml_table_expression:\nID\n  {\n    $$ = &TableName{Name: $1}\n  }\n| ID '.' ID\n  {\n    $$ = &TableName{Qualifier: $1, Name: $3}\n  }\n\nindex_hint_list:\n  {\n    $$ = nil\n  }\n| USE INDEX '(' index_list ')'\n  {\n    $$ = &IndexHints{Type: AST_USE, Indexes: $4}\n  }\n| IGNORE INDEX '(' index_list ')'\n  {\n    $$ = &IndexHints{Type: AST_IGNORE, Indexes: $4}\n  }\n| FORCE INDEX '(' index_list ')'\n  {\n    $$ = &IndexHints{Type: AST_FORCE, Indexes: $4}\n  }\n\nindex_list:\n  sql_id\n  {\n    $$ = [][]byte{$1}\n  }\n| index_list ',' sql_id\n  {\n    $$ = append($1, $3)\n  }\n\nfrom_expression_list_opt:\n  {\n    $$ = nil\n  }\n| FROM table_expression_list\n  {\n    $$ = $2\n  }\n\n\nwhere_expression_opt:\n  {\n    $$ = nil\n  }\n| WHERE boolean_expression\n  {\n    $$ = $2\n  }\n\nboolean_expression:\n  condition\n| boolean_expression AND boolean_expression\n  {\n    $$ = &AndExpr{Left: $1, Right: $3}\n  }\n| boolean_expression OR boolean_expression\n  {\n    $$ = &OrExpr{Left: $1, Right: $3}\n  }\n| NOT boolean_expression\n  {\n    $$ = &NotExpr{Expr: $2}\n  }\n| '(' boolean_expression ')'\n  {\n    $$ = &ParenBoolExpr{Expr: $2}\n  }\n\ncondition:\n  value_expression compare value_expression\n  {\n    $$ = &ComparisonExpr{Left: $1, Operator: $2, Right: $3}\n  }\n| value_expression IN col_tuple\n  {\n    $$ = &ComparisonExpr{Left: $1, Operator: AST_IN, Right: $3}\n  }\n| value_expression NOT IN col_tuple\n  {\n    $$ = &ComparisonExpr{Left: $1, Operator: AST_NOT_IN, Right: $4}\n  }\n| value_expression LIKE value_expression\n  {\n    $$ = &ComparisonExpr{Left: $1, Operator: AST_LIKE, Right: $3}\n  }\n| value_expression NOT LIKE value_expression\n  {\n    $$ = &ComparisonExpr{Left: $1, Operator: AST_NOT_LIKE, Right: $4}\n  }\n| value_expression BETWEEN value_expression AND value_expression\n  {\n    $$ = &RangeCond{Left: $1, Operator: AST_BETWEEN, From: $3, To: $5}\n  }\n| value_expression NOT BETWEEN value_expression AND value_expression\n  {\n    $$ = &RangeCond{Left: $1, Operator: AST_NOT_BETWEEN, From: $4, To: $6}\n  }\n| value_expression IS NULL\n  {\n    $$ = &NullCheck{Operator: AST_IS_NULL, Expr: $1}\n  }\n| value_expression IS NOT NULL\n  {\n    $$ = &NullCheck{Operator: AST_IS_NOT_NULL, Expr: $1}\n  }\n| EXISTS subquery\n  {\n    $$ = &ExistsExpr{Subquery: $2}\n  }\n| KEYRANGE '(' value ',' value ')'\n  {\n    $$ = &KeyrangeExpr{Start: $3, End: $5}\n  }\n\ncompare:\n  '='\n  {\n    $$ = AST_EQ\n  }\n| '<'\n  {\n    $$ = AST_LT\n  }\n| '>'\n  {\n    $$ = AST_GT\n  }\n| LE\n  {\n    $$ = AST_LE\n  }\n| GE\n  {\n    $$ = AST_GE\n  }\n| NE\n  {\n    $$ = AST_NE\n  }\n| NULL_SAFE_EQUAL\n  {\n    $$ = AST_NSE\n  }\n\ncol_tuple:\n  '(' value_expression_list ')'\n  {\n    $$ = ValTuple($2)\n  }\n| subquery\n  {\n    $$ = $1\n  }\n| LIST_ARG\n  {\n    $$ = ListArg($1)\n  }\n\nsubquery:\n  '(' select_statement ')'\n  {\n    $$ = &Subquery{$2}\n  }\n\nvalue_expression_list:\n  value_expression\n  {\n    $$ = ValExprs{$1}\n  }\n| value_expression_list ',' value_expression\n  {\n    $$ = append($1, $3)\n  }\n\nvalue_expression:\n  value\n  {\n    $$ = $1\n  }\n| column_name\n  {\n    $$ = $1\n  }\n| row_tuple\n  {\n    $$ = $1\n  }\n| value_expression '&' value_expression\n  {\n    $$ = &BinaryExpr{Left: $1, Operator: AST_BITAND, Right: $3}\n  }\n| value_expression '|' value_expression\n  {\n    $$ = &BinaryExpr{Left: $1, Operator: AST_BITOR, Right: $3}\n  }\n| value_expression '^' value_expression\n  {\n    $$ = &BinaryExpr{Left: $1, Operator: AST_BITXOR, Right: $3}\n  }\n| value_expression '+' value_expression\n  {\n    $$ = &BinaryExpr{Left: $1, Operator: AST_PLUS, Right: $3}\n  }\n| value_expression '-' value_expression\n  {\n    $$ = &BinaryExpr{Left: $1, Operator: AST_MINUS, Right: $3}\n  }\n| value_expression '*' value_expression\n  {\n    $$ = &BinaryExpr{Left: $1, Operator: AST_MULT, Right: $3}\n  }\n| value_expression '/' value_expression\n  {\n    $$ = &BinaryExpr{Left: $1, Operator: AST_DIV, Right: $3}\n  }\n| value_expression '%' value_expression\n  {\n    $$ = &BinaryExpr{Left: $1, Operator: AST_MOD, Right: $3}\n  }\n| unary_operator value_expression %prec UNARY\n  {\n    if num, ok := $2.(NumVal); ok {\n      switch $1 {\n      case '-':\n        $$ = append(NumVal(\"-\"), num...)\n      case '+':\n        $$ = num\n      default:\n        $$ = &UnaryExpr{Operator: $1, Expr: $2}\n      }\n    } else {\n      $$ = &UnaryExpr{Operator: $1, Expr: $2}\n    }\n  }\n| sql_id '(' ')'\n  {\n    $$ = &FuncExpr{Name: $1}\n  }\n| sql_id '(' select_expression_list ')'\n  {\n    $$ = &FuncExpr{Name: $1, Exprs: $3}\n  }\n| sql_id '(' DISTINCT select_expression_list ')'\n  {\n    $$ = &FuncExpr{Name: $1, Distinct: true, Exprs: $4}\n  }\n| keyword_as_func '(' select_expression_list ')'\n  {\n    $$ = &FuncExpr{Name: $1, Exprs: $3}\n  }\n| case_expression\n  {\n    $$ = $1\n  }\n\nkeyword_as_func:\n  IF\n  {\n    $$ = IF_BYTES\n  }\n| VALUES\n  {\n    $$ = VALUES_BYTES\n  }\n\nunary_operator:\n  '+'\n  {\n    $$ = AST_UPLUS\n  }\n| '-'\n  {\n    $$ = AST_UMINUS\n  }\n| '~'\n  {\n    $$ = AST_TILDA\n  }\n\ncase_expression:\n  CASE value_expression_opt when_expression_list else_expression_opt END\n  {\n    $$ = &CaseExpr{Expr: $2, Whens: $3, Else: $4}\n  }\n\nvalue_expression_opt:\n  {\n    $$ = nil\n  }\n| value_expression\n  {\n    $$ = $1\n  }\n\nwhen_expression_list:\n  when_expression\n  {\n    $$ = []*When{$1}\n  }\n| when_expression_list when_expression\n  {\n    $$ = append($1, $2)\n  }\n\nwhen_expression:\n  WHEN boolean_expression THEN value_expression\n  {\n    $$ = &When{Cond: $2, Val: $4}\n  }\n\nelse_expression_opt:\n  {\n    $$ = nil\n  }\n| ELSE value_expression\n  {\n    $$ = $2\n  }\n\ncolumn_name:\n  sql_id\n  {\n    $$ = &ColName{Name: $1}\n  }\n| ID '.' sql_id\n  {\n    $$ = &ColName{Qualifier: $1, Name: $3}\n  }\n\nvalue:\n  STRING\n  {\n    $$ = StrVal($1)\n  }\n| NUMBER\n  {\n    $$ = NumVal($1)\n  }\n| VALUE_ARG\n  {\n    $$ = ValArg($1)\n  }\n| NULL\n  {\n    $$ = &NullVal{}\n  }\n\ngroup_by_opt:\n  {\n    $$ = nil\n  }\n| GROUP BY value_expression_list\n  {\n    $$ = $3\n  }\n\nhaving_opt:\n  {\n    $$ = nil\n  }\n| HAVING boolean_expression\n  {\n    $$ = $2\n  }\n\norder_by_opt:\n  {\n    $$ = nil\n  }\n| ORDER BY order_list\n  {\n    $$ = $3\n  }\n\norder_list:\n  order\n  {\n    $$ = OrderBy{$1}\n  }\n| order_list ',' order\n  {\n    $$ = append($1, $3)\n  }\n\norder:\n  value_expression asc_desc_opt\n  {\n    $$ = &Order{Expr: $1, Direction: $2}\n  }\n\nasc_desc_opt:\n  {\n    $$ = AST_ASC\n  }\n| ASC\n  {\n    $$ = AST_ASC\n  }\n| DESC\n  {\n    $$ = AST_DESC\n  }\n\nlimit_opt:\n  {\n    $$ = nil\n  }\n| LIMIT value_expression\n  {\n    $$ = &Limit{Rowcount: $2}\n  }\n| LIMIT value_expression ',' value_expression\n  {\n    $$ = &Limit{Offset: $2, Rowcount: $4}\n  }\n\nlock_opt:\n  {\n    $$ = \"\"\n  }\n| FOR UPDATE\n  {\n    $$ = AST_FOR_UPDATE\n  }\n| LOCK IN sql_id sql_id\n  {\n    if !bytes.Equal($3, SHARE) {\n      yylex.Error(\"expecting share\")\n      return 1\n    }\n    if !bytes.Equal($4, MODE) {\n      yylex.Error(\"expecting mode\")\n      return 1\n    }\n    $$ = AST_SHARE_MODE\n  }\n\ncolumn_list_opt:\n  {\n    $$ = nil\n  }\n| '(' column_list ')'\n  {\n    $$ = $2\n  }\n\ncolumn_list:\n  column_name\n  {\n    $$ = Columns{&NonStarExpr{Expr: $1}}\n  }\n| column_list ',' column_name\n  {\n    $$ = append($$, &NonStarExpr{Expr: $3})\n  }\n\non_dup_opt:\n  {\n    $$ = nil\n  }\n| ON DUPLICATE KEY UPDATE update_list\n  {\n    $$ = $5\n  }\n\nrow_list:\n  VALUES tuple_list\n  {\n    $$ = $2\n  }\n| select_statement\n  {\n    $$ = $1\n  }\n\ntuple_list:\n  row_tuple\n  {\n    $$ = Values{$1}\n  }\n| tuple_list ',' row_tuple\n  {\n    $$ = append($1, $3)\n  }\n\nrow_tuple:\n  '(' value_expression_list ')'\n  {\n    $$ = ValTuple($2)\n  }\n| subquery\n  {\n    $$ = $1\n  }\n\nupdate_list:\n  update_expression\n  {\n    $$ = UpdateExprs{$1}\n  }\n| update_list ',' update_expression\n  {\n    $$ = append($1, $3)\n  }\n\nupdate_expression:\n  column_name '=' value_expression\n  {\n    $$ = &UpdateExpr{Name: $1, Expr: $3} \n  }\n\nexists_opt:\n  { $$ = struct{}{} }\n| IF EXISTS\n  { $$ = struct{}{} }\n\nnot_exists_opt:\n  { $$ = struct{}{} }\n| IF NOT EXISTS\n  { $$ = struct{}{} }\n\nignore_opt:\n  { $$ = struct{}{} }\n| IGNORE\n  { $$ = struct{}{} }\n\nnon_rename_operation:\n  ALTER\n  { $$ = struct{}{} }\n| DEFAULT\n  { $$ = struct{}{} }\n| DROP\n  { $$ = struct{}{} }\n| ORDER\n  { $$ = struct{}{} }\n| ID\n  { $$ = struct{}{} }\n\nto_opt:\n  { $$ = struct{}{} }\n| TO\n  { $$ = struct{}{} }\n\nconstraint_opt:\n  { $$ = struct{}{} }\n| UNIQUE\n  { $$ = struct{}{} }\n\nusing_opt:\n  { $$ = struct{}{} }\n| USING sql_id\n  { $$ = struct{}{} }\n\nsql_id:\n  ID\n  {\n    $$ = $1\n  }\n\nforce_eof:\n{\n  ForceEOF(yylex)\n}\n"
  },
  {
    "path": "sqlparser/sql_mod.go",
    "content": "package sqlparser\n\n// Magicify runs the SQL passed in, and a table name, throught a customized\n// TextQL SQL Parser. This provides the following functionality:\n//  - Queries that do not start with SELECT are implictly mapped to SELECT statements\n//  - Queries that are missing a FROM, have the FROM inserted with tableName\nfunc Magicify(sql string, tableName string) string {\n\tif tableName == \"\" {\n\t\treturn sql\n\t}\n\n\tstatement, err := Parse(sql)\n\n\tif err != nil {\n\t\treturn sql\n\t}\n\n\tswitch statement := statement.(type) {\n\tcase *Select:\n\t\treplaceFromInSelect(statement, tableName)\n\t\treturn generateQuery(statement)\n\tdefault:\n\t\treturn sql\n\t}\n}\n\nfunc replaceFromInSelect(statement *Select, tableName string) {\n\tif statement.From == nil {\n\t\ttableName := &TableName{[]byte(\"[\" + tableName + \"]\"), nil}\n\t\taliasedTableExpr := AliasedTableExpr{tableName, nil, nil}\n\t\ttableExprs := TableExprs{&aliasedTableExpr}\n\t\tstatement.From = &From{Type: AST_FROM, Expr: tableExprs}\n\t} else {\n\t\tfor _, expr := range statement.From.Expr {\n\t\t\tswitch expr := expr.(type) {\n\t\t\tcase *AliasedTableExpr:\n\t\t\t\tswitch subQuery := expr.Expr.(type) {\n\t\t\t\tcase *Subquery:\n\t\t\t\t\tswitch selectSubQuery := subQuery.Select.(type) {\n\t\t\t\t\tcase *Select:\n\t\t\t\t\t\treplaceFromInSelect(selectSubQuery, tableName)\n\t\t\t\t\tdefault:\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\tdefault:\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\tdefault:\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc generateQuery(statement Statement) string {\n\tbuf := NewTrackedBuffer(nil)\n\tstatement.Format(buf)\n\treturn buf.String()\n}\n"
  },
  {
    "path": "sqlparser/sqltypes/sqltypes.go",
    "content": "// Copyright 2012, Google Inc. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package sqltypes implements interfaces and types that represent SQL values.\npackage sqltypes\n\nimport (\n\t\"encoding/base64\"\n\t\"encoding/gob\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"reflect\"\n\t\"strconv\"\n\t\"time\"\n\t\"unsafe\"\n)\n\nvar (\n\tNULL       = Value{}\n\tDONTESCAPE = byte(255)\n\tnullstr    = []byte(\"null\")\n)\n\n// BinWriter interface is used for encoding values.\n// Types like bytes.Buffer conform to this interface.\n// We expect the writer objects to be in-memory buffers.\n// So, we don't expect the write operations to fail.\ntype BinWriter interface {\n\tWrite([]byte) (int, error)\n\tWriteByte(byte) error\n}\n\n// Value can store any SQL value. NULL is stored as nil.\ntype Value struct {\n\tInner InnerValue\n}\n\n// Numeric represents non-fractional SQL number.\ntype Numeric []byte\n\n// Fractional represents fractional types like float and decimal\n// It's functionally equivalent to Numeric other than how it's constructed\ntype Fractional []byte\n\n// String represents any SQL type that needs to be represented using quotes.\ntype String []byte\n\n// MakeNumeric makes a Numeric from a []byte without validation.\nfunc MakeNumeric(b []byte) Value {\n\treturn Value{Numeric(b)}\n}\n\n// MakeFractional makes a Fractional value from a []byte without validation.\nfunc MakeFractional(b []byte) Value {\n\treturn Value{Fractional(b)}\n}\n\n// MakeString makes a String value from a []byte.\nfunc MakeString(b []byte) Value {\n\treturn Value{String(b)}\n}\n\n// Raw returns the raw bytes. All types are currently implemented as []byte.\nfunc (v Value) Raw() []byte {\n\tif v.Inner == nil {\n\t\treturn nil\n\t}\n\treturn v.Inner.raw()\n}\n\n// String returns the raw value as a string\nfunc (v Value) String() string {\n\tif v.Inner == nil {\n\t\treturn \"\"\n\t}\n\treturn toString(v.Inner.raw())\n}\n\n// String force casts a []byte to a string.\n// USE AT YOUR OWN RISK\nfunc toString(b []byte) (s string) {\n\tif len(b) == 0 {\n\t\treturn \"\"\n\t}\n\tpbytes := (*reflect.SliceHeader)(unsafe.Pointer(&b))\n\tpstring := (*reflect.StringHeader)(unsafe.Pointer(&s))\n\tpstring.Data = pbytes.Data\n\tpstring.Len = pbytes.Len\n\treturn\n}\n\n// ParseInt64 will parse a Numeric value into an int64\nfunc (v Value) ParseInt64() (val int64, err error) {\n\tif v.Inner == nil {\n\t\treturn 0, fmt.Errorf(\"value is null\")\n\t}\n\tn, ok := v.Inner.(Numeric)\n\tif !ok {\n\t\treturn 0, fmt.Errorf(\"value is not Numeric\")\n\t}\n\treturn strconv.ParseInt(string(n.raw()), 10, 64)\n}\n\n// ParseUint64 will parse a Numeric value into a uint64\nfunc (v Value) ParseUint64() (val uint64, err error) {\n\tif v.Inner == nil {\n\t\treturn 0, fmt.Errorf(\"value is null\")\n\t}\n\tn, ok := v.Inner.(Numeric)\n\tif !ok {\n\t\treturn 0, fmt.Errorf(\"value is not Numeric\")\n\t}\n\treturn strconv.ParseUint(string(n.raw()), 10, 64)\n}\n\n// ParseFloat64 will parse a Fractional value into an float64\nfunc (v Value) ParseFloat64() (val float64, err error) {\n\tif v.Inner == nil {\n\t\treturn 0, fmt.Errorf(\"value is null\")\n\t}\n\tn, ok := v.Inner.(Fractional)\n\tif !ok {\n\t\treturn 0, fmt.Errorf(\"value is not Fractional\")\n\t}\n\treturn strconv.ParseFloat(string(n.raw()), 64)\n}\n\n// EncodeSql encodes the value into an SQL statement. Can be binary.\nfunc (v Value) EncodeSql(b BinWriter) {\n\tif v.Inner == nil {\n\t\tif _, err := b.Write(nullstr); err != nil {\n\t\t\tpanic(err)\n\t\t}\n\t} else {\n\t\tv.Inner.encodeSql(b)\n\t}\n}\n\n// EncodeAscii encodes the value using 7-bit clean ascii bytes.\nfunc (v Value) EncodeAscii(b BinWriter) {\n\tif v.Inner == nil {\n\t\tif _, err := b.Write(nullstr); err != nil {\n\t\t\tpanic(err)\n\t\t}\n\t} else {\n\t\tv.Inner.encodeAscii(b)\n\t}\n}\n\nfunc (v Value) IsNull() bool {\n\treturn v.Inner == nil\n}\n\nfunc (v Value) IsNumeric() (ok bool) {\n\tif v.Inner != nil {\n\t\t_, ok = v.Inner.(Numeric)\n\t}\n\treturn ok\n}\n\nfunc (v Value) IsFractional() (ok bool) {\n\tif v.Inner != nil {\n\t\t_, ok = v.Inner.(Fractional)\n\t}\n\treturn ok\n}\n\nfunc (v Value) IsString() (ok bool) {\n\tif v.Inner != nil {\n\t\t_, ok = v.Inner.(String)\n\t}\n\treturn ok\n}\n\n// MarshalJSON should only be used for testing.\n// It's not a complete implementation.\nfunc (v Value) MarshalJSON() ([]byte, error) {\n\treturn json.Marshal(v.Inner)\n}\n\n// UnmarshalJSON should only be used for testing.\n// It's not a complete implementation.\nfunc (v *Value) UnmarshalJSON(b []byte) error {\n\tif len(b) == 0 {\n\t\treturn fmt.Errorf(\"error unmarshaling empty bytes\")\n\t}\n\tvar val interface{}\n\tvar err error\n\tswitch b[0] {\n\tcase '-':\n\t\tvar ival int64\n\t\terr = json.Unmarshal(b, &ival)\n\t\tval = ival\n\tcase '\"':\n\t\tvar bval []byte\n\t\terr = json.Unmarshal(b, &bval)\n\t\tval = bval\n\tcase 'n': // null\n\t\terr = json.Unmarshal(b, &val)\n\tdefault:\n\t\tvar uval uint64\n\t\terr = json.Unmarshal(b, &uval)\n\t\tval = uval\n\t}\n\tif err != nil {\n\t\treturn err\n\t}\n\t*v, err = BuildValue(val)\n\treturn err\n}\n\n// InnerValue defines methods that need to be supported by all non-null value types.\ntype InnerValue interface {\n\traw() []byte\n\tencodeSql(BinWriter)\n\tencodeAscii(BinWriter)\n}\n\nfunc BuildValue(goval interface{}) (v Value, err error) {\n\tswitch bindVal := goval.(type) {\n\tcase nil:\n\t\t// no op\n\tcase int:\n\t\tv = Value{Numeric(strconv.AppendInt(nil, int64(bindVal), 10))}\n\tcase int32:\n\t\tv = Value{Numeric(strconv.AppendInt(nil, int64(bindVal), 10))}\n\tcase int64:\n\t\tv = Value{Numeric(strconv.AppendInt(nil, int64(bindVal), 10))}\n\tcase uint:\n\t\tv = Value{Numeric(strconv.AppendUint(nil, uint64(bindVal), 10))}\n\tcase uint32:\n\t\tv = Value{Numeric(strconv.AppendUint(nil, uint64(bindVal), 10))}\n\tcase uint64:\n\t\tv = Value{Numeric(strconv.AppendUint(nil, uint64(bindVal), 10))}\n\tcase float64:\n\t\tv = Value{Fractional(strconv.AppendFloat(nil, bindVal, 'f', -1, 64))}\n\tcase string:\n\t\tv = Value{String([]byte(bindVal))}\n\tcase []byte:\n\t\tv = Value{String(bindVal)}\n\tcase time.Time:\n\t\tv = Value{String([]byte(bindVal.Format(\"2006-01-02 15:04:05\")))}\n\tcase Numeric, Fractional, String:\n\t\tv = Value{bindVal.(InnerValue)}\n\tcase Value:\n\t\tv = bindVal\n\tdefault:\n\t\treturn Value{}, fmt.Errorf(\"unsupported bind variable type %T: %v\", goval, goval)\n\t}\n\treturn v, nil\n}\n\n// BuildNumeric builds a Numeric type that represents any whole number.\n// It normalizes the representation to ensure 1:1 mapping between the\n// number and its representation.\nfunc BuildNumeric(val string) (n Value, err error) {\n\tif val[0] == '-' || val[0] == '+' {\n\t\tsigned, err := strconv.ParseInt(val, 0, 64)\n\t\tif err != nil {\n\t\t\treturn Value{}, err\n\t\t}\n\t\tn = Value{Numeric(strconv.AppendInt(nil, signed, 10))}\n\t} else {\n\t\tunsigned, err := strconv.ParseUint(val, 0, 64)\n\t\tif err != nil {\n\t\t\treturn Value{}, err\n\t\t}\n\t\tn = Value{Numeric(strconv.AppendUint(nil, unsigned, 10))}\n\t}\n\treturn n, nil\n}\n\nfunc (n Numeric) raw() []byte {\n\treturn []byte(n)\n}\n\nfunc (n Numeric) encodeSql(b BinWriter) {\n\tif _, err := b.Write(n.raw()); err != nil {\n\t\tpanic(err)\n\t}\n}\n\nfunc (n Numeric) encodeAscii(b BinWriter) {\n\tif _, err := b.Write(n.raw()); err != nil {\n\t\tpanic(err)\n\t}\n}\n\nfunc (n Numeric) MarshalJSON() ([]byte, error) {\n\treturn n.raw(), nil\n}\n\nfunc (f Fractional) raw() []byte {\n\treturn []byte(f)\n}\n\nfunc (f Fractional) encodeSql(b BinWriter) {\n\tif _, err := b.Write(f.raw()); err != nil {\n\t\tpanic(err)\n\t}\n}\n\nfunc (f Fractional) encodeAscii(b BinWriter) {\n\tif _, err := b.Write(f.raw()); err != nil {\n\t\tpanic(err)\n\t}\n}\n\nfunc (s String) MarshalJSON() ([]byte, error) {\n\treturn json.Marshal(string(s.raw()))\n}\n\nfunc (s String) raw() []byte {\n\treturn []byte(s)\n}\n\nfunc (s String) encodeSql(b BinWriter) {\n\twritebyte(b, '\\'')\n\tfor _, ch := range s.raw() {\n\t\tif encodedChar := SqlEncodeMap[ch]; encodedChar == DONTESCAPE {\n\t\t\twritebyte(b, ch)\n\t\t} else {\n\t\t\twritebyte(b, '\\\\')\n\t\t\twritebyte(b, encodedChar)\n\t\t}\n\t}\n\twritebyte(b, '\\'')\n}\n\nfunc (s String) encodeAscii(b BinWriter) {\n\twritebyte(b, '\\'')\n\tencoder := base64.NewEncoder(base64.StdEncoding, b)\n\tencoder.Write(s.raw())\n\tencoder.Close()\n\twritebyte(b, '\\'')\n}\n\nfunc writebyte(b BinWriter, c byte) {\n\tif err := b.WriteByte(c); err != nil {\n\t\tpanic(err)\n\t}\n}\n\n// SqlEncodeMap specifies how to escape binary data with '\\'.\n// Complies to http://dev.mysql.com/doc/refman/5.1/en/string-syntax.html\nvar SqlEncodeMap [256]byte\n\n// SqlDecodeMap is the reverse of SqlEncodeMap\nvar SqlDecodeMap [256]byte\n\nvar encodeRef = map[byte]byte{\n\t'\\x00': '0',\n\t'\\'':   '\\'',\n\t'\"':    '\"',\n\t'\\b':   'b',\n\t'\\n':   'n',\n\t'\\r':   'r',\n\t'\\t':   't',\n\t26:     'Z', // ctl-Z\n\t'\\\\':   '\\\\',\n}\n\nfunc init() {\n\tfor i := range SqlEncodeMap {\n\t\tSqlEncodeMap[i] = DONTESCAPE\n\t\tSqlDecodeMap[i] = DONTESCAPE\n\t}\n\tfor i := range SqlEncodeMap {\n\t\tif to, ok := encodeRef[byte(i)]; ok {\n\t\t\tSqlEncodeMap[byte(i)] = to\n\t\t\tSqlDecodeMap[to] = byte(i)\n\t\t}\n\t}\n\tgob.Register(Numeric(nil))\n\tgob.Register(Fractional(nil))\n\tgob.Register(String(nil))\n}\n"
  },
  {
    "path": "sqlparser/sqltypes/type_test.go",
    "content": "// Copyright 2012, Google Inc. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage sqltypes\n\nimport (\n\t\"bytes\"\n\t\"testing\"\n\t\"time\"\n)\n\nfunc TestNull(t *testing.T) {\n\tn := Value{}\n\tif !n.IsNull() {\n\t\tt.Errorf(\"value is not null\")\n\t}\n\tif n.String() != \"\" {\n\t\tt.Errorf(\"Expecting '', got %s\", n.String())\n\t}\n\tb := bytes.NewBuffer(nil)\n\tn.EncodeSql(b)\n\tif b.String() != \"null\" {\n\t\tt.Errorf(\"Expecting null, got %s\", b.String())\n\t}\n\tn.EncodeAscii(b)\n\tif b.String() != \"nullnull\" {\n\t\tt.Errorf(\"Expecting nullnull, got %s\", b.String())\n\t}\n\tjs, err := n.MarshalJSON()\n\tif err != nil {\n\t\tt.Errorf(\"Unexpected error: %s\", err)\n\t}\n\tif string(js) != \"null\" {\n\t\tt.Errorf(\"Expecting null, received %s\", js)\n\t}\n}\n\nfunc TestNumeric(t *testing.T) {\n\tn := Value{Numeric([]byte(\"1234\"))}\n\tb := bytes.NewBuffer(nil)\n\tn.EncodeSql(b)\n\tif b.String() != \"1234\" {\n\t\tt.Errorf(\"Expecting 1234, got %s\", b.String())\n\t}\n\tn.EncodeAscii(b)\n\tif b.String() != \"12341234\" {\n\t\tt.Errorf(\"Expecting 12341234, got %s\", b.String())\n\t}\n\tjs, err := n.MarshalJSON()\n\tif err != nil {\n\t\tt.Errorf(\"Unexpected error: %s\", err)\n\t}\n\tif string(js) != \"1234\" {\n\t\tt.Errorf(\"Expecting 1234, received %s\", js)\n\t}\n}\n\nfunc TestTime(t *testing.T) {\n\tdate := time.Date(1999, 1, 2, 3, 4, 5, 0, time.UTC)\n\tv, _ := BuildValue(date)\n\tif !v.IsString() || v.String() != \"1999-01-02 03:04:05\" {\n\t\tt.Errorf(\"Expecting 1999-01-02 03:04:05, got %s\", v.String())\n\t}\n\n\tb := &bytes.Buffer{}\n\tv.EncodeSql(b)\n\tif b.String() != \"'1999-01-02 03:04:05'\" {\n\t\tt.Errorf(\"Expecting '1999-01-02 03:04:05', got %s\", b.String())\n\t}\n}\n\nconst (\n\tINVALIDNEG = \"-9223372036854775809\"\n\tMINNEG     = \"-9223372036854775808\"\n\tMAXPOS     = \"18446744073709551615\"\n\tINVALIDPOS = \"18446744073709551616\"\n\tNEGFLOAT   = \"1.234\"\n\tPOSFLOAT   = \"-1.234\"\n)\n\nfunc TestBuildNumeric(t *testing.T) {\n\tvar n Value\n\tvar err error\n\tn, err = BuildNumeric(MINNEG)\n\tif err != nil {\n\t\tt.Errorf(\"Unexpected error: %s\", err)\n\t}\n\tif n.String() != MINNEG {\n\t\tt.Errorf(\"Expecting %v, received %s\", MINNEG, n.Raw())\n\t}\n\tn, err = BuildNumeric(MAXPOS)\n\tif err != nil {\n\t\tt.Errorf(\"Unexpected error: %s\", err)\n\t}\n\tif n.String() != MAXPOS {\n\t\tt.Errorf(\"Expecting %v, received %s\", MAXPOS, n.Raw())\n\t}\n\tn, err = BuildNumeric(\"0xA\")\n\tif err != nil {\n\t\tt.Errorf(\"Unexpected error: %s\", err)\n\t}\n\tif n.String() != \"10\" {\n\t\tt.Errorf(\"Expecting %v, received %s\", 10, n.Raw())\n\t}\n\tn, err = BuildNumeric(\"012\")\n\tif err != nil {\n\t\tt.Errorf(\"Unexpected error: %s\", err)\n\t}\n\tif string(n.Raw()) != \"10\" {\n\t\tt.Errorf(\"Expecting %v, received %s\", 10, n.Raw())\n\t}\n\tif n, err = BuildNumeric(INVALIDNEG); err == nil {\n\t\tt.Errorf(\"Expecting error\")\n\t}\n\tif n, err = BuildNumeric(INVALIDPOS); err == nil {\n\t\tt.Errorf(\"Expecting error\")\n\t}\n\tif n, err = BuildNumeric(NEGFLOAT); err == nil {\n\t\tt.Errorf(\"Expecting error\")\n\t}\n\tif n, err = BuildNumeric(POSFLOAT); err == nil {\n\t\tt.Errorf(\"Expecting error\")\n\t}\n}\n\nconst (\n\tHARDSQL     = \"\\x00'\\\"\\b\\n\\r\\t\\x1A\\\\\"\n\tHARDESCAPED = \"'\\\\0\\\\'\\\\\\\"\\\\b\\\\n\\\\r\\\\t\\\\Z\\\\\\\\'\"\n\tHARDASCII   = \"'ACciCAoNCRpc'\"\n)\n\nfunc TestString(t *testing.T) {\n\ts := Value{String([]byte(HARDSQL))}\n\tb := bytes.NewBuffer(nil)\n\ts.EncodeSql(b)\n\tif b.String() != HARDESCAPED {\n\t\tt.Errorf(\"Expecting %s, received %s\", HARDESCAPED, b.String())\n\t}\n\tb = bytes.NewBuffer(nil)\n\ts.EncodeAscii(b)\n\tif b.String() != HARDASCII {\n\t\tt.Errorf(\"Expecting %s, received %#v\", HARDASCII, b.String())\n\t}\n\ts = Value{String([]byte(\"ab\\x01cd\"))}\n\tjs, err := s.MarshalJSON()\n\tif err != nil {\n\t\tt.Errorf(\"Unexpected error: %s\", err)\n\t}\n\tif got, want := string(js), \"\\\"ab\\\\u0001cd\\\"\"; got != want {\n\t\tt.Errorf(\"%#v.MarshalJSON() = %#v, want %#v\", s, got, want)\n\t}\n}\n\nfunc TestBuildValue(t *testing.T) {\n\tv, err := BuildValue(nil)\n\tif err != nil {\n\t\tt.Errorf(\"%v\", err)\n\t}\n\tif !v.IsNull() {\n\t\tt.Errorf(\"Expecting null\")\n\t}\n\tn64, err := v.ParseUint64()\n\tif err == nil || err.Error() != \"value is null\" {\n\t\tt.Errorf(\"%v\", err)\n\t}\n\tv, err = BuildValue(int(-1))\n\tif err != nil {\n\t\tt.Errorf(\"%v\", err)\n\t}\n\tif !v.IsNumeric() || v.String() != \"-1\" {\n\t\tt.Errorf(\"Expecting -1, received %T: %s\", v.Inner, v.String())\n\t}\n\tv, err = BuildValue(int32(-1))\n\tif err != nil {\n\t\tt.Errorf(\"%v\", err)\n\t}\n\tif !v.IsNumeric() || v.String() != \"-1\" {\n\t\tt.Errorf(\"Expecting -1, received %T: %s\", v.Inner, v.String())\n\t}\n\tv, err = BuildValue(int64(-1))\n\tif err != nil {\n\t\tt.Errorf(\"%v\", err)\n\t}\n\tif !v.IsNumeric() || v.String() != \"-1\" {\n\t\tt.Errorf(\"Expecting -1, received %T: %s\", v.Inner, v.String())\n\t}\n\tn64, err = v.ParseUint64()\n\tif err == nil {\n\t\tt.Errorf(\"-1 shouldn't convert into uint64\")\n\t}\n\ti64, err := v.ParseInt64()\n\tif i64 != -1 {\n\t\tt.Errorf(\"want -1, got %d\", i64)\n\t}\n\tif err != nil {\n\t\tt.Errorf(\"%v\", err)\n\t}\n\tv, err = BuildValue(uint(1))\n\tif err != nil {\n\t\tt.Errorf(\"%v\", err)\n\t}\n\tif !v.IsNumeric() || v.String() != \"1\" {\n\t\tt.Errorf(\"Expecting 1, received %T: %s\", v.Inner, v.String())\n\t}\n\tv, err = BuildValue(uint32(1))\n\tif err != nil {\n\t\tt.Errorf(\"%v\", err)\n\t}\n\tif !v.IsNumeric() || v.String() != \"1\" {\n\t\tt.Errorf(\"Expecting 1, received %T: %s\", v.Inner, v.String())\n\t}\n\tv, err = BuildValue(uint64(1))\n\tif err != nil {\n\t\tt.Errorf(\"%v\", err)\n\t}\n\tn64, err = v.ParseUint64()\n\tif err != nil {\n\t\tt.Errorf(\"%v\", err)\n\t}\n\tif n64 != 1 {\n\t\tt.Errorf(\"Expecting 1, got %v\", n64)\n\t}\n\tif !v.IsNumeric() || v.String() != \"1\" {\n\t\tt.Errorf(\"Expecting 1, received %T: %s\", v.Inner, v.String())\n\t}\n\tv, err = BuildValue(1.23)\n\tif err != nil {\n\t\tt.Errorf(\"%v\", err)\n\t}\n\tif !v.IsFractional() || v.String() != \"1.23\" {\n\t\tt.Errorf(\"Expecting 1.23, received %T: %s\", v.Inner, v.String())\n\t}\n\tn64, err = v.ParseUint64()\n\tif err == nil {\n\t\tt.Errorf(\"1.23 shouldn't convert into uint64\")\n\t}\n\tv, err = BuildValue(\"abcd\")\n\tif err != nil {\n\t\tt.Errorf(\"%v\", err)\n\t}\n\tif !v.IsString() || v.String() != \"abcd\" {\n\t\tt.Errorf(\"Expecting abcd, received %T: %s\", v.Inner, v.String())\n\t}\n\tv, err = BuildValue([]byte(\"abcd\"))\n\tif err != nil {\n\t\tt.Errorf(\"%v\", err)\n\t}\n\tif !v.IsString() || v.String() != \"abcd\" {\n\t\tt.Errorf(\"Expecting abcd, received %T: %s\", v.Inner, v.String())\n\t}\n\tn64, err = v.ParseUint64()\n\tif err == nil || err.Error() != \"value is not Numeric\" {\n\t\tt.Errorf(\"%v\", err)\n\t}\n\tv, err = BuildValue(time.Date(2012, time.February, 24, 23, 19, 43, 10, time.UTC))\n\tif err != nil {\n\t\tt.Errorf(\"%v\", err)\n\t}\n\tif !v.IsString() || v.String() != \"2012-02-24 23:19:43\" {\n\t\tt.Errorf(\"Expecting 2012-02-24 23:19:43, received %T: %s\", v.Inner, v.String())\n\t}\n\tv, err = BuildValue(Numeric([]byte(\"123\")))\n\tif err != nil {\n\t\tt.Errorf(\"%v\", err)\n\t}\n\tif !v.IsNumeric() || v.String() != \"123\" {\n\t\tt.Errorf(\"Expecting 123, received %T: %s\", v.Inner, v.String())\n\t}\n\tv, err = BuildValue(Fractional([]byte(\"12.3\")))\n\tif err != nil {\n\t\tt.Errorf(\"%v\", err)\n\t}\n\tif !v.IsFractional() || v.String() != \"12.3\" {\n\t\tt.Errorf(\"Expecting 12.3, received %T: %s\", v.Inner, v.String())\n\t}\n\tv, err = BuildValue(String([]byte(\"abc\")))\n\tif err != nil {\n\t\tt.Errorf(\"%v\", err)\n\t}\n\tif !v.IsString() || v.String() != \"abc\" {\n\t\tt.Errorf(\"Expecting abc, received %T: %s\", v.Inner, v.String())\n\t}\n\tv, err = BuildValue(float32(1.23))\n\tif err == nil {\n\t\tt.Errorf(\"Did not receive error\")\n\t}\n\tv1 := Value{String([]byte(\"ab\"))}\n\tv, err = BuildValue(v1)\n\tif err != nil {\n\t\tt.Errorf(\"%v\", err)\n\t}\n\tif !v.IsString() || v.String() != \"ab\" {\n\t\tt.Errorf(\"Expecting ab, received %T: %s\", v.Inner, v.String())\n\t}\n\tv, err = BuildValue(float32(1.23))\n\tif err == nil {\n\t\tt.Errorf(\"Did not receive error\")\n\t}\n}\n\n// Ensure DONTESCAPE is not escaped\nfunc TestEncode(t *testing.T) {\n\tif SqlEncodeMap[DONTESCAPE] != DONTESCAPE {\n\t\tt.Errorf(\"Encode fail: %v\", SqlEncodeMap[DONTESCAPE])\n\t}\n\tif SqlDecodeMap[DONTESCAPE] != DONTESCAPE {\n\t\tt.Errorf(\"Decode fail: %v\", SqlDecodeMap[DONTESCAPE])\n\t}\n}\n"
  },
  {
    "path": "sqlparser/token.go",
    "content": "// Copyright 2012, Google Inc. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage sqlparser\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"strings\"\n\n\t\"github.com/dinedal/textql/sqlparser/sqltypes\"\n)\n\nconst EOFCHAR = 0x100\n\n// Tokenizer is the struct used to generate SQL\n// tokens for the parser.\ntype Tokenizer struct {\n\tInStream      *strings.Reader\n\tAllowComments bool\n\tForceEOF      bool\n\tlastChar      uint16\n\tPosition      int\n\terrorToken    []byte\n\tLastError     string\n\tposVarIndex   int\n\tParseTree     Statement\n}\n\n// NewStringTokenizer creates a new Tokenizer for the\n// sql string.\nfunc NewStringTokenizer(sql string) *Tokenizer {\n\treturn &Tokenizer{InStream: strings.NewReader(sql)}\n}\n\nvar keywords = map[string]int{\n\t\"all\":           ALL,\n\t\"alter\":         ALTER,\n\t\"analyze\":       ANALYZE,\n\t\"and\":           AND,\n\t\"as\":            AS,\n\t\"asc\":           ASC,\n\t\"between\":       BETWEEN,\n\t\"by\":            BY,\n\t\"case\":          CASE,\n\t\"create\":        CREATE,\n\t\"cross\":         CROSS,\n\t\"default\":       DEFAULT,\n\t\"delete\":        DELETE,\n\t\"desc\":          DESC,\n\t\"describe\":      DESCRIBE,\n\t\"distinct\":      DISTINCT,\n\t\"drop\":          DROP,\n\t\"duplicate\":     DUPLICATE,\n\t\"else\":          ELSE,\n\t\"end\":           END,\n\t\"except\":        EXCEPT,\n\t\"exists\":        EXISTS,\n\t\"explain\":       EXPLAIN,\n\t\"for\":           FOR,\n\t\"force\":         FORCE,\n\t\"from\":          FROM,\n\t\"group\":         GROUP,\n\t\"having\":        HAVING,\n\t\"if\":            IF,\n\t\"ignore\":        IGNORE,\n\t\"in\":            IN,\n\t\"index\":         INDEX,\n\t\"inner\":         INNER,\n\t\"insert\":        INSERT,\n\t\"intersect\":     INTERSECT,\n\t\"into\":          INTO,\n\t\"is\":            IS,\n\t\"join\":          JOIN,\n\t\"key\":           KEY,\n\t\"keyrange\":      KEYRANGE,\n\t\"left\":          LEFT,\n\t\"like\":          LIKE,\n\t\"limit\":         LIMIT,\n\t\"lock\":          LOCK,\n\t\"minus\":         MINUS,\n\t\"natural\":       NATURAL,\n\t\"not\":           NOT,\n\t\"null\":          NULL,\n\t\"on\":            ON,\n\t\"or\":            OR,\n\t\"order\":         ORDER,\n\t\"outer\":         OUTER,\n\t\"rename\":        RENAME,\n\t\"right\":         RIGHT,\n\t\"select\":        SELECT,\n\t\"set\":           SET,\n\t\"show\":          SHOW,\n\t\"straight_join\": STRAIGHT_JOIN,\n\t\"table\":         TABLE,\n\t\"then\":          THEN,\n\t\"to\":            TO,\n\t\"union\":         UNION,\n\t\"unique\":        UNIQUE,\n\t\"update\":        UPDATE,\n\t\"use\":           USE,\n\t\"using\":         USING,\n\t\"values\":        VALUES,\n\t\"view\":          VIEW,\n\t\"when\":          WHEN,\n\t\"where\":         WHERE,\n}\n\n// Lex returns the next token form the Tokenizer.\n// This function is used by go yacc.\nfunc (tkn *Tokenizer) Lex(lval *yySymType) int {\n\ttyp, val := tkn.Scan()\n\tfor typ == COMMENT {\n\t\tif tkn.AllowComments {\n\t\t\tbreak\n\t\t}\n\t\ttyp, val = tkn.Scan()\n\t}\n\tswitch typ {\n\tcase ID, STRING, NUMBER, VALUE_ARG, LIST_ARG, COMMENT:\n\t\tlval.bytes = val\n\t}\n\ttkn.errorToken = val\n\treturn typ\n}\n\n// Error is called by go yacc if there's a parsing error.\nfunc (tkn *Tokenizer) Error(err string) {\n\tbuf := bytes.NewBuffer(make([]byte, 0, 32))\n\tif tkn.errorToken != nil {\n\t\tfmt.Fprintf(buf, \"%s at position %v near %s\", err, tkn.Position, tkn.errorToken)\n\t} else {\n\t\tfmt.Fprintf(buf, \"%s at position %v\", err, tkn.Position)\n\t}\n\ttkn.LastError = buf.String()\n}\n\n// Scan scans the tokenizer for the next token and returns\n// the token type and an optional value.\nfunc (tkn *Tokenizer) Scan() (int, []byte) {\n\tif tkn.ForceEOF {\n\t\treturn 0, nil\n\t}\n\n\tif tkn.lastChar == 0 {\n\t\ttkn.next()\n\t}\n\ttkn.skipBlank()\n\tswitch ch := tkn.lastChar; {\n\tcase isLetter(ch):\n\t\treturn tkn.scanIdentifier()\n\tcase isDigit(ch):\n\t\treturn tkn.scanNumber(false)\n\tcase ch == ':':\n\t\treturn tkn.scanBindVar()\n\tdefault:\n\t\ttkn.next()\n\t\tswitch ch {\n\t\tcase EOFCHAR:\n\t\t\treturn 0, nil\n\t\tcase '=', ',', ';', '(', ')', '+', '*', '%', '&', '|', '^', '~':\n\t\t\treturn int(ch), nil\n\t\tcase '?':\n\t\t\ttkn.posVarIndex++\n\t\t\tbuf := new(bytes.Buffer)\n\t\t\tfmt.Fprintf(buf, \":v%d\", tkn.posVarIndex)\n\t\t\treturn VALUE_ARG, buf.Bytes()\n\t\tcase '.':\n\t\t\tif isDigit(tkn.lastChar) {\n\t\t\t\treturn tkn.scanNumber(true)\n\t\t\t} else {\n\t\t\t\treturn int(ch), nil\n\t\t\t}\n\t\tcase '/':\n\t\t\tswitch tkn.lastChar {\n\t\t\tcase '/':\n\t\t\t\ttkn.next()\n\t\t\t\treturn tkn.scanCommentType1(\"//\")\n\t\t\tcase '*':\n\t\t\t\ttkn.next()\n\t\t\t\treturn tkn.scanCommentType2()\n\t\t\tdefault:\n\t\t\t\treturn int(ch), nil\n\t\t\t}\n\t\tcase '-':\n\t\t\tif tkn.lastChar == '-' {\n\t\t\t\ttkn.next()\n\t\t\t\treturn tkn.scanCommentType1(\"--\")\n\t\t\t} else {\n\t\t\t\treturn int(ch), nil\n\t\t\t}\n\t\tcase '<':\n\t\t\tswitch tkn.lastChar {\n\t\t\tcase '>':\n\t\t\t\ttkn.next()\n\t\t\t\treturn NE, nil\n\t\t\tcase '=':\n\t\t\t\ttkn.next()\n\t\t\t\tswitch tkn.lastChar {\n\t\t\t\tcase '>':\n\t\t\t\t\ttkn.next()\n\t\t\t\t\treturn NULL_SAFE_EQUAL, nil\n\t\t\t\tdefault:\n\t\t\t\t\treturn LE, nil\n\t\t\t\t}\n\t\t\tdefault:\n\t\t\t\treturn int(ch), nil\n\t\t\t}\n\t\tcase '>':\n\t\t\tif tkn.lastChar == '=' {\n\t\t\t\ttkn.next()\n\t\t\t\treturn GE, nil\n\t\t\t} else {\n\t\t\t\treturn int(ch), nil\n\t\t\t}\n\t\tcase '!':\n\t\t\tif tkn.lastChar == '=' {\n\t\t\t\ttkn.next()\n\t\t\t\treturn NE, nil\n\t\t\t} else {\n\t\t\t\treturn LEX_ERROR, []byte(\"!\")\n\t\t\t}\n\t\tcase '\\'', '\"':\n\t\t\treturn tkn.scanString(ch, STRING)\n\t\tcase '`':\n\t\t\treturn tkn.scanLiteralIdentifier()\n\t\tdefault:\n\t\t\treturn LEX_ERROR, []byte{byte(ch)}\n\t\t}\n\t}\n}\n\nfunc (tkn *Tokenizer) skipBlank() {\n\tch := tkn.lastChar\n\tfor ch == ' ' || ch == '\\n' || ch == '\\r' || ch == '\\t' {\n\t\ttkn.next()\n\t\tch = tkn.lastChar\n\t}\n}\n\nfunc (tkn *Tokenizer) scanIdentifier() (int, []byte) {\n\tbuffer := bytes.NewBuffer(make([]byte, 0, 8))\n\tbuffer.WriteByte(byte(tkn.lastChar))\n\tfor tkn.next(); isLetter(tkn.lastChar) || isDigit(tkn.lastChar); tkn.next() {\n\t\tbuffer.WriteByte(byte(tkn.lastChar))\n\t}\n\tlowered := bytes.ToLower(buffer.Bytes())\n\tif keywordId, found := keywords[string(lowered)]; found {\n\t\treturn keywordId, lowered\n\t}\n\treturn ID, buffer.Bytes()\n}\n\nfunc (tkn *Tokenizer) scanLiteralIdentifier() (int, []byte) {\n\tbuffer := bytes.NewBuffer(make([]byte, 0, 8))\n\tbuffer.WriteByte(byte(tkn.lastChar))\n\tif !isLetter(tkn.lastChar) {\n\t\treturn LEX_ERROR, buffer.Bytes()\n\t}\n\tfor tkn.next(); isLetter(tkn.lastChar) || isDigit(tkn.lastChar); tkn.next() {\n\t\tbuffer.WriteByte(byte(tkn.lastChar))\n\t}\n\tif tkn.lastChar != '`' {\n\t\treturn LEX_ERROR, buffer.Bytes()\n\t}\n\ttkn.next()\n\treturn ID, buffer.Bytes()\n}\n\nfunc (tkn *Tokenizer) scanBindVar() (int, []byte) {\n\tbuffer := bytes.NewBuffer(make([]byte, 0, 8))\n\tbuffer.WriteByte(byte(tkn.lastChar))\n\ttoken := VALUE_ARG\n\ttkn.next()\n\tif tkn.lastChar == ':' {\n\t\ttoken = LIST_ARG\n\t\tbuffer.WriteByte(byte(tkn.lastChar))\n\t\ttkn.next()\n\t}\n\tif !isLetter(tkn.lastChar) {\n\t\treturn LEX_ERROR, buffer.Bytes()\n\t}\n\tfor isLetter(tkn.lastChar) || isDigit(tkn.lastChar) || tkn.lastChar == '.' {\n\t\tbuffer.WriteByte(byte(tkn.lastChar))\n\t\ttkn.next()\n\t}\n\treturn token, buffer.Bytes()\n}\n\nfunc (tkn *Tokenizer) scanMantissa(base int, buffer *bytes.Buffer) {\n\tfor digitVal(tkn.lastChar) < base {\n\t\ttkn.ConsumeNext(buffer)\n\t}\n}\n\nfunc (tkn *Tokenizer) scanNumber(seenDecimalPoint bool) (int, []byte) {\n\tbuffer := bytes.NewBuffer(make([]byte, 0, 8))\n\tif seenDecimalPoint {\n\t\tbuffer.WriteByte('.')\n\t\ttkn.scanMantissa(10, buffer)\n\t\tgoto exponent\n\t}\n\n\tif tkn.lastChar == '0' {\n\t\t// int or float\n\t\ttkn.ConsumeNext(buffer)\n\t\tif tkn.lastChar == 'x' || tkn.lastChar == 'X' {\n\t\t\t// hexadecimal int\n\t\t\ttkn.ConsumeNext(buffer)\n\t\t\ttkn.scanMantissa(16, buffer)\n\t\t} else {\n\t\t\t// octal int or float\n\t\t\tseenDecimalDigit := false\n\t\t\ttkn.scanMantissa(8, buffer)\n\t\t\tif tkn.lastChar == '8' || tkn.lastChar == '9' {\n\t\t\t\t// illegal octal int or float\n\t\t\t\tseenDecimalDigit = true\n\t\t\t\ttkn.scanMantissa(10, buffer)\n\t\t\t}\n\t\t\tif tkn.lastChar == '.' || tkn.lastChar == 'e' || tkn.lastChar == 'E' {\n\t\t\t\tgoto fraction\n\t\t\t}\n\t\t\t// octal int\n\t\t\tif seenDecimalDigit {\n\t\t\t\treturn LEX_ERROR, buffer.Bytes()\n\t\t\t}\n\t\t}\n\t\tgoto exit\n\t}\n\n\t// decimal int or float\n\ttkn.scanMantissa(10, buffer)\n\nfraction:\n\tif tkn.lastChar == '.' {\n\t\ttkn.ConsumeNext(buffer)\n\t\ttkn.scanMantissa(10, buffer)\n\t}\n\nexponent:\n\tif tkn.lastChar == 'e' || tkn.lastChar == 'E' {\n\t\ttkn.ConsumeNext(buffer)\n\t\tif tkn.lastChar == '+' || tkn.lastChar == '-' {\n\t\t\ttkn.ConsumeNext(buffer)\n\t\t}\n\t\ttkn.scanMantissa(10, buffer)\n\t}\n\nexit:\n\treturn NUMBER, buffer.Bytes()\n}\n\nfunc (tkn *Tokenizer) scanString(delim uint16, typ int) (int, []byte) {\n\tbuffer := bytes.NewBuffer(make([]byte, 0, 8))\n\tfor {\n\t\tch := tkn.lastChar\n\t\ttkn.next()\n\t\tif ch == delim {\n\t\t\tif tkn.lastChar == delim {\n\t\t\t\ttkn.next()\n\t\t\t} else {\n\t\t\t\tbreak\n\t\t\t}\n\t\t} else if ch == '\\\\' {\n\t\t\tif tkn.lastChar == EOFCHAR {\n\t\t\t\treturn LEX_ERROR, buffer.Bytes()\n\t\t\t}\n\t\t\tif decodedChar := sqltypes.SqlDecodeMap[byte(tkn.lastChar)]; decodedChar == sqltypes.DONTESCAPE {\n\t\t\t\tch = tkn.lastChar\n\t\t\t} else {\n\t\t\t\tch = uint16(decodedChar)\n\t\t\t}\n\t\t\ttkn.next()\n\t\t}\n\t\tif ch == EOFCHAR {\n\t\t\treturn LEX_ERROR, buffer.Bytes()\n\t\t}\n\t\tbuffer.WriteByte(byte(ch))\n\t}\n\treturn typ, buffer.Bytes()\n}\n\nfunc (tkn *Tokenizer) scanCommentType1(prefix string) (int, []byte) {\n\tbuffer := bytes.NewBuffer(make([]byte, 0, 8))\n\tbuffer.WriteString(prefix)\n\tfor tkn.lastChar != EOFCHAR {\n\t\tif tkn.lastChar == '\\n' {\n\t\t\ttkn.ConsumeNext(buffer)\n\t\t\tbreak\n\t\t}\n\t\ttkn.ConsumeNext(buffer)\n\t}\n\treturn COMMENT, buffer.Bytes()\n}\n\nfunc (tkn *Tokenizer) scanCommentType2() (int, []byte) {\n\tbuffer := bytes.NewBuffer(make([]byte, 0, 8))\n\tbuffer.WriteString(\"/*\")\n\tfor {\n\t\tif tkn.lastChar == '*' {\n\t\t\ttkn.ConsumeNext(buffer)\n\t\t\tif tkn.lastChar == '/' {\n\t\t\t\ttkn.ConsumeNext(buffer)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\tif tkn.lastChar == EOFCHAR {\n\t\t\treturn LEX_ERROR, buffer.Bytes()\n\t\t}\n\t\ttkn.ConsumeNext(buffer)\n\t}\n\treturn COMMENT, buffer.Bytes()\n}\n\nfunc (tkn *Tokenizer) ConsumeNext(buffer *bytes.Buffer) {\n\tif tkn.lastChar == EOFCHAR {\n\t\t// This should never happen.\n\t\tpanic(\"unexpected EOF\")\n\t}\n\tbuffer.WriteByte(byte(tkn.lastChar))\n\ttkn.next()\n}\n\nfunc (tkn *Tokenizer) next() {\n\tif ch, err := tkn.InStream.ReadByte(); err != nil {\n\t\t// Only EOF is possible.\n\t\ttkn.lastChar = EOFCHAR\n\t} else {\n\t\ttkn.lastChar = uint16(ch)\n\t}\n\ttkn.Position++\n}\n\nfunc isLetter(ch uint16) bool {\n\treturn 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' || ch == '@'\n}\n\nfunc digitVal(ch uint16) int {\n\tswitch {\n\tcase '0' <= ch && ch <= '9':\n\t\treturn int(ch) - '0'\n\tcase 'a' <= ch && ch <= 'f':\n\t\treturn int(ch) - 'a' + 10\n\tcase 'A' <= ch && ch <= 'F':\n\t\treturn int(ch) - 'A' + 10\n\t}\n\treturn 16 // larger than any legal digit val\n}\n\nfunc isDigit(ch uint16) bool {\n\treturn '0' <= ch && ch <= '9'\n}\n"
  },
  {
    "path": "sqlparser/tracked_buffer.go",
    "content": "// Copyright 2012, Google Inc. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage sqlparser\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n)\n\n// TrackedBuffer is used to rebuild a query from the ast.\n// bindLocations keeps track of locations in the buffer that\n// use bind variables for efficient future substitutions.\n// nodeFormatter is the formatting function the buffer will\n// use to format a node. By default(nil), it's FormatNode.\n// But you can supply a different formatting function if you\n// want to generate a query that's different from the default.\ntype TrackedBuffer struct {\n\t*bytes.Buffer\n\tbindLocations []bindLocation\n\tnodeFormatter func(buf *TrackedBuffer, node SQLNode)\n}\n\nfunc NewTrackedBuffer(nodeFormatter func(buf *TrackedBuffer, node SQLNode)) *TrackedBuffer {\n\tbuf := &TrackedBuffer{\n\t\tBuffer:        bytes.NewBuffer(make([]byte, 0, 128)),\n\t\tbindLocations: make([]bindLocation, 0, 4),\n\t\tnodeFormatter: nodeFormatter,\n\t}\n\treturn buf\n}\n\n// Myprintf mimics fmt.Fprintf(buf, ...), but limited to Node(%v),\n// Node.Value(%s) and string(%s). It also allows a %a for a value argument, in\n// which case it adds tracking info for future substitutions.\n//\n// The name must be something other than the usual Printf() to avoid \"go vet\"\n// warnings due to our custom format specifiers.\nfunc (buf *TrackedBuffer) Myprintf(format string, values ...interface{}) {\n\tend := len(format)\n\tfieldnum := 0\n\tfor i := 0; i < end; {\n\t\tlasti := i\n\t\tfor i < end && format[i] != '%' {\n\t\t\ti++\n\t\t}\n\t\tif i > lasti {\n\t\t\tbuf.WriteString(format[lasti:i])\n\t\t}\n\t\tif i >= end {\n\t\t\tbreak\n\t\t}\n\t\ti++ // '%'\n\t\tswitch format[i] {\n\t\tcase 'c':\n\t\t\tswitch v := values[fieldnum].(type) {\n\t\t\tcase byte:\n\t\t\t\tbuf.WriteByte(v)\n\t\t\tcase rune:\n\t\t\t\tbuf.WriteRune(v)\n\t\t\tdefault:\n\t\t\t\tpanic(fmt.Sprintf(\"unexpected type %T\", v))\n\t\t\t}\n\t\tcase 's':\n\t\t\tswitch v := values[fieldnum].(type) {\n\t\t\tcase []byte:\n\t\t\t\tbuf.Write(v)\n\t\t\tcase string:\n\t\t\t\tbuf.WriteString(v)\n\t\t\tdefault:\n\t\t\t\tpanic(fmt.Sprintf(\"unexpected type %T\", v))\n\t\t\t}\n\t\tcase 'v':\n\t\t\tnode := values[fieldnum].(SQLNode)\n\t\t\tif buf.nodeFormatter == nil {\n\t\t\t\tnode.Format(buf)\n\t\t\t} else {\n\t\t\t\tbuf.nodeFormatter(buf, node)\n\t\t\t}\n\t\tcase 'a':\n\t\t\tbuf.WriteArg(values[fieldnum].(string))\n\t\tdefault:\n\t\t\tpanic(\"unexpected\")\n\t\t}\n\t\tfieldnum++\n\t\ti++\n\t}\n}\n\n// WriteArg writes a value argument into the buffer. arg should not contain\n// the ':' prefix. It also adds tracking info for future substitutions.\nfunc (buf *TrackedBuffer) WriteArg(arg string) {\n\tbuf.bindLocations = append(buf.bindLocations, bindLocation{\n\t\toffset: buf.Len(),\n\t\tlength: len(arg),\n\t})\n\tbuf.WriteString(arg)\n}\n\nfunc (buf *TrackedBuffer) ParsedQuery() *ParsedQuery {\n\treturn &ParsedQuery{Query: buf.String(), bindLocations: buf.bindLocations}\n}\n\nfunc (buf *TrackedBuffer) HasBindVars() bool {\n\treturn len(buf.bindLocations) != 0\n}\n"
  },
  {
    "path": "sqlparser/y.output",
    "content": "\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\tDELETE  shift 19\n\tDISTINCT  shift 29\n\tSET  shift 20\n\tCREATE  shift 21\n\tALTER  shift 22\n\tDROP  shift 24\n\tRENAME  shift 23\n\tANALYZE  shift 25\n\tSHOW  shift 26\n\tDESCRIBE  shift 27\n\tEXPLAIN  shift 28\n\t.  reduce 45 (src line 340)\n\n\tany_command  goto 1\n\tcommand  goto 2\n\tselect_statement  goto 3\n\tmissing_select_statement  goto 4\n\tinsert_statement  goto 5\n\tupdate_statement  goto 6\n\tdelete_statement  goto 7\n\tset_statement  goto 8\n\tcreate_statement  goto 9\n\talter_statement  goto 10\n\trename_statement  goto 11\n\tdrop_statement  goto 12\n\tanalyze_statement  goto 13\n\tother_statement  goto 14\n\tdistinct_opt  goto 16\n\nstate 1\n\t$accept:  any_command.$end \n\n\t$end  accept\n\t.  error\n\n\nstate 2\n\tany_command:  command.    (1)\n\n\t.  reduce 1 (src line 152)\n\n\nstate 3\n\tcommand:  select_statement.    (2)\n\tselect_statement:  select_statement.union_op select_statement \n\n\tUNION  shift 31\n\tMINUS  shift 32\n\tEXCEPT  shift 33\n\tINTERSECT  shift 34\n\t.  reduce 2 (src line 158)\n\n\tunion_op  goto 30\n\nstate 4\n\tcommand:  missing_select_statement.    (3)\n\n\t.  reduce 3 (src line 163)\n\n\nstate 5\n\tcommand:  insert_statement.    (4)\n\n\t.  reduce 4 (src line 167)\n\n\nstate 6\n\tcommand:  update_statement.    (5)\n\n\t.  reduce 5 (src line 168)\n\n\nstate 7\n\tcommand:  delete_statement.    (6)\n\n\t.  reduce 6 (src line 169)\n\n\nstate 8\n\tcommand:  set_statement.    (7)\n\n\t.  reduce 7 (src line 170)\n\n\nstate 9\n\tcommand:  create_statement.    (8)\n\n\t.  reduce 8 (src line 171)\n\n\nstate 10\n\tcommand:  alter_statement.    (9)\n\n\t.  reduce 9 (src line 172)\n\n\nstate 11\n\tcommand:  rename_statement.    (10)\n\n\t.  reduce 10 (src line 173)\n\n\nstate 12\n\tcommand:  drop_statement.    (11)\n\n\t.  reduce 11 (src line 174)\n\n\nstate 13\n\tcommand:  analyze_statement.    (12)\n\n\t.  reduce 12 (src line 175)\n\n\nstate 14\n\tcommand:  other_statement.    (13)\n\n\t.  reduce 13 (src line 176)\n\n\nstate 15\n\tselect_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 \n\t$$36: .    (36)\n\n\t.  reduce 36 (src line 299)\n\n\tcomment_opt  goto 35\n\t$$36  goto 36\n\nstate 16\n\tmissing_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 \n\n\tEXISTS  shift 54\n\tNULL  shift 59\n\tVALUES  shift 65\n\tKEYRANGE  shift 55\n\tID  shift 41\n\tSTRING  shift 56\n\tNUMBER  shift 57\n\tVALUE_ARG  shift 58\n\t'('  shift 46\n\t'~'  shift 63\n\tNOT  shift 45\n\t'+'  shift 61\n\t'-'  shift 62\n\t'*'  shift 39\n\tCASE  shift 66\n\tIF  shift 64\n\t.  error\n\n\tselect_expression_list  goto 37\n\tselect_expression  goto 38\n\texpression  goto 40\n\tboolean_expression  goto 42\n\tcondition  goto 44\n\tvalue  goto 47\n\tvalue_expression  goto 43\n\trow_tuple  goto 49\n\tkeyword_as_func  goto 52\n\tsubquery  goto 60\n\tunary_operator  goto 50\n\tcolumn_name  goto 48\n\tcase_expression  goto 53\n\tsql_id  goto 51\n\nstate 17\n\tinsert_statement:  INSERT.comment_opt INTO dml_table_expression column_list_opt row_list on_dup_opt \n\tinsert_statement:  INSERT.comment_opt INTO dml_table_expression SET update_list on_dup_opt \n\t$$36: .    (36)\n\n\t.  reduce 36 (src line 299)\n\n\tcomment_opt  goto 67\n\t$$36  goto 36\n\nstate 18\n\tupdate_statement:  UPDATE.comment_opt dml_table_expression SET update_list where_expression_opt order_by_opt limit_opt \n\t$$36: .    (36)\n\n\t.  reduce 36 (src line 299)\n\n\tcomment_opt  goto 68\n\t$$36  goto 36\n\nstate 19\n\tdelete_statement:  DELETE.comment_opt FROM dml_table_expression where_expression_opt order_by_opt limit_opt \n\t$$36: .    (36)\n\n\t.  reduce 36 (src line 299)\n\n\tcomment_opt  goto 69\n\t$$36  goto 36\n\nstate 20\n\tset_statement:  SET.comment_opt update_list \n\t$$36: .    (36)\n\n\t.  reduce 36 (src line 299)\n\n\tcomment_opt  goto 70\n\t$$36  goto 36\n\nstate 21\n\tcreate_statement:  CREATE.TABLE not_exists_opt ID force_eof \n\tcreate_statement:  CREATE.constraint_opt INDEX sql_id using_opt ON ID force_eof \n\tcreate_statement:  CREATE.VIEW sql_id force_eof \n\tconstraint_opt: .    (201)\n\n\tTABLE  shift 71\n\tVIEW  shift 73\n\tUNIQUE  shift 74\n\t.  reduce 201 (src line 1039)\n\n\tconstraint_opt  goto 72\n\nstate 22\n\talter_statement:  ALTER.ignore_opt TABLE ID non_rename_operation force_eof \n\talter_statement:  ALTER.ignore_opt TABLE ID RENAME to_opt ID \n\talter_statement:  ALTER.VIEW sql_id force_eof \n\tignore_opt: .    (192)\n\n\tVIEW  shift 76\n\tIGNORE  shift 77\n\t.  reduce 192 (src line 1017)\n\n\tignore_opt  goto 75\n\nstate 23\n\trename_statement:  RENAME.TABLE ID TO ID \n\n\tTABLE  shift 78\n\t.  error\n\n\nstate 24\n\tdrop_statement:  DROP.TABLE exists_opt ID \n\tdrop_statement:  DROP.INDEX sql_id ON ID \n\tdrop_statement:  DROP.VIEW exists_opt sql_id force_eof \n\n\tTABLE  shift 79\n\tINDEX  shift 80\n\tVIEW  shift 81\n\t.  error\n\n\nstate 25\n\tanalyze_statement:  ANALYZE.TABLE ID \n\n\tTABLE  shift 82\n\t.  error\n\n\nstate 26\n\tother_statement:  SHOW.force_eof \n\tforce_eof: .    (206)\n\n\t.  reduce 206 (src line 1055)\n\n\tforce_eof  goto 83\n\nstate 27\n\tother_statement:  DESCRIBE.force_eof \n\tforce_eof: .    (206)\n\n\t.  reduce 206 (src line 1055)\n\n\tforce_eof  goto 84\n\nstate 28\n\tother_statement:  EXPLAIN.force_eof \n\tforce_eof: .    (206)\n\n\t.  reduce 206 (src line 1055)\n\n\tforce_eof  goto 85\n\nstate 29\n\tdistinct_opt:  DISTINCT.    (46)\n\n\t.  reduce 46 (src line 344)\n\n\nstate 30\n\tselect_statement:  select_statement union_op.select_statement \n\n\tSELECT  shift 15\n\t.  error\n\n\tselect_statement  goto 86\n\nstate 31\n\tunion_op:  UNION.    (40)\n\tunion_op:  UNION.ALL \n\n\tALL  shift 87\n\t.  reduce 40 (src line 318)\n\n\nstate 32\n\tunion_op:  MINUS.    (42)\n\n\t.  reduce 42 (src line 327)\n\n\nstate 33\n\tunion_op:  EXCEPT.    (43)\n\n\t.  reduce 43 (src line 331)\n\n\nstate 34\n\tunion_op:  INTERSECT.    (44)\n\n\t.  reduce 44 (src line 335)\n\n\nstate 35\n\tselect_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 \n\tdistinct_opt: .    (45)\n\n\tDISTINCT  shift 29\n\t.  reduce 45 (src line 340)\n\n\tdistinct_opt  goto 88\n\nstate 36\n\tcomment_opt:  $$36.comment_list \n\tcomment_list: .    (38)\n\n\t.  reduce 38 (src line 309)\n\n\tcomment_list  goto 89\n\nstate 37\n\tmissing_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 \n\tselect_expression_list:  select_expression_list.',' select_expression \n\tfrom_expression_list_opt: .    (86)\n\n\tFROM  shift 92\n\t','  shift 91\n\t.  reduce 86 (src line 526)\n\n\tfrom_expression_list_opt  goto 90\n\nstate 38\n\tselect_expression_list:  select_expression.    (47)\n\n\t.  reduce 47 (src line 349)\n\n\nstate 39\n\tselect_expression:  '*'.    (49)\n\n\t.  reduce 49 (src line 359)\n\n\nstate 40\n\tselect_expression:  expression.as_lower_opt \n\tas_lower_opt: .    (54)\n\n\tAS  shift 95\n\tID  shift 96\n\t.  reduce 54 (src line 383)\n\n\tas_lower_opt  goto 93\n\tsql_id  goto 94\n\nstate 41\n\tselect_expression:  ID.'.' '*' \n\tcolumn_name:  ID.'.' sql_id \n\tsql_id:  ID.    (205)\n\n\t'.'  shift 97\n\t.  reduce 205 (src line 1049)\n\n\nstate 42\n\texpression:  boolean_expression.    (52)\n\tboolean_expression:  boolean_expression.AND boolean_expression \n\tboolean_expression:  boolean_expression.OR boolean_expression \n\n\tOR  shift 99\n\tAND  shift 98\n\t.  reduce 52 (src line 373)\n\n\nstate 43\n\texpression:  value_expression.    (53)\n\tcondition:  value_expression.compare value_expression \n\tcondition:  value_expression.IN col_tuple \n\tcondition:  value_expression.NOT IN col_tuple \n\tcondition:  value_expression.LIKE value_expression \n\tcondition:  value_expression.NOT LIKE value_expression \n\tcondition:  value_expression.BETWEEN value_expression AND value_expression \n\tcondition:  value_expression.NOT BETWEEN value_expression AND value_expression \n\tcondition:  value_expression.IS NULL \n\tcondition:  value_expression.IS NOT NULL \n\tvalue_expression:  value_expression.'&' value_expression \n\tvalue_expression:  value_expression.'|' value_expression \n\tvalue_expression:  value_expression.'^' value_expression \n\tvalue_expression:  value_expression.'+' value_expression \n\tvalue_expression:  value_expression.'-' value_expression \n\tvalue_expression:  value_expression.'*' value_expression \n\tvalue_expression:  value_expression.'/' value_expression \n\tvalue_expression:  value_expression.'%' value_expression \n\n\tIN  shift 101\n\tIS  shift 105\n\tLIKE  shift 103\n\tBETWEEN  shift 104\n\tLE  shift 117\n\tGE  shift 118\n\tNE  shift 119\n\tNULL_SAFE_EQUAL  shift 120\n\t'='  shift 114\n\t'<'  shift 115\n\t'>'  shift 116\n\tNOT  shift 102\n\t'&'  shift 106\n\t'|'  shift 107\n\t'^'  shift 108\n\t'+'  shift 109\n\t'-'  shift 110\n\t'*'  shift 111\n\t'/'  shift 112\n\t'%'  shift 113\n\t.  reduce 53 (src line 378)\n\n\tcompare  goto 100\n\nstate 44\n\tboolean_expression:  condition.    (90)\n\n\t.  reduce 90 (src line 545)\n\n\nstate 45\n\tboolean_expression:  NOT.boolean_expression \n\n\tEXISTS  shift 54\n\tNULL  shift 59\n\tVALUES  shift 65\n\tKEYRANGE  shift 55\n\tID  shift 123\n\tSTRING  shift 56\n\tNUMBER  shift 57\n\tVALUE_ARG  shift 58\n\t'('  shift 46\n\t'~'  shift 63\n\tNOT  shift 45\n\t'+'  shift 61\n\t'-'  shift 62\n\tCASE  shift 66\n\tIF  shift 64\n\t.  error\n\n\tboolean_expression  goto 121\n\tcondition  goto 44\n\tvalue  goto 47\n\tvalue_expression  goto 122\n\trow_tuple  goto 49\n\tkeyword_as_func  goto 52\n\tsubquery  goto 60\n\tunary_operator  goto 50\n\tcolumn_name  goto 48\n\tcase_expression  goto 53\n\tsql_id  goto 51\n\nstate 46\n\tboolean_expression:  '('.boolean_expression ')' \n\tsubquery:  '('.select_statement ')' \n\trow_tuple:  '('.value_expression_list ')' \n\n\tSELECT  shift 15\n\tEXISTS  shift 54\n\tNULL  shift 59\n\tVALUES  shift 65\n\tKEYRANGE  shift 55\n\tID  shift 123\n\tSTRING  shift 56\n\tNUMBER  shift 57\n\tVALUE_ARG  shift 58\n\t'('  shift 46\n\t'~'  shift 63\n\tNOT  shift 45\n\t'+'  shift 61\n\t'-'  shift 62\n\tCASE  shift 66\n\tIF  shift 64\n\t.  error\n\n\tselect_statement  goto 125\n\tboolean_expression  goto 124\n\tcondition  goto 44\n\tvalue  goto 47\n\tvalue_expression  goto 127\n\tvalue_expression_list  goto 126\n\trow_tuple  goto 49\n\tkeyword_as_func  goto 52\n\tsubquery  goto 60\n\tunary_operator  goto 50\n\tcolumn_name  goto 48\n\tcase_expression  goto 53\n\tsql_id  goto 51\n\nstate 47\n\tvalue_expression:  value.    (119)\n\n\t.  reduce 119 (src line 670)\n\n\nstate 48\n\tvalue_expression:  column_name.    (120)\n\n\t.  reduce 120 (src line 675)\n\n\nstate 49\n\tvalue_expression:  row_tuple.    (121)\n\n\t.  reduce 121 (src line 679)\n\n\nstate 50\n\tvalue_expression:  unary_operator.value_expression \n\n\tNULL  shift 59\n\tVALUES  shift 65\n\tID  shift 123\n\tSTRING  shift 56\n\tNUMBER  shift 57\n\tVALUE_ARG  shift 58\n\t'('  shift 129\n\t'~'  shift 63\n\t'+'  shift 61\n\t'-'  shift 62\n\tCASE  shift 66\n\tIF  shift 64\n\t.  error\n\n\tvalue  goto 47\n\tvalue_expression  goto 128\n\trow_tuple  goto 49\n\tkeyword_as_func  goto 52\n\tsubquery  goto 60\n\tunary_operator  goto 50\n\tcolumn_name  goto 48\n\tcase_expression  goto 53\n\tsql_id  goto 51\n\nstate 51\n\tvalue_expression:  sql_id.'(' ')' \n\tvalue_expression:  sql_id.'(' select_expression_list ')' \n\tvalue_expression:  sql_id.'(' DISTINCT select_expression_list ')' \n\tcolumn_name:  sql_id.    (149)\n\n\t'('  shift 130\n\t.  reduce 149 (src line 815)\n\n\nstate 52\n\tvalue_expression:  keyword_as_func.'(' select_expression_list ')' \n\n\t'('  shift 131\n\t.  error\n\n\nstate 53\n\tvalue_expression:  case_expression.    (135)\n\n\t.  reduce 135 (src line 746)\n\n\nstate 54\n\tcondition:  EXISTS.subquery \n\n\t'('  shift 133\n\t.  error\n\n\tsubquery  goto 132\n\nstate 55\n\tcondition:  KEYRANGE.'(' value ',' value ')' \n\n\t'('  shift 134\n\t.  error\n\n\nstate 56\n\tvalue:  STRING.    (151)\n\n\t.  reduce 151 (src line 825)\n\n\nstate 57\n\tvalue:  NUMBER.    (152)\n\n\t.  reduce 152 (src line 830)\n\n\nstate 58\n\tvalue:  VALUE_ARG.    (153)\n\n\t.  reduce 153 (src line 834)\n\n\nstate 59\n\tvalue:  NULL.    (154)\n\n\t.  reduce 154 (src line 838)\n\n\nstate 60\n\trow_tuple:  subquery.    (184)\n\n\t.  reduce 184 (src line 986)\n\n\nstate 61\n\tunary_operator:  '+'.    (138)\n\n\t.  reduce 138 (src line 761)\n\n\nstate 62\n\tunary_operator:  '-'.    (139)\n\n\t.  reduce 139 (src line 766)\n\n\nstate 63\n\tunary_operator:  '~'.    (140)\n\n\t.  reduce 140 (src line 770)\n\n\nstate 64\n\tkeyword_as_func:  IF.    (136)\n\n\t.  reduce 136 (src line 751)\n\n\nstate 65\n\tkeyword_as_func:  VALUES.    (137)\n\n\t.  reduce 137 (src line 756)\n\n\nstate 66\n\tcase_expression:  CASE.value_expression_opt when_expression_list else_expression_opt END \n\tvalue_expression_opt: .    (142)\n\n\tNULL  shift 59\n\tVALUES  shift 65\n\tID  shift 123\n\tSTRING  shift 56\n\tNUMBER  shift 57\n\tVALUE_ARG  shift 58\n\t'('  shift 129\n\t'~'  shift 63\n\t'+'  shift 61\n\t'-'  shift 62\n\tCASE  shift 66\n\tIF  shift 64\n\t.  reduce 142 (src line 781)\n\n\tvalue  goto 47\n\tvalue_expression  goto 136\n\trow_tuple  goto 49\n\tkeyword_as_func  goto 52\n\tsubquery  goto 60\n\tunary_operator  goto 50\n\tcolumn_name  goto 48\n\tcase_expression  goto 53\n\tvalue_expression_opt  goto 135\n\tsql_id  goto 51\n\nstate 67\n\tinsert_statement:  INSERT comment_opt.INTO dml_table_expression column_list_opt row_list on_dup_opt \n\tinsert_statement:  INSERT comment_opt.INTO dml_table_expression SET update_list on_dup_opt \n\n\tINTO  shift 137\n\t.  error\n\n\nstate 68\n\tupdate_statement:  UPDATE comment_opt.dml_table_expression SET update_list where_expression_opt order_by_opt limit_opt \n\n\tID  shift 139\n\t.  error\n\n\tdml_table_expression  goto 138\n\nstate 69\n\tdelete_statement:  DELETE comment_opt.FROM dml_table_expression where_expression_opt order_by_opt limit_opt \n\n\tFROM  shift 140\n\t.  error\n\n\nstate 70\n\tset_statement:  SET comment_opt.update_list \n\n\tID  shift 123\n\t.  error\n\n\tcolumn_name  goto 143\n\tupdate_list  goto 141\n\tupdate_expression  goto 142\n\tsql_id  goto 144\n\nstate 71\n\tcreate_statement:  CREATE TABLE.not_exists_opt ID force_eof \n\tnot_exists_opt: .    (190)\n\n\tIF  shift 146\n\t.  reduce 190 (src line 1012)\n\n\tnot_exists_opt  goto 145\n\nstate 72\n\tcreate_statement:  CREATE constraint_opt.INDEX sql_id using_opt ON ID force_eof \n\n\tINDEX  shift 147\n\t.  error\n\n\nstate 73\n\tcreate_statement:  CREATE VIEW.sql_id force_eof \n\n\tID  shift 96\n\t.  error\n\n\tsql_id  goto 148\n\nstate 74\n\tconstraint_opt:  UNIQUE.    (202)\n\n\t.  reduce 202 (src line 1041)\n\n\nstate 75\n\talter_statement:  ALTER ignore_opt.TABLE ID non_rename_operation force_eof \n\talter_statement:  ALTER ignore_opt.TABLE ID RENAME to_opt ID \n\n\tTABLE  shift 149\n\t.  error\n\n\nstate 76\n\talter_statement:  ALTER VIEW.sql_id force_eof \n\n\tID  shift 96\n\t.  error\n\n\tsql_id  goto 150\n\nstate 77\n\tignore_opt:  IGNORE.    (193)\n\n\t.  reduce 193 (src line 1019)\n\n\nstate 78\n\trename_statement:  RENAME TABLE.ID TO ID \n\n\tID  shift 151\n\t.  error\n\n\nstate 79\n\tdrop_statement:  DROP TABLE.exists_opt ID \n\texists_opt: .    (188)\n\n\tIF  shift 153\n\t.  reduce 188 (src line 1007)\n\n\texists_opt  goto 152\n\nstate 80\n\tdrop_statement:  DROP INDEX.sql_id ON ID \n\n\tID  shift 96\n\t.  error\n\n\tsql_id  goto 154\n\nstate 81\n\tdrop_statement:  DROP VIEW.exists_opt sql_id force_eof \n\texists_opt: .    (188)\n\n\tIF  shift 153\n\t.  reduce 188 (src line 1007)\n\n\texists_opt  goto 155\n\nstate 82\n\tanalyze_statement:  ANALYZE TABLE.ID \n\n\tID  shift 156\n\t.  error\n\n\nstate 83\n\tother_statement:  SHOW force_eof.    (33)\n\n\t.  reduce 33 (src line 285)\n\n\nstate 84\n\tother_statement:  DESCRIBE force_eof.    (34)\n\n\t.  reduce 34 (src line 290)\n\n\nstate 85\n\tother_statement:  EXPLAIN force_eof.    (35)\n\n\t.  reduce 35 (src line 294)\n\n\nstate 86\n\tselect_statement:  select_statement.union_op select_statement \n\tselect_statement:  select_statement union_op select_statement.    (16)\n\n\t.  reduce 16 (src line 189)\n\n\tunion_op  goto 30\n\nstate 87\n\tunion_op:  UNION ALL.    (41)\n\n\t.  reduce 41 (src line 323)\n\n\nstate 88\n\tselect_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 \n\n\tEXISTS  shift 54\n\tNULL  shift 59\n\tVALUES  shift 65\n\tKEYRANGE  shift 55\n\tID  shift 41\n\tSTRING  shift 56\n\tNUMBER  shift 57\n\tVALUE_ARG  shift 58\n\t'('  shift 46\n\t'~'  shift 63\n\tNOT  shift 45\n\t'+'  shift 61\n\t'-'  shift 62\n\t'*'  shift 39\n\tCASE  shift 66\n\tIF  shift 64\n\t.  error\n\n\tselect_expression_list  goto 157\n\tselect_expression  goto 38\n\texpression  goto 40\n\tboolean_expression  goto 42\n\tcondition  goto 44\n\tvalue  goto 47\n\tvalue_expression  goto 43\n\trow_tuple  goto 49\n\tkeyword_as_func  goto 52\n\tsubquery  goto 60\n\tunary_operator  goto 50\n\tcolumn_name  goto 48\n\tcase_expression  goto 53\n\tsql_id  goto 51\n\nstate 89\n\tcomment_opt:  $$36 comment_list.    (37)\n\tcomment_list:  comment_list.COMMENT \n\n\tCOMMENT  shift 158\n\t.  reduce 37 (src line 303)\n\n\nstate 90\n\tmissing_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 \n\twhere_expression_opt: .    (88)\n\n\tWHERE  shift 160\n\t.  reduce 88 (src line 536)\n\n\twhere_expression_opt  goto 159\n\nstate 91\n\tselect_expression_list:  select_expression_list ','.select_expression \n\n\tEXISTS  shift 54\n\tNULL  shift 59\n\tVALUES  shift 65\n\tKEYRANGE  shift 55\n\tID  shift 41\n\tSTRING  shift 56\n\tNUMBER  shift 57\n\tVALUE_ARG  shift 58\n\t'('  shift 46\n\t'~'  shift 63\n\tNOT  shift 45\n\t'+'  shift 61\n\t'-'  shift 62\n\t'*'  shift 39\n\tCASE  shift 66\n\tIF  shift 64\n\t.  error\n\n\tselect_expression  goto 161\n\texpression  goto 40\n\tboolean_expression  goto 42\n\tcondition  goto 44\n\tvalue  goto 47\n\tvalue_expression  goto 43\n\trow_tuple  goto 49\n\tkeyword_as_func  goto 52\n\tsubquery  goto 60\n\tunary_operator  goto 50\n\tcolumn_name  goto 48\n\tcase_expression  goto 53\n\tsql_id  goto 51\n\nstate 92\n\tfrom_expression_list_opt:  FROM.table_expression_list \n\n\tID  shift 166\n\t'('  shift 165\n\t.  error\n\n\ttable_expression_list  goto 162\n\ttable_expression  goto 163\n\tsimple_table_expression  goto 164\n\tsubquery  goto 167\n\nstate 93\n\tselect_expression:  expression as_lower_opt.    (50)\n\n\t.  reduce 50 (src line 364)\n\n\nstate 94\n\tas_lower_opt:  sql_id.    (55)\n\n\t.  reduce 55 (src line 387)\n\n\nstate 95\n\tas_lower_opt:  AS.sql_id \n\n\tID  shift 96\n\t.  error\n\n\tsql_id  goto 168\n\nstate 96\n\tsql_id:  ID.    (205)\n\n\t.  reduce 205 (src line 1049)\n\n\nstate 97\n\tselect_expression:  ID '.'.'*' \n\tcolumn_name:  ID '.'.sql_id \n\n\tID  shift 96\n\t'*'  shift 169\n\t.  error\n\n\tsql_id  goto 170\n\nstate 98\n\tboolean_expression:  boolean_expression AND.boolean_expression \n\n\tEXISTS  shift 54\n\tNULL  shift 59\n\tVALUES  shift 65\n\tKEYRANGE  shift 55\n\tID  shift 123\n\tSTRING  shift 56\n\tNUMBER  shift 57\n\tVALUE_ARG  shift 58\n\t'('  shift 46\n\t'~'  shift 63\n\tNOT  shift 45\n\t'+'  shift 61\n\t'-'  shift 62\n\tCASE  shift 66\n\tIF  shift 64\n\t.  error\n\n\tboolean_expression  goto 171\n\tcondition  goto 44\n\tvalue  goto 47\n\tvalue_expression  goto 122\n\trow_tuple  goto 49\n\tkeyword_as_func  goto 52\n\tsubquery  goto 60\n\tunary_operator  goto 50\n\tcolumn_name  goto 48\n\tcase_expression  goto 53\n\tsql_id  goto 51\n\nstate 99\n\tboolean_expression:  boolean_expression OR.boolean_expression \n\n\tEXISTS  shift 54\n\tNULL  shift 59\n\tVALUES  shift 65\n\tKEYRANGE  shift 55\n\tID  shift 123\n\tSTRING  shift 56\n\tNUMBER  shift 57\n\tVALUE_ARG  shift 58\n\t'('  shift 46\n\t'~'  shift 63\n\tNOT  shift 45\n\t'+'  shift 61\n\t'-'  shift 62\n\tCASE  shift 66\n\tIF  shift 64\n\t.  error\n\n\tboolean_expression  goto 172\n\tcondition  goto 44\n\tvalue  goto 47\n\tvalue_expression  goto 122\n\trow_tuple  goto 49\n\tkeyword_as_func  goto 52\n\tsubquery  goto 60\n\tunary_operator  goto 50\n\tcolumn_name  goto 48\n\tcase_expression  goto 53\n\tsql_id  goto 51\n\nstate 100\n\tcondition:  value_expression compare.value_expression \n\n\tNULL  shift 59\n\tVALUES  shift 65\n\tID  shift 123\n\tSTRING  shift 56\n\tNUMBER  shift 57\n\tVALUE_ARG  shift 58\n\t'('  shift 129\n\t'~'  shift 63\n\t'+'  shift 61\n\t'-'  shift 62\n\tCASE  shift 66\n\tIF  shift 64\n\t.  error\n\n\tvalue  goto 47\n\tvalue_expression  goto 173\n\trow_tuple  goto 49\n\tkeyword_as_func  goto 52\n\tsubquery  goto 60\n\tunary_operator  goto 50\n\tcolumn_name  goto 48\n\tcase_expression  goto 53\n\tsql_id  goto 51\n\nstate 101\n\tcondition:  value_expression IN.col_tuple \n\n\tLIST_ARG  shift 177\n\t'('  shift 175\n\t.  error\n\n\tcol_tuple  goto 174\n\tsubquery  goto 176\n\nstate 102\n\tcondition:  value_expression NOT.IN col_tuple \n\tcondition:  value_expression NOT.LIKE value_expression \n\tcondition:  value_expression NOT.BETWEEN value_expression AND value_expression \n\n\tIN  shift 178\n\tLIKE  shift 179\n\tBETWEEN  shift 180\n\t.  error\n\n\nstate 103\n\tcondition:  value_expression LIKE.value_expression \n\n\tNULL  shift 59\n\tVALUES  shift 65\n\tID  shift 123\n\tSTRING  shift 56\n\tNUMBER  shift 57\n\tVALUE_ARG  shift 58\n\t'('  shift 129\n\t'~'  shift 63\n\t'+'  shift 61\n\t'-'  shift 62\n\tCASE  shift 66\n\tIF  shift 64\n\t.  error\n\n\tvalue  goto 47\n\tvalue_expression  goto 181\n\trow_tuple  goto 49\n\tkeyword_as_func  goto 52\n\tsubquery  goto 60\n\tunary_operator  goto 50\n\tcolumn_name  goto 48\n\tcase_expression  goto 53\n\tsql_id  goto 51\n\nstate 104\n\tcondition:  value_expression BETWEEN.value_expression AND value_expression \n\n\tNULL  shift 59\n\tVALUES  shift 65\n\tID  shift 123\n\tSTRING  shift 56\n\tNUMBER  shift 57\n\tVALUE_ARG  shift 58\n\t'('  shift 129\n\t'~'  shift 63\n\t'+'  shift 61\n\t'-'  shift 62\n\tCASE  shift 66\n\tIF  shift 64\n\t.  error\n\n\tvalue  goto 47\n\tvalue_expression  goto 182\n\trow_tuple  goto 49\n\tkeyword_as_func  goto 52\n\tsubquery  goto 60\n\tunary_operator  goto 50\n\tcolumn_name  goto 48\n\tcase_expression  goto 53\n\tsql_id  goto 51\n\nstate 105\n\tcondition:  value_expression IS.NULL \n\tcondition:  value_expression IS.NOT NULL \n\n\tNULL  shift 183\n\tNOT  shift 184\n\t.  error\n\n\nstate 106\n\tvalue_expression:  value_expression '&'.value_expression \n\n\tNULL  shift 59\n\tVALUES  shift 65\n\tID  shift 123\n\tSTRING  shift 56\n\tNUMBER  shift 57\n\tVALUE_ARG  shift 58\n\t'('  shift 129\n\t'~'  shift 63\n\t'+'  shift 61\n\t'-'  shift 62\n\tCASE  shift 66\n\tIF  shift 64\n\t.  error\n\n\tvalue  goto 47\n\tvalue_expression  goto 185\n\trow_tuple  goto 49\n\tkeyword_as_func  goto 52\n\tsubquery  goto 60\n\tunary_operator  goto 50\n\tcolumn_name  goto 48\n\tcase_expression  goto 53\n\tsql_id  goto 51\n\nstate 107\n\tvalue_expression:  value_expression '|'.value_expression \n\n\tNULL  shift 59\n\tVALUES  shift 65\n\tID  shift 123\n\tSTRING  shift 56\n\tNUMBER  shift 57\n\tVALUE_ARG  shift 58\n\t'('  shift 129\n\t'~'  shift 63\n\t'+'  shift 61\n\t'-'  shift 62\n\tCASE  shift 66\n\tIF  shift 64\n\t.  error\n\n\tvalue  goto 47\n\tvalue_expression  goto 186\n\trow_tuple  goto 49\n\tkeyword_as_func  goto 52\n\tsubquery  goto 60\n\tunary_operator  goto 50\n\tcolumn_name  goto 48\n\tcase_expression  goto 53\n\tsql_id  goto 51\n\nstate 108\n\tvalue_expression:  value_expression '^'.value_expression \n\n\tNULL  shift 59\n\tVALUES  shift 65\n\tID  shift 123\n\tSTRING  shift 56\n\tNUMBER  shift 57\n\tVALUE_ARG  shift 58\n\t'('  shift 129\n\t'~'  shift 63\n\t'+'  shift 61\n\t'-'  shift 62\n\tCASE  shift 66\n\tIF  shift 64\n\t.  error\n\n\tvalue  goto 47\n\tvalue_expression  goto 187\n\trow_tuple  goto 49\n\tkeyword_as_func  goto 52\n\tsubquery  goto 60\n\tunary_operator  goto 50\n\tcolumn_name  goto 48\n\tcase_expression  goto 53\n\tsql_id  goto 51\n\nstate 109\n\tvalue_expression:  value_expression '+'.value_expression \n\n\tNULL  shift 59\n\tVALUES  shift 65\n\tID  shift 123\n\tSTRING  shift 56\n\tNUMBER  shift 57\n\tVALUE_ARG  shift 58\n\t'('  shift 129\n\t'~'  shift 63\n\t'+'  shift 61\n\t'-'  shift 62\n\tCASE  shift 66\n\tIF  shift 64\n\t.  error\n\n\tvalue  goto 47\n\tvalue_expression  goto 188\n\trow_tuple  goto 49\n\tkeyword_as_func  goto 52\n\tsubquery  goto 60\n\tunary_operator  goto 50\n\tcolumn_name  goto 48\n\tcase_expression  goto 53\n\tsql_id  goto 51\n\nstate 110\n\tvalue_expression:  value_expression '-'.value_expression \n\n\tNULL  shift 59\n\tVALUES  shift 65\n\tID  shift 123\n\tSTRING  shift 56\n\tNUMBER  shift 57\n\tVALUE_ARG  shift 58\n\t'('  shift 129\n\t'~'  shift 63\n\t'+'  shift 61\n\t'-'  shift 62\n\tCASE  shift 66\n\tIF  shift 64\n\t.  error\n\n\tvalue  goto 47\n\tvalue_expression  goto 189\n\trow_tuple  goto 49\n\tkeyword_as_func  goto 52\n\tsubquery  goto 60\n\tunary_operator  goto 50\n\tcolumn_name  goto 48\n\tcase_expression  goto 53\n\tsql_id  goto 51\n\nstate 111\n\tvalue_expression:  value_expression '*'.value_expression \n\n\tNULL  shift 59\n\tVALUES  shift 65\n\tID  shift 123\n\tSTRING  shift 56\n\tNUMBER  shift 57\n\tVALUE_ARG  shift 58\n\t'('  shift 129\n\t'~'  shift 63\n\t'+'  shift 61\n\t'-'  shift 62\n\tCASE  shift 66\n\tIF  shift 64\n\t.  error\n\n\tvalue  goto 47\n\tvalue_expression  goto 190\n\trow_tuple  goto 49\n\tkeyword_as_func  goto 52\n\tsubquery  goto 60\n\tunary_operator  goto 50\n\tcolumn_name  goto 48\n\tcase_expression  goto 53\n\tsql_id  goto 51\n\nstate 112\n\tvalue_expression:  value_expression '/'.value_expression \n\n\tNULL  shift 59\n\tVALUES  shift 65\n\tID  shift 123\n\tSTRING  shift 56\n\tNUMBER  shift 57\n\tVALUE_ARG  shift 58\n\t'('  shift 129\n\t'~'  shift 63\n\t'+'  shift 61\n\t'-'  shift 62\n\tCASE  shift 66\n\tIF  shift 64\n\t.  error\n\n\tvalue  goto 47\n\tvalue_expression  goto 191\n\trow_tuple  goto 49\n\tkeyword_as_func  goto 52\n\tsubquery  goto 60\n\tunary_operator  goto 50\n\tcolumn_name  goto 48\n\tcase_expression  goto 53\n\tsql_id  goto 51\n\nstate 113\n\tvalue_expression:  value_expression '%'.value_expression \n\n\tNULL  shift 59\n\tVALUES  shift 65\n\tID  shift 123\n\tSTRING  shift 56\n\tNUMBER  shift 57\n\tVALUE_ARG  shift 58\n\t'('  shift 129\n\t'~'  shift 63\n\t'+'  shift 61\n\t'-'  shift 62\n\tCASE  shift 66\n\tIF  shift 64\n\t.  error\n\n\tvalue  goto 47\n\tvalue_expression  goto 192\n\trow_tuple  goto 49\n\tkeyword_as_func  goto 52\n\tsubquery  goto 60\n\tunary_operator  goto 50\n\tcolumn_name  goto 48\n\tcase_expression  goto 53\n\tsql_id  goto 51\n\nstate 114\n\tcompare:  '='.    (106)\n\n\t.  reduce 106 (src line 610)\n\n\nstate 115\n\tcompare:  '<'.    (107)\n\n\t.  reduce 107 (src line 615)\n\n\nstate 116\n\tcompare:  '>'.    (108)\n\n\t.  reduce 108 (src line 619)\n\n\nstate 117\n\tcompare:  LE.    (109)\n\n\t.  reduce 109 (src line 623)\n\n\nstate 118\n\tcompare:  GE.    (110)\n\n\t.  reduce 110 (src line 627)\n\n\nstate 119\n\tcompare:  NE.    (111)\n\n\t.  reduce 111 (src line 631)\n\n\nstate 120\n\tcompare:  NULL_SAFE_EQUAL.    (112)\n\n\t.  reduce 112 (src line 635)\n\n\nstate 121\n\tboolean_expression:  boolean_expression.AND boolean_expression \n\tboolean_expression:  boolean_expression.OR boolean_expression \n\tboolean_expression:  NOT boolean_expression.    (93)\n\n\t.  reduce 93 (src line 555)\n\n\nstate 122\n\tcondition:  value_expression.compare value_expression \n\tcondition:  value_expression.IN col_tuple \n\tcondition:  value_expression.NOT IN col_tuple \n\tcondition:  value_expression.LIKE value_expression \n\tcondition:  value_expression.NOT LIKE value_expression \n\tcondition:  value_expression.BETWEEN value_expression AND value_expression \n\tcondition:  value_expression.NOT BETWEEN value_expression AND value_expression \n\tcondition:  value_expression.IS NULL \n\tcondition:  value_expression.IS NOT NULL \n\tvalue_expression:  value_expression.'&' value_expression \n\tvalue_expression:  value_expression.'|' value_expression \n\tvalue_expression:  value_expression.'^' value_expression \n\tvalue_expression:  value_expression.'+' value_expression \n\tvalue_expression:  value_expression.'-' value_expression \n\tvalue_expression:  value_expression.'*' value_expression \n\tvalue_expression:  value_expression.'/' value_expression \n\tvalue_expression:  value_expression.'%' value_expression \n\n\tIN  shift 101\n\tIS  shift 105\n\tLIKE  shift 103\n\tBETWEEN  shift 104\n\tLE  shift 117\n\tGE  shift 118\n\tNE  shift 119\n\tNULL_SAFE_EQUAL  shift 120\n\t'='  shift 114\n\t'<'  shift 115\n\t'>'  shift 116\n\tNOT  shift 102\n\t'&'  shift 106\n\t'|'  shift 107\n\t'^'  shift 108\n\t'+'  shift 109\n\t'-'  shift 110\n\t'*'  shift 111\n\t'/'  shift 112\n\t'%'  shift 113\n\t.  error\n\n\tcompare  goto 100\n\nstate 123\n\tcolumn_name:  ID.'.' sql_id \n\tsql_id:  ID.    (205)\n\n\t'.'  shift 193\n\t.  reduce 205 (src line 1049)\n\n\nstate 124\n\tboolean_expression:  boolean_expression.AND boolean_expression \n\tboolean_expression:  boolean_expression.OR boolean_expression \n\tboolean_expression:  '(' boolean_expression.')' \n\n\tOR  shift 99\n\tAND  shift 98\n\t')'  shift 194\n\t.  error\n\n\nstate 125\n\tselect_statement:  select_statement.union_op select_statement \n\tsubquery:  '(' select_statement.')' \n\n\tUNION  shift 31\n\tMINUS  shift 32\n\tEXCEPT  shift 33\n\tINTERSECT  shift 34\n\t')'  shift 195\n\t.  error\n\n\tunion_op  goto 30\n\nstate 126\n\tvalue_expression_list:  value_expression_list.',' value_expression \n\trow_tuple:  '(' value_expression_list.')' \n\n\t','  shift 196\n\t')'  shift 197\n\t.  error\n\n\nstate 127\n\tcondition:  value_expression.compare value_expression \n\tcondition:  value_expression.IN col_tuple \n\tcondition:  value_expression.NOT IN col_tuple \n\tcondition:  value_expression.LIKE value_expression \n\tcondition:  value_expression.NOT LIKE value_expression \n\tcondition:  value_expression.BETWEEN value_expression AND value_expression \n\tcondition:  value_expression.NOT BETWEEN value_expression AND value_expression \n\tcondition:  value_expression.IS NULL \n\tcondition:  value_expression.IS NOT NULL \n\tvalue_expression_list:  value_expression.    (117)\n\tvalue_expression:  value_expression.'&' value_expression \n\tvalue_expression:  value_expression.'|' value_expression \n\tvalue_expression:  value_expression.'^' value_expression \n\tvalue_expression:  value_expression.'+' value_expression \n\tvalue_expression:  value_expression.'-' value_expression \n\tvalue_expression:  value_expression.'*' value_expression \n\tvalue_expression:  value_expression.'/' value_expression \n\tvalue_expression:  value_expression.'%' value_expression \n\n\tIN  shift 101\n\tIS  shift 105\n\tLIKE  shift 103\n\tBETWEEN  shift 104\n\tLE  shift 117\n\tGE  shift 118\n\tNE  shift 119\n\tNULL_SAFE_EQUAL  shift 120\n\t'='  shift 114\n\t'<'  shift 115\n\t'>'  shift 116\n\tNOT  shift 102\n\t'&'  shift 106\n\t'|'  shift 107\n\t'^'  shift 108\n\t'+'  shift 109\n\t'-'  shift 110\n\t'*'  shift 111\n\t'/'  shift 112\n\t'%'  shift 113\n\t.  reduce 117 (src line 660)\n\n\tcompare  goto 100\n\nstate 128\n\tvalue_expression:  value_expression.'&' value_expression \n\tvalue_expression:  value_expression.'|' value_expression \n\tvalue_expression:  value_expression.'^' value_expression \n\tvalue_expression:  value_expression.'+' value_expression \n\tvalue_expression:  value_expression.'-' value_expression \n\tvalue_expression:  value_expression.'*' value_expression \n\tvalue_expression:  value_expression.'/' value_expression \n\tvalue_expression:  value_expression.'%' value_expression \n\tvalue_expression:  unary_operator value_expression.    (130)\n\n\t.  reduce 130 (src line 715)\n\n\nstate 129\n\tsubquery:  '('.select_statement ')' \n\trow_tuple:  '('.value_expression_list ')' \n\n\tSELECT  shift 15\n\tNULL  shift 59\n\tVALUES  shift 65\n\tID  shift 123\n\tSTRING  shift 56\n\tNUMBER  shift 57\n\tVALUE_ARG  shift 58\n\t'('  shift 129\n\t'~'  shift 63\n\t'+'  shift 61\n\t'-'  shift 62\n\tCASE  shift 66\n\tIF  shift 64\n\t.  error\n\n\tselect_statement  goto 125\n\tvalue  goto 47\n\tvalue_expression  goto 198\n\tvalue_expression_list  goto 126\n\trow_tuple  goto 49\n\tkeyword_as_func  goto 52\n\tsubquery  goto 60\n\tunary_operator  goto 50\n\tcolumn_name  goto 48\n\tcase_expression  goto 53\n\tsql_id  goto 51\n\nstate 130\n\tvalue_expression:  sql_id '('.')' \n\tvalue_expression:  sql_id '('.select_expression_list ')' \n\tvalue_expression:  sql_id '('.DISTINCT select_expression_list ')' \n\n\tDISTINCT  shift 201\n\tEXISTS  shift 54\n\tNULL  shift 59\n\tVALUES  shift 65\n\tKEYRANGE  shift 55\n\tID  shift 41\n\tSTRING  shift 56\n\tNUMBER  shift 57\n\tVALUE_ARG  shift 58\n\t'('  shift 46\n\t'~'  shift 63\n\tNOT  shift 45\n\t'+'  shift 61\n\t'-'  shift 62\n\t'*'  shift 39\n\tCASE  shift 66\n\tIF  shift 64\n\t')'  shift 199\n\t.  error\n\n\tselect_expression_list  goto 200\n\tselect_expression  goto 38\n\texpression  goto 40\n\tboolean_expression  goto 42\n\tcondition  goto 44\n\tvalue  goto 47\n\tvalue_expression  goto 43\n\trow_tuple  goto 49\n\tkeyword_as_func  goto 52\n\tsubquery  goto 60\n\tunary_operator  goto 50\n\tcolumn_name  goto 48\n\tcase_expression  goto 53\n\tsql_id  goto 51\n\nstate 131\n\tvalue_expression:  keyword_as_func '('.select_expression_list ')' \n\n\tEXISTS  shift 54\n\tNULL  shift 59\n\tVALUES  shift 65\n\tKEYRANGE  shift 55\n\tID  shift 41\n\tSTRING  shift 56\n\tNUMBER  shift 57\n\tVALUE_ARG  shift 58\n\t'('  shift 46\n\t'~'  shift 63\n\tNOT  shift 45\n\t'+'  shift 61\n\t'-'  shift 62\n\t'*'  shift 39\n\tCASE  shift 66\n\tIF  shift 64\n\t.  error\n\n\tselect_expression_list  goto 202\n\tselect_expression  goto 38\n\texpression  goto 40\n\tboolean_expression  goto 42\n\tcondition  goto 44\n\tvalue  goto 47\n\tvalue_expression  goto 43\n\trow_tuple  goto 49\n\tkeyword_as_func  goto 52\n\tsubquery  goto 60\n\tunary_operator  goto 50\n\tcolumn_name  goto 48\n\tcase_expression  goto 53\n\tsql_id  goto 51\n\nstate 132\n\tcondition:  EXISTS subquery.    (104)\n\n\t.  reduce 104 (src line 601)\n\n\nstate 133\n\tsubquery:  '('.select_statement ')' \n\n\tSELECT  shift 15\n\t.  error\n\n\tselect_statement  goto 125\n\nstate 134\n\tcondition:  KEYRANGE '('.value ',' value ')' \n\n\tNULL  shift 59\n\tSTRING  shift 56\n\tNUMBER  shift 57\n\tVALUE_ARG  shift 58\n\t.  error\n\n\tvalue  goto 203\n\nstate 135\n\tcase_expression:  CASE value_expression_opt.when_expression_list else_expression_opt END \n\n\tWHEN  shift 206\n\t.  error\n\n\twhen_expression_list  goto 204\n\twhen_expression  goto 205\n\nstate 136\n\tvalue_expression:  value_expression.'&' value_expression \n\tvalue_expression:  value_expression.'|' value_expression \n\tvalue_expression:  value_expression.'^' value_expression \n\tvalue_expression:  value_expression.'+' value_expression \n\tvalue_expression:  value_expression.'-' value_expression \n\tvalue_expression:  value_expression.'*' value_expression \n\tvalue_expression:  value_expression.'/' value_expression \n\tvalue_expression:  value_expression.'%' value_expression \n\tvalue_expression_opt:  value_expression.    (143)\n\n\t'&'  shift 106\n\t'|'  shift 107\n\t'^'  shift 108\n\t'+'  shift 109\n\t'-'  shift 110\n\t'*'  shift 111\n\t'/'  shift 112\n\t'%'  shift 113\n\t.  reduce 143 (src line 785)\n\n\nstate 137\n\tinsert_statement:  INSERT comment_opt INTO.dml_table_expression column_list_opt row_list on_dup_opt \n\tinsert_statement:  INSERT comment_opt INTO.dml_table_expression SET update_list on_dup_opt \n\n\tID  shift 139\n\t.  error\n\n\tdml_table_expression  goto 207\n\nstate 138\n\tupdate_statement:  UPDATE comment_opt dml_table_expression.SET update_list where_expression_opt order_by_opt limit_opt \n\n\tSET  shift 208\n\t.  error\n\n\nstate 139\n\tdml_table_expression:  ID.    (78)\n\tdml_table_expression:  ID.'.' ID \n\n\t'.'  shift 209\n\t.  reduce 78 (src line 489)\n\n\nstate 140\n\tdelete_statement:  DELETE comment_opt FROM.dml_table_expression where_expression_opt order_by_opt limit_opt \n\n\tID  shift 139\n\t.  error\n\n\tdml_table_expression  goto 210\n\nstate 141\n\tset_statement:  SET comment_opt update_list.    (21)\n\tupdate_list:  update_list.',' update_expression \n\n\t','  shift 211\n\t.  reduce 21 (src line 222)\n\n\nstate 142\n\tupdate_list:  update_expression.    (185)\n\n\t.  reduce 185 (src line 991)\n\n\nstate 143\n\tupdate_expression:  column_name.'=' value_expression \n\n\t'='  shift 212\n\t.  error\n\n\nstate 144\n\tcolumn_name:  sql_id.    (149)\n\n\t.  reduce 149 (src line 815)\n\n\nstate 145\n\tcreate_statement:  CREATE TABLE not_exists_opt.ID force_eof \n\n\tID  shift 213\n\t.  error\n\n\nstate 146\n\tnot_exists_opt:  IF.NOT EXISTS \n\n\tNOT  shift 214\n\t.  error\n\n\nstate 147\n\tcreate_statement:  CREATE constraint_opt INDEX.sql_id using_opt ON ID force_eof \n\n\tID  shift 96\n\t.  error\n\n\tsql_id  goto 215\n\nstate 148\n\tcreate_statement:  CREATE VIEW sql_id.force_eof \n\tforce_eof: .    (206)\n\n\t.  reduce 206 (src line 1055)\n\n\tforce_eof  goto 216\n\nstate 149\n\talter_statement:  ALTER ignore_opt TABLE.ID non_rename_operation force_eof \n\talter_statement:  ALTER ignore_opt TABLE.ID RENAME to_opt ID \n\n\tID  shift 217\n\t.  error\n\n\nstate 150\n\talter_statement:  ALTER VIEW sql_id.force_eof \n\tforce_eof: .    (206)\n\n\t.  reduce 206 (src line 1055)\n\n\tforce_eof  goto 218\n\nstate 151\n\trename_statement:  RENAME TABLE ID.TO ID \n\n\tTO  shift 219\n\t.  error\n\n\nstate 152\n\tdrop_statement:  DROP TABLE exists_opt.ID \n\n\tID  shift 220\n\t.  error\n\n\nstate 153\n\texists_opt:  IF.EXISTS \n\n\tEXISTS  shift 221\n\t.  error\n\n\nstate 154\n\tdrop_statement:  DROP INDEX sql_id.ON ID \n\n\tON  shift 222\n\t.  error\n\n\nstate 155\n\tdrop_statement:  DROP VIEW exists_opt.sql_id force_eof \n\n\tID  shift 96\n\t.  error\n\n\tsql_id  goto 223\n\nstate 156\n\tanalyze_statement:  ANALYZE TABLE ID.    (32)\n\n\t.  reduce 32 (src line 279)\n\n\nstate 157\n\tselect_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 \n\tselect_expression_list:  select_expression_list.',' select_expression \n\tfrom_expression_list_opt: .    (86)\n\n\tFROM  shift 92\n\t','  shift 91\n\t.  reduce 86 (src line 526)\n\n\tfrom_expression_list_opt  goto 224\n\nstate 158\n\tcomment_list:  comment_list COMMENT.    (39)\n\n\t.  reduce 39 (src line 313)\n\n\nstate 159\n\tmissing_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 \n\tgroup_by_opt: .    (155)\n\n\tGROUP  shift 226\n\t.  reduce 155 (src line 843)\n\n\tgroup_by_opt  goto 225\n\nstate 160\n\twhere_expression_opt:  WHERE.boolean_expression \n\n\tEXISTS  shift 54\n\tNULL  shift 59\n\tVALUES  shift 65\n\tKEYRANGE  shift 55\n\tID  shift 123\n\tSTRING  shift 56\n\tNUMBER  shift 57\n\tVALUE_ARG  shift 58\n\t'('  shift 46\n\t'~'  shift 63\n\tNOT  shift 45\n\t'+'  shift 61\n\t'-'  shift 62\n\tCASE  shift 66\n\tIF  shift 64\n\t.  error\n\n\tboolean_expression  goto 227\n\tcondition  goto 44\n\tvalue  goto 47\n\tvalue_expression  goto 122\n\trow_tuple  goto 49\n\tkeyword_as_func  goto 52\n\tsubquery  goto 60\n\tunary_operator  goto 50\n\tcolumn_name  goto 48\n\tcase_expression  goto 53\n\tsql_id  goto 51\n\nstate 161\n\tselect_expression_list:  select_expression_list ',' select_expression.    (48)\n\n\t.  reduce 48 (src line 354)\n\n\nstate 162\n\ttable_expression_list:  table_expression_list.',' table_expression \n\tfrom_expression_list_opt:  FROM table_expression_list.    (87)\n\n\t','  shift 228\n\t.  reduce 87 (src line 530)\n\n\nstate 163\n\ttable_expression_list:  table_expression.    (57)\n\ttable_expression:  table_expression.join_type table_expression \n\ttable_expression:  table_expression.join_type table_expression ON boolean_expression \n\n\tJOIN  shift 230\n\tSTRAIGHT_JOIN  shift 231\n\tLEFT  shift 232\n\tRIGHT  shift 233\n\tINNER  shift 234\n\tCROSS  shift 235\n\tNATURAL  shift 236\n\t.  reduce 57 (src line 396)\n\n\tjoin_type  goto 229\n\nstate 164\n\ttable_expression:  simple_table_expression.as_opt index_hint_list \n\tas_opt: .    (63)\n\n\tAS  shift 239\n\tID  shift 238\n\t.  reduce 63 (src line 424)\n\n\tas_opt  goto 237\n\nstate 165\n\ttable_expression:  '('.table_expression ')' \n\tsubquery:  '('.select_statement ')' \n\n\tSELECT  shift 15\n\tID  shift 166\n\t'('  shift 165\n\t.  error\n\n\tselect_statement  goto 125\n\ttable_expression  goto 240\n\tsimple_table_expression  goto 164\n\tsubquery  goto 167\n\nstate 166\n\tsimple_table_expression:  ID.    (75)\n\tsimple_table_expression:  ID.'.' ID \n\n\t'.'  shift 241\n\t.  reduce 75 (src line 475)\n\n\nstate 167\n\tsimple_table_expression:  subquery.    (77)\n\n\t.  reduce 77 (src line 484)\n\n\nstate 168\n\tas_lower_opt:  AS sql_id.    (56)\n\n\t.  reduce 56 (src line 391)\n\n\nstate 169\n\tselect_expression:  ID '.' '*'.    (51)\n\n\t.  reduce 51 (src line 368)\n\n\nstate 170\n\tcolumn_name:  ID '.' sql_id.    (150)\n\n\t.  reduce 150 (src line 820)\n\n\nstate 171\n\tboolean_expression:  boolean_expression.AND boolean_expression \n\tboolean_expression:  boolean_expression AND boolean_expression.    (91)\n\tboolean_expression:  boolean_expression.OR boolean_expression \n\n\t.  reduce 91 (src line 547)\n\n\nstate 172\n\tboolean_expression:  boolean_expression.AND boolean_expression \n\tboolean_expression:  boolean_expression.OR boolean_expression \n\tboolean_expression:  boolean_expression OR boolean_expression.    (92)\n\n\tAND  shift 98\n\t.  reduce 92 (src line 551)\n\n\nstate 173\n\tcondition:  value_expression compare value_expression.    (95)\n\tvalue_expression:  value_expression.'&' value_expression \n\tvalue_expression:  value_expression.'|' value_expression \n\tvalue_expression:  value_expression.'^' value_expression \n\tvalue_expression:  value_expression.'+' value_expression \n\tvalue_expression:  value_expression.'-' value_expression \n\tvalue_expression:  value_expression.'*' value_expression \n\tvalue_expression:  value_expression.'/' value_expression \n\tvalue_expression:  value_expression.'%' value_expression \n\n\t'&'  shift 106\n\t'|'  shift 107\n\t'^'  shift 108\n\t'+'  shift 109\n\t'-'  shift 110\n\t'*'  shift 111\n\t'/'  shift 112\n\t'%'  shift 113\n\t.  reduce 95 (src line 564)\n\n\nstate 174\n\tcondition:  value_expression IN col_tuple.    (96)\n\n\t.  reduce 96 (src line 569)\n\n\nstate 175\n\tcol_tuple:  '('.value_expression_list ')' \n\tsubquery:  '('.select_statement ')' \n\n\tSELECT  shift 15\n\tNULL  shift 59\n\tVALUES  shift 65\n\tID  shift 123\n\tSTRING  shift 56\n\tNUMBER  shift 57\n\tVALUE_ARG  shift 58\n\t'('  shift 129\n\t'~'  shift 63\n\t'+'  shift 61\n\t'-'  shift 62\n\tCASE  shift 66\n\tIF  shift 64\n\t.  error\n\n\tselect_statement  goto 125\n\tvalue  goto 47\n\tvalue_expression  goto 198\n\tvalue_expression_list  goto 242\n\trow_tuple  goto 49\n\tkeyword_as_func  goto 52\n\tsubquery  goto 60\n\tunary_operator  goto 50\n\tcolumn_name  goto 48\n\tcase_expression  goto 53\n\tsql_id  goto 51\n\nstate 176\n\tcol_tuple:  subquery.    (114)\n\n\t.  reduce 114 (src line 645)\n\n\nstate 177\n\tcol_tuple:  LIST_ARG.    (115)\n\n\t.  reduce 115 (src line 649)\n\n\nstate 178\n\tcondition:  value_expression NOT IN.col_tuple \n\n\tLIST_ARG  shift 177\n\t'('  shift 175\n\t.  error\n\n\tcol_tuple  goto 243\n\tsubquery  goto 176\n\nstate 179\n\tcondition:  value_expression NOT LIKE.value_expression \n\n\tNULL  shift 59\n\tVALUES  shift 65\n\tID  shift 123\n\tSTRING  shift 56\n\tNUMBER  shift 57\n\tVALUE_ARG  shift 58\n\t'('  shift 129\n\t'~'  shift 63\n\t'+'  shift 61\n\t'-'  shift 62\n\tCASE  shift 66\n\tIF  shift 64\n\t.  error\n\n\tvalue  goto 47\n\tvalue_expression  goto 244\n\trow_tuple  goto 49\n\tkeyword_as_func  goto 52\n\tsubquery  goto 60\n\tunary_operator  goto 50\n\tcolumn_name  goto 48\n\tcase_expression  goto 53\n\tsql_id  goto 51\n\nstate 180\n\tcondition:  value_expression NOT BETWEEN.value_expression AND value_expression \n\n\tNULL  shift 59\n\tVALUES  shift 65\n\tID  shift 123\n\tSTRING  shift 56\n\tNUMBER  shift 57\n\tVALUE_ARG  shift 58\n\t'('  shift 129\n\t'~'  shift 63\n\t'+'  shift 61\n\t'-'  shift 62\n\tCASE  shift 66\n\tIF  shift 64\n\t.  error\n\n\tvalue  goto 47\n\tvalue_expression  goto 245\n\trow_tuple  goto 49\n\tkeyword_as_func  goto 52\n\tsubquery  goto 60\n\tunary_operator  goto 50\n\tcolumn_name  goto 48\n\tcase_expression  goto 53\n\tsql_id  goto 51\n\nstate 181\n\tcondition:  value_expression LIKE value_expression.    (98)\n\tvalue_expression:  value_expression.'&' value_expression \n\tvalue_expression:  value_expression.'|' value_expression \n\tvalue_expression:  value_expression.'^' value_expression \n\tvalue_expression:  value_expression.'+' value_expression \n\tvalue_expression:  value_expression.'-' value_expression \n\tvalue_expression:  value_expression.'*' value_expression \n\tvalue_expression:  value_expression.'/' value_expression \n\tvalue_expression:  value_expression.'%' value_expression \n\n\t'&'  shift 106\n\t'|'  shift 107\n\t'^'  shift 108\n\t'+'  shift 109\n\t'-'  shift 110\n\t'*'  shift 111\n\t'/'  shift 112\n\t'%'  shift 113\n\t.  reduce 98 (src line 577)\n\n\nstate 182\n\tcondition:  value_expression BETWEEN value_expression.AND value_expression \n\tvalue_expression:  value_expression.'&' value_expression \n\tvalue_expression:  value_expression.'|' value_expression \n\tvalue_expression:  value_expression.'^' value_expression \n\tvalue_expression:  value_expression.'+' value_expression \n\tvalue_expression:  value_expression.'-' value_expression \n\tvalue_expression:  value_expression.'*' value_expression \n\tvalue_expression:  value_expression.'/' value_expression \n\tvalue_expression:  value_expression.'%' value_expression \n\n\tAND  shift 246\n\t'&'  shift 106\n\t'|'  shift 107\n\t'^'  shift 108\n\t'+'  shift 109\n\t'-'  shift 110\n\t'*'  shift 111\n\t'/'  shift 112\n\t'%'  shift 113\n\t.  error\n\n\nstate 183\n\tcondition:  value_expression IS NULL.    (102)\n\n\t.  reduce 102 (src line 593)\n\n\nstate 184\n\tcondition:  value_expression IS NOT.NULL \n\n\tNULL  shift 247\n\t.  error\n\n\nstate 185\n\tvalue_expression:  value_expression.'&' value_expression \n\tvalue_expression:  value_expression '&' value_expression.    (122)\n\tvalue_expression:  value_expression.'|' value_expression \n\tvalue_expression:  value_expression.'^' value_expression \n\tvalue_expression:  value_expression.'+' value_expression \n\tvalue_expression:  value_expression.'-' value_expression \n\tvalue_expression:  value_expression.'*' value_expression \n\tvalue_expression:  value_expression.'/' value_expression \n\tvalue_expression:  value_expression.'%' value_expression \n\n\t'+'  shift 109\n\t'-'  shift 110\n\t'*'  shift 111\n\t'/'  shift 112\n\t'%'  shift 113\n\t.  reduce 122 (src line 683)\n\n\nstate 186\n\tvalue_expression:  value_expression.'&' value_expression \n\tvalue_expression:  value_expression.'|' value_expression \n\tvalue_expression:  value_expression '|' value_expression.    (123)\n\tvalue_expression:  value_expression.'^' value_expression \n\tvalue_expression:  value_expression.'+' value_expression \n\tvalue_expression:  value_expression.'-' value_expression \n\tvalue_expression:  value_expression.'*' value_expression \n\tvalue_expression:  value_expression.'/' value_expression \n\tvalue_expression:  value_expression.'%' value_expression \n\n\t'+'  shift 109\n\t'-'  shift 110\n\t'*'  shift 111\n\t'/'  shift 112\n\t'%'  shift 113\n\t.  reduce 123 (src line 687)\n\n\nstate 187\n\tvalue_expression:  value_expression.'&' value_expression \n\tvalue_expression:  value_expression.'|' value_expression \n\tvalue_expression:  value_expression.'^' value_expression \n\tvalue_expression:  value_expression '^' value_expression.    (124)\n\tvalue_expression:  value_expression.'+' value_expression \n\tvalue_expression:  value_expression.'-' value_expression \n\tvalue_expression:  value_expression.'*' value_expression \n\tvalue_expression:  value_expression.'/' value_expression \n\tvalue_expression:  value_expression.'%' value_expression \n\n\t'+'  shift 109\n\t'-'  shift 110\n\t'*'  shift 111\n\t'/'  shift 112\n\t'%'  shift 113\n\t.  reduce 124 (src line 691)\n\n\nstate 188\n\tvalue_expression:  value_expression.'&' value_expression \n\tvalue_expression:  value_expression.'|' value_expression \n\tvalue_expression:  value_expression.'^' value_expression \n\tvalue_expression:  value_expression.'+' value_expression \n\tvalue_expression:  value_expression '+' value_expression.    (125)\n\tvalue_expression:  value_expression.'-' value_expression \n\tvalue_expression:  value_expression.'*' value_expression \n\tvalue_expression:  value_expression.'/' value_expression \n\tvalue_expression:  value_expression.'%' value_expression \n\n\t'*'  shift 111\n\t'/'  shift 112\n\t'%'  shift 113\n\t.  reduce 125 (src line 695)\n\n\nstate 189\n\tvalue_expression:  value_expression.'&' value_expression \n\tvalue_expression:  value_expression.'|' value_expression \n\tvalue_expression:  value_expression.'^' value_expression \n\tvalue_expression:  value_expression.'+' value_expression \n\tvalue_expression:  value_expression.'-' value_expression \n\tvalue_expression:  value_expression '-' value_expression.    (126)\n\tvalue_expression:  value_expression.'*' value_expression \n\tvalue_expression:  value_expression.'/' value_expression \n\tvalue_expression:  value_expression.'%' value_expression \n\n\t'*'  shift 111\n\t'/'  shift 112\n\t'%'  shift 113\n\t.  reduce 126 (src line 699)\n\n\nstate 190\n\tvalue_expression:  value_expression.'&' value_expression \n\tvalue_expression:  value_expression.'|' value_expression \n\tvalue_expression:  value_expression.'^' value_expression \n\tvalue_expression:  value_expression.'+' value_expression \n\tvalue_expression:  value_expression.'-' value_expression \n\tvalue_expression:  value_expression.'*' value_expression \n\tvalue_expression:  value_expression '*' value_expression.    (127)\n\tvalue_expression:  value_expression.'/' value_expression \n\tvalue_expression:  value_expression.'%' value_expression \n\n\t.  reduce 127 (src line 703)\n\n\nstate 191\n\tvalue_expression:  value_expression.'&' value_expression \n\tvalue_expression:  value_expression.'|' value_expression \n\tvalue_expression:  value_expression.'^' value_expression \n\tvalue_expression:  value_expression.'+' value_expression \n\tvalue_expression:  value_expression.'-' value_expression \n\tvalue_expression:  value_expression.'*' value_expression \n\tvalue_expression:  value_expression.'/' value_expression \n\tvalue_expression:  value_expression '/' value_expression.    (128)\n\tvalue_expression:  value_expression.'%' value_expression \n\n\t.  reduce 128 (src line 707)\n\n\nstate 192\n\tvalue_expression:  value_expression.'&' value_expression \n\tvalue_expression:  value_expression.'|' value_expression \n\tvalue_expression:  value_expression.'^' value_expression \n\tvalue_expression:  value_expression.'+' value_expression \n\tvalue_expression:  value_expression.'-' value_expression \n\tvalue_expression:  value_expression.'*' value_expression \n\tvalue_expression:  value_expression.'/' value_expression \n\tvalue_expression:  value_expression.'%' value_expression \n\tvalue_expression:  value_expression '%' value_expression.    (129)\n\n\t.  reduce 129 (src line 711)\n\n\nstate 193\n\tcolumn_name:  ID '.'.sql_id \n\n\tID  shift 96\n\t.  error\n\n\tsql_id  goto 170\n\nstate 194\n\tboolean_expression:  '(' boolean_expression ')'.    (94)\n\n\t.  reduce 94 (src line 559)\n\n\nstate 195\n\tsubquery:  '(' select_statement ')'.    (116)\n\n\t.  reduce 116 (src line 654)\n\n\nstate 196\n\tvalue_expression_list:  value_expression_list ','.value_expression \n\n\tNULL  shift 59\n\tVALUES  shift 65\n\tID  shift 123\n\tSTRING  shift 56\n\tNUMBER  shift 57\n\tVALUE_ARG  shift 58\n\t'('  shift 129\n\t'~'  shift 63\n\t'+'  shift 61\n\t'-'  shift 62\n\tCASE  shift 66\n\tIF  shift 64\n\t.  error\n\n\tvalue  goto 47\n\tvalue_expression  goto 248\n\trow_tuple  goto 49\n\tkeyword_as_func  goto 52\n\tsubquery  goto 60\n\tunary_operator  goto 50\n\tcolumn_name  goto 48\n\tcase_expression  goto 53\n\tsql_id  goto 51\n\nstate 197\n\trow_tuple:  '(' value_expression_list ')'.    (183)\n\n\t.  reduce 183 (src line 981)\n\n\nstate 198\n\tvalue_expression_list:  value_expression.    (117)\n\tvalue_expression:  value_expression.'&' value_expression \n\tvalue_expression:  value_expression.'|' value_expression \n\tvalue_expression:  value_expression.'^' value_expression \n\tvalue_expression:  value_expression.'+' value_expression \n\tvalue_expression:  value_expression.'-' value_expression \n\tvalue_expression:  value_expression.'*' value_expression \n\tvalue_expression:  value_expression.'/' value_expression \n\tvalue_expression:  value_expression.'%' value_expression \n\n\t'&'  shift 106\n\t'|'  shift 107\n\t'^'  shift 108\n\t'+'  shift 109\n\t'-'  shift 110\n\t'*'  shift 111\n\t'/'  shift 112\n\t'%'  shift 113\n\t.  reduce 117 (src line 660)\n\n\nstate 199\n\tvalue_expression:  sql_id '(' ')'.    (131)\n\n\t.  reduce 131 (src line 730)\n\n\nstate 200\n\tselect_expression_list:  select_expression_list.',' select_expression \n\tvalue_expression:  sql_id '(' select_expression_list.')' \n\n\t','  shift 91\n\t')'  shift 249\n\t.  error\n\n\nstate 201\n\tvalue_expression:  sql_id '(' DISTINCT.select_expression_list ')' \n\n\tEXISTS  shift 54\n\tNULL  shift 59\n\tVALUES  shift 65\n\tKEYRANGE  shift 55\n\tID  shift 41\n\tSTRING  shift 56\n\tNUMBER  shift 57\n\tVALUE_ARG  shift 58\n\t'('  shift 46\n\t'~'  shift 63\n\tNOT  shift 45\n\t'+'  shift 61\n\t'-'  shift 62\n\t'*'  shift 39\n\tCASE  shift 66\n\tIF  shift 64\n\t.  error\n\n\tselect_expression_list  goto 250\n\tselect_expression  goto 38\n\texpression  goto 40\n\tboolean_expression  goto 42\n\tcondition  goto 44\n\tvalue  goto 47\n\tvalue_expression  goto 43\n\trow_tuple  goto 49\n\tkeyword_as_func  goto 52\n\tsubquery  goto 60\n\tunary_operator  goto 50\n\tcolumn_name  goto 48\n\tcase_expression  goto 53\n\tsql_id  goto 51\n\nstate 202\n\tselect_expression_list:  select_expression_list.',' select_expression \n\tvalue_expression:  keyword_as_func '(' select_expression_list.')' \n\n\t','  shift 91\n\t')'  shift 251\n\t.  error\n\n\nstate 203\n\tcondition:  KEYRANGE '(' value.',' value ')' \n\n\t','  shift 252\n\t.  error\n\n\nstate 204\n\tcase_expression:  CASE value_expression_opt when_expression_list.else_expression_opt END \n\twhen_expression_list:  when_expression_list.when_expression \n\telse_expression_opt: .    (147)\n\n\tWHEN  shift 206\n\tELSE  shift 255\n\t.  reduce 147 (src line 806)\n\n\twhen_expression  goto 254\n\telse_expression_opt  goto 253\n\nstate 205\n\twhen_expression_list:  when_expression.    (144)\n\n\t.  reduce 144 (src line 790)\n\n\nstate 206\n\twhen_expression:  WHEN.boolean_expression THEN value_expression \n\n\tEXISTS  shift 54\n\tNULL  shift 59\n\tVALUES  shift 65\n\tKEYRANGE  shift 55\n\tID  shift 123\n\tSTRING  shift 56\n\tNUMBER  shift 57\n\tVALUE_ARG  shift 58\n\t'('  shift 46\n\t'~'  shift 63\n\tNOT  shift 45\n\t'+'  shift 61\n\t'-'  shift 62\n\tCASE  shift 66\n\tIF  shift 64\n\t.  error\n\n\tboolean_expression  goto 256\n\tcondition  goto 44\n\tvalue  goto 47\n\tvalue_expression  goto 122\n\trow_tuple  goto 49\n\tkeyword_as_func  goto 52\n\tsubquery  goto 60\n\tunary_operator  goto 50\n\tcolumn_name  goto 48\n\tcase_expression  goto 53\n\tsql_id  goto 51\n\nstate 207\n\tinsert_statement:  INSERT comment_opt INTO dml_table_expression.column_list_opt row_list on_dup_opt \n\tinsert_statement:  INSERT comment_opt INTO dml_table_expression.SET update_list on_dup_opt \n\tcolumn_list_opt: .    (173)\n\n\tSET  shift 258\n\t'('  shift 259\n\t.  reduce 173 (src line 933)\n\n\tcolumn_list_opt  goto 257\n\nstate 208\n\tupdate_statement:  UPDATE comment_opt dml_table_expression SET.update_list where_expression_opt order_by_opt limit_opt \n\n\tID  shift 123\n\t.  error\n\n\tcolumn_name  goto 143\n\tupdate_list  goto 260\n\tupdate_expression  goto 142\n\tsql_id  goto 144\n\nstate 209\n\tdml_table_expression:  ID '.'.ID \n\n\tID  shift 261\n\t.  error\n\n\nstate 210\n\tdelete_statement:  DELETE comment_opt FROM dml_table_expression.where_expression_opt order_by_opt limit_opt \n\twhere_expression_opt: .    (88)\n\n\tWHERE  shift 160\n\t.  reduce 88 (src line 536)\n\n\twhere_expression_opt  goto 262\n\nstate 211\n\tupdate_list:  update_list ','.update_expression \n\n\tID  shift 123\n\t.  error\n\n\tcolumn_name  goto 143\n\tupdate_expression  goto 263\n\tsql_id  goto 144\n\nstate 212\n\tupdate_expression:  column_name '='.value_expression \n\n\tNULL  shift 59\n\tVALUES  shift 65\n\tID  shift 123\n\tSTRING  shift 56\n\tNUMBER  shift 57\n\tVALUE_ARG  shift 58\n\t'('  shift 129\n\t'~'  shift 63\n\t'+'  shift 61\n\t'-'  shift 62\n\tCASE  shift 66\n\tIF  shift 64\n\t.  error\n\n\tvalue  goto 47\n\tvalue_expression  goto 264\n\trow_tuple  goto 49\n\tkeyword_as_func  goto 52\n\tsubquery  goto 60\n\tunary_operator  goto 50\n\tcolumn_name  goto 48\n\tcase_expression  goto 53\n\tsql_id  goto 51\n\nstate 213\n\tcreate_statement:  CREATE TABLE not_exists_opt ID.force_eof \n\tforce_eof: .    (206)\n\n\t.  reduce 206 (src line 1055)\n\n\tforce_eof  goto 265\n\nstate 214\n\tnot_exists_opt:  IF NOT.EXISTS \n\n\tEXISTS  shift 266\n\t.  error\n\n\nstate 215\n\tcreate_statement:  CREATE constraint_opt INDEX sql_id.using_opt ON ID force_eof \n\tusing_opt: .    (203)\n\n\tUSING  shift 268\n\t.  reduce 203 (src line 1044)\n\n\tusing_opt  goto 267\n\nstate 216\n\tcreate_statement:  CREATE VIEW sql_id force_eof.    (24)\n\n\t.  reduce 24 (src line 238)\n\n\nstate 217\n\talter_statement:  ALTER ignore_opt TABLE ID.non_rename_operation force_eof \n\talter_statement:  ALTER ignore_opt TABLE ID.RENAME to_opt ID \n\n\tORDER  shift 274\n\tDEFAULT  shift 272\n\tID  shift 275\n\tALTER  shift 271\n\tDROP  shift 273\n\tRENAME  shift 270\n\t.  error\n\n\tnon_rename_operation  goto 269\n\nstate 218\n\talter_statement:  ALTER VIEW sql_id force_eof.    (27)\n\n\t.  reduce 27 (src line 253)\n\n\nstate 219\n\trename_statement:  RENAME TABLE ID TO.ID \n\n\tID  shift 276\n\t.  error\n\n\nstate 220\n\tdrop_statement:  DROP TABLE exists_opt ID.    (29)\n\n\t.  reduce 29 (src line 264)\n\n\nstate 221\n\texists_opt:  IF EXISTS.    (189)\n\n\t.  reduce 189 (src line 1009)\n\n\nstate 222\n\tdrop_statement:  DROP INDEX sql_id ON.ID \n\n\tID  shift 277\n\t.  error\n\n\nstate 223\n\tdrop_statement:  DROP VIEW exists_opt sql_id.force_eof \n\tforce_eof: .    (206)\n\n\t.  reduce 206 (src line 1055)\n\n\tforce_eof  goto 278\n\nstate 224\n\tselect_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 \n\twhere_expression_opt: .    (88)\n\n\tWHERE  shift 160\n\t.  reduce 88 (src line 536)\n\n\twhere_expression_opt  goto 279\n\nstate 225\n\tmissing_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 \n\thaving_opt: .    (157)\n\n\tHAVING  shift 281\n\t.  reduce 157 (src line 852)\n\n\thaving_opt  goto 280\n\nstate 226\n\tgroup_by_opt:  GROUP.BY value_expression_list \n\n\tBY  shift 282\n\t.  error\n\n\nstate 227\n\twhere_expression_opt:  WHERE boolean_expression.    (89)\n\tboolean_expression:  boolean_expression.AND boolean_expression \n\tboolean_expression:  boolean_expression.OR boolean_expression \n\n\tOR  shift 99\n\tAND  shift 98\n\t.  reduce 89 (src line 540)\n\n\nstate 228\n\ttable_expression_list:  table_expression_list ','.table_expression \n\n\tID  shift 166\n\t'('  shift 165\n\t.  error\n\n\ttable_expression  goto 283\n\tsimple_table_expression  goto 164\n\tsubquery  goto 167\n\nstate 229\n\ttable_expression:  table_expression join_type.table_expression \n\ttable_expression:  table_expression join_type.table_expression ON boolean_expression \n\n\tID  shift 166\n\t'('  shift 165\n\t.  error\n\n\ttable_expression  goto 284\n\tsimple_table_expression  goto 164\n\tsubquery  goto 167\n\nstate 230\n\tjoin_type:  JOIN.    (66)\n\n\t.  reduce 66 (src line 437)\n\n\nstate 231\n\tjoin_type:  STRAIGHT_JOIN.    (67)\n\n\t.  reduce 67 (src line 442)\n\n\nstate 232\n\tjoin_type:  LEFT.JOIN \n\tjoin_type:  LEFT.OUTER JOIN \n\n\tJOIN  shift 285\n\tOUTER  shift 286\n\t.  error\n\n\nstate 233\n\tjoin_type:  RIGHT.JOIN \n\tjoin_type:  RIGHT.OUTER JOIN \n\n\tJOIN  shift 287\n\tOUTER  shift 288\n\t.  error\n\n\nstate 234\n\tjoin_type:  INNER.JOIN \n\n\tJOIN  shift 289\n\t.  error\n\n\nstate 235\n\tjoin_type:  CROSS.JOIN \n\n\tJOIN  shift 290\n\t.  error\n\n\nstate 236\n\tjoin_type:  NATURAL.JOIN \n\n\tJOIN  shift 291\n\t.  error\n\n\nstate 237\n\ttable_expression:  simple_table_expression as_opt.index_hint_list \n\tindex_hint_list: .    (80)\n\n\tUSE  shift 293\n\tFORCE  shift 295\n\tIGNORE  shift 294\n\t.  reduce 80 (src line 499)\n\n\tindex_hint_list  goto 292\n\nstate 238\n\tas_opt:  ID.    (64)\n\n\t.  reduce 64 (src line 428)\n\n\nstate 239\n\tas_opt:  AS.ID \n\n\tID  shift 296\n\t.  error\n\n\nstate 240\n\ttable_expression:  '(' table_expression.')' \n\ttable_expression:  table_expression.join_type table_expression \n\ttable_expression:  table_expression.join_type table_expression ON boolean_expression \n\n\tJOIN  shift 230\n\tSTRAIGHT_JOIN  shift 231\n\tLEFT  shift 232\n\tRIGHT  shift 233\n\tINNER  shift 234\n\tCROSS  shift 235\n\tNATURAL  shift 236\n\t')'  shift 297\n\t.  error\n\n\tjoin_type  goto 229\n\nstate 241\n\tsimple_table_expression:  ID '.'.ID \n\n\tID  shift 298\n\t.  error\n\n\nstate 242\n\tcol_tuple:  '(' value_expression_list.')' \n\tvalue_expression_list:  value_expression_list.',' value_expression \n\n\t','  shift 196\n\t')'  shift 299\n\t.  error\n\n\nstate 243\n\tcondition:  value_expression NOT IN col_tuple.    (97)\n\n\t.  reduce 97 (src line 573)\n\n\nstate 244\n\tcondition:  value_expression NOT LIKE value_expression.    (99)\n\tvalue_expression:  value_expression.'&' value_expression \n\tvalue_expression:  value_expression.'|' value_expression \n\tvalue_expression:  value_expression.'^' value_expression \n\tvalue_expression:  value_expression.'+' value_expression \n\tvalue_expression:  value_expression.'-' value_expression \n\tvalue_expression:  value_expression.'*' value_expression \n\tvalue_expression:  value_expression.'/' value_expression \n\tvalue_expression:  value_expression.'%' value_expression \n\n\t'&'  shift 106\n\t'|'  shift 107\n\t'^'  shift 108\n\t'+'  shift 109\n\t'-'  shift 110\n\t'*'  shift 111\n\t'/'  shift 112\n\t'%'  shift 113\n\t.  reduce 99 (src line 581)\n\n\nstate 245\n\tcondition:  value_expression NOT BETWEEN value_expression.AND value_expression \n\tvalue_expression:  value_expression.'&' value_expression \n\tvalue_expression:  value_expression.'|' value_expression \n\tvalue_expression:  value_expression.'^' value_expression \n\tvalue_expression:  value_expression.'+' value_expression \n\tvalue_expression:  value_expression.'-' value_expression \n\tvalue_expression:  value_expression.'*' value_expression \n\tvalue_expression:  value_expression.'/' value_expression \n\tvalue_expression:  value_expression.'%' value_expression \n\n\tAND  shift 300\n\t'&'  shift 106\n\t'|'  shift 107\n\t'^'  shift 108\n\t'+'  shift 109\n\t'-'  shift 110\n\t'*'  shift 111\n\t'/'  shift 112\n\t'%'  shift 113\n\t.  error\n\n\nstate 246\n\tcondition:  value_expression BETWEEN value_expression AND.value_expression \n\n\tNULL  shift 59\n\tVALUES  shift 65\n\tID  shift 123\n\tSTRING  shift 56\n\tNUMBER  shift 57\n\tVALUE_ARG  shift 58\n\t'('  shift 129\n\t'~'  shift 63\n\t'+'  shift 61\n\t'-'  shift 62\n\tCASE  shift 66\n\tIF  shift 64\n\t.  error\n\n\tvalue  goto 47\n\tvalue_expression  goto 301\n\trow_tuple  goto 49\n\tkeyword_as_func  goto 52\n\tsubquery  goto 60\n\tunary_operator  goto 50\n\tcolumn_name  goto 48\n\tcase_expression  goto 53\n\tsql_id  goto 51\n\nstate 247\n\tcondition:  value_expression IS NOT NULL.    (103)\n\n\t.  reduce 103 (src line 597)\n\n\nstate 248\n\tvalue_expression_list:  value_expression_list ',' value_expression.    (118)\n\tvalue_expression:  value_expression.'&' value_expression \n\tvalue_expression:  value_expression.'|' value_expression \n\tvalue_expression:  value_expression.'^' value_expression \n\tvalue_expression:  value_expression.'+' value_expression \n\tvalue_expression:  value_expression.'-' value_expression \n\tvalue_expression:  value_expression.'*' value_expression \n\tvalue_expression:  value_expression.'/' value_expression \n\tvalue_expression:  value_expression.'%' value_expression \n\n\t'&'  shift 106\n\t'|'  shift 107\n\t'^'  shift 108\n\t'+'  shift 109\n\t'-'  shift 110\n\t'*'  shift 111\n\t'/'  shift 112\n\t'%'  shift 113\n\t.  reduce 118 (src line 665)\n\n\nstate 249\n\tvalue_expression:  sql_id '(' select_expression_list ')'.    (132)\n\n\t.  reduce 132 (src line 734)\n\n\nstate 250\n\tselect_expression_list:  select_expression_list.',' select_expression \n\tvalue_expression:  sql_id '(' DISTINCT select_expression_list.')' \n\n\t','  shift 91\n\t')'  shift 302\n\t.  error\n\n\nstate 251\n\tvalue_expression:  keyword_as_func '(' select_expression_list ')'.    (134)\n\n\t.  reduce 134 (src line 742)\n\n\nstate 252\n\tcondition:  KEYRANGE '(' value ','.value ')' \n\n\tNULL  shift 59\n\tSTRING  shift 56\n\tNUMBER  shift 57\n\tVALUE_ARG  shift 58\n\t.  error\n\n\tvalue  goto 303\n\nstate 253\n\tcase_expression:  CASE value_expression_opt when_expression_list else_expression_opt.END \n\n\tEND  shift 304\n\t.  error\n\n\nstate 254\n\twhen_expression_list:  when_expression_list when_expression.    (145)\n\n\t.  reduce 145 (src line 795)\n\n\nstate 255\n\telse_expression_opt:  ELSE.value_expression \n\n\tNULL  shift 59\n\tVALUES  shift 65\n\tID  shift 123\n\tSTRING  shift 56\n\tNUMBER  shift 57\n\tVALUE_ARG  shift 58\n\t'('  shift 129\n\t'~'  shift 63\n\t'+'  shift 61\n\t'-'  shift 62\n\tCASE  shift 66\n\tIF  shift 64\n\t.  error\n\n\tvalue  goto 47\n\tvalue_expression  goto 305\n\trow_tuple  goto 49\n\tkeyword_as_func  goto 52\n\tsubquery  goto 60\n\tunary_operator  goto 50\n\tcolumn_name  goto 48\n\tcase_expression  goto 53\n\tsql_id  goto 51\n\nstate 256\n\tboolean_expression:  boolean_expression.AND boolean_expression \n\tboolean_expression:  boolean_expression.OR boolean_expression \n\twhen_expression:  WHEN boolean_expression.THEN value_expression \n\n\tOR  shift 99\n\tAND  shift 98\n\tTHEN  shift 306\n\t.  error\n\n\nstate 257\n\tinsert_statement:  INSERT comment_opt INTO dml_table_expression column_list_opt.row_list on_dup_opt \n\n\tSELECT  shift 15\n\tVALUES  shift 308\n\t.  error\n\n\tselect_statement  goto 309\n\trow_list  goto 307\n\nstate 258\n\tinsert_statement:  INSERT comment_opt INTO dml_table_expression SET.update_list on_dup_opt \n\n\tID  shift 123\n\t.  error\n\n\tcolumn_name  goto 143\n\tupdate_list  goto 310\n\tupdate_expression  goto 142\n\tsql_id  goto 144\n\nstate 259\n\tcolumn_list_opt:  '('.column_list ')' \n\n\tID  shift 123\n\t.  error\n\n\tcolumn_name  goto 312\n\tcolumn_list  goto 311\n\tsql_id  goto 144\n\nstate 260\n\tupdate_statement:  UPDATE comment_opt dml_table_expression SET update_list.where_expression_opt order_by_opt limit_opt \n\tupdate_list:  update_list.',' update_expression \n\twhere_expression_opt: .    (88)\n\n\tWHERE  shift 160\n\t','  shift 211\n\t.  reduce 88 (src line 536)\n\n\twhere_expression_opt  goto 313\n\nstate 261\n\tdml_table_expression:  ID '.' ID.    (79)\n\n\t.  reduce 79 (src line 494)\n\n\nstate 262\n\tdelete_statement:  DELETE comment_opt FROM dml_table_expression where_expression_opt.order_by_opt limit_opt \n\torder_by_opt: .    (159)\n\n\tORDER  shift 315\n\t.  reduce 159 (src line 861)\n\n\torder_by_opt  goto 314\n\nstate 263\n\tupdate_list:  update_list ',' update_expression.    (186)\n\n\t.  reduce 186 (src line 996)\n\n\nstate 264\n\tvalue_expression:  value_expression.'&' value_expression \n\tvalue_expression:  value_expression.'|' value_expression \n\tvalue_expression:  value_expression.'^' value_expression \n\tvalue_expression:  value_expression.'+' value_expression \n\tvalue_expression:  value_expression.'-' value_expression \n\tvalue_expression:  value_expression.'*' value_expression \n\tvalue_expression:  value_expression.'/' value_expression \n\tvalue_expression:  value_expression.'%' value_expression \n\tupdate_expression:  column_name '=' value_expression.    (187)\n\n\t'&'  shift 106\n\t'|'  shift 107\n\t'^'  shift 108\n\t'+'  shift 109\n\t'-'  shift 110\n\t'*'  shift 111\n\t'/'  shift 112\n\t'%'  shift 113\n\t.  reduce 187 (src line 1001)\n\n\nstate 265\n\tcreate_statement:  CREATE TABLE not_exists_opt ID force_eof.    (22)\n\n\t.  reduce 22 (src line 228)\n\n\nstate 266\n\tnot_exists_opt:  IF NOT EXISTS.    (191)\n\n\t.  reduce 191 (src line 1014)\n\n\nstate 267\n\tcreate_statement:  CREATE constraint_opt INDEX sql_id using_opt.ON ID force_eof \n\n\tON  shift 316\n\t.  error\n\n\nstate 268\n\tusing_opt:  USING.sql_id \n\n\tID  shift 96\n\t.  error\n\n\tsql_id  goto 317\n\nstate 269\n\talter_statement:  ALTER ignore_opt TABLE ID non_rename_operation.force_eof \n\tforce_eof: .    (206)\n\n\t.  reduce 206 (src line 1055)\n\n\tforce_eof  goto 318\n\nstate 270\n\talter_statement:  ALTER ignore_opt TABLE ID RENAME.to_opt ID \n\tto_opt: .    (199)\n\n\tTO  shift 320\n\t.  reduce 199 (src line 1034)\n\n\tto_opt  goto 319\n\nstate 271\n\tnon_rename_operation:  ALTER.    (194)\n\n\t.  reduce 194 (src line 1022)\n\n\nstate 272\n\tnon_rename_operation:  DEFAULT.    (195)\n\n\t.  reduce 195 (src line 1025)\n\n\nstate 273\n\tnon_rename_operation:  DROP.    (196)\n\n\t.  reduce 196 (src line 1027)\n\n\nstate 274\n\tnon_rename_operation:  ORDER.    (197)\n\n\t.  reduce 197 (src line 1029)\n\n\nstate 275\n\tnon_rename_operation:  ID.    (198)\n\n\t.  reduce 198 (src line 1031)\n\n\nstate 276\n\trename_statement:  RENAME TABLE ID TO ID.    (28)\n\n\t.  reduce 28 (src line 258)\n\n\nstate 277\n\tdrop_statement:  DROP INDEX sql_id ON ID.    (30)\n\n\t.  reduce 30 (src line 269)\n\n\nstate 278\n\tdrop_statement:  DROP VIEW exists_opt sql_id force_eof.    (31)\n\n\t.  reduce 31 (src line 274)\n\n\nstate 279\n\tselect_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 \n\tgroup_by_opt: .    (155)\n\n\tGROUP  shift 226\n\t.  reduce 155 (src line 843)\n\n\tgroup_by_opt  goto 321\n\nstate 280\n\tmissing_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 \n\torder_by_opt: .    (159)\n\n\tORDER  shift 315\n\t.  reduce 159 (src line 861)\n\n\torder_by_opt  goto 322\n\nstate 281\n\thaving_opt:  HAVING.boolean_expression \n\n\tEXISTS  shift 54\n\tNULL  shift 59\n\tVALUES  shift 65\n\tKEYRANGE  shift 55\n\tID  shift 123\n\tSTRING  shift 56\n\tNUMBER  shift 57\n\tVALUE_ARG  shift 58\n\t'('  shift 46\n\t'~'  shift 63\n\tNOT  shift 45\n\t'+'  shift 61\n\t'-'  shift 62\n\tCASE  shift 66\n\tIF  shift 64\n\t.  error\n\n\tboolean_expression  goto 323\n\tcondition  goto 44\n\tvalue  goto 47\n\tvalue_expression  goto 122\n\trow_tuple  goto 49\n\tkeyword_as_func  goto 52\n\tsubquery  goto 60\n\tunary_operator  goto 50\n\tcolumn_name  goto 48\n\tcase_expression  goto 53\n\tsql_id  goto 51\n\nstate 282\n\tgroup_by_opt:  GROUP BY.value_expression_list \n\n\tNULL  shift 59\n\tVALUES  shift 65\n\tID  shift 123\n\tSTRING  shift 56\n\tNUMBER  shift 57\n\tVALUE_ARG  shift 58\n\t'('  shift 129\n\t'~'  shift 63\n\t'+'  shift 61\n\t'-'  shift 62\n\tCASE  shift 66\n\tIF  shift 64\n\t.  error\n\n\tvalue  goto 47\n\tvalue_expression  goto 198\n\tvalue_expression_list  goto 324\n\trow_tuple  goto 49\n\tkeyword_as_func  goto 52\n\tsubquery  goto 60\n\tunary_operator  goto 50\n\tcolumn_name  goto 48\n\tcase_expression  goto 53\n\tsql_id  goto 51\n\nstate 283\n\ttable_expression_list:  table_expression_list ',' table_expression.    (58)\n\ttable_expression:  table_expression.join_type table_expression \n\ttable_expression:  table_expression.join_type table_expression ON boolean_expression \n\n\tJOIN  shift 230\n\tSTRAIGHT_JOIN  shift 231\n\tLEFT  shift 232\n\tRIGHT  shift 233\n\tINNER  shift 234\n\tCROSS  shift 235\n\tNATURAL  shift 236\n\t.  reduce 58 (src line 401)\n\n\tjoin_type  goto 229\n\nstate 284\n\ttable_expression:  table_expression.join_type table_expression \n\ttable_expression:  table_expression join_type table_expression.    (61)\n\ttable_expression:  table_expression.join_type table_expression ON boolean_expression \n\ttable_expression:  table_expression join_type table_expression.ON boolean_expression \n\n\tON  shift 325\n\t.  reduce 61 (src line 415)\n\n\tjoin_type  goto 229\n\nstate 285\n\tjoin_type:  LEFT JOIN.    (68)\n\n\t.  reduce 68 (src line 446)\n\n\nstate 286\n\tjoin_type:  LEFT OUTER.JOIN \n\n\tJOIN  shift 326\n\t.  error\n\n\nstate 287\n\tjoin_type:  RIGHT JOIN.    (70)\n\n\t.  reduce 70 (src line 454)\n\n\nstate 288\n\tjoin_type:  RIGHT OUTER.JOIN \n\n\tJOIN  shift 327\n\t.  error\n\n\nstate 289\n\tjoin_type:  INNER JOIN.    (72)\n\n\t.  reduce 72 (src line 462)\n\n\nstate 290\n\tjoin_type:  CROSS JOIN.    (73)\n\n\t.  reduce 73 (src line 466)\n\n\nstate 291\n\tjoin_type:  NATURAL JOIN.    (74)\n\n\t.  reduce 74 (src line 470)\n\n\nstate 292\n\ttable_expression:  simple_table_expression as_opt index_hint_list.    (59)\n\n\t.  reduce 59 (src line 406)\n\n\nstate 293\n\tindex_hint_list:  USE.INDEX '(' index_list ')' \n\n\tINDEX  shift 328\n\t.  error\n\n\nstate 294\n\tindex_hint_list:  IGNORE.INDEX '(' index_list ')' \n\n\tINDEX  shift 329\n\t.  error\n\n\nstate 295\n\tindex_hint_list:  FORCE.INDEX '(' index_list ')' \n\n\tINDEX  shift 330\n\t.  error\n\n\nstate 296\n\tas_opt:  AS ID.    (65)\n\n\t.  reduce 65 (src line 432)\n\n\nstate 297\n\ttable_expression:  '(' table_expression ')'.    (60)\n\n\t.  reduce 60 (src line 411)\n\n\nstate 298\n\tsimple_table_expression:  ID '.' ID.    (76)\n\n\t.  reduce 76 (src line 480)\n\n\nstate 299\n\tcol_tuple:  '(' value_expression_list ')'.    (113)\n\n\t.  reduce 113 (src line 640)\n\n\nstate 300\n\tcondition:  value_expression NOT BETWEEN value_expression AND.value_expression \n\n\tNULL  shift 59\n\tVALUES  shift 65\n\tID  shift 123\n\tSTRING  shift 56\n\tNUMBER  shift 57\n\tVALUE_ARG  shift 58\n\t'('  shift 129\n\t'~'  shift 63\n\t'+'  shift 61\n\t'-'  shift 62\n\tCASE  shift 66\n\tIF  shift 64\n\t.  error\n\n\tvalue  goto 47\n\tvalue_expression  goto 331\n\trow_tuple  goto 49\n\tkeyword_as_func  goto 52\n\tsubquery  goto 60\n\tunary_operator  goto 50\n\tcolumn_name  goto 48\n\tcase_expression  goto 53\n\tsql_id  goto 51\n\nstate 301\n\tcondition:  value_expression BETWEEN value_expression AND value_expression.    (100)\n\tvalue_expression:  value_expression.'&' value_expression \n\tvalue_expression:  value_expression.'|' value_expression \n\tvalue_expression:  value_expression.'^' value_expression \n\tvalue_expression:  value_expression.'+' value_expression \n\tvalue_expression:  value_expression.'-' value_expression \n\tvalue_expression:  value_expression.'*' value_expression \n\tvalue_expression:  value_expression.'/' value_expression \n\tvalue_expression:  value_expression.'%' value_expression \n\n\t'&'  shift 106\n\t'|'  shift 107\n\t'^'  shift 108\n\t'+'  shift 109\n\t'-'  shift 110\n\t'*'  shift 111\n\t'/'  shift 112\n\t'%'  shift 113\n\t.  reduce 100 (src line 585)\n\n\nstate 302\n\tvalue_expression:  sql_id '(' DISTINCT select_expression_list ')'.    (133)\n\n\t.  reduce 133 (src line 738)\n\n\nstate 303\n\tcondition:  KEYRANGE '(' value ',' value.')' \n\n\t')'  shift 332\n\t.  error\n\n\nstate 304\n\tcase_expression:  CASE value_expression_opt when_expression_list else_expression_opt END.    (141)\n\n\t.  reduce 141 (src line 775)\n\n\nstate 305\n\tvalue_expression:  value_expression.'&' value_expression \n\tvalue_expression:  value_expression.'|' value_expression \n\tvalue_expression:  value_expression.'^' value_expression \n\tvalue_expression:  value_expression.'+' value_expression \n\tvalue_expression:  value_expression.'-' value_expression \n\tvalue_expression:  value_expression.'*' value_expression \n\tvalue_expression:  value_expression.'/' value_expression \n\tvalue_expression:  value_expression.'%' value_expression \n\telse_expression_opt:  ELSE value_expression.    (148)\n\n\t'&'  shift 106\n\t'|'  shift 107\n\t'^'  shift 108\n\t'+'  shift 109\n\t'-'  shift 110\n\t'*'  shift 111\n\t'/'  shift 112\n\t'%'  shift 113\n\t.  reduce 148 (src line 810)\n\n\nstate 306\n\twhen_expression:  WHEN boolean_expression THEN.value_expression \n\n\tNULL  shift 59\n\tVALUES  shift 65\n\tID  shift 123\n\tSTRING  shift 56\n\tNUMBER  shift 57\n\tVALUE_ARG  shift 58\n\t'('  shift 129\n\t'~'  shift 63\n\t'+'  shift 61\n\t'-'  shift 62\n\tCASE  shift 66\n\tIF  shift 64\n\t.  error\n\n\tvalue  goto 47\n\tvalue_expression  goto 333\n\trow_tuple  goto 49\n\tkeyword_as_func  goto 52\n\tsubquery  goto 60\n\tunary_operator  goto 50\n\tcolumn_name  goto 48\n\tcase_expression  goto 53\n\tsql_id  goto 51\n\nstate 307\n\tinsert_statement:  INSERT comment_opt INTO dml_table_expression column_list_opt row_list.on_dup_opt \n\ton_dup_opt: .    (177)\n\n\tON  shift 335\n\t.  reduce 177 (src line 952)\n\n\ton_dup_opt  goto 334\n\nstate 308\n\trow_list:  VALUES.tuple_list \n\n\t'('  shift 129\n\t.  error\n\n\ttuple_list  goto 336\n\trow_tuple  goto 337\n\tsubquery  goto 60\n\nstate 309\n\tselect_statement:  select_statement.union_op select_statement \n\trow_list:  select_statement.    (180)\n\n\tUNION  shift 31\n\tMINUS  shift 32\n\tEXCEPT  shift 33\n\tINTERSECT  shift 34\n\t.  reduce 180 (src line 966)\n\n\tunion_op  goto 30\n\nstate 310\n\tinsert_statement:  INSERT comment_opt INTO dml_table_expression SET update_list.on_dup_opt \n\tupdate_list:  update_list.',' update_expression \n\ton_dup_opt: .    (177)\n\n\t','  shift 211\n\tON  shift 335\n\t.  reduce 177 (src line 952)\n\n\ton_dup_opt  goto 338\n\nstate 311\n\tcolumn_list_opt:  '(' column_list.')' \n\tcolumn_list:  column_list.',' column_name \n\n\t','  shift 340\n\t')'  shift 339\n\t.  error\n\n\nstate 312\n\tcolumn_list:  column_name.    (175)\n\n\t.  reduce 175 (src line 942)\n\n\nstate 313\n\tupdate_statement:  UPDATE comment_opt dml_table_expression SET update_list where_expression_opt.order_by_opt limit_opt \n\torder_by_opt: .    (159)\n\n\tORDER  shift 315\n\t.  reduce 159 (src line 861)\n\n\torder_by_opt  goto 341\n\nstate 314\n\tdelete_statement:  DELETE comment_opt FROM dml_table_expression where_expression_opt order_by_opt.limit_opt \n\tlimit_opt: .    (167)\n\n\tLIMIT  shift 343\n\t.  reduce 167 (src line 899)\n\n\tlimit_opt  goto 342\n\nstate 315\n\torder_by_opt:  ORDER.BY order_list \n\n\tBY  shift 344\n\t.  error\n\n\nstate 316\n\tcreate_statement:  CREATE constraint_opt INDEX sql_id using_opt ON.ID force_eof \n\n\tID  shift 345\n\t.  error\n\n\nstate 317\n\tusing_opt:  USING sql_id.    (204)\n\n\t.  reduce 204 (src line 1046)\n\n\nstate 318\n\talter_statement:  ALTER ignore_opt TABLE ID non_rename_operation force_eof.    (25)\n\n\t.  reduce 25 (src line 243)\n\n\nstate 319\n\talter_statement:  ALTER ignore_opt TABLE ID RENAME to_opt.ID \n\n\tID  shift 346\n\t.  error\n\n\nstate 320\n\tto_opt:  TO.    (200)\n\n\t.  reduce 200 (src line 1036)\n\n\nstate 321\n\tselect_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 \n\thaving_opt: .    (157)\n\n\tHAVING  shift 281\n\t.  reduce 157 (src line 852)\n\n\thaving_opt  goto 347\n\nstate 322\n\tmissing_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 \n\tlimit_opt: .    (167)\n\n\tLIMIT  shift 343\n\t.  reduce 167 (src line 899)\n\n\tlimit_opt  goto 348\n\nstate 323\n\tboolean_expression:  boolean_expression.AND boolean_expression \n\tboolean_expression:  boolean_expression.OR boolean_expression \n\thaving_opt:  HAVING boolean_expression.    (158)\n\n\tOR  shift 99\n\tAND  shift 98\n\t.  reduce 158 (src line 856)\n\n\nstate 324\n\tvalue_expression_list:  value_expression_list.',' value_expression \n\tgroup_by_opt:  GROUP BY value_expression_list.    (156)\n\n\t','  shift 196\n\t.  reduce 156 (src line 847)\n\n\nstate 325\n\ttable_expression:  table_expression join_type table_expression ON.boolean_expression \n\n\tEXISTS  shift 54\n\tNULL  shift 59\n\tVALUES  shift 65\n\tKEYRANGE  shift 55\n\tID  shift 123\n\tSTRING  shift 56\n\tNUMBER  shift 57\n\tVALUE_ARG  shift 58\n\t'('  shift 46\n\t'~'  shift 63\n\tNOT  shift 45\n\t'+'  shift 61\n\t'-'  shift 62\n\tCASE  shift 66\n\tIF  shift 64\n\t.  error\n\n\tboolean_expression  goto 349\n\tcondition  goto 44\n\tvalue  goto 47\n\tvalue_expression  goto 122\n\trow_tuple  goto 49\n\tkeyword_as_func  goto 52\n\tsubquery  goto 60\n\tunary_operator  goto 50\n\tcolumn_name  goto 48\n\tcase_expression  goto 53\n\tsql_id  goto 51\n\nstate 326\n\tjoin_type:  LEFT OUTER JOIN.    (69)\n\n\t.  reduce 69 (src line 450)\n\n\nstate 327\n\tjoin_type:  RIGHT OUTER JOIN.    (71)\n\n\t.  reduce 71 (src line 458)\n\n\nstate 328\n\tindex_hint_list:  USE INDEX.'(' index_list ')' \n\n\t'('  shift 350\n\t.  error\n\n\nstate 329\n\tindex_hint_list:  IGNORE INDEX.'(' index_list ')' \n\n\t'('  shift 351\n\t.  error\n\n\nstate 330\n\tindex_hint_list:  FORCE INDEX.'(' index_list ')' \n\n\t'('  shift 352\n\t.  error\n\n\nstate 331\n\tcondition:  value_expression NOT BETWEEN value_expression AND value_expression.    (101)\n\tvalue_expression:  value_expression.'&' value_expression \n\tvalue_expression:  value_expression.'|' value_expression \n\tvalue_expression:  value_expression.'^' value_expression \n\tvalue_expression:  value_expression.'+' value_expression \n\tvalue_expression:  value_expression.'-' value_expression \n\tvalue_expression:  value_expression.'*' value_expression \n\tvalue_expression:  value_expression.'/' value_expression \n\tvalue_expression:  value_expression.'%' value_expression \n\n\t'&'  shift 106\n\t'|'  shift 107\n\t'^'  shift 108\n\t'+'  shift 109\n\t'-'  shift 110\n\t'*'  shift 111\n\t'/'  shift 112\n\t'%'  shift 113\n\t.  reduce 101 (src line 589)\n\n\nstate 332\n\tcondition:  KEYRANGE '(' value ',' value ')'.    (105)\n\n\t.  reduce 105 (src line 605)\n\n\nstate 333\n\tvalue_expression:  value_expression.'&' value_expression \n\tvalue_expression:  value_expression.'|' value_expression \n\tvalue_expression:  value_expression.'^' value_expression \n\tvalue_expression:  value_expression.'+' value_expression \n\tvalue_expression:  value_expression.'-' value_expression \n\tvalue_expression:  value_expression.'*' value_expression \n\tvalue_expression:  value_expression.'/' value_expression \n\tvalue_expression:  value_expression.'%' value_expression \n\twhen_expression:  WHEN boolean_expression THEN value_expression.    (146)\n\n\t'&'  shift 106\n\t'|'  shift 107\n\t'^'  shift 108\n\t'+'  shift 109\n\t'-'  shift 110\n\t'*'  shift 111\n\t'/'  shift 112\n\t'%'  shift 113\n\t.  reduce 146 (src line 800)\n\n\nstate 334\n\tinsert_statement:  INSERT comment_opt INTO dml_table_expression column_list_opt row_list on_dup_opt.    (17)\n\n\t.  reduce 17 (src line 194)\n\n\nstate 335\n\ton_dup_opt:  ON.DUPLICATE KEY UPDATE update_list \n\n\tDUPLICATE  shift 353\n\t.  error\n\n\nstate 336\n\trow_list:  VALUES tuple_list.    (179)\n\ttuple_list:  tuple_list.',' row_tuple \n\n\t','  shift 354\n\t.  reduce 179 (src line 961)\n\n\nstate 337\n\ttuple_list:  row_tuple.    (181)\n\n\t.  reduce 181 (src line 971)\n\n\nstate 338\n\tinsert_statement:  INSERT comment_opt INTO dml_table_expression SET update_list on_dup_opt.    (18)\n\n\t.  reduce 18 (src line 199)\n\n\nstate 339\n\tcolumn_list_opt:  '(' column_list ')'.    (174)\n\n\t.  reduce 174 (src line 937)\n\n\nstate 340\n\tcolumn_list:  column_list ','.column_name \n\n\tID  shift 123\n\t.  error\n\n\tcolumn_name  goto 355\n\tsql_id  goto 144\n\nstate 341\n\tupdate_statement:  UPDATE comment_opt dml_table_expression SET update_list where_expression_opt order_by_opt.limit_opt \n\tlimit_opt: .    (167)\n\n\tLIMIT  shift 343\n\t.  reduce 167 (src line 899)\n\n\tlimit_opt  goto 356\n\nstate 342\n\tdelete_statement:  DELETE comment_opt FROM dml_table_expression where_expression_opt order_by_opt limit_opt.    (20)\n\n\t.  reduce 20 (src line 216)\n\n\nstate 343\n\tlimit_opt:  LIMIT.value_expression \n\tlimit_opt:  LIMIT.value_expression ',' value_expression \n\n\tNULL  shift 59\n\tVALUES  shift 65\n\tID  shift 123\n\tSTRING  shift 56\n\tNUMBER  shift 57\n\tVALUE_ARG  shift 58\n\t'('  shift 129\n\t'~'  shift 63\n\t'+'  shift 61\n\t'-'  shift 62\n\tCASE  shift 66\n\tIF  shift 64\n\t.  error\n\n\tvalue  goto 47\n\tvalue_expression  goto 357\n\trow_tuple  goto 49\n\tkeyword_as_func  goto 52\n\tsubquery  goto 60\n\tunary_operator  goto 50\n\tcolumn_name  goto 48\n\tcase_expression  goto 53\n\tsql_id  goto 51\n\nstate 344\n\torder_by_opt:  ORDER BY.order_list \n\n\tNULL  shift 59\n\tVALUES  shift 65\n\tID  shift 123\n\tSTRING  shift 56\n\tNUMBER  shift 57\n\tVALUE_ARG  shift 58\n\t'('  shift 129\n\t'~'  shift 63\n\t'+'  shift 61\n\t'-'  shift 62\n\tCASE  shift 66\n\tIF  shift 64\n\t.  error\n\n\tvalue  goto 47\n\tvalue_expression  goto 360\n\trow_tuple  goto 49\n\tkeyword_as_func  goto 52\n\tsubquery  goto 60\n\tunary_operator  goto 50\n\tcolumn_name  goto 48\n\tcase_expression  goto 53\n\torder_list  goto 358\n\torder  goto 359\n\tsql_id  goto 51\n\nstate 345\n\tcreate_statement:  CREATE constraint_opt INDEX sql_id using_opt ON ID.force_eof \n\tforce_eof: .    (206)\n\n\t.  reduce 206 (src line 1055)\n\n\tforce_eof  goto 361\n\nstate 346\n\talter_statement:  ALTER ignore_opt TABLE ID RENAME to_opt ID.    (26)\n\n\t.  reduce 26 (src line 248)\n\n\nstate 347\n\tselect_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 \n\torder_by_opt: .    (159)\n\n\tORDER  shift 315\n\t.  reduce 159 (src line 861)\n\n\torder_by_opt  goto 362\n\nstate 348\n\tmissing_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 \n\tlock_opt: .    (170)\n\n\tFOR  shift 364\n\tLOCK  shift 365\n\t.  reduce 170 (src line 912)\n\n\tlock_opt  goto 363\n\nstate 349\n\ttable_expression:  table_expression join_type table_expression ON boolean_expression.    (62)\n\tboolean_expression:  boolean_expression.AND boolean_expression \n\tboolean_expression:  boolean_expression.OR boolean_expression \n\n\tOR  shift 99\n\tAND  shift 98\n\t.  reduce 62 (src line 419)\n\n\nstate 350\n\tindex_hint_list:  USE INDEX '('.index_list ')' \n\n\tID  shift 96\n\t.  error\n\n\tindex_list  goto 366\n\tsql_id  goto 367\n\nstate 351\n\tindex_hint_list:  IGNORE INDEX '('.index_list ')' \n\n\tID  shift 96\n\t.  error\n\n\tindex_list  goto 368\n\tsql_id  goto 367\n\nstate 352\n\tindex_hint_list:  FORCE INDEX '('.index_list ')' \n\n\tID  shift 96\n\t.  error\n\n\tindex_list  goto 369\n\tsql_id  goto 367\n\nstate 353\n\ton_dup_opt:  ON DUPLICATE.KEY UPDATE update_list \n\n\tKEY  shift 370\n\t.  error\n\n\nstate 354\n\ttuple_list:  tuple_list ','.row_tuple \n\n\t'('  shift 129\n\t.  error\n\n\trow_tuple  goto 371\n\tsubquery  goto 60\n\nstate 355\n\tcolumn_list:  column_list ',' column_name.    (176)\n\n\t.  reduce 176 (src line 947)\n\n\nstate 356\n\tupdate_statement:  UPDATE comment_opt dml_table_expression SET update_list where_expression_opt order_by_opt limit_opt.    (19)\n\n\t.  reduce 19 (src line 210)\n\n\nstate 357\n\tvalue_expression:  value_expression.'&' value_expression \n\tvalue_expression:  value_expression.'|' value_expression \n\tvalue_expression:  value_expression.'^' value_expression \n\tvalue_expression:  value_expression.'+' value_expression \n\tvalue_expression:  value_expression.'-' value_expression \n\tvalue_expression:  value_expression.'*' value_expression \n\tvalue_expression:  value_expression.'/' value_expression \n\tvalue_expression:  value_expression.'%' value_expression \n\tlimit_opt:  LIMIT value_expression.    (168)\n\tlimit_opt:  LIMIT value_expression.',' value_expression \n\n\t','  shift 372\n\t'&'  shift 106\n\t'|'  shift 107\n\t'^'  shift 108\n\t'+'  shift 109\n\t'-'  shift 110\n\t'*'  shift 111\n\t'/'  shift 112\n\t'%'  shift 113\n\t.  reduce 168 (src line 903)\n\n\nstate 358\n\torder_by_opt:  ORDER BY order_list.    (160)\n\torder_list:  order_list.',' order \n\n\t','  shift 373\n\t.  reduce 160 (src line 865)\n\n\nstate 359\n\torder_list:  order.    (161)\n\n\t.  reduce 161 (src line 870)\n\n\nstate 360\n\tvalue_expression:  value_expression.'&' value_expression \n\tvalue_expression:  value_expression.'|' value_expression \n\tvalue_expression:  value_expression.'^' value_expression \n\tvalue_expression:  value_expression.'+' value_expression \n\tvalue_expression:  value_expression.'-' value_expression \n\tvalue_expression:  value_expression.'*' value_expression \n\tvalue_expression:  value_expression.'/' value_expression \n\tvalue_expression:  value_expression.'%' value_expression \n\torder:  value_expression.asc_desc_opt \n\tasc_desc_opt: .    (164)\n\n\tASC  shift 375\n\tDESC  shift 376\n\t'&'  shift 106\n\t'|'  shift 107\n\t'^'  shift 108\n\t'+'  shift 109\n\t'-'  shift 110\n\t'*'  shift 111\n\t'/'  shift 112\n\t'%'  shift 113\n\t.  reduce 164 (src line 886)\n\n\tasc_desc_opt  goto 374\n\nstate 361\n\tcreate_statement:  CREATE constraint_opt INDEX sql_id using_opt ON ID force_eof.    (23)\n\n\t.  reduce 23 (src line 233)\n\n\nstate 362\n\tselect_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 \n\tlimit_opt: .    (167)\n\n\tLIMIT  shift 343\n\t.  reduce 167 (src line 899)\n\n\tlimit_opt  goto 377\n\nstate 363\n\tmissing_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.    (14)\n\n\t.  reduce 14 (src line 178)\n\n\nstate 364\n\tlock_opt:  FOR.UPDATE \n\n\tUPDATE  shift 378\n\t.  error\n\n\nstate 365\n\tlock_opt:  LOCK.IN sql_id sql_id \n\n\tIN  shift 379\n\t.  error\n\n\nstate 366\n\tindex_hint_list:  USE INDEX '(' index_list.')' \n\tindex_list:  index_list.',' sql_id \n\n\t','  shift 381\n\t')'  shift 380\n\t.  error\n\n\nstate 367\n\tindex_list:  sql_id.    (84)\n\n\t.  reduce 84 (src line 516)\n\n\nstate 368\n\tindex_hint_list:  IGNORE INDEX '(' index_list.')' \n\tindex_list:  index_list.',' sql_id \n\n\t','  shift 381\n\t')'  shift 382\n\t.  error\n\n\nstate 369\n\tindex_hint_list:  FORCE INDEX '(' index_list.')' \n\tindex_list:  index_list.',' sql_id \n\n\t','  shift 381\n\t')'  shift 383\n\t.  error\n\n\nstate 370\n\ton_dup_opt:  ON DUPLICATE KEY.UPDATE update_list \n\n\tUPDATE  shift 384\n\t.  error\n\n\nstate 371\n\ttuple_list:  tuple_list ',' row_tuple.    (182)\n\n\t.  reduce 182 (src line 976)\n\n\nstate 372\n\tlimit_opt:  LIMIT value_expression ','.value_expression \n\n\tNULL  shift 59\n\tVALUES  shift 65\n\tID  shift 123\n\tSTRING  shift 56\n\tNUMBER  shift 57\n\tVALUE_ARG  shift 58\n\t'('  shift 129\n\t'~'  shift 63\n\t'+'  shift 61\n\t'-'  shift 62\n\tCASE  shift 66\n\tIF  shift 64\n\t.  error\n\n\tvalue  goto 47\n\tvalue_expression  goto 385\n\trow_tuple  goto 49\n\tkeyword_as_func  goto 52\n\tsubquery  goto 60\n\tunary_operator  goto 50\n\tcolumn_name  goto 48\n\tcase_expression  goto 53\n\tsql_id  goto 51\n\nstate 373\n\torder_list:  order_list ','.order \n\n\tNULL  shift 59\n\tVALUES  shift 65\n\tID  shift 123\n\tSTRING  shift 56\n\tNUMBER  shift 57\n\tVALUE_ARG  shift 58\n\t'('  shift 129\n\t'~'  shift 63\n\t'+'  shift 61\n\t'-'  shift 62\n\tCASE  shift 66\n\tIF  shift 64\n\t.  error\n\n\tvalue  goto 47\n\tvalue_expression  goto 360\n\trow_tuple  goto 49\n\tkeyword_as_func  goto 52\n\tsubquery  goto 60\n\tunary_operator  goto 50\n\tcolumn_name  goto 48\n\tcase_expression  goto 53\n\torder  goto 386\n\tsql_id  goto 51\n\nstate 374\n\torder:  value_expression asc_desc_opt.    (163)\n\n\t.  reduce 163 (src line 880)\n\n\nstate 375\n\tasc_desc_opt:  ASC.    (165)\n\n\t.  reduce 165 (src line 890)\n\n\nstate 376\n\tasc_desc_opt:  DESC.    (166)\n\n\t.  reduce 166 (src line 894)\n\n\nstate 377\n\tselect_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 \n\tlock_opt: .    (170)\n\n\tFOR  shift 364\n\tLOCK  shift 365\n\t.  reduce 170 (src line 912)\n\n\tlock_opt  goto 387\n\nstate 378\n\tlock_opt:  FOR UPDATE.    (171)\n\n\t.  reduce 171 (src line 916)\n\n\nstate 379\n\tlock_opt:  LOCK IN.sql_id sql_id \n\n\tID  shift 96\n\t.  error\n\n\tsql_id  goto 388\n\nstate 380\n\tindex_hint_list:  USE INDEX '(' index_list ')'.    (81)\n\n\t.  reduce 81 (src line 503)\n\n\nstate 381\n\tindex_list:  index_list ','.sql_id \n\n\tID  shift 96\n\t.  error\n\n\tsql_id  goto 389\n\nstate 382\n\tindex_hint_list:  IGNORE INDEX '(' index_list ')'.    (82)\n\n\t.  reduce 82 (src line 507)\n\n\nstate 383\n\tindex_hint_list:  FORCE INDEX '(' index_list ')'.    (83)\n\n\t.  reduce 83 (src line 511)\n\n\nstate 384\n\ton_dup_opt:  ON DUPLICATE KEY UPDATE.update_list \n\n\tID  shift 123\n\t.  error\n\n\tcolumn_name  goto 143\n\tupdate_list  goto 390\n\tupdate_expression  goto 142\n\tsql_id  goto 144\n\nstate 385\n\tvalue_expression:  value_expression.'&' value_expression \n\tvalue_expression:  value_expression.'|' value_expression \n\tvalue_expression:  value_expression.'^' value_expression \n\tvalue_expression:  value_expression.'+' value_expression \n\tvalue_expression:  value_expression.'-' value_expression \n\tvalue_expression:  value_expression.'*' value_expression \n\tvalue_expression:  value_expression.'/' value_expression \n\tvalue_expression:  value_expression.'%' value_expression \n\tlimit_opt:  LIMIT value_expression ',' value_expression.    (169)\n\n\t'&'  shift 106\n\t'|'  shift 107\n\t'^'  shift 108\n\t'+'  shift 109\n\t'-'  shift 110\n\t'*'  shift 111\n\t'/'  shift 112\n\t'%'  shift 113\n\t.  reduce 169 (src line 907)\n\n\nstate 386\n\torder_list:  order_list ',' order.    (162)\n\n\t.  reduce 162 (src line 875)\n\n\nstate 387\n\tselect_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.    (15)\n\n\t.  reduce 15 (src line 184)\n\n\nstate 388\n\tlock_opt:  LOCK IN sql_id.sql_id \n\n\tID  shift 96\n\t.  error\n\n\tsql_id  goto 391\n\nstate 389\n\tindex_list:  index_list ',' sql_id.    (85)\n\n\t.  reduce 85 (src line 521)\n\n\nstate 390\n\ton_dup_opt:  ON DUPLICATE KEY UPDATE update_list.    (178)\n\tupdate_list:  update_list.',' update_expression \n\n\t','  shift 211\n\t.  reduce 178 (src line 956)\n\n\nstate 391\n\tlock_opt:  LOCK IN sql_id sql_id.    (172)\n\n\t.  reduce 172 (src line 920)\n\n\n101 terminals, 75 nonterminals\n207 grammar rules, 392/2000 states\n0 shift/reduce, 0 reduce/reduce conflicts reported\n124 working sets used\nmemory: parser 742/30000\n405 extra closures\n1040 shift entries, 1 exceptions\n210 goto entries\n386 entries saved by goto default\nOptimizer space used: output 678/30000\n678 table entries, 102 zero\nmaximum spread: 101, maximum offset: 388\n"
  },
  {
    "path": "storage/sqlite.go",
    "content": "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/inputs\"\n\t\"github.com/dinedal/textql/sqlparser\"\n\n\tsqlite3 \"github.com/mattn/go-sqlite3\"\n)\n\n// SQLite3Storage represents a TextQL compatible SQL backend based on in-memory SQLite3\ntype SQLite3Storage struct {\n\toptions        *SQLite3Options\n\tdb             *sql.DB\n\tconnID         int\n\tfirstTableName string\n}\n\n// SQLite3Options are options passed into SQLite3 connection as needed.\ntype SQLite3Options struct{}\n\nvar (\n\tsqlite3conn          = []*sqlite3.SQLiteConn{}\n\tallWhiteSpace        = regexp.MustCompile(\"^\\\\s+$\")\n\ttableNameCheckRegEx  = regexp.MustCompile(`.*\\[.*\\].*`)\n\tcolumnNameCheckRegEx = regexp.MustCompile(`.*\\[.*\\].*`)\n)\n\ntype entrypoint struct {\n\tlib  string\n\tproc string\n}\n\nvar libNames = []entrypoint{\n\t{\"libgo-sqlite3-extension-functions.so\", \"sqlite3_extension_init\"},\n\t{\"libgo-sqlite3-extension-functions.dylib\", \"sqlite3_extension_init\"},\n\t{\"libgo-sqlite3-extension-functions.dll\", \"sqlite3_extension_init\"},\n}\n\nfunc init() {\n\tsql.Register(\"sqlite3_textql\",\n\t\t&sqlite3.SQLiteDriver{\n\t\t\tConnectHook: func(conn *sqlite3.SQLiteConn) error {\n\t\t\t\tfor _, v := range libNames {\n\t\t\t\t\tconn.LoadExtension(v.lib, v.proc)\n\t\t\t\t}\n\t\t\t\tsqlite3conn = append(sqlite3conn, conn)\n\t\t\t\treturn conn.RegisterFunc(\"regexp\", regExp, true)\n\t\t\t},\n\t\t})\n}\n\n// NewSQLite3StorageWithDefaults returns a SQLite3Storage with the default options.\nfunc NewSQLite3StorageWithDefaults() *SQLite3Storage {\n\treturn NewSQLite3Storage(&SQLite3Options{})\n}\n\n// NewSQLite3Storage returns a SQLite3Storage with the SQLite3Options provided applied.\nfunc NewSQLite3Storage(opts *SQLite3Options) *SQLite3Storage {\n\tsqlite3Storage := &SQLite3Storage{\n\t\toptions:        opts,\n\t\tfirstTableName: \"\",\n\t}\n\n\tsqlite3Storage.open()\n\treturn sqlite3Storage\n}\n\nfunc (sqlite3Storage *SQLite3Storage) open() {\n\tdb, err := sql.Open(\"sqlite3_textql\", \":memory:\")\n\n\tif err != nil {\n\t\tlog.Fatalln(err)\n\t}\n\n\terr = db.Ping()\n\n\tif err != nil {\n\t\tlog.Fatalln(err)\n\t}\n\n\tsqlite3Storage.connID = len(sqlite3conn) - 1\n\tsqlite3Storage.db = db\n}\n\n// LoadInput reads the entire Input provided into a table named after the Input name.\n// The name is cooreced into a valid SQLite3 table name prior to use.\nfunc (sqlite3Storage *SQLite3Storage) LoadInput(input inputs.Input) {\n\ttableName := strings.Replace(input.Name(), path.Ext(input.Name()), \"\", -1)\n\tsqlite3Storage.createTable(tableName, input.Header(), false)\n\n\ttx, txErr := sqlite3Storage.db.Begin()\n\n\tif txErr != nil {\n\t\tlog.Fatalln(txErr)\n\t}\n\n\tstmt := sqlite3Storage.createLoadStmt(tableName, len(input.Header()), tx)\n\n\trow := input.ReadRecord()\n\tfor {\n\t\tif row == nil {\n\t\t\tbreak\n\t\t}\n\t\tsqlite3Storage.loadRow(tableName, len(input.Header()), row, tx, stmt, true)\n\t\trow = input.ReadRecord()\n\t}\n\tstmt.Close()\n\ttx.Commit()\n\n\tif sqlite3Storage.firstTableName == \"\" {\n\t\tsqlite3Storage.firstTableName = tableName\n\t}\n}\n\nfunc (sqlite3Storage *SQLite3Storage) createTable(tableName string, columnNames []string, verbose bool) error {\n\tvar buffer bytes.Buffer\n\n\tif tableNameCheckRegEx.FindString(tableName) != \"\" {\n\t\tlog.Fatalln(\"Invalid table name\", tableName)\n\t}\n\n\tbuffer.WriteString(\"CREATE TABLE IF NOT EXISTS [\" + (tableName) + \"] (\")\n\n\tfor i, col := range columnNames {\n\t\tif columnNameCheckRegEx.FindString(col) != \"\" {\n\t\t\tlog.Fatalln(\"Invalid table name\", col)\n\t\t}\n\n\t\tbuffer.WriteString(\"[\" + col + \"] NUMERIC\")\n\n\t\tif i != len(columnNames)-1 {\n\t\t\tbuffer.WriteString(\", \")\n\t\t}\n\t}\n\n\tbuffer.WriteString(\");\")\n\n\t_, err := sqlite3Storage.db.Exec(buffer.String())\n\n\tif err != nil {\n\t\tlog.Fatalln(err)\n\t}\n\n\tif verbose {\n\t\tlog.Println(buffer.String())\n\t}\n\n\treturn err\n}\n\nfunc (sqlite3Storage *SQLite3Storage) createLoadStmt(tableName string, colCount int, db *sql.Tx) *sql.Stmt {\n\tif colCount == 0 {\n\t\tlog.Fatalln(\"Nothing to build insert with!\")\n\t}\n\tvar buffer bytes.Buffer\n\n\tbuffer.WriteString(\"INSERT INTO [\" + (tableName) + \"] VALUES (\")\n\t// Don't write the comma for the last column\n\tfor i := 1; i <= colCount; i++ {\n\t\tbuffer.WriteString(\"nullif(?,'')\")\n\t\tif i != colCount {\n\t\t\tbuffer.WriteString(\", \")\n\t\t}\n\t}\n\n\tbuffer.WriteString(\");\")\n\n\tstmt, err := db.Prepare(buffer.String())\n\n\tif err != nil {\n\t\tlog.Fatalln(err)\n\t}\n\treturn stmt\n}\n\nfunc (sqlite3Storage *SQLite3Storage) loadRow(tableName string, colCount int, values []string, db *sql.Tx, stmt *sql.Stmt, verbose bool) error {\n\tif len(values) == 0 || colCount == 0 {\n\t\treturn nil\n\t}\n\n\tvar vals []interface{}\n\n\tfor i := 0; i < colCount; i++ {\n\t\tif allWhiteSpace.MatchString(values[i]) {\n\t\t\tvals = append(vals, \"\")\n\t\t} else {\n\t\t\tvals = append(vals, values[i])\n\t\t}\n\t}\n\n\t_, err := stmt.Exec(vals...)\n\n\tif err != nil && verbose {\n\t\tlog.Printf(\"Bad row: %v\\n\", err)\n\t}\n\n\treturn err\n}\n\n// ExecuteSQLString maps the sqlQuery provided from short hand TextQL to SQL, then\n// applies the query to the sqlite3 in memory database, and lastly returns the sql.Rows\n// that resulted from the executing query.\nfunc (sqlite3Storage *SQLite3Storage) ExecuteSQLString(sqlQuery string) (*sql.Rows, error) {\n\tvar result *sql.Rows\n\tvar err error\n\n\tif strings.Trim(sqlQuery, \" \") != \"\" {\n\t\timplictFromSQL := sqlparser.Magicify(sqlQuery, sqlite3Storage.firstTableName)\n\t\tresult, err = sqlite3Storage.db.Query(implictFromSQL)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\n\treturn result, nil\n}\n\n// Exec maps the sqlQuery provided from short hand TextQL to SQL, then\n// applies the query to the sqlite3 in memory database, and lastly returns the sql.Result\n// that resulted from the executing query.\nfunc (sqlite3Storage *SQLite3Storage) Exec(sqlQuery string) (sql.Result, error) {\n\tvar result sql.Result\n\tvar err error\n\n\tif strings.Trim(sqlQuery, \" \") != \"\" {\n\t\timplictFromSQL := sqlparser.Magicify(sqlQuery, sqlite3Storage.firstTableName)\n\t\tresult, err = sqlite3Storage.db.Exec(implictFromSQL)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\n\treturn result, nil\n}\n\n// SaveTo saves the current in memory database to the path provided as a string.\nfunc (sqlite3Storage *SQLite3Storage) SaveTo(path string) error {\n\tbackupDb, openErr := sql.Open(\"sqlite3_textql\", path)\n\tif openErr != nil {\n\t\treturn openErr\n\t}\n\n\tbackupPingErr := backupDb.Ping()\n\tif backupPingErr != nil {\n\t\treturn backupPingErr\n\t}\n\tbackupConnID := len(sqlite3conn) - 1\n\n\tbackup, backupStartErr := sqlite3conn[backupConnID].Backup(\"main\", sqlite3conn[sqlite3Storage.connID], \"main\")\n\tif backupStartErr != nil {\n\t\treturn backupStartErr\n\t}\n\n\t_, backupPerformError := backup.Step(-1)\n\tif backupPerformError != nil {\n\t\treturn backupPerformError\n\t}\n\n\tbackupFinishError := backup.Finish()\n\tif backupFinishError != nil {\n\t\treturn backupFinishError\n\t}\n\n\tbackupCloseError := backupDb.Close()\n\tif backupCloseError != nil {\n\t\treturn backupCloseError\n\t}\n\n\treturn nil\n}\n\n// Close will close the current database\nfunc (sqlite3Storage *SQLite3Storage) Close() {\n\tsqlite3Storage.db.Close()\n}\n"
  },
  {
    "path": "storage/sqlite_regexp.go",
    "content": "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",
    "content": "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.com/dinedal/textql/test_util\"\n)\n\nvar (\n\tstorageOpts = &SQLite3Options{}\n\tsimpleCSV   = `a,b,c\n1,2,3\n4,5,6`\n\twhitespaceValuesCSV = `a,b,c\n  , ,\n1,2,3\n4,5,6`\n)\n\nfunc NewTestCSVInput() (input inputs.Input, fp *os.File) {\n\tfp = test_util.OpenFileFromString(simpleCSV)\n\n\topts := &inputs.CSVInputOptions{\n\t\tHasHeader: true,\n\t\tSeparator: ',',\n\t\tReadFrom:  fp,\n\t}\n\n\tnewInput, _ := inputs.NewCSVInput(opts)\n\treturn newInput, fp\n}\n\nfunc TestSQLiteStorageLoadInput(t *testing.T) {\n\tstorage := NewSQLite3Storage(storageOpts)\n\tinput, fp := NewTestCSVInput()\n\tdefer fp.Close()\n\tdefer os.Remove(fp.Name())\n\tdefer storage.Close()\n\n\tstorage.LoadInput(input)\n}\n\nfunc TestSQLiteStorageSaveTo(t *testing.T) {\n\tvar (\n\t\tcmdOut   []byte\n\t\terr      error\n\t\ttempFile *os.File\n\t)\n\n\tstorage := NewSQLite3Storage(storageOpts)\n\tinput, fp := NewTestCSVInput()\n\tdefer fp.Close()\n\tdefer os.Remove(fp.Name())\n\tdefer storage.Close()\n\n\tstorage.LoadInput(input)\n\n\ttempFile, err = ioutil.TempFile(os.TempDir(), \"textql_test\")\n\n\tif err != nil {\n\t\tt.Fatalf(err.Error())\n\t}\n\n\tdefer os.Remove(tempFile.Name())\n\ttempFile.Close()\n\tstorage.SaveTo(tempFile.Name())\n\tstorage.Close()\n\n\targs := []string{tempFile.Name(), \"pragma integrity_check;\"}\n\n\tcmd := exec.Command(\"sqlite3\", args...)\n\tcmd.Stderr = os.Stderr\n\tcmd.Stdin = os.Stdin\n\n\tif cmdOut, err = cmd.Output(); err != nil {\n\t\tfmt.Println(string(cmdOut))\n\t\tfmt.Println(args)\n\t\tt.Fatalf(err.Error())\n\t}\n\tcmdOutStr := string(cmdOut)\n\n\tif cmdOutStr != \"ok\\n\" {\n\t\tfmt.Println(cmdOutStr)\n\t\tt.Fatalf(\"SaveTo integrity check failed!\")\n\t}\n}\n\nfunc TestSQLiteStorageExecuteSQLStringNormalSQL(t *testing.T) {\n\tstorage := NewSQLite3Storage(storageOpts)\n\tinput, fp := NewTestCSVInput()\n\tdefer fp.Close()\n\tdefer os.Remove(fp.Name())\n\tdefer storage.Close()\n\n\tstorage.LoadInput(input)\n\n\tsqlString := \"select count(*) from \" + storage.firstTableName\n\n\trows, rowsErr := storage.ExecuteSQLString(sqlString)\n\n\tif rowsErr != nil {\n\t\tt.Fatalf(rowsErr.Error())\n\t}\n\n\tcols, colsErr := rows.Columns()\n\n\tif colsErr != nil {\n\t\tt.Fatalf(colsErr.Error())\n\t}\n\n\tif len(cols) != 1 {\n\t\tt.Fatalf(\"Expected 1 column, got (%v)\", len(cols))\n\t}\n\n\tvar dest int\n\n\tfor rows.Next() {\n\t\trows.Scan(&dest)\n\t\tif dest != 2 {\n\t\t\tt.Fatalf(\"Expected 2 rows counted, got (%v)\", dest)\n\t\t}\n\t}\n}\n\nfunc TestSQLiteStorageExecuteSQLStringMissingSelect(t *testing.T) {\n\tstorage := NewSQLite3Storage(storageOpts)\n\tinput, fp := NewTestCSVInput()\n\tdefer fp.Close()\n\tdefer os.Remove(fp.Name())\n\tdefer storage.Close()\n\n\tstorage.LoadInput(input)\n\n\tsqlString := \"count(*) from \" + storage.firstTableName\n\n\trows, rowsErr := storage.ExecuteSQLString(sqlString)\n\n\tif rowsErr != nil {\n\t\tt.Fatalf(rowsErr.Error())\n\t}\n\n\tcols, colsErr := rows.Columns()\n\n\tif colsErr != nil {\n\t\tt.Fatalf(colsErr.Error())\n\t}\n\n\tif len(cols) != 1 {\n\t\tt.Fatalf(\"Expected 1 column, got (%v)\", len(cols))\n\t}\n\n\tvar dest int\n\n\tfor rows.Next() {\n\t\trows.Scan(&dest)\n\t\tif dest != 2 {\n\t\t\tt.Fatalf(\"Expected 2 rows counted, got (%v)\", dest)\n\t\t}\n\t}\n}\n\nfunc LoadTestDataAndExecuteQuery(t *testing.T, testData string, sqlString string) (map[int]map[string]interface{}, []string) {\n\tstorage := NewSQLite3Storage(storageOpts)\n\tfp := test_util.OpenFileFromString(testData)\n\n\topts := &inputs.CSVInputOptions{\n\t\tHasHeader: true,\n\t\tSeparator: ',',\n\t\tReadFrom:  fp,\n\t}\n\n\tinput, _ := inputs.NewCSVInput(opts)\n\tdefer fp.Close()\n\tdefer os.Remove(fp.Name())\n\tdefer storage.Close()\n\n\tstorage.LoadInput(input)\n\n\trows, rowsErr := storage.ExecuteSQLString(sqlString)\n\n\tif rowsErr != nil {\n\t\tt.Fatalf(rowsErr.Error())\n\t}\n\n\tcols, colsErr := rows.Columns()\n\n\tif colsErr != nil {\n\t\tt.Fatalf(colsErr.Error())\n\t}\n\n\trowNumber := 0\n\tresult := make(map[int]map[string]interface{})\n\trawResult := make([]interface{}, len(cols))\n\tdest := make([]interface{}, len(cols))\n\n\tfor i := range cols {\n\t\tdest[i] = &rawResult[i]\n\t}\n\n\tfor rows.Next() {\n\t\tscanErr := rows.Scan(dest...)\n\n\t\tif scanErr != nil {\n\t\t\tt.Fatalf(scanErr.Error())\n\t\t}\n\n\t\tresult[rowNumber] = make(map[string]interface{})\n\t\tfor i, raw := range rawResult {\n\t\t\tresult[rowNumber][cols[i]] = raw\n\t\t}\n\t\trowNumber++\n\t}\n\n\treturn result, cols\n}\n\nfunc TestSQLiteStorageExecuteSQLStringMissingFromOuterQuery(t *testing.T) {\n\tdata, cols := LoadTestDataAndExecuteQuery(t, simpleCSV, \"count(*)\")\n\n\tif len(cols) != 1 {\n\t\tt.Fatalf(\"Expected 1 column, got (%v)\", len(cols))\n\t}\n\n\tintVal := data[0][\"count(*)\"].(int64)\n\tif intVal != 2 {\n\t\tt.Fatalf(\"Expected 2 rows counted, got (%v)\", intVal)\n\t}\n}\n\nfunc TestSQLiteStorageExecuteSQLStringMissingFromSubQuery(t *testing.T) {\n\tdata, cols := LoadTestDataAndExecuteQuery(t, simpleCSV, \"count(*) from (select *)\")\n\n\tif len(cols) != 1 {\n\t\tt.Fatalf(\"Expected 1 column, got (%v)\", len(cols))\n\t}\n\n\tintVal := data[0][\"count(*)\"].(int64)\n\tif intVal != 2 {\n\t\tt.Fatalf(\"Expected 2 rows counted, got (%v)\", intVal)\n\t}\n}\n\nfunc TestWhitespaceLoadsAsNull(t *testing.T) {\n\tdata, cols := LoadTestDataAndExecuteQuery(t, whitespaceValuesCSV, \"max(a)\")\n\n\tif len(cols) != 1 {\n\t\tt.Fatalf(\"Expected 1 column, got (%v)\", len(cols))\n\t}\n\n\tintVal := data[0][\"max(a)\"].(int64)\n\tif intVal != 4 {\n\t\tt.Fatalf(\"Expected 4 max value, got (%v)\", intVal)\n\t}\n\n\tdata, cols = LoadTestDataAndExecuteQuery(t, whitespaceValuesCSV, \"typeof(a)\")\n\n\tif len(cols) != 1 {\n\t\tt.Fatalf(\"Expected 1 column, got (%v)\", len(cols))\n\t}\n\n\tstrval := data[0][\"typeof(a)\"].(string)\n\tif strval != \"null\" {\n\t\tt.Fatalf(\"Expected null value, got (%v)\", strval)\n\t}\n\n\tstrval = data[1][\"typeof(a)\"].(string)\n\tif strval != \"integer\" {\n\t\tt.Fatalf(\"Expected integer value, got (%v)\", strval)\n\t}\n\n\tstrval = data[2][\"typeof(a)\"].(string)\n\tif strval != \"integer\" {\n\t\tt.Fatalf(\"Expected integer value, got (%v)\", strval)\n\t}\n\n\tdata, cols = LoadTestDataAndExecuteQuery(t, whitespaceValuesCSV, \"max(b)\")\n\n\tif len(cols) != 1 {\n\t\tt.Fatalf(\"Expected 1 column, got (%v)\", len(cols))\n\t}\n\n\tintVal = data[0][\"max(b)\"].(int64)\n\tif intVal != 5 {\n\t\tt.Fatalf(\"Expected 5 max value, got (%v)\", intVal)\n\t}\n\n\tdata, cols = LoadTestDataAndExecuteQuery(t, whitespaceValuesCSV, \"typeof(b)\")\n\n\tif len(cols) != 1 {\n\t\tt.Fatalf(\"Expected 1 column, got (%v)\", len(cols))\n\t}\n\n\tstrval = data[0][\"typeof(b)\"].(string)\n\tif strval != \"null\" {\n\t\tt.Fatalf(\"Expected null value, got (%v)\", strval)\n\t}\n\n\tstrval = data[1][\"typeof(b)\"].(string)\n\tif strval != \"integer\" {\n\t\tt.Fatalf(\"Expected integer value, got (%v)\", strval)\n\t}\n\n\tstrval = data[2][\"typeof(b)\"].(string)\n\tif strval != \"integer\" {\n\t\tt.Fatalf(\"Expected integer value, got (%v)\", strval)\n\t}\n}\n\nfunc TestSQLiteStorageExec(t *testing.T) {\n\tstorage := NewSQLite3Storage(storageOpts)\n\tinput, fp := NewTestCSVInput()\n\tdefer fp.Close()\n\tdefer os.Remove(fp.Name())\n\tdefer storage.Close()\n\n\tstorage.LoadInput(input)\n\n\tsqlString := \"insert into \" + storage.firstTableName + \" values (7,8,9)\"\n\n\tresult, resultErr := storage.Exec(sqlString)\n\n\tif resultErr != nil {\n\t\tt.Fatalf(resultErr.Error())\n\t}\n\n\trowsAffected, rowsErr := result.RowsAffected()\n\n\tif rowsErr != nil {\n\t\tt.Fatalf(rowsErr.Error())\n\t}\n\n\tif rowsAffected != 1 {\n\t\tt.Fatalf(\"Expected 1 row affected, got (%v)\", rowsAffected)\n\t}\n}\n"
  },
  {
    "path": "storage/storage.go",
    "content": "package storage\n\nimport (\n\t\"database/sql\"\n\n\t\"github.com/dinedal/textql/inputs\"\n)\n\n// Storage implentors are expected to be SQL capable engines.\n// A Storage should support loading data from a TextQL input,\n// executing any number of SQL statements and returning their resultant\n// sql.Rows, as well as supporting clean closing and \"backing up\" of\n// data to a specific path\ntype Storage interface {\n\t// LoadInput should make all the data in the input accessible to queries.\n\tLoadInput(*inputs.Input)\n\t// SaveTo should write the entire database of the SQL backend to the path given as a string.\n\t// Failure in any way should return an error, and nil if the operation was successful.\n\tSaveTo(string) error\n\t// ExecuteSQLString should first convert from TextQL shorthand SQL to normal SQL,\n\t// apply the query or transformation given to the SQL backend and return either nil\n\t// or the sql.Rows that were returned from the query.\n\tExecuteSQLString(string) (*sql.Rows, error)\n\t// Close should cleanly close the database backend, cleaning up data on disk if required.\n\tClose()\n}\n"
  },
  {
    "path": "test_util/test_util.go",
    "content": "package test_util\n\nimport (\n\t\"io/ioutil\"\n\t\"os\"\n)\n\nfunc OpenFileFromString(contents string) *os.File {\n\tf, _ := ioutil.TempFile(\"./\", \"csv\")\n\tf.WriteString(contents)\n\tf.Seek(0, 0)\n\treturn f\n}\n"
  },
  {
    "path": "textql/main.go",
    "content": "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/inputs\"\n\t\"github.com/dinedal/textql/outputs\"\n\t\"github.com/dinedal/textql/storage\"\n\t\"github.com/dinedal/textql/util\"\n)\n\ntype commandLineOptions struct {\n\tStatements      *string\n\tStatementsFile  *string\n\tSourceFile      *string\n\tDelimiter       *string\n\tHeader          *bool\n\tOutputHeader    *bool\n\tOutputDelimiter *string\n\tOutputFile      *string\n\tSaveTo          *string\n\tConsole         *bool\n\tVersion         *bool\n\tQuiet           *bool\n\tPretty          *bool\n}\n\n// Must be set at build via -ldflags \"-X main.VERSION=`cat VERSION`\"\nvar VERSION string\n\nfunc newCommandLineOptions() *commandLineOptions {\n\tcmdLineOpts := commandLineOptions{}\n\tcmdLineOpts.Statements = flag.String(\"sql\", \"\", \"SQL Statement(s) to run on the data\")\n\tcmdLineOpts.StatementsFile = flag.String(\"sqlfile\", \"\", \"SQL filepath to run on the data\")\n\tcmdLineOpts.Delimiter = flag.String(\"dlm\", \",\", \"Input delimiter character between fields -dlm=tab for tab, -dlm=0x## to specify a character code in hex\")\n\tcmdLineOpts.Header = flag.Bool(\"header\", false, \"Treat input files as having the first row as a header row\")\n\tcmdLineOpts.OutputHeader = flag.Bool(\"output-header\", false, \"Display column names in output\")\n\tcmdLineOpts.OutputDelimiter = flag.String(\"output-dlm\", \",\", \"Output delimiter character between fields -output-dlm=tab for tab, -dlm=0x## to specify a character code in hex\")\n\tcmdLineOpts.OutputFile = flag.String(\"output-file\", \"stdout\", \"Filename to write output to, if empty no output is written\")\n\tcmdLineOpts.SaveTo = flag.String(\"save-to\", \"\", \"SQLite3 db is left on disk at this file\")\n\tcmdLineOpts.Console = flag.Bool(\"console\", false, \"After all statements are run, open SQLite3 REPL with this data\")\n\tcmdLineOpts.Version = flag.Bool(\"version\", false, \"Print version and exit\")\n\tcmdLineOpts.Quiet = flag.Bool(\"quiet\", false, \"Surpress logging\")\n\tcmdLineOpts.Pretty = flag.Bool(\"pretty\", false, \"Output pretty formatting\")\n\tflag.Usage = cmdLineOpts.Usage\n\tflag.Parse()\n\n\treturn &cmdLineOpts\n}\n\nfunc (clo *commandLineOptions) GetStatements() (string, *error) {\n\tif clo.Statements == nil && clo.StatementsFile == nil {\n\t\terr := fmt.Errorf(\"No SQL statements provided\")\n\t\treturn \"\", &err\n\t}\n\tif clo.Statements != nil && *clo.Statements != \"\" {\n\t\treturn *clo.Statements, nil\n\t}\n\tfilepath := *clo.StatementsFile\n\tdat, err := os.ReadFile(filepath)\n\tif err != nil {\n\t\treturn \"\", &err\n\t}\n\treturn string(dat), nil\n}\n\nfunc (clo *commandLineOptions) GetSourceFiles() []string {\n\treturn flag.Args()\n}\n\nfunc (clo *commandLineOptions) GetDelimiter() string {\n\treturn *clo.Delimiter\n}\n\nfunc (clo *commandLineOptions) GetHeader() bool {\n\treturn *clo.Header\n}\n\nfunc (clo *commandLineOptions) GetOutputHeader() bool {\n\treturn *clo.OutputHeader\n}\n\nfunc (clo *commandLineOptions) GetOutputDelimiter() string {\n\treturn *clo.OutputDelimiter\n}\n\nfunc (clo *commandLineOptions) GetOutputFile() string {\n\treturn *clo.OutputFile\n}\n\nfunc (clo *commandLineOptions) GetSaveTo() string {\n\treturn util.CleanPath(*clo.SaveTo)\n}\n\nfunc (clo *commandLineOptions) GetConsole() bool {\n\treturn *clo.Console\n}\n\nfunc (clo *commandLineOptions) GetVersion() bool {\n\treturn *clo.Version\n}\n\nfunc (clo *commandLineOptions) GetQuiet() bool {\n\treturn *clo.Quiet\n}\n\nfunc (clo *commandLineOptions) GetPretty() bool {\n\treturn *clo.Pretty\n}\n\nfunc (clo *commandLineOptions) Usage() {\n\tif !clo.GetQuiet() {\n\t\tfmt.Fprintf(os.Stderr, \"Usage of %s:\\n\", os.Args[0])\n\t\tfmt.Fprintf(os.Stderr, \"\\n\")\n\t\tfmt.Fprintf(os.Stderr, \"  %s [-console] [-save-to path path] [-output-file path] [-output-dlm delimter] [-output-header] [-pretty] [-quiet] [-header] [-dlm delimter] [-sql sql_statements] [path ...] \\n\", os.Args[0])\n\t\tfmt.Fprintf(os.Stderr, \"\\n\")\n\t\tflag.PrintDefaults()\n\t}\n}\n\nfunc handleSemiColon(sqlStrings *[]string) []string {\n\tvar stack []string\n\tvar current string\n\tindex := 0\n\tcurrent = (*sqlStrings)[index]\n\tfor {\n\t\tif current == \"\" {\n\t\t\tcurrent = (*sqlStrings)[index]\n\t\t}\n\t\tcount := strings.Count(current, \"'\")\n\t\tif count%2 == 1 {\n\t\t\tcurrent = current + \";\" + (*sqlStrings)[index+1]\n\t\t} else {\n\t\t\tstack = append(stack, current)\n\t\t\tcurrent = \"\"\n\t\t}\n\t\tindex++\n\t\tif index == len((*sqlStrings)) {\n\t\t\tbreak\n\t\t}\n\t}\n\treturn stack\n}\n\nfunc main() {\n\tcmdLineOpts := newCommandLineOptions()\n\tvar outputer outputs.Output\n\n\tif cmdLineOpts.GetVersion() {\n\t\tfmt.Println(VERSION)\n\t\tos.Exit(0)\n\t}\n\n\tif len(cmdLineOpts.GetSourceFiles()) == 0 && !util.IsThereDataOnStdin() {\n\t\tcmdLineOpts.Usage()\n\t}\n\n\tif cmdLineOpts.GetQuiet() {\n\t\tlog.SetOutput(ioutil.Discard)\n\t}\n\n\tif cmdLineOpts.GetConsole() {\n\t\tif util.IsThereDataOnStdin() {\n\t\t\tlog.Fatalln(\"Can not open console with pipe input, read a file instead\")\n\t\t}\n\t\t_, sqlite3ConsolePathErr := exec.LookPath(\"sqlite3\")\n\t\tif sqlite3ConsolePathErr != nil {\n\t\t\tlog.Fatalln(\"Console requested but unable to locate `sqlite3` program on $PATH\")\n\t\t}\n\t}\n\n\tvar inputSources []string\n\n\tif util.IsThereDataOnStdin() {\n\t\tinputSources = append(inputSources, \"stdin\")\n\t}\n\n\tfor _, taggedName := range cmdLineOpts.GetSourceFiles() {\n\t\t// support <tablename>:<filename> syntax\n\t\tvar names = strings.SplitN(taggedName, \":\", 2)\n\t\tvar sourceFile = names[len(names)-1]\n\n\t\tif util.IsPathDir(sourceFile) {\n\t\t\tfor _, file := range util.AllFilesInDirectory(sourceFile) {\n\t\t\t\tinputSources = append(inputSources, file)\n\t\t\t}\n\t\t} else {\n\t\t\tinputSources = append(inputSources, taggedName)\n\t\t}\n\t}\n\n\tstorage := storage.NewSQLite3StorageWithDefaults()\n\n\tfor _, taggedName := range inputSources {\n\t\t// support <tablename>:<filename> syntax\n\t\tvar names = strings.SplitN(taggedName, \":\", 2)\n\t\tvar file = names[len(names)-1]\n\n\t\tfp := util.OpenFileOrStdDev(file, false)\n\n\t\tinputOpts := &inputs.CSVInputOptions{\n\t\t\tHasHeader: cmdLineOpts.GetHeader(),\n\t\t\tSeparator: util.DetermineSeparator(cmdLineOpts.GetDelimiter()),\n\t\t\tReadFrom:  fp,\n\t\t}\n\n\t\tinput, inputErr := inputs.NewCSVInput(inputOpts)\n\n\t\tif inputErr != nil {\n\t\t\tlog.Printf(\"Unable to load %v\\n\", file)\n\t\t}\n\n\t\tif len(names) > 1 {\n\t\t\tinput.SetName(names[0])\n\t\t}\n\t\tstorage.LoadInput(input)\n\t}\n\n\tstat, err := cmdLineOpts.GetStatements()\n\tif err != nil {\n\t\tlog.Fatalln(err)\n\t}\n\tif (strings.Count(stat, \"'\") % 2) == 1 {\n\t\tlog.Fatalln(\"String contains odd number of \\\"'(Single Quotes)\\\"\")\n\t}\n\n\tsqlStrings := strings.Split(stat, \";\")\n\n\tsqlStrings = handleSemiColon(&sqlStrings)\n\n\tif cmdLineOpts.GetOutputFile() != \"\" {\n\t\tif cmdLineOpts.GetPretty() {\n\t\t\tdisplayOpts := &outputs.PrettyCSVOutputOptions{\n\t\t\t\tWriteHeader: cmdLineOpts.GetOutputHeader(),\n\t\t\t\tWriteTo:     util.OpenFileOrStdDev(cmdLineOpts.GetOutputFile(), true),\n\t\t\t}\n\n\t\t\toutputer = outputs.NewPrettyCSVOutput(displayOpts)\n\t\t} else {\n\t\t\tdisplayOpts := &outputs.CSVOutputOptions{\n\t\t\t\tWriteHeader: cmdLineOpts.GetOutputHeader(),\n\t\t\t\tSeparator:   util.DetermineSeparator(cmdLineOpts.GetOutputDelimiter()),\n\t\t\t\tWriteTo:     util.OpenFileOrStdDev(cmdLineOpts.GetOutputFile(), true),\n\t\t\t}\n\n\t\t\toutputer = outputs.NewCSVOutput(displayOpts)\n\t\t}\n\t}\n\n\tfor _, sqlQuery := range sqlStrings {\n\t\tqueryResults, queryErr := storage.ExecuteSQLString(sqlQuery)\n\n\t\tif queryErr != nil {\n\t\t\tlog.Fatalln(queryErr)\n\t\t}\n\n\t\tif queryResults != nil && cmdLineOpts.GetOutputFile() != \"\" {\n\t\t\toutputer.Show(queryResults)\n\t\t}\n\t}\n\n\tif cmdLineOpts.GetSaveTo() != \"\" {\n\t\tstorage.SaveTo(cmdLineOpts.GetSaveTo())\n\t}\n\n\tif cmdLineOpts.GetConsole() {\n\t\tvar args []string\n\n\t\tif cmdLineOpts.GetOutputHeader() {\n\t\t\targs = []string{\"-header\"}\n\t\t} else {\n\t\t\targs = []string{}\n\t\t}\n\n\t\tif cmdLineOpts.GetSaveTo() != \"\" {\n\t\t\targs = append(args, cmdLineOpts.GetSaveTo())\n\t\t} else {\n\t\t\ttempFile, err := ioutil.TempFile(os.TempDir(), \"textql\")\n\t\t\tif err != nil {\n\t\t\t\tlog.Fatalln(err)\n\t\t\t}\n\t\t\tdefer os.Remove(tempFile.Name())\n\t\t\ttempFile.Close()\n\t\t\tsaveErr := storage.SaveTo(tempFile.Name())\n\n\t\t\tif saveErr != nil {\n\t\t\t\tlog.Fatalln(saveErr)\n\t\t\t}\n\n\t\t\targs = append(args, tempFile.Name())\n\t\t}\n\n\t\tcmd := exec.Command(\"sqlite3\", args...)\n\n\t\tcmd.Stdin = os.Stdin\n\t\tcmd.Stdout = os.Stdout\n\t\tcmd.Stderr = os.Stderr\n\t\tcmdErr := cmd.Run()\n\n\t\tif cmd.Process != nil {\n\t\t\tcmd.Process.Release()\n\t\t}\n\n\t\tif cmdErr != nil {\n\t\t\tlog.Fatalln(cmdErr)\n\t\t}\n\t} else {\n\t\tstorage.Close()\n\t}\n}\n"
  },
  {
    "path": "util/file_helpers.go",
    "content": "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) bool {\n\tfp, err := os.Open(CleanPath(path))\n\n\tif err != nil {\n\t\tlog.Fatalln(err)\n\t}\n\n\tdefer fp.Close()\n\n\tstat, statErr := fp.Stat()\n\n\tif statErr != nil {\n\t\tlog.Fatalln(statErr)\n\t}\n\n\treturn stat.IsDir()\n}\n\nfunc OpenFileOrStdDev(path string, write bool) *os.File {\n\tvar fp *os.File\n\tvar err error\n\n\tif path == \"stdin\" {\n\t\tfp = os.Stdin\n\t\terr = nil\n\t} else if path == \"stdout\" {\n\t\tfp = os.Stdout\n\t\terr = nil\n\t} else {\n\t\tif write {\n\t\t\tfp, err = os.Create(CleanPath(path))\n\t\t} else {\n\t\t\tfp, err = os.Open(CleanPath(path))\n\t\t}\n\t}\n\n\tif err != nil {\n\t\tlog.Fatalln(err)\n\t}\n\n\tstat, statErr := fp.Stat()\n\n\tif statErr != nil {\n\t\tlog.Fatalln(err)\n\t}\n\n\tif stat.IsDir() {\n\t\tlog.Fatalf(\"%s: is a directory\\n\", path)\n\t}\n\n\treturn fp\n}\n\nfunc CleanPath(path string) string {\n\tresult := \"\"\n\n\tif path == \"\" {\n\t\treturn \"\"\n\t}\n\n\tusr, err := user.Current()\n\tif err != nil {\n\t\tlog.Fatalln(err)\n\t}\n\n\tif len(path) > 1 && path[:2] == \"~/\" {\n\t\tdir := usr.HomeDir + \"/\"\n\t\tresult = strings.Replace(path, \"~/\", dir, 1)\n\t} else {\n\t\tresult = path\n\t}\n\n\tabsResult, absErr := filepath.Abs(result)\n\tif absErr != nil {\n\t\tlog.Fatalln(absErr)\n\t}\n\n\tcleanResult := filepath.Clean(absResult)\n\n\treturn cleanResult\n}\n\nfunc RewindFile(fileHandle *os.File) {\n\t_, rewindErr := fileHandle.Seek(0, 0)\n\n\tif rewindErr != nil {\n\t\tlog.Fatalln(\"Unable to rewind file\")\n\t}\n}\n\nfunc IsThereDataOnStdin() bool {\n\tstat, statErr := os.Stdin.Stat()\n\n\tif statErr != nil {\n\t\tlog.Fatalln(statErr)\n\t}\n\n\tif (stat.Mode() & os.ModeCharDevice) == 0 {\n\t\treturn true\n\t} else {\n\t\treturn false\n\t}\n}\n\nfunc AllFilesInDirectory(path string) []string {\n\tcleanPath := CleanPath(path)\n\tdirectoryEntries, err := ioutil.ReadDir(cleanPath)\n\tresult := make([]string, 0)\n\n\tif err != nil {\n\t\tlog.Fatalln(err)\n\t}\n\n\tfor _, entry := range directoryEntries {\n\t\tif !entry.IsDir() {\n\t\t\tresult = append(result, filepath.Join(cleanPath, entry.Name()))\n\t\t}\n\t}\n\n\treturn result\n}\n"
  },
  {
    "path": "util/seperator_helpers.go",
    "content": "package util\n\nimport (\n\t\"encoding/hex\"\n\t\"log\"\n\t\"strings\"\n\t\"unicode/utf8\"\n)\n\nfunc DetermineSeparator(delimiter string) rune {\n\tvar separator rune\n\n\tif delimiter == \"tab\" {\n\t\tseparator = '\\t'\n\t} else if strings.Index(delimiter, \"0x\") == 0 {\n\t\tdlm, hexErr := hex.DecodeString(delimiter[2:])\n\n\t\tif hexErr != nil {\n\t\t\tlog.Fatalln(hexErr)\n\t\t}\n\n\t\tseparator, _ = utf8.DecodeRuneInString(string(dlm))\n\t} else {\n\t\tseparator, _ = utf8.DecodeRuneInString(delimiter)\n\t}\n\treturn separator\n}\n"
  }
]