diff --git a/.github/PULL_REQUEST_TEMPLATE b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md similarity index 100% rename from .github/PULL_REQUEST_TEMPLATE rename to .github/PULL_REQUEST_TEMPLATE/pull_request_template.md diff --git a/MAINTAINERS.md b/MAINTAINERS.md index d991a272f25..46a675327bb 100644 --- a/MAINTAINERS.md +++ b/MAINTAINERS.md @@ -5,7 +5,7 @@ The following is the full list, alphabetically ordered. * Alkin Tezuysal ([askdba](https://github.com/askdba)) alkin@planetscale.com * Andres Taylor ([systay](https://github.com/systay)) andres@planetscale.com * Anthony Yeh ([enisoc](https://github.com/enisoc)) enisoc@planetscale.com -* Dan Kozlowski ([dkhenry](https://github.com/dkhenry)) koz@planetscale.com +* Dan Kozlowski ([dkhenry](https://github.com/dkhenry)) dan.kozlowski@gmail.com * David Weitzman ([dweitzman](https://github.com/dweitzman)) dweitzman@pinterest.com * Deepthi Sigireddi ([deepthi](https://github.com/deepthi)) deepthi@planetscale.com * Derek Perkins ([derekperkins](https://github.com/derekperkins)) derek@nozzle.io @@ -13,7 +13,6 @@ The following is the full list, alphabetically ordered. * Jon Tirsen ([tirsen](https://github.com/tirsen)) jontirsen@squareup.com * Michael Demmer ([demmer](https://github.com/demmer)) mdemmer@slack-corp.com * Michael Pawliszyn ([mpawliszyn](https://github.com/mpawliszyn)) mikepaw@squareup.com -* Morgan Tocker ([morgo](https://github.com/morgo)) morgan@planetscale.com * Paul Hemberger ([pH14](https://github.com/pH14)) phemberger@hubspot.com * Rafael Chacon ([rafael](https://github.com/rafael)) rchacon@slack-corp.com * Rohit Nayak ([rohit-nayak-ps](https://github.com/rohit-nayak-ps)) rohit@planetscale.com @@ -23,13 +22,13 @@ The following is the full list, alphabetically ordered. ## Areas of expertise ### General Vitess -sougou, demmer, rafael, dweitzman, tirsen, morgo, enisoc +sougou, demmer, rafael, dweitzman, tirsen, askdba, enisoc ### Builds -dkhenry, morgo +dkhenry, shlomi-noach ### Resharding -sougou, rafael, tirsen, dweitzman, systay +sougou, rafael, tirsen, dweitzman, systay, rohit-nayak-ps ### Parser sougou, dweitzman, deepthi, systay, harshit-gangal diff --git a/examples/compose/README.md b/examples/compose/README.md index f63f640a921..991c7d0ad85 100644 --- a/examples/compose/README.md +++ b/examples/compose/README.md @@ -280,6 +280,13 @@ To run against a specific compose service/container, use the environment variabl vitess/examples/compose$ (export CS=vttablet101; ./lvtctl.sh ) ``` +## Custom Image Tags +You may specify a custom `vitess:lite` image tag by setting the evnironment variable `VITESS_TAG`. +This is optional and defaults to the `latest` tag. Example; +* Set `VITESS_TAG=8.0.0` in your `.env` before running `docker-compose up -d` +* Run `VITESS_TAG=8.0.0; docker-compose up -d` + + ## Reference Checkout this excellent post about [The Life of a Vitess Cluster](https://vitess.io/blog/2020-04-27-life-of-a-cluster/) diff --git a/examples/compose/docker-compose.beginners.yml b/examples/compose/docker-compose.beginners.yml index 7b71117fb38..d01532c2f74 100644 --- a/examples/compose/docker-compose.beginners.yml +++ b/examples/compose/docker-compose.beginners.yml @@ -58,7 +58,7 @@ services: - "3306" vtctld: - image: vitess/lite + image: vitess/lite:${VITESS_TAG:-latest} ports: - "15000:$WEB_PORT" - "$GRPC_PORT" @@ -83,7 +83,7 @@ services: condition: service_healthy vtgate: - image: vitess/lite + image: vitess/lite:${VITESS_TAG:-latest} ports: - "15099:$WEB_PORT" - "$GRPC_PORT" @@ -113,7 +113,7 @@ services: condition: service_healthy schemaload: - image: vitess/lite + image: vitess/lite:${VITESS_TAG:-latest} command: - sh - -c @@ -137,7 +137,7 @@ services: condition: service_healthy vttablet100: - image: vitess/lite + image: vitess/lite:${VITESS_TAG:-latest} ports: - "15100:$WEB_PORT" - "$GRPC_PORT" @@ -169,7 +169,7 @@ services: retries: 15 vttablet101: - image: vitess/lite + image: vitess/lite:${VITESS_TAG:-latest} ports: - "15101:$WEB_PORT" - "$GRPC_PORT" @@ -201,7 +201,7 @@ services: retries: 15 vttablet102: - image: vitess/lite + image: vitess/lite:${VITESS_TAG:-latest} ports: - "15102:$WEB_PORT" - "$GRPC_PORT" @@ -233,7 +233,7 @@ services: retries: 15 vttablet103: - image: vitess/lite + image: vitess/lite:${VITESS_TAG:-latest} ports: - "15103:$WEB_PORT" - "$GRPC_PORT" @@ -265,7 +265,7 @@ services: retries: 15 vtorc: - image: vitess/lite + image: vitess/lite:${VITESS_TAG:-latest} command: ["sh", "-c", "/script/vtorc-up.sh"] depends_on: - vtctld @@ -293,7 +293,7 @@ services: retries: 15 vreplication: - image: vitess/lite + image: vitess/lite:${VITESS_TAG:-latest} volumes: - ".:/script" environment: diff --git a/examples/compose/tablet.yml b/examples/compose/tablet.yml new file mode 100644 index 00000000000..86cc8316a41 --- /dev/null +++ b/examples/compose/tablet.yml @@ -0,0 +1,24 @@ +externalConnections: + erpl: + flavor: FilePos + host: external_db_host + port: 3306 + dbName: commerce + app: + user: external_db_user + password: external_db_password + dba: + user: external_db_user + password: external_db_password + filtered: + user: external_db_user + password: external_db_password + repl: + user: external_db_user + password: external_db_password + appdebug: + user: external_db_user + password: external_db_password + allprivs: + user: external_db_user + password: external_db_password \ No newline at end of file diff --git a/examples/compose/vtcompose/vtcompose.go b/examples/compose/vtcompose/vtcompose.go index c2556c7e0cb..2b18317da6f 100644 --- a/examples/compose/vtcompose/vtcompose.go +++ b/examples/compose/vtcompose/vtcompose.go @@ -532,7 +532,7 @@ func generateDefaultShard(tabAlias int, shard string, keyspaceData keyspaceInfo, - op: add path: /services/init_shard_master%[2]d value: - image: vitess/lite + image: vitess/lite:${VITESS_TAG:-latest} command: ["sh", "-c", "/vt/bin/vtctlclient %[5]s InitShardMaster -force %[4]s/%[3]s %[6]s-%[2]d "] %[1]s `, dependsOn, aliases[0], shard, keyspaceData.keyspace, opts.topologyFlags, opts.cell) @@ -564,7 +564,7 @@ func generateExternalmaster( - op: add path: /services/vttablet%[1]d value: - image: vitess/lite + image: vitess/lite:${VITESS_TAG:-latest} ports: - "15%[1]d:%[3]d" - "%[4]d" @@ -626,7 +626,7 @@ func generateDefaultTablet(tabAlias int, shard, role, keyspace string, dbInfo ex - op: add path: /services/vttablet%[1]d value: - image: vitess/lite + image: vitess/lite:${VITESS_TAG:-latest} ports: - "15%[1]d:%[4]d" - "%[5]d" @@ -664,7 +664,7 @@ func generateVtctld(opts vtOptions) string { - op: add path: /services/vtctld value: - image: vitess/lite + image: vitess/lite:${VITESS_TAG:-latest} ports: - "15000:%[1]d" - "%[2]d" @@ -697,7 +697,7 @@ func generateVtgate(opts vtOptions) string { - op: add path: /services/vtgate value: - image: vitess/lite + image: vitess/lite:${VITESS_TAG:-latest} ports: - "15099:%[1]d" - "%[2]d" @@ -727,7 +727,7 @@ func generateVtwork(opts vtOptions) string { - op: add path: /services/vtwork value: - image: vitess/lite + image: vitess/lite:${VITESS_TAG:-latest} ports: - "%[1]d" - "%[2]d" @@ -754,7 +754,7 @@ func generateVtorc(dbInfo externalDbInfo, opts vtOptions) string { - op: add path: /services/vtorc value: - image: vitess/lite + image: vitess/lite:${VITESS_TAG:-latest} volumes: - ".:/script" environment: @@ -779,7 +779,7 @@ func generateVreplication(dbInfo externalDbInfo, opts vtOptions) string { - op: add path: /services/vreplication value: - image: vitess/lite + image: vitess/lite:${VITESS_TAG:-latest} volumes: - ".:/script" environment: @@ -817,7 +817,7 @@ func generateSchemaload( - op: add path: /services/schemaload_%[7]s value: - image: vitess/lite + image: vitess/lite:${VITESS_TAG:-latest} volumes: - ".:/script" environment: diff --git a/examples/compose/vttablet-up.sh b/examples/compose/vttablet-up.sh index 72fd21147f7..178620cf7e3 100755 --- a/examples/compose/vttablet-up.sh +++ b/examples/compose/vttablet-up.sh @@ -130,7 +130,6 @@ if [ $tablet_role = "externalmaster" ]; then -db_filtered_password $DB_PASS \ -db_repl_user $DB_USER \ -db_repl_password $DB_PASS \ - -init_populate_metadata=true \ -enable_replication_reporter=false \ -enforce_strict_trans_tables=false \ -track_schema_versions=true \ diff --git a/go.mod b/go.mod index 19d3687ecd3..2428cc21e96 100644 --- a/go.mod +++ b/go.mod @@ -9,6 +9,7 @@ require ( github.com/Azure/azure-storage-blob-go v0.10.0 github.com/Azure/go-autorest/autorest v0.10.0 github.com/Azure/go-autorest/autorest/validation v0.3.0 // indirect + github.com/DataDog/datadog-go v2.2.0+incompatible github.com/GeertJohan/go.rice v1.0.0 github.com/PuerkitoBio/goquery v1.5.1 github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6 diff --git a/go/cmd/vtgate/plugin_statsd.go b/go/cmd/vtgate/plugin_statsd.go new file mode 100644 index 00000000000..ae2ecb5b2e0 --- /dev/null +++ b/go/cmd/vtgate/plugin_statsd.go @@ -0,0 +1,7 @@ +package main + +import "vitess.io/vitess/go/stats/statsd" + +func init() { + statsd.Init("vtgate") +} diff --git a/go/cmd/vttablet/plugin_statsd.go b/go/cmd/vttablet/plugin_statsd.go new file mode 100644 index 00000000000..51761e6c406 --- /dev/null +++ b/go/cmd/vttablet/plugin_statsd.go @@ -0,0 +1,7 @@ +package main + +import "vitess.io/vitess/go/stats/statsd" + +func init() { + statsd.Init("vttablet") +} diff --git a/go/mysql/binlog_event.go b/go/mysql/binlog_event.go index 7a6d489879d..e965c7faf1b 100644 --- a/go/mysql/binlog_event.go +++ b/go/mysql/binlog_event.go @@ -128,14 +128,17 @@ type BinlogEvent interface { // This structure is passed to subsequent event types to let them know how to // parse themselves. type BinlogFormat struct { - // FormatVersion is the version number of the binlog file format. - // We only support version 4. - FormatVersion uint16 + // HeaderSizes is an array of sizes of the headers for each message. + HeaderSizes []byte // ServerVersion is the name of the MySQL server version. // It starts with something like 5.6.33-xxxx. ServerVersion string + // FormatVersion is the version number of the binlog file format. + // We only support version 4. + FormatVersion uint16 + // HeaderLength is the size in bytes of event headers other // than FORMAT_DESCRIPTION_EVENT. Almost always 19. HeaderLength byte @@ -143,9 +146,6 @@ type BinlogFormat struct { // ChecksumAlgorithm is the ID number of the binlog checksum algorithm. // See three possible values below. ChecksumAlgorithm byte - - // HeaderSizes is an array of sizes of the headers for each message. - HeaderSizes []byte } // IsZero returns true if the BinlogFormat has not been initialized. diff --git a/go/mysql/conn.go b/go/mysql/conn.go index 2367e245331..ac7e0378ab6 100644 --- a/go/mysql/conn.go +++ b/go/mysql/conn.go @@ -79,45 +79,12 @@ type Getter interface { // Use Connect on the client side to create a connection. // Use NewListener to create a server side and listen for connections. type Conn struct { - // conn is the underlying network connection. - // Calling Close() on the Conn will close this connection. - // If there are any ongoing reads or writes, they may get interrupted. - conn net.Conn - - // For server-side connections, listener points to the server object. - listener *Listener - - // ConnectionID is set: - // - at Connect() time for clients, with the value returned by - // the server. - // - at accept time for the server. - ConnectionID uint32 - - // closed is set to true when Close() is called on the connection. - closed sync2.AtomicBool - - // Capabilities is the current set of features this connection - // is using. It is the features that are both supported by - // the client and the server, and currently in use. - // It is set during the initial handshake. - // - // It is only used for CapabilityClientDeprecateEOF - // and CapabilityClientFoundRows. - Capabilities uint32 - - // CharacterSet is the character set used by the other side of the - // connection. - // It is set during the initial handshake. - // See the values in constants.go. - CharacterSet uint8 - - // User is the name used by the client to connect. - // It is set during the initial handshake. - User string - - // UserData is custom data returned by the AuthServer module. - // It is set during the initial handshake. - UserData Getter + // fields contains the fields definitions for an on-going + // streaming query. It is set by ExecuteStreamFetch, and + // cleared by the last FetchNext(). It is nil if no streaming + // query is in progress. If the streaming query returned no + // fields, this is set to an empty array (but not nil). + fields []*querypb.Field // schemaName is the default database name to use. It is set // during handshake, and by ComInitDb packets. Both client and @@ -126,43 +93,36 @@ type Conn struct { // through the 'USE' statement, which will bypass this variable. schemaName string - // ServerVersion is set during Connect with the server - // version. It is not changed afterwards. It is unused for - // server-side connections. - ServerVersion string + // ClientData is a place where an application can store any + // connection-related data. Mostly used on the server side, to + // avoid maps indexed by ConnectionID for instance. + ClientData interface{} + + // conn is the underlying network connection. + // Calling Close() on the Conn will close this connection. + // If there are any ongoing reads or writes, they may get interrupted. + conn net.Conn // flavor contains the auto-detected flavor for this client // connection. It is unused for server-side connections. flavor flavor - // StatusFlags are the status flags we will base our returned flags on. - // This is a bit field, with values documented in constants.go. - // An interesting value here would be ServerStatusAutocommit. - // It is only used by the server. These flags can be changed - // by Handler methods. - StatusFlags uint16 + // ServerVersion is set during Connect with the server + // version. It is not changed afterwards. It is unused for + // server-side connections. + ServerVersion string - // ClientData is a place where an application can store any - // connection-related data. Mostly used on the server side, to - // avoid maps indexed by ConnectionID for instance. - ClientData interface{} + // User is the name used by the client to connect. + // It is set during the initial handshake. + User string // For server-side connections, listener points to the server object. - // Packet encoding variables. - sequence uint8 - bufferedReader *bufio.Reader + // UserData is custom data returned by the AuthServer module. + // It is set during the initial handshake. + UserData Getter - // Buffered writing has a timer which flushes on inactivity. - bufMu sync.Mutex - bufferedWriter *bufio.Writer + bufferedReader *bufio.Reader flushTimer *time.Timer - // fields contains the fields definitions for an on-going - // streaming query. It is set by ExecuteStreamFetch, and - // cleared by the last FetchNext(). It is nil if no streaming - // query is in progress. If the streaming query returned no - // fields, this is set to an empty array (but not nil). - fields []*querypb.Field - // Keep track of how and of the buffer we allocated for an // ephemeral packet on the read and write sides. // These fields are used by: @@ -173,11 +133,53 @@ type Conn struct { // It can be allocated from bufPool or heap and should be recycled in the same manner. currentEphemeralBuffer *[]byte - // StatementID is the prepared statement ID. - StatementID uint32 + listener *Listener + + // Buffered writing has a timer which flushes on inactivity. + bufferedWriter *bufio.Writer // PrepareData is the map to use a prepared statement. PrepareData map[uint32]*PrepareData + + // protects the bufferedWriter and bufferedReader + bufMu sync.Mutex + + // Capabilities is the current set of features this connection + // is using. It is the features that are both supported by + // the client and the server, and currently in use. + // It is set during the initial handshake. + // + // It is only used for CapabilityClientDeprecateEOF + // and CapabilityClientFoundRows. + Capabilities uint32 + + // closed is set to true when Close() is called on the connection. + closed sync2.AtomicBool + + // ConnectionID is set: + // - at Connect() time for clients, with the value returned by + // the server. + // - at accept time for the server. + ConnectionID uint32 + + // StatementID is the prepared statement ID. + StatementID uint32 + + // StatusFlags are the status flags we will base our returned flags on. + // This is a bit field, with values documented in constants.go. + // An interesting value here would be ServerStatusAutocommit. + // It is only used by the server. These flags can be changed + // by Handler methods. + StatusFlags uint16 + + // CharacterSet is the character set used by the other side of the + // connection. + // It is set during the initial handshake. + // See the values in constants.go. + CharacterSet uint8 + + // Packet encoding variables. + sequence uint8 } // splitStatementFunciton is the function that is used to split the statement in cas ef a multi-statement query. @@ -185,12 +187,12 @@ var splitStatementFunction func(blob string) (pieces []string, err error) = sqlp // PrepareData is a buffer used for store prepare statement meta data type PrepareData struct { - StatementID uint32 - PrepareStmt string - ParamsCount uint16 ParamsType []int32 ColumnNames []string + PrepareStmt string BindVars map[string]*querypb.BindVariable + StatementID uint32 + ParamsCount uint16 } // execResult is an enum signifying the result of executing a query diff --git a/go/stats/statsd/statsd.go b/go/stats/statsd/statsd.go new file mode 100644 index 00000000000..61f33f9acca --- /dev/null +++ b/go/stats/statsd/statsd.go @@ -0,0 +1,227 @@ +package statsd + +import ( + "encoding/json" + "expvar" + "flag" + "fmt" + "strings" + + "github.com/DataDog/datadog-go/statsd" + "vitess.io/vitess/go/stats" + "vitess.io/vitess/go/vt/log" + "vitess.io/vitess/go/vt/servenv" +) + +var ( + statsdAddress = flag.String("statsd_address", "", "Address for statsd client") + statsdSampleRate = flag.Float64("statsd_sample_rate", 1.0, "") +) + +// StatsBackend implements PullBackend using statsd +type StatsBackend struct { + namespace string + statsdClient *statsd.Client + sampleRate float64 +} + +var ( + sb StatsBackend +) + +// makeLabel builds a tag list with a single label + value. +func makeLabel(labelName string, labelVal string) []string { + return []string{fmt.Sprintf("%s:%s", labelName, labelVal)} +} + +// makeLabels takes the vitess stat representation of label values ("."-separated list) and breaks it +// apart into a map of label name -> label value. +func makeLabels(labelNames []string, labelValsCombined string) []string { + tags := make([]string, len(labelNames)) + labelVals := strings.Split(labelValsCombined, ".") + for i, v := range labelVals { + tags[i] = fmt.Sprintf("%s:%s", labelNames[i], v) + } + return tags +} + +func (sb StatsBackend) addHistogram(name string, h *stats.Histogram, tags []string) { + labels := h.Labels() + buckets := h.Buckets() + for i := range labels { + name := fmt.Sprintf("%s.%s", name, labels[i]) + sb.statsdClient.Gauge(name, float64(buckets[i]), tags, sb.sampleRate) + } + sb.statsdClient.Gauge(fmt.Sprintf("%s.%s", name, h.CountLabel()), + (float64)(h.Count()), + tags, + sb.sampleRate, + ) + sb.statsdClient.Gauge(fmt.Sprintf("%s.%s", name, h.TotalLabel()), + (float64)(h.Total()), + tags, + sb.sampleRate, + ) +} + +// Init initializes the statsd with the given namespace. +func Init(namespace string) { + servenv.OnRun(func() { + if *statsdAddress == "" { + return + } + statsdC, err := statsd.NewBuffered(*statsdAddress, 100) + if err != nil { + log.Errorf("Failed to create statsd client %v", err) + return + } + statsdC.Namespace = namespace + "." + sb.namespace = namespace + sb.statsdClient = statsdC + sb.sampleRate = *statsdSampleRate + stats.RegisterPushBackend("statsd", sb) + }) +} + +func (sb StatsBackend) addExpVar(kv expvar.KeyValue) { + k := kv.Key + switch v := kv.Value.(type) { + case *stats.String: + if err := sb.statsdClient.Set(k, v.Get(), nil, sb.sampleRate); err != nil { + log.Errorf("Failed to add String %v for key %v", v, k) + } + case *stats.Counter: + if err := sb.statsdClient.Count(k, v.Get(), nil, sb.sampleRate); err != nil { + log.Errorf("Failed to add Counter %v for key %v", v, k) + } + case *stats.Gauge: + if err := sb.statsdClient.Gauge(k, float64(v.Get()), nil, sb.sampleRate); err != nil { + log.Errorf("Failed to add Gauge %v for key %v", v, k) + } + case *stats.GaugeFunc: + if err := sb.statsdClient.Gauge(k, float64(v.F()), nil, sb.sampleRate); err != nil { + log.Errorf("Failed to add GaugeFunc %v for key %v", v, k) + } + case *stats.CounterFunc: + if err := sb.statsdClient.Gauge(k, float64(v.F()), nil, sb.sampleRate); err != nil { + log.Errorf("Failed to add CounterFunc %v for key %v", v, k) + } + case *stats.CounterDuration: + if err := sb.statsdClient.TimeInMilliseconds(k, float64(v.Get().Milliseconds()), nil, sb.sampleRate); err != nil { + log.Errorf("Failed to add CounterDuration %v for key %v", v, k) + } + case *stats.CounterDurationFunc: + if err := sb.statsdClient.TimeInMilliseconds(k, float64(v.F().Milliseconds()), nil, sb.sampleRate); err != nil { + log.Errorf("Failed to add CounterDuration %v for key %v", v, k) + } + case *stats.GaugeDuration: + if err := sb.statsdClient.TimeInMilliseconds(k, float64(v.Get().Milliseconds()), nil, sb.sampleRate); err != nil { + log.Errorf("Failed to add GaugeDuration %v for key %v", v, k) + } + case *stats.GaugeDurationFunc: + if err := sb.statsdClient.TimeInMilliseconds(k, float64(v.F().Milliseconds()), nil, sb.sampleRate); err != nil { + log.Errorf("Failed to add GaugeDuration %v for key %v", v, k) + } + case *stats.CountersWithSingleLabel: + for labelVal, val := range v.Counts() { + if err := sb.statsdClient.Count(k, val, makeLabel(v.Label(), labelVal), sb.sampleRate); err != nil { + log.Errorf("Failed to add CountersWithSingleLabel %v for key %v", v, k) + } + } + case *stats.CountersWithMultiLabels: + for labelVals, val := range v.Counts() { + if err := sb.statsdClient.Count(k, val, makeLabels(v.Labels(), labelVals), sb.sampleRate); err != nil { + log.Errorf("Failed to add CountersFuncWithMultiLabels %v for key %v", v, k) + } + } + case *stats.CountersFuncWithMultiLabels: + for labelVals, val := range v.Counts() { + if err := sb.statsdClient.Count(k, val, makeLabels(v.Labels(), labelVals), sb.sampleRate); err != nil { + log.Errorf("Failed to add CountersFuncWithMultiLabels %v for key %v", v, k) + } + } + case *stats.GaugesWithMultiLabels: + for labelVals, val := range v.Counts() { + if err := sb.statsdClient.Gauge(k, float64(val), makeLabels(v.Labels(), labelVals), sb.sampleRate); err != nil { + log.Errorf("Failed to add GaugesWithMultiLabels %v for key %v", v, k) + } + } + case *stats.GaugesFuncWithMultiLabels: + for labelVals, val := range v.Counts() { + if err := sb.statsdClient.Gauge(k, float64(val), makeLabels(v.Labels(), labelVals), sb.sampleRate); err != nil { + log.Errorf("Failed to add GaugesFuncWithMultiLabels %v for key %v", v, k) + } + } + case *stats.GaugesWithSingleLabel: + for labelVal, val := range v.Counts() { + if err := sb.statsdClient.Gauge(k, float64(val), makeLabel(v.Label(), labelVal), sb.sampleRate); err != nil { + log.Errorf("Failed to add GaugesWithSingleLabel %v for key %v", v, k) + } + } + case *stats.MultiTimings: + labels := v.Labels() + hists := v.Histograms() + for labelValsCombined, histogram := range hists { + sb.addHistogram(k, histogram, makeLabels(labels, labelValsCombined)) + } + case *stats.Timings: + // TODO: for statsd.timing metrics, there is no good way to transfer the histogram to it + // If we store a in memory buffer for stats.Timings and flush it here it's hard to make the stats + // thread safe. + // Instead, we export the timings stats as histogram here. We won't have the percentile breakdown + // for the metrics, but we can still get the average from total and count + labels := []string{v.Label()} + hists := v.Histograms() + for labelValsCombined, histogram := range hists { + sb.addHistogram(k, histogram, makeLabels(labels, labelValsCombined)) + } + case *stats.Histogram: + sb.addHistogram(k, v, []string{}) + case expvar.Func: + // Export memstats as gauge so that we don't need to call extra ReadMemStats + if k == "memstats" { + var obj map[string]interface{} + if err := json.Unmarshal([]byte(v.String()), &obj); err != nil { + return + } + for k, v := range obj { + if k == "NumGC" { + if err := sb.statsdClient.Gauge("NumGC", v.(float64), []string{}, sb.sampleRate); err != nil { + log.Errorf("Failed to export NumGC %v", v) + } + } else if k == "Frees" { + if err := sb.statsdClient.Gauge("Frees", v.(float64), []string{}, sb.sampleRate); err != nil { + log.Errorf("Failed to export Frees %v", v) + } + } else if k == "GCCPUFraction" { + if err := sb.statsdClient.Gauge("GCCPUFraction", v.(float64), []string{}, sb.sampleRate); err != nil { + log.Errorf("Failed to export GCCPUFraction %v", v) + } + } else if k == "PauseTotalNs" { + if err := sb.statsdClient.Gauge("PauseTotalNs", v.(float64), []string{}, sb.sampleRate); err != nil { + log.Errorf("Failed to export PauseTotalNs %v", v) + } + } else if k == "HeapAlloc" { + if err := sb.statsdClient.Gauge("HeapAlloc", v.(float64), []string{}, sb.sampleRate); err != nil { + log.Errorf("Failed to export HeapAlloc %v", v) + } + } + } + } + case *stats.StringMapFunc, *stats.Rates, *stats.RatesFunc: + // Silently ignore metrics that does not make sense to be exported to statsd + default: + log.Warningf("Silently ignore metrics with key %v [%T]", k, kv.Value) + } +} + +// PushAll flush out the pending metrics +func (sb StatsBackend) PushAll() error { + expvar.Do(func(kv expvar.KeyValue) { + sb.addExpVar(kv) + }) + if err := sb.statsdClient.Flush(); err != nil { + return err + } + return nil +} diff --git a/go/stats/statsd/statsd_test.go b/go/stats/statsd/statsd_test.go new file mode 100644 index 00000000000..9d115bd44a4 --- /dev/null +++ b/go/stats/statsd/statsd_test.go @@ -0,0 +1,495 @@ +package statsd + +import ( + "expvar" + "net" + "sort" + "strings" + "testing" + "time" + + "github.com/DataDog/datadog-go/statsd" + "gotest.tools/assert" + "vitess.io/vitess/go/stats" +) + +func getBackend(t *testing.T) (StatsBackend, *net.UDPConn) { + addr := "localhost:1201" + udpAddr, _ := net.ResolveUDPAddr("udp", addr) + server, _ := net.ListenUDP("udp", udpAddr) + bufferLength := 9 + client, _ := statsd.NewBuffered(addr, bufferLength) + client.Namespace = "test." + var sb StatsBackend + sb.namespace = "foo" + sb.sampleRate = 1 + sb.statsdClient = client + return sb, server +} + +func TestStatsdString(t *testing.T) { + sb, server := getBackend(t) + defer server.Close() + name := "string_name" + stats.NewString(name).Set("foo") + found := false + expvar.Do(func(kv expvar.KeyValue) { + if kv.Key == name { + found = true + sb.addExpVar(kv) + if err := sb.statsdClient.Flush(); err != nil { + t.Errorf("Error flushing: %s", err) + } + bytes := make([]byte, 4096) + n, err := server.Read(bytes) + if err != nil { + t.Fatal(err) + } + result := string(bytes[:n]) + expected := "test.string_name:foo|s" + assert.Equal(t, result, expected) + } + }) + if !found { + t.Errorf("Stat %s not found...", name) + } +} + +func TestStatsdCounter(t *testing.T) { + sb, server := getBackend(t) + defer server.Close() + name := "counter_name" + c := stats.NewCounter(name, "counter description") + c.Add(1) + found := false + expvar.Do(func(kv expvar.KeyValue) { + found = true + if kv.Key == name { + sb.addExpVar(kv) + if err := sb.statsdClient.Flush(); err != nil { + t.Errorf("Error flushing: %s", err) + } + bytes := make([]byte, 4096) + n, err := server.Read(bytes) + if err != nil { + t.Fatal(err) + } + result := string(bytes[:n]) + expected := "test.counter_name:1|c" + assert.Equal(t, result, expected) + } + }) + if !found { + t.Errorf("Stat %s not found...", name) + } +} + +func TestStatsdGauge(t *testing.T) { + sb, server := getBackend(t) + defer server.Close() + name := "gauge_name" + s := stats.NewGauge(name, "help") + s.Set(10) + found := false + expvar.Do(func(kv expvar.KeyValue) { + if kv.Key == name { + found = true + sb.addExpVar(kv) + if err := sb.statsdClient.Flush(); err != nil { + t.Errorf("Error flushing: %s", err) + } + bytes := make([]byte, 4096) + n, err := server.Read(bytes) + if err != nil { + t.Fatal(err) + } + result := string(bytes[:n]) + expected := "test.gauge_name:10.000000|g" + assert.Equal(t, result, expected) + } + }) + if !found { + t.Errorf("Stat %s not found...", name) + } +} + +func TestStatsdGaugeFunc(t *testing.T) { + sb, server := getBackend(t) + defer server.Close() + name := "gauge_func_name" + stats.NewGaugeFunc(name, "help", func() int64 { + return 2 + }) + found := false + expvar.Do(func(kv expvar.KeyValue) { + if kv.Key == name { + found = true + sb.addExpVar(kv) + if err := sb.statsdClient.Flush(); err != nil { + t.Errorf("Error flushing: %s", err) + } + bytes := make([]byte, 4096) + n, err := server.Read(bytes) + if err != nil { + t.Fatal(err) + } + result := string(bytes[:n]) + expected := "test.gauge_func_name:2.000000|g" + assert.Equal(t, result, expected) + } + }) + if !found { + t.Errorf("Stat %s not found...", name) + } +} + +func TestStatsdCounterDuration(t *testing.T) { + sb, server := getBackend(t) + defer server.Close() + name := "counter_duration_name" + s := stats.NewCounterDuration(name, "help") + s.Add(1 * time.Millisecond) + found := false + expvar.Do(func(kv expvar.KeyValue) { + if kv.Key == name { + found = true + sb.addExpVar(kv) + if err := sb.statsdClient.Flush(); err != nil { + t.Errorf("Error flushing: %s", err) + } + bytes := make([]byte, 4096) + n, err := server.Read(bytes) + if err != nil { + t.Fatal(err) + } + result := string(bytes[:n]) + expected := "test.counter_duration_name:1.000000|ms" + assert.Equal(t, result, expected) + } + }) + if !found { + t.Errorf("Stat %s not found...", name) + } +} + +func TestStatsdCountersWithSingleLabel(t *testing.T) { + sb, server := getBackend(t) + defer server.Close() + name := "counter_with_single_label_name" + s := stats.NewCountersWithSingleLabel(name, "help", "label", "tag1", "tag2") + s.Add("tag1", 2) + found := false + expvar.Do(func(kv expvar.KeyValue) { + if kv.Key == name { + found = true + sb.addExpVar(kv) + if err := sb.statsdClient.Flush(); err != nil { + t.Errorf("Error flushing: %s", err) + } + bytes := make([]byte, 4096) + n, err := server.Read(bytes) + if err != nil { + t.Fatal(err) + } + result := strings.Split(string(bytes[:n]), "\n") + sort.Strings(result) + expected := []string{ + "test.counter_with_single_label_name:0|c|#label:tag2", + "test.counter_with_single_label_name:2|c|#label:tag1", + } + for i, res := range result { + assert.Equal(t, res, expected[i]) + } + } + }) + if !found { + t.Errorf("Stat %s not found...", name) + } +} + +func TestStatsdCountersWithMultiLabels(t *testing.T) { + sb, server := getBackend(t) + defer server.Close() + name := "counter_with_multiple_label_name" + s := stats.NewCountersWithMultiLabels(name, "help", []string{"label1", "label2"}) + s.Add([]string{"foo", "bar"}, 1) + found := false + expvar.Do(func(kv expvar.KeyValue) { + if kv.Key == name { + found = true + sb.addExpVar(kv) + if err := sb.statsdClient.Flush(); err != nil { + t.Errorf("Error flushing: %s", err) + } + bytes := make([]byte, 4096) + n, err := server.Read(bytes) + if err != nil { + t.Fatal(err) + } + result := string(bytes[:n]) + expected := "test.counter_with_multiple_label_name:1|c|#label1:foo,label2:bar" + assert.Equal(t, result, expected) + } + }) + if !found { + t.Errorf("Stat %s not found...", name) + } +} + +func TestStatsdCountersFuncWithMultiLabels(t *testing.T) { + sb, server := getBackend(t) + defer server.Close() + name := "counter_func_with_multiple_labels_name" + stats.NewCountersFuncWithMultiLabels(name, "help", []string{"label1", "label2"}, func() map[string]int64 { + m := make(map[string]int64) + m["foo.bar"] = 1 + m["bar.baz"] = 2 + return m + }) + found := false + expvar.Do(func(kv expvar.KeyValue) { + if kv.Key == name { + found = true + sb.addExpVar(kv) + if err := sb.statsdClient.Flush(); err != nil { + t.Errorf("Error flushing: %s", err) + } + bytes := make([]byte, 4096) + n, err := server.Read(bytes) + if err != nil { + t.Fatal(err) + } + result := strings.Split(string(bytes[:n]), "\n") + sort.Strings(result) + expected := []string{ + "test.counter_func_with_multiple_labels_name:1|c|#label1:foo,label2:bar", + "test.counter_func_with_multiple_labels_name:2|c|#label1:bar,label2:baz", + } + for i, res := range result { + assert.Equal(t, res, expected[i]) + } + } + }) + if !found { + t.Errorf("Stat %s not found...", name) + } +} + +func TestStatsdGaugesWithMultiLabels(t *testing.T) { + sb, server := getBackend(t) + defer server.Close() + name := "gauges_with_multiple_label_name" + s := stats.NewGaugesWithMultiLabels(name, "help", []string{"label1", "label2"}) + s.Add([]string{"foo", "bar"}, 3) + found := false + expvar.Do(func(kv expvar.KeyValue) { + if kv.Key == name { + found = true + sb.addExpVar(kv) + if err := sb.statsdClient.Flush(); err != nil { + t.Errorf("Error flushing: %s", err) + } + bytes := make([]byte, 4096) + n, err := server.Read(bytes) + if err != nil { + t.Fatal(err) + } + result := string(bytes[:n]) + expected := "test.gauges_with_multiple_label_name:3.000000|g|#label1:foo,label2:bar" + assert.Equal(t, result, expected) + } + }) + if !found { + t.Errorf("Stat %s not found...", name) + } +} + +func TestStatsdGaugesFuncWithMultiLabels(t *testing.T) { + sb, server := getBackend(t) + defer server.Close() + name := "gauges_func_with_multiple_labels_name" + stats.NewGaugesFuncWithMultiLabels(name, "help", []string{"label1", "label2"}, func() map[string]int64 { + m := make(map[string]int64) + m["foo.bar"] = 1 + m["bar.baz"] = 2 + return m + }) + found := false + expvar.Do(func(kv expvar.KeyValue) { + if kv.Key == name { + found = true + sb.addExpVar(kv) + if err := sb.statsdClient.Flush(); err != nil { + t.Errorf("Error flushing: %s", err) + } + bytes := make([]byte, 4096) + n, err := server.Read(bytes) + if err != nil { + t.Fatal(err) + } + result := strings.Split(string(bytes[:n]), "\n") + sort.Strings(result) + expected := []string{ + "test.gauges_func_with_multiple_labels_name:1.000000|g|#label1:foo,label2:bar", + "test.gauges_func_with_multiple_labels_name:2.000000|g|#label1:bar,label2:baz", + } + for i, res := range result { + assert.Equal(t, res, expected[i]) + } + } + }) + if !found { + t.Errorf("Stat %s not found...", name) + } +} + +func TestStatsdGaugesWithSingleLabel(t *testing.T) { + sb, server := getBackend(t) + defer server.Close() + name := "gauges_with_single_label_name" + s := stats.NewGaugesWithSingleLabel(name, "help", "label1") + s.Add("bar", 1) + found := false + expvar.Do(func(kv expvar.KeyValue) { + if kv.Key == name { + found = true + sb.addExpVar(kv) + if err := sb.statsdClient.Flush(); err != nil { + t.Errorf("Error flushing: %s", err) + } + bytes := make([]byte, 4096) + n, err := server.Read(bytes) + if err != nil { + t.Fatal(err) + } + result := string(bytes[:n]) + expected := "test.gauges_with_single_label_name:1.000000|g|#label1:bar" + assert.Equal(t, result, expected) + } + }) + if !found { + t.Errorf("Stat %s not found...", name) + } +} + +func TestStatsdMultiTimings(t *testing.T) { + sb, server := getBackend(t) + defer server.Close() + name := "multi_timings_name" + s := stats.NewMultiTimings(name, "help", []string{"label1", "label2"}) + s.Add([]string{"foo", "bar"}, 10*time.Millisecond) + found := false + expvar.Do(func(kv expvar.KeyValue) { + if kv.Key == name { + found = true + sb.addExpVar(kv) + if err := sb.statsdClient.Flush(); err != nil { + t.Errorf("Error flushing: %s", err) + } + bytes := make([]byte, 49152) + n, err := server.Read(bytes) + if err != nil { + t.Fatal(err) + } + result := string(bytes[:n]) + expected := []string{ + "test.multi_timings_name.500000:0.000000|g|#label1:foo,label2:bar", + "test.multi_timings_name.1000000:0.000000|g|#label1:foo,label2:bar", + "test.multi_timings_name.5000000:0.000000|g|#label1:foo,label2:bar", + "test.multi_timings_name.10000000:1.000000|g|#label1:foo,label2:bar", + "test.multi_timings_name.50000000:0.000000|g|#label1:foo,label2:bar", + "test.multi_timings_name.100000000:0.000000|g|#label1:foo,label2:bar", + "test.multi_timings_name.500000000:0.000000|g|#label1:foo,label2:bar", + "test.multi_timings_name.1000000000:0.000000|g|#label1:foo,label2:bar", + "test.multi_timings_name.5000000000:0.000000|g|#label1:foo,label2:bar", + } + for i, res := range strings.Split(result, "\n") { + assert.Equal(t, res, expected[i]) + } + } + }) + if !found { + t.Errorf("Stat %s not found...", name) + } +} + +func TestStatsdTimings(t *testing.T) { + sb, server := getBackend(t) + defer server.Close() + name := "timings_name" + s := stats.NewTimings(name, "help", "label1") + s.Add("foo", 2*time.Millisecond) + found := false + expvar.Do(func(kv expvar.KeyValue) { + if kv.Key == name { + found = true + sb.addExpVar(kv) + if err := sb.statsdClient.Flush(); err != nil { + t.Errorf("Error flushing: %s", err) + } + bytes := make([]byte, 49152) + n, err := server.Read(bytes) + if err != nil { + t.Fatal(err) + } + result := string(bytes[:n]) + expected := []string{ + "test.timings_name.500000:0.000000|g|#label1:foo", + "test.timings_name.1000000:0.000000|g|#label1:foo", + "test.timings_name.5000000:1.000000|g|#label1:foo", + "test.timings_name.10000000:0.000000|g|#label1:foo", + "test.timings_name.50000000:0.000000|g|#label1:foo", + "test.timings_name.100000000:0.000000|g|#label1:foo", + "test.timings_name.500000000:0.000000|g|#label1:foo", + "test.timings_name.1000000000:0.000000|g|#label1:foo", + "test.timings_name.5000000000:0.000000|g|#label1:foo", + } + for i, res := range strings.Split(result, "\n") { + assert.Equal(t, res, expected[i]) + } + } + }) + if !found { + t.Errorf("Stat %s not found...", name) + } +} + +func TestStatsdHistogram(t *testing.T) { + sb, server := getBackend(t) + defer server.Close() + name := "histogram_name" + s := stats.NewHistogram(name, "help", []int64{1, 5, 10}) + s.Add(2) + s.Add(3) + s.Add(6) + found := false + expvar.Do(func(kv expvar.KeyValue) { + if kv.Key == name { + found = true + sb.addExpVar(kv) + if err := sb.statsdClient.Flush(); err != nil { + t.Errorf("Error flushing: %s", err) + } + bytes := make([]byte, 4096) + n, err := server.Read(bytes) + if err != nil { + t.Fatal(err) + } + result := string(bytes[:n]) + expected := []string{ + "test.histogram_name.1:0.000000|g", + "test.histogram_name.5:2.000000|g", + "test.histogram_name.10:1.000000|g", + "test.histogram_name.inf:0.000000|g", + "test.histogram_name.Count:3.000000|g", + "test.histogram_name.Total:11.000000|g", + } + for i, res := range strings.Split(result, "\n") { + assert.Equal(t, res, expected[i]) + } + } + }) + if !found { + t.Errorf("Stat %s not found...", name) + } +} diff --git a/go/test/endtoend/cluster/vtctlclient_process.go b/go/test/endtoend/cluster/vtctlclient_process.go index 6de9306c88e..c6d52d004ff 100644 --- a/go/test/endtoend/cluster/vtctlclient_process.go +++ b/go/test/endtoend/cluster/vtctlclient_process.go @@ -48,16 +48,17 @@ func (vtctlclient *VtctlClientProcess) InitShardMaster(Keyspace string, Shard st } // ApplySchemaWithOutput applies SQL schema to the keyspace -func (vtctlclient *VtctlClientProcess) ApplySchemaWithOutput(Keyspace string, SQL string) (result string, err error) { +func (vtctlclient *VtctlClientProcess) ApplySchemaWithOutput(Keyspace string, SQL string, ddlStrategy string) (result string, err error) { return vtctlclient.ExecuteCommandWithOutput( "ApplySchema", "-sql", SQL, + "-ddl_strategy", ddlStrategy, Keyspace) } // ApplySchema applies SQL schema to the keyspace func (vtctlclient *VtctlClientProcess) ApplySchema(Keyspace string, SQL string) (err error) { - _, err = vtctlclient.ApplySchemaWithOutput(Keyspace, SQL) + _, err = vtctlclient.ApplySchemaWithOutput(Keyspace, SQL, "") return err } diff --git a/go/test/endtoend/onlineddl/onlineddl_test.go b/go/test/endtoend/onlineddl/onlineddl_test.go index 3ec883c7071..bc80ee466b3 100644 --- a/go/test/endtoend/onlineddl/onlineddl_test.go +++ b/go/test/endtoend/onlineddl/onlineddl_test.go @@ -17,6 +17,7 @@ limitations under the License. package onlineddl import ( + "context" "flag" "fmt" "os" @@ -26,20 +27,25 @@ import ( "testing" "time" + "vitess.io/vitess/go/mysql" + "vitess.io/vitess/go/sqltypes" "vitess.io/vitess/go/vt/schema" + "vitess.io/vitess/go/test/endtoend/cluster" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "vitess.io/vitess/go/test/endtoend/cluster" ) var ( clusterInstance *cluster.LocalProcessCluster + vtParams mysql.ConnParams hostname = "localhost" keyspaceName = "ks" cell = "zone1" schemaChangeDirectory = "" totalTableCount = 4 + ddlStrategyUnchanged = "-" createTable = ` CREATE TABLE %s ( id BIGINT(20) not NULL, @@ -50,19 +56,24 @@ var ( alterTableNormalStatement = ` ALTER TABLE %s ADD COLUMN non_online INT UNSIGNED NOT NULL` + // A trivial statement which must succeed and does not change the schema + alterTableTrivialStatement = ` + ALTER TABLE %s + ENGINE=InnoDB` // The following statement is valid alterTableSuccessfulStatement = ` - ALTER WITH 'gh-ost' TABLE %s + ALTER TABLE %s MODIFY id BIGINT UNSIGNED NOT NULL, ADD COLUMN ghost_col INT NOT NULL, ADD INDEX idx_msg(msg)` // The following statement will fail because gh-ost requires some shared unique key alterTableFailedStatement = ` - ALTER WITH 'gh-ost' TABLE %s + ALTER TABLE %s DROP PRIMARY KEY, DROP COLUMN ghost_col` + // We will run this query with "gh-ost --max-load=Threads_running=1" alterTableThrottlingStatement = ` - ALTER WITH 'gh-ost' '--max-load=Threads_running=1' TABLE %s + ALTER TABLE %s DROP COLUMN ghost_col` ) @@ -95,6 +106,9 @@ func TestMain(m *testing.M) { clusterInstance.VtTabletExtraArgs = []string{ "-migration_check_interval", "5s", } + clusterInstance.VtGateExtraArgs = []string{ + "-ddl_strategy", "gh-ost", + } if err := clusterInstance.StartTopo(); err != nil { return 1, err @@ -111,6 +125,21 @@ func TestMain(m *testing.M) { if err := clusterInstance.StartKeyspace(*keyspace, []string{"1"}, 1, false); err != nil { return 1, err } + + vtgateInstance := clusterInstance.NewVtgateInstance() + // set the gateway we want to use + vtgateInstance.GatewayImplementation = "tabletgateway" + // Start vtgate + if err := vtgateInstance.Setup(); err != nil { + return 1, err + } + // ensure it is torn down during cluster TearDown + clusterInstance.VtgateProcess = *vtgateInstance + vtParams = mysql.ConnParams{ + Host: clusterInstance.Hostname, + Port: clusterInstance.VtgateMySQLPort, + } + return m.Run(), nil }() if err != nil { @@ -127,23 +156,29 @@ func TestSchemaChange(t *testing.T) { assert.Equal(t, 2, len(clusterInstance.Keyspaces[0].Shards)) testWithInitialSchema(t) { - _ = testAlterTable(t, alterTableNormalStatement, false, "non_online") + _ = testAlterTable(t, alterTableNormalStatement, string(schema.DDLStrategyNormal), "vtctl", "non_online") + } + { + uuid := testAlterTable(t, alterTableSuccessfulStatement, ddlStrategyUnchanged, "vtgate", "ghost_col") + checkRecentMigrations(t, uuid, schema.OnlineDDLStatusComplete) + checkCancelMigration(t, uuid, false) + checkRetryMigration(t, uuid, false) } { - uuid := testAlterTable(t, alterTableSuccessfulStatement, true, "ghost_col") + uuid := testAlterTable(t, alterTableTrivialStatement, "gh-ost", "vtctl", "ghost_col") checkRecentMigrations(t, uuid, schema.OnlineDDLStatusComplete) checkCancelMigration(t, uuid, false) checkRetryMigration(t, uuid, false) } { - uuid := testAlterTable(t, alterTableThrottlingStatement, true, "ghost_col") + uuid := testAlterTable(t, alterTableThrottlingStatement, "gh-ost --max-load=Threads_running=1", "vtgate", "ghost_col") checkRecentMigrations(t, uuid, schema.OnlineDDLStatusRunning) checkCancelMigration(t, uuid, true) time.Sleep(2 * time.Second) checkRecentMigrations(t, uuid, schema.OnlineDDLStatusFailed) } { - uuid := testAlterTable(t, alterTableFailedStatement, true, "ghost_col") + uuid := testAlterTable(t, alterTableFailedStatement, "gh-ost", "vtgate", "ghost_col") checkRecentMigrations(t, uuid, schema.OnlineDDLStatusFailed) checkCancelMigration(t, uuid, false) checkRetryMigration(t, uuid, true) @@ -164,19 +199,31 @@ func testWithInitialSchema(t *testing.T) { } // testAlterTable runs an online DDL, ALTER statement -func testAlterTable(t *testing.T, alterStatement string, isOnlineDDL bool, expectColumn string) (uuid string) { +func testAlterTable(t *testing.T, alterStatement string, ddlStrategy string, executeStrategy string, expectColumn string) (uuid string) { tableName := fmt.Sprintf("vt_onlineddl_test_%02d", 3) sqlQuery := fmt.Sprintf(alterStatement, tableName) - uuid, err := clusterInstance.VtctlclientProcess.ApplySchemaWithOutput(keyspaceName, sqlQuery) - require.Nil(t, err) + if executeStrategy == "vtgate" { + row := vtgateExec(t, ddlStrategy, sqlQuery, "").Named().Row() + if row != nil { + uuid = row.AsString("uuid", "") + } + } else { + var err error + ddlStrategyArg := "" + if ddlStrategy != ddlStrategyUnchanged { + ddlStrategyArg = ddlStrategy + } + uuid, err = clusterInstance.VtctlclientProcess.ApplySchemaWithOutput(keyspaceName, sqlQuery, ddlStrategyArg) + assert.NoError(t, err) + } uuid = strings.TrimSpace(uuid) - if isOnlineDDL { - require.NotEmpty(t, uuid) - // Migration is asynchronous. Give it some time. + fmt.Println("# Generated UUID (for debug purposes):") + fmt.Printf("<%s>\n", uuid) + + if ddlStrategy != string(schema.DDLStrategyNormal) { time.Sleep(time.Second * 20) - } else { - require.Empty(t, uuid) } + checkMigratedTable(t, tableName, expectColumn) return uuid } @@ -267,3 +314,26 @@ func getCreateTableStatement(t *testing.T, tablet *cluster.Vttablet, tableName s statement = queryResult.Rows[0][1].ToString() return statement } + +func vtgateExec(t *testing.T, ddlStrategy string, query string, expectError string) *sqltypes.Result { + t.Helper() + + ctx := context.Background() + conn, err := mysql.Connect(ctx, &vtParams) + require.Nil(t, err) + defer conn.Close() + + if ddlStrategy != ddlStrategyUnchanged { + setSession := fmt.Sprintf("set @@ddl_strategy='%s'", ddlStrategy) + _, err := conn.ExecuteFetch(setSession, 1000, true) + assert.NoError(t, err) + } + qr, err := conn.ExecuteFetch(query, 1000, true) + if expectError == "" { + require.NoError(t, err) + } else { + require.Error(t, err, "error should not be nil") + assert.Contains(t, err.Error(), expectError, "Unexpected error") + } + return qr +} diff --git a/go/test/endtoend/vreplication/vreplication_test.go b/go/test/endtoend/vreplication/vreplication_test.go index 4928177189c..4bd74be0dfe 100644 --- a/go/test/endtoend/vreplication/vreplication_test.go +++ b/go/test/endtoend/vreplication/vreplication_test.go @@ -213,7 +213,7 @@ func shardCustomer(t *testing.T, testReverse bool, cells []*Cell, sourceCellOrAl query := "select * from customer" require.True(t, validateThatQueryExecutesOnTablet(t, vtgateConn, productTab, "product", query, query)) insertQuery1 := "insert into customer(cid, name) values(1001, 'tempCustomer1')" - matchInsertQuery1 := "insert into customer(cid, name) values (:vtg1, :vtg2)" + matchInsertQuery1 := "insert into customer(cid, `name`) values (:vtg1, :vtg2)" require.True(t, validateThatQueryExecutesOnTablet(t, vtgateConn, productTab, "product", insertQuery1, matchInsertQuery1)) vdiff(t, ksWorkflow) switchReadsDryRun(t, allCellNames, ksWorkflow, dryRunResultsReadCustomerShard) @@ -224,7 +224,7 @@ func shardCustomer(t *testing.T, testReverse bool, cells []*Cell, sourceCellOrAl ksShards := []string{"product/0", "customer/-80", "customer/80-"} printShardPositions(vc, ksShards) insertQuery2 := "insert into customer(name) values('tempCustomer2')" - matchInsertQuery2 := "insert into customer(name, cid) values (:vtg1, :_cid0)" + matchInsertQuery2 := "insert into customer(`name`, cid) values (:vtg1, :_cid0)" require.False(t, validateThatQueryExecutesOnTablet(t, vtgateConn, productTab, "customer", insertQuery2, matchInsertQuery2)) insertQuery2 = "insert into customer(name, cid) values('tempCustomer3', 101)" //ID 101, hence due to reverse_bits in shard 80- diff --git a/go/test/endtoend/vtgate/lookup_test.go b/go/test/endtoend/vtgate/lookup_test.go index d0c50b1c3e1..489bb814227 100644 --- a/go/test/endtoend/vtgate/lookup_test.go +++ b/go/test/endtoend/vtgate/lookup_test.go @@ -498,18 +498,20 @@ func TestSelectNullLookup(t *testing.T) { require.NoError(t, err) defer conn.Close() - exec(t, conn, "begin") exec(t, conn, "insert into t6(id1, id2) values(1, 'a'), (2, 'b'), (3, null)") - exec(t, conn, "commit") - - assertMatches(t, conn, "select id1, id2 from t6 order by id1", "[[INT64(1) VARCHAR(\"a\")] [INT64(2) VARCHAR(\"b\")] [INT64(3) NULL]]") - assertIsEmpty(t, conn, "select id1, id2 from t6 where id2 = null") - assertMatches(t, conn, "select id1, id2 from t6 where id2 is null", "[[INT64(3) NULL]]") - assertMatches(t, conn, "select id1, id2 from t6 where id2 is not null order by id1", "[[INT64(1) VARCHAR(\"a\")] [INT64(2) VARCHAR(\"b\")]]") - assertIsEmpty(t, conn, "select id1, id2 from t6 where id1 IN (null)") - assertMatches(t, conn, "select id1, id2 from t6 where id1 IN (1,2,null) order by id1", "[[INT64(1) VARCHAR(\"a\")] [INT64(2) VARCHAR(\"b\")]]") - assertIsEmpty(t, conn, "select id1, id2 from t6 where id1 NOT IN (1,null) order by id1") - assertMatches(t, conn, "select id1, id2 from t6 where id1 NOT IN (1,3)", "[[INT64(2) VARCHAR(\"b\")]]") - - exec(t, conn, "delete from t6") + defer exec(t, conn, "set workload = oltp;delete from t6") + + for _, workload := range []string{"oltp", "olap"} { + t.Run(workload, func(t *testing.T) { + exec(t, conn, "set workload = "+workload) + assertMatches(t, conn, "select id1, id2 from t6 order by id1", "[[INT64(1) VARCHAR(\"a\")] [INT64(2) VARCHAR(\"b\")] [INT64(3) NULL]]") + assertIsEmpty(t, conn, "select id1, id2 from t6 where id2 = null") + assertMatches(t, conn, "select id1, id2 from t6 where id2 is null", "[[INT64(3) NULL]]") + assertMatches(t, conn, "select id1, id2 from t6 where id2 is not null order by id1", "[[INT64(1) VARCHAR(\"a\")] [INT64(2) VARCHAR(\"b\")]]") + assertIsEmpty(t, conn, "select id1, id2 from t6 where id1 IN (null)") + assertMatches(t, conn, "select id1, id2 from t6 where id1 IN (1,2,null) order by id1", "[[INT64(1) VARCHAR(\"a\")] [INT64(2) VARCHAR(\"b\")]]") + assertIsEmpty(t, conn, "select id1, id2 from t6 where id1 NOT IN (1,null) order by id1") + assertMatches(t, conn, "select id1, id2 from t6 where id1 NOT IN (1,3)", "[[INT64(2) VARCHAR(\"b\")]]") + }) + } } diff --git a/go/test/endtoend/vtgate/misc_test.go b/go/test/endtoend/vtgate/misc_test.go index 50074559260..b1ba3dca712 100644 --- a/go/test/endtoend/vtgate/misc_test.go +++ b/go/test/endtoend/vtgate/misc_test.go @@ -85,6 +85,21 @@ func TestCastConvert(t *testing.T) { assertMatches(t, conn, `SELECT CAST("test" AS CHAR(60))`, `[[VARCHAR("test")]]`) } +func TestCompositeIN(t *testing.T) { + conn, err := mysql.Connect(context.Background(), &vtParams) + require.NoError(t, err) + defer conn.Close() + + // clean up before & after + exec(t, conn, "delete from t1") + defer exec(t, conn, "delete from t1") + + exec(t, conn, "insert into t1(id1, id2) values(1, 2), (4, 5)") + + // Just check for correct results. Plan generation is tested in unit tests. + assertMatches(t, conn, "select id1 from t1 where (id1, id2) in ((1, 2))", "[[INT64(1)]]") +} + func TestUnionAll(t *testing.T) { conn, err := mysql.Connect(context.Background(), &vtParams) require.NoError(t, err) @@ -450,6 +465,20 @@ func TestDistinct(t *testing.T) { exec(t, conn, "delete from aggr_test") } +func TestCreateIndex(t *testing.T) { + defer cluster.PanicHandler(t) + ctx := context.Background() + conn, err := mysql.Connect(ctx, &vtParams) + require.NoError(t, err) + defer conn.Close() + // Test that create index with the correct table name works + _, err = conn.ExecuteFetch(`create index i1 on t1 (id1)`, 1000, true) + require.NoError(t, err) + // Test routing rules for create index. + _, err = conn.ExecuteFetch(`create index i2 on ks.t1000 (id1)`, 1000, true) + require.NoError(t, err) +} + func assertMatches(t *testing.T, conn *mysql.Conn, query, expected string) { t.Helper() qr := exec(t, conn, query) diff --git a/go/vt/binlog/event_streamer_test.go b/go/vt/binlog/event_streamer_test.go index fc5434717a6..62a329ad0dd 100644 --- a/go/vt/binlog/event_streamer_test.go +++ b/go/vt/binlog/event_streamer_test.go @@ -29,14 +29,14 @@ import ( var dmlErrorCases = []string{ "query", - "query /* _stream 10 (eid id name ) (null 1 'bmFtZQ==' ); */", - "query /* _stream _table_ eid id name ) (null 1 'bmFtZQ==' ); */", - "query /* _stream _table_ (10 id name ) (null 1 'bmFtZQ==' ); */", - "query /* _stream _table_ (eid id name (null 1 'bmFtZQ==' ); */", - "query /* _stream _table_ (eid id name) (null 'aaa' 'bmFtZQ==' ); */", - "query /* _stream _table_ (eid id name) (null 'bmFtZQ==' ); */", - "query /* _stream _table_ (eid id name) (null 1.1 'bmFtZQ==' ); */", - "query /* _stream _table_ (eid id name) (null a 'bmFtZQ==' ); */", + "query /* _stream 10 (eid id `name` ) (null 1 'bmFtZQ==' ); */", + "query /* _stream _table_ eid id `name` ) (null 1 'bmFtZQ==' ); */", + "query /* _stream _table_ (10 id `name` ) (null 1 'bmFtZQ==' ); */", + "query /* _stream _table_ (eid id `name` (null 1 'bmFtZQ==' ); */", + "query /* _stream _table_ (eid id `name`) (null 'aaa' 'bmFtZQ==' ); */", + "query /* _stream _table_ (eid id `name`) (null 'bmFtZQ==' ); */", + "query /* _stream _table_ (eid id `name`) (null 1.1 'bmFtZQ==' ); */", + "query /* _stream _table_ (eid id `name`) (null a 'bmFtZQ==' ); */", } func TestEventErrors(t *testing.T) { @@ -115,7 +115,7 @@ func TestDMLEvent(t *testing.T) { { Statement: &binlogdatapb.BinlogTransaction_Statement{ Category: binlogdatapb.BinlogTransaction_Statement_BL_INSERT, - Sql: []byte("query /* _stream _table_ (eid id name) (null 1 'bmFtZQ==' ) (null 18446744073709551615 'bmFtZQ==' ); */"), + Sql: []byte("query /* _stream _table_ (eid id `name`) (null 1 'bmFtZQ==' ) (null 18446744073709551615 'bmFtZQ==' ); */"), }, }, { diff --git a/go/vt/key/key.go b/go/vt/key/key.go index 98143a1ff13..90f076403a3 100644 --- a/go/vt/key/key.go +++ b/go/vt/key/key.go @@ -289,10 +289,16 @@ func KeyRangeIncludes(big, small *topodatapb.KeyRange) bool { // specification. a-b-c-d will be parsed as a-b, b-c, c-d. The empty // string may serve both as the start and end of the keyspace: -a-b- // will be parsed as start-a, a-b, b-end. +// "0" is treated as "-", to allow us to not have to special-case +// client code. func ParseShardingSpec(spec string) ([]*topodatapb.KeyRange, error) { parts := strings.Split(spec, "-") if len(parts) == 1 { - return nil, fmt.Errorf("malformed spec: doesn't define a range: %q", spec) + if spec == "0" { + parts = []string{"", ""} + } else { + return nil, fmt.Errorf("malformed spec: doesn't define a range: %q", spec) + } } old := parts[0] ranges := make([]*topodatapb.KeyRange, len(parts)-1) diff --git a/go/vt/key/key_test.go b/go/vt/key/key_test.go index 89bac6311fc..8643d0bcc73 100644 --- a/go/vt/key/key_test.go +++ b/go/vt/key/key_test.go @@ -272,6 +272,7 @@ func TestParseShardingSpec(t *testing.T) { x80 := []byte{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} goodTable := map[string][]*topodatapb.KeyRange{ "-": {{}}, + "0": {{}}, "-4000000000000000-8000000000000000-": { {End: x40}, {Start: x40, End: x80}, diff --git a/go/vt/mysqlctl/s3backupstorage/s3.go b/go/vt/mysqlctl/s3backupstorage/s3.go index e6347a4a9fc..8d566351e9d 100644 --- a/go/vt/mysqlctl/s3backupstorage/s3.go +++ b/go/vt/mysqlctl/s3backupstorage/s3.go @@ -24,10 +24,13 @@ limitations under the License. package s3backupstorage import ( + "crypto/md5" "crypto/tls" + "encoding/base64" "flag" "fmt" "io" + "io/ioutil" "math" "net/http" "sort" @@ -74,7 +77,7 @@ var ( requiredLogLevel = flag.String("s3_backup_log_level", "LogOff", "determine the S3 loglevel to use from LogOff, LogDebug, LogDebugWithSigning, LogDebugWithHTTPBody, LogDebugWithRequestRetries, LogDebugWithRequestErrors") // sse is the server-side encryption algorithm used when storing this object in S3 - sse = flag.String("s3_backup_server_side_encryption", "", "server-side encryption algorithm (e.g., AES256, aws:kms)") + sse = flag.String("s3_backup_server_side_encryption", "", "server-side encryption algorithm (e.g., AES256, aws:kms, sse_c:/path/to/key/file)") // path component delimiter delimiter = "/" @@ -84,6 +87,8 @@ type logNameToLogLevel map[string]aws.LogLevelType var logNameMap logNameToLogLevel +const sseCustomerPrefix = "sse_c:" + // S3BackupHandle implements the backupstorage.BackupHandle interface. type S3BackupHandle struct { client s3iface.S3API @@ -147,15 +152,14 @@ func (bh *S3BackupHandle) AddFile(ctx context.Context, filename string, filesize }) object := objName(bh.dir, bh.name, filename) - var sseOption *string - if *sse != "" { - sseOption = sse - } _, err := uploader.Upload(&s3manager.UploadInput{ Bucket: bucket, Key: object, Body: reader, - ServerSideEncryption: sseOption, + ServerSideEncryption: bh.bs.s3SSE.awsAlg, + SSECustomerAlgorithm: bh.bs.s3SSE.customerAlg, + SSECustomerKey: bh.bs.s3SSE.customerKey, + SSECustomerKeyMD5: bh.bs.s3SSE.customerMd5, }) if err != nil { reader.CloseWithError(err) @@ -190,8 +194,11 @@ func (bh *S3BackupHandle) ReadFile(ctx context.Context, filename string) (io.Rea } object := objName(bh.dir, bh.name, filename) out, err := bh.client.GetObject(&s3.GetObjectInput{ - Bucket: bucket, - Key: object, + Bucket: bucket, + Key: object, + SSECustomerAlgorithm: bh.bs.s3SSE.customerAlg, + SSECustomerKey: bh.bs.s3SSE.customerKey, + SSECustomerKeyMD5: bh.bs.s3SSE.customerMd5, }) if err != nil { return nil, err @@ -201,10 +208,51 @@ func (bh *S3BackupHandle) ReadFile(ctx context.Context, filename string) (io.Rea var _ backupstorage.BackupHandle = (*S3BackupHandle)(nil) +type S3ServerSideEncryption struct { + awsAlg *string + customerAlg *string + customerKey *string + customerMd5 *string +} + +func (s3ServerSideEncryption *S3ServerSideEncryption) init() error { + s3ServerSideEncryption.reset() + + if strings.HasPrefix(*sse, sseCustomerPrefix) { + sseCustomerKeyFile := strings.TrimPrefix(*sse, sseCustomerPrefix) + base64CodedKey, err := ioutil.ReadFile(sseCustomerKeyFile) + if err != nil { + log.Errorf(err.Error()) + return err + } + + decodedKey, err := base64.StdEncoding.DecodeString(string(base64CodedKey)) + if err != nil { + decodedKey = base64CodedKey + } + + md5Hash := md5.Sum(decodedKey) + s3ServerSideEncryption.customerAlg = aws.String("AES256") + s3ServerSideEncryption.customerKey = aws.String(string(decodedKey)) + s3ServerSideEncryption.customerMd5 = aws.String(base64.StdEncoding.EncodeToString(md5Hash[:])) + } else if *sse != "" { + s3ServerSideEncryption.awsAlg = sse + } + return nil +} + +func (s3ServerSideEncryption *S3ServerSideEncryption) reset() { + s3ServerSideEncryption.awsAlg = nil + s3ServerSideEncryption.customerAlg = nil + s3ServerSideEncryption.customerKey = nil + s3ServerSideEncryption.customerMd5 = nil +} + // S3BackupStorage implements the backupstorage.BackupStorage interface. type S3BackupStorage struct { _client *s3.S3 mu sync.Mutex + s3SSE S3ServerSideEncryption } // ListBackups is part of the backupstorage.BackupStorage interface. @@ -339,6 +387,7 @@ func (bs *S3BackupStorage) Close() error { bs.mu.Lock() defer bs.mu.Unlock() bs._client = nil + bs.s3SSE.reset() return nil } @@ -394,6 +443,10 @@ func (bs *S3BackupStorage) client() (*s3.S3, error) { if _, err := bs._client.HeadBucket(&s3.HeadBucketInput{Bucket: bucket}); err != nil { return nil, err } + + if err := bs.s3SSE.init(); err != nil { + return nil, err + } } return bs._client, nil } diff --git a/go/vt/mysqlctl/s3backupstorage/s3_test.go b/go/vt/mysqlctl/s3backupstorage/s3_test.go index 25d958934f7..98bac3a59ba 100644 --- a/go/vt/mysqlctl/s3backupstorage/s3_test.go +++ b/go/vt/mysqlctl/s3backupstorage/s3_test.go @@ -1,8 +1,13 @@ package s3backupstorage import ( + "crypto/md5" + "crypto/rand" + "encoding/base64" "errors" + "io/ioutil" "net/http" + "os" "testing" "github.com/aws/aws-sdk-go/aws" @@ -25,7 +30,7 @@ func (s3errclient *s3ErrorClient) PutObjectRequest(in *s3.PutObjectInput) (*requ } func TestAddFileError(t *testing.T) { - bh := &S3BackupHandle{client: &s3ErrorClient{}, readOnly: false} + bh := &S3BackupHandle{client: &s3ErrorClient{}, bs: &S3BackupStorage{}, readOnly: false} wc, err := bh.AddFile(aws.BackgroundContext(), "somefile", 100000) require.NoErrorf(t, err, "AddFile() expected no error, got %s", err) @@ -41,3 +46,122 @@ func TestAddFileError(t *testing.T) { require.Equal(t, bh.HasErrors(), true, "AddFile() expected bh to record async error but did not") } + +func TestNoSSE(t *testing.T) { + sseData := S3ServerSideEncryption{} + err := sseData.init() + require.NoErrorf(t, err, "init() expected to succeed") + + assert.Nil(t, sseData.awsAlg, "awsAlg expected to be nil") + assert.Nil(t, sseData.customerAlg, "customerAlg expected to be nil") + assert.Nil(t, sseData.customerKey, "customerKey expected to be nil") + assert.Nil(t, sseData.customerMd5, "customerMd5 expected to be nil") + + sseData.reset() + require.NoErrorf(t, err, "reset() expected to succeed") +} + +func TestSSEAws(t *testing.T) { + sse = aws.String("aws:kms") + sseData := S3ServerSideEncryption{} + err := sseData.init() + require.NoErrorf(t, err, "init() expected to succeed") + + assert.Equal(t, aws.String("aws:kms"), sseData.awsAlg, "awsAlg expected to be aws:kms") + assert.Nil(t, sseData.customerAlg, "customerAlg expected to be nil") + assert.Nil(t, sseData.customerKey, "customerKey expected to be nil") + assert.Nil(t, sseData.customerMd5, "customerMd5 expected to be nil") + + sseData.reset() + require.NoErrorf(t, err, "reset() expected to succeed") + + assert.Nil(t, sseData.awsAlg, "awsAlg expected to be nil") + assert.Nil(t, sseData.customerAlg, "customerAlg expected to be nil") + assert.Nil(t, sseData.customerKey, "customerKey expected to be nil") + assert.Nil(t, sseData.customerMd5, "customerMd5 expected to be nil") +} + +func TestSSECustomerFileNotFound(t *testing.T) { + tempFile, err := ioutil.TempFile("", "filename") + require.NoErrorf(t, err, "TempFile() expected to succeed") + defer os.Remove(tempFile.Name()) + + err = tempFile.Close() + require.NoErrorf(t, err, "Close() expected to succeed") + + err = os.Remove(tempFile.Name()) + require.NoErrorf(t, err, "Remove() expected to succeed") + + sse = aws.String(sseCustomerPrefix + tempFile.Name()) + sseData := S3ServerSideEncryption{} + err = sseData.init() + require.Errorf(t, err, "init() expected to fail") +} + +func TestSSECustomerFileBinaryKey(t *testing.T) { + tempFile, err := ioutil.TempFile("", "filename") + require.NoErrorf(t, err, "TempFile() expected to succeed") + defer os.Remove(tempFile.Name()) + + randomKey := make([]byte, 32) + _, err = rand.Read(randomKey) + require.NoErrorf(t, err, "Read() expected to succeed") + _, err = tempFile.Write(randomKey) + require.NoErrorf(t, err, "Write() expected to succeed") + err = tempFile.Close() + require.NoErrorf(t, err, "Close() expected to succeed") + + sse = aws.String(sseCustomerPrefix + tempFile.Name()) + sseData := S3ServerSideEncryption{} + err = sseData.init() + require.NoErrorf(t, err, "init() expected to succeed") + + assert.Nil(t, sseData.awsAlg, "awsAlg expected to be nil") + assert.Equal(t, aws.String("AES256"), sseData.customerAlg, "customerAlg expected to be AES256") + assert.Equal(t, aws.String(string(randomKey)), sseData.customerKey, "customerKey expected to be equal to the generated randomKey") + md5Hash := md5.Sum(randomKey) + assert.Equal(t, aws.String(base64.StdEncoding.EncodeToString(md5Hash[:])), sseData.customerMd5, "customerMd5 expected to be equal to the customerMd5 hash of the generated randomKey") + + sseData.reset() + require.NoErrorf(t, err, "reset() expected to succeed") + + assert.Nil(t, sseData.awsAlg, "awsAlg expected to be nil") + assert.Nil(t, sseData.customerAlg, "customerAlg expected to be nil") + assert.Nil(t, sseData.customerKey, "customerKey expected to be nil") + assert.Nil(t, sseData.customerMd5, "customerMd5 expected to be nil") +} + +func TestSSECustomerFileBase64Key(t *testing.T) { + tempFile, err := ioutil.TempFile("", "filename") + require.NoErrorf(t, err, "TempFile() expected to succeed") + defer os.Remove(tempFile.Name()) + + randomKey := make([]byte, 32) + _, err = rand.Read(randomKey) + require.NoErrorf(t, err, "Read() expected to succeed") + + base64Key := base64.StdEncoding.EncodeToString(randomKey[:]) + _, err = tempFile.WriteString(base64Key) + require.NoErrorf(t, err, "WriteString() expected to succeed") + err = tempFile.Close() + require.NoErrorf(t, err, "Close() expected to succeed") + + sse = aws.String(sseCustomerPrefix + tempFile.Name()) + sseData := S3ServerSideEncryption{} + err = sseData.init() + require.NoErrorf(t, err, "init() expected to succeed") + + assert.Nil(t, sseData.awsAlg, "awsAlg expected to be nil") + assert.Equal(t, aws.String("AES256"), sseData.customerAlg, "customerAlg expected to be AES256") + assert.Equal(t, aws.String(string(randomKey)), sseData.customerKey, "customerKey expected to be equal to the generated randomKey") + md5Hash := md5.Sum(randomKey) + assert.Equal(t, aws.String(base64.StdEncoding.EncodeToString(md5Hash[:])), sseData.customerMd5, "customerMd5 expected to be equal to the customerMd5 hash of the generated randomKey") + + sseData.reset() + require.NoErrorf(t, err, "reset() expected to succeed") + + assert.Nil(t, sseData.awsAlg, "awsAlg expected to be nil") + assert.Nil(t, sseData.customerAlg, "customerAlg expected to be nil") + assert.Nil(t, sseData.customerKey, "customerKey expected to be nil") + assert.Nil(t, sseData.customerMd5, "customerMd5 expected to be nil") +} diff --git a/go/vt/schema/online_ddl.go b/go/vt/schema/online_ddl.go index 644a7382548..e6a1945a724 100644 --- a/go/vt/schema/online_ddl.go +++ b/go/vt/schema/online_ddl.go @@ -26,13 +26,13 @@ import ( "github.com/google/uuid" - "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/topo" ) var ( - migrationBasePath = "schema-migration" - onlineDdlUUIDRegexp = regexp.MustCompile(`^[0-f]{8}_[0-f]{4}_[0-f]{4}_[0-f]{4}_[0-f]{12}$`) + migrationBasePath = "schema-migration" + onlineDdlUUIDRegexp = regexp.MustCompile(`^[0-f]{8}_[0-f]{4}_[0-f]{4}_[0-f]{4}_[0-f]{12}$`) + strategyParserRegexp = regexp.MustCompile(`^([\S]+)\s+(.*)$`) ) // MigrationBasePath is the root for all schema migration entries @@ -75,40 +75,46 @@ const ( OnlineDDLStatusFailed OnlineDDLStatus = "failed" ) +// DDLStrategy suggests how an ALTER TABLE should run (e.g. "" for normal, "gh-ost" or "pt-osc") +type DDLStrategy string + const ( // DDLStrategyNormal means not an online-ddl migration. Just a normal MySQL ALTER TABLE - DDLStrategyNormal sqlparser.DDLStrategy = "" + DDLStrategyNormal DDLStrategy = "" // DDLStrategyGhost requests gh-ost to run the migration - DDLStrategyGhost sqlparser.DDLStrategy = "gh-ost" + DDLStrategyGhost DDLStrategy = "gh-ost" // DDLStrategyPTOSC requests pt-online-schema-change to run the migration - DDLStrategyPTOSC sqlparser.DDLStrategy = "pt-osc" + DDLStrategyPTOSC DDLStrategy = "pt-osc" ) // OnlineDDL encapsulates the relevant information in an online schema change request type OnlineDDL struct { - Keyspace string `json:"keyspace,omitempty"` - Table string `json:"table,omitempty"` - Schema string `json:"schema,omitempty"` - SQL string `json:"sql,omitempty"` - UUID string `json:"uuid,omitempty"` - Strategy sqlparser.DDLStrategy `json:"strategy,omitempty"` - Options string `json:"options,omitempty"` - RequestTime int64 `json:"time_created,omitempty"` - Status OnlineDDLStatus `json:"status,omitempty"` - TabletAlias string `json:"tablet,omitempty"` - Retries int64 `json:"retries,omitempty"` -} - -func ValidateDDLStrategy(strategy string) (sqlparser.DDLStrategy, error) { - switch sqlparser.DDLStrategy(strategy) { - case DDLStrategyGhost: - return DDLStrategyGhost, nil - case DDLStrategyPTOSC: - return DDLStrategyPTOSC, nil - case DDLStrategyNormal: - return DDLStrategyNormal, nil + Keyspace string `json:"keyspace,omitempty"` + Table string `json:"table,omitempty"` + Schema string `json:"schema,omitempty"` + SQL string `json:"sql,omitempty"` + UUID string `json:"uuid,omitempty"` + Strategy DDLStrategy `json:"strategy,omitempty"` + Options string `json:"options,omitempty"` + RequestTime int64 `json:"time_created,omitempty"` + Status OnlineDDLStatus `json:"status,omitempty"` + TabletAlias string `json:"tablet,omitempty"` + Retries int64 `json:"retries,omitempty"` +} + +// ParseDDLStrategy validates the given ddl_strategy variable value , and parses the strategy and options parts. +func ParseDDLStrategy(strategyVariable string) (strategy DDLStrategy, options string, err error) { + strategyName := strategyVariable + if submatch := strategyParserRegexp.FindStringSubmatch(strategyVariable); len(submatch) > 0 { + strategyName = submatch[1] + options = submatch[2] + } + + switch strategy = DDLStrategy(strategyName); strategy { + case DDLStrategyGhost, DDLStrategyPTOSC, DDLStrategyNormal: + return strategy, options, nil default: - return DDLStrategyNormal, fmt.Errorf("Unknown online DDL strategy: '%v'", strategy) + return strategy, options, fmt.Errorf("Unknown online DDL strategy: '%v'", strategy) } } @@ -133,7 +139,7 @@ func ReadTopo(ctx context.Context, conn topo.Conn, entryPath string) (*OnlineDDL } // NewOnlineDDL creates a schema change request with self generated UUID and RequestTime -func NewOnlineDDL(keyspace string, table string, sql string, strategy sqlparser.DDLStrategy, options string) (*OnlineDDL, error) { +func NewOnlineDDL(keyspace string, table string, sql string, strategy DDLStrategy, options string) (*OnlineDDL, error) { u, err := CreateUUID() if err != nil { return nil, err diff --git a/go/vt/schema/online_ddl_test.go b/go/vt/schema/online_ddl_test.go index f0bf0e9b5f2..f22fd453868 100644 --- a/go/vt/schema/online_ddl_test.go +++ b/go/vt/schema/online_ddl_test.go @@ -27,24 +27,38 @@ func TestCreateUUID(t *testing.T) { assert.NoError(t, err) } -func TestValidateDDLStrategy(t *testing.T) { - { - strategy, err := ValidateDDLStrategy("gh-ost") - assert.NoError(t, err) - assert.Equal(t, DDLStrategyGhost, strategy) - } - { - strategy, err := ValidateDDLStrategy("pt-osc") - assert.NoError(t, err) - assert.Equal(t, DDLStrategyPTOSC, strategy) +func TestParseDDLStrategy(t *testing.T) { + tt := []struct { + strategyVariable string + strategy DDLStrategy + options string + err error + }{ + { + strategyVariable: "gh-ost", + strategy: DDLStrategyGhost, + }, + { + strategyVariable: "pt-osc", + strategy: DDLStrategyPTOSC, + }, + { + strategy: DDLStrategyNormal, + }, + { + strategyVariable: "gh-ost --max-load=Threads_running=100 --allow-master", + strategy: DDLStrategyGhost, + options: "--max-load=Threads_running=100 --allow-master", + }, } - { - strategy, err := ValidateDDLStrategy("") + for _, ts := range tt { + strategy, options, err := ParseDDLStrategy(ts.strategyVariable) assert.NoError(t, err) - assert.Equal(t, DDLStrategyNormal, strategy) + assert.Equal(t, ts.strategy, strategy) + assert.Equal(t, ts.options, options) } { - _, err := ValidateDDLStrategy("other") + _, _, err := ParseDDLStrategy("other") assert.Error(t, err) } } diff --git a/go/vt/schema/parser.go b/go/vt/schema/parser.go index da09fb8cabf..ab956a0e5bc 100644 --- a/go/vt/schema/parser.go +++ b/go/vt/schema/parser.go @@ -17,21 +17,15 @@ limitations under the License. package schema import ( - "fmt" "regexp" "strings" ) var ( // ALTER TABLE - // ALTER WITH_GHOST TABLE - // ALTER WITH_GHOST LAG_'--max-lag-millis=2.5 --throttle-http=...' TABLE - // ALTER WITH_PT TABLE - alterTableBasicPattern = `(?s)(?i)\balter\s+(with\s+|\s+|).*?table\s+` + alterTableBasicPattern = `(?s)(?i)\balter\s+table\s+` alterTableExplicitSchemaTableRegexps = []*regexp.Regexp{ // ALTER TABLE `scm`.`tbl` something - // ALTER WITH_GHOST TABLE `scm`.`tbl` something - // ALTER WITH_PT TABLE `scm`.`tbl` something regexp.MustCompile(alterTableBasicPattern + "`" + `([^` + "`" + `]+)` + "`" + `[.]` + "`" + `([^` + "`" + `]+)` + "`" + `\s+(.*$)`), // ALTER TABLE `scm`.tbl something regexp.MustCompile(alterTableBasicPattern + "`" + `([^` + "`" + `]+)` + "`" + `[.]([\S]+)\s+(.*$)`), @@ -55,33 +49,18 @@ func ParseAlterTableOptions(alterStatement string) (explicitSchema, explicitTabl alterOptions = strings.TrimSpace(alterStatement) for _, alterTableRegexp := range alterTableExplicitSchemaTableRegexps { if submatch := alterTableRegexp.FindStringSubmatch(alterOptions); len(submatch) > 0 { - explicitSchema = submatch[2] - explicitTable = submatch[3] - alterOptions = submatch[4] + explicitSchema = submatch[1] + explicitTable = submatch[2] + alterOptions = submatch[3] return explicitSchema, explicitTable, alterOptions } } for _, alterTableRegexp := range alterTableExplicitTableRegexps { if submatch := alterTableRegexp.FindStringSubmatch(alterOptions); len(submatch) > 0 { - explicitTable = submatch[2] - alterOptions = submatch[3] + explicitTable = submatch[1] + alterOptions = submatch[2] return explicitSchema, explicitTable, alterOptions } } return explicitSchema, explicitTable, alterOptions } - -// RemoveOnlineDDLHints removes a WITH_GHOST or WITH_PT hint, which is vitess-specific, -// from an ALTER TABLE statement -// e.g "ALTER WITH 'gh-ost' TABLE my_table DROP COLUMN i" -> "ALTER TABLE `my_table` DROP COLUMN i" -func RemoveOnlineDDLHints(alterStatement string) (normalizedAlterStatement string) { - explicitSchema, explicitTable, alterOptions := ParseAlterTableOptions(alterStatement) - - if explicitTable == "" { - return alterOptions - } - if explicitSchema == "" { - return fmt.Sprintf("ALTER TABLE `%s` %s", explicitTable, alterOptions) - } - return fmt.Sprintf("ALTER TABLE `%s`.`%s` %s", explicitSchema, explicitTable, alterOptions) -} diff --git a/go/vt/schema/parser_test.go b/go/vt/schema/parser_test.go index c24ffe82f9f..fbaa0080b10 100644 --- a/go/vt/schema/parser_test.go +++ b/go/vt/schema/parser_test.go @@ -25,22 +25,18 @@ func TestParseAlterTableOptions(t *testing.T) { schema, table, options string } tests := map[string]expect{ - "add column i int, drop column d": {schema: "", table: "", options: "add column i int, drop column d"}, - " add column i int, drop column d ": {schema: "", table: "", options: "add column i int, drop column d"}, - "alter table t add column i int, drop column d": {schema: "", table: "t", options: "add column i int, drop column d"}, - "alter table t add column i int, drop column d": {schema: "", table: "t", options: "add column i int, drop column d"}, - "alter table `t` add column i int, drop column d": {schema: "", table: "t", options: "add column i int, drop column d"}, - "alter table `scm`.`t` add column i int, drop column d": {schema: "scm", table: "t", options: "add column i int, drop column d"}, - "alter table `scm`.t add column i int, drop column d": {schema: "scm", table: "t", options: "add column i int, drop column d"}, - "alter table scm.`t` add column i int, drop column d": {schema: "scm", table: "t", options: "add column i int, drop column d"}, - "alter table scm.t add column i int, drop column d": {schema: "scm", table: "t", options: "add column i int, drop column d"}, - "alter with 'gh-ost' table scm.t add column i int, drop column d": {schema: "scm", table: "t", options: "add column i int, drop column d"}, - " alter with 'gh-ost' table scm.`t` add column i int, drop column d": {schema: "scm", table: "t", options: "add column i int, drop column d"}, - "alter with 'pt-osc' table scm.t add column i int, drop column d": {schema: "scm", table: "t", options: "add column i int, drop column d"}, - "alter with 'gh-ost' '--some-option=5 --another-option=false' table scm.t add column i int, drop column d": {schema: "scm", table: "t", options: "add column i int, drop column d"}, - "alter with 'gh-ost' '--initially-drop-old-table' table scm.t add column i int, drop column d": {schema: "scm", table: "t", options: "add column i int, drop column d"}, - "alter with 'gh-ost' '--initially-drop-old-table --execute' table scm.t add column i int, drop column d": {schema: "scm", table: "t", options: "add column i int, drop column d"}, - "ALTER WITH 'gh-ost' TABLE scm.t ADD COLUMN i int, DROP COLUMN d": {schema: "scm", table: "t", options: "ADD COLUMN i int, DROP COLUMN d"}, + "add column i int, drop column d": {schema: "", table: "", options: "add column i int, drop column d"}, + " add column i int, drop column d ": {schema: "", table: "", options: "add column i int, drop column d"}, + "alter table t add column i int, drop column d": {schema: "", table: "t", options: "add column i int, drop column d"}, + "alter table t add column i int, drop column d": {schema: "", table: "t", options: "add column i int, drop column d"}, + "alter table `t` add column i int, drop column d": {schema: "", table: "t", options: "add column i int, drop column d"}, + "alter table `scm`.`t` add column i int, drop column d": {schema: "scm", table: "t", options: "add column i int, drop column d"}, + "alter table `scm`.t add column i int, drop column d": {schema: "scm", table: "t", options: "add column i int, drop column d"}, + "alter table scm.`t` add column i int, drop column d": {schema: "scm", table: "t", options: "add column i int, drop column d"}, + "alter table scm.t add column i int, drop column d": {schema: "scm", table: "t", options: "add column i int, drop column d"}, + " alter table scm.`t` add column i int, drop column d": {schema: "scm", table: "t", options: "add column i int, drop column d"}, + "ALTER table scm.t ADD COLUMN i int, DROP COLUMN d": {schema: "scm", table: "t", options: "ADD COLUMN i int, DROP COLUMN d"}, + "ALTER TABLE scm.t ADD COLUMN i int, DROP COLUMN d": {schema: "scm", table: "t", options: "ADD COLUMN i int, DROP COLUMN d"}, } for query, expect := range tests { schema, table, options := ParseAlterTableOptions(query) @@ -55,34 +51,3 @@ func TestParseAlterTableOptions(t *testing.T) { } } } - -func TestRemoveOnlineDDLHints(t *testing.T) { - tests := map[string]string{ - "ALTER TABLE my_table DROP COLUMN i": "ALTER TABLE `my_table` DROP COLUMN i", - " ALTER TABLE my_table DROP COLUMN i": "ALTER TABLE `my_table` DROP COLUMN i", - "ALTER WITH 'gh-ost' TABLE my_table DROP COLUMN i": "ALTER TABLE `my_table` DROP COLUMN i", - "ALTER WITH 'pt-osc' TABLE `my_table` DROP COLUMN i": "ALTER TABLE `my_table` DROP COLUMN i", - "ALTER WITH 'pt-osc' TABLE scm.`my_table` DROP COLUMN i": "ALTER TABLE `scm`.`my_table` DROP COLUMN i", - "ALTER WITH 'pt-osc' TABLE `scm`.`my_table` DROP COLUMN i": "ALTER TABLE `scm`.`my_table` DROP COLUMN i", - "ALTER WITH 'gh-ost' TABLE `scm`.`my_table` DROP COLUMN i": "ALTER TABLE `scm`.`my_table` DROP COLUMN i", - ` - ALTER WITH 'gh-ost' - TABLE scm.my_table - DROP COLUMN i - `: "ALTER TABLE `scm`.`my_table` DROP COLUMN i", - ` - ALTER - WITH - 'gh-ost' - TABLE scm.my_table DROP COLUMN i, - ADD j INT - `: "ALTER TABLE `scm`.`my_table` DROP COLUMN i," + ` - ADD j INT`, - } - for query, expect := range tests { - normalizedQuery := RemoveOnlineDDLHints(query) - if normalizedQuery != expect { - t.Errorf("got: %+v, want:%+v", normalizedQuery, expect) - } - } -} diff --git a/go/vt/schemamanager/tablet_executor.go b/go/vt/schemamanager/tablet_executor.go index 1f933967fa2..6c7094c5c9f 100644 --- a/go/vt/schemamanager/tablet_executor.go +++ b/go/vt/schemamanager/tablet_executor.go @@ -40,6 +40,7 @@ type TabletExecutor struct { allowBigSchemaChange bool keyspace string waitReplicasTimeout time.Duration + ddlStrategy string } // NewTabletExecutor creates a new TabletExecutor instance @@ -64,6 +65,15 @@ func (exec *TabletExecutor) DisallowBigSchemaChange() { exec.allowBigSchemaChange = false } +// SetDDLStrategy applies ddl_strategy from command line flags +func (exec *TabletExecutor) SetDDLStrategy(ddlStrategy string) error { + if _, _, err := schema.ParseDDLStrategy(ddlStrategy); err != nil { + return err + } + exec.ddlStrategy = ddlStrategy + return nil +} + // Open opens a connection to the master for every shard. func (exec *TabletExecutor) Open(ctx context.Context, keyspace string) error { if !exec.isClosed { @@ -118,18 +128,18 @@ func (exec *TabletExecutor) Validate(ctx context.Context, sqls []string) error { return err } -func (exec *TabletExecutor) parseDDLs(sqls []string) ([]*sqlparser.DDL, []*sqlparser.DBDDL, error) { - parsedDDLs := make([]*sqlparser.DDL, 0) - parsedDBDDLs := make([]*sqlparser.DBDDL, 0) +func (exec *TabletExecutor) parseDDLs(sqls []string) ([]sqlparser.DDLStatement, []sqlparser.DBDDLStatement, error) { + parsedDDLs := make([]sqlparser.DDLStatement, 0) + parsedDBDDLs := make([]sqlparser.DBDDLStatement, 0) for _, sql := range sqls { stat, err := sqlparser.Parse(sql) if err != nil { return nil, nil, fmt.Errorf("failed to parse sql: %s, got error: %v", sql, err) } switch ddl := stat.(type) { - case *sqlparser.DDL: + case sqlparser.DDLStatement: parsedDDLs = append(parsedDDLs, ddl) - case *sqlparser.DBDDL: + case sqlparser.DBDDLStatement: parsedDBDDLs = append(parsedDBDDLs, ddl) default: if len(exec.tablets) != 1 { @@ -140,11 +150,26 @@ func (exec *TabletExecutor) parseDDLs(sqls []string) ([]*sqlparser.DDL, []*sqlpa return parsedDDLs, parsedDBDDLs, nil } +// IsOnlineSchemaDDL returns true if the query is an online schema change DDL +func (exec *TabletExecutor) isOnlineSchemaDDL(ddl sqlparser.DDLStatement) (isOnline bool, strategy schema.DDLStrategy, options string) { + if ddl == nil { + return false, strategy, options + } + if ddl.GetAction() != sqlparser.AlterDDLAction { + return false, strategy, options + } + strategy, options, _ = schema.ParseDDLStrategy(exec.ddlStrategy) + if strategy != schema.DDLStrategyNormal { + return true, strategy, options + } + return false, strategy, options +} + // a schema change that satisfies any following condition is considered // to be a big schema change and will be rejected. // 1. Alter more than 100,000 rows. // 2. Change a table with more than 2,000,000 rows (Drops are fine). -func (exec *TabletExecutor) detectBigSchemaChanges(ctx context.Context, parsedDDLs []*sqlparser.DDL) (bool, error) { +func (exec *TabletExecutor) detectBigSchemaChanges(ctx context.Context, parsedDDLs []sqlparser.DDLStatement) (bool, error) { // exec.tablets is guaranteed to have at least one element; // Otherwise, Open should fail and executor should fail. masterTabletInfo := exec.tablets[0] @@ -159,20 +184,17 @@ func (exec *TabletExecutor) detectBigSchemaChanges(ctx context.Context, parsedDD tableWithCount[tableSchema.Name] = tableSchema.RowCount } for _, ddl := range parsedDDLs { - switch ddl.Action { + if isOnline, _, _ := exec.isOnlineSchemaDDL(ddl); isOnline { + // Since this is an online schema change, there is no need to worry about big changes + continue + } + switch ddl.GetAction() { case sqlparser.DropDDLAction, sqlparser.CreateDDLAction, sqlparser.TruncateDDLAction, sqlparser.RenameDDLAction: continue - case sqlparser.AlterDDLAction: - if ddl.OnlineHint != nil { - if ddl.OnlineHint.Strategy != schema.DDLStrategyNormal { - // Seeing that we intend to run an online-schema-change, we can skip the "big change" check. - continue - } - } } - tableName := ddl.Table.Name.String() + tableName := ddl.GetTable().Name.String() if rowCount, ok := tableWithCount[tableName]; ok { - if rowCount > 100000 && ddl.Action == sqlparser.AlterDDLAction { + if rowCount > 100000 && ddl.GetAction() == sqlparser.AlterDDLAction { return true, fmt.Errorf( "big schema change detected. Disable check with -allow_long_unavailability. ddl: %s alters a table with more than 100 thousand rows", sqlparser.String(ddl)) } @@ -218,19 +240,8 @@ func (exec *TabletExecutor) Execute(ctx context.Context, sqls []string) *Execute } }() - // We added the WITH_GHOST and WITH_PT hints to ALTER TABLE syntax, but these hints are - // obviously not accepted by MySQL. - // To run preflightSchemaChanges we must clean up such hints from the ALTER TABLE statement. - // Because our sqlparser does not do a complete parse of ALTER TABLE statements at this time, - // we resort to temporary regexp based parsing. - // TODO(shlomi): replace the below with sqlparser based reconstruction of the query, - // when sqlparser has a complete coverage of ALTER TABLE syntax - sqlsWithoutAlterTableHints := []string{} - for _, sql := range sqls { - sqlsWithoutAlterTableHints = append(sqlsWithoutAlterTableHints, schema.RemoveOnlineDDLHints(sql)) - } // Make sure the schema changes introduce a table definition change. - if err := exec.preflightSchemaChanges(ctx, sqlsWithoutAlterTableHints); err != nil { + if err := exec.preflightSchemaChanges(ctx, sqls); err != nil { execResult.ExecutorErr = err.Error() return &execResult } @@ -243,21 +254,19 @@ func (exec *TabletExecutor) Execute(ctx context.Context, sqls []string) *Execute execResult.ExecutorErr = err.Error() return &execResult } - strategy := schema.DDLStrategyNormal - options := "" + isOnlineDDL, strategy, options := exec.isOnlineSchemaDDL(nil) tableName := "" switch ddl := stat.(type) { - case *sqlparser.DDL: - if ddl.Action == sqlparser.AlterDDLAction { - if ddl.OnlineHint != nil { - strategy = ddl.OnlineHint.Strategy - options = ddl.OnlineHint.Options - } - } - tableName = ddl.Table.Name.String() + case sqlparser.DDLStatement: + tableName = ddl.GetTable().Name.String() + isOnlineDDL, strategy, options = exec.isOnlineSchemaDDL(ddl) + } + exec.wr.Logger().Infof("Received DDL request. strategy=%+v", strategy) + if isOnlineDDL { + exec.executeOnlineDDL(ctx, &execResult, sql, tableName, strategy, options) + } else { + exec.executeOnAllTablets(ctx, &execResult, sql) } - exec.wr.Logger().Infof("Received DDL request. strategy = %+v", strategy) - exec.executeOnAllTablets(ctx, &execResult, sql, tableName, strategy, options) if len(execResult.FailedShards) > 0 { break } @@ -265,30 +274,37 @@ func (exec *TabletExecutor) Execute(ctx context.Context, sqls []string) *Execute return &execResult } -func (exec *TabletExecutor) executeOnAllTablets( +// executeOnlineDDL submits an online DDL request; this runs on topo, not on tablets, and is a quick operation. +func (exec *TabletExecutor) executeOnlineDDL( ctx context.Context, execResult *ExecuteResult, sql string, - tableName string, strategy sqlparser.DDLStrategy, options string, + tableName string, strategy schema.DDLStrategy, options string, ) { - if strategy != schema.DDLStrategyNormal { - onlineDDL, err := schema.NewOnlineDDL(exec.keyspace, tableName, sql, strategy, options) - if err != nil { - execResult.ExecutorErr = err.Error() - return - } - conn, err := exec.wr.TopoServer().ConnForCell(ctx, topo.GlobalCell) - if err != nil { - execResult.ExecutorErr = fmt.Sprintf("online DDL ConnForCell error:%s", err.Error()) - return - } - err = onlineDDL.WriteTopo(ctx, conn, schema.MigrationRequestsPath()) - if err != nil { - execResult.ExecutorErr = err.Error() - } - exec.wr.Logger().Infof("UUID=%+v", onlineDDL.UUID) - exec.wr.Logger().Printf("%s\n", onlineDDL.UUID) + if strategy == schema.DDLStrategyNormal { + execResult.ExecutorErr = "Not an online DDL strategy" + return + } + onlineDDL, err := schema.NewOnlineDDL(exec.keyspace, tableName, sql, strategy, options) + if err != nil { + execResult.ExecutorErr = err.Error() return } + conn, err := exec.wr.TopoServer().ConnForCell(ctx, topo.GlobalCell) + if err != nil { + execResult.ExecutorErr = fmt.Sprintf("online DDL ConnForCell error:%s", err.Error()) + return + } + err = onlineDDL.WriteTopo(ctx, conn, schema.MigrationRequestsPath()) + if err != nil { + execResult.ExecutorErr = err.Error() + } + exec.wr.Logger().Infof("UUID=%+v", onlineDDL.UUID) + exec.wr.Logger().Printf("%s\n", onlineDDL.UUID) +} +// executeOnAllTablets runs a query on all tablets, synchronously. This can be a long running operation. +func (exec *TabletExecutor) executeOnAllTablets( + ctx context.Context, execResult *ExecuteResult, sql string, +) { var wg sync.WaitGroup numOfMasterTablets := len(exec.tablets) wg.Add(numOfMasterTablets) diff --git a/go/vt/schemamanager/tablet_executor_test.go b/go/vt/schemamanager/tablet_executor_test.go index 6928dbf30c1..f8e5fb4b354 100644 --- a/go/vt/schemamanager/tablet_executor_test.go +++ b/go/vt/schemamanager/tablet_executor_test.go @@ -27,8 +27,12 @@ import ( "vitess.io/vitess/go/vt/mysqlctl/tmutils" tabletmanagerdatapb "vitess.io/vitess/go/vt/proto/tabletmanagerdata" topodatapb "vitess.io/vitess/go/vt/proto/topodata" + "vitess.io/vitess/go/vt/schema" + "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/topo/memorytopo" "vitess.io/vitess/go/vt/wrangler" + + "github.com/stretchr/testify/assert" ) var ( @@ -216,3 +220,60 @@ func TestTabletExecutorExecute(t *testing.T) { t.Fatalf("execute should fail, call execute.Open first") } } + +func TestIsOnlineSchemaDDL(t *testing.T) { + tt := []struct { + query string + ddlStrategy string + isOnlineDDL bool + strategy schema.DDLStrategy + options string + }{ + { + query: "CREATE TABLE t(id int)", + isOnlineDDL: false, + }, + { + query: "CREATE TABLE t(id int)", + ddlStrategy: "gh-ost", + isOnlineDDL: false, + }, + { + query: "ALTER TABLE t ADD COLUMN i INT", + ddlStrategy: "", + isOnlineDDL: false, + }, + { + query: "ALTER TABLE t ADD COLUMN i INT", + ddlStrategy: "gh-ost", + isOnlineDDL: true, + strategy: schema.DDLStrategyGhost, + }, + { + query: "ALTER TABLE t ADD COLUMN i INT", + ddlStrategy: "gh-ost --max-load=Threads_running=100", + isOnlineDDL: true, + strategy: schema.DDLStrategyGhost, + options: "--max-load=Threads_running=100", + }, + } + + for _, ts := range tt { + e := &TabletExecutor{} + err := e.SetDDLStrategy(ts.ddlStrategy) + assert.NoError(t, err) + + stmt, err := sqlparser.Parse(ts.query) + assert.NoError(t, err) + + ddl, ok := stmt.(sqlparser.DDLStatement) + assert.True(t, ok) + + isOnlineDDL, strategy, options := e.isOnlineSchemaDDL(ddl) + assert.Equal(t, ts.isOnlineDDL, isOnlineDDL) + if isOnlineDDL { + assert.Equal(t, ts.strategy, strategy) + assert.Equal(t, ts.options, options) + } + } +} diff --git a/go/vt/sqlparser/analyzer.go b/go/vt/sqlparser/analyzer.go index 54dd0a1366e..2cbcb3126cd 100644 --- a/go/vt/sqlparser/analyzer.go +++ b/go/vt/sqlparser/analyzer.go @@ -74,7 +74,7 @@ func ASTToStatementType(stmt Statement) StatementType { return StmtSet case *Show: return StmtShow - case *DDL, *DBDDL: + case DDLStatement, DBDDLStatement: return StmtDDL case *Use: return StmtUse @@ -256,20 +256,12 @@ func IsDMLStatement(stmt Statement) bool { } //IsVschemaDDL returns true if the query is an Vschema alter ddl. -func IsVschemaDDL(ddl *DDL) bool { - switch ddl.Action { - case CreateVindexDDLAction, DropVindexDDLAction, AddVschemaTableDDLAction, DropVschemaTableDDLAction, AddColVindexDDLAction, DropColVindexDDLAction, AddSequenceDDLAction, AddAutoIncDDLAction: - return true - } - return false -} - -// IsOnlineSchemaDDL returns true if the query is an online schema change DDL -func IsOnlineSchemaDDL(ddl *DDL, sql string) bool { - switch ddl.Action { - case AlterDDLAction: - if ddl.OnlineHint != nil { - return ddl.OnlineHint.Strategy != "" +func IsVschemaDDL(ddl DDLStatement) bool { + switch ddlStatement := ddl.(type) { + case *DDL: + switch ddlStatement.Action { + case CreateVindexDDLAction, DropVindexDDLAction, AddVschemaTableDDLAction, DropVschemaTableDDLAction, AddColVindexDDLAction, DropColVindexDDLAction, AddSequenceDDLAction, AddAutoIncDDLAction: + return true } } return false diff --git a/go/vt/sqlparser/analyzer_test.go b/go/vt/sqlparser/analyzer_test.go index a448d7f22c0..9b665ef92dd 100644 --- a/go/vt/sqlparser/analyzer_test.go +++ b/go/vt/sqlparser/analyzer_test.go @@ -87,6 +87,7 @@ func TestPreview(t *testing.T) { {"/* leading comment no end select ...", StmtUnknown}, {"-- leading single line comment no end select ...", StmtUnknown}, + {"/*!40000 ALTER TABLE `t1` DISABLE KEYS */", StmtComment}, } for _, tcase := range testcases { if got := Preview(tcase.sql); got != tcase.want { diff --git a/go/vt/sqlparser/ast.go b/go/vt/sqlparser/ast.go index 32d8f044390..7aa02ba5d43 100644 --- a/go/vt/sqlparser/ast.go +++ b/go/vt/sqlparser/ast.go @@ -55,6 +55,32 @@ type ( SQLNode } + // DDLStatement represents any DDL Statement + DDLStatement interface { + iDDLStatement() + IsFullyParsed() bool + GetTable() TableName + GetAction() DDLAction + GetOptLike() *OptLike + GetTableSpec() *TableSpec + GetVindexSpec() *VindexSpec + GetFromTables() TableNames + GetToTables() TableNames + GetAutoIncSpec() *AutoIncSpec + GetVindexCols() []ColIdent + AffectedTables() TableNames + SetTable(qualifier string, name string) + Statement + } + + // DBDDLStatement represents any DBDDL Statement + DBDDLStatement interface { + iDBDDLStatement() + IsFullyParsed() bool + GetDatabaseName() string + Statement + } + // Select represents a SELECT statement. Select struct { Cache *bool // a reference here so it can be nil @@ -199,7 +225,7 @@ type ( // AccessMode is enum for the mode - ReadOnly or ReadWrite AccessMode int8 - // DBDDL represents a CREATE, DROP, or ALTER database statement. + // DBDDL represents a DROP, or ALTER database statement. DBDDL struct { Action DBDDLAction DBName string @@ -209,14 +235,32 @@ type ( Charset string } - // DDLStrategy suggests how an ALTER TABLE should run (e.g. "" for normal, "gh-ost" or "pt-osc") - DDLStrategy string + // CollateAndCharsetType is an enum for CollateAndCharset.Type + CollateAndCharsetType int8 + + // CollateAndCharset is a struct that stores Collation or Character Set value + CollateAndCharset struct { + Type CollateAndCharsetType + IsDefault bool + Value string + } - // OnlineDDLHint indicates strategy and options for running an online DDL - OnlineDDLHint struct { - Strategy DDLStrategy - Options string + // CreateDatabase represents a CREATE database statement. + CreateDatabase struct { + DBName string + IfNotExists bool + CreateOptions []CollateAndCharset + FullyParsed bool } + + // AlterDatabase represents a ALTER database statement. + AlterDatabase struct { + DBName string + UpdateDataDirectory bool + AlterOptions []CollateAndCharset + FullyParsed bool + } + // DBDDLAction is an enum for DBDDL Actions DBDDLAction int8 @@ -238,7 +282,6 @@ type ( TableSpec *TableSpec OptLike *OptLike PartitionSpec *PartitionSpec - OnlineHint *OnlineDDLHint // VindexSpec is set for CreateVindexDDLAction, DropVindexDDLAction, AddColVindexDDLAction, DropColVindexDDLAction. VindexSpec *VindexSpec @@ -250,6 +293,17 @@ type ( AutoIncSpec *AutoIncSpec } + // CreateIndex represents a CREATE INDEX query + CreateIndex struct { + Constraint string + Name ColIdent + IndexType string + Table TableName + Columns []*IndexColumn + Options []*IndexOption + FullyParsed bool + } + // DDLAction is an enum for DDL.Action DDLAction int8 @@ -343,6 +397,174 @@ func (*Select) iSelectStatement() {} func (*Union) iSelectStatement() {} func (*ParenSelect) iSelectStatement() {} func (*Load) iStatement() {} +func (*CreateIndex) iStatement() {} +func (*CreateDatabase) iStatement() {} +func (*AlterDatabase) iStatement() {} + +func (*DDL) iDDLStatement() {} +func (*CreateIndex) iDDLStatement() {} + +// IsFullyParsed implements the DDLStatement interface +func (*DDL) IsFullyParsed() bool { + return false +} + +// IsFullyParsed implements the DDLStatement interface +func (node *CreateIndex) IsFullyParsed() bool { + return node.FullyParsed +} + +// GetTable implements the DDLStatement interface +func (node *CreateIndex) GetTable() TableName { + return node.Table +} + +// GetTable implements the DDLStatement interface +func (node *DDL) GetTable() TableName { + return node.Table +} + +// GetAction implements the DDLStatement interface +func (node *CreateIndex) GetAction() DDLAction { + return AlterDDLAction +} + +// GetOptLike implements the DDLStatement interface +func (node *DDL) GetOptLike() *OptLike { + return node.OptLike +} + +// GetOptLike implements the DDLStatement interface +func (node *CreateIndex) GetOptLike() *OptLike { + return nil +} + +// GetTableSpec implements the DDLStatement interface +func (node *DDL) GetTableSpec() *TableSpec { + return node.TableSpec +} + +// GetTableSpec implements the DDLStatement interface +func (node *CreateIndex) GetTableSpec() *TableSpec { + return nil +} + +// GetVindexSpec implements the DDLStatement interface +func (node *DDL) GetVindexSpec() *VindexSpec { + return node.VindexSpec +} + +// GetVindexSpec implements the DDLStatement interface +func (node *CreateIndex) GetVindexSpec() *VindexSpec { + return nil +} + +// GetFromTables implements the DDLStatement interface +func (node *DDL) GetFromTables() TableNames { + return node.FromTables +} + +// GetFromTables implements the DDLStatement interface +func (node *CreateIndex) GetFromTables() TableNames { + return nil +} + +// GetToTables implements the DDLStatement interface +func (node *DDL) GetToTables() TableNames { + return node.ToTables +} + +// GetToTables implements the DDLStatement interface +func (node *CreateIndex) GetToTables() TableNames { + return nil +} + +// GetAutoIncSpec implements the DDLStatement interface +func (node *DDL) GetAutoIncSpec() *AutoIncSpec { + return node.AutoIncSpec +} + +// GetAutoIncSpec implements the DDLStatement interface +func (node *CreateIndex) GetAutoIncSpec() *AutoIncSpec { + return nil +} + +// GetVindexCols implements the DDLStatement interface +func (node *DDL) GetVindexCols() []ColIdent { + return node.VindexCols +} + +// GetVindexCols implements the DDLStatement interface +func (node *CreateIndex) GetVindexCols() []ColIdent { + return nil +} + +// GetAction implements the DDLStatement interface +func (node *DDL) GetAction() DDLAction { + return node.Action +} + +// AffectedTables returns the list table names affected by the DDLStatement. +func (node *DDL) AffectedTables() TableNames { + if node.Action == RenameDDLAction || node.Action == DropDDLAction { + list := make(TableNames, 0, len(node.FromTables)+len(node.ToTables)) + list = append(list, node.FromTables...) + list = append(list, node.ToTables...) + return list + } + return TableNames{node.Table} +} + +// AffectedTables implements DDLStatement. +func (node *CreateIndex) AffectedTables() TableNames { + return TableNames{node.Table} +} + +// SetTable implements DDLStatement. +func (node *CreateIndex) SetTable(qualifier string, name string) { + node.Table.Qualifier = NewTableIdent(qualifier) + node.Table.Name = NewTableIdent(name) +} + +// SetTable implements DDLStatement. +func (node *DDL) SetTable(qualifier string, name string) { + node.Table.Qualifier = NewTableIdent(qualifier) + node.Table.Name = NewTableIdent(name) +} + +func (*DBDDL) iDBDDLStatement() {} +func (*CreateDatabase) iDBDDLStatement() {} +func (*AlterDatabase) iDBDDLStatement() {} + +// IsFullyParsed implements the DBDDLStatement interface +func (node *DBDDL) IsFullyParsed() bool { + return false +} + +// IsFullyParsed implements the DBDDLStatement interface +func (node *CreateDatabase) IsFullyParsed() bool { + return node.FullyParsed +} + +// IsFullyParsed implements the DBDDLStatement interface +func (node *AlterDatabase) IsFullyParsed() bool { + return node.FullyParsed +} + +// GetDatabaseName implements the DBDDLStatement interface +func (node *DBDDL) GetDatabaseName() string { + return node.DBName +} + +// GetDatabaseName implements the DBDDLStatement interface +func (node *CreateDatabase) GetDatabaseName() string { + return node.DBName +} + +// GetDatabaseName implements the DBDDLStatement interface +func (node *AlterDatabase) GetDatabaseName() string { + return node.DBName +} // ParenSelect can actually not be a top level statement, // but we have to allow it because it's a requirement @@ -630,14 +852,19 @@ type ( Name, Qualifier TableIdent } - // Subquery represents a subquery. + // Subquery represents a subquery used as an value expression. Subquery struct { Select SelectStatement } + + // DerivedTable represents a subquery used as a table expression. + DerivedTable struct { + Select SelectStatement + } ) -func (TableName) iSimpleTableExpr() {} -func (*Subquery) iSimpleTableExpr() {} +func (TableName) iSimpleTableExpr() {} +func (*DerivedTable) iSimpleTableExpr() {} // TableNames is a list of TableName. type TableNames []TableName @@ -954,7 +1181,7 @@ type Order struct { Direction OrderDirection } -// OrderDirection is an enum for Order.Direction +// OrderDirection is an enum for the direction in which to order - asc or desc. type OrderDirection int8 // Limit represents a LIMIT clause. @@ -1345,13 +1572,16 @@ func (idx *IndexDefinition) Format(buf *TrackedBuffer) { if col.Length != nil { buf.astPrintf(idx, "(%v)", col.Length) } + if col.Direction == DescOrder { + buf.astPrintf(idx, " desc") + } } buf.astPrintf(idx, ")") for _, opt := range idx.Options { buf.astPrintf(idx, " %s", opt.Name) - if opt.Using != "" { - buf.astPrintf(idx, " %s", opt.Using) + if opt.String != "" { + buf.astPrintf(idx, " %s", opt.String) } else { buf.astPrintf(idx, " %v", opt.Value) } @@ -1828,6 +2058,11 @@ func (node *Subquery) Format(buf *TrackedBuffer) { buf.astPrintf(node, "(%v)", node.Select) } +// Format formats the node. +func (node *DerivedTable) Format(buf *TrackedBuffer) { + buf.astPrintf(node, "(%v)", node.Select) +} + // Format formats the node. func (node ListArg) Format(buf *TrackedBuffer) { buf.WriteArg(string(node)) @@ -2156,3 +2391,76 @@ func (node *SelectInto) Format(buf *TrackedBuffer) { } buf.astPrintf(node, "%s%s%s%s", node.FormatOption, node.ExportOption, node.Manifest, node.Overwrite) } + +// Format formats the node. +func (node *CreateIndex) Format(buf *TrackedBuffer) { + buf.WriteString("create") + if node.Constraint != "" { + buf.WriteString(" " + node.Constraint) + } + buf.astPrintf(node, " index %v", node.Name) + if node.IndexType != "" { + buf.WriteString(" using " + node.IndexType) + } + buf.astPrintf(node, " on %v (", node.Table) + for i, col := range node.Columns { + if i != 0 { + buf.astPrintf(node, ", %v", col.Column) + } else { + buf.astPrintf(node, "%v", col.Column) + } + if col.Length != nil { + buf.astPrintf(node, "(%v)", col.Length) + } + if col.Direction == DescOrder { + buf.WriteString(" desc") + } + } + buf.astPrintf(node, ")") + for _, opt := range node.Options { + buf.WriteString(" " + strings.ToLower(opt.Name)) + if opt.String != "" { + buf.WriteString(" " + opt.String) + } else { + buf.astPrintf(node, " %v", opt.Value) + } + } +} + +// Format formats the node. +func (node *CreateDatabase) Format(buf *TrackedBuffer) { + buf.WriteString("create database") + if node.IfNotExists { + buf.WriteString(" if not exists") + } + buf.astPrintf(node, " %s", node.DBName) + if node.CreateOptions != nil { + for _, createOption := range node.CreateOptions { + if createOption.IsDefault { + buf.WriteString(" default") + } + buf.WriteString(createOption.Type.ToString()) + buf.WriteString(" " + createOption.Value) + } + } +} + +// Format formats the node. +func (node *AlterDatabase) Format(buf *TrackedBuffer) { + buf.WriteString("alter database") + if node.DBName != "" { + buf.astPrintf(node, " %s", node.DBName) + } + if node.UpdateDataDirectory { + buf.WriteString(" upgrade data directory name") + } + if node.AlterOptions != nil { + for _, createOption := range node.AlterOptions { + if createOption.IsDefault { + buf.WriteString(" default") + } + buf.WriteString(createOption.Type.ToString()) + buf.WriteString(" " + createOption.Value) + } + } +} diff --git a/go/vt/sqlparser/ast_funcs.go b/go/vt/sqlparser/ast_funcs.go index a309894dca7..51b7762043e 100644 --- a/go/vt/sqlparser/ast_funcs.go +++ b/go/vt/sqlparser/ast_funcs.go @@ -75,8 +75,9 @@ func Append(buf *strings.Builder, node SQLNode) { // IndexColumn describes a column in an index definition with optional length type IndexColumn struct { - Column ColIdent - Length *Literal + Column ColIdent + Length *Literal + Direction OrderDirection } // LengthScaleOption is used for types that have an optional length @@ -86,11 +87,11 @@ type LengthScaleOption struct { Scale *Literal } -// IndexOption is used for trailing options for indexes: COMMENT, KEY_BLOCK_SIZE, USING +// IndexOption is used for trailing options for indexes: COMMENT, KEY_BLOCK_SIZE, USING, WITH PARSER type IndexOption struct { - Name string - Value *Literal - Using string + Name string + Value *Literal + String string } // ColumnKeyOption indicates whether or not the given column is defined as an @@ -147,17 +148,6 @@ const ( BitVal ) -// AffectedTables returns the list table names affected by the DDL. -func (node *DDL) AffectedTables() TableNames { - if node.Action == RenameDDLAction || node.Action == DropDDLAction { - list := make(TableNames, 0, len(node.FromTables)+len(node.ToTables)) - list = append(list, node.FromTables...) - list = append(list, node.ToTables...) - return list - } - return TableNames{node.Table} -} - // AddColumn appends the given column to the list in the spec func (ts *TableSpec) AddColumn(cd *ColumnDefinition) { ts.Columns = append(ts.Columns, cd) @@ -1138,6 +1128,7 @@ func (ty ExplainType) ToString() string { } } +// ToString returns the type as a string func (sel SelectIntoType) ToString() string { switch sel { case IntoOutfile: @@ -1151,6 +1142,18 @@ func (sel SelectIntoType) ToString() string { } } +// ToString returns the type as a string +func (node CollateAndCharsetType) ToString() string { + switch node { + case CharacterSetType: + return CharacterSetStr + case CollateType: + return CollateStr + default: + return "Unknown CollateAndCharsetType Type" + } +} + // AtCount represents the '@' count in ColIdent type AtCount int diff --git a/go/vt/sqlparser/ast_test.go b/go/vt/sqlparser/ast_test.go index d2de431d066..405df6c5b5b 100644 --- a/go/vt/sqlparser/ast_test.go +++ b/go/vt/sqlparser/ast_test.go @@ -177,7 +177,7 @@ func TestSetLimit(t *testing.T) { func TestDDL(t *testing.T) { testcases := []struct { query string - output *DDL + output DDLStatement affected []string }{{ query: "create table a", @@ -244,7 +244,7 @@ func TestDDL(t *testing.T) { for _, t := range tcase.affected { want = append(want, TableName{Name: NewTableIdent(t)}) } - if affected := got.(*DDL).AffectedTables(); !reflect.DeepEqual(affected, want) { + if affected := got.(DDLStatement).AffectedTables(); !reflect.DeepEqual(affected, want) { t.Errorf("Affected(%s): %v, want %v", tcase.query, affected, want) } } diff --git a/go/vt/sqlparser/constants.go b/go/vt/sqlparser/constants.go index 2b1223a9bbb..d3e31be595b 100644 --- a/go/vt/sqlparser/constants.go +++ b/go/vt/sqlparser/constants.go @@ -149,6 +149,9 @@ const ( NoOperatorStr = "" CharsetStr = "charset" + // CollateAndCharset.Type + CollateStr = " collate" + // MatchExpr.Option NoOptionStr = "" BooleanModeStr = " in boolean mode" @@ -378,3 +381,9 @@ const ( IntoOutfileS3 IntoDumpfile ) + +// Constant for Enum Type - CollateAndCharsetType +const ( + CollateType CollateAndCharsetType = iota + CharacterSetType +) diff --git a/go/vt/sqlparser/expression_rewriting.go b/go/vt/sqlparser/expression_rewriting.go index 7fc90d779d3..95e6f588adf 100644 --- a/go/vt/sqlparser/expression_rewriting.go +++ b/go/vt/sqlparser/expression_rewriting.go @@ -167,12 +167,7 @@ func (er *expressionRewriter) funcRewrite(cursor *Cursor, node *FuncExpr) { func (er *expressionRewriter) unnestSubQueries(cursor *Cursor, subquery *Subquery) { sel, isSimpleSelect := subquery.Select.(*Select) - // Today, subqueries and derived tables use the same AST struct, - // so we have to check what the parent is so we don't accidentally - // rewrite a FROM clause instead of an expression - _, isDerivedTable := cursor.Parent().(*AliasedTableExpr) - - if isDerivedTable || !isSimpleSelect { + if !isSimpleSelect { return } diff --git a/go/vt/sqlparser/normalizer.go b/go/vt/sqlparser/normalizer.go index 64f50dca138..ea5f7c3ee08 100644 --- a/go/vt/sqlparser/normalizer.go +++ b/go/vt/sqlparser/normalizer.go @@ -60,7 +60,7 @@ func newNormalizer(stmt Statement, bindVars map[string]*querypb.BindVariable, pr func (nz *normalizer) WalkStatement(cursor *Cursor) bool { switch node := cursor.Node().(type) { // no need to normalize the statement types - case *Set, *Show, *Begin, *Commit, *Rollback, *Savepoint, *SetTransaction, *DDL, *SRollback, *Release, *OtherAdmin, *OtherRead: + case *Set, *Show, *Begin, *Commit, *Rollback, *Savepoint, *SetTransaction, DDLStatement, *SRollback, *Release, *OtherAdmin, *OtherRead: return false case *Select: Rewrite(node, nz.WalkSelect, nil) diff --git a/go/vt/sqlparser/parse_table.go b/go/vt/sqlparser/parse_table.go new file mode 100644 index 00000000000..a8431aacc01 --- /dev/null +++ b/go/vt/sqlparser/parse_table.go @@ -0,0 +1,66 @@ +/* +Copyright 2020 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package sqlparser + +import ( + vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc" + "vitess.io/vitess/go/vt/vterrors" +) + +// ParseTable parses the input as a qualified table name. +// It handles all valid literal escaping. +func ParseTable(input string) (keyspace, table string, err error) { + tokenizer := NewStringTokenizer(input) + + // Start, want ID + token, value := tokenizer.Scan() + switch token { + case ID: + table = string(value) + default: + return "", "", vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "invalid table name: %s", input) + } + + // Seen first ID, want '.' or 0 + token, _ = tokenizer.Scan() + switch token { + case '.': + keyspace = table + case 0: + return keyspace, table, nil + default: + return "", "", vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "invalid table name: %s", input) + } + + // Seen '.', want ID + token, value = tokenizer.Scan() + switch token { + case ID: + table = string(value) + default: + return "", "", vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "invalid table name: %s", input) + } + + // Seen second ID, want 0 + token, _ = tokenizer.Scan() + switch token { + case 0: + return keyspace, table, nil + default: + return "", "", vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "invalid table name: %s", input) + } +} diff --git a/go/vt/sqlparser/parse_table_test.go b/go/vt/sqlparser/parse_table_test.go new file mode 100644 index 00000000000..09e7ea44177 --- /dev/null +++ b/go/vt/sqlparser/parse_table_test.go @@ -0,0 +1,69 @@ +/* +Copyright 2020 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package sqlparser + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestParseTable(t *testing.T) { + testcases := []struct { + input string + keyspace string + table string + err bool + }{{ + input: "t", + keyspace: "", + table: "t", + }, { + input: "k.t", + keyspace: "k", + table: "t", + }, { + input: "`k.k`.`t``.t`", + keyspace: "k.k", + table: "t`.t", + }, { + input: ".", + err: true, + }, { + input: "t,", + err: true, + }, { + input: "t,", + err: true, + }, { + input: "t..", + err: true, + }, { + input: "k.t.", + err: true, + }} + for _, tcase := range testcases { + keyspace, table, err := ParseTable(tcase.input) + assert.Equal(t, tcase.keyspace, keyspace) + assert.Equal(t, tcase.table, table) + if tcase.err { + assert.Error(t, err) + } else { + assert.NoError(t, err) + } + } +} diff --git a/go/vt/sqlparser/parse_test.go b/go/vt/sqlparser/parse_test.go index de0349d23c5..45277f9653d 100644 --- a/go/vt/sqlparser/parse_test.go +++ b/go/vt/sqlparser/parse_test.go @@ -32,8 +32,9 @@ import ( var ( validSQL = []struct { - input string - output string + input string + output string + partialDDL bool }{{ input: "select 1", output: "select 1 from dual", @@ -767,10 +768,10 @@ var ( output: "update (select id from foo) as subqalias set id = 4", }, { input: "update foo f, bar b set f.id = b.id where b.name = 'test'", - output: "update foo as f, bar as b set f.id = b.id where b.name = 'test'", + output: "update foo as f, bar as b set f.id = b.id where b.`name` = 'test'", }, { input: "update foo f join bar b on f.name = b.name set f.id = b.id where b.name = 'test'", - output: "update foo as f join bar as b on f.name = b.name set f.id = b.id where b.name = 'test'", + output: "update foo as f join bar as b on f.`name` = b.`name` set f.id = b.id where b.`name` = 'test'", }, { input: "update /* ignore */ ignore a set b = 3", }, { @@ -784,9 +785,11 @@ var ( }, { input: "delete /* limit */ from a limit b", }, { - input: "delete a from a join b on a.id = b.id where b.name = 'test'", + input: "delete a from a join b on a.id = b.id where b.name = 'test'", + output: "delete a from a join b on a.id = b.id where b.`name` = 'test'", }, { - input: "delete a, b from a, b where a.id = b.id and b.name = 'test'", + input: "delete a, b from a, b where a.id = b.id and b.name = 'test'", + output: "delete a, b from a, b where a.id = b.id and b.`name` = 'test'", }, { input: "delete /* simple */ ignore from a", }, { @@ -1040,29 +1043,30 @@ var ( input: "alter table a drop id", output: "alter table a", }, { - input: "alter database d default character set = charset", - output: "alter database d", + input: "alter database character set geostd8", + }, { + input: "alter database d character set geostd8", }, { - input: "alter database d character set = charset", - output: "alter database d", + input: "alter database d default collate 'utf8_bin'", }, { - input: "alter database d default collate = collation", - output: "alter database d", + input: "alter database default collate 'utf8_bin'", }, { - input: "alter database d collate = collation", - output: "alter database d", + input: "alter database d upgrade data directory name", }, { - input: "alter schema d default character set = charset", - output: "alter database d", + input: "alter database d collate = 'utf8_bin'", + output: "alter database d collate 'utf8_bin'", }, { - input: "alter schema d character set = charset", - output: "alter database d", + input: "alter schema d default character set = geostd8", + output: "alter database d default character set geostd8", }, { - input: "alter schema d default collate = collation", - output: "alter database d", + input: "alter schema d character set = geostd8", + output: "alter database d character set geostd8", }, { - input: "alter schema d collate = collation", - output: "alter database d", + input: "alter schema d default collate = 'utf8_bin'", + output: "alter database d default collate 'utf8_bin'", + }, { + input: "alter schema d collate = 'utf8_bin' character set = geostd8 character set = geostd8", + output: "alter database d collate 'utf8_bin' character set geostd8 character set geostd8", }, { input: "create table a", }, { @@ -1133,10 +1137,11 @@ var ( input: "alter vschema on a add vindex hash (id) using `hash`", output: "alter vschema on a add vindex hash (id) using hash", }, { - input: "alter vschema on user add vindex name_lookup_vdx (name) using lookup_hash with owner=user, table=name_user_idx, from=name, to=user_id", + input: "alter vschema on user add vindex name_lookup_vdx (name) using lookup_hash with owner=user, table=name_user_idx, from=name, to=user_id", + output: "alter vschema on user add vindex name_lookup_vdx (`name`) using lookup_hash with owner=user, table=name_user_idx, from=name, to=user_id", }, { input: "alter vschema on user2 add vindex name_lastname_lookup_vdx (name,lastname) using lookup with owner=`user`, table=`name_lastname_keyspace_id_map`, from=`name,lastname`, to=`keyspace_id`", - output: "alter vschema on user2 add vindex name_lastname_lookup_vdx (name, lastname) using lookup with owner=user, table=name_lastname_keyspace_id_map, from=name,lastname, to=keyspace_id", + output: "alter vschema on user2 add vindex name_lastname_lookup_vdx (`name`, lastname) using lookup with owner=user, table=name_lastname_keyspace_id_map, from=name,lastname, to=keyspace_id", }, { input: "alter vschema on a drop vindex hash", }, { @@ -1151,23 +1156,21 @@ var ( input: "alter vschema on a drop vindex `add`", output: "alter vschema on a drop vindex `add`", }, { - input: "create index a on b", - output: "alter table b", + input: "create index a on b (col1)", + }, { + input: "create unique index a on b (col1)", }, { - input: "create unique index a on b", - output: "alter table b", + input: "create unique index a using foo on b (col1 desc)", }, { - input: "create unique index a using foo on b", - output: "alter table b", + input: "create fulltext index a using foo on b (col1)", }, { - input: "create fulltext index a using foo on b", - output: "alter table b", + input: "create spatial index a using foo on b (col1)", }, { - input: "create spatial index a using foo on b", - output: "alter table b", + input: "create index a on b (col1) using btree key_block_size 12 with parser 'a' comment 'string' algorithm inplace lock none", }, { - input: "create fulltext index a using foo on b", - output: "alter table b", + input: "create index a on b ((col1 + col2), (col1*col2))", + output: "create index a on b ()", + partialDDL: true, }, { input: "create view a", output: "create table a", @@ -1604,13 +1607,17 @@ var ( }, { input: "select title from video as v where match(v.title, v.tag) against ('DEMO' in boolean mode)", }, { - input: "select name, group_concat(score) from t group by name", + input: "select name, group_concat(score) from t group by name", + output: "select `name`, group_concat(score) from t group by `name`", }, { - input: "select name, group_concat(distinct id, score order by id desc separator ':') from t group by name", + input: "select name, group_concat(distinct id, score order by id desc separator ':') from t group by name", + output: "select `name`, group_concat(distinct id, score order by id desc separator ':') from t group by `name`", }, { - input: "select name, group_concat(distinct id, score order by id desc separator ':' limit 1) from t group by name", + input: "select name, group_concat(distinct id, score order by id desc separator ':' limit 1) from t group by name", + output: "select `name`, group_concat(distinct id, score order by id desc separator ':' limit 1) from t group by `name`", }, { - input: "select name, group_concat(distinct id, score order by id desc separator ':' limit 10, 2) from t group by name", + input: "select name, group_concat(distinct id, score order by id desc separator ':' limit 10, 2) from t group by name", + output: "select `name`, group_concat(distinct id, score order by id desc separator ':' limit 10, 2) from t group by `name`", }, { input: "select * from t partition (p0)", }, { @@ -1657,6 +1664,14 @@ var ( }, { input: "create schema if not exists test_db", output: "create database if not exists test_db", + }, { + input: "create database test_db default collate 'utf8mb4_general_ci' collate utf8mb4_general_ci", + }, { + input: "create database test_db character set geostd8", + }, { + input: "create database test_db character set * unparsable", + output: "create database test_db", + partialDDL: true, }, { input: "drop database test_db", }, { @@ -1666,7 +1681,7 @@ var ( input: "drop database if exists test_db", }, { input: "delete a.*, b.* from tbl_a a, tbl_b b where a.id = b.id and b.name = 'test'", - output: "delete a, b from tbl_a as a, tbl_b as b where a.id = b.id and b.name = 'test'", + output: "delete a, b from tbl_a as a, tbl_b as b where a.id = b.id and b.`name` = 'test'", }, { input: "select distinctrow a.* from (select (1) from dual union all select 1 from dual) a", output: "select distinct a.* from (select 1 from dual union all select 1 from dual) as a", @@ -1769,6 +1784,18 @@ func TestValid(t *testing.T) { if tcase.output != out { t.Errorf("Parsing failed. \nExpected/Got:\n%s\n%s", tcase.output, out) } + + // CREATE INDEX currently only has 5.7 specifications. + // For mysql 8.0 syntax, the query is not entirely parsed. + // Add more structs as we go on adding full parsing support for DDL constructs for 5.7 syntax. + switch x := tree.(type) { + case *CreateIndex: + assert.Equal(t, !tcase.partialDDL, x.IsFullyParsed()) + case *CreateDatabase: + assert.Equal(t, !tcase.partialDDL, x.IsFullyParsed()) + case *AlterDatabase: + assert.Equal(t, !tcase.partialDDL, x.IsFullyParsed()) + } // This test just exercises the tree walking functionality. // There's no way automated way to verify that a node calls // all its children. But we can examine code coverage and @@ -1841,8 +1868,7 @@ func TestCaseSensitivity(t *testing.T) { input: "create table A (\n\t`B` int\n)", output: "create table A (\n\tB int\n)", }, { - input: "create index b on A", - output: "alter table A", + input: "create index b on A (col1 desc)", }, { input: "alter table A foo", output: "alter table A", @@ -2148,7 +2174,7 @@ func TestSelectInto(t *testing.T) { output string }{{ input: "select * from t order by name limit 100 into outfile s3 'out_file_name'", - output: "select * from t order by name asc limit 100 into outfile s3 'out_file_name'", + output: "select * from t order by `name` asc limit 100 into outfile s3 'out_file_name'", }, { input: "select * from t into dumpfile 'out_file_name'", }, { @@ -2156,7 +2182,8 @@ func TestSelectInto(t *testing.T) { }, { input: "select * from t into outfile s3 'out_file_name' character set binary format csv header fields terminated by 'term' optionally enclosed by 'c' escaped by 'e' lines starting by 'a' terminated by '\n' manifest on overwrite off", }, { - input: "select * from (select * from t union select * from t2) as t3 where t3.name in (select col from t4) into outfile s3 'out_file_name'", + input: "select * from (select * from t union select * from t2) as t3 where t3.name in (select col from t4) into outfile s3 'out_file_name'", + output: "select * from (select * from t union select * from t2) as t3 where t3.`name` in (select col from t4) into outfile s3 'out_file_name'", }, { // Invalid queries but these are parsed and errors caught in planbuilder input: "select * from t limit 100 into outfile s3 'out_file_name' union select * from t2", diff --git a/go/vt/sqlparser/rewriter.go b/go/vt/sqlparser/rewriter.go index 27b2f918fb3..1ee5fcd2367 100644 --- a/go/vt/sqlparser/rewriter.go +++ b/go/vt/sqlparser/rewriter.go @@ -168,6 +168,14 @@ func replaceConvertUsingExprExpr(newNode, parent SQLNode) { parent.(*ConvertUsingExpr).Expr = newNode.(Expr) } +func replaceCreateIndexName(newNode, parent SQLNode) { + parent.(*CreateIndex).Name = newNode.(ColIdent) +} + +func replaceCreateIndexTable(newNode, parent SQLNode) { + parent.(*CreateIndex).Table = newNode.(TableName) +} + func replaceCurTimeFuncExprFsp(newNode, parent SQLNode) { parent.(*CurTimeFuncExpr).Fsp = newNode.(Expr) } @@ -246,6 +254,10 @@ func replaceDeleteWhere(newNode, parent SQLNode) { parent.(*Delete).Where = newNode.(*Where) } +func replaceDerivedTableSelect(newNode, parent SQLNode) { + parent.(*DerivedTable).Select = newNode.(SelectStatement) +} + func replaceExistsExprSubquery(newNode, parent SQLNode) { parent.(*ExistsExpr).Subquery = newNode.(*Subquery) } @@ -934,6 +946,8 @@ func (a *application) apply(parent, node SQLNode, replacer replacerFunc) { a.apply(node, n.Hints, replaceAliasedTableExprHints) a.apply(node, n.Partitions, replaceAliasedTableExprPartitions) + case *AlterDatabase: + case *AndExpr: a.apply(node, n.Left, replaceAndExprLeft) a.apply(node, n.Right, replaceAndExprRight) @@ -1015,6 +1029,12 @@ func (a *application) apply(parent, node SQLNode, replacer replacerFunc) { case *ConvertUsingExpr: a.apply(node, n.Expr, replaceConvertUsingExprExpr) + case *CreateDatabase: + + case *CreateIndex: + a.apply(node, n.Name, replaceCreateIndexName) + a.apply(node, n.Table, replaceCreateIndexTable) + case *CurTimeFuncExpr: a.apply(node, n.Fsp, replaceCurTimeFuncExprFsp) a.apply(node, n.Name, replaceCurTimeFuncExprName) @@ -1048,6 +1068,9 @@ func (a *application) apply(parent, node SQLNode, replacer replacerFunc) { a.apply(node, n.Targets, replaceDeleteTargets) a.apply(node, n.Where, replaceDeleteWhere) + case *DerivedTable: + a.apply(node, n.Select, replaceDerivedTableSelect) + case *ExistsExpr: a.apply(node, n.Subquery, replaceExistsExprSubquery) diff --git a/go/vt/sqlparser/sql.go b/go/vt/sqlparser/sql.go index 12a0c8dbf34..05b55a689e6 100644 --- a/go/vt/sqlparser/sql.go +++ b/go/vt/sqlparser/sql.go @@ -15,8 +15,8 @@ func setAllowComments(yylex interface{}, allow bool) { yylex.(*Tokenizer).AllowComments = allow } -func setDDL(yylex interface{}, ddl *DDL) { - yylex.(*Tokenizer).partialDDL = ddl +func setDDL(yylex interface{}, node Statement) { + yylex.(*Tokenizer).partialDDL = node } func incNesting(yylex interface{}) bool { @@ -71,6 +71,7 @@ type yySymType struct { values Values valTuple ValTuple subquery *Subquery + derivedTable *DerivedTable whens []*When when *When orderBy OrderBy @@ -91,7 +92,6 @@ type yySymType struct { colKeyOpt ColumnKeyOption optVal Expr LengthScaleOption LengthScaleOption - OnlineDDLHint *OnlineDDLHint columnDefinition *ColumnDefinition indexDefinition *IndexDefinition indexInfo *IndexInfo @@ -121,6 +121,11 @@ type yySymType struct { orderDirection OrderDirection explainType ExplainType selectInto *SelectInto + createIndex *CreateIndex + createDatabase *CreateDatabase + alterDatabase *AlterDatabase + collateAndCharset CollateAndCharset + collateAndCharsets []CollateAndCharset } const LEX_ERROR = 57346 @@ -156,336 +161,346 @@ const UNLOCK = 57375 const KEYS = 57376 const DO = 57377 const DISTINCTROW = 57378 -const OUTFILE = 57379 -const S3 = 57380 -const DATA = 57381 -const LOAD = 57382 -const LINES = 57383 -const TERMINATED = 57384 -const ESCAPED = 57385 -const ENCLOSED = 57386 -const DUMPFILE = 57387 -const CSV = 57388 -const HEADER = 57389 -const MANIFEST = 57390 -const OVERWRITE = 57391 -const STARTING = 57392 -const OPTIONALLY = 57393 -const VALUES = 57394 -const LAST_INSERT_ID = 57395 -const NEXT = 57396 -const VALUE = 57397 -const SHARE = 57398 -const MODE = 57399 -const SQL_NO_CACHE = 57400 -const SQL_CACHE = 57401 -const SQL_CALC_FOUND_ROWS = 57402 -const JOIN = 57403 -const STRAIGHT_JOIN = 57404 -const LEFT = 57405 -const RIGHT = 57406 -const INNER = 57407 -const OUTER = 57408 -const CROSS = 57409 -const NATURAL = 57410 -const USE = 57411 -const FORCE = 57412 -const ON = 57413 -const USING = 57414 -const ID = 57415 -const AT_ID = 57416 -const AT_AT_ID = 57417 -const HEX = 57418 -const STRING = 57419 -const INTEGRAL = 57420 -const FLOAT = 57421 -const HEXNUM = 57422 -const VALUE_ARG = 57423 -const LIST_ARG = 57424 -const COMMENT = 57425 -const COMMENT_KEYWORD = 57426 -const BIT_LITERAL = 57427 -const NULL = 57428 -const TRUE = 57429 -const FALSE = 57430 -const OFF = 57431 -const OR = 57432 -const XOR = 57433 -const AND = 57434 -const NOT = 57435 -const BETWEEN = 57436 -const CASE = 57437 -const WHEN = 57438 -const THEN = 57439 -const ELSE = 57440 -const END = 57441 -const LE = 57442 -const GE = 57443 -const NE = 57444 -const NULL_SAFE_EQUAL = 57445 -const IS = 57446 -const LIKE = 57447 -const REGEXP = 57448 -const IN = 57449 -const SHIFT_LEFT = 57450 -const SHIFT_RIGHT = 57451 -const DIV = 57452 -const MOD = 57453 -const UNARY = 57454 -const COLLATE = 57455 -const BINARY = 57456 -const UNDERSCORE_BINARY = 57457 -const UNDERSCORE_UTF8MB4 = 57458 -const UNDERSCORE_UTF8 = 57459 -const UNDERSCORE_LATIN1 = 57460 -const INTERVAL = 57461 -const JSON_EXTRACT_OP = 57462 -const JSON_UNQUOTE_EXTRACT_OP = 57463 -const CREATE = 57464 -const ALTER = 57465 -const DROP = 57466 -const RENAME = 57467 -const ANALYZE = 57468 -const ADD = 57469 -const FLUSH = 57470 -const SCHEMA = 57471 -const TABLE = 57472 -const INDEX = 57473 -const VIEW = 57474 -const TO = 57475 -const IGNORE = 57476 -const IF = 57477 -const UNIQUE = 57478 -const PRIMARY = 57479 -const COLUMN = 57480 -const SPATIAL = 57481 -const FULLTEXT = 57482 -const KEY_BLOCK_SIZE = 57483 -const CHECK = 57484 -const INDEXES = 57485 -const ACTION = 57486 -const CASCADE = 57487 -const CONSTRAINT = 57488 -const FOREIGN = 57489 -const NO = 57490 -const REFERENCES = 57491 -const RESTRICT = 57492 -const SHOW = 57493 -const DESCRIBE = 57494 -const EXPLAIN = 57495 -const DATE = 57496 -const ESCAPE = 57497 -const REPAIR = 57498 -const OPTIMIZE = 57499 -const TRUNCATE = 57500 -const MAXVALUE = 57501 -const PARTITION = 57502 -const REORGANIZE = 57503 -const LESS = 57504 -const THAN = 57505 -const PROCEDURE = 57506 -const TRIGGER = 57507 -const VINDEX = 57508 -const VINDEXES = 57509 -const STATUS = 57510 -const VARIABLES = 57511 -const WARNINGS = 57512 -const SEQUENCE = 57513 -const BEGIN = 57514 -const START = 57515 -const TRANSACTION = 57516 -const COMMIT = 57517 -const ROLLBACK = 57518 -const SAVEPOINT = 57519 -const RELEASE = 57520 -const WORK = 57521 -const BIT = 57522 -const TINYINT = 57523 -const SMALLINT = 57524 -const MEDIUMINT = 57525 -const INT = 57526 -const INTEGER = 57527 -const BIGINT = 57528 -const INTNUM = 57529 -const REAL = 57530 -const DOUBLE = 57531 -const FLOAT_TYPE = 57532 -const DECIMAL = 57533 -const NUMERIC = 57534 -const TIME = 57535 -const TIMESTAMP = 57536 -const DATETIME = 57537 -const YEAR = 57538 -const CHAR = 57539 -const VARCHAR = 57540 -const BOOL = 57541 -const CHARACTER = 57542 -const VARBINARY = 57543 -const NCHAR = 57544 -const TEXT = 57545 -const TINYTEXT = 57546 -const MEDIUMTEXT = 57547 -const LONGTEXT = 57548 -const BLOB = 57549 -const TINYBLOB = 57550 -const MEDIUMBLOB = 57551 -const LONGBLOB = 57552 -const JSON = 57553 -const ENUM = 57554 -const GEOMETRY = 57555 -const POINT = 57556 -const LINESTRING = 57557 -const POLYGON = 57558 -const GEOMETRYCOLLECTION = 57559 -const MULTIPOINT = 57560 -const MULTILINESTRING = 57561 -const MULTIPOLYGON = 57562 -const NULLX = 57563 -const AUTO_INCREMENT = 57564 -const APPROXNUM = 57565 -const SIGNED = 57566 -const UNSIGNED = 57567 -const ZEROFILL = 57568 -const COLLATION = 57569 -const DATABASES = 57570 -const TABLES = 57571 -const VITESS_METADATA = 57572 -const VSCHEMA = 57573 -const FULL = 57574 -const PROCESSLIST = 57575 -const COLUMNS = 57576 -const FIELDS = 57577 -const ENGINES = 57578 -const PLUGINS = 57579 -const EXTENDED = 57580 -const KEYSPACES = 57581 -const VITESS_KEYSPACES = 57582 -const VITESS_SHARDS = 57583 -const VITESS_TABLETS = 57584 -const NAMES = 57585 -const CHARSET = 57586 -const GLOBAL = 57587 -const SESSION = 57588 -const ISOLATION = 57589 -const LEVEL = 57590 -const READ = 57591 -const WRITE = 57592 -const ONLY = 57593 -const REPEATABLE = 57594 -const COMMITTED = 57595 -const UNCOMMITTED = 57596 -const SERIALIZABLE = 57597 -const CURRENT_TIMESTAMP = 57598 -const DATABASE = 57599 -const CURRENT_DATE = 57600 -const CURRENT_TIME = 57601 -const LOCALTIME = 57602 -const LOCALTIMESTAMP = 57603 -const UTC_DATE = 57604 -const UTC_TIME = 57605 -const UTC_TIMESTAMP = 57606 -const REPLACE = 57607 -const CONVERT = 57608 -const CAST = 57609 -const SUBSTR = 57610 -const SUBSTRING = 57611 -const GROUP_CONCAT = 57612 -const SEPARATOR = 57613 -const TIMESTAMPADD = 57614 -const TIMESTAMPDIFF = 57615 -const MATCH = 57616 -const AGAINST = 57617 -const BOOLEAN = 57618 -const LANGUAGE = 57619 -const WITH = 57620 -const QUERY = 57621 -const EXPANSION = 57622 -const UNUSED = 57623 -const ARRAY = 57624 -const CUME_DIST = 57625 -const DESCRIPTION = 57626 -const DENSE_RANK = 57627 -const EMPTY = 57628 -const EXCEPT = 57629 -const FIRST_VALUE = 57630 -const GROUPING = 57631 -const GROUPS = 57632 -const JSON_TABLE = 57633 -const LAG = 57634 -const LAST_VALUE = 57635 -const LATERAL = 57636 -const LEAD = 57637 -const MEMBER = 57638 -const NTH_VALUE = 57639 -const NTILE = 57640 -const OF = 57641 -const OVER = 57642 -const PERCENT_RANK = 57643 -const RANK = 57644 -const RECURSIVE = 57645 -const ROW_NUMBER = 57646 -const SYSTEM = 57647 -const WINDOW = 57648 -const ACTIVE = 57649 -const ADMIN = 57650 -const BUCKETS = 57651 -const CLONE = 57652 -const COMPONENT = 57653 -const DEFINITION = 57654 -const ENFORCED = 57655 -const EXCLUDE = 57656 -const FOLLOWING = 57657 -const GEOMCOLLECTION = 57658 -const GET_MASTER_PUBLIC_KEY = 57659 -const HISTOGRAM = 57660 -const HISTORY = 57661 -const INACTIVE = 57662 -const INVISIBLE = 57663 -const LOCKED = 57664 -const MASTER_COMPRESSION_ALGORITHMS = 57665 -const MASTER_PUBLIC_KEY_PATH = 57666 -const MASTER_TLS_CIPHERSUITES = 57667 -const MASTER_ZSTD_COMPRESSION_LEVEL = 57668 -const NESTED = 57669 -const NETWORK_NAMESPACE = 57670 -const NOWAIT = 57671 -const NULLS = 57672 -const OJ = 57673 -const OLD = 57674 -const OPTIONAL = 57675 -const ORDINALITY = 57676 -const ORGANIZATION = 57677 -const OTHERS = 57678 -const PATH = 57679 -const PERSIST = 57680 -const PERSIST_ONLY = 57681 -const PRECEDING = 57682 -const PRIVILEGE_CHECKS_USER = 57683 -const PROCESS = 57684 -const RANDOM = 57685 -const REFERENCE = 57686 -const REQUIRE_ROW_FORMAT = 57687 -const RESOURCE = 57688 -const RESPECT = 57689 -const RESTART = 57690 -const RETAIN = 57691 -const REUSE = 57692 -const ROLE = 57693 -const SECONDARY = 57694 -const SECONDARY_ENGINE = 57695 -const SECONDARY_LOAD = 57696 -const SECONDARY_UNLOAD = 57697 -const SKIP = 57698 -const SRID = 57699 -const THREAD_PRIORITY = 57700 -const TIES = 57701 -const UNBOUNDED = 57702 -const VCPU = 57703 -const VISIBLE = 57704 -const FORMAT = 57705 -const TREE = 57706 -const VITESS = 57707 -const TRADITIONAL = 57708 +const PARSER = 57379 +const OUTFILE = 57380 +const S3 = 57381 +const DATA = 57382 +const LOAD = 57383 +const LINES = 57384 +const TERMINATED = 57385 +const ESCAPED = 57386 +const ENCLOSED = 57387 +const DUMPFILE = 57388 +const CSV = 57389 +const HEADER = 57390 +const MANIFEST = 57391 +const OVERWRITE = 57392 +const STARTING = 57393 +const OPTIONALLY = 57394 +const VALUES = 57395 +const LAST_INSERT_ID = 57396 +const NEXT = 57397 +const VALUE = 57398 +const SHARE = 57399 +const MODE = 57400 +const SQL_NO_CACHE = 57401 +const SQL_CACHE = 57402 +const SQL_CALC_FOUND_ROWS = 57403 +const JOIN = 57404 +const STRAIGHT_JOIN = 57405 +const LEFT = 57406 +const RIGHT = 57407 +const INNER = 57408 +const OUTER = 57409 +const CROSS = 57410 +const NATURAL = 57411 +const USE = 57412 +const FORCE = 57413 +const ON = 57414 +const USING = 57415 +const INPLACE = 57416 +const COPY = 57417 +const ALGORITHM = 57418 +const NONE = 57419 +const SHARED = 57420 +const EXCLUSIVE = 57421 +const ID = 57422 +const AT_ID = 57423 +const AT_AT_ID = 57424 +const HEX = 57425 +const STRING = 57426 +const INTEGRAL = 57427 +const FLOAT = 57428 +const HEXNUM = 57429 +const VALUE_ARG = 57430 +const LIST_ARG = 57431 +const COMMENT = 57432 +const COMMENT_KEYWORD = 57433 +const BIT_LITERAL = 57434 +const NULL = 57435 +const TRUE = 57436 +const FALSE = 57437 +const OFF = 57438 +const OR = 57439 +const XOR = 57440 +const AND = 57441 +const NOT = 57442 +const BETWEEN = 57443 +const CASE = 57444 +const WHEN = 57445 +const THEN = 57446 +const ELSE = 57447 +const END = 57448 +const LE = 57449 +const GE = 57450 +const NE = 57451 +const NULL_SAFE_EQUAL = 57452 +const IS = 57453 +const LIKE = 57454 +const REGEXP = 57455 +const IN = 57456 +const SHIFT_LEFT = 57457 +const SHIFT_RIGHT = 57458 +const DIV = 57459 +const MOD = 57460 +const UNARY = 57461 +const COLLATE = 57462 +const BINARY = 57463 +const UNDERSCORE_BINARY = 57464 +const UNDERSCORE_UTF8MB4 = 57465 +const UNDERSCORE_UTF8 = 57466 +const UNDERSCORE_LATIN1 = 57467 +const INTERVAL = 57468 +const JSON_EXTRACT_OP = 57469 +const JSON_UNQUOTE_EXTRACT_OP = 57470 +const CREATE = 57471 +const ALTER = 57472 +const DROP = 57473 +const RENAME = 57474 +const ANALYZE = 57475 +const ADD = 57476 +const FLUSH = 57477 +const SCHEMA = 57478 +const TABLE = 57479 +const INDEX = 57480 +const VIEW = 57481 +const TO = 57482 +const IGNORE = 57483 +const IF = 57484 +const UNIQUE = 57485 +const PRIMARY = 57486 +const COLUMN = 57487 +const SPATIAL = 57488 +const FULLTEXT = 57489 +const KEY_BLOCK_SIZE = 57490 +const CHECK = 57491 +const INDEXES = 57492 +const ACTION = 57493 +const CASCADE = 57494 +const CONSTRAINT = 57495 +const FOREIGN = 57496 +const NO = 57497 +const REFERENCES = 57498 +const RESTRICT = 57499 +const SHOW = 57500 +const DESCRIBE = 57501 +const EXPLAIN = 57502 +const DATE = 57503 +const ESCAPE = 57504 +const REPAIR = 57505 +const OPTIMIZE = 57506 +const TRUNCATE = 57507 +const MAXVALUE = 57508 +const PARTITION = 57509 +const REORGANIZE = 57510 +const LESS = 57511 +const THAN = 57512 +const PROCEDURE = 57513 +const TRIGGER = 57514 +const VINDEX = 57515 +const VINDEXES = 57516 +const DIRECTORY = 57517 +const NAME = 57518 +const UPGRADE = 57519 +const STATUS = 57520 +const VARIABLES = 57521 +const WARNINGS = 57522 +const SEQUENCE = 57523 +const BEGIN = 57524 +const START = 57525 +const TRANSACTION = 57526 +const COMMIT = 57527 +const ROLLBACK = 57528 +const SAVEPOINT = 57529 +const RELEASE = 57530 +const WORK = 57531 +const BIT = 57532 +const TINYINT = 57533 +const SMALLINT = 57534 +const MEDIUMINT = 57535 +const INT = 57536 +const INTEGER = 57537 +const BIGINT = 57538 +const INTNUM = 57539 +const REAL = 57540 +const DOUBLE = 57541 +const FLOAT_TYPE = 57542 +const DECIMAL = 57543 +const NUMERIC = 57544 +const TIME = 57545 +const TIMESTAMP = 57546 +const DATETIME = 57547 +const YEAR = 57548 +const CHAR = 57549 +const VARCHAR = 57550 +const BOOL = 57551 +const CHARACTER = 57552 +const VARBINARY = 57553 +const NCHAR = 57554 +const TEXT = 57555 +const TINYTEXT = 57556 +const MEDIUMTEXT = 57557 +const LONGTEXT = 57558 +const BLOB = 57559 +const TINYBLOB = 57560 +const MEDIUMBLOB = 57561 +const LONGBLOB = 57562 +const JSON = 57563 +const ENUM = 57564 +const GEOMETRY = 57565 +const POINT = 57566 +const LINESTRING = 57567 +const POLYGON = 57568 +const GEOMETRYCOLLECTION = 57569 +const MULTIPOINT = 57570 +const MULTILINESTRING = 57571 +const MULTIPOLYGON = 57572 +const NULLX = 57573 +const AUTO_INCREMENT = 57574 +const APPROXNUM = 57575 +const SIGNED = 57576 +const UNSIGNED = 57577 +const ZEROFILL = 57578 +const COLLATION = 57579 +const DATABASES = 57580 +const TABLES = 57581 +const VITESS_METADATA = 57582 +const VSCHEMA = 57583 +const FULL = 57584 +const PROCESSLIST = 57585 +const COLUMNS = 57586 +const FIELDS = 57587 +const ENGINES = 57588 +const PLUGINS = 57589 +const EXTENDED = 57590 +const KEYSPACES = 57591 +const VITESS_KEYSPACES = 57592 +const VITESS_SHARDS = 57593 +const VITESS_TABLETS = 57594 +const NAMES = 57595 +const CHARSET = 57596 +const GLOBAL = 57597 +const SESSION = 57598 +const ISOLATION = 57599 +const LEVEL = 57600 +const READ = 57601 +const WRITE = 57602 +const ONLY = 57603 +const REPEATABLE = 57604 +const COMMITTED = 57605 +const UNCOMMITTED = 57606 +const SERIALIZABLE = 57607 +const CURRENT_TIMESTAMP = 57608 +const DATABASE = 57609 +const CURRENT_DATE = 57610 +const CURRENT_TIME = 57611 +const LOCALTIME = 57612 +const LOCALTIMESTAMP = 57613 +const UTC_DATE = 57614 +const UTC_TIME = 57615 +const UTC_TIMESTAMP = 57616 +const REPLACE = 57617 +const CONVERT = 57618 +const CAST = 57619 +const SUBSTR = 57620 +const SUBSTRING = 57621 +const GROUP_CONCAT = 57622 +const SEPARATOR = 57623 +const TIMESTAMPADD = 57624 +const TIMESTAMPDIFF = 57625 +const MATCH = 57626 +const AGAINST = 57627 +const BOOLEAN = 57628 +const LANGUAGE = 57629 +const WITH = 57630 +const QUERY = 57631 +const EXPANSION = 57632 +const UNUSED = 57633 +const ARRAY = 57634 +const CUME_DIST = 57635 +const DESCRIPTION = 57636 +const DENSE_RANK = 57637 +const EMPTY = 57638 +const EXCEPT = 57639 +const FIRST_VALUE = 57640 +const GROUPING = 57641 +const GROUPS = 57642 +const JSON_TABLE = 57643 +const LAG = 57644 +const LAST_VALUE = 57645 +const LATERAL = 57646 +const LEAD = 57647 +const MEMBER = 57648 +const NTH_VALUE = 57649 +const NTILE = 57650 +const OF = 57651 +const OVER = 57652 +const PERCENT_RANK = 57653 +const RANK = 57654 +const RECURSIVE = 57655 +const ROW_NUMBER = 57656 +const SYSTEM = 57657 +const WINDOW = 57658 +const ACTIVE = 57659 +const ADMIN = 57660 +const BUCKETS = 57661 +const CLONE = 57662 +const COMPONENT = 57663 +const DEFINITION = 57664 +const ENFORCED = 57665 +const EXCLUDE = 57666 +const FOLLOWING = 57667 +const GEOMCOLLECTION = 57668 +const GET_MASTER_PUBLIC_KEY = 57669 +const HISTOGRAM = 57670 +const HISTORY = 57671 +const INACTIVE = 57672 +const INVISIBLE = 57673 +const LOCKED = 57674 +const MASTER_COMPRESSION_ALGORITHMS = 57675 +const MASTER_PUBLIC_KEY_PATH = 57676 +const MASTER_TLS_CIPHERSUITES = 57677 +const MASTER_ZSTD_COMPRESSION_LEVEL = 57678 +const NESTED = 57679 +const NETWORK_NAMESPACE = 57680 +const NOWAIT = 57681 +const NULLS = 57682 +const OJ = 57683 +const OLD = 57684 +const OPTIONAL = 57685 +const ORDINALITY = 57686 +const ORGANIZATION = 57687 +const OTHERS = 57688 +const PATH = 57689 +const PERSIST = 57690 +const PERSIST_ONLY = 57691 +const PRECEDING = 57692 +const PRIVILEGE_CHECKS_USER = 57693 +const PROCESS = 57694 +const RANDOM = 57695 +const REFERENCE = 57696 +const REQUIRE_ROW_FORMAT = 57697 +const RESOURCE = 57698 +const RESPECT = 57699 +const RESTART = 57700 +const RETAIN = 57701 +const REUSE = 57702 +const ROLE = 57703 +const SECONDARY = 57704 +const SECONDARY_ENGINE = 57705 +const SECONDARY_LOAD = 57706 +const SECONDARY_UNLOAD = 57707 +const SKIP = 57708 +const SRID = 57709 +const THREAD_PRIORITY = 57710 +const TIES = 57711 +const UNBOUNDED = 57712 +const VCPU = 57713 +const VISIBLE = 57714 +const FORMAT = 57715 +const TREE = 57716 +const VITESS = 57717 +const TRADITIONAL = 57718 var yyToknames = [...]string{ "$end", @@ -524,6 +539,7 @@ var yyToknames = [...]string{ "KEYS", "DO", "DISTINCTROW", + "PARSER", "OUTFILE", "S3", "DATA", @@ -560,6 +576,12 @@ var yyToknames = [...]string{ "FORCE", "ON", "USING", + "INPLACE", + "COPY", + "ALGORITHM", + "NONE", + "SHARED", + "EXCLUSIVE", "'('", "','", "')'", @@ -672,6 +694,9 @@ var yyToknames = [...]string{ "TRIGGER", "VINDEX", "VINDEXES", + "DIRECTORY", + "NAME", + "UPGRADE", "STATUS", "VARIABLES", "WARNINGS", @@ -884,2046 +909,2048 @@ var yyExca = [...]int{ -1, 1, 1, -1, -2, 0, - -1, 45, - 34, 324, - 148, 324, - 160, 324, - 185, 338, - 186, 338, - -2, 326, - -1, 50, - 150, 348, + -1, 41, + 136, 107, + 227, 107, + -2, 101, + -1, 48, + 34, 344, + 155, 344, + 167, 344, + 195, 358, + 196, 358, -2, 346, - -1, 74, - 54, 384, - -2, 392, - -1, 416, - 136, 749, - -2, 745, - -1, 417, - 136, 750, - -2, 746, - -1, 432, - 54, 385, - -2, 397, - -1, 433, - 54, 386, - -2, 398, - -1, 453, - 104, 1017, - -2, 76, + -1, 53, + 157, 368, + -2, 366, + -1, 77, + 55, 404, + -2, 412, + -1, 101, + 136, 107, + 227, 107, + -2, 102, + -1, 438, + 143, 779, + -2, 775, + -1, 439, + 143, 780, + -2, 776, -1, 454, - 104, 925, - -2, 77, - -1, 459, - 104, 887, - -2, 708, - -1, 461, - 104, 961, - -2, 710, - -1, 972, - 136, 752, - -2, 748, - -1, 1059, - 72, 58, - 74, 58, - -2, 62, - -1, 1424, - 5, 636, - 18, 636, - 20, 636, - 32, 636, - 75, 636, - -2, 423, - -1, 1623, - 44, 679, - -2, 677, + 55, 405, + -2, 417, + -1, 455, + 55, 406, + -2, 418, + -1, 475, + 111, 1055, + -2, 78, + -1, 476, + 111, 959, + -2, 79, + -1, 481, + 111, 918, + -2, 740, + -1, 483, + 111, 997, + -2, 742, + -1, 632, + 136, 107, + 227, 107, + -2, 270, + -1, 1018, + 143, 782, + -2, 778, + -1, 1105, + 73, 60, + 81, 60, + -2, 64, + -1, 1483, + 5, 656, + 18, 656, + 20, 656, + 32, 656, + 82, 656, + -2, 443, + -1, 1682, + 45, 711, + -2, 709, } const yyPrivate = 57344 -const yyLast = 19650 +const yyLast = 19518 var yyAct = [...]int{ - 416, 1719, 1709, 1471, 997, 1346, 1645, 1566, 1535, 1623, - 360, 1677, 1245, 1081, 1588, 1549, 639, 1265, 375, 1053, - 1400, 1440, 1403, 620, 1077, 73, 3, 1246, 1296, 1404, - 766, 1080, 1127, 719, 588, 1112, 1090, 389, 1410, 1232, - 94, 1416, 1365, 1050, 306, 893, 329, 306, 1313, 912, - 959, 458, 94, 966, 306, 1181, 1323, 637, 804, 797, - 71, 1095, 585, 1032, 792, 1055, 1039, 759, 764, 1106, - 425, 434, 362, 992, 787, 936, 769, 29, 428, 1123, - 786, 1061, 94, 584, 803, 94, 306, 419, 306, 346, - 794, 776, 801, 351, 69, 629, 358, 907, 455, 74, - 922, 68, 1620, 1464, 1545, 1568, 609, 1712, 304, 8, - 7, 732, 6, 1674, 1707, 1653, 294, 1700, 342, 292, - 733, 1472, 1673, 1652, 1382, 1501, 593, 1434, 302, 298, - 299, 300, 76, 77, 78, 79, 80, 81, 1071, 31, - 32, 33, 62, 35, 36, 347, 1304, 420, 350, 805, - 590, 806, 592, 440, 444, 1149, 349, 31, 652, 66, - 62, 35, 36, 348, 37, 56, 57, 1105, 59, 1148, - 1435, 1436, 1348, 60, 452, 1072, 1073, 1614, 681, 680, - 690, 691, 683, 684, 685, 686, 687, 688, 689, 682, - 1538, 401, 692, 407, 408, 405, 406, 404, 403, 402, - 645, 646, 46, 1655, 1113, 647, 61, 409, 410, 648, - 645, 646, 1492, 1490, 339, 96, 97, 98, 295, 1282, - 651, 921, 1281, 341, 61, 1283, 1147, 337, 1349, 96, - 97, 98, 640, 641, 650, 969, 881, 642, 1706, 1350, - 878, 1699, 1646, 1345, 293, 1033, 880, 1638, 1723, 635, - 1131, 1727, 1131, 923, 924, 925, 301, 1443, 610, 1131, - 96, 97, 98, 587, 1597, 296, 595, 1266, 1268, 1589, - 446, 1351, 39, 40, 42, 41, 44, 882, 58, 1144, - 1141, 1142, 879, 1140, 1591, 886, 655, 1099, 598, 869, - 1427, 1342, 1426, 306, 600, 601, 1425, 1344, 306, 309, - 611, 45, 65, 64, 306, 297, 54, 55, 43, 1099, - 306, 618, 1366, 591, 624, 1161, 1151, 1154, 1160, 1200, - 1078, 94, 47, 48, 1627, 49, 50, 51, 52, 1517, - 94, 626, 605, 628, 96, 97, 98, 1463, 1197, 704, - 705, 1433, 94, 94, 1237, 1210, 1189, 1067, 1651, 1267, - 1333, 692, 653, 1368, 780, 1590, 1146, 599, 1615, 717, - 616, 1278, 608, 634, 682, 625, 627, 692, 615, 661, - 1113, 837, 622, 1011, 617, 636, 630, 1656, 1145, 1721, - 672, 1636, 1722, 1606, 1720, 913, 908, 654, 1598, 1596, - 1370, 1414, 1374, 84, 1369, 807, 1367, 1329, 1330, 1331, - 602, 1372, 603, 665, 1384, 604, 1098, 612, 613, 614, - 1371, 631, 632, 993, 871, 63, 1343, 1641, 1341, 96, - 97, 98, 1150, 1373, 1375, 993, 943, 1207, 1098, 643, - 702, 1728, 85, 63, 1302, 1016, 1017, 1152, 666, 667, - 941, 942, 940, 94, 704, 705, 306, 757, 306, 306, - 756, 94, 1102, 664, 662, 773, 663, 94, 623, 1103, - 1195, 1665, 1194, 704, 705, 1544, 1543, 455, 720, 1332, - 825, 621, 1704, 1455, 1337, 1334, 1325, 1335, 1328, 1317, - 1324, 670, 671, 669, 1326, 1327, 669, 914, 909, 61, - 1729, 785, 685, 686, 687, 688, 689, 682, 1336, 672, - 692, 939, 672, 670, 671, 669, 770, 1701, 755, 1693, - 784, 838, 802, 796, 735, 737, 739, 741, 743, 745, - 746, 672, 758, 736, 738, 1316, 742, 744, 1702, 747, - 1694, 1174, 1175, 1176, 1305, 1703, 1390, 851, 854, 855, - 856, 857, 858, 859, 594, 860, 861, 862, 863, 864, - 839, 840, 841, 842, 823, 824, 852, 1695, 826, 1685, - 827, 828, 829, 830, 831, 832, 833, 834, 835, 836, - 843, 844, 845, 846, 847, 848, 849, 850, 1391, 1013, - 931, 933, 934, 1667, 306, 445, 1637, 932, 865, 670, - 671, 669, 867, 94, 450, 870, 1562, 872, 306, 306, - 94, 94, 94, 670, 671, 669, 306, 672, 1196, 1541, - 306, 1386, 1505, 306, 891, 892, 429, 306, 1392, 94, - 1318, 672, 1314, 906, 94, 94, 94, 306, 94, 94, - 671, 669, 898, 853, 1012, 596, 597, 884, 670, 671, - 669, 94, 94, 897, 96, 97, 98, 672, 815, 606, - 868, 1594, 1705, 670, 671, 669, 672, 875, 876, 877, - 1063, 1413, 873, 874, 1603, 447, 448, 768, 895, 1602, - 883, 672, 1669, 429, 796, 70, 896, 890, 670, 671, - 669, 900, 901, 902, 1451, 904, 905, 31, 96, 97, - 98, 903, 961, 960, 916, 1272, 672, 1062, 910, 911, - 887, 1100, 962, 690, 691, 683, 684, 685, 686, 687, - 688, 689, 682, 937, 1512, 692, 94, 96, 97, 98, - 1064, 1285, 1066, 974, 975, 683, 684, 685, 686, 687, - 688, 689, 682, 1573, 970, 692, 981, 984, 1594, 1649, - 668, 915, 994, 1594, 429, 429, 918, 1063, 938, 94, - 94, 976, 1594, 1628, 61, 378, 377, 380, 381, 382, - 383, 1025, 1007, 971, 379, 384, 1594, 1593, 94, 972, - 1533, 1532, 1519, 429, 31, 306, 1515, 429, 94, 1461, - 1460, 720, 306, 1233, 306, 1457, 1458, 1457, 1456, 1024, - 429, 1035, 306, 306, 306, 1036, 429, 970, 1233, 1240, - 94, 963, 964, 94, 72, 1002, 1003, 1064, 1605, 1062, - 668, 429, 1459, 973, 94, 94, 455, 1051, 1036, 455, - 1241, 814, 813, 1024, 1286, 1401, 1030, 1006, 1413, 1070, - 1082, 1213, 972, 1212, 1036, 422, 1024, 1018, 1062, 1027, - 1014, 61, 1026, 885, 1036, 799, 1031, 61, 1034, 1097, - 1041, 1044, 1045, 1046, 1042, 31, 1043, 1047, 1059, 1413, - 1417, 1418, 1024, 1686, 1114, 1115, 1116, 1551, 1107, 1028, - 306, 94, 1524, 94, 1128, 1153, 1447, 1065, 866, 306, - 306, 306, 306, 306, 1060, 1069, 306, 306, 1417, 1418, - 306, 94, 1068, 1108, 1109, 1110, 1111, 1129, 1085, 1290, - 1130, 1124, 61, 1118, 1117, 1347, 1552, 1134, 306, 1119, - 1120, 1121, 1122, 1714, 306, 306, 306, 1710, 1449, 1420, - 306, 94, 61, 1401, 1319, 919, 889, 1257, 1136, 1423, - 1138, 1422, 1258, 1255, 1135, 1254, 1167, 1253, 1256, 435, - 1171, 1125, 1126, 1155, 1156, 1157, 1158, 1159, 1165, 1690, - 1162, 1163, 1672, 436, 1164, 1393, 1222, 977, 978, 1688, - 767, 983, 986, 987, 1516, 1231, 1259, 1184, 1045, 1046, - 1230, 1185, 1166, 1661, 1658, 771, 772, 438, 937, 437, - 1170, 1692, 1192, 1193, 1172, 1676, 1001, 1678, 1199, 1004, - 1005, 1202, 1203, 1684, 1041, 1044, 1045, 1046, 1042, 1209, - 1043, 1047, 1683, 1211, 1220, 1624, 1214, 1215, 1216, 1217, - 1218, 1622, 1221, 938, 418, 989, 1177, 1309, 760, 812, - 619, 1301, 1697, 1643, 1642, 1571, 306, 1547, 1299, 990, - 761, 1292, 1510, 1009, 1137, 888, 1049, 306, 306, 306, - 306, 306, 423, 424, 1229, 426, 1247, 1191, 1696, 306, - 1681, 420, 1228, 306, 1662, 1262, 1263, 306, 1242, 1509, - 427, 1190, 306, 306, 417, 1206, 306, 306, 306, 1235, - 72, 1238, 1508, 1396, 1219, 1233, 649, 1201, 1264, 1284, - 1198, 94, 781, 1225, 1716, 1715, 1226, 774, 1716, 1625, - 1291, 1539, 1010, 422, 1287, 1297, 1297, 1082, 1236, 70, - 75, 1234, 67, 1, 95, 1273, 328, 1708, 307, 1275, - 1473, 307, 1249, 1250, 1260, 1252, 95, 1248, 307, 895, - 1251, 1548, 1270, 1271, 1298, 1143, 1276, 1274, 1644, 1279, - 1587, 1439, 1088, 1079, 83, 94, 94, 1308, 582, 1310, - 1311, 1312, 82, 1635, 1306, 1307, 95, 435, 1289, 95, - 307, 633, 307, 1087, 1293, 1294, 1295, 1086, 1595, 1303, - 1104, 436, 1537, 1448, 1300, 94, 1640, 1315, 681, 680, - 690, 691, 683, 684, 685, 686, 687, 688, 689, 682, - 820, 818, 692, 432, 433, 438, 819, 437, 817, 822, - 94, 1359, 1360, 1321, 821, 816, 960, 321, 1338, 920, - 338, 1048, 808, 1186, 1187, 1133, 1362, 775, 86, 1340, - 1339, 1139, 1462, 1101, 318, 644, 1353, 323, 291, 700, - 1354, 1363, 1352, 1227, 1204, 1182, 1280, 1387, 306, 1322, - 456, 449, 1407, 1682, 1355, 1383, 1659, 1657, 94, 1377, - 1621, 1567, 1361, 1660, 94, 94, 1376, 1619, 1408, 1691, - 1675, 1247, 1008, 1402, 1362, 1015, 971, 763, 1507, 1364, - 1395, 1205, 972, 729, 991, 790, 361, 930, 376, 1424, - 94, 373, 374, 306, 1019, 1239, 674, 359, 353, 1405, - 789, 782, 1040, 1038, 1037, 1412, 795, 94, 1419, 94, - 1415, 94, 1394, 1421, 1297, 1297, 1297, 788, 1023, 431, - 988, 1613, 1438, 1082, 1500, 1082, 430, 53, 1428, 1399, - 1454, 1429, 34, 1431, 343, 1432, 1430, 657, 1437, 439, - 306, 28, 1444, 1445, 1446, 23, 1097, 22, 1442, 21, - 20, 1452, 1453, 19, 25, 18, 17, 16, 607, 38, - 306, 27, 26, 15, 14, 13, 94, 12, 1474, 94, - 94, 94, 306, 11, 10, 9, 5, 307, 4, 660, - 24, 718, 307, 2, 0, 0, 1482, 0, 307, 0, - 1484, 0, 0, 0, 307, 0, 0, 1479, 1480, 1498, - 0, 1493, 1494, 0, 1465, 95, 0, 0, 0, 0, - 0, 0, 0, 0, 95, 390, 30, 0, 0, 0, - 0, 0, 0, 1488, 1468, 0, 95, 95, 0, 0, - 0, 1513, 1514, 1466, 0, 1518, 1478, 0, 0, 0, - 0, 0, 0, 1511, 1247, 0, 30, 1506, 1467, 0, - 1469, 0, 0, 1529, 1483, 0, 1485, 1486, 94, 1487, - 0, 1521, 1489, 1520, 1491, 0, 0, 0, 94, 0, - 0, 1287, 0, 0, 1082, 429, 0, 0, 0, 0, - 1530, 0, 0, 0, 0, 421, 94, 0, 0, 0, - 1531, 0, 0, 94, 681, 680, 690, 691, 683, 684, - 685, 686, 687, 688, 689, 682, 0, 1555, 692, 1550, - 0, 0, 1540, 0, 1542, 681, 680, 690, 691, 683, - 684, 685, 686, 687, 688, 689, 682, 95, 0, 692, - 307, 1534, 307, 307, 442, 95, 94, 0, 94, 0, - 94, 95, 1554, 1546, 0, 94, 0, 94, 94, 94, - 306, 1582, 0, 1580, 94, 1581, 1583, 1584, 0, 1576, - 1574, 1565, 1572, 1570, 0, 0, 0, 387, 0, 1585, - 1405, 1553, 94, 306, 1405, 1592, 0, 0, 1599, 0, - 1607, 1609, 1610, 1611, 1612, 1600, 1616, 1601, 1617, 1618, - 0, 1561, 0, 0, 352, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1629, 93, 1630, 1631, - 1634, 1579, 0, 0, 0, 94, 1626, 0, 0, 340, - 0, 1586, 1633, 1632, 0, 0, 94, 94, 0, 0, - 0, 1405, 0, 0, 0, 0, 0, 1608, 1650, 0, - 1648, 1647, 1550, 1082, 0, 0, 0, 1654, 94, 457, - 0, 0, 586, 0, 0, 0, 1247, 0, 1663, 306, - 0, 0, 0, 0, 0, 0, 0, 94, 307, 1668, - 0, 0, 0, 0, 0, 1671, 0, 95, 0, 0, - 0, 0, 307, 307, 95, 95, 95, 1680, 1679, 0, - 307, 0, 0, 0, 307, 1689, 1687, 307, 0, 0, - 0, 307, 0, 95, 0, 1504, 0, 94, 95, 95, - 95, 307, 95, 95, 0, 1698, 0, 0, 0, 0, - 0, 0, 0, 1666, 0, 95, 95, 0, 0, 0, - 0, 1713, 0, 0, 0, 0, 638, 0, 1724, 0, - 0, 0, 1725, 1726, 0, 638, 681, 680, 690, 691, - 683, 684, 685, 686, 687, 688, 689, 682, 0, 30, - 692, 0, 0, 0, 0, 0, 676, 0, 679, 0, - 0, 0, 701, 703, 693, 694, 695, 696, 697, 698, - 699, 0, 677, 678, 675, 681, 680, 690, 691, 683, - 684, 685, 686, 687, 688, 689, 682, 0, 1503, 692, - 95, 0, 0, 716, 0, 0, 0, 721, 722, 723, - 724, 725, 726, 727, 728, 0, 731, 734, 734, 734, - 740, 734, 734, 740, 734, 748, 749, 750, 751, 752, - 753, 754, 0, 95, 95, 0, 0, 30, 0, 681, - 680, 690, 691, 683, 684, 685, 686, 687, 688, 689, - 682, 0, 95, 692, 0, 0, 0, 0, 0, 307, - 0, 0, 95, 791, 0, 0, 307, 0, 307, 0, - 0, 0, 0, 0, 0, 0, 307, 307, 307, 0, - 0, 0, 0, 0, 95, 0, 0, 95, 457, 673, - 0, 0, 0, 0, 0, 0, 0, 457, 95, 95, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 656, - 658, 0, 0, 0, 96, 97, 98, 1356, 0, 0, - 0, 0, 0, 0, 0, 352, 0, 0, 0, 0, - 0, 0, 0, 0, 730, 0, 0, 681, 680, 690, - 691, 683, 684, 685, 686, 687, 688, 689, 682, 0, - 0, 692, 0, 0, 307, 95, 0, 95, 0, 0, - 0, 762, 765, 307, 307, 307, 307, 307, 310, 1497, - 307, 307, 0, 0, 307, 95, 0, 313, 0, 0, - 0, 0, 0, 0, 0, 322, 0, 0, 0, 0, - 0, 0, 307, 0, 0, 0, 0, 0, 307, 307, - 307, 0, 0, 0, 307, 95, 0, 0, 638, 0, - 778, 0, 0, 0, 0, 638, 638, 638, 457, 320, - 0, 0, 0, 0, 809, 327, 0, 0, 0, 0, - 0, 0, 0, 0, 638, 0, 0, 0, 0, 638, - 638, 638, 0, 638, 638, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 311, 638, 638, 0, 0, - 0, 0, 0, 0, 681, 680, 690, 691, 683, 684, - 685, 686, 687, 688, 689, 682, 1496, 0, 692, 0, - 0, 0, 324, 314, 0, 325, 326, 333, 0, 0, - 0, 317, 319, 330, 315, 316, 335, 334, 0, 312, - 332, 331, 0, 0, 0, 0, 0, 0, 0, 0, - 307, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 307, 307, 307, 307, 307, 1495, 0, 0, 0, - 0, 0, 0, 307, 0, 355, 0, 307, 0, 0, - 0, 307, 0, 0, 0, 0, 307, 307, 0, 0, - 307, 307, 307, 0, 0, 0, 0, 899, 0, 0, - 457, 0, 0, 0, 0, 95, 0, 457, 457, 457, - 0, 681, 680, 690, 691, 683, 684, 685, 686, 687, - 688, 689, 682, 0, 917, 692, 457, 0, 0, 0, - 0, 457, 457, 457, 0, 457, 457, 0, 0, 0, - 0, 0, 0, 926, 927, 928, 929, 1052, 457, 457, - 0, 0, 0, 0, 0, 0, 1183, 0, 0, 95, - 95, 681, 680, 690, 691, 683, 684, 685, 686, 687, - 688, 689, 682, 0, 0, 692, 681, 680, 690, 691, - 683, 684, 685, 686, 687, 688, 689, 682, 0, 95, - 692, 0, 0, 0, 0, 0, 0, 0, 979, 980, - 0, 681, 680, 690, 691, 683, 684, 685, 686, 687, - 688, 689, 682, 0, 95, 692, 0, 0, 0, 0, - 0, 0, 0, 965, 0, 457, 638, 0, 638, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 995, - 0, 0, 0, 0, 0, 0, 638, 0, 0, 0, - 0, 0, 307, 0, 0, 0, 999, 1000, 0, 0, - 0, 0, 95, 0, 0, 0, 0, 0, 95, 95, - 0, 0, 0, 0, 0, 1020, 0, 0, 0, 0, - 0, 0, 1076, 0, 0, 778, 0, 0, 457, 0, - 0, 0, 0, 0, 95, 0, 0, 307, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 457, 0, 0, - 457, 95, 0, 95, 0, 95, 0, 0, 0, 0, - 0, 457, 586, 0, 0, 0, 1188, 0, 0, 421, - 680, 690, 691, 683, 684, 685, 686, 687, 688, 689, - 682, 1132, 0, 692, 307, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 307, 0, 0, 0, 0, 0, - 95, 0, 0, 95, 95, 95, 307, 0, 457, 0, - 457, 791, 0, 0, 0, 0, 0, 0, 1243, 1244, - 0, 0, 791, 791, 791, 791, 791, 0, 457, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1052, 0, - 1269, 0, 0, 0, 0, 0, 0, 791, 0, 0, - 0, 791, 0, 0, 0, 0, 0, 0, 1173, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 706, - 707, 708, 709, 710, 711, 712, 713, 714, 715, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 95, 0, 0, 0, 0, 0, 1208, 0, - 0, 0, 95, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1223, 1224, 765, - 95, 638, 0, 0, 0, 0, 0, 95, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 638, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 95, 0, 95, 995, 95, 0, 0, 0, 0, 95, - 0, 95, 95, 95, 307, 0, 0, 0, 95, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 95, 307, 0, 0, - 388, 0, 0, 0, 0, 0, 0, 0, 457, 0, - 0, 0, 0, 0, 0, 0, 0, 1406, 0, 30, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, - 0, 0, 0, 0, 305, 0, 0, 336, 791, 0, - 95, 95, 0, 0, 305, 0, 0, 0, 0, 0, - 0, 0, 1320, 457, 0, 0, 0, 0, 0, 0, - 0, 0, 95, 0, 0, 0, 0, 443, 443, 0, - 0, 0, 0, 307, 0, 0, 305, 0, 305, 0, - 0, 95, 457, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1385, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 457, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1397, 0, - 0, 95, 0, 0, 0, 0, 0, 0, 457, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1499, 0, - 0, 0, 0, 0, 0, 457, 0, 0, 995, 0, - 935, 1409, 1411, 944, 945, 946, 947, 948, 949, 950, - 951, 952, 953, 954, 955, 956, 957, 958, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1411, 0, 0, - 0, 1526, 1527, 1528, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 457, 0, 457, 0, 1441, 0, + 438, 1771, 1682, 1529, 1760, 1729, 1591, 1404, 1611, 1662, + 382, 1310, 1628, 1330, 397, 1178, 1127, 1099, 1311, 411, + 1385, 1462, 1459, 1361, 1463, 786, 1297, 647, 1136, 1172, + 746, 76, 3, 905, 793, 613, 1384, 610, 447, 1096, + 1126, 1469, 1246, 480, 111, 1475, 939, 124, 664, 349, + 124, 1424, 958, 1005, 1012, 361, 464, 124, 1180, 1141, + 831, 824, 1377, 1123, 74, 607, 1078, 1101, 1085, 813, + 791, 441, 456, 796, 814, 384, 982, 1196, 1061, 1168, + 1038, 606, 29, 828, 1107, 361, 953, 656, 361, 124, + 361, 124, 830, 373, 803, 614, 380, 821, 72, 102, + 71, 77, 103, 968, 1679, 864, 8, 1630, 124, 124, + 1520, 7, 1601, 1764, 6, 1726, 124, 1758, 638, 374, + 1181, 1707, 124, 759, 1751, 1530, 1157, 896, 1725, 1706, + 760, 368, 1441, 1559, 79, 80, 81, 82, 83, 84, + 617, 1183, 91, 120, 116, 117, 118, 666, 99, 107, + 377, 108, 1493, 462, 466, 442, 423, 1117, 429, 430, + 427, 428, 426, 425, 424, 112, 113, 114, 474, 1494, + 1495, 31, 431, 432, 65, 35, 36, 1673, 708, 707, + 717, 718, 710, 711, 712, 713, 714, 715, 716, 709, + 369, 1347, 719, 372, 1346, 99, 92, 1348, 90, 1118, + 1119, 623, 95, 679, 622, 96, 97, 832, 371, 833, + 370, 852, 1182, 1151, 31, 32, 33, 65, 35, 36, + 674, 672, 673, 1369, 675, 672, 673, 1594, 112, 113, + 114, 1709, 477, 625, 69, 1158, 653, 1550, 655, 37, + 59, 60, 1406, 62, 1548, 64, 359, 967, 363, 63, + 357, 677, 865, 109, 1015, 633, 969, 970, 971, 927, + 667, 668, 669, 1409, 1226, 1408, 924, 1750, 678, 1739, + 652, 654, 1663, 1079, 119, 1218, 1692, 1777, 49, 98, + 1176, 878, 881, 882, 883, 884, 885, 886, 64, 887, + 888, 889, 890, 891, 866, 867, 868, 869, 850, 851, + 879, 1407, 853, 928, 854, 855, 856, 857, 858, 859, + 860, 861, 862, 863, 870, 871, 872, 873, 874, 875, + 876, 877, 1176, 926, 624, 1176, 98, 1500, 662, 609, + 124, 645, 1654, 637, 651, 619, 468, 1331, 1333, 1410, + 1145, 361, 932, 682, 899, 1486, 1485, 1519, 1145, 1484, + 361, 620, 1184, 917, 40, 42, 45, 44, 47, 925, + 61, 1674, 631, 1705, 361, 361, 650, 916, 329, 115, + 1775, 1225, 1158, 1686, 1224, 1575, 680, 880, 731, 732, + 1215, 1492, 1302, 48, 68, 67, 1217, 1265, 57, 58, + 46, 1275, 1254, 1262, 112, 113, 114, 688, 681, 1113, + 807, 744, 643, 1343, 112, 113, 114, 50, 51, 1425, + 52, 53, 54, 55, 1710, 709, 1124, 719, 719, 959, + 112, 113, 114, 658, 659, 1332, 1057, 657, 87, 1665, + 989, 915, 699, 700, 906, 1473, 628, 696, 629, 1261, + 834, 630, 692, 1206, 987, 988, 986, 1039, 954, 661, + 1427, 670, 101, 699, 649, 729, 1443, 66, 1511, 901, + 1752, 663, 636, 1655, 1653, 361, 1144, 88, 124, 374, + 124, 124, 691, 361, 1144, 784, 783, 689, 757, 361, + 690, 1039, 1148, 1272, 912, 909, 910, 1753, 908, 1149, + 1429, 1367, 1433, 1695, 1428, 747, 1426, 1202, 1203, 1204, + 66, 1431, 693, 694, 1778, 789, 792, 1600, 1773, 812, + 1430, 1774, 1216, 1772, 1214, 64, 697, 698, 696, 731, + 732, 919, 922, 1432, 1434, 731, 732, 985, 960, 797, + 698, 696, 1062, 1063, 699, 1744, 733, 734, 735, 736, + 737, 738, 739, 740, 741, 742, 785, 699, 762, 764, + 766, 768, 770, 772, 773, 763, 765, 955, 769, 771, + 648, 774, 1745, 632, 914, 800, 1599, 1059, 1525, 1205, + 1779, 1381, 782, 1380, 1210, 1207, 1198, 1208, 1201, 1187, + 1197, 639, 640, 641, 1199, 1200, 913, 707, 717, 718, + 710, 711, 712, 713, 714, 715, 716, 709, 1209, 1449, + 719, 1239, 1240, 1241, 1755, 1754, 124, 697, 698, 696, + 892, 1746, 618, 697, 698, 696, 1737, 361, 64, 124, + 477, 902, 903, 1720, 1624, 699, 1597, 921, 361, 1058, + 918, 699, 124, 1563, 112, 113, 114, 124, 1007, 1526, + 124, 937, 938, 1451, 124, 920, 361, 1450, 697, 698, + 696, 361, 361, 361, 124, 361, 361, 710, 711, 712, + 713, 714, 715, 716, 709, 898, 699, 719, 361, 361, + 112, 113, 114, 1382, 943, 1391, 923, 717, 718, 710, + 711, 712, 713, 714, 715, 716, 709, 941, 1378, 719, + 952, 697, 698, 696, 942, 977, 979, 980, 944, 946, + 947, 948, 978, 950, 951, 829, 945, 621, 795, 699, + 712, 713, 714, 715, 716, 709, 956, 957, 719, 451, + 1006, 1660, 983, 1659, 962, 1472, 112, 113, 114, 1008, + 1398, 467, 623, 963, 933, 622, 1651, 1756, 1393, 1260, + 697, 698, 696, 361, 1651, 1703, 1146, 1259, 1445, 1699, + 451, 1570, 972, 973, 974, 975, 695, 961, 699, 1651, + 451, 1651, 1687, 1027, 1030, 964, 697, 698, 696, 1040, + 400, 399, 402, 403, 404, 405, 361, 361, 984, 401, + 406, 1298, 1022, 1738, 699, 112, 113, 114, 1018, 1350, + 472, 1017, 112, 113, 114, 361, 1194, 1651, 1650, 895, + 1590, 73, 124, 1577, 451, 361, 31, 1025, 1026, 124, + 1337, 124, 1664, 747, 469, 470, 1573, 451, 1108, 124, + 124, 124, 1052, 1517, 1516, 1109, 439, 361, 1009, 1010, + 361, 1305, 1064, 1048, 1049, 1513, 1514, 1513, 1512, 1070, + 451, 361, 361, 75, 1019, 1082, 451, 695, 451, 1082, + 1097, 1018, 981, 1306, 1076, 990, 991, 992, 993, 994, + 995, 996, 997, 998, 999, 1000, 1001, 1002, 1003, 1004, + 1072, 895, 894, 125, 841, 840, 125, 1613, 451, 1143, + 64, 362, 1109, 125, 31, 1298, 1110, 1071, 1515, 1460, + 1081, 1122, 1016, 1082, 1112, 1351, 361, 1602, 1472, 1074, + 124, 1116, 1278, 1277, 1070, 1108, 1193, 1111, 1070, 1060, + 1114, 362, 1044, 931, 362, 125, 362, 125, 1106, 444, + 1115, 1174, 826, 1131, 31, 124, 124, 124, 124, 124, + 1175, 1635, 124, 124, 125, 125, 124, 361, 1192, 1387, + 1082, 1582, 125, 1110, 1603, 1604, 1605, 1405, 125, 897, + 1177, 1108, 1766, 1472, 124, 1016, 1070, 1173, 64, 1504, + 124, 124, 124, 893, 1355, 1169, 124, 361, 1170, 1171, + 1163, 1162, 89, 1614, 477, 1186, 1152, 477, 1153, 1154, + 1155, 1156, 1159, 1160, 1161, 1230, 1232, 1211, 1128, 1191, + 1236, 1185, 1761, 64, 1164, 1165, 1166, 1167, 64, 1386, + 1476, 1477, 1506, 1023, 1024, 451, 983, 1029, 1032, 1033, + 708, 707, 717, 718, 710, 711, 712, 713, 714, 715, + 716, 709, 1479, 1460, 719, 1606, 1395, 1087, 1090, 1091, + 1092, 1088, 1047, 1089, 1093, 1050, 1051, 1476, 1477, 1195, + 965, 935, 1482, 1387, 1043, 708, 707, 717, 718, 710, + 711, 712, 713, 714, 715, 716, 709, 1741, 1481, 719, + 1322, 1256, 984, 1242, 1319, 1323, 1320, 1247, 1318, 1607, + 1608, 1321, 124, 1087, 1090, 1091, 1092, 1088, 1284, 1089, + 1093, 1724, 1452, 124, 124, 124, 124, 124, 1287, 794, + 1291, 1255, 1312, 1722, 1574, 124, 1273, 1296, 1324, 124, + 1091, 1092, 442, 124, 1303, 1295, 1715, 1712, 124, 124, + 1307, 1300, 124, 124, 124, 1288, 1289, 792, 1271, 1743, + 1728, 450, 1730, 1736, 1285, 1349, 1735, 361, 1683, 1681, + 1329, 1290, 1286, 930, 440, 94, 1356, 1556, 1243, 1244, + 1245, 1362, 1362, 1352, 1299, 1301, 1392, 1338, 1386, 1035, + 1373, 1340, 1313, 904, 787, 1316, 125, 941, 1314, 1315, + 1562, 1317, 1325, 1036, 839, 1363, 788, 362, 646, 1366, + 1335, 105, 1336, 1697, 1341, 1696, 362, 1344, 106, 1633, + 1364, 1357, 1389, 1568, 1528, 1062, 1063, 1189, 1055, 361, + 362, 362, 361, 1397, 934, 1095, 448, 1354, 1358, 1359, + 1360, 708, 707, 717, 718, 710, 711, 712, 713, 714, + 715, 716, 709, 124, 1294, 719, 1390, 445, 446, 361, + 1748, 1372, 1293, 1374, 1375, 1376, 1379, 1747, 1733, 1716, + 361, 1567, 449, 75, 1566, 1455, 1298, 1394, 1388, 708, + 707, 717, 718, 710, 711, 712, 713, 714, 715, 716, + 709, 676, 1266, 719, 1263, 361, 1768, 1767, 78, 808, + 801, 1006, 1768, 1684, 1595, 1056, 444, 73, 1251, 1252, + 70, 1, 348, 1759, 1128, 110, 1531, 1610, 1411, 911, + 1370, 1371, 1423, 1661, 1412, 1383, 1414, 1179, 1413, 1269, + 1422, 362, 1134, 124, 125, 1125, 125, 125, 86, 362, + 604, 85, 660, 361, 1442, 362, 1133, 1132, 1420, 361, + 361, 1652, 1368, 1436, 1435, 1150, 1312, 1461, 1593, 1018, + 1505, 1365, 1017, 1694, 847, 845, 1464, 846, 1399, 1444, + 844, 849, 848, 843, 457, 361, 341, 1471, 124, 966, + 358, 1094, 1458, 1400, 835, 1402, 802, 1213, 458, 1212, + 907, 1518, 361, 1147, 361, 1456, 361, 338, 671, 1362, + 1362, 1362, 1480, 1488, 343, 1490, 727, 1491, 1292, 1345, + 1497, 798, 799, 460, 1510, 459, 1487, 1489, 478, 471, + 1466, 1190, 1501, 1502, 1503, 1499, 93, 1734, 1713, 1711, + 1680, 1498, 1496, 1629, 1143, 1714, 124, 1678, 1416, 1417, + 1742, 1727, 1421, 1054, 790, 1521, 1532, 361, 361, 361, + 457, 124, 1565, 1437, 1438, 1454, 1439, 1440, 1270, 756, + 1523, 1524, 1522, 1446, 458, 1037, 817, 383, 1447, 1448, + 976, 398, 125, 395, 1508, 1509, 396, 1065, 1304, 701, + 1537, 1538, 381, 362, 375, 125, 816, 454, 455, 460, + 1421, 459, 809, 1086, 362, 1084, 412, 30, 125, 1546, + 1083, 1541, 822, 125, 1478, 1474, 125, 815, 1069, 453, + 125, 1034, 362, 1672, 1558, 452, 56, 362, 362, 362, + 125, 362, 362, 1312, 1569, 34, 365, 30, 684, 461, + 28, 1579, 23, 22, 362, 362, 21, 361, 20, 1128, + 19, 1128, 1560, 25, 18, 361, 1578, 17, 16, 104, + 100, 43, 41, 1352, 39, 634, 1589, 1507, 38, 27, + 26, 15, 374, 1588, 14, 13, 12, 11, 10, 443, + 1580, 361, 9, 1581, 5, 4, 1583, 687, 24, 745, + 2, 0, 0, 0, 0, 1617, 0, 0, 0, 0, + 0, 0, 0, 1543, 1544, 0, 1545, 0, 0, 1547, + 0, 1549, 0, 0, 0, 0, 1539, 1615, 0, 362, + 0, 0, 0, 0, 361, 0, 361, 1564, 361, 0, + 0, 0, 0, 361, 0, 361, 361, 361, 124, 1642, + 1464, 1643, 1645, 1646, 1464, 1634, 1638, 1623, 1632, 0, + 0, 0, 362, 362, 1636, 1647, 1649, 0, 0, 0, + 1656, 0, 0, 0, 361, 124, 0, 1641, 0, 0, + 1666, 362, 0, 1631, 374, 0, 0, 1648, 125, 0, + 0, 362, 0, 0, 0, 125, 0, 125, 0, 1596, + 0, 1598, 0, 0, 1128, 125, 125, 125, 0, 0, + 0, 0, 361, 362, 0, 1464, 362, 1685, 0, 0, + 1657, 1691, 1658, 0, 361, 361, 361, 362, 362, 0, + 0, 1616, 0, 1701, 0, 0, 0, 0, 1612, 0, + 0, 0, 1702, 0, 0, 0, 0, 361, 0, 0, + 1627, 1708, 0, 124, 0, 1312, 1717, 0, 0, 0, + 0, 0, 0, 0, 1618, 1619, 1620, 1621, 1622, 1721, + 0, 1723, 1625, 1626, 1732, 0, 1731, 0, 0, 0, + 0, 0, 362, 0, 0, 0, 125, 1740, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 361, + 0, 0, 0, 0, 0, 1749, 0, 0, 0, 0, + 0, 125, 125, 125, 125, 125, 0, 0, 125, 125, + 0, 0, 125, 362, 1765, 0, 0, 0, 0, 0, + 1776, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 125, 0, 0, 0, 0, 0, 125, 125, 125, 0, + 1020, 1021, 125, 362, 0, 0, 0, 665, 0, 0, + 0, 0, 0, 0, 0, 0, 665, 0, 0, 0, + 0, 0, 1612, 1128, 0, 0, 0, 0, 0, 0, + 0, 0, 30, 0, 0, 0, 0, 0, 0, 1053, + 703, 0, 706, 0, 0, 728, 730, 0, 720, 721, + 722, 723, 724, 725, 726, 0, 704, 705, 702, 708, + 707, 717, 718, 710, 711, 712, 713, 714, 715, 716, + 709, 0, 0, 719, 0, 0, 743, 0, 1555, 0, + 748, 749, 750, 751, 752, 753, 754, 755, 0, 758, + 761, 761, 761, 767, 761, 761, 767, 761, 775, 776, + 777, 778, 779, 780, 781, 0, 1554, 0, 125, 0, + 30, 0, 0, 0, 0, 0, 0, 0, 1762, 125, + 125, 125, 125, 125, 1561, 0, 0, 0, 0, 0, + 0, 125, 0, 0, 0, 125, 818, 0, 0, 125, + 0, 0, 0, 0, 125, 125, 0, 0, 125, 125, + 125, 0, 409, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 362, 0, 708, 707, 717, 718, 710, + 711, 712, 713, 714, 715, 716, 709, 0, 0, 719, + 708, 707, 717, 718, 710, 711, 712, 713, 714, 715, + 716, 709, 0, 0, 719, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 360, 708, 707, + 717, 718, 710, 711, 712, 713, 714, 715, 716, 709, + 0, 0, 719, 0, 0, 362, 0, 0, 362, 0, + 0, 0, 0, 0, 0, 0, 0, 479, 0, 0, + 608, 0, 615, 0, 0, 0, 0, 0, 0, 125, + 0, 0, 0, 0, 0, 362, 0, 0, 0, 0, + 0, 0, 0, 1249, 0, 0, 362, 1250, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1257, 1258, + 0, 0, 0, 665, 1264, 0, 819, 1267, 1268, 0, + 0, 362, 0, 0, 665, 1274, 0, 0, 0, 1276, + 0, 0, 1279, 1280, 1281, 1282, 1283, 0, 0, 0, + 0, 0, 665, 0, 0, 0, 0, 665, 665, 665, + 0, 665, 665, 0, 0, 0, 0, 0, 0, 125, + 0, 0, 0, 122, 665, 665, 0, 0, 0, 362, + 0, 0, 0, 364, 0, 362, 362, 1553, 0, 0, + 0, 1327, 1328, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 112, 113, 114, 0, 0, 0, + 0, 362, 0, 0, 125, 612, 0, 616, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 362, 0, + 362, 0, 362, 0, 626, 627, 0, 0, 0, 0, + 0, 0, 635, 0, 0, 0, 0, 0, 642, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 330, 0, + 0, 0, 0, 0, 0, 0, 0, 333, 0, 0, + 0, 0, 125, 0, 0, 342, 0, 0, 0, 0, + 0, 0, 0, 362, 362, 362, 0, 125, 0, 708, + 707, 717, 718, 710, 711, 712, 713, 714, 715, 716, + 709, 0, 0, 719, 0, 0, 0, 0, 0, 340, + 0, 0, 0, 0, 0, 0, 0, 0, 347, 0, + 0, 0, 0, 0, 0, 1098, 0, 0, 0, 0, + 0, 0, 0, 479, 0, 0, 0, 0, 0, 0, + 1415, 0, 479, 0, 0, 0, 1418, 1419, 331, 0, + 0, 0, 0, 0, 0, 0, 683, 685, 410, 0, + 708, 707, 717, 718, 710, 711, 712, 713, 714, 715, + 716, 709, 0, 362, 719, 344, 334, 0, 345, 346, + 353, 362, 0, 0, 337, 339, 350, 335, 336, 355, + 354, 0, 332, 352, 351, 0, 0, 0, 0, 0, + 0, 0, 0, 1467, 0, 123, 1248, 362, 356, 0, + 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, + 0, 0, 0, 0, 1483, 0, 708, 707, 717, 718, + 710, 711, 712, 713, 714, 715, 716, 709, 465, 465, + 719, 0, 0, 665, 0, 0, 0, 123, 0, 123, + 362, 0, 362, 0, 362, 0, 644, 805, 0, 362, + 0, 362, 362, 362, 125, 479, 123, 123, 0, 0, + 0, 836, 0, 0, 123, 0, 0, 0, 0, 0, + 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 362, 125, 708, 707, 717, 718, 710, 711, 712, 713, + 714, 715, 716, 709, 0, 0, 719, 0, 0, 0, + 0, 0, 0, 0, 0, 1540, 0, 0, 0, 1542, + 0, 0, 0, 1253, 0, 0, 443, 0, 362, 0, + 1551, 1552, 0, 0, 0, 0, 0, 0, 0, 0, + 362, 362, 362, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1571, 1572, 0, 362, 1576, 0, 0, 0, 0, 125, + 0, 0, 0, 0, 0, 0, 0, 0, 818, 0, + 0, 0, 1587, 0, 0, 1308, 1309, 0, 0, 818, + 818, 818, 818, 818, 811, 0, 0, 823, 0, 0, + 0, 0, 0, 0, 0, 1098, 0, 1334, 0, 479, + 0, 0, 0, 0, 818, 362, 0, 0, 818, 0, + 479, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 479, 0, + 0, 0, 0, 479, 479, 479, 0, 479, 479, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 479, 479, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1644, + 0, 0, 0, 0, 0, 0, 0, 0, 123, 0, + 0, 0, 0, 0, 0, 665, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1668, 1669, 1670, 1671, 0, 1675, 0, + 1676, 1677, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 842, 0, 0, 1011, 665, 479, 1688, 0, + 1689, 1690, 0, 0, 0, 900, 0, 0, 0, 0, + 0, 1041, 0, 0, 0, 0, 1698, 0, 929, 0, + 0, 0, 0, 823, 0, 0, 936, 1704, 1045, 1046, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 949, 0, 0, 0, 0, 0, 0, 1066, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 805, 0, 0, + 479, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 465, 1465, 0, 30, 0, 0, 0, 479, + 0, 0, 479, 0, 0, 0, 123, 0, 123, 825, + 0, 0, 0, 479, 608, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 818, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1769, 1770, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 615, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1073, 479, + 0, 0, 0, 0, 0, 1077, 0, 1080, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1105, 1557, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1238, + 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 123, 1584, 1585, 1586, 0, 123, 0, 0, 123, 0, + 0, 0, 940, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1188, 0, 0, 0, + 0, 0, 0, 0, 0, 1609, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 998, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 638, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1219, 1220, 1221, 1222, 1223, 0, 0, 1227, 1228, + 0, 0, 1229, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1041, 0, 0, 1465, 0, 30, + 1231, 1465, 0, 0, 0, 0, 0, 0, 1235, 0, + 0, 0, 1237, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 465, 940, 0, 0, 0, 465, 465, 0, + 0, 465, 465, 465, 0, 0, 0, 1042, 0, 479, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 465, 465, 465, 465, + 465, 0, 1465, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1470, 0, 0, 1475, 1476, 1477, 0, - 0, 1502, 0, 0, 0, 0, 0, 0, 1406, 0, - 30, 0, 1406, 305, 0, 0, 0, 0, 305, 0, - 0, 352, 0, 0, 305, 0, 0, 0, 0, 1522, - 305, 0, 1523, 0, 0, 1525, 0, 0, 0, 0, - 0, 0, 0, 1604, 0, 0, 0, 0, 0, 0, + 123, 0, 0, 0, 0, 0, 940, 123, 0, 123, + 0, 0, 0, 0, 0, 0, 0, 123, 1103, 123, + 0, 479, 0, 0, 1396, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 995, 0, 0, 0, 0, 0, 0, 0, 1406, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 457, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1536, 0, 0, 0, 0, + 0, 1403, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 479, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1339, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 479, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1757, 123, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 479, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 457, 0, 0, 0, 0, 0, 0, - 457, 0, 0, 1569, 352, 0, 0, 0, 0, 0, + 0, 0, 0, 123, 123, 123, 123, 123, 0, 0, + 123, 123, 0, 0, 123, 479, 0, 0, 1041, 0, + 0, 1468, 1470, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 123, 0, 0, 0, 0, 0, 1233, 1234, + 123, 0, 0, 0, 123, 0, 0, 1470, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1401, + 0, 0, 0, 0, 479, 0, 479, 0, 615, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 443, 0, 0, 0, 0, 1178, 1179, 1180, - 0, 0, 0, 1575, 0, 1577, 305, 1578, 305, 798, - 0, 0, 1536, 0, 1536, 1536, 1536, 0, 0, 0, - 0, 1441, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1536, - 0, 0, 1711, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 465, 465, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 465, 0, 0, 0, 0, 0, 1533, + 1534, 1535, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1453, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 465, + 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1042, 123, 123, 123, 123, 123, 0, 0, 0, 0, + 0, 0, 0, 1326, 0, 0, 0, 123, 0, 0, + 0, 1103, 0, 0, 0, 1041, 123, 123, 0, 0, + 123, 1342, 940, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 479, + 0, 0, 0, 0, 0, 0, 0, 1592, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1639, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 457, 457, 0, 0, 0, 0, 0, + 0, 0, 1527, 479, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1536, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 995, 0, 1664, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1670, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 305, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 305, 305, - 0, 0, 0, 0, 0, 0, 305, 0, 0, 0, - 305, 0, 0, 305, 1536, 0, 0, 894, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 305, 0, 0, + 0, 0, 0, 0, 0, 0, 1637, 0, 1639, 0, + 1640, 123, 0, 0, 0, 1592, 0, 1592, 1592, 1592, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1592, 0, 0, 0, + 0, 0, 465, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 940, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1693, 0, 0, 0, 0, 0, + 0, 123, 0, 0, 0, 0, 1700, 479, 479, 0, + 0, 0, 0, 0, 1042, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1041, 0, 1718, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1357, 1358, + 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1378, 1379, 0, 1380, 1381, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1388, 1389, - 0, 0, 0, 0, 0, 0, 0, 443, 894, 0, - 0, 0, 443, 443, 0, 0, 443, 443, 443, 0, - 0, 0, 996, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 443, 443, 443, 443, 443, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 305, 0, 0, 0, 0, - 0, 894, 305, 0, 305, 0, 0, 0, 0, 0, - 0, 0, 305, 1057, 305, 0, 0, 1450, 0, 0, + 0, 1592, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1667, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1481, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 305, 0, 0, 0, 0, 0, 0, 0, 0, 305, - 305, 305, 305, 305, 0, 0, 305, 305, 0, 0, - 305, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 305, 0, - 0, 0, 0, 0, 1168, 1169, 305, 0, 0, 0, - 305, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 443, 443, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 443, - 0, 1556, 1557, 1558, 1559, 1560, 0, 0, 0, 1563, - 1564, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 443, 305, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 996, 305, 305, 305, - 305, 305, 0, 0, 0, 0, 0, 0, 0, 1261, - 0, 0, 0, 305, 0, 0, 0, 1057, 0, 0, - 0, 0, 305, 305, 0, 0, 305, 1277, 894, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 443, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1717, 0, 0, - 0, 894, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 305, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 996, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 305, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 305, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 305, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 305, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 996, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1057, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 305, 0, 0, 568, 556, 0, 0, - 512, 571, 485, 502, 579, 503, 506, 543, 470, 525, - 195, 500, 0, 489, 465, 496, 466, 487, 514, 131, - 518, 484, 558, 528, 570, 163, 0, 490, 545, 237, - 123, 171, 169, 255, 136, 132, 130, 122, 152, 175, - 205, 252, 199, 577, 166, 534, 0, 245, 183, 0, - 0, 0, 516, 560, 523, 553, 511, 544, 475, 533, - 572, 501, 541, 573, 0, 0, 996, 96, 97, 98, - 0, 1083, 1084, 0, 0, 0, 0, 0, 118, 305, - 538, 567, 498, 540, 542, 581, 464, 535, 0, 468, - 471, 578, 563, 493, 494, 1288, 0, 0, 0, 0, - 0, 0, 515, 524, 550, 509, 0, 0, 0, 0, - 0, 0, 0, 0, 491, 0, 532, 0, 0, 0, - 472, 469, 0, 0, 0, 0, 513, 0, 0, 0, - 474, 0, 492, 551, 0, 462, 142, 555, 562, 510, - 308, 566, 508, 507, 569, 216, 0, 249, 146, 162, - 114, 159, 100, 110, 0, 144, 192, 224, 228, 559, - 488, 497, 124, 495, 226, 203, 268, 531, 206, 225, - 167, 257, 217, 267, 277, 278, 253, 275, 286, 242, - 103, 251, 265, 119, 236, 0, 0, 0, 105, 263, - 248, 181, 156, 157, 104, 0, 222, 129, 140, 126, - 194, 260, 261, 125, 289, 111, 274, 107, 112, 273, - 188, 256, 264, 182, 174, 106, 262, 180, 173, 161, - 135, 148, 214, 170, 215, 149, 185, 184, 186, 0, - 467, 0, 246, 271, 290, 116, 483, 254, 282, 285, - 0, 218, 117, 141, 134, 213, 139, 164, 281, 283, - 284, 187, 113, 151, 243, 160, 168, 221, 288, 202, - 227, 120, 270, 244, 479, 482, 477, 478, 526, 527, - 574, 575, 576, 552, 473, 0, 480, 481, 0, 557, - 564, 565, 530, 99, 108, 165, 287, 219, 138, 272, - 463, 476, 128, 486, 0, 0, 499, 504, 505, 517, - 519, 520, 521, 522, 529, 536, 537, 539, 546, 547, - 548, 549, 554, 561, 580, 101, 102, 109, 115, 121, - 127, 133, 137, 143, 147, 150, 153, 154, 155, 158, - 172, 176, 177, 178, 179, 189, 190, 191, 193, 196, - 197, 198, 200, 201, 204, 207, 208, 209, 210, 211, - 212, 220, 223, 229, 230, 231, 232, 233, 234, 235, - 238, 239, 240, 241, 247, 250, 258, 259, 269, 276, - 279, 145, 266, 280, 568, 556, 0, 0, 512, 571, - 485, 502, 579, 503, 506, 543, 470, 525, 195, 500, - 0, 489, 465, 496, 466, 487, 514, 131, 518, 484, - 558, 528, 570, 163, 0, 490, 545, 237, 123, 171, - 169, 255, 136, 132, 130, 122, 152, 175, 205, 252, - 199, 577, 166, 534, 0, 245, 183, 0, 0, 0, - 516, 560, 523, 553, 511, 544, 475, 533, 572, 501, - 541, 573, 0, 0, 0, 96, 97, 98, 0, 1083, - 1084, 0, 0, 0, 0, 0, 118, 0, 538, 567, - 498, 540, 542, 581, 464, 535, 0, 468, 471, 578, - 563, 493, 494, 0, 0, 0, 0, 0, 0, 0, - 515, 524, 550, 509, 0, 0, 0, 0, 0, 0, - 0, 0, 491, 0, 532, 0, 0, 0, 472, 469, - 0, 0, 0, 0, 513, 0, 0, 0, 474, 0, - 492, 551, 0, 462, 142, 555, 562, 510, 308, 566, - 508, 507, 569, 216, 0, 249, 146, 162, 114, 159, - 100, 110, 0, 144, 192, 224, 228, 559, 488, 497, - 124, 495, 226, 203, 268, 531, 206, 225, 167, 257, - 217, 267, 277, 278, 253, 275, 286, 242, 103, 251, - 265, 119, 236, 0, 0, 0, 105, 263, 248, 181, - 156, 157, 104, 0, 222, 129, 140, 126, 194, 260, - 261, 125, 289, 111, 274, 107, 112, 273, 188, 256, - 264, 182, 174, 106, 262, 180, 173, 161, 135, 148, - 214, 170, 215, 149, 185, 184, 186, 0, 467, 0, - 246, 271, 290, 116, 483, 254, 282, 285, 0, 218, - 117, 141, 134, 213, 139, 164, 281, 283, 284, 187, - 113, 151, 243, 160, 168, 221, 288, 202, 227, 120, - 270, 244, 479, 482, 477, 478, 526, 527, 574, 575, - 576, 552, 473, 0, 480, 481, 0, 557, 564, 565, - 530, 99, 108, 165, 287, 219, 138, 272, 463, 476, - 128, 486, 0, 0, 499, 504, 505, 517, 519, 520, - 521, 522, 529, 536, 537, 539, 546, 547, 548, 549, - 554, 561, 580, 101, 102, 109, 115, 121, 127, 133, - 137, 143, 147, 150, 153, 154, 155, 158, 172, 176, - 177, 178, 179, 189, 190, 191, 193, 196, 197, 198, - 200, 201, 204, 207, 208, 209, 210, 211, 212, 220, - 223, 229, 230, 231, 232, 233, 234, 235, 238, 239, - 240, 241, 247, 250, 258, 259, 269, 276, 279, 145, - 266, 280, 568, 556, 0, 0, 512, 571, 485, 502, - 579, 503, 506, 543, 470, 525, 195, 500, 0, 489, - 465, 496, 466, 487, 514, 131, 518, 484, 558, 528, - 570, 163, 0, 490, 545, 237, 123, 171, 169, 255, - 136, 132, 130, 122, 152, 175, 205, 252, 199, 577, - 166, 534, 0, 245, 183, 0, 0, 0, 516, 560, - 523, 553, 511, 544, 475, 533, 572, 501, 541, 573, - 61, 0, 0, 96, 97, 98, 0, 0, 0, 0, - 0, 0, 0, 0, 118, 0, 538, 567, 498, 540, - 542, 581, 464, 535, 0, 468, 471, 578, 563, 493, - 494, 0, 0, 0, 0, 0, 0, 0, 515, 524, - 550, 509, 0, 0, 0, 0, 0, 0, 0, 0, - 491, 0, 532, 0, 0, 0, 472, 469, 0, 0, - 0, 0, 513, 0, 0, 0, 474, 0, 492, 551, - 0, 462, 142, 555, 562, 510, 308, 566, 508, 507, - 569, 216, 0, 249, 146, 162, 114, 159, 100, 110, - 0, 144, 192, 224, 228, 559, 488, 497, 124, 495, - 226, 203, 268, 531, 206, 225, 167, 257, 217, 267, - 277, 278, 253, 275, 286, 242, 103, 251, 265, 119, - 236, 0, 0, 0, 105, 263, 248, 181, 156, 157, - 104, 0, 222, 129, 140, 126, 194, 260, 261, 125, - 289, 111, 274, 107, 112, 273, 188, 256, 264, 182, - 174, 106, 262, 180, 173, 161, 135, 148, 214, 170, - 215, 149, 185, 184, 186, 0, 467, 0, 246, 271, - 290, 116, 483, 254, 282, 285, 0, 218, 117, 141, - 134, 213, 139, 164, 281, 283, 284, 187, 113, 151, - 243, 160, 168, 221, 288, 202, 227, 120, 270, 244, - 479, 482, 477, 478, 526, 527, 574, 575, 576, 552, - 473, 0, 480, 481, 0, 557, 564, 565, 530, 99, - 108, 165, 287, 219, 138, 272, 463, 476, 128, 486, - 0, 0, 499, 504, 505, 517, 519, 520, 521, 522, - 529, 536, 537, 539, 546, 547, 548, 549, 554, 561, - 580, 101, 102, 109, 115, 121, 127, 133, 137, 143, - 147, 150, 153, 154, 155, 158, 172, 176, 177, 178, - 179, 189, 190, 191, 193, 196, 197, 198, 200, 201, - 204, 207, 208, 209, 210, 211, 212, 220, 223, 229, - 230, 231, 232, 233, 234, 235, 238, 239, 240, 241, - 247, 250, 258, 259, 269, 276, 279, 145, 266, 280, - 568, 556, 0, 0, 512, 571, 485, 502, 579, 503, - 506, 543, 470, 525, 195, 500, 0, 489, 465, 496, - 466, 487, 514, 131, 518, 484, 558, 528, 570, 163, - 0, 490, 545, 237, 123, 171, 169, 255, 136, 132, - 130, 122, 152, 175, 205, 252, 199, 577, 166, 534, - 0, 245, 183, 0, 0, 0, 516, 560, 523, 553, - 511, 544, 475, 533, 572, 501, 541, 573, 0, 0, - 0, 96, 97, 98, 0, 0, 0, 0, 0, 0, - 0, 0, 118, 0, 538, 567, 498, 540, 542, 581, - 464, 535, 0, 468, 471, 578, 563, 493, 494, 0, - 0, 0, 0, 0, 0, 0, 515, 524, 550, 509, - 0, 0, 0, 0, 0, 0, 1398, 0, 491, 0, - 532, 0, 0, 0, 472, 469, 0, 0, 0, 0, - 513, 0, 0, 0, 474, 0, 492, 551, 0, 462, - 142, 555, 562, 510, 308, 566, 508, 507, 569, 216, - 0, 249, 146, 162, 114, 159, 100, 110, 0, 144, - 192, 224, 228, 559, 488, 497, 124, 495, 226, 203, - 268, 531, 206, 225, 167, 257, 217, 267, 277, 278, - 253, 275, 286, 242, 103, 251, 265, 119, 236, 0, - 0, 0, 105, 263, 248, 181, 156, 157, 104, 0, - 222, 129, 140, 126, 194, 260, 261, 125, 289, 111, - 274, 107, 112, 273, 188, 256, 264, 182, 174, 106, - 262, 180, 173, 161, 135, 148, 214, 170, 215, 149, - 185, 184, 186, 0, 467, 0, 246, 271, 290, 116, - 483, 254, 282, 285, 0, 218, 117, 141, 134, 213, - 139, 164, 281, 283, 284, 187, 113, 151, 243, 160, - 168, 221, 288, 202, 227, 120, 270, 244, 479, 482, - 477, 478, 526, 527, 574, 575, 576, 552, 473, 0, - 480, 481, 0, 557, 564, 565, 530, 99, 108, 165, - 287, 219, 138, 272, 463, 476, 128, 486, 0, 0, - 499, 504, 505, 517, 519, 520, 521, 522, 529, 536, - 537, 539, 546, 547, 548, 549, 554, 561, 580, 101, - 102, 109, 115, 121, 127, 133, 137, 143, 147, 150, - 153, 154, 155, 158, 172, 176, 177, 178, 179, 189, - 190, 191, 193, 196, 197, 198, 200, 201, 204, 207, - 208, 209, 210, 211, 212, 220, 223, 229, 230, 231, - 232, 233, 234, 235, 238, 239, 240, 241, 247, 250, - 258, 259, 269, 276, 279, 145, 266, 280, 568, 556, - 0, 0, 512, 571, 485, 502, 579, 503, 506, 543, - 470, 525, 195, 500, 0, 489, 465, 496, 466, 487, - 514, 131, 518, 484, 558, 528, 570, 163, 0, 490, - 545, 237, 123, 171, 169, 255, 136, 132, 130, 122, - 152, 175, 205, 252, 199, 577, 166, 534, 0, 245, - 183, 0, 0, 0, 516, 560, 523, 553, 511, 544, - 475, 533, 572, 501, 541, 573, 0, 0, 0, 96, - 97, 98, 0, 0, 0, 0, 0, 0, 0, 0, - 118, 0, 538, 567, 498, 540, 542, 581, 464, 535, - 0, 468, 471, 578, 563, 493, 494, 0, 0, 0, - 0, 0, 0, 0, 515, 524, 550, 509, 0, 0, - 0, 0, 0, 0, 1278, 0, 491, 0, 532, 0, - 0, 0, 472, 469, 0, 0, 0, 0, 513, 0, - 0, 0, 474, 0, 492, 551, 0, 462, 142, 555, - 562, 510, 308, 566, 508, 507, 569, 216, 0, 249, - 146, 162, 114, 159, 100, 110, 0, 144, 192, 224, - 228, 559, 488, 497, 124, 495, 226, 203, 268, 531, - 206, 225, 167, 257, 217, 267, 277, 278, 253, 275, - 286, 242, 103, 251, 265, 119, 236, 0, 0, 0, - 105, 263, 248, 181, 156, 157, 104, 0, 222, 129, - 140, 126, 194, 260, 261, 125, 289, 111, 274, 107, - 112, 273, 188, 256, 264, 182, 174, 106, 262, 180, - 173, 161, 135, 148, 214, 170, 215, 149, 185, 184, - 186, 0, 467, 0, 246, 271, 290, 116, 483, 254, - 282, 285, 0, 218, 117, 141, 134, 213, 139, 164, - 281, 283, 284, 187, 113, 151, 243, 160, 168, 221, - 288, 202, 227, 120, 270, 244, 479, 482, 477, 478, - 526, 527, 574, 575, 576, 552, 473, 0, 480, 481, - 0, 557, 564, 565, 530, 99, 108, 165, 287, 219, - 138, 272, 463, 476, 128, 486, 0, 0, 499, 504, - 505, 517, 519, 520, 521, 522, 529, 536, 537, 539, - 546, 547, 548, 549, 554, 561, 580, 101, 102, 109, - 115, 121, 127, 133, 137, 143, 147, 150, 153, 154, - 155, 158, 172, 176, 177, 178, 179, 189, 190, 191, - 193, 196, 197, 198, 200, 201, 204, 207, 208, 209, - 210, 211, 212, 220, 223, 229, 230, 231, 232, 233, - 234, 235, 238, 239, 240, 241, 247, 250, 258, 259, - 269, 276, 279, 145, 266, 280, 568, 556, 0, 0, - 512, 571, 485, 502, 579, 503, 506, 543, 470, 525, - 195, 500, 0, 489, 465, 496, 466, 487, 514, 131, - 518, 484, 558, 528, 570, 163, 0, 490, 545, 237, - 123, 171, 169, 255, 136, 132, 130, 122, 152, 175, - 205, 252, 199, 577, 166, 534, 0, 245, 183, 0, - 0, 0, 516, 560, 523, 553, 511, 544, 475, 533, - 572, 501, 541, 573, 0, 0, 0, 96, 97, 98, - 0, 0, 0, 0, 0, 0, 0, 0, 118, 0, - 538, 567, 498, 540, 542, 581, 464, 535, 0, 468, - 471, 578, 563, 493, 494, 0, 0, 0, 0, 0, - 0, 0, 515, 524, 550, 509, 0, 0, 0, 0, - 0, 0, 1029, 0, 491, 0, 532, 0, 0, 0, - 472, 469, 0, 0, 0, 0, 513, 0, 0, 0, - 474, 0, 492, 551, 0, 462, 142, 555, 562, 510, - 308, 566, 508, 507, 569, 216, 0, 249, 146, 162, - 114, 159, 100, 110, 0, 144, 192, 224, 228, 559, - 488, 497, 124, 495, 226, 203, 268, 531, 206, 225, - 167, 257, 217, 267, 277, 278, 253, 275, 286, 242, - 103, 251, 265, 119, 236, 0, 0, 0, 105, 263, - 248, 181, 156, 157, 104, 0, 222, 129, 140, 126, - 194, 260, 261, 125, 289, 111, 274, 107, 112, 273, - 188, 256, 264, 182, 174, 106, 262, 180, 173, 161, - 135, 148, 214, 170, 215, 149, 185, 184, 186, 0, - 467, 0, 246, 271, 290, 116, 483, 254, 282, 285, - 0, 218, 117, 141, 134, 213, 139, 164, 281, 283, - 284, 187, 113, 151, 243, 160, 168, 221, 288, 202, - 227, 120, 270, 244, 479, 482, 477, 478, 526, 527, - 574, 575, 576, 552, 473, 0, 480, 481, 0, 557, - 564, 565, 530, 99, 108, 165, 287, 219, 138, 272, - 463, 476, 128, 486, 0, 0, 499, 504, 505, 517, - 519, 520, 521, 522, 529, 536, 537, 539, 546, 547, - 548, 549, 554, 561, 580, 101, 102, 109, 115, 121, - 127, 133, 137, 143, 147, 150, 153, 154, 155, 158, - 172, 176, 177, 178, 179, 189, 190, 191, 193, 196, - 197, 198, 200, 201, 204, 207, 208, 209, 210, 211, - 212, 220, 223, 229, 230, 231, 232, 233, 234, 235, - 238, 239, 240, 241, 247, 250, 258, 259, 269, 276, - 279, 145, 266, 280, 568, 556, 0, 0, 512, 571, - 485, 502, 579, 503, 506, 543, 470, 525, 195, 500, - 0, 489, 465, 496, 466, 487, 514, 131, 518, 484, - 558, 528, 570, 163, 0, 490, 545, 237, 123, 171, - 169, 255, 136, 132, 130, 122, 152, 175, 205, 252, - 199, 577, 166, 534, 0, 245, 183, 0, 0, 0, - 516, 560, 523, 553, 511, 544, 475, 533, 572, 501, - 541, 573, 0, 0, 0, 96, 97, 98, 0, 0, - 0, 0, 0, 0, 0, 0, 118, 0, 538, 567, - 498, 540, 542, 581, 464, 535, 0, 468, 471, 578, - 563, 493, 494, 0, 0, 0, 0, 0, 0, 0, - 515, 524, 550, 509, 0, 0, 0, 0, 0, 0, - 0, 0, 491, 0, 532, 0, 0, 0, 472, 469, - 0, 0, 0, 0, 513, 0, 0, 0, 474, 0, - 492, 551, 0, 462, 142, 555, 562, 510, 308, 566, - 508, 507, 569, 216, 0, 249, 146, 162, 114, 159, - 100, 110, 0, 144, 192, 224, 228, 559, 488, 497, - 124, 495, 226, 203, 268, 531, 206, 225, 167, 257, - 217, 267, 277, 278, 253, 275, 286, 242, 103, 251, - 265, 119, 236, 0, 0, 0, 105, 263, 248, 181, - 156, 157, 104, 0, 222, 129, 140, 126, 194, 260, - 261, 125, 289, 111, 274, 107, 112, 273, 188, 256, - 264, 182, 174, 106, 262, 180, 173, 161, 135, 148, - 214, 170, 215, 149, 185, 184, 186, 0, 467, 0, - 246, 271, 290, 116, 483, 254, 282, 285, 0, 218, - 117, 141, 134, 213, 139, 164, 281, 283, 284, 187, - 113, 151, 243, 160, 168, 221, 288, 202, 227, 120, - 270, 244, 479, 482, 477, 478, 526, 527, 574, 575, - 576, 552, 473, 0, 480, 481, 0, 557, 564, 565, - 530, 99, 108, 165, 287, 219, 138, 272, 463, 476, - 128, 486, 0, 0, 499, 504, 505, 517, 519, 520, - 521, 522, 529, 536, 537, 539, 546, 547, 548, 549, - 554, 561, 580, 101, 102, 109, 115, 121, 127, 133, - 137, 143, 147, 150, 153, 154, 155, 158, 172, 176, - 177, 178, 179, 189, 190, 191, 193, 196, 197, 198, - 200, 201, 204, 207, 208, 209, 210, 211, 212, 220, - 223, 229, 230, 231, 232, 233, 234, 235, 238, 239, - 240, 241, 247, 250, 258, 259, 269, 276, 279, 145, - 266, 280, 568, 556, 0, 0, 512, 571, 485, 502, - 579, 503, 506, 543, 470, 525, 195, 500, 0, 489, - 465, 496, 466, 487, 514, 131, 518, 484, 558, 528, - 570, 163, 0, 490, 545, 237, 123, 171, 169, 255, - 136, 132, 130, 122, 152, 175, 205, 252, 199, 577, - 166, 534, 0, 245, 183, 0, 0, 0, 516, 560, - 523, 553, 511, 544, 475, 533, 572, 501, 541, 573, - 0, 0, 0, 96, 97, 98, 0, 0, 0, 0, - 0, 0, 0, 0, 118, 0, 538, 567, 498, 540, - 542, 581, 464, 535, 0, 468, 471, 578, 563, 493, - 494, 0, 0, 0, 0, 0, 0, 0, 515, 524, - 550, 509, 0, 0, 0, 0, 0, 0, 0, 0, - 491, 0, 532, 0, 0, 0, 472, 469, 0, 0, - 0, 0, 513, 0, 0, 0, 474, 0, 492, 551, - 0, 462, 142, 555, 562, 510, 308, 566, 508, 507, - 569, 216, 0, 249, 146, 162, 114, 159, 100, 110, - 0, 144, 192, 224, 228, 559, 488, 497, 124, 495, - 226, 203, 268, 531, 206, 225, 167, 257, 217, 267, - 277, 278, 253, 275, 286, 242, 103, 251, 265, 119, - 236, 0, 0, 0, 105, 263, 248, 181, 156, 157, - 104, 0, 222, 129, 140, 126, 194, 260, 261, 125, - 289, 111, 274, 107, 460, 273, 188, 256, 264, 182, - 174, 106, 262, 180, 173, 161, 135, 148, 214, 170, - 215, 149, 185, 184, 186, 0, 467, 0, 246, 271, - 290, 116, 483, 254, 282, 285, 0, 218, 117, 141, - 134, 213, 139, 164, 281, 283, 284, 461, 459, 454, - 453, 160, 168, 221, 288, 202, 227, 120, 270, 244, - 479, 482, 477, 478, 526, 527, 574, 575, 576, 552, - 473, 0, 480, 481, 0, 557, 564, 565, 530, 99, - 108, 165, 287, 219, 138, 272, 463, 476, 128, 486, - 0, 0, 499, 504, 505, 517, 519, 520, 521, 522, - 529, 536, 537, 539, 546, 547, 548, 549, 554, 561, - 580, 101, 102, 109, 115, 121, 127, 133, 137, 143, - 147, 150, 153, 154, 155, 158, 172, 176, 177, 178, - 179, 189, 190, 191, 193, 196, 197, 198, 200, 201, - 204, 207, 208, 209, 210, 211, 212, 220, 223, 229, - 230, 231, 232, 233, 234, 235, 238, 239, 240, 241, - 247, 250, 258, 259, 269, 276, 279, 145, 266, 280, - 568, 556, 0, 0, 512, 571, 485, 502, 579, 503, - 506, 543, 470, 525, 195, 500, 0, 489, 465, 496, - 466, 487, 514, 131, 518, 484, 558, 528, 570, 163, - 0, 490, 545, 237, 123, 171, 169, 255, 136, 132, - 130, 122, 152, 175, 205, 252, 199, 577, 166, 534, - 0, 245, 183, 0, 0, 0, 516, 560, 523, 553, - 511, 544, 475, 533, 572, 501, 541, 573, 0, 0, - 0, 96, 97, 98, 0, 0, 0, 0, 0, 0, - 0, 0, 118, 0, 538, 567, 498, 540, 542, 581, - 464, 535, 0, 468, 471, 578, 563, 493, 494, 0, - 0, 0, 0, 0, 0, 0, 515, 524, 550, 509, - 0, 0, 0, 0, 0, 0, 0, 0, 491, 0, - 532, 0, 0, 0, 472, 469, 0, 0, 0, 0, - 513, 0, 0, 0, 474, 0, 492, 551, 0, 462, - 142, 555, 562, 510, 308, 566, 508, 507, 569, 216, - 0, 249, 146, 162, 114, 159, 100, 110, 0, 144, - 192, 224, 228, 559, 488, 497, 124, 495, 226, 203, - 268, 531, 206, 225, 167, 257, 217, 267, 277, 278, - 253, 275, 286, 242, 103, 251, 800, 119, 236, 0, - 0, 0, 105, 263, 248, 181, 156, 157, 104, 0, - 222, 129, 140, 126, 194, 260, 261, 125, 289, 111, - 274, 107, 460, 273, 188, 256, 264, 182, 174, 106, - 262, 180, 173, 161, 135, 148, 214, 170, 215, 149, - 185, 184, 186, 0, 467, 0, 246, 271, 290, 116, - 483, 254, 282, 285, 0, 218, 117, 141, 134, 213, - 139, 164, 281, 283, 284, 461, 459, 454, 453, 160, - 168, 221, 288, 202, 227, 120, 270, 244, 479, 482, - 477, 478, 526, 527, 574, 575, 576, 552, 473, 0, - 480, 481, 0, 557, 564, 565, 530, 99, 108, 165, - 287, 219, 138, 272, 463, 476, 128, 486, 0, 0, - 499, 504, 505, 517, 519, 520, 521, 522, 529, 536, - 537, 539, 546, 547, 548, 549, 554, 561, 580, 101, - 102, 109, 115, 121, 127, 133, 137, 143, 147, 150, - 153, 154, 155, 158, 172, 176, 177, 178, 179, 189, - 190, 191, 193, 196, 197, 198, 200, 201, 204, 207, - 208, 209, 210, 211, 212, 220, 223, 229, 230, 231, - 232, 233, 234, 235, 238, 239, 240, 241, 247, 250, - 258, 259, 269, 276, 279, 145, 266, 280, 568, 556, - 0, 0, 512, 571, 485, 502, 579, 503, 506, 543, - 470, 525, 195, 500, 0, 489, 465, 496, 466, 487, - 514, 131, 518, 484, 558, 528, 570, 163, 0, 490, - 545, 237, 123, 171, 169, 255, 136, 132, 130, 122, - 152, 175, 205, 252, 199, 577, 166, 534, 0, 245, - 183, 0, 0, 0, 516, 560, 523, 553, 511, 544, - 475, 533, 572, 501, 541, 573, 0, 0, 0, 96, - 97, 98, 0, 0, 0, 0, 0, 0, 0, 0, - 118, 0, 538, 567, 498, 540, 542, 581, 464, 535, - 0, 468, 471, 578, 563, 493, 494, 0, 0, 0, - 0, 0, 0, 0, 515, 524, 550, 509, 0, 0, - 0, 0, 0, 0, 0, 0, 491, 0, 532, 0, - 0, 0, 472, 469, 0, 0, 0, 0, 513, 0, - 0, 0, 474, 0, 492, 551, 0, 462, 142, 555, - 562, 510, 308, 566, 508, 507, 569, 216, 0, 249, - 146, 162, 114, 159, 100, 110, 0, 144, 192, 224, - 228, 559, 488, 497, 124, 495, 226, 203, 268, 531, - 206, 225, 167, 257, 217, 267, 277, 278, 253, 275, - 286, 242, 103, 251, 451, 119, 236, 0, 0, 0, - 105, 263, 248, 181, 156, 157, 104, 0, 222, 129, - 140, 126, 194, 260, 261, 125, 289, 111, 274, 107, - 460, 273, 188, 256, 264, 182, 174, 106, 262, 180, - 173, 161, 135, 148, 214, 170, 215, 149, 185, 184, - 186, 0, 467, 0, 246, 271, 290, 116, 483, 254, - 282, 285, 0, 218, 117, 141, 134, 213, 139, 164, - 281, 283, 284, 461, 459, 454, 453, 160, 168, 221, - 288, 202, 227, 120, 270, 244, 479, 482, 477, 478, - 526, 527, 574, 575, 576, 552, 473, 0, 480, 481, - 0, 557, 564, 565, 530, 99, 108, 165, 287, 219, - 138, 272, 463, 476, 128, 486, 0, 0, 499, 504, - 505, 517, 519, 520, 521, 522, 529, 536, 537, 539, - 546, 547, 548, 549, 554, 561, 580, 101, 102, 109, - 115, 121, 127, 133, 137, 143, 147, 150, 153, 154, - 155, 158, 172, 176, 177, 178, 179, 189, 190, 191, - 193, 196, 197, 198, 200, 201, 204, 207, 208, 209, - 210, 211, 212, 220, 223, 229, 230, 231, 232, 233, - 234, 235, 238, 239, 240, 241, 247, 250, 258, 259, - 269, 276, 279, 145, 266, 280, 195, 0, 0, 967, - 0, 357, 0, 0, 0, 131, 0, 356, 0, 0, - 0, 163, 0, 968, 0, 237, 123, 171, 169, 255, - 136, 132, 130, 122, 152, 175, 205, 252, 199, 400, - 166, 0, 0, 245, 183, 0, 0, 0, 0, 0, - 391, 392, 0, 0, 0, 0, 0, 0, 0, 0, - 61, 0, 0, 96, 97, 98, 378, 377, 380, 381, - 382, 383, 0, 0, 118, 379, 384, 385, 386, 0, - 0, 0, 0, 354, 371, 0, 399, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 368, 369, 441, 0, - 0, 0, 414, 0, 370, 0, 0, 363, 364, 366, - 365, 367, 372, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 142, 413, 0, 0, 308, 0, 0, 411, - 0, 216, 0, 249, 146, 162, 114, 159, 100, 110, - 0, 144, 192, 224, 228, 0, 0, 0, 124, 0, - 226, 203, 268, 0, 206, 225, 167, 257, 217, 267, - 277, 278, 253, 275, 286, 242, 103, 251, 265, 119, - 236, 0, 0, 0, 105, 263, 248, 181, 156, 157, - 104, 0, 222, 129, 140, 126, 194, 260, 261, 125, - 289, 111, 274, 107, 112, 273, 188, 256, 264, 182, - 174, 106, 262, 180, 173, 161, 135, 148, 214, 170, - 215, 149, 185, 184, 186, 0, 0, 0, 246, 271, - 290, 116, 0, 254, 282, 285, 0, 218, 117, 141, - 134, 213, 139, 164, 281, 283, 284, 187, 113, 151, - 243, 160, 168, 221, 288, 202, 227, 120, 270, 244, - 401, 412, 407, 408, 405, 406, 404, 403, 402, 415, - 393, 394, 395, 396, 398, 0, 409, 410, 397, 99, - 108, 165, 287, 219, 138, 272, 0, 0, 128, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 101, 102, 109, 115, 121, 127, 133, 137, 143, - 147, 150, 153, 154, 155, 158, 172, 176, 177, 178, - 179, 189, 190, 191, 193, 196, 197, 198, 200, 201, - 204, 207, 208, 209, 210, 211, 212, 220, 223, 229, - 230, 231, 232, 233, 234, 235, 238, 239, 240, 241, - 247, 250, 258, 259, 269, 276, 279, 145, 266, 280, - 195, 0, 0, 0, 0, 357, 0, 0, 0, 131, - 0, 356, 0, 0, 0, 163, 0, 0, 0, 237, - 123, 171, 169, 255, 136, 132, 130, 122, 152, 175, - 205, 252, 199, 400, 166, 0, 0, 245, 183, 0, - 0, 0, 0, 0, 391, 392, 0, 0, 0, 0, - 0, 0, 1074, 0, 61, 0, 0, 96, 97, 98, - 378, 377, 380, 381, 382, 383, 0, 0, 118, 379, - 384, 385, 386, 1075, 0, 0, 0, 354, 371, 0, - 399, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 368, 369, 0, 0, 0, 0, 414, 0, 370, 0, - 0, 363, 364, 366, 365, 367, 372, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 142, 413, 0, 0, - 308, 0, 0, 411, 0, 216, 0, 249, 146, 162, - 114, 159, 100, 110, 0, 144, 192, 224, 228, 0, - 0, 0, 124, 0, 226, 203, 268, 0, 206, 225, - 167, 257, 217, 267, 277, 278, 253, 275, 286, 242, - 103, 251, 265, 119, 236, 0, 0, 0, 105, 263, - 248, 181, 156, 157, 104, 0, 222, 129, 140, 126, - 194, 260, 261, 125, 289, 111, 274, 107, 112, 273, - 188, 256, 264, 182, 174, 106, 262, 180, 173, 161, - 135, 148, 214, 170, 215, 149, 185, 184, 186, 0, - 0, 0, 246, 271, 290, 116, 0, 254, 282, 285, - 0, 218, 117, 141, 134, 213, 139, 164, 281, 283, - 284, 187, 113, 151, 243, 160, 168, 221, 288, 202, - 227, 120, 270, 244, 401, 412, 407, 408, 405, 406, - 404, 403, 402, 415, 393, 394, 395, 396, 398, 0, - 409, 410, 397, 99, 108, 165, 287, 219, 138, 272, - 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 101, 102, 109, 115, 121, - 127, 133, 137, 143, 147, 150, 153, 154, 155, 158, - 172, 176, 177, 178, 179, 189, 190, 191, 193, 196, - 197, 198, 200, 201, 204, 207, 208, 209, 210, 211, - 212, 220, 223, 229, 230, 231, 232, 233, 234, 235, - 238, 239, 240, 241, 247, 250, 258, 259, 269, 276, - 279, 145, 266, 280, 195, 0, 0, 0, 0, 357, - 0, 0, 0, 131, 0, 356, 0, 0, 0, 163, - 0, 0, 0, 237, 123, 171, 169, 255, 136, 132, - 130, 122, 152, 175, 205, 252, 199, 400, 166, 0, - 0, 245, 183, 0, 0, 0, 0, 0, 391, 392, - 0, 0, 0, 0, 0, 0, 0, 0, 61, 0, - 429, 96, 97, 98, 378, 377, 380, 381, 382, 383, - 0, 0, 118, 379, 384, 385, 386, 0, 0, 0, - 0, 354, 371, 0, 399, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 368, 369, 0, 0, 0, 0, - 414, 0, 370, 0, 0, 363, 364, 366, 365, 367, - 372, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 142, 413, 0, 0, 308, 0, 0, 411, 0, 216, - 0, 249, 146, 162, 114, 159, 100, 110, 0, 144, - 192, 224, 228, 0, 0, 0, 124, 0, 226, 203, - 268, 0, 206, 225, 167, 257, 217, 267, 277, 278, - 253, 275, 286, 242, 103, 251, 265, 119, 236, 0, - 0, 0, 105, 263, 248, 181, 156, 157, 104, 0, - 222, 129, 140, 126, 194, 260, 261, 125, 289, 111, - 274, 107, 112, 273, 188, 256, 264, 182, 174, 106, - 262, 180, 173, 161, 135, 148, 214, 170, 215, 149, - 185, 184, 186, 0, 0, 0, 246, 271, 290, 116, - 0, 254, 282, 285, 0, 218, 117, 141, 134, 213, - 139, 164, 281, 283, 284, 187, 113, 151, 243, 160, - 168, 221, 288, 202, 227, 120, 270, 244, 401, 412, - 407, 408, 405, 406, 404, 403, 402, 415, 393, 394, - 395, 396, 398, 0, 409, 410, 397, 99, 108, 165, - 287, 219, 138, 272, 0, 0, 128, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, - 102, 109, 115, 121, 127, 133, 137, 143, 147, 150, - 153, 154, 155, 158, 172, 176, 177, 178, 179, 189, - 190, 191, 193, 196, 197, 198, 200, 201, 204, 207, - 208, 209, 210, 211, 212, 220, 223, 229, 230, 231, - 232, 233, 234, 235, 238, 239, 240, 241, 247, 250, - 258, 259, 269, 276, 279, 145, 266, 280, 195, 0, - 0, 0, 0, 357, 0, 0, 0, 131, 0, 356, - 0, 0, 0, 163, 0, 0, 0, 237, 123, 171, - 169, 255, 136, 132, 130, 122, 152, 175, 205, 252, - 199, 400, 166, 0, 0, 245, 183, 0, 0, 0, - 0, 0, 391, 392, 0, 0, 0, 0, 0, 0, - 0, 0, 61, 0, 0, 96, 97, 98, 378, 377, - 380, 381, 382, 383, 0, 0, 118, 379, 384, 385, - 386, 0, 0, 0, 0, 354, 371, 0, 399, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 368, 369, - 441, 0, 0, 0, 414, 0, 370, 0, 0, 363, - 364, 366, 365, 367, 372, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 142, 413, 0, 0, 308, 0, - 0, 411, 0, 216, 0, 249, 146, 162, 114, 159, - 100, 110, 0, 144, 192, 224, 228, 0, 0, 0, - 124, 0, 226, 203, 268, 0, 206, 225, 167, 257, - 217, 267, 277, 278, 253, 275, 286, 242, 103, 251, - 265, 119, 236, 0, 0, 0, 105, 263, 248, 181, - 156, 157, 104, 0, 222, 129, 140, 126, 194, 260, - 261, 125, 289, 111, 274, 107, 112, 273, 188, 256, - 264, 182, 174, 106, 262, 180, 173, 161, 135, 148, - 214, 170, 215, 149, 185, 184, 186, 0, 0, 0, - 246, 271, 290, 116, 0, 254, 282, 285, 0, 218, - 117, 141, 134, 213, 139, 164, 281, 283, 284, 187, - 113, 151, 243, 160, 168, 221, 288, 202, 227, 120, - 270, 244, 401, 412, 407, 408, 405, 406, 404, 403, - 402, 415, 393, 394, 395, 396, 398, 0, 409, 410, - 397, 99, 108, 165, 287, 219, 138, 272, 0, 0, - 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 101, 102, 109, 115, 121, 127, 133, - 137, 143, 147, 150, 153, 154, 155, 158, 172, 176, - 177, 178, 179, 189, 190, 191, 193, 196, 197, 198, - 200, 201, 204, 207, 208, 209, 210, 211, 212, 220, - 223, 229, 230, 231, 232, 233, 234, 235, 238, 239, - 240, 241, 247, 250, 258, 259, 269, 276, 279, 145, - 266, 280, 195, 0, 0, 0, 0, 357, 0, 0, - 0, 131, 0, 356, 0, 0, 0, 163, 0, 0, - 0, 237, 123, 171, 169, 255, 136, 132, 130, 122, - 152, 175, 205, 252, 199, 400, 166, 0, 0, 245, - 183, 0, 0, 0, 0, 0, 391, 392, 0, 0, - 0, 0, 0, 0, 0, 0, 61, 0, 0, 96, - 97, 98, 378, 985, 380, 381, 382, 383, 0, 0, - 118, 379, 384, 385, 386, 0, 0, 0, 0, 354, - 371, 0, 399, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 368, 369, 441, 0, 0, 0, 414, 0, - 370, 0, 0, 363, 364, 366, 365, 367, 372, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 142, 413, - 0, 0, 308, 0, 0, 411, 0, 216, 0, 249, - 146, 162, 114, 159, 100, 110, 0, 144, 192, 224, - 228, 0, 0, 0, 124, 0, 226, 203, 268, 0, - 206, 225, 167, 257, 217, 267, 277, 278, 253, 275, - 286, 242, 103, 251, 265, 119, 236, 0, 0, 0, - 105, 263, 248, 181, 156, 157, 104, 0, 222, 129, - 140, 126, 194, 260, 261, 125, 289, 111, 274, 107, - 112, 273, 188, 256, 264, 182, 174, 106, 262, 180, - 173, 161, 135, 148, 214, 170, 215, 149, 185, 184, - 186, 0, 0, 0, 246, 271, 290, 116, 0, 254, - 282, 285, 0, 218, 117, 141, 134, 213, 139, 164, - 281, 283, 284, 187, 113, 151, 243, 160, 168, 221, - 288, 202, 227, 120, 270, 244, 401, 412, 407, 408, - 405, 406, 404, 403, 402, 415, 393, 394, 395, 396, - 398, 0, 409, 410, 397, 99, 108, 165, 287, 219, - 138, 272, 0, 0, 128, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 101, 102, 109, - 115, 121, 127, 133, 137, 143, 147, 150, 153, 154, - 155, 158, 172, 176, 177, 178, 179, 189, 190, 191, - 193, 196, 197, 198, 200, 201, 204, 207, 208, 209, - 210, 211, 212, 220, 223, 229, 230, 231, 232, 233, - 234, 235, 238, 239, 240, 241, 247, 250, 258, 259, - 269, 276, 279, 145, 266, 280, 195, 0, 0, 0, - 0, 357, 0, 0, 0, 131, 0, 356, 0, 0, - 0, 163, 0, 0, 0, 237, 123, 171, 169, 255, - 136, 132, 130, 122, 152, 175, 205, 252, 199, 400, - 166, 0, 0, 245, 183, 0, 0, 0, 0, 0, - 391, 392, 0, 0, 0, 0, 0, 0, 0, 0, - 61, 0, 0, 96, 97, 98, 378, 982, 380, 381, - 382, 383, 0, 0, 118, 379, 384, 385, 386, 0, - 0, 0, 0, 354, 371, 0, 399, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 368, 369, 441, 0, - 0, 0, 414, 0, 370, 0, 0, 363, 364, 366, - 365, 367, 372, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 142, 413, 0, 0, 308, 0, 0, 411, - 0, 216, 0, 249, 146, 162, 114, 159, 100, 110, - 0, 144, 192, 224, 228, 0, 0, 0, 124, 0, - 226, 203, 268, 0, 206, 225, 167, 257, 217, 267, - 277, 278, 253, 275, 286, 242, 103, 251, 265, 119, - 236, 0, 0, 0, 105, 263, 248, 181, 156, 157, - 104, 0, 222, 129, 140, 126, 194, 260, 261, 125, - 289, 111, 274, 107, 112, 273, 188, 256, 264, 182, - 174, 106, 262, 180, 173, 161, 135, 148, 214, 170, - 215, 149, 185, 184, 186, 0, 0, 0, 246, 271, - 290, 116, 0, 254, 282, 285, 0, 218, 117, 141, - 134, 213, 139, 164, 281, 283, 284, 187, 113, 151, - 243, 160, 168, 221, 288, 202, 227, 120, 270, 244, - 401, 412, 407, 408, 405, 406, 404, 403, 402, 415, - 393, 394, 395, 396, 398, 0, 409, 410, 397, 99, - 108, 165, 287, 219, 138, 272, 0, 0, 128, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 101, 102, 109, 115, 121, 127, 133, 137, 143, - 147, 150, 153, 154, 155, 158, 172, 176, 177, 178, - 179, 189, 190, 191, 193, 196, 197, 198, 200, 201, - 204, 207, 208, 209, 210, 211, 212, 220, 223, 229, - 230, 231, 232, 233, 234, 235, 238, 239, 240, 241, - 247, 250, 258, 259, 269, 276, 279, 145, 266, 280, - 422, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 195, 0, 0, 0, 0, 357, 0, - 0, 0, 131, 0, 356, 0, 0, 0, 163, 0, - 0, 0, 237, 123, 171, 169, 255, 136, 132, 130, - 122, 152, 175, 205, 252, 199, 400, 166, 0, 0, - 245, 183, 0, 0, 0, 0, 0, 391, 392, 0, - 0, 0, 0, 0, 0, 0, 0, 61, 0, 0, - 96, 97, 98, 378, 377, 380, 381, 382, 383, 0, - 0, 118, 379, 384, 385, 386, 0, 0, 0, 0, - 354, 371, 0, 399, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 368, 369, 0, 0, 0, 0, 414, - 0, 370, 0, 0, 363, 364, 366, 365, 367, 372, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 142, - 413, 0, 0, 308, 0, 0, 411, 0, 216, 0, - 249, 146, 162, 114, 159, 100, 110, 0, 144, 192, - 224, 228, 0, 0, 0, 124, 0, 226, 203, 268, - 0, 206, 225, 167, 257, 217, 267, 277, 278, 253, - 275, 286, 242, 103, 251, 265, 119, 236, 0, 0, - 0, 105, 263, 248, 181, 156, 157, 104, 0, 222, - 129, 140, 126, 194, 260, 261, 125, 289, 111, 274, - 107, 112, 273, 188, 256, 264, 182, 174, 106, 262, - 180, 173, 161, 135, 148, 214, 170, 215, 149, 185, - 184, 186, 0, 0, 0, 246, 271, 290, 116, 0, - 254, 282, 285, 0, 218, 117, 141, 134, 213, 139, - 164, 281, 283, 284, 187, 113, 151, 243, 160, 168, - 221, 288, 202, 227, 120, 270, 244, 401, 412, 407, - 408, 405, 406, 404, 403, 402, 415, 393, 394, 395, - 396, 398, 0, 409, 410, 397, 99, 108, 165, 287, - 219, 138, 272, 0, 0, 128, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 101, 102, - 109, 115, 121, 127, 133, 137, 143, 147, 150, 153, - 154, 155, 158, 172, 176, 177, 178, 179, 189, 190, - 191, 193, 196, 197, 198, 200, 201, 204, 207, 208, - 209, 210, 211, 212, 220, 223, 229, 230, 231, 232, - 233, 234, 235, 238, 239, 240, 241, 247, 250, 258, - 259, 269, 276, 279, 145, 266, 280, 195, 0, 0, - 0, 0, 357, 0, 0, 0, 131, 0, 356, 0, - 0, 0, 163, 0, 0, 0, 237, 123, 171, 169, - 255, 136, 132, 130, 122, 152, 175, 205, 252, 199, - 400, 166, 0, 0, 245, 183, 0, 0, 0, 0, - 0, 391, 392, 0, 0, 0, 0, 0, 0, 0, - 0, 61, 0, 0, 96, 97, 98, 378, 377, 380, - 381, 382, 383, 0, 0, 118, 379, 384, 385, 386, - 0, 0, 0, 0, 354, 371, 0, 399, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 368, 369, 0, - 0, 0, 0, 414, 0, 370, 0, 0, 363, 364, - 366, 365, 367, 372, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 142, 413, 0, 0, 308, 0, 0, - 411, 0, 216, 0, 249, 146, 162, 114, 159, 100, - 110, 0, 144, 192, 224, 228, 0, 0, 0, 124, - 0, 226, 203, 268, 0, 206, 225, 167, 257, 217, - 267, 277, 278, 253, 275, 286, 242, 103, 251, 265, - 119, 236, 0, 0, 0, 105, 263, 248, 181, 156, - 157, 104, 0, 222, 129, 140, 126, 194, 260, 261, - 125, 289, 111, 274, 107, 112, 273, 188, 256, 264, - 182, 174, 106, 262, 180, 173, 161, 135, 148, 214, - 170, 215, 149, 185, 184, 186, 0, 0, 0, 246, - 271, 290, 116, 0, 254, 282, 285, 0, 218, 117, - 141, 134, 213, 139, 164, 281, 283, 284, 187, 113, - 151, 243, 160, 168, 221, 288, 202, 227, 120, 270, - 244, 401, 412, 407, 408, 405, 406, 404, 403, 402, - 415, 393, 394, 395, 396, 398, 0, 409, 410, 397, - 99, 108, 165, 287, 219, 138, 272, 0, 0, 128, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 101, 102, 109, 115, 121, 127, 133, 137, - 143, 147, 150, 153, 154, 155, 158, 172, 176, 177, - 178, 179, 189, 190, 191, 193, 196, 197, 198, 200, - 201, 204, 207, 208, 209, 210, 211, 212, 220, 223, - 229, 230, 231, 232, 233, 234, 235, 238, 239, 240, - 241, 247, 250, 258, 259, 269, 276, 279, 145, 266, - 280, 195, 0, 0, 0, 0, 0, 0, 0, 0, - 131, 0, 0, 0, 0, 0, 163, 0, 0, 0, - 237, 123, 171, 169, 255, 136, 132, 130, 122, 152, - 175, 205, 252, 199, 400, 166, 0, 0, 245, 183, - 0, 0, 0, 0, 0, 391, 392, 0, 0, 0, - 0, 0, 0, 0, 0, 61, 0, 0, 96, 97, - 98, 378, 377, 380, 381, 382, 383, 0, 0, 118, - 379, 384, 385, 386, 0, 0, 0, 0, 0, 371, - 0, 399, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 368, 369, 0, 0, 0, 0, 414, 0, 370, - 0, 0, 363, 364, 366, 365, 367, 372, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 142, 413, 0, - 0, 308, 0, 0, 411, 0, 216, 0, 249, 146, - 162, 114, 159, 100, 110, 0, 144, 192, 224, 228, - 0, 0, 0, 124, 0, 226, 203, 268, 1718, 206, - 225, 167, 257, 217, 267, 277, 278, 253, 275, 286, - 242, 103, 251, 265, 119, 236, 0, 0, 0, 105, - 263, 248, 181, 156, 157, 104, 0, 222, 129, 140, - 126, 194, 260, 261, 125, 289, 111, 274, 107, 112, - 273, 188, 256, 264, 182, 174, 106, 262, 180, 173, - 161, 135, 148, 214, 170, 215, 149, 185, 184, 186, - 0, 0, 0, 246, 271, 290, 116, 0, 254, 282, - 285, 0, 218, 117, 141, 134, 213, 139, 164, 281, - 283, 284, 187, 113, 151, 243, 160, 168, 221, 288, - 202, 227, 120, 270, 244, 401, 412, 407, 408, 405, - 406, 404, 403, 402, 415, 393, 394, 395, 396, 398, - 0, 409, 410, 397, 99, 108, 165, 287, 219, 138, - 272, 0, 0, 128, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 101, 102, 109, 115, - 121, 127, 133, 137, 143, 147, 150, 153, 154, 155, - 158, 172, 176, 177, 178, 179, 189, 190, 191, 193, - 196, 197, 198, 200, 201, 204, 207, 208, 209, 210, - 211, 212, 220, 223, 229, 230, 231, 232, 233, 234, - 235, 238, 239, 240, 241, 247, 250, 258, 259, 269, - 276, 279, 145, 266, 280, 195, 0, 0, 0, 0, - 0, 0, 0, 0, 131, 0, 0, 0, 0, 0, - 163, 0, 0, 0, 237, 123, 171, 169, 255, 136, - 132, 130, 122, 152, 175, 205, 252, 199, 400, 166, - 0, 0, 245, 183, 0, 0, 0, 0, 0, 391, - 392, 0, 0, 0, 0, 0, 0, 0, 0, 61, - 0, 429, 96, 97, 98, 378, 377, 380, 381, 382, - 383, 0, 0, 118, 379, 384, 385, 386, 0, 0, - 0, 0, 0, 371, 0, 399, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 368, 369, 0, 0, 0, - 0, 414, 0, 370, 0, 0, 363, 364, 366, 365, - 367, 372, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 142, 413, 0, 0, 308, 0, 0, 411, 0, - 216, 0, 249, 146, 162, 114, 159, 100, 110, 0, - 144, 192, 224, 228, 0, 0, 0, 124, 0, 226, - 203, 268, 0, 206, 225, 167, 257, 217, 267, 277, - 278, 253, 275, 286, 242, 103, 251, 265, 119, 236, - 0, 0, 0, 105, 263, 248, 181, 156, 157, 104, - 0, 222, 129, 140, 126, 194, 260, 261, 125, 289, - 111, 274, 107, 112, 273, 188, 256, 264, 182, 174, - 106, 262, 180, 173, 161, 135, 148, 214, 170, 215, - 149, 185, 184, 186, 0, 0, 0, 246, 271, 290, - 116, 0, 254, 282, 285, 0, 218, 117, 141, 134, - 213, 139, 164, 281, 283, 284, 187, 113, 151, 243, - 160, 168, 221, 288, 202, 227, 120, 270, 244, 401, - 412, 407, 408, 405, 406, 404, 403, 402, 415, 393, - 394, 395, 396, 398, 0, 409, 410, 397, 99, 108, - 165, 287, 219, 138, 272, 0, 0, 128, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 101, 102, 109, 115, 121, 127, 133, 137, 143, 147, - 150, 153, 154, 155, 158, 172, 176, 177, 178, 179, - 189, 190, 191, 193, 196, 197, 198, 200, 201, 204, - 207, 208, 209, 210, 211, 212, 220, 223, 229, 230, - 231, 232, 233, 234, 235, 238, 239, 240, 241, 247, - 250, 258, 259, 269, 276, 279, 145, 266, 280, 195, - 0, 0, 0, 0, 0, 0, 0, 0, 131, 0, - 0, 0, 0, 0, 163, 0, 0, 0, 237, 123, - 171, 169, 255, 136, 132, 130, 122, 152, 175, 205, - 252, 199, 400, 166, 0, 0, 245, 183, 0, 0, - 0, 0, 0, 391, 392, 0, 0, 0, 0, 0, - 0, 0, 0, 61, 0, 0, 96, 97, 98, 378, - 377, 380, 381, 382, 383, 0, 0, 118, 379, 384, - 385, 386, 0, 0, 0, 0, 0, 371, 0, 399, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 368, - 369, 0, 0, 0, 0, 414, 0, 370, 0, 0, - 363, 364, 366, 365, 367, 372, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 142, 413, 0, 0, 308, - 0, 0, 411, 0, 216, 0, 249, 146, 162, 114, - 159, 100, 110, 0, 144, 192, 224, 228, 0, 0, - 0, 124, 0, 226, 203, 268, 0, 206, 225, 167, - 257, 217, 267, 277, 278, 253, 275, 286, 242, 103, - 251, 265, 119, 236, 0, 0, 0, 105, 263, 248, - 181, 156, 157, 104, 0, 222, 129, 140, 126, 194, - 260, 261, 125, 289, 111, 274, 107, 112, 273, 188, - 256, 264, 182, 174, 106, 262, 180, 173, 161, 135, - 148, 214, 170, 215, 149, 185, 184, 186, 0, 0, - 0, 246, 271, 290, 116, 0, 254, 282, 285, 0, - 218, 117, 141, 134, 213, 139, 164, 281, 283, 284, - 187, 113, 151, 243, 160, 168, 221, 288, 202, 227, - 120, 270, 244, 401, 412, 407, 408, 405, 406, 404, - 403, 402, 415, 393, 394, 395, 396, 398, 0, 409, - 410, 397, 99, 108, 165, 287, 219, 138, 272, 0, - 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 101, 102, 109, 115, 121, 127, - 133, 137, 143, 147, 150, 153, 154, 155, 158, 172, - 176, 177, 178, 179, 189, 190, 191, 193, 196, 197, - 198, 200, 201, 204, 207, 208, 209, 210, 211, 212, - 220, 223, 229, 230, 231, 232, 233, 234, 235, 238, - 239, 240, 241, 247, 250, 258, 259, 269, 276, 279, - 145, 266, 280, 195, 0, 0, 0, 0, 0, 0, - 0, 0, 131, 0, 0, 0, 0, 0, 163, 0, - 0, 0, 237, 123, 171, 169, 255, 136, 132, 130, - 122, 152, 175, 205, 252, 199, 0, 166, 0, 0, - 245, 183, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 96, 97, 98, 0, 0, 0, 0, 0, 0, 0, - 0, 118, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 681, - 680, 690, 691, 683, 684, 685, 686, 687, 688, 689, - 682, 0, 0, 692, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 142, - 0, 0, 0, 308, 0, 0, 0, 0, 216, 0, - 249, 146, 162, 114, 159, 100, 110, 0, 144, 192, - 224, 228, 0, 0, 0, 124, 0, 226, 203, 268, - 0, 206, 225, 167, 257, 217, 267, 277, 278, 253, - 275, 286, 242, 103, 251, 265, 119, 236, 0, 0, - 0, 105, 263, 248, 181, 156, 157, 104, 0, 222, - 129, 140, 126, 194, 260, 261, 125, 289, 111, 274, - 107, 112, 273, 188, 256, 264, 182, 174, 106, 262, - 180, 173, 161, 135, 148, 214, 170, 215, 149, 185, - 184, 186, 0, 0, 0, 246, 271, 290, 116, 0, - 254, 282, 285, 0, 218, 117, 141, 134, 213, 139, - 164, 281, 283, 284, 187, 113, 151, 243, 160, 168, - 221, 288, 202, 227, 120, 270, 244, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 99, 108, 165, 287, - 219, 138, 272, 0, 0, 128, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 101, 102, - 109, 115, 121, 127, 133, 137, 143, 147, 150, 153, - 154, 155, 158, 172, 176, 177, 178, 179, 189, 190, - 191, 193, 196, 197, 198, 200, 201, 204, 207, 208, - 209, 210, 211, 212, 220, 223, 229, 230, 231, 232, - 233, 234, 235, 238, 239, 240, 241, 247, 250, 258, - 259, 269, 276, 279, 145, 266, 280, 195, 0, 0, - 0, 777, 0, 0, 0, 0, 131, 0, 0, 0, - 0, 0, 163, 0, 0, 0, 237, 123, 171, 169, - 255, 136, 132, 130, 122, 152, 175, 205, 252, 199, - 0, 166, 0, 0, 245, 183, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 96, 97, 98, 0, 779, 0, - 0, 0, 0, 0, 0, 118, 0, 0, 0, 0, - 0, 670, 671, 669, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 672, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 142, 0, 0, 0, 308, 0, 0, - 0, 0, 216, 0, 249, 146, 162, 114, 159, 100, - 110, 0, 144, 192, 224, 228, 0, 0, 0, 124, - 0, 226, 203, 268, 0, 206, 225, 167, 257, 217, - 267, 277, 278, 253, 275, 286, 242, 103, 251, 265, - 119, 236, 0, 0, 0, 105, 263, 248, 181, 156, - 157, 104, 0, 222, 129, 140, 126, 194, 260, 261, - 125, 289, 111, 274, 107, 112, 273, 188, 256, 264, - 182, 174, 106, 262, 180, 173, 161, 135, 148, 214, - 170, 215, 149, 185, 184, 186, 0, 0, 0, 246, - 271, 290, 116, 0, 254, 282, 285, 0, 218, 117, - 141, 134, 213, 139, 164, 281, 283, 284, 187, 113, - 151, 243, 160, 168, 221, 288, 202, 227, 120, 270, - 244, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 99, 108, 165, 287, 219, 138, 272, 0, 0, 128, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 101, 102, 109, 115, 121, 127, 133, 137, - 143, 147, 150, 153, 154, 155, 158, 172, 176, 177, - 178, 179, 189, 190, 191, 193, 196, 197, 198, 200, - 201, 204, 207, 208, 209, 210, 211, 212, 220, 223, - 229, 230, 231, 232, 233, 234, 235, 238, 239, 240, - 241, 247, 250, 258, 259, 269, 276, 279, 145, 266, - 280, 195, 0, 0, 0, 0, 0, 0, 0, 0, - 131, 0, 0, 0, 0, 0, 163, 0, 0, 0, - 237, 123, 171, 169, 255, 136, 132, 130, 122, 152, - 175, 205, 252, 199, 0, 166, 0, 0, 245, 183, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 96, 97, - 98, 0, 0, 0, 0, 0, 0, 0, 0, 118, - 0, 0, 0, 0, 0, 88, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 142, 90, 91, - 0, 87, 0, 0, 0, 92, 216, 0, 249, 146, - 162, 114, 159, 100, 110, 0, 144, 192, 224, 228, - 0, 0, 0, 124, 0, 226, 203, 268, 0, 206, - 225, 167, 257, 217, 267, 277, 278, 253, 275, 286, - 242, 103, 251, 265, 119, 236, 0, 0, 0, 105, - 263, 248, 181, 156, 157, 104, 0, 222, 129, 140, - 126, 194, 260, 261, 125, 289, 111, 274, 107, 112, - 273, 188, 256, 264, 182, 174, 106, 262, 180, 173, - 161, 135, 148, 214, 170, 215, 149, 185, 184, 186, - 0, 0, 0, 246, 271, 290, 116, 0, 254, 282, - 285, 0, 218, 117, 141, 134, 213, 139, 164, 281, - 283, 284, 187, 113, 151, 243, 160, 168, 221, 288, - 202, 227, 120, 270, 244, 0, 89, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 99, 108, 165, 287, 219, 138, - 272, 0, 0, 128, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 101, 102, 109, 115, - 121, 127, 133, 137, 143, 147, 150, 153, 154, 155, - 158, 172, 176, 177, 178, 179, 189, 190, 191, 193, - 196, 197, 198, 200, 201, 204, 207, 208, 209, 210, - 211, 212, 220, 223, 229, 230, 231, 232, 233, 234, - 235, 238, 239, 240, 241, 247, 250, 258, 259, 269, - 276, 279, 145, 266, 280, 195, 0, 0, 0, 0, - 0, 0, 0, 0, 131, 1099, 0, 0, 0, 0, - 163, 0, 0, 0, 237, 123, 171, 169, 255, 136, - 132, 130, 122, 152, 175, 205, 252, 199, 0, 166, - 0, 0, 245, 183, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 96, 97, 98, 0, 0, 0, 0, 0, - 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 142, 0, 0, 1098, 308, 0, 0, 0, 1094, - 1091, 0, 1092, 1093, 162, 589, 159, 100, 110, 1089, - 1096, 192, 224, 228, 0, 0, 0, 124, 0, 226, - 203, 268, 0, 206, 225, 167, 257, 217, 267, 277, - 278, 253, 275, 286, 242, 103, 251, 265, 119, 236, - 0, 0, 0, 105, 263, 248, 181, 156, 157, 104, - 0, 222, 129, 140, 126, 194, 260, 261, 125, 289, - 111, 274, 107, 112, 273, 188, 256, 264, 182, 174, - 106, 262, 180, 173, 161, 135, 148, 214, 170, 215, - 149, 185, 184, 186, 0, 0, 0, 246, 271, 290, - 116, 0, 254, 282, 285, 0, 218, 117, 141, 134, - 213, 139, 164, 281, 283, 284, 187, 113, 151, 243, - 160, 168, 221, 288, 202, 227, 120, 270, 244, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 99, 108, - 165, 287, 219, 138, 272, 0, 0, 128, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 101, 102, 109, 115, 121, 127, 133, 137, 143, 147, - 150, 153, 154, 155, 158, 172, 176, 177, 178, 179, - 189, 190, 191, 193, 196, 197, 198, 200, 201, 204, - 207, 208, 209, 210, 211, 212, 220, 223, 229, 230, - 231, 232, 233, 234, 235, 238, 239, 240, 241, 247, - 250, 258, 259, 269, 276, 279, 145, 266, 280, 31, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 195, 0, 0, 0, 0, 0, 0, 0, - 0, 131, 0, 0, 0, 0, 0, 163, 0, 0, - 0, 237, 123, 171, 169, 255, 136, 132, 130, 122, - 152, 175, 205, 252, 199, 0, 166, 0, 0, 245, - 183, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 61, 0, 429, 96, - 97, 98, 0, 0, 0, 0, 0, 0, 0, 0, - 118, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 142, 0, - 0, 0, 308, 0, 0, 0, 0, 216, 0, 249, - 146, 162, 114, 159, 100, 110, 0, 144, 192, 224, - 228, 0, 0, 0, 124, 0, 226, 203, 268, 0, - 206, 225, 167, 257, 217, 267, 277, 278, 253, 275, - 286, 242, 103, 251, 265, 119, 236, 0, 0, 0, - 105, 263, 248, 181, 156, 157, 104, 0, 222, 129, - 140, 126, 194, 260, 261, 125, 289, 111, 274, 107, - 112, 273, 188, 256, 264, 182, 174, 106, 262, 180, - 173, 161, 135, 148, 214, 170, 215, 149, 185, 184, - 186, 0, 0, 0, 246, 271, 290, 116, 0, 254, - 282, 285, 0, 218, 117, 141, 134, 213, 139, 164, - 281, 283, 284, 187, 113, 151, 243, 160, 168, 221, - 288, 202, 227, 120, 270, 244, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 99, 108, 165, 287, 219, - 138, 272, 0, 0, 128, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 101, 102, 109, - 115, 121, 127, 133, 137, 143, 147, 150, 153, 154, - 155, 158, 172, 176, 177, 178, 179, 189, 190, 191, - 193, 196, 197, 198, 200, 201, 204, 207, 208, 209, - 210, 211, 212, 220, 223, 229, 230, 231, 232, 233, - 234, 235, 238, 239, 240, 241, 247, 250, 258, 259, - 269, 276, 279, 145, 266, 280, 195, 0, 0, 0, - 1056, 0, 0, 0, 0, 131, 0, 0, 0, 0, - 0, 163, 0, 0, 0, 237, 123, 171, 169, 255, - 136, 132, 130, 122, 152, 175, 205, 252, 199, 0, - 166, 0, 0, 245, 183, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 96, 97, 98, 0, 1058, 0, 0, - 0, 0, 0, 0, 118, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 142, 0, 0, 0, 308, 0, 0, 0, - 0, 216, 0, 249, 146, 162, 114, 159, 100, 110, - 0, 144, 192, 224, 228, 0, 0, 0, 124, 0, - 226, 203, 268, 0, 206, 225, 167, 257, 217, 267, - 277, 278, 253, 275, 286, 242, 103, 251, 265, 119, - 236, 0, 0, 0, 105, 263, 248, 181, 156, 157, - 104, 0, 222, 129, 140, 126, 194, 260, 261, 125, - 289, 111, 274, 107, 112, 273, 188, 256, 264, 182, - 174, 106, 262, 180, 173, 161, 135, 148, 214, 170, - 215, 149, 185, 184, 186, 0, 0, 0, 246, 271, - 290, 116, 0, 254, 282, 285, 0, 218, 117, 141, - 134, 213, 139, 164, 281, 283, 284, 187, 113, 151, - 243, 160, 168, 221, 288, 202, 227, 120, 270, 244, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, - 108, 165, 287, 219, 138, 272, 0, 0, 128, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 101, 102, 109, 115, 121, 127, 133, 137, 143, - 147, 150, 153, 154, 155, 158, 172, 176, 177, 178, - 179, 189, 190, 191, 193, 196, 197, 198, 200, 201, - 204, 207, 208, 209, 210, 211, 212, 220, 223, 229, - 230, 231, 232, 233, 234, 235, 238, 239, 240, 241, - 247, 250, 258, 259, 269, 276, 279, 145, 266, 280, - 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 195, 0, 0, 0, 0, 0, 0, - 0, 0, 131, 0, 0, 0, 0, 0, 163, 0, - 0, 0, 237, 123, 171, 169, 255, 136, 132, 130, - 122, 152, 175, 205, 252, 199, 0, 166, 0, 0, - 245, 183, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 61, 0, 0, - 96, 97, 98, 0, 0, 0, 0, 0, 0, 0, - 0, 118, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 142, - 0, 0, 0, 308, 0, 0, 0, 0, 216, 0, - 249, 146, 162, 114, 159, 100, 110, 0, 144, 192, - 224, 228, 0, 0, 0, 124, 0, 226, 203, 268, - 0, 206, 225, 167, 257, 217, 267, 277, 278, 253, - 275, 286, 242, 103, 251, 265, 119, 236, 0, 0, - 0, 105, 263, 248, 181, 156, 157, 104, 0, 222, - 129, 140, 126, 194, 260, 261, 125, 289, 111, 274, - 107, 112, 273, 188, 256, 264, 182, 174, 106, 262, - 180, 173, 161, 135, 148, 214, 170, 215, 149, 185, - 184, 186, 0, 0, 0, 246, 271, 290, 116, 0, - 254, 282, 285, 0, 218, 117, 141, 134, 213, 139, - 164, 281, 283, 284, 187, 113, 151, 243, 160, 168, - 221, 288, 202, 227, 120, 270, 244, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 99, 108, 165, 287, - 219, 138, 272, 0, 0, 128, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 101, 102, - 109, 115, 121, 127, 133, 137, 143, 147, 150, 153, - 154, 155, 158, 172, 176, 177, 178, 179, 189, 190, - 191, 193, 196, 197, 198, 200, 201, 204, 207, 208, - 209, 210, 211, 212, 220, 223, 229, 230, 231, 232, - 233, 234, 235, 238, 239, 240, 241, 247, 250, 258, - 259, 269, 276, 279, 145, 266, 280, 195, 0, 0, - 0, 1056, 0, 0, 0, 0, 131, 0, 0, 0, - 0, 0, 163, 0, 0, 0, 237, 123, 171, 169, - 255, 136, 132, 130, 122, 152, 175, 205, 252, 199, - 0, 166, 0, 0, 245, 183, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 96, 97, 98, 0, 1058, 0, - 0, 0, 0, 0, 0, 118, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 142, 0, 0, 0, 308, 0, 0, - 0, 0, 216, 0, 249, 146, 162, 114, 159, 100, - 110, 0, 144, 192, 224, 228, 0, 0, 0, 124, - 0, 226, 203, 268, 0, 1054, 225, 167, 257, 217, - 267, 277, 278, 253, 275, 286, 242, 103, 251, 265, - 119, 236, 0, 0, 0, 105, 263, 248, 181, 156, - 157, 104, 0, 222, 129, 140, 126, 194, 260, 261, - 125, 289, 111, 274, 107, 112, 273, 188, 256, 264, - 182, 174, 106, 262, 180, 173, 161, 135, 148, 214, - 170, 215, 149, 185, 184, 186, 0, 0, 0, 246, - 271, 290, 116, 0, 254, 282, 285, 0, 218, 117, - 141, 134, 213, 139, 164, 281, 283, 284, 187, 113, - 151, 243, 160, 168, 221, 288, 202, 227, 120, 270, - 244, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 99, 108, 165, 287, 219, 138, 272, 0, 0, 128, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 101, 102, 109, 115, 121, 127, 133, 137, - 143, 147, 150, 153, 154, 155, 158, 172, 176, 177, - 178, 179, 189, 190, 191, 193, 196, 197, 198, 200, - 201, 204, 207, 208, 209, 210, 211, 212, 220, 223, - 229, 230, 231, 232, 233, 234, 235, 238, 239, 240, - 241, 247, 250, 258, 259, 269, 276, 279, 145, 266, - 280, 195, 0, 0, 0, 0, 0, 0, 0, 0, - 131, 0, 0, 0, 0, 0, 163, 0, 0, 0, - 237, 123, 171, 169, 255, 136, 132, 130, 122, 152, - 175, 205, 252, 199, 0, 166, 0, 0, 245, 183, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 96, 97, - 98, 0, 0, 1021, 0, 0, 1022, 0, 0, 118, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 142, 0, 0, - 0, 308, 0, 0, 0, 0, 216, 0, 249, 146, - 162, 114, 159, 100, 110, 0, 144, 192, 224, 228, - 0, 0, 0, 124, 0, 226, 203, 268, 0, 206, - 225, 167, 257, 217, 267, 277, 278, 253, 275, 286, - 242, 103, 251, 265, 119, 236, 0, 0, 0, 105, - 263, 248, 181, 156, 157, 104, 0, 222, 129, 140, - 126, 194, 260, 261, 125, 289, 111, 274, 107, 112, - 273, 188, 256, 264, 182, 174, 106, 262, 180, 173, - 161, 135, 148, 214, 170, 215, 149, 185, 184, 186, - 0, 0, 0, 246, 271, 290, 116, 0, 254, 282, - 285, 0, 218, 117, 141, 134, 213, 139, 164, 281, - 283, 284, 187, 113, 151, 243, 160, 168, 221, 288, - 202, 227, 120, 270, 244, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 99, 108, 165, 287, 219, 138, - 272, 0, 0, 128, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 101, 102, 109, 115, - 121, 127, 133, 137, 143, 147, 150, 153, 154, 155, - 158, 172, 176, 177, 178, 179, 189, 190, 191, 193, - 196, 197, 198, 200, 201, 204, 207, 208, 209, 210, - 211, 212, 220, 223, 229, 230, 231, 232, 233, 234, - 235, 238, 239, 240, 241, 247, 250, 258, 259, 269, - 276, 279, 145, 266, 280, 195, 0, 0, 0, 0, - 0, 0, 0, 0, 131, 0, 811, 0, 0, 0, - 163, 0, 0, 0, 237, 123, 171, 169, 255, 136, - 132, 130, 122, 152, 175, 205, 252, 199, 0, 166, - 0, 0, 245, 183, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 96, 97, 98, 0, 810, 0, 0, 0, - 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 142, 0, 0, 0, 308, 0, 0, 0, 0, - 216, 0, 249, 146, 162, 114, 159, 100, 110, 0, - 144, 192, 224, 228, 0, 0, 0, 124, 0, 226, - 203, 268, 0, 206, 225, 167, 257, 217, 267, 277, - 278, 253, 275, 286, 242, 103, 251, 265, 119, 236, - 0, 0, 0, 105, 263, 248, 181, 156, 157, 104, - 0, 222, 129, 140, 126, 194, 260, 261, 125, 289, - 111, 274, 107, 112, 273, 188, 256, 264, 182, 174, - 106, 262, 180, 173, 161, 135, 148, 214, 170, 215, - 149, 185, 184, 186, 0, 0, 0, 246, 271, 290, - 116, 0, 254, 282, 285, 0, 218, 117, 141, 134, - 213, 139, 164, 281, 283, 284, 187, 113, 151, 243, - 160, 168, 221, 288, 202, 227, 120, 270, 244, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 99, 108, - 165, 287, 219, 138, 272, 0, 0, 128, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 101, 102, 109, 115, 121, 127, 133, 137, 143, 147, - 150, 153, 154, 155, 158, 172, 176, 177, 178, 179, - 189, 190, 191, 193, 196, 197, 198, 200, 201, 204, - 207, 208, 209, 210, 211, 212, 220, 223, 229, 230, - 231, 232, 233, 234, 235, 238, 239, 240, 241, 247, - 250, 258, 259, 269, 276, 279, 145, 266, 280, 195, - 0, 0, 0, 0, 0, 0, 0, 0, 131, 0, - 0, 0, 0, 0, 163, 0, 0, 0, 237, 123, - 171, 169, 255, 136, 132, 130, 122, 152, 175, 205, - 252, 199, 0, 166, 0, 0, 245, 183, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 96, 97, 98, 0, - 0, 0, 0, 0, 0, 0, 0, 118, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 583, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 142, 0, 0, 0, 308, - 0, 0, 0, 0, 216, 0, 249, 146, 162, 589, - 159, 100, 110, 587, 144, 192, 224, 228, 0, 0, - 0, 124, 0, 226, 203, 268, 0, 206, 225, 167, - 257, 217, 267, 277, 278, 253, 275, 286, 242, 103, - 251, 265, 119, 236, 0, 0, 0, 105, 263, 248, - 181, 156, 157, 104, 0, 222, 129, 140, 126, 194, - 260, 261, 125, 289, 111, 274, 107, 112, 273, 188, - 256, 264, 182, 174, 106, 262, 180, 173, 161, 135, - 148, 214, 170, 215, 149, 185, 184, 186, 0, 0, - 0, 246, 271, 290, 116, 0, 254, 282, 285, 0, - 218, 117, 141, 134, 213, 139, 164, 281, 283, 284, - 187, 113, 151, 243, 160, 168, 221, 288, 202, 227, - 120, 270, 244, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 99, 108, 165, 287, 219, 138, 272, 0, - 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 101, 102, 109, 115, 121, 127, - 133, 137, 143, 147, 150, 153, 154, 155, 158, 172, - 176, 177, 178, 179, 189, 190, 191, 193, 196, 197, - 198, 200, 201, 204, 207, 208, 209, 210, 211, 212, - 220, 223, 229, 230, 231, 232, 233, 234, 235, 238, - 239, 240, 241, 247, 250, 258, 259, 269, 276, 279, - 145, 266, 280, 195, 0, 0, 0, 0, 0, 0, - 0, 0, 131, 0, 0, 0, 0, 0, 163, 0, - 0, 0, 237, 123, 171, 169, 255, 136, 132, 130, - 122, 152, 175, 205, 252, 199, 0, 166, 0, 0, - 245, 183, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 429, - 96, 97, 98, 0, 0, 0, 0, 0, 0, 0, - 0, 118, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 142, - 0, 0, 0, 308, 0, 0, 0, 0, 216, 0, - 249, 146, 162, 114, 159, 100, 110, 0, 144, 192, - 224, 228, 0, 0, 0, 124, 0, 226, 203, 268, - 0, 206, 225, 167, 257, 217, 267, 277, 278, 253, - 275, 286, 242, 103, 251, 265, 119, 236, 0, 0, - 0, 105, 263, 248, 181, 156, 157, 104, 0, 222, - 129, 140, 126, 194, 260, 261, 125, 289, 111, 274, - 107, 112, 273, 188, 256, 264, 182, 174, 106, 262, - 180, 173, 161, 135, 148, 214, 170, 215, 149, 185, - 184, 186, 0, 0, 0, 246, 271, 290, 116, 0, - 254, 282, 285, 0, 218, 117, 141, 134, 213, 139, - 164, 281, 283, 284, 187, 113, 151, 243, 160, 168, - 221, 288, 202, 227, 120, 270, 244, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 99, 108, 165, 287, - 219, 138, 272, 0, 0, 128, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 101, 102, - 109, 115, 121, 127, 133, 137, 143, 147, 150, 153, - 154, 155, 158, 172, 176, 177, 178, 179, 189, 190, - 191, 193, 196, 197, 198, 200, 201, 204, 207, 208, - 209, 210, 211, 212, 220, 223, 229, 230, 231, 232, - 233, 234, 235, 238, 239, 240, 241, 247, 250, 258, - 259, 269, 276, 279, 145, 266, 280, 195, 0, 0, - 0, 0, 0, 0, 0, 0, 131, 0, 0, 0, - 0, 0, 163, 0, 0, 0, 237, 123, 171, 169, - 255, 136, 132, 130, 122, 152, 175, 205, 252, 199, - 0, 166, 0, 0, 245, 183, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 61, 0, 0, 96, 97, 98, 0, 0, 0, - 0, 0, 0, 0, 0, 118, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 142, 0, 0, 0, 308, 0, 0, - 0, 0, 216, 0, 249, 146, 162, 114, 159, 100, - 110, 0, 144, 192, 224, 228, 0, 0, 0, 124, - 0, 226, 203, 268, 0, 206, 225, 167, 257, 217, - 267, 277, 278, 253, 275, 286, 242, 103, 251, 265, - 119, 236, 0, 0, 0, 105, 263, 248, 181, 156, - 157, 104, 0, 222, 129, 140, 126, 194, 260, 261, - 125, 289, 111, 274, 107, 112, 273, 188, 256, 264, - 182, 174, 106, 262, 180, 173, 161, 135, 148, 214, - 170, 215, 149, 185, 184, 186, 0, 0, 0, 246, - 271, 290, 116, 0, 254, 282, 285, 0, 218, 117, - 141, 134, 213, 139, 164, 281, 283, 284, 187, 113, - 151, 243, 160, 168, 221, 288, 202, 227, 120, 270, - 244, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 99, 108, 165, 287, 219, 138, 272, 0, 0, 128, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 101, 102, 109, 115, 121, 127, 133, 137, - 143, 147, 150, 153, 154, 155, 158, 172, 176, 177, - 178, 179, 189, 190, 191, 193, 196, 197, 198, 200, - 201, 204, 207, 208, 209, 210, 211, 212, 220, 223, - 229, 230, 231, 232, 233, 234, 235, 238, 239, 240, - 241, 247, 250, 258, 259, 269, 276, 279, 145, 266, - 280, 195, 0, 0, 0, 0, 0, 0, 0, 0, - 131, 0, 0, 0, 0, 0, 163, 0, 0, 0, - 237, 123, 171, 169, 255, 136, 132, 130, 122, 152, - 175, 205, 252, 199, 0, 166, 0, 0, 245, 183, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 96, 97, - 98, 0, 1058, 0, 0, 0, 0, 0, 0, 118, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 142, 0, 0, - 0, 308, 0, 0, 0, 0, 216, 0, 249, 146, - 162, 114, 159, 100, 110, 0, 144, 192, 224, 228, - 0, 0, 0, 124, 0, 226, 203, 268, 0, 206, - 225, 167, 257, 217, 267, 277, 278, 253, 275, 286, - 242, 103, 251, 265, 119, 236, 0, 0, 0, 105, - 263, 248, 181, 156, 157, 104, 0, 222, 129, 140, - 126, 194, 260, 261, 125, 289, 111, 274, 107, 112, - 273, 188, 256, 264, 182, 174, 106, 262, 180, 173, - 161, 135, 148, 214, 170, 215, 149, 185, 184, 186, - 0, 0, 0, 246, 271, 290, 116, 0, 254, 282, - 285, 0, 218, 117, 141, 134, 213, 139, 164, 281, - 283, 284, 187, 113, 151, 243, 160, 168, 221, 288, - 202, 227, 120, 270, 244, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 99, 108, 165, 287, 219, 138, - 272, 0, 0, 128, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 101, 102, 109, 115, - 121, 127, 133, 137, 143, 147, 150, 153, 154, 155, - 158, 172, 176, 177, 178, 179, 189, 190, 191, 193, - 196, 197, 198, 200, 201, 204, 207, 208, 209, 210, - 211, 212, 220, 223, 229, 230, 231, 232, 233, 234, - 235, 238, 239, 240, 241, 247, 250, 258, 259, 269, - 276, 279, 145, 266, 280, 195, 0, 0, 0, 0, - 0, 0, 0, 0, 131, 0, 0, 0, 0, 0, - 163, 0, 0, 0, 237, 123, 171, 169, 255, 136, - 132, 130, 122, 152, 175, 205, 252, 199, 0, 166, - 0, 0, 245, 183, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 96, 97, 98, 0, 779, 0, 0, 0, - 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 142, 0, 0, 0, 308, 0, 0, 0, 0, - 216, 0, 249, 146, 162, 114, 159, 100, 110, 0, - 144, 192, 224, 228, 0, 0, 0, 124, 0, 226, - 203, 268, 0, 206, 225, 167, 257, 217, 267, 277, - 278, 253, 275, 286, 242, 103, 251, 265, 119, 236, - 0, 0, 0, 105, 263, 248, 181, 156, 157, 104, - 0, 222, 129, 140, 126, 194, 260, 261, 125, 289, - 111, 274, 107, 112, 273, 188, 256, 264, 182, 174, - 106, 262, 180, 173, 161, 135, 148, 214, 170, 215, - 149, 185, 184, 186, 0, 0, 0, 246, 271, 290, - 116, 0, 254, 282, 285, 0, 218, 117, 141, 134, - 213, 139, 164, 281, 283, 284, 187, 113, 151, 243, - 160, 168, 221, 288, 202, 227, 120, 270, 244, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 99, 108, - 165, 287, 219, 138, 272, 0, 0, 128, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 101, 102, 109, 115, 121, 127, 133, 137, 143, 147, - 150, 153, 154, 155, 158, 172, 176, 177, 178, 179, - 189, 190, 191, 193, 196, 197, 198, 200, 201, 204, - 207, 208, 209, 210, 211, 212, 220, 223, 229, 230, - 231, 232, 233, 234, 235, 238, 239, 240, 241, 247, - 250, 258, 259, 269, 276, 279, 145, 266, 280, 793, - 0, 0, 0, 0, 0, 0, 195, 0, 0, 0, - 0, 0, 0, 0, 0, 131, 0, 0, 0, 0, - 0, 163, 0, 0, 0, 237, 123, 171, 169, 255, - 136, 132, 130, 122, 152, 175, 205, 252, 199, 0, - 166, 0, 0, 245, 183, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 96, 97, 98, 0, 0, 0, 0, - 0, 0, 0, 0, 118, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 142, 0, 0, 0, 308, 0, 0, 0, - 0, 216, 0, 249, 146, 162, 114, 159, 100, 110, - 0, 144, 192, 224, 228, 0, 0, 0, 124, 0, - 226, 203, 268, 0, 206, 225, 167, 257, 217, 267, - 277, 278, 253, 275, 286, 242, 103, 251, 265, 119, - 236, 0, 0, 0, 105, 263, 248, 181, 156, 157, - 104, 0, 222, 129, 140, 126, 194, 260, 261, 125, - 289, 111, 274, 107, 112, 273, 188, 256, 264, 182, - 174, 106, 262, 180, 173, 161, 135, 148, 214, 170, - 215, 149, 185, 184, 186, 0, 0, 0, 246, 271, - 290, 116, 0, 254, 282, 285, 0, 218, 117, 141, - 134, 213, 139, 164, 281, 283, 284, 187, 113, 151, - 243, 160, 168, 221, 288, 202, 227, 120, 270, 244, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, - 108, 165, 287, 219, 138, 272, 0, 0, 128, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 101, 102, 109, 115, 121, 127, 133, 137, 143, - 147, 150, 153, 154, 155, 158, 172, 176, 177, 178, - 179, 189, 190, 191, 193, 196, 197, 198, 200, 201, - 204, 207, 208, 209, 210, 211, 212, 220, 223, 229, - 230, 231, 232, 233, 234, 235, 238, 239, 240, 241, - 247, 250, 258, 259, 269, 276, 279, 145, 266, 280, - 195, 0, 0, 0, 0, 0, 0, 0, 783, 131, - 0, 0, 0, 0, 0, 163, 0, 0, 0, 237, - 123, 171, 169, 255, 136, 132, 130, 122, 152, 175, - 205, 252, 199, 0, 166, 0, 0, 245, 183, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 96, 97, 98, - 0, 0, 0, 0, 0, 0, 0, 0, 118, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 142, 0, 0, 0, - 308, 0, 0, 0, 0, 216, 0, 249, 146, 162, - 114, 159, 100, 110, 0, 144, 192, 224, 228, 0, - 0, 0, 124, 0, 226, 203, 268, 0, 206, 225, - 167, 257, 217, 267, 277, 278, 253, 275, 286, 242, - 103, 251, 265, 119, 236, 0, 0, 0, 105, 263, - 248, 181, 156, 157, 104, 0, 222, 129, 140, 126, - 194, 260, 261, 125, 289, 111, 274, 107, 112, 273, - 188, 256, 264, 182, 174, 106, 262, 180, 173, 161, - 135, 148, 214, 170, 215, 149, 185, 184, 186, 0, - 0, 0, 246, 271, 290, 116, 0, 254, 282, 285, - 0, 218, 117, 141, 134, 213, 139, 164, 281, 283, - 284, 187, 113, 151, 243, 160, 168, 221, 288, 202, - 227, 120, 270, 244, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 99, 108, 165, 287, 219, 138, 272, - 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 101, 102, 109, 115, 121, - 127, 133, 137, 143, 147, 150, 153, 154, 155, 158, - 172, 176, 177, 178, 179, 189, 190, 191, 193, 196, - 197, 198, 200, 201, 204, 207, 208, 209, 210, 211, - 212, 220, 223, 229, 230, 231, 232, 233, 234, 235, - 238, 239, 240, 241, 247, 250, 258, 259, 269, 276, - 279, 145, 266, 280, 195, 0, 0, 0, 0, 0, - 0, 0, 0, 131, 0, 0, 0, 0, 0, 163, - 0, 0, 0, 237, 123, 171, 169, 255, 136, 132, - 130, 122, 152, 175, 205, 252, 199, 0, 166, 0, - 0, 245, 183, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 96, 97, 98, 0, 659, 0, 0, 0, 0, - 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 142, 0, 0, 0, 308, 0, 0, 0, 0, 216, - 0, 249, 146, 162, 114, 159, 100, 110, 0, 144, - 192, 224, 228, 0, 0, 0, 124, 0, 226, 203, - 268, 0, 206, 225, 167, 257, 217, 267, 277, 278, - 253, 275, 286, 242, 103, 251, 265, 119, 236, 0, - 0, 0, 105, 263, 248, 181, 156, 157, 104, 0, - 222, 129, 140, 126, 194, 260, 261, 125, 289, 111, - 274, 107, 112, 273, 188, 256, 264, 182, 174, 106, - 262, 180, 173, 161, 135, 148, 214, 170, 215, 149, - 185, 184, 186, 0, 0, 0, 246, 271, 290, 116, - 0, 254, 282, 285, 0, 218, 117, 141, 134, 213, - 139, 164, 281, 283, 284, 187, 113, 151, 243, 160, - 168, 221, 288, 202, 227, 120, 270, 244, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 99, 108, 165, - 287, 219, 138, 272, 0, 0, 128, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, - 102, 109, 115, 121, 127, 133, 137, 143, 147, 150, - 153, 154, 155, 158, 172, 176, 177, 178, 179, 189, - 190, 191, 193, 196, 197, 198, 200, 201, 204, 207, - 208, 209, 210, 211, 212, 220, 223, 229, 230, 231, - 232, 233, 234, 235, 238, 239, 240, 241, 247, 250, - 258, 259, 269, 276, 279, 145, 266, 280, 195, 0, - 0, 0, 0, 0, 0, 0, 0, 131, 0, 0, - 0, 0, 0, 163, 0, 0, 0, 237, 123, 171, - 169, 255, 136, 132, 130, 122, 152, 175, 205, 252, - 199, 0, 166, 0, 0, 245, 183, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 96, 97, 98, 0, 0, - 0, 0, 0, 0, 0, 0, 118, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 345, 0, 142, 0, 0, 0, 308, 0, - 0, 0, 0, 216, 0, 249, 146, 162, 114, 159, - 100, 110, 0, 144, 192, 224, 228, 0, 0, 0, - 124, 0, 226, 203, 268, 0, 206, 225, 167, 257, - 217, 267, 277, 278, 253, 275, 286, 242, 103, 251, - 265, 119, 236, 0, 0, 0, 105, 263, 248, 181, - 156, 157, 104, 0, 222, 129, 140, 126, 194, 260, - 261, 125, 289, 111, 274, 107, 112, 273, 188, 256, - 264, 182, 174, 106, 262, 180, 173, 161, 135, 148, - 214, 170, 215, 149, 185, 184, 186, 0, 0, 0, - 246, 271, 290, 116, 0, 254, 282, 285, 0, 218, - 117, 141, 134, 213, 139, 164, 281, 283, 284, 187, - 113, 151, 243, 160, 168, 221, 288, 202, 227, 120, - 270, 244, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 99, 108, 165, 287, 219, 138, 272, 0, 0, - 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 101, 102, 109, 115, 121, 127, 133, - 137, 143, 147, 150, 153, 154, 155, 158, 172, 176, - 177, 178, 179, 189, 190, 191, 193, 196, 197, 198, - 200, 201, 204, 207, 208, 209, 210, 211, 212, 220, - 223, 229, 230, 231, 232, 233, 234, 235, 238, 239, - 240, 241, 247, 250, 258, 259, 269, 276, 279, 344, - 266, 280, 195, 0, 0, 0, 0, 0, 0, 0, - 0, 131, 0, 0, 0, 0, 0, 163, 0, 0, - 0, 237, 123, 171, 169, 255, 136, 132, 130, 122, - 152, 175, 205, 252, 199, 0, 166, 0, 0, 245, - 183, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, - 97, 98, 0, 0, 0, 0, 0, 0, 0, 0, - 118, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 142, 0, - 303, 0, 308, 0, 0, 0, 0, 216, 0, 249, - 146, 162, 114, 159, 100, 110, 0, 144, 192, 224, - 228, 0, 0, 0, 124, 0, 226, 203, 268, 0, - 206, 225, 167, 257, 217, 267, 277, 278, 253, 275, - 286, 242, 103, 251, 265, 119, 236, 0, 0, 0, - 105, 263, 248, 181, 156, 157, 104, 0, 222, 129, - 140, 126, 194, 260, 261, 125, 289, 111, 274, 107, - 112, 273, 188, 256, 264, 182, 174, 106, 262, 180, - 173, 161, 135, 148, 214, 170, 215, 149, 185, 184, - 186, 0, 0, 0, 246, 271, 290, 116, 0, 254, - 282, 285, 0, 218, 117, 141, 134, 213, 139, 164, - 281, 283, 284, 187, 113, 151, 243, 160, 168, 221, - 288, 202, 227, 120, 270, 244, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 99, 108, 165, 287, 219, - 138, 272, 0, 0, 128, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 101, 102, 109, - 115, 121, 127, 133, 137, 143, 147, 150, 153, 154, - 155, 158, 172, 176, 177, 178, 179, 189, 190, 191, - 193, 196, 197, 198, 200, 201, 204, 207, 208, 209, - 210, 211, 212, 220, 223, 229, 230, 231, 232, 233, - 234, 235, 238, 239, 240, 241, 247, 250, 258, 259, - 269, 276, 279, 145, 266, 280, 195, 0, 0, 0, - 0, 0, 0, 0, 0, 131, 0, 0, 0, 0, - 0, 163, 0, 0, 0, 237, 123, 171, 169, 255, - 136, 132, 130, 122, 152, 175, 205, 252, 199, 0, - 166, 0, 0, 245, 183, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 96, 97, 98, 0, 0, 0, 0, - 0, 0, 0, 0, 118, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 142, 0, 0, 0, 308, 0, 0, 0, - 0, 216, 0, 249, 146, 162, 114, 159, 100, 110, - 0, 144, 192, 224, 228, 0, 0, 0, 124, 0, - 226, 203, 268, 0, 206, 225, 167, 257, 217, 267, - 277, 278, 253, 275, 286, 242, 103, 251, 265, 119, - 236, 0, 0, 0, 105, 263, 248, 181, 156, 157, - 104, 0, 222, 129, 140, 126, 194, 260, 261, 125, - 289, 111, 274, 107, 112, 273, 188, 256, 264, 182, - 174, 106, 262, 180, 173, 161, 135, 148, 214, 170, - 215, 149, 185, 184, 186, 0, 0, 0, 246, 271, - 290, 116, 0, 254, 282, 285, 0, 218, 117, 141, - 134, 213, 139, 164, 281, 283, 284, 187, 113, 151, - 243, 160, 168, 221, 288, 202, 227, 120, 270, 244, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, - 108, 165, 287, 219, 138, 272, 0, 0, 128, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 101, 102, 109, 115, 121, 127, 133, 137, 143, - 147, 150, 153, 154, 155, 158, 172, 176, 177, 178, - 179, 189, 190, 191, 193, 196, 197, 198, 200, 201, - 204, 207, 208, 209, 210, 211, 212, 220, 223, 229, - 230, 231, 232, 233, 234, 235, 238, 239, 240, 241, - 247, 250, 258, 259, 269, 276, 279, 145, 266, 280, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1719, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1042, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1103, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1042, 0, 0, 0, 0, 590, 578, + 0, 123, 534, 593, 507, 524, 601, 525, 528, 565, + 492, 547, 229, 522, 0, 511, 487, 518, 488, 509, + 536, 161, 540, 506, 580, 550, 592, 195, 0, 512, + 240, 567, 272, 152, 203, 201, 291, 166, 162, 160, + 151, 183, 207, 239, 288, 233, 599, 198, 556, 0, + 280, 215, 0, 0, 0, 538, 582, 545, 575, 533, + 566, 497, 555, 594, 523, 563, 595, 187, 150, 130, + 226, 281, 168, 0, 0, 0, 112, 113, 114, 0, + 1129, 1130, 0, 0, 0, 0, 0, 146, 0, 560, + 589, 520, 562, 564, 603, 486, 557, 0, 490, 493, + 600, 585, 515, 516, 1353, 0, 0, 0, 0, 0, + 0, 537, 546, 572, 531, 0, 0, 0, 0, 0, + 0, 0, 0, 513, 0, 554, 0, 0, 0, 494, + 491, 0, 0, 0, 0, 535, 0, 0, 0, 496, + 0, 514, 573, 0, 484, 173, 577, 584, 532, 314, + 588, 530, 529, 591, 251, 0, 285, 177, 194, 142, + 191, 127, 138, 0, 175, 225, 259, 263, 581, 510, + 519, 153, 517, 261, 237, 304, 553, 241, 260, 199, + 293, 252, 303, 315, 316, 158, 219, 309, 289, 312, + 324, 277, 131, 287, 301, 147, 271, 0, 0, 0, + 133, 299, 284, 213, 188, 189, 132, 0, 257, 159, + 171, 155, 228, 296, 297, 154, 327, 139, 311, 135, + 140, 310, 221, 292, 300, 214, 206, 134, 298, 212, + 205, 193, 165, 179, 249, 202, 250, 180, 217, 216, + 218, 0, 489, 0, 282, 307, 328, 144, 505, 290, + 320, 323, 0, 253, 145, 172, 164, 248, 170, 196, + 319, 321, 322, 220, 141, 182, 278, 192, 200, 256, + 326, 236, 262, 148, 306, 279, 501, 504, 499, 500, + 548, 549, 596, 597, 598, 574, 495, 0, 502, 503, + 0, 579, 586, 587, 552, 126, 136, 197, 325, 254, + 169, 308, 485, 498, 157, 508, 0, 0, 521, 526, + 527, 539, 541, 542, 543, 544, 551, 558, 559, 561, + 568, 569, 570, 571, 576, 583, 602, 128, 129, 137, + 143, 149, 156, 163, 167, 174, 178, 181, 184, 185, + 186, 190, 204, 208, 209, 210, 211, 222, 223, 224, + 227, 230, 231, 232, 234, 235, 238, 242, 243, 244, + 245, 246, 247, 255, 258, 264, 265, 266, 267, 268, + 269, 270, 273, 274, 275, 276, 283, 286, 294, 295, + 305, 313, 317, 176, 302, 318, 590, 578, 0, 0, + 534, 593, 507, 524, 601, 525, 528, 565, 492, 547, + 229, 522, 0, 511, 487, 518, 488, 509, 536, 161, + 540, 506, 580, 550, 592, 195, 0, 512, 240, 567, + 272, 152, 203, 201, 291, 166, 162, 160, 151, 183, + 207, 239, 288, 233, 599, 198, 556, 0, 280, 215, + 0, 0, 0, 538, 582, 545, 575, 533, 566, 497, + 555, 594, 523, 563, 595, 187, 150, 130, 226, 281, + 168, 0, 0, 0, 112, 113, 114, 0, 1129, 1130, + 0, 0, 0, 0, 0, 146, 0, 560, 589, 520, + 562, 564, 603, 486, 557, 0, 490, 493, 600, 585, + 515, 516, 0, 0, 0, 0, 0, 0, 0, 537, + 546, 572, 531, 0, 0, 0, 0, 0, 0, 0, + 0, 513, 0, 554, 0, 0, 0, 494, 491, 0, + 0, 0, 0, 535, 0, 0, 0, 496, 0, 514, + 573, 0, 484, 173, 577, 584, 532, 314, 588, 530, + 529, 591, 251, 0, 285, 177, 194, 142, 191, 127, + 138, 0, 175, 225, 259, 263, 581, 510, 519, 153, + 517, 261, 237, 304, 553, 241, 260, 199, 293, 252, + 303, 315, 316, 158, 219, 309, 289, 312, 324, 277, + 131, 287, 301, 147, 271, 0, 0, 0, 133, 299, + 284, 213, 188, 189, 132, 0, 257, 159, 171, 155, + 228, 296, 297, 154, 327, 139, 311, 135, 140, 310, + 221, 292, 300, 214, 206, 134, 298, 212, 205, 193, + 165, 179, 249, 202, 250, 180, 217, 216, 218, 0, + 489, 0, 282, 307, 328, 144, 505, 290, 320, 323, + 0, 253, 145, 172, 164, 248, 170, 196, 319, 321, + 322, 220, 141, 182, 278, 192, 200, 256, 326, 236, + 262, 148, 306, 279, 501, 504, 499, 500, 548, 549, + 596, 597, 598, 574, 495, 0, 502, 503, 0, 579, + 586, 587, 552, 126, 136, 197, 325, 254, 169, 308, + 485, 498, 157, 508, 0, 0, 521, 526, 527, 539, + 541, 542, 543, 544, 551, 558, 559, 561, 568, 569, + 570, 571, 576, 583, 602, 128, 129, 137, 143, 149, + 156, 163, 167, 174, 178, 181, 184, 185, 186, 190, + 204, 208, 209, 210, 211, 222, 223, 224, 227, 230, + 231, 232, 234, 235, 238, 242, 243, 244, 245, 246, + 247, 255, 258, 264, 265, 266, 267, 268, 269, 270, + 273, 274, 275, 276, 283, 286, 294, 295, 305, 313, + 317, 176, 302, 318, 590, 578, 0, 0, 534, 593, + 507, 524, 601, 525, 528, 565, 492, 547, 229, 522, + 0, 511, 487, 518, 488, 509, 536, 161, 540, 506, + 580, 550, 592, 195, 0, 512, 240, 567, 272, 152, + 203, 201, 291, 166, 162, 160, 151, 183, 207, 239, + 288, 233, 599, 198, 556, 0, 280, 215, 0, 0, + 0, 538, 582, 545, 575, 533, 566, 497, 555, 594, + 523, 563, 595, 187, 150, 130, 226, 281, 168, 0, + 0, 0, 112, 113, 114, 0, 0, 0, 0, 0, + 0, 0, 0, 146, 0, 560, 589, 520, 562, 564, + 603, 486, 557, 0, 490, 493, 600, 585, 515, 516, + 0, 0, 0, 0, 0, 0, 0, 537, 546, 572, + 531, 0, 0, 0, 0, 0, 0, 1457, 0, 513, + 0, 554, 0, 0, 0, 494, 491, 0, 0, 0, + 0, 535, 0, 0, 0, 496, 0, 514, 573, 0, + 484, 173, 577, 584, 532, 314, 588, 530, 529, 591, + 251, 0, 285, 177, 194, 142, 191, 127, 138, 0, + 175, 225, 259, 263, 581, 510, 519, 153, 517, 261, + 237, 304, 553, 241, 260, 199, 293, 252, 303, 315, + 316, 158, 219, 309, 289, 312, 324, 277, 131, 287, + 301, 147, 271, 0, 0, 0, 133, 299, 284, 213, + 188, 189, 132, 0, 257, 159, 171, 155, 228, 296, + 297, 154, 327, 139, 311, 135, 140, 310, 221, 292, + 300, 214, 206, 134, 298, 212, 205, 193, 165, 179, + 249, 202, 250, 180, 217, 216, 218, 0, 489, 0, + 282, 307, 328, 144, 505, 290, 320, 323, 0, 253, + 145, 172, 164, 248, 170, 196, 319, 321, 322, 220, + 141, 182, 278, 192, 200, 256, 326, 236, 262, 148, + 306, 279, 501, 504, 499, 500, 548, 549, 596, 597, + 598, 574, 495, 0, 502, 503, 0, 579, 586, 587, + 552, 126, 136, 197, 325, 254, 169, 308, 485, 498, + 157, 508, 0, 0, 521, 526, 527, 539, 541, 542, + 543, 544, 551, 558, 559, 561, 568, 569, 570, 571, + 576, 583, 602, 128, 129, 137, 143, 149, 156, 163, + 167, 174, 178, 181, 184, 185, 186, 190, 204, 208, + 209, 210, 211, 222, 223, 224, 227, 230, 231, 232, + 234, 235, 238, 242, 243, 244, 245, 246, 247, 255, + 258, 264, 265, 266, 267, 268, 269, 270, 273, 274, + 275, 276, 283, 286, 294, 295, 305, 313, 317, 176, + 302, 318, 590, 578, 0, 0, 534, 593, 507, 524, + 601, 525, 528, 565, 492, 547, 229, 522, 0, 511, + 487, 518, 488, 509, 536, 161, 540, 506, 580, 550, + 592, 195, 0, 512, 240, 567, 272, 152, 203, 201, + 291, 166, 162, 160, 151, 183, 207, 239, 288, 233, + 599, 198, 556, 0, 280, 215, 0, 0, 0, 538, + 582, 545, 575, 533, 566, 497, 555, 594, 523, 563, + 595, 187, 150, 130, 226, 281, 168, 64, 0, 0, + 112, 113, 114, 0, 0, 0, 0, 0, 0, 0, + 0, 146, 0, 560, 589, 520, 562, 564, 603, 486, + 557, 0, 490, 493, 600, 585, 515, 516, 0, 0, + 0, 0, 0, 0, 0, 537, 546, 572, 531, 0, + 0, 0, 0, 0, 0, 0, 0, 513, 0, 554, + 0, 0, 0, 494, 491, 0, 0, 0, 0, 535, + 0, 0, 0, 496, 0, 514, 573, 0, 484, 173, + 577, 584, 532, 314, 588, 530, 529, 591, 251, 0, + 285, 177, 194, 142, 191, 127, 138, 0, 175, 225, + 259, 263, 581, 510, 519, 153, 517, 261, 237, 304, + 553, 241, 260, 199, 293, 252, 303, 315, 316, 158, + 219, 309, 289, 312, 324, 277, 131, 287, 301, 147, + 271, 0, 0, 0, 133, 299, 284, 213, 188, 189, + 132, 0, 257, 159, 171, 155, 228, 296, 297, 154, + 327, 139, 311, 135, 140, 310, 221, 292, 300, 214, + 206, 134, 298, 212, 205, 193, 165, 179, 249, 202, + 250, 180, 217, 216, 218, 0, 489, 0, 282, 307, + 328, 144, 505, 290, 320, 323, 0, 253, 145, 172, + 164, 248, 170, 196, 319, 321, 322, 220, 141, 182, + 278, 192, 200, 256, 326, 236, 262, 148, 306, 279, + 501, 504, 499, 500, 548, 549, 596, 597, 598, 574, + 495, 0, 502, 503, 0, 579, 586, 587, 552, 126, + 136, 197, 325, 254, 169, 308, 485, 498, 157, 508, + 0, 0, 521, 526, 527, 539, 541, 542, 543, 544, + 551, 558, 559, 561, 568, 569, 570, 571, 576, 583, + 602, 128, 129, 137, 143, 149, 156, 163, 167, 174, + 178, 181, 184, 185, 186, 190, 204, 208, 209, 210, + 211, 222, 223, 224, 227, 230, 231, 232, 234, 235, + 238, 242, 243, 244, 245, 246, 247, 255, 258, 264, + 265, 266, 267, 268, 269, 270, 273, 274, 275, 276, + 283, 286, 294, 295, 305, 313, 317, 176, 302, 318, + 590, 578, 0, 0, 534, 593, 507, 524, 601, 525, + 528, 565, 492, 547, 229, 522, 0, 511, 487, 518, + 488, 509, 536, 161, 540, 506, 580, 550, 592, 195, + 0, 512, 240, 567, 272, 152, 203, 201, 291, 166, + 162, 160, 151, 183, 207, 239, 288, 233, 599, 198, + 556, 0, 280, 215, 0, 0, 0, 538, 582, 545, + 575, 533, 566, 497, 555, 594, 523, 563, 595, 187, + 150, 130, 226, 281, 168, 0, 0, 0, 112, 113, + 114, 0, 0, 0, 0, 0, 0, 0, 0, 146, + 0, 560, 589, 520, 562, 564, 603, 486, 557, 0, + 490, 493, 600, 585, 515, 516, 0, 0, 0, 0, + 0, 0, 0, 537, 546, 572, 531, 0, 0, 0, + 0, 0, 0, 1343, 0, 513, 0, 554, 0, 0, + 0, 494, 491, 0, 0, 0, 0, 535, 0, 0, + 0, 496, 0, 514, 573, 0, 484, 173, 577, 584, + 532, 314, 588, 530, 529, 591, 251, 0, 285, 177, + 194, 142, 191, 127, 138, 0, 175, 225, 259, 263, + 581, 510, 519, 153, 517, 261, 237, 304, 553, 241, + 260, 199, 293, 252, 303, 315, 316, 158, 219, 309, + 289, 312, 324, 277, 131, 287, 301, 147, 271, 0, + 0, 0, 133, 299, 284, 213, 188, 189, 132, 0, + 257, 159, 171, 155, 228, 296, 297, 154, 327, 139, + 311, 135, 140, 310, 221, 292, 300, 214, 206, 134, + 298, 212, 205, 193, 165, 179, 249, 202, 250, 180, + 217, 216, 218, 0, 489, 0, 282, 307, 328, 144, + 505, 290, 320, 323, 0, 253, 145, 172, 164, 248, + 170, 196, 319, 321, 322, 220, 141, 182, 278, 192, + 200, 256, 326, 236, 262, 148, 306, 279, 501, 504, + 499, 500, 548, 549, 596, 597, 598, 574, 495, 0, + 502, 503, 0, 579, 586, 587, 552, 126, 136, 197, + 325, 254, 169, 308, 485, 498, 157, 508, 0, 0, + 521, 526, 527, 539, 541, 542, 543, 544, 551, 558, + 559, 561, 568, 569, 570, 571, 576, 583, 602, 128, + 129, 137, 143, 149, 156, 163, 167, 174, 178, 181, + 184, 185, 186, 190, 204, 208, 209, 210, 211, 222, + 223, 224, 227, 230, 231, 232, 234, 235, 238, 242, + 243, 244, 245, 246, 247, 255, 258, 264, 265, 266, + 267, 268, 269, 270, 273, 274, 275, 276, 283, 286, + 294, 295, 305, 313, 317, 176, 302, 318, 590, 578, + 0, 0, 534, 593, 507, 524, 601, 525, 528, 565, + 492, 547, 229, 522, 0, 511, 487, 518, 488, 509, + 536, 161, 540, 506, 580, 550, 592, 195, 0, 512, + 240, 567, 272, 152, 203, 201, 291, 166, 162, 160, + 151, 183, 207, 239, 288, 233, 599, 198, 556, 0, + 280, 215, 0, 0, 0, 538, 582, 545, 575, 533, + 566, 497, 555, 594, 523, 563, 595, 187, 150, 130, + 226, 281, 168, 0, 0, 0, 112, 113, 114, 0, + 0, 0, 0, 0, 0, 0, 0, 146, 0, 560, + 589, 520, 562, 564, 603, 486, 557, 0, 490, 493, + 600, 585, 515, 516, 0, 0, 0, 0, 0, 0, + 0, 537, 546, 572, 531, 0, 0, 0, 0, 0, + 0, 1075, 0, 513, 0, 554, 0, 0, 0, 494, + 491, 0, 0, 0, 0, 535, 0, 0, 0, 496, + 0, 514, 573, 0, 484, 173, 577, 584, 532, 314, + 588, 530, 529, 591, 251, 0, 285, 177, 194, 142, + 191, 127, 138, 0, 175, 225, 259, 263, 581, 510, + 519, 153, 517, 261, 237, 304, 553, 241, 260, 199, + 293, 252, 303, 315, 316, 158, 219, 309, 289, 312, + 324, 277, 131, 287, 301, 147, 271, 0, 0, 0, + 133, 299, 284, 213, 188, 189, 132, 0, 257, 159, + 171, 155, 228, 296, 297, 154, 327, 139, 311, 135, + 140, 310, 221, 292, 300, 214, 206, 134, 298, 212, + 205, 193, 165, 179, 249, 202, 250, 180, 217, 216, + 218, 0, 489, 0, 282, 307, 328, 144, 505, 290, + 320, 323, 0, 253, 145, 172, 164, 248, 170, 196, + 319, 321, 322, 220, 141, 182, 278, 192, 200, 256, + 326, 236, 262, 148, 306, 279, 501, 504, 499, 500, + 548, 549, 596, 597, 598, 574, 495, 0, 502, 503, + 0, 579, 586, 587, 552, 126, 136, 197, 325, 254, + 169, 308, 485, 498, 157, 508, 0, 0, 521, 526, + 527, 539, 541, 542, 543, 544, 551, 558, 559, 561, + 568, 569, 570, 571, 576, 583, 602, 128, 129, 137, + 143, 149, 156, 163, 167, 174, 178, 181, 184, 185, + 186, 190, 204, 208, 209, 210, 211, 222, 223, 224, + 227, 230, 231, 232, 234, 235, 238, 242, 243, 244, + 245, 246, 247, 255, 258, 264, 265, 266, 267, 268, + 269, 270, 273, 274, 275, 276, 283, 286, 294, 295, + 305, 313, 317, 176, 302, 318, 590, 578, 0, 0, + 534, 593, 507, 524, 601, 525, 528, 565, 492, 547, + 229, 522, 0, 511, 487, 518, 488, 509, 536, 161, + 540, 506, 580, 550, 592, 195, 0, 512, 240, 567, + 272, 152, 203, 201, 291, 166, 162, 160, 151, 183, + 207, 239, 288, 233, 599, 198, 556, 0, 280, 215, + 0, 0, 0, 538, 582, 545, 575, 533, 566, 497, + 555, 594, 523, 563, 595, 187, 150, 130, 226, 281, + 168, 0, 0, 0, 112, 113, 114, 0, 0, 0, + 0, 0, 0, 0, 0, 146, 0, 560, 589, 520, + 562, 564, 603, 486, 557, 0, 490, 493, 600, 585, + 515, 516, 0, 0, 0, 0, 0, 0, 0, 537, + 546, 572, 531, 0, 0, 0, 0, 0, 0, 0, + 0, 513, 0, 554, 0, 0, 0, 494, 491, 0, + 0, 0, 0, 535, 0, 0, 0, 496, 0, 514, + 573, 0, 484, 173, 577, 584, 532, 314, 588, 530, + 529, 591, 251, 0, 285, 177, 194, 142, 191, 127, + 138, 0, 175, 225, 259, 263, 581, 510, 519, 153, + 517, 261, 237, 304, 553, 241, 260, 199, 293, 252, + 303, 315, 316, 158, 219, 309, 289, 312, 324, 277, + 131, 287, 301, 147, 271, 0, 0, 0, 133, 299, + 284, 213, 188, 189, 132, 0, 257, 159, 171, 155, + 228, 296, 297, 154, 327, 139, 311, 135, 140, 310, + 221, 292, 300, 214, 206, 134, 298, 212, 205, 193, + 165, 179, 249, 202, 250, 180, 217, 216, 218, 0, + 489, 0, 282, 307, 328, 144, 505, 290, 320, 323, + 0, 253, 145, 172, 164, 248, 170, 196, 319, 321, + 322, 220, 141, 182, 278, 192, 200, 256, 326, 236, + 262, 148, 306, 279, 501, 504, 499, 500, 548, 549, + 596, 597, 598, 574, 495, 0, 502, 503, 0, 579, + 586, 587, 552, 126, 136, 197, 325, 254, 169, 308, + 485, 498, 157, 508, 0, 0, 521, 526, 527, 539, + 541, 542, 543, 544, 551, 558, 559, 561, 568, 569, + 570, 571, 576, 583, 602, 128, 129, 137, 143, 149, + 156, 163, 167, 174, 178, 181, 184, 185, 186, 190, + 204, 208, 209, 210, 211, 222, 223, 224, 227, 230, + 231, 232, 234, 235, 238, 242, 243, 244, 245, 246, + 247, 255, 258, 264, 265, 266, 267, 268, 269, 270, + 273, 274, 275, 276, 283, 286, 294, 295, 305, 313, + 317, 176, 302, 318, 590, 578, 0, 0, 534, 593, + 507, 524, 601, 525, 528, 565, 492, 547, 229, 522, + 0, 511, 487, 518, 488, 509, 536, 161, 540, 506, + 580, 550, 592, 195, 0, 512, 240, 567, 272, 152, + 203, 201, 291, 166, 162, 160, 151, 183, 207, 239, + 288, 233, 599, 198, 556, 0, 280, 215, 0, 0, + 0, 538, 582, 545, 575, 533, 566, 497, 555, 594, + 523, 563, 595, 187, 150, 130, 226, 281, 168, 0, + 0, 0, 112, 113, 114, 0, 0, 0, 0, 0, + 0, 0, 0, 146, 0, 560, 589, 520, 562, 564, + 603, 486, 557, 0, 490, 493, 600, 585, 515, 516, + 0, 0, 0, 0, 0, 0, 0, 537, 546, 572, + 531, 0, 0, 0, 0, 0, 0, 0, 0, 513, + 0, 554, 0, 0, 0, 494, 491, 0, 0, 0, + 0, 535, 0, 0, 0, 496, 0, 514, 573, 0, + 484, 173, 577, 584, 532, 314, 588, 530, 529, 591, + 251, 0, 285, 177, 194, 142, 191, 127, 138, 0, + 175, 225, 259, 263, 581, 510, 519, 153, 517, 261, + 237, 304, 553, 241, 260, 199, 293, 252, 303, 315, + 316, 158, 219, 309, 289, 312, 324, 277, 131, 287, + 301, 147, 271, 0, 0, 0, 133, 299, 284, 213, + 188, 189, 132, 0, 257, 159, 171, 155, 228, 296, + 297, 154, 327, 139, 311, 135, 482, 310, 221, 292, + 300, 214, 206, 134, 298, 212, 205, 193, 165, 179, + 249, 202, 250, 180, 217, 216, 218, 0, 489, 0, + 282, 307, 328, 144, 505, 290, 320, 323, 0, 253, + 145, 172, 164, 248, 170, 196, 319, 321, 322, 483, + 481, 476, 475, 192, 200, 256, 326, 236, 262, 148, + 306, 279, 501, 504, 499, 500, 548, 549, 596, 597, + 598, 574, 495, 0, 502, 503, 0, 579, 586, 587, + 552, 126, 136, 197, 325, 254, 169, 308, 485, 498, + 157, 508, 0, 0, 521, 526, 527, 539, 541, 542, + 543, 544, 551, 558, 559, 561, 568, 569, 570, 571, + 576, 583, 602, 128, 129, 137, 143, 149, 156, 163, + 167, 174, 178, 181, 184, 185, 186, 190, 204, 208, + 209, 210, 211, 222, 223, 224, 227, 230, 231, 232, + 234, 235, 238, 242, 243, 244, 245, 246, 247, 255, + 258, 264, 265, 266, 267, 268, 269, 270, 273, 274, + 275, 276, 283, 286, 294, 295, 305, 313, 317, 176, + 302, 318, 590, 578, 0, 0, 534, 593, 507, 524, + 601, 525, 528, 565, 492, 547, 229, 522, 0, 511, + 487, 518, 488, 509, 536, 161, 540, 506, 580, 550, + 592, 195, 0, 512, 240, 567, 272, 152, 203, 201, + 291, 166, 162, 160, 151, 183, 207, 239, 288, 233, + 599, 198, 556, 0, 280, 215, 0, 0, 0, 538, + 582, 545, 575, 533, 566, 497, 555, 594, 523, 563, + 595, 187, 150, 130, 226, 281, 168, 0, 0, 0, + 112, 113, 114, 0, 0, 0, 0, 0, 0, 0, + 0, 146, 0, 560, 589, 520, 562, 564, 603, 486, + 557, 0, 490, 493, 600, 585, 515, 516, 0, 0, + 0, 0, 0, 0, 0, 537, 546, 572, 531, 0, + 0, 0, 0, 0, 0, 0, 0, 513, 0, 554, + 0, 0, 0, 494, 491, 0, 0, 0, 0, 535, + 0, 0, 0, 496, 0, 514, 573, 0, 484, 173, + 577, 584, 532, 314, 588, 530, 529, 591, 251, 0, + 285, 177, 194, 142, 191, 127, 138, 0, 175, 225, + 259, 263, 581, 510, 519, 153, 517, 261, 237, 304, + 553, 241, 260, 199, 293, 252, 303, 315, 316, 158, + 219, 309, 289, 312, 324, 277, 131, 287, 827, 147, + 271, 0, 0, 0, 133, 299, 284, 213, 188, 189, + 132, 0, 257, 159, 171, 155, 228, 296, 297, 154, + 327, 139, 311, 135, 482, 310, 221, 292, 300, 214, + 206, 134, 298, 212, 205, 193, 165, 179, 249, 202, + 250, 180, 217, 216, 218, 0, 489, 0, 282, 307, + 328, 144, 505, 290, 320, 323, 0, 253, 145, 172, + 164, 248, 170, 196, 319, 321, 322, 483, 481, 476, + 475, 192, 200, 256, 326, 236, 262, 148, 306, 279, + 501, 504, 499, 500, 548, 549, 596, 597, 598, 574, + 495, 0, 502, 503, 0, 579, 586, 587, 552, 126, + 136, 197, 325, 254, 169, 308, 485, 498, 157, 508, + 0, 0, 521, 526, 527, 539, 541, 542, 543, 544, + 551, 558, 559, 561, 568, 569, 570, 571, 576, 583, + 602, 128, 129, 137, 143, 149, 156, 163, 167, 174, + 178, 181, 184, 185, 186, 190, 204, 208, 209, 210, + 211, 222, 223, 224, 227, 230, 231, 232, 234, 235, + 238, 242, 243, 244, 245, 246, 247, 255, 258, 264, + 265, 266, 267, 268, 269, 270, 273, 274, 275, 276, + 283, 286, 294, 295, 305, 313, 317, 176, 302, 318, + 590, 578, 0, 0, 534, 593, 507, 524, 601, 525, + 528, 565, 492, 547, 229, 522, 0, 511, 487, 518, + 488, 509, 536, 161, 540, 506, 580, 550, 592, 195, + 0, 512, 240, 567, 272, 152, 203, 201, 291, 166, + 162, 160, 151, 183, 207, 239, 288, 233, 599, 198, + 556, 0, 280, 215, 0, 0, 0, 538, 582, 545, + 575, 533, 566, 497, 555, 594, 523, 563, 595, 187, + 150, 130, 226, 281, 168, 0, 0, 0, 112, 113, + 114, 0, 0, 0, 0, 0, 0, 0, 0, 146, + 0, 560, 589, 520, 562, 564, 603, 486, 557, 0, + 490, 493, 600, 585, 515, 516, 0, 0, 0, 0, + 0, 0, 0, 537, 546, 572, 531, 0, 0, 0, + 0, 0, 0, 0, 0, 513, 0, 554, 0, 0, + 0, 494, 491, 0, 0, 0, 0, 535, 0, 0, + 0, 496, 0, 514, 573, 0, 484, 173, 577, 584, + 532, 314, 588, 530, 529, 591, 251, 0, 285, 177, + 194, 142, 191, 127, 138, 0, 175, 225, 259, 263, + 581, 510, 519, 153, 517, 261, 237, 304, 553, 241, + 260, 199, 293, 252, 303, 315, 316, 158, 219, 309, + 289, 312, 324, 277, 131, 287, 473, 147, 271, 0, + 0, 0, 133, 299, 284, 213, 188, 189, 132, 0, + 257, 159, 171, 155, 228, 296, 297, 154, 327, 139, + 311, 135, 482, 310, 221, 292, 300, 214, 206, 134, + 298, 212, 205, 193, 165, 179, 249, 202, 250, 180, + 217, 216, 218, 0, 489, 0, 282, 307, 328, 144, + 505, 290, 320, 323, 0, 253, 145, 172, 164, 248, + 170, 196, 319, 321, 322, 483, 481, 476, 475, 192, + 200, 256, 326, 236, 262, 148, 306, 279, 501, 504, + 499, 500, 548, 549, 596, 597, 598, 574, 495, 0, + 502, 503, 0, 579, 586, 587, 552, 126, 136, 197, + 325, 254, 169, 308, 485, 498, 157, 508, 0, 0, + 521, 526, 527, 539, 541, 542, 543, 544, 551, 558, + 559, 561, 568, 569, 570, 571, 576, 583, 602, 128, + 129, 137, 143, 149, 156, 163, 167, 174, 178, 181, + 184, 185, 186, 190, 204, 208, 209, 210, 211, 222, + 223, 224, 227, 230, 231, 232, 234, 235, 238, 242, + 243, 244, 245, 246, 247, 255, 258, 264, 265, 266, + 267, 268, 269, 270, 273, 274, 275, 276, 283, 286, + 294, 295, 305, 313, 317, 176, 302, 318, 229, 0, + 0, 1013, 0, 379, 0, 0, 0, 161, 0, 378, + 0, 0, 0, 195, 0, 1014, 240, 0, 272, 152, + 203, 201, 291, 166, 162, 160, 151, 183, 207, 239, + 288, 233, 422, 198, 0, 0, 280, 215, 0, 0, + 0, 0, 0, 413, 414, 0, 0, 0, 0, 0, + 0, 0, 0, 187, 150, 130, 226, 281, 168, 64, + 0, 0, 112, 113, 114, 400, 399, 402, 403, 404, + 405, 0, 0, 146, 401, 406, 407, 408, 0, 0, + 0, 0, 376, 393, 0, 421, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 390, 391, 463, 0, 0, + 0, 436, 0, 392, 0, 0, 385, 386, 388, 387, + 389, 394, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 173, 435, 0, 0, 314, 0, 0, 433, 0, + 251, 0, 285, 177, 194, 142, 191, 127, 138, 0, + 175, 225, 259, 263, 0, 0, 0, 153, 0, 261, + 237, 304, 0, 241, 260, 199, 293, 252, 303, 315, + 316, 158, 219, 309, 289, 312, 324, 277, 131, 287, + 301, 147, 271, 0, 0, 0, 133, 299, 284, 213, + 188, 189, 132, 0, 257, 159, 171, 155, 228, 296, + 297, 154, 327, 139, 311, 135, 140, 310, 221, 292, + 300, 214, 206, 134, 298, 212, 205, 193, 165, 179, + 249, 202, 250, 180, 217, 216, 218, 0, 0, 0, + 282, 307, 328, 144, 0, 290, 320, 323, 0, 253, + 145, 172, 164, 248, 170, 196, 319, 321, 322, 220, + 141, 182, 278, 192, 200, 256, 326, 236, 262, 148, + 306, 279, 423, 434, 429, 430, 427, 428, 426, 425, + 424, 437, 415, 416, 417, 418, 420, 0, 431, 432, + 419, 126, 136, 197, 325, 254, 169, 308, 0, 0, + 157, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 128, 129, 137, 143, 149, 156, 163, + 167, 174, 178, 181, 184, 185, 186, 190, 204, 208, + 209, 210, 211, 222, 223, 224, 227, 230, 231, 232, + 234, 235, 238, 242, 243, 244, 245, 246, 247, 255, + 258, 264, 265, 266, 267, 268, 269, 270, 273, 274, + 275, 276, 283, 286, 294, 295, 305, 313, 317, 176, + 302, 318, 229, 0, 0, 0, 0, 379, 0, 0, + 0, 161, 0, 378, 0, 0, 0, 195, 0, 0, + 240, 0, 272, 152, 203, 201, 291, 166, 162, 160, + 151, 183, 207, 239, 288, 233, 422, 198, 0, 0, + 280, 215, 0, 0, 0, 0, 0, 413, 414, 0, + 0, 0, 0, 0, 0, 1120, 0, 187, 150, 130, + 226, 281, 168, 64, 0, 0, 112, 113, 114, 400, + 399, 402, 403, 404, 405, 0, 0, 146, 401, 406, + 407, 408, 1121, 0, 0, 0, 376, 393, 0, 421, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 390, + 391, 0, 0, 0, 0, 436, 0, 392, 0, 0, + 385, 386, 388, 387, 389, 394, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 173, 435, 0, 0, 314, + 0, 0, 433, 0, 251, 0, 285, 177, 194, 142, + 191, 127, 138, 0, 175, 225, 259, 263, 0, 0, + 0, 153, 0, 261, 237, 304, 0, 241, 260, 199, + 293, 252, 303, 315, 316, 158, 219, 309, 289, 312, + 324, 277, 131, 287, 301, 147, 271, 0, 0, 0, + 133, 299, 284, 213, 188, 189, 132, 0, 257, 159, + 171, 155, 228, 296, 297, 154, 327, 139, 311, 135, + 140, 310, 221, 292, 300, 214, 206, 134, 298, 212, + 205, 193, 165, 179, 249, 202, 250, 180, 217, 216, + 218, 0, 0, 0, 282, 307, 328, 144, 0, 290, + 320, 323, 0, 253, 145, 172, 164, 248, 170, 196, + 319, 321, 322, 220, 141, 182, 278, 192, 200, 256, + 326, 236, 262, 148, 306, 279, 423, 434, 429, 430, + 427, 428, 426, 425, 424, 437, 415, 416, 417, 418, + 420, 0, 431, 432, 419, 126, 136, 197, 325, 254, + 169, 308, 0, 0, 157, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 128, 129, 137, + 143, 149, 156, 163, 167, 174, 178, 181, 184, 185, + 186, 190, 204, 208, 209, 210, 211, 222, 223, 224, + 227, 230, 231, 232, 234, 235, 238, 242, 243, 244, + 245, 246, 247, 255, 258, 264, 265, 266, 267, 268, + 269, 270, 273, 274, 275, 276, 283, 286, 294, 295, + 305, 313, 317, 176, 302, 318, 229, 0, 0, 0, + 0, 379, 0, 0, 0, 161, 0, 378, 0, 0, + 0, 195, 0, 0, 240, 0, 272, 152, 203, 201, + 291, 166, 162, 160, 151, 183, 207, 239, 288, 233, + 422, 198, 0, 0, 280, 215, 0, 0, 0, 0, + 0, 413, 414, 0, 0, 0, 0, 0, 0, 0, + 0, 187, 150, 130, 226, 281, 168, 64, 0, 451, + 112, 113, 114, 400, 399, 402, 403, 404, 405, 0, + 0, 146, 401, 406, 407, 408, 0, 0, 0, 0, + 376, 393, 0, 421, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 390, 391, 0, 0, 0, 0, 436, + 0, 392, 0, 0, 385, 386, 388, 387, 389, 394, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 173, + 435, 0, 0, 314, 0, 0, 433, 0, 251, 0, + 285, 177, 194, 142, 191, 127, 138, 0, 175, 225, + 259, 263, 0, 0, 0, 153, 0, 261, 237, 304, + 0, 241, 260, 199, 293, 252, 303, 315, 316, 158, + 219, 309, 289, 312, 324, 277, 131, 287, 301, 147, + 271, 0, 0, 0, 133, 299, 284, 213, 188, 189, + 132, 0, 257, 159, 171, 155, 228, 296, 297, 154, + 327, 139, 311, 135, 140, 310, 221, 292, 300, 214, + 206, 134, 298, 212, 205, 193, 165, 179, 249, 202, + 250, 180, 217, 216, 218, 0, 0, 0, 282, 307, + 328, 144, 0, 290, 320, 323, 0, 253, 145, 172, + 164, 248, 170, 196, 319, 321, 322, 220, 141, 182, + 278, 192, 200, 256, 326, 236, 262, 148, 306, 279, + 423, 434, 429, 430, 427, 428, 426, 425, 424, 437, + 415, 416, 417, 418, 420, 0, 431, 432, 419, 126, + 136, 197, 325, 254, 169, 308, 0, 0, 157, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 128, 129, 137, 143, 149, 156, 163, 167, 174, + 178, 181, 184, 185, 186, 190, 204, 208, 209, 210, + 211, 222, 223, 224, 227, 230, 231, 232, 234, 235, + 238, 242, 243, 244, 245, 246, 247, 255, 258, 264, + 265, 266, 267, 268, 269, 270, 273, 274, 275, 276, + 283, 286, 294, 295, 305, 313, 317, 176, 302, 318, + 229, 0, 0, 0, 0, 379, 0, 0, 0, 161, + 0, 378, 0, 0, 0, 195, 0, 0, 240, 0, + 272, 152, 203, 201, 291, 166, 162, 160, 151, 183, + 207, 239, 288, 233, 422, 198, 0, 0, 280, 215, + 0, 0, 0, 0, 0, 413, 414, 0, 0, 0, + 0, 0, 0, 0, 0, 187, 150, 130, 226, 281, + 168, 64, 0, 0, 112, 113, 114, 400, 399, 402, + 403, 404, 405, 0, 0, 146, 401, 406, 407, 408, + 0, 0, 0, 0, 376, 393, 0, 421, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 390, 391, 463, + 0, 0, 0, 436, 0, 392, 0, 0, 385, 386, + 388, 387, 389, 394, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 173, 435, 0, 0, 314, 0, 0, + 433, 0, 251, 0, 285, 177, 194, 142, 191, 127, + 138, 0, 175, 225, 259, 263, 0, 0, 0, 153, + 0, 261, 237, 304, 0, 241, 260, 199, 293, 252, + 303, 315, 316, 158, 219, 309, 289, 312, 324, 277, + 131, 287, 301, 147, 271, 0, 0, 0, 133, 299, + 284, 213, 188, 189, 132, 0, 257, 159, 171, 155, + 228, 296, 297, 154, 327, 139, 311, 135, 140, 310, + 221, 292, 300, 214, 206, 134, 298, 212, 205, 193, + 165, 179, 249, 202, 250, 180, 217, 216, 218, 0, + 0, 0, 282, 307, 328, 144, 0, 290, 320, 323, + 0, 253, 145, 172, 164, 248, 170, 196, 319, 321, + 322, 220, 141, 182, 278, 192, 200, 256, 326, 236, + 262, 148, 306, 279, 423, 434, 429, 430, 427, 428, + 426, 425, 424, 437, 415, 416, 417, 418, 420, 0, + 431, 432, 419, 126, 136, 197, 325, 254, 169, 308, + 0, 0, 157, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 128, 129, 137, 143, 149, + 156, 163, 167, 174, 178, 181, 184, 185, 186, 190, + 204, 208, 209, 210, 211, 222, 223, 224, 227, 230, + 231, 232, 234, 235, 238, 242, 243, 244, 245, 246, + 247, 255, 258, 264, 265, 266, 267, 268, 269, 270, + 273, 274, 275, 276, 283, 286, 294, 295, 305, 313, + 317, 176, 302, 318, 229, 0, 0, 0, 0, 379, + 0, 0, 0, 161, 0, 378, 0, 0, 0, 195, + 0, 0, 240, 0, 272, 152, 203, 201, 291, 166, + 162, 160, 151, 183, 207, 239, 288, 233, 422, 198, + 0, 0, 280, 215, 0, 0, 0, 0, 0, 413, + 414, 0, 0, 0, 0, 0, 0, 0, 0, 187, + 150, 130, 226, 281, 168, 64, 0, 0, 112, 113, + 114, 400, 1031, 402, 403, 404, 405, 0, 0, 146, + 401, 406, 407, 408, 0, 0, 0, 0, 376, 393, + 0, 421, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 390, 391, 463, 0, 0, 0, 436, 0, 392, + 0, 0, 385, 386, 388, 387, 389, 394, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 173, 435, 0, + 0, 314, 0, 0, 433, 0, 251, 0, 285, 177, + 194, 142, 191, 127, 138, 0, 175, 225, 259, 263, + 0, 0, 0, 153, 0, 261, 237, 304, 0, 241, + 260, 199, 293, 252, 303, 315, 316, 158, 219, 309, + 289, 312, 324, 277, 131, 287, 301, 147, 271, 0, + 0, 0, 133, 299, 284, 213, 188, 189, 132, 0, + 257, 159, 171, 155, 228, 296, 297, 154, 327, 139, + 311, 135, 140, 310, 221, 292, 300, 214, 206, 134, + 298, 212, 205, 193, 165, 179, 249, 202, 250, 180, + 217, 216, 218, 0, 0, 0, 282, 307, 328, 144, + 0, 290, 320, 323, 0, 253, 145, 172, 164, 248, + 170, 196, 319, 321, 322, 220, 141, 182, 278, 192, + 200, 256, 326, 236, 262, 148, 306, 279, 423, 434, + 429, 430, 427, 428, 426, 425, 424, 437, 415, 416, + 417, 418, 420, 0, 431, 432, 419, 126, 136, 197, + 325, 254, 169, 308, 0, 0, 157, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, + 129, 137, 143, 149, 156, 163, 167, 174, 178, 181, + 184, 185, 186, 190, 204, 208, 209, 210, 211, 222, + 223, 224, 227, 230, 231, 232, 234, 235, 238, 242, + 243, 244, 245, 246, 247, 255, 258, 264, 265, 266, + 267, 268, 269, 270, 273, 274, 275, 276, 283, 286, + 294, 295, 305, 313, 317, 176, 302, 318, 229, 0, + 0, 0, 0, 379, 0, 0, 0, 161, 0, 378, + 0, 0, 0, 195, 0, 0, 240, 0, 272, 152, + 203, 201, 291, 166, 162, 160, 151, 183, 207, 239, + 288, 233, 422, 198, 0, 0, 280, 215, 0, 0, + 0, 0, 0, 413, 414, 0, 0, 0, 0, 0, + 0, 0, 0, 187, 150, 130, 226, 281, 168, 64, + 0, 0, 112, 113, 114, 400, 1028, 402, 403, 404, + 405, 0, 0, 146, 401, 406, 407, 408, 0, 0, + 0, 0, 376, 393, 0, 421, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 390, 391, 463, 0, 0, + 0, 436, 0, 392, 0, 0, 385, 386, 388, 387, + 389, 394, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 173, 435, 0, 0, 314, 0, 0, 433, 0, + 251, 0, 285, 177, 194, 142, 191, 127, 138, 0, + 175, 225, 259, 263, 0, 0, 0, 153, 0, 261, + 237, 304, 0, 241, 260, 199, 293, 252, 303, 315, + 316, 158, 219, 309, 289, 312, 324, 277, 131, 287, + 301, 147, 271, 0, 0, 0, 133, 299, 284, 213, + 188, 189, 132, 0, 257, 159, 171, 155, 228, 296, + 297, 154, 327, 139, 311, 135, 140, 310, 221, 292, + 300, 214, 206, 134, 298, 212, 205, 193, 165, 179, + 249, 202, 250, 180, 217, 216, 218, 0, 0, 0, + 282, 307, 328, 144, 0, 290, 320, 323, 0, 253, + 145, 172, 164, 248, 170, 196, 319, 321, 322, 220, + 141, 182, 278, 192, 200, 256, 326, 236, 262, 148, + 306, 279, 423, 434, 429, 430, 427, 428, 426, 425, + 424, 437, 415, 416, 417, 418, 420, 0, 431, 432, + 419, 126, 136, 197, 325, 254, 169, 308, 0, 0, + 157, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 128, 129, 137, 143, 149, 156, 163, + 167, 174, 178, 181, 184, 185, 186, 190, 204, 208, + 209, 210, 211, 222, 223, 224, 227, 230, 231, 232, + 234, 235, 238, 242, 243, 244, 245, 246, 247, 255, + 258, 264, 265, 266, 267, 268, 269, 270, 273, 274, + 275, 276, 283, 286, 294, 295, 305, 313, 317, 176, + 302, 318, 444, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 229, 0, 0, 0, 0, + 379, 0, 0, 0, 161, 0, 378, 0, 0, 0, + 195, 0, 0, 240, 0, 272, 152, 203, 201, 291, + 166, 162, 160, 151, 183, 207, 239, 288, 233, 422, + 198, 0, 0, 280, 215, 0, 0, 0, 0, 0, + 413, 414, 0, 0, 0, 0, 0, 0, 0, 0, + 187, 150, 130, 226, 281, 168, 64, 0, 0, 112, + 113, 114, 400, 399, 402, 403, 404, 405, 0, 0, + 146, 401, 406, 407, 408, 0, 0, 0, 0, 376, + 393, 0, 421, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 390, 391, 0, 0, 0, 0, 436, 0, + 392, 0, 0, 385, 386, 388, 387, 389, 394, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 173, 435, + 0, 0, 314, 0, 0, 433, 0, 251, 0, 285, + 177, 194, 142, 191, 127, 138, 0, 175, 225, 259, + 263, 0, 0, 0, 153, 0, 261, 237, 304, 0, + 241, 260, 199, 293, 252, 303, 315, 316, 158, 219, + 309, 289, 312, 324, 277, 131, 287, 301, 147, 271, + 0, 0, 0, 133, 299, 284, 213, 188, 189, 132, + 0, 257, 159, 171, 155, 228, 296, 297, 154, 327, + 139, 311, 135, 140, 310, 221, 292, 300, 214, 206, + 134, 298, 212, 205, 193, 165, 179, 249, 202, 250, + 180, 217, 216, 218, 0, 0, 0, 282, 307, 328, + 144, 0, 290, 320, 323, 0, 253, 145, 172, 164, + 248, 170, 196, 319, 321, 322, 220, 141, 182, 278, + 192, 200, 256, 326, 236, 262, 148, 306, 279, 423, + 434, 429, 430, 427, 428, 426, 425, 424, 437, 415, + 416, 417, 418, 420, 0, 431, 432, 419, 126, 136, + 197, 325, 254, 169, 308, 0, 0, 157, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 128, 129, 137, 143, 149, 156, 163, 167, 174, 178, + 181, 184, 185, 186, 190, 204, 208, 209, 210, 211, + 222, 223, 224, 227, 230, 231, 232, 234, 235, 238, + 242, 243, 244, 245, 246, 247, 255, 258, 264, 265, + 266, 267, 268, 269, 270, 273, 274, 275, 276, 283, + 286, 294, 295, 305, 313, 317, 176, 302, 318, 229, + 0, 0, 0, 0, 379, 0, 0, 0, 161, 0, + 378, 0, 0, 0, 195, 0, 0, 240, 0, 272, + 152, 203, 201, 291, 166, 162, 160, 151, 183, 207, + 239, 288, 233, 422, 198, 0, 0, 280, 215, 0, + 0, 0, 0, 0, 413, 414, 0, 0, 0, 0, + 0, 0, 0, 0, 187, 150, 130, 226, 281, 168, + 64, 0, 0, 112, 113, 114, 400, 399, 402, 403, + 404, 405, 0, 0, 146, 401, 406, 407, 408, 0, + 0, 0, 0, 376, 393, 0, 421, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 390, 391, 0, 0, + 0, 0, 436, 0, 392, 0, 0, 385, 386, 388, + 387, 389, 394, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 173, 435, 0, 0, 314, 0, 0, 433, + 0, 251, 0, 285, 177, 194, 142, 191, 127, 138, + 0, 175, 225, 259, 263, 0, 0, 0, 153, 0, + 261, 237, 304, 0, 241, 260, 199, 293, 252, 303, + 315, 316, 158, 219, 309, 289, 312, 324, 277, 131, + 287, 301, 147, 271, 0, 0, 0, 133, 299, 284, + 213, 188, 189, 132, 0, 257, 159, 171, 155, 228, + 296, 297, 154, 327, 139, 311, 135, 140, 310, 221, + 292, 300, 214, 206, 134, 298, 212, 205, 193, 165, + 179, 249, 202, 250, 180, 217, 216, 218, 0, 0, + 0, 282, 307, 328, 144, 0, 290, 320, 323, 0, + 253, 145, 172, 164, 248, 170, 196, 319, 321, 322, + 220, 141, 182, 278, 192, 200, 256, 326, 236, 262, + 148, 306, 279, 423, 434, 429, 430, 427, 428, 426, + 425, 424, 437, 415, 416, 417, 418, 420, 0, 431, + 432, 419, 126, 136, 197, 325, 254, 169, 308, 0, + 0, 157, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 128, 129, 137, 143, 149, 156, + 163, 167, 174, 178, 181, 184, 185, 186, 190, 204, + 208, 209, 210, 211, 222, 223, 224, 227, 230, 231, + 232, 234, 235, 238, 242, 243, 244, 245, 246, 247, + 255, 258, 264, 265, 266, 267, 268, 269, 270, 273, + 274, 275, 276, 283, 286, 294, 295, 305, 313, 317, + 176, 302, 318, 229, 0, 0, 0, 0, 0, 0, + 0, 0, 161, 0, 0, 0, 0, 0, 195, 0, + 0, 240, 0, 272, 152, 203, 201, 291, 166, 162, + 160, 151, 183, 207, 239, 288, 233, 422, 198, 0, + 0, 280, 215, 0, 0, 0, 0, 0, 413, 414, + 0, 0, 0, 0, 0, 0, 0, 0, 187, 150, + 130, 226, 281, 168, 64, 0, 0, 112, 113, 114, + 400, 399, 402, 403, 404, 405, 0, 0, 146, 401, + 406, 407, 408, 0, 0, 0, 0, 0, 393, 0, + 421, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 390, 391, 0, 0, 0, 0, 436, 0, 392, 0, + 0, 385, 386, 388, 387, 389, 394, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 173, 435, 0, 0, + 314, 0, 0, 433, 0, 251, 0, 285, 177, 194, + 142, 191, 127, 138, 0, 175, 225, 259, 263, 0, + 0, 0, 153, 0, 261, 237, 304, 1763, 241, 260, + 199, 293, 252, 303, 315, 316, 158, 219, 309, 289, + 312, 324, 277, 131, 287, 301, 147, 271, 0, 0, + 0, 133, 299, 284, 213, 188, 189, 132, 0, 257, + 159, 171, 155, 228, 296, 297, 154, 327, 139, 311, + 135, 140, 310, 221, 292, 300, 214, 206, 134, 298, + 212, 205, 193, 165, 179, 249, 202, 250, 180, 217, + 216, 218, 0, 0, 0, 282, 307, 328, 144, 0, + 290, 320, 323, 0, 253, 145, 172, 164, 248, 170, + 196, 319, 321, 322, 220, 141, 182, 278, 192, 200, + 256, 326, 236, 262, 148, 306, 279, 423, 434, 429, + 430, 427, 428, 426, 425, 424, 437, 415, 416, 417, + 418, 420, 0, 431, 432, 419, 126, 136, 197, 325, + 254, 169, 308, 0, 0, 157, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 128, 129, + 137, 143, 149, 156, 163, 167, 174, 178, 181, 184, + 185, 186, 190, 204, 208, 209, 210, 211, 222, 223, + 224, 227, 230, 231, 232, 234, 235, 238, 242, 243, + 244, 245, 246, 247, 255, 258, 264, 265, 266, 267, + 268, 269, 270, 273, 274, 275, 276, 283, 286, 294, + 295, 305, 313, 317, 176, 302, 318, 229, 0, 0, + 0, 0, 0, 0, 0, 0, 161, 0, 0, 0, + 0, 0, 195, 0, 0, 240, 0, 272, 152, 203, + 201, 291, 166, 162, 160, 151, 183, 207, 239, 288, + 233, 422, 198, 0, 0, 280, 215, 0, 0, 0, + 0, 0, 413, 414, 0, 0, 0, 0, 0, 0, + 0, 0, 187, 150, 130, 226, 281, 168, 64, 0, + 451, 112, 113, 114, 400, 399, 402, 403, 404, 405, + 0, 0, 146, 401, 406, 407, 408, 0, 0, 0, + 0, 0, 393, 0, 421, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 390, 391, 0, 0, 0, 0, + 436, 0, 392, 0, 0, 385, 386, 388, 387, 389, + 394, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 173, 435, 0, 0, 314, 0, 0, 433, 0, 251, + 0, 285, 177, 194, 142, 191, 127, 138, 0, 175, + 225, 259, 263, 0, 0, 0, 153, 0, 261, 237, + 304, 0, 241, 260, 199, 293, 252, 303, 315, 316, + 158, 219, 309, 289, 312, 324, 277, 131, 287, 301, + 147, 271, 0, 0, 0, 133, 299, 284, 213, 188, + 189, 132, 0, 257, 159, 171, 155, 228, 296, 297, + 154, 327, 139, 311, 135, 140, 310, 221, 292, 300, + 214, 206, 134, 298, 212, 205, 193, 165, 179, 249, + 202, 250, 180, 217, 216, 218, 0, 0, 0, 282, + 307, 328, 144, 0, 290, 320, 323, 0, 253, 145, + 172, 164, 248, 170, 196, 319, 321, 322, 220, 141, + 182, 278, 192, 200, 256, 326, 236, 262, 148, 306, + 279, 423, 434, 429, 430, 427, 428, 426, 425, 424, + 437, 415, 416, 417, 418, 420, 0, 431, 432, 419, + 126, 136, 197, 325, 254, 169, 308, 0, 0, 157, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 128, 129, 137, 143, 149, 156, 163, 167, + 174, 178, 181, 184, 185, 186, 190, 204, 208, 209, + 210, 211, 222, 223, 224, 227, 230, 231, 232, 234, + 235, 238, 242, 243, 244, 245, 246, 247, 255, 258, + 264, 265, 266, 267, 268, 269, 270, 273, 274, 275, + 276, 283, 286, 294, 295, 305, 313, 317, 176, 302, + 318, 229, 0, 0, 0, 0, 0, 0, 0, 0, + 161, 0, 0, 0, 0, 0, 195, 0, 0, 240, + 0, 272, 152, 203, 201, 291, 166, 162, 160, 151, + 183, 207, 239, 288, 233, 422, 198, 0, 0, 280, + 215, 0, 0, 0, 0, 0, 413, 414, 0, 0, + 0, 0, 0, 0, 0, 0, 187, 150, 130, 226, + 281, 168, 64, 0, 0, 112, 113, 114, 400, 399, + 402, 403, 404, 405, 0, 0, 146, 401, 406, 407, + 408, 0, 0, 0, 0, 0, 393, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 390, 391, + 0, 0, 0, 0, 436, 0, 392, 0, 0, 385, + 386, 388, 387, 389, 394, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 173, 435, 0, 0, 314, 0, + 0, 433, 0, 251, 0, 285, 177, 194, 142, 191, + 127, 138, 0, 175, 225, 259, 263, 0, 0, 0, + 153, 0, 261, 237, 304, 0, 241, 260, 199, 293, + 252, 303, 315, 316, 158, 219, 309, 289, 312, 324, + 277, 131, 287, 301, 147, 271, 0, 0, 0, 133, + 299, 284, 213, 188, 189, 132, 0, 257, 159, 171, + 155, 228, 296, 297, 154, 327, 139, 311, 135, 140, + 310, 221, 292, 300, 214, 206, 134, 298, 212, 205, + 193, 165, 179, 249, 202, 250, 180, 217, 216, 218, + 0, 0, 0, 282, 307, 328, 144, 0, 290, 320, + 323, 0, 253, 145, 172, 164, 248, 170, 196, 319, + 321, 322, 220, 141, 182, 278, 192, 200, 256, 326, + 236, 262, 148, 306, 279, 423, 434, 429, 430, 427, + 428, 426, 425, 424, 437, 415, 416, 417, 418, 420, + 0, 431, 432, 419, 126, 136, 197, 325, 254, 169, + 308, 0, 0, 157, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 128, 129, 137, 143, + 149, 156, 163, 167, 174, 178, 181, 184, 185, 186, + 190, 204, 208, 209, 210, 211, 222, 223, 224, 227, + 230, 231, 232, 234, 235, 238, 242, 243, 244, 245, + 246, 247, 255, 258, 264, 265, 266, 267, 268, 269, + 270, 273, 274, 275, 276, 283, 286, 294, 295, 305, + 313, 317, 176, 302, 318, 229, 0, 0, 0, 0, + 0, 0, 0, 0, 161, 0, 0, 0, 0, 0, + 195, 0, 0, 240, 0, 272, 152, 203, 201, 291, + 166, 162, 160, 151, 183, 207, 239, 288, 233, 0, + 198, 0, 0, 280, 215, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 187, 150, 130, 226, 281, 168, 0, 0, 0, 112, + 113, 114, 0, 0, 0, 0, 0, 0, 0, 0, + 146, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 708, 707, + 717, 718, 710, 711, 712, 713, 714, 715, 716, 709, + 0, 0, 719, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 173, 0, + 0, 0, 314, 0, 0, 0, 0, 251, 0, 285, + 177, 194, 142, 191, 127, 138, 0, 175, 225, 259, + 263, 0, 0, 0, 153, 0, 261, 237, 304, 0, + 241, 260, 199, 293, 252, 303, 315, 316, 158, 219, + 309, 289, 312, 324, 277, 131, 287, 301, 147, 271, + 0, 0, 0, 133, 299, 284, 213, 188, 189, 132, + 0, 257, 159, 171, 155, 228, 296, 297, 154, 327, + 139, 311, 135, 140, 310, 221, 292, 300, 214, 206, + 134, 298, 212, 205, 193, 165, 179, 249, 202, 250, + 180, 217, 216, 218, 0, 0, 0, 282, 307, 328, + 144, 0, 290, 320, 323, 0, 253, 145, 172, 164, + 248, 170, 196, 319, 321, 322, 220, 141, 182, 278, + 192, 200, 256, 326, 236, 262, 148, 306, 279, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 126, 136, + 197, 325, 254, 169, 308, 0, 0, 157, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 128, 129, 137, 143, 149, 156, 163, 167, 174, 178, + 181, 184, 185, 186, 190, 204, 208, 209, 210, 211, + 222, 223, 224, 227, 230, 231, 232, 234, 235, 238, + 242, 243, 244, 245, 246, 247, 255, 258, 264, 265, + 266, 267, 268, 269, 270, 273, 274, 275, 276, 283, + 286, 294, 295, 305, 313, 317, 176, 302, 318, 229, + 0, 0, 0, 804, 0, 0, 0, 0, 161, 0, + 0, 0, 0, 0, 195, 0, 0, 240, 0, 272, + 152, 203, 201, 291, 166, 162, 160, 151, 183, 207, + 239, 288, 233, 0, 198, 0, 0, 280, 215, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 187, 150, 130, 226, 281, 168, + 0, 0, 0, 112, 113, 114, 0, 806, 0, 0, + 0, 0, 0, 0, 146, 0, 0, 0, 0, 0, + 697, 698, 696, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 699, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 173, 0, 0, 0, 314, 0, 0, 0, + 0, 251, 0, 285, 177, 194, 142, 191, 127, 138, + 0, 175, 225, 259, 263, 0, 0, 0, 153, 0, + 261, 237, 304, 0, 241, 260, 199, 293, 252, 303, + 315, 316, 158, 219, 309, 289, 312, 324, 277, 131, + 287, 301, 147, 271, 0, 0, 0, 133, 299, 284, + 213, 188, 189, 132, 0, 257, 159, 171, 155, 228, + 296, 297, 154, 327, 139, 311, 135, 140, 310, 221, + 292, 300, 214, 206, 134, 298, 212, 205, 193, 165, + 179, 249, 202, 250, 180, 217, 216, 218, 0, 0, + 0, 282, 307, 328, 144, 0, 290, 320, 323, 0, + 253, 145, 172, 164, 248, 170, 196, 319, 321, 322, + 220, 141, 182, 278, 192, 200, 256, 326, 236, 262, + 148, 306, 279, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 126, 136, 197, 325, 254, 169, 308, 0, + 0, 157, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 128, 129, 137, 143, 149, 156, + 163, 167, 174, 178, 181, 184, 185, 186, 190, 204, + 208, 209, 210, 211, 222, 223, 224, 227, 230, 231, + 232, 234, 235, 238, 242, 243, 244, 245, 246, 247, + 255, 258, 264, 265, 266, 267, 268, 269, 270, 273, + 274, 275, 276, 283, 286, 294, 295, 305, 313, 317, + 176, 302, 318, 229, 0, 0, 0, 0, 0, 0, + 0, 0, 161, 1145, 0, 0, 0, 0, 195, 0, + 0, 240, 0, 272, 152, 203, 201, 291, 166, 162, + 160, 151, 183, 207, 239, 288, 233, 0, 198, 0, + 0, 280, 215, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 187, 150, + 130, 226, 281, 168, 0, 0, 0, 112, 113, 114, + 0, 0, 0, 0, 0, 0, 0, 0, 146, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 173, 0, 0, 1144, + 314, 0, 0, 0, 1140, 1137, 0, 1138, 1139, 194, + 611, 191, 127, 138, 1135, 1142, 225, 259, 263, 0, + 0, 0, 153, 0, 261, 237, 304, 0, 241, 260, + 199, 293, 252, 303, 315, 316, 158, 219, 309, 289, + 312, 324, 277, 131, 287, 301, 147, 271, 0, 0, + 0, 133, 299, 284, 213, 188, 189, 132, 0, 257, + 159, 171, 155, 228, 296, 297, 154, 327, 139, 311, + 135, 140, 310, 221, 292, 300, 214, 206, 134, 298, + 212, 205, 193, 165, 179, 249, 202, 250, 180, 217, + 216, 218, 0, 0, 0, 282, 307, 328, 144, 0, + 290, 320, 323, 0, 253, 145, 172, 164, 248, 170, + 196, 319, 321, 322, 220, 141, 182, 278, 192, 200, + 256, 326, 236, 262, 148, 306, 279, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 126, 136, 197, 325, + 254, 169, 308, 0, 0, 157, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 128, 129, + 137, 143, 149, 156, 163, 167, 174, 178, 181, 184, + 185, 186, 190, 204, 208, 209, 210, 211, 222, 223, + 224, 227, 230, 231, 232, 234, 235, 238, 242, 243, + 244, 245, 246, 247, 255, 258, 264, 265, 266, 267, + 268, 269, 270, 273, 274, 275, 276, 283, 286, 294, + 295, 305, 313, 317, 176, 302, 318, 31, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 229, 0, 0, 0, 0, 0, 0, 0, 0, 161, + 0, 0, 0, 0, 0, 195, 0, 0, 240, 0, + 272, 152, 203, 201, 291, 166, 162, 160, 151, 183, + 207, 239, 288, 233, 0, 198, 0, 0, 280, 215, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 187, 150, 130, 226, 281, + 168, 64, 0, 451, 112, 113, 114, 0, 0, 0, + 0, 0, 0, 0, 0, 146, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 173, 0, 0, 0, 314, 0, 0, + 0, 0, 251, 0, 285, 177, 194, 142, 191, 127, + 138, 0, 175, 225, 259, 263, 0, 0, 0, 153, + 0, 261, 237, 304, 0, 241, 260, 199, 293, 252, + 303, 315, 316, 158, 219, 309, 289, 312, 324, 277, + 131, 287, 301, 147, 271, 0, 0, 0, 133, 299, + 284, 213, 188, 189, 132, 0, 257, 159, 171, 155, + 228, 296, 297, 154, 327, 139, 311, 135, 140, 310, + 221, 292, 300, 214, 206, 134, 298, 212, 205, 193, + 165, 179, 249, 202, 250, 180, 217, 216, 218, 0, + 0, 0, 282, 307, 328, 144, 0, 290, 320, 323, + 0, 253, 145, 172, 164, 248, 170, 196, 319, 321, + 322, 220, 141, 182, 278, 192, 200, 256, 326, 236, + 262, 148, 306, 279, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 126, 136, 197, 325, 254, 169, 308, + 0, 0, 157, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 128, 129, 137, 143, 149, + 156, 163, 167, 174, 178, 181, 184, 185, 186, 190, + 204, 208, 209, 210, 211, 222, 223, 224, 227, 230, + 231, 232, 234, 235, 238, 242, 243, 244, 245, 246, + 247, 255, 258, 264, 265, 266, 267, 268, 269, 270, + 273, 274, 275, 276, 283, 286, 294, 295, 305, 313, + 317, 176, 302, 318, 229, 0, 0, 0, 1102, 0, + 0, 0, 0, 161, 0, 0, 0, 0, 0, 195, + 0, 0, 240, 0, 272, 152, 203, 201, 291, 166, + 162, 160, 151, 183, 207, 239, 288, 233, 0, 198, + 0, 0, 280, 215, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 187, + 150, 130, 226, 281, 168, 0, 0, 0, 112, 113, + 114, 0, 1104, 0, 0, 0, 0, 0, 0, 146, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, + 0, 314, 0, 0, 0, 0, 251, 0, 285, 177, + 194, 142, 191, 127, 138, 0, 175, 225, 259, 263, + 0, 0, 0, 153, 0, 261, 237, 304, 0, 241, + 260, 199, 293, 252, 303, 315, 316, 158, 219, 309, + 289, 312, 324, 277, 131, 287, 301, 147, 271, 0, + 0, 0, 133, 299, 284, 213, 188, 189, 132, 0, + 257, 159, 171, 155, 228, 296, 297, 154, 327, 139, + 311, 135, 140, 310, 221, 292, 300, 214, 206, 134, + 298, 212, 205, 193, 165, 179, 249, 202, 250, 180, + 217, 216, 218, 0, 0, 0, 282, 307, 328, 144, + 0, 290, 320, 323, 0, 253, 145, 172, 164, 248, + 170, 196, 319, 321, 322, 220, 141, 182, 278, 192, + 200, 256, 326, 236, 262, 148, 306, 279, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 126, 136, 197, + 325, 254, 169, 308, 0, 0, 157, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, + 129, 137, 143, 149, 156, 163, 167, 174, 178, 181, + 184, 185, 186, 190, 204, 208, 209, 210, 211, 222, + 223, 224, 227, 230, 231, 232, 234, 235, 238, 242, + 243, 244, 245, 246, 247, 255, 258, 264, 265, 266, + 267, 268, 269, 270, 273, 274, 275, 276, 283, 286, + 294, 295, 305, 313, 317, 176, 302, 318, 31, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 229, 0, 0, 0, 0, 0, 0, 0, 0, + 161, 0, 0, 0, 0, 0, 195, 0, 0, 240, + 0, 272, 152, 203, 201, 291, 166, 162, 160, 151, + 183, 207, 239, 288, 233, 0, 198, 0, 0, 280, + 215, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 187, 150, 130, 226, + 281, 168, 64, 0, 0, 112, 113, 114, 0, 0, + 0, 0, 0, 0, 0, 0, 146, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 173, 0, 0, 0, 314, 0, + 0, 0, 0, 251, 0, 285, 177, 194, 142, 191, + 127, 138, 0, 175, 225, 259, 263, 0, 0, 0, + 153, 0, 261, 237, 304, 0, 241, 260, 199, 293, + 252, 303, 315, 316, 158, 219, 309, 289, 312, 324, + 277, 131, 287, 301, 147, 271, 0, 0, 0, 133, + 299, 284, 213, 188, 189, 132, 0, 257, 159, 171, + 155, 228, 296, 297, 154, 327, 139, 311, 135, 140, + 310, 221, 292, 300, 214, 206, 134, 298, 212, 205, + 193, 165, 179, 249, 202, 250, 180, 217, 216, 218, + 0, 0, 0, 282, 307, 328, 144, 0, 290, 320, + 323, 0, 253, 145, 172, 164, 248, 170, 196, 319, + 321, 322, 220, 141, 182, 278, 192, 200, 256, 326, + 236, 262, 148, 306, 279, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 126, 136, 197, 325, 254, 169, + 308, 0, 0, 157, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 128, 129, 137, 143, + 149, 156, 163, 167, 174, 178, 181, 184, 185, 186, + 190, 204, 208, 209, 210, 211, 222, 223, 224, 227, + 230, 231, 232, 234, 235, 238, 242, 243, 244, 245, + 246, 247, 255, 258, 264, 265, 266, 267, 268, 269, + 270, 273, 274, 275, 276, 283, 286, 294, 295, 305, + 313, 317, 176, 302, 318, 229, 0, 0, 0, 1102, + 0, 0, 0, 0, 161, 0, 0, 0, 0, 0, + 195, 0, 0, 240, 0, 272, 152, 203, 201, 291, + 166, 162, 160, 151, 183, 207, 239, 288, 233, 0, + 198, 0, 0, 280, 215, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 187, 150, 130, 226, 281, 168, 0, 0, 0, 112, + 113, 114, 0, 1104, 0, 0, 0, 0, 0, 0, + 146, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 173, 0, + 0, 0, 314, 0, 0, 0, 0, 251, 0, 285, + 177, 194, 142, 191, 127, 138, 0, 175, 225, 259, + 263, 0, 0, 0, 153, 0, 261, 237, 304, 0, + 1100, 260, 199, 293, 252, 303, 315, 316, 158, 219, + 309, 289, 312, 324, 277, 131, 287, 301, 147, 271, + 0, 0, 0, 133, 299, 284, 213, 188, 189, 132, + 0, 257, 159, 171, 155, 228, 296, 297, 154, 327, + 139, 311, 135, 140, 310, 221, 292, 300, 214, 206, + 134, 298, 212, 205, 193, 165, 179, 249, 202, 250, + 180, 217, 216, 218, 0, 0, 0, 282, 307, 328, + 144, 0, 290, 320, 323, 0, 253, 145, 172, 164, + 248, 170, 196, 319, 321, 322, 220, 141, 182, 278, + 192, 200, 256, 326, 236, 262, 148, 306, 279, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 126, 136, + 197, 325, 254, 169, 308, 0, 0, 157, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 128, 129, 137, 143, 149, 156, 163, 167, 174, 178, + 181, 184, 185, 186, 190, 204, 208, 209, 210, 211, + 222, 223, 224, 227, 230, 231, 232, 234, 235, 238, + 242, 243, 244, 245, 246, 247, 255, 258, 264, 265, + 266, 267, 268, 269, 270, 273, 274, 275, 276, 283, + 286, 294, 295, 305, 313, 317, 176, 302, 318, 229, + 0, 0, 0, 0, 0, 0, 0, 0, 161, 0, + 0, 0, 0, 0, 195, 0, 0, 240, 0, 272, + 152, 203, 201, 291, 166, 162, 160, 151, 183, 207, + 239, 288, 233, 0, 198, 0, 0, 280, 215, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 187, 150, 130, 226, 281, 168, + 0, 0, 0, 112, 113, 114, 0, 0, 1067, 0, + 0, 1068, 0, 0, 146, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 173, 0, 0, 0, 314, 0, 0, 0, + 0, 251, 0, 285, 177, 194, 142, 191, 127, 138, + 0, 175, 225, 259, 263, 0, 0, 0, 153, 0, + 261, 237, 304, 0, 241, 260, 199, 293, 252, 303, + 315, 316, 158, 219, 309, 289, 312, 324, 277, 131, + 287, 301, 147, 271, 0, 0, 0, 133, 299, 284, + 213, 188, 189, 132, 0, 257, 159, 171, 155, 228, + 296, 297, 154, 327, 139, 311, 135, 140, 310, 221, + 292, 300, 214, 206, 134, 298, 212, 205, 193, 165, + 179, 249, 202, 250, 180, 217, 216, 218, 0, 0, + 0, 282, 307, 328, 144, 0, 290, 320, 323, 0, + 253, 145, 172, 164, 248, 170, 196, 319, 321, 322, + 220, 141, 182, 278, 192, 200, 256, 326, 236, 262, + 148, 306, 279, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 126, 136, 197, 325, 254, 169, 308, 0, + 0, 157, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 128, 129, 137, 143, 149, 156, + 163, 167, 174, 178, 181, 184, 185, 186, 190, 204, + 208, 209, 210, 211, 222, 223, 224, 227, 230, 231, + 232, 234, 235, 238, 242, 243, 244, 245, 246, 247, + 255, 258, 264, 265, 266, 267, 268, 269, 270, 273, + 274, 275, 276, 283, 286, 294, 295, 305, 313, 317, + 176, 302, 318, 229, 0, 0, 0, 0, 0, 0, + 0, 0, 161, 0, 838, 0, 0, 0, 195, 0, + 0, 240, 0, 272, 152, 203, 201, 291, 166, 162, + 160, 151, 183, 207, 239, 288, 233, 0, 198, 0, + 0, 280, 215, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 187, 150, + 130, 226, 281, 168, 0, 0, 0, 112, 113, 114, + 0, 837, 0, 0, 0, 0, 0, 0, 146, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, + 314, 0, 0, 0, 0, 251, 0, 285, 177, 194, + 142, 191, 127, 138, 0, 175, 225, 259, 263, 0, + 0, 0, 153, 0, 261, 237, 304, 0, 241, 260, + 199, 293, 252, 303, 315, 316, 158, 219, 309, 289, + 312, 324, 277, 131, 287, 301, 147, 271, 0, 0, + 0, 133, 299, 284, 213, 188, 189, 132, 0, 257, + 159, 171, 155, 228, 296, 297, 154, 327, 139, 311, + 135, 140, 310, 221, 292, 300, 214, 206, 134, 298, + 212, 205, 193, 165, 179, 249, 202, 250, 180, 217, + 216, 218, 0, 0, 0, 282, 307, 328, 144, 0, + 290, 320, 323, 0, 253, 145, 172, 164, 248, 170, + 196, 319, 321, 322, 220, 141, 182, 278, 192, 200, + 256, 326, 236, 262, 148, 306, 279, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 126, 136, 197, 325, + 254, 169, 308, 0, 0, 157, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 128, 129, + 137, 143, 149, 156, 163, 167, 174, 178, 181, 184, + 185, 186, 190, 204, 208, 209, 210, 211, 222, 223, + 224, 227, 230, 231, 232, 234, 235, 238, 242, 243, + 244, 245, 246, 247, 255, 258, 264, 265, 266, 267, + 268, 269, 270, 273, 274, 275, 276, 283, 286, 294, + 295, 305, 313, 317, 176, 302, 318, 229, 0, 0, + 0, 0, 0, 0, 0, 0, 161, 0, 0, 0, + 0, 0, 195, 0, 0, 240, 0, 272, 152, 203, + 201, 291, 166, 162, 160, 151, 183, 207, 239, 288, + 233, 0, 198, 0, 0, 280, 215, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 187, 150, 130, 226, 281, 168, 0, 0, + 0, 112, 113, 114, 0, 0, 0, 0, 0, 0, + 0, 0, 146, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 605, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 173, 0, 0, 0, 314, 0, 0, 0, 0, 251, + 0, 285, 177, 194, 611, 191, 127, 138, 609, 175, + 225, 259, 263, 0, 0, 0, 153, 0, 261, 237, + 304, 0, 241, 260, 199, 293, 252, 303, 315, 316, + 158, 219, 309, 289, 312, 324, 277, 131, 287, 301, + 147, 271, 0, 0, 0, 133, 299, 284, 213, 188, + 189, 132, 0, 257, 159, 171, 155, 228, 296, 297, + 154, 327, 139, 311, 135, 140, 310, 221, 292, 300, + 214, 206, 134, 298, 212, 205, 193, 165, 179, 249, + 202, 250, 180, 217, 216, 218, 0, 0, 0, 282, + 307, 328, 144, 0, 290, 320, 323, 0, 253, 145, + 172, 164, 248, 170, 196, 319, 321, 322, 220, 141, + 182, 278, 192, 200, 256, 326, 236, 262, 148, 306, + 279, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 126, 136, 197, 325, 254, 169, 308, 0, 0, 157, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 128, 129, 137, 143, 149, 156, 163, 167, + 174, 178, 181, 184, 185, 186, 190, 204, 208, 209, + 210, 211, 222, 223, 224, 227, 230, 231, 232, 234, + 235, 238, 242, 243, 244, 245, 246, 247, 255, 258, + 264, 265, 266, 267, 268, 269, 270, 273, 274, 275, + 276, 283, 286, 294, 295, 305, 313, 317, 176, 302, + 318, 229, 0, 0, 0, 0, 0, 0, 0, 0, + 161, 0, 0, 0, 0, 0, 195, 0, 0, 240, + 0, 272, 152, 203, 201, 291, 166, 162, 160, 151, + 183, 207, 239, 288, 233, 0, 198, 0, 0, 280, + 215, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 187, 150, 130, 226, + 281, 168, 0, 0, 451, 112, 113, 114, 0, 0, + 0, 0, 0, 0, 0, 0, 146, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 173, 0, 0, 0, 314, 0, + 0, 0, 0, 251, 0, 285, 177, 194, 142, 191, + 127, 138, 0, 175, 225, 259, 263, 0, 0, 0, + 153, 0, 261, 237, 304, 0, 241, 260, 199, 293, + 252, 303, 315, 316, 158, 219, 309, 289, 312, 324, + 277, 131, 287, 301, 147, 271, 0, 0, 0, 133, + 299, 284, 213, 188, 189, 132, 0, 257, 159, 171, + 155, 228, 296, 297, 154, 327, 139, 311, 135, 140, + 310, 221, 292, 300, 214, 206, 134, 298, 212, 205, + 193, 165, 179, 249, 202, 250, 180, 217, 216, 218, + 0, 0, 0, 282, 307, 328, 144, 0, 290, 320, + 323, 0, 253, 145, 172, 164, 248, 170, 196, 319, + 321, 322, 220, 141, 182, 278, 192, 200, 256, 326, + 236, 262, 148, 306, 279, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 126, 136, 197, 325, 254, 169, + 308, 0, 0, 157, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 128, 129, 137, 143, + 149, 156, 163, 167, 174, 178, 181, 184, 185, 186, + 190, 204, 208, 209, 210, 211, 222, 223, 224, 227, + 230, 231, 232, 234, 235, 238, 242, 243, 244, 245, + 246, 247, 255, 258, 264, 265, 266, 267, 268, 269, + 270, 273, 274, 275, 276, 283, 286, 294, 295, 305, + 313, 317, 176, 302, 318, 229, 0, 0, 0, 0, + 0, 0, 0, 0, 161, 0, 0, 0, 0, 0, + 195, 0, 0, 240, 0, 272, 152, 203, 201, 291, + 166, 162, 160, 151, 183, 207, 239, 288, 233, 0, + 198, 0, 0, 280, 215, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 187, 150, 130, 226, 281, 168, 64, 0, 0, 112, + 113, 114, 0, 0, 0, 0, 0, 0, 0, 0, + 146, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 173, 0, + 0, 0, 314, 0, 0, 0, 0, 251, 0, 285, + 177, 194, 142, 191, 127, 138, 0, 175, 225, 259, + 263, 0, 0, 0, 153, 0, 261, 237, 304, 0, + 241, 260, 199, 293, 252, 303, 315, 316, 158, 219, + 309, 289, 312, 324, 277, 131, 287, 301, 147, 271, + 0, 0, 0, 133, 299, 284, 213, 188, 189, 132, + 0, 257, 159, 171, 155, 228, 296, 297, 154, 327, + 139, 311, 135, 140, 310, 221, 292, 300, 214, 206, + 134, 298, 212, 205, 193, 165, 179, 249, 202, 250, + 180, 217, 216, 218, 0, 0, 0, 282, 307, 328, + 144, 0, 290, 320, 323, 0, 253, 145, 172, 164, + 248, 170, 196, 319, 321, 322, 220, 141, 182, 278, + 192, 200, 256, 326, 236, 262, 148, 306, 279, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 126, 136, + 197, 325, 254, 169, 308, 0, 0, 157, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 128, 129, 137, 143, 149, 156, 163, 167, 174, 178, + 181, 184, 185, 186, 190, 204, 208, 209, 210, 211, + 222, 223, 224, 227, 230, 231, 232, 234, 235, 238, + 242, 243, 244, 245, 246, 247, 255, 258, 264, 265, + 266, 267, 268, 269, 270, 273, 274, 275, 276, 283, + 286, 294, 295, 305, 313, 317, 176, 302, 318, 229, + 0, 0, 0, 0, 0, 0, 0, 0, 161, 0, + 0, 0, 0, 0, 195, 0, 0, 240, 0, 272, + 152, 203, 201, 291, 166, 162, 160, 151, 183, 207, + 239, 288, 233, 0, 198, 0, 0, 280, 215, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 187, 150, 130, 226, 281, 168, + 0, 0, 0, 112, 113, 114, 0, 1104, 0, 0, + 0, 0, 0, 0, 146, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 173, 0, 0, 0, 314, 0, 0, 0, + 0, 251, 0, 285, 177, 194, 142, 191, 127, 138, + 0, 175, 225, 259, 263, 0, 0, 0, 153, 0, + 261, 237, 304, 0, 241, 260, 199, 293, 252, 303, + 315, 316, 158, 219, 309, 289, 312, 324, 277, 131, + 287, 301, 147, 271, 0, 0, 0, 133, 299, 284, + 213, 188, 189, 132, 0, 257, 159, 171, 155, 228, + 296, 297, 154, 327, 139, 311, 135, 140, 310, 221, + 292, 300, 214, 206, 134, 298, 212, 205, 193, 165, + 179, 249, 202, 250, 180, 217, 216, 218, 0, 0, + 0, 282, 307, 328, 144, 0, 290, 320, 323, 0, + 253, 145, 172, 164, 248, 170, 196, 319, 321, 322, + 220, 141, 182, 278, 192, 200, 256, 326, 236, 262, + 148, 306, 279, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 126, 136, 197, 325, 254, 169, 308, 0, + 0, 157, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 128, 129, 137, 143, 149, 156, + 163, 167, 174, 178, 181, 184, 185, 186, 190, 204, + 208, 209, 210, 211, 222, 223, 224, 227, 230, 231, + 232, 234, 235, 238, 242, 243, 244, 245, 246, 247, + 255, 258, 264, 265, 266, 267, 268, 269, 270, 273, + 274, 275, 276, 283, 286, 294, 295, 305, 313, 317, + 176, 302, 318, 229, 0, 0, 0, 0, 0, 0, + 0, 0, 161, 0, 0, 0, 0, 0, 195, 0, + 0, 240, 0, 272, 152, 203, 201, 291, 166, 162, + 160, 151, 183, 207, 239, 288, 233, 0, 198, 0, + 0, 280, 215, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 187, 150, + 130, 226, 281, 168, 0, 0, 0, 112, 113, 114, + 0, 806, 0, 0, 0, 0, 0, 0, 146, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, + 314, 0, 0, 0, 0, 251, 0, 285, 177, 194, + 142, 191, 127, 138, 0, 175, 225, 259, 263, 0, + 0, 0, 153, 0, 261, 237, 304, 0, 241, 260, + 199, 293, 252, 303, 315, 316, 158, 219, 309, 289, + 312, 324, 277, 131, 287, 301, 147, 271, 0, 0, + 0, 133, 299, 284, 213, 188, 189, 132, 0, 257, + 159, 171, 155, 228, 296, 297, 154, 327, 139, 311, + 135, 140, 310, 221, 292, 300, 214, 206, 134, 298, + 212, 205, 193, 165, 179, 249, 202, 250, 180, 217, + 216, 218, 0, 0, 0, 282, 307, 328, 144, 0, + 290, 320, 323, 0, 253, 145, 172, 164, 248, 170, + 196, 319, 321, 322, 220, 141, 182, 278, 192, 200, + 256, 326, 236, 262, 148, 306, 279, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 126, 136, 197, 325, + 254, 169, 308, 0, 0, 157, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 128, 129, + 137, 143, 149, 156, 163, 167, 174, 178, 181, 184, + 185, 186, 190, 204, 208, 209, 210, 211, 222, 223, + 224, 227, 230, 231, 232, 234, 235, 238, 242, 243, + 244, 245, 246, 247, 255, 258, 264, 265, 266, 267, + 268, 269, 270, 273, 274, 275, 276, 283, 286, 294, + 295, 305, 313, 317, 176, 302, 318, 820, 0, 0, + 0, 0, 0, 0, 229, 0, 0, 0, 0, 0, + 0, 0, 0, 161, 0, 0, 0, 0, 0, 195, + 0, 0, 240, 0, 272, 152, 203, 201, 291, 166, + 162, 160, 151, 183, 207, 239, 288, 233, 0, 198, + 0, 0, 280, 215, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 187, + 150, 130, 226, 281, 168, 0, 0, 0, 112, 113, + 114, 0, 0, 0, 0, 0, 0, 0, 0, 146, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, + 0, 314, 0, 0, 0, 0, 251, 0, 285, 177, + 194, 142, 191, 127, 138, 0, 175, 225, 259, 263, + 0, 0, 0, 153, 0, 261, 237, 304, 0, 241, + 260, 199, 293, 252, 303, 315, 316, 158, 219, 309, + 289, 312, 324, 277, 131, 287, 301, 147, 271, 0, + 0, 0, 133, 299, 284, 213, 188, 189, 132, 0, + 257, 159, 171, 155, 228, 296, 297, 154, 327, 139, + 311, 135, 140, 310, 221, 292, 300, 214, 206, 134, + 298, 212, 205, 193, 165, 179, 249, 202, 250, 180, + 217, 216, 218, 0, 0, 0, 282, 307, 328, 144, + 0, 290, 320, 323, 0, 253, 145, 172, 164, 248, + 170, 196, 319, 321, 322, 220, 141, 182, 278, 192, + 200, 256, 326, 236, 262, 148, 306, 279, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 126, 136, 197, + 325, 254, 169, 308, 0, 0, 157, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, + 129, 137, 143, 149, 156, 163, 167, 174, 178, 181, + 184, 185, 186, 190, 204, 208, 209, 210, 211, 222, + 223, 224, 227, 230, 231, 232, 234, 235, 238, 242, + 243, 244, 245, 246, 247, 255, 258, 264, 265, 266, + 267, 268, 269, 270, 273, 274, 275, 276, 283, 286, + 294, 295, 305, 313, 317, 176, 302, 318, 229, 0, + 0, 0, 0, 0, 0, 0, 810, 161, 0, 0, + 0, 0, 0, 195, 0, 0, 240, 0, 272, 152, + 203, 201, 291, 166, 162, 160, 151, 183, 207, 239, + 288, 233, 0, 198, 0, 0, 280, 215, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 187, 150, 130, 226, 281, 168, 0, + 0, 0, 112, 113, 114, 0, 0, 0, 0, 0, + 0, 0, 0, 146, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 173, 0, 0, 0, 314, 0, 0, 0, 0, + 251, 0, 285, 177, 194, 142, 191, 127, 138, 0, + 175, 225, 259, 263, 0, 0, 0, 153, 0, 261, + 237, 304, 0, 241, 260, 199, 293, 252, 303, 315, + 316, 158, 219, 309, 289, 312, 324, 277, 131, 287, + 301, 147, 271, 0, 0, 0, 133, 299, 284, 213, + 188, 189, 132, 0, 257, 159, 171, 155, 228, 296, + 297, 154, 327, 139, 311, 135, 140, 310, 221, 292, + 300, 214, 206, 134, 298, 212, 205, 193, 165, 179, + 249, 202, 250, 180, 217, 216, 218, 0, 0, 0, + 282, 307, 328, 144, 0, 290, 320, 323, 0, 253, + 145, 172, 164, 248, 170, 196, 319, 321, 322, 220, + 141, 182, 278, 192, 200, 256, 326, 236, 262, 148, + 306, 279, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 126, 136, 197, 325, 254, 169, 308, 0, 0, + 157, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 128, 129, 137, 143, 149, 156, 163, + 167, 174, 178, 181, 184, 185, 186, 190, 204, 208, + 209, 210, 211, 222, 223, 224, 227, 230, 231, 232, + 234, 235, 238, 242, 243, 244, 245, 246, 247, 255, + 258, 264, 265, 266, 267, 268, 269, 270, 273, 274, + 275, 276, 283, 286, 294, 295, 305, 313, 317, 176, + 302, 318, 229, 0, 0, 0, 0, 0, 0, 0, + 0, 161, 0, 0, 0, 0, 0, 195, 0, 0, + 240, 0, 272, 152, 203, 201, 291, 166, 162, 160, + 151, 183, 207, 239, 288, 233, 0, 198, 0, 0, + 280, 215, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 187, 150, 130, + 226, 281, 168, 0, 0, 0, 112, 113, 114, 0, + 686, 0, 0, 0, 0, 0, 0, 146, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 173, 0, 0, 0, 314, + 0, 0, 0, 0, 251, 0, 285, 177, 194, 142, + 191, 127, 138, 0, 175, 225, 259, 263, 0, 0, + 0, 153, 0, 261, 237, 304, 0, 241, 260, 199, + 293, 252, 303, 315, 316, 158, 219, 309, 289, 312, + 324, 277, 131, 287, 301, 147, 271, 0, 0, 0, + 133, 299, 284, 213, 188, 189, 132, 0, 257, 159, + 171, 155, 228, 296, 297, 154, 327, 139, 311, 135, + 140, 310, 221, 292, 300, 214, 206, 134, 298, 212, + 205, 193, 165, 179, 249, 202, 250, 180, 217, 216, + 218, 0, 0, 0, 282, 307, 328, 144, 0, 290, + 320, 323, 0, 253, 145, 172, 164, 248, 170, 196, + 319, 321, 322, 220, 141, 182, 278, 192, 200, 256, + 326, 236, 262, 148, 306, 279, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 126, 136, 197, 325, 254, + 169, 308, 0, 0, 157, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 128, 129, 137, + 143, 149, 156, 163, 167, 174, 178, 181, 184, 185, + 186, 190, 204, 208, 209, 210, 211, 222, 223, 224, + 227, 230, 231, 232, 234, 235, 238, 242, 243, 244, + 245, 246, 247, 255, 258, 264, 265, 266, 267, 268, + 269, 270, 273, 274, 275, 276, 283, 286, 294, 295, + 305, 313, 317, 176, 302, 318, 229, 0, 0, 0, + 0, 0, 0, 0, 0, 161, 0, 0, 0, 0, + 0, 195, 0, 0, 240, 0, 272, 152, 203, 201, + 291, 166, 162, 160, 151, 183, 207, 239, 288, 233, + 0, 198, 0, 0, 280, 215, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 187, 150, 130, 226, 281, 168, 0, 0, 0, + 112, 113, 114, 0, 0, 0, 0, 0, 0, 0, + 0, 146, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 367, 0, 173, + 0, 0, 0, 314, 0, 0, 0, 0, 251, 0, + 285, 177, 194, 142, 191, 127, 138, 0, 175, 225, + 259, 263, 0, 0, 0, 153, 0, 261, 237, 304, + 0, 241, 260, 199, 293, 252, 303, 315, 316, 158, + 219, 309, 289, 312, 324, 277, 131, 287, 301, 147, + 271, 0, 0, 0, 133, 299, 284, 213, 188, 189, + 132, 0, 257, 159, 171, 155, 228, 296, 297, 154, + 327, 139, 311, 135, 140, 310, 221, 292, 300, 214, + 206, 134, 298, 212, 205, 193, 165, 179, 249, 202, + 250, 180, 217, 216, 218, 0, 0, 0, 282, 307, + 328, 144, 0, 290, 320, 323, 0, 253, 145, 172, + 164, 248, 170, 196, 319, 321, 322, 220, 141, 182, + 278, 192, 200, 256, 326, 236, 262, 148, 306, 279, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 126, + 136, 197, 325, 254, 169, 308, 0, 0, 157, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 128, 129, 137, 143, 149, 156, 163, 167, 174, + 178, 181, 184, 185, 186, 190, 204, 208, 209, 210, + 211, 222, 223, 224, 227, 230, 231, 232, 234, 235, + 238, 242, 243, 244, 245, 246, 247, 255, 258, 264, + 265, 266, 267, 268, 269, 270, 273, 274, 275, 276, + 283, 286, 294, 295, 305, 313, 317, 366, 302, 318, + 229, 0, 0, 0, 0, 0, 0, 0, 0, 161, + 0, 0, 0, 0, 0, 195, 0, 0, 240, 0, + 272, 152, 203, 201, 291, 166, 162, 160, 151, 183, + 207, 239, 288, 233, 0, 198, 0, 0, 280, 215, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 187, 150, 130, 226, 281, + 168, 0, 0, 0, 112, 113, 114, 0, 0, 0, + 0, 0, 0, 0, 0, 146, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 173, 0, 121, 0, 314, 0, 0, + 0, 0, 251, 0, 285, 177, 194, 142, 191, 127, + 138, 0, 175, 225, 259, 263, 0, 0, 0, 153, + 0, 261, 237, 304, 0, 241, 260, 199, 293, 252, + 303, 315, 316, 158, 219, 309, 289, 312, 324, 277, + 131, 287, 301, 147, 271, 0, 0, 0, 133, 299, + 284, 213, 188, 189, 132, 0, 257, 159, 171, 155, + 228, 296, 297, 154, 327, 139, 311, 135, 140, 310, + 221, 292, 300, 214, 206, 134, 298, 212, 205, 193, + 165, 179, 249, 202, 250, 180, 217, 216, 218, 0, + 0, 0, 282, 307, 328, 144, 0, 290, 320, 323, + 0, 253, 145, 172, 164, 248, 170, 196, 319, 321, + 322, 220, 141, 182, 278, 192, 200, 256, 326, 236, + 262, 148, 306, 279, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 126, 136, 197, 325, 254, 169, 308, + 0, 0, 157, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 128, 129, 137, 143, 149, + 156, 163, 167, 174, 178, 181, 184, 185, 186, 190, + 204, 208, 209, 210, 211, 222, 223, 224, 227, 230, + 231, 232, 234, 235, 238, 242, 243, 244, 245, 246, + 247, 255, 258, 264, 265, 266, 267, 268, 269, 270, + 273, 274, 275, 276, 283, 286, 294, 295, 305, 313, + 317, 176, 302, 318, 229, 0, 0, 0, 0, 0, + 0, 0, 0, 161, 0, 0, 0, 0, 0, 195, + 0, 0, 240, 0, 272, 152, 203, 201, 291, 166, + 162, 160, 151, 183, 207, 239, 288, 233, 0, 198, + 0, 0, 280, 215, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 187, + 150, 130, 226, 281, 168, 0, 0, 0, 112, 113, + 114, 0, 0, 0, 0, 0, 0, 0, 0, 146, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, + 0, 314, 0, 0, 0, 0, 251, 0, 285, 177, + 194, 142, 191, 127, 138, 0, 175, 225, 259, 263, + 0, 0, 0, 153, 0, 261, 237, 304, 0, 241, + 260, 199, 293, 252, 303, 315, 316, 158, 219, 309, + 289, 312, 324, 277, 131, 287, 301, 147, 271, 0, + 0, 0, 133, 299, 284, 213, 188, 189, 132, 0, + 257, 159, 171, 155, 228, 296, 297, 154, 327, 139, + 311, 135, 140, 310, 221, 292, 300, 214, 206, 134, + 298, 212, 205, 193, 165, 179, 249, 202, 250, 180, + 217, 216, 218, 0, 0, 0, 282, 307, 328, 144, + 0, 290, 320, 323, 0, 253, 145, 172, 164, 248, + 170, 196, 319, 321, 322, 220, 141, 182, 278, 192, + 200, 256, 326, 236, 262, 148, 306, 279, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 126, 136, 197, + 325, 254, 169, 308, 0, 0, 157, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, + 129, 137, 143, 149, 156, 163, 167, 174, 178, 181, + 184, 185, 186, 190, 204, 208, 209, 210, 211, 222, + 223, 224, 227, 230, 231, 232, 234, 235, 238, 242, + 243, 244, 245, 246, 247, 255, 258, 264, 265, 266, + 267, 268, 269, 270, 273, 274, 275, 276, 283, 286, + 294, 295, 305, 313, 317, 176, 302, 318, } var yyPact = [...]int{ - 133, -1000, -283, 1094, -1000, -1000, -1000, -1000, -1000, -1000, + 208, -1000, -294, 1262, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 1054, - 849, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 320, 12682, - -30, 158, -18, 18903, 152, 1818, 19267, -1000, 36, -1000, - 18, 19267, 29, 18539, -1000, -1000, -83, -90, -1000, 10498, - 975, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 829, - 1021, 1027, 1043, 670, 1125, -1000, 9029, 9029, 119, 119, - 119, 7573, -1000, -1000, 15620, 19267, 165, 19267, -156, 114, - 114, 114, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 1217, + 918, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 348, 892, + 42, 1141, -5, 587, 215, -10, 18751, 214, 2071, 19125, + -1000, 49, -1000, 40, 19125, 44, 18377, -1000, -1000, -46, + -48, -1000, 10490, 1094, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, 913, 1196, 1178, 1215, 796, 1388, -1000, 8981, + 8981, 178, 178, 178, 7485, -1000, -1000, 15378, 19125, 19125, + 19125, -152, 176, 196, 176, -1000, -1000, -1000, -1000, -1000, + -1000, 1141, -1000, -1000, 97, -1000, -1000, 19125, 19125, 290, + 1141, 61, -1000, -1000, -1000, 19125, 174, 587, 174, 174, + 174, 19125, -1000, 259, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, @@ -2943,24 +2970,23 @@ var yyPact = [...]int{ -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, 141, 19267, 568, 568, 261, 569, 19267, 106, 568, - 106, 106, 106, 19267, -1000, 224, -1000, -1000, -1000, 19267, - 568, 989, 359, 184, 264, 264, 264, -1000, 215, -1000, - 4927, 47, 52, -41, 1063, 48, -26, -1000, 359, 4927, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 136, -1000, - -1000, 19267, 18175, 151, 299, -1000, -1000, -1000, -1000, -1000, - -1000, 666, 496, -1000, 10498, 1650, 774, 774, -1000, -1000, - 202, -1000, -1000, 11590, 11590, 11590, 11590, 11590, 11590, 11590, - 11590, 11590, 11590, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, 774, 223, -1000, - 10134, 774, 774, 774, 774, 774, 774, 774, 774, 10498, - 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, - 774, 774, 774, 774, 774, 774, -1000, -1000, -1000, 1054, - -1000, 849, -1000, -1000, -1000, 998, 10498, 10498, 1054, -1000, - 906, 9029, -1000, -1000, 917, -1000, -1000, -1000, -1000, 369, - 1075, -1000, 12318, 218, 1070, 17811, -1000, 16348, 17447, 771, - 7195, -115, -1000, -1000, -1000, 291, 15256, -1000, -1000, -1000, - 988, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 19125, + 587, 1137, 441, 82, 308, 308, 308, -1000, 294, -1000, + 5157, 65, 67, -36, 1238, 55, 12, -1000, 441, 5157, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 186, -1000, + -1000, -1000, -1000, 19125, 18003, 165, 331, -1000, -1000, -1000, + -1000, -1000, -1000, 675, 513, -1000, 10490, 1727, 538, 538, + -1000, -1000, 234, -1000, -1000, 11612, 11612, 11612, 11612, 11612, + 11612, 11612, 11612, 11612, 11612, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 538, + 258, -1000, 10116, 538, 538, 538, 538, 538, 538, 538, + 538, 10490, 538, 538, 538, 538, 538, 538, 538, 538, + 538, 538, 538, 538, 538, 538, 538, 538, -1000, -1000, + -1000, 1217, -1000, 918, -1000, -1000, -1000, 1134, 10490, 10490, + 1217, -1000, 1034, 8981, -1000, -1000, 1312, -1000, -1000, -1000, + -1000, 472, 1248, -1000, 12360, 257, 1247, 17629, -1000, 16126, + 17255, 841, 7097, -67, -1000, -1000, -1000, 329, 15004, -1000, + -1000, -1000, 1133, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, @@ -2972,288 +2998,298 @@ var yyPact = [...]int{ -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, 747, 19267, -1000, -1000, 340, 568, -1000, 805, - -1000, 568, 4927, 140, 568, 318, 568, 19267, 19267, 4927, - 4927, 4927, 57, 99, 89, 19267, 557, 769, 135, 19267, - 1011, 855, 19267, 568, 568, -1000, 6439, -1000, 4927, 359, - -1000, 552, 10498, 4927, 4927, 4927, 19267, 4927, 4927, -1000, - 543, -1000, -1000, 374, -1000, -1000, -1000, -1000, -1000, -1000, - 4927, 4927, 373, 374, 373, -1000, -1000, -1000, -1000, 10498, - 264, -1000, 854, -1000, -1000, 27, -1000, -1000, -1000, -1000, - -1000, 1094, -1000, -1000, -1000, -128, -1000, -1000, 10498, 10498, - 10498, 10498, 491, 269, 11590, 416, 328, 11590, 11590, 11590, - 11590, 11590, 11590, 11590, 11590, 11590, 11590, 11590, 11590, 11590, - 11590, 11590, 612, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, 568, -1000, 1087, 676, 676, 222, 222, 222, 222, - 222, 222, 222, 222, 222, 11954, 7937, 6439, 670, 736, - 1054, 9029, 9029, 10498, 10498, 9757, 9393, 9029, 993, 313, - 496, 19267, -1000, -1000, 11226, -1000, -1000, -1000, -1000, -1000, - 541, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 19267, 19267, - 9029, 9029, 9029, 9029, 9029, -1000, 1027, 670, 917, 1006, - 1082, 259, 560, 766, -1000, 410, 1027, 14892, 749, -1000, - 917, -1000, -1000, -1000, 19267, -1000, -1000, 17076, -1000, -1000, - 6061, 19267, 68, 19267, -1000, 760, 933, -1000, -1000, -1000, - 1013, 14164, 14528, 19267, 735, 648, -1000, -1000, 211, 6817, - -115, -1000, 6817, 755, -1000, -127, -92, 8301, 191, -1000, - -1000, -1000, -1000, 4549, 13046, 626, 363, -75, -1000, -1000, - -1000, 795, -1000, 795, 795, 795, 795, -13, -13, -13, - -13, -1000, -1000, -1000, -1000, -1000, 831, 830, -1000, 795, - 795, 795, 795, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, 793, 19125, -1000, -1000, 74, 587, + -1000, 883, -1000, 790, -1000, 869, 5157, 188, 19125, 356, + 587, 587, -1000, -1000, 1122, 323, 337, 5157, 76, 169, + 105, 19125, 1141, 1093, 832, 185, 19125, 1170, 969, 19125, + 587, 587, -1000, 6321, -1000, 5157, 441, -1000, 611, 10490, + 5157, 5157, 5157, 19125, 5157, 5157, -1000, 603, -1000, -1000, + 436, -1000, -1000, -1000, -1000, -1000, -1000, 5157, 5157, 407, + 436, 407, -1000, -1000, -1000, -1000, 10490, 308, -1000, 968, + -1000, -1000, 43, -1000, -1000, -1000, -1000, -1000, 1262, -1000, + -1000, -1000, -135, -1000, -1000, 10490, 10490, 10490, 10490, 599, + 314, 11612, 435, 325, 11612, 11612, 11612, 11612, 11612, 11612, + 11612, 11612, 11612, 11612, 11612, 11612, 11612, 11612, 11612, 551, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 587, -1000, + 1260, 684, 684, 281, 281, 281, 281, 281, 281, 281, + 281, 281, 11986, 7859, 6321, 796, 766, 1217, 8981, 8981, + 10490, 10490, 9729, 9355, 8981, 1127, 340, 513, 19125, -1000, + -1000, 11238, -1000, -1000, -1000, -1000, -1000, 637, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, 19125, 19125, 8981, 8981, 8981, + 8981, 8981, -1000, 1178, 796, 1312, 1161, 1255, 305, 548, + 828, -1000, 507, 1178, 14630, 875, -1000, 1312, -1000, -1000, + -1000, 19125, -1000, -1000, 16874, -1000, -1000, 5933, 19125, 89, + 19125, -1000, 859, 1011, -1000, -1000, -1000, 1172, 13882, 14256, + 19125, 870, 813, -1000, -1000, 256, 6709, -67, -1000, 6709, + 820, -1000, -118, -78, 8233, 280, -1000, -1000, -1000, -1000, + 4381, 12734, 664, 386, -39, -1000, -1000, -1000, 869, -1000, + 869, 869, 869, 869, 8, 8, 8, 8, -1000, -1000, + -1000, -1000, -1000, 891, 890, -1000, 869, 869, 869, 869, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - 828, 828, 828, 801, 801, 91, 10498, 835, -1000, 19267, - 4927, 1010, 4927, -1000, 139, -1000, -1000, -1000, 19267, 19267, - 19267, 19267, 19267, 174, -1000, 19267, 19267, 764, -1000, 19267, - 4927, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 496, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, 19267, -1000, -1000, - -1000, -1000, 359, 19267, 19267, 19267, 359, 496, -1000, 19267, - 19267, -1000, -1000, -1000, -1000, -1000, 496, 269, 536, 391, - -1000, -1000, 442, -1000, -1000, 2126, -1000, -1000, -1000, -1000, - 416, 11590, 11590, 11590, 1053, 2126, 2101, 586, 2254, 222, - 371, 371, 238, 238, 238, 238, 238, 606, 606, -1000, - -1000, -1000, 541, -1000, -1000, -1000, 541, 9029, 9029, 762, - 774, 210, -1000, 829, -1000, -1000, 1027, 715, 715, 388, - 585, 326, 1068, 715, 307, 1065, 715, 715, 9029, -1000, - -1000, 325, -1000, 10498, 541, -1000, 209, -1000, 1380, 759, - 757, 715, 541, 541, 715, 715, 998, -1000, -1000, 967, - -1000, 900, 10498, 10498, 10498, -1000, -1000, -1000, 998, 1032, - -1000, 918, 913, 1062, 9029, 16348, 917, -1000, -1000, -1000, - 208, 1062, 768, 774, -1000, 19267, 16348, 16348, 16348, 16348, - 16348, -1000, 876, 874, -1000, 872, 866, 905, 19267, -1000, - 721, 670, 14164, 198, 774, -1000, 16712, -1000, -1000, 68, - 623, 16348, 19267, -1000, -1000, 16348, 19267, 5683, -1000, 755, - -115, -47, -1000, -1000, -1000, -1000, 496, -1000, 641, 750, - 4171, -1000, -1000, -1000, -1000, 100, -1000, -1000, 826, 568, - -1000, 1002, 280, 280, 258, 568, 999, -1000, -1000, -1000, - -1000, 991, -1000, 345, -97, -1000, -1000, 453, -13, -13, - -1000, -1000, 191, 986, 191, 191, 191, 542, 542, -1000, - -1000, -1000, -1000, -1000, 444, -1000, -1000, -1000, 398, -1000, - -1000, 805, 545, 853, 19267, 4927, -1000, -1000, -1000, -1000, - 321, 321, 268, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, 66, 833, -1000, -1000, -1000, -1000, - -11, 56, 121, -1000, 4927, -1000, 373, -1000, -1000, -1000, - 373, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 1053, 2126, - 1802, -1000, 11590, 11590, -1000, -1000, 715, 715, 9029, 6439, - 1054, 998, -1000, -1000, 182, 612, 182, 11590, 11590, -1000, - 11590, 11590, -1000, -168, 788, 301, -1000, 10498, 510, -1000, - 6439, -1000, 11590, 11590, -1000, -1000, -1000, -1000, -1000, -1000, - 498, 538, 898, 496, 496, -1000, -1000, 19267, -1000, -1000, - -1000, -1000, 1059, 10498, -1000, 744, -1000, 5305, 1027, 852, - 19267, 774, 1094, 13423, 19267, 785, -1000, 287, 933, 817, - 848, 789, -1000, -1000, -1000, -1000, 870, -1000, 868, -1000, - -1000, -1000, -1000, -1000, 670, -1000, 148, 144, 142, 19267, - -1000, 1062, 16348, 770, -1000, 770, -1000, 205, -1000, -1000, - -1000, -139, -100, -1000, -1000, -1000, 4549, -1000, 4549, -1000, - 19267, 93, -1000, 568, 568, 568, -1000, -1000, -1000, 803, - 847, 11590, -1000, -1000, -1000, 609, 191, 191, -1000, 343, - -1000, -1000, -1000, 713, -1000, 711, 738, 705, 7, 19267, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, 885, 885, 885, + 877, 877, 114, 10490, 47, 19125, 1160, 491, -1000, 19125, + -1000, 1163, 916, -1000, 323, 709, -1000, -1000, 414, 414, + 357, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, 91, -1000, 19125, 19125, 19125, 19125, 19125, 223, + 72, 19125, 19125, 824, -1000, 19125, 5157, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, 513, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, 19125, -1000, -1000, -1000, -1000, 441, 19125, + 19125, 19125, 441, 513, -1000, 19125, 19125, -1000, -1000, -1000, + -1000, -1000, 513, 314, 429, 335, -1000, -1000, 505, -1000, + -1000, 2320, -1000, -1000, -1000, -1000, 435, 11612, 11612, 11612, + 888, 2320, 2254, 553, 464, 281, 582, 582, 282, 282, + 282, 282, 282, 531, 531, -1000, -1000, -1000, 637, -1000, + -1000, -1000, 637, 8981, 8981, 823, 538, 249, -1000, 913, + -1000, -1000, 1178, 758, 758, 666, 416, 381, 1242, 758, + 375, 1240, 758, 758, 8981, -1000, -1000, 374, -1000, 10490, + 637, -1000, 248, -1000, 923, 822, 821, 758, 637, 637, + 758, 758, 1134, -1000, -1000, 1086, -1000, 1031, 10490, 10490, + 10490, -1000, -1000, -1000, 1134, 1202, -1000, 1052, 1044, 1223, + 8981, 16126, 1312, -1000, -1000, -1000, 239, 1223, 800, 538, + -1000, 19125, 16126, 16126, 16126, 16126, 16126, -1000, 1006, 1002, + -1000, 1004, 998, 1036, 19125, -1000, 764, 796, 13882, 267, + 538, -1000, 16500, -1000, -1000, 89, 737, 16126, 19125, -1000, + -1000, 16126, 19125, 5545, -1000, 820, -67, -85, -1000, -1000, + -1000, -1000, 513, -1000, 702, 814, 3993, -1000, -1000, -1000, + -1000, 159, -1000, -1000, 884, 587, -1000, 1152, 319, 319, + 311, 587, 1151, -1000, -1000, -1000, -1000, 1139, -1000, 395, + -30, -1000, -1000, 8, 8, -1000, -1000, 280, 1119, 280, + 280, 280, 601, 601, -1000, -1000, -1000, -1000, -1000, 485, + -1000, -1000, -1000, 483, -1000, -1000, 883, 591, 967, 47, + -1000, 587, 323, 588, 1109, -1000, -1000, 656, 5157, -1000, + 954, 19125, 643, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 19267, - -1000, -1000, -1000, -1000, -1000, 19267, -174, 568, 19267, 19267, - 19267, 19267, -1000, 359, 359, -1000, 11590, 2126, 2126, -1000, - -1000, 541, -1000, 1027, -1000, 541, 795, 795, -1000, 795, - 801, -1000, 795, 11, 795, 10, 541, 541, 2086, 2036, - 1929, 1359, 774, -163, -1000, 496, 10498, -1000, 1704, 1611, - 532, -13, -1000, -1000, -1000, 1057, 1042, 496, -1000, -1000, - -1000, 1004, 754, 640, -1000, -1000, 8665, 702, 912, 193, - 698, -1000, 1054, 19267, 10498, -1000, -1000, 10498, 799, -1000, - 10498, -1000, -1000, -1000, 1054, 774, 774, 774, 698, 1054, - 770, -1000, -1000, 240, -1000, -1000, -1000, 4171, -1000, 696, - -1000, 795, -1000, 999, -1000, -1000, -1000, 19267, -49, 1081, - 2126, -1000, -1000, -1000, -1000, -1000, -13, 529, -13, 385, - -1000, 384, -1000, -1000, -226, 4927, -1000, -1000, -1000, -1000, - 1000, -1000, 6439, -1000, -1000, 794, 834, -1000, -1000, -1000, - -1000, 2126, -1000, 998, -1000, -1000, 153, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, 11590, 11590, 11590, 11590, 11590, - 1027, 516, 496, 11590, 11590, -13, -51, -1000, 10498, 10498, - 996, -1000, 774, -1000, 681, 19267, 774, 19267, -1000, 19267, - 1027, -1000, 496, 496, 19267, 496, 15984, 19267, 19267, 13787, - 1027, -1000, 197, 19267, -1000, 692, -1000, 235, -1000, -82, - 191, -1000, 191, 594, 589, -1000, -1000, 774, 734, -1000, - 279, 19267, 19267, -1000, -1000, -1000, 1380, 1380, 1380, 1380, - 63, 541, -1000, 1380, 1380, -278, -1000, 970, 963, 496, - 666, 1079, -1000, 774, 1094, 188, 640, -1000, -1000, -1000, - 678, 669, -1000, 669, 669, 198, -1000, 197, -1000, 568, - 277, 506, -1000, 81, 19267, 330, 995, -1000, 994, -1000, - -1000, -1000, -1000, -1000, 65, 6439, 4549, 664, -1000, -1000, - -1000, -1000, -1000, 541, 55, -181, -1000, -1000, -1000, -51, - 157, -1000, 924, 922, 1037, 19267, 640, 19267, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, 380, -1000, -1000, 19267, -1000, - -1000, 503, -1000, -1000, 598, -1000, 19267, -1000, -1000, 833, - -1000, 895, -172, -184, 937, 940, 940, 963, 1033, 959, - 949, -1000, 479, 587, -1000, -1000, 790, -1000, -1000, 65, - 907, -174, -1000, 892, -1000, 932, 438, -1000, -1000, -1000, - -1000, 477, -1000, 1031, 1005, -1000, 19267, -1000, 62, -1000, - -178, -1000, 436, -1000, -1000, -1000, 455, 392, 577, 58, - -182, -1000, -1000, -1000, -1000, 846, 774, -190, 842, -1000, - 1074, 10862, -1000, -1000, 1078, 217, 217, 1380, 541, -1000, - -1000, -1000, 90, 401, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, 19125, -1000, -1000, -1000, -1000, -1000, 19125, 874, + -1000, -1000, -1000, -1000, 52, 75, 70, 182, -1000, 5157, + -1000, 407, -1000, -1000, -1000, 407, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, 888, 2320, 2188, -1000, 11612, 11612, -1000, + -1000, 758, 758, 8981, 6321, 1217, 1134, -1000, -1000, 272, + 551, 272, 11612, 11612, -1000, 11612, 11612, -1000, -170, 827, + 346, -1000, 10490, 640, -1000, 6321, -1000, 11612, 11612, -1000, + -1000, -1000, -1000, -1000, -1000, 560, 556, 1024, 513, 513, + -1000, -1000, 19125, -1000, -1000, -1000, -1000, 1221, 10490, -1000, + 812, -1000, 4769, 1178, 951, 19125, 538, 1262, 13121, 19125, + 872, -1000, 324, 1011, 928, 950, 965, -1000, -1000, -1000, + -1000, 996, -1000, 980, -1000, -1000, -1000, -1000, -1000, 796, + -1000, 194, 191, 190, 19125, -1000, 1223, 16126, 768, -1000, + 768, -1000, 238, -1000, -1000, -1000, -124, -111, -1000, -1000, + -1000, 4381, -1000, 4381, -1000, 19125, 156, -1000, 587, 587, + 587, -1000, -1000, -1000, 879, 930, 11612, -1000, -1000, -1000, + 280, 280, -1000, 321, -1000, -1000, -1000, 756, -1000, 754, + 807, 742, 7, -1000, 863, 1116, 323, 323, -1000, -1000, + 480, -1000, 552, -1000, -1000, 19125, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, 1157, -180, 587, 19125, 19125, 19125, -1000, + 19125, -1000, 441, 441, -1000, 11612, 2320, 2320, -1000, -1000, + 637, -1000, 1178, -1000, 637, 869, 869, -1000, 869, 877, + -1000, 869, 32, 869, 25, 637, 637, 2117, 1876, 1848, + 1117, 538, -165, -1000, 513, 10490, -1000, 1833, 1079, 546, + 8, -1000, -1000, -1000, 1219, 1214, 513, -1000, -1000, -1000, + 1155, 817, 670, -1000, -1000, 8607, 735, 1041, 232, 722, + -1000, 1217, 19125, 10490, -1000, -1000, 10490, 861, -1000, 10490, + -1000, -1000, -1000, 1217, 538, 538, 538, 722, 1217, 768, + -1000, -1000, 275, -1000, -1000, -1000, 3993, -1000, 718, -1000, + 1151, -1000, -1000, -1000, 19125, -22, 1254, 2320, -1000, -1000, + -1000, -1000, 8, 539, 8, 478, -1000, 419, -1000, -1000, + -228, -1000, -1000, 867, 995, -1000, -1000, -1000, 538, -1000, + 6321, -1000, -1000, 797, 900, -1000, -1000, -1000, -1000, 2320, + -1000, 1134, -1000, -1000, 145, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, 11612, 11612, 11612, 11612, 11612, 1178, 537, + 513, 11612, 11612, 8, -40, -1000, 10490, 10490, 1150, -1000, + 538, -1000, 878, 19125, 538, 19125, -1000, 19125, 1178, -1000, + 513, 513, 19125, 513, 15752, 19125, 19125, 13495, 1178, -1000, + 47, 716, -1000, 303, -1000, -127, 280, -1000, 280, 641, + 639, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 88, + 731, -1000, 318, 19125, 19125, -1000, -1000, -1000, 923, 923, + 923, 923, 56, 637, -1000, 923, 923, -286, -1000, 1087, + 1085, 513, 675, 1253, -1000, 538, 1262, 230, 670, -1000, + -1000, -1000, 680, 678, -1000, 678, 678, 267, -1000, -1000, + 103, 19125, 399, 1146, -1000, 1144, -1000, -1000, -1000, -1000, + -1000, 668, -1000, 19125, 6321, 4381, 663, -1000, -1000, -1000, + -1000, -1000, 637, 60, -185, -1000, -1000, -1000, -40, 184, + -1000, 1056, 1054, 1212, 19125, 670, 19125, -1000, -1000, -1000, + -1000, -1000, 19125, -1000, -1000, 536, -1000, -1000, -1000, 88, + 1040, -1000, -1000, 874, -1000, 1023, -176, -192, 1071, 1074, + 1074, 1085, 1211, 1082, 1078, -1000, 529, 644, -1000, 703, + -1000, -1000, 83, -180, -1000, 999, -1000, 1069, 463, -1000, + -1000, -1000, -1000, 524, -1000, 1210, 1203, -1000, 19125, 80, + -1000, -181, -1000, 388, -1000, -1000, -1000, 518, 517, 655, + 538, -189, -1000, -1000, -1000, -1000, 920, 10864, -194, 880, + -1000, 1246, 923, 637, -1000, -1000, 1252, 339, 339, -1000, + -1000, -1000, -1000, -1000, 109, 474, -1000, -1000, -1000, -1000, } var yyPgo = [...]int{ - 0, 1363, 1361, 25, 77, 87, 1360, 1359, 1358, 1356, - 112, 110, 109, 1355, 1354, 1353, 1347, 1345, 1344, 1343, - 1342, 1341, 1339, 1338, 1337, 1336, 1335, 1334, 1333, 1330, - 1329, 1327, 1325, 1321, 99, 1319, 1317, 1314, 1312, 1307, - 1306, 1304, 1301, 1300, 94, 55, 235, 53, 76, 1299, - 71, 1514, 1298, 43, 80, 74, 1297, 41, 1290, 1288, - 90, 1286, 1284, 66, 1283, 1282, 64, 1281, 59, 1280, - 17, 39, 1278, 1277, 1276, 1275, 96, 2115, 1274, 1272, - 18, 1271, 1268, 120, 1267, 75, 33, 22, 37, 29, - 1266, 72, 1265, 10, 1264, 73, 1263, 1261, 1260, 1258, - 30, 1257, 68, 1255, 70, 1252, 11, 7, 1250, 1249, - 1247, 1243, 1241, 1240, 9, 1237, 1236, 1233, 67, 1232, - 8, 63, 38, 20, 12, 1231, 1230, 27, 92, 58, - 84, 1226, 1223, 1219, 585, 1218, 1217, 49, 1215, 105, - 1214, 23, 95, 106, 544, 1213, 1212, 1211, 1210, 1209, - 1208, 51, 1064, 1547, 16, 91, 1207, 1205, 1202, 2620, - 45, 65, 19, 1201, 1200, 1199, 89, 57, 50, 512, - 1197, 42, 1195, 1194, 1189, 1188, 1186, 1181, 1180, 69, - 1166, 1164, 1163, 35, 24, 79, 32, 1162, 1160, 1159, - 1158, 48, 83, 1157, 1153, 62, 61, 1151, 97, 28, - 1143, 1142, 1138, 1134, 1133, 31, 13, 1132, 21, 1131, - 14, 1130, 36, 34, 1128, 6, 1125, 15, 1121, 3, - 0, 1110, 5, 56, 1, 1107, 2, 1106, 1103, 1102, - 1395, 4, 81, 1100, 111, + 0, 1540, 1539, 31, 82, 71, 1538, 1537, 1535, 1534, + 114, 111, 106, 1532, 1528, 1527, 1526, 1525, 1524, 1521, + 1520, 1519, 1518, 1515, 1514, 1512, 1511, 102, 99, 452, + 1510, 1509, 1508, 1507, 1504, 1503, 1500, 1498, 1496, 1493, + 1492, 1490, 101, 1489, 1488, 1486, 1485, 1476, 1475, 1474, + 1473, 1471, 98, 42, 254, 54, 73, 1469, 72, 56, + 1468, 39, 69, 74, 1467, 45, 1465, 1464, 97, 1462, + 1460, 68, 1455, 1453, 2076, 1452, 61, 1446, 13, 26, + 1444, 1442, 1439, 1438, 96, 150, 1437, 1436, 14, 1433, + 1431, 130, 1430, 76, 30, 21, 19, 24, 1427, 75, + 1426, 10, 1425, 80, 1419, 1418, 1415, 1412, 34, 1404, + 70, 78, 38, 1403, 5, 12, 1401, 1400, 1397, 1395, + 1393, 1390, 2, 1389, 1388, 1387, 1386, 1381, 25, 1380, + 6, 66, 41, 22, 11, 1379, 1378, 18, 83, 60, + 92, 1369, 1368, 1366, 731, 1364, 52, 1358, 107, 1357, + 27, 87, 462, 612, 1353, 1351, 1350, 1349, 1347, 43, + 826, 1942, 147, 94, 1346, 1344, 2308, 46, 67, 17, + 1341, 1340, 1339, 131, 48, 53, 705, 1336, 51, 1333, + 1332, 1331, 1330, 1327, 1325, 1324, 127, 1323, 1321, 1320, + 126, 63, 79, 29, 1318, 1315, 1312, 1311, 62, 81, + 1307, 1306, 65, 59, 1302, 86, 23, 33, 1301, 1300, + 1298, 1295, 40, 16, 1292, 95, 35, 58, 36, 20, + 1287, 15, 1285, 28, 37, 1283, 9, 1279, 8, 1277, + 3, 0, 1276, 7, 1275, 77, 1135, 1, 1273, 4, + 1272, 1271, 1270, 1456, 1044, 84, 1258, 123, } var yyR1 = [...]int{ - 0, 228, 229, 229, 1, 1, 1, 1, 1, 1, + 0, 241, 242, 242, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 220, 220, 220, 21, 33, 3, 3, 3, 3, - 2, 2, 8, 9, 4, 5, 5, 10, 10, 38, - 38, 11, 12, 12, 12, 12, 232, 232, 60, 60, - 61, 61, 121, 121, 13, 14, 14, 130, 130, 129, - 129, 129, 131, 131, 131, 131, 169, 169, 15, 15, - 15, 15, 15, 15, 15, 222, 222, 221, 219, 219, - 218, 218, 217, 22, 201, 203, 203, 202, 202, 202, - 202, 202, 202, 192, 172, 172, 172, 172, 175, 175, - 173, 173, 173, 173, 173, 173, 173, 173, 173, 174, - 174, 174, 174, 174, 176, 176, 176, 176, 176, 177, - 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, - 177, 177, 177, 177, 178, 178, 178, 178, 178, 178, - 178, 178, 191, 191, 179, 179, 185, 185, 186, 186, - 186, 188, 188, 189, 189, 145, 145, 145, 181, 181, - 182, 182, 187, 187, 183, 183, 183, 184, 184, 184, - 190, 190, 190, 190, 190, 180, 180, 193, 193, 211, - 211, 210, 210, 210, 200, 200, 207, 207, 207, 207, - 207, 207, 197, 197, 197, 198, 198, 196, 196, 199, - 199, 209, 209, 208, 194, 194, 195, 195, 212, 212, - 212, 212, 212, 213, 225, 226, 224, 224, 224, 224, - 224, 146, 146, 146, 204, 204, 204, 205, 205, 205, - 206, 206, 206, 16, 16, 16, 16, 16, 16, 16, + 1, 231, 231, 231, 234, 234, 21, 41, 3, 3, + 3, 3, 2, 2, 8, 9, 4, 5, 5, 10, + 10, 46, 46, 11, 12, 12, 12, 12, 245, 245, + 68, 68, 69, 69, 131, 131, 13, 14, 14, 140, + 140, 139, 139, 139, 141, 141, 141, 141, 176, 176, + 15, 15, 15, 15, 15, 15, 233, 233, 232, 230, + 230, 229, 229, 228, 22, 24, 25, 26, 236, 236, + 208, 30, 30, 29, 29, 29, 29, 31, 31, 28, + 28, 27, 27, 210, 210, 209, 209, 209, 209, 209, + 209, 199, 179, 179, 179, 179, 182, 182, 180, 180, + 180, 180, 180, 180, 180, 180, 180, 181, 181, 181, + 181, 181, 183, 183, 183, 183, 183, 184, 184, 184, + 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, + 184, 184, 185, 185, 185, 185, 185, 185, 185, 185, + 198, 198, 186, 186, 192, 192, 193, 193, 193, 195, + 195, 196, 196, 154, 154, 154, 188, 188, 189, 189, + 194, 194, 190, 190, 190, 191, 191, 191, 197, 197, + 197, 197, 197, 187, 187, 200, 221, 221, 220, 220, + 217, 217, 217, 217, 207, 207, 214, 214, 214, 214, + 214, 214, 204, 204, 204, 205, 205, 203, 203, 206, + 206, 216, 216, 215, 201, 201, 202, 202, 223, 223, + 223, 223, 223, 224, 238, 239, 237, 237, 237, 237, + 237, 155, 155, 155, 211, 211, 211, 212, 212, 212, + 213, 213, 213, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, - 223, 223, 223, 223, 216, 214, 214, 215, 215, 17, - 23, 23, 18, 18, 18, 18, 18, 19, 19, 24, - 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, - 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, - 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, - 138, 138, 227, 227, 140, 140, 136, 136, 139, 139, - 137, 137, 137, 141, 141, 141, 142, 142, 170, 170, - 170, 26, 26, 28, 28, 29, 30, 30, 164, 164, - 165, 165, 31, 32, 37, 37, 37, 37, 37, 37, - 39, 39, 39, 7, 7, 7, 7, 36, 36, 36, - 6, 6, 27, 27, 27, 27, 20, 233, 34, 35, - 35, 44, 44, 44, 40, 40, 40, 43, 43, 43, - 47, 47, 49, 49, 49, 49, 49, 50, 50, 50, - 50, 50, 50, 46, 46, 48, 48, 48, 48, 156, - 156, 156, 155, 155, 52, 52, 53, 53, 54, 54, - 55, 55, 55, 92, 69, 69, 120, 120, 122, 122, - 56, 56, 56, 56, 57, 57, 58, 58, 59, 59, - 163, 163, 162, 162, 162, 161, 161, 62, 62, 62, - 64, 63, 63, 63, 63, 65, 65, 67, 67, 66, - 66, 68, 70, 70, 70, 70, 70, 71, 71, 51, - 51, 51, 51, 51, 51, 51, 51, 133, 133, 73, - 73, 72, 72, 72, 72, 72, 72, 72, 72, 72, - 72, 84, 84, 84, 84, 84, 84, 74, 74, 74, - 74, 74, 74, 74, 45, 45, 85, 85, 85, 91, - 86, 86, 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 81, 81, 81, 81, - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80, 80, 234, - 234, 83, 82, 82, 82, 82, 82, 82, 82, 42, - 42, 42, 42, 42, 168, 168, 171, 171, 171, 171, - 171, 171, 171, 171, 171, 171, 171, 171, 171, 96, - 96, 41, 41, 94, 94, 95, 97, 97, 93, 93, - 93, 76, 76, 76, 76, 76, 76, 76, 76, 78, - 78, 78, 98, 98, 99, 99, 100, 100, 101, 101, - 102, 103, 103, 103, 104, 104, 104, 104, 118, 118, - 118, 105, 105, 105, 105, 110, 110, 110, 106, 106, - 108, 108, 108, 109, 109, 109, 107, 113, 113, 115, - 115, 114, 114, 112, 112, 117, 117, 116, 116, 111, - 111, 75, 75, 75, 75, 75, 119, 119, 119, 119, - 123, 123, 87, 87, 89, 89, 88, 90, 124, 124, - 127, 125, 125, 128, 128, 128, 128, 128, 126, 126, - 126, 158, 158, 158, 132, 132, 143, 143, 144, 144, - 134, 134, 147, 147, 147, 147, 147, 147, 147, 147, - 147, 147, 135, 135, 135, 148, 148, 148, 149, 149, - 150, 150, 150, 157, 157, 153, 153, 154, 154, 159, - 159, 160, 160, 151, 151, 151, 151, 151, 151, 151, - 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, - 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, - 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, - 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, - 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, - 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, - 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, - 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, - 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, - 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, - 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, - 151, 151, 151, 152, 152, 152, 152, 152, 152, 152, - 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, - 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, - 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, - 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, - 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, - 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, - 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, - 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, - 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, - 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, - 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, - 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, - 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, - 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, - 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, - 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, - 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, - 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, - 152, 152, 152, 152, 152, 152, 230, 231, 166, 167, - 167, 167, + 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, + 235, 235, 235, 235, 227, 225, 225, 226, 226, 17, + 23, 23, 18, 18, 18, 18, 18, 19, 19, 32, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 147, 147, 240, 240, 149, 149, 145, 145, 148, 148, + 146, 146, 146, 150, 150, 150, 151, 151, 177, 177, + 177, 34, 34, 36, 36, 37, 38, 38, 171, 171, + 172, 172, 39, 40, 45, 45, 45, 45, 45, 45, + 47, 47, 47, 7, 7, 7, 7, 44, 44, 44, + 6, 6, 35, 35, 35, 35, 20, 246, 42, 43, + 43, 52, 52, 52, 48, 48, 48, 51, 51, 51, + 55, 55, 57, 57, 57, 57, 57, 58, 58, 58, + 58, 58, 58, 54, 54, 56, 56, 56, 56, 164, + 164, 164, 163, 163, 60, 60, 61, 61, 62, 62, + 63, 63, 63, 100, 77, 77, 130, 130, 132, 132, + 64, 64, 64, 64, 65, 65, 66, 66, 67, 67, + 170, 170, 169, 169, 169, 168, 168, 70, 70, 70, + 72, 71, 71, 71, 71, 73, 73, 75, 75, 74, + 74, 76, 78, 78, 78, 78, 78, 79, 79, 59, + 59, 59, 59, 59, 59, 59, 59, 143, 143, 81, + 81, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 92, 92, 92, 92, 92, 92, 82, 82, 82, + 82, 82, 82, 82, 53, 53, 93, 93, 93, 99, + 94, 94, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 89, 89, 89, 89, + 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, + 87, 87, 87, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 247, + 247, 91, 90, 90, 90, 90, 90, 90, 90, 50, + 50, 50, 50, 50, 175, 175, 178, 178, 178, 178, + 178, 178, 178, 178, 178, 178, 178, 178, 178, 104, + 104, 49, 49, 102, 102, 103, 105, 105, 101, 101, + 101, 84, 84, 84, 84, 84, 84, 84, 84, 86, + 86, 86, 106, 106, 107, 107, 108, 108, 109, 109, + 110, 111, 111, 111, 112, 112, 112, 112, 222, 222, + 222, 222, 222, 218, 218, 218, 218, 219, 219, 219, + 128, 128, 128, 113, 113, 113, 113, 118, 118, 118, + 114, 114, 116, 116, 116, 117, 117, 117, 115, 121, + 121, 123, 123, 122, 122, 120, 120, 125, 125, 124, + 124, 119, 119, 83, 83, 83, 83, 83, 129, 129, + 129, 129, 133, 133, 95, 95, 97, 97, 96, 98, + 134, 134, 137, 135, 135, 138, 138, 138, 138, 138, + 136, 136, 136, 165, 165, 165, 142, 142, 152, 152, + 153, 153, 144, 144, 156, 156, 156, 156, 156, 156, + 156, 156, 156, 156, 157, 157, 157, 158, 158, 126, + 126, 126, 126, 127, 127, 161, 161, 162, 162, 166, + 166, 167, 167, 159, 159, 159, 159, 159, 159, 159, + 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, + 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, + 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, + 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, + 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, + 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, + 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, + 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, + 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, + 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, + 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, + 159, 159, 159, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 243, 244, 173, 174, + 174, 174, } var yyR2 = [...]int{ 0, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 0, 1, 1, 1, 2, 3, 5, 6, 6, 7, - 4, 6, 5, 7, 8, 1, 3, 7, 8, 1, - 1, 9, 9, 8, 7, 7, 1, 1, 1, 3, - 1, 3, 0, 4, 3, 5, 4, 1, 3, 3, - 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, - 8, 4, 6, 5, 5, 0, 2, 1, 0, 2, - 1, 3, 3, 4, 4, 2, 4, 1, 1, 3, - 4, 3, 3, 8, 3, 1, 1, 1, 2, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, - 2, 2, 2, 2, 1, 2, 2, 2, 2, 4, - 4, 2, 2, 3, 3, 3, 3, 1, 1, 1, - 1, 1, 6, 6, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 3, 0, 3, 0, 5, 0, 3, - 5, 0, 1, 0, 1, 0, 1, 2, 0, 2, - 0, 3, 0, 1, 0, 3, 3, 0, 2, 2, - 0, 2, 1, 2, 1, 0, 2, 5, 4, 1, - 2, 2, 3, 2, 0, 1, 2, 3, 3, 3, + 0, 1, 1, 1, 0, 1, 2, 3, 5, 6, + 6, 7, 4, 6, 5, 7, 8, 1, 3, 7, + 8, 1, 1, 9, 9, 8, 7, 7, 1, 1, + 1, 3, 1, 3, 0, 4, 3, 5, 4, 1, + 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, + 2, 2, 6, 4, 6, 2, 0, 2, 1, 0, + 2, 1, 3, 3, 4, 7, 4, 2, 1, 1, + 4, 0, 1, 1, 1, 2, 2, 0, 1, 5, + 5, 4, 4, 2, 4, 1, 1, 3, 4, 3, + 3, 8, 3, 1, 1, 1, 2, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, + 2, 2, 1, 2, 2, 2, 2, 4, 4, 2, + 2, 3, 3, 3, 3, 1, 1, 1, 1, 1, + 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 3, 0, 3, 0, 5, 0, 3, 5, 0, + 1, 0, 1, 0, 1, 2, 0, 2, 0, 3, + 0, 1, 0, 3, 3, 0, 2, 2, 0, 2, + 1, 2, 1, 0, 2, 5, 0, 1, 1, 2, + 2, 3, 2, 3, 0, 1, 2, 3, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, - 1, 1, 3, 2, 3, 1, 3, 1, 10, 11, + 1, 1, 3, 3, 3, 1, 3, 1, 10, 11, 11, 12, 1, 5, 3, 3, 1, 1, 2, 2, 2, 0, 1, 2, 0, 1, 3, 1, 2, 3, - 1, 1, 1, 6, 7, 7, 7, 7, 4, 5, - 4, 4, 7, 5, 5, 5, 12, 7, 5, 9, + 1, 1, 1, 5, 6, 6, 6, 6, 4, 4, + 3, 6, 7, 5, 5, 5, 12, 7, 5, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 7, 1, 3, 8, 8, 3, 3, 5, 4, 6, 5, 4, 4, 3, 2, 3, @@ -3293,16 +3329,18 @@ var yyR2 = [...]int{ 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 0, 3, 0, 2, 0, 3, 1, 3, 2, 0, 1, 1, 0, 2, 4, 4, 0, 2, - 4, 0, 9, 3, 5, 0, 3, 3, 0, 1, - 0, 2, 2, 0, 2, 2, 2, 0, 3, 0, - 3, 0, 3, 0, 4, 0, 3, 0, 4, 0, - 1, 2, 1, 5, 4, 4, 1, 3, 3, 5, - 0, 5, 1, 3, 1, 2, 3, 1, 1, 3, - 3, 1, 3, 3, 3, 3, 3, 2, 1, 2, - 1, 1, 1, 1, 1, 1, 0, 2, 0, 3, - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 0, 2, 3, 0, 1, 1, 1, 1, - 0, 1, 1, 0, 2, 1, 1, 1, 1, 1, + 2, 1, 1, 3, 3, 3, 3, 3, 3, 3, + 0, 2, 4, 0, 9, 3, 5, 0, 3, 3, + 0, 1, 0, 2, 2, 0, 2, 2, 2, 0, + 3, 0, 3, 0, 3, 0, 4, 0, 3, 0, + 4, 0, 1, 2, 1, 5, 4, 4, 1, 3, + 3, 5, 0, 5, 1, 3, 1, 2, 3, 1, + 1, 3, 3, 1, 3, 3, 3, 3, 3, 2, + 1, 2, 1, 1, 1, 1, 1, 1, 0, 2, + 0, 3, 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, + 1, 1, 1, 0, 2, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -3339,371 +3377,381 @@ var yyR2 = [...]int{ } var yyChk = [...]int{ - -1000, -228, -1, -3, -8, -9, -10, -11, -12, -13, - -14, -15, -16, -17, -18, -19, -24, -25, -26, -28, - -29, -30, -31, -32, -6, -27, -20, -21, -33, -4, - -230, 6, 7, 8, -38, 10, 11, 31, -22, 139, - 140, 142, 141, 175, 143, 168, 69, 189, 190, 192, - 193, 194, 195, -39, 173, 174, 32, 33, 145, 35, - 40, 73, 9, 282, 170, 169, 26, -229, 384, -44, - 5, -100, 16, -3, -34, -233, -34, -34, -34, -34, - -34, -34, -201, -203, 73, 112, -150, 149, 93, 274, - 146, 147, 153, -153, -220, -152, 76, 77, 78, 292, - 161, 324, 325, 189, 203, 197, 224, 216, 293, 326, - 162, 214, 217, 261, 159, 327, 244, 251, 87, 192, - 270, 328, 46, 39, 171, 212, 208, 329, 301, 206, - 45, 28, 44, 330, 253, 229, 43, 331, 297, 255, - 207, 252, 145, 332, 164, 380, 157, 333, 230, 234, - 334, 262, 47, 335, 336, 337, 201, 202, 338, 160, - 264, 228, 158, 34, 256, 294, 53, 179, 265, 41, - 232, 40, 339, 227, 223, 48, 340, 341, 342, 343, - 226, 200, 222, 57, 236, 235, 237, 260, 219, 344, - 345, 346, 165, 347, 209, 19, 348, 349, 350, 51, - 351, 352, 268, 174, 353, 49, 177, 354, 355, 356, - 357, 358, 359, 254, 231, 233, 154, 181, 250, 296, - 360, 266, 205, 361, 166, 178, 173, 269, 167, 362, - 363, 364, 365, 366, 367, 368, 193, 38, 369, 370, - 371, 372, 188, 263, 272, 56, 241, 373, 199, 156, - 374, 190, 50, 185, 246, 42, 220, 180, 375, 376, - 210, 211, 225, 198, 221, 191, 381, 182, 175, 377, - 271, 242, 298, 218, 215, 186, 378, 183, 184, 379, - 382, 257, 247, 258, 259, 248, 187, 295, 267, 213, - 243, -135, 149, 274, 146, 248, 295, 147, 147, 148, - 149, 274, 146, 147, -66, -159, -220, -152, 149, 147, - 130, 217, 261, 139, 245, 256, 257, 253, -140, 254, - 181, -170, 147, -136, 244, 247, 248, 187, -227, -220, - 255, 263, 262, 249, 259, 258, -159, 191, -164, 196, - -153, 194, -66, -37, 380, 143, -166, -166, 246, 246, - -166, -86, -51, -72, 96, -77, 30, 24, -76, -73, - -93, -90, -91, 130, 131, 133, 132, 134, 119, 120, - 127, 97, 135, -81, -79, -80, -82, 80, 79, 88, - 81, 82, 83, 84, 89, 90, 91, -153, -159, -88, - -230, 63, 64, 283, 284, 285, 286, 291, 287, 99, - 52, 273, 281, 280, 279, 277, 278, 275, 276, 289, - 290, 152, 274, 146, 125, 282, -220, -152, 39, -5, - -4, -230, 6, 21, 22, -104, 18, 17, -231, 75, - -40, -49, 58, 59, -50, 22, 36, 62, 60, -35, - -48, 121, -51, -159, -48, -134, 151, -134, -134, -125, - -169, 191, -128, 263, 262, -154, -126, -153, -151, 261, - 217, 260, 144, 299, 95, 23, 25, 239, 98, 130, - 17, 99, 129, 283, 139, 67, 300, 275, 276, 273, - 285, 286, 274, 245, 30, 11, 302, 26, 169, 22, - 36, 123, 141, 102, 103, 172, 24, 170, 91, 305, - 20, 70, 12, 14, 306, 307, 15, 152, 151, 114, - 148, 65, 9, 135, 27, 111, 61, 308, 29, 309, - 310, 311, 312, 63, 112, 18, 277, 278, 32, 313, - 291, 176, 125, 68, 54, 96, 314, 315, 89, 316, - 92, 71, 93, 16, 66, 37, 317, 318, 319, 320, - 113, 142, 282, 64, 321, 146, 6, 288, 31, 168, - 62, 322, 147, 101, 289, 290, 150, 90, 5, 153, - 33, 10, 69, 72, 279, 280, 281, 52, 100, 13, - 323, 94, -202, 112, -192, -195, -153, 163, -213, 159, - -66, 148, -66, 282, -144, 152, -144, -144, 147, -66, - -220, -220, 139, 141, 144, 71, 80, -23, -66, -143, - 152, -220, -143, -143, -143, -66, 136, -66, -220, 31, - -141, 112, 13, 274, -220, 181, 147, 182, 149, -142, - 112, -142, -142, -197, 148, 34, 160, -167, -230, -154, - 185, 186, 185, -139, -138, 251, 252, 246, 250, 13, - 186, 246, 184, -141, -167, 150, -153, -36, -153, 80, - -7, -3, -11, -10, -12, 104, -166, -166, 74, 95, - 93, 94, 111, -51, -74, 114, 96, 112, 113, 98, - 116, 115, 126, 119, 120, 121, 122, 123, 124, 125, - 117, 118, 129, 104, 105, 106, 107, 108, 109, 110, - -133, -230, -91, -230, 137, 138, -77, -77, -77, -77, - -77, -77, -77, -77, -77, -77, -230, 136, -2, -86, - -4, -230, -230, -230, -230, -230, -230, -230, -230, -96, - -51, -230, -234, -83, -230, -234, -83, -234, -83, -234, - -230, -234, -83, -234, -83, -234, -234, -83, -230, -230, - -230, -230, -230, -230, -230, -166, -100, -3, -34, -118, - 20, 32, -51, -101, -102, -51, -100, 54, -46, -48, - -50, 58, 59, 86, 12, -156, -155, 23, -153, 80, - 136, 12, -67, 27, -66, -53, -54, -55, -56, -69, - -92, -230, -66, 12, -60, -61, -66, -68, -159, 74, - 191, -128, -169, -130, -129, 264, 266, 104, -158, -153, - 80, 30, 31, 75, 74, -66, -172, -175, -177, -176, - -178, -173, -174, 214, 215, 130, 218, 220, 221, 222, - 223, 224, 225, 226, 227, 228, 229, 31, 171, 210, - 211, 212, 213, 230, 231, 232, 233, 234, 235, 236, - 237, 197, 216, 293, 198, 199, 200, 201, 202, 203, - 205, 206, 207, 208, 209, -220, 73, -220, -167, 149, - -220, 96, -220, -66, -66, -167, -167, -167, 183, 183, - 147, 147, 188, -66, 80, 74, 150, -60, 24, 71, - -66, -220, -220, -160, -159, -151, -167, -141, 80, -51, - -167, -167, -167, -66, -167, -167, 80, -198, 12, 114, - -167, -167, -137, 12, 114, -198, -137, -51, -142, 71, - -165, 194, 228, 381, 382, 383, -51, -51, -51, -51, - -84, 89, 96, 90, 91, -77, -85, -88, -91, 85, - 114, 112, 113, 98, -77, -77, -77, -77, -77, -77, - -77, -77, -77, -77, -77, -77, -77, -77, -77, -168, - -220, 80, -220, -76, -76, -153, -47, 22, 36, -46, - -154, -160, -151, -44, -231, -231, -100, -46, -46, -51, - -51, -93, 80, -46, -93, 80, -46, -46, -43, 22, - 36, -94, -95, 100, -93, -153, -159, -231, -77, -153, - -153, -46, -47, -47, -46, -46, -104, -231, -105, 27, - 10, 114, 74, 19, 74, -103, 25, 26, -104, -78, - -153, 81, 84, -52, 74, 12, -50, -66, -155, 121, - -160, -66, -121, 177, -66, 31, 74, -62, -64, -63, - -65, 61, 65, 67, 62, 63, 64, 68, -163, 23, - -53, -3, -230, -162, 177, -161, 23, -159, 80, -66, - -60, -232, 74, 12, 72, -232, 74, 136, -128, -130, - 74, 265, 267, 268, 71, 92, -51, -184, 129, -204, - -205, -206, -154, 80, 81, -192, -193, -194, -207, 163, - -212, 154, 156, 157, 153, -196, 164, -213, 148, 29, - 75, -145, 89, 96, -188, 242, -179, 73, -179, -179, - -179, -179, -183, 217, -183, -183, -183, 73, 73, -179, - -179, -179, -179, -185, 73, -185, -185, -186, 73, -186, - -213, 159, -51, -157, 72, -66, -167, 24, -167, -147, - 144, 141, 142, -216, 140, 239, 217, 87, 30, 16, - 283, 177, 298, -220, 178, -66, -66, -66, -66, -66, - 144, 141, -66, -66, -66, -167, -66, -141, -159, -159, - -66, -141, -66, -153, 89, 90, 91, -85, -77, -77, - -77, -45, 172, 95, -231, -231, -46, -46, -230, 136, - -5, -104, -231, -231, 74, 72, 23, 12, 12, -231, - 12, 12, -231, -231, -46, -97, -95, 102, -51, -231, - 136, -231, 74, 74, -231, -231, -231, -231, -231, -118, - 37, 45, 56, -51, -51, -102, -118, -132, 20, 12, - 52, 52, -71, 13, -48, -53, -50, 136, -71, -75, - 31, 52, -3, -230, -230, -124, -127, -93, -54, -55, - -55, -54, -55, 61, 61, 61, 66, 61, 66, 61, - -63, -159, -231, -231, -3, -70, 69, 151, 70, -230, - -161, -121, 72, -53, -66, -53, -68, -159, 121, -129, - -131, 269, 266, 272, -220, 80, 74, -206, 104, -195, - 73, -220, 29, -196, -196, -196, -199, -220, -199, 29, - -181, 30, 89, -189, 243, 81, -183, -183, -184, 31, - -184, -184, -184, -191, 80, -191, 81, 81, 75, 71, - -153, -167, -166, -223, 159, 155, 163, 164, 157, 76, - 77, 78, 148, 29, 154, 156, 177, 153, -223, -148, - -149, 150, 23, 148, 29, 177, -222, 72, 183, 239, - 183, 150, -167, -137, -137, -45, 95, -77, -77, -231, - -231, -47, -154, -100, -118, -171, 130, 214, 171, 212, - 208, 228, 219, 241, 210, 242, -168, -171, -77, -77, - -77, -77, 292, -100, 103, -51, 101, -154, -77, -77, - 38, 80, 80, 57, -66, -98, 14, -51, 121, -104, - -123, 71, -124, -87, -89, -88, -230, -119, -231, -153, - -122, -153, -71, 74, 104, -58, -57, 71, 72, -59, - 71, -57, 61, 61, -231, 148, 148, 148, -122, -71, - -53, -71, -71, 136, 266, 270, 271, -205, -206, -209, - -208, -153, -212, 164, -199, -199, -199, 73, -182, 71, - -77, 75, -184, -184, -220, 130, 75, 74, 75, 74, - 75, 74, -146, 330, 96, -66, -166, -166, -66, -166, - -153, -219, 295, -221, -220, -153, -153, -153, -66, -141, - -141, -77, -231, -104, -231, -179, -179, -179, -186, -179, - 202, -179, 202, -231, -231, 20, 20, 20, 20, -230, - -41, 288, -51, 74, 74, 80, -183, -99, 15, 17, - 28, -123, 74, -231, -231, 74, 52, 136, -231, 74, - -100, -127, -51, -51, 73, -51, -230, -230, -230, -231, - -100, -71, 75, 74, -179, -120, -153, -187, 239, 10, - -183, 80, -183, 81, 81, 330, -167, 27, -218, -217, - -154, 73, 72, -118, -183, -220, -77, -77, -77, -77, - -77, -104, 80, -77, -77, -183, -107, -112, -139, -51, - -86, 29, -89, 52, -3, -153, -87, -153, -153, -104, - -120, -120, -231, -120, -120, -162, -104, -211, -210, 72, - 158, 87, -208, 75, 74, -190, 154, 29, 153, -80, - -184, -184, 75, 75, -230, 74, 104, -120, -66, -231, - -231, -231, -231, -42, 114, 295, -231, -231, -231, -110, - 380, -113, 41, -114, 42, 10, -87, 136, 75, -231, - -231, -231, -70, -210, -220, -200, 104, 80, 166, -153, - -180, 87, 29, 29, -214, -215, 177, -217, -206, 75, - -231, 293, 68, 296, -107, 46, 220, -115, 50, -116, - -111, 51, 17, -124, -153, 81, -66, 80, -231, 74, - -153, -222, 57, 294, 297, -108, 48, -106, 47, -106, - -114, 17, -117, 43, 44, 80, 73, -215, 52, -219, - 57, -109, 49, 71, 92, 80, 17, 17, -120, 179, - 295, 71, 92, 80, 80, 75, 180, 296, -225, -226, - 71, -230, 297, -226, 71, 11, 10, -77, 176, -224, - 167, 162, 165, 31, -224, -231, -231, 161, 30, 89, + -1000, -241, -1, -3, -8, -9, -10, -11, -12, -13, + -14, -15, -16, -17, -18, -19, -32, -33, -34, -36, + -37, -38, -39, -40, -6, -35, -20, -21, -41, -4, + -243, 6, 7, 8, -46, 10, 11, 31, -22, -24, + 146, -25, 147, -26, 149, 148, 182, 150, 175, 70, + 199, 200, 202, 203, 204, 205, -47, 180, 181, 32, + 33, 152, 35, 41, 80, 9, 292, 177, 176, 26, + -242, 394, -52, 5, -108, 16, -3, -42, -246, -42, + -42, -42, -42, -42, -42, -208, -210, 80, 119, 80, + 156, 100, 154, -126, -236, 160, 163, 164, 284, 153, + -30, -29, -28, -27, -31, 30, -236, 154, 156, 258, + -234, -231, 83, 84, 85, 154, 154, 155, 156, 284, + 153, 154, -74, -166, -231, -160, 302, 168, 334, 335, + 76, 199, 213, 207, 234, 226, 303, 336, 169, 224, + 227, 271, 166, 337, 254, 261, 94, 202, 280, 338, + 75, 47, 40, 178, 222, 218, 339, 311, 192, 216, + 46, 28, 45, 340, 263, 239, 44, 341, 79, 307, + 265, 217, 262, 152, 342, 171, 390, 164, 343, 240, + 244, 344, 272, 48, 345, 346, 347, 74, 211, 212, + 348, 167, 274, 238, 165, 34, 266, 304, 54, 186, + 275, 42, 242, 41, 349, 237, 233, 49, 350, 351, + 352, 353, 236, 210, 232, 58, 246, 245, 247, 193, + 270, 229, 354, 355, 356, 172, 77, 357, 219, 19, + 358, 359, 360, 52, 361, 362, 278, 181, 363, 50, + 37, 184, 364, 365, 366, 367, 368, 369, 264, 241, + 243, 161, 188, 260, 306, 370, 276, 215, 371, 173, + 185, 180, 279, 174, 372, 373, 374, 375, 376, 377, + 378, 203, 39, 379, 380, 381, 382, 198, 273, 282, + 57, 78, 251, 383, 209, 163, 384, 200, 51, 195, + 256, 43, 230, 187, 385, 386, 220, 221, 235, 208, + 231, 201, 391, 189, 182, 387, 281, 252, 308, 194, + 228, 225, 196, 388, 156, 190, 191, 389, 392, 267, + 257, 268, 269, 258, 197, 305, 277, 223, 253, 154, + 137, 227, 271, 146, 255, 266, 267, 263, -149, 264, + 188, -177, 154, -145, 254, 257, 258, 197, -240, -231, + 265, 273, 272, 259, 269, 268, -166, 201, -171, 206, + -161, -231, -160, 204, -74, -45, 390, 150, -173, -173, + 256, 256, -173, -94, -59, -80, 103, -85, 30, 24, + -84, -81, -101, -98, -99, 137, 138, 140, 139, 141, + 126, 127, 134, 104, 142, -89, -87, -88, -90, 87, + 86, 95, 88, 89, 90, 91, 96, 97, 98, -161, + -166, -96, -243, 64, 65, 293, 294, 295, 296, 301, + 297, 106, 53, 283, 291, 290, 289, 287, 288, 285, + 286, 299, 300, 159, 284, 153, 132, 292, -231, -160, + 40, -5, -4, -243, 6, 21, 22, -112, 18, 17, + -244, 82, -48, -57, 59, 60, -58, 22, 36, 63, + 61, -43, -56, 128, -59, -166, -56, -144, 158, -144, + -144, -135, -176, 201, -138, 273, 272, -162, -136, -161, + -159, 271, 227, 270, 151, 309, 102, 23, 25, 249, + 105, 137, 17, 106, 136, 293, 146, 68, 310, 285, + 286, 283, 295, 296, 284, 255, 30, 11, 312, 26, + 176, 22, 36, 130, 148, 109, 110, 179, 24, 177, + 98, 315, 20, 71, 12, 14, 316, 317, 15, 159, + 158, 121, 155, 66, 9, 142, 27, 118, 62, 318, + 29, 319, 320, 321, 322, 64, 119, 18, 287, 288, + 32, 323, 301, 183, 132, 69, 55, 103, 324, 325, + 96, 326, 99, 72, 100, 16, 67, 38, 327, 328, + 329, 330, 120, 149, 292, 65, 331, 153, 6, 298, + 31, 175, 63, 332, 154, 108, 299, 300, 157, 97, + 5, 160, 33, 10, 70, 73, 289, 290, 291, 53, + 107, 13, 333, 101, -209, 119, -199, -202, -161, 170, + -224, 166, -74, -216, -215, -161, -74, 292, -153, 159, + 155, -153, -27, -28, 227, 136, -74, -74, 146, 148, + 151, 72, -29, 194, -23, -74, -152, 159, -231, -152, + -152, -152, -74, 143, -74, -231, 31, -150, 119, 13, + 284, -231, 188, 154, 189, 156, -151, 119, -151, -151, + -204, 155, 34, 167, -174, -243, -162, 195, 196, 195, + -148, -147, 261, 262, 256, 260, 13, 196, 256, 191, + -150, -174, 157, -161, -44, -161, 87, -7, -3, -11, + -10, -12, 111, -173, -173, 81, 102, 100, 101, 118, + -59, -82, 121, 103, 119, 120, 105, 123, 122, 133, + 126, 127, 128, 129, 130, 131, 132, 124, 125, 136, + 111, 112, 113, 114, 115, 116, 117, -143, -243, -99, + -243, 144, 145, -85, -85, -85, -85, -85, -85, -85, + -85, -85, -85, -243, 143, -2, -94, -4, -243, -243, + -243, -243, -243, -243, -243, -243, -104, -59, -243, -247, + -91, -243, -247, -91, -247, -91, -247, -243, -247, -91, + -247, -91, -247, -247, -91, -243, -243, -243, -243, -243, + -243, -243, -173, -108, -3, -42, -128, 20, 32, -59, + -109, -110, -59, -108, 55, -54, -56, -58, 59, 60, + 93, 12, -164, -163, 23, -161, 87, 143, 12, -75, + 27, -74, -61, -62, -63, -64, -77, -100, -243, -74, + 12, -68, -69, -74, -76, -166, 81, 201, -138, -176, + -140, -139, 274, 276, 111, -165, -161, 87, 30, 31, + 82, 81, -74, -179, -182, -184, -183, -185, -180, -181, + 224, 225, 137, 228, 230, 231, 232, 233, 234, 235, + 236, 237, 238, 239, 31, 178, 220, 221, 222, 223, + 240, 241, 242, 243, 244, 245, 246, 247, 207, 226, + 303, 208, 209, 210, 211, 212, 213, 215, 216, 217, + 218, 219, -231, 80, 82, 81, -186, 80, -174, 156, + -74, 103, -231, -231, 31, -207, 111, -156, 151, 148, + 149, -227, 147, 249, 227, 94, 30, 16, 293, 184, + 308, -231, 185, -174, 190, 190, 154, 154, 198, -74, + 40, 81, 157, -68, 24, 72, -74, -231, -231, -167, + -166, -159, -174, -150, 87, -59, -174, -174, -174, -74, + -174, -174, 87, -205, 12, 121, -174, -174, -146, 12, + 121, -205, -146, -59, -151, 72, -172, 204, 238, 391, + 392, 393, -59, -59, -59, -59, -92, 96, 103, 97, + 98, -85, -93, -96, -99, 92, 121, 119, 120, 105, + -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, + -85, -85, -85, -85, -85, -175, -231, 87, -231, -84, + -84, -161, -55, 22, 36, -54, -162, -167, -159, -52, + -244, -244, -108, -54, -54, -59, -59, -101, 87, -54, + -101, 87, -54, -54, -51, 22, 36, -102, -103, 107, + -101, -161, -166, -244, -85, -161, -161, -54, -55, -55, + -54, -54, -112, -244, -113, 27, 10, 121, 81, 19, + 81, -111, 25, 26, -112, -86, -161, 88, 91, -60, + 81, 12, -58, -74, -163, 128, -167, -74, -131, 184, + -74, 31, 81, -70, -72, -71, -73, 62, 66, 68, + 63, 64, 65, 69, -170, 23, -61, -3, -243, -169, + 184, -168, 23, -166, 87, -74, -68, -245, 81, 12, + 73, -245, 81, 143, -138, -140, 81, 275, 277, 278, + 72, 99, -59, -191, 136, -211, -212, -213, -162, 87, + 88, -199, -200, -201, -214, 170, -223, 161, 163, 164, + 160, -203, 171, -224, 155, 29, 82, -154, 96, 103, + -195, 252, -186, -186, -186, -186, -186, -190, 227, -190, + -190, -190, 80, 80, -186, -186, -186, -186, -192, 80, + -192, -192, -193, 80, -193, -224, 166, -59, -221, -220, + -217, 73, 165, 94, 305, -215, -111, 88, -74, 24, + -127, 73, -207, -231, 87, -173, -235, 166, 162, 170, + 171, 164, 83, 84, 85, 155, 29, 161, 163, 184, + 160, -235, -157, -158, 157, 23, 155, 29, 184, -74, + -74, -74, -74, -74, 151, 148, 192, -74, -74, -74, + -174, -74, -150, -166, -166, -74, -150, -74, -161, 96, + 97, 98, -93, -85, -85, -85, -53, 179, 102, -244, + -244, -54, -54, -243, 143, -5, -112, -244, -244, 81, + 73, 23, 12, 12, -244, 12, 12, -244, -244, -54, + -105, -103, 109, -59, -244, 143, -244, 81, 81, -244, + -244, -244, -244, -244, -128, 38, 46, 57, -59, -59, + -110, -128, -142, 20, 12, 53, 53, -79, 13, -56, + -61, -58, 143, -79, -83, 31, 53, -3, -243, -243, + -134, -137, -101, -62, -63, -63, -62, -63, 62, 62, + 62, 67, 62, 67, 62, -71, -166, -244, -244, -3, + -78, 70, 158, 71, -243, -168, -131, 73, -61, -74, + -61, -76, -166, 128, -139, -141, 279, 276, 282, -231, + 87, 81, -213, 111, -202, 80, -231, 29, -203, -203, + -203, -206, -231, -206, 29, -188, 30, 96, -196, 253, + -190, -190, -191, 31, -191, -191, -191, -198, 87, -198, + 88, 88, 82, -222, -218, -219, 32, 76, -217, -231, + -207, 87, 37, 82, -174, 72, -161, -231, 87, -173, + -173, -74, -173, -161, -233, 73, 190, 249, 190, 193, + 157, -174, -146, -146, -53, 102, -85, -85, -244, -244, + -55, -162, -108, -128, -178, 137, 224, 178, 222, 218, + 238, 229, 251, 220, 252, -175, -178, -85, -85, -85, + -85, 302, -108, 110, -59, 108, -162, -85, -85, 39, + 87, 87, 58, -74, -106, 14, -59, 128, -112, -133, + 72, -134, -95, -97, -96, -243, -129, -244, -161, -132, + -161, -79, 81, 111, -66, -65, 72, 73, -67, 72, + -65, 62, 62, -244, 155, 155, 155, -132, -79, -61, + -79, -79, 143, 276, 280, 281, -212, -213, -216, -223, + 171, -206, -206, -206, 80, -189, 72, -85, -191, -191, + -231, 137, 82, 81, 82, 81, 82, 81, -155, 340, + 103, -219, -218, -207, -207, 88, 87, -74, 27, -230, + 305, -232, -231, -161, -161, -161, -74, -150, -150, -85, + -244, -112, -244, -186, -186, -186, -193, -186, 212, -186, + 212, -244, -244, 20, 20, 20, 20, -243, -49, 298, + -59, 81, 81, 87, -190, -107, 15, 17, 28, -133, + 81, -244, -244, 81, 53, 143, -244, 81, -108, -137, + -59, -59, 80, -59, -243, -243, -243, -244, -108, -79, + 82, -130, -161, -194, 249, 10, -190, 87, -190, 88, + 88, 340, 30, 77, 78, 79, 30, 74, 75, -243, + -229, -228, -162, 80, 73, -128, -190, -231, -85, -85, + -85, -85, -85, -112, 87, -85, -85, -190, -115, -120, + -148, -59, -94, 29, -97, 53, -3, -161, -95, -161, + -161, -112, -130, -130, -244, -130, -130, -169, -112, -221, + 82, 81, -197, 161, 29, 160, -88, -191, -191, 82, + 82, -225, -226, 184, 81, 111, -130, -74, -244, -244, + -244, -244, -50, 121, 305, -244, -244, -244, -118, 390, + -121, 42, -122, 43, 10, -95, 143, 82, -244, -244, + -244, -78, 173, -161, -187, 94, 29, 29, -244, 81, + -161, -228, -213, 82, -244, 303, 69, 306, -115, 47, + 230, -123, 51, -124, -119, 52, 17, -134, -161, -74, + 87, -226, 53, -233, 58, 304, 307, -116, 49, -114, + 48, -114, -122, 17, -125, 44, 45, 87, 80, 186, + -230, 58, -117, 50, 72, 99, 87, 17, 17, -130, + 187, 305, 72, 99, 87, 87, 82, -243, 306, -238, + -239, 72, -85, 183, 307, -239, 72, 11, 10, -244, + -244, -237, 174, 169, 172, 31, -237, 168, 30, 96, } var yyDef = [...]int{ 30, -2, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, - 21, 22, 23, 24, 25, 26, 27, 28, 29, 636, - 0, 377, 377, 377, 377, 377, 377, 377, 0, 740, - 732, 0, 0, 0, 0, -2, 342, 343, 0, 345, - -2, 0, 0, 354, 1068, 1068, 0, 0, 1068, 0, - 0, 1066, 49, 50, 360, 361, 362, 1, 3, 0, - 381, 644, 0, 0, -2, 379, 0, 0, 720, 720, - 720, 0, 78, 79, 0, 0, 0, 1051, 0, 718, - 718, 718, 741, 742, 745, 746, 31, 32, 33, 873, - 874, 875, 876, 877, 878, 879, 880, 881, 882, 883, - 884, 885, 886, 887, 888, 889, 890, 891, 892, 893, - 894, 895, 896, 897, 898, 899, 900, 901, 902, 903, - 904, 905, 906, 907, 908, 909, 910, 911, 912, 913, - 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, - 924, 925, 926, 927, 928, 929, 930, 931, 932, 933, - 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, - 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, - 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, - 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, - 974, 975, 976, 977, 978, 979, 980, 981, 982, 983, - 984, 985, 986, 987, 988, 989, 990, 991, 992, 993, - 994, 995, 996, 997, 998, 999, 1000, 1001, 1002, 1003, - 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1012, 1013, - 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023, - 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, - 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, - 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1052, 1053, 1054, - 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, - 1065, 0, 0, 0, 0, 0, 0, 0, 716, 0, - 716, 716, 716, 0, 288, 459, 749, 750, 1051, 0, - 0, 0, 333, 0, 336, 336, 336, 302, 0, 304, - 1069, 0, 0, 0, 311, 0, 0, 317, 333, 1069, - 325, 339, 340, 327, 322, 323, 341, 344, 0, 349, - 352, 0, 367, 0, 919, 359, 372, 373, 1068, 1068, - 376, 34, 510, 469, 0, 475, 477, 0, 512, 513, - 514, 515, 516, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 542, 543, 544, 545, 621, 622, 623, - 624, 625, 626, 627, 628, 479, 480, 618, 0, 697, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 609, - 0, 579, 579, 579, 579, 579, 579, 579, 579, 0, - 0, 0, 0, 0, 0, 0, -2, -2, 1068, 636, - 45, 0, 377, 382, 383, 648, 0, 0, 636, 1067, - 0, 0, -2, -2, 393, 399, 400, 401, 402, 378, - 0, 405, 409, 0, 0, 0, 721, 0, 0, 64, - 0, 1039, 701, -2, -2, 0, 0, 747, 748, -2, - 886, -2, 753, 754, 755, 756, 757, 758, 759, 760, - 761, 762, 763, 764, 765, 766, 767, 768, 769, 770, - 771, 772, 773, 774, 775, 776, 777, 778, 779, 780, - 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, - 791, 792, 793, 794, 795, 796, 797, 798, 799, 800, - 801, 802, 803, 804, 805, 806, 807, 808, 809, 810, - 811, 812, 813, 814, 815, 816, 817, 818, 819, 820, - 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, - 831, 832, 833, 834, 835, 836, 837, 838, 839, 840, - 841, 842, 843, 844, 845, 846, 847, 848, 849, 850, - 851, 852, 853, 854, 855, 856, 857, 858, 859, 860, - 861, 862, 863, 864, 865, 866, 867, 868, 869, 870, - 871, 872, 0, 0, 97, 98, 0, 0, 217, 888, - 95, 0, 1069, 0, 0, 0, 0, 0, 0, 1069, - 1069, 1069, 0, 0, 0, 0, 733, 279, 0, 0, - 0, 0, 0, 0, 0, 287, 0, 289, 1069, 333, - 292, 0, 0, 1069, 1069, 1069, 0, 1069, 1069, 299, - 0, 300, 301, 0, 202, 203, 204, 305, 1070, 1071, - 1069, 1069, 330, 0, 330, 328, 329, 320, 321, 0, - 336, 314, 315, 318, 319, 350, 353, 370, 368, 369, - 371, 363, 364, 365, 366, 0, 374, 375, 0, 0, - 0, 0, 0, 473, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 497, 498, 499, 500, 501, 502, 503, - 476, 0, 490, 0, 0, 0, 532, 533, 534, 535, - 536, 537, 538, 539, 540, 0, 390, 0, 0, 0, - 636, 0, 0, 0, 0, 0, 0, 0, 387, 0, - 610, 0, 563, 571, 0, 564, 572, 565, 573, 566, - 0, 567, 574, 568, 575, 569, 570, 576, 0, 0, - 0, 390, 390, 0, 0, 35, 644, 0, 392, 651, - 0, 0, 645, 637, 638, 641, 644, 0, 414, 403, - 394, 397, 398, 380, 0, 406, 410, 0, 412, 413, - 0, 0, 62, 0, 458, 0, 416, 418, 419, 420, - 440, 0, 442, 0, 0, 0, 58, 60, 459, 0, - 1039, 707, 0, 66, 67, 0, 0, 0, 177, 711, - 712, 713, 709, 234, 0, 0, 165, 161, 105, 106, - 107, 154, 109, 154, 154, 154, 154, 174, 174, 174, - 174, 137, 138, 139, 140, 141, 0, 0, 124, 154, - 154, 154, 154, 144, 145, 146, 147, 148, 149, 150, - 151, 110, 111, 112, 113, 114, 115, 116, 117, 118, - 156, 156, 156, 158, 158, 0, 0, 743, 81, 0, - 1069, 0, 1069, 93, 0, 248, 250, 251, 0, 0, - 0, 0, 0, 0, 734, 0, 0, 282, 717, 0, - 1069, 285, 286, 460, 751, 752, 290, 291, 334, 335, - 293, 294, 295, 296, 297, 298, 337, 0, 205, 206, - 306, 310, 333, 0, 0, 0, 333, 312, 313, 0, - 0, 351, 355, 356, 357, 358, 511, 470, 471, 472, - 474, 491, 0, 493, 495, 481, 482, 506, 507, 508, - 0, 0, 0, 0, 504, 486, 0, 517, 518, 519, - 520, 521, 522, 523, 524, 525, 526, 527, 528, 531, - 594, 595, 0, 529, 530, 541, 0, 0, 0, 391, - 619, 0, -2, 0, 509, 696, 644, 0, 0, 0, - 0, 514, 621, 0, 514, 621, 0, 0, 0, 388, - 389, 616, 613, 0, 0, 618, 0, 580, 0, 0, - 0, 0, 0, 0, 0, 0, 648, 46, 36, 0, - 649, 0, 0, 0, 0, 640, 642, 643, 648, 0, - 629, 0, 0, 467, 0, 0, 395, 42, 411, 407, - 0, 467, 0, 0, 457, 0, 0, 0, 0, 0, - 0, 447, 0, 0, 450, 0, 0, 0, 0, 441, - 0, 0, 0, 462, 980, 443, 0, 445, 446, -2, - 0, 0, 0, 56, 57, 0, 0, 0, 702, 65, - 0, 0, 70, 71, 703, 704, 705, 706, 0, 94, - 235, 237, 240, 241, 242, 99, 101, 102, 0, 0, - 215, 990, 1023, 920, 209, 209, 918, 222, 207, 208, - 96, 168, 166, 0, 163, 162, 108, 0, 174, 174, - 131, 132, 177, 0, 177, 177, 177, 0, 0, 125, - 126, 127, 128, 119, 0, 120, 121, 122, 0, 123, - 216, 0, 0, 0, 0, 1069, 83, 719, 84, 1068, - 0, 0, 735, 249, 722, 723, 724, 725, 726, 727, - 728, 729, 730, 731, 0, 85, 253, 255, 254, 258, - 0, 0, 0, 280, 1069, 284, 330, 307, 331, 332, - 330, 309, 316, 347, 492, 494, 496, 483, 504, 487, - 0, 484, 0, 0, 478, 546, 0, 0, 390, 0, - 636, 648, 550, 551, 0, 0, 0, 0, 0, 587, - 0, 0, 588, 0, 636, 0, 614, 0, 0, 562, - 0, 581, 0, 0, 582, 583, 584, 585, 586, 38, - 0, 0, 0, 646, 647, 639, 37, 0, 714, 715, - 630, 631, 632, 0, 404, 415, 396, 0, 644, 690, - 0, 0, 682, 0, 0, 467, 698, 0, 417, 436, - 438, 0, 433, 448, 449, 451, 0, 453, 0, 455, - 456, 421, 422, 423, 0, 424, 0, 0, 0, 0, - 444, 467, 0, 467, 59, 467, 61, 0, 461, 68, - 69, 0, 0, 75, 178, 179, 0, 238, 0, 100, - 0, 0, 196, 209, 209, 209, 200, 210, 201, 0, - 170, 0, 167, 104, 164, 0, 177, 177, 133, 0, - 134, 135, 136, 0, 152, 0, 0, 0, 231, 0, - 744, 82, 243, 1068, 260, 261, 262, 263, 264, 265, - 266, 267, 268, 269, 270, 271, 272, 273, 1068, 0, - 1068, 736, 737, 738, 739, 0, 88, 0, 0, 0, - 0, 0, 283, 333, 333, 485, 0, 505, 488, 547, - 548, 0, 620, 644, 40, 0, 154, 154, 599, 154, - 158, 602, 154, 604, 154, 607, 0, 0, 0, 0, - 0, 0, 0, 611, 561, 617, 0, 619, 0, 0, - 0, 174, 653, 650, 39, 634, 0, 468, 408, 43, - 47, 0, 690, 681, 692, 694, 0, 0, 0, 686, - 0, 428, 636, 0, 0, 430, 437, 0, 0, 431, - 0, 432, 452, 454, -2, 0, 0, 0, 0, 636, - 467, 54, 55, 0, 72, 73, 74, 236, 239, 0, - 211, 154, 214, 0, 197, 198, 199, 0, 172, 0, - 169, 155, 129, 130, 175, 176, 174, 0, 174, 0, - 159, 0, 223, 232, 0, 1069, 244, 245, 246, 247, - 0, 252, 0, 86, 87, 0, 0, 257, 281, 303, - 308, 489, 549, 648, 552, 596, 174, 600, 601, 603, - 605, 606, 608, 554, 553, 0, 0, 0, 0, 0, - 644, 0, 615, 0, 0, 174, 673, 44, 0, 0, - 0, 48, 0, 695, 0, 0, 0, 0, 63, 0, - 644, 699, 700, 434, 0, 439, 0, 0, 0, 442, - 644, 53, 188, 0, 213, 0, 426, 180, 173, 0, - 177, 153, 177, 0, 0, 233, 80, 0, 89, 90, - 0, 0, 0, 41, 597, 598, 0, 0, 0, 0, - 589, 0, 612, 0, 0, 655, 654, 667, 671, 635, - 633, 0, 693, 0, 685, 688, 684, 687, 429, 51, - 0, 0, 464, 0, 0, 462, 52, 187, 189, 0, - 194, 0, 212, 0, 0, 185, 0, 182, 184, 171, - 142, 143, 157, 160, 0, 0, 0, 0, 259, 555, - 557, 556, 558, 0, 0, 0, 560, 577, 578, 673, - 0, 666, 669, -2, 0, 0, 683, 0, 435, 463, - 465, 466, 425, 190, 191, 0, 195, 193, 0, 427, - 103, 0, 181, 183, 0, 275, 0, 91, 92, 85, - 559, 0, 0, 0, 660, 658, 658, 671, 0, 675, - 0, 680, 0, 691, 689, 192, 0, 186, 274, 0, - 0, 88, 590, 0, 593, 663, 0, 656, 659, 657, - 668, 0, 674, 0, 0, 672, 0, 276, 0, 256, - 591, 652, 0, 661, 662, 670, 0, 0, 0, 0, - 0, 664, 665, 676, 678, 218, 0, 0, 219, 220, - 0, 0, 592, 221, 0, 0, 0, 0, 0, 224, - 226, 227, 0, 0, 225, 277, 278, 228, 229, 230, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 656, + 0, 397, 397, 397, 397, 397, 397, 397, 0, 0, + 769, -2, 0, 34, 0, 0, 0, 0, -2, 362, + 363, 0, 365, -2, 0, 0, 374, 1108, 1108, 0, + 0, 1108, 0, 0, 1106, 51, 52, 380, 381, 382, + 1, 3, 0, 401, 664, 0, 0, -2, 399, 0, + 0, 752, 752, 752, 0, 80, 81, 0, 0, 0, + 0, 0, 750, 0, 750, 770, 771, 772, 98, 99, + 85, -2, 103, 104, 0, 108, 97, 0, 0, 0, + 107, 35, 31, 32, 33, 0, 748, 0, 748, 748, + 748, 0, 308, 479, 779, 780, 903, 904, 905, 906, + 907, 908, 909, 910, 911, 912, 913, 914, 915, 916, + 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, + 927, 928, 929, 930, 931, 932, 933, 934, 935, 936, + 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, + 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, + 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, + 967, 968, 969, 970, 971, 972, 973, 974, 975, 976, + 977, 978, 979, 980, 981, 982, 983, 984, 985, 986, + 987, 988, 989, 990, 991, 992, 993, 994, 995, 996, + 997, 998, 999, 1000, 1001, 1002, 1003, 1004, 1005, 1006, + 1007, 1008, 1009, 1010, 1011, 1012, 1013, 1014, 1015, 1016, + 1017, 1018, 1019, 1020, 1021, 1022, 1023, 1024, 1025, 1026, + 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, + 1037, 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, + 1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, 1056, + 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066, + 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, + 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, + 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, + 1097, 1098, 1099, 1100, 1101, 1102, 1103, 1104, 1105, 0, + 0, 0, 353, 0, 356, 356, 356, 322, 0, 324, + 1109, 0, 0, 0, 331, 0, 0, 337, 353, 1109, + 345, 359, 360, 347, 342, 343, 361, 364, 0, 369, + 372, 775, 776, 0, 387, 0, 953, 379, 392, 393, + 1108, 1108, 396, 36, 530, 489, 0, 495, 497, 0, + 532, 533, 534, 535, 536, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 562, 563, 564, 565, 641, + 642, 643, 644, 645, 646, 647, 648, 499, 500, 638, + 0, 729, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 629, 0, 599, 599, 599, 599, 599, 599, 599, + 599, 0, 0, 0, 0, 0, 0, 0, -2, -2, + 1108, 656, 47, 0, 397, 402, 403, 680, 0, 0, + 656, 1107, 0, 0, -2, -2, 413, 419, 420, 421, + 422, 398, 0, 425, 429, 0, 0, 0, 753, 0, + 0, 66, 0, 1078, 733, -2, -2, 0, 0, 777, + 778, -2, 917, -2, 783, 784, 785, 786, 787, 788, + 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, + 799, 800, 801, 802, 803, 804, 805, 806, 807, 808, + 809, 810, 811, 812, 813, 814, 815, 816, 817, 818, + 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, + 829, 830, 831, 832, 833, 834, 835, 836, 837, 838, + 839, 840, 841, 842, 843, 844, 845, 846, 847, 848, + 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, + 859, 860, 861, 862, 863, 864, 865, 866, 867, 868, + 869, 870, 871, 872, 873, 874, 875, 876, 877, 878, + 879, 880, 881, 882, 883, 884, 885, 886, 887, 888, + 889, 890, 891, 892, 893, 894, 895, 896, 897, 898, + 899, 900, 901, 902, 0, 0, 115, 116, 0, 0, + 237, 919, 113, 0, 231, 172, 1109, 0, 0, 0, + 0, 0, 105, 106, 0, 214, 0, 1109, 0, 0, + 0, 0, -2, 0, 299, 0, 0, 0, 0, 0, + 0, 0, 307, 0, 309, 1109, 353, 312, 0, 0, + 1109, 1109, 1109, 0, 1109, 1109, 319, 0, 320, 321, + 0, 222, 223, 224, 325, 1110, 1111, 1109, 1109, 350, + 0, 350, 348, 349, 340, 341, 0, 356, 334, 335, + 338, 339, 370, 373, 390, 388, 389, 391, 383, 384, + 385, 386, 0, 394, 395, 0, 0, 0, 0, 0, + 493, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 517, 518, 519, 520, 521, 522, 523, 496, 0, 510, + 0, 0, 0, 552, 553, 554, 555, 556, 557, 558, + 559, 560, 0, 410, 0, 0, 0, 656, 0, 0, + 0, 0, 0, 0, 0, 407, 0, 630, 0, 583, + 591, 0, 584, 592, 585, 593, 586, 0, 587, 594, + 588, 595, 589, 590, 596, 0, 0, 0, 410, 410, + 0, 0, 37, 664, 0, 412, 683, 0, 0, 665, + 657, 658, 661, 664, 0, 434, 423, 414, 417, 418, + 400, 0, 426, 430, 0, 432, 433, 0, 0, 64, + 0, 478, 0, 436, 438, 439, 440, 460, 0, 462, + 0, 0, 0, 60, 62, 479, 0, 1078, 739, 0, + 68, 69, 0, 0, 0, 195, 743, 744, 745, 741, + 254, 0, 0, 183, 179, 123, 124, 125, 172, 127, + 172, 172, 172, 172, 192, 192, 192, 192, 155, 156, + 157, 158, 159, 0, 0, 142, 172, 172, 172, 172, + 162, 163, 164, 165, 166, 167, 168, 169, 128, 129, + 130, 131, 132, 133, 134, 135, 136, 174, 174, 174, + 176, 176, 0, 0, 206, 0, 661, 0, 83, 0, + 94, 0, 773, 96, 214, 0, 215, 1108, 0, 0, + 764, 269, 754, 755, 756, 757, 758, 759, 760, 761, + 762, 763, 0, 268, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 302, 749, 0, 1109, 305, 306, 480, + 781, 782, 310, 311, 354, 355, 313, 314, 315, 316, + 317, 318, 357, 0, 225, 226, 326, 330, 353, 0, + 0, 0, 353, 332, 333, 0, 0, 371, 375, 376, + 377, 378, 531, 490, 491, 492, 494, 511, 0, 513, + 515, 501, 502, 526, 527, 528, 0, 0, 0, 0, + 524, 506, 0, 537, 538, 539, 540, 541, 542, 543, + 544, 545, 546, 547, 548, 551, 614, 615, 0, 549, + 550, 561, 0, 0, 0, 411, 639, 0, -2, 0, + 529, 728, 664, 0, 0, 0, 0, 534, 641, 0, + 534, 641, 0, 0, 0, 408, 409, 636, 633, 0, + 0, 638, 0, 600, 0, 0, 0, 0, 0, 0, + 0, 0, 680, 48, 38, 0, 681, 0, 0, 0, + 0, 660, 662, 663, 680, 0, 649, 0, 0, 487, + 0, 0, 415, 44, 431, 427, 0, 487, 0, 0, + 477, 0, 0, 0, 0, 0, 0, 467, 0, 0, + 470, 0, 0, 0, 0, 461, 0, 0, 0, 482, + 1018, 463, 0, 465, 466, -2, 0, 0, 0, 58, + 59, 0, 0, 0, 734, 67, 0, 0, 72, 73, + 735, 736, 737, 738, 0, 100, 255, 257, 260, 261, + 262, 117, 119, 120, 0, 0, 235, 1028, 1062, 954, + 229, 229, 952, 242, 227, 228, 114, 186, 184, 0, + 181, 180, 126, 192, 192, 149, 150, 195, 0, 195, + 195, 195, 0, 0, 143, 144, 145, 146, 137, 0, + 138, 139, 140, 0, 141, 236, 0, 0, 668, 207, + 208, 0, 214, 0, 0, 232, 233, 0, 1109, 751, + 0, 0, 0, 111, 112, 263, 1108, 280, 281, 282, + 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, + 293, 1108, 0, 1108, 765, 766, 767, 768, 0, 86, + 273, 275, 274, 278, 0, 0, 0, 0, 300, 1109, + 304, 350, 327, 351, 352, 350, 329, 336, 367, 512, + 514, 516, 503, 524, 507, 0, 504, 0, 0, 498, + 566, 0, 0, 410, 0, 656, 680, 570, 571, 0, + 0, 0, 0, 0, 607, 0, 0, 608, 0, 656, + 0, 634, 0, 0, 582, 0, 601, 0, 0, 602, + 603, 604, 605, 606, 40, 0, 0, 0, 666, 667, + 659, 39, 0, 746, 747, 650, 651, 652, 0, 424, + 435, 416, 0, 664, 722, 0, 0, 714, 0, 0, + 487, 730, 0, 437, 456, 458, 0, 453, 468, 469, + 471, 0, 473, 0, 475, 476, 441, 442, 443, 0, + 444, 0, 0, 0, 0, 464, 487, 0, 487, 61, + 487, 63, 0, 481, 70, 71, 0, 0, 77, 196, + 197, 0, 258, 0, 118, 0, 0, 216, 229, 229, + 229, 220, 230, 221, 0, 188, 0, 185, 122, 182, + 195, 195, 151, 0, 152, 153, 154, 0, 170, 0, + 0, 0, 251, 82, 672, 671, 214, 214, 209, 210, + 0, 212, 0, 173, 84, 0, 774, 109, 110, 264, + 265, 266, 267, 0, 89, 0, 0, 0, 0, 271, + 0, 303, 353, 353, 505, 0, 525, 508, 567, 568, + 0, 640, 664, 42, 0, 172, 172, 619, 172, 176, + 622, 172, 624, 172, 627, 0, 0, 0, 0, 0, + 0, 0, 631, 581, 637, 0, 639, 0, 0, 0, + 192, 685, 682, 41, 654, 0, 488, 428, 45, 49, + 0, 722, 713, 724, 726, 0, 0, 0, 718, 0, + 448, 656, 0, 0, 450, 457, 0, 0, 451, 0, + 452, 472, 474, -2, 0, 0, 0, 0, 656, 487, + 56, 57, 0, 74, 75, 76, 256, 259, 0, 234, + 0, 217, 218, 219, 0, 190, 0, 187, 147, 148, + 193, 194, 192, 0, 192, 0, 177, 0, 243, 252, + 0, 669, 670, 0, 0, 211, 213, 95, 0, 272, + 0, 87, 88, 0, 0, 277, 301, 323, 328, 509, + 569, 680, 572, 616, 192, 620, 621, 623, 625, 626, + 628, 574, 573, 0, 0, 0, 0, 0, 664, 0, + 635, 0, 0, 192, 705, 46, 0, 0, 0, 50, + 0, 727, 0, 0, 0, 0, 65, 0, 664, 731, + 732, 454, 0, 459, 0, 0, 0, 462, 664, 55, + 206, 0, 446, 198, 191, 0, 195, 171, 195, 0, + 0, 253, 673, 674, 675, 676, 677, 678, 679, 0, + 90, 91, 0, 0, 0, 43, 617, 618, 0, 0, + 0, 0, 609, 0, 632, 0, 0, 687, 686, 699, + 703, 655, 653, 0, 725, 0, 717, 720, 716, 719, + 449, 53, 0, 0, 484, 0, 0, 482, 54, 205, + 0, 0, 203, 0, 200, 202, 189, 160, 161, 175, + 178, 0, 295, 0, 0, 0, 0, 279, 575, 577, + 576, 578, 0, 0, 0, 580, 597, 598, 705, 0, + 698, 701, -2, 0, 0, 715, 0, 455, 483, 485, + 486, 445, 0, 447, 121, 0, 199, 201, 294, 0, + 0, 92, 93, 86, 579, 0, 0, 0, 692, 690, + 690, 703, 0, 707, 0, 712, 0, 723, 721, 0, + 204, 296, 0, 89, 610, 0, 613, 695, 0, 688, + 691, 689, 700, 0, 706, 0, 0, 704, 0, 0, + 276, 611, 684, 0, 693, 694, 702, 0, 0, 0, + 0, 0, 696, 697, 708, 710, 238, 0, 0, 239, + 240, 0, 0, 0, 612, 241, 0, 0, 0, 297, + 298, 244, 246, 247, 0, 0, 245, 248, 249, 250, } var yyTok1 = [...]int{ 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 97, 3, 3, 3, 124, 116, 3, - 73, 75, 121, 119, 74, 120, 136, 122, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 384, - 105, 104, 106, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 104, 3, 3, 3, 131, 123, 3, + 80, 82, 128, 126, 81, 127, 143, 129, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 394, + 112, 111, 113, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 126, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 133, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 115, 3, 127, + 3, 3, 3, 3, 122, 3, 134, } var yyTok2 = [...]int{ @@ -3714,12 +3762,12 @@ var yyTok2 = [...]int{ 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, - 72, 76, 77, 78, 79, 80, 81, 82, 83, 84, + 72, 73, 74, 75, 76, 77, 78, 79, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, - 95, 96, 98, 99, 100, 101, 102, 103, 107, 108, - 109, 110, 111, 112, 113, 114, 117, 118, 123, 125, - 128, 129, 130, 131, 132, 133, 134, 135, 137, 138, - 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, + 95, 96, 97, 98, 99, 100, 101, 102, 103, 105, + 106, 107, 108, 109, 110, 114, 115, 116, 117, 118, + 119, 120, 121, 124, 125, 130, 132, 135, 136, 137, + 138, 139, 140, 141, 142, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, @@ -3756,7 +3804,9 @@ var yyTok3 = [...]int{ 57690, 365, 57691, 366, 57692, 367, 57693, 368, 57694, 369, 57695, 370, 57696, 371, 57697, 372, 57698, 373, 57699, 374, 57700, 375, 57701, 376, 57702, 377, 57703, 378, 57704, 379, - 57705, 380, 57706, 381, 57707, 382, 57708, 383, 0, + 57705, 380, 57706, 381, 57707, 382, 57708, 383, 57709, 384, + 57710, 385, 57711, 386, 57712, 387, 57713, 388, 57714, 389, + 57715, 390, 57716, 391, 57717, 392, 57718, 393, 0, } var yyErrorMessages = [...]struct { @@ -4098,65 +4148,77 @@ yydefault: case 1: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:363 +//line sql.y:374 { setParseTree(yylex, yyDollar[1].statement) } case 2: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:368 +//line sql.y:379 { } case 3: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:369 +//line sql.y:380 { } case 4: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:373 +//line sql.y:384 { yyVAL.statement = yyDollar[1].selStmt } case 30: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:402 +//line sql.y:413 { setParseTree(yylex, nil) } case 31: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:408 +//line sql.y:419 { yyVAL.colIdent = NewColIdentWithAt(string(yyDollar[1].bytes), NoAt) } case 32: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:412 +//line sql.y:423 { yyVAL.colIdent = NewColIdentWithAt(string(yyDollar[1].bytes), SingleAt) } case 33: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:416 +//line sql.y:427 { yyVAL.colIdent = NewColIdentWithAt(string(yyDollar[1].bytes), DoubleAt) } case 34: + yyDollar = yyS[yypt-0 : yypt+1] +//line sql.y:432 + { + yyVAL.colIdent = NewColIdentWithAt("", NoAt) + } + case 35: + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:436 + { + yyVAL.colIdent = yyDollar[1].colIdent + } + case 36: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:422 +//line sql.y:442 { yyVAL.statement = &OtherAdmin{} } - case 35: + case 37: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:428 +//line sql.y:448 { yyVAL.statement = &Load{} } - case 36: + case 38: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:434 +//line sql.y:454 { sel := yyDollar[1].selStmt.(*Select) sel.OrderBy = yyDollar[2].orderBy @@ -4165,27 +4227,27 @@ yydefault: sel.Into = yyDollar[5].selectInto yyVAL.selStmt = sel } - case 37: + case 39: yyDollar = yyS[yypt-6 : yypt+1] -//line sql.y:443 +//line sql.y:463 { yyVAL.selStmt = &Union{FirstStatement: &ParenSelect{Select: yyDollar[2].selStmt}, OrderBy: yyDollar[4].orderBy, Limit: yyDollar[5].limit, Lock: yyDollar[6].lock} } - case 38: + case 40: yyDollar = yyS[yypt-6 : yypt+1] -//line sql.y:447 +//line sql.y:467 { yyVAL.selStmt = Unionize(yyDollar[1].selStmt, yyDollar[3].selStmt, yyDollar[2].boolean, yyDollar[4].orderBy, yyDollar[5].limit, yyDollar[6].lock) } - case 39: + case 41: yyDollar = yyS[yypt-7 : yypt+1] -//line sql.y:451 +//line sql.y:471 { yyVAL.selStmt = NewSelect(Comments(yyDollar[2].bytes2), SelectExprs{Nextval{Expr: yyDollar[5].expr}}, []string{yyDollar[3].str} /*options*/, TableExprs{&AliasedTableExpr{Expr: yyDollar[7].tableName}}, nil /*where*/, nil /*groupBy*/, nil /*having*/) } - case 40: + case 42: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:474 +//line sql.y:494 { sel := yyDollar[1].selStmt.(*Select) sel.OrderBy = yyDollar[2].orderBy @@ -4193,45 +4255,45 @@ yydefault: sel.Lock = yyDollar[4].lock yyVAL.selStmt = sel } - case 41: + case 43: yyDollar = yyS[yypt-6 : yypt+1] -//line sql.y:482 +//line sql.y:502 { yyVAL.selStmt = Unionize(yyDollar[1].selStmt, yyDollar[3].selStmt, yyDollar[2].boolean, yyDollar[4].orderBy, yyDollar[5].limit, yyDollar[6].lock) } - case 42: + case 44: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:488 +//line sql.y:508 { yyVAL.statement = &Stream{Comments: Comments(yyDollar[2].bytes2), SelectExpr: yyDollar[3].selectExpr, Table: yyDollar[5].tableName} } - case 43: + case 45: yyDollar = yyS[yypt-7 : yypt+1] -//line sql.y:494 +//line sql.y:514 { yyVAL.statement = &VStream{Comments: Comments(yyDollar[2].bytes2), SelectExpr: yyDollar[3].selectExpr, Table: yyDollar[5].tableName, Where: NewWhere(WhereClause, yyDollar[6].expr), Limit: yyDollar[7].limit} } - case 44: + case 46: yyDollar = yyS[yypt-8 : yypt+1] -//line sql.y:502 +//line sql.y:522 { yyVAL.selStmt = NewSelect(Comments(yyDollar[2].bytes2), yyDollar[4].selectExprs /*SelectExprs*/, yyDollar[3].strs /*options*/, yyDollar[5].tableExprs /*from*/, NewWhere(WhereClause, yyDollar[6].expr), GroupBy(yyDollar[7].exprs), NewWhere(HavingClause, yyDollar[8].expr)) } - case 45: + case 47: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:508 +//line sql.y:528 { yyVAL.selStmt = yyDollar[1].selStmt } - case 46: + case 48: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:512 +//line sql.y:532 { yyVAL.selStmt = &ParenSelect{Select: yyDollar[2].selStmt} } - case 47: + case 49: yyDollar = yyS[yypt-7 : yypt+1] -//line sql.y:519 +//line sql.y:539 { // insert_data returns a *Insert pre-filled with Columns & Values ins := yyDollar[6].ins @@ -4243,9 +4305,9 @@ yydefault: ins.OnDup = OnDup(yyDollar[7].updateExprs) yyVAL.statement = ins } - case 48: + case 50: yyDollar = yyS[yypt-8 : yypt+1] -//line sql.y:531 +//line sql.y:551 { cols := make(Columns, 0, len(yyDollar[7].updateExprs)) vals := make(ValTuple, 0, len(yyDollar[8].updateExprs)) @@ -4255,1249 +4317,1358 @@ yydefault: } yyVAL.statement = &Insert{Action: yyDollar[1].insertAction, Comments: Comments(yyDollar[2].bytes2), Ignore: yyDollar[3].ignore, Table: yyDollar[4].tableName, Partitions: yyDollar[5].partitions, Columns: cols, Rows: Values{vals}, OnDup: OnDup(yyDollar[8].updateExprs)} } - case 49: + case 51: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:543 +//line sql.y:563 { yyVAL.insertAction = InsertAct } - case 50: + case 52: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:547 +//line sql.y:567 { yyVAL.insertAction = ReplaceAct } - case 51: + case 53: yyDollar = yyS[yypt-9 : yypt+1] -//line sql.y:553 +//line sql.y:573 { yyVAL.statement = &Update{Comments: Comments(yyDollar[2].bytes2), Ignore: yyDollar[3].ignore, TableExprs: yyDollar[4].tableExprs, Exprs: yyDollar[6].updateExprs, Where: NewWhere(WhereClause, yyDollar[7].expr), OrderBy: yyDollar[8].orderBy, Limit: yyDollar[9].limit} } - case 52: + case 54: yyDollar = yyS[yypt-9 : yypt+1] -//line sql.y:559 +//line sql.y:579 { yyVAL.statement = &Delete{Comments: Comments(yyDollar[2].bytes2), Ignore: yyDollar[3].ignore, TableExprs: TableExprs{&AliasedTableExpr{Expr: yyDollar[5].tableName}}, Partitions: yyDollar[6].partitions, Where: NewWhere(WhereClause, yyDollar[7].expr), OrderBy: yyDollar[8].orderBy, Limit: yyDollar[9].limit} } - case 53: + case 55: yyDollar = yyS[yypt-8 : yypt+1] -//line sql.y:563 +//line sql.y:583 { yyVAL.statement = &Delete{Comments: Comments(yyDollar[2].bytes2), Ignore: yyDollar[3].ignore, Targets: yyDollar[5].tableNames, TableExprs: yyDollar[7].tableExprs, Where: NewWhere(WhereClause, yyDollar[8].expr)} } - case 54: + case 56: yyDollar = yyS[yypt-7 : yypt+1] -//line sql.y:567 +//line sql.y:587 { yyVAL.statement = &Delete{Comments: Comments(yyDollar[2].bytes2), Ignore: yyDollar[3].ignore, Targets: yyDollar[4].tableNames, TableExprs: yyDollar[6].tableExprs, Where: NewWhere(WhereClause, yyDollar[7].expr)} } - case 55: + case 57: yyDollar = yyS[yypt-7 : yypt+1] -//line sql.y:571 +//line sql.y:591 { yyVAL.statement = &Delete{Comments: Comments(yyDollar[2].bytes2), Ignore: yyDollar[3].ignore, Targets: yyDollar[4].tableNames, TableExprs: yyDollar[6].tableExprs, Where: NewWhere(WhereClause, yyDollar[7].expr)} } - case 56: + case 58: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:576 +//line sql.y:596 { } - case 57: + case 59: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:577 +//line sql.y:597 { } - case 58: + case 60: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:581 +//line sql.y:601 { yyVAL.tableNames = TableNames{yyDollar[1].tableName} } - case 59: + case 61: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:585 +//line sql.y:605 { yyVAL.tableNames = append(yyVAL.tableNames, yyDollar[3].tableName) } - case 60: + case 62: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:591 +//line sql.y:611 { yyVAL.tableNames = TableNames{yyDollar[1].tableName} } - case 61: + case 63: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:595 +//line sql.y:615 { yyVAL.tableNames = append(yyVAL.tableNames, yyDollar[3].tableName) } - case 62: + case 64: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:600 +//line sql.y:620 { yyVAL.partitions = nil } - case 63: + case 65: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:604 +//line sql.y:624 { yyVAL.partitions = yyDollar[3].partitions } - case 64: + case 66: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:610 +//line sql.y:630 { yyVAL.statement = &Set{Comments: Comments(yyDollar[2].bytes2), Exprs: yyDollar[3].setExprs} } - case 65: + case 67: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:616 +//line sql.y:636 { yyVAL.statement = &SetTransaction{Comments: Comments(yyDollar[2].bytes2), Scope: yyDollar[3].scope, Characteristics: yyDollar[5].characteristics} } - case 66: + case 68: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:620 +//line sql.y:640 { yyVAL.statement = &SetTransaction{Comments: Comments(yyDollar[2].bytes2), Characteristics: yyDollar[4].characteristics, Scope: ImplicitScope} } - case 67: + case 69: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:626 +//line sql.y:646 { yyVAL.characteristics = []Characteristic{yyDollar[1].characteristic} } - case 68: + case 70: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:630 +//line sql.y:650 { yyVAL.characteristics = append(yyVAL.characteristics, yyDollar[3].characteristic) } - case 69: + case 71: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:636 +//line sql.y:656 { yyVAL.characteristic = yyDollar[3].isolationLevel } - case 70: + case 72: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:640 +//line sql.y:660 { yyVAL.characteristic = ReadWrite } - case 71: + case 73: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:644 +//line sql.y:664 { yyVAL.characteristic = ReadOnly } - case 72: + case 74: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:650 +//line sql.y:670 { yyVAL.isolationLevel = RepeatableRead } - case 73: + case 75: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:654 +//line sql.y:674 { yyVAL.isolationLevel = ReadCommitted } - case 74: + case 76: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:658 +//line sql.y:678 { yyVAL.isolationLevel = ReadUncommitted } - case 75: + case 77: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:662 +//line sql.y:682 { yyVAL.isolationLevel = Serializable } - case 76: + case 78: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:668 +//line sql.y:688 { yyVAL.scope = SessionScope } - case 77: + case 79: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:672 +//line sql.y:692 { yyVAL.scope = GlobalScope } - case 78: + case 80: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:678 +//line sql.y:698 { yyDollar[1].ddl.TableSpec = yyDollar[2].TableSpec yyVAL.statement = yyDollar[1].ddl } - case 79: + case 81: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:683 +//line sql.y:703 { // Create table [name] like [name] yyDollar[1].ddl.OptLike = yyDollar[2].optLike yyVAL.statement = yyDollar[1].ddl } - case 80: - yyDollar = yyS[yypt-8 : yypt+1] -//line sql.y:689 + case 82: + yyDollar = yyS[yypt-6 : yypt+1] +//line sql.y:709 { - // Change this to an alter statement - yyVAL.statement = &DDL{Action: AlterDDLAction, Table: yyDollar[7].tableName} + yyDollar[1].createIndex.Columns = yyDollar[3].indexColumns + yyDollar[1].createIndex.Options = append(yyDollar[5].indexOptions, yyDollar[6].indexOptions...) + yyDollar[1].createIndex.FullyParsed = true + yyVAL.statement = yyDollar[1].createIndex } - case 81: + case 83: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:694 +//line sql.y:716 { yyVAL.statement = &DDL{Action: CreateDDLAction, Table: yyDollar[3].tableName.ToViewName()} } - case 82: + case 84: yyDollar = yyS[yypt-6 : yypt+1] -//line sql.y:698 +//line sql.y:720 { yyVAL.statement = &DDL{Action: CreateDDLAction, Table: yyDollar[5].tableName.ToViewName()} } - case 83: - yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:702 - { - yyVAL.statement = &DBDDL{Action: CreateDBDDLAction, DBName: string(yyDollar[4].colIdent.String()), IfNotExists: yyDollar[3].boolean} - } - case 84: - yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:706 + case 85: + yyDollar = yyS[yypt-2 : yypt+1] +//line sql.y:724 { - yyVAL.statement = &DBDDL{Action: CreateDBDDLAction, DBName: string(yyDollar[4].colIdent.String()), IfNotExists: yyDollar[3].boolean} + yyDollar[1].createDatabase.FullyParsed = true + yyDollar[1].createDatabase.CreateOptions = yyDollar[2].collateAndCharsets + yyVAL.statement = yyDollar[1].createDatabase } - case 85: + case 86: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:711 +//line sql.y:731 { yyVAL.colIdent = NewColIdent("") } - case 86: + case 87: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:715 +//line sql.y:735 { yyVAL.colIdent = yyDollar[2].colIdent } - case 87: + case 88: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:721 +//line sql.y:741 { yyVAL.colIdent = yyDollar[1].colIdent } - case 88: + case 89: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:726 +//line sql.y:746 { var v []VindexParam yyVAL.vindexParams = v } - case 89: + case 90: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:731 +//line sql.y:751 { yyVAL.vindexParams = yyDollar[2].vindexParams } - case 90: + case 91: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:737 +//line sql.y:757 { yyVAL.vindexParams = make([]VindexParam, 0, 4) yyVAL.vindexParams = append(yyVAL.vindexParams, yyDollar[1].vindexParam) } - case 91: + case 92: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:742 +//line sql.y:762 { yyVAL.vindexParams = append(yyVAL.vindexParams, yyDollar[3].vindexParam) } - case 92: + case 93: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:748 +//line sql.y:768 { yyVAL.vindexParam = VindexParam{Key: yyDollar[1].colIdent, Val: yyDollar[3].str} } - case 93: + case 94: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:754 +//line sql.y:774 { yyVAL.ddl = &DDL{Action: CreateDDLAction, Table: yyDollar[4].tableName} setDDL(yylex, yyVAL.ddl) } - case 94: - yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:761 - { - yyVAL.TableSpec = yyDollar[2].TableSpec - yyVAL.TableSpec.Options = yyDollar[4].str - } case 95: - yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:768 + yyDollar = yyS[yypt-7 : yypt+1] +//line sql.y:781 { - yyVAL.optLike = &OptLike{LikeTable: yyDollar[2].tableName} + yyVAL.createIndex = &CreateIndex{Constraint: yyDollar[2].str, Name: yyDollar[4].colIdent, IndexType: yyDollar[5].str, Table: yyDollar[7].tableName} + setDDL(yylex, yyVAL.createIndex) } case 96: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:772 +//line sql.y:788 { - yyVAL.optLike = &OptLike{LikeTable: yyDollar[3].tableName} + yyVAL.createDatabase = &CreateDatabase{DBName: string(yyDollar[4].colIdent.String()), IfNotExists: yyDollar[3].boolean} + setDDL(yylex, yyVAL.createDatabase) } case 97: - yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:778 - { - yyVAL.TableSpec = &TableSpec{} - yyVAL.TableSpec.AddColumn(yyDollar[1].columnDefinition) - } - case 98: - yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:783 - { - yyVAL.TableSpec = &TableSpec{} - yyVAL.TableSpec.AddConstraint(yyDollar[1].constraintDefinition) - } - case 99: - yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:788 + yyDollar = yyS[yypt-2 : yypt+1] +//line sql.y:795 { - yyVAL.TableSpec.AddColumn(yyDollar[3].columnDefinition) + yyVAL.alterDatabase = &AlterDatabase{} + setDDL(yylex, yyVAL.alterDatabase) } case 100: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:792 +//line sql.y:806 { - yyVAL.TableSpec.AddColumn(yyDollar[3].columnDefinition) - yyVAL.TableSpec.AddConstraint(yyDollar[4].constraintDefinition) + yyVAL.TableSpec = yyDollar[2].TableSpec + yyVAL.TableSpec.Options = yyDollar[4].str } case 101: - yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:797 + yyDollar = yyS[yypt-0 : yypt+1] +//line sql.y:812 { - yyVAL.TableSpec.AddIndex(yyDollar[3].indexDefinition) + yyVAL.collateAndCharsets = nil } case 102: - yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:801 + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:816 { - yyVAL.TableSpec.AddConstraint(yyDollar[3].constraintDefinition) + yyVAL.collateAndCharsets = yyDollar[1].collateAndCharsets } case 103: - yyDollar = yyS[yypt-8 : yypt+1] -//line sql.y:807 + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:822 { - yyDollar[2].columnType.NotNull = yyDollar[3].boolean - yyDollar[2].columnType.Default = yyDollar[4].optVal - yyDollar[2].columnType.OnUpdate = yyDollar[5].optVal - yyDollar[2].columnType.Autoincrement = yyDollar[6].boolean - yyDollar[2].columnType.KeyOpt = yyDollar[7].colKeyOpt - yyDollar[2].columnType.Comment = yyDollar[8].literal - yyVAL.columnDefinition = &ColumnDefinition{Name: yyDollar[1].colIdent, Type: yyDollar[2].columnType} + yyVAL.collateAndCharsets = []CollateAndCharset{yyDollar[1].collateAndCharset} } case 104: + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:826 + { + yyVAL.collateAndCharsets = []CollateAndCharset{yyDollar[1].collateAndCharset} + } + case 105: + yyDollar = yyS[yypt-2 : yypt+1] +//line sql.y:830 + { + yyVAL.collateAndCharsets = append(yyDollar[1].collateAndCharsets, yyDollar[2].collateAndCharset) + } + case 106: + yyDollar = yyS[yypt-2 : yypt+1] +//line sql.y:834 + { + yyVAL.collateAndCharsets = append(yyDollar[1].collateAndCharsets, yyDollar[2].collateAndCharset) + } + case 107: + yyDollar = yyS[yypt-0 : yypt+1] +//line sql.y:839 + { + yyVAL.boolean = false + } + case 108: + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:843 + { + yyVAL.boolean = true + } + case 109: + yyDollar = yyS[yypt-5 : yypt+1] +//line sql.y:849 + { + yyVAL.collateAndCharset = CollateAndCharset{Type: CharacterSetType, Value: (yyDollar[5].colIdent.String()), IsDefault: yyDollar[1].boolean} + } + case 110: + yyDollar = yyS[yypt-5 : yypt+1] +//line sql.y:853 + { + yyVAL.collateAndCharset = CollateAndCharset{Type: CharacterSetType, Value: ("'" + string(yyDollar[5].bytes) + "'"), IsDefault: yyDollar[1].boolean} + } + case 111: + yyDollar = yyS[yypt-4 : yypt+1] +//line sql.y:859 + { + yyVAL.collateAndCharset = CollateAndCharset{Type: CollateType, Value: (yyDollar[4].colIdent.String()), IsDefault: yyDollar[1].boolean} + } + case 112: + yyDollar = yyS[yypt-4 : yypt+1] +//line sql.y:863 + { + yyVAL.collateAndCharset = CollateAndCharset{Type: CollateType, Value: ("'" + string(yyDollar[4].bytes) + "'"), IsDefault: yyDollar[1].boolean} + } + case 113: + yyDollar = yyS[yypt-2 : yypt+1] +//line sql.y:870 + { + yyVAL.optLike = &OptLike{LikeTable: yyDollar[2].tableName} + } + case 114: + yyDollar = yyS[yypt-4 : yypt+1] +//line sql.y:874 + { + yyVAL.optLike = &OptLike{LikeTable: yyDollar[3].tableName} + } + case 115: + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:880 + { + yyVAL.TableSpec = &TableSpec{} + yyVAL.TableSpec.AddColumn(yyDollar[1].columnDefinition) + } + case 116: + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:885 + { + yyVAL.TableSpec = &TableSpec{} + yyVAL.TableSpec.AddConstraint(yyDollar[1].constraintDefinition) + } + case 117: + yyDollar = yyS[yypt-3 : yypt+1] +//line sql.y:890 + { + yyVAL.TableSpec.AddColumn(yyDollar[3].columnDefinition) + } + case 118: + yyDollar = yyS[yypt-4 : yypt+1] +//line sql.y:894 + { + yyVAL.TableSpec.AddColumn(yyDollar[3].columnDefinition) + yyVAL.TableSpec.AddConstraint(yyDollar[4].constraintDefinition) + } + case 119: + yyDollar = yyS[yypt-3 : yypt+1] +//line sql.y:899 + { + yyVAL.TableSpec.AddIndex(yyDollar[3].indexDefinition) + } + case 120: + yyDollar = yyS[yypt-3 : yypt+1] +//line sql.y:903 + { + yyVAL.TableSpec.AddConstraint(yyDollar[3].constraintDefinition) + } + case 121: + yyDollar = yyS[yypt-8 : yypt+1] +//line sql.y:909 + { + yyDollar[2].columnType.NotNull = yyDollar[3].boolean + yyDollar[2].columnType.Default = yyDollar[4].optVal + yyDollar[2].columnType.OnUpdate = yyDollar[5].optVal + yyDollar[2].columnType.Autoincrement = yyDollar[6].boolean + yyDollar[2].columnType.KeyOpt = yyDollar[7].colKeyOpt + yyDollar[2].columnType.Comment = yyDollar[8].literal + yyVAL.columnDefinition = &ColumnDefinition{Name: yyDollar[1].colIdent, Type: yyDollar[2].columnType} + } + case 122: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:818 +//line sql.y:920 { yyVAL.columnType = yyDollar[1].columnType yyVAL.columnType.Unsigned = yyDollar[2].boolean yyVAL.columnType.Zerofill = yyDollar[3].boolean } - case 108: + case 126: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:829 +//line sql.y:931 { yyVAL.columnType = yyDollar[1].columnType yyVAL.columnType.Length = yyDollar[2].literal } - case 109: + case 127: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:834 +//line sql.y:936 { yyVAL.columnType = yyDollar[1].columnType } - case 110: + case 128: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:840 +//line sql.y:942 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } - case 111: + case 129: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:844 +//line sql.y:946 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } - case 112: + case 130: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:848 +//line sql.y:950 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } - case 113: + case 131: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:852 +//line sql.y:954 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } - case 114: + case 132: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:856 +//line sql.y:958 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } - case 115: + case 133: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:860 +//line sql.y:962 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } - case 116: + case 134: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:864 +//line sql.y:966 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } - case 117: + case 135: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:868 +//line sql.y:970 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } - case 118: + case 136: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:872 +//line sql.y:974 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } - case 119: + case 137: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:878 +//line sql.y:980 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} yyVAL.columnType.Length = yyDollar[2].LengthScaleOption.Length yyVAL.columnType.Scale = yyDollar[2].LengthScaleOption.Scale } - case 120: + case 138: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:884 +//line sql.y:986 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} yyVAL.columnType.Length = yyDollar[2].LengthScaleOption.Length yyVAL.columnType.Scale = yyDollar[2].LengthScaleOption.Scale } - case 121: + case 139: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:890 +//line sql.y:992 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} yyVAL.columnType.Length = yyDollar[2].LengthScaleOption.Length yyVAL.columnType.Scale = yyDollar[2].LengthScaleOption.Scale } - case 122: + case 140: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:896 +//line sql.y:998 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} yyVAL.columnType.Length = yyDollar[2].LengthScaleOption.Length yyVAL.columnType.Scale = yyDollar[2].LengthScaleOption.Scale } - case 123: + case 141: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:902 +//line sql.y:1004 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} yyVAL.columnType.Length = yyDollar[2].LengthScaleOption.Length yyVAL.columnType.Scale = yyDollar[2].LengthScaleOption.Scale } - case 124: + case 142: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:910 +//line sql.y:1012 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } - case 125: + case 143: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:914 +//line sql.y:1016 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].literal} } - case 126: + case 144: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:918 +//line sql.y:1020 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].literal} } - case 127: + case 145: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:922 +//line sql.y:1024 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].literal} } - case 128: + case 146: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:926 +//line sql.y:1028 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].literal} } - case 129: + case 147: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:932 +//line sql.y:1034 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].literal, Charset: yyDollar[3].str, Collate: yyDollar[4].str} } - case 130: + case 148: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:936 +//line sql.y:1038 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].literal, Charset: yyDollar[3].str, Collate: yyDollar[4].str} } - case 131: + case 149: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:940 +//line sql.y:1042 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].literal} } - case 132: + case 150: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:944 +//line sql.y:1046 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].literal} } - case 133: + case 151: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:948 +//line sql.y:1050 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Charset: yyDollar[2].str, Collate: yyDollar[3].str} } - case 134: + case 152: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:952 +//line sql.y:1054 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Charset: yyDollar[2].str, Collate: yyDollar[3].str} } - case 135: + case 153: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:956 +//line sql.y:1058 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Charset: yyDollar[2].str, Collate: yyDollar[3].str} } - case 136: + case 154: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:960 +//line sql.y:1062 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Charset: yyDollar[2].str, Collate: yyDollar[3].str} } - case 137: + case 155: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:964 +//line sql.y:1066 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } - case 138: + case 156: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:968 +//line sql.y:1070 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } - case 139: + case 157: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:972 +//line sql.y:1074 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } - case 140: + case 158: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:976 +//line sql.y:1078 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } - case 141: + case 159: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:980 +//line sql.y:1082 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } - case 142: + case 160: yyDollar = yyS[yypt-6 : yypt+1] -//line sql.y:984 +//line sql.y:1086 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), EnumValues: yyDollar[3].strs, Charset: yyDollar[5].str, Collate: yyDollar[6].str} } - case 143: + case 161: yyDollar = yyS[yypt-6 : yypt+1] -//line sql.y:989 +//line sql.y:1091 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), EnumValues: yyDollar[3].strs, Charset: yyDollar[5].str, Collate: yyDollar[6].str} } - case 144: + case 162: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:995 +//line sql.y:1097 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } - case 145: + case 163: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:999 +//line sql.y:1101 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } - case 146: + case 164: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1003 +//line sql.y:1105 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } - case 147: + case 165: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1007 +//line sql.y:1109 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } - case 148: + case 166: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1011 +//line sql.y:1113 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } - case 149: + case 167: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1015 +//line sql.y:1117 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } - case 150: + case 168: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1019 +//line sql.y:1121 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } - case 151: + case 169: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1023 +//line sql.y:1125 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } - case 152: + case 170: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1029 +//line sql.y:1131 { yyVAL.strs = make([]string, 0, 4) yyVAL.strs = append(yyVAL.strs, "'"+string(yyDollar[1].bytes)+"'") } - case 153: + case 171: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1034 +//line sql.y:1136 { yyVAL.strs = append(yyDollar[1].strs, "'"+string(yyDollar[3].bytes)+"'") } - case 154: + case 172: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1039 +//line sql.y:1141 { yyVAL.literal = nil } - case 155: + case 173: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1043 +//line sql.y:1145 { yyVAL.literal = NewIntLiteral(yyDollar[2].bytes) } - case 156: + case 174: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1048 +//line sql.y:1150 { yyVAL.LengthScaleOption = LengthScaleOption{} } - case 157: + case 175: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:1052 +//line sql.y:1154 { yyVAL.LengthScaleOption = LengthScaleOption{ Length: NewIntLiteral(yyDollar[2].bytes), Scale: NewIntLiteral(yyDollar[4].bytes), } } - case 158: + case 176: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1060 +//line sql.y:1162 { yyVAL.LengthScaleOption = LengthScaleOption{} } - case 159: + case 177: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1064 +//line sql.y:1166 { yyVAL.LengthScaleOption = LengthScaleOption{ Length: NewIntLiteral(yyDollar[2].bytes), } } - case 160: + case 178: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:1070 +//line sql.y:1172 { yyVAL.LengthScaleOption = LengthScaleOption{ Length: NewIntLiteral(yyDollar[2].bytes), Scale: NewIntLiteral(yyDollar[4].bytes), } } - case 161: + case 179: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1078 +//line sql.y:1180 { yyVAL.boolean = false } - case 162: + case 180: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1082 +//line sql.y:1184 { yyVAL.boolean = true } - case 163: + case 181: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1087 +//line sql.y:1189 { yyVAL.boolean = false } - case 164: + case 182: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1091 +//line sql.y:1193 { yyVAL.boolean = true } - case 165: + case 183: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1097 +//line sql.y:1199 { yyVAL.boolean = false } - case 166: + case 184: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1101 +//line sql.y:1203 { yyVAL.boolean = false } - case 167: + case 185: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1105 +//line sql.y:1207 { yyVAL.boolean = true } - case 168: + case 186: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1110 +//line sql.y:1212 { yyVAL.optVal = nil } - case 169: + case 187: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1114 +//line sql.y:1216 { yyVAL.optVal = yyDollar[2].expr } - case 170: + case 188: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1119 +//line sql.y:1221 { yyVAL.optVal = nil } - case 171: + case 189: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1123 +//line sql.y:1225 { yyVAL.optVal = yyDollar[3].expr } - case 172: + case 190: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1128 +//line sql.y:1230 { yyVAL.boolean = false } - case 173: + case 191: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1132 +//line sql.y:1234 { yyVAL.boolean = true } - case 174: + case 192: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1137 +//line sql.y:1239 { yyVAL.str = "" } - case 175: + case 193: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1141 +//line sql.y:1243 { yyVAL.str = string(yyDollar[3].colIdent.String()) } - case 176: + case 194: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1145 +//line sql.y:1247 { yyVAL.str = string(yyDollar[3].bytes) } - case 177: + case 195: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1150 +//line sql.y:1252 { yyVAL.str = "" } - case 178: + case 196: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1154 +//line sql.y:1256 { yyVAL.str = string(yyDollar[2].colIdent.String()) } - case 179: + case 197: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1158 +//line sql.y:1260 { yyVAL.str = string(yyDollar[2].bytes) } - case 180: + case 198: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1163 +//line sql.y:1265 { yyVAL.colKeyOpt = colKeyNone } - case 181: + case 199: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1167 +//line sql.y:1269 { yyVAL.colKeyOpt = colKeyPrimary } - case 182: + case 200: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1171 +//line sql.y:1273 { yyVAL.colKeyOpt = colKey } - case 183: + case 201: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1175 +//line sql.y:1277 { yyVAL.colKeyOpt = colKeyUniqueKey } - case 184: + case 202: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1179 +//line sql.y:1281 { yyVAL.colKeyOpt = colKeyUnique } - case 185: + case 203: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1184 +//line sql.y:1286 { yyVAL.literal = nil } - case 186: + case 204: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1188 +//line sql.y:1290 { yyVAL.literal = NewStrLiteral(yyDollar[2].bytes) } - case 187: + case 205: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:1194 +//line sql.y:1296 { yyVAL.indexDefinition = &IndexDefinition{Info: yyDollar[1].indexInfo, Columns: yyDollar[3].indexColumns, Options: yyDollar[5].indexOptions} } - case 188: - yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1198 + case 206: + yyDollar = yyS[yypt-0 : yypt+1] +//line sql.y:1301 { - yyVAL.indexDefinition = &IndexDefinition{Info: yyDollar[1].indexInfo, Columns: yyDollar[3].indexColumns} + yyVAL.indexOptions = nil } - case 189: + case 207: + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:1305 + { + yyVAL.indexOptions = yyDollar[1].indexOptions + } + case 208: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1204 +//line sql.y:1311 { yyVAL.indexOptions = []*IndexOption{yyDollar[1].indexOption} } - case 190: + case 209: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1208 +//line sql.y:1315 { yyVAL.indexOptions = append(yyVAL.indexOptions, yyDollar[2].indexOption) } - case 191: + case 210: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1214 +//line sql.y:1321 { - yyVAL.indexOption = &IndexOption{Name: string(yyDollar[1].bytes), Using: string(yyDollar[2].colIdent.String())} + yyVAL.indexOption = &IndexOption{Name: string(yyDollar[1].bytes), String: string(yyDollar[2].colIdent.String())} } - case 192: + case 211: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1218 +//line sql.y:1325 { // should not be string yyVAL.indexOption = &IndexOption{Name: string(yyDollar[1].bytes), Value: NewIntLiteral(yyDollar[3].bytes)} } - case 193: + case 212: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1223 +//line sql.y:1330 { yyVAL.indexOption = &IndexOption{Name: string(yyDollar[1].bytes), Value: NewStrLiteral(yyDollar[2].bytes)} } - case 194: + case 213: + yyDollar = yyS[yypt-3 : yypt+1] +//line sql.y:1334 + { + yyVAL.indexOption = &IndexOption{Name: string(yyDollar[1].bytes) + " " + string(yyDollar[2].bytes), Value: NewStrLiteral(yyDollar[3].bytes)} + } + case 214: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1229 +//line sql.y:1340 { yyVAL.str = "" } - case 195: + case 215: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1233 +//line sql.y:1344 { yyVAL.str = string(yyDollar[1].bytes) } - case 196: + case 216: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1239 +//line sql.y:1350 { yyVAL.indexInfo = &IndexInfo{Type: string(yyDollar[1].bytes) + " " + string(yyDollar[2].bytes), Name: NewColIdent("PRIMARY"), Primary: true, Unique: true} } - case 197: + case 217: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1243 +//line sql.y:1354 { yyVAL.indexInfo = &IndexInfo{Type: string(yyDollar[1].bytes) + " " + string(yyDollar[2].str), Name: NewColIdent(yyDollar[3].str), Spatial: true, Unique: false} } - case 198: + case 218: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1247 +//line sql.y:1358 { yyVAL.indexInfo = &IndexInfo{Type: string(yyDollar[1].bytes) + " " + string(yyDollar[2].str), Name: NewColIdent(yyDollar[3].str), Fulltext: true, Unique: false} } - case 199: + case 219: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1251 +//line sql.y:1362 { yyVAL.indexInfo = &IndexInfo{Type: string(yyDollar[1].bytes) + " " + string(yyDollar[2].str), Name: NewColIdent(yyDollar[3].str), Unique: true} } - case 200: + case 220: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1255 +//line sql.y:1366 { yyVAL.indexInfo = &IndexInfo{Type: string(yyDollar[1].bytes), Name: NewColIdent(yyDollar[2].str), Unique: true} } - case 201: + case 221: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1259 +//line sql.y:1370 { yyVAL.indexInfo = &IndexInfo{Type: string(yyDollar[1].str), Name: NewColIdent(yyDollar[2].str), Unique: false} } - case 202: + case 222: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1265 +//line sql.y:1376 { yyVAL.str = string(yyDollar[1].bytes) } - case 203: + case 223: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1269 +//line sql.y:1380 { yyVAL.str = string(yyDollar[1].bytes) } - case 204: + case 224: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1273 +//line sql.y:1384 { yyVAL.str = string(yyDollar[1].bytes) } - case 205: + case 225: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1280 +//line sql.y:1391 { yyVAL.str = string(yyDollar[1].bytes) } - case 206: + case 226: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1284 +//line sql.y:1395 { yyVAL.str = string(yyDollar[1].bytes) } - case 207: + case 227: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1290 +//line sql.y:1401 { yyVAL.str = string(yyDollar[1].bytes) } - case 208: + case 228: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1294 +//line sql.y:1405 { yyVAL.str = string(yyDollar[1].bytes) } - case 209: + case 229: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1299 +//line sql.y:1410 { yyVAL.str = "" } - case 210: + case 230: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1303 +//line sql.y:1414 { yyVAL.str = string(yyDollar[1].colIdent.String()) } - case 211: + case 231: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1309 +//line sql.y:1420 { yyVAL.indexColumns = []*IndexColumn{yyDollar[1].indexColumn} } - case 212: + case 232: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1313 +//line sql.y:1424 { yyVAL.indexColumns = append(yyVAL.indexColumns, yyDollar[3].indexColumn) } - case 213: - yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1319 + case 233: + yyDollar = yyS[yypt-3 : yypt+1] +//line sql.y:1430 { - yyVAL.indexColumn = &IndexColumn{Column: yyDollar[1].colIdent, Length: yyDollar[2].literal} + yyVAL.indexColumn = &IndexColumn{Column: yyDollar[1].colIdent, Length: yyDollar[2].literal, Direction: yyDollar[3].orderDirection} } - case 214: + case 234: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1325 +//line sql.y:1436 { yyVAL.constraintDefinition = &ConstraintDefinition{Name: string(yyDollar[2].colIdent.String()), Details: yyDollar[3].constraintInfo} } - case 215: + case 235: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1329 +//line sql.y:1440 { yyVAL.constraintDefinition = &ConstraintDefinition{Details: yyDollar[1].constraintInfo} } - case 216: + case 236: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1335 +//line sql.y:1446 { yyVAL.constraintDefinition = &ConstraintDefinition{Name: string(yyDollar[2].colIdent.String()), Details: yyDollar[3].constraintInfo} } - case 217: + case 237: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1339 +//line sql.y:1450 { yyVAL.constraintDefinition = &ConstraintDefinition{Details: yyDollar[1].constraintInfo} } - case 218: + case 238: yyDollar = yyS[yypt-10 : yypt+1] -//line sql.y:1345 +//line sql.y:1456 { yyVAL.constraintInfo = &ForeignKeyDefinition{Source: yyDollar[4].columns, ReferencedTable: yyDollar[7].tableName, ReferencedColumns: yyDollar[9].columns} } - case 219: + case 239: yyDollar = yyS[yypt-11 : yypt+1] -//line sql.y:1349 +//line sql.y:1460 { yyVAL.constraintInfo = &ForeignKeyDefinition{Source: yyDollar[4].columns, ReferencedTable: yyDollar[7].tableName, ReferencedColumns: yyDollar[9].columns, OnDelete: yyDollar[11].ReferenceAction} } - case 220: + case 240: yyDollar = yyS[yypt-11 : yypt+1] -//line sql.y:1353 +//line sql.y:1464 { yyVAL.constraintInfo = &ForeignKeyDefinition{Source: yyDollar[4].columns, ReferencedTable: yyDollar[7].tableName, ReferencedColumns: yyDollar[9].columns, OnUpdate: yyDollar[11].ReferenceAction} } - case 221: + case 241: yyDollar = yyS[yypt-12 : yypt+1] -//line sql.y:1357 +//line sql.y:1468 { yyVAL.constraintInfo = &ForeignKeyDefinition{Source: yyDollar[4].columns, ReferencedTable: yyDollar[7].tableName, ReferencedColumns: yyDollar[9].columns, OnDelete: yyDollar[11].ReferenceAction, OnUpdate: yyDollar[12].ReferenceAction} } - case 222: + case 242: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1361 +//line sql.y:1472 { yyVAL.constraintInfo = yyDollar[1].constraintInfo } - case 223: + case 243: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:1367 +//line sql.y:1478 { yyVAL.constraintInfo = &CheckConstraintDefinition{Expr: yyDollar[3].expr, Enforced: yyDollar[5].boolean} } - case 224: + case 244: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1373 +//line sql.y:1484 { yyVAL.ReferenceAction = yyDollar[3].ReferenceAction } - case 225: + case 245: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1379 +//line sql.y:1490 { yyVAL.ReferenceAction = yyDollar[3].ReferenceAction } - case 226: + case 246: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1385 +//line sql.y:1496 { yyVAL.ReferenceAction = Restrict } - case 227: + case 247: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1389 +//line sql.y:1500 { yyVAL.ReferenceAction = Cascade } - case 228: + case 248: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1393 +//line sql.y:1504 { yyVAL.ReferenceAction = NoAction } - case 229: + case 249: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1397 +//line sql.y:1508 { yyVAL.ReferenceAction = SetDefault } - case 230: + case 250: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1401 +//line sql.y:1512 { yyVAL.ReferenceAction = SetNull } - case 231: + case 251: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1406 +//line sql.y:1517 { yyVAL.boolean = true } - case 232: + case 252: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1410 +//line sql.y:1521 { yyVAL.boolean = true } - case 233: + case 253: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1414 +//line sql.y:1525 { yyVAL.boolean = false } - case 234: + case 254: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1419 +//line sql.y:1530 { yyVAL.str = "" } - case 235: + case 255: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1423 +//line sql.y:1534 { yyVAL.str = " " + string(yyDollar[1].str) } - case 236: + case 256: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1427 +//line sql.y:1538 { yyVAL.str = string(yyDollar[1].str) + ", " + string(yyDollar[3].str) } - case 237: + case 257: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1435 +//line sql.y:1546 { yyVAL.str = yyDollar[1].str } - case 238: + case 258: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1439 +//line sql.y:1550 { yyVAL.str = yyDollar[1].str + " " + yyDollar[2].str } - case 239: + case 259: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1443 +//line sql.y:1554 { yyVAL.str = yyDollar[1].str + "=" + yyDollar[3].str } - case 240: + case 260: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1449 +//line sql.y:1560 { yyVAL.str = yyDollar[1].colIdent.String() } - case 241: + case 261: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1453 +//line sql.y:1564 { yyVAL.str = "'" + string(yyDollar[1].bytes) + "'" } - case 242: + case 262: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1457 +//line sql.y:1568 { yyVAL.str = string(yyDollar[1].bytes) } - case 243: - yyDollar = yyS[yypt-6 : yypt+1] -//line sql.y:1463 + case 263: + yyDollar = yyS[yypt-5 : yypt+1] +//line sql.y:1574 { - yyVAL.statement = &DDL{Action: AlterDDLAction, OnlineHint: yyDollar[2].OnlineDDLHint, Table: yyDollar[4].tableName} + yyVAL.statement = &DDL{Action: AlterDDLAction, Table: yyDollar[3].tableName} } - case 244: - yyDollar = yyS[yypt-7 : yypt+1] -//line sql.y:1467 + case 264: + yyDollar = yyS[yypt-6 : yypt+1] +//line sql.y:1578 { - yyVAL.statement = &DDL{Action: AlterDDLAction, OnlineHint: yyDollar[2].OnlineDDLHint, Table: yyDollar[4].tableName} + yyVAL.statement = &DDL{Action: AlterDDLAction, Table: yyDollar[3].tableName} } - case 245: - yyDollar = yyS[yypt-7 : yypt+1] -//line sql.y:1471 + case 265: + yyDollar = yyS[yypt-6 : yypt+1] +//line sql.y:1582 { - yyVAL.statement = &DDL{Action: AlterDDLAction, OnlineHint: yyDollar[2].OnlineDDLHint, Table: yyDollar[4].tableName} + yyVAL.statement = &DDL{Action: AlterDDLAction, Table: yyDollar[3].tableName} } - case 246: - yyDollar = yyS[yypt-7 : yypt+1] -//line sql.y:1475 + case 266: + yyDollar = yyS[yypt-6 : yypt+1] +//line sql.y:1586 { // Change this to a rename statement - yyVAL.statement = &DDL{Action: RenameDDLAction, FromTables: TableNames{yyDollar[4].tableName}, ToTables: TableNames{yyDollar[7].tableName}} + yyVAL.statement = &DDL{Action: RenameDDLAction, FromTables: TableNames{yyDollar[3].tableName}, ToTables: TableNames{yyDollar[6].tableName}} } - case 247: - yyDollar = yyS[yypt-7 : yypt+1] -//line sql.y:1480 + case 267: + yyDollar = yyS[yypt-6 : yypt+1] +//line sql.y:1591 { // Rename an index can just be an alter - yyVAL.statement = &DDL{Action: AlterDDLAction, OnlineHint: yyDollar[2].OnlineDDLHint, Table: yyDollar[4].tableName} + yyVAL.statement = &DDL{Action: AlterDDLAction, Table: yyDollar[3].tableName} } - case 248: + case 268: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1485 +//line sql.y:1596 { yyVAL.statement = &DDL{Action: AlterDDLAction, Table: yyDollar[3].tableName.ToViewName()} } - case 249: - yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:1489 + case 269: + yyDollar = yyS[yypt-4 : yypt+1] +//line sql.y:1600 { - yyVAL.statement = &DDL{Action: AlterDDLAction, OnlineHint: yyDollar[2].OnlineDDLHint, Table: yyDollar[4].tableName, PartitionSpec: yyDollar[5].partSpec} + yyVAL.statement = &DDL{Action: AlterDDLAction, Table: yyDollar[3].tableName, PartitionSpec: yyDollar[4].partSpec} } - case 250: - yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1493 + case 270: + yyDollar = yyS[yypt-3 : yypt+1] +//line sql.y:1604 { - yyVAL.statement = &DBDDL{Action: AlterDBDDLAction, DBName: string(yyDollar[3].colIdent.String())} + yyDollar[1].alterDatabase.FullyParsed = true + yyDollar[1].alterDatabase.DBName = yyDollar[2].colIdent.String() + yyDollar[1].alterDatabase.AlterOptions = yyDollar[3].collateAndCharsets + yyVAL.statement = yyDollar[1].alterDatabase } - case 251: - yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1497 + case 271: + yyDollar = yyS[yypt-6 : yypt+1] +//line sql.y:1611 { - yyVAL.statement = &DBDDL{Action: AlterDBDDLAction, DBName: string(yyDollar[3].colIdent.String())} + yyDollar[1].alterDatabase.FullyParsed = true + yyDollar[1].alterDatabase.DBName = yyDollar[2].colIdent.String() + yyDollar[1].alterDatabase.UpdateDataDirectory = true + yyVAL.statement = yyDollar[1].alterDatabase } - case 252: + case 272: yyDollar = yyS[yypt-7 : yypt+1] -//line sql.y:1501 +//line sql.y:1618 { yyVAL.statement = &DDL{ Action: CreateVindexDDLAction, @@ -5509,9 +5680,9 @@ yydefault: }, } } - case 253: + case 273: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:1513 +//line sql.y:1630 { yyVAL.statement = &DDL{ Action: DropVindexDDLAction, @@ -5521,21 +5692,21 @@ yydefault: }, } } - case 254: + case 274: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:1523 +//line sql.y:1640 { yyVAL.statement = &DDL{Action: AddVschemaTableDDLAction, Table: yyDollar[5].tableName} } - case 255: + case 275: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:1527 +//line sql.y:1644 { yyVAL.statement = &DDL{Action: DropVschemaTableDDLAction, Table: yyDollar[5].tableName} } - case 256: + case 276: yyDollar = yyS[yypt-12 : yypt+1] -//line sql.y:1531 +//line sql.y:1648 { yyVAL.statement = &DDL{ Action: AddColVindexDDLAction, @@ -5548,9 +5719,9 @@ yydefault: VindexCols: yyDollar[9].columns, } } - case 257: + case 277: yyDollar = yyS[yypt-7 : yypt+1] -//line sql.y:1544 +//line sql.y:1661 { yyVAL.statement = &DDL{ Action: DropColVindexDDLAction, @@ -5560,15 +5731,15 @@ yydefault: }, } } - case 258: + case 278: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:1554 +//line sql.y:1671 { yyVAL.statement = &DDL{Action: AddSequenceDDLAction, Table: yyDollar[5].tableName} } - case 259: + case 279: yyDollar = yyS[yypt-9 : yypt+1] -//line sql.y:1558 +//line sql.y:1675 { yyVAL.statement = &DDL{ Action: AddAutoIncDDLAction, @@ -5579,228 +5750,228 @@ yydefault: }, } } - case 274: + case 294: yyDollar = yyS[yypt-7 : yypt+1] -//line sql.y:1587 +//line sql.y:1704 { yyVAL.partSpec = &PartitionSpec{Action: ReorganizeAction, Name: yyDollar[3].colIdent, Definitions: yyDollar[6].partDefs} } - case 275: + case 295: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1593 +//line sql.y:1710 { yyVAL.partDefs = []*PartitionDefinition{yyDollar[1].partDef} } - case 276: + case 296: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1597 +//line sql.y:1714 { yyVAL.partDefs = append(yyDollar[1].partDefs, yyDollar[3].partDef) } - case 277: + case 297: yyDollar = yyS[yypt-8 : yypt+1] -//line sql.y:1603 +//line sql.y:1720 { yyVAL.partDef = &PartitionDefinition{Name: yyDollar[2].colIdent, Limit: yyDollar[7].expr} } - case 278: + case 298: yyDollar = yyS[yypt-8 : yypt+1] -//line sql.y:1607 +//line sql.y:1724 { yyVAL.partDef = &PartitionDefinition{Name: yyDollar[2].colIdent, Maxvalue: true} } - case 279: + case 299: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1613 +//line sql.y:1730 { yyVAL.statement = yyDollar[3].ddl } - case 280: + case 300: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1619 +//line sql.y:1736 { yyVAL.ddl = &DDL{Action: RenameDDLAction, FromTables: TableNames{yyDollar[1].tableName}, ToTables: TableNames{yyDollar[3].tableName}} } - case 281: + case 301: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:1623 +//line sql.y:1740 { yyVAL.ddl = yyDollar[1].ddl yyVAL.ddl.FromTables = append(yyVAL.ddl.FromTables, yyDollar[3].tableName) yyVAL.ddl.ToTables = append(yyVAL.ddl.ToTables, yyDollar[5].tableName) } - case 282: + case 302: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1631 +//line sql.y:1748 { yyVAL.statement = &DDL{Action: DropDDLAction, FromTables: yyDollar[4].tableNames, IfExists: yyDollar[3].boolean} } - case 283: + case 303: yyDollar = yyS[yypt-6 : yypt+1] -//line sql.y:1635 +//line sql.y:1752 { // Change this to an alter statement yyVAL.statement = &DDL{Action: AlterDDLAction, Table: yyDollar[5].tableName} } - case 284: + case 304: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:1640 +//line sql.y:1757 { yyVAL.statement = &DDL{Action: DropDDLAction, FromTables: TableNames{yyDollar[4].tableName.ToViewName()}, IfExists: yyDollar[3].boolean} } - case 285: + case 305: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1644 +//line sql.y:1761 { yyVAL.statement = &DBDDL{Action: DropDBDDLAction, DBName: string(yyDollar[4].colIdent.String()), IfExists: yyDollar[3].boolean} } - case 286: + case 306: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1648 +//line sql.y:1765 { yyVAL.statement = &DBDDL{Action: DropDBDDLAction, DBName: string(yyDollar[4].colIdent.String()), IfExists: yyDollar[3].boolean} } - case 287: + case 307: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1654 +//line sql.y:1771 { yyVAL.statement = &DDL{Action: TruncateDDLAction, Table: yyDollar[3].tableName} } - case 288: + case 308: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1658 +//line sql.y:1775 { yyVAL.statement = &DDL{Action: TruncateDDLAction, Table: yyDollar[2].tableName} } - case 289: + case 309: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1663 +//line sql.y:1780 { yyVAL.statement = &OtherRead{} } - case 290: + case 310: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1669 +//line sql.y:1786 { yyVAL.statement = &Show{&ShowLegacy{Type: string(yyDollar[2].bytes) + " " + string(yyDollar[3].colIdent.String()), Scope: ImplicitScope}} } - case 291: + case 311: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1674 +//line sql.y:1791 { showTablesOpt := &ShowTablesOpt{Filter: yyDollar[4].showFilter} yyVAL.statement = &Show{&ShowLegacy{Type: CharsetStr, ShowTablesOpt: showTablesOpt, Scope: ImplicitScope}} } - case 292: + case 312: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1679 +//line sql.y:1796 { showTablesOpt := &ShowTablesOpt{Filter: yyDollar[3].showFilter} yyVAL.statement = &Show{&ShowLegacy{Type: string(yyDollar[2].bytes), ShowTablesOpt: showTablesOpt, Scope: ImplicitScope}} } - case 293: + case 313: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1684 +//line sql.y:1801 { yyVAL.statement = &Show{&ShowLegacy{Type: string(yyDollar[2].bytes) + " " + string(yyDollar[3].bytes), Scope: ImplicitScope}} } - case 294: + case 314: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1689 +//line sql.y:1806 { yyVAL.statement = &Show{&ShowLegacy{Type: string(yyDollar[2].bytes) + " " + string(yyDollar[3].colIdent.String()), Scope: ImplicitScope}} } - case 295: + case 315: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1693 +//line sql.y:1810 { yyVAL.statement = &Show{&ShowLegacy{Type: string(yyDollar[2].bytes) + " " + string(yyDollar[3].bytes), Scope: ImplicitScope}} } - case 296: + case 316: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1697 +//line sql.y:1814 { yyVAL.statement = &Show{&ShowLegacy{Type: string(yyDollar[2].bytes) + " " + string(yyDollar[3].bytes), Table: yyDollar[4].tableName, Scope: ImplicitScope}} } - case 297: + case 317: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1701 +//line sql.y:1818 { yyVAL.statement = &Show{&ShowLegacy{Type: string(yyDollar[2].bytes) + " " + string(yyDollar[3].bytes), Scope: ImplicitScope}} } - case 298: + case 318: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1705 +//line sql.y:1822 { yyVAL.statement = &Show{&ShowLegacy{Type: string(yyDollar[2].bytes) + " " + string(yyDollar[3].bytes), Scope: ImplicitScope}} } - case 299: + case 319: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1709 +//line sql.y:1826 { showTablesOpt := &ShowTablesOpt{Filter: yyDollar[3].showFilter} yyVAL.statement = &Show{&ShowLegacy{Type: string(yyDollar[2].bytes), ShowTablesOpt: showTablesOpt, Scope: ImplicitScope}} } - case 300: + case 320: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1714 +//line sql.y:1831 { showTablesOpt := &ShowTablesOpt{Filter: yyDollar[3].showFilter} yyVAL.statement = &Show{&ShowLegacy{Type: string(yyDollar[2].bytes), ShowTablesOpt: showTablesOpt, Scope: ImplicitScope}} } - case 301: + case 321: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1719 +//line sql.y:1836 { showTablesOpt := &ShowTablesOpt{Filter: yyDollar[3].showFilter} yyVAL.statement = &Show{&ShowLegacy{Type: string(yyDollar[2].bytes), ShowTablesOpt: showTablesOpt, Scope: ImplicitScope}} } - case 302: + case 322: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1724 +//line sql.y:1841 { yyVAL.statement = &Show{&ShowLegacy{Type: string(yyDollar[2].bytes), Scope: ImplicitScope}} } - case 303: + case 323: yyDollar = yyS[yypt-7 : yypt+1] -//line sql.y:1728 +//line sql.y:1845 { showTablesOpt := &ShowTablesOpt{DbName: yyDollar[6].str, Filter: yyDollar[7].showFilter} yyVAL.statement = &Show{&ShowLegacy{Extended: string(yyDollar[2].str), Type: string(yyDollar[3].str), ShowTablesOpt: showTablesOpt, OnTable: yyDollar[5].tableName, Scope: ImplicitScope}} } - case 304: + case 324: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1733 +//line sql.y:1850 { yyVAL.statement = &Show{&ShowLegacy{Type: string(yyDollar[2].bytes), Scope: ImplicitScope}} } - case 305: + case 325: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1737 +//line sql.y:1854 { yyVAL.statement = &Show{&ShowLegacy{Type: string(yyDollar[2].bytes), Scope: ImplicitScope}} } - case 306: + case 326: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1741 +//line sql.y:1858 { yyVAL.statement = &Show{&ShowLegacy{Scope: yyDollar[2].scope, Type: string(yyDollar[3].bytes)}} } - case 307: + case 327: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:1745 +//line sql.y:1862 { yyVAL.statement = &Show{&ShowTableStatus{DatabaseName: yyDollar[4].str, Filter: yyDollar[5].showFilter}} } - case 308: + case 328: yyDollar = yyS[yypt-7 : yypt+1] -//line sql.y:1749 +//line sql.y:1866 { yyVAL.statement = &Show{&ShowColumns{Full: yyDollar[2].str, Table: yyDollar[5].tableName, DbName: yyDollar[6].str, Filter: yyDollar[7].showFilter}} } - case 309: + case 329: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:1753 +//line sql.y:1870 { // this is ugly, but I couldn't find a better way for now if yyDollar[3].str == "processlist" { @@ -5810,866 +5981,866 @@ yydefault: yyVAL.statement = &Show{&ShowLegacy{Type: yyDollar[3].str, ShowTablesOpt: showTablesOpt, Scope: ImplicitScope}} } } - case 310: + case 330: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1763 +//line sql.y:1880 { yyVAL.statement = &Show{&ShowLegacy{Scope: yyDollar[2].scope, Type: string(yyDollar[3].bytes)}} } - case 311: + case 331: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1767 +//line sql.y:1884 { yyVAL.statement = &Show{&ShowLegacy{Type: string(yyDollar[2].bytes), Scope: ImplicitScope}} } - case 312: + case 332: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1771 +//line sql.y:1888 { yyVAL.statement = &Show{&ShowLegacy{Type: string(yyDollar[2].bytes), ShowCollationFilterOpt: yyDollar[4].expr, Scope: ImplicitScope}} } - case 313: + case 333: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1775 +//line sql.y:1892 { showTablesOpt := &ShowTablesOpt{Filter: yyDollar[4].showFilter} yyVAL.statement = &Show{&ShowLegacy{Scope: VitessMetadataScope, Type: string(yyDollar[3].bytes), ShowTablesOpt: showTablesOpt}} } - case 314: + case 334: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1780 +//line sql.y:1897 { yyVAL.statement = &Show{&ShowLegacy{Type: string(yyDollar[2].bytes) + " " + string(yyDollar[3].bytes), Scope: ImplicitScope}} } - case 315: + case 335: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1784 +//line sql.y:1901 { yyVAL.statement = &Show{&ShowLegacy{Type: string(yyDollar[2].bytes) + " " + string(yyDollar[3].bytes), Scope: ImplicitScope}} } - case 316: + case 336: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:1788 +//line sql.y:1905 { yyVAL.statement = &Show{&ShowLegacy{Type: string(yyDollar[2].bytes) + " " + string(yyDollar[3].bytes), OnTable: yyDollar[5].tableName, Scope: ImplicitScope}} } - case 317: + case 337: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1792 +//line sql.y:1909 { yyVAL.statement = &Show{&ShowLegacy{Type: string(yyDollar[2].bytes), Scope: ImplicitScope}} } - case 318: + case 338: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1797 +//line sql.y:1914 { // This should probably be a different type (ShowVitessTopoOpt), but // just getting the thing working for now showTablesOpt := &ShowTablesOpt{Filter: yyDollar[3].showFilter} yyVAL.statement = &Show{&ShowLegacy{Type: yyDollar[2].str, ShowTablesOpt: showTablesOpt}} } - case 319: + case 339: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1811 +//line sql.y:1928 { yyVAL.statement = &Show{&ShowLegacy{Type: string(yyDollar[2].colIdent.String()), Scope: ImplicitScope}} } - case 320: + case 340: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1817 +//line sql.y:1934 { yyVAL.str = string(yyDollar[1].bytes) } - case 321: + case 341: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1821 +//line sql.y:1938 { yyVAL.str = string(yyDollar[1].bytes) } - case 322: + case 342: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1827 +//line sql.y:1944 { yyVAL.str = string(yyDollar[1].bytes) } - case 323: + case 343: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1831 +//line sql.y:1948 { yyVAL.str = string(yyDollar[1].bytes) } - case 324: + case 344: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1837 +//line sql.y:1954 { yyVAL.str = "" } - case 325: + case 345: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1841 +//line sql.y:1958 { yyVAL.str = "extended " } - case 326: + case 346: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1847 +//line sql.y:1964 { yyVAL.str = "" } - case 327: + case 347: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1851 +//line sql.y:1968 { yyVAL.str = "full " } - case 328: + case 348: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1857 +//line sql.y:1974 { yyVAL.str = string(yyDollar[1].bytes) } - case 329: + case 349: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1861 +//line sql.y:1978 { yyVAL.str = string(yyDollar[1].bytes) } - case 330: + case 350: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1867 +//line sql.y:1984 { yyVAL.str = "" } - case 331: + case 351: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1871 +//line sql.y:1988 { yyVAL.str = yyDollar[2].tableIdent.v } - case 332: + case 352: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1875 +//line sql.y:1992 { yyVAL.str = yyDollar[2].tableIdent.v } - case 333: + case 353: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1881 +//line sql.y:1998 { yyVAL.showFilter = nil } - case 334: + case 354: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1885 +//line sql.y:2002 { yyVAL.showFilter = &ShowFilter{Like: string(yyDollar[2].bytes)} } - case 335: + case 355: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1889 +//line sql.y:2006 { yyVAL.showFilter = &ShowFilter{Filter: yyDollar[2].expr} } - case 336: + case 356: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1895 +//line sql.y:2012 { yyVAL.showFilter = nil } - case 337: + case 357: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1899 +//line sql.y:2016 { yyVAL.showFilter = &ShowFilter{Like: string(yyDollar[2].bytes)} } - case 338: + case 358: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1905 +//line sql.y:2022 { yyVAL.scope = ImplicitScope } - case 339: + case 359: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1909 +//line sql.y:2026 { yyVAL.scope = SessionScope } - case 340: + case 360: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1913 +//line sql.y:2030 { yyVAL.scope = GlobalScope } - case 341: + case 361: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1919 +//line sql.y:2036 { yyVAL.statement = &Use{DBName: yyDollar[2].tableIdent} } - case 342: + case 362: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1923 +//line sql.y:2040 { yyVAL.statement = &Use{DBName: TableIdent{v: ""}} } - case 343: + case 363: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1929 +//line sql.y:2046 { yyVAL.statement = &Begin{} } - case 344: + case 364: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1933 +//line sql.y:2050 { yyVAL.statement = &Begin{} } - case 345: + case 365: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1939 +//line sql.y:2056 { yyVAL.statement = &Commit{} } - case 346: + case 366: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1945 +//line sql.y:2062 { yyVAL.statement = &Rollback{} } - case 347: + case 367: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:1949 +//line sql.y:2066 { yyVAL.statement = &SRollback{Name: yyDollar[5].colIdent} } - case 348: + case 368: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1954 +//line sql.y:2071 { yyVAL.empty = struct{}{} } - case 349: + case 369: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1956 +//line sql.y:2073 { yyVAL.empty = struct{}{} } - case 350: + case 370: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1959 +//line sql.y:2076 { yyVAL.empty = struct{}{} } - case 351: + case 371: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1961 +//line sql.y:2078 { yyVAL.empty = struct{}{} } - case 352: + case 372: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1966 +//line sql.y:2083 { yyVAL.statement = &Savepoint{Name: yyDollar[2].colIdent} } - case 353: + case 373: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1972 +//line sql.y:2089 { yyVAL.statement = &Release{Name: yyDollar[3].colIdent} } - case 354: + case 374: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1977 +//line sql.y:2094 { yyVAL.explainType = EmptyType } - case 355: + case 375: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1981 +//line sql.y:2098 { yyVAL.explainType = JSONType } - case 356: + case 376: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1985 +//line sql.y:2102 { yyVAL.explainType = TreeType } - case 357: + case 377: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1989 +//line sql.y:2106 { yyVAL.explainType = VitessType } - case 358: + case 378: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1993 +//line sql.y:2110 { yyVAL.explainType = TraditionalType } - case 359: + case 379: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1997 +//line sql.y:2114 { yyVAL.explainType = AnalyzeType } - case 360: + case 380: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2003 +//line sql.y:2120 { yyVAL.bytes = yyDollar[1].bytes } - case 361: + case 381: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2007 +//line sql.y:2124 { yyVAL.bytes = yyDollar[1].bytes } - case 362: + case 382: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2011 +//line sql.y:2128 { yyVAL.bytes = yyDollar[1].bytes } - case 363: + case 383: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2017 +//line sql.y:2134 { yyVAL.statement = yyDollar[1].selStmt } - case 364: + case 384: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2021 +//line sql.y:2138 { yyVAL.statement = yyDollar[1].statement } - case 365: + case 385: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2025 +//line sql.y:2142 { yyVAL.statement = yyDollar[1].statement } - case 366: + case 386: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2029 +//line sql.y:2146 { yyVAL.statement = yyDollar[1].statement } - case 367: + case 387: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2034 +//line sql.y:2151 { yyVAL.str = "" } - case 368: + case 388: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2038 +//line sql.y:2155 { yyVAL.str = "" } - case 369: + case 389: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2042 +//line sql.y:2159 { yyVAL.str = "" } - case 370: + case 390: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2048 +//line sql.y:2165 { yyVAL.statement = &OtherRead{} } - case 371: + case 391: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2052 +//line sql.y:2169 { yyVAL.statement = &Explain{Type: yyDollar[2].explainType, Statement: yyDollar[3].statement} } - case 372: + case 392: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2058 +//line sql.y:2175 { yyVAL.statement = &OtherAdmin{} } - case 373: + case 393: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2062 +//line sql.y:2179 { yyVAL.statement = &OtherAdmin{} } - case 374: + case 394: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2066 +//line sql.y:2183 { yyVAL.statement = &OtherAdmin{} } - case 375: + case 395: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2070 +//line sql.y:2187 { yyVAL.statement = &OtherAdmin{} } - case 376: + case 396: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2076 +//line sql.y:2193 { yyVAL.statement = &DDL{Action: FlushDDLAction} } - case 377: + case 397: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2080 +//line sql.y:2197 { setAllowComments(yylex, true) } - case 378: + case 398: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2084 +//line sql.y:2201 { yyVAL.bytes2 = yyDollar[2].bytes2 setAllowComments(yylex, false) } - case 379: + case 399: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2090 +//line sql.y:2207 { yyVAL.bytes2 = nil } - case 380: + case 400: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2094 +//line sql.y:2211 { yyVAL.bytes2 = append(yyDollar[1].bytes2, yyDollar[2].bytes) } - case 381: + case 401: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2100 +//line sql.y:2217 { yyVAL.boolean = true } - case 382: + case 402: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2104 +//line sql.y:2221 { yyVAL.boolean = false } - case 383: + case 403: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2108 +//line sql.y:2225 { yyVAL.boolean = true } - case 384: + case 404: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2113 +//line sql.y:2230 { yyVAL.str = "" } - case 385: + case 405: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2117 +//line sql.y:2234 { yyVAL.str = SQLNoCacheStr } - case 386: + case 406: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2121 +//line sql.y:2238 { yyVAL.str = SQLCacheStr } - case 387: + case 407: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2126 +//line sql.y:2243 { yyVAL.boolean = false } - case 388: + case 408: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2130 +//line sql.y:2247 { yyVAL.boolean = true } - case 389: + case 409: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2134 +//line sql.y:2251 { yyVAL.boolean = true } - case 390: + case 410: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2139 +//line sql.y:2256 { yyVAL.selectExprs = nil } - case 391: + case 411: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2143 +//line sql.y:2260 { yyVAL.selectExprs = yyDollar[1].selectExprs } - case 392: + case 412: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2148 +//line sql.y:2265 { yyVAL.strs = nil } - case 393: + case 413: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2152 +//line sql.y:2269 { yyVAL.strs = []string{yyDollar[1].str} } - case 394: + case 414: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2156 +//line sql.y:2273 { // TODO: This is a hack since I couldn't get it to work in a nicer way. I got 'conflicts: 8 shift/reduce' yyVAL.strs = []string{yyDollar[1].str, yyDollar[2].str} } - case 395: + case 415: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2160 +//line sql.y:2277 { yyVAL.strs = []string{yyDollar[1].str, yyDollar[2].str, yyDollar[3].str} } - case 396: + case 416: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2164 +//line sql.y:2281 { yyVAL.strs = []string{yyDollar[1].str, yyDollar[2].str, yyDollar[3].str, yyDollar[4].str} } - case 397: + case 417: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2170 +//line sql.y:2287 { yyVAL.str = SQLNoCacheStr } - case 398: + case 418: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2174 +//line sql.y:2291 { yyVAL.str = SQLCacheStr } - case 399: + case 419: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2178 +//line sql.y:2295 { yyVAL.str = DistinctStr } - case 400: + case 420: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2182 +//line sql.y:2299 { yyVAL.str = DistinctStr } - case 401: + case 421: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2186 +//line sql.y:2303 { yyVAL.str = StraightJoinHint } - case 402: + case 422: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2190 +//line sql.y:2307 { yyVAL.str = SQLCalcFoundRowsStr } - case 403: + case 423: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2196 +//line sql.y:2313 { yyVAL.selectExprs = SelectExprs{yyDollar[1].selectExpr} } - case 404: + case 424: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2200 +//line sql.y:2317 { yyVAL.selectExprs = append(yyVAL.selectExprs, yyDollar[3].selectExpr) } - case 405: + case 425: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2206 +//line sql.y:2323 { yyVAL.selectExpr = &StarExpr{} } - case 406: + case 426: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2210 +//line sql.y:2327 { yyVAL.selectExpr = &AliasedExpr{Expr: yyDollar[1].expr, As: yyDollar[2].colIdent} } - case 407: + case 427: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2214 +//line sql.y:2331 { yyVAL.selectExpr = &StarExpr{TableName: TableName{Name: yyDollar[1].tableIdent}} } - case 408: + case 428: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:2218 +//line sql.y:2335 { yyVAL.selectExpr = &StarExpr{TableName: TableName{Qualifier: yyDollar[1].tableIdent, Name: yyDollar[3].tableIdent}} } - case 409: + case 429: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2223 +//line sql.y:2340 { yyVAL.colIdent = ColIdent{} } - case 410: + case 430: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2227 +//line sql.y:2344 { yyVAL.colIdent = yyDollar[1].colIdent } - case 411: + case 431: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2231 +//line sql.y:2348 { yyVAL.colIdent = yyDollar[2].colIdent } - case 413: + case 433: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2238 +//line sql.y:2355 { yyVAL.colIdent = NewColIdent(string(yyDollar[1].bytes)) } - case 414: + case 434: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2243 +//line sql.y:2360 { yyVAL.tableExprs = TableExprs{&AliasedTableExpr{Expr: TableName{Name: NewTableIdent("dual")}}} } - case 415: + case 435: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2247 +//line sql.y:2364 { yyVAL.tableExprs = yyDollar[2].tableExprs } - case 416: + case 436: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2253 +//line sql.y:2370 { yyVAL.tableExprs = TableExprs{yyDollar[1].tableExpr} } - case 417: + case 437: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2257 +//line sql.y:2374 { yyVAL.tableExprs = append(yyVAL.tableExprs, yyDollar[3].tableExpr) } - case 420: + case 440: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2267 +//line sql.y:2384 { yyVAL.tableExpr = yyDollar[1].aliasedTableName } - case 421: + case 441: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2271 +//line sql.y:2388 { - yyVAL.tableExpr = &AliasedTableExpr{Expr: yyDollar[1].subquery, As: yyDollar[3].tableIdent} + yyVAL.tableExpr = &AliasedTableExpr{Expr: yyDollar[1].derivedTable, As: yyDollar[3].tableIdent} } - case 422: + case 442: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2275 +//line sql.y:2392 { yyVAL.tableExpr = &ParenTableExpr{Exprs: yyDollar[2].tableExprs} } - case 423: + case 443: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2281 +//line sql.y:2398 { - yyVAL.subquery = &Subquery{yyDollar[2].selStmt} + yyVAL.derivedTable = &DerivedTable{yyDollar[2].selStmt} } - case 424: + case 444: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2287 +//line sql.y:2404 { yyVAL.aliasedTableName = &AliasedTableExpr{Expr: yyDollar[1].tableName, As: yyDollar[2].tableIdent, Hints: yyDollar[3].indexHints} } - case 425: + case 445: yyDollar = yyS[yypt-7 : yypt+1] -//line sql.y:2291 +//line sql.y:2408 { yyVAL.aliasedTableName = &AliasedTableExpr{Expr: yyDollar[1].tableName, Partitions: yyDollar[4].partitions, As: yyDollar[6].tableIdent, Hints: yyDollar[7].indexHints} } - case 426: + case 446: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2297 +//line sql.y:2414 { yyVAL.columns = Columns{yyDollar[1].colIdent} } - case 427: + case 447: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2301 +//line sql.y:2418 { yyVAL.columns = append(yyVAL.columns, yyDollar[3].colIdent) } - case 428: + case 448: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2307 +//line sql.y:2424 { yyVAL.partitions = Partitions{yyDollar[1].colIdent} } - case 429: + case 449: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2311 +//line sql.y:2428 { yyVAL.partitions = append(yyVAL.partitions, yyDollar[3].colIdent) } - case 430: + case 450: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2324 +//line sql.y:2441 { yyVAL.tableExpr = &JoinTableExpr{LeftExpr: yyDollar[1].tableExpr, Join: yyDollar[2].joinType, RightExpr: yyDollar[3].tableExpr, Condition: yyDollar[4].joinCondition} } - case 431: + case 451: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2328 +//line sql.y:2445 { yyVAL.tableExpr = &JoinTableExpr{LeftExpr: yyDollar[1].tableExpr, Join: yyDollar[2].joinType, RightExpr: yyDollar[3].tableExpr, Condition: yyDollar[4].joinCondition} } - case 432: + case 452: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2332 +//line sql.y:2449 { yyVAL.tableExpr = &JoinTableExpr{LeftExpr: yyDollar[1].tableExpr, Join: yyDollar[2].joinType, RightExpr: yyDollar[3].tableExpr, Condition: yyDollar[4].joinCondition} } - case 433: + case 453: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2336 +//line sql.y:2453 { yyVAL.tableExpr = &JoinTableExpr{LeftExpr: yyDollar[1].tableExpr, Join: yyDollar[2].joinType, RightExpr: yyDollar[3].tableExpr} } - case 434: + case 454: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2342 +//line sql.y:2459 { yyVAL.joinCondition = JoinCondition{On: yyDollar[2].expr} } - case 435: + case 455: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2344 +//line sql.y:2461 { yyVAL.joinCondition = JoinCondition{Using: yyDollar[3].columns} } - case 436: + case 456: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2348 +//line sql.y:2465 { yyVAL.joinCondition = JoinCondition{} } - case 437: + case 457: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2350 +//line sql.y:2467 { yyVAL.joinCondition = yyDollar[1].joinCondition } - case 438: + case 458: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2354 +//line sql.y:2471 { yyVAL.joinCondition = JoinCondition{} } - case 439: + case 459: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2356 +//line sql.y:2473 { yyVAL.joinCondition = JoinCondition{On: yyDollar[2].expr} } - case 440: + case 460: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2359 +//line sql.y:2476 { yyVAL.empty = struct{}{} } - case 441: + case 461: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2361 +//line sql.y:2478 { yyVAL.empty = struct{}{} } - case 442: + case 462: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2364 +//line sql.y:2481 { yyVAL.tableIdent = NewTableIdent("") } - case 443: + case 463: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2368 +//line sql.y:2485 { yyVAL.tableIdent = yyDollar[1].tableIdent } - case 444: + case 464: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2372 +//line sql.y:2489 { yyVAL.tableIdent = yyDollar[2].tableIdent } - case 446: + case 466: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2379 +//line sql.y:2496 { yyVAL.tableIdent = NewTableIdent(string(yyDollar[1].bytes)) } - case 447: + case 467: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2385 +//line sql.y:2502 { yyVAL.joinType = NormalJoinType } - case 448: + case 468: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2389 +//line sql.y:2506 { yyVAL.joinType = NormalJoinType } - case 449: + case 469: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2393 +//line sql.y:2510 { yyVAL.joinType = NormalJoinType } - case 450: + case 470: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2399 +//line sql.y:2516 { yyVAL.joinType = StraightJoinType } - case 451: + case 471: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2405 +//line sql.y:2522 { yyVAL.joinType = LeftJoinType } - case 452: + case 472: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2409 +//line sql.y:2526 { yyVAL.joinType = LeftJoinType } - case 453: + case 473: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2413 +//line sql.y:2530 { yyVAL.joinType = RightJoinType } - case 454: + case 474: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2417 +//line sql.y:2534 { yyVAL.joinType = RightJoinType } - case 455: + case 475: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2423 +//line sql.y:2540 { yyVAL.joinType = NaturalJoinType } - case 456: + case 476: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2427 +//line sql.y:2544 { if yyDollar[2].joinType == LeftJoinType { yyVAL.joinType = NaturalLeftJoinType @@ -6677,489 +6848,489 @@ yydefault: yyVAL.joinType = NaturalRightJoinType } } - case 457: + case 477: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2437 +//line sql.y:2554 { yyVAL.tableName = yyDollar[2].tableName } - case 458: + case 478: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2441 +//line sql.y:2558 { yyVAL.tableName = yyDollar[1].tableName } - case 459: + case 479: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2447 +//line sql.y:2564 { yyVAL.tableName = TableName{Name: yyDollar[1].tableIdent} } - case 460: + case 480: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2451 +//line sql.y:2568 { yyVAL.tableName = TableName{Qualifier: yyDollar[1].tableIdent, Name: yyDollar[3].tableIdent} } - case 461: + case 481: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2457 +//line sql.y:2574 { yyVAL.tableName = TableName{Name: yyDollar[1].tableIdent} } - case 462: + case 482: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2462 +//line sql.y:2579 { yyVAL.indexHints = nil } - case 463: + case 483: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:2466 +//line sql.y:2583 { yyVAL.indexHints = &IndexHints{Type: UseOp, Indexes: yyDollar[4].columns} } - case 464: + case 484: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2470 +//line sql.y:2587 { yyVAL.indexHints = &IndexHints{Type: UseOp} } - case 465: + case 485: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:2474 +//line sql.y:2591 { yyVAL.indexHints = &IndexHints{Type: IgnoreOp, Indexes: yyDollar[4].columns} } - case 466: + case 486: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:2478 +//line sql.y:2595 { yyVAL.indexHints = &IndexHints{Type: ForceOp, Indexes: yyDollar[4].columns} } - case 467: + case 487: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2483 +//line sql.y:2600 { yyVAL.expr = nil } - case 468: + case 488: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2487 +//line sql.y:2604 { yyVAL.expr = yyDollar[2].expr } - case 469: + case 489: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2493 +//line sql.y:2610 { yyVAL.expr = yyDollar[1].expr } - case 470: + case 490: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2497 +//line sql.y:2614 { yyVAL.expr = &AndExpr{Left: yyDollar[1].expr, Right: yyDollar[3].expr} } - case 471: + case 491: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2501 +//line sql.y:2618 { yyVAL.expr = &OrExpr{Left: yyDollar[1].expr, Right: yyDollar[3].expr} } - case 472: + case 492: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2505 +//line sql.y:2622 { yyVAL.expr = &XorExpr{Left: yyDollar[1].expr, Right: yyDollar[3].expr} } - case 473: + case 493: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2509 +//line sql.y:2626 { yyVAL.expr = &NotExpr{Expr: yyDollar[2].expr} } - case 474: + case 494: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2513 +//line sql.y:2630 { yyVAL.expr = &IsExpr{Operator: yyDollar[3].isExprOperator, Expr: yyDollar[1].expr} } - case 475: + case 495: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2517 +//line sql.y:2634 { yyVAL.expr = yyDollar[1].expr } - case 476: + case 496: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2521 +//line sql.y:2638 { yyVAL.expr = &Default{ColName: yyDollar[2].str} } - case 477: + case 497: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2527 +//line sql.y:2644 { yyVAL.str = "" } - case 478: + case 498: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2531 +//line sql.y:2648 { yyVAL.str = string(yyDollar[2].colIdent.String()) } - case 479: + case 499: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2537 +//line sql.y:2654 { yyVAL.boolVal = BoolVal(true) } - case 480: + case 500: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2541 +//line sql.y:2658 { yyVAL.boolVal = BoolVal(false) } - case 481: + case 501: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2547 +//line sql.y:2664 { yyVAL.expr = &ComparisonExpr{Left: yyDollar[1].expr, Operator: yyDollar[2].comparisonExprOperator, Right: yyDollar[3].expr} } - case 482: + case 502: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2551 +//line sql.y:2668 { yyVAL.expr = &ComparisonExpr{Left: yyDollar[1].expr, Operator: InOp, Right: yyDollar[3].colTuple} } - case 483: + case 503: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2555 +//line sql.y:2672 { yyVAL.expr = &ComparisonExpr{Left: yyDollar[1].expr, Operator: NotInOp, Right: yyDollar[4].colTuple} } - case 484: + case 504: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2559 +//line sql.y:2676 { yyVAL.expr = &ComparisonExpr{Left: yyDollar[1].expr, Operator: LikeOp, Right: yyDollar[3].expr, Escape: yyDollar[4].expr} } - case 485: + case 505: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:2563 +//line sql.y:2680 { yyVAL.expr = &ComparisonExpr{Left: yyDollar[1].expr, Operator: NotLikeOp, Right: yyDollar[4].expr, Escape: yyDollar[5].expr} } - case 486: + case 506: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2567 +//line sql.y:2684 { yyVAL.expr = &ComparisonExpr{Left: yyDollar[1].expr, Operator: RegexpOp, Right: yyDollar[3].expr} } - case 487: + case 507: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2571 +//line sql.y:2688 { yyVAL.expr = &ComparisonExpr{Left: yyDollar[1].expr, Operator: NotRegexpOp, Right: yyDollar[4].expr} } - case 488: + case 508: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:2575 +//line sql.y:2692 { yyVAL.expr = &RangeCond{Left: yyDollar[1].expr, Operator: BetweenOp, From: yyDollar[3].expr, To: yyDollar[5].expr} } - case 489: + case 509: yyDollar = yyS[yypt-6 : yypt+1] -//line sql.y:2579 +//line sql.y:2696 { yyVAL.expr = &RangeCond{Left: yyDollar[1].expr, Operator: NotBetweenOp, From: yyDollar[4].expr, To: yyDollar[6].expr} } - case 490: + case 510: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2583 +//line sql.y:2700 { yyVAL.expr = &ExistsExpr{Subquery: yyDollar[2].subquery} } - case 491: + case 511: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2589 +//line sql.y:2706 { yyVAL.isExprOperator = IsNullOp } - case 492: + case 512: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2593 +//line sql.y:2710 { yyVAL.isExprOperator = IsNotNullOp } - case 493: + case 513: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2597 +//line sql.y:2714 { yyVAL.isExprOperator = IsTrueOp } - case 494: + case 514: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2601 +//line sql.y:2718 { yyVAL.isExprOperator = IsNotTrueOp } - case 495: + case 515: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2605 +//line sql.y:2722 { yyVAL.isExprOperator = IsFalseOp } - case 496: + case 516: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2609 +//line sql.y:2726 { yyVAL.isExprOperator = IsNotFalseOp } - case 497: + case 517: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2615 +//line sql.y:2732 { yyVAL.comparisonExprOperator = EqualOp } - case 498: + case 518: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2619 +//line sql.y:2736 { yyVAL.comparisonExprOperator = LessThanOp } - case 499: + case 519: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2623 +//line sql.y:2740 { yyVAL.comparisonExprOperator = GreaterThanOp } - case 500: + case 520: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2627 +//line sql.y:2744 { yyVAL.comparisonExprOperator = LessEqualOp } - case 501: + case 521: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2631 +//line sql.y:2748 { yyVAL.comparisonExprOperator = GreaterEqualOp } - case 502: + case 522: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2635 +//line sql.y:2752 { yyVAL.comparisonExprOperator = NotEqualOp } - case 503: + case 523: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2639 +//line sql.y:2756 { yyVAL.comparisonExprOperator = NullSafeEqualOp } - case 504: + case 524: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2644 +//line sql.y:2761 { yyVAL.expr = nil } - case 505: + case 525: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2648 +//line sql.y:2765 { yyVAL.expr = yyDollar[2].expr } - case 506: + case 526: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2654 +//line sql.y:2771 { yyVAL.colTuple = yyDollar[1].valTuple } - case 507: + case 527: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2658 +//line sql.y:2775 { yyVAL.colTuple = yyDollar[1].subquery } - case 508: + case 528: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2662 +//line sql.y:2779 { yyVAL.colTuple = ListArg(yyDollar[1].bytes) } - case 509: + case 529: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2668 +//line sql.y:2785 { yyVAL.subquery = &Subquery{yyDollar[2].selStmt} } - case 510: + case 530: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2674 +//line sql.y:2791 { yyVAL.exprs = Exprs{yyDollar[1].expr} } - case 511: + case 531: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2678 +//line sql.y:2795 { yyVAL.exprs = append(yyDollar[1].exprs, yyDollar[3].expr) } - case 512: + case 532: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2684 +//line sql.y:2801 { yyVAL.expr = yyDollar[1].expr } - case 513: + case 533: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2688 +//line sql.y:2805 { yyVAL.expr = yyDollar[1].boolVal } - case 514: + case 534: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2692 +//line sql.y:2809 { yyVAL.expr = yyDollar[1].colName } - case 515: + case 535: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2696 +//line sql.y:2813 { yyVAL.expr = yyDollar[1].expr } - case 516: + case 536: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2700 +//line sql.y:2817 { yyVAL.expr = yyDollar[1].subquery } - case 517: + case 537: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2704 +//line sql.y:2821 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: BitAndOp, Right: yyDollar[3].expr} } - case 518: + case 538: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2708 +//line sql.y:2825 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: BitOrOp, Right: yyDollar[3].expr} } - case 519: + case 539: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2712 +//line sql.y:2829 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: BitXorOp, Right: yyDollar[3].expr} } - case 520: + case 540: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2716 +//line sql.y:2833 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: PlusOp, Right: yyDollar[3].expr} } - case 521: + case 541: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2720 +//line sql.y:2837 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: MinusOp, Right: yyDollar[3].expr} } - case 522: + case 542: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2724 +//line sql.y:2841 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: MultOp, Right: yyDollar[3].expr} } - case 523: + case 543: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2728 +//line sql.y:2845 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: DivOp, Right: yyDollar[3].expr} } - case 524: + case 544: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2732 +//line sql.y:2849 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: IntDivOp, Right: yyDollar[3].expr} } - case 525: + case 545: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2736 +//line sql.y:2853 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: ModOp, Right: yyDollar[3].expr} } - case 526: + case 546: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2740 +//line sql.y:2857 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: ModOp, Right: yyDollar[3].expr} } - case 527: + case 547: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2744 +//line sql.y:2861 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: ShiftLeftOp, Right: yyDollar[3].expr} } - case 528: + case 548: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2748 +//line sql.y:2865 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: ShiftRightOp, Right: yyDollar[3].expr} } - case 529: + case 549: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2752 +//line sql.y:2869 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].colName, Operator: JSONExtractOp, Right: yyDollar[3].expr} } - case 530: + case 550: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2756 +//line sql.y:2873 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].colName, Operator: JSONUnquoteExtractOp, Right: yyDollar[3].expr} } - case 531: + case 551: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2760 +//line sql.y:2877 { yyVAL.expr = &CollateExpr{Expr: yyDollar[1].expr, Charset: yyDollar[3].str} } - case 532: + case 552: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2764 +//line sql.y:2881 { yyVAL.expr = &UnaryExpr{Operator: BinaryOp, Expr: yyDollar[2].expr} } - case 533: + case 553: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2768 +//line sql.y:2885 { yyVAL.expr = &UnaryExpr{Operator: UBinaryOp, Expr: yyDollar[2].expr} } - case 534: + case 554: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2772 +//line sql.y:2889 { yyVAL.expr = &UnaryExpr{Operator: Utf8Op, Expr: yyDollar[2].expr} } - case 535: + case 555: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2776 +//line sql.y:2893 { yyVAL.expr = &UnaryExpr{Operator: Utf8mb4Op, Expr: yyDollar[2].expr} } - case 536: + case 556: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2780 +//line sql.y:2897 { yyVAL.expr = &UnaryExpr{Operator: Latin1Op, Expr: yyDollar[2].expr} } - case 537: + case 557: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2784 +//line sql.y:2901 { if num, ok := yyDollar[2].expr.(*Literal); ok && num.Type == IntVal { yyVAL.expr = num @@ -7167,9 +7338,9 @@ yydefault: yyVAL.expr = &UnaryExpr{Operator: UPlusOp, Expr: yyDollar[2].expr} } } - case 538: + case 558: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2792 +//line sql.y:2909 { if num, ok := yyDollar[2].expr.(*Literal); ok && num.Type == IntVal { // Handle double negative @@ -7183,21 +7354,21 @@ yydefault: yyVAL.expr = &UnaryExpr{Operator: UMinusOp, Expr: yyDollar[2].expr} } } - case 539: + case 559: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2806 +//line sql.y:2923 { yyVAL.expr = &UnaryExpr{Operator: TildaOp, Expr: yyDollar[2].expr} } - case 540: + case 560: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2810 +//line sql.y:2927 { yyVAL.expr = &UnaryExpr{Operator: BangOp, Expr: yyDollar[2].expr} } - case 541: + case 561: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2814 +//line sql.y:2931 { // This rule prevents the usage of INTERVAL // as a function. If support is needed for that, @@ -7205,497 +7376,497 @@ yydefault: // will be non-trivial because of grammar conflicts. yyVAL.expr = &IntervalExpr{Expr: yyDollar[2].expr, Unit: yyDollar[3].colIdent.String()} } - case 546: + case 566: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2832 +//line sql.y:2949 { yyVAL.expr = &FuncExpr{Name: yyDollar[1].colIdent, Exprs: yyDollar[3].selectExprs} } - case 547: + case 567: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:2836 +//line sql.y:2953 { yyVAL.expr = &FuncExpr{Name: yyDollar[1].colIdent, Distinct: true, Exprs: yyDollar[4].selectExprs} } - case 548: + case 568: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:2840 +//line sql.y:2957 { yyVAL.expr = &FuncExpr{Name: yyDollar[1].colIdent, Distinct: true, Exprs: yyDollar[4].selectExprs} } - case 549: + case 569: yyDollar = yyS[yypt-6 : yypt+1] -//line sql.y:2844 +//line sql.y:2961 { yyVAL.expr = &FuncExpr{Qualifier: yyDollar[1].tableIdent, Name: yyDollar[3].colIdent, Exprs: yyDollar[5].selectExprs} } - case 550: + case 570: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2854 +//line sql.y:2971 { yyVAL.expr = &FuncExpr{Name: NewColIdent("left"), Exprs: yyDollar[3].selectExprs} } - case 551: + case 571: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2858 +//line sql.y:2975 { yyVAL.expr = &FuncExpr{Name: NewColIdent("right"), Exprs: yyDollar[3].selectExprs} } - case 552: + case 572: yyDollar = yyS[yypt-6 : yypt+1] -//line sql.y:2862 +//line sql.y:2979 { yyVAL.expr = &ConvertExpr{Expr: yyDollar[3].expr, Type: yyDollar[5].convertType} } - case 553: + case 573: yyDollar = yyS[yypt-6 : yypt+1] -//line sql.y:2866 +//line sql.y:2983 { yyVAL.expr = &ConvertExpr{Expr: yyDollar[3].expr, Type: yyDollar[5].convertType} } - case 554: + case 574: yyDollar = yyS[yypt-6 : yypt+1] -//line sql.y:2870 +//line sql.y:2987 { yyVAL.expr = &ConvertUsingExpr{Expr: yyDollar[3].expr, Type: yyDollar[5].str} } - case 555: + case 575: yyDollar = yyS[yypt-8 : yypt+1] -//line sql.y:2874 +//line sql.y:2991 { yyVAL.expr = &SubstrExpr{Name: yyDollar[3].colName, From: yyDollar[5].expr, To: yyDollar[7].expr} } - case 556: + case 576: yyDollar = yyS[yypt-8 : yypt+1] -//line sql.y:2878 +//line sql.y:2995 { yyVAL.expr = &SubstrExpr{Name: yyDollar[3].colName, From: yyDollar[5].expr, To: yyDollar[7].expr} } - case 557: + case 577: yyDollar = yyS[yypt-8 : yypt+1] -//line sql.y:2882 +//line sql.y:2999 { yyVAL.expr = &SubstrExpr{StrVal: NewStrLiteral(yyDollar[3].bytes), From: yyDollar[5].expr, To: yyDollar[7].expr} } - case 558: + case 578: yyDollar = yyS[yypt-8 : yypt+1] -//line sql.y:2886 +//line sql.y:3003 { yyVAL.expr = &SubstrExpr{StrVal: NewStrLiteral(yyDollar[3].bytes), From: yyDollar[5].expr, To: yyDollar[7].expr} } - case 559: + case 579: yyDollar = yyS[yypt-9 : yypt+1] -//line sql.y:2890 +//line sql.y:3007 { yyVAL.expr = &MatchExpr{Columns: yyDollar[3].selectExprs, Expr: yyDollar[7].expr, Option: yyDollar[8].matchExprOption} } - case 560: + case 580: yyDollar = yyS[yypt-8 : yypt+1] -//line sql.y:2894 +//line sql.y:3011 { yyVAL.expr = &GroupConcatExpr{Distinct: yyDollar[3].boolean, Exprs: yyDollar[4].selectExprs, OrderBy: yyDollar[5].orderBy, Separator: yyDollar[6].str, Limit: yyDollar[7].limit} } - case 561: + case 581: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:2898 +//line sql.y:3015 { yyVAL.expr = &CaseExpr{Expr: yyDollar[2].expr, Whens: yyDollar[3].whens, Else: yyDollar[4].expr} } - case 562: + case 582: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2902 +//line sql.y:3019 { yyVAL.expr = &ValuesFuncExpr{Name: yyDollar[3].colName} } - case 563: + case 583: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2912 +//line sql.y:3029 { yyVAL.expr = &FuncExpr{Name: NewColIdent("current_timestamp")} } - case 564: + case 584: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2916 +//line sql.y:3033 { yyVAL.expr = &FuncExpr{Name: NewColIdent("utc_timestamp")} } - case 565: + case 585: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2920 +//line sql.y:3037 { yyVAL.expr = &FuncExpr{Name: NewColIdent("utc_time")} } - case 566: + case 586: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2925 +//line sql.y:3042 { yyVAL.expr = &FuncExpr{Name: NewColIdent("utc_date")} } - case 567: + case 587: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2930 +//line sql.y:3047 { yyVAL.expr = &FuncExpr{Name: NewColIdent("localtime")} } - case 568: + case 588: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2935 +//line sql.y:3052 { yyVAL.expr = &FuncExpr{Name: NewColIdent("localtimestamp")} } - case 569: + case 589: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2941 +//line sql.y:3058 { yyVAL.expr = &FuncExpr{Name: NewColIdent("current_date")} } - case 570: + case 590: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2946 +//line sql.y:3063 { yyVAL.expr = &FuncExpr{Name: NewColIdent("current_time")} } - case 571: + case 591: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2951 +//line sql.y:3068 { yyVAL.expr = &CurTimeFuncExpr{Name: NewColIdent("current_timestamp"), Fsp: yyDollar[2].expr} } - case 572: + case 592: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2955 +//line sql.y:3072 { yyVAL.expr = &CurTimeFuncExpr{Name: NewColIdent("utc_timestamp"), Fsp: yyDollar[2].expr} } - case 573: + case 593: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2959 +//line sql.y:3076 { yyVAL.expr = &CurTimeFuncExpr{Name: NewColIdent("utc_time"), Fsp: yyDollar[2].expr} } - case 574: + case 594: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2964 +//line sql.y:3081 { yyVAL.expr = &CurTimeFuncExpr{Name: NewColIdent("localtime"), Fsp: yyDollar[2].expr} } - case 575: + case 595: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2969 +//line sql.y:3086 { yyVAL.expr = &CurTimeFuncExpr{Name: NewColIdent("localtimestamp"), Fsp: yyDollar[2].expr} } - case 576: + case 596: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2974 +//line sql.y:3091 { yyVAL.expr = &CurTimeFuncExpr{Name: NewColIdent("current_time"), Fsp: yyDollar[2].expr} } - case 577: + case 597: yyDollar = yyS[yypt-8 : yypt+1] -//line sql.y:2978 +//line sql.y:3095 { yyVAL.expr = &TimestampFuncExpr{Name: string("timestampadd"), Unit: yyDollar[3].colIdent.String(), Expr1: yyDollar[5].expr, Expr2: yyDollar[7].expr} } - case 578: + case 598: yyDollar = yyS[yypt-8 : yypt+1] -//line sql.y:2982 +//line sql.y:3099 { yyVAL.expr = &TimestampFuncExpr{Name: string("timestampdiff"), Unit: yyDollar[3].colIdent.String(), Expr1: yyDollar[5].expr, Expr2: yyDollar[7].expr} } - case 581: + case 601: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2992 +//line sql.y:3109 { yyVAL.expr = yyDollar[2].expr } - case 582: + case 602: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:3002 +//line sql.y:3119 { yyVAL.expr = &FuncExpr{Name: NewColIdent("if"), Exprs: yyDollar[3].selectExprs} } - case 583: + case 603: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:3006 +//line sql.y:3123 { yyVAL.expr = &FuncExpr{Name: NewColIdent("database"), Exprs: yyDollar[3].selectExprs} } - case 584: + case 604: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:3010 +//line sql.y:3127 { yyVAL.expr = &FuncExpr{Name: NewColIdent("schema"), Exprs: yyDollar[3].selectExprs} } - case 585: + case 605: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:3014 +//line sql.y:3131 { yyVAL.expr = &FuncExpr{Name: NewColIdent("mod"), Exprs: yyDollar[3].selectExprs} } - case 586: + case 606: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:3018 +//line sql.y:3135 { yyVAL.expr = &FuncExpr{Name: NewColIdent("replace"), Exprs: yyDollar[3].selectExprs} } - case 587: + case 607: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:3022 +//line sql.y:3139 { yyVAL.expr = &FuncExpr{Name: NewColIdent("substr"), Exprs: yyDollar[3].selectExprs} } - case 588: + case 608: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:3026 +//line sql.y:3143 { yyVAL.expr = &FuncExpr{Name: NewColIdent("substr"), Exprs: yyDollar[3].selectExprs} } - case 589: + case 609: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3032 +//line sql.y:3149 { yyVAL.matchExprOption = NoOption } - case 590: + case 610: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3036 +//line sql.y:3153 { yyVAL.matchExprOption = BooleanModeOpt } - case 591: + case 611: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:3040 +//line sql.y:3157 { yyVAL.matchExprOption = NaturalLanguageModeOpt } - case 592: + case 612: yyDollar = yyS[yypt-7 : yypt+1] -//line sql.y:3044 +//line sql.y:3161 { yyVAL.matchExprOption = NaturalLanguageModeWithQueryExpansionOpt } - case 593: + case 613: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3048 +//line sql.y:3165 { yyVAL.matchExprOption = QueryExpansionOpt } - case 594: + case 614: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3054 +//line sql.y:3171 { yyVAL.str = string(yyDollar[1].colIdent.String()) } - case 595: + case 615: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3058 +//line sql.y:3175 { yyVAL.str = string(yyDollar[1].bytes) } - case 596: + case 616: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3064 +//line sql.y:3181 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].literal} } - case 597: + case 617: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3068 +//line sql.y:3185 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].literal, Charset: yyDollar[3].str, Operator: CharacterSetOp} } - case 598: + case 618: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3072 +//line sql.y:3189 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].literal, Charset: string(yyDollar[3].colIdent.String())} } - case 599: + case 619: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3076 +//line sql.y:3193 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} } - case 600: + case 620: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3080 +//line sql.y:3197 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].literal} } - case 601: + case 621: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3084 +//line sql.y:3201 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} yyVAL.convertType.Length = yyDollar[2].LengthScaleOption.Length yyVAL.convertType.Scale = yyDollar[2].LengthScaleOption.Scale } - case 602: + case 622: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3090 +//line sql.y:3207 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} } - case 603: + case 623: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3094 +//line sql.y:3211 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].literal} } - case 604: + case 624: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3098 +//line sql.y:3215 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} } - case 605: + case 625: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3102 +//line sql.y:3219 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} } - case 606: + case 626: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3106 +//line sql.y:3223 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].literal} } - case 607: + case 627: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3110 +//line sql.y:3227 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} } - case 608: + case 628: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3114 +//line sql.y:3231 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} } - case 609: + case 629: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3119 +//line sql.y:3236 { yyVAL.expr = nil } - case 610: + case 630: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3123 +//line sql.y:3240 { yyVAL.expr = yyDollar[1].expr } - case 611: + case 631: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3128 +//line sql.y:3245 { yyVAL.str = string("") } - case 612: + case 632: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3132 +//line sql.y:3249 { yyVAL.str = " separator '" + string(yyDollar[2].bytes) + "'" } - case 613: + case 633: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3138 +//line sql.y:3255 { yyVAL.whens = []*When{yyDollar[1].when} } - case 614: + case 634: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3142 +//line sql.y:3259 { yyVAL.whens = append(yyDollar[1].whens, yyDollar[2].when) } - case 615: + case 635: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:3148 +//line sql.y:3265 { yyVAL.when = &When{Cond: yyDollar[2].expr, Val: yyDollar[4].expr} } - case 616: + case 636: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3153 +//line sql.y:3270 { yyVAL.expr = nil } - case 617: + case 637: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3157 +//line sql.y:3274 { yyVAL.expr = yyDollar[2].expr } - case 618: + case 638: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3163 +//line sql.y:3280 { yyVAL.colName = &ColName{Name: yyDollar[1].colIdent} } - case 619: + case 639: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3167 +//line sql.y:3284 { yyVAL.colName = &ColName{Qualifier: TableName{Name: yyDollar[1].tableIdent}, Name: yyDollar[3].colIdent} } - case 620: + case 640: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:3171 +//line sql.y:3288 { yyVAL.colName = &ColName{Qualifier: TableName{Qualifier: yyDollar[1].tableIdent, Name: yyDollar[3].tableIdent}, Name: yyDollar[5].colIdent} } - case 621: + case 641: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3177 +//line sql.y:3294 { yyVAL.expr = NewStrLiteral(yyDollar[1].bytes) } - case 622: + case 642: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3181 +//line sql.y:3298 { yyVAL.expr = NewHexLiteral(yyDollar[1].bytes) } - case 623: + case 643: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3185 +//line sql.y:3302 { yyVAL.expr = NewBitLiteral(yyDollar[1].bytes) } - case 624: + case 644: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3189 +//line sql.y:3306 { yyVAL.expr = NewIntLiteral(yyDollar[1].bytes) } - case 625: + case 645: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3193 +//line sql.y:3310 { yyVAL.expr = NewFloatLiteral(yyDollar[1].bytes) } - case 626: + case 646: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3197 +//line sql.y:3314 { yyVAL.expr = NewHexNumLiteral(yyDollar[1].bytes) } - case 627: + case 647: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3201 +//line sql.y:3318 { yyVAL.expr = NewArgument(yyDollar[1].bytes) } - case 628: + case 648: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3205 +//line sql.y:3322 { yyVAL.expr = &NullVal{} } - case 629: + case 649: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3211 +//line sql.y:3328 { // TODO(sougou): Deprecate this construct. if yyDollar[1].colIdent.Lowered() != "value" { @@ -7704,411 +7875,483 @@ yydefault: } yyVAL.expr = NewIntLiteral([]byte("1")) } - case 630: + case 650: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3220 +//line sql.y:3337 { yyVAL.expr = NewIntLiteral(yyDollar[1].bytes) } - case 631: + case 651: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3224 +//line sql.y:3341 { yyVAL.expr = NewArgument(yyDollar[1].bytes) } - case 632: + case 652: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3229 +//line sql.y:3346 { yyVAL.exprs = nil } - case 633: + case 653: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3233 +//line sql.y:3350 { yyVAL.exprs = yyDollar[3].exprs } - case 634: + case 654: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3238 +//line sql.y:3355 { yyVAL.expr = nil } - case 635: + case 655: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3242 +//line sql.y:3359 { yyVAL.expr = yyDollar[2].expr } - case 636: + case 656: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3247 +//line sql.y:3364 { yyVAL.orderBy = nil } - case 637: + case 657: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3251 +//line sql.y:3368 { yyVAL.orderBy = yyDollar[3].orderBy } - case 638: + case 658: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3257 +//line sql.y:3374 { yyVAL.orderBy = OrderBy{yyDollar[1].order} } - case 639: + case 659: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3261 +//line sql.y:3378 { yyVAL.orderBy = append(yyDollar[1].orderBy, yyDollar[3].order) } - case 640: + case 660: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3267 +//line sql.y:3384 { yyVAL.order = &Order{Expr: yyDollar[1].expr, Direction: yyDollar[2].orderDirection} } - case 641: + case 661: + yyDollar = yyS[yypt-0 : yypt+1] +//line sql.y:3389 + { + yyVAL.orderDirection = AscOrder + } + case 662: + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:3393 + { + yyVAL.orderDirection = AscOrder + } + case 663: + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:3397 + { + yyVAL.orderDirection = DescOrder + } + case 664: + yyDollar = yyS[yypt-0 : yypt+1] +//line sql.y:3402 + { + yyVAL.limit = nil + } + case 665: + yyDollar = yyS[yypt-2 : yypt+1] +//line sql.y:3406 + { + yyVAL.limit = &Limit{Rowcount: yyDollar[2].expr} + } + case 666: + yyDollar = yyS[yypt-4 : yypt+1] +//line sql.y:3410 + { + yyVAL.limit = &Limit{Offset: yyDollar[2].expr, Rowcount: yyDollar[4].expr} + } + case 667: + yyDollar = yyS[yypt-4 : yypt+1] +//line sql.y:3414 + { + yyVAL.limit = &Limit{Offset: yyDollar[4].expr, Rowcount: yyDollar[2].expr} + } + case 668: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3272 +//line sql.y:3419 + { + yyVAL.indexOptions = nil + } + case 669: + yyDollar = yyS[yypt-2 : yypt+1] +//line sql.y:3423 + { + yyVAL.indexOptions = []*IndexOption{yyDollar[1].indexOption, yyDollar[2].indexOption} + } + case 670: + yyDollar = yyS[yypt-2 : yypt+1] +//line sql.y:3427 + { + yyVAL.indexOptions = []*IndexOption{yyDollar[1].indexOption, yyDollar[2].indexOption} + } + case 671: + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:3431 + { + yyVAL.indexOptions = []*IndexOption{yyDollar[1].indexOption} + } + case 672: + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:3435 + { + yyVAL.indexOptions = []*IndexOption{yyDollar[1].indexOption} + } + case 673: + yyDollar = yyS[yypt-3 : yypt+1] +//line sql.y:3442 { - yyVAL.orderDirection = AscOrder + yyVAL.indexOption = &IndexOption{Name: string(yyDollar[1].bytes), String: string(yyDollar[3].bytes)} } - case 642: - yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3276 + case 674: + yyDollar = yyS[yypt-3 : yypt+1] +//line sql.y:3446 { - yyVAL.orderDirection = AscOrder + yyVAL.indexOption = &IndexOption{Name: string(yyDollar[1].bytes), String: string(yyDollar[3].bytes)} } - case 643: - yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3280 + case 675: + yyDollar = yyS[yypt-3 : yypt+1] +//line sql.y:3450 { - yyVAL.orderDirection = DescOrder + yyVAL.indexOption = &IndexOption{Name: string(yyDollar[1].bytes), String: string(yyDollar[3].bytes)} } - case 644: - yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3285 + case 676: + yyDollar = yyS[yypt-3 : yypt+1] +//line sql.y:3454 { - yyVAL.limit = nil + yyVAL.indexOption = &IndexOption{Name: string(yyDollar[1].bytes), String: string(yyDollar[3].bytes)} } - case 645: - yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3289 + case 677: + yyDollar = yyS[yypt-3 : yypt+1] +//line sql.y:3460 { - yyVAL.limit = &Limit{Rowcount: yyDollar[2].expr} + yyVAL.indexOption = &IndexOption{Name: string(yyDollar[1].bytes), String: string(yyDollar[3].bytes)} } - case 646: - yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:3293 + case 678: + yyDollar = yyS[yypt-3 : yypt+1] +//line sql.y:3464 { - yyVAL.limit = &Limit{Offset: yyDollar[2].expr, Rowcount: yyDollar[4].expr} + yyVAL.indexOption = &IndexOption{Name: string(yyDollar[1].bytes), String: string(yyDollar[3].bytes)} } - case 647: - yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:3297 + case 679: + yyDollar = yyS[yypt-3 : yypt+1] +//line sql.y:3468 { - yyVAL.limit = &Limit{Offset: yyDollar[4].expr, Rowcount: yyDollar[2].expr} + yyVAL.indexOption = &IndexOption{Name: string(yyDollar[1].bytes), String: string(yyDollar[3].bytes)} } - case 648: + case 680: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3302 +//line sql.y:3473 { yyVAL.lock = NoLock } - case 649: + case 681: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3306 +//line sql.y:3477 { yyVAL.lock = ForUpdateLock } - case 650: + case 682: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:3310 +//line sql.y:3481 { yyVAL.lock = ShareModeLock } - case 651: + case 683: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3315 +//line sql.y:3486 { yyVAL.selectInto = nil } - case 652: + case 684: yyDollar = yyS[yypt-9 : yypt+1] -//line sql.y:3319 +//line sql.y:3490 { yyVAL.selectInto = &SelectInto{Type: IntoOutfileS3, FileName: string(yyDollar[4].bytes), Charset: yyDollar[5].str, FormatOption: yyDollar[6].str, ExportOption: yyDollar[7].str, Manifest: yyDollar[8].str, Overwrite: yyDollar[9].str} } - case 653: + case 685: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3323 +//line sql.y:3494 { yyVAL.selectInto = &SelectInto{Type: IntoDumpfile, FileName: string(yyDollar[3].bytes), Charset: "", FormatOption: "", ExportOption: "", Manifest: "", Overwrite: ""} } - case 654: + case 686: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:3327 +//line sql.y:3498 { yyVAL.selectInto = &SelectInto{Type: IntoOutfile, FileName: string(yyDollar[3].bytes), Charset: yyDollar[4].str, FormatOption: "", ExportOption: yyDollar[5].str, Manifest: "", Overwrite: ""} } - case 655: + case 687: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3332 +//line sql.y:3503 { yyVAL.str = "" } - case 656: + case 688: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3336 +//line sql.y:3507 { yyVAL.str = " format csv" + yyDollar[3].str } - case 657: + case 689: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3340 +//line sql.y:3511 { yyVAL.str = " format text" + yyDollar[3].str } - case 658: + case 690: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3345 +//line sql.y:3516 { yyVAL.str = "" } - case 659: + case 691: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3349 +//line sql.y:3520 { yyVAL.str = " header" } - case 660: + case 692: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3354 +//line sql.y:3525 { yyVAL.str = "" } - case 661: + case 693: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3358 +//line sql.y:3529 { yyVAL.str = " manifest on" } - case 662: + case 694: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3362 +//line sql.y:3533 { yyVAL.str = " manifest off" } - case 663: + case 695: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3367 +//line sql.y:3538 { yyVAL.str = "" } - case 664: + case 696: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3371 +//line sql.y:3542 { yyVAL.str = " overwrite on" } - case 665: + case 697: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3375 +//line sql.y:3546 { yyVAL.str = " overwrite off" } - case 666: + case 698: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3381 +//line sql.y:3552 { yyVAL.str = yyDollar[1].str + yyDollar[2].str } - case 667: + case 699: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3386 +//line sql.y:3557 { yyVAL.str = "" } - case 668: + case 700: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3390 +//line sql.y:3561 { yyVAL.str = " lines" + yyDollar[2].str + yyDollar[3].str } - case 669: + case 701: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3395 +//line sql.y:3566 { yyVAL.str = "" } - case 670: + case 702: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3399 +//line sql.y:3570 { yyVAL.str = " starting by '" + string(yyDollar[3].bytes) + "'" } - case 671: + case 703: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3404 +//line sql.y:3575 { yyVAL.str = "" } - case 672: + case 704: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3408 +//line sql.y:3579 { yyVAL.str = " terminated by '" + string(yyDollar[3].bytes) + "'" } - case 673: + case 705: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3413 +//line sql.y:3584 { yyVAL.str = "" } - case 674: + case 706: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:3417 +//line sql.y:3588 { yyVAL.str = " " + yyDollar[1].str + yyDollar[2].str + yyDollar[3].str + yyDollar[4].str } - case 675: + case 707: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3422 +//line sql.y:3593 { yyVAL.str = "" } - case 676: + case 708: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3426 +//line sql.y:3597 { yyVAL.str = " escaped by '" + string(yyDollar[3].bytes) + "'" } - case 677: + case 709: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3431 +//line sql.y:3602 { yyVAL.str = "" } - case 678: + case 710: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:3435 +//line sql.y:3606 { yyVAL.str = yyDollar[1].str + " enclosed by '" + string(yyDollar[4].bytes) + "'" } - case 679: + case 711: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3440 +//line sql.y:3611 { yyVAL.str = "" } - case 680: + case 712: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3444 +//line sql.y:3615 { yyVAL.str = " optionally" } - case 681: + case 713: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3457 +//line sql.y:3628 { yyVAL.ins = &Insert{Rows: yyDollar[2].values} } - case 682: + case 714: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3461 +//line sql.y:3632 { yyVAL.ins = &Insert{Rows: yyDollar[1].selStmt} } - case 683: + case 715: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:3465 +//line sql.y:3636 { yyVAL.ins = &Insert{Columns: yyDollar[2].columns, Rows: yyDollar[5].values} } - case 684: + case 716: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:3469 +//line sql.y:3640 { yyVAL.ins = &Insert{Rows: yyDollar[4].values} } - case 685: + case 717: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:3473 +//line sql.y:3644 { yyVAL.ins = &Insert{Columns: yyDollar[2].columns, Rows: yyDollar[4].selStmt} } - case 686: + case 718: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3479 +//line sql.y:3650 { yyVAL.columns = Columns{yyDollar[1].colIdent} } - case 687: + case 719: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3483 +//line sql.y:3654 { yyVAL.columns = Columns{yyDollar[3].colIdent} } - case 688: + case 720: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3487 +//line sql.y:3658 { yyVAL.columns = append(yyVAL.columns, yyDollar[3].colIdent) } - case 689: + case 721: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:3491 +//line sql.y:3662 { yyVAL.columns = append(yyVAL.columns, yyDollar[5].colIdent) } - case 690: + case 722: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3496 +//line sql.y:3667 { yyVAL.updateExprs = nil } - case 691: + case 723: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:3500 +//line sql.y:3671 { yyVAL.updateExprs = yyDollar[5].updateExprs } - case 692: + case 724: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3506 +//line sql.y:3677 { yyVAL.values = Values{yyDollar[1].valTuple} } - case 693: + case 725: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3510 +//line sql.y:3681 { yyVAL.values = append(yyDollar[1].values, yyDollar[3].valTuple) } - case 694: + case 726: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3516 +//line sql.y:3687 { yyVAL.valTuple = yyDollar[1].valTuple } - case 695: + case 727: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3520 +//line sql.y:3691 { yyVAL.valTuple = ValTuple{} } - case 696: + case 728: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3526 +//line sql.y:3697 { yyVAL.valTuple = ValTuple(yyDollar[2].exprs) } - case 697: + case 729: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3532 +//line sql.y:3703 { if len(yyDollar[1].valTuple) == 1 { yyVAL.expr = yyDollar[1].valTuple[0] @@ -8116,342 +8359,325 @@ yydefault: yyVAL.expr = yyDollar[1].valTuple } } - case 698: + case 730: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3542 +//line sql.y:3713 { yyVAL.updateExprs = UpdateExprs{yyDollar[1].updateExpr} } - case 699: + case 731: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3546 +//line sql.y:3717 { yyVAL.updateExprs = append(yyDollar[1].updateExprs, yyDollar[3].updateExpr) } - case 700: + case 732: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3552 +//line sql.y:3723 { yyVAL.updateExpr = &UpdateExpr{Name: yyDollar[1].colName, Expr: yyDollar[3].expr} } - case 701: + case 733: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3558 +//line sql.y:3729 { yyVAL.setExprs = SetExprs{yyDollar[1].setExpr} } - case 702: + case 734: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3562 +//line sql.y:3733 { yyVAL.setExprs = append(yyDollar[1].setExprs, yyDollar[3].setExpr) } - case 703: + case 735: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3568 +//line sql.y:3739 { yyVAL.setExpr = &SetExpr{Name: yyDollar[1].colIdent, Scope: ImplicitScope, Expr: NewStrLiteral([]byte("on"))} } - case 704: + case 736: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3572 +//line sql.y:3743 { yyVAL.setExpr = &SetExpr{Name: yyDollar[1].colIdent, Scope: ImplicitScope, Expr: NewStrLiteral([]byte("off"))} } - case 705: + case 737: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3576 +//line sql.y:3747 { yyVAL.setExpr = &SetExpr{Name: yyDollar[1].colIdent, Scope: ImplicitScope, Expr: yyDollar[3].expr} } - case 706: + case 738: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3580 +//line sql.y:3751 { yyVAL.setExpr = &SetExpr{Name: NewColIdent(string(yyDollar[1].bytes)), Scope: ImplicitScope, Expr: yyDollar[2].expr} } - case 707: + case 739: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3584 +//line sql.y:3755 { yyDollar[2].setExpr.Scope = yyDollar[1].scope yyVAL.setExpr = yyDollar[2].setExpr } - case 709: + case 741: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3592 +//line sql.y:3763 { yyVAL.bytes = []byte("charset") } - case 711: + case 743: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3599 +//line sql.y:3770 { yyVAL.expr = NewStrLiteral([]byte(yyDollar[1].colIdent.String())) } - case 712: + case 744: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3603 +//line sql.y:3774 { yyVAL.expr = NewStrLiteral(yyDollar[1].bytes) } - case 713: + case 745: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3607 +//line sql.y:3778 { yyVAL.expr = &Default{} } - case 716: + case 748: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3616 +//line sql.y:3787 { yyVAL.boolean = false } - case 717: + case 749: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3618 +//line sql.y:3789 { yyVAL.boolean = true } - case 718: + case 750: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3621 +//line sql.y:3792 { yyVAL.boolean = false } - case 719: + case 751: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3623 +//line sql.y:3794 { yyVAL.boolean = true } - case 720: + case 752: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3626 +//line sql.y:3797 { yyVAL.ignore = false } - case 721: + case 753: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3628 +//line sql.y:3799 { yyVAL.ignore = true } - case 722: + case 754: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3632 +//line sql.y:3803 { yyVAL.empty = struct{}{} } - case 723: + case 755: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3634 +//line sql.y:3805 { yyVAL.empty = struct{}{} } - case 724: + case 756: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3636 +//line sql.y:3807 { yyVAL.empty = struct{}{} } - case 725: + case 757: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3638 +//line sql.y:3809 { yyVAL.empty = struct{}{} } - case 726: + case 758: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3640 +//line sql.y:3811 { yyVAL.empty = struct{}{} } - case 727: + case 759: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3642 +//line sql.y:3813 { yyVAL.empty = struct{}{} } - case 728: + case 760: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3644 +//line sql.y:3815 { yyVAL.empty = struct{}{} } - case 729: + case 761: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3646 +//line sql.y:3817 { yyVAL.empty = struct{}{} } - case 730: + case 762: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3648 +//line sql.y:3819 { yyVAL.empty = struct{}{} } - case 731: + case 763: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3650 +//line sql.y:3821 { yyVAL.empty = struct{}{} } - case 732: - yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3654 - { - yyVAL.OnlineDDLHint = &OnlineDDLHint{} - } - case 733: - yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3658 - { - yyVAL.OnlineDDLHint = &OnlineDDLHint{ - Strategy: DDLStrategy(yyDollar[2].bytes), - } - } - case 734: - yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3664 - { - yyVAL.OnlineDDLHint = &OnlineDDLHint{ - Strategy: DDLStrategy(yyDollar[2].bytes), - Options: string(yyDollar[3].bytes), - } - } - case 735: + case 764: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3672 +//line sql.y:3825 { yyVAL.empty = struct{}{} } - case 736: + case 765: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3674 +//line sql.y:3827 { yyVAL.empty = struct{}{} } - case 737: + case 766: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3676 +//line sql.y:3829 { yyVAL.empty = struct{}{} } - case 738: + case 767: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3680 +//line sql.y:3833 { yyVAL.empty = struct{}{} } - case 739: + case 768: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3682 +//line sql.y:3835 { yyVAL.empty = struct{}{} } - case 740: + case 769: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3685 +//line sql.y:3838 { - yyVAL.empty = struct{}{} + yyVAL.str = "" } - case 741: + case 770: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3687 +//line sql.y:3840 { - yyVAL.empty = struct{}{} + yyVAL.str = string(yyDollar[1].bytes) } - case 742: + case 771: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3689 +//line sql.y:3842 { - yyVAL.empty = struct{}{} + yyVAL.str = string(yyDollar[1].bytes) } - case 743: + case 772: + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:3844 + { + yyVAL.str = string(yyDollar[1].bytes) + } + case 773: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3692 +//line sql.y:3847 { - yyVAL.colIdent = ColIdent{} + yyVAL.str = "" } - case 744: + case 774: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3694 +//line sql.y:3849 { - yyVAL.colIdent = yyDollar[2].colIdent + yyVAL.str = yyDollar[2].colIdent.val } - case 745: + case 775: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3698 +//line sql.y:3853 { yyVAL.colIdent = yyDollar[1].colIdent } - case 746: + case 776: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3702 +//line sql.y:3857 { yyVAL.colIdent = NewColIdent(string(yyDollar[1].bytes)) } - case 748: + case 778: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3709 +//line sql.y:3864 { yyVAL.colIdent = NewColIdent(string(yyDollar[1].bytes)) } - case 749: + case 779: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3715 +//line sql.y:3870 { yyVAL.tableIdent = NewTableIdent(string(yyDollar[1].colIdent.String())) } - case 750: + case 780: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3719 +//line sql.y:3874 { yyVAL.tableIdent = NewTableIdent(string(yyDollar[1].bytes)) } - case 752: + case 782: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3726 +//line sql.y:3881 { yyVAL.tableIdent = NewTableIdent(string(yyDollar[1].bytes)) } - case 1066: + case 1106: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4065 +//line sql.y:4230 { if incNesting(yylex) { yylex.Error("max nesting level reached") return 1 } } - case 1067: + case 1107: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4074 +//line sql.y:4239 { decNesting(yylex) } - case 1068: + case 1108: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4079 +//line sql.y:4244 { skipToEnd(yylex) } - case 1069: + case 1109: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4084 +//line sql.y:4249 { skipToEnd(yylex) } - case 1070: + case 1110: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4088 +//line sql.y:4253 { skipToEnd(yylex) } - case 1071: + case 1111: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4092 +//line sql.y:4257 { skipToEnd(yylex) } diff --git a/go/vt/sqlparser/sql.y b/go/vt/sqlparser/sql.y index d90b44dfc81..c076833220c 100644 --- a/go/vt/sqlparser/sql.y +++ b/go/vt/sqlparser/sql.y @@ -25,8 +25,8 @@ func setAllowComments(yylex interface{}, allow bool) { yylex.(*Tokenizer).AllowComments = allow } -func setDDL(yylex interface{}, ddl *DDL) { - yylex.(*Tokenizer).partialDDL = ddl +func setDDL(yylex interface{}, node Statement) { + yylex.(*Tokenizer).partialDDL = node } func incNesting(yylex interface{}) bool { @@ -81,6 +81,7 @@ func skipToEnd(yylex interface{}) { values Values valTuple ValTuple subquery *Subquery + derivedTable *DerivedTable whens []*When when *When orderBy OrderBy @@ -101,7 +102,6 @@ func skipToEnd(yylex interface{}) { colKeyOpt ColumnKeyOption optVal Expr LengthScaleOption LengthScaleOption - OnlineDDLHint *OnlineDDLHint columnDefinition *ColumnDefinition indexDefinition *IndexDefinition indexInfo *IndexInfo @@ -131,20 +131,25 @@ func skipToEnd(yylex interface{}) { orderDirection OrderDirection explainType ExplainType selectInto *SelectInto + createIndex *CreateIndex + createDatabase *CreateDatabase + alterDatabase *AlterDatabase + collateAndCharset CollateAndCharset + collateAndCharsets []CollateAndCharset } %token LEX_ERROR %left UNION %token SELECT STREAM VSTREAM INSERT UPDATE DELETE FROM WHERE GROUP HAVING ORDER BY LIMIT OFFSET FOR %token ALL DISTINCT AS EXISTS ASC DESC INTO DUPLICATE KEY DEFAULT SET LOCK UNLOCK KEYS DO -%token DISTINCTROW +%token DISTINCTROW PARSER %token OUTFILE S3 DATA LOAD LINES TERMINATED ESCAPED ENCLOSED %token DUMPFILE CSV HEADER MANIFEST OVERWRITE STARTING OPTIONALLY %token VALUES LAST_INSERT_ID %token NEXT VALUE SHARE MODE %token SQL_NO_CACHE SQL_CACHE SQL_CALC_FOUND_ROWS %left JOIN STRAIGHT_JOIN LEFT RIGHT INNER OUTER CROSS NATURAL USE FORCE -%left ON USING +%left ON USING INPLACE COPY ALGORITHM NONE SHARED EXCLUSIVE %token '(' ',' ')' %token ID AT_ID AT_AT_ID HEX STRING INTEGRAL FLOAT HEXNUM VALUE_ARG LIST_ARG COMMENT COMMENT_KEYWORD BIT_LITERAL %token NULL TRUE FALSE OFF @@ -183,7 +188,7 @@ func skipToEnd(yylex interface{}) { %token ACTION CASCADE CONSTRAINT FOREIGN NO REFERENCES RESTRICT %token SHOW DESCRIBE EXPLAIN DATE ESCAPE REPAIR OPTIMIZE TRUNCATE %token MAXVALUE PARTITION REORGANIZE LESS THAN PROCEDURE TRIGGER -%token VINDEX VINDEXES +%token VINDEX VINDEXES DIRECTORY NAME UPGRADE %token STATUS VARIABLES WARNINGS %token SEQUENCE @@ -240,6 +245,12 @@ func skipToEnd(yylex interface{}) { %type stream_statement vstream_statement insert_statement update_statement delete_statement set_statement set_transaction_statement %type create_statement alter_statement rename_statement drop_statement truncate_statement flush_statement do_statement %type create_table_prefix rename_list +%type create_index_prefix +%type create_database_prefix +%type alter_database_prefix +%type collate character_set +%type create_options create_options_opt +%type default_optional %type analyze_statement show_statement use_statement other_statement %type begin_statement commit_statement rollback_statement savepoint_statement release_statement load_statement %type comment_opt comment_list @@ -277,7 +288,8 @@ func skipToEnd(yylex interface{}) { %type tuple_list %type row_tuple tuple_or_empty %type tuple_expression -%type subquery derived_table +%type subquery +%type derived_table %type column_name %type when_expression_list %type when_expression @@ -290,7 +302,7 @@ func skipToEnd(yylex interface{}) { %type limit_opt %type into_option %type header_opt export_options manifest_opt overwrite_opt format_opt optionally_opt -%type fields_opt lines_opt terminated_by_opt starting_by_opt enclosed_by_opt escaped_by_opt +%type fields_opt lines_opt terminated_by_opt starting_by_opt enclosed_by_opt escaped_by_opt constraint_opt using_opt %type lock_opt %type ins_column_list column_list %type opt_partition_clause partition_list @@ -306,13 +318,12 @@ func skipToEnd(yylex interface{}) { %type for_from %type default_opt %type ignore_opt -%type online_hint_opt %type full_opt from_database_opt tables_or_processlist columns_or_fields extended_opt %type like_or_where_opt like_opt %type exists_opt not_exists_opt null_opt enforced_opt -%type non_add_drop_or_rename_operation to_opt index_opt constraint_opt +%type non_add_drop_or_rename_operation to_opt index_opt %type reserved_keyword non_reserved_keyword -%type sql_id reserved_sql_id col_alias as_ci_opt using_opt +%type sql_id reserved_sql_id col_alias as_ci_opt %type charset_value %type table_id reserved_table_id table_alias as_opt_id %type as_opt work_opt savepoint_opt @@ -341,16 +352,16 @@ func skipToEnd(yylex interface{}) { %type index_info %type index_column %type index_column_list -%type index_option -%type index_option_list +%type index_option lock_index algorithm_index +%type index_option_list index_option_list_opt algorithm_lock_opt %type constraint_info check_constraint_info %type partition_definitions %type partition_definition %type partition_operation %type vindex_param %type vindex_param_list vindex_params_opt -%type id_or_var vindex_type vindex_type_opt -%type alter_object_type +%type id_or_var vindex_type vindex_type_opt id_or_var_opt +%type alter_object_type database_or_schema %type fk_reference_action fk_on_delete fk_on_update %type vitess_topo @@ -417,6 +428,15 @@ id_or_var: $$ = NewColIdentWithAt(string($1), DoubleAt) } +id_or_var_opt: + { + $$ = NewColIdentWithAt("", NoAt) + } +| id_or_var + { + $$ = $1 + } + do_statement: DO expression_list { @@ -685,10 +705,12 @@ create_statement: $1.OptLike = $2 $$ = $1 } -| CREATE constraint_opt INDEX id_or_var using_opt ON table_name ddl_skip_to_end +| create_index_prefix '(' index_column_list ')' index_option_list_opt algorithm_lock_opt { - // Change this to an alter statement - $$ = &DDL{Action: AlterDDLAction, Table: $7} + $1.Columns = $3 + $1.Options = append($5,$6...) + $1.FullyParsed = true + $$ = $1 } | CREATE VIEW table_name ddl_skip_to_end { @@ -698,13 +720,11 @@ create_statement: { $$ = &DDL{Action: CreateDDLAction, Table: $5.ToViewName()} } -| CREATE DATABASE not_exists_opt id_or_var ddl_skip_to_end - { - $$ = &DBDDL{Action: CreateDBDDLAction, DBName: string($4.String()), IfNotExists: $3} - } -| CREATE SCHEMA not_exists_opt id_or_var ddl_skip_to_end +| create_database_prefix create_options_opt { - $$ = &DBDDL{Action: CreateDBDDLAction, DBName: string($4.String()), IfNotExists: $3} + $1.FullyParsed = true + $1.CreateOptions = $2 + $$ = $1 } vindex_type_opt: @@ -756,6 +776,31 @@ create_table_prefix: setDDL(yylex, $$) } +create_index_prefix: + CREATE constraint_opt INDEX id_or_var using_opt ON table_name + { + $$ = &CreateIndex{Constraint: $2, Name: $4, IndexType: $5, Table: $7} + setDDL(yylex, $$) + } + +create_database_prefix: + CREATE database_or_schema not_exists_opt id_or_var + { + $$ = &CreateDatabase{DBName: string($4.String()), IfNotExists: $3} + setDDL(yylex,$$) + } + +alter_database_prefix: + ALTER database_or_schema + { + $$ = &AlterDatabase{} + setDDL(yylex,$$) + } + +database_or_schema: + DATABASE +| SCHEMA + table_spec: '(' table_column_list ')' table_option_list { @@ -763,6 +808,63 @@ table_spec: $$.Options = $4 } +create_options_opt: + { + $$ = nil + } +| create_options + { + $$ = $1 + } + +create_options: + character_set + { + $$ = []CollateAndCharset{$1} + } +| collate + { + $$ = []CollateAndCharset{$1} + } +| create_options collate + { + $$ = append($1,$2) + } +| create_options character_set + { + $$ = append($1,$2) + } + +default_optional: + { + $$ = false + } +| DEFAULT + { + $$ = true + } + +character_set: + default_optional CHARACTER SET equal_opt id_or_var + { + $$ = CollateAndCharset{Type:CharacterSetType, Value:($5.String()), IsDefault:$1} + } +| default_optional CHARACTER SET equal_opt STRING + { + $$ = CollateAndCharset{Type:CharacterSetType, Value:("'" + string($5) + "'"), IsDefault:$1} + } + +collate: + default_optional COLLATE equal_opt id_or_var + { + $$ = CollateAndCharset{Type:CollateType, Value:($4.String()), IsDefault:$1} + } +| default_optional COLLATE equal_opt STRING + { + $$ = CollateAndCharset{Type:CollateType, Value:("'" + string($4) + "'"), IsDefault:$1} + } + + create_like: LIKE table_name { @@ -1190,13 +1292,18 @@ column_comment_opt: } index_definition: - index_info '(' index_column_list ')' index_option_list + index_info '(' index_column_list ')' index_option_list_opt { $$ = &IndexDefinition{Info: $1, Columns: $3, Options: $5} } -| index_info '(' index_column_list ')' + +index_option_list_opt: { - $$ = &IndexDefinition{Info: $1, Columns: $3} + $$ = nil + } +| index_option_list + { + $$ = $1 } index_option_list: @@ -1212,7 +1319,7 @@ index_option_list: index_option: USING id_or_var { - $$ = &IndexOption{Name: string($1), Using: string($2.String())} + $$ = &IndexOption{Name: string($1), String: string($2.String())} } | KEY_BLOCK_SIZE equal_opt INTEGRAL { @@ -1223,6 +1330,10 @@ index_option: { $$ = &IndexOption{Name: string($1), Value: NewStrLiteral($2)} } +| WITH PARSER STRING + { + $$ = &IndexOption{Name: string($1) + " " + string($2), Value: NewStrLiteral($3)} + } equal_opt: /* empty */ @@ -1315,9 +1426,9 @@ index_column_list: } index_column: - sql_id length_opt + sql_id length_opt asc_desc_opt { - $$ = &IndexColumn{Column: $1, Length: $2} + $$ = &IndexColumn{Column: $1, Length: $2, Direction: $3} } constraint_definition: @@ -1459,43 +1570,49 @@ table_opt_value: } alter_statement: - ALTER online_hint_opt TABLE table_name non_add_drop_or_rename_operation skip_to_end + ALTER TABLE table_name non_add_drop_or_rename_operation skip_to_end { - $$ = &DDL{Action: AlterDDLAction, OnlineHint: $2, Table: $4} + $$ = &DDL{Action: AlterDDLAction, Table: $3} } -| ALTER online_hint_opt TABLE table_name ADD alter_object_type skip_to_end +| ALTER TABLE table_name ADD alter_object_type skip_to_end { - $$ = &DDL{Action: AlterDDLAction, OnlineHint: $2, Table: $4} + $$ = &DDL{Action: AlterDDLAction, Table: $3} } -| ALTER online_hint_opt TABLE table_name DROP alter_object_type skip_to_end +| ALTER TABLE table_name DROP alter_object_type skip_to_end { - $$ = &DDL{Action: AlterDDLAction, OnlineHint: $2, Table: $4} + $$ = &DDL{Action: AlterDDLAction, Table: $3} } -| ALTER online_hint_opt TABLE table_name RENAME to_opt table_name +| ALTER TABLE table_name RENAME to_opt table_name { // Change this to a rename statement - $$ = &DDL{Action: RenameDDLAction, FromTables: TableNames{$4}, ToTables: TableNames{$7}} + $$ = &DDL{Action: RenameDDLAction, FromTables: TableNames{$3}, ToTables: TableNames{$6}} } -| ALTER online_hint_opt TABLE table_name RENAME index_opt skip_to_end +| ALTER TABLE table_name RENAME index_opt skip_to_end { // Rename an index can just be an alter - $$ = &DDL{Action: AlterDDLAction, OnlineHint: $2, Table: $4} + $$ = &DDL{Action: AlterDDLAction, Table: $3} } | ALTER VIEW table_name ddl_skip_to_end { $$ = &DDL{Action: AlterDDLAction, Table: $3.ToViewName()} } -| ALTER online_hint_opt TABLE table_name partition_operation +| ALTER TABLE table_name partition_operation { - $$ = &DDL{Action: AlterDDLAction, OnlineHint: $2, Table: $4, PartitionSpec: $5} + $$ = &DDL{Action: AlterDDLAction, Table: $3, PartitionSpec: $4} } -| ALTER DATABASE id_or_var ddl_skip_to_end +| alter_database_prefix id_or_var_opt create_options { - $$ = &DBDDL{Action: AlterDBDDLAction, DBName: string($3.String())} + $1.FullyParsed = true + $1.DBName = $2.String() + $1.AlterOptions = $3 + $$ = $1 } -| ALTER SCHEMA id_or_var ddl_skip_to_end +| alter_database_prefix id_or_var UPGRADE DATA DIRECTORY NAME { - $$ = &DBDDL{Action: AlterDBDDLAction, DBName: string($3.String())} + $1.FullyParsed = true + $1.DBName = $2.String() + $1.UpdateDataDirectory = true + $$ = $1 } | ALTER VSCHEMA CREATE VINDEX table_name vindex_type_opt vindex_params_opt { @@ -2279,7 +2396,7 @@ table_factor: derived_table: openb select_statement closeb { - $$ = &Subquery{$2} + $$ = &DerivedTable{$2} } aliased_table_name: @@ -3298,6 +3415,60 @@ limit_opt: $$ = &Limit{Offset: $4, Rowcount: $2} } +algorithm_lock_opt: + { + $$ = nil + } +| lock_index algorithm_index + { + $$ = []*IndexOption{$1,$2} + } +| algorithm_index lock_index + { + $$ = []*IndexOption{$1,$2} + } +| algorithm_index + { + $$ = []*IndexOption{$1} + } +| lock_index + { + $$ = []*IndexOption{$1} + } + + +lock_index: + LOCK equal_opt DEFAULT + { + $$ = &IndexOption{Name: string($1), String: string($3)} + } +| LOCK equal_opt NONE + { + $$ = &IndexOption{Name: string($1), String: string($3)} + } +| LOCK equal_opt SHARED + { + $$ = &IndexOption{Name: string($1), String: string($3)} + } +| LOCK equal_opt EXCLUSIVE + { + $$ = &IndexOption{Name: string($1), String: string($3)} + } + +algorithm_index: + ALGORITHM equal_opt DEFAULT + { + $$ = &IndexOption{Name: string($1), String: string($3)} + } +| ALGORITHM equal_opt INPLACE + { + $$ = &IndexOption{Name: string($1), String: string($3)} + } +| ALGORITHM equal_opt COPY + { + $$ = &IndexOption{Name: string($1), String: string($3)} + } + lock_opt: { $$ = NoLock @@ -3650,24 +3821,6 @@ non_add_drop_or_rename_operation: { $$ = struct{}{} } -online_hint_opt: - { - $$ = &OnlineDDLHint{} - } -| WITH STRING - { - $$ = &OnlineDDLHint{ - Strategy: DDLStrategy($2), - } - } -| WITH STRING STRING - { - $$ = &OnlineDDLHint{ - Strategy: DDLStrategy($2), - Options: string($3), - } - } - to_opt: { $$ = struct{}{} } | TO @@ -3682,16 +3835,18 @@ index_opt: { $$ = struct{}{} } constraint_opt: - { $$ = struct{}{} } + { $$ = "" } | UNIQUE - { $$ = struct{}{} } -| sql_id - { $$ = struct{}{} } + { $$ = string($1) } +| SPATIAL + { $$ = string($1) } +| FULLTEXT + { $$ = string($1) } using_opt: - { $$ = ColIdent{} } + { $$ = "" } | USING sql_id - { $$ = $2 } + { $$ = $2.val } sql_id: id_or_var @@ -3870,6 +4025,7 @@ non_reserved_keyword: | ACTION | ACTIVE | ADMIN +| ALGORITHM | BEGIN | BIGINT | BIT @@ -3889,6 +4045,7 @@ non_reserved_keyword: | COMMIT | COMMITTED | COMPONENT +| COPY | CSV | DATA | DATE @@ -3896,6 +4053,7 @@ non_reserved_keyword: | DECIMAL | DEFINITION | DESCRIPTION +| DIRECTORY | DOUBLE | DUMPFILE | DUPLICATE @@ -3905,6 +4063,7 @@ non_reserved_keyword: | ENUM | ESCAPED | EXCLUDE +| EXCLUSIVE | EXPANSION | EXTENDED | FLOAT_TYPE @@ -3923,6 +4082,7 @@ non_reserved_keyword: | HISTOGRAM | HISTORY | INACTIVE +| INPLACE | INT | INTEGER | INVISIBLE @@ -3954,12 +4114,14 @@ non_reserved_keyword: | MULTILINESTRING | MULTIPOINT | MULTIPOLYGON +| NAME | NAMES | NCHAR | NESTED | NETWORK_NAMESPACE | NOWAIT | NO +| NONE | NULLS | NUMERIC | OFFSET @@ -3973,6 +4135,7 @@ non_reserved_keyword: | OPTIMIZE | OTHERS | OVERWRITE +| PARSER | PARTITION | PATH | PERSIST @@ -4013,6 +4176,7 @@ non_reserved_keyword: | SESSION | SERIALIZABLE | SHARE +| SHARED | SIGNED | SKIP | SMALLINT @@ -4040,6 +4204,7 @@ non_reserved_keyword: | UNCOMMITTED | UNSIGNED | UNUSED +| UPGRADE | VARBINARY | VARCHAR | VARIABLES diff --git a/go/vt/sqlparser/token.go b/go/vt/sqlparser/token.go index be9cd17e428..ab6ab337bbc 100644 --- a/go/vt/sqlparser/token.go +++ b/go/vt/sqlparser/token.go @@ -44,7 +44,7 @@ type Tokenizer struct { LastError error posVarIndex int ParseTree Statement - partialDDL *DDL + partialDDL Statement nesting int multi bool specialComment *Tokenizer @@ -88,6 +88,7 @@ var keywords = map[string]int{ "action": ACTION, "add": ADD, "against": AGAINST, + "algorithm": ALGORITHM, "all": ALL, "alter": ALTER, "analyze": ANALYZE, @@ -131,6 +132,7 @@ var keywords = map[string]int{ "constraint": CONSTRAINT, "continue": UNUSED, "convert": CONVERT, + "copy": COPY, "substr": SUBSTR, "substring": SUBSTRING, "create": CREATE, @@ -159,6 +161,7 @@ var keywords = map[string]int{ "desc": DESC, "describe": DESCRIBE, "deterministic": UNUSED, + "directory": DIRECTORY, "distinct": DISTINCT, "distinctrow": DISTINCTROW, "div": DIV, @@ -176,6 +179,7 @@ var keywords = map[string]int{ "enum": ENUM, "escape": ESCAPE, "escaped": ESCAPED, + "exclusive": EXCLUSIVE, "exists": EXISTS, "exit": UNUSED, "explain": EXPLAIN, @@ -217,6 +221,7 @@ var keywords = map[string]int{ "infile": UNUSED, "inout": UNUSED, "inner": INNER, + "inplace": INPLACE, "insensitive": UNUSED, "insert": INSERT, "int": INT, @@ -276,11 +281,13 @@ var keywords = map[string]int{ "multilinestring": MULTILINESTRING, "multipoint": MULTIPOINT, "multipolygon": MULTIPOLYGON, + "name": NAME, "names": NAMES, "natural": NATURAL, "nchar": NCHAR, "next": NEXT, "no": NO, + "none": NONE, "not": NOT, "no_write_to_binlog": UNUSED, "null": NULL, @@ -299,6 +306,7 @@ var keywords = map[string]int{ "outer": OUTER, "outfile": OUTFILE, "overwrite": OVERWRITE, + "parser": PARSER, "partition": PARTITION, "plugins": PLUGINS, "point": POINT, @@ -342,6 +350,7 @@ var keywords = map[string]int{ "session": SESSION, "set": SET, "share": SHARE, + "shared": SHARED, "show": SHOW, "signal": UNUSED, "signed": SIGNED, @@ -393,6 +402,7 @@ var keywords = map[string]int{ "unlock": UNLOCK, "unsigned": UNSIGNED, "update": UPDATE, + "upgrade": UPGRADE, "usage": UNUSED, "use": USE, "using": USING, diff --git a/go/vt/topotools/vschema_ddl.go b/go/vt/topotools/vschema_ddl.go index a268888c6cc..c6745b0124e 100644 --- a/go/vt/topotools/vschema_ddl.go +++ b/go/vt/topotools/vschema_ddl.go @@ -29,7 +29,7 @@ import ( // ApplyVSchemaDDL applies the given DDL statement to the vschema // keyspace definition and returns the modified keyspace object. -func ApplyVSchemaDDL(ksName string, ks *vschemapb.Keyspace, ddl *sqlparser.DDL) (*vschemapb.Keyspace, error) { +func ApplyVSchemaDDL(ksName string, ks *vschemapb.Keyspace, ddl sqlparser.DDLStatement) (*vschemapb.Keyspace, error) { if ks == nil { ks = new(vschemapb.Keyspace) } @@ -44,14 +44,14 @@ func ApplyVSchemaDDL(ksName string, ks *vschemapb.Keyspace, ddl *sqlparser.DDL) var tableName string var table *vschemapb.Table - if !ddl.Table.IsEmpty() { - tableName = ddl.Table.Name.String() + if !ddl.GetTable().IsEmpty() { + tableName = ddl.GetTable().Name.String() table = ks.Tables[tableName] } - switch ddl.Action { + switch ddl.GetAction() { case sqlparser.CreateVindexDDLAction: - name := ddl.VindexSpec.Name.String() + name := ddl.GetVindexSpec().Name.String() if _, ok := ks.Vindexes[name]; ok { return nil, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "vindex %s already exists in keyspace %s", name, ksName) } @@ -62,9 +62,9 @@ func ApplyVSchemaDDL(ksName string, ks *vschemapb.Keyspace, ddl *sqlparser.DDL) ks.Sharded = true } - owner, params := ddl.VindexSpec.ParseParams() + owner, params := ddl.GetVindexSpec().ParseParams() ks.Vindexes[name] = &vschemapb.Vindex{ - Type: ddl.VindexSpec.Type.String(), + Type: ddl.GetVindexSpec().Type.String(), Params: params, Owner: owner, } @@ -72,7 +72,7 @@ func ApplyVSchemaDDL(ksName string, ks *vschemapb.Keyspace, ddl *sqlparser.DDL) return ks, nil case sqlparser.DropVindexDDLAction: - name := ddl.VindexSpec.Name.String() + name := ddl.GetVindexSpec().Name.String() if _, ok := ks.Vindexes[name]; !ok { return nil, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "vindex %s does not exists in keyspace %s", name, ksName) } @@ -95,7 +95,7 @@ func ApplyVSchemaDDL(ksName string, ks *vschemapb.Keyspace, ddl *sqlparser.DDL) return nil, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "add vschema table: unsupported on sharded keyspace %s", ksName) } - name := ddl.Table.Name.String() + name := ddl.GetTable().Name.String() if _, ok := ks.Tables[name]; ok { return nil, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "vschema already contains table %s in keyspace %s", name, ksName) } @@ -105,7 +105,7 @@ func ApplyVSchemaDDL(ksName string, ks *vschemapb.Keyspace, ddl *sqlparser.DDL) return ks, nil case sqlparser.DropVschemaTableDDLAction: - name := ddl.Table.Name.String() + name := ddl.GetTable().Name.String() if _, ok := ks.Tables[name]; !ok { return nil, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "vschema does not contain table %s in keyspace %s", name, ksName) } @@ -123,7 +123,7 @@ func ApplyVSchemaDDL(ksName string, ks *vschemapb.Keyspace, ddl *sqlparser.DDL) // // 2. The vindex type is not specified. Make sure the vindex // already exists. - spec := ddl.VindexSpec + spec := ddl.GetVindexSpec() name := spec.Name.String() if !spec.Type.IsEmpty() { owner, params := spec.ParseParams() @@ -171,8 +171,8 @@ func ApplyVSchemaDDL(ksName string, ks *vschemapb.Keyspace, ddl *sqlparser.DDL) } } - columns := make([]string, len(ddl.VindexCols)) - for i, col := range ddl.VindexCols { + columns := make([]string, len(ddl.GetVindexCols())) + for i, col := range ddl.GetVindexCols() { columns[i] = col.String() } table.ColumnVindexes = append(table.ColumnVindexes, &vschemapb.ColumnVindex{ @@ -184,7 +184,7 @@ func ApplyVSchemaDDL(ksName string, ks *vschemapb.Keyspace, ddl *sqlparser.DDL) return ks, nil case sqlparser.DropColVindexDDLAction: - spec := ddl.VindexSpec + spec := ddl.GetVindexSpec() name := spec.Name.String() if table == nil { return nil, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "table %s.%s not defined in vschema", ksName, tableName) @@ -206,7 +206,7 @@ func ApplyVSchemaDDL(ksName string, ks *vschemapb.Keyspace, ddl *sqlparser.DDL) return nil, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "add sequence table: unsupported on sharded keyspace %s", ksName) } - name := ddl.Table.Name.String() + name := ddl.GetTable().Name.String() if _, ok := ks.Tables[name]; ok { return nil, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "vschema already contains sequence %s in keyspace %s", name, ksName) } @@ -216,7 +216,7 @@ func ApplyVSchemaDDL(ksName string, ks *vschemapb.Keyspace, ddl *sqlparser.DDL) return ks, nil case sqlparser.AddAutoIncDDLAction: - name := ddl.Table.Name.String() + name := ddl.GetTable().Name.String() table := ks.Tables[name] if table == nil { return nil, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "vschema does not contain table %s in keyspace %s", name, ksName) @@ -226,19 +226,19 @@ func ApplyVSchemaDDL(ksName string, ks *vschemapb.Keyspace, ddl *sqlparser.DDL) return nil, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "vschema already contains auto inc %v on table %s in keyspace %s", table.AutoIncrement, name, ksName) } - sequence := ddl.AutoIncSpec.Sequence + sequence := ddl.GetAutoIncSpec().Sequence sequenceFqn := sequence.Name.String() if sequence.Qualifier.String() != "" { sequenceFqn = fmt.Sprintf("%s.%s", sequence.Qualifier.String(), sequenceFqn) } table.AutoIncrement = &vschemapb.AutoIncrement{ - Column: ddl.AutoIncSpec.Column.String(), + Column: ddl.GetAutoIncSpec().Column.String(), Sequence: sequenceFqn, } return ks, nil } - return nil, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "unexpected vindex ddl operation %s", ddl.Action.ToString()) + return nil, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "unexpected vindex ddl operation %s", ddl.GetAction().ToString()) } diff --git a/go/vt/vtctl/endtoend/get_schema_test.go b/go/vt/vtctl/endtoend/get_schema_test.go new file mode 100644 index 00000000000..ddb0c204048 --- /dev/null +++ b/go/vt/vtctl/endtoend/get_schema_test.go @@ -0,0 +1,235 @@ +package endtoend + +import ( + "context" + "fmt" + "testing" + + "github.com/google/uuid" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "vitess.io/vitess/go/json2" + "vitess.io/vitess/go/vt/logutil" + "vitess.io/vitess/go/vt/topo/memorytopo" + "vitess.io/vitess/go/vt/topo/topoproto" + "vitess.io/vitess/go/vt/vtctl" + "vitess.io/vitess/go/vt/vttablet/faketmclient" + "vitess.io/vitess/go/vt/vttablet/tmclient" + "vitess.io/vitess/go/vt/wrangler" + + querypb "vitess.io/vitess/go/vt/proto/query" + tabletmanagerdatapb "vitess.io/vitess/go/vt/proto/tabletmanagerdata" + topodatapb "vitess.io/vitess/go/vt/proto/topodata" +) + +type fakeTabletManagerClient struct { + tmclient.TabletManagerClient + schemas map[string]*tabletmanagerdatapb.SchemaDefinition +} + +func newTMClient() *fakeTabletManagerClient { + return &fakeTabletManagerClient{ + TabletManagerClient: faketmclient.NewFakeTabletManagerClient(), + schemas: map[string]*tabletmanagerdatapb.SchemaDefinition{}, + } +} + +func (c *fakeTabletManagerClient) GetSchema(ctx context.Context, tablet *topodatapb.Tablet, tablets []string, excludeTables []string, includeViews bool) (*tabletmanagerdatapb.SchemaDefinition, error) { + key := topoproto.TabletAliasString(tablet.Alias) + + schema, ok := c.schemas[key] + if !ok { + return nil, fmt.Errorf("no schemas for %s", key) + } + + return schema, nil +} + +func TestGetSchema(t *testing.T) { + ctx := context.Background() + + topo := memorytopo.NewServer("zone1", "zone2", "zone3") + + tablet := &topodatapb.Tablet{ + Alias: &topodatapb.TabletAlias{ + Cell: "zone1", + Uid: uuid.New().ID(), + }, + Hostname: "abcd", + Keyspace: "testkeyspace", + Shard: "-", + Type: topodatapb.TabletType_MASTER, + } + require.NoError(t, topo.CreateTablet(ctx, tablet)) + + sd := &tabletmanagerdatapb.SchemaDefinition{ + TableDefinitions: []*tabletmanagerdatapb.TableDefinition{ + { + Name: "foo", + RowCount: 1000, + DataLength: 1000000, + Schema: `CREATE TABLE foo ( + id INT(11) NOT NULL, + name VARCHAR(255) NOT NULL, + PRIMARY KEY(id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4`, + Columns: []string{ + "id", + "name", + }, + PrimaryKeyColumns: []string{ + "id", + }, + Fields: []*querypb.Field{ + { + Name: "id", + Type: querypb.Type_INT32, + Table: "foo", + OrgTable: "foo", + Database: "vt_testkeyspace", + OrgName: "id", + ColumnLength: 11, + Charset: 63, + Decimals: 0, + }, + { + Name: "name", + Type: querypb.Type_VARCHAR, + Table: "foo", + OrgTable: "foo", + Database: "vt_testkeyspace", + OrgName: "name", + ColumnLength: 1020, + Charset: 45, + Decimals: 0, + }, + }, + }, + { + Name: "bar", + RowCount: 1, + DataLength: 10, + Schema: `CREATE TABLE bar ( + id INT(11) NOT NULL + foo_id INT(11) NOT NULL + is_active TINYINT(1) NOT NULL DEFAULT 1 +) ENGINE=InnoDB`, + Columns: []string{ + "id", + "foo_id", + "is_active", + }, + PrimaryKeyColumns: []string{ + "id", + }, + Fields: []*querypb.Field{ + { + Name: "id", + Type: querypb.Type_INT32, + Table: "bar", + OrgTable: "bar", + Database: "vt_testkeyspace", + OrgName: "id", + ColumnLength: 11, + Charset: 63, + Decimals: 0, + }, + { + Name: "foo_id", + Type: querypb.Type_INT32, + Table: "bar", + OrgTable: "bar", + Database: "vt_testkeyspace", + OrgName: "foo_id", + ColumnLength: 11, + Charset: 63, + Decimals: 0, + }, + { + Name: "is_active", + Type: querypb.Type_INT8, + Table: "bar", + OrgTable: "bar", + Database: "vt_testkeyspace", + OrgName: "is_active", + ColumnLength: 1, + Charset: 63, + Decimals: 0, + }, + }, + }, + }, + } + + tmc := newTMClient() + tmc.schemas[topoproto.TabletAliasString(tablet.Alias)] = sd + + logger := logutil.NewMemoryLogger() + + err := vtctl.RunCommand(ctx, wrangler.New(logger, topo, tmc), []string{ + "GetSchema", + topoproto.TabletAliasString(tablet.Alias), + }) + require.NoError(t, err) + + events := logger.Events + assert.Equal(t, 1, len(events), "expected 1 event from GetSchema") + val := events[0].Value + + actual := &tabletmanagerdatapb.SchemaDefinition{} + err = json2.Unmarshal([]byte(val), actual) + require.NoError(t, err) + + assert.Equal(t, sd, actual) + + // reset for the next invocation, where we verify that passing + // -table_sizes_only does not include the create table statement or columns. + logger.Events = nil + sd = &tabletmanagerdatapb.SchemaDefinition{ + TableDefinitions: []*tabletmanagerdatapb.TableDefinition{ + { + Name: "foo", + RowCount: 1000, + DataLength: 1000000, + Columns: []string{}, + PrimaryKeyColumns: []string{}, + Fields: []*querypb.Field{}, + }, + { + Name: "bar", + RowCount: 1, + DataLength: 10, + Columns: []string{}, + PrimaryKeyColumns: []string{}, + Fields: []*querypb.Field{}, + }, + }, + } + + err = vtctl.RunCommand(ctx, wrangler.New(logger, topo, tmc), []string{ + "GetSchema", + "-table_sizes_only", + topoproto.TabletAliasString(tablet.Alias), + }) + require.NoError(t, err) + + events = logger.Events + assert.Equal(t, 1, len(events), "expected 1 event from GetSchema") + val = events[0].Value + + actual = &tabletmanagerdatapb.SchemaDefinition{} + err = json2.Unmarshal([]byte(val), actual) + require.NoError(t, err) + + assert.Equal(t, sd, actual) +} + +func init() { + // enforce we will use the right protocol (gRPC) (note the + // client is unused, but it is initialized, so it needs to exist) + *tmclient.TabletManagerProtocol = "grpc" + tmclient.RegisterTabletManagerClientFactory("grpc", func() tmclient.TabletManagerClient { + return nil + }) +} diff --git a/go/vt/vtctl/vtctl.go b/go/vt/vtctl/vtctl.go index 37cc4ea4723..33b66033b62 100644 --- a/go/vt/vtctl/vtctl.go +++ b/go/vt/vtctl/vtctl.go @@ -117,6 +117,7 @@ import ( "vitess.io/vitess/go/vt/wrangler" replicationdatapb "vitess.io/vitess/go/vt/proto/replicationdata" + tabletmanagerdatapb "vitess.io/vitess/go/vt/proto/tabletmanagerdata" topodatapb "vitess.io/vitess/go/vt/proto/topodata" vschemapb "vitess.io/vitess/go/vt/proto/vschema" vtctldatapb "vitess.io/vitess/go/vt/proto/vtctldata" @@ -406,8 +407,8 @@ var commands = []commandGroup{ "[-exclude_tables=''] [-include-views] [-skip-no-master] ", "Validates that the master schema from shard 0 matches the schema on all of the other tablets in the keyspace."}, {"ApplySchema", commandApplySchema, - "[-allow_long_unavailability] [-wait_replicas_timeout=10s] {-sql= || -sql-file=} ", - "Applies the schema change to the specified keyspace on every master, running in parallel on all shards. The changes are then propagated to replicas via replication. If -allow_long_unavailability is set, schema changes affecting a large number of rows (and possibly incurring a longer period of unavailability) will not be rejected."}, + "[-allow_long_unavailability] [-wait_replicas_timeout=10s] [-ddl_strategy=] {-sql= || -sql-file=} ", + "Applies the schema change to the specified keyspace on every master, running in parallel on all shards. The changes are then propagated to replicas via replication. If -allow_long_unavailability is set, schema changes affecting a large number of rows (and possibly incurring a longer period of unavailability) will not be rejected. ddl_strategy is used to intruct migrations via gh-ost or pt-osc with optional parameters"}, {"CopySchemaShard", commandCopySchemaShard, "[-tables=,,...] [-exclude_tables=,,...] [-include-views] [-skip-verify] [-wait_replicas_timeout=10s] { || } ", "Copies the schema from a source shard's master (or a specific tablet) to a destination shard. The schema is applied directly on the master of the destination shard, and it is propagated to the replicas through binlogs."}, @@ -1909,19 +1910,32 @@ func commandMoveTables(ctx context.Context, wr *wrangler.Wrangler, subFlags *fla workflow := subFlags.String("workflow", "", "Workflow name. Can be any descriptive string. Will be used to later migrate traffic via SwitchReads/SwitchWrites.") cells := subFlags.String("cells", "", "Cell(s) or CellAlias(es) (comma-separated) to replicate from.") tabletTypes := subFlags.String("tablet_types", "", "Source tablet types to replicate from (e.g. master, replica, rdonly). Defaults to -vreplication_tablet_type parameter value for the tablet, which has the default value of replica.") + allTables := subFlags.Bool("all", false, "Move all tables from the source keyspace") + excludes := subFlags.String("exclude", "", "Tables to exclude (comma-separated) if -all is specified") + if err := subFlags.Parse(args); err != nil { return err } if *workflow == "" { return fmt.Errorf("a workflow name must be specified") } - if subFlags.NArg() != 3 { - return fmt.Errorf("three arguments are required: source_keyspace, target_keyspace, tableSpecs") + if !*allTables && len(*excludes) > 0 { + return fmt.Errorf("you can only specify tables to exclude if all tables are to be moved (with -all)") } + if *allTables { + if subFlags.NArg() != 2 { + return fmt.Errorf("two arguments are required: source_keyspace, target_keyspace") + } + } else { + if subFlags.NArg() != 3 { + return fmt.Errorf("three arguments are required: source_keyspace, target_keyspace, tableSpecs") + } + } + source := subFlags.Arg(0) target := subFlags.Arg(1) tableSpecs := subFlags.Arg(2) - return wr.MoveTables(ctx, *workflow, source, target, tableSpecs, *cells, *tabletTypes) + return wr.MoveTables(ctx, *workflow, source, target, tableSpecs, *cells, *tabletTypes, *allTables, *excludes) } func commandCreateLookupVindex(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { @@ -2301,6 +2315,8 @@ func commandGetSchema(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag excludeTables := subFlags.String("exclude_tables", "", "Specifies a comma-separated list of tables to exclude. Each is either an exact match, or a regular expression of the form /regexp/") includeViews := subFlags.Bool("include-views", false, "Includes views in the output") tableNamesOnly := subFlags.Bool("table_names_only", false, "Only displays table names that match") + tableSizesOnly := subFlags.Bool("table_sizes_only", false, "Only displays size information for tables. Ignored if -table_names_only is passed.") + if err := subFlags.Parse(args); err != nil { return err } @@ -2330,6 +2346,21 @@ func commandGetSchema(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag } return nil } + + if *tableSizesOnly { + sizeTds := make([]*tabletmanagerdatapb.TableDefinition, len(sd.TableDefinitions)) + for i, td := range sd.TableDefinitions { + sizeTds[i] = &tabletmanagerdatapb.TableDefinition{ + Name: td.Name, + Type: td.Type, + RowCount: td.RowCount, + DataLength: td.DataLength, + } + } + + sd.TableDefinitions = sizeTds + } + return printJSON(wr.Logger(), sd) } @@ -2422,6 +2453,7 @@ func commandApplySchema(ctx context.Context, wr *wrangler.Wrangler, subFlags *fl allowLongUnavailability := subFlags.Bool("allow_long_unavailability", false, "Allow large schema changes which incur a longer unavailability of the database.") sql := subFlags.String("sql", "", "A list of semicolon-delimited SQL commands") sqlFile := subFlags.String("sql-file", "", "Identifies the file that contains the SQL commands") + ddlStrategy := subFlags.String("ddl_strategy", "", "Online DDL strategy, compatible with @@ddl_strategy session variable (examples: 'gh-ost', 'pt-osc', 'gh-ost --max-load=Threads_running=100'") // for backwards compatibility deprecatedTimeout := subFlags.Duration("wait_slave_timeout", wrangler.DefaultWaitReplicasTimeout, "DEPRECATED -- use -wait_replicas_timeout") waitReplicasTimeout := subFlags.Duration("wait_replicas_timeout", wrangler.DefaultWaitReplicasTimeout, "The amount of time to wait for replicas to receive the schema change via replication.") @@ -2445,6 +2477,10 @@ func commandApplySchema(ctx context.Context, wr *wrangler.Wrangler, subFlags *fl if *allowLongUnavailability { executor.AllowBigSchemaChange() } + if err := executor.SetDDLStrategy(*ddlStrategy); err != nil { + return nil + } + return schemamanager.Run( ctx, schemamanager.NewPlainController(change, keyspace), @@ -2731,7 +2767,7 @@ func commandApplyVSchema(ctx context.Context, wr *wrangler.Wrangler, subFlags *f if err != nil { return fmt.Errorf("error parsing vschema statement `%s`: %v", *sql, err) } - ddl, ok := stmt.(*sqlparser.DDL) + ddl, ok := stmt.(sqlparser.DDLStatement) if !ok { return fmt.Errorf("error parsing vschema statement `%s`: not a ddl statement", *sql) } diff --git a/go/vt/vtexplain/testdata/multi-output/deletesharded-output.txt b/go/vt/vtexplain/testdata/multi-output/deletesharded-output.txt index 73db1a50d6e..c3b32309a6e 100644 --- a/go/vt/vtexplain/testdata/multi-output/deletesharded-output.txt +++ b/go/vt/vtexplain/testdata/multi-output/deletesharded-output.txt @@ -16,9 +16,9 @@ delete from music_extra where id=1 and extra='abc' delete from user where id=1 1 ks_sharded/-40: begin -1 ks_sharded/-40: select id, name from user where id = 1 limit 10001 for update +1 ks_sharded/-40: select id, `name` from user where id = 1 limit 10001 for update 2 ks_sharded/40-80: begin -2 ks_sharded/40-80: delete from name_user_map where name = 'name_val_2' and user_id = 1 limit 10001 +2 ks_sharded/40-80: delete from name_user_map where `name` = 'name_val_2' and user_id = 1 limit 10001 3 ks_sharded/-40: delete from user where id = 1 limit 10001 4 ks_sharded/-40: commit 5 ks_sharded/40-80: commit @@ -27,12 +27,12 @@ delete from user where id=1 delete from user where name='billy' 1 ks_sharded/c0-: begin -1 ks_sharded/c0-: select name, user_id from name_user_map where name in ('billy') limit 10001 for update +1 ks_sharded/c0-: select `name`, user_id from name_user_map where `name` in ('billy') limit 10001 for update 2 ks_sharded/-40: begin -2 ks_sharded/-40: select id, name from user where name = 'billy' limit 10001 for update +2 ks_sharded/-40: select id, `name` from user where `name` = 'billy' limit 10001 for update 3 ks_sharded/40-80: begin -3 ks_sharded/40-80: delete from name_user_map where name = 'name_val_2' and user_id = 1 limit 10001 -4 ks_sharded/-40: delete from user where name = 'billy' limit 10001 +3 ks_sharded/40-80: delete from name_user_map where `name` = 'name_val_2' and user_id = 1 limit 10001 +4 ks_sharded/-40: delete from user where `name` = 'billy' limit 10001 5 ks_sharded/c0-: commit 6 ks_sharded/-40: commit 7 ks_sharded/40-80: commit diff --git a/go/vt/vtexplain/testdata/multi-output/insertsharded-output.txt b/go/vt/vtexplain/testdata/multi-output/insertsharded-output.txt index e9779e78b4b..c43ebac4000 100644 --- a/go/vt/vtexplain/testdata/multi-output/insertsharded-output.txt +++ b/go/vt/vtexplain/testdata/multi-output/insertsharded-output.txt @@ -2,9 +2,9 @@ insert into user (id, name) values(1, 'alice') 1 ks_sharded/40-80: begin -1 ks_sharded/40-80: insert into name_user_map(name, user_id) values ('alice', 1) +1 ks_sharded/40-80: insert into name_user_map(`name`, user_id) values ('alice', 1) 2 ks_sharded/-40: begin -2 ks_sharded/-40: insert into user(id, name) values (1, 'alice') +2 ks_sharded/-40: insert into user(id, `name`) values (1, 'alice') 3 ks_sharded/40-80: commit 4 ks_sharded/-40: commit @@ -12,9 +12,9 @@ insert into user (id, name) values(1, 'alice') insert into user (id, name) values(2, 'bob') 1 ks_sharded/c0-: begin -1 ks_sharded/c0-: insert into name_user_map(name, user_id) values ('bob', 2) +1 ks_sharded/c0-: insert into name_user_map(`name`, user_id) values ('bob', 2) 2 ks_sharded/-40: begin -2 ks_sharded/-40: insert into user(id, name) values (2, 'bob') +2 ks_sharded/-40: insert into user(id, `name`) values (2, 'bob') 3 ks_sharded/c0-: commit 4 ks_sharded/-40: commit @@ -22,10 +22,10 @@ insert into user (id, name) values(2, 'bob') insert ignore into user (id, name) values(2, 'bob') 1 ks_sharded/c0-: begin -1 ks_sharded/c0-: insert ignore into name_user_map(name, user_id) values ('bob', 2) -2 ks_sharded/c0-: select name from name_user_map where name = 'bob' and user_id = 2 limit 10001 +1 ks_sharded/c0-: insert ignore into name_user_map(`name`, user_id) values ('bob', 2) +2 ks_sharded/c0-: select `name` from name_user_map where `name` = 'bob' and user_id = 2 limit 10001 3 ks_sharded/-40: begin -3 ks_sharded/-40: insert ignore into user(id, name) values (2, 'bob') +3 ks_sharded/-40: insert ignore into user(id, `name`) values (2, 'bob') 4 ks_sharded/c0-: commit 5 ks_sharded/-40: commit @@ -33,10 +33,10 @@ insert ignore into user (id, name) values(2, 'bob') insert ignore into user (id, name, nickname) values(2, 'bob', 'bob') 1 ks_sharded/c0-: begin -1 ks_sharded/c0-: insert ignore into name_user_map(name, user_id) values ('bob', 2) -2 ks_sharded/c0-: select name from name_user_map where name = 'bob' and user_id = 2 limit 10001 +1 ks_sharded/c0-: insert ignore into name_user_map(`name`, user_id) values ('bob', 2) +2 ks_sharded/c0-: select `name` from name_user_map where `name` = 'bob' and user_id = 2 limit 10001 3 ks_sharded/-40: begin -3 ks_sharded/-40: insert ignore into user(id, name, nickname) values (2, 'bob', 'bob') +3 ks_sharded/-40: insert ignore into user(id, `name`, nickname) values (2, 'bob', 'bob') 4 ks_sharded/c0-: commit 5 ks_sharded/-40: commit @@ -44,10 +44,10 @@ insert ignore into user (id, name, nickname) values(2, 'bob', 'bob') insert into user (id, name, nickname) values(2, 'bob', 'bobby') on duplicate key update nickname='bobby' 1 ks_sharded/c0-: begin -1 ks_sharded/c0-: insert ignore into name_user_map(name, user_id) values ('bob', 2) -2 ks_sharded/c0-: select name from name_user_map where name = 'bob' and user_id = 2 limit 10001 +1 ks_sharded/c0-: insert ignore into name_user_map(`name`, user_id) values ('bob', 2) +2 ks_sharded/c0-: select `name` from name_user_map where `name` = 'bob' and user_id = 2 limit 10001 3 ks_sharded/-40: begin -3 ks_sharded/-40: insert into user(id, name, nickname) values (2, 'bob', 'bobby') on duplicate key update nickname = 'bobby' +3 ks_sharded/-40: insert into user(id, `name`, nickname) values (2, 'bob', 'bobby') on duplicate key update nickname = 'bobby' 4 ks_sharded/c0-: commit 5 ks_sharded/-40: commit @@ -55,10 +55,10 @@ insert into user (id, name, nickname) values(2, 'bob', 'bobby') on duplicate key insert into user (id, name, nickname, address) values(2, 'bob', 'bobby', '123 main st') on duplicate key update nickname=values(nickname), address=values(address) 1 ks_sharded/c0-: begin -1 ks_sharded/c0-: insert ignore into name_user_map(name, user_id) values ('bob', 2) -2 ks_sharded/c0-: select name from name_user_map where name = 'bob' and user_id = 2 limit 10001 +1 ks_sharded/c0-: insert ignore into name_user_map(`name`, user_id) values ('bob', 2) +2 ks_sharded/c0-: select `name` from name_user_map where `name` = 'bob' and user_id = 2 limit 10001 3 ks_sharded/-40: begin -3 ks_sharded/-40: insert into user(id, name, nickname, address) values (2, 'bob', 'bobby', '123 main st') on duplicate key update nickname = values(nickname), address = values(address) +3 ks_sharded/-40: insert into user(id, `name`, nickname, address) values (2, 'bob', 'bobby', '123 main st') on duplicate key update nickname = values(nickname), address = values(address) 4 ks_sharded/c0-: commit 5 ks_sharded/-40: commit diff --git a/go/vt/vtexplain/testdata/multi-output/options-output.txt b/go/vt/vtexplain/testdata/multi-output/options-output.txt index 9784cf89477..21db05ab44d 100644 --- a/go/vt/vtexplain/testdata/multi-output/options-output.txt +++ b/go/vt/vtexplain/testdata/multi-output/options-output.txt @@ -17,9 +17,9 @@ select * from user where id in (1,2,3,4,5,6,7,8) insert into user (id, name) values (2, 'bob') 1 ks_sharded/c0-: begin -1 ks_sharded/c0-: insert into name_user_map(name, user_id) values ('bob', 2) +1 ks_sharded/c0-: insert into name_user_map(`name`, user_id) values ('bob', 2) 2 ks_sharded/-40: begin -2 ks_sharded/-40: insert into user(id, name) values (2, 'bob') +2 ks_sharded/-40: insert into user(id, `name`) values (2, 'bob') 3 ks_sharded/c0-: commit 4 ks_sharded/-40: commit diff --git a/go/vt/vtexplain/testdata/multi-output/selectsharded-output.txt b/go/vt/vtexplain/testdata/multi-output/selectsharded-output.txt index 9ff0438d7b8..69a10e8198c 100644 --- a/go/vt/vtexplain/testdata/multi-output/selectsharded-output.txt +++ b/go/vt/vtexplain/testdata/multi-output/selectsharded-output.txt @@ -22,28 +22,28 @@ select * from user where id > 100 /* scatter range */ ---------------------------------------------------------------------- select * from user where name = 'bob' /* vindex lookup */ -1 ks_sharded/c0-: select name, user_id from name_user_map where name in ('bob') limit 10001 /* vindex lookup */ -2 ks_sharded/-40: select * from user where name = 'bob' limit 10001 /* vindex lookup */ +1 ks_sharded/c0-: select `name`, user_id from name_user_map where `name` in ('bob') limit 10001 /* vindex lookup */ +2 ks_sharded/-40: select * from user where `name` = 'bob' limit 10001 /* vindex lookup */ ---------------------------------------------------------------------- select * from user where name = 'bob' or nickname = 'bob' /* vindex lookup */ -1 ks_sharded/-40: select * from user where name = 'bob' or nickname = 'bob' limit 10001 /* vindex lookup */ -1 ks_sharded/40-80: select * from user where name = 'bob' or nickname = 'bob' limit 10001 /* vindex lookup */ -1 ks_sharded/80-c0: select * from user where name = 'bob' or nickname = 'bob' limit 10001 /* vindex lookup */ -1 ks_sharded/c0-: select * from user where name = 'bob' or nickname = 'bob' limit 10001 /* vindex lookup */ +1 ks_sharded/-40: select * from user where `name` = 'bob' or nickname = 'bob' limit 10001 /* vindex lookup */ +1 ks_sharded/40-80: select * from user where `name` = 'bob' or nickname = 'bob' limit 10001 /* vindex lookup */ +1 ks_sharded/80-c0: select * from user where `name` = 'bob' or nickname = 'bob' limit 10001 /* vindex lookup */ +1 ks_sharded/c0-: select * from user where `name` = 'bob' or nickname = 'bob' limit 10001 /* vindex lookup */ ---------------------------------------------------------------------- select u.id, u.name, u.nickname, n.info from user u join name_info n on u.name = n.name /* join on varchar */ -1 ks_sharded/-40: select u.id, u.name, u.nickname from user as u limit 10001 /* join on varchar */ -1 ks_sharded/40-80: select u.id, u.name, u.nickname from user as u limit 10001 /* join on varchar */ -1 ks_sharded/80-c0: select u.id, u.name, u.nickname from user as u limit 10001 /* join on varchar */ -1 ks_sharded/c0-: select u.id, u.name, u.nickname from user as u limit 10001 /* join on varchar */ -2 ks_sharded/40-80: select n.info from name_info as n where n.name = 'name_val_2' limit 10001 /* join on varchar */ -3 ks_sharded/40-80: select n.info from name_info as n where n.name = 'name_val_2' limit 10001 /* join on varchar */ -4 ks_sharded/40-80: select n.info from name_info as n where n.name = 'name_val_2' limit 10001 /* join on varchar */ -5 ks_sharded/40-80: select n.info from name_info as n where n.name = 'name_val_2' limit 10001 /* join on varchar */ +1 ks_sharded/-40: select u.id, u.`name`, u.nickname from user as u limit 10001 /* join on varchar */ +1 ks_sharded/40-80: select u.id, u.`name`, u.nickname from user as u limit 10001 /* join on varchar */ +1 ks_sharded/80-c0: select u.id, u.`name`, u.nickname from user as u limit 10001 /* join on varchar */ +1 ks_sharded/c0-: select u.id, u.`name`, u.nickname from user as u limit 10001 /* join on varchar */ +2 ks_sharded/40-80: select n.info from name_info as n where n.`name` = 'name_val_2' limit 10001 /* join on varchar */ +3 ks_sharded/40-80: select n.info from name_info as n where n.`name` = 'name_val_2' limit 10001 /* join on varchar */ +4 ks_sharded/40-80: select n.info from name_info as n where n.`name` = 'name_val_2' limit 10001 /* join on varchar */ +5 ks_sharded/40-80: select n.info from name_info as n where n.`name` = 'name_val_2' limit 10001 /* join on varchar */ ---------------------------------------------------------------------- select m.id, m.song, e.extra from music m join music_extra e on m.id = e.id where m.user_id = 100 /* join on int */ @@ -59,17 +59,17 @@ select count(*) from user where id = 1 /* point aggregate */ ---------------------------------------------------------------------- select count(*) from user where name in ('alice','bob') /* scatter aggregate */ -1 ks_sharded/40-80: select name, user_id from name_user_map where name in ('alice') limit 10001 /* scatter aggregate */ -1 ks_sharded/c0-: select name, user_id from name_user_map where name in ('bob') limit 10001 /* scatter aggregate */ -2 ks_sharded/-40: select count(*) from user where name in ('alice', 'bob') limit 10001 /* scatter aggregate */ +1 ks_sharded/40-80: select `name`, user_id from name_user_map where `name` in ('alice') limit 10001 /* scatter aggregate */ +1 ks_sharded/c0-: select `name`, user_id from name_user_map where `name` in ('bob') limit 10001 /* scatter aggregate */ +2 ks_sharded/-40: select count(*) from user where `name` in ('alice', 'bob') limit 10001 /* scatter aggregate */ ---------------------------------------------------------------------- select name, count(*) from user group by name /* scatter aggregate */ -1 ks_sharded/-40: select name, count(*) from user group by name limit 10001 /* scatter aggregate */ -1 ks_sharded/40-80: select name, count(*) from user group by name limit 10001 /* scatter aggregate */ -1 ks_sharded/80-c0: select name, count(*) from user group by name limit 10001 /* scatter aggregate */ -1 ks_sharded/c0-: select name, count(*) from user group by name limit 10001 /* scatter aggregate */ +1 ks_sharded/-40: select `name`, count(*) from user group by `name` limit 10001 /* scatter aggregate */ +1 ks_sharded/40-80: select `name`, count(*) from user group by `name` limit 10001 /* scatter aggregate */ +1 ks_sharded/80-c0: select `name`, count(*) from user group by `name` limit 10001 /* scatter aggregate */ +1 ks_sharded/c0-: select `name`, count(*) from user group by `name` limit 10001 /* scatter aggregate */ ---------------------------------------------------------------------- select 1, "hello", 3.14, null from user limit 10 /* select constant sql values */ @@ -91,74 +91,74 @@ select * from (select id from user) s /* scatter paren select */ select name from user where id = (select id from t1) /* non-correlated subquery as value */ 1 ks_unsharded/-: select id from t1 limit 10001 /* non-correlated subquery as value */ -2 ks_sharded/-40: select name from user where id = 1 limit 10001 /* non-correlated subquery as value */ +2 ks_sharded/-40: select `name` from user where id = 1 limit 10001 /* non-correlated subquery as value */ ---------------------------------------------------------------------- select name from user where id in (select id from t1) /* non-correlated subquery in IN clause */ 1 ks_unsharded/-: select id from t1 limit 10001 /* non-correlated subquery in IN clause */ -2 ks_sharded/-40: select name from user where 1 = 1 and id in (1) limit 10001 /* non-correlated subquery in IN clause */ +2 ks_sharded/-40: select `name` from user where 1 = 1 and id in (1) limit 10001 /* non-correlated subquery in IN clause */ ---------------------------------------------------------------------- select name from user where id not in (select id from t1) /* non-correlated subquery in NOT IN clause */ 1 ks_unsharded/-: select id from t1 limit 10001 /* non-correlated subquery in NOT IN clause */ -2 ks_sharded/-40: select name from user where 1 = 0 or id not in (1) limit 10001 /* non-correlated subquery in NOT IN clause */ -2 ks_sharded/40-80: select name from user where 1 = 0 or id not in (1) limit 10001 /* non-correlated subquery in NOT IN clause */ -2 ks_sharded/80-c0: select name from user where 1 = 0 or id not in (1) limit 10001 /* non-correlated subquery in NOT IN clause */ -2 ks_sharded/c0-: select name from user where 1 = 0 or id not in (1) limit 10001 /* non-correlated subquery in NOT IN clause */ +2 ks_sharded/-40: select `name` from user where 1 = 0 or id not in (1) limit 10001 /* non-correlated subquery in NOT IN clause */ +2 ks_sharded/40-80: select `name` from user where 1 = 0 or id not in (1) limit 10001 /* non-correlated subquery in NOT IN clause */ +2 ks_sharded/80-c0: select `name` from user where 1 = 0 or id not in (1) limit 10001 /* non-correlated subquery in NOT IN clause */ +2 ks_sharded/c0-: select `name` from user where 1 = 0 or id not in (1) limit 10001 /* non-correlated subquery in NOT IN clause */ ---------------------------------------------------------------------- select name from user where exists (select id from t1) /* non-correlated subquery as EXISTS */ 1 ks_unsharded/-: select id from t1 limit 10001 /* non-correlated subquery as EXISTS */ -2 ks_sharded/-40: select name from user where 1 limit 10001 /* non-correlated subquery as EXISTS */ -2 ks_sharded/40-80: select name from user where 1 limit 10001 /* non-correlated subquery as EXISTS */ -2 ks_sharded/80-c0: select name from user where 1 limit 10001 /* non-correlated subquery as EXISTS */ -2 ks_sharded/c0-: select name from user where 1 limit 10001 /* non-correlated subquery as EXISTS */ +2 ks_sharded/-40: select `name` from user where 1 limit 10001 /* non-correlated subquery as EXISTS */ +2 ks_sharded/40-80: select `name` from user where 1 limit 10001 /* non-correlated subquery as EXISTS */ +2 ks_sharded/80-c0: select `name` from user where 1 limit 10001 /* non-correlated subquery as EXISTS */ +2 ks_sharded/c0-: select `name` from user where 1 limit 10001 /* non-correlated subquery as EXISTS */ ---------------------------------------------------------------------- select * from name_info order by info /* select * and order by varchar column */ -1 ks_sharded/-40: select name, info, weight_string(info) from name_info order by info asc limit 10001 /* select * and order by varchar column */ -1 ks_sharded/40-80: select name, info, weight_string(info) from name_info order by info asc limit 10001 /* select * and order by varchar column */ -1 ks_sharded/80-c0: select name, info, weight_string(info) from name_info order by info asc limit 10001 /* select * and order by varchar column */ -1 ks_sharded/c0-: select name, info, weight_string(info) from name_info order by info asc limit 10001 /* select * and order by varchar column */ +1 ks_sharded/-40: select `name`, info, weight_string(info) from name_info order by info asc limit 10001 /* select * and order by varchar column */ +1 ks_sharded/40-80: select `name`, info, weight_string(info) from name_info order by info asc limit 10001 /* select * and order by varchar column */ +1 ks_sharded/80-c0: select `name`, info, weight_string(info) from name_info order by info asc limit 10001 /* select * and order by varchar column */ +1 ks_sharded/c0-: select `name`, info, weight_string(info) from name_info order by info asc limit 10001 /* select * and order by varchar column */ ---------------------------------------------------------------------- select distinct(name) from user where id = 1 /* select distinct */ -1 ks_sharded/-40: select distinct name from user where id = 1 limit 10001 /* select distinct */ +1 ks_sharded/-40: select distinct `name` from user where id = 1 limit 10001 /* select distinct */ ---------------------------------------------------------------------- select distinct name from user where id = 1 /* select distinct */ -1 ks_sharded/-40: select distinct name from user where id = 1 limit 10001 /* select distinct */ +1 ks_sharded/-40: select distinct `name` from user where id = 1 limit 10001 /* select distinct */ ---------------------------------------------------------------------- select id, substring(name, 1, -1) from user where id = 123 /* select substring */ -1 ks_sharded/-40: select id, substr(name, 1, -1) from user where id = 123 limit 10001 /* select substring */ +1 ks_sharded/-40: select id, substr(`name`, 1, -1) from user where id = 123 limit 10001 /* select substring */ ---------------------------------------------------------------------- select id, substring_index(name, '123456', -1) from user where id = 123 /* select substring_index */ -1 ks_sharded/-40: select id, substring_index(name, '123456', -1) from user where id = 123 limit 10001 /* select substring_index */ +1 ks_sharded/-40: select id, substring_index(`name`, '123456', -1) from user where id = 123 limit 10001 /* select substring_index */ ---------------------------------------------------------------------- select id, case when name = 'alice' then 'ALICE' when name = 'bob' then 'BOB' end as name from user where id = 1 /* select case */ -1 ks_sharded/-40: select id, case when name = 'alice' then 'ALICE' when name = 'bob' then 'BOB' end as name from user where id = 1 limit 10001 /* select case */ +1 ks_sharded/-40: select id, case when `name` = 'alice' then 'ALICE' when `name` = 'bob' then 'BOB' end as `name` from user where id = 1 limit 10001 /* select case */ ---------------------------------------------------------------------- select id, case when name = 'alice' then 'ALICE' when name = 'bob' then 'BOB' else 'OTHER' end as name from user where id = 1 /* select case */ -1 ks_sharded/-40: select id, case when name = 'alice' then 'ALICE' when name = 'bob' then 'BOB' else 'OTHER' end as name from user where id = 1 limit 10001 /* select case */ +1 ks_sharded/-40: select id, case when `name` = 'alice' then 'ALICE' when `name` = 'bob' then 'BOB' else 'OTHER' end as `name` from user where id = 1 limit 10001 /* select case */ ---------------------------------------------------------------------- select id, case when substr(name, 1, 5) = 'alice' then 'ALICE' when name = 'bob' then 'BOB' else 'OTHER' end as name from user where id = 1 /* select case */ -1 ks_sharded/-40: select id, case when substr(name, 1, 5) = 'alice' then 'ALICE' when name = 'bob' then 'BOB' else 'OTHER' end as name from user where id = 1 limit 10001 /* select case */ +1 ks_sharded/-40: select id, case when substr(`name`, 1, 5) = 'alice' then 'ALICE' when `name` = 'bob' then 'BOB' else 'OTHER' end as `name` from user where id = 1 limit 10001 /* select case */ ---------------------------------------------------------------------- select id, 'abc' as test from user where id = 1 union all select id, 'def' as test from user where id = 1 union all select id, 'ghi' as test from user where id = 1 /* union all */ diff --git a/go/vt/vtexplain/testdata/multi-output/target-output.txt b/go/vt/vtexplain/testdata/multi-output/target-output.txt index 3e767f4dde3..4a99a3485e4 100644 --- a/go/vt/vtexplain/testdata/multi-output/target-output.txt +++ b/go/vt/vtexplain/testdata/multi-output/target-output.txt @@ -11,6 +11,6 @@ select * from user where id in (1,2,3,4,5,6,7,8) ---------------------------------------------------------------------- insert into user (id, name) values (2, 'bob') -1 ks_sharded/40-80: insert into user(id, name) values (2, 'bob') +1 ks_sharded/40-80: insert into user(id, `name`) values (2, 'bob') ---------------------------------------------------------------------- diff --git a/go/vt/vtexplain/testdata/multi-output/updatesharded-output.txt b/go/vt/vtexplain/testdata/multi-output/updatesharded-output.txt index 9df3b3f352a..4d952c6ba3e 100644 --- a/go/vt/vtexplain/testdata/multi-output/updatesharded-output.txt +++ b/go/vt/vtexplain/testdata/multi-output/updatesharded-output.txt @@ -9,9 +9,9 @@ update user set nickname='alice' where id=1 update user set nickname='alice' where name='alice' 1 ks_sharded/40-80: begin -1 ks_sharded/40-80: select name, user_id from name_user_map where name in ('alice') limit 10001 for update +1 ks_sharded/40-80: select `name`, user_id from name_user_map where `name` in ('alice') limit 10001 for update 2 ks_sharded/-40: begin -2 ks_sharded/-40: update user set nickname = 'alice' where name = 'alice' limit 10001 +2 ks_sharded/-40: update user set nickname = 'alice' where `name` = 'alice' limit 10001 3 ks_sharded/40-80: commit 4 ks_sharded/-40: commit @@ -26,12 +26,12 @@ update user set pet='fido' where id=1 update user set name='alicia' where id=1 1 ks_sharded/-40: begin -1 ks_sharded/-40: select id, name, name = 'alicia' from user where id = 1 limit 10001 for update +1 ks_sharded/-40: select id, `name`, `name` = 'alicia' from user where id = 1 limit 10001 for update 2 ks_sharded/40-80: begin -2 ks_sharded/40-80: delete from name_user_map where name = 'name_val_2' and user_id = 1 limit 10001 +2 ks_sharded/40-80: delete from name_user_map where `name` = 'name_val_2' and user_id = 1 limit 10001 3 ks_sharded/c0-: begin -3 ks_sharded/c0-: insert into name_user_map(name, user_id) values ('alicia', 1) -4 ks_sharded/-40: update user set name = 'alicia' where id = 1 limit 10001 +3 ks_sharded/c0-: insert into name_user_map(`name`, user_id) values ('alicia', 1) +4 ks_sharded/-40: update user set `name` = 'alicia' where id = 1 limit 10001 5 ks_sharded/-40: commit 6 ks_sharded/40-80: commit 7 ks_sharded/c0-: commit @@ -40,13 +40,13 @@ update user set name='alicia' where id=1 update user set name='alicia' where name='alice' 1 ks_sharded/40-80: begin -1 ks_sharded/40-80: select name, user_id from name_user_map where name in ('alice') limit 10001 for update +1 ks_sharded/40-80: select `name`, user_id from name_user_map where `name` in ('alice') limit 10001 for update 2 ks_sharded/-40: begin -2 ks_sharded/-40: select id, name, name = 'alicia' from user where name = 'alice' limit 10001 for update -3 ks_sharded/40-80: delete from name_user_map where name = 'name_val_2' and user_id = 1 limit 10001 +2 ks_sharded/-40: select id, `name`, `name` = 'alicia' from user where `name` = 'alice' limit 10001 for update +3 ks_sharded/40-80: delete from name_user_map where `name` = 'name_val_2' and user_id = 1 limit 10001 4 ks_sharded/c0-: begin -4 ks_sharded/c0-: insert into name_user_map(name, user_id) values ('alicia', 1) -5 ks_sharded/-40: update user set name = 'alicia' where name = 'alice' limit 10001 +4 ks_sharded/c0-: insert into name_user_map(`name`, user_id) values ('alicia', 1) +5 ks_sharded/-40: update user set `name` = 'alicia' where `name` = 'alice' limit 10001 6 ks_sharded/40-80: commit 7 ks_sharded/-40: commit 8 ks_sharded/c0-: commit @@ -71,9 +71,9 @@ update /*vt+ MULTI_SHARD_AUTOCOMMIT=1 */ name_info set has_nickname=1 where nick update user set pet='rover' where name='alice' 1 ks_sharded/40-80: begin -1 ks_sharded/40-80: select name, user_id from name_user_map where name in ('alice') limit 10001 for update +1 ks_sharded/40-80: select `name`, user_id from name_user_map where `name` in ('alice') limit 10001 for update 2 ks_sharded/-40: begin -2 ks_sharded/-40: update user set pet = 'rover' where name = 'alice' limit 10001 +2 ks_sharded/-40: update user set pet = 'rover' where `name` = 'alice' limit 10001 3 ks_sharded/40-80: commit 4 ks_sharded/-40: commit diff --git a/go/vt/vtexplain/vtexplain.go b/go/vt/vtexplain/vtexplain.go index 63a384c79c9..6c4476ebbf3 100644 --- a/go/vt/vtexplain/vtexplain.go +++ b/go/vt/vtexplain/vtexplain.go @@ -181,8 +181,8 @@ func Stop() { } } -func parseSchema(sqlSchema string, opts *Options) ([]*sqlparser.DDL, error) { - parsedDDLs := make([]*sqlparser.DDL, 0, 16) +func parseSchema(sqlSchema string, opts *Options) ([]sqlparser.DDLStatement, error) { + parsedDDLs := make([]sqlparser.DDLStatement, 0, 16) for { sql, rem, err := sqlparser.SplitStatement(sqlSchema) sqlSchema = rem @@ -210,16 +210,16 @@ func parseSchema(sqlSchema string, opts *Options) ([]*sqlparser.DDL, error) { continue } } - ddl, ok := stmt.(*sqlparser.DDL) + ddl, ok := stmt.(sqlparser.DDLStatement) if !ok { log.Infof("ignoring non-DDL statement: %s", sql) continue } - if ddl.Action != sqlparser.CreateDDLAction { - log.Infof("ignoring %s table statement", ddl.Action.ToString()) + if ddl.GetAction() != sqlparser.CreateDDLAction { + log.Infof("ignoring %s table statement", ddl.GetAction().ToString()) continue } - if ddl.TableSpec == nil && ddl.OptLike == nil { + if ddl.GetTableSpec() == nil && ddl.GetOptLike() == nil { log.Errorf("invalid create table statement: %s", sql) continue } diff --git a/go/vt/vtexplain/vtexplain_vttablet.go b/go/vt/vtexplain/vtexplain_vttablet.go index 6cd44416bb2..193da213c16 100644 --- a/go/vt/vtexplain/vtexplain_vttablet.go +++ b/go/vt/vtexplain/vtexplain_vttablet.go @@ -270,7 +270,7 @@ func (t *explainTablet) Close(ctx context.Context) error { return t.tsv.Close(ctx) } -func initTabletEnvironment(ddls []*sqlparser.DDL, opts *Options) error { +func initTabletEnvironment(ddls []sqlparser.DDLStatement, opts *Options) error { tableColumns = make(map[string]map[string]querypb.Type) schemaQueries = map[string]*sqltypes.Result{ "select unix_timestamp()": { @@ -370,7 +370,7 @@ func initTabletEnvironment(ddls []*sqlparser.DDL, opts *Options) error { showTableRows := make([][]sqltypes.Value, 0, 4) for _, ddl := range ddls { - table := ddl.Table.Name.String() + table := ddl.GetTable().Name.String() showTableRows = append(showTableRows, mysql.BaseShowTablesRow(table, false, "")) } schemaQueries[mysql.BaseShowTables] = &sqltypes.Result{ @@ -380,17 +380,17 @@ func initTabletEnvironment(ddls []*sqlparser.DDL, opts *Options) error { indexRows := make([][]sqltypes.Value, 0, 4) for _, ddl := range ddls { - table := sqlparser.String(ddl.Table.Name) + table := sqlparser.String(ddl.GetTable().Name) - if ddl.OptLike != nil { - likeTable := ddl.OptLike.LikeTable.Name.String() + if ddl.GetOptLike() != nil { + likeTable := ddl.GetOptLike().LikeTable.Name.String() if _, ok := schemaQueries["select * from "+likeTable+" where 1 != 1"]; !ok { return fmt.Errorf("check your schema, table[%s] doesn't exist", likeTable) } schemaQueries["select * from "+table+" where 1 != 1"] = schemaQueries["select * from "+likeTable+" where 1 != 1"] continue } - for _, idx := range ddl.TableSpec.Indexes { + for _, idx := range ddl.GetTableSpec().Indexes { if !idx.Info.Primary { continue } @@ -402,7 +402,7 @@ func initTabletEnvironment(ddls []*sqlparser.DDL, opts *Options) error { tableColumns[table] = make(map[string]querypb.Type) var rowTypes []*querypb.Field - for _, col := range ddl.TableSpec.Columns { + for _, col := range ddl.GetTableSpec().Columns { colName := strings.ToLower(col.Name.String()) rowType := &querypb.Field{ Name: colName, diff --git a/go/vt/vtgate/autocommit_test.go b/go/vt/vtgate/autocommit_test.go index b5576adb3ab..87b0c3d3512 100644 --- a/go/vt/vtgate/autocommit_test.go +++ b/go/vt/vtgate/autocommit_test.go @@ -93,14 +93,14 @@ func TestAutocommitUpdateVindexChange(t *testing.T) { require.NoError(t, err) testQueries(t, "sbclookup", sbclookup, []*querypb.BoundQuery{{ - Sql: "delete from name_lastname_keyspace_id_map where name = :name and lastname = :lastname and keyspace_id = :keyspace_id", + Sql: "delete from name_lastname_keyspace_id_map where `name` = :name and lastname = :lastname and keyspace_id = :keyspace_id", BindVariables: map[string]*querypb.BindVariable{ "lastname": sqltypes.ValueBindVariable(sqltypes.NewVarChar("foo")), "name": sqltypes.Int32BindVariable(1), "keyspace_id": sqltypes.BytesBindVariable([]byte("\026k@\264J\272K\326")), }, }, { - Sql: "insert into name_lastname_keyspace_id_map(name, lastname, keyspace_id) values (:name_0, :lastname_0, :keyspace_id_0)", + Sql: "insert into name_lastname_keyspace_id_map(`name`, lastname, keyspace_id) values (:name_0, :lastname_0, :keyspace_id_0)", BindVariables: map[string]*querypb.BindVariable{ "name_0": sqltypes.BytesBindVariable([]byte("myname")), "lastname_0": sqltypes.BytesBindVariable([]byte("mylastname")), @@ -110,10 +110,10 @@ func TestAutocommitUpdateVindexChange(t *testing.T) { testCommitCount(t, "sbclookup", sbclookup, 1) testQueries(t, "sbc", sbc, []*querypb.BoundQuery{{ - Sql: "select id, name, lastname, name = 'myname' and lastname = 'mylastname' from user2 where id = 1 for update", + Sql: "select id, `name`, lastname, `name` = 'myname' and lastname = 'mylastname' from user2 where id = 1 for update", BindVariables: map[string]*querypb.BindVariable{}, }, { - Sql: "update user2 set name = 'myname', lastname = 'mylastname' where id = 1", + Sql: "update user2 set `name` = 'myname', lastname = 'mylastname' where id = 1", BindVariables: map[string]*querypb.BindVariable{}, }}) testCommitCount(t, "sbc", sbc, 1) @@ -262,7 +262,7 @@ func TestAutocommitInsertLookup(t *testing.T) { require.NoError(t, err) testQueries(t, "sbclookup", sbclookup, []*querypb.BoundQuery{{ - Sql: "insert into name_user_map(name, user_id) values (:name_0, :user_id_0)", + Sql: "insert into name_user_map(`name`, user_id) values (:name_0, :user_id_0)", BindVariables: map[string]*querypb.BindVariable{ "name_0": sqltypes.BytesBindVariable([]byte("myname")), "user_id_0": sqltypes.Uint64BindVariable(1), @@ -271,7 +271,7 @@ func TestAutocommitInsertLookup(t *testing.T) { testCommitCount(t, "sbclookup", sbclookup, 1) testQueries(t, "sbc1", sbc1, []*querypb.BoundQuery{{ - Sql: "insert into user(id, v, name) values (:_Id_0, 2, :_name_0)", + Sql: "insert into user(id, v, `name`) values (:_Id_0, 2, :_name_0)", BindVariables: map[string]*querypb.BindVariable{ "_Id_0": sqltypes.Int64BindVariable(1), "_name_0": sqltypes.BytesBindVariable([]byte("myname")), @@ -362,7 +362,7 @@ func TestAutocommitInsertAutoinc(t *testing.T) { Sql: "select next :n values from user_seq", BindVariables: map[string]*querypb.BindVariable{"n": sqltypes.Int64BindVariable(1)}, }, { - Sql: "insert into main1(id, name) values (:__seq0, 'myname')", + Sql: "insert into main1(id, `name`) values (:__seq0, 'myname')", BindVariables: map[string]*querypb.BindVariable{ "__seq0": sqltypes.Int64BindVariable(1), }, diff --git a/go/vt/vtgate/engine/ddl.go b/go/vt/vtgate/engine/ddl.go new file mode 100644 index 00000000000..fbe5594da1f --- /dev/null +++ b/go/vt/vtgate/engine/ddl.go @@ -0,0 +1,107 @@ +/* +Copyright 2020 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package engine + +import ( + "vitess.io/vitess/go/sqltypes" + "vitess.io/vitess/go/vt/proto/query" + vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc" + "vitess.io/vitess/go/vt/schema" + "vitess.io/vitess/go/vt/sqlparser" + "vitess.io/vitess/go/vt/vterrors" + "vitess.io/vitess/go/vt/vtgate/vindexes" +) + +var _ Primitive = (*DDL)(nil) + +// DDL represents a DDL statement, either normal or online DDL +type DDL struct { + Keyspace *vindexes.Keyspace + SQL string + DDL sqlparser.DDLStatement + + NormalDDL *Send + OnlineDDL *OnlineDDL + + noTxNeeded + + noInputs +} + +func (v *DDL) description() PrimitiveDescription { + return PrimitiveDescription{ + OperatorType: "DDL", + Keyspace: v.Keyspace, + Other: map[string]interface{}{ + "Query": v.SQL, + }, + } +} + +// RouteType implements the Primitive interface +func (v *DDL) RouteType() string { + return "DDL" +} + +// GetKeyspaceName implements the Primitive interface +func (v *DDL) GetKeyspaceName() string { + return v.Keyspace.Name +} + +// GetTableName implements the Primitive interface +func (v *DDL) GetTableName() string { + return v.DDL.GetTable().Name.String() +} + +// IsOnlineSchemaDDL returns true if the query is an online schema change DDL +func (v *DDL) isOnlineSchemaDDL() bool { + switch v.DDL.GetAction() { + case sqlparser.AlterDDLAction: + return v.OnlineDDL.Strategy != schema.DDLStrategyNormal + } + return false +} + +// Execute implements the Primitive interface +func (v *DDL) Execute(vcursor VCursor, bindVars map[string]*query.BindVariable, wantfields bool) (result *sqltypes.Result, err error) { + strategy, options, err := schema.ParseDDLStrategy(vcursor.Session().GetDDLStrategy()) + if err != nil { + return nil, err + } + v.OnlineDDL.Strategy = strategy + v.OnlineDDL.Options = options + + if v.isOnlineSchemaDDL() { + return v.OnlineDDL.Execute(vcursor, bindVars, wantfields) + } + + return v.NormalDDL.Execute(vcursor, bindVars, wantfields) +} + +// StreamExecute implements the Primitive interface +func (v *DDL) StreamExecute(vcursor VCursor, bindVars map[string]*query.BindVariable, wantfields bool, callback func(*sqltypes.Result) error) error { + results, err := v.Execute(vcursor, bindVars, wantfields) + if err != nil { + return err + } + return callback(results) +} + +// GetFields implements the Primitive interface +func (v *DDL) GetFields(vcursor VCursor, bindVars map[string]*query.BindVariable) (*sqltypes.Result, error) { + return nil, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "not reachable") +} diff --git a/go/vt/vtgate/engine/fake_vcursor_test.go b/go/vt/vtgate/engine/fake_vcursor_test.go index cea216e3310..09ac0bfd2c6 100644 --- a/go/vt/vtgate/engine/fake_vcursor_test.go +++ b/go/vt/vtgate/engine/fake_vcursor_test.go @@ -57,7 +57,11 @@ type noopVCursor struct { ctx context.Context } -func (t noopVCursor) SetDDLStrategy(strategy sqlparser.DDLStrategy) { +func (t noopVCursor) SetDDLStrategy(strategy string) { + panic("implement me") +} + +func (t noopVCursor) GetDDLStrategy() string { panic("implement me") } @@ -112,7 +116,7 @@ func (t noopVCursor) ShardSession() []*srvtopo.ResolvedShard { panic("implement me") } -func (t noopVCursor) ExecuteVSchema(keyspace string, vschemaDDL *sqlparser.DDL) error { +func (t noopVCursor) ExecuteVSchema(keyspace string, vschemaDDL sqlparser.DDLStatement) error { panic("implement me") } @@ -162,6 +166,10 @@ func (t noopVCursor) ExceedsMaxMemoryRows(numRows int) bool { return !testIgnoreMaxMemoryRows && numRows > testMaxMemoryRows } +func (t noopVCursor) GetKeyspace() string { + return "" +} + func (t noopVCursor) SetContextTimeout(timeout time.Duration) context.CancelFunc { return func() {} } @@ -273,7 +281,7 @@ func (f *loggingVCursor) ShardSession() []*srvtopo.ResolvedShard { return nil } -func (f *loggingVCursor) ExecuteVSchema(string, *sqlparser.DDL) error { +func (f *loggingVCursor) ExecuteVSchema(string, sqlparser.DDLStatement) error { panic("implement me") } @@ -298,6 +306,10 @@ func (f *loggingVCursor) ErrorGroupCancellableContext() (*errgroup.Group, func() panic("implement me") } +func (f *loggingVCursor) GetKeyspace() string { + return "" +} + func (f *loggingVCursor) RecordWarning(warning *querypb.QueryWarning) { f.warnings = append(f.warnings, warning) } diff --git a/go/vt/vtgate/engine/online_ddl.go b/go/vt/vtgate/engine/online_ddl.go index c2e5aa0bad0..48a6c5d69f4 100644 --- a/go/vt/vtgate/engine/online_ddl.go +++ b/go/vt/vtgate/engine/online_ddl.go @@ -32,9 +32,9 @@ var _ Primitive = (*OnlineDDL)(nil) //OnlineDDL represents the instructions to perform an online schema change via vtctld type OnlineDDL struct { Keyspace *vindexes.Keyspace - DDL *sqlparser.DDL + DDL sqlparser.DDLStatement SQL string - Strategy sqlparser.DDLStrategy + Strategy schema.DDLStrategy Options string noTxNeeded @@ -47,7 +47,7 @@ func (v *OnlineDDL) description() PrimitiveDescription { OperatorType: "OnlineDDL", Keyspace: v.Keyspace, Other: map[string]interface{}{ - "query": sqlparser.String(v.DDL), + "query": v.SQL, }, } } @@ -64,7 +64,7 @@ func (v *OnlineDDL) GetKeyspaceName() string { //GetTableName implements the Primitive interface func (v *OnlineDDL) GetTableName() string { - return v.DDL.Table.Name.String() + return v.DDL.GetTable().Name.String() } //Execute implements the Primitive interface @@ -96,11 +96,15 @@ func (v *OnlineDDL) Execute(vcursor VCursor, bindVars map[string]*query.BindVari } //StreamExecute implements the Primitive interface -func (v *OnlineDDL) StreamExecute(vcursor VCursor, bindVars map[string]*query.BindVariable, wantields bool, callback func(*sqltypes.Result) error) error { - return vterrors.Errorf(vtrpcpb.Code_INTERNAL, "not reachable") // TODO: shlomi - have no idea if this should work +func (v *OnlineDDL) StreamExecute(vcursor VCursor, bindVars map[string]*query.BindVariable, wantfields bool, callback func(*sqltypes.Result) error) error { + results, err := v.Execute(vcursor, bindVars, wantfields) + if err != nil { + return err + } + return callback(results) } //GetFields implements the Primitive interface func (v *OnlineDDL) GetFields(vcursor VCursor, bindVars map[string]*query.BindVariable) (*sqltypes.Result, error) { - return nil, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "not reachable") // TODO: shlomi - have no idea if this should work + return nil, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "not reachable") } diff --git a/go/vt/vtgate/engine/primitive.go b/go/vt/vtgate/engine/primitive.go index 8577632fef0..587aa9bc43f 100644 --- a/go/vt/vtgate/engine/primitive.go +++ b/go/vt/vtgate/engine/primitive.go @@ -53,6 +53,7 @@ type ( // Context returns the context of the current request. Context() context.Context + GetKeyspace() string // MaxMemoryRows returns the maxMemoryRows flag value. MaxMemoryRows() int @@ -83,7 +84,7 @@ type ( // Will replace all of the Topo functions. ResolveDestinations(keyspace string, ids []*querypb.Value, destinations []key.Destination) ([]*srvtopo.ResolvedShard, [][]*querypb.Value, error) - ExecuteVSchema(keyspace string, vschemaDDL *sqlparser.DDL) error + ExecuteVSchema(keyspace string, vschemaDDL sqlparser.DDLStatement) error SubmitOnlineDDL(onlineDDl *schema.OnlineDDL) error @@ -126,7 +127,8 @@ type ( SetWorkload(querypb.ExecuteOptions_Workload) SetFoundRows(uint64) - SetDDLStrategy(sqlparser.DDLStrategy) + SetDDLStrategy(string) + GetDDLStrategy() string // SetReadAfterWriteGTID sets the GTID that the user expects a replica to have caught up with before answering a query SetReadAfterWriteGTID(string) diff --git a/go/vt/vtgate/engine/route.go b/go/vt/vtgate/engine/route.go index 7d8fe4dc30c..71067fa51a9 100644 --- a/go/vt/vtgate/engine/route.go +++ b/go/vt/vtgate/engine/route.go @@ -160,6 +160,11 @@ const ( // clause using a Vindex. Requires: A Vindex, // and a Values list. SelectIN + // SelectMultiEqual is the opcode for routing a query + // based on multiple vindex input values, similar to + // SelectIN, but the query sent to each shard is the + // same. + SelectMultiEqual // SelectScatter is for routing a scatter query // to all shards of a keyspace. SelectScatter @@ -180,6 +185,7 @@ var routeName = map[RouteOpcode]string{ SelectEqualUnique: "SelectEqualUnique", SelectEqual: "SelectEqual", SelectIN: "SelectIN", + SelectMultiEqual: "SelectMultiEqual", SelectScatter: "SelectScatter", SelectNext: "SelectNext", SelectDBA: "SelectDBA", @@ -245,6 +251,8 @@ func (route *Route) execute(vcursor VCursor, bindVars map[string]*querypb.BindVa rss, bvs, err = route.paramsSelectEqual(vcursor, bindVars) case SelectIN: rss, bvs, err = route.paramsSelectIn(vcursor, bindVars) + case SelectMultiEqual: + rss, bvs, err = route.paramsSelectMultiEqual(vcursor, bindVars) case SelectNone: rss, bvs, err = nil, nil, nil default: @@ -308,6 +316,10 @@ func (route *Route) StreamExecute(vcursor VCursor, bindVars map[string]*querypb. rss, bvs, err = route.paramsSelectEqual(vcursor, bindVars) case SelectIN: rss, bvs, err = route.paramsSelectIn(vcursor, bindVars) + case SelectMultiEqual: + rss, bvs, err = route.paramsSelectMultiEqual(vcursor, bindVars) + case SelectNone: + rss, bvs, err = nil, nil, nil default: return fmt.Errorf("query %q cannot be used for streaming", route.Query) } @@ -516,6 +528,22 @@ func (route *Route) paramsSelectIn(vcursor VCursor, bindVars map[string]*querypb return rss, shardVars(bindVars, values), nil } +func (route *Route) paramsSelectMultiEqual(vcursor VCursor, bindVars map[string]*querypb.BindVariable) ([]*srvtopo.ResolvedShard, []map[string]*querypb.BindVariable, error) { + keys, err := route.Values[0].ResolveList(bindVars) + if err != nil { + return nil, nil, vterrors.Wrap(err, "paramsSelectIn") + } + rss, _, err := resolveShards(vcursor, route.Vindex, route.Keyspace, keys) + if err != nil { + return nil, nil, vterrors.Wrap(err, "paramsSelectIn") + } + multiBindVars := make([]map[string]*querypb.BindVariable, len(rss)) + for i := range multiBindVars { + multiBindVars[i] = bindVars + } + return rss, multiBindVars, nil +} + func resolveShards(vcursor VCursor, vindex vindexes.SingleColumn, keyspace *vindexes.Keyspace, vindexKeys []sqltypes.Value) ([]*srvtopo.ResolvedShard, [][]*querypb.Value, error) { // Convert vindexKeys to []*querypb.Value ids := make([]*querypb.Value, len(vindexKeys)) diff --git a/go/vt/vtgate/engine/route_test.go b/go/vt/vtgate/engine/route_test.go index 48e8720f145..bb8bad02339 100644 --- a/go/vt/vtgate/engine/route_test.go +++ b/go/vt/vtgate/engine/route_test.go @@ -270,14 +270,10 @@ func TestSelectNone(t *testing.T) { expectResult(t, "sel.Execute", result, &sqltypes.Result{}) vc.Rewind() - - result, err = sel.Execute(vc, map[string]*querypb.BindVariable{}, true) + result, err = wrapStreamExecute(sel, vc, map[string]*querypb.BindVariable{}, false) require.NoError(t, err) - vc.ExpectLog(t, []string{ - `ResolveDestinations ks [] Destinations:DestinationAnyShard()`, - `ExecuteMultiShard ks.-20: dummy_select_field {} false false`, - }) - expectResult(t, "sel.Execute", result, &sqltypes.Result{}) + require.Empty(t, vc.log) + expectResult(t, "sel.StreamExecute", result, nil) } func TestSelectEqualUniqueScatter(t *testing.T) { @@ -547,6 +543,55 @@ func TestSelectINNonUnique(t *testing.T) { expectResult(t, "sel.StreamExecute", result, defaultSelectResult) } +func TestSelectMultiEqual(t *testing.T) { + vindex, _ := vindexes.NewHash("", nil) + sel := NewRoute( + SelectMultiEqual, + &vindexes.Keyspace{ + Name: "ks", + Sharded: true, + }, + "dummy_select", + "dummy_select_field", + ) + sel.Vindex = vindex.(vindexes.SingleColumn) + sel.Values = []sqltypes.PlanValue{{ + Values: []sqltypes.PlanValue{{ + Value: sqltypes.NewInt64(1), + }, { + Value: sqltypes.NewInt64(2), + }, { + Value: sqltypes.NewInt64(4), + }}, + }} + + vc := &loggingVCursor{ + shards: []string{"-20", "20-"}, + shardForKsid: []string{"-20", "-20", "20-"}, + results: []*sqltypes.Result{defaultSelectResult}, + } + result, err := sel.Execute(vc, map[string]*querypb.BindVariable{}, false) + if err != nil { + t.Fatal(err) + } + vc.ExpectLog(t, []string{ + `ResolveDestinations ks [type:INT64 value:"1" type:INT64 value:"2" type:INT64 value:"4" ] Destinations:DestinationKeyspaceID(166b40b44aba4bd6),DestinationKeyspaceID(06e7ea22ce92708f),DestinationKeyspaceID(d2fd8867d50d2dfe)`, + `ExecuteMultiShard ks.-20: dummy_select {} ks.20-: dummy_select {} false false`, + }) + expectResult(t, "sel.Execute", result, defaultSelectResult) + + vc.Rewind() + result, err = wrapStreamExecute(sel, vc, map[string]*querypb.BindVariable{}, false) + if err != nil { + t.Fatal(err) + } + vc.ExpectLog(t, []string{ + `ResolveDestinations ks [type:INT64 value:"1" type:INT64 value:"2" type:INT64 value:"4" ] Destinations:DestinationKeyspaceID(166b40b44aba4bd6),DestinationKeyspaceID(06e7ea22ce92708f),DestinationKeyspaceID(d2fd8867d50d2dfe)`, + `StreamExecuteMulti dummy_select ks.-20: {} ks.20-: {} `, + }) + expectResult(t, "sel.StreamExecute", result, defaultSelectResult) +} + func TestSelectNext(t *testing.T) { sel := NewRoute( SelectNext, diff --git a/go/vt/vtgate/engine/set.go b/go/vt/vtgate/engine/set.go index 655f3f1ba43..43401cb8a25 100644 --- a/go/vt/vtgate/engine/set.go +++ b/go/vt/vtgate/engine/set.go @@ -404,11 +404,10 @@ func (svss *SysVarSetAware) Execute(vcursor VCursor, env evalengine.ExpressionEn if err != nil { return err } - strategy, err := schema.ValidateDDLStrategy(str) - if err != nil { + if _, _, err := schema.ParseDDLStrategy(str); err != nil { return vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "invalid DDL strategy: %s", str) } - vcursor.Session().SetDDLStrategy(strategy) + vcursor.Session().SetDDLStrategy(str) case sysvars.Charset.Name, sysvars.Names.Name: str, err := svss.evalAsString(env) if err != nil { diff --git a/go/vt/vtgate/engine/vindex_func.go b/go/vt/vtgate/engine/vindex_func.go index d301b238bb1..eb1c3b50b8d 100644 --- a/go/vt/vtgate/engine/vindex_func.go +++ b/go/vt/vtgate/engine/vindex_func.go @@ -18,6 +18,7 @@ package engine import ( "encoding/json" + "fmt" "vitess.io/vitess/go/vt/vtgate/evalengine" @@ -131,10 +132,25 @@ func (vf *VindexFunc) mapVindex(vcursor VCursor, bindVars map[string]*querypb.Bi } case key.DestinationKeyspaceID: if len(d) > 0 { - result.Rows = [][]sqltypes.Value{ - vf.buildRow(vkey, d, nil), + if vcursor != nil { + resolvedShards, _, err := vcursor.ResolveDestinations(vcursor.GetKeyspace(), nil, []key.Destination{d}) + if err != nil { + return nil, err + } + kr, err := key.ParseShardingSpec(resolvedShards[0].Target.Shard) + if err != nil { + return nil, err + } + result.Rows = [][]sqltypes.Value{ + vf.buildRow(vkey, d, kr[0]), + } + result.RowsAffected = 1 + } else { + result.Rows = [][]sqltypes.Value{ + vf.buildRow(vkey, d, nil), + } + result.RowsAffected = 1 } - result.RowsAffected = 1 } case key.DestinationKeyspaceIDs: for _, ksid := range d { @@ -173,6 +189,18 @@ func (vf *VindexFunc) buildRow(id sqltypes.Value, ksid []byte, kr *topodatapb.Ke } else { row = append(row, sqltypes.NULL) } + case 4: + if ksid != nil { + row = append(row, sqltypes.NewVarBinary(fmt.Sprintf("%x", ksid))) + } else { + row = append(row, sqltypes.NULL) + } + case 5: + if ksid != nil { + row = append(row, sqltypes.NewVarBinary(key.KeyRangeString(kr))) + } else { + row = append(row, sqltypes.NULL) + } default: panic("BUG: unexpected column number") } diff --git a/go/vt/vtgate/engine/vindex_func_test.go b/go/vt/vtgate/engine/vindex_func_test.go index ff22fe4e601..eb8e3265ae8 100644 --- a/go/vt/vtgate/engine/vindex_func_test.go +++ b/go/vt/vtgate/engine/vindex_func_test.go @@ -98,7 +98,7 @@ func TestVindexFuncMap(t *testing.T) { t.Fatal(err) } want := &sqltypes.Result{ - Fields: sqltypes.MakeTestFields("id|keyspace_id|range_start|range_end", "varbinary|varbinary|varbinary|varbinary"), + Fields: sqltypes.MakeTestFields("id|keyspace_id|hex(keyspace_id)|range_start|range_end", "varbinary|varbinary|varbinary|varbinary|varbinary"), } if !reflect.DeepEqual(got, want) { t.Errorf("Execute(Map, uvindex(none)):\n%v, want\n%v", got, want) @@ -111,9 +111,13 @@ func TestVindexFuncMap(t *testing.T) { t.Fatal(err) } want = sqltypes.MakeTestResult( - sqltypes.MakeTestFields("id|keyspace_id|range_start|range_end", "varbinary|varbinary|varbinary|varbinary"), - "1|foo", + sqltypes.MakeTestFields("id|keyspace_id|hex(keyspace_id)|range_start|range_end", "varbinary|varbinary|varbinary|varbinary|varbinary"), + "1|foo|||666f6f", ) + for _, row := range want.Rows { + row[2] = sqltypes.NULL + row[3] = sqltypes.NULL + } if !reflect.DeepEqual(got, want) { t.Errorf("Execute(Map, uvindex(none)):\n%v, want\n%v", got, want) } @@ -125,12 +129,13 @@ func TestVindexFuncMap(t *testing.T) { t.Fatal(err) } want = &sqltypes.Result{ - Fields: sqltypes.MakeTestFields("id|keyspace_id|range_start|range_end", "varbinary|varbinary|varbinary|varbinary"), + Fields: sqltypes.MakeTestFields("id|keyspace_id|hex(keyspace_id)|range_start|range_end", "varbinary|varbinary|varbinary|varbinary|varbinary"), Rows: [][]sqltypes.Value{{ sqltypes.NewVarBinary("1"), sqltypes.NULL, sqltypes.MakeTrusted(sqltypes.VarBinary, []byte{0x40}), sqltypes.MakeTrusted(sqltypes.VarBinary, []byte{0x60}), + sqltypes.NULL, }}, RowsAffected: 1, } @@ -145,7 +150,7 @@ func TestVindexFuncMap(t *testing.T) { t.Fatal(err) } want = &sqltypes.Result{ - Fields: sqltypes.MakeTestFields("id|keyspace_id|range_start|range_end", "varbinary|varbinary|varbinary|varbinary"), + Fields: sqltypes.MakeTestFields("id|keyspace_id|hex(keyspace_id)|range_start|range_end", "varbinary|varbinary|varbinary|varbinary|varbinary"), } if !reflect.DeepEqual(got, want) { t.Errorf("Execute(Map, uvindex(none)):\n%v, want\n%v", got, want) @@ -158,9 +163,9 @@ func TestVindexFuncMap(t *testing.T) { t.Fatal(err) } want = sqltypes.MakeTestResult( - sqltypes.MakeTestFields("id|keyspace_id|range_start|range_end", "varbinary|varbinary|varbinary|varbinary"), - "1|foo||", - "1|bar||", + sqltypes.MakeTestFields("id|keyspace_id|hex(keyspace_id)|range_start|range_end", "varbinary|varbinary|varbinary|varbinary|varbinary"), + "1|foo|||666f6f", + "1|bar|||626172", ) // Massage the rows because MakeTestResult doesn't do NULL values. for _, row := range want.Rows { @@ -178,12 +183,13 @@ func TestVindexFuncMap(t *testing.T) { t.Fatal(err) } want = &sqltypes.Result{ - Fields: sqltypes.MakeTestFields("id|keyspace_id|range_start|range_end", "varbinary|varbinary|varbinary|varbinary"), + Fields: sqltypes.MakeTestFields("id|keyspace_id|hex(keyspace_id)|range_start|range_end", "varbinary|varbinary|varbinary|varbinary|varbinary"), Rows: [][]sqltypes.Value{{ sqltypes.NewVarBinary("1"), sqltypes.NULL, sqltypes.MakeTrusted(sqltypes.VarBinary, []byte{0x40}), sqltypes.MakeTrusted(sqltypes.VarBinary, []byte{0x60}), + sqltypes.NULL, }}, RowsAffected: 1, } @@ -195,12 +201,12 @@ func TestVindexFuncMap(t *testing.T) { func TestVindexFuncStreamExecute(t *testing.T) { vf := testVindexFunc(&nvindex{matchid: true}) want := []*sqltypes.Result{{ - Fields: sqltypes.MakeTestFields("id|keyspace_id|range_start|range_end", "varbinary|varbinary|varbinary|varbinary"), + Fields: sqltypes.MakeTestFields("id|keyspace_id|hex(keyspace_id)|range_start|range_end", "varbinary|varbinary|varbinary|varbinary|varbinary"), }, { Rows: [][]sqltypes.Value{{ - sqltypes.NewVarBinary("1"), sqltypes.NewVarBinary("foo"), sqltypes.NULL, sqltypes.NULL, + sqltypes.NewVarBinary("1"), sqltypes.NewVarBinary("foo"), sqltypes.NULL, sqltypes.NULL, sqltypes.NewVarBinary("666f6f"), }, { - sqltypes.NewVarBinary("1"), sqltypes.NewVarBinary("bar"), sqltypes.NULL, sqltypes.NULL, + sqltypes.NewVarBinary("1"), sqltypes.NewVarBinary("bar"), sqltypes.NULL, sqltypes.NULL, sqltypes.NewVarBinary("626172"), }}, }} i := 0 @@ -223,7 +229,7 @@ func TestVindexFuncGetFields(t *testing.T) { t.Fatal(err) } want := &sqltypes.Result{ - Fields: sqltypes.MakeTestFields("id|keyspace_id|range_start|range_end", "varbinary|varbinary|varbinary|varbinary"), + Fields: sqltypes.MakeTestFields("id|keyspace_id|hex(keyspace_id)|range_start|range_end", "varbinary|varbinary|varbinary|varbinary|varbinary"), } if !reflect.DeepEqual(got, want) { t.Errorf("Execute(Map, uvindex(none)):\n%v, want\n%v", got, want) @@ -250,8 +256,8 @@ func TestFieldOrder(t *testing.T) { func testVindexFunc(v vindexes.SingleColumn) *VindexFunc { return &VindexFunc{ - Fields: sqltypes.MakeTestFields("id|keyspace_id|range_start|range_end", "varbinary|varbinary|varbinary|varbinary"), - Cols: []int{0, 1, 2, 3}, + Fields: sqltypes.MakeTestFields("id|keyspace_id|hex(keyspace_id)|range_start|range_end", "varbinary|varbinary|varbinary|varbinary|varbinary"), + Cols: []int{0, 1, 2, 3, 4}, Opcode: VindexMap, Vindex: v, Value: int64PlanValue(1), diff --git a/go/vt/vtgate/engine/vschema_ddl.go b/go/vt/vtgate/engine/vschema_ddl.go index 29085a66032..3fe128ff328 100644 --- a/go/vt/vtgate/engine/vschema_ddl.go +++ b/go/vt/vtgate/engine/vschema_ddl.go @@ -31,7 +31,7 @@ var _ Primitive = (*AlterVSchema)(nil) type AlterVSchema struct { Keyspace *vindexes.Keyspace - DDL *sqlparser.DDL + DDL sqlparser.DDLStatement noTxNeeded @@ -60,7 +60,7 @@ func (v *AlterVSchema) GetKeyspaceName() string { //GetTableName implements the Primitive interface func (v *AlterVSchema) GetTableName() string { - return v.DDL.Table.Name.String() + return v.DDL.GetTable().Name.String() } //Execute implements the Primitive interface diff --git a/go/vt/vtgate/evalengine/arithmetic.go b/go/vt/vtgate/evalengine/arithmetic.go index 6941c9bc73f..98ee792d089 100644 --- a/go/vt/vtgate/evalengine/arithmetic.go +++ b/go/vt/vtgate/evalengine/arithmetic.go @@ -229,7 +229,7 @@ func isByteComparable(v sqltypes.Value) bool { return true } switch v.Type() { - case sqltypes.Timestamp, sqltypes.Date, sqltypes.Time, sqltypes.Datetime, sqltypes.Enum, sqltypes.Set: + case sqltypes.Timestamp, sqltypes.Date, sqltypes.Time, sqltypes.Datetime, sqltypes.Enum, sqltypes.Set, sqltypes.TypeJSON: return true } return false diff --git a/go/vt/vtgate/executor_dml_test.go b/go/vt/vtgate/executor_dml_test.go index 65054118020..7c8dc31948a 100644 --- a/go/vt/vtgate/executor_dml_test.go +++ b/go/vt/vtgate/executor_dml_test.go @@ -106,15 +106,15 @@ func TestUpdateEqual(t *testing.T) { ), }) - _, err = executorExec(executor, "update user2 set name='myname', lastname='mylastname' where id = 1", nil) + _, err = executorExec(executor, "update user2 set `name`='myname', lastname='mylastname' where id = 1", nil) require.NoError(t, err) wantQueries = []*querypb.BoundQuery{ { - Sql: "select id, name, lastname, name = 'myname' and lastname = 'mylastname' from user2 where id = 1 for update", + Sql: "select id, `name`, lastname, `name` = 'myname' and lastname = 'mylastname' from user2 where id = 1 for update", BindVariables: map[string]*querypb.BindVariable{}, }, { - Sql: "update user2 set name = 'myname', lastname = 'mylastname' where id = 1", + Sql: "update user2 set `name` = 'myname', lastname = 'mylastname' where id = 1", BindVariables: map[string]*querypb.BindVariable{}, }, } @@ -127,7 +127,7 @@ func TestUpdateEqual(t *testing.T) { wantQueries = []*querypb.BoundQuery{ { - Sql: "delete from name_lastname_keyspace_id_map where name = :name and lastname = :lastname and keyspace_id = :keyspace_id", + Sql: "delete from name_lastname_keyspace_id_map where `name` = :name and lastname = :lastname and keyspace_id = :keyspace_id", BindVariables: map[string]*querypb.BindVariable{ "lastname": sqltypes.ValueBindVariable(sqltypes.NewVarChar("foo")), "name": sqltypes.Int32BindVariable(1), @@ -135,7 +135,7 @@ func TestUpdateEqual(t *testing.T) { }, }, { - Sql: "insert into name_lastname_keyspace_id_map(name, lastname, keyspace_id) values (:name_0, :lastname_0, :keyspace_id_0)", + Sql: "insert into name_lastname_keyspace_id_map(`name`, lastname, keyspace_id) values (:name_0, :lastname_0, :keyspace_id_0)", BindVariables: map[string]*querypb.BindVariable{ "name_0": sqltypes.BytesBindVariable([]byte("myname")), "lastname_0": sqltypes.BytesBindVariable([]byte("mylastname")), @@ -341,7 +341,7 @@ func TestDeleteEqual(t *testing.T) { _, err := executorExec(executor, "delete from user where id = 1", nil) require.NoError(t, err) wantQueries := []*querypb.BoundQuery{{ - Sql: "select Id, name from user where id = 1 for update", + Sql: "select Id, `name` from user where id = 1 for update", BindVariables: map[string]*querypb.BindVariable{}, }, { Sql: "delete from user where id = 1", @@ -352,7 +352,7 @@ func TestDeleteEqual(t *testing.T) { } wantQueries = []*querypb.BoundQuery{{ - Sql: "delete from name_user_map where name = :name and user_id = :user_id", + Sql: "delete from name_user_map where `name` = :name and user_id = :user_id", BindVariables: map[string]*querypb.BindVariable{ "user_id": sqltypes.Uint64BindVariable(1), "name": sqltypes.ValueBindVariable(sqltypes.NewVarChar("myname")), @@ -368,7 +368,7 @@ func TestDeleteEqual(t *testing.T) { _, err = executorExec(executor, "delete from user where id = 1", nil) require.NoError(t, err) wantQueries = []*querypb.BoundQuery{{ - Sql: "select Id, name from user where id = 1 for update", + Sql: "select Id, `name` from user where id = 1 for update", BindVariables: map[string]*querypb.BindVariable{}, }, { Sql: "delete from user where id = 1", @@ -428,7 +428,7 @@ func TestDeleteEqual(t *testing.T) { require.NoError(t, err) wantQueries = []*querypb.BoundQuery{ { - Sql: "select id, name, lastname from user2 where id = 1 for update", + Sql: "select id, `name`, lastname from user2 where id = 1 for update", BindVariables: map[string]*querypb.BindVariable{}, }, { @@ -442,7 +442,7 @@ func TestDeleteEqual(t *testing.T) { wantQueries = []*querypb.BoundQuery{ { - Sql: "delete from name_lastname_keyspace_id_map where name = :name and lastname = :lastname and keyspace_id = :keyspace_id", + Sql: "delete from name_lastname_keyspace_id_map where `name` = :name and lastname = :lastname and keyspace_id = :keyspace_id", BindVariables: map[string]*querypb.BindVariable{ "lastname": sqltypes.ValueBindVariable(sqltypes.NewVarChar("foo")), "name": sqltypes.Int32BindVariable(1), @@ -526,7 +526,7 @@ func TestDeleteComments(t *testing.T) { _, err := executorExec(executor, "delete from user where id = 1 /* trailing */", nil) require.NoError(t, err) wantQueries := []*querypb.BoundQuery{{ - Sql: "select Id, name from user where id = 1 for update /* trailing */", + Sql: "select Id, `name` from user where id = 1 for update /* trailing */", BindVariables: map[string]*querypb.BindVariable{}, }, { Sql: "delete from user where id = 1 /* trailing */", @@ -537,7 +537,7 @@ func TestDeleteComments(t *testing.T) { } wantQueries = []*querypb.BoundQuery{{ - Sql: "delete from name_user_map where name = :name and user_id = :user_id /* trailing */", + Sql: "delete from name_user_map where `name` = :name and user_id = :user_id /* trailing */", BindVariables: map[string]*querypb.BindVariable{ "user_id": sqltypes.Uint64BindVariable(1), "name": sqltypes.ValueBindVariable(sqltypes.NewVarChar("myname")), @@ -557,7 +557,7 @@ func TestInsertSharded(t *testing.T) { _, err := executorExec(executor, "insert into user(id, v, name) values (1, 2, 'myname')", nil) require.NoError(t, err) wantQueries := []*querypb.BoundQuery{{ - Sql: "insert into user(id, v, name) values (:_Id_0, 2, :_name_0)", + Sql: "insert into user(id, v, `name`) values (:_Id_0, 2, :_name_0)", BindVariables: map[string]*querypb.BindVariable{ "_Id_0": sqltypes.Int64BindVariable(1), "_name_0": sqltypes.BytesBindVariable([]byte("myname")), @@ -571,7 +571,7 @@ func TestInsertSharded(t *testing.T) { t.Errorf("sbc2.Queries: %+v, want nil\n", sbc2.Queries) } wantQueries = []*querypb.BoundQuery{{ - Sql: "insert into name_user_map(name, user_id) values (:name_0, :user_id_0)", + Sql: "insert into name_user_map(`name`, user_id) values (:name_0, :user_id_0)", BindVariables: map[string]*querypb.BindVariable{ "name_0": sqltypes.BytesBindVariable([]byte("myname")), "user_id_0": sqltypes.Uint64BindVariable(1), @@ -589,7 +589,7 @@ func TestInsertSharded(t *testing.T) { _, err = executorExec(executor, "insert into user(id, v, name) values (3, 2, 'myname2')", nil) require.NoError(t, err) wantQueries = []*querypb.BoundQuery{{ - Sql: "insert into user(id, v, name) values (:_Id_0, 2, :_name_0)", + Sql: "insert into user(id, v, `name`) values (:_Id_0, 2, :_name_0)", BindVariables: map[string]*querypb.BindVariable{ "_Id_0": sqltypes.Int64BindVariable(3), "__seq0": sqltypes.Int64BindVariable(3), @@ -603,7 +603,7 @@ func TestInsertSharded(t *testing.T) { t.Errorf("sbc1.Queries: %+v, want nil\n", sbc1.Queries) } wantQueries = []*querypb.BoundQuery{{ - Sql: "insert into name_user_map(name, user_id) values (:name_0, :user_id_0)", + Sql: "insert into name_user_map(`name`, user_id) values (:name_0, :user_id_0)", BindVariables: map[string]*querypb.BindVariable{ "name_0": sqltypes.BytesBindVariable([]byte("myname2")), "user_id_0": sqltypes.Uint64BindVariable(3), @@ -617,7 +617,7 @@ func TestInsertSharded(t *testing.T) { _, err = executorExec(executor, "insert into user2(id, name, lastname) values (2, 'myname', 'mylastname')", nil) require.NoError(t, err) wantQueries = []*querypb.BoundQuery{{ - Sql: "insert into user2(id, name, lastname) values (:_id_0, :_name_0, :_lastname_0)", + Sql: "insert into user2(id, `name`, lastname) values (:_id_0, :_name_0, :_lastname_0)", BindVariables: map[string]*querypb.BindVariable{ "_id_0": sqltypes.Int64BindVariable(2), "_name_0": sqltypes.BytesBindVariable([]byte("myname")), @@ -691,7 +691,7 @@ func TestInsertShardedAutocommitLookup(t *testing.T) { _, err := executorExec(executor, "insert into user(id, v, name) values (1, 2, 'myname')", nil) require.NoError(t, err) wantQueries := []*querypb.BoundQuery{{ - Sql: "insert into user(id, v, name) values (:_Id_0, 2, :_name_0)", + Sql: "insert into user(id, v, `name`) values (:_Id_0, 2, :_name_0)", BindVariables: map[string]*querypb.BindVariable{ "_Id_0": sqltypes.Int64BindVariable(1), "_name_0": sqltypes.BytesBindVariable([]byte("myname")), @@ -705,7 +705,7 @@ func TestInsertShardedAutocommitLookup(t *testing.T) { t.Errorf("sbc2.Queries: %+v, want nil\n", sbc2.Queries) } wantQueries = []*querypb.BoundQuery{{ - Sql: "insert into name_user_map(name, user_id) values (:name_0, :user_id_0) on duplicate key update name = values(name), user_id = values(user_id)", + Sql: "insert into name_user_map(`name`, user_id) values (:name_0, :user_id_0) on duplicate key update `name` = values(`name`), user_id = values(user_id)", BindVariables: map[string]*querypb.BindVariable{ "name_0": sqltypes.BytesBindVariable([]byte("myname")), "user_id_0": sqltypes.Uint64BindVariable(1), @@ -952,7 +952,7 @@ func TestInsertComments(t *testing.T) { _, err := executorExec(executor, "insert into user(id, v, name) values (1, 2, 'myname') /* trailing */", nil) require.NoError(t, err) wantQueries := []*querypb.BoundQuery{{ - Sql: "insert into user(id, v, name) values (:_Id_0, 2, :_name_0) /* trailing */", + Sql: "insert into user(id, v, `name`) values (:_Id_0, 2, :_name_0) /* trailing */", BindVariables: map[string]*querypb.BindVariable{ "_Id_0": sqltypes.Int64BindVariable(1), "_name_0": sqltypes.BytesBindVariable([]byte("myname")), @@ -966,7 +966,7 @@ func TestInsertComments(t *testing.T) { t.Errorf("sbc2.Queries: %+v, want nil\n", sbc2.Queries) } wantQueries = []*querypb.BoundQuery{{ - Sql: "insert into name_user_map(name, user_id) values (:name_0, :user_id_0) /* trailing */", + Sql: "insert into name_user_map(`name`, user_id) values (:name_0, :user_id_0) /* trailing */", BindVariables: map[string]*querypb.BindVariable{ "name_0": sqltypes.BytesBindVariable([]byte("myname")), "user_id_0": sqltypes.Uint64BindVariable(1), @@ -987,10 +987,10 @@ func TestInsertGeneratorSharded(t *testing.T) { RowsAffected: 1, InsertID: 1, }}) - result, err := executorExec(executor, "insert into user(v, name) values (2, 'myname')", nil) + result, err := executorExec(executor, "insert into user(v, `name`) values (2, 'myname')", nil) require.NoError(t, err) wantQueries := []*querypb.BoundQuery{{ - Sql: "insert into user(v, name, id) values (2, :_name_0, :_Id_0)", + Sql: "insert into user(v, `name`, id) values (2, :_name_0, :_Id_0)", BindVariables: map[string]*querypb.BindVariable{ "_Id_0": sqltypes.Int64BindVariable(1), "__seq0": sqltypes.Int64BindVariable(1), @@ -1004,7 +1004,7 @@ func TestInsertGeneratorSharded(t *testing.T) { Sql: "select next :n values from user_seq", BindVariables: map[string]*querypb.BindVariable{"n": sqltypes.Int64BindVariable(1)}, }, { - Sql: "insert into name_user_map(name, user_id) values (:name_0, :user_id_0)", + Sql: "insert into name_user_map(`name`, user_id) values (:name_0, :user_id_0)", BindVariables: map[string]*querypb.BindVariable{ "name_0": sqltypes.BytesBindVariable([]byte("myname")), "user_id_0": sqltypes.Uint64BindVariable(1), @@ -1055,7 +1055,7 @@ func TestInsertGeneratorUnsharded(t *testing.T) { Sql: "select next :n values from user_seq", BindVariables: map[string]*querypb.BindVariable{"n": sqltypes.Int64BindVariable(1)}, }, { - Sql: "insert into main1(id, name) values (:__seq0, 'myname')", + Sql: "insert into main1(id, `name`) values (:__seq0, 'myname')", BindVariables: map[string]*querypb.BindVariable{ "__seq0": sqltypes.Int64BindVariable(1), }, @@ -1274,7 +1274,7 @@ func TestMultiInsertSharded(t *testing.T) { _, err := executorExec(executor, "insert into user(id, v, name) values (1, 1, 'myname1'),(3, 3, 'myname3')", nil) require.NoError(t, err) wantQueries1 := []*querypb.BoundQuery{{ - Sql: "insert into user(id, v, name) values (:_Id_0, 1, :_name_0)", + Sql: "insert into user(id, v, `name`) values (:_Id_0, 1, :_name_0)", BindVariables: map[string]*querypb.BindVariable{ "_Id_0": sqltypes.Int64BindVariable(1), "_name_0": sqltypes.BytesBindVariable([]byte("myname1")), @@ -1286,7 +1286,7 @@ func TestMultiInsertSharded(t *testing.T) { }} wantQueries2 := []*querypb.BoundQuery{{ - Sql: "insert into user(id, v, name) values (:_Id_1, 3, :_name_1)", + Sql: "insert into user(id, v, `name`) values (:_Id_1, 3, :_name_1)", BindVariables: map[string]*querypb.BindVariable{ "_Id_0": sqltypes.Int64BindVariable(1), "_name_0": sqltypes.BytesBindVariable([]byte("myname1")), @@ -1305,7 +1305,7 @@ func TestMultiInsertSharded(t *testing.T) { } wantQueries1 = []*querypb.BoundQuery{{ - Sql: "insert into name_user_map(name, user_id) values (:name_0, :user_id_0), (:name_1, :user_id_1)", + Sql: "insert into name_user_map(`name`, user_id) values (:name_0, :user_id_0), (:name_1, :user_id_1)", BindVariables: map[string]*querypb.BindVariable{ "name_0": sqltypes.BytesBindVariable([]byte("myname1")), "user_id_0": sqltypes.Uint64BindVariable(1), @@ -1323,7 +1323,7 @@ func TestMultiInsertSharded(t *testing.T) { _, err = executorExec(executor, "insert into user(id, v, name) values (1, 1, 'myname1'),(2, 2, 'myname2')", nil) require.NoError(t, err) wantQueries := []*querypb.BoundQuery{{ - Sql: "insert into user(id, v, name) values (:_Id_0, 1, :_name_0),(:_Id_1, 2, :_name_1)", + Sql: "insert into user(id, v, `name`) values (:_Id_0, 1, :_name_0),(:_Id_1, 2, :_name_1)", BindVariables: map[string]*querypb.BindVariable{ "_Id_0": sqltypes.Int64BindVariable(1), "__seq0": sqltypes.Int64BindVariable(1), @@ -1341,7 +1341,7 @@ func TestMultiInsertSharded(t *testing.T) { t.Errorf("sbc2.Queries: %+v, want nil\n", sbc2.Queries) } wantQueries = []*querypb.BoundQuery{{ - Sql: "insert into name_user_map(name, user_id) values (:name_0, :user_id_0), (:name_1, :user_id_1)", + Sql: "insert into name_user_map(`name`, user_id) values (:name_0, :user_id_0), (:name_1, :user_id_1)", BindVariables: map[string]*querypb.BindVariable{ "name_0": sqltypes.BytesBindVariable([]byte("myname1")), "user_id_0": sqltypes.Uint64BindVariable(1), @@ -1357,10 +1357,10 @@ func TestMultiInsertSharded(t *testing.T) { sbc1.Queries = nil sbclookup.Queries = nil sbc2.Queries = nil - _, err = executorExec(executor, "insert into user2(id, name, lastname) values (2, 'myname', 'mylastname'), (3, 'myname2', 'mylastname2')", nil) + _, err = executorExec(executor, "insert into user2(id, `name`, lastname) values (2, 'myname', 'mylastname'), (3, 'myname2', 'mylastname2')", nil) require.NoError(t, err) wantQueries = []*querypb.BoundQuery{{ - Sql: "insert into user2(id, name, lastname) values (:_id_0, :_name_0, :_lastname_0)", + Sql: "insert into user2(id, `name`, lastname) values (:_id_0, :_name_0, :_lastname_0)", BindVariables: map[string]*querypb.BindVariable{ "_id_0": sqltypes.Int64BindVariable(2), "_name_0": sqltypes.BytesBindVariable([]byte("myname")), @@ -1374,7 +1374,7 @@ func TestMultiInsertSharded(t *testing.T) { t.Errorf("sbc1.Queries:\n%+v, want\n%+v\n", sbc1.Queries, wantQueries) } wantQueries = []*querypb.BoundQuery{{ - Sql: "insert into name_lastname_keyspace_id_map(name, lastname, keyspace_id) values (:name_0, :lastname_0, :keyspace_id_0), (:name_1, :lastname_1, :keyspace_id_1)", + Sql: "insert into name_lastname_keyspace_id_map(`name`, lastname, keyspace_id) values (:name_0, :lastname_0, :keyspace_id_0), (:name_1, :lastname_1, :keyspace_id_1)", BindVariables: map[string]*querypb.BindVariable{ "name_0": sqltypes.BytesBindVariable([]byte("myname")), "lastname_0": sqltypes.BytesBindVariable([]byte("mylastname")), @@ -1399,10 +1399,10 @@ func TestMultiInsertGenerator(t *testing.T) { RowsAffected: 1, InsertID: 1, }}) - result, err := executorExec(executor, "insert into music(user_id, name) values (:u, 'myname1'),(:u, 'myname2')", map[string]*querypb.BindVariable{"u": sqltypes.Int64BindVariable(2)}) + result, err := executorExec(executor, "insert into music(user_id, `name`) values (:u, 'myname1'),(:u, 'myname2')", map[string]*querypb.BindVariable{"u": sqltypes.Int64BindVariable(2)}) require.NoError(t, err) wantQueries := []*querypb.BoundQuery{{ - Sql: "insert into music(user_id, name, id) values (:_user_id_0, 'myname1', :_id_0),(:_user_id_1, 'myname2', :_id_1)", + Sql: "insert into music(user_id, `name`, id) values (:_user_id_0, 'myname1', :_id_0),(:_user_id_1, 'myname2', :_id_1)", BindVariables: map[string]*querypb.BindVariable{ "u": sqltypes.Int64BindVariable(2), "_id_0": sqltypes.Int64BindVariable(1), @@ -1449,7 +1449,7 @@ func TestMultiInsertGeneratorSparse(t *testing.T) { result, err := executorExec(executor, "insert into music(id, user_id, name) values (NULL, :u, 'myname1'),(2, :u, 'myname2'), (NULL, :u, 'myname3')", map[string]*querypb.BindVariable{"u": sqltypes.Int64BindVariable(2)}) require.NoError(t, err) wantQueries := []*querypb.BoundQuery{{ - Sql: "insert into music(id, user_id, name) values (:_id_0, :_user_id_0, 'myname1'),(:_id_1, :_user_id_1, 'myname2'),(:_id_2, :_user_id_2, 'myname3')", + Sql: "insert into music(id, user_id, `name`) values (:_id_0, :_user_id_0, 'myname1'),(:_id_1, :_user_id_1, 'myname2'),(:_id_2, :_user_id_2, 'myname3')", BindVariables: map[string]*querypb.BindVariable{ "u": sqltypes.Int64BindVariable(2), "_id_0": sqltypes.Int64BindVariable(1), diff --git a/go/vt/vtgate/executor_select_test.go b/go/vt/vtgate/executor_select_test.go index 2041fe90040..aee0e89f424 100644 --- a/go/vt/vtgate/executor_select_test.go +++ b/go/vt/vtgate/executor_select_test.go @@ -600,7 +600,7 @@ func TestSelectBindvars(t *testing.T) { }) require.NoError(t, err) wantQueries = []*querypb.BoundQuery{{ - Sql: "select id from user where name in ::__vals", + Sql: "select id from user where `name` in ::__vals", BindVariables: map[string]*querypb.BindVariable{ "name1": sqltypes.BytesBindVariable([]byte("foo1")), "name2": sqltypes.BytesBindVariable([]byte("foo2")), @@ -622,7 +622,7 @@ func TestSelectBindvars(t *testing.T) { }) require.NoError(t, err) wantQueries = []*querypb.BoundQuery{{ - Sql: "select id from user where name in ::__vals", + Sql: "select id from user where `name` in ::__vals", BindVariables: map[string]*querypb.BindVariable{ "name1": sqltypes.BytesBindVariable([]byte("foo1")), "name2": sqltypes.BytesBindVariable([]byte("foo2")), @@ -668,7 +668,7 @@ func TestSelectBindvars(t *testing.T) { vars, err := sqltypes.BuildBindVariable([]interface{}{sqltypes.NewVarBinary("nonexistent")}) require.NoError(t, err) wantLookupQueries := []*querypb.BoundQuery{{ - Sql: "select name, user_id from name_user_map where name in ::name", + Sql: "select `name`, user_id from name_user_map where `name` in ::name", BindVariables: map[string]*querypb.BindVariable{ "name": vars, }, @@ -740,7 +740,7 @@ func TestSelectEqual(t *testing.T) { _, err = executorExec(executor, "select id from user where name = 'foo'", nil) require.NoError(t, err) wantQueries = []*querypb.BoundQuery{{ - Sql: "select id from user where name = 'foo'", + Sql: "select id from user where `name` = 'foo'", BindVariables: map[string]*querypb.BindVariable{}, }} if !reflect.DeepEqual(sbc1.Queries, wantQueries) { @@ -749,7 +749,7 @@ func TestSelectEqual(t *testing.T) { vars, err := sqltypes.BuildBindVariable([]interface{}{sqltypes.NewVarBinary("foo")}) require.NoError(t, err) wantQueries = []*querypb.BoundQuery{{ - Sql: "select name, user_id from name_user_map where name in ::name", + Sql: "select `name`, user_id from name_user_map where `name` in ::name", BindVariables: map[string]*querypb.BindVariable{ "name": vars, }, @@ -982,7 +982,7 @@ func TestSelectIN(t *testing.T) { _, err = executorExec(executor, "select id from user where name = 'foo'", nil) require.NoError(t, err) wantQueries = []*querypb.BoundQuery{{ - Sql: "select id from user where name = 'foo'", + Sql: "select id from user where `name` = 'foo'", BindVariables: map[string]*querypb.BindVariable{}, }} if !reflect.DeepEqual(sbc1.Queries, wantQueries) { @@ -991,7 +991,7 @@ func TestSelectIN(t *testing.T) { vars, err := sqltypes.BuildBindVariable([]interface{}{sqltypes.NewVarBinary("foo")}) require.NoError(t, err) wantQueries = []*querypb.BoundQuery{{ - Sql: "select name, user_id from name_user_map where name in ::name", + Sql: "select `name`, user_id from name_user_map where `name` in ::name", BindVariables: map[string]*querypb.BindVariable{ "name": vars, }, @@ -1038,7 +1038,7 @@ func TestStreamSelectIN(t *testing.T) { vars, err := sqltypes.BuildBindVariable([]interface{}{sqltypes.NewVarBinary("foo")}) require.NoError(t, err) wantQueries := []*querypb.BoundQuery{{ - Sql: "select name, user_id from name_user_map where name in ::name", + Sql: "select `name`, user_id from name_user_map where `name` in ::name", BindVariables: map[string]*querypb.BindVariable{ "name": vars, }, diff --git a/go/vt/vtgate/planbuilder/builder.go b/go/vt/vtgate/planbuilder/builder.go index d0be9ca8279..2a2bc34881a 100644 --- a/go/vt/vtgate/planbuilder/builder.go +++ b/go/vt/vtgate/planbuilder/builder.go @@ -19,6 +19,9 @@ package planbuilder import ( "errors" + "vitess.io/vitess/go/sqltypes" + querypb "vitess.io/vitess/go/vt/proto/query" + "vitess.io/vitess/go/vt/vterrors" "vitess.io/vitess/go/vt/key" @@ -44,6 +47,7 @@ type ContextVSchema interface { FirstSortedKeyspace() (*vindexes.Keyspace, error) SysVarSetEnabled() bool NewPlanner() bool + KeyspaceExists(keyspace string) bool } type truncater interface { @@ -102,14 +106,11 @@ func createInstructionFor(query string, stmt sqlparser.Statement, vschema Contex return buildRoutePlan(stmt, vschema, buildDeletePlan) case *sqlparser.Union: return buildRoutePlan(stmt, vschema, buildUnionPlan) - case *sqlparser.DDL: + case sqlparser.DDLStatement: if sqlparser.IsVschemaDDL(stmt) { return buildVSchemaDDLPlan(stmt, vschema) } - if sqlparser.IsOnlineSchemaDDL(stmt, query) { - return buildOnlineDDLPlan(query, stmt, vschema) - } - return buildDDLPlan(query, stmt, vschema) + return buildGeneralDDLPlan(query, stmt, vschema) case *sqlparser.Use: return buildUsePlan(stmt, vschema) case *sqlparser.Explain: @@ -127,8 +128,8 @@ func createInstructionFor(query string, stmt sqlparser.Statement, vschema Contex return buildSetPlan(stmt, vschema) case *sqlparser.Load: return buildLoadPlan(query, vschema) - case *sqlparser.DBDDL: - return nil, vterrors.Errorf(vtrpcpb.Code_UNIMPLEMENTED, "unsupported: Database DDL %v", sqlparser.String(stmt)) + case sqlparser.DBDDLStatement: + return buildRoutePlan(stmt, vschema, buildDBDDLPlan) case *sqlparser.SetTransaction: return nil, ErrPlanNotSupported case *sqlparser.Begin, *sqlparser.Commit, *sqlparser.Rollback, *sqlparser.Savepoint, *sqlparser.SRollback, *sqlparser.Release: @@ -141,6 +142,49 @@ func createInstructionFor(query string, stmt sqlparser.Statement, vschema Contex return nil, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "BUG: unexpected statement type: %T", stmt) } +func buildDBDDLPlan(stmt sqlparser.Statement, vschema ContextVSchema) (engine.Primitive, error) { + dbDDLstmt := stmt.(sqlparser.DBDDLStatement) + ksName := dbDDLstmt.GetDatabaseName() + if ksName == "" { + ks, err := vschema.DefaultKeyspace() + if err != nil { + return nil, err + } + ksName = ks.Name + } + ksExists := vschema.KeyspaceExists(ksName) + + switch dbDDL := dbDDLstmt.(type) { + case *sqlparser.DBDDL: + switch dbDDL.Action { + case sqlparser.DropDBDDLAction: + if dbDDL.IfExists && !ksExists { + return engine.NewRowsPrimitive(make([][]sqltypes.Value, 0), make([]*querypb.Field, 0)), nil + } + if !ksExists { + return nil, vterrors.Errorf(vtrpcpb.Code_FAILED_PRECONDITION, "cannot drop database '%s'; database does not exists", ksName) + } + return nil, vterrors.New(vtrpcpb.Code_UNIMPLEMENTED, "drop database not allowed") + default: + return nil, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "[BUG] unreachable code path: %s", sqlparser.String(dbDDLstmt)) + } + case *sqlparser.AlterDatabase: + if !ksExists { + return nil, vterrors.Errorf(vtrpcpb.Code_FAILED_PRECONDITION, "cannot alter database '%s'; database does not exists", ksName) + } + return nil, vterrors.New(vtrpcpb.Code_UNIMPLEMENTED, "alter database not allowed") + case *sqlparser.CreateDatabase: + if dbDDL.IfNotExists && ksExists { + return engine.NewRowsPrimitive(make([][]sqltypes.Value, 0), make([]*querypb.Field, 0)), nil + } + if !dbDDL.IfNotExists && ksExists { + return nil, vterrors.Errorf(vtrpcpb.Code_ALREADY_EXISTS, "cannot create database '%s'; database exists", ksName) + } + return nil, vterrors.New(vtrpcpb.Code_UNIMPLEMENTED, "create database not allowed") + } + return nil, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "[BUG] unreachable code path: %s", sqlparser.String(dbDDLstmt)) +} + func buildLoadPlan(query string, vschema ContextVSchema) (engine.Primitive, error) { keyspace, err := vschema.DefaultKeyspace() if err != nil { diff --git a/go/vt/vtgate/planbuilder/ddl.go b/go/vt/vtgate/planbuilder/ddl.go index f95b1b637a5..d179ad2ed74 100644 --- a/go/vt/vtgate/planbuilder/ddl.go +++ b/go/vt/vtgate/planbuilder/ddl.go @@ -1,60 +1,109 @@ package planbuilder import ( - "fmt" + "vitess.io/vitess/go/vt/proto/vtrpc" + "vitess.io/vitess/go/vt/vterrors" + "vitess.io/vitess/go/vt/vtgate/vindexes" "vitess.io/vitess/go/vt/key" - "vitess.io/vitess/go/vt/schema" "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/vtgate/engine" ) -func buildDDLPlan(sql string, in sqlparser.Statement, vschema ContextVSchema) (engine.Primitive, error) { - stmt := in.(*sqlparser.DDL) - // This method call will validate the destination != nil check. - destination, keyspace, _, err := vschema.TargetDestination(stmt.Table.Qualifier.String()) +// buildGeneralDDLPlan builds a general DDL plan, which can be either normal DDL or online DDL. +// The two behave compeltely differently, and have two very different primitives. +// We want to be able to dynamically choose between normal/online plans according to Session settings. +// However, due to caching of plans, we're unable to make that choice right now. In this function we don't have +// a session context. It's only when we Execute() the primitive that we have that context. +// This is why we return a compound primitive (DDL) which contains fully populated primitives (Send & OnlineDDL), +// and which chooses which of the two to invoke at runtime. +func buildGeneralDDLPlan(sql string, ddlStatement sqlparser.DDLStatement, vschema ContextVSchema) (engine.Primitive, error) { + normalDDLPlan, err := buildDDLPlan(sql, ddlStatement, vschema) if err != nil { return nil, err } + onlineDDLPlan, err := buildOnlineDDLPlan(sql, ddlStatement, vschema) + if err != nil { + return nil, err + } + query := sql + // If the query is fully parsed, generate the query from the ast. Otherwise, use the original query + if ddlStatement.IsFullyParsed() { + query = sqlparser.String(ddlStatement) + } + + return &engine.DDL{ + Keyspace: normalDDLPlan.Keyspace, + SQL: query, + DDL: ddlStatement, + NormalDDL: normalDDLPlan, + OnlineDDL: onlineDDLPlan, + }, nil +} + +func buildDDLPlan(sql string, ddlStatement sqlparser.DDLStatement, vschema ContextVSchema) (*engine.Send, error) { + var table *vindexes.Table + var destination key.Destination + var keyspace *vindexes.Keyspace + var err error + + switch ddlStatement.(type) { + case *sqlparser.CreateIndex: + // For Create index, the table must already exist + // We should find the target of the query from this tables location + table, _, _, _, destination, err = vschema.FindTableOrVindex(ddlStatement.GetTable()) + keyspace = table.Keyspace + if err != nil { + return nil, err + } + if table == nil { + return nil, vterrors.Errorf(vtrpc.Code_INVALID_ARGUMENT, "table does not exists: %s", ddlStatement.GetTable().Name.String()) + } + ddlStatement.SetTable("", table.Name.String()) + case *sqlparser.DDL: + destination, keyspace, _, err = vschema.TargetDestination(ddlStatement.GetTable().Qualifier.String()) + if err != nil { + return nil, err + } + } if destination == nil { destination = key.DestinationAllShards{} } + query := sql + // If the query is fully parsed, generate the query from the ast. Otherwise, use the original query + if ddlStatement.IsFullyParsed() { + query = sqlparser.String(ddlStatement) + } + return &engine.Send{ Keyspace: keyspace, TargetDestination: destination, - Query: sql, //This is original sql query to be passed as the parser can provide partial ddl AST. + Query: query, IsDML: false, SingleShardOnly: false, }, nil } -func buildOnlineDDLPlan(query string, stmt *sqlparser.DDL, vschema ContextVSchema) (engine.Primitive, error) { - _, keyspace, _, err := vschema.TargetDestination(stmt.Table.Qualifier.String()) +func buildOnlineDDLPlan(query string, ddlStatement sqlparser.DDLStatement, vschema ContextVSchema) (*engine.OnlineDDL, error) { + _, keyspace, _, err := vschema.TargetDestination(ddlStatement.GetTable().Qualifier.String()) if err != nil { return nil, err } - if stmt.OnlineHint == nil { - return nil, fmt.Errorf("Not an online DDL: %s", query) - } - switch stmt.OnlineHint.Strategy { - case schema.DDLStrategyGhost, schema.DDLStrategyPTOSC: // OK, do nothing - case schema.DDLStrategyNormal: - return nil, fmt.Errorf("Not an online DDL strategy") - default: - return nil, fmt.Errorf("Unknown online DDL strategy: '%v'", stmt.OnlineHint.Strategy) - } + // strategy and options will be computed in real time, on Execute() return &engine.OnlineDDL{ Keyspace: keyspace, - DDL: stmt, + DDL: ddlStatement, SQL: query, - Strategy: stmt.OnlineHint.Strategy, - Options: stmt.OnlineHint.Options, }, nil } -func buildVSchemaDDLPlan(stmt *sqlparser.DDL, vschema ContextVSchema) (engine.Primitive, error) { +func buildVSchemaDDLPlan(ddlStmt sqlparser.DDLStatement, vschema ContextVSchema) (engine.Primitive, error) { + stmt, ok := ddlStmt.(*sqlparser.DDL) + if !ok { + return nil, vterrors.Errorf(vtrpc.Code_INTERNAL, "Incorrect type %T", ddlStmt) + } _, keyspace, _, err := vschema.TargetDestination(stmt.Table.Qualifier.String()) if err != nil { return nil, err diff --git a/go/vt/vtgate/planbuilder/expr.go b/go/vt/vtgate/planbuilder/expr.go index 1b21d42ce4f..2a863c449af 100644 --- a/go/vt/vtgate/planbuilder/expr.go +++ b/go/vt/vtgate/planbuilder/expr.go @@ -211,7 +211,8 @@ func (pb *primitiveBuilder) findOrigin(expr sqlparser.Expr) (pullouts []*pullout func hasSubquery(node sqlparser.SQLNode) bool { has := false _ = sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { - if _, ok := node.(*sqlparser.Subquery); ok { + switch node.(type) { + case *sqlparser.DerivedTable, *sqlparser.Subquery: has = true return false, errors.New("dummy") } diff --git a/go/vt/vtgate/planbuilder/filtering.go b/go/vt/vtgate/planbuilder/filtering.go index a01c64dd657..6193f66b5ec 100644 --- a/go/vt/vtgate/planbuilder/filtering.go +++ b/go/vt/vtgate/planbuilder/filtering.go @@ -65,13 +65,6 @@ func planFilter(pb *primitiveBuilder, input logicalPlan, filter sqlparser.Expr, return node, nil case *vindexFunc: return filterVindexFunc(node, filter) - case *mergeSort, *pulloutSubquery: - filteredInput, err := planFilter(pb, node.Inputs()[0], filter, whereType, origin) - if err != nil { - return nil, err - } - err = node.Rewrite(filteredInput) - return node, err case *subquery: return nil, errors.New("unsupported: filtering on results of cross-shard subquery") case *orderedAggregate: diff --git a/go/vt/vtgate/planbuilder/from.go b/go/vt/vtgate/planbuilder/from.go index bc602bd63c5..370e9238b81 100644 --- a/go/vt/vtgate/planbuilder/from.go +++ b/go/vt/vtgate/planbuilder/from.go @@ -99,7 +99,7 @@ func (pb *primitiveBuilder) processAliasedTable(tableExpr *sqlparser.AliasedTabl switch expr := tableExpr.Expr.(type) { case sqlparser.TableName: return pb.buildTablePrimitive(tableExpr, expr) - case *sqlparser.Subquery: + case *sqlparser.DerivedTable: spb := newPrimitiveBuilder(pb.vschema, pb.jt) switch stmt := expr.Select.(type) { case *sqlparser.Select: diff --git a/go/vt/vtgate/planbuilder/grouping.go b/go/vt/vtgate/planbuilder/grouping.go index 8ae5d3cbca8..e3d81b3ea86 100644 --- a/go/vt/vtgate/planbuilder/grouping.go +++ b/go/vt/vtgate/planbuilder/grouping.go @@ -50,8 +50,8 @@ func planGroupBy(pb *primitiveBuilder, input logicalPlan, groupBy sqlparser.Grou node.Select.(*sqlparser.Select).GroupBy = groupBy return node, nil case *orderedAggregate: - colNumber := -1 for _, expr := range groupBy { + colNumber := -1 switch e := expr.(type) { case *sqlparser.ColName: c := e.Metadata.(*column) @@ -90,8 +90,6 @@ func planGroupBy(pb *primitiveBuilder, input logicalPlan, groupBy sqlparser.Grou node.input = newInput return node, nil - case *join: - return nil, vterrors.New(vtrpcpb.Code_UNIMPLEMENTED, "unsupported: group by on cross-shard join") } return nil, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "%T.groupBy: unreachable", input) } @@ -99,17 +97,6 @@ func planGroupBy(pb *primitiveBuilder, input logicalPlan, groupBy sqlparser.Grou // planDistinct makes the output distinct func planDistinct(input logicalPlan) (logicalPlan, error) { switch node := input.(type) { - case *mergeSort, *pulloutSubquery: - inputs := node.Inputs() - input := inputs[0] - - newInput, err := planDistinct(input) - if err != nil { - return nil, err - } - inputs[0] = newInput - node.Rewrite(inputs...) - return node, nil case *route: node.Select.MakeDistinct() return node, nil @@ -131,12 +118,6 @@ func planDistinct(input logicalPlan) (logicalPlan, error) { node.input = newInput return node, nil - case *subquery: - return nil, vterrors.New(vtrpcpb.Code_UNIMPLEMENTED, "unsupported: distinct on cross-shard subquery") - case *concatenate: - return newDistinct(node), nil - case *join: - return nil, vterrors.New(vtrpcpb.Code_UNIMPLEMENTED, "unsupported: distinct on cross-shard join") case *distinct: return input, nil } diff --git a/go/vt/vtgate/planbuilder/plan_test.go b/go/vt/vtgate/planbuilder/plan_test.go index 8d0b30f63a5..237daa7b7ee 100644 --- a/go/vt/vtgate/planbuilder/plan_test.go +++ b/go/vt/vtgate/planbuilder/plan_test.go @@ -285,6 +285,13 @@ type vschemaWrapper struct { newPlanner bool } +func (vw *vschemaWrapper) KeyspaceExists(keyspace string) bool { + if vw.keyspace != nil { + return vw.keyspace.Name == keyspace + } + return false +} + func (vw *vschemaWrapper) SysVarSetEnabled() bool { return vw.sysVarEnabled } diff --git a/go/vt/vtgate/planbuilder/route.go b/go/vt/vtgate/planbuilder/route.go index a53a07eeae0..f99e4360f4c 100644 --- a/go/vt/vtgate/planbuilder/route.go +++ b/go/vt/vtgate/planbuilder/route.go @@ -519,9 +519,18 @@ func (rb *route) UpdatePlan(pb *primitiveBuilder, filter sqlparser.Expr) { rb.updateRoute(opcode, vindex, values) } } + case engine.SelectMultiEqual: + switch opcode { + case engine.SelectEqualUnique, engine.SelectEqual, engine.SelectIN: + rb.updateRoute(opcode, vindex, values) + case engine.SelectMultiEqual: + if vindex.Cost() < rb.eroute.Vindex.Cost() { + rb.updateRoute(opcode, vindex, values) + } + } case engine.SelectScatter: switch opcode { - case engine.SelectEqualUnique, engine.SelectEqual, engine.SelectIN, engine.SelectNone: + case engine.SelectEqualUnique, engine.SelectEqual, engine.SelectIN, engine.SelectMultiEqual, engine.SelectNone: rb.updateRoute(opcode, vindex, values) } } @@ -577,8 +586,8 @@ func (rb *route) computeEqualPlan(pb *primitiveBuilder, comparison *sqlparser.Co return engine.SelectEqual, vindex, right } -// computeEqualPlan computes the plan for an equality constraint. -func (rb *route) computeISPlan(pb *primitiveBuilder, comparison *sqlparser.IsExpr) (opcode engine.RouteOpcode, vindex vindexes.SingleColumn, condition sqlparser.Expr) { +// computeIS computes the plan for an equality constraint. +func (rb *route) computeISPlan(pb *primitiveBuilder, comparison *sqlparser.IsExpr) (opcode engine.RouteOpcode, vindex vindexes.SingleColumn, expr sqlparser.Expr) { // we only handle IS NULL correct. IsExpr can contain other expressions as well if comparison.Operator != sqlparser.IsNullOp { return engine.SelectScatter, nil, nil @@ -596,7 +605,18 @@ func (rb *route) computeISPlan(pb *primitiveBuilder, comparison *sqlparser.IsExp } // computeINPlan computes the plan for an IN constraint. -func (rb *route) computeINPlan(pb *primitiveBuilder, comparison *sqlparser.ComparisonExpr) (opcode engine.RouteOpcode, vindex vindexes.SingleColumn, condition sqlparser.Expr) { +func (rb *route) computeINPlan(pb *primitiveBuilder, comparison *sqlparser.ComparisonExpr) (opcode engine.RouteOpcode, vindex vindexes.SingleColumn, expr sqlparser.Expr) { + switch comparison.Left.(type) { + case *sqlparser.ColName: + return rb.computeSimpleINPlan(pb, comparison) + case sqlparser.ValTuple: + return rb.computeCompositeINPlan(pb, comparison) + } + return engine.SelectScatter, nil, nil +} + +// computeSimpleINPlan computes the plan for a simple IN constraint. +func (rb *route) computeSimpleINPlan(pb *primitiveBuilder, comparison *sqlparser.ComparisonExpr) (opcode engine.RouteOpcode, vindex vindexes.SingleColumn, expr sqlparser.Expr) { vindex = pb.st.Vindex(comparison.Left, rb) if vindex == nil { return engine.SelectScatter, nil, nil @@ -619,6 +639,86 @@ func (rb *route) computeINPlan(pb *primitiveBuilder, comparison *sqlparser.Compa return engine.SelectScatter, nil, nil } +// computeCompositeINPlan computes the plan for a composite IN constraint. +func (rb *route) computeCompositeINPlan(pb *primitiveBuilder, comparison *sqlparser.ComparisonExpr) (opcode engine.RouteOpcode, vindex vindexes.SingleColumn, values sqlparser.Expr) { + leftTuple := comparison.Left.(sqlparser.ValTuple) + return rb.iterateCompositeIN(pb, comparison, nil, leftTuple) +} + +// iterateCompositeIN recursively walks the LHS tuple of the IN clause looking +// for column names. For those that match a vindex, it builds a multi-value plan +// using the corresponding values in the RHS. It returns the best of the plans built. +func (rb *route) iterateCompositeIN(pb *primitiveBuilder, comparison *sqlparser.ComparisonExpr, coordinates []int, tuple sqlparser.ValTuple) (opcode engine.RouteOpcode, vindex vindexes.SingleColumn, values sqlparser.Expr) { + opcode = engine.SelectScatter + + cindex := len(coordinates) + coordinates = append(coordinates, 0) + for idx, expr := range tuple { + coordinates[cindex] = idx + switch expr := expr.(type) { + case sqlparser.ValTuple: + newOpcode, newVindex, newValues := rb.iterateCompositeIN(pb, comparison, coordinates, expr) + opcode, vindex, values = bestOfComposite(opcode, newOpcode, vindex, newVindex, values, newValues) + case *sqlparser.ColName: + newVindex := pb.st.Vindex(expr, rb) + if newVindex != nil { + newOpcode, newValues := rb.compositePlanForCol(pb, comparison, coordinates) + opcode, vindex, values = bestOfComposite(opcode, newOpcode, vindex, newVindex, values, newValues) + } + } + } + return opcode, vindex, values +} + +// compositePlanForCol builds a plan for a matched column in the LHS +// of a composite IN clause. +func (rb *route) compositePlanForCol(pb *primitiveBuilder, comparison *sqlparser.ComparisonExpr, coordinates []int) (opcode engine.RouteOpcode, values sqlparser.Expr) { + rightTuple, ok := comparison.Right.(sqlparser.ValTuple) + if !ok { + return engine.SelectScatter, nil + } + retVal := make(sqlparser.ValTuple, len(rightTuple)) + for i, rval := range rightTuple { + val := tupleAccess(rval, coordinates) + if val == nil { + return engine.SelectScatter, nil + } + if !rb.exprIsValue(val) { + return engine.SelectScatter, nil + } + retVal[i] = val + } + return engine.SelectMultiEqual, retVal +} + +// tupleAccess returns the value of the expression that corresponds +// to the specified coordinates. +func tupleAccess(expr sqlparser.Expr, coordinates []int) sqlparser.Expr { + tuple, _ := expr.(sqlparser.ValTuple) + for _, idx := range coordinates { + if idx >= len(tuple) { + return nil + } + expr = tuple[idx] + tuple, _ = expr.(sqlparser.ValTuple) + } + return expr +} + +// bestOfComposite returns the best of two composite IN clause plans. +func bestOfComposite(opcode1, opcode2 engine.RouteOpcode, vindex1, vindex2 vindexes.SingleColumn, values1, values2 sqlparser.Expr) (opcode engine.RouteOpcode, vindex vindexes.SingleColumn, values sqlparser.Expr) { + if opcode1 == engine.SelectScatter { + return opcode2, vindex2, values2 + } + if opcode2 == engine.SelectScatter { + return opcode1, vindex1, values1 + } + if vindex1.Cost() < vindex2.Cost() { + return opcode1, vindex1, values1 + } + return opcode2, vindex2, values2 +} + // computeNotInPlan looks for null values to produce a SelectNone if found func (rb *route) computeNotInPlan(right sqlparser.Expr) engine.RouteOpcode { switch node := right.(type) { diff --git a/go/vt/vtgate/planbuilder/route_test.go b/go/vt/vtgate/planbuilder/route_test.go index 8683c225839..ca133f946ba 100644 --- a/go/vt/vtgate/planbuilder/route_test.go +++ b/go/vt/vtgate/planbuilder/route_test.go @@ -32,25 +32,27 @@ For easy reference, opcodes are: SelectEqualUnique 1 SelectEqual 2 SelectIN 3 - SelectScatter 4 - SelectNext 5 - SelectDBA 6 - SelectReference 7 - SelectNone 8 - NumRouteOpcodes 9 + SelectMultiEqual 4 + SelectScatter 5 + SelectNext 6 + SelectDBA 7 + SelectReference 8 + SelectNone 9 + NumRouteOpcodes 10 */ func TestJoinCanMerge(t *testing.T) { testcases := [engine.NumRouteOpcodes][engine.NumRouteOpcodes]bool{ - {true, false, false, false, false, false, false, true, false}, - {false, true, false, false, false, false, false, true, false}, - {false, false, false, false, false, false, false, true, false}, - {false, false, false, false, false, false, false, true, false}, - {false, false, false, false, false, false, false, true, false}, - {false, false, false, false, false, false, false, true, false}, - {false, false, false, false, false, false, true, true, false}, - {true, true, true, true, true, true, true, true, true}, - {false, false, false, false, false, false, false, true, false}, + {true, false, false, false, false, false, false, false, true, false}, + {false, true, false, false, false, false, false, false, true, false}, + {false, false, false, false, false, false, false, false, true, false}, + {false, false, false, false, false, false, false, false, true, false}, + {false, false, false, false, false, false, false, false, true, false}, + {false, false, false, false, false, false, false, false, true, false}, + {false, false, false, false, false, false, false, false, true, false}, + {false, false, false, false, false, false, false, true, true, false}, + {true, true, true, true, true, true, true, true, true, true}, + {false, false, false, false, false, false, false, false, true, false}, } ks := &vindexes.Keyspace{} @@ -75,15 +77,16 @@ func TestJoinCanMerge(t *testing.T) { func TestSubqueryCanMerge(t *testing.T) { testcases := [engine.NumRouteOpcodes][engine.NumRouteOpcodes]bool{ - {true, false, false, false, false, false, false, true, false}, - {false, false, false, false, false, false, false, true, false}, - {false, false, false, false, false, false, false, true, false}, - {false, false, false, false, false, false, false, true, false}, - {false, false, false, false, false, false, false, true, false}, - {false, false, false, false, false, false, false, false, false}, - {false, false, false, false, false, false, true, true, false}, - {false, false, false, false, false, false, false, true, false}, - {false, false, false, false, false, false, false, true, false}, + {true, false, false, false, false, false, false, false, true, false}, + {false, false, false, false, false, false, false, false, true, false}, + {false, false, false, false, false, false, false, false, true, false}, + {false, false, false, false, false, false, false, false, true, false}, + {false, false, false, false, false, false, false, false, true, false}, + {false, false, false, false, false, false, false, false, true, false}, + {false, false, false, false, false, false, false, false, false, false}, + {false, false, false, false, false, false, false, true, true, false}, + {false, false, false, false, false, false, false, false, true, false}, + {false, false, false, false, false, false, false, false, true, false}, } ks := &vindexes.Keyspace{} @@ -103,15 +106,16 @@ func TestSubqueryCanMerge(t *testing.T) { func TestUnionCanMerge(t *testing.T) { testcases := [engine.NumRouteOpcodes][engine.NumRouteOpcodes]bool{ - {true, false, false, false, false, false, false, false, false}, - {false, false, false, false, false, false, false, false, false}, - {false, false, false, false, false, false, false, false, false}, - {false, false, false, false, false, false, false, false, false}, - {false, false, false, false, true, false, false, false, false}, - {false, false, false, false, false, false, false, false, false}, - {false, false, false, false, false, false, true, false, false}, - {false, false, false, false, false, false, false, true, false}, - {false, false, false, false, false, false, false, false, false}, + {true, false, false, false, false, false, false, false, false, false}, + {false, false, false, false, false, false, false, false, false, false}, + {false, false, false, false, false, false, false, false, false, false}, + {false, false, false, false, false, false, false, false, false, false}, + {false, false, false, false, false, false, false, false, false, false}, + {false, false, false, false, false, true, false, false, false, false}, + {false, false, false, false, false, false, false, false, false, false}, + {false, false, false, false, false, false, false, true, false, false}, + {false, false, false, false, false, false, false, false, true, false}, + {false, false, false, false, false, false, false, false, false, false}, } ks := &vindexes.Keyspace{} lRoute := &route{} diff --git a/go/vt/vtgate/planbuilder/select.go b/go/vt/vtgate/planbuilder/select.go index aba2ce24729..5b385b06840 100644 --- a/go/vt/vtgate/planbuilder/select.go +++ b/go/vt/vtgate/planbuilder/select.go @@ -271,7 +271,7 @@ func buildSQLCalcFoundRowsPlan(query string, sel *sqlparser.Select, outer *symta SelectExprs: countStartExpr, From: []sqlparser.TableExpr{ &sqlparser.AliasedTableExpr{ - Expr: &sqlparser.Subquery{Select: sel2}, + Expr: &sqlparser.DerivedTable{Select: sel2}, As: sqlparser.NewTableIdent("t"), }, }, diff --git a/go/vt/vtgate/planbuilder/testdata/aggr_cases.txt b/go/vt/vtgate/planbuilder/testdata/aggr_cases.txt index 32a87d8e486..8d194f0cf9d 100644 --- a/go/vt/vtgate/planbuilder/testdata/aggr_cases.txt +++ b/go/vt/vtgate/planbuilder/testdata/aggr_cases.txt @@ -389,6 +389,10 @@ } } +# group by must only reference expressions in the select list +"select col, count(*) from user group by col, baz" +"unsupported: in scatter query: group by column must reference column in SELECT list" + # group by a non-unique vindex column should use an OrderdAggregate primitive "select name, count(*) from user group by name" { @@ -408,9 +412,9 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select name, count(*) from user where 1 != 1 group by name", + "FieldQuery": "select `name`, count(*) from user where 1 != 1 group by `name`", "OrderBy": "0 ASC", - "Query": "select name, count(*) from user group by name order by name asc", + "Query": "select `name`, count(*) from user group by `name` order by `name` asc", "Table": "user" } ] @@ -905,6 +909,34 @@ } } +# scatter aggregate multiple group by columns inverse order +"select a, b, count(*) from user group by b, a" +{ + "QueryType": "SELECT", + "Original": "select a, b, count(*) from user group by b, a", + "Instructions": { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "Aggregates": "count(2)", + "Distinct": "false", + "GroupBy": "1, 0", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "SelectScatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select a, b, count(*) from user where 1 != 1 group by b, a", + "OrderBy": "1 ASC, 0 ASC", + "Query": "select a, b, count(*) from user group by b, a order by b asc, a asc", + "Table": "user" + } + ] + } +} + # scatter aggregate group by column number "select col from user group by 1" { diff --git a/go/vt/vtgate/planbuilder/testdata/bypass_cases.txt b/go/vt/vtgate/planbuilder/testdata/bypass_cases.txt index c7345318933..daafda9d360 100644 --- a/go/vt/vtgate/planbuilder/testdata/bypass_cases.txt +++ b/go/vt/vtgate/planbuilder/testdata/bypass_cases.txt @@ -65,7 +65,7 @@ }, "TargetDestination": "Shard(-80)", "IsDML": true, - "Query": "insert into USER(ID, NAME) values (42, 'ms X')", + "Query": "insert into USER(ID, `NAME`) values (42, 'ms X')", "SingleShardOnly": false } } diff --git a/go/vt/vtgate/planbuilder/testdata/ddl_cases.txt b/go/vt/vtgate/planbuilder/testdata/ddl_cases.txt index c5bc58e56aa..5ab474c585a 100644 --- a/go/vt/vtgate/planbuilder/testdata/ddl_cases.txt +++ b/go/vt/vtgate/planbuilder/testdata/ddl_cases.txt @@ -4,15 +4,12 @@ "QueryType": "DDL", "Original": "create table t1(id bigint, primary key(id))", "Instructions": { - "OperatorType": "Send", + "OperatorType": "DDL", "Keyspace": { "Name": "main", "Sharded": false }, - "TargetDestination": "AllShards()", - "IsDML": false, - "Query": "create table t1(id bigint, primary key(id))", - "SingleShardOnly": false + "Query": "create table t1(id bigint, primary key(id))" } } @@ -22,15 +19,12 @@ "QueryType": "DDL", "Original": "create table user.t1(id bigint, primary key(id))", "Instructions": { - "OperatorType": "Send", + "OperatorType": "DDL", "Keyspace": { "Name": "user", "Sharded": true }, - "TargetDestination": "AllShards()", - "IsDML": false, - "Query": "create table user.t1(id bigint, primary key(id))", - "SingleShardOnly": false + "Query": "create table user.t1(id bigint, primary key(id))" } } @@ -40,15 +34,12 @@ "QueryType": "DDL", "Original": "create table a(id int)", "Instructions": { - "OperatorType": "Send", + "OperatorType": "DDL", "Keyspace": { "Name": "main", "Sharded": false }, - "TargetDestination": "AllShards()", - "IsDML": false, - "Query": "create table a(id int)", - "SingleShardOnly": false + "Query": "create table a(id int)" } } @@ -62,15 +53,12 @@ "QueryType": "DDL", "Original": "alter table a ADD id int", "Instructions": { - "OperatorType": "Send", + "OperatorType": "DDL", "Keyspace": { "Name": "main", "Sharded": false }, - "TargetDestination": "AllShards()", - "IsDML": false, - "Query": "alter table a ADD id int", - "SingleShardOnly": false + "Query": "alter table a ADD id int" } } @@ -80,18 +68,98 @@ "QueryType": "DDL", "Original": "alter table user.b ADD id int", "Instructions": { - "OperatorType": "Send", + "OperatorType": "DDL", "Keyspace": { "Name": "user", "Sharded": true }, - "TargetDestination": "AllShards()", - "IsDML": false, - "Query": "alter table user.b ADD id int", - "SingleShardOnly": false + "Query": "alter table user.b ADD id int" } } #Alter table with unknown qualifier "alter table a.b ADD id int" "no keyspace with name [a] found" + +# create db foo +"create database foo" +"create database not allowed" + +# create db main +"create database main" +"cannot create database 'main'; database exists" + +# create db if not exists main +"create database if not exists main" +{ + "QueryType": "DDL", + "Original": "create database if not exists main", + "Instructions": { + "OperatorType": "Rows" + } +} + +# alter db foo +"alter database foo collate utf8" +"cannot alter database 'foo'; database does not exists" + +# alter db main +"alter database main collate utf8" +"alter database not allowed" + +# drop db foo +"drop database foo" +"cannot drop database 'foo'; database does not exists" + +# drop db main +"drop database main" +"drop database not allowed" + +# drop db if exists main +"drop database if exists main" +"drop database not allowed" + +# DDL +"create index a on user(id)" +{ + "QueryType": "DDL", + "Original": "create index a on user(id)", + "Instructions": { + "OperatorType": "DDL", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "Query": "create index a on user (id)" + } +} + +# DDL with qualifier +"create index a on user.user(id)" +{ + "QueryType": "DDL", + "Original": "create index a on user.user(id)", + "Instructions": { + "OperatorType": "DDL", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "Query": "create index a on user (id)" + } +} + +# DDL with qualifier for a table not in vschema of an unsharded keyspace +"create index a on main.unknown(id)" +{ + "QueryType": "DDL", + "Original": "create index a on main.unknown(id)", + "Instructions": { + "OperatorType": "DDL", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "Query": "create index a on unknown (id)" + } +} diff --git a/go/vt/vtgate/planbuilder/testdata/dml_cases.txt b/go/vt/vtgate/planbuilder/testdata/dml_cases.txt index 449b16b4c47..435378c7e04 100644 --- a/go/vt/vtgate/planbuilder/testdata/dml_cases.txt +++ b/go/vt/vtgate/planbuilder/testdata/dml_cases.txt @@ -256,7 +256,7 @@ }, "TargetTabletType": "MASTER", "MultiShardAutocommit": false, - "Query": "update user set val = 1 where name = 'foo' and id = 1", + "Query": "update user set val = 1 where `name` = 'foo' and id = 1", "Table": "user", "Values": [ 1 @@ -415,7 +415,7 @@ "TargetTabletType": "MASTER", "KsidVindex": "user_index", "MultiShardAutocommit": false, - "OwnedVindexQuery": "select Id, Name, Costly from user where id = 1 for update", + "OwnedVindexQuery": "select Id, `Name`, Costly from user where id = 1 for update", "Query": "delete from user where id = 1", "Table": "user", "Values": [ @@ -494,7 +494,7 @@ "TargetTabletType": "MASTER", "KsidVindex": "user_index", "MultiShardAutocommit": false, - "OwnedVindexQuery": "select Id, Name, Costly from user where id = 1 for update", + "OwnedVindexQuery": "select Id, `Name`, Costly from user where id = 1 for update", "Query": "delete from user as route1 where id = 1", "Table": "user", "Values": [ @@ -894,7 +894,7 @@ }, "TargetTabletType": "MASTER", "MultiShardAutocommit": false, - "Query": "insert into user(id, val, Name, Costly) values (:_Id_0, 1, :_Name_0, :_Costly_0)", + "Query": "insert into user(id, val, `Name`, Costly) values (:_Id_0, 1, :_Name_0, :_Costly_0)", "TableName": "user" } } @@ -913,7 +913,7 @@ }, "TargetTabletType": "MASTER", "MultiShardAutocommit": false, - "Query": "insert into user(id, Name, Costly) values (:_Id_0, :_Name_0, :_Costly_0)", + "Query": "insert into user(id, `Name`, Costly) values (:_Id_0, :_Name_0, :_Costly_0)", "TableName": "user" } } @@ -955,7 +955,7 @@ }, "TargetTabletType": "MASTER", "MultiShardAutocommit": false, - "Query": "insert into user(id, Name, Costly) values (:_Id_0, :_Name_0, :_Costly_0)", + "Query": "insert into user(id, `Name`, Costly) values (:_Id_0, :_Name_0, :_Costly_0)", "TableName": "user" } } @@ -974,7 +974,7 @@ }, "TargetTabletType": "MASTER", "MultiShardAutocommit": false, - "Query": "insert into user(id, Name, Costly) values (:_Id_0, :_Name_0, :_Costly_0)", + "Query": "insert into user(id, `Name`, Costly) values (:_Id_0, :_Name_0, :_Costly_0)", "TableName": "user" } } @@ -993,7 +993,7 @@ }, "TargetTabletType": "MASTER", "MultiShardAutocommit": false, - "Query": "insert ignore into user(id, Name, Costly) values (:_Id_0, :_Name_0, :_Costly_0)", + "Query": "insert ignore into user(id, `Name`, Costly) values (:_Id_0, :_Name_0, :_Costly_0)", "TableName": "user" } } @@ -1012,7 +1012,7 @@ }, "TargetTabletType": "MASTER", "MultiShardAutocommit": false, - "Query": "insert into user(id, Name, Costly) values (:_Id_0, :_Name_0, :_Costly_0) on duplicate key update col = 2", + "Query": "insert into user(id, `Name`, Costly) values (:_Id_0, :_Name_0, :_Costly_0) on duplicate key update col = 2", "TableName": "user" } } @@ -1031,7 +1031,7 @@ }, "TargetTabletType": "MASTER", "MultiShardAutocommit": false, - "Query": "insert into user(id, Name, Costly) values (:_Id_0, :_Name_0, :_Costly_0)", + "Query": "insert into user(id, `Name`, Costly) values (:_Id_0, :_Name_0, :_Costly_0)", "TableName": "user" } } @@ -1050,7 +1050,7 @@ }, "TargetTabletType": "MASTER", "MultiShardAutocommit": false, - "Query": "insert into user(nonid, id, Name, Costly) values (2, :_Id_0, :_Name_0, :_Costly_0)", + "Query": "insert into user(nonid, id, `Name`, Costly) values (2, :_Id_0, :_Name_0, :_Costly_0)", "TableName": "user" } } @@ -1069,7 +1069,7 @@ }, "TargetTabletType": "MASTER", "MultiShardAutocommit": false, - "Query": "insert into user(id, nonid, Name, Costly) values (:_Id_0, 2, :_Name_0, :_Costly_0)", + "Query": "insert into user(id, nonid, `Name`, Costly) values (:_Id_0, 2, :_Name_0, :_Costly_0)", "TableName": "user" } } @@ -1088,7 +1088,7 @@ }, "TargetTabletType": "MASTER", "MultiShardAutocommit": false, - "Query": "insert into user(nonid, id, Name, Costly) values (true, :_Id_0, :_Name_0, :_Costly_0)", + "Query": "insert into user(nonid, id, `Name`, Costly) values (true, :_Id_0, :_Name_0, :_Costly_0)", "TableName": "user" } } @@ -1107,7 +1107,7 @@ }, "TargetTabletType": "MASTER", "MultiShardAutocommit": false, - "Query": "insert into user(nonid, name, id, Costly) values (2, :_Name_0, :_Id_0, :_Costly_0)", + "Query": "insert into user(nonid, `name`, id, Costly) values (2, :_Name_0, :_Id_0, :_Costly_0)", "TableName": "user" } } @@ -1199,7 +1199,7 @@ }, "TargetTabletType": "MASTER", "MultiShardAutocommit": false, - "Query": "insert into user(id, Name, Costly) values (:_Id_0, :_Name_0, :_Costly_0), (:_Id_1, :_Name_1, :_Costly_1)", + "Query": "insert into user(id, `Name`, Costly) values (:_Id_0, :_Name_0, :_Costly_0), (:_Id_1, :_Name_1, :_Costly_1)", "TableName": "user" } } @@ -1218,7 +1218,7 @@ }, "TargetTabletType": "MASTER", "MultiShardAutocommit": false, - "Query": "insert /*vt+ QUERY_TIMEOUT_MS=1 */ into user(id, Name, Costly) values (:_Id_0, :_Name_0, :_Costly_0), (:_Id_1, :_Name_1, :_Costly_1)", + "Query": "insert /*vt+ QUERY_TIMEOUT_MS=1 */ into user(id, `Name`, Costly) values (:_Id_0, :_Name_0, :_Costly_0), (:_Id_1, :_Name_1, :_Costly_1)", "QueryTimeout": 1, "TableName": "user" } @@ -1238,7 +1238,7 @@ }, "TargetTabletType": "MASTER", "MultiShardAutocommit": true, - "Query": "insert /*vt+ MULTI_SHARD_AUTOCOMMIT=1 */ into user(id, Name, Costly) values (:_Id_0, :_Name_0, :_Costly_0), (:_Id_1, :_Name_1, :_Costly_1)", + "Query": "insert /*vt+ MULTI_SHARD_AUTOCOMMIT=1 */ into user(id, `Name`, Costly) values (:_Id_0, :_Name_0, :_Costly_0), (:_Id_1, :_Name_1, :_Costly_1)", "TableName": "user" } } @@ -1625,7 +1625,7 @@ }, "TargetTabletType": "MASTER", "MultiShardAutocommit": false, - "Query": "update user_extra set val = 1 where name = 'foo'", + "Query": "update user_extra set val = 1 where `name` = 'foo'", "Table": "user_extra" } } @@ -1663,7 +1663,7 @@ }, "TargetTabletType": "MASTER", "MultiShardAutocommit": false, - "Query": "update user_extra set val = 1 where name = 'foo' or id = 1", + "Query": "update user_extra set val = 1 where `name` = 'foo' or id = 1", "Table": "user_extra" } } @@ -1739,7 +1739,7 @@ }, "TargetTabletType": "MASTER", "MultiShardAutocommit": false, - "Query": "delete from user_extra where name = 'jose'", + "Query": "delete from user_extra where `name` = 'jose'", "Table": "user_extra" } } @@ -1758,7 +1758,7 @@ }, "TargetTabletType": "MASTER", "MultiShardAutocommit": true, - "Query": "delete /*vt+ MULTI_SHARD_AUTOCOMMIT=1 */ from user_extra where name = 'jose'", + "Query": "delete /*vt+ MULTI_SHARD_AUTOCOMMIT=1 */ from user_extra where `name` = 'jose'", "Table": "user_extra" } } @@ -1777,7 +1777,7 @@ }, "TargetTabletType": "MASTER", "MultiShardAutocommit": false, - "Query": "delete /*vt+ QUERY_TIMEOUT_MS=1 */ from user_extra where name = 'jose'", + "Query": "delete /*vt+ QUERY_TIMEOUT_MS=1 */ from user_extra where `name` = 'jose'", "QueryTimeout": 1, "Table": "user_extra" } @@ -1863,8 +1863,8 @@ ], "KsidVindex": "user_index", "MultiShardAutocommit": false, - "OwnedVindexQuery": "select Id, Name, Costly, name = null from user where id = 1 for update", - "Query": "update user set name = null where id = 1", + "OwnedVindexQuery": "select Id, `Name`, Costly, `name` = null from user where id = 1 for update", + "Query": "update user set `name` = null where id = 1", "Table": "user", "Values": [ 1 @@ -1910,8 +1910,8 @@ ], "KsidVindex": "user_index", "MultiShardAutocommit": false, - "OwnedVindexQuery": "select Id, Name, Costly, name = null from user where id in (1, 2, 3) for update", - "Query": "update user set name = null where id in (1, 2, 3)", + "OwnedVindexQuery": "select Id, `Name`, Costly, `name` = null from user where id in (1, 2, 3) for update", + "Query": "update user set `name` = null where id in (1, 2, 3)", "Table": "user", "Values": [ [ @@ -1942,8 +1942,8 @@ ], "KsidVindex": "user_index", "MultiShardAutocommit": false, - "OwnedVindexQuery": "select Id, Name, Costly, name = null from user for update", - "Query": "update user set name = null", + "OwnedVindexQuery": "select Id, `Name`, Costly, `name` = null from user for update", + "Query": "update user set `name` = null", "Table": "user" } } @@ -1966,8 +1966,8 @@ ], "KsidVindex": "user_index", "MultiShardAutocommit": false, - "OwnedVindexQuery": "select Id, Name, Costly, name = null from user where id + 1 = 2 for update", - "Query": "update user set name = null where id + 1 = 2", + "OwnedVindexQuery": "select Id, `Name`, Costly, `name` = null from user where id + 1 = 2 for update", + "Query": "update user set `name` = null where id + 1 = 2", "Table": "user" } } @@ -1987,7 +1987,7 @@ "TargetTabletType": "MASTER", "KsidVindex": "user_index", "MultiShardAutocommit": false, - "OwnedVindexQuery": "select Id, Name, Costly from user where id in (1, 2, 3) for update", + "OwnedVindexQuery": "select Id, `Name`, Costly from user where id in (1, 2, 3) for update", "Query": "delete from user where id in (1, 2, 3)", "Table": "user", "Values": [ @@ -2016,7 +2016,7 @@ "TargetTabletType": "MASTER", "KsidVindex": "user_index", "MultiShardAutocommit": false, - "OwnedVindexQuery": "select Id, Name, Costly from user where id + 1 = 2 for update", + "OwnedVindexQuery": "select Id, `Name`, Costly from user where id + 1 = 2 for update", "Query": "delete from user where id + 1 = 2", "Table": "user" } @@ -2037,7 +2037,7 @@ "TargetTabletType": "MASTER", "KsidVindex": "user_index", "MultiShardAutocommit": false, - "OwnedVindexQuery": "select Id, Name, Costly from user for update", + "OwnedVindexQuery": "select Id, `Name`, Costly from user for update", "Query": "delete from user", "Table": "user" } @@ -2102,7 +2102,7 @@ "TargetTabletType": "MASTER", "KsidVindex": "user_index", "MultiShardAutocommit": false, - "OwnedVindexQuery": "select Id, Name, Costly from user for update", + "OwnedVindexQuery": "select Id, `Name`, Costly from user for update", "Query": "delete from user", "Table": "user" } @@ -2154,8 +2154,8 @@ ], "KsidVindex": "user_index", "MultiShardAutocommit": false, - "OwnedVindexQuery": "select Id, Name, Costly, name = _binary 'abc' from user where id = 1 for update", - "Query": "update user set name = _binary 'abc' where id = 1", + "OwnedVindexQuery": "select Id, `Name`, Costly, `name` = _binary 'abc' from user where id = 1 for update", + "Query": "update user set `name` = _binary 'abc' where id = 1", "Table": "user", "Values": [ 1 @@ -2179,8 +2179,8 @@ "TargetTabletType": "MASTER", "KsidVindex": "user_index", "MultiShardAutocommit": false, - "OwnedVindexQuery": "select Id, Name, Costly from user where name = _binary 'abc' for update", - "Query": "delete from user where name = _binary 'abc'", + "OwnedVindexQuery": "select Id, `Name`, Costly from user where `name` = _binary 'abc' for update", + "Query": "delete from user where `name` = _binary 'abc'", "Table": "user" } } @@ -2200,7 +2200,7 @@ "TargetTabletType": "MASTER", "KsidVindex": "user_index", "MultiShardAutocommit": false, - "OwnedVindexQuery": "select Id, Name, Costly from user for update", + "OwnedVindexQuery": "select Id, `Name`, Costly from user for update", "Query": "delete from user", "Table": "user" } @@ -2224,8 +2224,8 @@ ], "KsidVindex": "user_index", "MultiShardAutocommit": false, - "OwnedVindexQuery": "select Id, Name, Costly, name = 'myname' from user for update", - "Query": "update user set name = 'myname'", + "OwnedVindexQuery": "select Id, `Name`, Costly, `name` = 'myname' from user for update", + "Query": "update user set `name` = 'myname'", "Table": "user" } } diff --git a/go/vt/vtgate/planbuilder/testdata/filter_cases.txt b/go/vt/vtgate/planbuilder/testdata/filter_cases.txt index ba88fc63406..01f8cf364bc 100644 --- a/go/vt/vtgate/planbuilder/testdata/filter_cases.txt +++ b/go/vt/vtgate/planbuilder/testdata/filter_cases.txt @@ -109,7 +109,7 @@ "Sharded": true }, "FieldQuery": "select id from user where 1 != 1", - "Query": "select id from user where costly = 'aa' and name = 'bb'", + "Query": "select id from user where costly = 'aa' and `name` = 'bb'", "Table": "user", "Values": [ "bb" @@ -131,7 +131,7 @@ "Sharded": true }, "FieldQuery": "select id from user where 1 != 1", - "Query": "select id from user where costly in ('aa', 'bb') and name in ::__vals", + "Query": "select id from user where costly in ('aa', 'bb') and `name` in ::__vals", "Table": "user", "Values": [ [ @@ -143,6 +143,299 @@ } } +# Composite IN clause +"select id from user where (name, col) in (('aa', 'bb'), ('cc', 'dd'))" +{ + "QueryType": "SELECT", + "Original": "select id from user where (name, col) in (('aa', 'bb'), ('cc', 'dd'))", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectMultiEqual", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id from user where 1 != 1", + "Query": "select id from user where (`name`, col) in (('aa', 'bb'), ('cc', 'dd'))", + "Table": "user", + "Values": [ + [ + "aa", + "cc" + ] + ], + "Vindex": "name_user_map" + } +} + +# Composite IN clause, swapped columns +"select id from user where (col, name) in (('aa', 'bb'), ('cc', 'dd'))" +{ + "QueryType": "SELECT", + "Original": "select id from user where (col, name) in (('aa', 'bb'), ('cc', 'dd'))", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectMultiEqual", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id from user where 1 != 1", + "Query": "select id from user where (col, `name`) in (('aa', 'bb'), ('cc', 'dd'))", + "Table": "user", + "Values": [ + [ + "bb", + "dd" + ] + ], + "Vindex": "name_user_map" + } +} + +# Composite IN clause, choose cost within tuple +"select id from user where (costly, name) in (('aa', 'bb'), ('cc', 'dd'))" +{ + "QueryType": "SELECT", + "Original": "select id from user where (costly, name) in (('aa', 'bb'), ('cc', 'dd'))", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectMultiEqual", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id from user where 1 != 1", + "Query": "select id from user where (costly, `name`) in (('aa', 'bb'), ('cc', 'dd'))", + "Table": "user", + "Values": [ + [ + "bb", + "dd" + ] + ], + "Vindex": "name_user_map" + } +} + +# Composite IN clause, choose cost within tuple, swapped +"select id from user where (name, costly) in (('aa', 'bb'), ('cc', 'dd'))" +{ + "QueryType": "SELECT", + "Original": "select id from user where (name, costly) in (('aa', 'bb'), ('cc', 'dd'))", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectMultiEqual", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id from user where 1 != 1", + "Query": "select id from user where (`name`, costly) in (('aa', 'bb'), ('cc', 'dd'))", + "Table": "user", + "Values": [ + [ + "aa", + "cc" + ] + ], + "Vindex": "name_user_map" + } +} + +# Composite IN clause, choose cost +"select id from user where (col, costly) in (('aa', 'bb')) and (col, name) in (('cc', 'dd'))" +{ + "QueryType": "SELECT", + "Original": "select id from user where (col, costly) in (('aa', 'bb')) and (col, name) in (('cc', 'dd'))", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectMultiEqual", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id from user where 1 != 1", + "Query": "select id from user where (col, costly) in (('aa', 'bb')) and (col, `name`) in (('cc', 'dd'))", + "Table": "user", + "Values": [ + [ + "dd" + ] + ], + "Vindex": "name_user_map" + } +} + +# Composite IN clause vs equality +"select id from user where (col, name) in (('aa', 'bb')) and id = 5" +{ + "QueryType": "SELECT", + "Original": "select id from user where (col, name) in (('aa', 'bb')) and id = 5", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectEqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id from user where 1 != 1", + "Query": "select id from user where (col, `name`) in (('aa', 'bb')) and id = 5", + "Table": "user", + "Values": [ + 5 + ], + "Vindex": "user_index" + } +} + +# Composite IN: multiple vindex matches +"select id from user where (costly, name) in (('aa', 'bb'), ('cc', 'dd'))" +{ + "QueryType": "SELECT", + "Original": "select id from user where (costly, name) in (('aa', 'bb'), ('cc', 'dd'))", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectMultiEqual", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id from user where 1 != 1", + "Query": "select id from user where (costly, `name`) in (('aa', 'bb'), ('cc', 'dd'))", + "Table": "user", + "Values": [ + [ + "bb", + "dd" + ] + ], + "Vindex": "name_user_map" + } +} + +# Composite IN: tuple inside tuple +"select id from user where ((col1, name), col2) in ((('aa', 'bb'), 'cc'), (('dd', 'ee'), 'ff'))" +{ + "QueryType": "SELECT", + "Original": "select id from user where ((col1, name), col2) in ((('aa', 'bb'), 'cc'), (('dd', 'ee'), 'ff'))", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectMultiEqual", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id from user where 1 != 1", + "Query": "select id from user where ((col1, `name`), col2) in ((('aa', 'bb'), 'cc'), (('dd', 'ee'), 'ff'))", + "Table": "user", + "Values": [ + [ + "bb", + "ee" + ] + ], + "Vindex": "name_user_map" + } +} + +# Composite IN: tuple inside tuple, but no match in tuple +"select id from user where (name, (col1, col2)) in (('aa', ('bb', 'cc')), ('dd', ('ee', 'ff')))" +{ + "QueryType": "SELECT", + "Original": "select id from user where (name, (col1, col2)) in (('aa', ('bb', 'cc')), ('dd', ('ee', 'ff')))", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectMultiEqual", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id from user where 1 != 1", + "Query": "select id from user where (`name`, (col1, col2)) in (('aa', ('bb', 'cc')), ('dd', ('ee', 'ff')))", + "Table": "user", + "Values": [ + [ + "aa", + "dd" + ] + ], + "Vindex": "name_user_map" + } +} + +# Composite IN: tuple inside tuple, mismiatched values +"select id from user where ((col1, name), col2) in (('aa', 'bb', 'cc'), (('dd', 'ee'), 'ff'))" +{ + "QueryType": "SELECT", + "Original": "select id from user where ((col1, name), col2) in (('aa', 'bb', 'cc'), (('dd', 'ee'), 'ff'))", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectScatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id from user where 1 != 1", + "Query": "select id from user where ((col1, `name`), col2) in (('aa', 'bb', 'cc'), (('dd', 'ee'), 'ff'))", + "Table": "user" + } +} + +# Composite IN: RHS not tuple +"select id from user where (col1, name) in (select * from music where music.user_id=user.id)" +{ + "QueryType": "SELECT", + "Original": "select id from user where (col1, name) in (select * from music where music.user_id=user.id)", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectScatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id from user where 1 != 1", + "Query": "select id from user where (col1, `name`) in (select * from music where music.user_id = user.id)", + "Table": "user" + } +} + +# Composite IN: RHS has no simple values +"select id from user where (col1, name) in (('aa', 1+1))" +{ + "QueryType": "SELECT", + "Original": "select id from user where (col1, name) in (('aa', 1+1))", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectScatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id from user where 1 != 1", + "Query": "select id from user where (col1, `name`) in (('aa', 1 + 1))", + "Table": "user" + } +} + +# IN clause: LHS is neither column nor composite tuple +"select Id from user where 1 in ('aa', 'bb')" +{ + "QueryType": "SELECT", + "Original": "select Id from user where 1 in ('aa', 'bb')", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectScatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select Id from user where 1 != 1", + "Query": "select Id from user where 1 in ('aa', 'bb')", + "Table": "user" + } +} + # Single table complex in clause "select id from user where name in (col, 'bb')" { @@ -156,7 +449,7 @@ "Sharded": true }, "FieldQuery": "select id from user where 1 != 1", - "Query": "select id from user where name in (col, 'bb')", + "Query": "select id from user where `name` in (col, 'bb')", "Table": "user" } } @@ -174,7 +467,7 @@ "Sharded": true }, "FieldQuery": "select id from user where 1 != 1", - "Query": "select id from user where name = :a", + "Query": "select id from user where `name` = :a", "Table": "user", "Values": [ ":a" @@ -196,7 +489,7 @@ "Sharded": true }, "FieldQuery": "select id from user where 1 != 1", - "Query": "select id from user where name = 18446744073709551615", + "Query": "select id from user where `name` = 18446744073709551615", "Table": "user", "Values": [ 18446744073709551615 @@ -218,7 +511,7 @@ "Sharded": true }, "FieldQuery": "select id from user where 1 != 1", - "Query": "select id from user where name in ::__vals", + "Query": "select id from user where `name` in ::__vals", "Table": "user", "Values": [ "::list" @@ -542,7 +835,7 @@ "Sharded": true }, "FieldQuery": "select id or col as val from user where 1 != 1", - "Query": "select id or col as val from user where user.col = 5 and user.id in (1, 2) and user.name = 'aa'", + "Query": "select id or col as val from user where user.col = 5 and user.id in (1, 2) and user.`name` = 'aa'", "Table": "user", "Values": [ "aa" @@ -564,7 +857,7 @@ "Sharded": true }, "FieldQuery": "select id from user where 1 != 1", - "Query": "select id from user where user.col = false and user.id in (1, 2) and user.name = 'aa'", + "Query": "select id from user where user.col = false and user.id in (1, 2) and user.`name` = 'aa'", "Table": "user", "Values": [ "aa" @@ -586,7 +879,7 @@ "Sharded": true }, "FieldQuery": "select id from user where 1 != 1", - "Query": "select id from user where user.col = 5 and user.id in (1, 2) and user.name = 'aa' and user.id = 1", + "Query": "select id from user where user.col = 5 and user.id in (1, 2) and user.`name` = 'aa' and user.id = 1", "Table": "user", "Values": [ 1 @@ -608,7 +901,7 @@ "Sharded": true }, "FieldQuery": "select id from user where 1 != 1", - "Query": "select id from user where user.id = 1 and user.name = 'aa' and user.id in (1, 2) and user.col = 5", + "Query": "select id from user where user.id = 1 and user.`name` = 'aa' and user.id in (1, 2) and user.col = 5", "Table": "user", "Values": [ 1 @@ -630,7 +923,7 @@ "Sharded": true }, "FieldQuery": "select id from user where 1 != 1", - "Query": "select id from user where user.id = 1 or user.name = 'aa' and user.id in (1, 2)", + "Query": "select id from user where user.id = 1 or user.`name` = 'aa' and user.id in (1, 2)", "Table": "user" } } @@ -1480,4 +1773,3 @@ "SysTableTableSchema": "VARBINARY(\"ks\")" } } - \ No newline at end of file diff --git a/go/vt/vtgate/planbuilder/testdata/from_cases.txt b/go/vt/vtgate/planbuilder/testdata/from_cases.txt index 67195e515f4..ca27e5041cc 100644 --- a/go/vt/vtgate/planbuilder/testdata/from_cases.txt +++ b/go/vt/vtgate/planbuilder/testdata/from_cases.txt @@ -234,7 +234,7 @@ # routing rules bad table "select * from bad_table" -"keyspace none not found in vschema" +"keyspace noks not found in vschema" # routing rules disabled table "select * from disabled" @@ -996,7 +996,7 @@ "Sharded": true }, "FieldQuery": "select user.col from user where 1 != 1", - "Query": "select user.col from user where user.name = :user_extra_user_id", + "Query": "select user.col from user where user.`name` = :user_extra_user_id", "Table": "user", "Values": [ ":user_extra_user_id" @@ -1061,7 +1061,6 @@ } } - # reference table can merge with other opcodes left to right and vindex value is in the plan. # This tests that route.Merge also copies the condition to the LHS. "select ref.col from ref join (select aa from user where user.id=1) user" diff --git a/go/vt/vtgate/planbuilder/testdata/schema_test.json b/go/vt/vtgate/planbuilder/testdata/schema_test.json index c078fe52870..bc55db85684 100644 --- a/go/vt/vtgate/planbuilder/testdata/schema_test.json +++ b/go/vt/vtgate/planbuilder/testdata/schema_test.json @@ -14,7 +14,7 @@ "to_tables": ["user.user"] }, { "from_table": "bad_table", - "to_tables": ["none.none"] + "to_tables": ["noks.noks"] }, { "from_table": "disabled", "to_tables": [] diff --git a/go/vt/vtgate/planbuilder/testdata/select_cases.txt b/go/vt/vtgate/planbuilder/testdata/select_cases.txt index b069f8e85f0..e80cb524aef 100644 --- a/go/vt/vtgate/planbuilder/testdata/select_cases.txt +++ b/go/vt/vtgate/planbuilder/testdata/select_cases.txt @@ -861,7 +861,7 @@ "Sharded": true }, "FieldQuery": "select * from user where 1 != 1", - "Query": "select * from user where name = 'abc' and id = 4 limit 5", + "Query": "select * from user where `name` = 'abc' and id = 4 limit 5", "Table": "user", "Values": [ 4 @@ -883,7 +883,7 @@ "Sharded": true }, "FieldQuery": "select * from user where 1 != 1", - "Query": "select * from user where id = 4 and name = 'abc' limit 5", + "Query": "select * from user where id = 4 and `name` = 'abc' limit 5", "Table": "user", "Values": [ 4 @@ -905,7 +905,7 @@ "Sharded": true }, "FieldQuery": "select * from user where 1 != 1", - "Query": "select * from user where id = 4 and name = 'abc' limit 5", + "Query": "select * from user where id = 4 and `name` = 'abc' limit 5", "Table": "user", "Values": [ 4 @@ -971,7 +971,7 @@ "Sharded": true }, "FieldQuery": "select * from user where 1 != 1", - "Query": "select * from user where id = 1 and name = true limit 5", + "Query": "select * from user where id = 1 and `name` = true limit 5", "Table": "user", "Values": [ 1 @@ -993,7 +993,7 @@ "Sharded": true }, "FieldQuery": "select * from user where 1 != 1", - "Query": "select * from user where id = 1 and name limit 5", + "Query": "select * from user where id = 1 and `name` limit 5", "Table": "user", "Values": [ 1 @@ -1015,7 +1015,7 @@ "Sharded": true }, "FieldQuery": "select * from user where 1 != 1", - "Query": "select * from user where id = 5 and name = true limit 5", + "Query": "select * from user where id = 5 and `name` = true limit 5", "Table": "user", "Values": [ 5 @@ -1237,8 +1237,8 @@ "Name": "main", "Sharded": false }, - "FieldQuery": "select id, name from unsharded where 1 != 1", - "Query": "select id, name from unsharded where id in (select id from unsharded where id = 1 union select id from unsharded where id = 3)", + "FieldQuery": "select id, `name` from unsharded where 1 != 1", + "Query": "select id, `name` from unsharded where id in (select id from unsharded where id = 1 union select id from unsharded where id = 3)", "Table": "unsharded" } } @@ -1288,8 +1288,8 @@ "Name": "main", "Sharded": false }, - "FieldQuery": "(select id from unsharded where 1 != 1 union select id from unsharded_auto where 1 != 1) union (select id from unsharded_auto where 1 != 1 union select name from unsharded where 1 != 1)", - "Query": "(select id from unsharded union select id from unsharded_auto) union (select id from unsharded_auto union select name from unsharded)", + "FieldQuery": "(select id from unsharded where 1 != 1 union select id from unsharded_auto where 1 != 1) union (select id from unsharded_auto where 1 != 1 union select `name` from unsharded where 1 != 1)", + "Query": "(select id from unsharded union select id from unsharded_auto) union (select id from unsharded_auto union select `name` from unsharded)", "Table": "unsharded" } } diff --git a/go/vt/vtgate/planbuilder/testdata/union_cases.txt b/go/vt/vtgate/planbuilder/testdata/union_cases.txt index 97052ea565e..18ae0f63053 100644 --- a/go/vt/vtgate/planbuilder/testdata/union_cases.txt +++ b/go/vt/vtgate/planbuilder/testdata/union_cases.txt @@ -446,8 +446,8 @@ "Name": "main", "Sharded": false }, - "FieldQuery": "select name from unsharded where 1 != 1", - "Query": "select name from unsharded", + "FieldQuery": "select `name` from unsharded where 1 != 1", + "Query": "select `name` from unsharded", "Table": "unsharded" } ] @@ -504,8 +504,8 @@ "Name": "main", "Sharded": false }, - "FieldQuery": "select name from unsharded where 1 != 1", - "Query": "select name from unsharded", + "FieldQuery": "select `name` from unsharded where 1 != 1", + "Query": "select `name` from unsharded", "Table": "unsharded" } ] @@ -716,8 +716,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select user.id, user.name from user where 1 != 1", - "Query": "select user.id, user.name from user", + "FieldQuery": "select user.id, user.`name` from user where 1 != 1", + "Query": "select user.id, user.`name` from user", "Table": "user" }, { @@ -785,8 +785,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select user.id, user.name from user where 1 != 1", - "Query": "select user.id, user.name from user", + "FieldQuery": "select user.id, user.`name` from user where 1 != 1", + "Query": "select user.id, user.`name` from user", "Table": "user" }, { diff --git a/go/vt/vtgate/planbuilder/testdata/unsupported_cases.txt b/go/vt/vtgate/planbuilder/testdata/unsupported_cases.txt index 5c40af9e1e4..1e4adfc46ae 100644 --- a/go/vt/vtgate/planbuilder/testdata/unsupported_cases.txt +++ b/go/vt/vtgate/planbuilder/testdata/unsupported_cases.txt @@ -340,10 +340,6 @@ "delete music,user from music inner join user where music.id = user.id" "unsupported: multi-shard or vindex write statement" -# Database DDL -"create database foo" -"unsupported: Database DDL create database foo" - # order by inside and outside parenthesis select "(select 1 from user order by 1 desc) order by 1 asc limit 2" "can't do ORDER BY on top of ORDER BY" diff --git a/go/vt/vtgate/planbuilder/testdata/vindex_func_cases.txt b/go/vt/vtgate/planbuilder/testdata/vindex_func_cases.txt index 88356784fd8..c492ad196a7 100644 --- a/go/vt/vtgate/planbuilder/testdata/vindex_func_cases.txt +++ b/go/vt/vtgate/planbuilder/testdata/vindex_func_cases.txt @@ -1,8 +1,8 @@ # vindex func read all cols -"select id, keyspace_id, range_start, range_end from user_index where id = :id" +"select id, keyspace_id, range_start, range_end, hex_keyspace_id, shard from user_index where id = :id" { "QueryType": "SELECT", - "Original": "select id, keyspace_id, range_start, range_end from user_index where id = :id", + "Original": "select id, keyspace_id, range_start, range_end, hex_keyspace_id, shard from user_index where id = :id", "Instructions": { "OperatorType": "VindexFunc", "Variant": "VindexMap", @@ -10,13 +10,17 @@ 0, 1, 2, - 3 + 3, + 4, + 5 ], "Fields": { + "hex_keyspace_id": "VARBINARY", "id": "VARBINARY", "keyspace_id": "VARBINARY", "range_end": "VARBINARY", - "range_start": "VARBINARY" + "range_start": "VARBINARY", + "shard": "VARBINARY" }, "Value": ":id", "Vindex": "user_index" @@ -35,13 +39,17 @@ 0, 1, 2, - 3 + 3, + 4, + 5 ], "Fields": { + "hex_keyspace_id": "VARBINARY", "id": "VARBINARY", "keyspace_id": "VARBINARY", "range_end": "VARBINARY", - "range_start": "VARBINARY" + "range_start": "VARBINARY", + "shard": "VARBINARY" }, "Value": ":id", "Vindex": "user_index" @@ -293,7 +301,7 @@ } "select none from user_index where id = :id" -"symbol none not found in table or subquery" +"symbol `none` not found in table or subquery" "select * from samecolvin where col = :col" { diff --git a/go/vt/vtgate/planbuilder/vindex_func.go b/go/vt/vtgate/planbuilder/vindex_func.go index 8891e42a0af..e29eb7a2308 100644 --- a/go/vt/vtgate/planbuilder/vindex_func.go +++ b/go/vt/vtgate/planbuilder/vindex_func.go @@ -61,6 +61,8 @@ func newVindexFunc(alias sqlparser.TableName, vindex vindexes.SingleColumn) (*vi t.addColumn(sqlparser.NewColIdent("keyspace_id"), &column{origin: vf}) t.addColumn(sqlparser.NewColIdent("range_start"), &column{origin: vf}) t.addColumn(sqlparser.NewColIdent("range_end"), &column{origin: vf}) + t.addColumn(sqlparser.NewColIdent("hex_keyspace_id"), &column{origin: vf}) + t.addColumn(sqlparser.NewColIdent("shard"), &column{origin: vf}) t.isAuthoritative = true st := newSymtab() diff --git a/go/vt/vtgate/plugin_mysql_server.go b/go/vt/vtgate/plugin_mysql_server.go index 317f100e55c..905f4b3672a 100644 --- a/go/vt/vtgate/plugin_mysql_server.go +++ b/go/vt/vtgate/plugin_mysql_server.go @@ -339,7 +339,8 @@ func (vh *vtgateHandler) session(c *mysql.Conn) *vtgatepb.Session { IncludedFields: querypb.ExecuteOptions_ALL, Workload: querypb.ExecuteOptions_Workload(mysqlDefaultWorkload), }, - Autocommit: true, + Autocommit: true, + DDLStrategy: *defaultDDLStrategy, } if c.Capabilities&mysql.CapabilityClientFoundRows != 0 { session.Options.ClientFoundRows = true diff --git a/go/vt/vtgate/safe_session.go b/go/vt/vtgate/safe_session.go index a5ef0ebb032..7b6c6104462 100644 --- a/go/vt/vtgate/safe_session.go +++ b/go/vt/vtgate/safe_session.go @@ -22,7 +22,6 @@ import ( "time" "github.com/golang/protobuf/proto" - "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/vterrors" querypb "vitess.io/vitess/go/vt/proto/query" @@ -455,10 +454,17 @@ func (session *SafeSession) ResetShard(tabletAlias *topodatapb.TabletAlias) erro } // SetDDLStrategy set the DDLStrategy setting. -func (session *SafeSession) SetDDLStrategy(strategy sqlparser.DDLStrategy) { +func (session *SafeSession) SetDDLStrategy(strategy string) { session.mu.Lock() defer session.mu.Unlock() - session.DDLStrategy = string(strategy) + session.DDLStrategy = strategy +} + +// GetDDLStrategy returns the DDLStrategy value. +func (session *SafeSession) GetDDLStrategy() string { + session.mu.Lock() + defer session.mu.Unlock() + return session.DDLStrategy } // SetReadAfterWriteGTID set the ReadAfterWriteGtid setting. diff --git a/go/vt/vtgate/vcursor_impl.go b/go/vt/vtgate/vcursor_impl.go index b50de41e82d..f2bf48a9939 100644 --- a/go/vt/vtgate/vcursor_impl.go +++ b/go/vt/vtgate/vcursor_impl.go @@ -99,7 +99,11 @@ type vcursorImpl struct { vm VSchemaOperator } -func (vc *vcursorImpl) ExecuteVSchema(keyspace string, vschemaDDL *sqlparser.DDL) error { +func (vc *vcursorImpl) GetKeyspace() string { + return vc.keyspace +} + +func (vc *vcursorImpl) ExecuteVSchema(keyspace string, vschemaDDL sqlparser.DDLStatement) error { srvVschema := vc.vm.GetCurrentSrvVschema() if srvVschema == nil { return vterrors.Errorf(vtrpcpb.Code_INTERNAL, "vschema not loaded") @@ -113,8 +117,8 @@ func (vc *vcursorImpl) ExecuteVSchema(keyspace string, vschemaDDL *sqlparser.DDL // Resolve the keyspace either from the table qualifier or the target keyspace var ksName string - if !vschemaDDL.Table.IsEmpty() { - ksName = vschemaDDL.Table.Qualifier.String() + if !vschemaDDL.GetTable().IsEmpty() { + ksName = vschemaDDL.GetTable().Qualifier.String() } if ksName == "" { ksName = keyspace @@ -318,6 +322,16 @@ func (vc *vcursorImpl) FirstSortedKeyspace() (*vindexes.Keyspace, error) { return kss[keys[0]].Keyspace, nil } +// SysVarSetEnabled implements the ContextVSchema interface +func (vc *vcursorImpl) SysVarSetEnabled() bool { + return *sysVarSetEnabled +} + +// KeyspaceExists provides whether the keyspace exists or not. +func (vc *vcursorImpl) KeyspaceExists(ks string) bool { + return vc.vschema.Keyspaces[ks] != nil +} + // TargetString returns the current TargetString of the session. func (vc *vcursorImpl) TargetString() string { return vc.safeSession.TargetString @@ -574,11 +588,6 @@ func (vc *vcursorImpl) SetWorkload(workload querypb.ExecuteOptions_Workload) { vc.safeSession.GetOrCreateOptions().Workload = workload } -// SysVarSetEnabled implements the SessionActions interface -func (vc *vcursorImpl) SysVarSetEnabled() bool { - return *sysVarSetEnabled -} - // SysVarSetEnabled implements the SessionActions interface func (vc *vcursorImpl) NewPlanner() bool { return false @@ -591,10 +600,15 @@ func (vc *vcursorImpl) SetFoundRows(foundRows uint64) { } // SetReadAfterWriteGTID implements the SessionActions interface -func (vc *vcursorImpl) SetDDLStrategy(strategy sqlparser.DDLStrategy) { +func (vc *vcursorImpl) SetDDLStrategy(strategy string) { vc.safeSession.SetDDLStrategy(strategy) } +// SetReadAfterWriteGTID implements the SessionActions interface +func (vc *vcursorImpl) GetDDLStrategy() string { + return vc.safeSession.GetDDLStrategy() +} + // SetReadAfterWriteGTID implements the SessionActions interface func (vc *vcursorImpl) SetReadAfterWriteGTID(vtgtid string) { vc.safeSession.SetReadAfterWriteGTID(vtgtid) diff --git a/go/vt/vtgate/vindexes/consistent_lookup_test.go b/go/vt/vtgate/vindexes/consistent_lookup_test.go index dcc3b7da32b..e91c972ef14 100644 --- a/go/vt/vtgate/vindexes/consistent_lookup_test.go +++ b/go/vt/vtgate/vindexes/consistent_lookup_test.go @@ -452,7 +452,6 @@ func TestConsistentLookupUpdateBecauseUncomparableTypes(t *testing.T) { {querypb.Type_CHAR, "some string"}, {querypb.Type_BIT, "some string"}, {querypb.Type_GEOMETRY, "some string"}, - {querypb.Type_JSON, "some string"}, } for _, val := range tests { diff --git a/go/vt/vtgate/vindexes/vschema.go b/go/vt/vtgate/vindexes/vschema.go index ff7a041e24d..8046572a9b6 100644 --- a/go/vt/vtgate/vindexes/vschema.go +++ b/go/vt/vtgate/vindexes/vschema.go @@ -22,7 +22,6 @@ import ( "fmt" "io/ioutil" "sort" - "strings" "vitess.io/vitess/go/json2" "vitess.io/vitess/go/sqltypes" @@ -352,7 +351,11 @@ func resolveAutoIncrement(source *vschemapb.SrvVSchema, vschema *VSchema) { if t == nil || table.AutoIncrement == nil { continue } - seq, err := vschema.findQualified(table.AutoIncrement.Sequence) + seqks, seqtab, err := sqlparser.ParseTable(table.AutoIncrement.Sequence) + var seq *Table + if err == nil { + seq, err = vschema.FindTable(seqks, seqtab) + } if err != nil { // Better to remove the table than to leave it partially initialized. delete(ksvschema.Tables, tname) @@ -410,14 +413,20 @@ outer: } continue outer } - parts := strings.Split(toTable, ".") - if len(parts) != 2 { + toks, totabname, err := sqlparser.ParseTable(toTable) + if err != nil { + vschema.RoutingRules[rule.FromTable] = &RoutingRule{ + Error: err, + } + continue outer + } + if toks == "" { vschema.RoutingRules[rule.FromTable] = &RoutingRule{ Error: fmt.Errorf("table %s must be qualified", toTable), } continue outer } - t, err := vschema.FindTable(parts[0], parts[1]) + t, err := vschema.FindTable(toks, totabname) if err != nil { vschema.RoutingRules[rule.FromTable] = &RoutingRule{ Error: err, @@ -430,18 +439,6 @@ outer: } } -// findQualified finds a table t or k.t. -func (vschema *VSchema) findQualified(name string) (*Table, error) { - splits := strings.Split(name, ".") - switch len(splits) { - case 1: - return vschema.FindTable("", splits[0]) - case 2: - return vschema.FindTable(splits[0], splits[1]) - } - return nil, fmt.Errorf("table %s not found", name) -} - // FindTable returns a pointer to the Table. If a keyspace is specified, only tables // from that keyspace are searched. If the specified keyspace is unsharded // and no tables matched, it's considered valid: FindTable will construct a table diff --git a/go/vt/vtgate/vindexes/vschema_test.go b/go/vt/vtgate/vindexes/vschema_test.go index 7455a8e1be0..823b46f4e8c 100644 --- a/go/vt/vtgate/vindexes/vschema_test.go +++ b/go/vt/vtgate/vindexes/vschema_test.go @@ -664,12 +664,18 @@ func TestVSchemaRoutingRules(t *testing.T) { }, { FromTable: "rt2", ToTables: []string{"ks2.t2"}, + }, { + FromTable: "escaped", + ToTables: []string{"`ks2`.`t2`"}, }, { FromTable: "dup", ToTables: []string{"ks1.t1"}, }, { FromTable: "dup", ToTables: []string{"ks1.t1"}, + }, { + FromTable: "badname", + ToTables: []string{"t1.t2.t3"}, }, { FromTable: "unqualified", ToTables: []string{"t1"}, @@ -753,9 +759,15 @@ func TestVSchemaRoutingRules(t *testing.T) { "rt2": { Tables: []*Table{t2}, }, + "escaped": { + Tables: []*Table{t2}, + }, "dup": { Error: errors.New("duplicate rule for entry dup"), }, + "badname": { + Error: errors.New("invalid table name: t1.t2.t3"), + }, "unqualified": { Error: errors.New("table t1 must be qualified"), }, @@ -1856,7 +1868,7 @@ func TestSequence(t *testing.T) { }, AutoIncrement: &vschemapb.AutoIncrement{ Column: "c2", - Sequence: "unsharded.seq", + Sequence: "`unsharded`.`seq`", }, }, }, @@ -2072,9 +2084,9 @@ func TestBadSequenceName(t *testing.T) { } got, _ := BuildVSchema(&bad) err := got.Keyspaces["sharded"].Error - want := "cannot resolve sequence a.b.seq: table a.b.seq not found" - if err == nil || err.Error() != want { - t.Errorf("BuildVSchema: %v, want %v", err, want) + want := "invalid table name: a.b.seq" + if err == nil || !strings.Contains(err.Error(), want) { + t.Errorf("BuildVSchema: %v, must contain %v", err, want) } if t1 := got.Keyspaces["sharded"].Tables["t1"]; t1 != nil { t.Errorf("BuildVSchema: table t1 must not be present in the keyspace: %v", t1) diff --git a/go/vt/vtgate/vtgate.go b/go/vt/vtgate/vtgate.go index f3287900d37..84870af5339 100644 --- a/go/vt/vtgate/vtgate.go +++ b/go/vt/vtgate/vtgate.go @@ -36,6 +36,7 @@ import ( "vitess.io/vitess/go/vt/key" "vitess.io/vitess/go/vt/log" "vitess.io/vitess/go/vt/logutil" + "vitess.io/vitess/go/vt/schema" "vitess.io/vitess/go/vt/servenv" "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/srvtopo" @@ -60,6 +61,7 @@ var ( _ = flag.Bool("disable_local_gateway", false, "deprecated: if specified, this process will not route any queries to local tablets in the local cell") maxMemoryRows = flag.Int("max_memory_rows", 300000, "Maximum number of rows that will be held in memory for intermediate results as well as the final result.") warnMemoryRows = flag.Int("warn_memory_rows", 30000, "Warning threshold for in-memory results. A row count higher than this amount will cause the VtGateWarnings.ResultsExceeded counter to be incremented.") + defaultDDLStrategy = flag.String("ddl_strategy", "", "Set default strategy for DDL statements. Override with @@ddl_strategy session variable") // TODO(deepthi): change these two vars to unexported and move to healthcheck.go when LegacyHealthcheck is removed @@ -165,6 +167,9 @@ func Init(ctx context.Context, serv srvtopo.Server, cell string, tabletTypesToWa } } + if _, _, err := schema.ParseDDLStrategy(*defaultDDLStrategy); err != nil { + log.Fatalf("Invalid value for -ddl_strategy: %v", err.Error()) + } tc := NewTxConn(gw, getTxMode()) // ScatterConn depends on TxConn to perform forced rollbacks. sc := NewScatterConn("VttabletCall", tc, gw) diff --git a/go/vt/vttablet/endtoend/queries_test.go b/go/vt/vttablet/endtoend/queries_test.go index 992da441dcf..a3e6322b790 100644 --- a/go/vt/vttablet/endtoend/queries_test.go +++ b/go/vt/vttablet/endtoend/queries_test.go @@ -539,7 +539,7 @@ func TestQueries(t *testing.T) { &framework.TestCase{ Query: "insert /* qualified */ into vitess_a(eid, id, name, foo) values (3, 1, 'aaaa', 'cccc')", Rewritten: []string{ - "insert /* qualified */ into vitess_a(eid, id, name, foo) values (3, 1, 'aaaa', 'cccc')", + "insert /* qualified */ into vitess_a(eid, id, `name`, foo) values (3, 1, 'aaaa', 'cccc')", }, RowsAffected: 1, }, @@ -586,7 +586,7 @@ func TestQueries(t *testing.T) { &framework.TestCase{ Query: "insert /* auto_increment */ into vitess_e(name, foo) values ('aaaa', 'cccc')", Rewritten: []string{ - "insert /* auto_increment */ into vitess_e(name, foo) values ('aaaa', 'cccc')", + "insert /* auto_increment */ into vitess_e(`name`, foo) values ('aaaa', 'cccc')", }, RowsAffected: 1, }, @@ -610,7 +610,7 @@ func TestQueries(t *testing.T) { &framework.TestCase{ Query: "insert /* auto_increment */ into vitess_e(eid, name, foo) values (NULL, 'aaaa', 'cccc')", Rewritten: []string{ - "insert /* auto_increment */ into vitess_e(eid, name, foo) values (null, 'aaaa', 'cccc')", + "insert /* auto_increment */ into vitess_e(eid, `name`, foo) values (null, 'aaaa', 'cccc')", }, RowsAffected: 1, }, @@ -633,7 +633,7 @@ func TestQueries(t *testing.T) { &framework.TestCase{ Query: "insert /* num default */ into vitess_a(eid, name, foo) values (3, 'aaaa', 'cccc')", Rewritten: []string{ - "insert /* num default */ into vitess_a(eid, name, foo) values (3, 'aaaa', 'cccc')", + "insert /* num default */ into vitess_a(eid, `name`, foo) values (3, 'aaaa', 'cccc')", }, RowsAffected: 1, }, @@ -685,7 +685,7 @@ func TestQueries(t *testing.T) { "id": sqltypes.Int64BindVariable(1), }, Rewritten: []string{ - "insert /* bind values */ into vitess_a(eid, id, name, foo) values (4, 1, 'aaaa', 'cccc')", + "insert /* bind values */ into vitess_a(eid, id, `name`, foo) values (4, 1, 'aaaa', 'cccc')", }, RowsAffected: 1, }, @@ -714,7 +714,7 @@ func TestQueries(t *testing.T) { "v4": sqltypes.StringBindVariable("cccc"), }, Rewritten: []string{ - "insert /* positional values */ into vitess_a(eid, id, name, foo) values (4, 1, 'aaaa', 'cccc')", + "insert /* positional values */ into vitess_a(eid, id, `name`, foo) values (4, 1, 'aaaa', 'cccc')", }, RowsAffected: 1, }, @@ -737,7 +737,7 @@ func TestQueries(t *testing.T) { &framework.TestCase{ Query: "insert into vitess_a(id, eid, foo, name) values (-1, 5, 'aaa', 'bbb')", Rewritten: []string{ - "insert into vitess_a(id, eid, foo, name) values (-1, 5, 'aaa', 'bbb')", + "insert into vitess_a(id, eid, foo, `name`) values (-1, 5, 'aaa', 'bbb')", }, RowsAffected: 1, }, @@ -760,7 +760,7 @@ func TestQueries(t *testing.T) { &framework.TestCase{ Query: "insert /* subquery */ into vitess_a(eid, name, foo) select eid, name, foo from vitess_c", Rewritten: []string{ - "insert /* subquery */ into vitess_a(eid, name, foo) select eid, name, foo from vitess_c", + "insert /* subquery */ into vitess_a(eid, `name`, foo) select eid, `name`, foo from vitess_c", }, RowsAffected: 2, }, @@ -777,7 +777,7 @@ func TestQueries(t *testing.T) { &framework.TestCase{ Query: "insert into vitess_e(id, name, foo) select eid, name, foo from vitess_c", Rewritten: []string{ - "insert into vitess_e(id, name, foo) select eid, name, foo from vitess_c", + "insert into vitess_e(id, `name`, foo) select eid, `name`, foo from vitess_c", }, RowsAffected: 2, }, @@ -802,7 +802,7 @@ func TestQueries(t *testing.T) { &framework.TestCase{ Query: "insert into vitess_a(eid, id, name, foo) values (5, 1, '', ''), (7, 1, '', '')", Rewritten: []string{ - "insert into vitess_a(eid, id, name, foo) values (5, 1, '', ''), (7, 1, '', '')", + "insert into vitess_a(eid, id, `name`, foo) values (5, 1, '', ''), (7, 1, '', '')", }, RowsAffected: 2, }, diff --git a/go/vt/vttablet/onlineddl/executor.go b/go/vt/vttablet/onlineddl/executor.go index a1d4b52cbfa..859797b7380 100644 --- a/go/vt/vttablet/onlineddl/executor.go +++ b/go/vt/vttablet/onlineddl/executor.go @@ -798,7 +798,7 @@ func (e *Executor) readMigration(ctx context.Context, uuid string) (onlineDDL *s Schema: row["mysql_schema"].ToString(), SQL: row["migration_statement"].ToString(), UUID: row["migration_uuid"].ToString(), - Strategy: sqlparser.DDLStrategy(row["strategy"].ToString()), + Strategy: schema.DDLStrategy(row["strategy"].ToString()), Options: row["options"].ToString(), Status: schema.OnlineDDLStatus(row["migration_status"].ToString()), Retries: row.AsInt64("retries", 0), @@ -883,6 +883,17 @@ func (e *Executor) cancelMigration(ctx context.Context, uuid string, terminateRu return result, nil } +// cancelMigrations attempts to abort a list of migrations +func (e *Executor) cancelMigrations(ctx context.Context, uuids []string) (err error) { + for _, uuid := range uuids { + log.Infof("cancelMigrations: cancelling %s", uuid) + if _, err := e.cancelMigration(ctx, uuid, true); err != nil { + return err + } + } + return nil +} + // scheduleNextMigration attemps to schedule a single migration to run next. // possibly there's no migrations to run. Possibly there's a migration running right now, // in which cases nothing happens. @@ -900,11 +911,13 @@ func (e *Executor) scheduleNextMigration(ctx context.Context) error { if err != nil { return err } + row := r.Named().Row() countReady, err := row.ToInt64("count_ready") if err != nil { return err } + if countReady > 0 { // seems like there's already one migration that's good to go return nil @@ -938,7 +951,7 @@ func (e *Executor) runNextMigration(ctx context.Context) error { Schema: row["mysql_schema"].ToString(), SQL: row["migration_statement"].ToString(), UUID: row["migration_uuid"].ToString(), - Strategy: sqlparser.DDLStrategy(row["strategy"].ToString()), + Strategy: schema.DDLStrategy(row["strategy"].ToString()), Options: row["options"].ToString(), Status: schema.OnlineDDLStatus(row["migration_status"].ToString()), } @@ -1038,18 +1051,21 @@ func (e *Executor) dropPTOSCMigrationTriggers(ctx context.Context, onlineDDL *sc // reviewRunningMigrations iterates migrations in 'running' state (there really should just be one that is // actually running). -func (e *Executor) reviewRunningMigrations(ctx context.Context) (countRunnning int, err error) { +func (e *Executor) reviewRunningMigrations(ctx context.Context) (countRunnning int, runningNotByThisProcess []string, err error) { + e.migrationMutex.Lock() + defer e.migrationMutex.Unlock() + parsed := sqlparser.BuildParsedQuery(sqlSelectRunningMigrations, "_vt", ":strategy") bindVars := map[string]*querypb.BindVariable{ "strategy": sqltypes.StringBindVariable(string(schema.DDLStrategyPTOSC)), } bound, err := parsed.GenerateQuery(bindVars, nil) if err != nil { - return countRunnning, err + return countRunnning, runningNotByThisProcess, err } r, err := e.execQuery(ctx, bound) if err != nil { - return countRunnning, err + return countRunnning, runningNotByThisProcess, err } for _, row := range r.Named().Rows { uuid := row["migration_uuid"].ToString() @@ -1059,8 +1075,16 @@ func (e *Executor) reviewRunningMigrations(ctx context.Context) (countRunnning i _ = e.updateMigrationTimestamp(ctx, "liveness_timestamp", uuid) } countRunnning++ + + if uuid != e.lastMigrationUUID { + // This executor can only run one migration at a time. And that + // migration is identified by e.lastMigrationUUID. + // If we find a _running_ migration that does not have this UUID, it _must_ + // mean the migration was started by a former vttablet (ie vttablet crashed and restarted) + runningNotByThisProcess = append(runningNotByThisProcess, uuid) + } } - return countRunnning, err + return countRunnning, runningNotByThisProcess, err } // reviewStaleMigrations marks as 'failed' migrations whose status is 'running' but which have @@ -1191,7 +1215,9 @@ func (e *Executor) onMigrationCheckTick() { if err := e.runNextMigration(ctx); err != nil { log.Error(err) } - if _, err := e.reviewRunningMigrations(ctx); err != nil { + if _, runningNotByThisProcess, err := e.reviewRunningMigrations(ctx); err != nil { + log.Error(err) + } else if err := e.cancelMigrations(ctx, runningNotByThisProcess); err != nil { log.Error(err) } if err := e.reviewStaleMigrations(ctx); err != nil { diff --git a/go/vt/vttablet/tabletserver/planbuilder/permission.go b/go/vt/vttablet/tabletserver/planbuilder/permission.go index dc0e2fb0583..1d64ea43c56 100644 --- a/go/vt/vttablet/tabletserver/planbuilder/permission.go +++ b/go/vt/vttablet/tabletserver/planbuilder/permission.go @@ -49,7 +49,7 @@ func BuildPermissions(stmt sqlparser.Statement) []Permission { permissions = buildSubqueryPermissions(node, tableacl.READER, permissions) case *sqlparser.Set, *sqlparser.Show, *sqlparser.OtherRead, *sqlparser.Explain: // no-op - case *sqlparser.DDL: + case sqlparser.DDLStatement: for _, t := range node.AffectedTables() { permissions = buildTableNamePermissions(t, tableacl.ADMIN, permissions) } @@ -94,7 +94,7 @@ func buildTableExprPermissions(node sqlparser.TableExpr, role tableacl.Role, per switch node := node.Expr.(type) { case sqlparser.TableName: permissions = buildTableNamePermissions(node, role, permissions) - case *sqlparser.Subquery: + case *sqlparser.DerivedTable: permissions = buildSubqueryPermissions(node.Select, role, permissions) } case *sqlparser.ParenTableExpr: diff --git a/go/vt/vttablet/tabletserver/planbuilder/plan.go b/go/vt/vttablet/tabletserver/planbuilder/plan.go index 3479bc02226..563000fd761 100644 --- a/go/vt/vttablet/tabletserver/planbuilder/plan.go +++ b/go/vt/vttablet/tabletserver/planbuilder/plan.go @@ -181,10 +181,16 @@ func Build(statement sqlparser.Statement, tables map[string]*schema.Table, isRes plan, err = analyzeDelete(stmt, tables) case *sqlparser.Set: plan, err = analyzeSet(stmt), nil - case *sqlparser.DDL: - // DDLs and other statements below don't get fully parsed. + case sqlparser.DDLStatement: + // DDLs and some other statements below don't get fully parsed. // We have to use the original query at the time of execution. - plan = &Plan{PlanID: PlanDDL} + // We are in the process of changing this + var fullQuery *sqlparser.ParsedQuery + // If the query is fully parsed, then use the ast and store the fullQuery + if stmt.IsFullyParsed() { + fullQuery = GenerateFullQuery(stmt) + } + plan = &Plan{PlanID: PlanDDL, FullQuery: fullQuery} case *sqlparser.Show: plan, err = analyzeShow(stmt, dbName) case *sqlparser.OtherRead, *sqlparser.Explain: diff --git a/go/vt/vttablet/tabletserver/planbuilder/testdata/exec_cases.txt b/go/vt/vttablet/tabletserver/planbuilder/testdata/exec_cases.txt index 2b9d31892fb..5a6f2fe726c 100644 --- a/go/vt/vttablet/tabletserver/planbuilder/testdata/exec_cases.txt +++ b/go/vt/vttablet/tabletserver/planbuilder/testdata/exec_cases.txt @@ -295,7 +295,7 @@ "Role": 1 } ], - "FullQuery": "insert into a(eid, id) values (1, 2) on duplicate key update name = func(a)" + "FullQuery": "insert into a(eid, id) values (1, 2) on duplicate key update `name` = func(a)" } # replace @@ -337,8 +337,8 @@ "Role": 1 } ], - "FullQuery": "update d set foo = 'foo' where name in ('a', 'b') limit :#maxLimit", - "WhereClause": "where name in ('a', 'b')" + "FullQuery": "update d set foo = 'foo' where `name` in ('a', 'b') limit :#maxLimit", + "WhereClause": "where `name` in ('a', 'b')" } # normal update @@ -353,8 +353,8 @@ options:PassthroughDMLs "Role": 1 } ], - "FullQuery": "update d set foo = 'foo' where name in ('a', 'b')", - "WhereClause": "where name in ('a', 'b')" + "FullQuery": "update d set foo = 'foo' where `name` in ('a', 'b')", + "WhereClause": "where `name` in ('a', 'b')" } # cross-db update @@ -368,8 +368,8 @@ options:PassthroughDMLs "Role": 1 } ], - "FullQuery": "update a.b set foo = 'foo' where name in ('a', 'b')", - "WhereClause": "where name in ('a', 'b')" + "FullQuery": "update a.b set foo = 'foo' where `name` in ('a', 'b')", + "WhereClause": "where `name` in ('a', 'b')" } # update unknown table @@ -383,7 +383,7 @@ options:PassthroughDMLs "Role": 1 } ], - "FullQuery": "update bogus set name = 'foo' where id = 1", + "FullQuery": "update bogus set `name` = 'foo' where id = 1", "WhereClause": "where id = 1" } @@ -399,7 +399,7 @@ options:PassthroughDMLs "Role": 1 } ], - "FullQuery": "update bogus set name = 'foo' where id = 1", + "FullQuery": "update bogus set `name` = 'foo' where id = 1", "WhereClause": "where id = 1" } @@ -418,7 +418,7 @@ options:PassthroughDMLs "Role": 1 } ], - "FullQuery": "update a, b set a.name = 'foo' where a.id = b.id and b.var = 'test'", + "FullQuery": "update a, b set a.`name` = 'foo' where a.id = b.id and b.var = 'test'", "WhereClause": "where a.id = b.id and b.var = 'test'" } @@ -438,7 +438,7 @@ options:PassthroughDMLs "Role": 1 } ], - "FullQuery": "update a join b on a.id = b.id set a.name = 'foo' where b.var = 'test'", + "FullQuery": "update a join b on a.id = b.id set a.`name` = 'foo' where b.var = 'test'", "WhereClause": "where b.var = 'test'" } @@ -454,7 +454,7 @@ options:PassthroughDMLs "Role": 1 } ], - "FullQuery": "update a set name = 'foo' limit 1" + "FullQuery": "update a set `name` = 'foo' limit 1" } # update with limit @@ -469,7 +469,7 @@ options:PassthroughDMLs "Role": 1 } ], - "FullQuery": "update a set name = 'foo' limit 1" + "FullQuery": "update a set `name` = 'foo' limit 1" } # delete with no where clause @@ -497,8 +497,8 @@ options:PassthroughDMLs "Role": 1 } ], - "FullQuery": "delete from d where name in ('a', 'b') limit :#maxLimit", - "WhereClause": "where name in ('a', 'b')" + "FullQuery": "delete from d where `name` in ('a', 'b') limit :#maxLimit", + "WhereClause": "where `name` in ('a', 'b')" } # normal delete @@ -513,8 +513,8 @@ options:PassthroughDMLs "Role": 1 } ], - "FullQuery": "delete from d where name in ('a', 'b')", - "WhereClause": "where name in ('a', 'b')" + "FullQuery": "delete from d where `name` in ('a', 'b')", + "WhereClause": "where `name` in ('a', 'b')" } # delete unknown table @@ -640,6 +640,21 @@ options:PassthroughDMLs ] } +# create index +"create index a on b(id)" +{ + "PlanID": "DDL", + "TableName": "", + "Permissions": [ + { + "TableName": "b", + "Role": 2 + } + ], + "FullQuery":"create index a on b (id)" +} + + # alter "alter table a add column(a int)" { diff --git a/go/vt/vttablet/tabletserver/query_executor.go b/go/vt/vttablet/tabletserver/query_executor.go index 310f7c0e21a..229261d4e9d 100644 --- a/go/vt/vttablet/tabletserver/query_executor.go +++ b/go/vt/vttablet/tabletserver/query_executor.go @@ -380,7 +380,17 @@ func (qre *QueryExecutor) execDDL(conn *StatefulConnection) (*sqltypes.Result, e } }() - result, err := qre.execStatefulConn(conn, qre.query, true) + sql := qre.query + // If FullQuery is not nil, then the DDL query was fully parsed + // and we should use the ast to generate the query instead. + if qre.plan.FullQuery != nil { + var err error + sql, _, err = qre.generateFinalSQL(qre.plan.FullQuery, qre.bindVars) + if err != nil { + return nil, err + } + } + result, err := qre.execStatefulConn(conn, sql, true) if err != nil { return nil, err } diff --git a/go/vt/vttablet/tabletserver/query_executor_test.go b/go/vt/vttablet/tabletserver/query_executor_test.go index d33d4c46b3d..2cf8abbe7fe 100644 --- a/go/vt/vttablet/tabletserver/query_executor_test.go +++ b/go/vt/vttablet/tabletserver/query_executor_test.go @@ -219,6 +219,26 @@ func TestQueryExecutorPlans(t *testing.T) { planWant: "Savepoint", logWant: "savepoint a", inTxWant: "savepoint a", + }, { + input: "create index a on user(id)", + dbResponses: []dbResponse{{ + query: "create index a on user (id)", + result: emptyResult, + }}, + resultWant: emptyResult, + planWant: "DDL", + logWant: "create index a on user (id)", + inTxWant: "create index a on user (id)", + }, { + input: "create index a on user(id1 + id2)", + dbResponses: []dbResponse{{ + query: "create index a on user(id1 + id2)", + result: emptyResult, + }}, + resultWant: emptyResult, + planWant: "DDL", + logWant: "create index a on user(id1 + id2)", + inTxWant: "create index a on user(id1 + id2)", }, { input: "ROLLBACK work to SAVEPOINT a", dbResponses: []dbResponse{{ diff --git a/go/vt/vttablet/tabletserver/tabletserver.go b/go/vt/vttablet/tabletserver/tabletserver.go index 9fc8aa83a7a..ed7c9f04772 100644 --- a/go/vt/vttablet/tabletserver/tabletserver.go +++ b/go/vt/vttablet/tabletserver/tabletserver.go @@ -1500,13 +1500,15 @@ func (tsv *TabletServer) Close(ctx context.Context) error { var okMessage = []byte("ok\n") +// Health check +// Returns ok if we are in the desired serving state func (tsv *TabletServer) registerHealthzHealthHandler() { tsv.exporter.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) { if err := acl.CheckAccessHTTP(r, acl.MONITORING); err != nil { acl.SendError(w, err) return } - if tsv.sm.Target().TabletType != topodatapb.TabletType_SPARE && !tsv.sm.IsServing() { + if tsv.sm.wantState == StateServing && !tsv.sm.IsServing() { http.Error(w, "500 internal server error: vttablet is not serving", http.StatusInternalServerError) return } @@ -1516,6 +1518,8 @@ func (tsv *TabletServer) registerHealthzHealthHandler() { }) } +// Query service health check +// Returns ok if a query can go all the way to database and back func (tsv *TabletServer) registerDebugHealthHandler() { tsv.exporter.HandleFunc("/debug/health", func(w http.ResponseWriter, r *http.Request) { if err := acl.CheckAccessHTTP(r, acl.MONITORING); err != nil { diff --git a/go/vt/vttablet/tabletserver/tabletserver_test.go b/go/vt/vttablet/tabletserver/tabletserver_test.go index b10d387958e..ff0560e29c8 100644 --- a/go/vt/vttablet/tabletserver/tabletserver_test.go +++ b/go/vt/vttablet/tabletserver/tabletserver_test.go @@ -91,7 +91,7 @@ func TestTabletServerMasterToReplica(t *testing.T) { txid1, _, err := tsv.Begin(ctx, &target, nil) require.NoError(t, err) - _, err = tsv.Execute(ctx, &target, "update test_table set name = 2 where pk = 1", nil, txid1, 0, nil) + _, err = tsv.Execute(ctx, &target, "update test_table set `name` = 2 where pk = 1", nil, txid1, 0, nil) require.NoError(t, err) err = tsv.Prepare(ctx, &target, txid1, "aa") require.NoError(t, err) @@ -153,13 +153,13 @@ func TestTabletServerRedoLogIsKeptBetweenRestarts(t *testing.T) { sqltypes.NewVarBinary("dtid0"), sqltypes.NewInt64(RedoStatePrepared), sqltypes.NewVarBinary(""), - sqltypes.NewVarBinary("update test_table set name = 2 where pk = 1 limit 10001"), + sqltypes.NewVarBinary("update test_table set `name` = 2 where pk = 1 limit 10001"), }}, }) turnOnTxEngine() assert.EqualValues(t, 1, len(tsv.te.preparedPool.conns), "len(tsv.te.preparedPool.conns)") got := tsv.te.preparedPool.conns["dtid0"].TxProperties().Queries - want := []string{"update test_table set name = 2 where pk = 1 limit 10001"} + want := []string{"update test_table set `name` = 2 where pk = 1 limit 10001"} utils.MustMatch(t, want, got, "Prepared queries") turnOffTxEngine() assert.Empty(t, tsv.te.preparedPool.conns, "tsv.te.preparedPool.conns") @@ -182,7 +182,7 @@ func TestTabletServerRedoLogIsKeptBetweenRestarts(t *testing.T) { sqltypes.NewVarBinary("a:b:10"), sqltypes.NewInt64(RedoStatePrepared), sqltypes.NewVarBinary(""), - sqltypes.NewVarBinary("update test_table set name = 2 where pk = 1 limit 10001"), + sqltypes.NewVarBinary("update test_table set `name` = 2 where pk = 1 limit 10001"), }, { sqltypes.NewVarBinary("a:b:20"), sqltypes.NewInt64(RedoStateFailed), @@ -193,7 +193,7 @@ func TestTabletServerRedoLogIsKeptBetweenRestarts(t *testing.T) { turnOnTxEngine() assert.EqualValues(t, 1, len(tsv.te.preparedPool.conns), "len(tsv.te.preparedPool.conns)") got = tsv.te.preparedPool.conns["a:b:10"].TxProperties().Queries - want = []string{"update test_table set name = 2 where pk = 1 limit 10001"} + want = []string{"update test_table set `name` = 2 where pk = 1 limit 10001"} utils.MustMatch(t, want, got, "Prepared queries") wantFailed := map[string]error{"a:b:20": errPrepFailed} if !reflect.DeepEqual(tsv.te.preparedPool.reserved, wantFailed) { @@ -450,7 +450,7 @@ func TestTabletServerPrepare(t *testing.T) { target := querypb.Target{TabletType: topodatapb.TabletType_MASTER} transactionID, _, err := tsv.Begin(ctx, &target, nil) require.NoError(t, err) - _, err = tsv.Execute(ctx, &target, "update test_table set name = 2 where pk = 1", nil, transactionID, 0, nil) + _, err = tsv.Execute(ctx, &target, "update test_table set `name` = 2 where pk = 1", nil, transactionID, 0, nil) require.NoError(t, err) defer tsv.RollbackPrepared(ctx, &target, "aa", 0) err = tsv.Prepare(ctx, &target, transactionID, "aa") @@ -465,7 +465,7 @@ func TestTabletServerCommitPrepared(t *testing.T) { target := querypb.Target{TabletType: topodatapb.TabletType_MASTER} transactionID, _, err := tsv.Begin(ctx, &target, nil) require.NoError(t, err) - _, err = tsv.Execute(ctx, &target, "update test_table set name = 2 where pk = 1", nil, transactionID, 0, nil) + _, err = tsv.Execute(ctx, &target, "update test_table set `name` = 2 where pk = 1", nil, transactionID, 0, nil) require.NoError(t, err) err = tsv.Prepare(ctx, &target, transactionID, "aa") require.NoError(t, err) @@ -628,7 +628,7 @@ func TestTabletServerRollbackPrepared(t *testing.T) { target := querypb.Target{TabletType: topodatapb.TabletType_MASTER} transactionID, _, err := tsv.Begin(ctx, &target, nil) require.NoError(t, err) - _, err = tsv.Execute(ctx, &target, "update test_table set name = 2 where pk = 1", nil, transactionID, 0, nil) + _, err = tsv.Execute(ctx, &target, "update test_table set `name` = 2 where pk = 1", nil, transactionID, 0, nil) require.NoError(t, err) err = tsv.Prepare(ctx, &target, transactionID, "aa") require.NoError(t, err) @@ -898,9 +898,9 @@ func TestSerializeTransactionsSameRow(t *testing.T) { countStart := tsv.stats.WaitTimings.Counts()["TabletServerTest.TxSerializer"] // Fake data. - q1 := "update test_table set name_string = 'tx1' where pk = :pk and name = :name" - q2 := "update test_table set name_string = 'tx2' where pk = :pk and name = :name" - q3 := "update test_table set name_string = 'tx3' where pk = :pk and name = :name" + q1 := "update test_table set name_string = 'tx1' where pk = :pk and `name` = :name" + q2 := "update test_table set name_string = 'tx2' where pk = :pk and `name` = :name" + q3 := "update test_table set name_string = 'tx3' where pk = :pk and `name` = :name" // Every request needs their own bind variables to avoid data races. bvTx1 := map[string]*querypb.BindVariable{ "pk": sqltypes.Int64BindVariable(1), @@ -920,10 +920,10 @@ func TestSerializeTransactionsSameRow(t *testing.T) { // Make sure that tx3 could finish while tx2 could not. tx3Finished := make(chan struct{}) - db.SetBeforeFunc("update test_table set name_string = 'tx1' where pk = 1 and name = 1 limit 10001", + db.SetBeforeFunc("update test_table set name_string = 'tx1' where pk = 1 and `name` = 1 limit 10001", func() { close(tx1Started) - if err := waitForTxSerializationPendingQueries(tsv, "test_table where pk = 1 and name = 1", 2); err != nil { + if err := waitForTxSerializationPendingQueries(tsv, "test_table where pk = 1 and `name` = 1", 2); err != nil { t.Fatal(err) } }) @@ -1039,9 +1039,9 @@ func TestSerializeTransactionsSameRow_ExecuteBatchAsTransaction(t *testing.T) { countStart := tsv.stats.WaitTimings.Counts()["TabletServerTest.TxSerializer"] // Fake data. - q1 := "update test_table set name_string = 'tx1' where pk = :pk and name = :name" - q2 := "update test_table set name_string = 'tx2' where pk = :pk and name = :name" - q3 := "update test_table set name_string = 'tx3' where pk = :pk and name = :name" + q1 := "update test_table set name_string = 'tx1' where pk = :pk and `name` = :name" + q2 := "update test_table set name_string = 'tx2' where pk = :pk and `name` = :name" + q3 := "update test_table set name_string = 'tx3' where pk = :pk and `name` = :name" // Every request needs their own bind variables to avoid data races. bvTx1 := map[string]*querypb.BindVariable{ "pk": sqltypes.Int64BindVariable(1), @@ -1059,10 +1059,10 @@ func TestSerializeTransactionsSameRow_ExecuteBatchAsTransaction(t *testing.T) { // Make sure that tx2 and tx3 start only after tx1 is running its Execute(). tx1Started := make(chan struct{}) - db.SetBeforeFunc("update test_table set name_string = 'tx1' where pk = 1 and name = 1 limit 10001", + db.SetBeforeFunc("update test_table set name_string = 'tx1' where pk = 1 and `name` = 1 limit 10001", func() { close(tx1Started) - if err := waitForTxSerializationPendingQueries(tsv, "test_table where pk = 1 and name = 1", 2); err != nil { + if err := waitForTxSerializationPendingQueries(tsv, "test_table where pk = 1 and `name` = 1", 2); err != nil { t.Fatal(err) } }) @@ -1151,9 +1151,9 @@ func TestSerializeTransactionsSameRow_ConcurrentTransactions(t *testing.T) { countStart := tsv.stats.WaitTimings.Counts()["TabletServerTest.TxSerializer"] // Fake data. - q1 := "update test_table set name_string = 'tx1' where pk = :pk and name = :name" - q2 := "update test_table set name_string = 'tx2' where pk = :pk and name = :name" - q3 := "update test_table set name_string = 'tx3' where pk = :pk and name = :name" + q1 := "update test_table set name_string = 'tx1' where pk = :pk and `name` = :name" + q2 := "update test_table set name_string = 'tx2' where pk = :pk and `name` = :name" + q3 := "update test_table set name_string = 'tx3' where pk = :pk and `name` = :name" // Every request needs their own bind variables to avoid data races. bvTx1 := map[string]*querypb.BindVariable{ "pk": sqltypes.Int64BindVariable(1), @@ -1170,7 +1170,7 @@ func TestSerializeTransactionsSameRow_ConcurrentTransactions(t *testing.T) { tx1Started := make(chan struct{}) allQueriesPending := make(chan struct{}) - db.SetBeforeFunc("update test_table set name_string = 'tx1' where pk = 1 and name = 1 limit 10001", + db.SetBeforeFunc("update test_table set name_string = 'tx1' where pk = 1 and `name` = 1 limit 10001", func() { close(tx1Started) <-allQueriesPending @@ -1239,7 +1239,7 @@ func TestSerializeTransactionsSameRow_ConcurrentTransactions(t *testing.T) { // transactions via db.SetBeforeFunc() for the same reason as mentioned // in TestSerializeTransactionsSameRow: The MySQL C client does not seem // to allow more than connection attempt at a time. - err := waitForTxSerializationPendingQueries(tsv, "test_table where pk = 1 and name = 1", 3) + err := waitForTxSerializationPendingQueries(tsv, "test_table where pk = 1 and `name` = 1", 3) require.NoError(t, err) close(allQueriesPending) @@ -1285,8 +1285,8 @@ func TestSerializeTransactionsSameRow_TooManyPendingRequests(t *testing.T) { countStart := tsv.stats.WaitTimings.Counts()["TabletServerTest.TxSerializer"] // Fake data. - q1 := "update test_table set name_string = 'tx1' where pk = :pk and name = :name" - q2 := "update test_table set name_string = 'tx2' where pk = :pk and name = :name" + q1 := "update test_table set name_string = 'tx1' where pk = :pk and `name` = :name" + q2 := "update test_table set name_string = 'tx2' where pk = :pk and `name` = :name" // Every request needs their own bind variables to avoid data races. bvTx1 := map[string]*querypb.BindVariable{ "pk": sqltypes.Int64BindVariable(1), @@ -1302,7 +1302,7 @@ func TestSerializeTransactionsSameRow_TooManyPendingRequests(t *testing.T) { // Signal when tx2 is done. tx2Failed := make(chan struct{}) - db.SetBeforeFunc("update test_table set name_string = 'tx1' where pk = 1 and name = 1 limit 10001", + db.SetBeforeFunc("update test_table set name_string = 'tx1' where pk = 1 and `name` = 1 limit 10001", func() { close(tx1Started) <-tx2Failed @@ -1333,7 +1333,7 @@ func TestSerializeTransactionsSameRow_TooManyPendingRequests(t *testing.T) { <-tx1Started _, _, _, err := tsv.BeginExecute(ctx, &target, nil, q2, bvTx2, 0, nil) - if err == nil || vterrors.Code(err) != vtrpcpb.Code_RESOURCE_EXHAUSTED || err.Error() != "hot row protection: too many queued transactions (1 >= 1) for the same row (table + WHERE clause: 'test_table where pk = 1 and name = 1')" { + if err == nil || vterrors.Code(err) != vtrpcpb.Code_RESOURCE_EXHAUSTED || err.Error() != "hot row protection: too many queued transactions (1 >= 1) for the same row (table + WHERE clause: 'test_table where pk = 1 and `name` = 1')" { t.Errorf("tx2 should have failed because there are too many pending requests: %v", err) } // No commit necessary because the Begin failed. @@ -1368,8 +1368,8 @@ func TestSerializeTransactionsSameRow_TooManyPendingRequests_ExecuteBatchAsTrans countStart := tsv.stats.WaitTimings.Counts()["TabletServerTest.TxSerializer"] // Fake data. - q1 := "update test_table set name_string = 'tx1' where pk = :pk and name = :name" - q2 := "update test_table set name_string = 'tx2' where pk = :pk and name = :name" + q1 := "update test_table set name_string = 'tx1' where pk = :pk and `name` = :name" + q2 := "update test_table set name_string = 'tx2' where pk = :pk and `name` = :name" // Every request needs their own bind variables to avoid data races. bvTx1 := map[string]*querypb.BindVariable{ "pk": sqltypes.Int64BindVariable(1), @@ -1385,7 +1385,7 @@ func TestSerializeTransactionsSameRow_TooManyPendingRequests_ExecuteBatchAsTrans // Signal when tx2 is done. tx2Failed := make(chan struct{}) - db.SetBeforeFunc("update test_table set name_string = 'tx1' where pk = 1 and name = 1 limit 10001", + db.SetBeforeFunc("update test_table set name_string = 'tx1' where pk = 1 and `name` = 1 limit 10001", func() { close(tx1Started) <-tx2Failed @@ -1422,7 +1422,7 @@ func TestSerializeTransactionsSameRow_TooManyPendingRequests_ExecuteBatchAsTrans Sql: q2, BindVariables: bvTx2, }}, true /*asTransaction*/, 0 /*connID*/, nil /*options*/) - if err == nil || vterrors.Code(err) != vtrpcpb.Code_RESOURCE_EXHAUSTED || err.Error() != "hot row protection: too many queued transactions (1 >= 1) for the same row (table + WHERE clause: 'test_table where pk = 1 and name = 1')" { + if err == nil || vterrors.Code(err) != vtrpcpb.Code_RESOURCE_EXHAUSTED || err.Error() != "hot row protection: too many queued transactions (1 >= 1) for the same row (table + WHERE clause: 'test_table where pk = 1 and `name` = 1')" { t.Errorf("tx2 should have failed because there are too many pending requests: %v results: %+v", err, results) } }() @@ -1454,9 +1454,9 @@ func TestSerializeTransactionsSameRow_RequestCanceled(t *testing.T) { countStart := tsv.stats.WaitTimings.Counts()["TabletServerTest.TxSerializer"] // Fake data. - q1 := "update test_table set name_string = 'tx1' where pk = :pk and name = :name" - q2 := "update test_table set name_string = 'tx2' where pk = :pk and name = :name" - q3 := "update test_table set name_string = 'tx3' where pk = :pk and name = :name" + q1 := "update test_table set name_string = 'tx1' where pk = :pk and `name` = :name" + q2 := "update test_table set name_string = 'tx2' where pk = :pk and `name` = :name" + q3 := "update test_table set name_string = 'tx3' where pk = :pk and `name` = :name" // Every request needs their own bind variables to avoid data races. bvTx1 := map[string]*querypb.BindVariable{ "pk": sqltypes.Int64BindVariable(1), @@ -1476,7 +1476,7 @@ func TestSerializeTransactionsSameRow_RequestCanceled(t *testing.T) { // Signal when tx2 is done. tx2Done := make(chan struct{}) - db.SetBeforeFunc("update test_table set name_string = 'tx1' where pk = 1 and name = 1 limit 10001", + db.SetBeforeFunc("update test_table set name_string = 'tx1' where pk = 1 and `name` = 1 limit 10001", func() { close(tx1Started) // Keep blocking until tx2 was canceled. @@ -1524,7 +1524,7 @@ func TestSerializeTransactionsSameRow_RequestCanceled(t *testing.T) { defer wg.Done() // Wait until tx1 and tx2 are pending to make the test deterministic. - if err := waitForTxSerializationPendingQueries(tsv, "test_table where pk = 1 and name = 1", 2); err != nil { + if err := waitForTxSerializationPendingQueries(tsv, "test_table where pk = 1 and `name` = 1", 2); err != nil { t.Error(err) } @@ -1539,7 +1539,7 @@ func TestSerializeTransactionsSameRow_RequestCanceled(t *testing.T) { }() // Wait until tx1, 2 and 3 are pending. - err := waitForTxSerializationPendingQueries(tsv, "test_table where pk = 1 and name = 1", 3) + err := waitForTxSerializationPendingQueries(tsv, "test_table where pk = 1 and `name` = 1", 3) require.NoError(t, err) // Now unblock tx2 and cancel it. cancelTx2() @@ -2463,17 +2463,17 @@ func setupFakeDB(t *testing.T) *fakesqldb.DB { func getSupportedQueries() map[string]*sqltypes.Result { return map[string]*sqltypes.Result{ // Queries for how row protection test (txserializer). - "update test_table set name_string = 'tx1' where pk = 1 and name = 1 limit 10001": { + "update test_table set name_string = 'tx1' where pk = 1 and `name` = 1 limit 10001": { RowsAffected: 1, }, - "update test_table set name_string = 'tx2' where pk = 1 and name = 1 limit 10001": { + "update test_table set name_string = 'tx2' where pk = 1 and `name` = 1 limit 10001": { RowsAffected: 1, }, - "update test_table set name_string = 'tx3' where pk = 1 and name = 1 limit 10001": { + "update test_table set name_string = 'tx3' where pk = 1 and `name` = 1 limit 10001": { RowsAffected: 1, }, // tx3, but with different primary key. - "update test_table set name_string = 'tx3' where pk = 2 and name = 1 limit 10001": { + "update test_table set name_string = 'tx3' where pk = 2 and `name` = 1 limit 10001": { RowsAffected: 1, }, // queries for twopc diff --git a/go/vt/vttablet/tabletserver/tx_executor_test.go b/go/vt/vttablet/tabletserver/tx_executor_test.go index efd3a9b8868..bb386745958 100644 --- a/go/vt/vttablet/tabletserver/tx_executor_test.go +++ b/go/vt/vttablet/tabletserver/tx_executor_test.go @@ -500,7 +500,7 @@ func newTestTxExecutor(t *testing.T) (txe *TxExecutor, tsv *TabletServer, db *fa db.AddQueryPattern("insert into _vt\\.redo_statement.*", &sqltypes.Result{}) db.AddQuery("delete from _vt.redo_state where dtid = 'aa'", &sqltypes.Result{}) db.AddQuery("delete from _vt.redo_statement where dtid = 'aa'", &sqltypes.Result{}) - db.AddQuery("update test_table set name = 2 where pk = 1 limit 10001", &sqltypes.Result{}) + db.AddQuery("update test_table set `name` = 2 where pk = 1 limit 10001", &sqltypes.Result{}) return &TxExecutor{ ctx: ctx, logStats: logStats, @@ -517,7 +517,7 @@ func newShortAgeExecutor(t *testing.T) (txe *TxExecutor, tsv *TabletServer, db * db.AddQueryPattern("insert into _vt\\.redo_statement.*", &sqltypes.Result{}) db.AddQuery("delete from _vt.redo_state where dtid = 'aa'", &sqltypes.Result{}) db.AddQuery("delete from _vt.redo_statement where dtid = 'aa'", &sqltypes.Result{}) - db.AddQuery("update test_table set name = 2 where pk = 1 limit 10001", &sqltypes.Result{}) + db.AddQuery("update test_table set `name` = 2 where pk = 1 limit 10001", &sqltypes.Result{}) return &TxExecutor{ ctx: ctx, logStats: logStats, diff --git a/go/vt/vttablet/tabletserver/vstreamer/planbuilder.go b/go/vt/vttablet/tabletserver/vstreamer/planbuilder.go index a61ce1bf1ba..3454183b069 100644 --- a/go/vt/vttablet/tabletserver/vstreamer/planbuilder.go +++ b/go/vt/vttablet/tabletserver/vstreamer/planbuilder.go @@ -191,18 +191,18 @@ func mustSendDDL(query mysql.Query, dbname string, filter *binlogdatapb.Filter) return true } switch stmt := ast.(type) { - case *sqlparser.DBDDL: + case sqlparser.DBDDLStatement: return false - case *sqlparser.DDL: - if !stmt.Table.IsEmpty() { - return tableMatches(stmt.Table, dbname, filter) + case sqlparser.DDLStatement: + if !stmt.GetTable().IsEmpty() { + return tableMatches(stmt.GetTable(), dbname, filter) } - for _, table := range stmt.FromTables { + for _, table := range stmt.GetFromTables() { if tableMatches(table, dbname, filter) { return true } } - for _, table := range stmt.ToTables { + for _, table := range stmt.GetToTables() { if tableMatches(table, dbname, filter) { return true } diff --git a/go/vt/vttablet/tabletserver/vstreamer/planbuilder_test.go b/go/vt/vttablet/tabletserver/vstreamer/planbuilder_test.go index 8d50af55950..a18d84b863f 100644 --- a/go/vt/vttablet/tabletserver/vstreamer/planbuilder_test.go +++ b/go/vt/vttablet/tabletserver/vstreamer/planbuilder_test.go @@ -525,7 +525,7 @@ func TestPlanbuilder(t *testing.T) { }, { inTable: t1, inRule: &binlogdatapb.Rule{Match: "t1", Filter: "select none from t1"}, - outErr: `column none not found in table t1`, + outErr: "column `none` not found in table t1", }, { inTable: t1, inRule: &binlogdatapb.Rule{Match: "t1", Filter: "select id, val, max(val) from t1"}, diff --git a/go/vt/vttablet/tabletserver/vstreamer/vstreamer.go b/go/vt/vttablet/tabletserver/vstreamer/vstreamer.go index 8d38c958c89..ad40a34c696 100644 --- a/go/vt/vttablet/tabletserver/vstreamer/vstreamer.go +++ b/go/vt/vttablet/tabletserver/vstreamer/vstreamer.go @@ -463,7 +463,7 @@ func (vs *vstreamer) parseEvent(ev mysql.BinlogEvent) ([]*binlogdatapb.VEvent, e Statement: q.SQL, }) } - case sqlparser.StmtOther, sqlparser.StmtPriv, sqlparser.StmtSet: + case sqlparser.StmtOther, sqlparser.StmtPriv, sqlparser.StmtSet, sqlparser.StmtComment: // These are either: // 1) DBA statements like REPAIR that can be ignored. // 2) Privilege-altering statements like GRANT/REVOKE diff --git a/go/vt/vttablet/tabletserver/vstreamer/vstreamer_test.go b/go/vt/vttablet/tabletserver/vstreamer/vstreamer_test.go index 14f57fa19c8..f6e1d3a7bf8 100644 --- a/go/vt/vttablet/tabletserver/vstreamer/vstreamer_test.go +++ b/go/vt/vttablet/tabletserver/vstreamer/vstreamer_test.go @@ -201,6 +201,41 @@ func TestSetStatement(t *testing.T) { runCases(t, nil, testcases, "current", nil) } +func TestStmtComment(t *testing.T) { + + if testing.Short() { + t.Skip() + } + + execStatements(t, []string{ + "create table t1(id int, val varbinary(128), primary key(id))", + }) + defer execStatements(t, []string{ + "drop table t1", + }) + engine.se.Reload(context.Background()) + queries := []string{ + "begin", + "insert into t1 values (1, 'aaa')", + "commit", + "/*!40000 ALTER TABLE `t1` DISABLE KEYS */", + } + testcases := []testcase{{ + input: queries, + output: [][]string{{ + `begin`, + `type:FIELD field_event: fields: > `, + `type:ROW row_event: > > `, + `gtid`, + `commit`, + }, { + `gtid`, + `other`, + }}, + }} + runCases(t, nil, testcases, "current", nil) +} + func TestVersion(t *testing.T) { if testing.Short() { t.Skip() diff --git a/go/vt/wrangler/materializer.go b/go/vt/wrangler/materializer.go index 01bfed3082a..cce22b66fe3 100644 --- a/go/vt/wrangler/materializer.go +++ b/go/vt/wrangler/materializer.go @@ -62,12 +62,20 @@ const ( ) // MoveTables initiates moving table(s) over to another keyspace -func (wr *Wrangler) MoveTables(ctx context.Context, workflow, sourceKeyspace, targetKeyspace, tableSpecs, cell, tabletTypes string) error { +func (wr *Wrangler) MoveTables(ctx context.Context, workflow, sourceKeyspace, targetKeyspace, tableSpecs, + cell, tabletTypes string, allTables bool, excludeTables string) error { + //FIXME validate tableSpecs, allTables, excludeTables var tables []string var err error var vschema *vschemapb.Keyspace vschema, err = wr.ts.GetVSchema(ctx, targetKeyspace) + if err != nil { + return err + } + if vschema == nil { + return fmt.Errorf("no vschema found for target keyspace %s", targetKeyspace) + } if strings.HasPrefix(tableSpecs, "{") { if vschema.Tables == nil { vschema.Tables = make(map[string]*vschemapb.Table) @@ -85,7 +93,51 @@ func (wr *Wrangler) MoveTables(ctx context.Context, workflow, sourceKeyspace, ta tables = append(tables, table) } } else { - tables = strings.Split(tableSpecs, ",") + if len(strings.TrimSpace(tableSpecs)) > 0 { + tables = strings.Split(tableSpecs, ",") + } + ksTables, err := wr.getKeyspaceTables(ctx, sourceKeyspace) + if err != nil { + return err + } + if len(tables) > 0 { + err = wr.validateSourceTablesExist(ctx, sourceKeyspace, ksTables, tables) + if err != nil { + return err + } + } else { + if allTables { + var excludeTablesList []string + excludeTables = strings.TrimSpace(excludeTables) + if excludeTables != "" { + excludeTablesList = strings.Split(excludeTables, ",") + } + err = wr.validateSourceTablesExist(ctx, sourceKeyspace, ksTables, excludeTablesList) + if err != nil { + return err + } + if len(excludeTablesList) > 0 { + for _, ksTable := range ksTables { + exclude := false + for _, table := range excludeTablesList { + if ksTable == table { + exclude = true + break + } + } + if !exclude { + tables = append(tables, ksTable) + } + } + } else { + tables = ksTables + } + } else { + return fmt.Errorf("no tables to move") + } + } + log.Infof("Found tables to move: %s", strings.Join(tables, ",")) + if !vschema.Sharded { if vschema.Tables == nil { vschema.Tables = make(map[string]*vschemapb.Table) @@ -164,6 +216,54 @@ func (wr *Wrangler) MoveTables(ctx context.Context, workflow, sourceKeyspace, ta return mz.startStreams(ctx) } +func (wr *Wrangler) validateSourceTablesExist(ctx context.Context, sourceKeyspace string, ksTables, tables []string) error { + // validate that tables provided are present in the source keyspace + var missingTables []string + for _, table := range tables { + found := false + for _, ksTable := range ksTables { + if table == ksTable { + found = true + break + } + } + if !found { + missingTables = append(missingTables, table) + } + } + if len(missingTables) > 0 { + return fmt.Errorf("table(s) not found in source keyspace %s: %s", sourceKeyspace, strings.Join(missingTables, ",")) + } + return nil +} + +func (wr *Wrangler) getKeyspaceTables(ctx context.Context, ks string) ([]string, error) { + shards, err := wr.ts.GetServingShards(ctx, ks) + if err != nil { + return nil, err + } + if len(shards) == 0 { + return nil, fmt.Errorf("keyspace %s has no shards", ks) + } + master := shards[0].MasterAlias + if master == nil { + return nil, fmt.Errorf("shard does not have a master: %v", shards[0].ShardName()) + } + allTables := []string{"/.*/"} + + schema, err := wr.GetSchema(ctx, master, allTables, nil, false) + if err != nil { + return nil, err + } + log.Infof("got table schemas from source master %v.", master) + + var sourceTables []string + for _, td := range schema.TableDefinitions { + sourceTables = append(sourceTables, td.Name) + } + return sourceTables, nil +} + func (wr *Wrangler) checkIfPreviousJournalExists(ctx context.Context, mz *materializer, migrationID int64) (bool, []string, error) { forAllSources := func(f func(*topo.ShardInfo) error) error { var wg sync.WaitGroup @@ -850,9 +950,9 @@ func stripTableConstraints(ddl string) (string, error) { stripConstraints := func(cursor *sqlparser.Cursor) bool { switch node := cursor.Node().(type) { - case *sqlparser.DDL: - if node.TableSpec != nil { - node.TableSpec.Constraints = nil + case sqlparser.DDLStatement: + if node.GetTableSpec() != nil { + node.GetTableSpec().Constraints = nil } } return true diff --git a/go/vt/wrangler/materializer_test.go b/go/vt/wrangler/materializer_test.go index 922fbf9da29..f829de67714 100644 --- a/go/vt/wrangler/materializer_test.go +++ b/go/vt/wrangler/materializer_test.go @@ -18,6 +18,7 @@ package wrangler import ( "fmt" + "sort" "strings" "testing" @@ -60,7 +61,7 @@ func TestMigrateTables(t *testing.T) { env.tmc.expectVRQuery(200, mzUpdateQuery, &sqltypes.Result{}) ctx := context.Background() - err := env.wr.MoveTables(ctx, "workflow", "sourceks", "targetks", "t1", "", "") + err := env.wr.MoveTables(ctx, "workflow", "sourceks", "targetks", "t1", "", "", false, "") require.NoError(t, err) vschema, err := env.wr.ts.GetSrvVSchema(ctx, env.cell) require.NoError(t, err) @@ -75,6 +76,101 @@ func TestMigrateTables(t *testing.T) { } } +func TestMissingTables(t *testing.T) { + ms := &vtctldatapb.MaterializeSettings{ + Workflow: "workflow", + SourceKeyspace: "sourceks", + TargetKeyspace: "targetks", + TableSettings: []*vtctldatapb.TableMaterializeSettings{{ + TargetTable: "t1", + SourceExpression: "select * from t1", + }, { + TargetTable: "t2", + SourceExpression: "select * from t2", + }, { + TargetTable: "t3", + SourceExpression: "select * from t3", + }}, + } + env := newTestMaterializerEnv(t, ms, []string{"0"}, []string{"0"}) + defer env.close() + + env.tmc.expectVRQuery(100, mzCheckJournal, &sqltypes.Result{}) + env.tmc.expectVRQuery(200, mzSelectFrozenQuery, &sqltypes.Result{}) + env.tmc.expectVRQuery(200, insertPrefix, &sqltypes.Result{}) + env.tmc.expectVRQuery(200, mzSelectIDQuery, &sqltypes.Result{}) + env.tmc.expectVRQuery(200, mzUpdateQuery, &sqltypes.Result{}) + + ctx := context.Background() + err := env.wr.MoveTables(ctx, "workflow", "sourceks", "targetks", "t1,tyt", "", "", false, "") + require.EqualError(t, err, "table(s) not found in source keyspace sourceks: tyt") + err = env.wr.MoveTables(ctx, "workflow", "sourceks", "targetks", "t1,tyt,t2,txt", "", "", false, "") + require.EqualError(t, err, "table(s) not found in source keyspace sourceks: tyt,txt") + err = env.wr.MoveTables(ctx, "workflow", "sourceks", "targetks", "t1", "", "", false, "") + require.NoError(t, err) +} + +func TestMoveTablesAllAndExclude(t *testing.T) { + ms := &vtctldatapb.MaterializeSettings{ + Workflow: "workflow", + SourceKeyspace: "sourceks", + TargetKeyspace: "targetks", + TableSettings: []*vtctldatapb.TableMaterializeSettings{{ + TargetTable: "t1", + SourceExpression: "select * from t1", + }, { + TargetTable: "t2", + SourceExpression: "select * from t2", + }, { + TargetTable: "t3", + SourceExpression: "select * from t3", + }}, + } + + ctx := context.Background() + var err error + + var targetTables = func(env *testMaterializerEnv) []string { + vschema, err := env.wr.ts.GetSrvVSchema(ctx, env.cell) + require.NoError(t, err) + var targetTables []string + for table := range vschema.Keyspaces["targetks"].Tables { + targetTables = append(targetTables, table) + } + sort.Strings(targetTables) + return targetTables + } + allTables := []string{"t1", "t2", "t3"} + sort.Strings(allTables) + + type testCase struct { + allTables bool + excludeTables string + want []string + } + testCases := []*testCase{ + {true, "", allTables}, + {true, "t2,t3", []string{"t1"}}, + {true, "t1", []string{"t2", "t3"}}, + } + for _, tcase := range testCases { + t.Run("", func(t *testing.T) { + env := newTestMaterializerEnv(t, ms, []string{"0"}, []string{"0"}) + defer env.close() + env.tmc.expectVRQuery(100, mzCheckJournal, &sqltypes.Result{}) + env.tmc.expectVRQuery(200, mzSelectFrozenQuery, &sqltypes.Result{}) + env.tmc.expectVRQuery(200, insertPrefix, &sqltypes.Result{}) + env.tmc.expectVRQuery(200, mzSelectIDQuery, &sqltypes.Result{}) + env.tmc.expectVRQuery(200, mzUpdateQuery, &sqltypes.Result{}) + err = env.wr.MoveTables(ctx, "workflow", "sourceks", "targetks", "", "", "", tcase.allTables, tcase.excludeTables) + require.NoError(t, err) + require.EqualValues(t, tcase.want, targetTables(env)) + }) + + } + +} + func TestMigrateVSchema(t *testing.T) { ms := &vtctldatapb.MaterializeSettings{ Workflow: "workflow", @@ -95,7 +191,7 @@ func TestMigrateVSchema(t *testing.T) { env.tmc.expectVRQuery(200, mzUpdateQuery, &sqltypes.Result{}) ctx := context.Background() - err := env.wr.MoveTables(ctx, "workflow", "sourceks", "targetks", `{"t1":{}}`, "", "") + err := env.wr.MoveTables(ctx, "workflow", "sourceks", "targetks", `{"t1":{}}`, "", "", false, "") require.NoError(t, err) vschema, err := env.wr.ts.GetSrvVSchema(ctx, env.cell) require.NoError(t, err)