From e5e619a06b3cc922103ad22778007cd4758ca3e1 Mon Sep 17 00:00:00 2001 From: Geoff Flarity Date: Thu, 1 Mar 2018 13:45:23 -0500 Subject: [PATCH 01/41] default helm vtgate maxReplicas to replicas Signed-off-by: Geoff Flarity --- helm/vitess/templates/_vtgate.tpl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/helm/vitess/templates/_vtgate.tpl b/helm/vitess/templates/_vtgate.tpl index 7699c061f13..f0acf0644ff 100644 --- a/helm/vitess/templates/_vtgate.tpl +++ b/helm/vitess/templates/_vtgate.tpl @@ -138,7 +138,8 @@ spec: component: vtgate cell: {{ $cellClean }} -{{ if gt .maxReplicas .replicas }} +{{ $maxReplicas := .maxReplicas | default .replicas }} +{{ if gt $maxReplicas .replicas }} ################################### # optional HPA for vtgate ################################### @@ -153,7 +154,7 @@ spec: kind: Deployment name: vtgate-{{ $cellClean }} minReplicas: {{ .replicas }} - maxReplicas: {{ .maxReplicas }} + maxReplicas: {{ $maxReplicas }} metrics: - type: Resource resource: From 581eab9dc11c66506b3ef8d451645736bc846a37 Mon Sep 17 00:00:00 2001 From: Harrison McGonigal Date: Tue, 17 Apr 2018 15:14:22 -0400 Subject: [PATCH 02/41] dynamically calculate s3 upload partsize for backups Signed-off-by: Harrison McGonigal --- go/vt/mysqlctl/backup.go | 9 +++++++-- go/vt/mysqlctl/backupstorage/interface.go | 2 +- go/vt/mysqlctl/cephbackupstorage/ceph.go | 2 +- go/vt/mysqlctl/filebackupstorage/file.go | 2 +- go/vt/mysqlctl/filebackupstorage/file_test.go | 4 ++-- go/vt/mysqlctl/gcsbackupstorage/gcs.go | 2 +- go/vt/mysqlctl/s3backupstorage/s3.go | 18 ++++++++++++++++-- 7 files changed, 29 insertions(+), 10 deletions(-) diff --git a/go/vt/mysqlctl/backup.go b/go/vt/mysqlctl/backup.go index ea4e195a445..64eae6ea78a 100644 --- a/go/vt/mysqlctl/backup.go +++ b/go/vt/mysqlctl/backup.go @@ -402,7 +402,7 @@ func backupFiles(ctx context.Context, mysqld MysqlDaemon, logger logutil.Logger, } // open the MANIFEST - wc, err := bh.AddFile(ctx, backupManifest) + wc, err := bh.AddFile(ctx, backupManifest, 0) if err != nil { return fmt.Errorf("cannot add %v to backup: %v", backupManifest, err) } @@ -440,8 +440,13 @@ func backupFile(ctx context.Context, mysqld MysqlDaemon, logger logutil.Logger, } defer source.Close() + fi, err := source.Stat() + if err != nil { + return err + } + // Open the destination file for writing, and a buffer. - wc, err := bh.AddFile(ctx, name) + wc, err := bh.AddFile(ctx, name, fi.Size()) if err != nil { return fmt.Errorf("cannot add file: %v", err) } diff --git a/go/vt/mysqlctl/backupstorage/interface.go b/go/vt/mysqlctl/backupstorage/interface.go index 7d8e55ee936..e6dacb05177 100644 --- a/go/vt/mysqlctl/backupstorage/interface.go +++ b/go/vt/mysqlctl/backupstorage/interface.go @@ -49,7 +49,7 @@ type BackupHandle interface { // multiple go routines once a backup has been started. // The context is valid for the duration of the writes, until the // WriteCloser is closed. - AddFile(ctx context.Context, filename string) (io.WriteCloser, error) + AddFile(ctx context.Context, filename string, filesize int64) (io.WriteCloser, error) // EndBackup stops and closes a backup. The contents should be kept. // Only works for read-write backups (created by StartBackup). diff --git a/go/vt/mysqlctl/cephbackupstorage/ceph.go b/go/vt/mysqlctl/cephbackupstorage/ceph.go index 8d7d05c5537..5c0b616625e 100644 --- a/go/vt/mysqlctl/cephbackupstorage/ceph.go +++ b/go/vt/mysqlctl/cephbackupstorage/ceph.go @@ -73,7 +73,7 @@ func (bh *CephBackupHandle) Name() string { } // AddFile implements BackupHandle. -func (bh *CephBackupHandle) AddFile(ctx context.Context, filename string) (io.WriteCloser, error) { +func (bh *CephBackupHandle) AddFile(ctx context.Context, filename string, filesize int64) (io.WriteCloser, error) { if bh.readOnly { return nil, fmt.Errorf("AddFile cannot be called on read-only backup") } diff --git a/go/vt/mysqlctl/filebackupstorage/file.go b/go/vt/mysqlctl/filebackupstorage/file.go index 52f10707f0b..d2a93ea0ddc 100644 --- a/go/vt/mysqlctl/filebackupstorage/file.go +++ b/go/vt/mysqlctl/filebackupstorage/file.go @@ -56,7 +56,7 @@ func (fbh *FileBackupHandle) Name() string { } // AddFile is part of the BackupHandle interface -func (fbh *FileBackupHandle) AddFile(ctx context.Context, filename string) (io.WriteCloser, error) { +func (fbh *FileBackupHandle) AddFile(ctx context.Context, filename string, filesize int64) (io.WriteCloser, error) { if fbh.readOnly { return nil, fmt.Errorf("AddFile cannot be called on read-only backup") } diff --git a/go/vt/mysqlctl/filebackupstorage/file_test.go b/go/vt/mysqlctl/filebackupstorage/file_test.go index 41718e8f7fa..fe23d949fbc 100644 --- a/go/vt/mysqlctl/filebackupstorage/file_test.go +++ b/go/vt/mysqlctl/filebackupstorage/file_test.go @@ -140,7 +140,7 @@ func TestListBackups(t *testing.T) { } // check we cannot chaneg a backup we listed - if _, err := bhs[0].AddFile(ctx, "test"); err == nil { + if _, err := bhs[0].AddFile(ctx, "test", 0); err == nil { t.Fatalf("was able to AddFile to read-only backup") } if err := bhs[0].EndBackup(ctx); err == nil { @@ -166,7 +166,7 @@ func TestFileContents(t *testing.T) { if err != nil { t.Fatalf("fbs.StartBackup failed: %v", err) } - wc, err := bh.AddFile(ctx, filename1) + wc, err := bh.AddFile(ctx, filename1, 0) if err != nil { t.Fatalf("bh.AddFile failed: %v", err) } diff --git a/go/vt/mysqlctl/gcsbackupstorage/gcs.go b/go/vt/mysqlctl/gcsbackupstorage/gcs.go index d62a2c21a00..b6fbcfdc69c 100644 --- a/go/vt/mysqlctl/gcsbackupstorage/gcs.go +++ b/go/vt/mysqlctl/gcsbackupstorage/gcs.go @@ -66,7 +66,7 @@ func (bh *GCSBackupHandle) Name() string { } // AddFile implements BackupHandle. -func (bh *GCSBackupHandle) AddFile(ctx context.Context, filename string) (io.WriteCloser, error) { +func (bh *GCSBackupHandle) AddFile(ctx context.Context, filename string, filesize int64) (io.WriteCloser, error) { if bh.readOnly { return nil, fmt.Errorf("AddFile cannot be called on read-only backup") } diff --git a/go/vt/mysqlctl/s3backupstorage/s3.go b/go/vt/mysqlctl/s3backupstorage/s3.go index f9436f240a7..03bdd41b72b 100644 --- a/go/vt/mysqlctl/s3backupstorage/s3.go +++ b/go/vt/mysqlctl/s3backupstorage/s3.go @@ -27,6 +27,7 @@ import ( "flag" "fmt" "io" + "math" "sort" "strings" "sync" @@ -80,17 +81,30 @@ func (bh *S3BackupHandle) Name() string { } // AddFile is part of the backupstorage.BackupHandle interface. -func (bh *S3BackupHandle) AddFile(ctx context.Context, filename string) (io.WriteCloser, error) { +func (bh *S3BackupHandle) AddFile(ctx context.Context, filename string, filesize int64) (io.WriteCloser, error) { if bh.readOnly { return nil, fmt.Errorf("AddFile cannot be called on read-only backup") } + // Calculate s3 upload part size using the source filesize + partSizeMB := s3manager.DefaultUploadPartSize + if filesize > 0 { + minimumPartSize := float64(filesize) / float64(s3manager.MaxUploadParts) + // Convert partsize to mb and round up to ensure large enough partsize + calculatedPartSizeMB := int64(math.Ceil(minimumPartSize / 1024 * 1024)) + if calculatedPartSizeMB > partSizeMB { + partSizeMB = calculatedPartSizeMB + } + } + reader, writer := io.Pipe() bh.waitGroup.Add(1) go func() { defer bh.waitGroup.Done() - uploader := s3manager.NewUploaderWithClient(bh.client) + uploader := s3manager.NewUploaderWithClient(bh.client, func(u *s3manager.Uploader) { + u.PartSize = partSizeMB + }) object := objName(bh.dir, bh.name, filename) var sseOption *string From 051b8c5a3cfc7db5bf1cdb1934773b717f9d64ad Mon Sep 17 00:00:00 2001 From: tpetr Date: Thu, 19 Apr 2018 00:28:35 -0400 Subject: [PATCH 03/41] add support for BIGINT UNSIGNED <--> java.math.BigInteger Signed-off-by: tpetr --- .../vitess/jdbc/VitessPreparedStatement.java | 11 +- .../java/io/vitess/jdbc/VitessResultSet.java | 33 +++- .../jdbc/VitessPreparedStatementTest.java | 147 ++++++++++-------- .../io/vitess/jdbc/VitessResultSetTest.java | 20 ++- 4 files changed, 137 insertions(+), 74 deletions(-) diff --git a/java/jdbc/src/main/java/io/vitess/jdbc/VitessPreparedStatement.java b/java/jdbc/src/main/java/io/vitess/jdbc/VitessPreparedStatement.java index 9b0a347cbb6..2c69fa0ef32 100644 --- a/java/jdbc/src/main/java/io/vitess/jdbc/VitessPreparedStatement.java +++ b/java/jdbc/src/main/java/io/vitess/jdbc/VitessPreparedStatement.java @@ -19,6 +19,7 @@ import java.io.InputStream; import java.io.Reader; import java.math.BigDecimal; +import java.math.BigInteger; import java.net.URL; import java.sql.Array; import java.sql.Blob; @@ -247,6 +248,11 @@ public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException this.bindVariables.put(Constants.LITERAL_V + parameterIndex, x); } + public void setBigInteger(int parameterIndex, BigInteger x) throws SQLException { + checkOpen(); + this.bindVariables.put(Constants.LITERAL_V + parameterIndex, x); + } + public void setString(int parameterIndex, String x) throws SQLException { checkOpen(); this.bindVariables.put(Constants.LITERAL_V + parameterIndex, x); @@ -322,6 +328,8 @@ public void setObject(int parameterIndex, Object x) throws SQLException { setTimestamp(parameterIndex, (Timestamp) x); } else if (x instanceof BigDecimal) { setBigDecimal(parameterIndex, (BigDecimal) x); + } else if (x instanceof BigInteger) { + setBigInteger(parameterIndex, (BigInteger) x); } else if (x instanceof byte[]) { setBytes(parameterIndex, (byte[]) x); } else if (getConnection().getTreatUtilDateAsTimestamp() && x instanceof java.util.Date) { @@ -890,8 +898,7 @@ private void setNumericObject(int parameterIndex, Object parameterObj, int targe } setBigDecimal(parameterIndex, scaledBigDecimal); } else if (numberParam instanceof java.math.BigInteger) { - setBigDecimal(parameterIndex, - new java.math.BigDecimal((java.math.BigInteger) numberParam, scale)); + setBigInteger(parameterIndex, (BigInteger) numberParam); } else { setBigDecimal(parameterIndex, new java.math.BigDecimal(numberParam.doubleValue())); diff --git a/java/jdbc/src/main/java/io/vitess/jdbc/VitessResultSet.java b/java/jdbc/src/main/java/io/vitess/jdbc/VitessResultSet.java index 6825265d0a2..c2c28e19484 100644 --- a/java/jdbc/src/main/java/io/vitess/jdbc/VitessResultSet.java +++ b/java/jdbc/src/main/java/io/vitess/jdbc/VitessResultSet.java @@ -16,13 +16,12 @@ package io.vitess.jdbc; -import com.google.common.annotations.VisibleForTesting; -import com.google.protobuf.ByteString; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.io.Reader; import java.io.UnsupportedEncodingException; import java.math.BigDecimal; +import java.math.BigInteger; import java.net.URL; import java.sql.Array; import java.sql.Blob; @@ -46,8 +45,12 @@ import java.util.List; import java.util.Map; import java.util.logging.Logger; + import javax.sql.rowset.serial.SerialClob; +import com.google.common.annotations.VisibleForTesting; +import com.google.protobuf.ByteString; + import io.vitess.client.cursor.Cursor; import io.vitess.client.cursor.Row; import io.vitess.client.cursor.SimpleCursor; @@ -428,6 +431,27 @@ public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException return value; } + public BigInteger getBigInteger(int columnIndex) throws SQLException { + String bigIntegerString; + BigInteger value; + + preAccessor(columnIndex); + + if (isNull(columnIndex)) { + return null; + } + + bigIntegerString = this.getString(columnIndex); + + try { + value = new BigInteger(bigIntegerString); + } catch (Exception ex) { + throw new SQLException(ex); + } + + return value; + } + public byte[] getBytes(int columnIndex) throws SQLException { String bytesString; byte[] value; @@ -528,6 +552,11 @@ public BigDecimal getBigDecimal(String columnLabel, int scale) throws SQLExcepti return getBigDecimal(columnIndex, scale); } + public BigInteger getBigInteger(String columnLabel) throws SQLException { + int columnIndex = this.findColumn(columnLabel); + return getBigInteger(columnIndex); + } + public byte[] getBytes(String columnLabel) throws SQLException { int columnIndex = this.findColumn(columnLabel); return getBytes(columnIndex); diff --git a/java/jdbc/src/test/java/io/vitess/jdbc/VitessPreparedStatementTest.java b/java/jdbc/src/test/java/io/vitess/jdbc/VitessPreparedStatementTest.java index 6005dc4e665..31b7356f1f0 100644 --- a/java/jdbc/src/test/java/io/vitess/jdbc/VitessPreparedStatementTest.java +++ b/java/jdbc/src/test/java/io/vitess/jdbc/VitessPreparedStatementTest.java @@ -16,9 +16,9 @@ package io.vitess.jdbc; -import com.google.common.collect.ImmutableMap; import java.lang.reflect.Field; import java.math.BigDecimal; +import java.math.BigInteger; import java.sql.BatchUpdateException; import java.sql.Date; import java.sql.ResultSet; @@ -32,7 +32,9 @@ import java.util.List; import java.util.Map; import java.util.TimeZone; + import javax.sql.rowset.serial.SerialClob; + import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; @@ -42,6 +44,8 @@ import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; +import com.google.common.collect.ImmutableMap; + import io.vitess.client.Context; import io.vitess.client.SQLFuture; import io.vitess.client.VTGateConnection; @@ -456,6 +460,7 @@ private void testExecute(int fetchSize, boolean simpleExecute, boolean shouldRun Double doubleValue = Double.MAX_VALUE; BigDecimal bigDecimalValue = new BigDecimal(3.14159265358979323846); BigDecimal expectedDecimalValue = new BigDecimal("3.14159"); + BigInteger bigIntegerValue = new BigInteger("18446744073709551615"); String stringValue = "vitess"; byte[] bytesValue = stringValue.getBytes(); Date dateValue = new Date(0); @@ -473,41 +478,43 @@ private void testExecute(int fetchSize, boolean simpleExecute, boolean shouldRun preparedStatement.setFloat(7, floatValue); preparedStatement.setDouble(8, doubleValue); preparedStatement.setBigDecimal(9, bigDecimalValue); - preparedStatement.setString(10, stringValue); - preparedStatement.setBytes(11, bytesValue); - preparedStatement.setDate(12, dateValue); - preparedStatement.setTime(13, timeValue); - preparedStatement.setTimestamp(14, timestampValue); - preparedStatement.setDate(15, dateValue, Calendar.getInstance(TimeZone.getDefault())); - preparedStatement.setTime(16, timeValue, Calendar.getInstance(TimeZone.getDefault())); + preparedStatement.setBigInteger(10, bigIntegerValue); + preparedStatement.setString(11, stringValue); + preparedStatement.setBytes(12, bytesValue); + preparedStatement.setDate(13, dateValue); + preparedStatement.setTime(14, timeValue); + preparedStatement.setTimestamp(15, timestampValue); + preparedStatement.setDate(16, dateValue, Calendar.getInstance(TimeZone.getDefault())); + preparedStatement.setTime(17, timeValue, Calendar.getInstance(TimeZone.getDefault())); preparedStatement - .setTimestamp(17, timestampValue, Calendar.getInstance(TimeZone.getDefault())); - preparedStatement.setObject(18, boolValue); - preparedStatement.setObject(19, byteValue); - preparedStatement.setObject(20, shortValue); - preparedStatement.setObject(21, intValue); - preparedStatement.setObject(22, longValue); - preparedStatement.setObject(23, floatValue); - preparedStatement.setObject(24, doubleValue); - preparedStatement.setObject(25, bigDecimalValue); - preparedStatement.setObject(26, stringValue); - preparedStatement.setObject(27, dateValue); - preparedStatement.setObject(28, timeValue); - preparedStatement.setObject(29, timestampValue); - preparedStatement.setObject(30, 'a'); - preparedStatement.setObject(31, null); - preparedStatement.setObject(32, boolValue, Types.BOOLEAN, 0); - preparedStatement.setObject(33, shortValue, Types.SMALLINT, 0); - preparedStatement.setObject(34, longValue, Types.BIGINT, 0); - preparedStatement.setObject(35, floatValue, Types.DOUBLE, 2); - preparedStatement.setObject(36, doubleValue, Types.DOUBLE, 3); - preparedStatement.setObject(37, bigDecimalValue, Types.DECIMAL, 5); - preparedStatement.setObject(38, stringValue, Types.VARCHAR, 0); - preparedStatement.setObject(39, dateValue, Types.DATE, 0); - preparedStatement.setObject(40, timeValue, Types.TIME, 0); - preparedStatement.setObject(41, timestampValue, Types.TIMESTAMP, 0); - preparedStatement.setClob(42, new SerialClob("clob".toCharArray())); - preparedStatement.setObject(43, bytesValue); + .setTimestamp(18, timestampValue, Calendar.getInstance(TimeZone.getDefault())); + preparedStatement.setObject(19, boolValue); + preparedStatement.setObject(20, byteValue); + preparedStatement.setObject(21, shortValue); + preparedStatement.setObject(22, intValue); + preparedStatement.setObject(23, longValue); + preparedStatement.setObject(24, floatValue); + preparedStatement.setObject(25, doubleValue); + preparedStatement.setObject(26, bigDecimalValue); + preparedStatement.setObject(27, bigIntegerValue); + preparedStatement.setObject(28, stringValue); + preparedStatement.setObject(29, dateValue); + preparedStatement.setObject(30, timeValue); + preparedStatement.setObject(31, timestampValue); + preparedStatement.setObject(32, 'a'); + preparedStatement.setObject(33, null); + preparedStatement.setObject(34, boolValue, Types.BOOLEAN, 0); + preparedStatement.setObject(35, shortValue, Types.SMALLINT, 0); + preparedStatement.setObject(36, longValue, Types.BIGINT, 0); + preparedStatement.setObject(37, floatValue, Types.DOUBLE, 2); + preparedStatement.setObject(38, doubleValue, Types.DOUBLE, 3); + preparedStatement.setObject(39, bigDecimalValue, Types.DECIMAL, 5); + preparedStatement.setObject(40, stringValue, Types.VARCHAR, 0); + preparedStatement.setObject(41, dateValue, Types.DATE, 0); + preparedStatement.setObject(42, timeValue, Types.TIME, 0); + preparedStatement.setObject(43, timestampValue, Types.TIMESTAMP, 0); + preparedStatement.setClob(44, new SerialClob("clob".toCharArray())); + preparedStatement.setObject(45, bytesValue); Field bindVariablesMap = preparedStatement.getClass().getDeclaredField("bindVariables"); bindVariablesMap.setAccessible(true); Map bindVariables = @@ -521,40 +528,42 @@ private void testExecute(int fetchSize, boolean simpleExecute, boolean shouldRun Assert.assertEquals(floatValue, bindVariables.get("v7")); Assert.assertEquals(doubleValue, bindVariables.get("v8")); Assert.assertEquals(bigDecimalValue, bindVariables.get("v9")); - Assert.assertEquals(stringValue, bindVariables.get("v10")); - Assert.assertEquals(bytesValue, bindVariables.get("v11")); - Assert.assertEquals(dateValue.toString(), bindVariables.get("v12")); - Assert.assertEquals(timeValue.toString(), bindVariables.get("v13")); - Assert.assertEquals(timestampValue.toString(), bindVariables.get("v14")); - Assert.assertEquals(dateValue.toString(), bindVariables.get("v15")); - Assert.assertEquals(timeValue.toString(), bindVariables.get("v16")); - Assert.assertEquals(timestampValue.toString(), bindVariables.get("v17")); - Assert.assertEquals(boolValue, bindVariables.get("v18")); - Assert.assertEquals(byteValue, bindVariables.get("v19")); - Assert.assertEquals(shortValue, bindVariables.get("v20")); - Assert.assertEquals(intValue, bindVariables.get("v21")); - Assert.assertEquals(longValue, bindVariables.get("v22")); - Assert.assertEquals(floatValue, bindVariables.get("v23")); - Assert.assertEquals(doubleValue, bindVariables.get("v24")); - Assert.assertEquals(bigDecimalValue, bindVariables.get("v25")); - Assert.assertEquals(stringValue, bindVariables.get("v26")); - Assert.assertEquals(dateValue.toString(), bindVariables.get("v27")); - Assert.assertEquals(timeValue.toString(), bindVariables.get("v28")); - Assert.assertEquals(timestampValue.toString(), bindVariables.get("v29")); - Assert.assertEquals("a", bindVariables.get("v30")); - Assert.assertEquals(null, bindVariables.get("v31")); - Assert.assertEquals(boolValue, bindVariables.get("v32")); - Assert.assertEquals(shortValue.intValue(), bindVariables.get("v33")); - Assert.assertEquals(longValue, bindVariables.get("v34")); - Assert.assertEquals((double) floatValue, (double) bindVariables.get("v35"), 0.1); - Assert.assertEquals(doubleValue, (double) bindVariables.get("v36"), 0.1); - Assert.assertEquals(expectedDecimalValue, bindVariables.get("v37")); - Assert.assertEquals(stringValue, bindVariables.get("v38")); - Assert.assertEquals(dateValue.toString(), bindVariables.get("v39")); - Assert.assertEquals(timeValue.toString(), bindVariables.get("v40")); - Assert.assertEquals(timestampValue.toString(), bindVariables.get("v41")); - Assert.assertEquals("clob", bindVariables.get("v42")); - Assert.assertArrayEquals(bytesValue, (byte[])bindVariables.get("v43")); + Assert.assertEquals(bigIntegerValue, bindVariables.get("v10")); + Assert.assertEquals(stringValue, bindVariables.get("v11")); + Assert.assertEquals(bytesValue, bindVariables.get("v12")); + Assert.assertEquals(dateValue.toString(), bindVariables.get("v13")); + Assert.assertEquals(timeValue.toString(), bindVariables.get("v14")); + Assert.assertEquals(timestampValue.toString(), bindVariables.get("v15")); + Assert.assertEquals(dateValue.toString(), bindVariables.get("v16")); + Assert.assertEquals(timeValue.toString(), bindVariables.get("v17")); + Assert.assertEquals(timestampValue.toString(), bindVariables.get("v18")); + Assert.assertEquals(boolValue, bindVariables.get("v19")); + Assert.assertEquals(byteValue, bindVariables.get("v20")); + Assert.assertEquals(shortValue, bindVariables.get("v21")); + Assert.assertEquals(intValue, bindVariables.get("v22")); + Assert.assertEquals(longValue, bindVariables.get("v23")); + Assert.assertEquals(floatValue, bindVariables.get("v24")); + Assert.assertEquals(doubleValue, bindVariables.get("v25")); + Assert.assertEquals(bigDecimalValue, bindVariables.get("v26")); + Assert.assertEquals(bigIntegerValue, bindVariables.get("v27")); + Assert.assertEquals(stringValue, bindVariables.get("v28")); + Assert.assertEquals(dateValue.toString(), bindVariables.get("v29")); + Assert.assertEquals(timeValue.toString(), bindVariables.get("v30")); + Assert.assertEquals(timestampValue.toString(), bindVariables.get("v31")); + Assert.assertEquals("a", bindVariables.get("v32")); + Assert.assertEquals(null, bindVariables.get("v33")); + Assert.assertEquals(boolValue, bindVariables.get("v34")); + Assert.assertEquals(shortValue.intValue(), bindVariables.get("v35")); + Assert.assertEquals(longValue, bindVariables.get("v36")); + Assert.assertEquals((double) floatValue, (double) bindVariables.get("v37"), 0.1); + Assert.assertEquals(doubleValue, (double) bindVariables.get("v38"), 0.1); + Assert.assertEquals(expectedDecimalValue, bindVariables.get("v39")); + Assert.assertEquals(stringValue, bindVariables.get("v40")); + Assert.assertEquals(dateValue.toString(), bindVariables.get("v41")); + Assert.assertEquals(timeValue.toString(), bindVariables.get("v42")); + Assert.assertEquals(timestampValue.toString(), bindVariables.get("v43")); + Assert.assertEquals("clob", bindVariables.get("v44")); + Assert.assertArrayEquals(bytesValue, (byte[])bindVariables.get("v45")); preparedStatement.clearParameters(); } diff --git a/java/jdbc/src/test/java/io/vitess/jdbc/VitessResultSetTest.java b/java/jdbc/src/test/java/io/vitess/jdbc/VitessResultSetTest.java index f31de052f5a..726398de68a 100644 --- a/java/jdbc/src/test/java/io/vitess/jdbc/VitessResultSetTest.java +++ b/java/jdbc/src/test/java/io/vitess/jdbc/VitessResultSetTest.java @@ -16,7 +16,6 @@ package io.vitess.jdbc; -import com.google.protobuf.ByteString; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.UnsupportedEncodingException; @@ -27,6 +26,7 @@ import java.sql.Time; import java.sql.Timestamp; import java.util.Properties; + import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; @@ -36,6 +36,8 @@ import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; +import com.google.protobuf.ByteString; + import io.vitess.client.cursor.Cursor; import io.vitess.client.cursor.SimpleCursor; import io.vitess.proto.Query; @@ -266,6 +268,14 @@ public Cursor getCursorWithRowsAsNull() { Assert.assertEquals(new BigInteger("1000"), vitessResultSet.getObject(10)); } + @Test public void getBigInteger() throws SQLException { + Cursor cursor = getCursorWithRowsAsNull(); + VitessResultSet vitessResultSet = new VitessResultSet(cursor, getVitessStatement()); + vitessResultSet.next(); + + Assert.assertEquals(new BigInteger("1000"), vitessResultSet.getBigInteger(10)); + } + @Test public void testgetBoolean() throws SQLException { Cursor cursor = getCursorWithRows(); Cursor cursorWithRowsAsNull = getCursorWithRowsAsNull(); @@ -448,6 +458,14 @@ public Cursor getCursorWithRowsAsNull() { Assert.assertEquals(-1000, vitessResultSet.getInt("col9")); } + @Test public void testBigIntegerbyColumnLabel() throws SQLException { + Cursor cursor = getCursorWithRows(); + VitessResultSet vitessResultSet = new VitessResultSet(cursor, getVitessStatement()); + vitessResultSet.next(); + Assert.assertEquals(new BigInteger("1000"), + vitessResultSet.getBigInteger("col10")); + } + @Test public void testgetFloatbyColumnLabel() throws SQLException { Cursor cursor = getCursorWithRows(); VitessResultSet vitessResultSet = new VitessResultSet(cursor, getVitessStatement()); From 74ce7e29b1086d3ecdbb879b51ab61eeb8b2b6e1 Mon Sep 17 00:00:00 2001 From: Arthur Neves Date: Thu, 19 Apr 2018 20:37:24 +0200 Subject: [PATCH 04/41] Move vtcombo initTabletMap func to vtcombo package The idea is so another commands can reuse the initTabletMap. In my case, I am building a new command and importing libs from vitess. In my cmd I am faking a topology(using memory) and starting vttablets for it. Similar on what vtcombo does. Signed-off-by: Arthur Neves --- go/cmd/vtcombo/main.go | 3 ++- go/{cmd => vt}/vtcombo/tablet_map.go | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) rename go/{cmd => vt}/vtcombo/tablet_map.go (99%) diff --git a/go/cmd/vtcombo/main.go b/go/cmd/vtcombo/main.go index a6e97ff1372..1e423dcf156 100644 --- a/go/cmd/vtcombo/main.go +++ b/go/cmd/vtcombo/main.go @@ -38,6 +38,7 @@ import ( "vitess.io/vitess/go/vt/srvtopo" "vitess.io/vitess/go/vt/topo" "vitess.io/vitess/go/vt/topo/memorytopo" + "vitess.io/vitess/go/vt/vtcombo" "vitess.io/vitess/go/vt/vtctld" "vitess.io/vitess/go/vt/vtgate" "vitess.io/vitess/go/vt/vttablet/tabletserver/tabletenv" @@ -109,7 +110,7 @@ func main() { servenv.OnClose(mysqld.Close) // tablets configuration and init - if err := initTabletMap(ts, tpb, mysqld, *dbcfgs, *schemaDir, mycnf); err != nil { + if err := vtcombo.InitTabletMap(ts, tpb, mysqld, *dbcfgs, *schemaDir, mycnf); err != nil { log.Errorf("initTabletMapProto failed: %v", err) exit.Return(1) } diff --git a/go/cmd/vtcombo/tablet_map.go b/go/vt/vtcombo/tablet_map.go similarity index 99% rename from go/cmd/vtcombo/tablet_map.go rename to go/vt/vtcombo/tablet_map.go index 89035f0da66..56bb233ba3c 100644 --- a/go/cmd/vtcombo/tablet_map.go +++ b/go/vt/vtcombo/tablet_map.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package main +package vtcombo import ( "flag" @@ -106,7 +106,7 @@ func createTablet(ctx context.Context, ts *topo.Server, cell string, uid uint32, // initTabletMap creates the action agents and associated data structures // for all tablets, based on the vttest proto parameter. -func initTabletMap(ts *topo.Server, tpb *vttestpb.VTTestTopology, mysqld mysqlctl.MysqlDaemon, dbcfgs dbconfigs.DBConfigs, schemaDir string, mycnf *mysqlctl.Mycnf) error { +func InitTabletMap(ts *topo.Server, tpb *vttestpb.VTTestTopology, mysqld mysqlctl.MysqlDaemon, dbcfgs dbconfigs.DBConfigs, schemaDir string, mycnf *mysqlctl.Mycnf) error { tabletMap = make(map[uint32]*tablet) ctx := context.Background() From e9b0d3be5af3e020ba9fd70c66a59ca4db38509b Mon Sep 17 00:00:00 2001 From: Sugu Sougoumarane Date: Thu, 19 Apr 2018 21:39:51 -0700 Subject: [PATCH 05/41] Add JD.com to the list of adopters Signed-off-by: Sugu Sougoumarane --- ADOPTERS.md | 1 + vitess.io/images/users/jd.jpg | Bin 0 -> 11983 bytes vitess.io/index.md | 9 ++++++--- 3 files changed, 7 insertions(+), 3 deletions(-) create mode 100644 vitess.io/images/users/jd.jpg diff --git a/ADOPTERS.md b/ADOPTERS.md index f36b4b44c21..11ee7b0efdf 100644 --- a/ADOPTERS.md +++ b/ADOPTERS.md @@ -5,6 +5,7 @@ This is an alphabetical list of known adopters of Vitess. Some have already gone * [BetterCloud](http://bettercloud.com) * [FlipKart](http://flipkart.com) * [HubSpot](http://product.hubspot.com/) +* [JD](http://jd.com/) * [Nozzle](http://nozzle.io) * [Pixel Federation](http://pixelfederation.com) * [Quiz of Kings](http://quizofkings.com) diff --git a/vitess.io/images/users/jd.jpg b/vitess.io/images/users/jd.jpg new file mode 100644 index 0000000000000000000000000000000000000000..affd8ad4ec3b9da1702e352716d67ff8b214a7f8 GIT binary patch literal 11983 zcmeHtXIN9))@~FPMFlAVq{ya2C{ZBvvZV(EHjsc20-FvAMIiKMqYG@hbg3Z;0V$yu zrAhC-sq`YfBjvKs{m$9v+#lyW-@kjG`_1)Zjc3g<$5>;|wca_#yVm9S;a5)7~0^GWB^VZE9w{G3MMNWR}HpK%9iaU2G=qRb~Jz$_?WMrVDr)Og2 zW@BRJWTB`3Mer9+9$tPB|3fyR$3lFMx%v3{{xoupoSdBEHU%vO1uY*FJrm!5yIp<) zP~Qe@UI&p~;{aTzzD7oU?Xm^H0=NbsyY^=T{Jq^GzkTiI4YKQ3y#@~e*T}A4C!-+0 zdz+m6=ASy(u9ICwLrqS@PRsD*Da_pERou{RItksFtP*+-5kaO00FYB$Prqz% zPSn8SO?-9}7q=Kh)iRbxNm=Ff_LW`cD|gqg-2UC=)%nKFE6caYuR3L^0oSixzkci1 z9Wt_;|6Av8PN`{V*`MeR07ahaWtH3#Gk0-)74vzUjzgcG^E2PcO7Y=NOxk!gaM(6kXs19^`zzaw>CTV-!XywKEO-OGaI-`QmxFc_xX~UMo(PTtak1Cf)J7T)^ zSSL8E;{*Cya$V#eR^>-MY+ z?QW_qYU{hy8t4V@eoypncHvEIod@rtc<;#9CPRr-%xFYCvIf^}v}*l4qtIk3<;4OT zzWK`D5v5MR#_?rIWB;Iu)y(!HEAH6AFwa&?~wmlFkE5>UcE|2z^ zC#zcj6@)}o%US-!WbLuGPk7p$b5YB)0)ps21^JJD)okpwA#sJy@QpbRuN6e845p3bvtEC3wl# z4VU&=DI5}y>%(ug%u4*`dq^#C3h{;7(&cUX?SeIfYGUWLPkm19@a(QuOX|a}V7&x+ zNPk{KNpwN8h|qmK$LUA-5`|>Rsda6Oz@R7Tadav~dtww+R}@2eR4STBs4R?0x4sQS zcq9xv6@5HSR;g;B+I$BMES(l)U>HE+azIB`rgMTUK zE=BvyZ>YVaWR*;M`Mv*|$Uwa|FTN^3x#6G?{Dwec8z4jpWTO) zpEv4xs(gKcy#(kDUum1I)3H|WQn^lE8F)Gs$PV8Mi;y=h+{b>CXlcy^8~EsNGff73 zEm*0&pt}UD8D}h(6V5F{DlU{77WeU)2Xu0kyFi0uugb->K8=7IKNTfQfBLk|3b@z6 zU_-~{(ZezNf&+-yZMRfK%+jFIxi*8iXT@-yu|_J?c0`^qk_kQZ)q*!+AEZbZ6159bQb@x2t1e zL4U;UwGT7hXvmN=N1 z#qy4!-_fTcRs1an;`euIpe%Ljq1L{MaZj#7$oKIjsmO|`FN^Rj#xb{~J+f%sj%>XH zgov}`#YjM1GxBJ|LK_YUg9U`)-@LO1mk5Ic5z~tMZg+#T#)vG_l{U2uB0tKe%CR05 z`X>Bfw)eP5E{htE?6u-s_INcH|DSB%W!}OJ(bGK{&yNf?ozZcEBeK)22RVZEpPtJX z^qFgVLGiw&AHH1zUh7oMqdpE`b5pycgJ&-CPo{d)FdmyxGjBEh9FV&kW+#Ey8pMT9 zJc`d6Us3l+1>1Kkk7|akH9mDdL$6fR%44Vkp5DF6phr2iIxjgSC z_4=(=zGM&KIV#JO@qtwgy*6FI0Dk}RpRnxxN?@l-+$!>rMJX&QO6@lUdz~+fga|VAHIg%DD3sD!30CCAJYbN&m9F$ zjYW+#OSUfow^k++m8mqxrQT!jX{>o?JI z)PQ8J)0Y4_tMra7P1OYTpM5D!aEBsM1ULDDxrz!pp-4qVD?Fm*PH*z|>GLP826HpU z#={!#Vi3)#FbxvKtyy$2Aw!rmiBiT?fu*>h5sNv(lZ#u^p4Gkyfcx zM^iE%R_GE1Pw_Ke1tWym9biC+b%n5aeonof{_vmy$y{q9bOC*ATgI8CWhsQ8Eb;Gz%)7b)^J@y{t$8_H9(p9;i}m^wf1{T21RzWO8;Z%qHb=1Y;z6UAG{agIi=FqwGmy)Js9Jq&gK> z_s&=l9_52MiY2kk*vi;aiNa=sp!{}U%7Y>&5W~5fPNJy0uHOD(M2|oA9be%6wcP7R zXd8v>xw1!HcV1+M)JD>uz5BY&2i<>T+jQ)Fd)i6ikBun;r-5Q>xMR!|^SZuZzMriz ziC1f3SKx8&UG%Bbi=l9Y^w)1wjHvwZ(pDvXbhPV-L@tb=>e|AHR#*}>)!-wJ&lM4M z59U&C6c8}dKU{~nl0_lU%2vCNFxCqfpAS@hDGZzR_dDOLK@X=ri4sgcD#8zKDUNn? zcm~g>GIY$jOkA>OWn=N?{u(oNag(A?Ic_R7636c>7Jne-9{SN*RJVPsXtZb+ z(^WWdP{n+|Lrs*k^tUIQmN6{j`eG(kzb$L)<5;<4tV0J$9}96hTFaGk;B7c#4#Ub? zF_nq^hDUxYQjpRCyu;;0NDvqHQ{hV^KM>RoHe!#noO3Oi;j8xlvinv#&dpcH(9&9a zkWy^Qdt-7>8X(5=@;^Wyk2KqEjMb^3f5?M5%dATPKfO+#=eP?=zLdl4l&BMQ!n8H_ zN4?02Xrn**?AxKg__%S(CMlHLQ%XL+Ew%{z?jytvtN0L7D`|(-z+%XX1i6tUjp`M-kFvBYrsgUo8JBsU`;y8+$X8>^ROp5-Y(kOetORBV*_A|c!l8p^kUX|EZohfHTuhi#`1XS(FMT<~WP90G$=Lfm#*!q{_Oc`U|S z7vh$5j6f6CX|oI7(dzil(x6Dz(zrgb?ZpW&>8&ux(SP#pea^DiVV*|Q5!-pN@!8zN z_>)supAh^R2`C~B&2z2aa$PEdPvU(g-EMzL?oZCq+Xc(RK#JA*8PzC1A|=xG$3h@ zl0g{@tKrFf_+S*L6K|V4sb3iLu9L!jucXc&g|D~j3QmB~cK9f0jkfTb3LFx_3?Czg zdbnkGddL!D+ZKF*k_ilA;=* zu%_piv`>^>rKX;=7mG_PoKwU7i8^lJk~7F`|6qP2M!eXW&U@0Zlok9|<`*WA%^F&^mWV&F`!^<;&D z&#i=Q&oZxI%9I9Gyr!8*H84=OmU(^Dv`oP~LP(XpQFjt23I#oiG_>Ak-bo)0PHC%( z4N>!wX7W+CeOJo$I{fBwXINq>Hdzw3>QLJ2Ivu{HzOIpLZmsE%f8?uh)K0A9c%mub zBz8!lwyvgmG8w}0W9-jGn;O+uTQ}5)Si?vVJ!$CT)v9??;EPbcjOeRH<4ir__$t^> zIAE1;Yipgza559O*uSbn*+H7^wU%QxpidFpfg0XIy~}d z{3{t+V`Bvsg6(j;$v7ZT=J_g1HIJ4S-kQj7A#U-`+6bYIFOSK7dcByLIb)Ut*F$!7 zrbNtoE2yn@R&@)H$#o>mwWr3UF}DX7L4jvLFilvtz*KuuefGY$2! z!gjc{!ZUp^?|-DP#4*d<{^|~zC7=i}ht;2uIUkH|<@;!7eM7;FCA0Z)xB9HSn?L7C z{sVjV9=#O~{%(O6i}yo>;-o9a^~$@?@^f#5OD64$m;6n)j8ihDGr1+ zS4FdheYMa^sGhSz8R0_)`y?{B*Ji@=;EP# zna-T4U3=$WC1Ri?@1L;Ff6RdRheQA**$!%Lj z^{tiJID(PFiGR#cIEGqB8@jD3O87ho>vGD;NzBHm7M77Zmq_v;D_pFNw`A}EGE{iT z#3@dYB;wAgA4b&XT9O?)`jCSwE(}i$zr$OQFj*KSzEq^|$TJ$ormG5M^@~kHAF_oM zrhc2@n)#TXa5&{a7iF1;nab^POA9XuOKjD7!ryF6Sv}e|Q9RQ9!D3_D!fBNQQ+(a0 z!@>^qDQ00ks1>Yx=o8R|`2 z2K`Y`(VZDGGhq-MlmmT%VCz4A9sMcu_j91dJt&Ji*wS&IYBCPSu`VUMVM~SOeEzv( zAAHSYnTpDoWV0WM*brgjs;_ z5ZR6|FcW27)tFNT3tITCfd8O(y$q`1A`DbAuQh82J zq&a2{I^-?o>@AzQT!q_KeT@Hn00D}xX+ZJZC{av05Ki2a;GRfcnv+=!;HcGfsd-j9 ztYG27iD((c(mYB8e`e_By96BN31il(#q+`b%r(a~?E_8PP&<*Ow?g=?1F=%a!w*^? zZDNJTHF|_<#%^*Za}h)u4DfhRHZKkK{n@@@kiAO)N9zOvcTx}-TL%-dR^KJGB znfk?14oO=!5}t=&umDr=XrwZ9D`8_w`?%hPl|Xt8xg7g=mg??gOh+`5uNcJ6huE!y z-Qn>Eab+0HleKKs2ofzyc)GM3SCXF3OwV6!yqa;so|oi?&fHEA(WWh&*Hy810tq_( zAeg`+D-o48Uy|(S0hB6L{{cI$TW5`~+w*iJ(M6fZPUnuEZD7D{tCv@6-|^$Yrv&DUk{ zP|u_kk??KWzfgqcFLVjVUlCd|)c-|j{U3E-$F}~5LO=Gi^u~2vUrmh}RlhNcgHAJ= zJyG(9Lus}eZ`M9t5wtH{eyEsQ-MahcbH(u5JE)nPTOdS}a$zjce*KuYa3JlrqL@;t98*9)0NRxR<%3{6E<=6PI#?a6$%~L31K|h10@oV{v2TV&W8f0$@QK?DG=l|wZm$qE^p7KE z56=VJ)P9x3(tJC|@#hl>!6}K5*lgPzP76O<&_XE6f$R;@>(-~!&Sk}fpNaKI%VWkc zl5s@K@Iiv}8)8_}JuO2_dg#i=PPSU+2HTh6(1y67?eJC_qP6@LC4nGgj2m8Pykq#S zGE1bdUo$&F68&(|#W(@HIUl0ut>%}xykt8ciJ3q^lvY2MKYN{AOOLlf%bnjxMrx;x zeRv}SWvm`V6L+y`e9z{VCKC3LUXpTXYQ@W3TXTcFIdkz=YqF)EAjT2Lk66&r1manv1J%f?NR z%N|WSm%T;Y{Vt)3E@lB?hofS*q`lw3$*$jFdyi)0!Nkv16e=H-qq2G&xj`I$KvWrL{ixNo*0~|kB);Lvqr1iNK0k=DI_xeN!y6%_9V^}2@H&shM zS2c9x$|&y-Dz>ERgHj%rx-Qh&pY|;Cr3?M;`R!+?d`yvhJ`Vo7YZ0ndn;xvjkbb-2 zVg2y;sYRi|u+G>|KSrv5_C#}gyvE5ZYn zCz5ykqx>X7*NN`8t3O==ycUmtAc>yFkDg}BvOlg|yenw9CV7D8(>HK5Wl*m3*R0Hf z^-di8v93ST#W`v&(Rnxtd34_Q^}_SDd)73lDwRR8>ff`i zl6mQy*;e&Cg)RZ>0zZ^g?eLcXdEOHE3`kTtr4-o{vBMZ1I=ug|PoqKC`4V7cWKnbkORw8-6cwGX>NuV0ABmP_%~oj$wq|89_Vdi`a8suZ3)c4u9aWS%PY$EBz@zn z)Tl=m=MH5e_U5NqGKS^WO~YM+{36jrv?kMbhd!rq*l;*uO&qpx!~xM&LHJ3v9 zv+Evx%pL7Q!q+Oe!%@Skieo$)F+9_|%Vy^L-;k6DhoLV)q8K51rih7O13_L5l+w!67 zX1Xqh2A`EQAzCJd;Tb%H*`p%$VQt`(i$7dAcMSLm)xxE};$uFI`8}V?F!MP`o$ga* zk}C{ZnMotefQSL(jwgrIrGIg7|6G(lus;~9JCY2+!~ctr`xibg$o4xKU7X#iYBTeK z=ew5bCwM}0_uq)Q_lVBjKeN30Hq5E4Vp%NAL;H+sqoVT&&xL_Ftps%)0r^GOQe5Wz zLg8FNu|Kz@=>NJLY2FNW_!&E9 zSn2!@#^XacPuymgS6$G|bIjgLUf3~HKN!F`xGNVJ*Xo&EJ7a_G2)72bZxra zUdv0g*WEcPezI-`7Bi4>7#Y(D)*n(1FLFx?Nv4hTewUY>|PAlHytdy)wJjjmjaJhHkQz3*n@0iy{C&44FzTw=iw$JI^WoT`Q$-AXM%7h zsUNA`>xIYkd>=-`yOMG^NJ2a@`#vO2)zq{KuFwnn+;hA|o2prw@T`6o8=a{ysPcQL z8)jY~&=@HpAE}k;ZM2F-ip6=(h<>+0GKH%9u@)0Qw2%_3XCtE;#4xDFavNXi0mFWu z3~Db^n^AoW>E|Q;)nPXc@P0s@*NaPYYtjlcPp!ud^pYK zO_5o~k`W7mMWLcFd};5Ggz0C_%t=}IWpY8sj}s$NSy-42QABr0BGQC7qNC`@jS!5_ z8~4_M^58oo3w?T)4?%3?&+2D%lE}jqz-KAye!TL)ke^@oW46e_L&*&VmjE=B>g{s# z$4h|kMV!FM1QC8wd-D>&R>mXE+2Uex2Ap$0fx@4CrN^Nw)++^LX6)BhL}%riyrdI6qfjZ{h@c)zeA3MxH=_3lq}I-caQw^BHqiq`k+6${kpWHZUH8u(4?B8(acp z#=@koeB9C2;G47_+1`EUkW)$Ww(4{ecY|$G{PnhbE1Ot3OP~PAXUI z`pBbsS2ICLlR?aRI((IvfWqREyM3SMJ9hn1W+*zF1i$RB7o`m?z{ZKtrohuNHU%-2 zUvDUl{u`iX5uzfu>SKc*NXZdFyWUw52bGi-s{+NqM_{eF;%GBCaw`E5YZaDBJ(z^F zF`T>l$S+;;x`*^}^uAVzt72i%kOu>HRKsIz1WcbRjk~Z`ltW<0kNF(*z_LTxJ~4D3 z-B*i-mWQ`BPg8M_tq$+fy$(qokxPJo#kf6v{)Q1yjKA$*vi?p}y{dQJYAv;a^2!Q( z?uWj4Qf*FLj$B4|W%V?{iKLCIhWEf_DhP`{)joAIYWy>;?wSZ46++Ll3pen`UZi2bTAu4a*FKpE4mx&ld!`0fm`q_EXh9ltf zDtFz$T^NU_znu1hn}2G`)HE&OKwSfg!nfIv(Eq2xBb_+Vu8 zy|&{CQ8Z!5LjO}i4dER7g17R0UsasCSLy@Oz?eyHc(Rvy{@IWrR){c~tL5b;sl8Ro z*HF3-=gD&i$1bVw(MW>9{xRk1T{fndNAVc8S{O@? z4F*FPeJ%lN?zzfF_L)RHp`;xbOY+f$?NKsnVN*mURdY>v%5=PQhO`rJRuo34nIw1z zJ}pSL-7D(?8!67EE^2c%jv~?2%v_s2jA{2!JX$CW`yyGM#vra##XpMH(UMnM6FnC& z?5^KG(hS$+Xq5%4m8>>JX%(OxZoYH$I&4`pUTPvurX*lot>fx8mFH2(&&~_*YkVk6 zTy}2y^ziwKD9FL?}P$>A1YZ4D4qIrmKk=Xp~u#O)RBbp$7Oi)+Q}RIy&h>F9)x zr5E;c7Qn_9Nu*RpM>8!C+tQ^HR%4#vL z7~X4o$Rc>9&#Hj1yWR+_-py^n!yme&ZK)9zZ<)iI+r{LSZhZO^XZNM1Hc)ao+0{-- zJw{LI5o<#qj>&ftx_}J31UMQ-r1oowMP&O3YU*-#4hZl$IX{~X&rC`7TTi;amz8p7 z^ZsDQFU>DX69&Z_!cv)m8u)75lG=;K?&{Es zePLcbV~n?$bE#%^6Bvm=mv$DDG}CMaAU&N2(5-kw1123P5Ge!6Opc%(OP)-lVkCMOZTzV1|nT1Q)dPI_9J z<}NIUm9B7~1v3Y+jVE3L;siG1bXG)xSK0Pm?)$LNwez;lGF}l%sYq*$Y@{AjGw2lV@HsaGjWD(dar^?bjvK1g0b8Vw>Y*e-3y0 z5aHj?Rf{Y8b>;<*cD=N^>Ui`;G#*^l zQZ4g8^omT#)e%Q^Y#jMF%j)EL7Y|J*O@BE5U5}~y1uMJr?6zO{d-~pgnEZzxYVp(m Uxc;9B|DVU~|K692^K#;U0RR}d+yDRo literal 0 HcmV?d00001 diff --git a/vitess.io/index.md b/vitess.io/index.md index 4ccbc79aae8..161d31bd208 100644 --- a/vitess.io/index.md +++ b/vitess.io/index.md @@ -60,21 +60,24 @@ Slack and Nozzle are swapped for aesthetics, because the icons don't align well Hubspot
- Slack + JD
+
+ Slack +
Pixel Federation
Quiz of Kings
+
+
Nozzle
-
-
Square
From b9142b34c7eb3eadbdf46a5fba97186fb24ac43d Mon Sep 17 00:00:00 2001 From: Arthur Neves Date: Mon, 23 Apr 2018 09:45:47 -0700 Subject: [PATCH 06/41] Fix method name on comment Signed-off-by: Arthur Neves --- go/vt/vtcombo/tablet_map.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go/vt/vtcombo/tablet_map.go b/go/vt/vtcombo/tablet_map.go index b391db31f07..186fc4586d0 100644 --- a/go/vt/vtcombo/tablet_map.go +++ b/go/vt/vtcombo/tablet_map.go @@ -104,7 +104,7 @@ func createTablet(ctx context.Context, ts *topo.Server, cell string, uid uint32, return nil } -// initTabletMap creates the action agents and associated data structures +// InitTabletMap creates the action agents and associated data structures // for all tablets, based on the vttest proto parameter. func InitTabletMap(ts *topo.Server, tpb *vttestpb.VTTestTopology, mysqld mysqlctl.MysqlDaemon, dbcfgs dbconfigs.DBConfigs, schemaDir string, mycnf *mysqlctl.Mycnf) error { tabletMap = make(map[uint32]*tablet) From 4398d36baf3479d44cfd7a318a655ce5297610a0 Mon Sep 17 00:00:00 2001 From: Arthur Neves Date: Mon, 23 Apr 2018 09:48:15 -0700 Subject: [PATCH 07/41] Expose CreateTablet too Signed-off-by: Arthur Neves --- go/vt/vtcombo/tablet_map.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/go/vt/vtcombo/tablet_map.go b/go/vt/vtcombo/tablet_map.go index 186fc4586d0..9fc9cfa36b4 100644 --- a/go/vt/vtcombo/tablet_map.go +++ b/go/vt/vtcombo/tablet_map.go @@ -71,9 +71,9 @@ type tablet struct { // tabletMap maps the tablet uid to the tablet record var tabletMap map[uint32]*tablet -// createTablet creates an individual tablet, with its agent, and adds +// CreateTablet creates an individual tablet, with its agent, and adds // it to the map. If it's a master tablet, it also issues a TER. -func createTablet(ctx context.Context, ts *topo.Server, cell string, uid uint32, keyspace, shard, dbname string, tabletType topodatapb.TabletType, mysqld mysqlctl.MysqlDaemon, dbcfgs dbconfigs.DBConfigs) error { +func CreateTablet(ctx context.Context, ts *topo.Server, cell string, uid uint32, keyspace, shard, dbname string, tabletType topodatapb.TabletType, mysqld mysqlctl.MysqlDaemon, dbcfgs dbconfigs.DBConfigs) error { alias := &topodatapb.TabletAlias{ Cell: cell, Uid: uid, @@ -183,7 +183,7 @@ func InitTabletMap(ts *topo.Server, tpb *vttestpb.VTTestTopology, mysqld mysqlct replicas-- // create the master - if err := createTablet(ctx, ts, cell, uid, keyspace, shard, dbname, topodatapb.TabletType_MASTER, mysqld, dbcfgs); err != nil { + if err := CreateTablet(ctx, ts, cell, uid, keyspace, shard, dbname, topodatapb.TabletType_MASTER, mysqld, dbcfgs); err != nil { return err } uid++ @@ -191,7 +191,7 @@ func InitTabletMap(ts *topo.Server, tpb *vttestpb.VTTestTopology, mysqld mysqlct for i := 0; i < replicas; i++ { // create a replica slave - if err := createTablet(ctx, ts, cell, uid, keyspace, shard, dbname, topodatapb.TabletType_REPLICA, mysqld, dbcfgs); err != nil { + if err := CreateTablet(ctx, ts, cell, uid, keyspace, shard, dbname, topodatapb.TabletType_REPLICA, mysqld, dbcfgs); err != nil { return err } uid++ @@ -199,7 +199,7 @@ func InitTabletMap(ts *topo.Server, tpb *vttestpb.VTTestTopology, mysqld mysqlct for i := 0; i < rdonlys; i++ { // create a rdonly slave - if err := createTablet(ctx, ts, cell, uid, keyspace, shard, dbname, topodatapb.TabletType_RDONLY, mysqld, dbcfgs); err != nil { + if err := CreateTablet(ctx, ts, cell, uid, keyspace, shard, dbname, topodatapb.TabletType_RDONLY, mysqld, dbcfgs); err != nil { return err } uid++ From 987f0c71b68c178d0852c23dec51261789373f8b Mon Sep 17 00:00:00 2001 From: Harrison McGonigal Date: Mon, 23 Apr 2018 14:18:15 -0400 Subject: [PATCH 08/41] Set orchestrator maintenance mode when demoting a master, and disable it when fixing replication on the old master. Signed-off-by: Harrison McGonigal --- .../vttablet/tabletmanager/rpc_replication.go | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/go/vt/vttablet/tabletmanager/rpc_replication.go b/go/vt/vttablet/tabletmanager/rpc_replication.go index 0dccfe51791..18bc659f22b 100644 --- a/go/vt/vttablet/tabletmanager/rpc_replication.go +++ b/go/vt/vttablet/tabletmanager/rpc_replication.go @@ -287,6 +287,17 @@ func (agent *ActionAgent) DemoteMaster(ctx context.Context) (string, error) { } defer agent.unlock() + // Tell Orchestrator we're stopped on purpose the demotion. + // This is a best effort task, so run it in a goroutine. + go func() { + if agent.orc == nil { + return + } + if err := agent.orc.BeginMaintenance(agent.Tablet(), "vttablet has been told to DemoteMaster"); err != nil { + log.Warningf("Orchestrator BeginMaintenance failed: %v", err) + } + }() + // Set the server read-only. Note all active connections are not // affected. if err := agent.MysqlDaemon.SetReadOnly(true); err != nil { @@ -399,6 +410,21 @@ func (agent *ActionAgent) setMasterLocked(ctx context.Context, parentAlias *topo return err } + // If this tablet used to be a master, end orchestrator maintenance after we are connected to the new master. + // This is a best effort operation, so it should happen in a goroutine + if agent.Tablet().Type == topodatapb.TabletType_MASTER { + defer func() { + go func() { + if agent.orc == nil { + return + } + if err := agent.orc.EndMaintenance(agent.Tablet()); err != nil { + log.Warningf("Orchestrator EndMaintenance failed: %v", err) + } + }() + }() + } + // See if we were replicating at all, and should be replicating wasReplicating := false shouldbeReplicating := false From f241d5429f58fe62ec352b9334f458634f718e61 Mon Sep 17 00:00:00 2001 From: Michael Berlin Date: Mon, 23 Apr 2018 12:46:22 -0700 Subject: [PATCH 09/41] vt/log: Do not use an alias when importing the "glog" package. The alias was "glog" as well and therefore redundant. Signed-off-by: Michael Berlin --- go/vt/log/log.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/go/vt/log/log.go b/go/vt/log/log.go index 2a6b9a3b3a8..4f06ec38cc6 100644 --- a/go/vt/log/log.go +++ b/go/vt/log/log.go @@ -5,9 +5,7 @@ package log -import ( - glog "github.com/golang/glog" -) +import "github.com/golang/glog" // Level is used with V() to test log verbosity. type Level = glog.Level From 35fde4c184769e1a1efddbe728a58f6d8baaa14f Mon Sep 17 00:00:00 2001 From: Michael Demmer Date: Mon, 23 Apr 2018 14:58:17 -0700 Subject: [PATCH 10/41] include the MultiShardAutocommit boolean in the plan json To help debugging whether or not the comment was parsed properly, include the boolean for MultiShardAutocommit in the plan JSON. Signed-off-by: Michael Demmer --- data/test/vtgate/dml_cases.txt | 43 ++++++++++++++++++++++++++++++++++ go/vt/vtgate/engine/delete.go | 30 +++++++++++++----------- go/vt/vtgate/engine/insert.go | 38 ++++++++++++++++-------------- 3 files changed, 79 insertions(+), 32 deletions(-) diff --git a/data/test/vtgate/dml_cases.txt b/data/test/vtgate/dml_cases.txt index 7a7a7e80354..41930d54083 100644 --- a/data/test/vtgate/dml_cases.txt +++ b/data/test/vtgate/dml_cases.txt @@ -921,6 +921,33 @@ } } +# insert with multiple rows - multi-shard autocommit +"insert /*vt+ MULTI_SHARD_AUTOCOMMIT=1 */ into user(id) values (1), (2)" +{ + "Original": "insert /*vt+ MULTI_SHARD_AUTOCOMMIT=1 */ into user(id) values (1), (2)", + "Instructions": { + "Opcode": "InsertSharded", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "Query": "insert /*vt+ MULTI_SHARD_AUTOCOMMIT=1 */ into user(id, Name, Costly) values (:_Id0, :_Name0, :_Costly0), (:_Id1, :_Name1, :_Costly1)", + "Values": [[[":__seq0",":__seq1"]],[[null,null]],[[null,null]]], + "Table": "user", + "Generate": { + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "Query": "select next :n values from seq", + "Values": [1,2] + }, + "Prefix": "insert /*vt+ MULTI_SHARD_AUTOCOMMIT=1 */ into user(id, Name, Costly) values ", + "Mid": ["(:_Id0, :_Name0, :_Costly0)","(:_Id1, :_Name1, :_Costly1)"], + "MultiShardAutocommit": true + } +} + # simple replace unsharded "replace into unsharded values(1, 2)" { @@ -1253,6 +1280,22 @@ } } +# delete from with no index match - multi shard autocommit +"delete /*vt+ MULTI_SHARD_AUTOCOMMIT=1 */ from user_extra where name = 'jose'" +{ + "Original": "delete /*vt+ MULTI_SHARD_AUTOCOMMIT=1 */ from user_extra where name = 'jose'", + "Instructions": { + "Opcode": "DeleteScatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "Query": "delete /*vt+ MULTI_SHARD_AUTOCOMMIT=1 */ from user_extra where name = 'jose'", + "Table": "user_extra", + "MultiShardAutocommit": true + } +} + # delete from with primary id in through IN clause "delete from user_extra where user_id in (1, 2)" { diff --git a/go/vt/vtgate/engine/delete.go b/go/vt/vtgate/engine/delete.go index f682ded7be0..0cf3075b72d 100644 --- a/go/vt/vtgate/engine/delete.go +++ b/go/vt/vtgate/engine/delete.go @@ -76,21 +76,23 @@ func (del *Delete) MarshalJSON() ([]byte, error) { vindexName = del.Vindex.String() } marshalDelete := struct { - Opcode DeleteOpcode - Keyspace *vindexes.Keyspace `json:",omitempty"` - Query string `json:",omitempty"` - Vindex string `json:",omitempty"` - Values []sqltypes.PlanValue `json:",omitempty"` - Table string `json:",omitempty"` - OwnedVindexQuery string `json:",omitempty"` + Opcode DeleteOpcode + Keyspace *vindexes.Keyspace `json:",omitempty"` + Query string `json:",omitempty"` + Vindex string `json:",omitempty"` + Values []sqltypes.PlanValue `json:",omitempty"` + Table string `json:",omitempty"` + OwnedVindexQuery string `json:",omitempty"` + MultiShardAutocommit bool `json:",omitempty"` }{ - Opcode: del.Opcode, - Keyspace: del.Keyspace, - Query: del.Query, - Vindex: vindexName, - Values: del.Values, - Table: tname, - OwnedVindexQuery: del.OwnedVindexQuery, + Opcode: del.Opcode, + Keyspace: del.Keyspace, + Query: del.Query, + Vindex: vindexName, + Values: del.Values, + Table: tname, + OwnedVindexQuery: del.OwnedVindexQuery, + MultiShardAutocommit: del.MultiShardAutocommit, } return jsonutil.MarshalNoEscape(marshalDelete) } diff --git a/go/vt/vtgate/engine/insert.go b/go/vt/vtgate/engine/insert.go index 2ad78c1a9c7..6a6e2d4f014 100644 --- a/go/vt/vtgate/engine/insert.go +++ b/go/vt/vtgate/engine/insert.go @@ -86,25 +86,27 @@ func (ins *Insert) MarshalJSON() ([]byte, error) { tname = ins.Table.Name.String() } marshalInsert := struct { - Opcode InsertOpcode - Keyspace *vindexes.Keyspace `json:",omitempty"` - Query string `json:",omitempty"` - Values []sqltypes.PlanValue `json:",omitempty"` - Table string `json:",omitempty"` - Generate *Generate `json:",omitempty"` - Prefix string `json:",omitempty"` - Mid []string `json:",omitempty"` - Suffix string `json:",omitempty"` + Opcode InsertOpcode + Keyspace *vindexes.Keyspace `json:",omitempty"` + Query string `json:",omitempty"` + Values []sqltypes.PlanValue `json:",omitempty"` + Table string `json:",omitempty"` + Generate *Generate `json:",omitempty"` + Prefix string `json:",omitempty"` + Mid []string `json:",omitempty"` + Suffix string `json:",omitempty"` + MultiShardAutocommit bool `json:",omitempty"` }{ - Opcode: ins.Opcode, - Keyspace: ins.Keyspace, - Query: ins.Query, - Values: ins.VindexValues, - Table: tname, - Generate: ins.Generate, - Prefix: ins.Prefix, - Mid: ins.Mid, - Suffix: ins.Suffix, + Opcode: ins.Opcode, + Keyspace: ins.Keyspace, + Query: ins.Query, + Values: ins.VindexValues, + Table: tname, + Generate: ins.Generate, + Prefix: ins.Prefix, + Mid: ins.Mid, + Suffix: ins.Suffix, + MultiShardAutocommit: ins.MultiShardAutocommit, } return jsonutil.MarshalNoEscape(marshalInsert) } From 17be11d2b70c33dd03bbdfd807b67f73445b33de Mon Sep 17 00:00:00 2001 From: Michael Pawliszyn Date: Thu, 5 Apr 2018 11:59:19 -0400 Subject: [PATCH 11/41] Adds the possibility to vary the template of tablet debug urls. Signed-off-by: Michael Pawliszyn --- go/vt/discovery/healthcheck.go | 61 +++++++++++++++++++++++++++-- go/vt/discovery/healthcheck_test.go | 36 +++++++++++++++++ 2 files changed, 93 insertions(+), 4 deletions(-) diff --git a/go/vt/discovery/healthcheck.go b/go/vt/discovery/healthcheck.go index 440f1d3de06..7fe2edebe2a 100644 --- a/go/vt/discovery/healthcheck.go +++ b/go/vt/discovery/healthcheck.go @@ -39,6 +39,7 @@ package discovery import ( "bytes" "encoding/json" + "flag" "fmt" "html/template" "net/http" @@ -67,6 +68,8 @@ var ( hcErrorCounters = stats.NewCountersWithMultiLabels("HealthcheckErrors", "Healthcheck Errors", []string{"Keyspace", "ShardName", "TabletType"}) hcMasterPromotedCounters = stats.NewCountersWithMultiLabels("HealthcheckMasterPromoted", "Master promoted in keyspace/shard name because of health check errors", []string{"Keyspace", "ShardName"}) healthcheckOnce sync.Once + tabletURLTemplateString = flag.String("tablet_url_template", "http://{{.GetTabletHostPort}}", "format string describing debug tablet url formatting. See the Go code for getTabletDebugURL() how to customize this.") + tabletURLTemplate *template.Template ) // See the documentation for NewHealthCheck below for an explanation of these parameters. @@ -117,6 +120,20 @@ const ( ` ) +func init() { + LoadTabletURLTemplate() +} + +// LoadTabletURLTemplate loads or reloads the URL template. +// Should only be used independently for testing. +func LoadTabletURLTemplate() { + tabletURLTemplate = template.New("") + _, err := tabletURLTemplate.Parse(*tabletURLTemplateString) + if err != nil { + log.Exitf("error parsing template: %v", err) + } +} + // HealthCheckStatsListener is the listener to receive health check stats update. type HealthCheckStatsListener interface { // StatsUpdate is called when: @@ -187,6 +204,44 @@ func (e *TabletStats) DeepEqual(f *TabletStats) bool { (e.LastError != nil && f.LastError != nil && e.LastError.Error() == f.LastError.Error())) } +// GetTabletHostPort formats a tablet host port address. +func (e TabletStats) GetTabletHostPort() string { + vtPort := e.Tablet.PortMap["vt"] + return netutil.JoinHostPort(e.Tablet.Hostname, vtPort) +} + +// GetHostNameLevel returns the specified hostname level. If the level does not exist it will pick the closest level. +// This seems unused but can be utilized by certain url formatting templates. See getTabletDebugURL for more details. +func (e TabletStats) GetHostNameLevel(level int) string { + chunkedHostname := strings.Split(e.Tablet.Hostname, ".") + + if level < 0 { + return chunkedHostname[0] + } else if level >= len(chunkedHostname) { + return chunkedHostname[len(chunkedHostname)-1] + } else { + return chunkedHostname[level] + } +} + +// getTabletDebugURL formats a debug url to the tablet. +// It uses a format string that can be passed into the app to format +// the debug URL to accommodate different network setups. It applies +// the html/template string defined to a TabletStats object. The +// format string can refer to members and functions of TabletStats +// like a regular html/template string. +// +// For instance given a tablet with hostname:port of host.dc.domain:22 +// could be configured as follows: +// http://{{.GetTabletHostPort}} -> http://host.dc.domain:22 +// https://{{.Tablet.Hostname}} -> https://host.dc.domain +// https://{{.GetHostNameLevel 0}}.bastion.corp -> https://host.bastion.corp +func (e TabletStats) getTabletDebugURL() string { + var buffer bytes.Buffer + tabletURLTemplate.Execute(&buffer, e) + return buffer.String() +} + // HealthCheck defines the interface of health checking module. // The goal of this object is to maintain a StreamHealth RPC // to a lot of tablets. Tablets are added / removed by calling the @@ -737,7 +792,6 @@ func (tcs *TabletsCacheStatus) StatusAsHTML() template.HTML { sort.Sort(tcs.TabletsStats) } for _, ts := range tcs.TabletsStats { - vtPort := ts.Tablet.PortMap["vt"] color := "green" extra := "" if ts.LastError != nil { @@ -755,11 +809,10 @@ func (tcs *TabletsCacheStatus) StatusAsHTML() template.HTML { extra = fmt.Sprintf(" (RepLag: %v)", ts.Stats.SecondsBehindMaster) } name := ts.Name - addr := netutil.JoinHostPort(ts.Tablet.Hostname, vtPort) if name == "" { - name = addr + name = ts.GetTabletHostPort() } - tLinks = append(tLinks, fmt.Sprintf(`%v%v`, addr, color, name, extra)) + tLinks = append(tLinks, fmt.Sprintf(`%v%v`, ts.getTabletDebugURL(), color, name, extra)) } return template.HTML(strings.Join(tLinks, "
")) } diff --git a/go/vt/discovery/healthcheck_test.go b/go/vt/discovery/healthcheck_test.go index 637d8445a81..dac000635b3 100644 --- a/go/vt/discovery/healthcheck_test.go +++ b/go/vt/discovery/healthcheck_test.go @@ -573,6 +573,42 @@ func TestTemplate(t *testing.T) { } } +func TestDebugURLFormatting(t *testing.T) { + flag.Set("tablet_url_template", "https://{{.GetHostNameLevel 0}}.bastion.{{.Tablet.Alias.Cell}}.corp") + LoadTabletURLTemplate() + + tablet := topo.NewTablet(0, "cell", "host.dc.domain") + ts := []*TabletStats{ + { + Key: "a", + Tablet: tablet, + Target: &querypb.Target{Keyspace: "k", Shard: "s", TabletType: topodatapb.TabletType_REPLICA}, + Up: true, + Serving: false, + Stats: &querypb.RealtimeStats{SecondsBehindMaster: 1, CpuUsage: 0.3}, + TabletExternallyReparentedTimestamp: 0, + }, + } + tcs := &TabletsCacheStatus{ + Cell: "cell", + Target: &querypb.Target{Keyspace: "k", Shard: "s", TabletType: topodatapb.TabletType_REPLICA}, + TabletsStats: ts, + } + templ := template.New("").Funcs(status.StatusFuncs) + templ, err := templ.Parse(HealthCheckTemplate) + if err != nil { + t.Fatalf("error parsing template: %v", err) + } + wr := &bytes.Buffer{} + if err := templ.Execute(wr, []*TabletsCacheStatus{tcs}); err != nil { + t.Fatalf("error executing template: %v", err) + } + expectedURL := "https://host.bastion.cell.corp" + if !strings.Contains(wr.String(), expectedURL) { + t.Fatalf("output missing formatted URL, expectedURL: %s , output: %s", expectedURL, wr.String()) + } +} + type listener struct { output chan *TabletStats } From 0d373f4e930bb66ac93633eebd3a9bab19c0ec7c Mon Sep 17 00:00:00 2001 From: Michael Berlin Date: Wed, 25 Apr 2018 10:07:32 -0700 Subject: [PATCH 12/41] vt/discovery: Fix import groups in healthcheck files. Signed-off-by: Michael Berlin --- go/vt/discovery/healthcheck.go | 3 +-- go/vt/discovery/healthcheck_test.go | 5 ++--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/go/vt/discovery/healthcheck.go b/go/vt/discovery/healthcheck.go index 7fe2edebe2a..e7cac724ebf 100644 --- a/go/vt/discovery/healthcheck.go +++ b/go/vt/discovery/healthcheck.go @@ -48,9 +48,8 @@ import ( "sync" "time" - "golang.org/x/net/context" - "github.com/golang/protobuf/proto" + "golang.org/x/net/context" "vitess.io/vitess/go/netutil" "vitess.io/vitess/go/stats" "vitess.io/vitess/go/vt/grpcclient" diff --git a/go/vt/discovery/healthcheck_test.go b/go/vt/discovery/healthcheck_test.go index dac000635b3..bcff21f7dae 100644 --- a/go/vt/discovery/healthcheck_test.go +++ b/go/vt/discovery/healthcheck_test.go @@ -23,6 +23,8 @@ import ( "html/template" "io" "reflect" + "strings" + "sync" "testing" "time" @@ -35,9 +37,6 @@ import ( "vitess.io/vitess/go/vt/vttablet/queryservice/fakes" "vitess.io/vitess/go/vt/vttablet/tabletconn" - "strings" - "sync" - querypb "vitess.io/vitess/go/vt/proto/query" topodatapb "vitess.io/vitess/go/vt/proto/topodata" ) From a990225feec67779efe40deb990a17949642bb10 Mon Sep 17 00:00:00 2001 From: Michael Berlin Date: Wed, 25 Apr 2018 10:08:29 -0700 Subject: [PATCH 13/41] vt/discovery: Do not export LoadTabletURLTemplate. It is only used for tests in the same package. Signed-off-by: Michael Berlin --- go/vt/discovery/healthcheck.go | 6 +++--- go/vt/discovery/healthcheck_test.go | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/go/vt/discovery/healthcheck.go b/go/vt/discovery/healthcheck.go index e7cac724ebf..27612dd5675 100644 --- a/go/vt/discovery/healthcheck.go +++ b/go/vt/discovery/healthcheck.go @@ -120,12 +120,12 @@ const ( ) func init() { - LoadTabletURLTemplate() + loadTabletURLTemplate() } -// LoadTabletURLTemplate loads or reloads the URL template. +// loadTabletURLTemplate loads or reloads the URL template. // Should only be used independently for testing. -func LoadTabletURLTemplate() { +func loadTabletURLTemplate() { tabletURLTemplate = template.New("") _, err := tabletURLTemplate.Parse(*tabletURLTemplateString) if err != nil { diff --git a/go/vt/discovery/healthcheck_test.go b/go/vt/discovery/healthcheck_test.go index bcff21f7dae..cddc3cdc135 100644 --- a/go/vt/discovery/healthcheck_test.go +++ b/go/vt/discovery/healthcheck_test.go @@ -574,7 +574,7 @@ func TestTemplate(t *testing.T) { func TestDebugURLFormatting(t *testing.T) { flag.Set("tablet_url_template", "https://{{.GetHostNameLevel 0}}.bastion.{{.Tablet.Alias.Cell}}.corp") - LoadTabletURLTemplate() + loadTabletURLTemplate() tablet := topo.NewTablet(0, "cell", "host.dc.domain") ts := []*TabletStats{ From 9dd560d3ecd82648b3fafa7b1ca15e46acc03bdb Mon Sep 17 00:00:00 2001 From: Michael Berlin Date: Wed, 25 Apr 2018 10:10:02 -0700 Subject: [PATCH 14/41] vt/discovery: Check for quotes in template output as well. This way we avoid that a partial match would be a success as well. Signed-off-by: Michael Berlin --- go/vt/discovery/healthcheck_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go/vt/discovery/healthcheck_test.go b/go/vt/discovery/healthcheck_test.go index cddc3cdc135..1e6086da33f 100644 --- a/go/vt/discovery/healthcheck_test.go +++ b/go/vt/discovery/healthcheck_test.go @@ -602,7 +602,7 @@ func TestDebugURLFormatting(t *testing.T) { if err := templ.Execute(wr, []*TabletsCacheStatus{tcs}); err != nil { t.Fatalf("error executing template: %v", err) } - expectedURL := "https://host.bastion.cell.corp" + expectedURL := `"https://host.bastion.cell.corp"` if !strings.Contains(wr.String(), expectedURL) { t.Fatalf("output missing formatted URL, expectedURL: %s , output: %s", expectedURL, wr.String()) } From a535c6b328bf3fef31dbf48491b4f9287fd41a94 Mon Sep 17 00:00:00 2001 From: Michael Berlin Date: Fri, 27 Apr 2018 16:04:56 -0700 Subject: [PATCH 15/41] stats: Move Counter* and Gauge* types into new file counter.go. Move Duration* types into duration.go. This is a mere move of code and no change in functionality. By splitting out the code, I hope it will be easier to maintain it. Signed-off-by: Michael Berlin --- go/stats/counter.go | 168 ++++++++++++++++++++++++++++++++++++++ go/stats/counter_test.go | 73 +++++++++++++++++ go/stats/counters.go | 148 --------------------------------- go/stats/duration.go | 70 ++++++++++++++++ go/stats/duration_test.go | 75 +++++++++++++++++ go/stats/export.go | 47 ----------- go/stats/export_test.go | 106 ------------------------ 7 files changed, 386 insertions(+), 301 deletions(-) create mode 100644 go/stats/counter.go create mode 100644 go/stats/counter_test.go create mode 100644 go/stats/duration.go create mode 100644 go/stats/duration_test.go diff --git a/go/stats/counter.go b/go/stats/counter.go new file mode 100644 index 00000000000..06244eed99e --- /dev/null +++ b/go/stats/counter.go @@ -0,0 +1,168 @@ +/* +Copyright 2018 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 stats + +import ( + "strconv" + "time" + + "vitess.io/vitess/go/sync2" + "vitess.io/vitess/go/vt/logutil" +) + +// logCounterNegative is for throttling adding a negative value to a counter messages in logs +var logCounterNegative = logutil.NewThrottledLogger("StatsCounterNegative", 1*time.Minute) + +// Counter is expvar.Int+Get+hook +type Counter struct { + i sync2.AtomicInt64 + help string +} + +// NewCounter returns a new Counter +func NewCounter(name string, help string) *Counter { + v := &Counter{help: help} + if name != "" { + publish(name, v) + } + return v +} + +// Add adds the provided value to the Counter +func (v *Counter) Add(delta int64) { + if delta < 0 { + logCounterNegative.Warningf("Adding a negative value to a counter, %v should be a gauge instead", v) + } + v.i.Add(delta) +} + +// Reset resets the counter value to 0 +func (v *Counter) Reset() { + v.i.Set(int64(0)) +} + +// Get returns the value +func (v *Counter) Get() int64 { + return v.i.Get() +} + +// String is the implementation of expvar.var +func (v *Counter) String() string { + return strconv.FormatInt(v.i.Get(), 10) +} + +// Help returns the help string +func (v *Counter) Help() string { + return v.help +} + +// CounterFunc converts a function that returns +// an int64 as an expvar. +// For implementations that differentiate between Counters/Gauges, +// CounterFunc's values only go up (or are reset to 0) +type CounterFunc struct { + Mf MetricFunc + help string +} + +// NewCounterFunc creates a new CounterFunc instance and publishes it if name is set +func NewCounterFunc(name string, help string, Mf MetricFunc) *CounterFunc { + c := &CounterFunc{ + Mf: Mf, + help: help, + } + + if name != "" { + publish(name, c) + } + return c +} + +// Help returns the help string +func (cf *CounterFunc) Help() string { + return cf.help +} + +// String implements expvar.Var +func (cf *CounterFunc) String() string { + return cf.Mf.String() +} + +// MetricFunc defines an interface for things that can be exported with calls to stats.CounterFunc/stats.GaugeFunc +type MetricFunc interface { + FloatVal() float64 + String() string +} + +// IntFunc converst a function that returns an int64 as both an expvar and a MetricFunc +type IntFunc func() int64 + +// FloatVal is the implementation of MetricFunc +func (f IntFunc) FloatVal() float64 { + return float64(f()) +} + +// String is the implementation of expvar.var +func (f IntFunc) String() string { + return strconv.FormatInt(f(), 10) +} + +// Gauge is an unlabeled metric whose values can go up/down. +type Gauge struct { + Counter +} + +// NewGauge creates a new Gauge and publishes it if name is set +func NewGauge(name string, help string) *Gauge { + v := &Gauge{Counter: Counter{help: help}} + + if name != "" { + publish(name, v) + } + return v +} + +// Set sets the value +func (v *Gauge) Set(value int64) { + v.Counter.i.Set(value) +} + +// Add adds the provided value to the Gauge +func (v *Gauge) Add(delta int64) { + v.Counter.i.Add(delta) +} + +// GaugeFunc converts a function that returns an int64 as an expvar. +// It's a wrapper around CounterFunc for values that go up/down +// for implementations (like Prometheus) that need to differ between Counters and Gauges. +type GaugeFunc struct { + CounterFunc +} + +// NewGaugeFunc creates a new GaugeFunc instance and publishes it if name is set +func NewGaugeFunc(name string, help string, Mf MetricFunc) *GaugeFunc { + i := &GaugeFunc{ + CounterFunc: CounterFunc{ + Mf: Mf, + help: help, + }} + + if name != "" { + publish(name, i) + } + return i +} diff --git a/go/stats/counter_test.go b/go/stats/counter_test.go new file mode 100644 index 00000000000..3e99f07343d --- /dev/null +++ b/go/stats/counter_test.go @@ -0,0 +1,73 @@ +/* +Copyright 2018 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 stats + +import ( + "expvar" + "testing" +) + +func TestCounter(t *testing.T) { + var gotname string + var gotv *Counter + clear() + Register(func(name string, v expvar.Var) { + gotname = name + gotv = v.(*Counter) + }) + v := NewCounter("Int", "help") + if gotname != "Int" { + t.Errorf("want Int, got %s", gotname) + } + if gotv != v { + t.Errorf("want %#v, got %#v", v, gotv) + } + v.Add(1) + if v.Get() != 1 { + t.Errorf("want 1, got %v", v.Get()) + } + if v.String() != "1" { + t.Errorf("want 1, got %v", v.Get()) + } + v.Reset() + if v.Get() != 0 { + t.Errorf("want 0, got %v", v.Get()) + } +} + +func TestGaugeFunc(t *testing.T) { + var gotname string + var gotv *GaugeFunc + clear() + Register(func(name string, v expvar.Var) { + gotname = name + gotv = v.(*GaugeFunc) + }) + + v := NewGaugeFunc("name", "help", IntFunc(func() int64 { + return 1 + })) + if v.String() != "1" { + t.Errorf("want 1, got %f", v.String()) + } + if gotv != v { + t.Errorf("want %#v, got %#v", v, gotv) + } + if gotname != "name" { + t.Errorf("want name, got %s", gotname) + } +} diff --git a/go/stats/counters.go b/go/stats/counters.go index d71f01fbe8b..57ce7200c2e 100644 --- a/go/stats/counters.go +++ b/go/stats/counters.go @@ -19,87 +19,11 @@ package stats import ( "bytes" "fmt" - "strconv" "strings" "sync" "sync/atomic" - "time" - - "vitess.io/vitess/go/sync2" - "vitess.io/vitess/go/vt/logutil" ) -// logCounterNegative is for throttling adding a negative value to a counter messages in logs -var logCounterNegative = logutil.NewThrottledLogger("StatsCounterNegative", 1*time.Minute) - -// Counter is expvar.Int+Get+hook -type Counter struct { - i sync2.AtomicInt64 - help string -} - -// NewCounter returns a new Counter -func NewCounter(name string, help string) *Counter { - v := &Counter{help: help} - if name != "" { - publish(name, v) - } - return v -} - -// Add adds the provided value to the Counter -func (v *Counter) Add(delta int64) { - if delta < 0 { - logCounterNegative.Warningf("Adding a negative value to a counter, %v should be a gauge instead", v) - } - v.i.Add(delta) -} - -// Reset resets the counter value to 0 -func (v *Counter) Reset() { - v.i.Set(int64(0)) -} - -// Get returns the value -func (v *Counter) Get() int64 { - return v.i.Get() -} - -// String is the implementation of expvar.var -func (v *Counter) String() string { - return strconv.FormatInt(v.i.Get(), 10) -} - -// Help returns the help string -func (v *Counter) Help() string { - return v.help -} - -// Gauge is an unlabeled metric whose values can go up/down. -type Gauge struct { - Counter -} - -// NewGauge creates a new Gauge and publishes it if name is set -func NewGauge(name string, help string) *Gauge { - v := &Gauge{Counter: Counter{help: help}} - - if name != "" { - publish(name, v) - } - return v -} - -// Set sets the value -func (v *Gauge) Set(value int64) { - v.Counter.i.Set(value) -} - -// Add adds the provided value to the Gauge -func (v *Gauge) Add(delta int64) { - v.Counter.i.Add(delta) -} - // counters is similar to expvar.Map, except that // it doesn't allow floats. It is used to build CountersWithLabels and GaugesWithLabels. type counters struct { @@ -265,78 +189,6 @@ func (g *GaugesWithLabels) Add(name string, value int64) { atomic.AddInt64(a, value) } -// CounterFunc converts a function that returns -// an int64 as an expvar. -// For implementations that differentiate between Counters/Gauges, -// CounterFunc's values only go up (or are reset to 0) -type CounterFunc struct { - Mf MetricFunc - help string -} - -// NewCounterFunc creates a new CounterFunc instance and publishes it if name is set -func NewCounterFunc(name string, help string, Mf MetricFunc) *CounterFunc { - c := &CounterFunc{ - Mf: Mf, - help: help, - } - - if name != "" { - publish(name, c) - } - return c -} - -// Help returns the help string -func (cf *CounterFunc) Help() string { - return cf.help -} - -// String implements expvar.Var -func (cf *CounterFunc) String() string { - return cf.Mf.String() -} - -// MetricFunc defines an interface for things that can be exported with calls to stats.CounterFunc/stats.GaugeFunc -type MetricFunc interface { - FloatVal() float64 - String() string -} - -// IntFunc converst a function that returns an int64 as both an expvar and a MetricFunc -type IntFunc func() int64 - -// FloatVal is the implementation of MetricFunc -func (f IntFunc) FloatVal() float64 { - return float64(f()) -} - -// String is the implementation of expvar.var -func (f IntFunc) String() string { - return strconv.FormatInt(f(), 10) -} - -// GaugeFunc converts a function that returns an int64 as an expvar. -// It's a wrapper around CounterFunc for values that go up/down -// for implementations (like Prometheus) that need to differ between Counters and Gauges. -type GaugeFunc struct { - CounterFunc -} - -// NewGaugeFunc creates a new GaugeFunc instance and publishes it if name is set -func NewGaugeFunc(name string, help string, Mf MetricFunc) *GaugeFunc { - i := &GaugeFunc{ - CounterFunc: CounterFunc{ - Mf: Mf, - help: help, - }} - - if name != "" { - publish(name, i) - } - return i -} - // CountersFunc converts a function that returns // a map of int64 as an expvar. type CountersFunc func() map[string]int64 diff --git a/go/stats/duration.go b/go/stats/duration.go new file mode 100644 index 00000000000..710ff20195d --- /dev/null +++ b/go/stats/duration.go @@ -0,0 +1,70 @@ +/* +Copyright 2018 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 stats + +import ( + "strconv" + "time" + + "vitess.io/vitess/go/sync2" +) + +// Duration exports a time.Duration +type Duration struct { + i sync2.AtomicDuration +} + +// NewDuration returns a new Duration +func NewDuration(name string) *Duration { + v := new(Duration) + publish(name, v) + return v +} + +// Add adds the provided value to the Duration +func (v *Duration) Add(delta time.Duration) { + v.i.Add(delta) +} + +// Set sets the value +func (v *Duration) Set(value time.Duration) { + v.i.Set(value) +} + +// Get returns the value +func (v *Duration) Get() time.Duration { + return v.i.Get() +} + +// String is the implementation of expvar.var +func (v *Duration) String() string { + return strconv.FormatInt(int64(v.i.Get()), 10) +} + +// DurationFunc converts a function that returns +// an time.Duration as an expvar. +type DurationFunc func() time.Duration + +// String is the implementation of expvar.var +func (f DurationFunc) String() string { + return strconv.FormatInt(int64(f()), 10) +} + +// FloatVal is the implementation of MetricFunc +func (f DurationFunc) FloatVal() float64 { + return f().Seconds() +} diff --git a/go/stats/duration_test.go b/go/stats/duration_test.go new file mode 100644 index 00000000000..d28281687bc --- /dev/null +++ b/go/stats/duration_test.go @@ -0,0 +1,75 @@ +/* +Copyright 2018 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 stats + +import ( + "expvar" + "testing" + "time" +) + +func TestDuration(t *testing.T) { + var gotname string + var gotv *Duration + clear() + Register(func(name string, v expvar.Var) { + gotname = name + gotv = v.(*Duration) + }) + v := NewDuration("Duration") + if gotname != "Duration" { + t.Errorf("want Duration, got %s", gotname) + } + if gotv != v { + t.Errorf("want %#v, got %#v", v, gotv) + } + v.Set(time.Duration(5)) + if v.Get() != 5 { + t.Errorf("want 5, got %v", v.Get()) + } + v.Add(time.Duration(1)) + if v.Get() != 6 { + t.Errorf("want 6, got %v", v.Get()) + } + if v.String() != "6" { + t.Errorf("want 6, got %v", v.Get()) + } +} + +func TestDurationFunc(t *testing.T) { + var gotname string + var gotv *CounterFunc + clear() + Register(func(name string, v expvar.Var) { + gotname = name + gotv = v.(*CounterFunc) + }) + + v := NewCounterFunc("duration", "help", DurationFunc(func() time.Duration { + return time.Duration(1) + })) + + if gotv != v { + t.Errorf("want %#v, got %#v", v, gotv) + } + if v.String() != "1" { + t.Errorf("want 1, got %v", v.String()) + } + if gotname != "duration" { + t.Errorf("want duration, got %s", gotname) + } +} diff --git a/go/stats/export.go b/go/stats/export.go index ffd5d51759c..626d8a3e1f7 100644 --- a/go/stats/export.go +++ b/go/stats/export.go @@ -36,7 +36,6 @@ import ( "sync" "time" - "vitess.io/vitess/go/sync2" "vitess.io/vitess/go/vt/log" ) @@ -196,52 +195,6 @@ func (f FloatFunc) String() string { return strconv.FormatFloat(f(), 'g', -1, 64) } -// Duration exports a time.Duration -type Duration struct { - i sync2.AtomicDuration -} - -// NewDuration returns a new Duration -func NewDuration(name string) *Duration { - v := new(Duration) - publish(name, v) - return v -} - -// Add adds the provided value to the Duration -func (v *Duration) Add(delta time.Duration) { - v.i.Add(delta) -} - -// Set sets the value -func (v *Duration) Set(value time.Duration) { - v.i.Set(value) -} - -// Get returns the value -func (v *Duration) Get() time.Duration { - return v.i.Get() -} - -// String is the implementation of expvar.var -func (v *Duration) String() string { - return strconv.FormatInt(int64(v.i.Get()), 10) -} - -// DurationFunc converts a function that returns -// an time.Duration as an expvar. -type DurationFunc func() time.Duration - -// String is the implementation of expvar.var -func (f DurationFunc) String() string { - return strconv.FormatInt(int64(f()), 10) -} - -// FloatVal is the implementation of MetricFunc -func (f DurationFunc) FloatVal() float64 { - return f().Seconds() -} - // String is expvar.String+Get+hook type String struct { mu sync.Mutex diff --git a/go/stats/export_test.go b/go/stats/export_test.go index b95db711fa7..32d71057c40 100644 --- a/go/stats/export_test.go +++ b/go/stats/export_test.go @@ -19,7 +19,6 @@ package stats import ( "expvar" "testing" - "time" ) func clear() { @@ -71,111 +70,6 @@ func TestFloat(t *testing.T) { } } -func TestCounter(t *testing.T) { - var gotname string - var gotv *Counter - clear() - Register(func(name string, v expvar.Var) { - gotname = name - gotv = v.(*Counter) - }) - v := NewCounter("Int", "help") - if gotname != "Int" { - t.Errorf("want Int, got %s", gotname) - } - if gotv != v { - t.Errorf("want %#v, got %#v", v, gotv) - } - v.Add(1) - if v.Get() != 1 { - t.Errorf("want 1, got %v", v.Get()) - } - if v.String() != "1" { - t.Errorf("want 1, got %v", v.Get()) - } - v.Reset() - if v.Get() != 0 { - t.Errorf("want 0, got %v", v.Get()) - } - -} - -func TestGaugeFunc(t *testing.T) { - var gotname string - var gotv *GaugeFunc - clear() - Register(func(name string, v expvar.Var) { - gotname = name - gotv = v.(*GaugeFunc) - }) - - v := NewGaugeFunc("name", "help", IntFunc(func() int64 { - return 1 - })) - if v.String() != "1" { - t.Errorf("want 1, got %f", v.String()) - } - if gotv != v { - t.Errorf("want %#v, got %#v", v, gotv) - } - if gotname != "name" { - t.Errorf("want name, got %s", gotname) - } -} - -func TestDuration(t *testing.T) { - var gotname string - var gotv *Duration - clear() - Register(func(name string, v expvar.Var) { - gotname = name - gotv = v.(*Duration) - }) - v := NewDuration("Duration") - if gotname != "Duration" { - t.Errorf("want Duration, got %s", gotname) - } - if gotv != v { - t.Errorf("want %#v, got %#v", v, gotv) - } - v.Set(time.Duration(5)) - if v.Get() != 5 { - t.Errorf("want 5, got %v", v.Get()) - } - v.Add(time.Duration(1)) - if v.Get() != 6 { - t.Errorf("want 6, got %v", v.Get()) - } - if v.String() != "6" { - t.Errorf("want 6, got %v", v.Get()) - } - -} - -func TestDurationFunc(t *testing.T) { - var gotname string - var gotv *CounterFunc - clear() - Register(func(name string, v expvar.Var) { - gotname = name - gotv = v.(*CounterFunc) - }) - - v := NewCounterFunc("duration", "help", DurationFunc(func() time.Duration { - return time.Duration(1) - })) - - if gotv != v { - t.Errorf("want %#v, got %#v", v, gotv) - } - if v.String() != "1" { - t.Errorf("want 1, got %v", v.String()) - } - if gotname != "duration" { - t.Errorf("want duration, got %s", gotname) - } -} - func TestString(t *testing.T) { var gotname string var gotv *String From cac79493f2593753ddd86e5f216ef765526ec36b Mon Sep 17 00:00:00 2001 From: Michael Berlin Date: Fri, 27 Apr 2018 17:37:33 -0700 Subject: [PATCH 16/41] stats: Simplify code for single-value stat variables. https://github.com/vitessio/vitess/pull/3784 introduced two layers of code for "stats.Counter" (and the new type "stats.Gauge"). As a consequence, it was for example possible to create a "stats.Gauge" for a time.Duration value. This approach did not work well with our internal usage of the stats package. Therefore, I reversed this and simplified the code: - MetricFunc() interface was removed. Instead, a CountFunc or a GaugeFunc requires a simple func() int64 as input. - IntFunc() removed. Before https://github.com/vitessio/vitess/pull/3784, it was used to implement the expvar.Var interface. But now, this is taken care of by the types itself e.g "stats.CounterFunc". Therefore, we do not need it anymore and users of the "stats" package can just pass a plain func() int64. - Added types "Duration" and "DurationFunc" back. - Added "Variable" interface. This allowed to simplify the Prometheus code which depends on the Help() method for each stats variable. - Prometheus: Conversion to float64 values is now done in prometheusbackend.go and removed from the stats package. BUG=78571948 Signed-off-by: Michael Berlin --- go/stats/counter.go | 63 +++++++------------ go/stats/counter_test.go | 4 +- go/stats/duration.go | 56 ++++++++++++----- go/stats/duration_test.go | 10 +-- go/stats/prometheusbackend/collectors.go | 33 +++------- .../prometheusbackend/prometheusbackend.go | 35 +++++------ .../prometheusbackend_test.go | 25 ++++++-- go/stats/variable_interface.go | 29 +++++++++ go/vt/dbconnpool/connection_pool.go | 18 +++--- go/vt/vtgate/executor.go | 8 +-- .../vttablet/tabletmanager/binlog_players.go | 8 +-- go/vt/vttablet/tabletserver/connpool/pool.go | 18 +++--- go/vt/vttablet/tabletserver/query_engine.go | 22 +++---- .../tabletserver/replication_watcher.go | 4 +- go/vt/vttablet/tabletserver/schema/engine.go | 2 +- go/vt/vttablet/tabletserver/tabletserver.go | 10 +-- go/vt/vttablet/tabletserver/tx_pool.go | 4 +- 17 files changed, 190 insertions(+), 159 deletions(-) create mode 100644 go/stats/variable_interface.go diff --git a/go/stats/counter.go b/go/stats/counter.go index 06244eed99e..772f1d9d1e1 100644 --- a/go/stats/counter.go +++ b/go/stats/counter.go @@ -70,19 +70,19 @@ func (v *Counter) Help() string { return v.help } -// CounterFunc converts a function that returns -// an int64 as an expvar. +// CounterFunc allows to provide the counter value via a custom function. // For implementations that differentiate between Counters/Gauges, -// CounterFunc's values only go up (or are reset to 0) +// CounterFunc's values only go up (or are reset to 0). type CounterFunc struct { - Mf MetricFunc + F func() int64 help string } -// NewCounterFunc creates a new CounterFunc instance and publishes it if name is set -func NewCounterFunc(name string, help string, Mf MetricFunc) *CounterFunc { +// NewCounterFunc creates a new CounterFunc instance and publishes it if name is +// set. +func NewCounterFunc(name string, help string, f func() int64) *CounterFunc { c := &CounterFunc{ - Mf: Mf, + F: f, help: help, } @@ -92,33 +92,14 @@ func NewCounterFunc(name string, help string, Mf MetricFunc) *CounterFunc { return c } -// Help returns the help string -func (cf *CounterFunc) Help() string { +// Help returns the help string. +func (cf CounterFunc) Help() string { return cf.help } -// String implements expvar.Var -func (cf *CounterFunc) String() string { - return cf.Mf.String() -} - -// MetricFunc defines an interface for things that can be exported with calls to stats.CounterFunc/stats.GaugeFunc -type MetricFunc interface { - FloatVal() float64 - String() string -} - -// IntFunc converst a function that returns an int64 as both an expvar and a MetricFunc -type IntFunc func() int64 - -// FloatVal is the implementation of MetricFunc -func (f IntFunc) FloatVal() float64 { - return float64(f()) -} - -// String is the implementation of expvar.var -func (f IntFunc) String() string { - return strconv.FormatInt(f(), 10) +// String implements expvar.Var. +func (cf CounterFunc) String() string { + return strconv.FormatInt(cf.F(), 10) } // Gauge is an unlabeled metric whose values can go up/down. @@ -126,7 +107,7 @@ type Gauge struct { Counter } -// NewGauge creates a new Gauge and publishes it if name is set +// NewGauge creates a new Gauge and publishes it if name is set. func NewGauge(name string, help string) *Gauge { v := &Gauge{Counter: Counter{help: help}} @@ -136,28 +117,30 @@ func NewGauge(name string, help string) *Gauge { return v } -// Set sets the value +// Set overwrites the current value. func (v *Gauge) Set(value int64) { v.Counter.i.Set(value) } -// Add adds the provided value to the Gauge +// Add adds the provided value to the Gauge. func (v *Gauge) Add(delta int64) { v.Counter.i.Add(delta) } -// GaugeFunc converts a function that returns an int64 as an expvar. -// It's a wrapper around CounterFunc for values that go up/down -// for implementations (like Prometheus) that need to differ between Counters and Gauges. +// GaugeFunc is the same as CounterFunc but meant for gauges. +// It's a wrapper around CounterFunc for values that go up/down for +// implementations (like Prometheus) that need to differ between Counters and +// Gauges. type GaugeFunc struct { CounterFunc } -// NewGaugeFunc creates a new GaugeFunc instance and publishes it if name is set -func NewGaugeFunc(name string, help string, Mf MetricFunc) *GaugeFunc { +// NewGaugeFunc creates a new GaugeFunc instance and publishes it if name is +// set. +func NewGaugeFunc(name string, help string, f func() int64) *GaugeFunc { i := &GaugeFunc{ CounterFunc: CounterFunc{ - Mf: Mf, + F: f, help: help, }} diff --git a/go/stats/counter_test.go b/go/stats/counter_test.go index 3e99f07343d..bc2dbd17181 100644 --- a/go/stats/counter_test.go +++ b/go/stats/counter_test.go @@ -58,9 +58,9 @@ func TestGaugeFunc(t *testing.T) { gotv = v.(*GaugeFunc) }) - v := NewGaugeFunc("name", "help", IntFunc(func() int64 { + v := NewGaugeFunc("name", "help", func() int64 { return 1 - })) + }) if v.String() != "1" { t.Errorf("want 1, got %f", v.String()) } diff --git a/go/stats/duration.go b/go/stats/duration.go index 710ff20195d..d537bc7f52c 100644 --- a/go/stats/duration.go +++ b/go/stats/duration.go @@ -25,16 +25,29 @@ import ( // Duration exports a time.Duration type Duration struct { - i sync2.AtomicDuration + i sync2.AtomicDuration + help string } -// NewDuration returns a new Duration -func NewDuration(name string) *Duration { - v := new(Duration) +// NewDuration returns a new Duration. +func NewDuration(name, help string) *Duration { + v := &Duration{ + help: help, + } publish(name, v) return v } +// Help implements the Variable interface. +func (v Duration) Help() string { + return v.help +} + +// String is the implementation of expvar.var. +func (v Duration) String() string { + return strconv.FormatInt(int64(v.i.Get()), 10) +} + // Add adds the provided value to the Duration func (v *Duration) Add(delta time.Duration) { v.i.Add(delta) @@ -50,21 +63,32 @@ func (v *Duration) Get() time.Duration { return v.i.Get() } -// String is the implementation of expvar.var -func (v *Duration) String() string { - return strconv.FormatInt(int64(v.i.Get()), 10) +// DurationFunc allows to provide the value via a custom function. +type DurationFunc struct { + F func() time.Duration + help string } -// DurationFunc converts a function that returns -// an time.Duration as an expvar. -type DurationFunc func() time.Duration +// NewDurationFunc creates a new DurationFunc instance and publishes it if name +// is set. +func NewDurationFunc(name string, help string, f func() time.Duration) *DurationFunc { + df := &DurationFunc{ + F: f, + help: help, + } + + if name != "" { + publish(name, df) + } + return df +} -// String is the implementation of expvar.var -func (f DurationFunc) String() string { - return strconv.FormatInt(int64(f()), 10) +// Help implements the Variable interface. +func (df DurationFunc) Help() string { + return df.help } -// FloatVal is the implementation of MetricFunc -func (f DurationFunc) FloatVal() float64 { - return f().Seconds() +// String is the implementation of expvar.var. +func (df DurationFunc) String() string { + return strconv.FormatInt(int64(df.F()), 10) } diff --git a/go/stats/duration_test.go b/go/stats/duration_test.go index d28281687bc..f463d911e6e 100644 --- a/go/stats/duration_test.go +++ b/go/stats/duration_test.go @@ -30,7 +30,7 @@ func TestDuration(t *testing.T) { gotname = name gotv = v.(*Duration) }) - v := NewDuration("Duration") + v := NewDuration("Duration", "help") if gotname != "Duration" { t.Errorf("want Duration, got %s", gotname) } @@ -52,16 +52,16 @@ func TestDuration(t *testing.T) { func TestDurationFunc(t *testing.T) { var gotname string - var gotv *CounterFunc + var gotv *DurationFunc clear() Register(func(name string, v expvar.Var) { gotname = name - gotv = v.(*CounterFunc) + gotv = v.(*DurationFunc) }) - v := NewCounterFunc("duration", "help", DurationFunc(func() time.Duration { + v := NewDurationFunc("duration", "help", func() time.Duration { return time.Duration(1) - })) + }) if gotv != v { t.Errorf("want %#v, got %#v", v, gotv) diff --git a/go/stats/prometheusbackend/collectors.go b/go/stats/prometheusbackend/collectors.go index e5d02f80da6..bacaa57f369 100644 --- a/go/stats/prometheusbackend/collectors.go +++ b/go/stats/prometheusbackend/collectors.go @@ -7,20 +7,21 @@ import ( "vitess.io/vitess/go/stats" ) -type metricCollector struct { - counter *stats.Counter - desc *prometheus.Desc - vt prometheus.ValueType +type metricFuncCollector struct { + // f returns the floating point value of the metric. + f func() float64 + desc *prometheus.Desc + vt prometheus.ValueType } // Describe implements Collector. -func (c *metricCollector) Describe(ch chan<- *prometheus.Desc) { - ch <- c.desc +func (mc *metricFuncCollector) Describe(ch chan<- *prometheus.Desc) { + ch <- mc.desc } // Collect implements Collector. -func (c *metricCollector) Collect(ch chan<- prometheus.Metric) { - ch <- prometheus.MustNewConstMetric(c.desc, c.vt, float64(c.counter.Get())) +func (mc *metricFuncCollector) Collect(ch chan<- prometheus.Metric) { + ch <- prometheus.MustNewConstMetric(mc.desc, mc.vt, float64(mc.f())) } // countersWithLabelsCollector collects stats.CountersWithLabels @@ -183,19 +184,3 @@ func (c *multiTimingsCollector) Collect(ch chan<- prometheus.Metric) { labelValues...) } } - -type metricFuncCollector struct { - cf *stats.CounterFunc - desc *prometheus.Desc - vt prometheus.ValueType -} - -// Describe implements Collector. -func (c *metricFuncCollector) Describe(ch chan<- *prometheus.Desc) { - ch <- c.desc -} - -// Collect implements Collector. -func (c *metricFuncCollector) Collect(ch chan<- prometheus.Metric) { - ch <- prometheus.MustNewConstMetric(c.desc, c.vt, float64(c.cf.Mf.FloatVal())) -} diff --git a/go/stats/prometheusbackend/prometheusbackend.go b/go/stats/prometheusbackend/prometheusbackend.go index 2dbfaa027e3..372e6cbb579 100644 --- a/go/stats/prometheusbackend/prometheusbackend.go +++ b/go/stats/prometheusbackend/prometheusbackend.go @@ -34,13 +34,13 @@ func Init(namespace string) { func (be *PromBackend) publishPrometheusMetric(name string, v expvar.Var) { switch st := v.(type) { case *stats.Counter: - be.newMetric(st, name, prometheus.CounterValue) - case *stats.Gauge: - be.newMetric(&st.Counter, name, prometheus.GaugeValue) + be.newMetric(st, name, prometheus.CounterValue, func() float64 { return float64(st.Get()) }) case *stats.CounterFunc: - be.newMetricFunc(st, name, prometheus.CounterValue) + be.newMetric(st, name, prometheus.CounterValue, func() float64 { return float64(st.F()) }) + case *stats.Gauge: + be.newMetric(st, name, prometheus.GaugeValue, func() float64 { return float64(st.Get()) }) case *stats.GaugeFunc: - be.newMetricFunc(&st.CounterFunc, name, prometheus.GaugeValue) + be.newMetric(st, name, prometheus.GaugeValue, func() float64 { return float64(st.F()) }) case *stats.CountersWithLabels: be.newCountersWithLabels(st, name, st.LabelName(), prometheus.CounterValue) case *stats.CountersWithMultiLabels: @@ -53,6 +53,12 @@ func (be *PromBackend) publishPrometheusMetric(name string, v expvar.Var) { be.newGaugesWithLabels(st, name, st.LabelName(), prometheus.GaugeValue) case *stats.GaugesWithMultiLabels: be.newGaugesWithMultiLabels(st, name) + case *stats.Duration: + // TODO(mberlin): For now, we only support duration as gauge value. + be.newMetric(st, name, prometheus.GaugeValue, func() float64 { return st.Get().Seconds() }) + case *stats.DurationFunc: + // TODO(mberlin): For now, we only support duration as gauge value. + be.newMetric(st, name, prometheus.GaugeValue, func() float64 { return st.F().Seconds() }) case *stats.Timings: be.newTiming(st, name) case *stats.MultiTimings: @@ -154,25 +160,12 @@ func (be *PromBackend) newMultiTiming(mt *stats.MultiTimings, name string) { prometheus.MustRegister(collector) } -func (be *PromBackend) newMetric(c *stats.Counter, name string, vt prometheus.ValueType) { - collector := &metricCollector{ - counter: c, - desc: prometheus.NewDesc( - be.buildPromName(name), - c.Help(), - nil, - nil), - vt: vt} - - prometheus.MustRegister(collector) -} - -func (be *PromBackend) newMetricFunc(cf *stats.CounterFunc, name string, vt prometheus.ValueType) { +func (be *PromBackend) newMetric(v stats.Variable, name string, vt prometheus.ValueType, f func() float64) { collector := &metricFuncCollector{ - cf: cf, + f: f, desc: prometheus.NewDesc( be.buildPromName(name), - cf.Help(), + v.Help(), nil, nil), vt: vt} diff --git a/go/stats/prometheusbackend/prometheusbackend_test.go b/go/stats/prometheusbackend/prometheusbackend_test.go index a688389717f..3b44b6b59ad 100644 --- a/go/stats/prometheusbackend/prometheusbackend_test.go +++ b/go/stats/prometheusbackend/prometheusbackend_test.go @@ -42,9 +42,9 @@ func TestPrometheusGauge(t *testing.T) { func TestPrometheusCounterFunc(t *testing.T) { name := "blah_counterfunc" - stats.NewCounterFunc(name, "help", stats.IntFunc(func() int64 { + stats.NewCounterFunc(name, "help", func() int64 { return 2 - })) + }) checkHandlerForMetrics(t, name, 2) } @@ -52,13 +52,30 @@ func TestPrometheusCounterFunc(t *testing.T) { func TestPrometheusGaugeFunc(t *testing.T) { name := "blah_gaugefunc" - stats.NewGaugeFunc(name, "help", stats.IntFunc(func() int64 { + stats.NewGaugeFunc(name, "help", func() int64 { return -3 - })) + }) checkHandlerForMetrics(t, name, -3) } +func TestPrometheusDuration(t *testing.T) { + name := "blah_duration" + + d := stats.NewDuration(name, "help") + d.Set(1 * time.Second) + + checkHandlerForMetrics(t, name, 1) +} + +func TestPrometheusDurationFunc(t *testing.T) { + name := "blah_durationfunc" + + stats.NewDurationFunc(name, "help", func() time.Duration { return 1 * time.Second }) + + checkHandlerForMetrics(t, name, 1) +} + func checkHandlerForMetrics(t *testing.T, metric string, value int) { response := testMetricsHandler(t) diff --git a/go/stats/variable_interface.go b/go/stats/variable_interface.go new file mode 100644 index 00000000000..49b9201e4af --- /dev/null +++ b/go/stats/variable_interface.go @@ -0,0 +1,29 @@ +/* +Copyright 2018 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 stats + +// Variable is the minimal interface which each type in this "stats" package +// must implement. +// When integrating the Vitess stats types ("variables") with the different +// monitoring systems, you can rely on this interface. +type Variable interface { + // Help returns the description of the variable. + Help() string + + // String must implement String() from the expvar.Var interface. + String() string +} diff --git a/go/vt/dbconnpool/connection_pool.go b/go/vt/dbconnpool/connection_pool.go index 2d27c337aaf..f2de0a79143 100644 --- a/go/vt/dbconnpool/connection_pool.go +++ b/go/vt/dbconnpool/connection_pool.go @@ -65,15 +65,15 @@ func NewConnectionPool(name string, capacity int, idleTimeout time.Duration) *Co return cp } usedNames[name] = true - stats.NewGaugeFunc(name+"Capacity", "Connection pool capacity", stats.IntFunc(cp.Capacity)) - stats.NewGaugeFunc(name+"Available", "Connection pool available", stats.IntFunc(cp.Available)) - stats.NewGaugeFunc(name+"Active", "Connection pool active", stats.IntFunc(cp.Active)) - stats.NewGaugeFunc(name+"InUse", "Connection pool in-use", stats.IntFunc(cp.InUse)) - stats.NewGaugeFunc(name+"MaxCap", "Connection pool max cap", stats.IntFunc(cp.MaxCap)) - stats.NewCounterFunc(name+"WaitCount", "Connection pool wait count", stats.IntFunc(cp.WaitCount)) - stats.NewCounterFunc(name+"WaitTime", "Connection pool wait time", stats.DurationFunc(cp.WaitTime)) - stats.NewCounterFunc(name+"IdleTimeout", "Connection pool idle timeout", stats.DurationFunc(cp.IdleTimeout)) - stats.NewGaugeFunc(name+"IdleClosed", "Connection pool idle closed", stats.IntFunc(cp.IdleClosed)) + stats.NewGaugeFunc(name+"Capacity", "Connection pool capacity", cp.Capacity) + stats.NewGaugeFunc(name+"Available", "Connection pool available", cp.Available) + stats.NewGaugeFunc(name+"Active", "Connection pool active", cp.Active) + stats.NewGaugeFunc(name+"InUse", "Connection pool in-use", cp.InUse) + stats.NewGaugeFunc(name+"MaxCap", "Connection pool max cap", cp.MaxCap) + stats.NewCounterFunc(name+"WaitCount", "Connection pool wait count", cp.WaitCount) + stats.NewDurationFunc(name+"WaitTime", "Connection pool wait time", cp.WaitTime) + stats.NewDurationFunc(name+"IdleTimeout", "Connection pool idle timeout", cp.IdleTimeout) + stats.NewGaugeFunc(name+"IdleClosed", "Connection pool idle closed", cp.IdleClosed) return cp } diff --git a/go/vt/vtgate/executor.go b/go/vt/vtgate/executor.go index 543dae4782e..c4990da4214 100644 --- a/go/vt/vtgate/executor.go +++ b/go/vt/vtgate/executor.go @@ -104,10 +104,10 @@ func NewExecutor(ctx context.Context, serv srvtopo.Server, cell, statsName strin e.vm.watchSrvVSchema(ctx, cell) executorOnce.Do(func() { - stats.NewGaugeFunc("QueryPlanCacheLength", "Query plan cache length", stats.IntFunc(e.plans.Length)) - stats.NewGaugeFunc("QueryPlanCacheSize", "Query plan cache size", stats.IntFunc(e.plans.Size)) - stats.NewGaugeFunc("QueryPlanCacheCapacity", "Query plan cache capacity", stats.IntFunc(e.plans.Capacity)) - stats.NewCounterFunc("QueryPlanCacheEvictions", "Query plan cache evictions", stats.IntFunc(e.plans.Evictions)) + stats.NewGaugeFunc("QueryPlanCacheLength", "Query plan cache length", e.plans.Length) + stats.NewGaugeFunc("QueryPlanCacheSize", "Query plan cache size", e.plans.Size) + stats.NewGaugeFunc("QueryPlanCacheCapacity", "Query plan cache capacity", e.plans.Capacity) + stats.NewCounterFunc("QueryPlanCacheEvictions", "Query plan cache evictions", e.plans.Evictions) stats.Publish("QueryPlanCacheOldest", stats.StringFunc(func() string { return fmt.Sprintf("%v", e.plans.Oldest()) })) diff --git a/go/vt/vttablet/tabletmanager/binlog_players.go b/go/vt/vttablet/tabletmanager/binlog_players.go index 436e2b0297f..168afea52d0 100644 --- a/go/vt/vttablet/tabletmanager/binlog_players.go +++ b/go/vt/vttablet/tabletmanager/binlog_players.go @@ -421,19 +421,19 @@ func NewBinlogPlayerMap(ts *topo.Server, mysqld mysqlctl.MysqlDaemon, vtClientFa // RegisterBinlogPlayerMap registers the varz for the players. func RegisterBinlogPlayerMap(blm *BinlogPlayerMap) { - stats.NewGaugeFunc("BinlogPlayerMapSize", "Binlog player map size", stats.IntFunc(func() int64 { + stats.NewGaugeFunc("BinlogPlayerMapSize", "Binlog player map size", func() int64 { blm.mu.Lock() defer blm.mu.Unlock() return int64(len(blm.players)) - })) + }) stats.NewGaugeFunc( "BinlogPlayerSecondsBehindMaster", "Binlog player seconds behind master", - stats.IntFunc(func() int64 { + func() int64 { blm.mu.Lock() defer blm.mu.Unlock() return blm.maxSecondsBehindMasterUNGUARDED() - })) + }) stats.Publish("BinlogPlayerSecondsBehindMasterMap", stats.CountersFunc(func() map[string]int64 { blm.mu.Lock() result := make(map[string]int64, len(blm.players)) diff --git a/go/vt/vttablet/tabletserver/connpool/pool.go b/go/vt/vttablet/tabletserver/connpool/pool.go index a36e4f29863..f010b652d03 100644 --- a/go/vt/vttablet/tabletserver/connpool/pool.go +++ b/go/vt/vttablet/tabletserver/connpool/pool.go @@ -82,15 +82,15 @@ func New( return cp } usedNames[name] = true - stats.NewGaugeFunc(name+"Capacity", "Tablet server conn pool capacity", stats.IntFunc(cp.Capacity)) - stats.NewGaugeFunc(name+"Available", "Tablet server conn pool available", stats.IntFunc(cp.Available)) - stats.NewGaugeFunc(name+"Active", "Tablet server conn pool active", stats.IntFunc(cp.Active)) - stats.NewGaugeFunc(name+"InUse", "Tablet server conn pool in use", stats.IntFunc(cp.InUse)) - stats.NewGaugeFunc(name+"MaxCap", "Tablet server conn pool max cap", stats.IntFunc(cp.MaxCap)) - stats.NewCounterFunc(name+"WaitCount", "Tablet server conn pool wait count", stats.IntFunc(cp.WaitCount)) - stats.NewCounterFunc(name+"WaitTime", "Tablet server wait time", stats.DurationFunc(cp.WaitTime)) - stats.NewCounterFunc(name+"IdleTimeout", "Tablet server idle timeout", stats.DurationFunc(cp.IdleTimeout)) - stats.NewCounterFunc(name+"IdleClosed", "Tablet server conn pool idle closed", stats.IntFunc(cp.IdleClosed)) + stats.NewGaugeFunc(name+"Capacity", "Tablet server conn pool capacity", cp.Capacity) + stats.NewGaugeFunc(name+"Available", "Tablet server conn pool available", cp.Available) + stats.NewGaugeFunc(name+"Active", "Tablet server conn pool active", cp.Active) + stats.NewGaugeFunc(name+"InUse", "Tablet server conn pool in use", cp.InUse) + stats.NewGaugeFunc(name+"MaxCap", "Tablet server conn pool max cap", cp.MaxCap) + stats.NewCounterFunc(name+"WaitCount", "Tablet server conn pool wait count", cp.WaitCount) + stats.NewDurationFunc(name+"WaitTime", "Tablet server wait time", cp.WaitTime) + stats.NewDurationFunc(name+"IdleTimeout", "Tablet server idle timeout", cp.IdleTimeout) + stats.NewCounterFunc(name+"IdleClosed", "Tablet server conn pool idle closed", cp.IdleClosed) return cp } diff --git a/go/vt/vttablet/tabletserver/query_engine.go b/go/vt/vttablet/tabletserver/query_engine.go index 72fd512c0c4..85490e9d824 100644 --- a/go/vt/vttablet/tabletserver/query_engine.go +++ b/go/vt/vttablet/tabletserver/query_engine.go @@ -234,17 +234,17 @@ func NewQueryEngine(checker connpool.MySQLChecker, se *schema.Engine, config tab qe.accessCheckerLogger = logutil.NewThrottledLogger("accessChecker", 1*time.Second) qeOnce.Do(func() { - stats.NewGaugeFunc("MaxResultSize", "Query engine max result size", stats.IntFunc(qe.maxResultSize.Get)) - stats.NewGaugeFunc("WarnResultSize", "Query engine warn result size", stats.IntFunc(qe.warnResultSize.Get)) - stats.NewGaugeFunc("MaxDMLRows", "Query engine max DML rows", stats.IntFunc(qe.maxDMLRows.Get)) - stats.NewGaugeFunc("StreamBufferSize", "Query engine stream buffer size", stats.IntFunc(qe.streamBufferSize.Get)) - stats.NewCounterFunc("TableACLExemptCount", "Query engine table ACL exempt count", stats.IntFunc(qe.tableaclExemptCount.Get)) - stats.NewGaugeFunc("QueryPoolWaiters", "Query engine query pool waiters", stats.IntFunc(qe.queryPoolWaiters.Get)) - - stats.NewGaugeFunc("QueryCacheLength", "Query engine query cache length", stats.IntFunc(qe.plans.Length)) - stats.NewGaugeFunc("QueryCacheSize", "Query engine query cache size", stats.IntFunc(qe.plans.Size)) - stats.NewGaugeFunc("QueryCacheCapacity", "Query engine query cache capacity", stats.IntFunc(qe.plans.Capacity)) - stats.NewCounterFunc("QueryCacheEvictions", "Query engine query cache evictions", stats.IntFunc(qe.plans.Evictions)) + stats.NewGaugeFunc("MaxResultSize", "Query engine max result size", qe.maxResultSize.Get) + stats.NewGaugeFunc("WarnResultSize", "Query engine warn result size", qe.warnResultSize.Get) + stats.NewGaugeFunc("MaxDMLRows", "Query engine max DML rows", qe.maxDMLRows.Get) + stats.NewGaugeFunc("StreamBufferSize", "Query engine stream buffer size", qe.streamBufferSize.Get) + stats.NewCounterFunc("TableACLExemptCount", "Query engine table ACL exempt count", qe.tableaclExemptCount.Get) + stats.NewGaugeFunc("QueryPoolWaiters", "Query engine query pool waiters", qe.queryPoolWaiters.Get) + + stats.NewGaugeFunc("QueryCacheLength", "Query engine query cache length", qe.plans.Length) + stats.NewGaugeFunc("QueryCacheSize", "Query engine query cache size", qe.plans.Size) + stats.NewGaugeFunc("QueryCacheCapacity", "Query engine query cache capacity", qe.plans.Capacity) + stats.NewCounterFunc("QueryCacheEvictions", "Query engine query cache evictions", qe.plans.Evictions) stats.Publish("QueryCacheOldest", stats.StringFunc(func() string { return fmt.Sprintf("%v", qe.plans.Oldest()) })) diff --git a/go/vt/vttablet/tabletserver/replication_watcher.go b/go/vt/vttablet/tabletserver/replication_watcher.go index ba9459b4961..3c2e6986959 100644 --- a/go/vt/vttablet/tabletserver/replication_watcher.go +++ b/go/vt/vttablet/tabletserver/replication_watcher.go @@ -71,12 +71,12 @@ func NewReplicationWatcher(se *schema.Engine, config tabletenv.TabletConfig) *Re stats.NewGaugeFunc( "EventTokenTimestamp", "Replication watcher event token timestamp", - stats.IntFunc(func() int64 { + func() int64 { if e := rpw.EventToken(); e != nil { return e.Timestamp } return 0 - })) + }) }) return rpw } diff --git a/go/vt/vttablet/tabletserver/schema/engine.go b/go/vt/vttablet/tabletserver/schema/engine.go index 4389f1613b7..a2491576b06 100644 --- a/go/vt/vttablet/tabletserver/schema/engine.go +++ b/go/vt/vttablet/tabletserver/schema/engine.go @@ -77,7 +77,7 @@ func NewEngine(checker connpool.MySQLChecker, config tabletenv.TabletConfig) *En reloadTime: reloadTime, } schemaOnce.Do(func() { - _ = stats.NewGaugeFunc("SchemaReloadTime", "vttablet keeps table schemas in its own memory and periodically refreshes it from MySQL. This config controls the reload time.", stats.DurationFunc(se.ticks.Interval)) + _ = stats.NewDurationFunc("SchemaReloadTime", "vttablet keeps table schemas in its own memory and periodically refreshes it from MySQL. This config controls the reload time.", se.ticks.Interval) _ = stats.NewGaugesFuncWithMultiLabels("TableRows", []string{"Table"}, "table rows created in tabletserver", se.getTableRows) _ = stats.NewGaugesFuncWithMultiLabels("DataLength", []string{"Table"}, "data length in tabletserver", se.getDataLength) _ = stats.NewGaugesFuncWithMultiLabels("IndexLength", []string{"Table"}, "index length in tabletserver", se.getIndexLength) diff --git a/go/vt/vttablet/tabletserver/tabletserver.go b/go/vt/vttablet/tabletserver/tabletserver.go index 539a1957444..71e3dcf7ad2 100644 --- a/go/vt/vttablet/tabletserver/tabletserver.go +++ b/go/vt/vttablet/tabletserver/tabletserver.go @@ -238,15 +238,15 @@ func NewTabletServer(config tabletenv.TabletConfig, topoServer *topo.Server, ali // So that vtcombo doesn't even call it once, on the first tablet. // And we can remove the tsOnce variable. tsOnce.Do(func() { - stats.NewGaugeFunc("TabletState", "Tablet server state", stats.IntFunc(func() int64 { + stats.NewGaugeFunc("TabletState", "Tablet server state", func() int64 { tsv.mu.Lock() state := tsv.state tsv.mu.Unlock() return state - })) - stats.NewGaugeFunc("QueryTimeout", "Tablet server query timeout", stats.DurationFunc(tsv.QueryTimeout.Get)) - stats.NewGaugeFunc("QueryPoolTimeout", "Tablet server timeout to get a connection from the query pool", stats.DurationFunc(tsv.qe.connTimeout.Get)) - stats.NewGaugeFunc("BeginTimeout", "Tablet server begin timeout", stats.DurationFunc(tsv.BeginTimeout.Get)) + }) + stats.NewDurationFunc("QueryTimeout", "Tablet server query timeout", tsv.QueryTimeout.Get) + stats.NewDurationFunc("QueryPoolTimeout", "Tablet server timeout to get a connection from the query pool", tsv.qe.connTimeout.Get) + stats.NewDurationFunc("BeginTimeout", "Tablet server begin timeout", tsv.BeginTimeout.Get) stats.Publish("TabletStateName", stats.StringFunc(tsv.GetState)) }) return tsv diff --git a/go/vt/vttablet/tabletserver/tx_pool.go b/go/vt/vttablet/tabletserver/tx_pool.go index 956cf477b33..e4a3058cb15 100644 --- a/go/vt/vttablet/tabletserver/tx_pool.go +++ b/go/vt/vttablet/tabletserver/tx_pool.go @@ -119,8 +119,8 @@ func NewTxPool( txOnce.Do(func() { // Careful: conns also exports name+"xxx" vars, // but we know it doesn't export Timeout. - stats.NewGaugeFunc(prefix+"TransactionPoolTimeout", "Transaction pool timeout", stats.DurationFunc(axp.timeout.Get)) - stats.NewGaugeFunc(prefix+"TransactionPoolWaiters", "Transaction pool waiters", stats.IntFunc(axp.waiters.Get)) + stats.NewDurationFunc(prefix+"TransactionPoolTimeout", "Transaction pool timeout", axp.timeout.Get) + stats.NewGaugeFunc(prefix+"TransactionPoolWaiters", "Transaction pool waiters", axp.waiters.Get) }) return axp } From 7a533bf7afe9b17181e52dd0dacc2b75e65dc5bf Mon Sep 17 00:00:00 2001 From: xhh1989 Date: Sat, 28 Apr 2018 13:28:40 +0800 Subject: [PATCH 17/41] support parse sql like : DELETE FROM a1, a2 USING t1 AS a1 INNER JOIN t2 AS a2 WHERE a1.id=a2.id; related issue: https://github.com/vitessio/vitess/issues/3787 Signed-off-by: xhh1989 --- go/vt/sqlparser/parse_test.go | 3 + go/vt/sqlparser/sql.go | 3775 +++++++++++++++++---------------- go/vt/sqlparser/sql.y | 4 + 3 files changed, 1899 insertions(+), 1883 deletions(-) diff --git a/go/vt/sqlparser/parse_test.go b/go/vt/sqlparser/parse_test.go index ff3c9a27e24..b52c148e3fc 100644 --- a/go/vt/sqlparser/parse_test.go +++ b/go/vt/sqlparser/parse_test.go @@ -665,6 +665,9 @@ var ( input: "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 from a1, a2 using t1 as a1 inner join t2 as a2 where a1.id=a2.id", + output: "delete a1, a2 from t1 as a1 join t2 as a2 where a1.id = a2.id", }, { input: "set /* simple */ a = 3", }, { diff --git a/go/vt/sqlparser/sql.go b/go/vt/sqlparser/sql.go index 72485c55817..d6117590bc9 100644 --- a/go/vt/sqlparser/sql.go +++ b/go/vt/sqlparser/sql.go @@ -567,322 +567,302 @@ var yyExca = [...]int{ 5, 27, -2, 4, -1, 227, - 109, 554, - -2, 550, - -1, 228, 109, 555, -2, 551, + -1, 228, + 109, 556, + -2, 552, -1, 296, - 80, 706, - -2, 46, - -1, 297, - 80, 673, + 80, 707, -2, 47, + -1, 297, + 80, 674, + -2, 48, -1, 302, - 80, 658, - -2, 516, + 80, 659, + -2, 517, -1, 304, - 80, 691, - -2, 518, - -1, 686, - 109, 557, - -2, 553, - -1, 880, + 80, 692, + -2, 519, + -1, 562, + 52, 41, + 54, 41, + -2, 43, + -1, 687, + 109, 558, + -2, 554, + -1, 882, 5, 28, - -2, 363, - -1, 905, + -2, 364, + -1, 907, 5, 27, - -2, 492, - -1, 1112, - 5, 28, -2, 493, - -1, 1156, - 5, 27, - -2, 495, - -1, 1209, + -1, 1116, 5, 28, + -2, 494, + -1, 1160, + 5, 27, -2, 496, + -1, 1213, + 5, 28, + -2, 497, } const yyPrivate = 57344 -const yyLast = 9538 +const yyLast = 9530 var yyAct = [...]int{ - 258, 47, 627, 509, 748, 1026, 232, 1200, 257, 1118, - 1050, 825, 822, 766, 1027, 781, 805, 960, 554, 556, - 1023, 206, 780, 819, 777, 924, 53, 908, 749, 872, - 951, 1000, 718, 711, 913, 508, 3, 963, 791, 737, - 688, 721, 442, 448, 295, 558, 200, 454, 47, 398, - 745, 230, 815, 462, 301, 854, 211, 799, 293, 523, - 215, 52, 288, 543, 1187, 475, 474, 484, 485, 477, - 478, 479, 480, 481, 482, 483, 476, 1228, 1218, 486, - 282, 1226, 1207, 205, 1224, 826, 1217, 283, 1018, 1106, - 201, 202, 203, 204, 402, 1056, 1057, 1058, 57, 1206, - 1172, 219, 942, 1061, 1059, 798, 284, 171, 167, 168, - 169, 1130, 1145, 806, 1095, 1093, 199, 434, 435, 1225, - 1223, 1201, 984, 59, 60, 61, 62, 63, 423, 746, - 767, 769, 412, 411, 475, 474, 484, 485, 477, 478, - 479, 480, 481, 482, 483, 476, 405, 164, 486, 165, - 165, 635, 626, 923, 793, 922, 1170, 793, 921, 400, - 408, 179, 1192, 166, 793, 1065, 477, 478, 479, 480, - 481, 482, 483, 476, 1115, 228, 486, 498, 499, 873, - 778, 486, 399, 987, 429, 429, 429, 429, 888, 429, - 429, 425, 936, 427, 866, 981, 429, 660, 466, 418, - 657, 983, 476, 170, 768, 486, 76, 1188, 461, 695, - 176, 1075, 47, 176, 911, 1066, 1020, 424, 426, 459, - 569, 738, 234, 693, 694, 692, 738, 495, 895, 1001, - 497, 630, 806, 940, 404, 461, 450, 176, 176, 76, - 1195, 456, 1136, 176, 428, 76, 792, 451, 163, 792, - 1060, 790, 788, 1171, 1169, 789, 792, 507, 1003, 511, - 512, 513, 514, 515, 516, 517, 518, 519, 1135, 522, + 258, 47, 628, 827, 749, 509, 232, 1204, 1122, 1029, + 508, 3, 824, 779, 767, 257, 1054, 1030, 556, 963, + 783, 206, 554, 782, 910, 807, 750, 1026, 200, 926, + 712, 874, 301, 1003, 722, 719, 966, 954, 821, 793, + 915, 689, 53, 738, 442, 448, 817, 746, 47, 398, + 295, 284, 454, 558, 543, 230, 211, 462, 205, 856, + 215, 291, 288, 293, 283, 52, 1232, 1222, 1230, 1211, + 1228, 828, 201, 202, 203, 204, 1221, 1021, 1110, 402, + 234, 1176, 945, 423, 282, 1210, 800, 1060, 1061, 1062, + 1134, 808, 1099, 1097, 219, 1065, 1063, 171, 167, 168, + 169, 57, 523, 199, 1149, 434, 435, 1191, 475, 474, + 484, 485, 477, 478, 479, 480, 481, 482, 483, 476, + 1229, 844, 486, 411, 1227, 1205, 59, 60, 61, 62, + 63, 987, 747, 412, 1004, 843, 405, 165, 1174, 768, + 770, 164, 287, 165, 636, 984, 425, 627, 427, 780, + 925, 986, 924, 923, 400, 408, 1196, 795, 179, 166, + 498, 499, 848, 1006, 795, 721, 1119, 990, 890, 868, + 661, 842, 424, 426, 466, 225, 228, 418, 486, 476, + 1079, 1069, 486, 658, 429, 429, 429, 429, 461, 429, + 429, 913, 939, 170, 570, 1008, 429, 1012, 1023, 1007, + 739, 1005, 696, 739, 795, 897, 1010, 76, 460, 459, + 185, 176, 47, 769, 176, 1009, 694, 695, 693, 839, + 836, 837, 451, 835, 808, 461, 631, 495, 1011, 1013, + 497, 1070, 399, 1199, 195, 1175, 1173, 459, 176, 176, + 76, 422, 1064, 985, 176, 983, 76, 846, 849, 794, + 1192, 943, 450, 461, 456, 660, 794, 507, 801, 511, + 512, 513, 514, 515, 516, 517, 518, 519, 1209, 522, 524, 524, 524, 524, 524, 524, 524, 524, 532, 533, - 534, 535, 1205, 712, 287, 713, 422, 50, 842, 555, - 1005, 955, 1009, 982, 1004, 980, 1002, 691, 885, 954, - 943, 1007, 841, 414, 415, 416, 406, 407, 1211, 281, - 1006, 452, 474, 484, 485, 477, 478, 479, 480, 481, - 482, 483, 476, 1008, 1010, 486, 460, 459, 1152, 846, - 525, 526, 527, 528, 529, 530, 531, 1053, 840, 795, - 176, 1133, 176, 461, 796, 952, 460, 459, 176, 460, - 459, 1214, 441, 568, 1052, 176, 1022, 663, 664, 76, - 76, 76, 76, 461, 76, 76, 461, 678, 680, 681, - 937, 76, 679, 484, 485, 477, 478, 479, 480, 481, - 482, 483, 476, 225, 971, 486, 837, 834, 835, 441, - 833, 479, 480, 481, 482, 483, 476, 76, 928, 486, - 1160, 1198, 429, 460, 459, 863, 864, 865, 1160, 441, - 429, 828, 969, 714, 844, 847, 1160, 1161, 1127, 1126, - 461, 429, 429, 429, 429, 429, 429, 429, 429, 431, - 432, 433, 641, 436, 437, 429, 429, 1045, 441, 1176, - 439, 640, 884, 631, 883, 1114, 441, 1175, 720, 839, - 1072, 1071, 496, 1068, 1069, 1068, 1067, 176, 878, 441, - 460, 459, 629, 659, 176, 176, 176, 23, 540, 441, - 76, 838, 665, 644, 642, 76, 970, 461, 689, 723, - 441, 975, 972, 965, 966, 973, 968, 967, 624, 576, - 575, 903, 420, 565, 904, 413, 843, 974, 47, 658, - 399, 21, 23, 977, 256, 1024, 1062, 539, 909, 845, - 990, 287, 511, 667, 50, 460, 459, 682, 910, 910, - 54, 686, 684, 730, 733, 909, 723, 1110, 430, 1155, - 540, 540, 461, 1074, 566, 74, 564, 1070, 890, 23, - 929, 288, 288, 288, 288, 288, 750, 725, 878, 50, - 715, 716, 887, 878, 567, 661, 555, 210, 770, 878, - 540, 909, 212, 50, 288, 1140, 742, 735, 300, 545, - 548, 549, 550, 546, 403, 547, 551, 76, 800, 914, - 915, 889, 773, 176, 176, 76, 50, 176, 820, 1039, - 176, 725, 298, 932, 176, 886, 76, 76, 76, 76, - 76, 76, 76, 76, 816, 771, 807, 808, 809, 50, - 76, 76, 775, 772, 176, 763, 914, 915, 628, 500, - 501, 502, 503, 504, 505, 506, 785, 811, 751, 76, - 429, 754, 429, 176, 810, 65, 823, 1055, 1024, 76, - 429, 956, 801, 802, 803, 804, 625, 821, 752, 753, - 917, 755, 638, 438, 634, 673, 971, 760, 812, 813, - 814, 440, 761, 920, 919, 645, 646, 647, 648, 649, - 650, 651, 652, 817, 818, 762, 758, 549, 550, 653, - 654, 759, 76, 757, 969, 756, 867, 1222, 300, 300, - 300, 300, 690, 300, 300, 216, 217, 1216, 76, 986, - 300, 689, 851, 1221, 861, 855, 860, 455, 856, 947, - 443, 574, 421, 176, 939, 686, 176, 176, 176, 176, - 176, 453, 444, 1197, 1196, 1153, 464, 933, 176, 1108, - 1141, 176, 830, 868, 637, 176, 553, 213, 214, 176, - 176, 455, 859, 76, 207, 1181, 906, 907, 970, 208, - 858, 76, 54, 975, 972, 965, 966, 973, 968, 967, - 1180, 1143, 457, 287, 287, 287, 287, 287, 910, 974, - 1189, 221, 1131, 656, 56, 964, 894, 58, 287, 563, - 51, 905, 1, 827, 959, 836, 287, 1199, 1049, 918, - 787, 545, 548, 549, 550, 546, 930, 547, 551, 300, - 926, 927, 176, 779, 571, 76, 397, 76, 64, 786, - 1168, 176, 1129, 794, 176, 76, 941, 797, 944, 945, - 1054, 1194, 938, 298, 581, 429, 579, 580, 934, 935, - 946, 578, 948, 949, 950, 247, 246, 249, 250, 251, - 252, 583, 953, 582, 248, 253, 577, 187, 294, 552, - 429, 441, 687, 570, 458, 696, 697, 698, 699, 700, - 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, - 66, 979, 976, 978, 829, 832, 831, 494, 857, 962, - 299, 1031, 662, 447, 850, 1179, 1142, 475, 474, 484, - 485, 477, 478, 479, 480, 481, 482, 483, 476, 994, - 993, 486, 893, 520, 736, 1029, 300, 47, 1025, 233, - 750, 677, 245, 1028, 300, 690, 750, 1012, 1011, 1019, - 999, 242, 1041, 1042, 1043, 300, 300, 300, 300, 300, - 300, 300, 300, 1033, 244, 1034, 243, 668, 1035, 300, - 300, 902, 1030, 686, 468, 231, 76, 1048, 223, 286, - 536, 544, 1047, 1046, 542, 541, 76, 291, 669, 916, - 912, 726, 727, 285, 989, 1105, 1186, 734, 464, 1063, - 1064, 300, 672, 25, 55, 218, 19, 18, 17, 445, - 449, 741, 20, 743, 744, 16, 15, 14, 29, 13, - 12, 288, 11, 10, 9, 685, 467, 8, 7, 76, - 76, 6, 76, 5, 4, 209, 22, 2, 0, 1084, - 1076, 717, 0, 0, 0, 0, 0, 1083, 0, 1104, - 0, 731, 731, 1078, 0, 76, 1081, 739, 0, 1091, - 510, 0, 0, 176, 0, 0, 0, 0, 0, 521, - 0, 0, 76, 0, 731, 0, 1109, 0, 0, 0, - 0, 1120, 1121, 1122, 0, 0, 1117, 0, 0, 1088, - 1089, 0, 1090, 930, 1123, 1092, 0, 1094, 1125, 958, - 0, 0, 300, 0, 429, 0, 0, 869, 870, 871, - 300, 0, 76, 76, 1132, 0, 1134, 0, 0, 0, - 0, 1139, 1138, 0, 985, 0, 298, 0, 0, 0, - 0, 0, 0, 0, 782, 76, 1144, 76, 76, 1128, - 0, 1029, 0, 666, 1157, 0, 0, 0, 0, 1028, - 0, 862, 0, 0, 0, 1154, 0, 0, 0, 0, - 0, 0, 176, 0, 300, 0, 300, 1165, 1167, 1166, - 76, 0, 1178, 0, 300, 0, 0, 0, 0, 1156, - 1177, 0, 0, 76, 176, 0, 1029, 1173, 47, 1174, - 76, 1190, 0, 76, 1028, 300, 176, 0, 877, 0, - 722, 724, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 892, 1203, 740, 0, 0, 685, - 0, 0, 0, 1191, 1208, 0, 750, 1102, 441, 0, - 0, 1212, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 287, 0, 76, 765, 76, 76, 76, - 176, 76, 1220, 76, 1219, 0, 1227, 0, 0, 0, - 0, 675, 676, 0, 475, 474, 484, 485, 477, 478, - 479, 480, 481, 482, 483, 476, 0, 0, 486, 76, - 76, 76, 0, 0, 0, 0, 0, 996, 997, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 185, - 1013, 1014, 0, 1016, 1017, 925, 0, 0, 0, 0, - 0, 0, 0, 510, 0, 300, 728, 729, 0, 0, - 76, 76, 0, 195, 0, 0, 0, 0, 0, 446, - 0, 0, 0, 76, 0, 0, 0, 0, 0, 782, - 0, 0, 0, 0, 0, 0, 76, 0, 1137, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 957, 300, - 0, 300, 0, 0, 174, 0, 76, 198, 0, 289, - 0, 776, 0, 180, 0, 0, 1103, 0, 0, 182, - 0, 0, 0, 0, 300, 961, 188, 184, 0, 222, - 0, 174, 174, 0, 0, 0, 0, 174, 76, 0, - 0, 300, 0, 0, 173, 0, 875, 76, 0, 1086, - 876, 0, 186, 0, 0, 190, 0, 880, 881, 882, - 0, 0, 0, 300, 0, 992, 891, 0, 0, 0, - 0, 897, 292, 898, 899, 900, 901, 401, 731, 0, - 0, 1032, 925, 181, 731, 0, 0, 1015, 475, 474, + 534, 535, 841, 1140, 180, 865, 866, 867, 887, 555, + 182, 659, 1215, 414, 415, 416, 794, 188, 184, 50, + 1139, 792, 790, 163, 840, 791, 797, 460, 459, 692, + 496, 798, 958, 957, 452, 477, 478, 479, 480, 481, + 482, 483, 476, 186, 461, 486, 190, 946, 404, 845, + 479, 480, 481, 482, 483, 476, 460, 459, 486, 1156, + 974, 176, 847, 176, 428, 664, 665, 1137, 955, 176, + 460, 459, 563, 461, 181, 1057, 176, 1025, 569, 1056, + 76, 76, 76, 76, 281, 76, 76, 461, 972, 287, + 1218, 441, 76, 525, 526, 527, 528, 529, 530, 531, + 940, 183, 189, 191, 192, 193, 194, 1164, 1202, 197, + 196, 460, 459, 931, 679, 681, 682, 830, 76, 680, + 406, 407, 429, 713, 715, 714, 1164, 441, 461, 642, + 429, 500, 501, 502, 503, 504, 505, 506, 1164, 1165, + 441, 429, 429, 429, 429, 429, 429, 429, 429, 430, + 1131, 1130, 973, 1048, 441, 429, 429, 978, 975, 968, + 969, 976, 971, 970, 886, 641, 885, 1118, 441, 1076, + 1075, 645, 632, 977, 1072, 1073, 1072, 1071, 176, 980, + 880, 441, 460, 459, 630, 176, 176, 176, 540, 441, + 23, 76, 666, 724, 441, 1180, 76, 625, 643, 461, + 577, 576, 21, 420, 566, 690, 247, 246, 249, 250, + 251, 252, 413, 298, 905, 248, 253, 906, 47, 687, + 399, 1179, 1066, 911, 1027, 23, 256, 911, 54, 912, + 724, 539, 511, 668, 993, 1114, 892, 50, 912, 889, + 23, 683, 726, 731, 734, 567, 685, 565, 540, 431, + 432, 433, 1159, 436, 437, 540, 1078, 74, 210, 1074, + 439, 288, 288, 288, 288, 288, 751, 880, 932, 880, + 691, 540, 50, 50, 716, 717, 555, 880, 771, 891, + 911, 774, 888, 565, 568, 288, 726, 50, 1144, 743, + 300, 662, 736, 212, 802, 822, 403, 1042, 76, 935, + 916, 917, 629, 440, 176, 176, 76, 775, 176, 818, + 813, 176, 812, 753, 754, 176, 756, 76, 76, 76, + 76, 76, 76, 76, 76, 752, 764, 65, 755, 825, + 773, 76, 76, 772, 1059, 176, 809, 810, 811, 777, + 50, 287, 287, 287, 287, 287, 1027, 787, 959, 919, + 76, 429, 639, 429, 176, 438, 287, 761, 759, 922, + 76, 429, 762, 760, 688, 287, 674, 697, 698, 699, + 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, + 710, 711, 763, 823, 549, 550, 921, 758, 819, 820, + 545, 548, 549, 550, 546, 757, 547, 551, 727, 728, + 916, 917, 1226, 76, 735, 216, 217, 869, 1220, 989, + 300, 300, 300, 300, 687, 300, 300, 853, 742, 76, + 744, 745, 300, 1225, 863, 862, 950, 575, 857, 690, + 421, 858, 455, 443, 176, 942, 1201, 176, 176, 176, + 176, 176, 1145, 1200, 298, 444, 453, 1157, 464, 176, + 936, 1112, 176, 832, 638, 870, 176, 553, 213, 214, + 455, 176, 176, 861, 207, 76, 626, 908, 909, 1185, + 208, 860, 54, 76, 635, 1184, 1147, 907, 912, 457, + 1193, 1135, 657, 56, 58, 646, 647, 648, 649, 650, + 651, 652, 653, 564, 691, 288, 51, 1, 829, 654, + 655, 896, 974, 484, 485, 477, 478, 479, 480, 481, + 482, 483, 476, 962, 838, 486, 920, 929, 928, 1203, + 930, 300, 1053, 933, 176, 789, 572, 76, 781, 76, + 972, 397, 64, 176, 788, 1172, 176, 76, 1133, 796, + 944, 949, 799, 951, 952, 953, 1058, 429, 1198, 947, + 948, 937, 938, 941, 545, 548, 549, 550, 546, 864, + 547, 551, 582, 580, 803, 804, 805, 806, 581, 579, + 584, 956, 429, 583, 578, 287, 187, 294, 552, 571, + 814, 815, 816, 965, 458, 66, 982, 981, 834, 494, + 871, 872, 873, 979, 973, 859, 299, 1034, 663, 978, + 975, 968, 969, 976, 971, 970, 879, 447, 1183, 1146, + 895, 520, 737, 233, 678, 977, 686, 245, 242, 244, + 243, 967, 894, 997, 669, 996, 904, 1032, 300, 47, + 1028, 468, 751, 231, 223, 1002, 300, 1014, 751, 1033, + 286, 1015, 1031, 687, 1044, 1045, 1046, 300, 300, 300, + 300, 300, 300, 300, 300, 536, 544, 1022, 1038, 1036, + 542, 300, 300, 541, 918, 914, 285, 992, 76, 1109, + 1190, 176, 673, 1037, 1050, 1052, 1051, 25, 55, 76, + 670, 1067, 1068, 218, 19, 18, 17, 20, 16, 15, + 464, 1049, 14, 300, 29, 831, 221, 833, 13, 12, + 11, 10, 9, 8, 7, 852, 6, 5, 4, 209, + 22, 2, 0, 0, 288, 1080, 0, 0, 298, 0, + 0, 0, 76, 76, 0, 76, 784, 0, 1082, 0, + 0, 1085, 0, 718, 0, 0, 1088, 1087, 0, 0, + 0, 0, 1108, 732, 732, 0, 0, 0, 76, 740, + 0, 0, 0, 0, 0, 667, 176, 0, 0, 0, + 0, 0, 0, 0, 0, 76, 732, 1095, 0, 0, + 0, 999, 1000, 1124, 1125, 1126, 1113, 0, 0, 1121, + 0, 0, 0, 0, 1016, 1017, 1127, 1019, 1020, 0, + 0, 1129, 933, 0, 287, 300, 0, 0, 429, 0, + 0, 0, 0, 300, 0, 76, 76, 0, 0, 0, + 0, 686, 723, 725, 0, 0, 0, 1136, 1142, 1138, + 1143, 0, 0, 0, 0, 0, 0, 0, 741, 76, + 0, 76, 76, 0, 0, 1032, 0, 0, 1161, 1148, + 0, 0, 0, 0, 0, 0, 0, 0, 1160, 0, + 1031, 0, 1158, 0, 0, 0, 176, 300, 766, 300, + 0, 0, 1169, 1170, 76, 0, 1182, 300, 1171, 0, + 1177, 0, 1178, 1181, 0, 0, 0, 76, 176, 0, + 1032, 0, 47, 0, 76, 0, 0, 76, 300, 1194, + 176, 961, 1195, 0, 1090, 1031, 0, 0, 0, 0, + 0, 0, 0, 0, 445, 449, 0, 0, 0, 0, + 0, 1207, 0, 0, 0, 0, 988, 0, 1212, 0, + 751, 467, 0, 0, 0, 1216, 0, 0, 0, 0, + 0, 0, 784, 0, 0, 0, 0, 0, 0, 76, + 1223, 76, 76, 76, 176, 76, 1224, 0, 76, 0, + 1231, 0, 0, 0, 0, 510, 0, 0, 0, 0, + 0, 0, 0, 0, 521, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 76, 76, 76, 0, 964, 0, + 0, 0, 0, 1092, 1093, 0, 1094, 0, 0, 1096, + 0, 1098, 0, 0, 0, 0, 0, 0, 927, 1150, + 1151, 0, 1152, 1153, 1154, 0, 0, 446, 0, 300, + 0, 0, 0, 0, 0, 76, 76, 0, 995, 877, + 0, 0, 0, 878, 0, 0, 0, 0, 76, 0, + 882, 883, 884, 289, 1132, 0, 0, 0, 0, 893, + 1018, 76, 174, 0, 899, 198, 900, 901, 902, 903, + 0, 0, 960, 300, 0, 300, 0, 0, 0, 0, + 0, 76, 0, 0, 0, 0, 0, 222, 173, 174, + 174, 0, 0, 0, 0, 174, 0, 0, 300, 0, + 0, 0, 784, 0, 784, 0, 0, 0, 0, 0, + 0, 0, 0, 76, 0, 300, 292, 0, 0, 0, + 0, 401, 76, 0, 475, 474, 484, 485, 477, 478, + 479, 480, 481, 482, 483, 476, 0, 300, 486, 0, + 0, 0, 0, 0, 0, 0, 0, 1233, 0, 0, + 0, 0, 732, 0, 0, 1035, 927, 0, 732, 0, + 995, 0, 1141, 0, 0, 0, 0, 0, 0, 875, + 0, 0, 0, 0, 0, 0, 676, 677, 0, 300, + 0, 300, 1055, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 174, 0, 174, 0, 0, 0, 0, 0, + 174, 0, 0, 1001, 0, 0, 0, 174, 0, 0, + 0, 0, 0, 0, 1081, 0, 0, 0, 409, 0, + 410, 784, 0, 0, 0, 0, 417, 1083, 510, 0, + 0, 729, 730, 419, 1086, 1106, 441, 300, 0, 0, + 0, 23, 24, 48, 26, 27, 0, 0, 964, 784, + 1047, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 42, 0, 0, 0, 0, 28, 599, 0, 0, 0, + 0, 0, 475, 474, 484, 485, 477, 478, 479, 480, + 481, 482, 483, 476, 37, 0, 486, 778, 50, 1123, + 0, 1123, 1123, 1123, 0, 1128, 0, 0, 300, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 174, + 0, 0, 0, 0, 0, 0, 174, 560, 174, 0, + 1089, 0, 0, 0, 300, 300, 300, 1091, 0, 0, + 0, 0, 0, 0, 0, 538, 0, 0, 1100, 1101, + 1102, 0, 587, 1105, 562, 0, 0, 30, 31, 33, + 32, 35, 0, 0, 0, 0, 1115, 1116, 1117, 0, + 1120, 0, 0, 0, 0, 1162, 1163, 36, 43, 44, + 0, 600, 45, 46, 34, 0, 854, 855, 1055, 449, + 0, 0, 0, 0, 0, 0, 38, 39, 0, 40, + 41, 1123, 613, 614, 615, 616, 617, 618, 619, 0, + 620, 621, 622, 623, 624, 601, 602, 603, 604, 585, + 586, 1197, 0, 588, 0, 589, 590, 591, 592, 593, + 594, 595, 596, 597, 598, 605, 606, 607, 608, 609, + 610, 611, 612, 1155, 0, 174, 174, 0, 0, 174, + 732, 881, 174, 1214, 0, 0, 644, 0, 1166, 1167, + 1168, 0, 1219, 0, 0, 0, 898, 49, 1103, 441, + 0, 633, 634, 0, 0, 637, 174, 0, 640, 0, + 0, 0, 0, 0, 1186, 1187, 1188, 1189, 0, 0, + 0, 0, 0, 0, 0, 174, 0, 0, 0, 0, + 0, 0, 656, 0, 644, 475, 474, 484, 485, 477, + 478, 479, 480, 481, 482, 483, 476, 0, 0, 486, + 0, 675, 0, 0, 1208, 0, 0, 0, 0, 1213, + 0, 0, 0, 0, 0, 0, 0, 1217, 0, 0, + 0, 0, 0, 0, 0, 222, 0, 0, 0, 0, + 222, 222, 0, 0, 733, 733, 222, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1235, 1236, 441, + 222, 222, 222, 222, 0, 174, 1107, 733, 174, 174, + 174, 174, 174, 0, 0, 0, 0, 0, 0, 0, + 765, 0, 0, 174, 0, 0, 0, 560, 0, 0, + 0, 748, 174, 174, 0, 475, 474, 484, 485, 477, + 478, 479, 480, 481, 482, 483, 476, 0, 0, 486, + 0, 0, 0, 0, 1024, 0, 0, 0, 0, 776, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1039, + 1040, 0, 0, 1041, 1104, 0, 1043, 0, 475, 474, 484, 485, 477, 478, 479, 480, 481, 482, 483, 476, - 852, 853, 486, 449, 300, 0, 300, 1051, 0, 0, - 183, 189, 191, 192, 193, 194, 0, 0, 197, 196, - 0, 0, 0, 0, 0, 0, 0, 0, 782, 0, - 782, 0, 0, 0, 174, 0, 174, 0, 0, 1077, - 0, 0, 174, 0, 0, 0, 0, 0, 0, 174, - 0, 1100, 1079, 1146, 1147, 0, 1148, 1149, 1150, 1082, - 1099, 441, 300, 0, 0, 879, 0, 0, 0, 0, - 0, 0, 0, 0, 409, 0, 410, 0, 0, 0, - 896, 0, 417, 0, 0, 0, 992, 0, 0, 419, - 0, 0, 0, 0, 0, 0, 0, 475, 474, 484, - 485, 477, 478, 479, 480, 481, 482, 483, 476, 998, - 0, 486, 0, 0, 1119, 0, 1119, 1119, 1119, 0, - 1124, 0, 300, 475, 474, 484, 485, 477, 478, 479, - 480, 481, 482, 483, 476, 0, 0, 486, 0, 0, - 0, 995, 0, 0, 0, 0, 782, 0, 300, 300, - 300, 174, 0, 0, 0, 0, 1044, 0, 174, 560, - 174, 475, 474, 484, 485, 477, 478, 479, 480, 481, - 482, 483, 476, 961, 782, 486, 0, 0, 0, 0, - 0, 1229, 0, 874, 0, 0, 0, 0, 0, 1158, - 1159, 538, 0, 0, 0, 0, 0, 0, 0, 0, - 562, 0, 1051, 475, 474, 484, 485, 477, 478, 479, - 480, 481, 482, 483, 476, 1119, 0, 486, 0, 0, - 0, 0, 0, 0, 0, 1085, 0, 0, 0, 0, - 0, 0, 1087, 0, 0, 1193, 0, 1021, 0, 0, - 0, 0, 0, 1096, 1097, 1098, 0, 0, 1101, 0, - 0, 0, 1036, 1037, 0, 0, 1038, 0, 0, 1040, - 0, 1111, 1112, 1113, 731, 1116, 0, 1210, 0, 0, - 0, 0, 0, 0, 0, 0, 1215, 174, 174, 0, - 0, 174, 0, 0, 174, 0, 0, 0, 643, 475, - 474, 484, 485, 477, 478, 479, 480, 481, 482, 483, - 476, 0, 0, 486, 0, 0, 0, 0, 174, 0, - 0, 0, 0, 0, 0, 0, 0, 632, 633, 0, - 0, 636, 0, 0, 639, 0, 0, 174, 0, 0, - 0, 0, 0, 0, 0, 0, 643, 1151, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 655, 0, - 0, 0, 1162, 1163, 1164, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1107, 0, 0, 674, 0, 0, - 0, 510, 0, 0, 0, 0, 0, 222, 1182, 1183, - 1184, 1185, 222, 222, 0, 0, 732, 732, 222, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 222, 222, 222, 222, 0, 174, 0, 732, - 174, 174, 174, 174, 174, 0, 0, 0, 1204, 0, - 0, 0, 764, 1209, 0, 174, 0, 0, 0, 560, - 0, 1213, 0, 174, 174, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 747, 0, 0, + 0, 0, 486, 0, 0, 174, 0, 121, 0, 0, + 0, 0, 0, 0, 174, 0, 92, 174, 0, 0, + 0, 104, 0, 106, 0, 0, 134, 114, 0, 0, + 0, 826, 0, 0, 0, 0, 0, 0, 0, 644, + 850, 0, 0, 851, 0, 75, 0, 0, 0, 0, + 0, 222, 0, 0, 86, 0, 475, 474, 484, 485, + 477, 478, 479, 480, 481, 482, 483, 476, 0, 0, + 486, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 475, 474, 484, 485, 477, 478, 479, 480, 481, 482, + 483, 476, 1111, 0, 486, 0, 0, 0, 222, 510, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1231, 1232, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 774, 0, 0, 0, 0, 0, + 177, 0, 0, 0, 222, 126, 0, 0, 137, 97, + 96, 0, 0, 0, 88, 0, 131, 122, 149, 0, + 123, 130, 107, 141, 127, 148, 178, 155, 139, 154, + 78, 138, 147, 87, 132, 80, 145, 136, 112, 101, + 102, 79, 174, 129, 91, 95, 90, 120, 142, 143, + 89, 161, 83, 153, 82, 84, 152, 119, 140, 146, + 113, 110, 81, 144, 111, 109, 103, 93, 98, 124, + 108, 125, 99, 116, 115, 117, 998, 0, 0, 135, + 150, 162, 0, 0, 156, 157, 158, 159, 118, 85, + 100, 133, 0, 0, 0, 0, 475, 474, 484, 485, + 477, 478, 479, 480, 481, 482, 483, 476, 0, 77, + 486, 105, 160, 128, 94, 151, 474, 484, 485, 477, + 478, 479, 480, 481, 482, 483, 476, 174, 0, 486, + 0, 0, 0, 0, 0, 0, 0, 222, 0, 0, + 0, 1206, 510, 0, 0, 0, 0, 0, 222, 0, + 0, 0, 0, 991, 0, 0, 0, 0, 644, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 121, 0, 0, 0, 0, 0, 174, 0, 0, 92, - 0, 0, 0, 0, 104, 174, 106, 0, 174, 134, - 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1202, 510, 0, 0, 0, 0, 75, 0, - 643, 0, 0, 0, 0, 0, 824, 86, 0, 0, - 0, 0, 222, 0, 0, 848, 0, 0, 849, 0, + 0, 0, 470, 733, 473, 0, 0, 0, 0, 733, + 487, 488, 489, 490, 491, 492, 493, 876, 471, 472, + 469, 475, 474, 484, 485, 477, 478, 479, 480, 481, + 482, 483, 476, 0, 0, 486, 0, 475, 474, 484, + 485, 477, 478, 479, 480, 481, 482, 483, 476, 0, + 0, 486, 0, 0, 0, 0, 0, 174, 475, 474, + 484, 485, 477, 478, 479, 480, 481, 482, 483, 476, + 0, 0, 486, 0, 0, 0, 0, 0, 0, 174, + 0, 0, 0, 1077, 0, 0, 0, 0, 0, 0, + 0, 174, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1084, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 475, 474, 484, 485, 477, 478, 479, - 480, 481, 482, 483, 476, 0, 0, 486, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, - 0, 0, 0, 177, 0, 0, 0, 0, 126, 0, - 0, 137, 97, 96, 0, 222, 0, 88, 0, 131, - 122, 149, 0, 123, 130, 107, 141, 127, 148, 178, - 155, 139, 154, 78, 138, 147, 87, 132, 80, 145, - 136, 112, 101, 102, 79, 0, 129, 91, 95, 90, - 120, 142, 143, 89, 161, 83, 153, 82, 84, 152, - 119, 140, 146, 113, 110, 81, 144, 111, 109, 103, - 93, 98, 124, 108, 125, 99, 116, 115, 117, 0, - 0, 0, 135, 150, 162, 0, 0, 156, 157, 158, - 159, 118, 85, 100, 133, 0, 0, 0, 0, 0, - 0, 23, 24, 48, 26, 27, 0, 0, 0, 0, - 0, 0, 77, 0, 105, 160, 128, 94, 151, 0, - 42, 0, 0, 0, 0, 28, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 174, 0, 0, - 0, 0, 0, 0, 37, 0, 0, 222, 50, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 222, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 643, 0, - 0, 0, 0, 0, 0, 0, 0, 988, 0, 0, - 0, 0, 0, 732, 0, 0, 0, 0, 0, 732, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 30, 31, 33, - 32, 35, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 36, 43, 44, - 0, 0, 45, 46, 34, 0, 174, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 38, 39, 0, 40, - 41, 0, 0, 0, 0, 0, 0, 0, 174, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 174, 0, 0, 0, 0, 0, 1073, 0, 0, 0, - 0, 0, 0, 470, 0, 473, 0, 0, 0, 0, - 0, 487, 488, 489, 490, 491, 492, 493, 1080, 471, - 472, 469, 475, 474, 484, 485, 477, 478, 479, 480, - 481, 482, 483, 476, 0, 0, 486, 49, 0, 0, - 0, 0, 0, 0, 560, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 560, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 386, 376, 0, 348, - 388, 326, 340, 396, 341, 342, 369, 312, 356, 121, - 338, 0, 329, 307, 335, 308, 327, 350, 92, 353, - 325, 378, 359, 104, 394, 106, 364, 0, 134, 114, - 0, 0, 352, 380, 354, 374, 347, 370, 317, 363, - 389, 339, 367, 390, 0, 0, 0, 75, 0, 783, - 784, 0, 0, 0, 0, 0, 86, 0, 366, 385, - 337, 368, 306, 365, 0, 310, 313, 395, 383, 332, - 333, 931, 0, 0, 0, 0, 0, 0, 351, 355, - 371, 345, 0, 0, 0, 0, 0, 0, 0, 0, - 330, 0, 362, 0, 0, 0, 314, 311, 0, 349, - 0, 0, 0, 316, 0, 331, 372, 0, 305, 375, - 381, 346, 177, 384, 344, 343, 387, 126, 0, 732, - 137, 97, 96, 379, 328, 336, 88, 334, 131, 122, - 149, 361, 123, 130, 107, 141, 127, 148, 178, 155, - 139, 154, 78, 138, 147, 87, 132, 80, 145, 136, - 112, 101, 102, 79, 0, 129, 91, 95, 90, 120, - 142, 143, 89, 161, 83, 153, 82, 84, 152, 119, - 140, 146, 113, 110, 81, 144, 111, 109, 103, 93, - 98, 124, 108, 125, 99, 116, 115, 117, 0, 309, - 0, 135, 150, 162, 324, 382, 156, 157, 158, 159, - 118, 85, 100, 133, 320, 323, 318, 319, 357, 358, - 391, 392, 393, 373, 315, 0, 321, 322, 0, 377, - 360, 77, 0, 105, 160, 128, 94, 151, 386, 376, + 0, 0, 0, 0, 0, 0, 0, 0, 386, 376, 0, 348, 388, 326, 340, 396, 341, 342, 369, 312, 356, 121, 338, 0, 329, 307, 335, 308, 327, 350, 92, 353, 325, 378, 359, 104, 394, 106, 364, 0, 134, 114, 0, 0, 352, 380, 354, 374, 347, 370, 317, 363, 389, 339, 367, 390, 0, 0, 0, 75, - 0, 783, 784, 0, 0, 0, 0, 0, 86, 0, + 0, 785, 786, 0, 0, 0, 0, 0, 86, 0, 366, 385, 337, 368, 306, 365, 0, 310, 313, 395, - 383, 332, 333, 0, 0, 0, 0, 0, 0, 0, + 383, 332, 333, 934, 0, 0, 0, 0, 0, 0, 351, 355, 371, 345, 0, 0, 0, 0, 0, 0, 0, 0, 330, 0, 362, 0, 0, 0, 314, 311, 0, 349, 0, 0, 0, 316, 0, 331, 372, 0, 305, 375, 381, 346, 177, 384, 344, 343, 387, 126, - 0, 0, 137, 97, 96, 379, 328, 336, 88, 334, + 0, 733, 137, 97, 96, 379, 328, 336, 88, 334, 131, 122, 149, 361, 123, 130, 107, 141, 127, 148, 178, 155, 139, 154, 78, 138, 147, 87, 132, 80, 145, 136, 112, 101, 102, 79, 0, 129, 91, 95, @@ -897,8 +877,8 @@ var yyAct = [...]int{ 369, 312, 356, 121, 338, 0, 329, 307, 335, 308, 327, 350, 92, 353, 325, 378, 359, 104, 394, 106, 364, 0, 134, 114, 0, 0, 352, 380, 354, 374, - 347, 370, 317, 363, 389, 339, 367, 390, 50, 0, - 0, 75, 0, 0, 0, 0, 0, 0, 0, 0, + 347, 370, 317, 363, 389, 339, 367, 390, 0, 0, + 0, 75, 0, 785, 786, 0, 0, 0, 0, 0, 86, 0, 366, 385, 337, 368, 306, 365, 0, 310, 313, 395, 383, 332, 333, 0, 0, 0, 0, 0, 0, 0, 351, 355, 371, 345, 0, 0, 0, 0, @@ -921,11 +901,11 @@ var yyAct = [...]int{ 335, 308, 327, 350, 92, 353, 325, 378, 359, 104, 394, 106, 364, 0, 134, 114, 0, 0, 352, 380, 354, 374, 347, 370, 317, 363, 389, 339, 367, 390, - 0, 0, 0, 75, 0, 0, 0, 0, 0, 0, + 50, 0, 0, 75, 0, 0, 0, 0, 0, 0, 0, 0, 86, 0, 366, 385, 337, 368, 306, 365, 0, 310, 313, 395, 383, 332, 333, 0, 0, 0, 0, 0, 0, 0, 351, 355, 371, 345, 0, 0, - 0, 0, 0, 0, 991, 0, 330, 0, 362, 0, + 0, 0, 0, 0, 0, 0, 330, 0, 362, 0, 0, 0, 314, 311, 0, 349, 0, 0, 0, 316, 0, 331, 372, 0, 305, 375, 381, 346, 177, 384, 344, 343, 387, 126, 0, 0, 137, 97, 96, 379, @@ -944,11 +924,11 @@ var yyAct = [...]int{ 329, 307, 335, 308, 327, 350, 92, 353, 325, 378, 359, 104, 394, 106, 364, 0, 134, 114, 0, 0, 352, 380, 354, 374, 347, 370, 317, 363, 389, 339, - 367, 390, 0, 0, 0, 227, 0, 0, 0, 0, + 367, 390, 0, 0, 0, 75, 0, 0, 0, 0, 0, 0, 0, 0, 86, 0, 366, 385, 337, 368, 306, 365, 0, 310, 313, 395, 383, 332, 333, 0, 0, 0, 0, 0, 0, 0, 351, 355, 371, 345, - 0, 0, 0, 0, 0, 0, 683, 0, 330, 0, + 0, 0, 0, 0, 0, 0, 994, 0, 330, 0, 362, 0, 0, 0, 314, 311, 0, 349, 0, 0, 0, 316, 0, 331, 372, 0, 305, 375, 381, 346, 177, 384, 344, 343, 387, 126, 0, 0, 137, 97, @@ -967,11 +947,11 @@ var yyAct = [...]int{ 338, 0, 329, 307, 335, 308, 327, 350, 92, 353, 325, 378, 359, 104, 394, 106, 364, 0, 134, 114, 0, 0, 352, 380, 354, 374, 347, 370, 317, 363, - 389, 339, 367, 390, 0, 0, 0, 75, 0, 0, + 389, 339, 367, 390, 0, 0, 0, 227, 0, 0, 0, 0, 0, 0, 0, 0, 86, 0, 366, 385, 337, 368, 306, 365, 0, 310, 313, 395, 383, 332, 333, 0, 0, 0, 0, 0, 0, 0, 351, 355, - 371, 345, 0, 0, 0, 0, 0, 0, 0, 0, + 371, 345, 0, 0, 0, 0, 0, 0, 684, 0, 330, 0, 362, 0, 0, 0, 314, 311, 0, 349, 0, 0, 0, 316, 0, 331, 372, 0, 305, 375, 381, 346, 177, 384, 344, 343, 387, 126, 0, 0, @@ -990,7 +970,7 @@ var yyAct = [...]int{ 356, 121, 338, 0, 329, 307, 335, 308, 327, 350, 92, 353, 325, 378, 359, 104, 394, 106, 364, 0, 134, 114, 0, 0, 352, 380, 354, 374, 347, 370, - 317, 363, 389, 339, 367, 390, 0, 0, 0, 227, + 317, 363, 389, 339, 367, 390, 0, 0, 0, 75, 0, 0, 0, 0, 0, 0, 0, 0, 86, 0, 366, 385, 337, 368, 306, 365, 0, 310, 313, 395, 383, 332, 333, 0, 0, 0, 0, 0, 0, 0, @@ -1014,7 +994,7 @@ var yyAct = [...]int{ 327, 350, 92, 353, 325, 378, 359, 104, 394, 106, 364, 0, 134, 114, 0, 0, 352, 380, 354, 374, 347, 370, 317, 363, 389, 339, 367, 390, 0, 0, - 0, 75, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 227, 0, 0, 0, 0, 0, 0, 0, 0, 86, 0, 366, 385, 337, 368, 306, 365, 0, 310, 313, 395, 383, 332, 333, 0, 0, 0, 0, 0, 0, 0, 351, 355, 371, 345, 0, 0, 0, 0, @@ -1026,10 +1006,10 @@ var yyAct = [...]int{ 127, 148, 178, 155, 139, 154, 78, 138, 147, 87, 132, 80, 145, 136, 112, 101, 102, 79, 0, 129, 91, 95, 90, 120, 142, 143, 89, 161, 83, 153, - 82, 303, 152, 119, 140, 146, 113, 110, 81, 144, + 82, 84, 152, 119, 140, 146, 113, 110, 81, 144, 111, 109, 103, 93, 98, 124, 108, 125, 99, 116, 115, 117, 0, 309, 0, 135, 150, 162, 324, 382, - 156, 157, 158, 159, 304, 302, 100, 133, 320, 323, + 156, 157, 158, 159, 118, 85, 100, 133, 320, 323, 318, 319, 357, 358, 391, 392, 393, 373, 315, 0, 321, 322, 0, 377, 360, 77, 0, 105, 160, 128, 94, 151, 386, 376, 0, 348, 388, 326, 340, 396, @@ -1037,7 +1017,7 @@ var yyAct = [...]int{ 335, 308, 327, 350, 92, 353, 325, 378, 359, 104, 394, 106, 364, 0, 134, 114, 0, 0, 352, 380, 354, 374, 347, 370, 317, 363, 389, 339, 367, 390, - 0, 0, 0, 175, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 75, 0, 0, 0, 0, 0, 0, 0, 0, 86, 0, 366, 385, 337, 368, 306, 365, 0, 310, 313, 395, 383, 332, 333, 0, 0, 0, 0, 0, 0, 0, 351, 355, 371, 345, 0, 0, @@ -1049,10 +1029,10 @@ var yyAct = [...]int{ 107, 141, 127, 148, 178, 155, 139, 154, 78, 138, 147, 87, 132, 80, 145, 136, 112, 101, 102, 79, 0, 129, 91, 95, 90, 120, 142, 143, 89, 161, - 83, 153, 82, 84, 152, 119, 140, 146, 113, 110, + 83, 153, 82, 303, 152, 119, 140, 146, 113, 110, 81, 144, 111, 109, 103, 93, 98, 124, 108, 125, 99, 116, 115, 117, 0, 309, 0, 135, 150, 162, - 324, 382, 156, 157, 158, 159, 118, 85, 100, 133, + 324, 382, 156, 157, 158, 159, 304, 302, 100, 133, 320, 323, 318, 319, 357, 358, 391, 392, 393, 373, 315, 0, 321, 322, 0, 377, 360, 77, 0, 105, 160, 128, 94, 151, 386, 376, 0, 348, 388, 326, @@ -1060,7 +1040,7 @@ var yyAct = [...]int{ 329, 307, 335, 308, 327, 350, 92, 353, 325, 378, 359, 104, 394, 106, 364, 0, 134, 114, 0, 0, 352, 380, 354, 374, 347, 370, 317, 363, 389, 339, - 367, 390, 0, 0, 0, 75, 0, 0, 0, 0, + 367, 390, 0, 0, 0, 175, 0, 0, 0, 0, 0, 0, 0, 0, 86, 0, 366, 385, 337, 368, 306, 365, 0, 310, 313, 395, 383, 332, 333, 0, 0, 0, 0, 0, 0, 0, 351, 355, 371, 345, @@ -1072,79 +1052,80 @@ var yyAct = [...]int{ 123, 130, 107, 141, 127, 148, 178, 155, 139, 154, 78, 138, 147, 87, 132, 80, 145, 136, 112, 101, 102, 79, 0, 129, 91, 95, 90, 120, 142, 143, - 89, 161, 83, 153, 82, 303, 152, 119, 140, 146, + 89, 161, 83, 153, 82, 84, 152, 119, 140, 146, 113, 110, 81, 144, 111, 109, 103, 93, 98, 124, 108, 125, 99, 116, 115, 117, 0, 309, 0, 135, - 150, 162, 324, 382, 156, 157, 158, 159, 304, 302, - 297, 296, 320, 323, 318, 319, 357, 358, 391, 392, + 150, 162, 324, 382, 156, 157, 158, 159, 118, 85, + 100, 133, 320, 323, 318, 319, 357, 358, 391, 392, 393, 373, 315, 0, 321, 322, 0, 377, 360, 77, - 0, 105, 160, 128, 94, 151, 121, 0, 0, 719, - 0, 229, 0, 0, 0, 92, 0, 226, 0, 0, - 104, 268, 106, 0, 0, 134, 114, 0, 0, 0, - 0, 259, 260, 0, 0, 0, 0, 0, 0, 0, - 0, 50, 0, 0, 227, 247, 246, 249, 250, 251, - 252, 0, 0, 86, 248, 253, 254, 255, 0, 0, - 224, 240, 0, 267, 0, 0, 0, 0, 0, 0, + 0, 105, 160, 128, 94, 151, 386, 376, 0, 348, + 388, 326, 340, 396, 341, 342, 369, 312, 356, 121, + 338, 0, 329, 307, 335, 308, 327, 350, 92, 353, + 325, 378, 359, 104, 394, 106, 364, 0, 134, 114, + 0, 0, 352, 380, 354, 374, 347, 370, 317, 363, + 389, 339, 367, 390, 0, 0, 0, 75, 0, 0, + 0, 0, 0, 0, 0, 0, 86, 0, 366, 385, + 337, 368, 306, 365, 0, 310, 313, 395, 383, 332, + 333, 0, 0, 0, 0, 0, 0, 0, 351, 355, + 371, 345, 0, 0, 0, 0, 0, 0, 0, 0, + 330, 0, 362, 0, 0, 0, 314, 311, 0, 349, + 0, 0, 0, 316, 0, 331, 372, 0, 305, 375, + 381, 346, 177, 384, 344, 343, 387, 126, 0, 0, + 137, 97, 96, 379, 328, 336, 88, 334, 131, 122, + 149, 361, 123, 130, 107, 141, 127, 148, 178, 155, + 139, 154, 78, 138, 147, 87, 132, 80, 145, 136, + 112, 101, 102, 79, 0, 129, 91, 95, 90, 120, + 142, 143, 89, 161, 83, 153, 82, 303, 152, 119, + 140, 146, 113, 110, 81, 144, 111, 109, 103, 93, + 98, 124, 108, 125, 99, 116, 115, 117, 0, 309, + 0, 135, 150, 162, 324, 382, 156, 157, 158, 159, + 304, 302, 297, 296, 320, 323, 318, 319, 357, 358, + 391, 392, 393, 373, 315, 0, 321, 322, 0, 377, + 360, 77, 0, 105, 160, 128, 94, 151, 121, 0, + 0, 720, 0, 229, 0, 0, 0, 92, 0, 226, + 0, 0, 104, 268, 106, 0, 0, 134, 114, 0, + 0, 0, 0, 259, 260, 0, 0, 0, 0, 0, + 0, 0, 0, 50, 0, 0, 227, 247, 246, 249, + 250, 251, 252, 0, 0, 86, 248, 253, 254, 255, + 0, 0, 224, 240, 0, 267, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 237, 238, 220, 0, 0, 0, 279, - 0, 239, 0, 0, 235, 236, 241, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 177, - 0, 0, 277, 0, 126, 0, 0, 137, 97, 96, - 0, 0, 0, 88, 0, 131, 122, 149, 0, 123, - 130, 107, 141, 127, 148, 178, 155, 139, 154, 78, - 138, 147, 87, 132, 80, 145, 136, 112, 101, 102, - 79, 0, 129, 91, 95, 90, 120, 142, 143, 89, - 161, 83, 153, 82, 84, 152, 119, 140, 146, 113, - 110, 81, 144, 111, 109, 103, 93, 98, 124, 108, - 125, 99, 116, 115, 117, 0, 0, 0, 135, 150, - 162, 0, 0, 156, 157, 158, 159, 118, 85, 100, - 133, 269, 278, 275, 276, 273, 274, 272, 271, 270, - 280, 261, 262, 263, 264, 266, 0, 265, 77, 0, - 105, 160, 128, 94, 151, 121, 0, 0, 0, 0, - 229, 0, 0, 0, 92, 0, 226, 0, 0, 104, - 268, 106, 0, 0, 134, 114, 0, 0, 0, 0, - 259, 260, 0, 0, 0, 0, 0, 0, 0, 0, - 50, 0, 441, 227, 247, 246, 249, 250, 251, 252, - 0, 0, 86, 248, 253, 254, 255, 0, 0, 224, - 240, 0, 267, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 237, 238, 220, 0, 0, + 0, 279, 0, 239, 0, 0, 235, 236, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 237, 238, 0, 0, 0, 0, 279, 0, - 239, 0, 0, 235, 236, 241, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 177, 0, - 0, 277, 0, 126, 0, 0, 137, 97, 96, 0, - 0, 0, 88, 0, 131, 122, 149, 0, 123, 130, - 107, 141, 127, 148, 178, 155, 139, 154, 78, 138, - 147, 87, 132, 80, 145, 136, 112, 101, 102, 79, - 0, 129, 91, 95, 90, 120, 142, 143, 89, 161, - 83, 153, 82, 84, 152, 119, 140, 146, 113, 110, - 81, 144, 111, 109, 103, 93, 98, 124, 108, 125, - 99, 116, 115, 117, 0, 0, 0, 135, 150, 162, - 0, 0, 156, 157, 158, 159, 118, 85, 100, 133, - 269, 278, 275, 276, 273, 274, 272, 271, 270, 280, - 261, 262, 263, 264, 266, 0, 265, 77, 0, 105, - 160, 128, 94, 151, 121, 0, 0, 0, 0, 229, - 0, 0, 0, 92, 0, 226, 0, 0, 104, 268, - 106, 0, 0, 134, 114, 0, 0, 0, 0, 259, - 260, 0, 0, 0, 0, 0, 0, 0, 0, 50, - 0, 0, 227, 247, 246, 249, 250, 251, 252, 0, - 0, 86, 248, 253, 254, 255, 0, 0, 224, 240, - 0, 267, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 177, 0, 0, 277, 0, 126, 0, 0, 137, + 97, 96, 0, 0, 0, 88, 0, 131, 122, 149, + 0, 123, 130, 107, 141, 127, 148, 178, 155, 139, + 154, 78, 138, 147, 87, 132, 80, 145, 136, 112, + 101, 102, 79, 0, 129, 91, 95, 90, 120, 142, + 143, 89, 161, 83, 153, 82, 84, 152, 119, 140, + 146, 113, 110, 81, 144, 111, 109, 103, 93, 98, + 124, 108, 125, 99, 116, 115, 117, 0, 0, 0, + 135, 150, 162, 0, 0, 156, 157, 158, 159, 118, + 85, 100, 133, 269, 278, 275, 276, 273, 274, 272, + 271, 270, 280, 261, 262, 263, 264, 266, 0, 265, + 77, 0, 105, 160, 128, 94, 151, 121, 0, 0, + 0, 0, 229, 0, 0, 0, 92, 0, 226, 0, + 0, 104, 268, 106, 0, 0, 134, 114, 0, 0, + 0, 0, 259, 260, 0, 0, 0, 0, 0, 0, + 0, 0, 50, 0, 441, 227, 247, 246, 249, 250, + 251, 252, 0, 0, 86, 248, 253, 254, 255, 0, + 0, 224, 240, 0, 267, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 237, 238, 220, 0, 0, 0, 279, 0, 239, - 0, 0, 235, 236, 241, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 177, 0, 0, - 277, 0, 126, 0, 0, 137, 97, 96, 0, 0, - 0, 88, 0, 131, 122, 149, 0, 123, 130, 107, - 141, 127, 148, 178, 155, 139, 154, 78, 138, 147, - 87, 132, 80, 145, 136, 112, 101, 102, 79, 0, - 129, 91, 95, 90, 120, 142, 143, 89, 161, 83, - 153, 82, 84, 152, 119, 140, 146, 113, 110, 81, - 144, 111, 109, 103, 93, 98, 124, 108, 125, 99, - 116, 115, 117, 0, 0, 0, 135, 150, 162, 0, - 0, 156, 157, 158, 159, 118, 85, 100, 133, 269, - 278, 275, 276, 273, 274, 272, 271, 270, 280, 261, - 262, 263, 264, 266, 23, 265, 77, 0, 105, 160, - 128, 94, 151, 0, 0, 0, 121, 0, 0, 0, + 0, 0, 0, 0, 237, 238, 0, 0, 0, 0, + 279, 0, 239, 0, 0, 235, 236, 241, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 177, 0, 0, 277, 0, 126, 0, 0, 137, 97, + 96, 0, 0, 0, 88, 0, 131, 122, 149, 0, + 123, 130, 107, 141, 127, 148, 178, 155, 139, 154, + 78, 138, 147, 87, 132, 80, 145, 136, 112, 101, + 102, 79, 0, 129, 91, 95, 90, 120, 142, 143, + 89, 161, 83, 153, 82, 84, 152, 119, 140, 146, + 113, 110, 81, 144, 111, 109, 103, 93, 98, 124, + 108, 125, 99, 116, 115, 117, 0, 0, 0, 135, + 150, 162, 0, 0, 156, 157, 158, 159, 118, 85, + 100, 133, 269, 278, 275, 276, 273, 274, 272, 271, + 270, 280, 261, 262, 263, 264, 266, 0, 265, 77, + 0, 105, 160, 128, 94, 151, 121, 0, 0, 0, 0, 229, 0, 0, 0, 92, 0, 226, 0, 0, 104, 268, 106, 0, 0, 134, 114, 0, 0, 0, 0, 259, 260, 0, 0, 0, 0, 0, 0, 0, @@ -1152,7 +1133,7 @@ var yyAct = [...]int{ 252, 0, 0, 86, 248, 253, 254, 255, 0, 0, 224, 240, 0, 267, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 237, 238, 0, 0, 0, 0, 279, + 0, 0, 0, 237, 238, 220, 0, 0, 0, 279, 0, 239, 0, 0, 235, 236, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177, 0, 0, 277, 0, 126, 0, 0, 137, 97, 96, @@ -1165,196 +1146,181 @@ var yyAct = [...]int{ 125, 99, 116, 115, 117, 0, 0, 0, 135, 150, 162, 0, 0, 156, 157, 158, 159, 118, 85, 100, 133, 269, 278, 275, 276, 273, 274, 272, 271, 270, - 280, 261, 262, 263, 264, 266, 0, 265, 77, 0, - 105, 160, 128, 94, 151, 121, 0, 0, 0, 0, - 229, 0, 0, 0, 92, 0, 226, 0, 0, 104, - 268, 106, 0, 0, 134, 114, 0, 0, 0, 0, - 259, 260, 0, 0, 0, 0, 0, 0, 0, 0, - 50, 0, 0, 227, 247, 246, 249, 250, 251, 252, - 0, 0, 86, 248, 253, 254, 255, 0, 0, 224, - 240, 0, 267, 0, 0, 0, 0, 0, 0, 0, + 280, 261, 262, 263, 264, 266, 23, 265, 77, 0, + 105, 160, 128, 94, 151, 0, 0, 0, 121, 0, + 0, 0, 0, 229, 0, 0, 0, 92, 0, 226, + 0, 0, 104, 268, 106, 0, 0, 134, 114, 0, + 0, 0, 0, 259, 260, 0, 0, 0, 0, 0, + 0, 0, 0, 50, 0, 0, 227, 247, 246, 249, + 250, 251, 252, 0, 0, 86, 248, 253, 254, 255, + 0, 0, 224, 240, 0, 267, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 237, 238, 0, 0, 0, 0, 279, 0, - 239, 0, 0, 235, 236, 241, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 177, 0, - 0, 277, 0, 126, 0, 0, 137, 97, 96, 0, - 0, 0, 88, 0, 131, 122, 149, 0, 123, 130, - 107, 141, 127, 148, 178, 155, 139, 154, 78, 138, - 147, 87, 132, 80, 145, 136, 112, 101, 102, 79, - 0, 129, 91, 95, 90, 120, 142, 143, 89, 161, - 83, 153, 82, 84, 152, 119, 140, 146, 113, 110, - 81, 144, 111, 109, 103, 93, 98, 124, 108, 125, - 99, 116, 115, 117, 0, 0, 0, 135, 150, 162, - 0, 0, 156, 157, 158, 159, 118, 85, 100, 133, - 269, 278, 275, 276, 273, 274, 272, 271, 270, 280, - 261, 262, 263, 264, 266, 121, 265, 77, 0, 105, - 160, 128, 94, 151, 92, 0, 0, 0, 0, 104, - 268, 106, 0, 0, 134, 114, 0, 0, 0, 0, - 259, 260, 0, 0, 0, 0, 0, 0, 0, 0, - 50, 0, 0, 227, 247, 246, 249, 250, 251, 252, - 0, 0, 86, 248, 253, 254, 255, 0, 0, 0, - 240, 0, 267, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 237, 238, 0, 0, 0, + 0, 279, 0, 239, 0, 0, 235, 236, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 237, 238, 0, 0, 0, 0, 279, 0, - 239, 0, 0, 235, 236, 241, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 177, 0, - 0, 277, 0, 126, 0, 0, 137, 97, 96, 0, - 0, 0, 88, 0, 131, 122, 149, 1230, 123, 130, - 107, 141, 127, 148, 178, 155, 139, 154, 78, 138, - 147, 87, 132, 80, 145, 136, 112, 101, 102, 79, - 0, 129, 91, 95, 90, 120, 142, 143, 89, 161, - 83, 153, 82, 84, 152, 119, 140, 146, 113, 110, - 81, 144, 111, 109, 103, 93, 98, 124, 108, 125, - 99, 116, 115, 117, 0, 0, 0, 135, 150, 162, - 0, 0, 156, 157, 158, 159, 118, 85, 100, 133, - 269, 278, 275, 276, 273, 274, 272, 271, 270, 280, - 261, 262, 263, 264, 266, 121, 265, 77, 0, 105, - 160, 128, 94, 151, 92, 0, 0, 0, 0, 104, - 268, 106, 0, 0, 134, 114, 0, 0, 0, 0, - 259, 260, 0, 0, 0, 0, 0, 0, 0, 0, - 50, 0, 0, 227, 247, 246, 249, 250, 251, 252, - 0, 0, 86, 248, 253, 254, 255, 0, 0, 0, - 240, 0, 267, 0, 0, 0, 0, 0, 0, 0, + 0, 177, 0, 0, 277, 0, 126, 0, 0, 137, + 97, 96, 0, 0, 0, 88, 0, 131, 122, 149, + 0, 123, 130, 107, 141, 127, 148, 178, 155, 139, + 154, 78, 138, 147, 87, 132, 80, 145, 136, 112, + 101, 102, 79, 0, 129, 91, 95, 90, 120, 142, + 143, 89, 161, 83, 153, 82, 84, 152, 119, 140, + 146, 113, 110, 81, 144, 111, 109, 103, 93, 98, + 124, 108, 125, 99, 116, 115, 117, 0, 0, 0, + 135, 150, 162, 0, 0, 156, 157, 158, 159, 118, + 85, 100, 133, 269, 278, 275, 276, 273, 274, 272, + 271, 270, 280, 261, 262, 263, 264, 266, 0, 265, + 77, 0, 105, 160, 128, 94, 151, 121, 0, 0, + 0, 0, 229, 0, 0, 0, 92, 0, 226, 0, + 0, 104, 268, 106, 0, 0, 134, 114, 0, 0, + 0, 0, 259, 260, 0, 0, 0, 0, 0, 0, + 0, 0, 50, 0, 0, 227, 247, 246, 249, 250, + 251, 252, 0, 0, 86, 248, 253, 254, 255, 0, + 0, 224, 240, 0, 267, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 237, 238, 0, 0, 0, 0, 279, 0, - 239, 0, 0, 235, 236, 241, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 177, 0, - 0, 277, 0, 126, 0, 0, 137, 97, 96, 0, - 0, 0, 88, 0, 131, 122, 149, 0, 123, 130, - 107, 141, 127, 148, 178, 155, 139, 154, 78, 138, - 147, 87, 132, 80, 145, 136, 112, 101, 102, 79, - 0, 129, 91, 95, 90, 120, 142, 143, 89, 161, - 83, 153, 82, 84, 152, 119, 140, 146, 113, 110, - 81, 144, 111, 109, 103, 93, 98, 124, 108, 125, - 99, 116, 115, 117, 0, 0, 0, 135, 150, 162, - 0, 0, 156, 157, 158, 159, 118, 85, 100, 133, - 269, 278, 275, 276, 273, 274, 272, 271, 270, 280, - 261, 262, 263, 264, 266, 0, 265, 77, 0, 105, - 160, 128, 94, 151, 121, 0, 0, 0, 463, 0, - 0, 0, 0, 92, 0, 0, 0, 0, 104, 0, - 106, 0, 0, 134, 114, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 237, 238, 0, 0, 0, 0, + 279, 0, 239, 0, 0, 235, 236, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 75, 0, 465, 0, 0, 0, 0, 0, - 0, 86, 0, 0, 0, 0, 460, 459, 0, 0, + 177, 0, 0, 277, 0, 126, 0, 0, 137, 97, + 96, 0, 0, 0, 88, 0, 131, 122, 149, 0, + 123, 130, 107, 141, 127, 148, 178, 155, 139, 154, + 78, 138, 147, 87, 132, 80, 145, 136, 112, 101, + 102, 79, 0, 129, 91, 95, 90, 120, 142, 143, + 89, 161, 83, 153, 82, 84, 152, 119, 140, 146, + 113, 110, 81, 144, 111, 109, 103, 93, 98, 124, + 108, 125, 99, 116, 115, 117, 0, 0, 0, 135, + 150, 162, 0, 0, 156, 157, 158, 159, 118, 85, + 100, 133, 269, 278, 275, 276, 273, 274, 272, 271, + 270, 280, 261, 262, 263, 264, 266, 121, 265, 77, + 0, 105, 160, 128, 94, 151, 92, 0, 0, 0, + 0, 104, 268, 106, 0, 0, 134, 114, 0, 0, + 0, 0, 259, 260, 0, 0, 0, 0, 0, 0, + 0, 0, 50, 0, 0, 227, 247, 246, 249, 250, + 251, 252, 0, 0, 86, 248, 253, 254, 255, 0, + 0, 0, 240, 0, 267, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 461, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 237, 238, 0, 0, 0, 0, + 279, 0, 239, 0, 0, 235, 236, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 177, 0, 0, 277, 0, 126, 0, 0, 137, 97, + 96, 0, 0, 0, 88, 0, 131, 122, 149, 1234, + 123, 130, 107, 141, 127, 148, 178, 155, 139, 154, + 78, 138, 147, 87, 132, 80, 145, 136, 112, 101, + 102, 79, 0, 129, 91, 95, 90, 120, 142, 143, + 89, 161, 83, 153, 82, 84, 152, 119, 140, 146, + 113, 110, 81, 144, 111, 109, 103, 93, 98, 124, + 108, 125, 99, 116, 115, 117, 0, 0, 0, 135, + 150, 162, 0, 0, 156, 157, 158, 159, 118, 85, + 100, 133, 269, 278, 275, 276, 273, 274, 272, 271, + 270, 280, 261, 262, 263, 264, 266, 121, 265, 77, + 0, 105, 160, 128, 94, 151, 92, 0, 0, 0, + 0, 104, 268, 106, 0, 0, 134, 114, 0, 0, + 0, 0, 259, 260, 0, 0, 0, 0, 0, 0, + 0, 0, 50, 0, 0, 227, 247, 246, 249, 250, + 251, 252, 0, 0, 86, 248, 253, 254, 255, 0, + 0, 0, 240, 0, 267, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 177, 0, 0, - 0, 0, 126, 0, 0, 137, 97, 96, 0, 0, - 0, 88, 0, 131, 122, 149, 0, 123, 130, 107, - 141, 127, 148, 178, 155, 139, 154, 78, 138, 147, - 87, 132, 80, 145, 136, 112, 101, 102, 79, 0, - 129, 91, 95, 90, 120, 142, 143, 89, 161, 83, - 153, 82, 84, 152, 119, 140, 146, 113, 110, 81, - 144, 111, 109, 103, 93, 98, 124, 108, 125, 99, - 116, 115, 117, 0, 0, 0, 135, 150, 162, 0, - 121, 156, 157, 158, 159, 118, 85, 100, 133, 92, - 0, 0, 0, 0, 104, 0, 106, 0, 0, 134, - 114, 0, 0, 0, 0, 0, 77, 0, 105, 160, - 128, 94, 151, 0, 0, 0, 0, 0, 75, 0, - 0, 0, 0, 0, 0, 0, 0, 86, 0, 0, - 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 237, 238, 0, 0, 0, 0, + 279, 0, 239, 0, 0, 235, 236, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 177, 0, 0, 277, 0, 126, 0, 0, 137, 97, + 96, 0, 0, 0, 88, 0, 131, 122, 149, 0, + 123, 130, 107, 141, 127, 148, 178, 155, 139, 154, + 78, 138, 147, 87, 132, 80, 145, 136, 112, 101, + 102, 79, 0, 129, 91, 95, 90, 120, 142, 143, + 89, 161, 83, 153, 82, 84, 152, 119, 140, 146, + 113, 110, 81, 144, 111, 109, 103, 93, 98, 124, + 108, 125, 99, 116, 115, 117, 0, 0, 0, 135, + 150, 162, 0, 0, 156, 157, 158, 159, 118, 85, + 100, 133, 269, 278, 275, 276, 273, 274, 272, 271, + 270, 280, 261, 262, 263, 264, 266, 0, 265, 77, + 0, 105, 160, 128, 94, 151, 121, 0, 0, 0, + 463, 0, 0, 0, 0, 92, 0, 0, 0, 0, + 104, 0, 106, 0, 0, 134, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 75, 0, 465, 0, 0, 0, + 0, 0, 0, 86, 0, 0, 0, 0, 460, 459, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 461, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 71, 72, 0, 67, 0, 0, 0, 73, 126, 0, - 0, 137, 97, 96, 0, 0, 0, 88, 0, 131, - 122, 149, 0, 123, 130, 107, 141, 127, 148, 69, - 155, 139, 154, 78, 138, 147, 87, 132, 80, 145, - 136, 112, 101, 102, 79, 598, 129, 91, 95, 90, - 120, 142, 143, 89, 161, 83, 153, 82, 84, 152, - 119, 140, 146, 113, 110, 81, 144, 111, 109, 103, - 93, 98, 124, 108, 125, 99, 116, 115, 117, 0, - 0, 0, 135, 150, 162, 0, 0, 156, 157, 158, - 159, 118, 85, 100, 133, 0, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 77, 0, 105, 160, 128, 94, 151, 121, - 0, 586, 0, 559, 0, 0, 0, 0, 92, 0, - 0, 0, 0, 104, 0, 106, 0, 0, 134, 114, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 177, + 0, 0, 0, 0, 126, 0, 0, 137, 97, 96, + 0, 0, 0, 88, 0, 131, 122, 149, 0, 123, + 130, 107, 141, 127, 148, 178, 155, 139, 154, 78, + 138, 147, 87, 132, 80, 145, 136, 112, 101, 102, + 79, 0, 129, 91, 95, 90, 120, 142, 143, 89, + 161, 83, 153, 82, 84, 152, 119, 140, 146, 113, + 110, 81, 144, 111, 109, 103, 93, 98, 124, 108, + 125, 99, 116, 115, 117, 0, 0, 0, 135, 150, + 162, 0, 121, 156, 157, 158, 159, 118, 85, 100, + 133, 92, 0, 0, 0, 0, 104, 0, 106, 0, + 0, 134, 114, 0, 0, 0, 0, 0, 77, 0, + 105, 160, 128, 94, 151, 0, 0, 0, 0, 0, + 75, 0, 0, 0, 0, 0, 0, 0, 0, 86, + 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 599, 0, 0, 0, 0, 0, 0, 175, 0, 561, - 0, 0, 0, 0, 0, 0, 86, 0, 0, 0, - 0, 612, 613, 614, 615, 616, 617, 618, 0, 619, - 620, 621, 622, 623, 600, 601, 602, 603, 584, 585, - 0, 0, 587, 0, 588, 589, 590, 591, 592, 593, - 594, 595, 596, 597, 604, 605, 606, 607, 608, 609, - 610, 611, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 177, 0, 0, 0, 0, 126, 0, 0, - 137, 97, 96, 0, 0, 0, 88, 0, 131, 122, - 149, 0, 123, 130, 107, 141, 127, 148, 178, 155, - 139, 154, 78, 138, 147, 87, 132, 80, 145, 136, - 112, 101, 102, 79, 0, 129, 91, 95, 90, 120, - 142, 143, 89, 161, 83, 153, 82, 84, 152, 119, - 140, 146, 113, 110, 81, 144, 111, 109, 103, 93, - 98, 124, 108, 125, 99, 116, 115, 117, 0, 0, - 0, 135, 150, 162, 0, 0, 156, 157, 158, 159, - 118, 85, 100, 133, 0, 0, 0, 23, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, - 0, 77, 0, 105, 160, 128, 94, 151, 92, 0, - 0, 0, 0, 104, 0, 106, 0, 0, 134, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 50, 0, 0, 75, 0, 0, - 0, 0, 0, 0, 0, 0, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 71, 72, 0, 67, 0, 0, 0, 73, + 126, 0, 0, 137, 97, 96, 0, 0, 0, 88, + 0, 131, 122, 149, 0, 123, 130, 107, 141, 127, + 148, 69, 155, 139, 154, 78, 138, 147, 87, 132, + 80, 145, 136, 112, 101, 102, 79, 0, 129, 91, + 95, 90, 120, 142, 143, 89, 161, 83, 153, 82, + 84, 152, 119, 140, 146, 113, 110, 81, 144, 111, + 109, 103, 93, 98, 124, 108, 125, 99, 116, 115, + 117, 0, 0, 0, 135, 150, 162, 0, 0, 156, + 157, 158, 159, 118, 85, 100, 133, 0, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 77, 0, 105, 160, 128, 94, + 151, 121, 0, 0, 0, 559, 0, 0, 0, 0, + 92, 0, 0, 0, 0, 104, 0, 106, 0, 0, + 134, 114, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 175, + 0, 561, 0, 0, 0, 0, 0, 0, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 177, 0, 0, 0, 0, 126, 0, 0, - 137, 97, 96, 0, 0, 0, 88, 0, 131, 122, - 149, 0, 123, 130, 107, 141, 127, 148, 178, 155, - 139, 154, 78, 138, 147, 87, 132, 80, 145, 136, - 112, 101, 102, 79, 0, 129, 91, 95, 90, 120, - 142, 143, 89, 161, 83, 153, 82, 84, 152, 119, - 140, 146, 113, 110, 81, 144, 111, 109, 103, 93, - 98, 124, 108, 125, 99, 116, 115, 117, 0, 0, - 0, 135, 150, 162, 0, 0, 156, 157, 158, 159, - 118, 85, 100, 133, 0, 0, 0, 23, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, - 0, 77, 0, 105, 160, 128, 94, 151, 92, 0, - 0, 0, 0, 104, 0, 106, 0, 0, 134, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 50, 0, 0, 175, 0, 0, - 0, 0, 0, 0, 0, 0, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 177, 0, 0, 0, 0, 126, + 0, 0, 137, 97, 96, 0, 0, 0, 88, 0, + 131, 122, 149, 0, 123, 130, 107, 141, 127, 148, + 178, 155, 139, 154, 78, 138, 147, 87, 132, 80, + 145, 136, 112, 101, 102, 79, 0, 129, 91, 95, + 90, 120, 142, 143, 89, 161, 83, 153, 82, 84, + 152, 119, 140, 146, 113, 110, 81, 144, 111, 109, + 103, 93, 98, 124, 108, 125, 99, 116, 115, 117, + 0, 0, 0, 135, 150, 162, 0, 0, 156, 157, + 158, 159, 118, 85, 100, 133, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 121, 0, 77, 0, 105, 160, 128, 94, 151, + 92, 0, 0, 0, 0, 104, 0, 106, 0, 0, + 134, 114, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 50, 0, 0, 75, + 0, 0, 0, 0, 0, 0, 0, 0, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 177, 0, 0, 0, 0, 126, 0, 0, - 137, 97, 96, 0, 0, 0, 88, 0, 131, 122, - 149, 0, 123, 130, 107, 141, 127, 148, 178, 155, - 139, 154, 78, 138, 147, 87, 132, 80, 145, 136, - 112, 101, 102, 79, 0, 129, 91, 95, 90, 120, - 142, 143, 89, 161, 83, 153, 82, 84, 152, 119, - 140, 146, 113, 110, 81, 144, 111, 109, 103, 93, - 98, 124, 108, 125, 99, 116, 115, 117, 0, 0, - 0, 135, 150, 162, 0, 121, 156, 157, 158, 159, - 118, 85, 100, 133, 92, 0, 0, 0, 0, 104, - 0, 106, 0, 0, 134, 114, 0, 0, 0, 0, - 0, 77, 0, 105, 160, 128, 94, 151, 0, 0, - 0, 0, 0, 75, 0, 0, 670, 0, 0, 671, - 0, 0, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 177, 0, 0, 0, 0, 126, + 0, 0, 137, 97, 96, 0, 0, 0, 88, 0, + 131, 122, 149, 0, 123, 130, 107, 141, 127, 148, + 178, 155, 139, 154, 78, 138, 147, 87, 132, 80, + 145, 136, 112, 101, 102, 79, 0, 129, 91, 95, + 90, 120, 142, 143, 89, 161, 83, 153, 82, 84, + 152, 119, 140, 146, 113, 110, 81, 144, 111, 109, + 103, 93, 98, 124, 108, 125, 99, 116, 115, 117, + 0, 0, 0, 135, 150, 162, 0, 0, 156, 157, + 158, 159, 118, 85, 100, 133, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 177, 0, - 0, 0, 0, 126, 0, 0, 137, 97, 96, 0, - 0, 0, 88, 0, 131, 122, 149, 0, 123, 130, - 107, 141, 127, 148, 178, 155, 139, 154, 78, 138, - 147, 87, 132, 80, 145, 136, 112, 101, 102, 79, - 0, 129, 91, 95, 90, 120, 142, 143, 89, 161, - 83, 153, 82, 84, 152, 119, 140, 146, 113, 110, - 81, 144, 111, 109, 103, 93, 98, 124, 108, 125, - 99, 116, 115, 117, 0, 0, 0, 135, 150, 162, - 0, 121, 156, 157, 158, 159, 118, 85, 100, 133, - 92, 0, 573, 0, 0, 104, 0, 106, 0, 0, - 134, 114, 0, 0, 0, 0, 0, 77, 0, 105, - 160, 128, 94, 151, 0, 0, 0, 0, 0, 75, - 0, 572, 0, 0, 0, 0, 0, 0, 86, 0, + 0, 121, 0, 77, 0, 105, 160, 128, 94, 151, + 92, 0, 0, 0, 0, 104, 0, 106, 0, 0, + 134, 114, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 50, 0, 0, 175, + 0, 0, 0, 0, 0, 0, 0, 0, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -1368,51 +1334,51 @@ var yyAct = [...]int{ 90, 120, 142, 143, 89, 161, 83, 153, 82, 84, 152, 119, 140, 146, 113, 110, 81, 144, 111, 109, 103, 93, 98, 124, 108, 125, 99, 116, 115, 117, - 0, 0, 0, 135, 150, 162, 0, 0, 156, 157, - 158, 159, 118, 85, 100, 133, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 135, 150, 162, 0, 121, 156, 157, + 158, 159, 118, 85, 100, 133, 92, 0, 0, 0, + 0, 104, 0, 106, 0, 0, 134, 114, 0, 0, 0, 0, 0, 77, 0, 105, 160, 128, 94, 151, - 121, 0, 0, 0, 559, 0, 0, 0, 0, 92, - 0, 0, 0, 0, 104, 0, 106, 0, 0, 134, - 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 175, 0, - 561, 0, 0, 0, 0, 0, 0, 86, 0, 0, + 0, 0, 0, 0, 0, 75, 0, 0, 671, 0, + 0, 672, 0, 0, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 177, 0, 0, 0, 0, 126, 0, - 0, 137, 97, 96, 0, 0, 0, 88, 0, 131, - 122, 149, 0, 557, 130, 107, 141, 127, 148, 178, - 155, 139, 154, 78, 138, 147, 87, 132, 80, 145, - 136, 112, 101, 102, 79, 0, 129, 91, 95, 90, - 120, 142, 143, 89, 161, 83, 153, 82, 84, 152, - 119, 140, 146, 113, 110, 81, 144, 111, 109, 103, - 93, 98, 124, 108, 125, 99, 116, 115, 117, 0, - 0, 0, 135, 150, 162, 0, 121, 156, 157, 158, - 159, 118, 85, 100, 133, 92, 0, 0, 0, 0, - 104, 0, 106, 0, 0, 134, 114, 0, 0, 0, - 0, 0, 77, 0, 105, 160, 128, 94, 151, 0, - 0, 50, 0, 0, 175, 0, 0, 0, 0, 0, - 0, 0, 0, 86, 0, 0, 0, 0, 0, 0, + 177, 0, 0, 0, 0, 126, 0, 0, 137, 97, + 96, 0, 0, 0, 88, 0, 131, 122, 149, 0, + 123, 130, 107, 141, 127, 148, 178, 155, 139, 154, + 78, 138, 147, 87, 132, 80, 145, 136, 112, 101, + 102, 79, 0, 129, 91, 95, 90, 120, 142, 143, + 89, 161, 83, 153, 82, 84, 152, 119, 140, 146, + 113, 110, 81, 144, 111, 109, 103, 93, 98, 124, + 108, 125, 99, 116, 115, 117, 0, 0, 0, 135, + 150, 162, 0, 121, 156, 157, 158, 159, 118, 85, + 100, 133, 92, 0, 574, 0, 0, 104, 0, 106, + 0, 0, 134, 114, 0, 0, 0, 0, 0, 77, + 0, 105, 160, 128, 94, 151, 0, 0, 0, 0, + 0, 75, 0, 573, 0, 0, 0, 0, 0, 0, + 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 177, - 0, 0, 0, 0, 126, 0, 0, 137, 97, 96, - 0, 0, 0, 88, 0, 131, 122, 149, 0, 123, - 130, 107, 141, 127, 148, 178, 155, 139, 154, 78, - 138, 147, 87, 132, 80, 145, 136, 112, 101, 102, - 79, 0, 129, 91, 95, 90, 120, 142, 143, 89, - 161, 83, 153, 82, 84, 152, 119, 140, 146, 113, - 110, 81, 144, 111, 109, 103, 93, 98, 124, 108, - 125, 99, 116, 115, 117, 0, 0, 0, 135, 150, - 162, 0, 121, 156, 157, 158, 159, 118, 85, 100, - 133, 92, 0, 0, 0, 0, 104, 0, 106, 0, - 0, 134, 114, 0, 0, 0, 0, 0, 77, 0, - 105, 160, 128, 94, 151, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 177, 0, 0, 0, + 0, 126, 0, 0, 137, 97, 96, 0, 0, 0, + 88, 0, 131, 122, 149, 0, 123, 130, 107, 141, + 127, 148, 178, 155, 139, 154, 78, 138, 147, 87, + 132, 80, 145, 136, 112, 101, 102, 79, 0, 129, + 91, 95, 90, 120, 142, 143, 89, 161, 83, 153, + 82, 84, 152, 119, 140, 146, 113, 110, 81, 144, + 111, 109, 103, 93, 98, 124, 108, 125, 99, 116, + 115, 117, 0, 0, 0, 135, 150, 162, 0, 0, + 156, 157, 158, 159, 118, 85, 100, 133, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 77, 0, 105, 160, 128, + 94, 151, 121, 0, 0, 0, 559, 0, 0, 0, + 0, 92, 0, 0, 0, 0, 104, 0, 106, 0, + 0, 134, 114, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 175, 0, 561, 0, 0, 0, 0, 0, 0, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -1421,7 +1387,7 @@ var yyAct = [...]int{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177, 0, 0, 0, 0, 126, 0, 0, 137, 97, 96, 0, 0, 0, 88, - 0, 131, 122, 149, 0, 123, 130, 107, 141, 127, + 0, 131, 122, 149, 0, 557, 130, 107, 141, 127, 148, 178, 155, 139, 154, 78, 138, 147, 87, 132, 80, 145, 136, 112, 101, 102, 79, 0, 129, 91, 95, 90, 120, 142, 143, 89, 161, 83, 153, 82, @@ -1431,7 +1397,7 @@ var yyAct = [...]int{ 157, 158, 159, 118, 85, 100, 133, 92, 0, 0, 0, 0, 104, 0, 106, 0, 0, 134, 114, 0, 0, 0, 0, 0, 77, 0, 105, 160, 128, 94, - 151, 0, 0, 0, 0, 0, 75, 0, 465, 0, + 151, 0, 0, 50, 0, 0, 175, 0, 0, 0, 0, 0, 0, 0, 0, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -1446,57 +1412,57 @@ var yyAct = [...]int{ 143, 89, 161, 83, 153, 82, 84, 152, 119, 140, 146, 113, 110, 81, 144, 111, 109, 103, 93, 98, 124, 108, 125, 99, 116, 115, 117, 0, 0, 0, - 135, 150, 162, 0, 0, 156, 157, 158, 159, 118, - 85, 100, 133, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, - 77, 0, 105, 160, 128, 94, 151, 537, 92, 0, - 0, 0, 0, 104, 0, 106, 0, 0, 134, 114, + 135, 150, 162, 0, 121, 156, 157, 158, 159, 118, + 85, 100, 133, 92, 0, 0, 0, 0, 104, 0, + 106, 0, 0, 134, 114, 0, 0, 0, 0, 0, + 77, 0, 105, 160, 128, 94, 151, 0, 0, 0, + 0, 0, 175, 0, 561, 0, 0, 0, 0, 0, + 0, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 175, 0, 0, - 0, 0, 0, 0, 0, 0, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 177, 0, 0, + 0, 0, 126, 0, 0, 137, 97, 96, 0, 0, + 0, 88, 0, 131, 122, 149, 0, 123, 130, 107, + 141, 127, 148, 178, 155, 139, 154, 78, 138, 147, + 87, 132, 80, 145, 136, 112, 101, 102, 79, 0, + 129, 91, 95, 90, 120, 142, 143, 89, 161, 83, + 153, 82, 84, 152, 119, 140, 146, 113, 110, 81, + 144, 111, 109, 103, 93, 98, 124, 108, 125, 99, + 116, 115, 117, 0, 0, 0, 135, 150, 162, 0, + 121, 156, 157, 158, 159, 118, 85, 100, 133, 92, + 0, 0, 0, 0, 104, 0, 106, 0, 0, 134, + 114, 0, 0, 0, 0, 0, 77, 0, 105, 160, + 128, 94, 151, 0, 0, 0, 0, 0, 75, 0, + 465, 0, 0, 0, 0, 0, 0, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 177, 0, 0, 0, 0, 126, 0, 0, - 137, 97, 96, 0, 0, 0, 88, 0, 131, 122, - 149, 0, 123, 130, 107, 141, 127, 148, 178, 155, - 139, 154, 78, 138, 147, 87, 132, 80, 145, 136, - 112, 101, 102, 79, 0, 129, 91, 95, 90, 120, - 142, 143, 89, 161, 83, 153, 82, 84, 152, 119, - 140, 146, 113, 110, 81, 144, 111, 109, 103, 93, - 98, 124, 108, 125, 99, 116, 115, 117, 290, 0, - 0, 135, 150, 162, 0, 121, 156, 157, 158, 159, - 118, 85, 100, 133, 92, 0, 0, 0, 0, 104, - 0, 106, 0, 0, 134, 114, 0, 0, 0, 0, - 0, 77, 0, 105, 160, 128, 94, 151, 0, 0, - 0, 0, 0, 175, 0, 0, 0, 0, 0, 0, - 0, 0, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 177, 0, 0, 0, 0, 126, 0, + 0, 137, 97, 96, 0, 0, 0, 88, 0, 131, + 122, 149, 0, 123, 130, 107, 141, 127, 148, 178, + 155, 139, 154, 78, 138, 147, 87, 132, 80, 145, + 136, 112, 101, 102, 79, 0, 129, 91, 95, 90, + 120, 142, 143, 89, 161, 83, 153, 82, 84, 152, + 119, 140, 146, 113, 110, 81, 144, 111, 109, 103, + 93, 98, 124, 108, 125, 99, 116, 115, 117, 0, + 0, 0, 135, 150, 162, 0, 0, 156, 157, 158, + 159, 118, 85, 100, 133, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 177, 0, - 0, 0, 0, 126, 0, 0, 137, 97, 96, 0, - 0, 0, 88, 0, 131, 122, 149, 0, 123, 130, - 107, 141, 127, 148, 178, 155, 139, 154, 78, 138, - 147, 87, 132, 80, 145, 136, 112, 101, 102, 79, - 0, 129, 91, 95, 90, 120, 142, 143, 89, 161, - 83, 153, 82, 84, 152, 119, 140, 146, 113, 110, - 81, 144, 111, 109, 103, 93, 98, 124, 108, 125, - 99, 116, 115, 117, 0, 0, 0, 135, 150, 162, - 0, 121, 156, 157, 158, 159, 118, 85, 100, 133, + 0, 121, 77, 0, 105, 160, 128, 94, 151, 537, 92, 0, 0, 0, 0, 104, 0, 106, 0, 0, - 134, 114, 0, 0, 0, 0, 0, 77, 0, 105, - 160, 128, 94, 151, 0, 0, 0, 0, 0, 175, + 134, 114, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 175, 0, 0, 0, 0, 0, 0, 0, 0, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 172, 0, 177, 0, 0, 0, 0, 126, + 0, 0, 0, 0, 177, 0, 0, 0, 0, 126, 0, 0, 137, 97, 96, 0, 0, 0, 88, 0, 131, 122, 149, 0, 123, 130, 107, 141, 127, 148, 178, 155, 139, 154, 78, 138, 147, 87, 132, 80, @@ -1504,11 +1470,11 @@ var yyAct = [...]int{ 90, 120, 142, 143, 89, 161, 83, 153, 82, 84, 152, 119, 140, 146, 113, 110, 81, 144, 111, 109, 103, 93, 98, 124, 108, 125, 99, 116, 115, 117, - 0, 0, 0, 135, 150, 162, 0, 121, 156, 157, + 290, 0, 0, 135, 150, 162, 0, 121, 156, 157, 158, 159, 118, 85, 100, 133, 92, 0, 0, 0, 0, 104, 0, 106, 0, 0, 134, 114, 0, 0, 0, 0, 0, 77, 0, 105, 160, 128, 94, 151, - 0, 0, 0, 0, 0, 75, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 175, 0, 0, 0, 0, 0, 0, 0, 0, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -1527,13 +1493,13 @@ var yyAct = [...]int{ 100, 133, 92, 0, 0, 0, 0, 104, 0, 106, 0, 0, 134, 114, 0, 0, 0, 0, 0, 77, 0, 105, 160, 128, 94, 151, 0, 0, 0, 0, - 0, 227, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 175, 0, 0, 0, 0, 0, 0, 0, 0, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 177, 0, 0, 0, + 0, 0, 0, 0, 172, 0, 177, 0, 0, 0, 0, 126, 0, 0, 137, 97, 96, 0, 0, 0, 88, 0, 131, 122, 149, 0, 123, 130, 107, 141, 127, 148, 178, 155, 139, 154, 78, 138, 147, 87, @@ -1545,7 +1511,7 @@ var yyAct = [...]int{ 156, 157, 158, 159, 118, 85, 100, 133, 92, 0, 0, 0, 0, 104, 0, 106, 0, 0, 134, 114, 0, 0, 0, 0, 0, 77, 0, 105, 160, 128, - 94, 151, 0, 0, 0, 0, 0, 175, 0, 0, + 94, 151, 0, 0, 0, 0, 0, 75, 0, 0, 0, 0, 0, 0, 0, 0, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -1560,21 +1526,59 @@ var yyAct = [...]int{ 142, 143, 89, 161, 83, 153, 82, 84, 152, 119, 140, 146, 113, 110, 81, 144, 111, 109, 103, 93, 98, 124, 108, 125, 99, 116, 115, 117, 0, 0, - 0, 135, 150, 162, 0, 0, 156, 157, 158, 159, - 118, 85, 100, 133, 0, 0, 0, 0, 0, 0, + 0, 135, 150, 162, 0, 121, 156, 157, 158, 159, + 118, 85, 100, 133, 92, 0, 0, 0, 0, 104, + 0, 106, 0, 0, 134, 114, 0, 0, 0, 0, + 0, 77, 0, 105, 160, 128, 94, 151, 0, 0, + 0, 0, 0, 227, 0, 0, 0, 0, 0, 0, + 0, 0, 86, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 177, 0, + 0, 0, 0, 126, 0, 0, 137, 97, 96, 0, + 0, 0, 88, 0, 131, 122, 149, 0, 123, 130, + 107, 141, 127, 148, 178, 155, 139, 154, 78, 138, + 147, 87, 132, 80, 145, 136, 112, 101, 102, 79, + 0, 129, 91, 95, 90, 120, 142, 143, 89, 161, + 83, 153, 82, 84, 152, 119, 140, 146, 113, 110, + 81, 144, 111, 109, 103, 93, 98, 124, 108, 125, + 99, 116, 115, 117, 0, 0, 0, 135, 150, 162, + 0, 121, 156, 157, 158, 159, 118, 85, 100, 133, + 92, 0, 0, 0, 0, 104, 0, 106, 0, 0, + 134, 114, 0, 0, 0, 0, 0, 77, 0, 105, + 160, 128, 94, 151, 0, 0, 0, 0, 0, 175, + 0, 0, 0, 0, 0, 0, 0, 0, 86, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 77, 0, 105, 160, 128, 94, 151, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 177, 0, 0, 0, 0, 126, + 0, 0, 137, 97, 96, 0, 0, 0, 88, 0, + 131, 122, 149, 0, 123, 130, 107, 141, 127, 148, + 178, 155, 139, 154, 78, 138, 147, 87, 132, 80, + 145, 136, 112, 101, 102, 79, 0, 129, 91, 95, + 90, 120, 142, 143, 89, 161, 83, 153, 82, 84, + 152, 119, 140, 146, 113, 110, 81, 144, 111, 109, + 103, 93, 98, 124, 108, 125, 99, 116, 115, 117, + 0, 0, 0, 135, 150, 162, 0, 0, 156, 157, + 158, 159, 118, 85, 100, 133, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 77, 0, 105, 160, 128, 94, 151, } var yyPact = [...]int{ - 2115, -1000, -176, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + 1495, -1000, -172, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, 737, 758, -1000, -1000, -1000, -1000, -1000, -1000, 554, + 6364, 20, 40, -21, 8735, 39, 178, 9293, -1000, -50, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, 514, -1000, -1000, + -1000, -1000, -1000, 727, 734, 567, 718, 646, -1000, 5098, + 14, 7780, 8549, 4441, -1000, 444, 34, 9293, -143, 8921, + 12, 12, 12, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, 737, 769, -1000, -1000, -1000, -1000, -1000, -1000, 582, - 6372, 26, 44, -11, 8743, 42, 1237, 9301, -1000, -37, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, 533, -1000, -1000, - -1000, -1000, -1000, 727, 733, 556, 717, 656, -1000, 5106, - 27, 7788, 8557, 4449, -1000, 444, 39, 9301, -128, 8929, - 22, 22, 22, -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, @@ -1582,22 +1586,22 @@ 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, -1000, 36, 9293, -1000, 9293, 9, 436, 9, + 9, 9, 9293, -1000, 68, -1000, -1000, -1000, -1000, 9293, + 427, 680, 27, 2817, 2817, 2817, 2817, -44, 2817, 2817, + 584, -1000, -1000, -1000, -1000, 2817, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, 365, 694, 5539, 5539, 737, + -1000, 514, -1000, -1000, -1000, 691, -1000, -1000, 190, 748, + -1000, 6178, 65, -1000, 5539, 2120, 500, -1000, -1000, 500, + -1000, -1000, 50, -1000, -1000, 5959, 5959, 5959, 5959, 5959, + 5959, 5959, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, 500, -1000, 5320, 500, + 500, 500, 500, 500, 500, 500, 500, 5539, 500, 500, + 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, + 500, 8363, 481, 793, -1000, -1000, -1000, 715, 7003, 7594, + 9293, 473, -1000, 510, 3977, -1000, -1000, -1000, 114, 7375, + -1000, -1000, -1000, 677, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, 41, 9301, -1000, 9301, 8, 439, 8, - 8, 8, 9301, -1000, 90, -1000, -1000, -1000, -1000, 9301, - 436, 682, 72, 2825, 2825, 2825, 2825, -32, 2825, 2825, - 602, -1000, -1000, -1000, -1000, 2825, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, 334, 691, 5547, 5547, 737, - -1000, 533, -1000, -1000, -1000, 686, -1000, -1000, 177, 751, - -1000, 6186, 89, -1000, 5547, 2231, 510, -1000, -1000, 510, - -1000, -1000, 67, -1000, -1000, 5967, 5967, 5967, 5967, 5967, - 5967, 5967, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, 510, -1000, 5328, 510, - 510, 510, 510, 510, 510, 510, 510, 5547, 510, 510, - 510, 510, 510, 510, 510, 510, 510, 510, 510, 510, - 510, 8371, 477, 750, -1000, -1000, -1000, 714, 7011, 7602, - 9301, 482, -1000, 500, 3985, -1000, -1000, -1000, 140, 7383, - -1000, -1000, -1000, 681, -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, @@ -1605,172 +1609,171 @@ 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, -1000, -1000, -1000, -1000, -1000, 426, -1000, 1496, + 421, 2817, 26, 530, 408, 154, 396, 9293, 9293, 2817, + 22, 9293, 711, 581, 9293, 389, 353, -1000, 4209, -1000, + 2817, 2817, 2817, 2817, 2817, 2817, 2817, 2817, -1000, -1000, + -1000, -1000, -1000, -1000, 2817, 2817, -1000, -1000, 9293, -1000, + -1000, -1000, -1000, 753, 93, 237, 61, 517, -1000, 321, + 727, 365, 646, 7189, 604, -1000, -1000, 9293, -1000, 5539, + 5539, 327, -1000, 8152, -1000, -1000, 3281, 101, 5959, 246, + 128, 5959, 5959, 5959, 5959, 5959, 5959, 5959, 5959, 5959, + 5959, 5959, 5959, 5959, 5959, 5959, 347, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, 348, -1000, 514, 429, 429, + 73, 73, 73, 73, 73, 73, 1899, 4660, 365, 419, + 138, 5320, 5098, 5098, 5539, 5539, 9107, 9107, 5098, 719, + 124, 138, 8921, -1000, 365, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, 5098, 5098, 5098, 5098, -9, 9293, -1000, 9107, + 7780, 7780, 7780, 7780, 7780, -1000, 634, 626, -1000, 597, + 596, 621, 9293, -1000, 414, 7003, 90, 500, -1000, 7966, + -1000, -1000, -9, 509, 7780, 9293, -1000, -1000, 3977, 510, + 5539, 44, -1000, -1000, -1000, -1000, 2585, 176, 239, -115, + -1000, -1000, -1000, 521, -1000, 521, 521, 521, 521, -85, + -85, -85, -85, -1000, -1000, -1000, -1000, -1000, 539, 537, + -1000, 521, 521, 521, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, 435, -1000, 6505, - 432, 2825, 31, 566, 406, 159, 387, 9301, 9301, 2825, - 29, 9301, 711, 601, 9301, 385, 376, -1000, 4217, -1000, - 2825, 2825, 2825, 2825, 2825, 2825, 2825, 2825, -1000, -1000, - -1000, -1000, -1000, -1000, 2825, 2825, -1000, -1000, 9301, -1000, - -1000, -1000, -1000, 764, 110, 445, 88, 501, -1000, 333, - 727, 334, 656, 7197, 613, -1000, -1000, 9301, -1000, 5547, - 5547, 300, -1000, 8160, -1000, -1000, 3289, 121, 5967, 234, - 135, 5967, 5967, 5967, 5967, 5967, 5967, 5967, 5967, 5967, - 5967, 5967, 5967, 5967, 5967, 5967, 227, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, 357, -1000, 533, 778, 778, - 76, 76, 76, 76, 76, 76, 1902, 4668, 334, 425, - 256, 5328, 5106, 5106, 5547, 5547, 9115, 9115, 5106, 720, - 145, 256, 8929, -1000, 334, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, 5106, 5106, 5106, 5106, -12, 9301, -1000, 9115, - 7788, 7788, 7788, 7788, 7788, -1000, 644, 642, -1000, 635, - 616, 634, 9301, -1000, 414, 7011, 81, 510, -1000, 7974, - -1000, -1000, -12, 7788, 9301, -1000, -1000, 3985, 500, 5547, - 75, -1000, -1000, -1000, -1000, 2593, 126, 272, -96, -1000, - -1000, -1000, 525, -1000, 525, 525, 525, 525, -63, -63, - -63, -63, -1000, -1000, -1000, -1000, -1000, 581, 574, -1000, - 525, 525, 525, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 551, - 551, 551, 535, 535, 584, -1000, 9301, -148, 355, 2825, - 709, 2825, -1000, 273, -1000, 9301, -1000, -1000, 9301, 2825, + 536, 536, 536, 522, 522, 557, -1000, 9293, -162, 341, + 2817, 710, 2817, -1000, 106, -1000, 9293, -1000, -1000, 9293, + 2817, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 660, 5539, + 5539, 3745, 5539, -1000, -1000, -1000, 694, -1000, 719, 732, + -1000, 672, 671, 5098, -1000, -1000, 101, 166, -1000, -1000, + 218, -1000, -1000, -1000, -1000, 60, 500, -1000, 2157, -1000, + -1000, -1000, -1000, 246, 5959, 5959, 5959, 1293, 2157, 2136, + 690, 2044, 73, 233, 233, 77, 77, 77, 77, 77, + 220, 220, -1000, -1000, -1000, 365, -1000, -1000, -1000, 365, + 5098, 495, -1000, -1000, 5539, -1000, 365, 406, 406, 392, + 266, 508, -1000, 59, 505, 406, 5098, 127, -1000, 5539, + 365, -1000, 406, 365, 406, 406, 464, 500, -1000, 506, + -1000, 111, 793, 529, 578, 629, -1000, -1000, -1000, -1000, + 625, -1000, 598, -1000, -1000, -1000, -1000, -1000, 33, 32, + 30, 8921, -1000, 746, 7780, 497, -1000, -1000, 138, -1000, + 337, 494, 2353, -1000, -1000, -1000, -1000, -1000, -1000, 526, + 702, 129, 136, 324, -1000, -1000, 686, -1000, 184, -120, + -1000, -1000, 268, -85, -85, -1000, -1000, 44, 676, 44, + 44, 44, 290, 290, -1000, -1000, -1000, -1000, 254, -1000, + -1000, -1000, 253, -1000, 577, 8921, 2817, -1000, 3513, -1000, + -1000, -1000, -1000, -1000, -1000, 754, 312, 123, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -10, + -1000, 2817, -1000, 651, 138, 138, 58, -1000, -1000, 9293, + -1000, -1000, -1000, -1000, 503, -1000, -1000, -1000, 3049, 5098, + -1000, 1293, 2157, 2025, -1000, 5959, 5959, -1000, -1000, 406, + 5098, 138, -1000, -1000, -1000, 28, 347, 28, 5959, 5959, + 3745, 5959, 5959, -153, 493, 119, -1000, 5539, 280, -1000, + -1000, -1000, -1000, -1000, 575, 9107, 500, -1000, 6793, 8921, + 737, 9107, 5539, 5539, -1000, -1000, 5539, 524, -1000, 5539, + -1000, -1000, -1000, 500, 500, 500, 379, -1000, 737, 497, + -1000, -1000, 2585, -1000, 2585, 8921, -1000, 303, 299, -1000, + -1000, 563, 29, -1000, -1000, -1000, 447, 44, 44, -1000, + 125, -1000, -1000, -1000, 402, -1000, 400, 485, 395, 9293, + -1000, -1000, 482, -1000, 100, -1000, -1000, 8921, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, 665, 5547, 5547, - 3753, 5547, -1000, -1000, -1000, 691, -1000, 720, 731, -1000, - 673, 671, 5106, -1000, -1000, 121, 148, -1000, -1000, 338, - -1000, -1000, -1000, -1000, 85, 510, -1000, 1628, -1000, -1000, - -1000, -1000, 234, 5967, 5967, 5967, 43, 1628, 1542, 280, - 220, 76, 294, 294, 100, 100, 100, 100, 100, 71, - 71, -1000, -1000, -1000, 334, -1000, -1000, -1000, 334, 5106, - 494, -1000, -1000, 5547, -1000, 334, 404, 404, 390, 276, - 541, -1000, 79, 527, 404, 5106, 150, -1000, 5547, 334, - -1000, 404, 334, 404, 404, 461, 510, -1000, 507, -1000, - 134, 750, 565, 599, 528, -1000, -1000, -1000, -1000, 623, - -1000, 622, -1000, -1000, -1000, -1000, -1000, 38, 35, 33, - 8929, -1000, 756, 506, -1000, -1000, 256, -1000, 342, 486, - 2361, -1000, -1000, -1000, -1000, -1000, -1000, 540, 699, 129, - 136, 314, -1000, -1000, 685, -1000, 166, -100, -1000, -1000, - 241, -63, -63, -1000, -1000, 75, 679, 75, 75, 75, - 287, 287, -1000, -1000, -1000, -1000, 240, -1000, -1000, -1000, - 232, -1000, 590, 8929, 2825, -1000, 3521, -1000, -1000, -1000, - -1000, -1000, -1000, 628, 356, 173, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -19, -1000, 2825, - -1000, 661, 256, 256, 74, -1000, -1000, 9301, -1000, -1000, - -1000, -1000, 499, -1000, -1000, -1000, 3057, 5106, -1000, 43, - 1628, 1500, -1000, 5967, 5967, -1000, -1000, 404, 5106, 256, - -1000, -1000, -1000, 123, 227, 123, 5967, 5967, 3753, 5967, - 5967, -142, 505, 137, -1000, 5547, 279, -1000, -1000, -1000, - -1000, -1000, 587, 9115, 510, -1000, 6801, 8929, 737, 9115, - 5547, 5547, -1000, -1000, 5547, 536, -1000, 5547, -1000, -1000, - -1000, 510, 510, 510, 383, -1000, 737, -1000, -1000, 2593, - -1000, 2593, 8929, -1000, 298, 281, -1000, -1000, 586, 37, - -1000, -1000, -1000, 451, 75, 75, -1000, 109, -1000, -1000, - -1000, 401, -1000, 399, 483, 396, 9301, -1000, -1000, 479, - -1000, 131, -1000, -1000, 8929, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, 8929, 9301, -1000, - -1000, -1000, -1000, -1000, 8929, -1000, -1000, 3521, -1000, 756, - 7788, -1000, -1000, 334, -1000, 5967, 1628, 1628, -1000, -1000, - 334, 525, 525, -1000, 525, 535, -1000, 525, -46, 525, - -47, 334, 334, 1436, 1462, -1000, 1143, 1327, 510, -139, - -1000, 256, 5547, -1000, 702, 454, 473, -1000, -1000, 4887, - 334, 391, 65, 383, 727, -1000, 256, 256, 256, 8929, - 256, 8929, 8929, 8929, 6591, 8929, 727, 2361, -1000, 364, - -1000, 525, -1000, -1000, -87, 763, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -63, 283, -63, - 209, -1000, 183, 2825, 3521, 2593, -1000, 512, -1000, -1000, - -1000, -1000, 704, 748, 476, -1000, 1628, -1000, -1000, 56, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 5967, - 5967, -1000, 5967, 5967, 5967, 334, 270, 256, 697, -1000, - 510, -1000, -1000, 496, 8929, 8929, -1000, -1000, 362, -1000, - 354, 354, 354, 81, -1000, -1000, 584, 8929, -1000, 128, - -1000, -113, 75, -1000, 75, 392, 384, -1000, -1000, -1000, - 8929, 510, 746, 729, -1000, -1000, 796, 796, 796, 796, - -26, -1000, -1000, 761, -1000, 510, -1000, 533, 53, -1000, - 8929, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 175, 696, - -1000, 695, -1000, -1000, -1000, -1000, -1000, 346, -20, -1000, - 5547, 5547, -1000, -1000, -1000, -1000, 334, 51, -152, 9115, - 473, 334, 8929, -1000, -1000, 250, -1000, -1000, 566, 297, - -1000, 8929, 256, 472, -1000, 659, -146, -157, 471, -1000, - -1000, -1000, -148, -1000, -20, 670, -1000, 649, -1000, -1000, - -1000, -23, -149, -25, -153, 510, -158, 5757, -1000, 796, - 334, -1000, -1000, + 8921, 9293, -1000, -1000, -1000, -1000, -1000, 8921, -1000, -1000, + 3513, -1000, 746, 7780, -1000, -1000, 365, -1000, 5959, 2157, + 2157, -1000, -1000, 365, 521, 521, -1000, 521, 522, -1000, + 521, -68, 521, -69, 365, 365, 1664, 1875, -1000, 1441, + 1807, 500, -150, -1000, 138, 5539, -1000, 704, 453, 461, + -1000, -1000, 4879, 365, 393, 57, 379, 727, -1000, 138, + 138, 138, 8921, 138, 8921, 8921, 8921, 6583, 8921, 727, + -1000, 2353, -1000, 376, -1000, 521, -1000, -1000, -108, 752, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -85, 289, -85, 241, -1000, 224, 2817, 3513, 2585, + -1000, 515, -1000, -1000, -1000, -1000, 696, 743, 474, -1000, + 2157, -1000, -1000, 48, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, 5959, 5959, -1000, 5959, 5959, 5959, 365, + 281, 138, 699, -1000, 500, -1000, -1000, 499, 8921, 8921, + -1000, -1000, 364, -1000, 352, 352, 352, 90, -1000, -1000, + 557, 8921, -1000, 110, -1000, -132, 44, -1000, 44, 446, + 420, -1000, -1000, -1000, 8921, 500, 741, 733, -1000, -1000, + 1764, 1764, 1764, 1764, 17, -1000, -1000, 751, -1000, 500, + -1000, 514, 47, -1000, 8921, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, 168, 695, -1000, 688, -1000, -1000, -1000, -1000, + -1000, 333, -16, -1000, 5539, 5539, -1000, -1000, -1000, -1000, + 365, 37, -165, 9107, 461, 365, 8921, -1000, -1000, 234, + -1000, -1000, 530, 316, -1000, 8921, 138, 456, -1000, 650, + -156, -168, 449, -1000, -1000, -1000, -162, -1000, -16, 670, + -1000, 644, -1000, -1000, -1000, -19, -163, -24, -166, 500, + -169, 5749, -1000, 1764, 365, -1000, -1000, } var yyPgo = [...]int{ - 0, 1007, 35, 501, 1006, 1005, 1004, 1003, 1001, 998, - 997, 994, 993, 992, 990, 989, 988, 987, 986, 985, - 982, 978, 977, 976, 98, 975, 974, 973, 47, 972, - 60, 966, 965, 29, 448, 32, 41, 771, 964, 18, - 87, 106, 963, 34, 960, 959, 957, 955, 63, 954, - 951, 1339, 950, 949, 13, 27, 948, 945, 944, 941, - 51, 383, 937, 936, 934, 921, 912, 911, 40, 3, - 5, 8, 14, 909, 222, 6, 904, 39, 903, 902, - 886, 885, 26, 883, 43, 882, 21, 42, 881, 9, - 50, 25, 20, 4, 58, 880, 28, 44, 878, 248, - 877, 133, 234, 875, 873, 871, 870, 54, 175, 504, - 528, 53, 854, 12, 853, 1299, 55, 45, 19, 849, - 46, 244, 33, 848, 847, 31, 846, 843, 841, 831, - 827, 826, 824, 57, 822, 821, 820, 16, 24, 817, - 816, 52, 23, 813, 812, 810, 30, 49, 809, 38, - 808, 806, 803, 22, 15, 790, 10, 788, 787, 7, - 785, 17, 784, 11, 783, 2, 37, 782, 780, 0, - 661, 779, 777, 59, + 0, 991, 10, 482, 990, 989, 988, 987, 986, 984, + 983, 982, 981, 980, 979, 978, 974, 972, 969, 968, + 967, 966, 965, 964, 101, 963, 958, 957, 52, 952, + 60, 950, 949, 31, 165, 35, 34, 976, 947, 22, + 64, 51, 946, 40, 945, 944, 61, 943, 54, 940, + 936, 1313, 935, 920, 14, 24, 914, 913, 911, 906, + 55, 175, 904, 900, 899, 898, 897, 894, 41, 5, + 9, 15, 17, 893, 80, 6, 892, 43, 891, 890, + 889, 888, 42, 887, 45, 878, 21, 44, 877, 8, + 47, 29, 27, 4, 63, 876, 26, 50, 875, 303, + 869, 123, 328, 868, 867, 866, 865, 32, 176, 506, + 429, 57, 864, 12, 859, 1287, 59, 53, 18, 858, + 28, 344, 30, 857, 856, 33, 854, 853, 850, 849, + 848, 843, 842, 258, 833, 828, 826, 25, 13, 822, + 820, 46, 38, 819, 818, 815, 37, 49, 814, 39, + 812, 811, 808, 23, 20, 805, 16, 802, 799, 7, + 794, 19, 793, 3, 778, 2, 36, 777, 776, 0, + 583, 773, 764, 102, } var yyR1 = [...]int{ 0, 167, 168, 168, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 6, 3, 4, 4, 5, - 5, 7, 7, 27, 27, 8, 9, 9, 171, 171, - 46, 46, 90, 90, 10, 10, 123, 123, 11, 11, - 11, 11, 11, 11, 11, 165, 165, 164, 163, 163, - 162, 162, 161, 16, 150, 151, 151, 151, 147, 126, - 126, 126, 126, 129, 129, 127, 127, 127, 127, 127, - 127, 127, 128, 128, 128, 128, 128, 130, 130, 130, - 130, 130, 131, 131, 131, 131, 131, 131, 131, 131, - 131, 131, 131, 131, 131, 131, 131, 132, 132, 132, - 132, 132, 132, 132, 132, 146, 146, 133, 133, 141, - 141, 142, 142, 142, 139, 139, 140, 140, 143, 143, - 143, 134, 134, 134, 134, 134, 134, 134, 136, 136, - 144, 144, 137, 137, 137, 138, 138, 145, 145, 145, - 145, 145, 135, 135, 148, 155, 155, 155, 155, 155, - 149, 149, 157, 157, 156, 152, 152, 152, 153, 153, - 153, 154, 154, 154, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 166, 166, 166, 166, 166, 166, 166, - 166, 166, 166, 166, 160, 158, 158, 159, 159, 13, - 14, 14, 14, 14, 14, 15, 15, 17, 18, 18, + 5, 7, 7, 27, 27, 8, 9, 9, 9, 171, + 171, 46, 46, 90, 90, 10, 10, 123, 123, 11, + 11, 11, 11, 11, 11, 11, 165, 165, 164, 163, + 163, 162, 162, 161, 16, 150, 151, 151, 151, 147, + 126, 126, 126, 126, 129, 129, 127, 127, 127, 127, + 127, 127, 127, 128, 128, 128, 128, 128, 130, 130, + 130, 130, 130, 131, 131, 131, 131, 131, 131, 131, + 131, 131, 131, 131, 131, 131, 131, 131, 132, 132, + 132, 132, 132, 132, 132, 132, 146, 146, 133, 133, + 141, 141, 142, 142, 142, 139, 139, 140, 140, 143, + 143, 143, 134, 134, 134, 134, 134, 134, 134, 136, + 136, 144, 144, 137, 137, 137, 138, 138, 145, 145, + 145, 145, 145, 135, 135, 148, 155, 155, 155, 155, + 155, 149, 149, 157, 157, 156, 152, 152, 152, 153, + 153, 153, 154, 154, 154, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 166, 166, 166, 166, 166, 166, + 166, 166, 166, 166, 166, 160, 158, 158, 159, 159, + 13, 14, 14, 14, 14, 14, 15, 15, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 124, 124, 124, 19, 19, 21, 21, 22, 23, - 20, 20, 20, 20, 20, 172, 24, 25, 25, 26, - 26, 26, 30, 30, 30, 28, 28, 29, 29, 35, - 35, 34, 34, 36, 36, 36, 36, 112, 112, 112, - 111, 111, 38, 38, 39, 39, 40, 40, 41, 41, - 41, 53, 53, 89, 89, 91, 91, 42, 42, 42, - 42, 43, 43, 44, 44, 45, 45, 119, 119, 118, - 118, 118, 117, 117, 47, 47, 47, 49, 48, 48, - 48, 48, 50, 50, 52, 52, 51, 51, 54, 54, - 54, 54, 55, 55, 37, 37, 37, 37, 37, 37, - 37, 100, 100, 57, 57, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 67, 67, 67, 67, 67, - 67, 58, 58, 58, 58, 58, 58, 58, 33, 33, - 68, 68, 68, 74, 69, 69, 61, 61, 61, 61, + 18, 18, 124, 124, 124, 19, 19, 21, 21, 22, + 23, 20, 20, 20, 20, 20, 172, 24, 25, 25, + 26, 26, 26, 30, 30, 30, 28, 28, 29, 29, + 35, 35, 34, 34, 36, 36, 36, 36, 112, 112, + 112, 111, 111, 38, 38, 39, 39, 40, 40, 41, + 41, 41, 53, 53, 89, 89, 91, 91, 42, 42, + 42, 42, 43, 43, 44, 44, 45, 45, 119, 119, + 118, 118, 118, 117, 117, 47, 47, 47, 49, 48, + 48, 48, 48, 50, 50, 52, 52, 51, 51, 54, + 54, 54, 54, 55, 55, 37, 37, 37, 37, 37, + 37, 37, 100, 100, 57, 57, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 67, 67, 67, 67, + 67, 67, 58, 58, 58, 58, 58, 58, 58, 33, + 33, 68, 68, 68, 74, 69, 69, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, - 61, 61, 61, 61, 61, 61, 61, 65, 65, 65, - 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, - 63, 63, 63, 63, 63, 64, 64, 64, 64, 64, - 64, 64, 64, 173, 173, 66, 66, 66, 66, 31, - 31, 31, 31, 31, 122, 122, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 78, - 78, 32, 32, 76, 76, 77, 79, 79, 75, 75, - 75, 60, 60, 60, 60, 60, 60, 60, 60, 62, - 62, 62, 80, 80, 81, 81, 82, 82, 83, 83, - 84, 85, 85, 85, 86, 86, 86, 86, 87, 87, - 87, 59, 59, 59, 59, 59, 59, 88, 88, 88, - 88, 92, 92, 70, 70, 72, 72, 71, 73, 93, - 93, 96, 94, 94, 97, 97, 95, 95, 95, 114, - 114, 114, 98, 98, 101, 101, 102, 102, 99, 99, - 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, - 104, 104, 104, 105, 105, 106, 106, 106, 113, 113, - 109, 109, 110, 110, 115, 115, 116, 116, 107, 107, + 61, 61, 61, 61, 61, 61, 61, 61, 65, 65, + 65, 63, 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 64, 64, 64, 64, + 64, 64, 64, 64, 173, 173, 66, 66, 66, 66, + 31, 31, 31, 31, 31, 122, 122, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 78, 78, 32, 32, 76, 76, 77, 79, 79, 75, + 75, 75, 60, 60, 60, 60, 60, 60, 60, 60, + 62, 62, 62, 80, 80, 81, 81, 82, 82, 83, + 83, 84, 85, 85, 85, 86, 86, 86, 86, 87, + 87, 87, 59, 59, 59, 59, 59, 59, 88, 88, + 88, 88, 92, 92, 70, 70, 72, 72, 71, 73, + 93, 93, 96, 94, 94, 97, 97, 95, 95, 95, + 114, 114, 114, 98, 98, 101, 101, 102, 102, 99, + 99, 103, 103, 103, 103, 103, 103, 103, 103, 103, + 103, 104, 104, 104, 105, 105, 106, 106, 106, 113, + 113, 109, 109, 110, 110, 115, 115, 116, 116, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, @@ -1780,6 +1783,7 @@ var yyR1 = [...]int{ 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, + 107, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, @@ -1787,68 +1791,67 @@ var yyR1 = [...]int{ 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 169, 170, - 120, 121, 121, 121, + 108, 108, 108, 108, 108, 108, 108, 108, 108, 169, + 170, 120, 121, 121, 121, } 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, 4, 6, 7, 5, 10, 1, 3, 1, - 3, 7, 8, 1, 1, 8, 8, 6, 1, 1, - 1, 3, 0, 4, 3, 4, 1, 1, 2, 8, - 4, 6, 5, 5, 5, 0, 2, 1, 0, 2, - 1, 3, 3, 4, 4, 1, 3, 3, 8, 3, - 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, - 1, 1, 2, 2, 2, 2, 2, 1, 2, 2, - 2, 1, 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, 2, 2, 2, 2, 2, 0, 3, - 0, 1, 0, 3, 3, 0, 2, 0, 2, 1, - 2, 1, 0, 2, 5, 2, 3, 3, 2, 2, - 1, 1, 1, 3, 2, 0, 1, 3, 1, 2, - 3, 1, 1, 1, 6, 7, 7, 12, 7, 7, - 7, 4, 5, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 7, 1, 3, 8, 8, 5, - 4, 6, 5, 4, 4, 3, 2, 3, 4, 4, - 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, - 4, 3, 3, 4, 2, 4, 2, 2, 2, 2, - 3, 0, 1, 1, 2, 1, 1, 2, 1, 1, - 2, 2, 2, 2, 2, 0, 2, 0, 2, 1, - 2, 2, 0, 1, 1, 0, 1, 0, 1, 0, - 1, 1, 3, 1, 2, 3, 5, 0, 1, 2, - 1, 1, 0, 2, 1, 3, 1, 1, 1, 3, - 3, 3, 7, 1, 3, 1, 3, 4, 4, 4, - 3, 2, 4, 0, 1, 0, 2, 0, 1, 0, - 1, 2, 1, 1, 1, 2, 2, 1, 2, 3, - 2, 3, 2, 2, 2, 1, 1, 3, 0, 5, - 5, 5, 0, 2, 1, 3, 3, 2, 3, 1, - 2, 0, 3, 1, 1, 3, 3, 4, 4, 5, - 3, 4, 5, 6, 2, 1, 2, 1, 2, 1, - 2, 1, 1, 1, 1, 1, 1, 1, 0, 2, - 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, - 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, - 2, 2, 3, 1, 1, 1, 1, 4, 5, 6, - 4, 4, 6, 6, 6, 6, 8, 8, 6, 8, - 8, 9, 7, 5, 4, 2, 2, 2, 2, 2, - 2, 2, 2, 0, 2, 4, 4, 4, 4, 0, - 3, 4, 7, 3, 1, 1, 2, 3, 3, 1, - 2, 2, 1, 2, 1, 2, 2, 1, 2, 0, - 1, 0, 2, 1, 2, 4, 0, 2, 1, 3, - 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, 2, 1, 3, 5, 4, 6, 1, 3, 3, - 5, 0, 5, 1, 3, 1, 2, 3, 1, 1, - 3, 3, 1, 3, 3, 3, 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, 0, 2, + 3, 7, 8, 1, 1, 8, 8, 7, 6, 1, + 1, 1, 3, 0, 4, 3, 4, 1, 1, 2, + 8, 4, 6, 5, 5, 5, 0, 2, 1, 0, + 2, 1, 3, 3, 4, 4, 1, 3, 3, 8, + 3, 1, 1, 1, 2, 1, 1, 1, 1, 1, + 1, 1, 1, 2, 2, 2, 2, 2, 1, 2, + 2, 2, 1, 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, 2, 2, 2, 2, 2, 0, + 3, 0, 1, 0, 3, 3, 0, 2, 0, 2, + 1, 2, 1, 0, 2, 5, 2, 3, 3, 2, + 2, 1, 1, 1, 3, 2, 0, 1, 3, 1, + 2, 3, 1, 1, 1, 6, 7, 7, 12, 7, + 7, 7, 4, 5, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 7, 1, 3, 8, 8, + 5, 4, 6, 5, 4, 4, 3, 2, 3, 4, + 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, + 3, 4, 3, 3, 4, 2, 4, 2, 2, 2, + 2, 3, 0, 1, 1, 2, 1, 1, 2, 1, + 1, 2, 2, 2, 2, 2, 0, 2, 0, 2, + 1, 2, 2, 0, 1, 1, 0, 1, 0, 1, + 0, 1, 1, 3, 1, 2, 3, 5, 0, 1, + 2, 1, 1, 0, 2, 1, 3, 1, 1, 1, + 3, 3, 3, 7, 1, 3, 1, 3, 4, 4, + 4, 3, 2, 4, 0, 1, 0, 2, 0, 1, + 0, 1, 2, 1, 1, 1, 2, 2, 1, 2, + 3, 2, 3, 2, 2, 2, 1, 1, 3, 0, + 5, 5, 5, 0, 2, 1, 3, 3, 2, 3, + 1, 2, 0, 3, 1, 1, 3, 3, 4, 4, + 5, 3, 4, 5, 6, 2, 1, 2, 1, 2, + 1, 2, 1, 1, 1, 1, 1, 1, 1, 0, + 2, 1, 1, 1, 3, 1, 3, 1, 1, 1, + 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, + 2, 2, 2, 3, 1, 1, 1, 1, 4, 5, + 6, 4, 4, 6, 6, 6, 6, 8, 8, 6, + 8, 8, 9, 7, 5, 4, 2, 2, 2, 2, + 2, 2, 2, 2, 0, 2, 4, 4, 4, 4, + 0, 3, 4, 7, 3, 1, 1, 2, 3, 3, + 1, 2, 2, 1, 2, 1, 2, 2, 1, 2, + 0, 1, 0, 2, 1, 2, 4, 0, 2, 1, + 3, 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, 2, 1, 3, 5, 4, 6, 1, 3, + 3, 5, 0, 5, 1, 3, 1, 2, 3, 1, + 1, 3, 3, 1, 3, 3, 3, 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, 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, @@ -1867,7 +1870,7 @@ var yyR2 = [...]int{ 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, - 0, 0, 1, 1, + 1, 0, 0, 1, 1, } var yyChk = [...]int{ @@ -1927,201 +1930,201 @@ var yyChk = [...]int{ -173, -173, -169, -169, -169, -169, -52, 26, -51, 30, 54, -47, -49, -48, -50, 41, 45, 47, 42, 43, 44, 48, -119, 22, -39, -169, -118, 141, -117, 22, - -115, 58, -51, -171, 54, 11, 52, 54, -94, 80, - -114, -109, 58, 29, 30, 55, 54, -126, -129, -131, - -130, -132, -127, -128, 173, 174, 106, 177, 179, 180, - 181, 182, 183, 184, 185, 186, 187, 188, 30, 135, - 169, 170, 171, 172, 189, 190, 191, 192, 193, 194, - 195, 196, 156, 157, 158, 159, 160, 161, 162, 164, - 165, 166, 167, 168, 56, -121, 121, -165, 52, 56, - 72, 56, -51, -51, -121, 122, -51, 23, 51, -51, - 56, 56, -116, -115, -107, -121, -121, -121, -121, -121, - -121, -121, -121, -121, -121, -51, 9, 90, 54, 18, - 109, 54, -85, 24, 25, -86, -170, -30, -62, -109, - 59, 62, -29, 42, -51, -37, -37, -67, 67, 72, - 68, 69, -111, 97, -116, -110, -107, -61, -68, -71, - -74, 63, 90, 88, 89, 74, -61, -61, -61, -61, + -115, 58, -51, -46, -171, 54, 11, 52, 54, -94, + 80, -114, -109, 58, 29, 30, 55, 54, -126, -129, + -131, -130, -132, -127, -128, 173, 174, 106, 177, 179, + 180, 181, 182, 183, 184, 185, 186, 187, 188, 30, + 135, 169, 170, 171, 172, 189, 190, 191, 192, 193, + 194, 195, 196, 156, 157, 158, 159, 160, 161, 162, + 164, 165, 166, 167, 168, 56, -121, 121, -165, 52, + 56, 72, 56, -51, -51, -121, 122, -51, 23, 51, + -51, 56, 56, -116, -115, -107, -121, -121, -121, -121, + -121, -121, -121, -121, -121, -121, -51, 9, 90, 54, + 18, 109, 54, -85, 24, 25, -86, -170, -30, -62, + -109, 59, 62, -29, 42, -51, -37, -37, -67, 67, + 72, 68, 69, -111, 97, -116, -110, -107, -61, -68, + -71, -74, 63, 90, 88, 89, 74, -61, -61, -61, -61, -61, -61, -61, -61, -61, -61, -61, -61, -61, - -61, -122, 56, 58, 56, -60, -60, -109, -35, 21, - -34, -36, -170, 54, -170, -2, -34, -34, -37, -37, - -75, -109, -115, -75, -34, -28, -76, -77, 76, -109, - -170, -34, -35, -34, -34, -90, 141, -51, -93, -96, - -75, -40, -41, -41, -40, -41, 41, 41, 41, 46, - 41, 46, 41, -48, -115, -170, -54, 49, 123, 50, - -169, -117, -90, -39, -51, -97, -37, -138, 105, -152, - -153, -154, -110, 58, 59, -147, -148, -155, 126, 129, - 125, -149, 120, 28, -143, 67, 72, -139, 201, -133, - 53, -133, -133, -133, -133, -137, 176, -137, -137, -137, - 53, 53, -133, -133, -133, -141, 53, -141, -141, -142, - 53, -142, -113, 52, -51, -163, 233, -164, 56, -121, - 23, -121, -103, 117, 114, 115, -160, 113, 198, 176, - 65, 29, 15, 223, 141, 236, 56, 142, -51, -51, - -121, 37, -37, -37, -116, -84, -87, -98, 19, 11, - 33, 33, -34, 67, 68, 69, 109, -169, -68, -61, - -61, -61, -33, 136, 71, -170, -170, -34, 54, -37, - -170, -170, -170, 54, 52, 22, 54, 11, 109, 54, - 11, -170, -34, -79, -77, 78, -37, -170, -170, -170, - -170, -170, -59, 30, 33, -2, -169, -169, -55, 54, - 12, 80, -44, -43, 51, 52, -45, 51, -43, 41, - 41, 120, 120, 120, -91, -109, -55, -55, 56, 54, - -154, 80, 53, 28, -149, -149, 56, 56, -134, 29, - 67, -140, 202, 59, -137, -137, -138, 30, -138, -138, - -138, -146, 58, -146, 59, 59, 51, -109, -121, -162, - -161, -110, -120, -166, 147, 127, 128, 131, 130, 56, - 120, 28, 126, 129, 141, 125, -166, 147, -104, -105, - 122, 22, 120, 28, 141, -121, 38, 109, -51, -38, - 11, 97, -110, -35, -33, 71, -61, -61, -170, -36, - -125, 106, 173, 135, 171, 167, 187, 178, 200, 169, - 201, -122, -125, -61, -61, -110, -61, -61, 230, -82, - 79, -37, 77, -92, 51, -93, -70, -72, -71, -169, - -2, -88, -109, -91, -82, -96, -37, -37, -37, 53, - -37, -169, -169, -169, -170, 54, -82, -153, -154, -157, - -156, -109, 56, 56, -136, 51, 58, 59, 60, 67, - 213, 66, 55, -138, -138, 56, 106, 55, 54, 55, - 54, 55, 54, -51, 54, 80, -120, -109, -120, -109, - -51, -120, -109, -55, -39, -170, -61, -170, -133, -133, - -133, -142, -133, 161, -133, 161, -170, -170, -170, 54, - 19, -170, 54, 19, -169, -32, 228, -37, 27, -92, - 54, -170, -170, -170, 54, 109, -170, -86, -89, -109, - -89, -89, -89, -118, -109, -86, 55, 54, -133, -144, - 198, 9, -137, 58, -137, 59, 59, -121, -161, -154, - 53, 26, -80, 13, -137, 56, -61, -61, -61, -61, - -61, -170, 58, 28, -72, 33, -2, -169, -109, -109, - 54, 55, -170, -170, -170, -54, -113, -156, -145, 126, - 28, 125, 213, -138, -138, 55, 55, -89, -169, -81, - 14, 16, -170, -170, -170, -170, -31, 90, 233, 9, - -70, -2, 109, -109, -135, 65, 28, 28, 55, -158, - -159, 141, -37, -69, -170, 231, 48, 234, -93, -170, - -109, 58, -165, -170, 54, -109, 38, 232, 235, -163, - -159, 33, 38, 143, 233, 144, 234, -169, 235, -61, - 140, -170, -170, + -61, -61, -122, 56, 58, 56, -60, -60, -109, -35, + 21, -34, -36, -170, 54, -170, -2, -34, -34, -37, + -37, -75, -109, -115, -75, -34, -28, -76, -77, 76, + -109, -170, -34, -35, -34, -34, -90, 141, -51, -93, + -96, -75, -40, -41, -41, -40, -41, 41, 41, 41, + 46, 41, 46, 41, -48, -115, -170, -54, 49, 123, + 50, -169, -117, -90, 52, -39, -51, -97, -37, -138, + 105, -152, -153, -154, -110, 58, 59, -147, -148, -155, + 126, 129, 125, -149, 120, 28, -143, 67, 72, -139, + 201, -133, 53, -133, -133, -133, -133, -137, 176, -137, + -137, -137, 53, 53, -133, -133, -133, -141, 53, -141, + -141, -142, 53, -142, -113, 52, -51, -163, 233, -164, + 56, -121, 23, -121, -103, 117, 114, 115, -160, 113, + 198, 176, 65, 29, 15, 223, 141, 236, 56, 142, + -51, -51, -121, 37, -37, -37, -116, -84, -87, -98, + 19, 11, 33, 33, -34, 67, 68, 69, 109, -169, + -68, -61, -61, -61, -33, 136, 71, -170, -170, -34, + 54, -37, -170, -170, -170, 54, 52, 22, 54, 11, + 109, 54, 11, -170, -34, -79, -77, 78, -37, -170, + -170, -170, -170, -170, -59, 30, 33, -2, -169, -169, + -55, 54, 12, 80, -44, -43, 51, 52, -45, 51, + -43, 41, 41, 120, 120, 120, -91, -109, -55, -39, + -55, 56, 54, -154, 80, 53, 28, -149, -149, 56, + 56, -134, 29, 67, -140, 202, 59, -137, -137, -138, + 30, -138, -138, -138, -146, 58, -146, 59, 59, 51, + -109, -121, -162, -161, -110, -120, -166, 147, 127, 128, + 131, 130, 56, 120, 28, 126, 129, 141, 125, -166, + 147, -104, -105, 122, 22, 120, 28, 141, -121, 38, + 109, -51, -38, 11, 97, -110, -35, -33, 71, -61, + -61, -170, -36, -125, 106, 173, 135, 171, 167, 187, + 178, 200, 169, 201, -122, -125, -61, -61, -110, -61, + -61, 230, -82, 79, -37, 77, -92, 51, -93, -70, + -72, -71, -169, -2, -88, -109, -91, -82, -96, -37, + -37, -37, 53, -37, -169, -169, -169, -170, 54, -82, + -55, -153, -154, -157, -156, -109, 56, 56, -136, 51, + 58, 59, 60, 67, 213, 66, 55, -138, -138, 56, + 106, 55, 54, 55, 54, 55, 54, -51, 54, 80, + -120, -109, -120, -109, -51, -120, -109, -55, -39, -170, + -61, -170, -133, -133, -133, -142, -133, 161, -133, 161, + -170, -170, -170, 54, 19, -170, 54, 19, -169, -32, + 228, -37, 27, -92, 54, -170, -170, -170, 54, 109, + -170, -86, -89, -109, -89, -89, -89, -118, -109, -86, + 55, 54, -133, -144, 198, 9, -137, 58, -137, 59, + 59, -121, -161, -154, 53, 26, -80, 13, -137, 56, + -61, -61, -61, -61, -61, -170, 58, 28, -72, 33, + -2, -169, -109, -109, 54, 55, -170, -170, -170, -54, + -113, -156, -145, 126, 28, 125, 213, -138, -138, 55, + 55, -89, -169, -81, 14, 16, -170, -170, -170, -170, + -31, 90, 233, 9, -70, -2, 109, -109, -135, 65, + 28, 28, 55, -158, -159, 141, -37, -69, -170, 231, + 48, 234, -93, -170, -109, 58, -165, -170, 54, -109, + 38, 232, 235, -163, -159, 33, 38, 143, 233, 144, + 234, -169, 235, -61, 140, -170, -170, } var yyDef = [...]int{ 0, -2, 2, -2, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, - 21, 476, 0, 245, 245, 245, 245, 245, 245, 0, - 545, 528, 0, 0, 0, 0, 231, 235, 236, 0, - 238, 239, 740, 740, 740, 740, 740, 0, 33, 34, - 738, 1, 3, 484, 0, 0, 249, 252, 247, 0, - 528, 0, 0, 0, 48, 0, 0, 728, 0, 729, - 526, 526, 526, 546, 547, 550, 551, 650, 651, 652, - 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, - 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, - 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, - 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, - 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, - 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, - 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, - 723, 724, 725, 726, 727, 730, 731, 732, 733, 734, - 735, 736, 737, 0, 0, 529, 0, 524, 0, 524, - 524, 524, 0, 206, 316, 554, 555, 728, 729, 0, - 0, 0, 0, 741, 741, 741, 741, 0, 741, 741, - 224, 226, 227, 228, 229, 741, 232, 233, 234, 237, - 240, 241, 242, 243, 244, 27, 488, 0, 0, 476, - 29, 0, 245, 250, 251, 255, 253, 254, 246, 0, - 263, 267, 0, 324, 0, 329, 331, -2, -2, 0, - 366, 367, 368, 369, 370, 0, 0, 0, 0, 0, - 0, 0, 393, 394, 395, 396, 461, 462, 463, 464, - 465, 466, 467, 468, 333, 334, 458, 508, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 449, 0, 423, - 423, 423, 423, 423, 423, 423, 423, 0, 0, 0, - 0, 0, 0, 274, 276, 277, 278, 297, 0, 299, - 0, 0, 40, 44, 0, 512, -2, -2, 0, 0, - 552, 553, -2, 657, -2, 558, 559, 560, 561, 562, - 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, - 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, - 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, - 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, - 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, - 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, - 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, - 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, - 643, 644, 645, 646, 647, 648, 649, 0, 65, 0, - 0, 741, 0, 55, 0, 0, 0, 0, 0, 741, - 0, 0, 0, 0, 0, 0, 0, 205, 0, 207, - 741, 741, 741, 741, 741, 741, 741, 741, 216, 742, - 743, 217, 218, 219, 741, 741, 221, 222, 0, 230, - 28, 739, 22, 0, 0, 485, 0, 477, 478, 481, - 484, 27, 252, 0, 257, 256, 248, 0, 264, 0, - 0, 0, 268, 0, 270, 271, 0, 327, 0, 0, + 21, 477, 0, 246, 246, 246, 246, 246, 246, 0, + 546, 529, 0, 0, 0, 0, 232, 236, 237, 0, + 239, 240, 741, 741, 741, 741, 741, 0, 33, 34, + 739, 1, 3, 485, 0, 0, 250, 253, 248, 0, + 529, 0, 0, 0, 49, 0, 0, 729, 0, 730, + 527, 527, 527, 547, 548, 551, 552, 651, 652, 653, + 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, + 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, + 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, + 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, + 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, + 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, + 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, + 724, 725, 726, 727, 728, 731, 732, 733, 734, 735, + 736, 737, 738, 0, 0, 530, 0, 525, 0, 525, + 525, 525, 0, 207, 317, 555, 556, 729, 730, 0, + 0, 0, 0, 742, 742, 742, 742, 0, 742, 742, + 225, 227, 228, 229, 230, 742, 233, 234, 235, 238, + 241, 242, 243, 244, 245, 27, 489, 0, 0, 477, + 29, 0, 246, 251, 252, 256, 254, 255, 247, 0, + 264, 268, 0, 325, 0, 330, 332, -2, -2, 0, + 367, 368, 369, 370, 371, 0, 0, 0, 0, 0, + 0, 0, 394, 395, 396, 397, 462, 463, 464, 465, + 466, 467, 468, 469, 334, 335, 459, 509, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 450, 0, 424, + 424, 424, 424, 424, 424, 424, 424, 0, 0, 0, + 0, 0, 0, 275, 277, 278, 279, 298, 0, 300, + 0, 0, 41, 45, 0, 513, -2, -2, 0, 0, + 553, 554, -2, 658, -2, 559, 560, 561, 562, 563, + 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, + 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, + 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, + 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, + 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, + 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, + 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, + 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, + 644, 645, 646, 647, 648, 649, 650, 0, 66, 0, + 0, 742, 0, 56, 0, 0, 0, 0, 0, 742, + 0, 0, 0, 0, 0, 0, 0, 206, 0, 208, + 742, 742, 742, 742, 742, 742, 742, 742, 217, 743, + 744, 218, 219, 220, 742, 742, 222, 223, 0, 231, + 28, 740, 22, 0, 0, 486, 0, 478, 479, 482, + 485, 27, 253, 0, 258, 257, 249, 0, 265, 0, + 0, 0, 269, 0, 271, 272, 0, 328, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 351, 352, 353, - 354, 355, 356, 357, 330, 0, 344, 0, 0, 0, - 386, 387, 388, 389, 390, 391, 0, 259, 27, 0, - 364, 0, 0, 0, 0, 0, 0, 0, 0, 255, - 0, 450, 0, 415, 0, 416, 417, 418, 419, 420, - 421, 422, 0, 259, 0, 0, 42, 0, 315, 0, - 0, 0, 0, 0, 0, 304, 0, 0, 307, 0, - 0, 0, 0, 298, 0, 0, 318, 696, 300, 0, - 302, 303, 42, 0, 0, 38, 39, 0, 45, 0, - 145, 519, 520, 521, 517, 165, 0, 128, 124, 70, - 71, 72, 117, 74, 117, 117, 117, 117, 142, 142, - 142, 142, 100, 101, 102, 103, 104, 0, 0, 87, - 117, 117, 117, 91, 107, 108, 109, 110, 111, 112, - 113, 114, 75, 76, 77, 78, 79, 80, 81, 119, - 119, 119, 121, 121, 548, 50, 0, 58, 0, 741, - 0, 741, 63, 0, 181, 0, 200, 525, 0, 741, - 203, 204, 317, 556, 557, 208, 209, 210, 211, 212, - 213, 214, 215, 220, 223, 225, 489, 0, 0, 0, - 0, 0, 480, 482, 483, 488, 30, 255, 0, 469, - 0, 0, 0, 258, 25, 325, 326, 328, 345, 0, - 347, 349, 269, 265, 0, 459, -2, 335, 336, 360, - 361, 362, 0, 0, 0, 0, 358, 340, 0, 371, + 0, 0, 0, 0, 0, 0, 0, 352, 353, 354, + 355, 356, 357, 358, 331, 0, 345, 0, 0, 0, + 387, 388, 389, 390, 391, 392, 0, 260, 27, 0, + 365, 0, 0, 0, 0, 0, 0, 0, 0, 256, + 0, 451, 0, 416, 0, 417, 418, 419, 420, 421, + 422, 423, 0, 260, 0, 0, 43, 0, 316, 0, + 0, 0, 0, 0, 0, 305, 0, 0, 308, 0, + 0, 0, 0, 299, 0, 0, 319, 697, 301, 0, + 303, 304, -2, 0, 0, 0, 39, 40, 0, 46, + 0, 146, 520, 521, 522, 518, 166, 0, 129, 125, + 71, 72, 73, 118, 75, 118, 118, 118, 118, 143, + 143, 143, 143, 101, 102, 103, 104, 105, 0, 0, + 88, 118, 118, 118, 92, 108, 109, 110, 111, 112, + 113, 114, 115, 76, 77, 78, 79, 80, 81, 82, + 120, 120, 120, 122, 122, 549, 51, 0, 59, 0, + 742, 0, 742, 64, 0, 182, 0, 201, 526, 0, + 742, 204, 205, 318, 557, 558, 209, 210, 211, 212, + 213, 214, 215, 216, 221, 224, 226, 490, 0, 0, + 0, 0, 0, 481, 483, 484, 489, 30, 256, 0, + 470, 0, 0, 0, 259, 25, 326, 327, 329, 346, + 0, 348, 350, 270, 266, 0, 460, -2, 336, 337, + 361, 362, 363, 0, 0, 0, 0, 359, 341, 0, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, - 382, 385, 434, 435, 0, 383, 384, 392, 0, 0, - 260, 261, 363, 0, 507, 27, 0, 0, 0, 0, - 0, 458, 0, 0, 0, 0, 456, 453, 0, 0, - 424, 0, 0, 0, 0, 0, 0, 314, 322, 509, - 0, 275, 293, 295, 0, 290, 305, 306, 308, 0, - 310, 0, 312, 313, 279, 280, 281, 0, 0, 0, - 0, 301, 322, 322, 41, 513, 514, 515, 0, 64, - 166, 168, 171, 172, 173, 66, 67, 0, 0, 0, - 0, 0, 160, 161, 131, 129, 0, 126, 125, 73, - 0, 142, 142, 94, 95, 145, 0, 145, 145, 145, - 0, 0, 88, 89, 90, 82, 0, 83, 84, 85, - 0, 86, 0, 0, 741, 52, 0, 56, 57, 53, - 527, 54, 740, 0, 0, 540, 182, 530, 531, 532, - 533, 534, 535, 536, 537, 538, 539, 0, 199, 741, - 202, 0, 486, 487, 0, 479, 23, 0, 522, 523, - 470, 471, 272, 346, 348, 350, 0, 259, 337, 358, - 341, 0, 338, 0, 0, 332, 397, 0, 0, 365, - -2, 400, 401, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 476, 0, 454, 0, 0, 414, 425, 426, - 427, 428, 501, 0, 0, -2, 0, 0, 476, 0, - 0, 0, 287, 294, 0, 0, 288, 0, 289, 309, - 311, 0, 0, 0, 0, 285, 476, 37, 146, 0, - 169, 0, 0, 155, 0, 0, 158, 159, 138, 0, - 130, 69, 127, 0, 145, 145, 96, 0, 97, 98, - 99, 0, 115, 0, 0, 0, 0, 549, 51, 59, - 60, 0, 174, 740, 0, 183, 184, 185, 186, 187, - 188, 189, 190, 191, 192, 193, 740, 0, 0, 740, - 541, 542, 543, 544, 0, 201, 490, 0, 24, 322, - 0, 266, 460, 0, 339, 0, 359, 342, 398, 262, - 0, 117, 117, 439, 117, 121, 442, 117, 444, 117, - 447, 0, 0, 0, 0, 459, 0, 0, 0, 451, - 413, 457, 0, 31, 0, 501, 491, 503, 505, 0, - 27, 0, 497, 0, 484, 510, 323, 511, 291, 0, - 296, 0, 0, 0, 299, 0, 484, 167, 170, 0, - 162, 117, 156, 157, 140, 0, 132, 133, 134, 135, - 136, 137, 118, 92, 93, 143, 144, 142, 0, 142, - 0, 122, 0, 741, 0, 0, 175, 0, 176, 178, - 179, 180, 0, 472, 273, 399, 343, 402, 436, 142, - 440, 441, 443, 445, 446, 448, 404, 403, 405, 0, - 0, 408, 0, 0, 0, 0, 0, 455, 0, 32, - 0, 506, -2, 0, 0, 0, 43, 35, 0, 283, - 0, 0, 0, 318, 286, 36, 548, 0, 164, 147, - 141, 0, 145, 116, 145, 0, 0, 49, 61, 62, - 0, 0, 474, 0, 437, 438, 0, 0, 0, 0, - 429, 412, 452, 0, 504, 0, -2, 0, 499, 498, - 0, 292, 319, 320, 321, 282, 154, 163, 152, 0, - 149, 151, 139, 105, 106, 120, 123, 0, 0, 26, - 0, 0, 406, 407, 409, 410, 0, 0, 0, 0, - 494, 27, 0, 284, 68, 0, 148, 150, 55, 0, - 195, 0, 475, 473, 411, 0, 0, 0, 502, -2, - 500, 153, 58, 194, 0, 0, 430, 0, 433, 177, - 196, 0, 431, 0, 0, 0, 0, 0, 432, 0, - 0, 197, 198, + 382, 383, 386, 435, 436, 0, 384, 385, 393, 0, + 0, 261, 262, 364, 0, 508, 27, 0, 0, 0, + 0, 0, 459, 0, 0, 0, 0, 457, 454, 0, + 0, 425, 0, 0, 0, 0, 0, 0, 315, 323, + 510, 0, 276, 294, 296, 0, 291, 306, 307, 309, + 0, 311, 0, 313, 314, 280, 281, 282, 0, 0, + 0, 0, 302, 323, 0, 323, 42, 514, 515, 516, + 0, 65, 167, 169, 172, 173, 174, 67, 68, 0, + 0, 0, 0, 0, 161, 162, 132, 130, 0, 127, + 126, 74, 0, 143, 143, 95, 96, 146, 0, 146, + 146, 146, 0, 0, 89, 90, 91, 83, 0, 84, + 85, 86, 0, 87, 0, 0, 742, 53, 0, 57, + 58, 54, 528, 55, 741, 0, 0, 541, 183, 531, + 532, 533, 534, 535, 536, 537, 538, 539, 540, 0, + 200, 742, 203, 0, 487, 488, 0, 480, 23, 0, + 523, 524, 471, 472, 273, 347, 349, 351, 0, 260, + 338, 359, 342, 0, 339, 0, 0, 333, 398, 0, + 0, 366, -2, 401, 402, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 477, 0, 455, 0, 0, 415, + 426, 427, 428, 429, 502, 0, 0, -2, 0, 0, + 477, 0, 0, 0, 288, 295, 0, 0, 289, 0, + 290, 310, 312, 0, 0, 0, 0, 286, 477, 323, + 38, 147, 0, 170, 0, 0, 156, 0, 0, 159, + 160, 139, 0, 131, 70, 128, 0, 146, 146, 97, + 0, 98, 99, 100, 0, 116, 0, 0, 0, 0, + 550, 52, 60, 61, 0, 175, 741, 0, 184, 185, + 186, 187, 188, 189, 190, 191, 192, 193, 194, 741, + 0, 0, 741, 542, 543, 544, 545, 0, 202, 491, + 0, 24, 323, 0, 267, 461, 0, 340, 0, 360, + 343, 399, 263, 0, 118, 118, 440, 118, 122, 443, + 118, 445, 118, 448, 0, 0, 0, 0, 460, 0, + 0, 0, 452, 414, 458, 0, 31, 0, 502, 492, + 504, 506, 0, 27, 0, 498, 0, 485, 511, 324, + 512, 292, 0, 297, 0, 0, 0, 300, 0, 485, + 37, 168, 171, 0, 163, 118, 157, 158, 141, 0, + 133, 134, 135, 136, 137, 138, 119, 93, 94, 144, + 145, 143, 0, 143, 0, 123, 0, 742, 0, 0, + 176, 0, 177, 179, 180, 181, 0, 473, 274, 400, + 344, 403, 437, 143, 441, 442, 444, 446, 447, 449, + 405, 404, 406, 0, 0, 409, 0, 0, 0, 0, + 0, 456, 0, 32, 0, 507, -2, 0, 0, 0, + 44, 35, 0, 284, 0, 0, 0, 319, 287, 36, + 549, 0, 165, 148, 142, 0, 146, 117, 146, 0, + 0, 50, 62, 63, 0, 0, 475, 0, 438, 439, + 0, 0, 0, 0, 430, 413, 453, 0, 505, 0, + -2, 0, 500, 499, 0, 293, 320, 321, 322, 283, + 155, 164, 153, 0, 150, 152, 140, 106, 107, 121, + 124, 0, 0, 26, 0, 0, 407, 408, 410, 411, + 0, 0, 0, 0, 495, 27, 0, 285, 69, 0, + 149, 151, 56, 0, 196, 0, 476, 474, 412, 0, + 0, 0, 503, -2, 501, 154, 59, 195, 0, 0, + 431, 0, 434, 178, 197, 0, 432, 0, 0, 0, + 0, 0, 433, 0, 0, 198, 199, } var yyTok1 = [...]int{ @@ -2636,98 +2639,104 @@ yydefault: yyVAL.statement = &Delete{Comments: Comments(yyDollar[2].bytes2), TableExprs: TableExprs{&AliasedTableExpr{Expr: yyDollar[4].tableName}}, Partitions: yyDollar[5].partitions, Where: NewWhere(WhereStr, yyDollar[6].expr), OrderBy: yyDollar[7].orderBy, Limit: yyDollar[8].limit} } case 37: - yyDollar = yyS[yypt-6 : yypt+1] + yyDollar = yyS[yypt-7 : yypt+1] //line sql.y:423 { - yyVAL.statement = &Delete{Comments: Comments(yyDollar[2].bytes2), Targets: yyDollar[3].tableNames, TableExprs: yyDollar[5].tableExprs, Where: NewWhere(WhereStr, yyDollar[6].expr)} + yyVAL.statement = &Delete{Comments: Comments(yyDollar[2].bytes2), Targets: yyDollar[4].tableNames, TableExprs: yyDollar[6].tableExprs, Where: NewWhere(WhereStr, yyDollar[7].expr)} } case 38: - yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:428 + yyDollar = yyS[yypt-6 : yypt+1] + //line sql.y:427 { + yyVAL.statement = &Delete{Comments: Comments(yyDollar[2].bytes2), Targets: yyDollar[3].tableNames, TableExprs: yyDollar[5].tableExprs, Where: NewWhere(WhereStr, yyDollar[6].expr)} } case 39: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:429 + //line sql.y:432 { } case 40: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:433 { - yyVAL.tableNames = TableNames{yyDollar[1].tableName} } case 41: - yyDollar = yyS[yypt-3 : yypt+1] + yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:437 { - yyVAL.tableNames = append(yyVAL.tableNames, yyDollar[3].tableName) + yyVAL.tableNames = TableNames{yyDollar[1].tableName} } case 42: + yyDollar = yyS[yypt-3 : yypt+1] + //line sql.y:441 + { + yyVAL.tableNames = append(yyVAL.tableNames, yyDollar[3].tableName) + } + case 43: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:442 + //line sql.y:446 { yyVAL.partitions = nil } - case 43: + case 44: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:446 + //line sql.y:450 { yyVAL.partitions = yyDollar[3].partitions } - case 44: + case 45: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:452 + //line sql.y:456 { yyVAL.statement = &Set{Comments: Comments(yyDollar[2].bytes2), Exprs: yyDollar[3].setExprs} } - case 45: + case 46: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:456 + //line sql.y:460 { yyVAL.statement = &Set{Comments: Comments(yyDollar[2].bytes2), Scope: yyDollar[3].str, Exprs: yyDollar[4].setExprs} } - case 46: + case 47: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:462 + //line sql.y:466 { yyVAL.str = SessionStr } - case 47: + case 48: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:466 + //line sql.y:470 { yyVAL.str = GlobalStr } - case 48: + case 49: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:472 + //line sql.y:476 { yyDollar[1].ddl.TableSpec = yyDollar[2].TableSpec yyVAL.statement = yyDollar[1].ddl } - case 49: + case 50: yyDollar = yyS[yypt-8 : yypt+1] - //line sql.y:477 + //line sql.y:481 { // Change this to an alter statement yyVAL.statement = &DDL{Action: AlterStr, Table: yyDollar[7].tableName, NewName: yyDollar[7].tableName} } - case 50: + case 51: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:482 + //line sql.y:486 { yyVAL.statement = &DDL{Action: CreateStr, NewName: yyDollar[3].tableName.ToViewName()} } - case 51: + case 52: yyDollar = yyS[yypt-6 : yypt+1] - //line sql.y:486 + //line sql.y:490 { yyVAL.statement = &DDL{Action: CreateStr, NewName: yyDollar[5].tableName.ToViewName()} } - case 52: + case 53: yyDollar = yyS[yypt-5 : yypt+1] - //line sql.y:490 + //line sql.y:494 { yyVAL.statement = &DDL{Action: CreateVindexStr, VindexSpec: &VindexSpec{ Name: yyDollar[3].colIdent, @@ -2735,104 +2744,104 @@ yydefault: Params: yyDollar[5].vindexParams, }} } - case 53: + case 54: yyDollar = yyS[yypt-5 : yypt+1] - //line sql.y:498 + //line sql.y:502 { yyVAL.statement = &DBDDL{Action: CreateStr, DBName: string(yyDollar[4].bytes)} } - case 54: + case 55: yyDollar = yyS[yypt-5 : yypt+1] - //line sql.y:502 + //line sql.y:506 { yyVAL.statement = &DBDDL{Action: CreateStr, DBName: string(yyDollar[4].bytes)} } - case 55: + case 56: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:507 + //line sql.y:511 { yyVAL.colIdent = NewColIdent("") } - case 56: + case 57: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:511 + //line sql.y:515 { yyVAL.colIdent = yyDollar[2].colIdent } - case 57: + case 58: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:517 + //line sql.y:521 { yyVAL.colIdent = NewColIdent(string(yyDollar[1].bytes)) } - case 58: + case 59: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:522 + //line sql.y:526 { var v []VindexParam yyVAL.vindexParams = v } - case 59: + case 60: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:527 + //line sql.y:531 { yyVAL.vindexParams = yyDollar[2].vindexParams } - case 60: + case 61: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:533 + //line sql.y:537 { yyVAL.vindexParams = make([]VindexParam, 0, 4) yyVAL.vindexParams = append(yyVAL.vindexParams, yyDollar[1].vindexParam) } - case 61: + case 62: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:538 + //line sql.y:542 { yyVAL.vindexParams = append(yyVAL.vindexParams, yyDollar[3].vindexParam) } - case 62: + case 63: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:544 + //line sql.y:548 { yyVAL.vindexParam = VindexParam{Key: yyDollar[1].colIdent, Val: yyDollar[3].str} } - case 63: + case 64: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:550 + //line sql.y:554 { yyVAL.ddl = &DDL{Action: CreateStr, NewName: yyDollar[4].tableName} setDDL(yylex, yyVAL.ddl) } - case 64: + case 65: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:557 + //line sql.y:561 { yyVAL.TableSpec = yyDollar[2].TableSpec yyVAL.TableSpec.Options = yyDollar[4].str } - case 65: + case 66: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:564 + //line sql.y:568 { yyVAL.TableSpec = &TableSpec{} yyVAL.TableSpec.AddColumn(yyDollar[1].columnDefinition) } - case 66: + case 67: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:569 + //line sql.y:573 { yyVAL.TableSpec.AddColumn(yyDollar[3].columnDefinition) } - case 67: + case 68: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:573 + //line sql.y:577 { yyVAL.TableSpec.AddIndex(yyDollar[3].indexDefinition) } - case 68: + case 69: yyDollar = yyS[yypt-8 : yypt+1] - //line sql.y:579 + //line sql.y:583 { yyDollar[2].columnType.NotNull = yyDollar[3].boolVal yyDollar[2].columnType.Default = yyDollar[4].optVal @@ -2842,32 +2851,26 @@ yydefault: yyDollar[2].columnType.Comment = yyDollar[8].optVal yyVAL.columnDefinition = &ColumnDefinition{Name: NewColIdent(string(yyDollar[1].bytes)), Type: yyDollar[2].columnType} } - case 69: + case 70: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:590 + //line sql.y:594 { yyVAL.columnType = yyDollar[1].columnType yyVAL.columnType.Unsigned = yyDollar[2].boolVal yyVAL.columnType.Zerofill = yyDollar[3].boolVal } - case 73: + case 74: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:601 + //line sql.y:605 { yyVAL.columnType = yyDollar[1].columnType yyVAL.columnType.Length = yyDollar[2].optVal } - case 74: - yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:606 - { - yyVAL.columnType = yyDollar[1].columnType - } case 75: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:612 + //line sql.y:610 { - yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} + yyVAL.columnType = yyDollar[1].columnType } case 76: yyDollar = yyS[yypt-1 : yypt+1] @@ -2906,16 +2909,14 @@ yydefault: yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 82: - yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:642 + yyDollar = yyS[yypt-1 : yypt+1] + //line sql.y:640 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} - yyVAL.columnType.Length = yyDollar[2].LengthScaleOption.Length - yyVAL.columnType.Scale = yyDollar[2].LengthScaleOption.Scale } case 83: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:648 + //line sql.y:646 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} yyVAL.columnType.Length = yyDollar[2].LengthScaleOption.Length @@ -2923,7 +2924,7 @@ yydefault: } case 84: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:654 + //line sql.y:652 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} yyVAL.columnType.Length = yyDollar[2].LengthScaleOption.Length @@ -2931,7 +2932,7 @@ yydefault: } case 85: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:660 + //line sql.y:658 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} yyVAL.columnType.Length = yyDollar[2].LengthScaleOption.Length @@ -2939,23 +2940,25 @@ yydefault: } case 86: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:666 + //line sql.y:664 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} yyVAL.columnType.Length = yyDollar[2].LengthScaleOption.Length yyVAL.columnType.Scale = yyDollar[2].LengthScaleOption.Scale } case 87: - yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:674 + yyDollar = yyS[yypt-2 : yypt+1] + //line sql.y:670 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} + yyVAL.columnType.Length = yyDollar[2].LengthScaleOption.Length + yyVAL.columnType.Scale = yyDollar[2].LengthScaleOption.Scale } case 88: - yyDollar = yyS[yypt-2 : yypt+1] + yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:678 { - yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].optVal} + yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 89: yyDollar = yyS[yypt-2 : yypt+1] @@ -2970,16 +2973,16 @@ yydefault: yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].optVal} } case 91: - yyDollar = yyS[yypt-1 : yypt+1] + yyDollar = yyS[yypt-2 : yypt+1] //line sql.y:690 { - yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} + yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].optVal} } case 92: - yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:696 + yyDollar = yyS[yypt-1 : yypt+1] + //line sql.y:694 { - yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].optVal, Charset: yyDollar[3].str, Collate: yyDollar[4].str} + yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 93: yyDollar = yyS[yypt-4 : yypt+1] @@ -2988,10 +2991,10 @@ yydefault: yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].optVal, Charset: yyDollar[3].str, Collate: yyDollar[4].str} } case 94: - yyDollar = yyS[yypt-2 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] //line sql.y:704 { - yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].optVal} + yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].optVal, Charset: yyDollar[3].str, Collate: yyDollar[4].str} } case 95: yyDollar = yyS[yypt-2 : yypt+1] @@ -3000,10 +3003,10 @@ yydefault: yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].optVal} } case 96: - yyDollar = yyS[yypt-3 : yypt+1] + yyDollar = yyS[yypt-2 : yypt+1] //line sql.y:712 { - yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Charset: yyDollar[2].str, Collate: yyDollar[3].str} + yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].optVal} } case 97: yyDollar = yyS[yypt-3 : yypt+1] @@ -3024,10 +3027,10 @@ yydefault: yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Charset: yyDollar[2].str, Collate: yyDollar[3].str} } case 100: - yyDollar = yyS[yypt-1 : yypt+1] + yyDollar = yyS[yypt-3 : yypt+1] //line sql.y:728 { - yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} + yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Charset: yyDollar[2].str, Collate: yyDollar[3].str} } case 101: yyDollar = yyS[yypt-1 : yypt+1] @@ -3054,22 +3057,22 @@ yydefault: yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 105: - yyDollar = yyS[yypt-6 : yypt+1] + yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:748 { - yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), EnumValues: yyDollar[3].strs, Charset: yyDollar[5].str, Collate: yyDollar[6].str} + yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 106: yyDollar = yyS[yypt-6 : yypt+1] - //line sql.y:753 + //line sql.y:752 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), EnumValues: yyDollar[3].strs, Charset: yyDollar[5].str, Collate: yyDollar[6].str} } case 107: - yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:759 + yyDollar = yyS[yypt-6 : yypt+1] + //line sql.y:757 { - yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} + yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), EnumValues: yyDollar[3].strs, Charset: yyDollar[5].str, Collate: yyDollar[6].str} } case 108: yyDollar = yyS[yypt-1 : yypt+1] @@ -3115,138 +3118,138 @@ yydefault: } case 115: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:793 + //line sql.y:791 + { + yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} + } + case 116: + yyDollar = yyS[yypt-1 : yypt+1] + //line sql.y:797 { yyVAL.strs = make([]string, 0, 4) yyVAL.strs = append(yyVAL.strs, "'"+string(yyDollar[1].bytes)+"'") } - case 116: + case 117: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:798 + //line sql.y:802 { yyVAL.strs = append(yyDollar[1].strs, "'"+string(yyDollar[3].bytes)+"'") } - case 117: + case 118: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:803 + //line sql.y:807 { yyVAL.optVal = nil } - case 118: + case 119: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:807 + //line sql.y:811 { yyVAL.optVal = NewIntVal(yyDollar[2].bytes) } - case 119: + case 120: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:812 + //line sql.y:816 { yyVAL.LengthScaleOption = LengthScaleOption{} } - case 120: + case 121: yyDollar = yyS[yypt-5 : yypt+1] - //line sql.y:816 + //line sql.y:820 { yyVAL.LengthScaleOption = LengthScaleOption{ Length: NewIntVal(yyDollar[2].bytes), Scale: NewIntVal(yyDollar[4].bytes), } } - case 121: + case 122: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:824 + //line sql.y:828 { yyVAL.LengthScaleOption = LengthScaleOption{} } - case 122: + case 123: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:828 + //line sql.y:832 { yyVAL.LengthScaleOption = LengthScaleOption{ Length: NewIntVal(yyDollar[2].bytes), } } - case 123: + case 124: yyDollar = yyS[yypt-5 : yypt+1] - //line sql.y:834 + //line sql.y:838 { yyVAL.LengthScaleOption = LengthScaleOption{ Length: NewIntVal(yyDollar[2].bytes), Scale: NewIntVal(yyDollar[4].bytes), } } - case 124: + case 125: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:842 + //line sql.y:846 { yyVAL.boolVal = BoolVal(false) } - case 125: + case 126: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:846 + //line sql.y:850 { yyVAL.boolVal = BoolVal(true) } - case 126: + case 127: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:851 + //line sql.y:855 { yyVAL.boolVal = BoolVal(false) } - case 127: + case 128: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:855 + //line sql.y:859 { yyVAL.boolVal = BoolVal(true) } - case 128: - yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:861 - { - yyVAL.boolVal = BoolVal(false) - } case 129: - yyDollar = yyS[yypt-1 : yypt+1] + yyDollar = yyS[yypt-0 : yypt+1] //line sql.y:865 { yyVAL.boolVal = BoolVal(false) } case 130: - yyDollar = yyS[yypt-2 : yypt+1] + yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:869 { - yyVAL.boolVal = BoolVal(true) + yyVAL.boolVal = BoolVal(false) } case 131: - yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:874 + yyDollar = yyS[yypt-2 : yypt+1] + //line sql.y:873 { - yyVAL.optVal = nil + yyVAL.boolVal = BoolVal(true) } case 132: - yyDollar = yyS[yypt-2 : yypt+1] + yyDollar = yyS[yypt-0 : yypt+1] //line sql.y:878 { - yyVAL.optVal = NewStrVal(yyDollar[2].bytes) + yyVAL.optVal = nil } case 133: yyDollar = yyS[yypt-2 : yypt+1] //line sql.y:882 { - yyVAL.optVal = NewIntVal(yyDollar[2].bytes) + yyVAL.optVal = NewStrVal(yyDollar[2].bytes) } case 134: yyDollar = yyS[yypt-2 : yypt+1] //line sql.y:886 { - yyVAL.optVal = NewFloatVal(yyDollar[2].bytes) + yyVAL.optVal = NewIntVal(yyDollar[2].bytes) } case 135: yyDollar = yyS[yypt-2 : yypt+1] //line sql.y:890 { - yyVAL.optVal = NewValArg(yyDollar[2].bytes) + yyVAL.optVal = NewFloatVal(yyDollar[2].bytes) } case 136: yyDollar = yyS[yypt-2 : yypt+1] @@ -3258,145 +3261,145 @@ yydefault: yyDollar = yyS[yypt-2 : yypt+1] //line sql.y:898 { - yyVAL.optVal = NewBitVal(yyDollar[2].bytes) + yyVAL.optVal = NewValArg(yyDollar[2].bytes) } case 138: + yyDollar = yyS[yypt-2 : yypt+1] + //line sql.y:902 + { + yyVAL.optVal = NewBitVal(yyDollar[2].bytes) + } + case 139: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:903 + //line sql.y:907 { yyVAL.optVal = nil } - case 139: + case 140: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:907 + //line sql.y:911 { yyVAL.optVal = NewValArg(yyDollar[3].bytes) } - case 140: + case 141: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:912 + //line sql.y:916 { yyVAL.boolVal = BoolVal(false) } - case 141: + case 142: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:916 + //line sql.y:920 { yyVAL.boolVal = BoolVal(true) } - case 142: + case 143: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:921 + //line sql.y:925 { yyVAL.str = "" } - case 143: + case 144: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:925 + //line sql.y:929 { yyVAL.str = string(yyDollar[3].bytes) } - case 144: + case 145: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:929 + //line sql.y:933 { yyVAL.str = string(yyDollar[3].bytes) } - case 145: + case 146: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:934 + //line sql.y:938 { yyVAL.str = "" } - case 146: + case 147: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:938 + //line sql.y:942 { yyVAL.str = string(yyDollar[2].bytes) } - case 147: + case 148: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:943 + //line sql.y:947 { yyVAL.colKeyOpt = colKeyNone } - case 148: + case 149: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:947 + //line sql.y:951 { yyVAL.colKeyOpt = colKeyPrimary } - case 149: + case 150: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:951 + //line sql.y:955 { yyVAL.colKeyOpt = colKey } - case 150: + case 151: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:955 + //line sql.y:959 { yyVAL.colKeyOpt = colKeyUniqueKey } - case 151: + case 152: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:959 + //line sql.y:963 { yyVAL.colKeyOpt = colKeyUnique } - case 152: + case 153: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:964 + //line sql.y:968 { yyVAL.optVal = nil } - case 153: + case 154: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:968 + //line sql.y:972 { yyVAL.optVal = NewStrVal(yyDollar[2].bytes) } - case 154: + case 155: yyDollar = yyS[yypt-5 : yypt+1] - //line sql.y:974 + //line sql.y:978 { yyVAL.indexDefinition = &IndexDefinition{Info: yyDollar[1].indexInfo, Columns: yyDollar[3].indexColumns, Using: yyDollar[5].colIdent} } - case 155: - yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:980 - { - yyVAL.indexInfo = &IndexInfo{Type: string(yyDollar[1].bytes) + " " + string(yyDollar[2].bytes), Name: NewColIdent("PRIMARY"), Primary: true, Unique: true} - } case 156: - yyDollar = yyS[yypt-3 : yypt+1] + yyDollar = yyS[yypt-2 : yypt+1] //line sql.y:984 { - yyVAL.indexInfo = &IndexInfo{Type: string(yyDollar[1].bytes) + " " + string(yyDollar[2].str), Name: NewColIdent(string(yyDollar[3].bytes)), Spatial: true, Unique: false} + yyVAL.indexInfo = &IndexInfo{Type: string(yyDollar[1].bytes) + " " + string(yyDollar[2].bytes), Name: NewColIdent("PRIMARY"), Primary: true, Unique: true} } case 157: yyDollar = yyS[yypt-3 : yypt+1] //line sql.y:988 { - yyVAL.indexInfo = &IndexInfo{Type: string(yyDollar[1].bytes) + " " + string(yyDollar[2].str), Name: NewColIdent(string(yyDollar[3].bytes)), Unique: true} + yyVAL.indexInfo = &IndexInfo{Type: string(yyDollar[1].bytes) + " " + string(yyDollar[2].str), Name: NewColIdent(string(yyDollar[3].bytes)), Spatial: true, Unique: false} } case 158: - yyDollar = yyS[yypt-2 : yypt+1] + yyDollar = yyS[yypt-3 : yypt+1] //line sql.y:992 { - yyVAL.indexInfo = &IndexInfo{Type: string(yyDollar[1].bytes), Name: NewColIdent(string(yyDollar[2].bytes)), Unique: true} + yyVAL.indexInfo = &IndexInfo{Type: string(yyDollar[1].bytes) + " " + string(yyDollar[2].str), Name: NewColIdent(string(yyDollar[3].bytes)), Unique: true} } case 159: yyDollar = yyS[yypt-2 : yypt+1] //line sql.y:996 { - yyVAL.indexInfo = &IndexInfo{Type: string(yyDollar[1].str), Name: NewColIdent(string(yyDollar[2].bytes)), Unique: false} + yyVAL.indexInfo = &IndexInfo{Type: string(yyDollar[1].bytes), Name: NewColIdent(string(yyDollar[2].bytes)), Unique: true} } case 160: - yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1002 + yyDollar = yyS[yypt-2 : yypt+1] + //line sql.y:1000 { - yyVAL.str = string(yyDollar[1].bytes) + yyVAL.indexInfo = &IndexInfo{Type: string(yyDollar[1].str), Name: NewColIdent(string(yyDollar[2].bytes)), Unique: false} } case 161: yyDollar = yyS[yypt-1 : yypt+1] @@ -3406,84 +3409,84 @@ yydefault: } case 162: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1012 + //line sql.y:1010 { - yyVAL.indexColumns = []*IndexColumn{yyDollar[1].indexColumn} + yyVAL.str = string(yyDollar[1].bytes) } case 163: - yyDollar = yyS[yypt-3 : yypt+1] + yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:1016 { - yyVAL.indexColumns = append(yyVAL.indexColumns, yyDollar[3].indexColumn) + yyVAL.indexColumns = []*IndexColumn{yyDollar[1].indexColumn} } case 164: + yyDollar = yyS[yypt-3 : yypt+1] + //line sql.y:1020 + { + yyVAL.indexColumns = append(yyVAL.indexColumns, yyDollar[3].indexColumn) + } + case 165: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1022 + //line sql.y:1026 { yyVAL.indexColumn = &IndexColumn{Column: yyDollar[1].colIdent, Length: yyDollar[2].optVal} } - case 165: + case 166: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1027 + //line sql.y:1031 { yyVAL.str = "" } - case 166: + case 167: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1031 + //line sql.y:1035 { yyVAL.str = " " + string(yyDollar[1].str) } - case 167: + case 168: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1035 + //line sql.y:1039 { yyVAL.str = string(yyDollar[1].str) + ", " + string(yyDollar[3].str) } - case 168: + case 169: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1043 + //line sql.y:1047 { yyVAL.str = yyDollar[1].str } - case 169: + case 170: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1047 + //line sql.y:1051 { yyVAL.str = yyDollar[1].str + " " + yyDollar[2].str } - case 170: + case 171: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1051 + //line sql.y:1055 { yyVAL.str = yyDollar[1].str + "=" + yyDollar[3].str } - case 171: - yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1057 - { - yyVAL.str = yyDollar[1].colIdent.String() - } case 172: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:1061 { - yyVAL.str = "'" + string(yyDollar[1].bytes) + "'" + yyVAL.str = yyDollar[1].colIdent.String() } case 173: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:1065 { - yyVAL.str = string(yyDollar[1].bytes) + yyVAL.str = "'" + string(yyDollar[1].bytes) + "'" } case 174: - yyDollar = yyS[yypt-6 : yypt+1] - //line sql.y:1071 + yyDollar = yyS[yypt-1 : yypt+1] + //line sql.y:1069 { - yyVAL.statement = &DDL{Action: AlterStr, Table: yyDollar[4].tableName, NewName: yyDollar[4].tableName} + yyVAL.str = string(yyDollar[1].bytes) } case 175: - yyDollar = yyS[yypt-7 : yypt+1] + yyDollar = yyS[yypt-6 : yypt+1] //line sql.y:1075 { yyVAL.statement = &DDL{Action: AlterStr, Table: yyDollar[4].tableName, NewName: yyDollar[4].tableName} @@ -3495,8 +3498,14 @@ yydefault: yyVAL.statement = &DDL{Action: AlterStr, Table: yyDollar[4].tableName, NewName: yyDollar[4].tableName} } case 177: - yyDollar = yyS[yypt-12 : yypt+1] + yyDollar = yyS[yypt-7 : yypt+1] //line sql.y:1083 + { + yyVAL.statement = &DDL{Action: AlterStr, Table: yyDollar[4].tableName, NewName: yyDollar[4].tableName} + } + case 178: + yyDollar = yyS[yypt-12 : yypt+1] + //line sql.y:1087 { yyVAL.statement = &DDL{ Action: AddColVindexStr, @@ -3509,9 +3518,9 @@ yydefault: VindexCols: yyDollar[9].columns, } } - case 178: + case 179: yyDollar = yyS[yypt-7 : yypt+1] - //line sql.y:1096 + //line sql.y:1100 { yyVAL.statement = &DDL{ Action: DropColVindexStr, @@ -3521,71 +3530,71 @@ yydefault: }, } } - case 179: + case 180: yyDollar = yyS[yypt-7 : yypt+1] - //line sql.y:1106 + //line sql.y:1110 { // Change this to a rename statement yyVAL.statement = &DDL{Action: RenameStr, Table: yyDollar[4].tableName, NewName: yyDollar[7].tableName} } - case 180: + case 181: yyDollar = yyS[yypt-7 : yypt+1] - //line sql.y:1111 + //line sql.y:1115 { // Rename an index can just be an alter yyVAL.statement = &DDL{Action: AlterStr, Table: yyDollar[4].tableName, NewName: yyDollar[4].tableName} } - case 181: + case 182: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:1116 + //line sql.y:1120 { yyVAL.statement = &DDL{Action: AlterStr, Table: yyDollar[3].tableName.ToViewName(), NewName: yyDollar[3].tableName.ToViewName()} } - case 182: + case 183: yyDollar = yyS[yypt-5 : yypt+1] - //line sql.y:1120 + //line sql.y:1124 { yyVAL.statement = &DDL{Action: AlterStr, Table: yyDollar[4].tableName, PartitionSpec: yyDollar[5].partSpec} } - case 194: + case 195: yyDollar = yyS[yypt-7 : yypt+1] - //line sql.y:1139 + //line sql.y:1143 { yyVAL.partSpec = &PartitionSpec{Action: ReorganizeStr, Name: yyDollar[3].colIdent, Definitions: yyDollar[6].partDefs} } - case 195: + case 196: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1145 + //line sql.y:1149 { yyVAL.partDefs = []*PartitionDefinition{yyDollar[1].partDef} } - case 196: + case 197: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1149 + //line sql.y:1153 { yyVAL.partDefs = append(yyDollar[1].partDefs, yyDollar[3].partDef) } - case 197: + case 198: yyDollar = yyS[yypt-8 : yypt+1] - //line sql.y:1155 + //line sql.y:1159 { yyVAL.partDef = &PartitionDefinition{Name: yyDollar[2].colIdent, Limit: yyDollar[7].expr} } - case 198: + case 199: yyDollar = yyS[yypt-8 : yypt+1] - //line sql.y:1159 + //line sql.y:1163 { yyVAL.partDef = &PartitionDefinition{Name: yyDollar[2].colIdent, Maxvalue: true} } - case 199: + case 200: yyDollar = yyS[yypt-5 : yypt+1] - //line sql.y:1165 + //line sql.y:1169 { yyVAL.statement = &DDL{Action: RenameStr, Table: yyDollar[3].tableName, NewName: yyDollar[5].tableName} } - case 200: + case 201: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:1171 + //line sql.y:1175 { var exists bool if yyDollar[3].byt != 0 { @@ -3593,16 +3602,16 @@ yydefault: } yyVAL.statement = &DDL{Action: DropStr, Table: yyDollar[4].tableName, IfExists: exists} } - case 201: + case 202: yyDollar = yyS[yypt-6 : yypt+1] - //line sql.y:1179 + //line sql.y:1183 { // Change this to an alter statement yyVAL.statement = &DDL{Action: AlterStr, Table: yyDollar[5].tableName, NewName: yyDollar[5].tableName} } - case 202: + case 203: yyDollar = yyS[yypt-5 : yypt+1] - //line sql.y:1184 + //line sql.y:1188 { var exists bool if yyDollar[3].byt != 0 { @@ -3610,42 +3619,36 @@ yydefault: } yyVAL.statement = &DDL{Action: DropStr, Table: yyDollar[4].tableName.ToViewName(), IfExists: exists} } - case 203: + case 204: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:1192 + //line sql.y:1196 { yyVAL.statement = &DBDDL{Action: DropStr, DBName: string(yyDollar[4].bytes)} } - case 204: + case 205: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:1196 + //line sql.y:1200 { yyVAL.statement = &DBDDL{Action: DropStr, DBName: string(yyDollar[4].bytes)} } - case 205: + case 206: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1202 + //line sql.y:1206 { yyVAL.statement = &DDL{Action: TruncateStr, Table: yyDollar[3].tableName} } - case 206: + case 207: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1206 + //line sql.y:1210 { yyVAL.statement = &DDL{Action: TruncateStr, Table: yyDollar[2].tableName} } - case 207: + case 208: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1211 + //line sql.y:1215 { yyVAL.statement = &DDL{Action: AlterStr, Table: yyDollar[3].tableName, NewName: yyDollar[3].tableName} } - case 208: - yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:1217 - { - yyVAL.statement = &Show{Type: string(yyDollar[2].bytes) + " " + string(yyDollar[3].bytes)} - } case 209: yyDollar = yyS[yypt-4 : yypt+1] //line sql.y:1221 @@ -3660,7 +3663,7 @@ yydefault: } case 211: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:1230 + //line sql.y:1229 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes) + " " + string(yyDollar[3].bytes)} } @@ -3689,10 +3692,10 @@ yydefault: yyVAL.statement = &Show{Type: string(yyDollar[2].bytes) + " " + string(yyDollar[3].bytes)} } case 216: - yyDollar = yyS[yypt-3 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] //line sql.y:1250 { - yyVAL.statement = &Show{Type: string(yyDollar[2].bytes)} + yyVAL.statement = &Show{Type: string(yyDollar[2].bytes) + " " + string(yyDollar[3].bytes)} } case 217: yyDollar = yyS[yypt-3 : yypt+1] @@ -3713,16 +3716,16 @@ yydefault: yyVAL.statement = &Show{Type: string(yyDollar[2].bytes)} } case 220: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-3 : yypt+1] //line sql.y:1266 { - yyVAL.statement = &Show{Scope: yyDollar[2].str, Type: string(yyDollar[3].bytes)} + yyVAL.statement = &Show{Type: string(yyDollar[2].bytes)} } case 221: - yyDollar = yyS[yypt-3 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] //line sql.y:1270 { - yyVAL.statement = &Show{Type: string(yyDollar[2].bytes)} + yyVAL.statement = &Show{Scope: yyDollar[2].str, Type: string(yyDollar[3].bytes)} } case 222: yyDollar = yyS[yypt-3 : yypt+1] @@ -3731,28 +3734,28 @@ yydefault: yyVAL.statement = &Show{Type: string(yyDollar[2].bytes)} } case 223: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-3 : yypt+1] //line sql.y:1278 { - yyVAL.statement = &Show{Scope: yyDollar[2].str, Type: string(yyDollar[3].bytes)} + yyVAL.statement = &Show{Type: string(yyDollar[2].bytes)} } case 224: - yyDollar = yyS[yypt-2 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] //line sql.y:1282 { - yyVAL.statement = &Show{Type: string(yyDollar[2].bytes)} + yyVAL.statement = &Show{Scope: yyDollar[2].str, Type: string(yyDollar[3].bytes)} } case 225: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-2 : yypt+1] //line sql.y:1286 { - yyVAL.statement = &Show{Type: string(yyDollar[2].bytes), OnTable: yyDollar[4].tableName} + yyVAL.statement = &Show{Type: string(yyDollar[2].bytes)} } case 226: - yyDollar = yyS[yypt-2 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] //line sql.y:1290 { - yyVAL.statement = &Show{Type: string(yyDollar[2].bytes)} + yyVAL.statement = &Show{Type: string(yyDollar[2].bytes), OnTable: yyDollar[4].tableName} } case 227: yyDollar = yyS[yypt-2 : yypt+1] @@ -3773,70 +3776,70 @@ yydefault: yyVAL.statement = &Show{Type: string(yyDollar[2].bytes)} } case 230: - yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1312 + yyDollar = yyS[yypt-2 : yypt+1] + //line sql.y:1306 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes)} } case 231: - yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1318 + yyDollar = yyS[yypt-3 : yypt+1] + //line sql.y:1316 { - yyVAL.str = "" + yyVAL.statement = &Show{Type: string(yyDollar[2].bytes)} } case 232: - yyDollar = yyS[yypt-1 : yypt+1] + yyDollar = yyS[yypt-0 : yypt+1] //line sql.y:1322 { - yyVAL.str = SessionStr + yyVAL.str = "" } case 233: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:1326 { - yyVAL.str = GlobalStr + yyVAL.str = SessionStr } case 234: - yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1332 + yyDollar = yyS[yypt-1 : yypt+1] + //line sql.y:1330 { - yyVAL.statement = &Use{DBName: yyDollar[2].tableIdent} + yyVAL.str = GlobalStr } case 235: - yyDollar = yyS[yypt-1 : yypt+1] + yyDollar = yyS[yypt-2 : yypt+1] //line sql.y:1336 { - yyVAL.statement = &Use{DBName: TableIdent{v: ""}} + yyVAL.statement = &Use{DBName: yyDollar[2].tableIdent} } case 236: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1342 + //line sql.y:1340 { - yyVAL.statement = &Begin{} + yyVAL.statement = &Use{DBName: TableIdent{v: ""}} } case 237: - yyDollar = yyS[yypt-2 : yypt+1] + yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:1346 { yyVAL.statement = &Begin{} } case 238: - yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1352 + yyDollar = yyS[yypt-2 : yypt+1] + //line sql.y:1350 { - yyVAL.statement = &Commit{} + yyVAL.statement = &Begin{} } case 239: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1358 + //line sql.y:1356 { - yyVAL.statement = &Rollback{} + yyVAL.statement = &Commit{} } case 240: - yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1364 + yyDollar = yyS[yypt-1 : yypt+1] + //line sql.y:1362 { - yyVAL.statement = &OtherRead{} + yyVAL.statement = &Rollback{} } case 241: yyDollar = yyS[yypt-2 : yypt+1] @@ -3854,7 +3857,7 @@ yydefault: yyDollar = yyS[yypt-2 : yypt+1] //line sql.y:1376 { - yyVAL.statement = &OtherAdmin{} + yyVAL.statement = &OtherRead{} } case 244: yyDollar = yyS[yypt-2 : yypt+1] @@ -3863,246 +3866,246 @@ yydefault: yyVAL.statement = &OtherAdmin{} } case 245: + yyDollar = yyS[yypt-2 : yypt+1] + //line sql.y:1384 + { + yyVAL.statement = &OtherAdmin{} + } + case 246: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1385 + //line sql.y:1389 { setAllowComments(yylex, true) } - case 246: + case 247: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1389 + //line sql.y:1393 { yyVAL.bytes2 = yyDollar[2].bytes2 setAllowComments(yylex, false) } - case 247: + case 248: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1395 + //line sql.y:1399 { yyVAL.bytes2 = nil } - case 248: + case 249: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1399 + //line sql.y:1403 { yyVAL.bytes2 = append(yyDollar[1].bytes2, yyDollar[2].bytes) } - case 249: + case 250: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1405 + //line sql.y:1409 { yyVAL.str = UnionStr } - case 250: + case 251: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1409 + //line sql.y:1413 { yyVAL.str = UnionAllStr } - case 251: + case 252: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1413 + //line sql.y:1417 { yyVAL.str = UnionDistinctStr } - case 252: + case 253: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1418 + //line sql.y:1422 { yyVAL.str = "" } - case 253: + case 254: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1422 + //line sql.y:1426 { yyVAL.str = SQLNoCacheStr } - case 254: + case 255: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1426 + //line sql.y:1430 { yyVAL.str = SQLCacheStr } - case 255: + case 256: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1431 + //line sql.y:1435 { yyVAL.str = "" } - case 256: + case 257: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1435 + //line sql.y:1439 { yyVAL.str = DistinctStr } - case 257: + case 258: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1440 + //line sql.y:1444 { yyVAL.str = "" } - case 258: + case 259: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1444 + //line sql.y:1448 { yyVAL.str = StraightJoinHint } - case 259: + case 260: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1449 + //line sql.y:1453 { yyVAL.selectExprs = nil } - case 260: + case 261: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1453 + //line sql.y:1457 { yyVAL.selectExprs = yyDollar[1].selectExprs } - case 261: + case 262: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1459 + //line sql.y:1463 { yyVAL.selectExprs = SelectExprs{yyDollar[1].selectExpr} } - case 262: + case 263: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1463 + //line sql.y:1467 { yyVAL.selectExprs = append(yyVAL.selectExprs, yyDollar[3].selectExpr) } - case 263: + case 264: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1469 + //line sql.y:1473 { yyVAL.selectExpr = &StarExpr{} } - case 264: + case 265: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1473 + //line sql.y:1477 { yyVAL.selectExpr = &AliasedExpr{Expr: yyDollar[1].expr, As: yyDollar[2].colIdent} } - case 265: + case 266: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1477 + //line sql.y:1481 { yyVAL.selectExpr = &StarExpr{TableName: TableName{Name: yyDollar[1].tableIdent}} } - case 266: + case 267: yyDollar = yyS[yypt-5 : yypt+1] - //line sql.y:1481 + //line sql.y:1485 { yyVAL.selectExpr = &StarExpr{TableName: TableName{Qualifier: yyDollar[1].tableIdent, Name: yyDollar[3].tableIdent}} } - case 267: + case 268: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1486 + //line sql.y:1490 { yyVAL.colIdent = ColIdent{} } - case 268: + case 269: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1490 + //line sql.y:1494 { yyVAL.colIdent = yyDollar[1].colIdent } - case 269: + case 270: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1494 + //line sql.y:1498 { yyVAL.colIdent = yyDollar[2].colIdent } - case 271: + case 272: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1501 + //line sql.y:1505 { yyVAL.colIdent = NewColIdent(string(yyDollar[1].bytes)) } - case 272: + case 273: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1506 + //line sql.y:1510 { yyVAL.tableExprs = TableExprs{&AliasedTableExpr{Expr: TableName{Name: NewTableIdent("dual")}}} } - case 273: + case 274: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1510 + //line sql.y:1514 { yyVAL.tableExprs = yyDollar[2].tableExprs } - case 274: + case 275: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1516 + //line sql.y:1520 { yyVAL.tableExprs = TableExprs{yyDollar[1].tableExpr} } - case 275: + case 276: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1520 + //line sql.y:1524 { yyVAL.tableExprs = append(yyVAL.tableExprs, yyDollar[3].tableExpr) } - case 278: + case 279: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1530 + //line sql.y:1534 { yyVAL.tableExpr = yyDollar[1].aliasedTableName } - case 279: + case 280: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1534 + //line sql.y:1538 { yyVAL.tableExpr = &AliasedTableExpr{Expr: yyDollar[1].subquery, As: yyDollar[3].tableIdent} } - case 280: + case 281: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1538 + //line sql.y:1542 { yyVAL.tableExpr = &ParenTableExpr{Exprs: yyDollar[2].tableExprs} } - case 281: + case 282: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1544 + //line sql.y:1548 { yyVAL.aliasedTableName = &AliasedTableExpr{Expr: yyDollar[1].tableName, As: yyDollar[2].tableIdent, Hints: yyDollar[3].indexHints} } - case 282: + case 283: yyDollar = yyS[yypt-7 : yypt+1] - //line sql.y:1548 + //line sql.y:1552 { yyVAL.aliasedTableName = &AliasedTableExpr{Expr: yyDollar[1].tableName, Partitions: yyDollar[4].partitions, As: yyDollar[6].tableIdent, Hints: yyDollar[7].indexHints} } - case 283: + case 284: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1554 + //line sql.y:1558 { yyVAL.columns = Columns{yyDollar[1].colIdent} } - case 284: + case 285: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1558 + //line sql.y:1562 { yyVAL.columns = append(yyVAL.columns, yyDollar[3].colIdent) } - case 285: + case 286: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1564 + //line sql.y:1568 { yyVAL.partitions = Partitions{yyDollar[1].colIdent} } - case 286: + case 287: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1568 + //line sql.y:1572 { yyVAL.partitions = append(yyVAL.partitions, yyDollar[3].colIdent) } - case 287: - yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:1581 - { - yyVAL.tableExpr = &JoinTableExpr{LeftExpr: yyDollar[1].tableExpr, Join: yyDollar[2].str, RightExpr: yyDollar[3].tableExpr, Condition: yyDollar[4].joinCondition} - } case 288: yyDollar = yyS[yypt-4 : yypt+1] //line sql.y:1585 @@ -4116,91 +4119,91 @@ yydefault: yyVAL.tableExpr = &JoinTableExpr{LeftExpr: yyDollar[1].tableExpr, Join: yyDollar[2].str, RightExpr: yyDollar[3].tableExpr, Condition: yyDollar[4].joinCondition} } case 290: - yyDollar = yyS[yypt-3 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] //line sql.y:1593 { - yyVAL.tableExpr = &JoinTableExpr{LeftExpr: yyDollar[1].tableExpr, Join: yyDollar[2].str, RightExpr: yyDollar[3].tableExpr} + yyVAL.tableExpr = &JoinTableExpr{LeftExpr: yyDollar[1].tableExpr, Join: yyDollar[2].str, RightExpr: yyDollar[3].tableExpr, Condition: yyDollar[4].joinCondition} } case 291: + yyDollar = yyS[yypt-3 : yypt+1] + //line sql.y:1597 + { + yyVAL.tableExpr = &JoinTableExpr{LeftExpr: yyDollar[1].tableExpr, Join: yyDollar[2].str, RightExpr: yyDollar[3].tableExpr} + } + case 292: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1599 + //line sql.y:1603 { yyVAL.joinCondition = JoinCondition{On: yyDollar[2].expr} } - case 292: + case 293: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:1601 + //line sql.y:1605 { yyVAL.joinCondition = JoinCondition{Using: yyDollar[3].columns} } - case 293: + case 294: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1605 + //line sql.y:1609 { yyVAL.joinCondition = JoinCondition{} } - case 294: + case 295: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1607 + //line sql.y:1611 { yyVAL.joinCondition = yyDollar[1].joinCondition } - case 295: + case 296: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1611 + //line sql.y:1615 { yyVAL.joinCondition = JoinCondition{} } - case 296: + case 297: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1613 + //line sql.y:1617 { yyVAL.joinCondition = JoinCondition{On: yyDollar[2].expr} } - case 297: + case 298: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1616 + //line sql.y:1620 { yyVAL.empty = struct{}{} } - case 298: + case 299: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1618 + //line sql.y:1622 { yyVAL.empty = struct{}{} } - case 299: + case 300: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1621 + //line sql.y:1625 { yyVAL.tableIdent = NewTableIdent("") } - case 300: + case 301: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1625 + //line sql.y:1629 { yyVAL.tableIdent = yyDollar[1].tableIdent } - case 301: + case 302: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1629 + //line sql.y:1633 { yyVAL.tableIdent = yyDollar[2].tableIdent } - case 303: - yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1636 - { - yyVAL.tableIdent = NewTableIdent(string(yyDollar[1].bytes)) - } case 304: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1642 + //line sql.y:1640 { - yyVAL.str = JoinStr + yyVAL.tableIdent = NewTableIdent(string(yyDollar[1].bytes)) } case 305: - yyDollar = yyS[yypt-2 : yypt+1] + yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:1646 { yyVAL.str = JoinStr @@ -4212,44 +4215,50 @@ yydefault: yyVAL.str = JoinStr } case 307: - yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1656 + yyDollar = yyS[yypt-2 : yypt+1] + //line sql.y:1654 { - yyVAL.str = StraightJoinStr + yyVAL.str = JoinStr } case 308: - yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1662 + yyDollar = yyS[yypt-1 : yypt+1] + //line sql.y:1660 { - yyVAL.str = LeftJoinStr + yyVAL.str = StraightJoinStr } case 309: - yyDollar = yyS[yypt-3 : yypt+1] + yyDollar = yyS[yypt-2 : yypt+1] //line sql.y:1666 { yyVAL.str = LeftJoinStr } case 310: - yyDollar = yyS[yypt-2 : yypt+1] + yyDollar = yyS[yypt-3 : yypt+1] //line sql.y:1670 { - yyVAL.str = RightJoinStr + yyVAL.str = LeftJoinStr } case 311: - yyDollar = yyS[yypt-3 : yypt+1] + yyDollar = yyS[yypt-2 : yypt+1] //line sql.y:1674 { yyVAL.str = RightJoinStr } case 312: - yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1680 + yyDollar = yyS[yypt-3 : yypt+1] + //line sql.y:1678 { - yyVAL.str = NaturalJoinStr + yyVAL.str = RightJoinStr } case 313: yyDollar = yyS[yypt-2 : yypt+1] //line sql.y:1684 + { + yyVAL.str = NaturalJoinStr + } + case 314: + yyDollar = yyS[yypt-2 : yypt+1] + //line sql.y:1688 { if yyDollar[2].str == LeftJoinStr { yyVAL.str = NaturalLeftJoinStr @@ -4257,401 +4266,395 @@ yydefault: yyVAL.str = NaturalRightJoinStr } } - case 314: + case 315: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1694 + //line sql.y:1698 { yyVAL.tableName = yyDollar[2].tableName } - case 315: + case 316: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1698 + //line sql.y:1702 { yyVAL.tableName = yyDollar[1].tableName } - case 316: + case 317: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1704 + //line sql.y:1708 { yyVAL.tableName = TableName{Name: yyDollar[1].tableIdent} } - case 317: + case 318: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1708 + //line sql.y:1712 { yyVAL.tableName = TableName{Qualifier: yyDollar[1].tableIdent, Name: yyDollar[3].tableIdent} } - case 318: + case 319: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1713 + //line sql.y:1717 { yyVAL.indexHints = nil } - case 319: + case 320: yyDollar = yyS[yypt-5 : yypt+1] - //line sql.y:1717 + //line sql.y:1721 { yyVAL.indexHints = &IndexHints{Type: UseStr, Indexes: yyDollar[4].columns} } - case 320: + case 321: yyDollar = yyS[yypt-5 : yypt+1] - //line sql.y:1721 + //line sql.y:1725 { yyVAL.indexHints = &IndexHints{Type: IgnoreStr, Indexes: yyDollar[4].columns} } - case 321: + case 322: yyDollar = yyS[yypt-5 : yypt+1] - //line sql.y:1725 + //line sql.y:1729 { yyVAL.indexHints = &IndexHints{Type: ForceStr, Indexes: yyDollar[4].columns} } - case 322: + case 323: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1730 + //line sql.y:1734 { yyVAL.expr = nil } - case 323: + case 324: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1734 + //line sql.y:1738 { yyVAL.expr = yyDollar[2].expr } - case 324: + case 325: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1740 + //line sql.y:1744 { yyVAL.expr = yyDollar[1].expr } - case 325: + case 326: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1744 + //line sql.y:1748 { yyVAL.expr = &AndExpr{Left: yyDollar[1].expr, Right: yyDollar[3].expr} } - case 326: + case 327: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1748 + //line sql.y:1752 { yyVAL.expr = &OrExpr{Left: yyDollar[1].expr, Right: yyDollar[3].expr} } - case 327: + case 328: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1752 + //line sql.y:1756 { yyVAL.expr = &NotExpr{Expr: yyDollar[2].expr} } - case 328: + case 329: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1756 + //line sql.y:1760 { yyVAL.expr = &IsExpr{Operator: yyDollar[3].str, Expr: yyDollar[1].expr} } - case 329: + case 330: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1760 + //line sql.y:1764 { yyVAL.expr = yyDollar[1].expr } - case 330: + case 331: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1764 + //line sql.y:1768 { yyVAL.expr = &Default{ColName: yyDollar[2].str} } - case 331: + case 332: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1770 + //line sql.y:1774 { yyVAL.str = "" } - case 332: + case 333: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1774 + //line sql.y:1778 { yyVAL.str = string(yyDollar[2].bytes) } - case 333: - yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1780 - { - yyVAL.boolVal = BoolVal(true) - } case 334: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:1784 { - yyVAL.boolVal = BoolVal(false) + yyVAL.boolVal = BoolVal(true) } case 335: - yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1790 + yyDollar = yyS[yypt-1 : yypt+1] + //line sql.y:1788 { - yyVAL.expr = &ComparisonExpr{Left: yyDollar[1].expr, Operator: yyDollar[2].str, Right: yyDollar[3].expr} + yyVAL.boolVal = BoolVal(false) } case 336: yyDollar = yyS[yypt-3 : yypt+1] //line sql.y:1794 { - yyVAL.expr = &ComparisonExpr{Left: yyDollar[1].expr, Operator: InStr, Right: yyDollar[3].colTuple} + yyVAL.expr = &ComparisonExpr{Left: yyDollar[1].expr, Operator: yyDollar[2].str, Right: yyDollar[3].expr} } case 337: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-3 : yypt+1] //line sql.y:1798 { - yyVAL.expr = &ComparisonExpr{Left: yyDollar[1].expr, Operator: NotInStr, Right: yyDollar[4].colTuple} + yyVAL.expr = &ComparisonExpr{Left: yyDollar[1].expr, Operator: InStr, Right: yyDollar[3].colTuple} } case 338: yyDollar = yyS[yypt-4 : yypt+1] //line sql.y:1802 { - yyVAL.expr = &ComparisonExpr{Left: yyDollar[1].expr, Operator: LikeStr, Right: yyDollar[3].expr, Escape: yyDollar[4].expr} + yyVAL.expr = &ComparisonExpr{Left: yyDollar[1].expr, Operator: NotInStr, Right: yyDollar[4].colTuple} } case 339: - yyDollar = yyS[yypt-5 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] //line sql.y:1806 { - yyVAL.expr = &ComparisonExpr{Left: yyDollar[1].expr, Operator: NotLikeStr, Right: yyDollar[4].expr, Escape: yyDollar[5].expr} + yyVAL.expr = &ComparisonExpr{Left: yyDollar[1].expr, Operator: LikeStr, Right: yyDollar[3].expr, Escape: yyDollar[4].expr} } case 340: - yyDollar = yyS[yypt-3 : yypt+1] + yyDollar = yyS[yypt-5 : yypt+1] //line sql.y:1810 { - yyVAL.expr = &ComparisonExpr{Left: yyDollar[1].expr, Operator: RegexpStr, Right: yyDollar[3].expr} + yyVAL.expr = &ComparisonExpr{Left: yyDollar[1].expr, Operator: NotLikeStr, Right: yyDollar[4].expr, Escape: yyDollar[5].expr} } case 341: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-3 : yypt+1] //line sql.y:1814 { - yyVAL.expr = &ComparisonExpr{Left: yyDollar[1].expr, Operator: NotRegexpStr, Right: yyDollar[4].expr} + yyVAL.expr = &ComparisonExpr{Left: yyDollar[1].expr, Operator: RegexpStr, Right: yyDollar[3].expr} } case 342: - yyDollar = yyS[yypt-5 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] //line sql.y:1818 { - yyVAL.expr = &RangeCond{Left: yyDollar[1].expr, Operator: BetweenStr, From: yyDollar[3].expr, To: yyDollar[5].expr} + yyVAL.expr = &ComparisonExpr{Left: yyDollar[1].expr, Operator: NotRegexpStr, Right: yyDollar[4].expr} } case 343: - yyDollar = yyS[yypt-6 : yypt+1] + yyDollar = yyS[yypt-5 : yypt+1] //line sql.y:1822 { - yyVAL.expr = &RangeCond{Left: yyDollar[1].expr, Operator: NotBetweenStr, From: yyDollar[4].expr, To: yyDollar[6].expr} + yyVAL.expr = &RangeCond{Left: yyDollar[1].expr, Operator: BetweenStr, From: yyDollar[3].expr, To: yyDollar[5].expr} } case 344: - yyDollar = yyS[yypt-2 : yypt+1] + yyDollar = yyS[yypt-6 : yypt+1] //line sql.y:1826 { - yyVAL.expr = &ExistsExpr{Subquery: yyDollar[2].subquery} + yyVAL.expr = &RangeCond{Left: yyDollar[1].expr, Operator: NotBetweenStr, From: yyDollar[4].expr, To: yyDollar[6].expr} } case 345: - yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1832 + yyDollar = yyS[yypt-2 : yypt+1] + //line sql.y:1830 { - yyVAL.str = IsNullStr + yyVAL.expr = &ExistsExpr{Subquery: yyDollar[2].subquery} } case 346: - yyDollar = yyS[yypt-2 : yypt+1] + yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:1836 { - yyVAL.str = IsNotNullStr + yyVAL.str = IsNullStr } case 347: - yyDollar = yyS[yypt-1 : yypt+1] + yyDollar = yyS[yypt-2 : yypt+1] //line sql.y:1840 { - yyVAL.str = IsTrueStr + yyVAL.str = IsNotNullStr } case 348: - yyDollar = yyS[yypt-2 : yypt+1] + yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:1844 { - yyVAL.str = IsNotTrueStr + yyVAL.str = IsTrueStr } case 349: - yyDollar = yyS[yypt-1 : yypt+1] + yyDollar = yyS[yypt-2 : yypt+1] //line sql.y:1848 { - yyVAL.str = IsFalseStr + yyVAL.str = IsNotTrueStr } case 350: - yyDollar = yyS[yypt-2 : yypt+1] + yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:1852 { - yyVAL.str = IsNotFalseStr + yyVAL.str = IsFalseStr } case 351: - yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1858 + yyDollar = yyS[yypt-2 : yypt+1] + //line sql.y:1856 { - yyVAL.str = EqualStr + yyVAL.str = IsNotFalseStr } case 352: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:1862 { - yyVAL.str = LessThanStr + yyVAL.str = EqualStr } case 353: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:1866 { - yyVAL.str = GreaterThanStr + yyVAL.str = LessThanStr } case 354: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:1870 { - yyVAL.str = LessEqualStr + yyVAL.str = GreaterThanStr } case 355: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:1874 { - yyVAL.str = GreaterEqualStr + yyVAL.str = LessEqualStr } case 356: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:1878 { - yyVAL.str = NotEqualStr + yyVAL.str = GreaterEqualStr } case 357: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:1882 { - yyVAL.str = NullSafeEqualStr + yyVAL.str = NotEqualStr } case 358: + yyDollar = yyS[yypt-1 : yypt+1] + //line sql.y:1886 + { + yyVAL.str = NullSafeEqualStr + } + case 359: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1887 + //line sql.y:1891 { yyVAL.expr = nil } - case 359: + case 360: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1891 + //line sql.y:1895 { yyVAL.expr = yyDollar[2].expr } - case 360: + case 361: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1897 + //line sql.y:1901 { yyVAL.colTuple = yyDollar[1].valTuple } - case 361: + case 362: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1901 + //line sql.y:1905 { yyVAL.colTuple = yyDollar[1].subquery } - case 362: + case 363: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1905 + //line sql.y:1909 { yyVAL.colTuple = ListArg(yyDollar[1].bytes) } - case 363: + case 364: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1911 + //line sql.y:1915 { yyVAL.subquery = &Subquery{yyDollar[2].selStmt} } - case 364: + case 365: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1917 + //line sql.y:1921 { yyVAL.exprs = Exprs{yyDollar[1].expr} } - case 365: + case 366: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1921 + //line sql.y:1925 { yyVAL.exprs = append(yyDollar[1].exprs, yyDollar[3].expr) } - case 366: - yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1927 - { - yyVAL.expr = yyDollar[1].expr - } case 367: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:1931 { - yyVAL.expr = yyDollar[1].boolVal + yyVAL.expr = yyDollar[1].expr } case 368: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:1935 { - yyVAL.expr = yyDollar[1].colName + yyVAL.expr = yyDollar[1].boolVal } case 369: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:1939 { - yyVAL.expr = yyDollar[1].expr + yyVAL.expr = yyDollar[1].colName } case 370: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:1943 { - yyVAL.expr = yyDollar[1].subquery + yyVAL.expr = yyDollar[1].expr } case 371: - yyDollar = yyS[yypt-3 : yypt+1] + yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:1947 { - yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: BitAndStr, Right: yyDollar[3].expr} + yyVAL.expr = yyDollar[1].subquery } case 372: yyDollar = yyS[yypt-3 : yypt+1] //line sql.y:1951 { - yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: BitOrStr, Right: yyDollar[3].expr} + yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: BitAndStr, Right: yyDollar[3].expr} } case 373: yyDollar = yyS[yypt-3 : yypt+1] //line sql.y:1955 { - yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: BitXorStr, Right: yyDollar[3].expr} + yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: BitOrStr, Right: yyDollar[3].expr} } case 374: yyDollar = yyS[yypt-3 : yypt+1] //line sql.y:1959 { - yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: PlusStr, Right: yyDollar[3].expr} + yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: BitXorStr, Right: yyDollar[3].expr} } case 375: yyDollar = yyS[yypt-3 : yypt+1] //line sql.y:1963 { - yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: MinusStr, Right: yyDollar[3].expr} + yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: PlusStr, Right: yyDollar[3].expr} } case 376: yyDollar = yyS[yypt-3 : yypt+1] //line sql.y:1967 { - yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: MultStr, Right: yyDollar[3].expr} + yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: MinusStr, Right: yyDollar[3].expr} } case 377: yyDollar = yyS[yypt-3 : yypt+1] //line sql.y:1971 { - yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: DivStr, Right: yyDollar[3].expr} + yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: MultStr, Right: yyDollar[3].expr} } case 378: yyDollar = yyS[yypt-3 : yypt+1] //line sql.y:1975 { - yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: IntDivStr, Right: yyDollar[3].expr} + yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: DivStr, Right: yyDollar[3].expr} } case 379: yyDollar = yyS[yypt-3 : yypt+1] //line sql.y:1979 { - yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: ModStr, Right: yyDollar[3].expr} + yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: IntDivStr, Right: yyDollar[3].expr} } case 380: yyDollar = yyS[yypt-3 : yypt+1] @@ -4663,47 +4666,53 @@ yydefault: yyDollar = yyS[yypt-3 : yypt+1] //line sql.y:1987 { - yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: ShiftLeftStr, Right: yyDollar[3].expr} + yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: ModStr, Right: yyDollar[3].expr} } case 382: yyDollar = yyS[yypt-3 : yypt+1] //line sql.y:1991 { - yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: ShiftRightStr, Right: yyDollar[3].expr} + yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: ShiftLeftStr, Right: yyDollar[3].expr} } case 383: yyDollar = yyS[yypt-3 : yypt+1] //line sql.y:1995 { - yyVAL.expr = &BinaryExpr{Left: yyDollar[1].colName, Operator: JSONExtractOp, Right: yyDollar[3].expr} + yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: ShiftRightStr, Right: yyDollar[3].expr} } case 384: yyDollar = yyS[yypt-3 : yypt+1] //line sql.y:1999 { - yyVAL.expr = &BinaryExpr{Left: yyDollar[1].colName, Operator: JSONUnquoteExtractOp, Right: yyDollar[3].expr} + yyVAL.expr = &BinaryExpr{Left: yyDollar[1].colName, Operator: JSONExtractOp, Right: yyDollar[3].expr} } case 385: yyDollar = yyS[yypt-3 : yypt+1] //line sql.y:2003 { - yyVAL.expr = &CollateExpr{Expr: yyDollar[1].expr, Charset: yyDollar[3].str} + yyVAL.expr = &BinaryExpr{Left: yyDollar[1].colName, Operator: JSONUnquoteExtractOp, Right: yyDollar[3].expr} } case 386: - yyDollar = yyS[yypt-2 : yypt+1] + yyDollar = yyS[yypt-3 : yypt+1] //line sql.y:2007 { - yyVAL.expr = &UnaryExpr{Operator: BinaryStr, Expr: yyDollar[2].expr} + yyVAL.expr = &CollateExpr{Expr: yyDollar[1].expr, Charset: yyDollar[3].str} } case 387: yyDollar = yyS[yypt-2 : yypt+1] //line sql.y:2011 { - yyVAL.expr = &UnaryExpr{Operator: UBinaryStr, Expr: yyDollar[2].expr} + yyVAL.expr = &UnaryExpr{Operator: BinaryStr, Expr: yyDollar[2].expr} } case 388: yyDollar = yyS[yypt-2 : yypt+1] //line sql.y:2015 + { + yyVAL.expr = &UnaryExpr{Operator: UBinaryStr, Expr: yyDollar[2].expr} + } + case 389: + yyDollar = yyS[yypt-2 : yypt+1] + //line sql.y:2019 { if num, ok := yyDollar[2].expr.(*SQLVal); ok && num.Type == IntVal { yyVAL.expr = num @@ -4711,9 +4720,9 @@ yydefault: yyVAL.expr = &UnaryExpr{Operator: UPlusStr, Expr: yyDollar[2].expr} } } - case 389: + case 390: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2023 + //line sql.y:2027 { if num, ok := yyDollar[2].expr.(*SQLVal); ok && num.Type == IntVal { // Handle double negative @@ -4727,21 +4736,21 @@ yydefault: yyVAL.expr = &UnaryExpr{Operator: UMinusStr, Expr: yyDollar[2].expr} } } - case 390: + case 391: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2037 + //line sql.y:2041 { yyVAL.expr = &UnaryExpr{Operator: TildaStr, Expr: yyDollar[2].expr} } - case 391: + case 392: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2041 + //line sql.y:2045 { yyVAL.expr = &UnaryExpr{Operator: BangStr, Expr: yyDollar[2].expr} } - case 392: + case 393: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2045 + //line sql.y:2049 { // This rule prevents the usage of INTERVAL // as a function. If support is needed for that, @@ -4749,41 +4758,35 @@ yydefault: // will be non-trivial because of grammar conflicts. yyVAL.expr = &IntervalExpr{Expr: yyDollar[2].expr, Unit: yyDollar[3].colIdent.String()} } - case 397: + case 398: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:2063 + //line sql.y:2067 { yyVAL.expr = &FuncExpr{Name: yyDollar[1].colIdent, Exprs: yyDollar[3].selectExprs} } - case 398: + case 399: yyDollar = yyS[yypt-5 : yypt+1] - //line sql.y:2067 + //line sql.y:2071 { yyVAL.expr = &FuncExpr{Name: yyDollar[1].colIdent, Distinct: true, Exprs: yyDollar[4].selectExprs} } - case 399: + case 400: yyDollar = yyS[yypt-6 : yypt+1] - //line sql.y:2071 + //line sql.y:2075 { yyVAL.expr = &FuncExpr{Qualifier: yyDollar[1].tableIdent, Name: yyDollar[3].colIdent, Exprs: yyDollar[5].selectExprs} } - case 400: - yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:2081 - { - yyVAL.expr = &FuncExpr{Name: NewColIdent("left"), Exprs: yyDollar[3].selectExprs} - } case 401: yyDollar = yyS[yypt-4 : yypt+1] //line sql.y:2085 { - yyVAL.expr = &FuncExpr{Name: NewColIdent("right"), Exprs: yyDollar[3].selectExprs} + yyVAL.expr = &FuncExpr{Name: NewColIdent("left"), Exprs: yyDollar[3].selectExprs} } case 402: - yyDollar = yyS[yypt-6 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] //line sql.y:2089 { - yyVAL.expr = &ConvertExpr{Expr: yyDollar[3].expr, Type: yyDollar[5].convertType} + yyVAL.expr = &FuncExpr{Name: NewColIdent("right"), Exprs: yyDollar[3].selectExprs} } case 403: yyDollar = yyS[yypt-6 : yypt+1] @@ -4795,19 +4798,19 @@ yydefault: yyDollar = yyS[yypt-6 : yypt+1] //line sql.y:2097 { - yyVAL.expr = &ConvertUsingExpr{Expr: yyDollar[3].expr, Type: yyDollar[5].str} + yyVAL.expr = &ConvertExpr{Expr: yyDollar[3].expr, Type: yyDollar[5].convertType} } case 405: yyDollar = yyS[yypt-6 : yypt+1] //line sql.y:2101 { - yyVAL.expr = &SubstrExpr{Name: yyDollar[3].colName, From: yyDollar[5].expr, To: nil} + yyVAL.expr = &ConvertUsingExpr{Expr: yyDollar[3].expr, Type: yyDollar[5].str} } case 406: - yyDollar = yyS[yypt-8 : yypt+1] + yyDollar = yyS[yypt-6 : yypt+1] //line sql.y:2105 { - yyVAL.expr = &SubstrExpr{Name: yyDollar[3].colName, From: yyDollar[5].expr, To: yyDollar[7].expr} + yyVAL.expr = &SubstrExpr{Name: yyDollar[3].colName, From: yyDollar[5].expr, To: nil} } case 407: yyDollar = yyS[yypt-8 : yypt+1] @@ -4816,16 +4819,16 @@ yydefault: yyVAL.expr = &SubstrExpr{Name: yyDollar[3].colName, From: yyDollar[5].expr, To: yyDollar[7].expr} } case 408: - yyDollar = yyS[yypt-6 : yypt+1] + yyDollar = yyS[yypt-8 : yypt+1] //line sql.y:2113 { - yyVAL.expr = &SubstrExpr{Name: yyDollar[3].colName, From: yyDollar[5].expr, To: nil} + yyVAL.expr = &SubstrExpr{Name: yyDollar[3].colName, From: yyDollar[5].expr, To: yyDollar[7].expr} } case 409: - yyDollar = yyS[yypt-8 : yypt+1] + yyDollar = yyS[yypt-6 : yypt+1] //line sql.y:2117 { - yyVAL.expr = &SubstrExpr{Name: yyDollar[3].colName, From: yyDollar[5].expr, To: yyDollar[7].expr} + yyVAL.expr = &SubstrExpr{Name: yyDollar[3].colName, From: yyDollar[5].expr, To: nil} } case 410: yyDollar = yyS[yypt-8 : yypt+1] @@ -4834,136 +4837,136 @@ yydefault: yyVAL.expr = &SubstrExpr{Name: yyDollar[3].colName, From: yyDollar[5].expr, To: yyDollar[7].expr} } case 411: - yyDollar = yyS[yypt-9 : yypt+1] + yyDollar = yyS[yypt-8 : yypt+1] //line sql.y:2125 { - yyVAL.expr = &MatchExpr{Columns: yyDollar[3].selectExprs, Expr: yyDollar[7].expr, Option: yyDollar[8].str} + yyVAL.expr = &SubstrExpr{Name: yyDollar[3].colName, From: yyDollar[5].expr, To: yyDollar[7].expr} } case 412: - yyDollar = yyS[yypt-7 : yypt+1] + yyDollar = yyS[yypt-9 : yypt+1] //line sql.y:2129 { - yyVAL.expr = &GroupConcatExpr{Distinct: yyDollar[3].str, Exprs: yyDollar[4].selectExprs, OrderBy: yyDollar[5].orderBy, Separator: yyDollar[6].str} + yyVAL.expr = &MatchExpr{Columns: yyDollar[3].selectExprs, Expr: yyDollar[7].expr, Option: yyDollar[8].str} } case 413: - yyDollar = yyS[yypt-5 : yypt+1] + yyDollar = yyS[yypt-7 : yypt+1] //line sql.y:2133 { - yyVAL.expr = &CaseExpr{Expr: yyDollar[2].expr, Whens: yyDollar[3].whens, Else: yyDollar[4].expr} + yyVAL.expr = &GroupConcatExpr{Distinct: yyDollar[3].str, Exprs: yyDollar[4].selectExprs, OrderBy: yyDollar[5].orderBy, Separator: yyDollar[6].str} } case 414: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-5 : yypt+1] //line sql.y:2137 { - yyVAL.expr = &ValuesFuncExpr{Name: yyDollar[3].colIdent} + yyVAL.expr = &CaseExpr{Expr: yyDollar[2].expr, Whens: yyDollar[3].whens, Else: yyDollar[4].expr} } case 415: - yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2147 + yyDollar = yyS[yypt-4 : yypt+1] + //line sql.y:2141 { - yyVAL.expr = &FuncExpr{Name: NewColIdent("current_timestamp")} + yyVAL.expr = &ValuesFuncExpr{Name: yyDollar[3].colIdent} } case 416: yyDollar = yyS[yypt-2 : yypt+1] //line sql.y:2151 { - yyVAL.expr = &FuncExpr{Name: NewColIdent("utc_timestamp")} + yyVAL.expr = &FuncExpr{Name: NewColIdent("current_timestamp")} } case 417: yyDollar = yyS[yypt-2 : yypt+1] //line sql.y:2155 { - yyVAL.expr = &FuncExpr{Name: NewColIdent("utc_time")} + yyVAL.expr = &FuncExpr{Name: NewColIdent("utc_timestamp")} } case 418: yyDollar = yyS[yypt-2 : yypt+1] //line sql.y:2159 { - yyVAL.expr = &FuncExpr{Name: NewColIdent("utc_date")} + yyVAL.expr = &FuncExpr{Name: NewColIdent("utc_time")} } case 419: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2164 + //line sql.y:2163 { - yyVAL.expr = &FuncExpr{Name: NewColIdent("localtime")} + yyVAL.expr = &FuncExpr{Name: NewColIdent("utc_date")} } case 420: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2169 + //line sql.y:2168 { - yyVAL.expr = &FuncExpr{Name: NewColIdent("localtimestamp")} + yyVAL.expr = &FuncExpr{Name: NewColIdent("localtime")} } case 421: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2174 + //line sql.y:2173 { - yyVAL.expr = &FuncExpr{Name: NewColIdent("current_date")} + yyVAL.expr = &FuncExpr{Name: NewColIdent("localtimestamp")} } case 422: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2179 + //line sql.y:2178 { - yyVAL.expr = &FuncExpr{Name: NewColIdent("current_time")} + yyVAL.expr = &FuncExpr{Name: NewColIdent("current_date")} } - case 425: - yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:2193 + case 423: + yyDollar = yyS[yypt-2 : yypt+1] + //line sql.y:2183 { - yyVAL.expr = &FuncExpr{Name: NewColIdent("if"), Exprs: yyDollar[3].selectExprs} + yyVAL.expr = &FuncExpr{Name: NewColIdent("current_time")} } case 426: yyDollar = yyS[yypt-4 : yypt+1] //line sql.y:2197 { - yyVAL.expr = &FuncExpr{Name: NewColIdent("database"), Exprs: yyDollar[3].selectExprs} + yyVAL.expr = &FuncExpr{Name: NewColIdent("if"), Exprs: yyDollar[3].selectExprs} } case 427: yyDollar = yyS[yypt-4 : yypt+1] //line sql.y:2201 { - yyVAL.expr = &FuncExpr{Name: NewColIdent("mod"), Exprs: yyDollar[3].selectExprs} + yyVAL.expr = &FuncExpr{Name: NewColIdent("database"), Exprs: yyDollar[3].selectExprs} } case 428: yyDollar = yyS[yypt-4 : yypt+1] //line sql.y:2205 { - yyVAL.expr = &FuncExpr{Name: NewColIdent("replace"), Exprs: yyDollar[3].selectExprs} + yyVAL.expr = &FuncExpr{Name: NewColIdent("mod"), Exprs: yyDollar[3].selectExprs} } case 429: - yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:2211 + yyDollar = yyS[yypt-4 : yypt+1] + //line sql.y:2209 { - yyVAL.str = "" + yyVAL.expr = &FuncExpr{Name: NewColIdent("replace"), Exprs: yyDollar[3].selectExprs} } case 430: - yyDollar = yyS[yypt-3 : yypt+1] + yyDollar = yyS[yypt-0 : yypt+1] //line sql.y:2215 { - yyVAL.str = BooleanModeStr + yyVAL.str = "" } case 431: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-3 : yypt+1] //line sql.y:2219 { - yyVAL.str = NaturalLanguageModeStr + yyVAL.str = BooleanModeStr } case 432: - yyDollar = yyS[yypt-7 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] //line sql.y:2223 { - yyVAL.str = NaturalLanguageModeWithQueryExpansionStr + yyVAL.str = NaturalLanguageModeStr } case 433: - yyDollar = yyS[yypt-3 : yypt+1] + yyDollar = yyS[yypt-7 : yypt+1] //line sql.y:2227 { - yyVAL.str = QueryExpansionStr + yyVAL.str = NaturalLanguageModeWithQueryExpansionStr } case 434: - yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2233 + yyDollar = yyS[yypt-3 : yypt+1] + //line sql.y:2231 { - yyVAL.str = string(yyDollar[1].bytes) + yyVAL.str = QueryExpansionStr } case 435: yyDollar = yyS[yypt-1 : yypt+1] @@ -4972,63 +4975,63 @@ yydefault: yyVAL.str = string(yyDollar[1].bytes) } case 436: - yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2243 + yyDollar = yyS[yypt-1 : yypt+1] + //line sql.y:2241 { - yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].optVal} + yyVAL.str = string(yyDollar[1].bytes) } case 437: - yyDollar = yyS[yypt-3 : yypt+1] + yyDollar = yyS[yypt-2 : yypt+1] //line sql.y:2247 { - yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].optVal, Charset: yyDollar[3].str, Operator: CharacterSetStr} + yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].optVal} } case 438: yyDollar = yyS[yypt-3 : yypt+1] //line sql.y:2251 { - yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].optVal, Charset: string(yyDollar[3].bytes)} + yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].optVal, Charset: yyDollar[3].str, Operator: CharacterSetStr} } case 439: - yyDollar = yyS[yypt-1 : yypt+1] + yyDollar = yyS[yypt-3 : yypt+1] //line sql.y:2255 { - yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} + yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].optVal, Charset: string(yyDollar[3].bytes)} } case 440: - yyDollar = yyS[yypt-2 : yypt+1] + yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:2259 { - yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].optVal} + yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} } case 441: yyDollar = yyS[yypt-2 : yypt+1] //line sql.y:2263 { - yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} - yyVAL.convertType.Length = yyDollar[2].LengthScaleOption.Length - yyVAL.convertType.Scale = yyDollar[2].LengthScaleOption.Scale + yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].optVal} } case 442: - yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2269 + yyDollar = yyS[yypt-2 : yypt+1] + //line sql.y:2267 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} + yyVAL.convertType.Length = yyDollar[2].LengthScaleOption.Length + yyVAL.convertType.Scale = yyDollar[2].LengthScaleOption.Scale } case 443: - yyDollar = yyS[yypt-2 : yypt+1] + yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:2273 { - yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].optVal} + yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} } case 444: - yyDollar = yyS[yypt-1 : yypt+1] + yyDollar = yyS[yypt-2 : yypt+1] //line sql.y:2277 { - yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} + yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].optVal} } case 445: - yyDollar = yyS[yypt-2 : yypt+1] + yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:2281 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} @@ -5037,143 +5040,149 @@ yydefault: yyDollar = yyS[yypt-2 : yypt+1] //line sql.y:2285 { - yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].optVal} + yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} } case 447: - yyDollar = yyS[yypt-1 : yypt+1] + yyDollar = yyS[yypt-2 : yypt+1] //line sql.y:2289 { - yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} + yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].optVal} } case 448: - yyDollar = yyS[yypt-2 : yypt+1] + yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:2293 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} } case 449: + yyDollar = yyS[yypt-2 : yypt+1] + //line sql.y:2297 + { + yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} + } + case 450: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:2298 + //line sql.y:2302 { yyVAL.expr = nil } - case 450: + case 451: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2302 + //line sql.y:2306 { yyVAL.expr = yyDollar[1].expr } - case 451: + case 452: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:2307 + //line sql.y:2311 { yyVAL.str = string("") } - case 452: + case 453: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2311 + //line sql.y:2315 { yyVAL.str = " separator '" + string(yyDollar[2].bytes) + "'" } - case 453: + case 454: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2317 + //line sql.y:2321 { yyVAL.whens = []*When{yyDollar[1].when} } - case 454: + case 455: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2321 + //line sql.y:2325 { yyVAL.whens = append(yyDollar[1].whens, yyDollar[2].when) } - case 455: + case 456: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:2327 + //line sql.y:2331 { yyVAL.when = &When{Cond: yyDollar[2].expr, Val: yyDollar[4].expr} } - case 456: + case 457: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:2332 + //line sql.y:2336 { yyVAL.expr = nil } - case 457: + case 458: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2336 + //line sql.y:2340 { yyVAL.expr = yyDollar[2].expr } - case 458: - yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2342 - { - yyVAL.colName = &ColName{Name: yyDollar[1].colIdent} - } case 459: - yyDollar = yyS[yypt-3 : yypt+1] + yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:2346 { - yyVAL.colName = &ColName{Qualifier: TableName{Name: yyDollar[1].tableIdent}, Name: yyDollar[3].colIdent} + yyVAL.colName = &ColName{Name: yyDollar[1].colIdent} } case 460: - yyDollar = yyS[yypt-5 : yypt+1] + yyDollar = yyS[yypt-3 : yypt+1] //line sql.y:2350 { - yyVAL.colName = &ColName{Qualifier: TableName{Qualifier: yyDollar[1].tableIdent, Name: yyDollar[3].tableIdent}, Name: yyDollar[5].colIdent} + yyVAL.colName = &ColName{Qualifier: TableName{Name: yyDollar[1].tableIdent}, Name: yyDollar[3].colIdent} } case 461: - yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2356 + yyDollar = yyS[yypt-5 : yypt+1] + //line sql.y:2354 { - yyVAL.expr = NewStrVal(yyDollar[1].bytes) + yyVAL.colName = &ColName{Qualifier: TableName{Qualifier: yyDollar[1].tableIdent, Name: yyDollar[3].tableIdent}, Name: yyDollar[5].colIdent} } case 462: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:2360 { - yyVAL.expr = NewHexVal(yyDollar[1].bytes) + yyVAL.expr = NewStrVal(yyDollar[1].bytes) } case 463: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:2364 { - yyVAL.expr = NewBitVal(yyDollar[1].bytes) + yyVAL.expr = NewHexVal(yyDollar[1].bytes) } case 464: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:2368 { - yyVAL.expr = NewIntVal(yyDollar[1].bytes) + yyVAL.expr = NewBitVal(yyDollar[1].bytes) } case 465: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:2372 { - yyVAL.expr = NewFloatVal(yyDollar[1].bytes) + yyVAL.expr = NewIntVal(yyDollar[1].bytes) } case 466: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:2376 { - yyVAL.expr = NewHexNum(yyDollar[1].bytes) + yyVAL.expr = NewFloatVal(yyDollar[1].bytes) } case 467: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:2380 { - yyVAL.expr = NewValArg(yyDollar[1].bytes) + yyVAL.expr = NewHexNum(yyDollar[1].bytes) } case 468: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:2384 { - yyVAL.expr = &NullVal{} + yyVAL.expr = NewValArg(yyDollar[1].bytes) } case 469: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2390 + //line sql.y:2388 + { + yyVAL.expr = &NullVal{} + } + case 470: + yyDollar = yyS[yypt-1 : yypt+1] + //line sql.y:2394 { // TODO(sougou): Deprecate this construct. if yyDollar[1].colIdent.Lowered() != "value" { @@ -5182,239 +5191,239 @@ yydefault: } yyVAL.expr = NewIntVal([]byte("1")) } - case 470: + case 471: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2399 + //line sql.y:2403 { yyVAL.expr = NewIntVal(yyDollar[1].bytes) } - case 471: + case 472: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2403 + //line sql.y:2407 { yyVAL.expr = NewValArg(yyDollar[1].bytes) } - case 472: + case 473: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:2408 + //line sql.y:2412 { yyVAL.exprs = nil } - case 473: + case 474: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2412 + //line sql.y:2416 { yyVAL.exprs = yyDollar[3].exprs } - case 474: + case 475: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:2417 + //line sql.y:2421 { yyVAL.expr = nil } - case 475: + case 476: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2421 + //line sql.y:2425 { yyVAL.expr = yyDollar[2].expr } - case 476: + case 477: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:2426 + //line sql.y:2430 { yyVAL.orderBy = nil } - case 477: + case 478: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2430 + //line sql.y:2434 { yyVAL.orderBy = yyDollar[3].orderBy } - case 478: + case 479: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2436 + //line sql.y:2440 { yyVAL.orderBy = OrderBy{yyDollar[1].order} } - case 479: + case 480: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2440 + //line sql.y:2444 { yyVAL.orderBy = append(yyDollar[1].orderBy, yyDollar[3].order) } - case 480: + case 481: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2446 + //line sql.y:2450 { yyVAL.order = &Order{Expr: yyDollar[1].expr, Direction: yyDollar[2].str} } - case 481: + case 482: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:2451 + //line sql.y:2455 { yyVAL.str = AscScr } - case 482: + case 483: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2455 + //line sql.y:2459 { yyVAL.str = AscScr } - case 483: + case 484: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2459 + //line sql.y:2463 { yyVAL.str = DescScr } - case 484: + case 485: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:2464 + //line sql.y:2468 { yyVAL.limit = nil } - case 485: + case 486: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2468 + //line sql.y:2472 { yyVAL.limit = &Limit{Rowcount: yyDollar[2].expr} } - case 486: + case 487: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:2472 + //line sql.y:2476 { yyVAL.limit = &Limit{Offset: yyDollar[2].expr, Rowcount: yyDollar[4].expr} } - case 487: + case 488: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:2476 + //line sql.y:2480 { yyVAL.limit = &Limit{Offset: yyDollar[4].expr, Rowcount: yyDollar[2].expr} } - case 488: + case 489: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:2481 + //line sql.y:2485 { yyVAL.str = "" } - case 489: + case 490: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2485 + //line sql.y:2489 { yyVAL.str = ForUpdateStr } - case 490: + case 491: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:2489 + //line sql.y:2493 { yyVAL.str = ShareModeStr } - case 491: + case 492: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2502 + //line sql.y:2506 { yyVAL.ins = &Insert{Rows: yyDollar[2].values} } - case 492: + case 493: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2506 + //line sql.y:2510 { yyVAL.ins = &Insert{Rows: yyDollar[1].selStmt} } - case 493: + case 494: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2510 + //line sql.y:2514 { // Drop the redundant parenthesis. yyVAL.ins = &Insert{Rows: yyDollar[2].selStmt} } - case 494: + case 495: yyDollar = yyS[yypt-5 : yypt+1] - //line sql.y:2515 + //line sql.y:2519 { yyVAL.ins = &Insert{Columns: yyDollar[2].columns, Rows: yyDollar[5].values} } - case 495: + case 496: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:2519 + //line sql.y:2523 { yyVAL.ins = &Insert{Columns: yyDollar[2].columns, Rows: yyDollar[4].selStmt} } - case 496: + case 497: yyDollar = yyS[yypt-6 : yypt+1] - //line sql.y:2523 + //line sql.y:2527 { // Drop the redundant parenthesis. yyVAL.ins = &Insert{Columns: yyDollar[2].columns, Rows: yyDollar[5].selStmt} } - case 497: + case 498: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2530 + //line sql.y:2534 { yyVAL.columns = Columns{yyDollar[1].colIdent} } - case 498: + case 499: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2534 + //line sql.y:2538 { yyVAL.columns = Columns{yyDollar[3].colIdent} } - case 499: + case 500: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2538 + //line sql.y:2542 { yyVAL.columns = append(yyVAL.columns, yyDollar[3].colIdent) } - case 500: + case 501: yyDollar = yyS[yypt-5 : yypt+1] - //line sql.y:2542 + //line sql.y:2546 { yyVAL.columns = append(yyVAL.columns, yyDollar[5].colIdent) } - case 501: + case 502: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:2547 + //line sql.y:2551 { yyVAL.updateExprs = nil } - case 502: + case 503: yyDollar = yyS[yypt-5 : yypt+1] - //line sql.y:2551 + //line sql.y:2555 { yyVAL.updateExprs = yyDollar[5].updateExprs } - case 503: + case 504: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2557 + //line sql.y:2561 { yyVAL.values = Values{yyDollar[1].valTuple} } - case 504: + case 505: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2561 + //line sql.y:2565 { yyVAL.values = append(yyDollar[1].values, yyDollar[3].valTuple) } - case 505: + case 506: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2567 + //line sql.y:2571 { yyVAL.valTuple = yyDollar[1].valTuple } - case 506: + case 507: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2571 + //line sql.y:2575 { yyVAL.valTuple = ValTuple{} } - case 507: + case 508: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2577 + //line sql.y:2581 { yyVAL.valTuple = ValTuple(yyDollar[2].exprs) } - case 508: + case 509: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2583 + //line sql.y:2587 { if len(yyDollar[1].valTuple) == 1 { yyVAL.expr = &ParenExpr{yyDollar[1].valTuple[0]} @@ -5422,183 +5431,177 @@ yydefault: yyVAL.expr = yyDollar[1].valTuple } } - case 509: + case 510: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2593 + //line sql.y:2597 { yyVAL.updateExprs = UpdateExprs{yyDollar[1].updateExpr} } - case 510: + case 511: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2597 + //line sql.y:2601 { yyVAL.updateExprs = append(yyDollar[1].updateExprs, yyDollar[3].updateExpr) } - case 511: + case 512: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2603 + //line sql.y:2607 { yyVAL.updateExpr = &UpdateExpr{Name: yyDollar[1].colName, Expr: yyDollar[3].expr} } - case 512: + case 513: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2609 + //line sql.y:2613 { yyVAL.setExprs = SetExprs{yyDollar[1].setExpr} } - case 513: + case 514: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2613 + //line sql.y:2617 { yyVAL.setExprs = append(yyDollar[1].setExprs, yyDollar[3].setExpr) } - case 514: + case 515: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2619 + //line sql.y:2623 { yyVAL.setExpr = &SetExpr{Name: yyDollar[1].colIdent, Expr: yyDollar[3].expr} } - case 515: + case 516: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2623 + //line sql.y:2627 { yyVAL.setExpr = &SetExpr{Name: NewColIdent(string(yyDollar[1].bytes)), Expr: yyDollar[2].expr} } - case 517: + case 518: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2630 + //line sql.y:2634 { yyVAL.bytes = []byte("charset") } - case 519: + case 520: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2637 + //line sql.y:2641 { yyVAL.expr = NewStrVal([]byte(yyDollar[1].colIdent.String())) } - case 520: + case 521: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2641 + //line sql.y:2645 { yyVAL.expr = NewStrVal(yyDollar[1].bytes) } - case 521: + case 522: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2645 + //line sql.y:2649 { yyVAL.expr = &Default{} } - case 524: + case 525: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:2654 + //line sql.y:2658 { yyVAL.byt = 0 } - case 525: + case 526: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2656 + //line sql.y:2660 { yyVAL.byt = 1 } - case 526: + case 527: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:2659 + //line sql.y:2663 { yyVAL.empty = struct{}{} } - case 527: + case 528: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:2661 + //line sql.y:2665 { yyVAL.empty = struct{}{} } - case 528: + case 529: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:2664 + //line sql.y:2668 { yyVAL.str = "" } - case 529: - yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2666 - { - yyVAL.str = IgnoreStr - } case 530: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:2670 { - yyVAL.empty = struct{}{} + yyVAL.str = IgnoreStr } case 531: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2672 + //line sql.y:2674 { yyVAL.empty = struct{}{} } case 532: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2674 + //line sql.y:2676 { yyVAL.empty = struct{}{} } case 533: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2676 + //line sql.y:2678 { yyVAL.empty = struct{}{} } case 534: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2678 + //line sql.y:2680 { yyVAL.empty = struct{}{} } case 535: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2680 + //line sql.y:2682 { yyVAL.empty = struct{}{} } case 536: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2682 + //line sql.y:2684 { yyVAL.empty = struct{}{} } case 537: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2684 + //line sql.y:2686 { yyVAL.empty = struct{}{} } case 538: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2686 + //line sql.y:2688 { yyVAL.empty = struct{}{} } case 539: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2688 + //line sql.y:2690 { yyVAL.empty = struct{}{} } case 540: - yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:2691 + yyDollar = yyS[yypt-1 : yypt+1] + //line sql.y:2692 { yyVAL.empty = struct{}{} } case 541: - yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2693 + yyDollar = yyS[yypt-0 : yypt+1] + //line sql.y:2695 { yyVAL.empty = struct{}{} } case 542: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2695 + //line sql.y:2697 { yyVAL.empty = struct{}{} } @@ -5610,45 +5613,45 @@ yydefault: } case 544: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2701 + //line sql.y:2703 { yyVAL.empty = struct{}{} } case 545: - yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:2704 + yyDollar = yyS[yypt-1 : yypt+1] + //line sql.y:2705 { yyVAL.empty = struct{}{} } case 546: - yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2706 + yyDollar = yyS[yypt-0 : yypt+1] + //line sql.y:2708 { yyVAL.empty = struct{}{} } case 547: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2708 + //line sql.y:2710 { yyVAL.empty = struct{}{} } case 548: - yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:2711 + yyDollar = yyS[yypt-1 : yypt+1] + //line sql.y:2712 { - yyVAL.colIdent = ColIdent{} + yyVAL.empty = struct{}{} } case 549: - yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:2713 + yyDollar = yyS[yypt-0 : yypt+1] + //line sql.y:2715 { - yyVAL.colIdent = yyDollar[2].colIdent + yyVAL.colIdent = ColIdent{} } case 550: - yyDollar = yyS[yypt-1 : yypt+1] + yyDollar = yyS[yypt-2 : yypt+1] //line sql.y:2717 { - yyVAL.colIdent = NewColIdent(string(yyDollar[1].bytes)) + yyVAL.colIdent = yyDollar[2].colIdent } case 551: yyDollar = yyS[yypt-1 : yypt+1] @@ -5656,17 +5659,17 @@ yydefault: { yyVAL.colIdent = NewColIdent(string(yyDollar[1].bytes)) } - case 553: + case 552: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2728 + //line sql.y:2725 { yyVAL.colIdent = NewColIdent(string(yyDollar[1].bytes)) } case 554: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2734 + //line sql.y:2732 { - yyVAL.tableIdent = NewTableIdent(string(yyDollar[1].bytes)) + yyVAL.colIdent = NewColIdent(string(yyDollar[1].bytes)) } case 555: yyDollar = yyS[yypt-1 : yypt+1] @@ -5674,41 +5677,41 @@ yydefault: { yyVAL.tableIdent = NewTableIdent(string(yyDollar[1].bytes)) } - case 557: + case 556: + yyDollar = yyS[yypt-1 : yypt+1] + //line sql.y:2742 + { + yyVAL.tableIdent = NewTableIdent(string(yyDollar[1].bytes)) + } + case 558: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2745 + //line sql.y:2749 { yyVAL.tableIdent = NewTableIdent(string(yyDollar[1].bytes)) } - case 738: + case 739: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2951 + //line sql.y:2955 { if incNesting(yylex) { yylex.Error("max nesting level reached") return 1 } } - case 739: + case 740: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2960 + //line sql.y:2964 { decNesting(yylex) } - case 740: - yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:2965 - { - forceEOF(yylex) - } case 741: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:2970 + //line sql.y:2969 { forceEOF(yylex) } case 742: - yyDollar = yyS[yypt-1 : yypt+1] + yyDollar = yyS[yypt-0 : yypt+1] //line sql.y:2974 { forceEOF(yylex) @@ -5719,6 +5722,12 @@ yydefault: { forceEOF(yylex) } + case 744: + yyDollar = yyS[yypt-1 : yypt+1] + //line sql.y:2982 + { + forceEOF(yylex) + } } goto yystack /* stack new state and value */ } diff --git a/go/vt/sqlparser/sql.y b/go/vt/sqlparser/sql.y index eb6f7d78cf0..40e4ddcfd16 100644 --- a/go/vt/sqlparser/sql.y +++ b/go/vt/sqlparser/sql.y @@ -419,6 +419,10 @@ delete_statement: { $$ = &Delete{Comments: Comments($2), TableExprs: TableExprs{&AliasedTableExpr{Expr:$4}}, Partitions: $5, Where: NewWhere(WhereStr, $6), OrderBy: $7, Limit: $8} } +| DELETE comment_opt FROM table_name_list USING table_references where_expression_opt + { + $$ = &Delete{Comments: Comments($2), Targets: $4, TableExprs: $6, Where: NewWhere(WhereStr, $7)} + } | DELETE comment_opt table_name_list from_or_using table_references where_expression_opt { $$ = &Delete{Comments: Comments($2), Targets: $3, TableExprs: $5, Where: NewWhere(WhereStr, $6)} From fbe5eb4686efb7bb19dd8640706fafaba9e93252 Mon Sep 17 00:00:00 2001 From: Michael Berlin Date: Sat, 28 Apr 2018 08:55:00 -0700 Subject: [PATCH 18/41] stats: Fix invalid format string in test. Signed-off-by: Michael Berlin --- go/stats/counter_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go/stats/counter_test.go b/go/stats/counter_test.go index bc2dbd17181..439e4d6a096 100644 --- a/go/stats/counter_test.go +++ b/go/stats/counter_test.go @@ -62,7 +62,7 @@ func TestGaugeFunc(t *testing.T) { return 1 }) if v.String() != "1" { - t.Errorf("want 1, got %f", v.String()) + t.Errorf("want 1, got %v", v.String()) } if gotv != v { t.Errorf("want %#v, got %#v", v, gotv) From 56190fa3cc6a855a1541f0692c22e55600f72efc Mon Sep 17 00:00:00 2001 From: Michael Berlin Date: Sat, 28 Apr 2018 08:57:55 -0700 Subject: [PATCH 19/41] stats: Reorder calls in test to make them consistent with the other tests. "gotname" and "gotv" type should always be checked first. Signed-off-by: Michael Berlin --- go/stats/counter_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/go/stats/counter_test.go b/go/stats/counter_test.go index 439e4d6a096..465621acf3e 100644 --- a/go/stats/counter_test.go +++ b/go/stats/counter_test.go @@ -61,13 +61,13 @@ func TestGaugeFunc(t *testing.T) { v := NewGaugeFunc("name", "help", func() int64 { return 1 }) - if v.String() != "1" { - t.Errorf("want 1, got %v", v.String()) + if gotname != "name" { + t.Errorf("want name, got %s", gotname) } if gotv != v { t.Errorf("want %#v, got %#v", v, gotv) } - if gotname != "name" { - t.Errorf("want name, got %s", gotname) + if v.String() != "1" { + t.Errorf("want 1, got %v", v.String()) } } From cd6afec7765769e1fd8a0afcb8f448140c591f80 Mon Sep 17 00:00:00 2001 From: Michael Berlin Date: Sat, 28 Apr 2018 09:17:45 -0700 Subject: [PATCH 20/41] stats: Split Duration* types into CounterDuration* and GaugeDuration*. So far, the pool wait time is the only metric in our code base which requires a counter duration. All other metrics are just exposures of a duration configuration parameter. Signed-off-by: Michael Berlin --- go/stats/duration.go | 103 ++++++++++++------ go/stats/duration_test.go | 76 ++++++++++--- .../prometheusbackend/prometheusbackend.go | 10 +- .../prometheusbackend_test.go | 29 ++++- go/vt/dbconnpool/connection_pool.go | 4 +- go/vt/vttablet/tabletserver/connpool/pool.go | 4 +- go/vt/vttablet/tabletserver/schema/engine.go | 2 +- go/vt/vttablet/tabletserver/tabletserver.go | 6 +- go/vt/vttablet/tabletserver/tx_pool.go | 2 +- 9 files changed, 172 insertions(+), 64 deletions(-) diff --git a/go/stats/duration.go b/go/stats/duration.go index d537bc7f52c..3e32054915f 100644 --- a/go/stats/duration.go +++ b/go/stats/duration.go @@ -23,72 +23,111 @@ import ( "vitess.io/vitess/go/sync2" ) -// Duration exports a time.Duration -type Duration struct { +// CounterDuration exports a time.Duration as counter. +type CounterDuration struct { i sync2.AtomicDuration help string } -// NewDuration returns a new Duration. -func NewDuration(name, help string) *Duration { - v := &Duration{ +// NewCounterDuration returns a new CounterDuration. +func NewCounterDuration(name, help string) *CounterDuration { + cd := &CounterDuration{ help: help, } - publish(name, v) - return v + publish(name, cd) + return cd } // Help implements the Variable interface. -func (v Duration) Help() string { - return v.help +func (cd CounterDuration) Help() string { + return cd.help } // String is the implementation of expvar.var. -func (v Duration) String() string { - return strconv.FormatInt(int64(v.i.Get()), 10) +func (cd CounterDuration) String() string { + return strconv.FormatInt(int64(cd.i.Get()), 10) } -// Add adds the provided value to the Duration -func (v *Duration) Add(delta time.Duration) { - v.i.Add(delta) +// Add adds the provided value to the CounterDuration. +func (cd *CounterDuration) Add(delta time.Duration) { + cd.i.Add(delta) } -// Set sets the value -func (v *Duration) Set(value time.Duration) { - v.i.Set(value) +// Get returns the value. +func (cd *CounterDuration) Get() time.Duration { + return cd.i.Get() } -// Get returns the value -func (v *Duration) Get() time.Duration { - return v.i.Get() +// GaugeDuration exports a time.Duration as gauge. +// In addition to CounterDuration, it also has Set() which allows overriding +// the current value. +type GaugeDuration struct { + CounterDuration } -// DurationFunc allows to provide the value via a custom function. -type DurationFunc struct { +// NewGaugeDuration returns a new GaugeDuration. +func NewGaugeDuration(name, help string) *GaugeDuration { + gd := &GaugeDuration{ + CounterDuration: CounterDuration{ + help: help, + }, + } + publish(name, gd) + return gd +} + +// Set sets the value. +func (gd *GaugeDuration) Set(value time.Duration) { + gd.i.Set(value) +} + +// CounterDurationFunc allows to provide the value via a custom function. +type CounterDurationFunc struct { F func() time.Duration help string } -// NewDurationFunc creates a new DurationFunc instance and publishes it if name -// is set. -func NewDurationFunc(name string, help string, f func() time.Duration) *DurationFunc { - df := &DurationFunc{ +// NewCounterDurationFunc creates a new CounterDurationFunc instance and +// publishes it if name is set. +func NewCounterDurationFunc(name string, help string, f func() time.Duration) *CounterDurationFunc { + cf := &CounterDurationFunc{ F: f, help: help, } if name != "" { - publish(name, df) + publish(name, cf) } - return df + return cf } // Help implements the Variable interface. -func (df DurationFunc) Help() string { - return df.help +func (cf CounterDurationFunc) Help() string { + return cf.help } // String is the implementation of expvar.var. -func (df DurationFunc) String() string { - return strconv.FormatInt(int64(df.F()), 10) +func (cf CounterDurationFunc) String() string { + return strconv.FormatInt(int64(cf.F()), 10) +} + +// GaugeDurationFunc allows to provide the value via a custom function. +type GaugeDurationFunc struct { + CounterDurationFunc +} + +// NewGaugeDurationFunc creates a new GaugeDurationFunc instance and +// publishes it if name is set. +func NewGaugeDurationFunc(name string, help string, f func() time.Duration) *GaugeDurationFunc { + gf := &GaugeDurationFunc{ + CounterDurationFunc: CounterDurationFunc{ + F: f, + help: help, + }, + } + + if name != "" { + publish(name, gf) + } + return gf } diff --git a/go/stats/duration_test.go b/go/stats/duration_test.go index f463d911e6e..f661a5be590 100644 --- a/go/stats/duration_test.go +++ b/go/stats/duration_test.go @@ -22,17 +22,67 @@ import ( "time" ) -func TestDuration(t *testing.T) { +func TestCounterDuration(t *testing.T) { var gotname string - var gotv *Duration + var gotv *CounterDuration clear() Register(func(name string, v expvar.Var) { gotname = name - gotv = v.(*Duration) + gotv = v.(*CounterDuration) }) - v := NewDuration("Duration", "help") - if gotname != "Duration" { - t.Errorf("want Duration, got %s", gotname) + v := NewCounterDuration("CounterDuration", "help") + if gotname != "CounterDuration" { + t.Errorf("want CounterDuration, got %s", gotname) + } + if gotv != v { + t.Errorf("want %#v, got %#v", v, gotv) + } + if v.Get() != 0 { + t.Errorf("want 0, got %v", v.Get()) + } + v.Add(time.Duration(1)) + if v.Get() != 1 { + t.Errorf("want 1, got %v", v.Get()) + } + if v.String() != "1" { + t.Errorf("want 1, got %v", v.Get()) + } +} + +func TestCounterDurationFunc(t *testing.T) { + var gotname string + var gotv *CounterDurationFunc + clear() + Register(func(name string, v expvar.Var) { + gotname = name + gotv = v.(*CounterDurationFunc) + }) + + v := NewCounterDurationFunc("CounterDurationFunc", "help", func() time.Duration { + return time.Duration(1) + }) + if gotname != "CounterDurationFunc" { + t.Errorf("want CounterDurationFunc, got %s", gotname) + } + if gotv != v { + t.Errorf("want %#v, got %#v", v, gotv) + } + if v.String() != "1" { + t.Errorf("want 1, got %v", v.String()) + } +} + +func TestGaugeDuration(t *testing.T) { + var gotname string + var gotv *GaugeDuration + clear() + Register(func(name string, v expvar.Var) { + gotname = name + gotv = v.(*GaugeDuration) + }) + v := NewGaugeDuration("GaugeDuration", "help") + if gotname != "GaugeDuration" { + t.Errorf("want GaugeDuration, got %s", gotname) } if gotv != v { t.Errorf("want %#v, got %#v", v, gotv) @@ -50,26 +100,26 @@ func TestDuration(t *testing.T) { } } -func TestDurationFunc(t *testing.T) { +func TestGaugeDurationFunc(t *testing.T) { var gotname string - var gotv *DurationFunc + var gotv *GaugeDurationFunc clear() Register(func(name string, v expvar.Var) { gotname = name - gotv = v.(*DurationFunc) + gotv = v.(*GaugeDurationFunc) }) - v := NewDurationFunc("duration", "help", func() time.Duration { + v := NewGaugeDurationFunc("GaugeDurationFunc", "help", func() time.Duration { return time.Duration(1) }) + if gotname != "GaugeDurationFunc" { + t.Errorf("want GaugeDurationFunc, got %s", gotname) + } if gotv != v { t.Errorf("want %#v, got %#v", v, gotv) } if v.String() != "1" { t.Errorf("want 1, got %v", v.String()) } - if gotname != "duration" { - t.Errorf("want duration, got %s", gotname) - } } diff --git a/go/stats/prometheusbackend/prometheusbackend.go b/go/stats/prometheusbackend/prometheusbackend.go index 372e6cbb579..79f39b7d5a6 100644 --- a/go/stats/prometheusbackend/prometheusbackend.go +++ b/go/stats/prometheusbackend/prometheusbackend.go @@ -53,11 +53,13 @@ func (be *PromBackend) publishPrometheusMetric(name string, v expvar.Var) { be.newGaugesWithLabels(st, name, st.LabelName(), prometheus.GaugeValue) case *stats.GaugesWithMultiLabels: be.newGaugesWithMultiLabels(st, name) - case *stats.Duration: - // TODO(mberlin): For now, we only support duration as gauge value. + case *stats.CounterDuration: + be.newMetric(st, name, prometheus.CounterValue, func() float64 { return st.Get().Seconds() }) + case *stats.CounterDurationFunc: + be.newMetric(st, name, prometheus.CounterValue, func() float64 { return st.F().Seconds() }) + case *stats.GaugeDuration: be.newMetric(st, name, prometheus.GaugeValue, func() float64 { return st.Get().Seconds() }) - case *stats.DurationFunc: - // TODO(mberlin): For now, we only support duration as gauge value. + case *stats.GaugeDurationFunc: be.newMetric(st, name, prometheus.GaugeValue, func() float64 { return st.F().Seconds() }) case *stats.Timings: be.newTiming(st, name) diff --git a/go/stats/prometheusbackend/prometheusbackend_test.go b/go/stats/prometheusbackend/prometheusbackend_test.go index 3b44b6b59ad..021b8c4762a 100644 --- a/go/stats/prometheusbackend/prometheusbackend_test.go +++ b/go/stats/prometheusbackend/prometheusbackend_test.go @@ -59,19 +59,36 @@ func TestPrometheusGaugeFunc(t *testing.T) { checkHandlerForMetrics(t, name, -3) } -func TestPrometheusDuration(t *testing.T) { - name := "blah_duration" +func TestPrometheusCounterDuration(t *testing.T) { + name := "blah_counterduration" - d := stats.NewDuration(name, "help") + d := stats.NewCounterDuration(name, "help") + d.Add(1 * time.Second) + + checkHandlerForMetrics(t, name, 1) +} + +func TestPrometheusCounterDurationFunc(t *testing.T) { + name := "blah_counterdurationfunc" + + stats.NewCounterDurationFunc(name, "help", func() time.Duration { return 1 * time.Second }) + + checkHandlerForMetrics(t, name, 1) +} + +func TestPrometheusGaugeDuration(t *testing.T) { + name := "blah_gaugeduration" + + d := stats.NewGaugeDuration(name, "help") d.Set(1 * time.Second) checkHandlerForMetrics(t, name, 1) } -func TestPrometheusDurationFunc(t *testing.T) { - name := "blah_durationfunc" +func TestPrometheusGaugeDurationFunc(t *testing.T) { + name := "blah_gaugedurationfunc" - stats.NewDurationFunc(name, "help", func() time.Duration { return 1 * time.Second }) + stats.NewGaugeDurationFunc(name, "help", func() time.Duration { return 1 * time.Second }) checkHandlerForMetrics(t, name, 1) } diff --git a/go/vt/dbconnpool/connection_pool.go b/go/vt/dbconnpool/connection_pool.go index f2de0a79143..3a9e4b00cc8 100644 --- a/go/vt/dbconnpool/connection_pool.go +++ b/go/vt/dbconnpool/connection_pool.go @@ -71,8 +71,8 @@ func NewConnectionPool(name string, capacity int, idleTimeout time.Duration) *Co stats.NewGaugeFunc(name+"InUse", "Connection pool in-use", cp.InUse) stats.NewGaugeFunc(name+"MaxCap", "Connection pool max cap", cp.MaxCap) stats.NewCounterFunc(name+"WaitCount", "Connection pool wait count", cp.WaitCount) - stats.NewDurationFunc(name+"WaitTime", "Connection pool wait time", cp.WaitTime) - stats.NewDurationFunc(name+"IdleTimeout", "Connection pool idle timeout", cp.IdleTimeout) + stats.NewCounterDurationFunc(name+"WaitTime", "Connection pool wait time", cp.WaitTime) + stats.NewGaugeDurationFunc(name+"IdleTimeout", "Connection pool idle timeout", cp.IdleTimeout) stats.NewGaugeFunc(name+"IdleClosed", "Connection pool idle closed", cp.IdleClosed) return cp } diff --git a/go/vt/vttablet/tabletserver/connpool/pool.go b/go/vt/vttablet/tabletserver/connpool/pool.go index f010b652d03..7c96b1dd642 100644 --- a/go/vt/vttablet/tabletserver/connpool/pool.go +++ b/go/vt/vttablet/tabletserver/connpool/pool.go @@ -88,8 +88,8 @@ func New( stats.NewGaugeFunc(name+"InUse", "Tablet server conn pool in use", cp.InUse) stats.NewGaugeFunc(name+"MaxCap", "Tablet server conn pool max cap", cp.MaxCap) stats.NewCounterFunc(name+"WaitCount", "Tablet server conn pool wait count", cp.WaitCount) - stats.NewDurationFunc(name+"WaitTime", "Tablet server wait time", cp.WaitTime) - stats.NewDurationFunc(name+"IdleTimeout", "Tablet server idle timeout", cp.IdleTimeout) + stats.NewCounterDurationFunc(name+"WaitTime", "Tablet server wait time", cp.WaitTime) + stats.NewGaugeDurationFunc(name+"IdleTimeout", "Tablet server idle timeout", cp.IdleTimeout) stats.NewCounterFunc(name+"IdleClosed", "Tablet server conn pool idle closed", cp.IdleClosed) return cp } diff --git a/go/vt/vttablet/tabletserver/schema/engine.go b/go/vt/vttablet/tabletserver/schema/engine.go index a2491576b06..ead5d0098bb 100644 --- a/go/vt/vttablet/tabletserver/schema/engine.go +++ b/go/vt/vttablet/tabletserver/schema/engine.go @@ -77,7 +77,7 @@ func NewEngine(checker connpool.MySQLChecker, config tabletenv.TabletConfig) *En reloadTime: reloadTime, } schemaOnce.Do(func() { - _ = stats.NewDurationFunc("SchemaReloadTime", "vttablet keeps table schemas in its own memory and periodically refreshes it from MySQL. This config controls the reload time.", se.ticks.Interval) + _ = stats.NewGaugeDurationFunc("SchemaReloadTime", "vttablet keeps table schemas in its own memory and periodically refreshes it from MySQL. This config controls the reload time.", se.ticks.Interval) _ = stats.NewGaugesFuncWithMultiLabels("TableRows", []string{"Table"}, "table rows created in tabletserver", se.getTableRows) _ = stats.NewGaugesFuncWithMultiLabels("DataLength", []string{"Table"}, "data length in tabletserver", se.getDataLength) _ = stats.NewGaugesFuncWithMultiLabels("IndexLength", []string{"Table"}, "index length in tabletserver", se.getIndexLength) diff --git a/go/vt/vttablet/tabletserver/tabletserver.go b/go/vt/vttablet/tabletserver/tabletserver.go index 71e3dcf7ad2..e91c003c1be 100644 --- a/go/vt/vttablet/tabletserver/tabletserver.go +++ b/go/vt/vttablet/tabletserver/tabletserver.go @@ -244,9 +244,9 @@ func NewTabletServer(config tabletenv.TabletConfig, topoServer *topo.Server, ali tsv.mu.Unlock() return state }) - stats.NewDurationFunc("QueryTimeout", "Tablet server query timeout", tsv.QueryTimeout.Get) - stats.NewDurationFunc("QueryPoolTimeout", "Tablet server timeout to get a connection from the query pool", tsv.qe.connTimeout.Get) - stats.NewDurationFunc("BeginTimeout", "Tablet server begin timeout", tsv.BeginTimeout.Get) + stats.NewGaugeDurationFunc("QueryTimeout", "Tablet server query timeout", tsv.QueryTimeout.Get) + stats.NewGaugeDurationFunc("QueryPoolTimeout", "Tablet server timeout to get a connection from the query pool", tsv.qe.connTimeout.Get) + stats.NewGaugeDurationFunc("BeginTimeout", "Tablet server begin timeout", tsv.BeginTimeout.Get) stats.Publish("TabletStateName", stats.StringFunc(tsv.GetState)) }) return tsv diff --git a/go/vt/vttablet/tabletserver/tx_pool.go b/go/vt/vttablet/tabletserver/tx_pool.go index e4a3058cb15..55bb730ea83 100644 --- a/go/vt/vttablet/tabletserver/tx_pool.go +++ b/go/vt/vttablet/tabletserver/tx_pool.go @@ -119,7 +119,7 @@ func NewTxPool( txOnce.Do(func() { // Careful: conns also exports name+"xxx" vars, // but we know it doesn't export Timeout. - stats.NewDurationFunc(prefix+"TransactionPoolTimeout", "Transaction pool timeout", axp.timeout.Get) + stats.NewGaugeDurationFunc(prefix+"TransactionPoolTimeout", "Transaction pool timeout", axp.timeout.Get) stats.NewGaugeFunc(prefix+"TransactionPoolWaiters", "Transaction pool waiters", axp.waiters.Get) }) return axp From 3b11bceedc3ff240e0608a36731cba0eeadbd25c Mon Sep 17 00:00:00 2001 From: Michael Berlin Date: Sat, 28 Apr 2018 10:57:22 -0700 Subject: [PATCH 21/41] stats: Reorder code in counters.go. It should read as follows now: - counters - single label - counters - single label (function) - counters - multiple labels - counters - multiple labels (function) and then the same thing for gauges as well. This commit did not change any functionality. Signed-off-by: Michael Berlin --- go/stats/counters.go | 208 +++++++++++++++++++++++-------------------- 1 file changed, 109 insertions(+), 99 deletions(-) diff --git a/go/stats/counters.go b/go/stats/counters.go index 57ce7200c2e..de660033e3a 100644 --- a/go/stats/counters.go +++ b/go/stats/counters.go @@ -24,17 +24,22 @@ import ( "sync/atomic" ) -// counters is similar to expvar.Map, except that -// it doesn't allow floats. It is used to build CountersWithLabels and GaugesWithLabels. +// counters is similar to expvar.Map, except that it doesn't allow floats. +// It is used to build CountersWithLabels and GaugesWithLabels. type counters struct { - // mu only protects adding and retrieving the value (*int64) from the map, - // modification to the actual number (int64) should be done with atomic funcs. + // mu only protects adding and retrieving the value (*int64) from the + // map. + // The modification to the actual number (int64) must be done with + // atomic funcs. + // If a value for a given name already exists in the map, we only have + // to use a read-lock to retrieve it. This is an important performance + // optimizations because it allows to concurrently increment a counter. mu sync.RWMutex counts map[string]*int64 help string } -// String implements expvar +// String implements the expvar.Var interface. func (c *counters) String() string { b := bytes.NewBuffer(make([]byte, 0, 4096)) @@ -90,7 +95,7 @@ func (c *counters) ResetAll() { c.counts = make(map[string]*int64) } -// Reset resets a specific counter value to 0 +// Reset resets a specific counter value to 0. func (c *counters) Reset(name string) { a := c.getValueAddr(name) atomic.StoreInt64(a, int64(0)) @@ -120,9 +125,10 @@ type CountersWithLabels struct { labelName string } -// NewCountersWithLabels create a new Counters instance. If name is set, the variable -// gets published. The function also accepts an optional list of tags that -// pre-creates them initialized to 0. +// NewCountersWithLabels create a new Counters instance. +// If name is set, the variable gets published. +// The function also accepts an optional list of tags that pre-creates them +// initialized to 0. // labelName is a category name used to organize the tags in Prometheus. func NewCountersWithLabels(name string, help string, labelName string, tags ...string) *CountersWithLabels { c := &CountersWithLabels{ @@ -156,39 +162,6 @@ func (c *CountersWithLabels) Add(name string, value int64) { atomic.AddInt64(a, value) } -// GaugesWithLabels is similar to CountersWithLabels, except its values can go up and down. -type GaugesWithLabels struct { - CountersWithLabels -} - -// NewGaugesWithLabels creates a new GaugesWithLabels and publishes it if the name is set. -func NewGaugesWithLabels(name string, help string, labelName string, tags ...string) *GaugesWithLabels { - g := &GaugesWithLabels{CountersWithLabels: CountersWithLabels{counters: counters{ - counts: make(map[string]*int64), - help: help, - }, labelName: labelName}} - - for _, tag := range tags { - g.CountersWithLabels.counts[tag] = new(int64) - } - if name != "" { - publish(name, g) - } - return g -} - -// Set sets the value of a named gauge. -func (g *GaugesWithLabels) Set(name string, value int64) { - a := g.CountersWithLabels.getValueAddr(name) - atomic.StoreInt64(a, value) -} - -// Add adds a value to a named gauge. -func (g *GaugesWithLabels) Add(name string, value int64) { - a := g.getValueAddr(name) - atomic.AddInt64(a, value) -} - // CountersFunc converts a function that returns // a map of int64 as an expvar. type CountersFunc func() map[string]int64 @@ -198,7 +171,7 @@ func (f CountersFunc) Counts() map[string]int64 { return f() } -// String is used by expvar. +// String implements the expvar.Var interface. func (f CountersFunc) String() string { m := f() if m == nil { @@ -219,16 +192,16 @@ func (f CountersFunc) String() string { return b.String() } -// CountersWithMultiLabels is a multidimensional Counters implementation where -// names of categories are compound names made with joining multiple +// CountersWithMultiLabels is a multidimensional counters implementation +// where names of categories are compound names made with joining multiple // strings with '.'. type CountersWithMultiLabels struct { counters labels []string } -// NewCountersWithMultiLabels creates a new CountersWithMultiLabels instance, and publishes it -// if name is set. +// NewCountersWithMultiLabels creates a new CountersWithMultiLabels +// instance, and publishes it if name is set. func NewCountersWithMultiLabels(name string, help string, labels []string) *CountersWithMultiLabels { t := &CountersWithMultiLabels{ counters: counters{ @@ -248,8 +221,8 @@ func (mc *CountersWithMultiLabels) Labels() []string { return mc.labels } -// Add adds a value to a named counter. len(names) must be equal to -// len(Labels) +// Add adds a value to a named counter. +// len(names) must be equal to len(Labels) func (mc *CountersWithMultiLabels) Add(names []string, value int64) { if len(names) != len(mc.labels) { panic("CountersWithMultiLabels: wrong number of values in Add") @@ -261,8 +234,8 @@ func (mc *CountersWithMultiLabels) Add(names []string, value int64) { mc.counters.Add(mapKey(names), value) } -// Reset resets the value of a named counter back to 0. len(names) -// must be equal to len(Labels) +// Reset resets the value of a named counter back to 0. +// len(names) must be equal to len(Labels). func (mc *CountersWithMultiLabels) Reset(names []string) { if len(names) != len(mc.labels) { panic("CountersWithMultiLabels: wrong number of values in Reset") @@ -272,54 +245,12 @@ func (mc *CountersWithMultiLabels) Reset(names []string) { } // Counts returns a copy of the Counters' map. -// The key is a single string where all labels are joiend by a "." e.g. +// The key is a single string where all labels are joined by a "." e.g. // "label1.label2". func (mc *CountersWithMultiLabels) Counts() map[string]int64 { return mc.counters.Counts() } -// GaugesWithMultiLabels is a CountersWithMultiLabels implementation where the values can go up and down -type GaugesWithMultiLabels struct { - CountersWithMultiLabels -} - -// NewGaugesWithMultiLabels creates a new GaugesWithMultiLabels instance, and publishes it -// if name is set. -func NewGaugesWithMultiLabels(name string, help string, labels []string) *GaugesWithMultiLabels { - t := &GaugesWithMultiLabels{ - CountersWithMultiLabels: CountersWithMultiLabels{counters: counters{ - counts: make(map[string]*int64), - help: help, - }, - labels: labels, - }} - if name != "" { - publish(name, t) - } - - return t -} - -// Set sets the value of a named counter. len(names) must be equal to -// len(Labels) -func (mg *GaugesWithMultiLabels) Set(names []string, value int64) { - if len(names) != len(mg.CountersWithMultiLabels.labels) { - panic("GaugesWithMultiLabels: wrong number of values in Set") - } - a := mg.getValueAddr(mapKey(names)) - atomic.StoreInt64(a, value) -} - -// Add adds a value to a named gauge. len(names) must be equal to -// len(Labels) -func (mg *GaugesWithMultiLabels) Add(names []string, value int64) { - if len(names) != len(mg.labels) { - panic("CountersWithMultiLabels: wrong number of values in Add") - } - - mg.counters.Add(mapKey(names), value) -} - // CountersFuncWithMultiLabels is a multidimensional CountersFunc implementation // where names of categories are compound names made with joining // multiple strings with '.'. Since the map is returned by the @@ -342,8 +273,8 @@ func (mcf *CountersFuncWithMultiLabels) Help() string { return mcf.help } -// NewCountersFuncWithMultiLabels creates a new CountersFuncWithMultiLabels mapping to the provided -// function. +// NewCountersFuncWithMultiLabels creates a new CountersFuncWithMultiLabels +// mapping to the provided function. func NewCountersFuncWithMultiLabels(name string, labels []string, help string, f CountersFunc) *CountersFuncWithMultiLabels { t := &CountersFuncWithMultiLabels{ CountersFunc: f, @@ -357,14 +288,93 @@ func NewCountersFuncWithMultiLabels(name string, labels []string, help string, f return t } +// GaugesWithLabels is similar to CountersWithLabels, except its values can +// go up and down. +type GaugesWithLabels struct { + CountersWithLabels +} + +// NewGaugesWithLabels creates a new GaugesWithLabels and publishes it if +// the name is set. +func NewGaugesWithLabels(name string, help string, labelName string, tags ...string) *GaugesWithLabels { + g := &GaugesWithLabels{CountersWithLabels: CountersWithLabels{counters: counters{ + counts: make(map[string]*int64), + help: help, + }, labelName: labelName}} + + for _, tag := range tags { + g.CountersWithLabels.counts[tag] = new(int64) + } + if name != "" { + publish(name, g) + } + return g +} + +// Set sets the value of a named gauge. +func (g *GaugesWithLabels) Set(name string, value int64) { + a := g.CountersWithLabels.getValueAddr(name) + atomic.StoreInt64(a, value) +} + +// Add adds a value to a named gauge. +func (g *GaugesWithLabels) Add(name string, value int64) { + a := g.getValueAddr(name) + atomic.AddInt64(a, value) +} + +// GaugesWithMultiLabels is a CountersWithMultiLabels implementation where +// the values can go up and down. +type GaugesWithMultiLabels struct { + CountersWithMultiLabels +} + +// NewGaugesWithMultiLabels creates a new GaugesWithMultiLabels instance, +// and publishes it if name is set. +func NewGaugesWithMultiLabels(name string, help string, labels []string) *GaugesWithMultiLabels { + t := &GaugesWithMultiLabels{ + CountersWithMultiLabels: CountersWithMultiLabels{counters: counters{ + counts: make(map[string]*int64), + help: help, + }, + labels: labels, + }} + if name != "" { + publish(name, t) + } + + return t +} + +// Set sets the value of a named counter. +// len(names) must be equal to len(Labels). +func (mg *GaugesWithMultiLabels) Set(names []string, value int64) { + if len(names) != len(mg.CountersWithMultiLabels.labels) { + panic("GaugesWithMultiLabels: wrong number of values in Set") + } + a := mg.getValueAddr(mapKey(names)) + atomic.StoreInt64(a, value) +} + +// Add adds a value to a named gauge. +// len(names) must be equal to len(Labels). +func (mg *GaugesWithMultiLabels) Add(names []string, value int64) { + if len(names) != len(mg.labels) { + panic("CountersWithMultiLabels: wrong number of values in Add") + } + + mg.counters.Add(mapKey(names), value) +} + // GaugesFuncWithMultiLabels is a wrapper around CountersFuncWithMultiLabels -// for values that go up/down for implementations (like Prometheus) that need to differ between Counters and Gauges. +// for values that go up/down for implementations (like Prometheus) that +// need to differ between Counters and Gauges. type GaugesFuncWithMultiLabels struct { CountersFuncWithMultiLabels } -// NewGaugesFuncWithMultiLabels creates a new GaugesFuncWithMultiLabels mapping to the provided -// function. +// NewGaugesFuncWithMultiLabels creates a new GaugesFuncWithMultiLabels +// mapping to the provided function. func NewGaugesFuncWithMultiLabels(name string, labels []string, help string, f CountersFunc) *GaugesFuncWithMultiLabels { t := &GaugesFuncWithMultiLabels{ CountersFuncWithMultiLabels: CountersFuncWithMultiLabels{ From a20b453db0915f69f84d11f8d5c29da6731425d9 Mon Sep 17 00:00:00 2001 From: Michael Berlin Date: Sat, 28 Apr 2018 11:59:40 -0700 Subject: [PATCH 22/41] stats: Rename (Counters|Gauges)WithLabels to *WithSingleLabel. The new name is more consistent with the *WithMultiLabels counterparts. Signed-off-by: Michael Berlin --- go/stats/counters.go | 55 ++++++++++--------- go/stats/counters_test.go | 14 ++--- go/stats/prometheusbackend/collectors.go | 20 +++---- .../prometheusbackend/prometheusbackend.go | 16 +++--- .../prometheusbackend_test.go | 38 ++++++------- go/stats/rates_test.go | 6 +- go/streamlog/streamlog.go | 2 +- go/vt/binlog/binlog_streamer.go | 2 +- go/vt/binlog/updatestreamctl.go | 4 +- go/vt/srvtopo/resilient_server.go | 4 +- go/vt/vtgate/vtgate.go | 8 +-- .../tabletserver/tabletenv/tabletenv.go | 10 ++-- .../tabletserver/txlimiter/tx_limiter.go | 4 +- .../txserializer/tx_serializer.go | 8 +-- go/vt/worker/row_aggregator.go | 6 +- go/vt/worker/row_differ.go | 4 +- go/vt/worker/split_clone.go | 6 +- go/vt/worker/worker.go | 26 ++++----- 18 files changed, 118 insertions(+), 115 deletions(-) diff --git a/go/stats/counters.go b/go/stats/counters.go index de660033e3a..2bcdbdeeab2 100644 --- a/go/stats/counters.go +++ b/go/stats/counters.go @@ -25,7 +25,7 @@ import ( ) // counters is similar to expvar.Map, except that it doesn't allow floats. -// It is used to build CountersWithLabels and GaugesWithLabels. +// It is used to build CountersWithSingleLabel and GaugesWithSingleLabel. type counters struct { // mu only protects adding and retrieving the value (*int64) from the // map. @@ -118,20 +118,20 @@ func (c *counters) Help() string { return c.help } -// CountersWithLabels provides a labelName for the tagged values in Counters +// CountersWithSingleLabel provides a labelName for the tagged values in Counters // It provides a Counts method which can be used for tracking rates. -type CountersWithLabels struct { +type CountersWithSingleLabel struct { counters labelName string } -// NewCountersWithLabels create a new Counters instance. +// NewCountersWithSingleLabel create a new Counters instance. // If name is set, the variable gets published. // The function also accepts an optional list of tags that pre-creates them // initialized to 0. // labelName is a category name used to organize the tags in Prometheus. -func NewCountersWithLabels(name string, help string, labelName string, tags ...string) *CountersWithLabels { - c := &CountersWithLabels{ +func NewCountersWithSingleLabel(name string, help string, labelName string, tags ...string) *CountersWithSingleLabel { + c := &CountersWithSingleLabel{ counters: counters{ counts: make(map[string]*int64), help: help, @@ -149,12 +149,12 @@ func NewCountersWithLabels(name string, help string, labelName string, tags ...s } // LabelName returns the label name. -func (c *CountersWithLabels) LabelName() string { +func (c *CountersWithSingleLabel) LabelName() string { return c.labelName } // Add adds a value to a named counter. -func (c *CountersWithLabels) Add(name string, value int64) { +func (c *CountersWithSingleLabel) Add(name string, value int64) { if value < 0 { logCounterNegative.Warningf("Adding a negative value to a counter, %v should be a gauge instead", c) } @@ -288,22 +288,26 @@ func NewCountersFuncWithMultiLabels(name string, labels []string, help string, f return t } -// GaugesWithLabels is similar to CountersWithLabels, except its values can +// GaugesWithSingleLabel is similar to CountersWithSingleLabel, except its values can // go up and down. -type GaugesWithLabels struct { - CountersWithLabels +type GaugesWithSingleLabel struct { + CountersWithSingleLabel } -// NewGaugesWithLabels creates a new GaugesWithLabels and publishes it if +// NewGaugesWithSingleLabel creates a new GaugesWithSingleLabel and publishes it if // the name is set. -func NewGaugesWithLabels(name string, help string, labelName string, tags ...string) *GaugesWithLabels { - g := &GaugesWithLabels{CountersWithLabels: CountersWithLabels{counters: counters{ - counts: make(map[string]*int64), - help: help, - }, labelName: labelName}} +func NewGaugesWithSingleLabel(name string, help string, labelName string, tags ...string) *GaugesWithSingleLabel { + g := &GaugesWithSingleLabel{ + CountersWithSingleLabel: CountersWithSingleLabel{ + counters: counters{ + counts: make(map[string]*int64), + help: help, + }, + labelName: labelName}, + } for _, tag := range tags { - g.CountersWithLabels.counts[tag] = new(int64) + g.counts[tag] = new(int64) } if name != "" { publish(name, g) @@ -312,13 +316,13 @@ func NewGaugesWithLabels(name string, help string, labelName string, tags ...str } // Set sets the value of a named gauge. -func (g *GaugesWithLabels) Set(name string, value int64) { - a := g.CountersWithLabels.getValueAddr(name) +func (g *GaugesWithSingleLabel) Set(name string, value int64) { + a := g.getValueAddr(name) atomic.StoreInt64(a, value) } // Add adds a value to a named gauge. -func (g *GaugesWithLabels) Add(name string, value int64) { +func (g *GaugesWithSingleLabel) Add(name string, value int64) { a := g.getValueAddr(name) atomic.AddInt64(a, value) } @@ -333,10 +337,11 @@ type GaugesWithMultiLabels struct { // and publishes it if name is set. func NewGaugesWithMultiLabels(name string, help string, labels []string) *GaugesWithMultiLabels { t := &GaugesWithMultiLabels{ - CountersWithMultiLabels: CountersWithMultiLabels{counters: counters{ - counts: make(map[string]*int64), - help: help, - }, + CountersWithMultiLabels: CountersWithMultiLabels{ + counters: counters{ + counts: make(map[string]*int64), + help: help, + }, labels: labels, }} if name != "" { diff --git a/go/stats/counters_test.go b/go/stats/counters_test.go index 43cf800f6da..bffca623652 100644 --- a/go/stats/counters_test.go +++ b/go/stats/counters_test.go @@ -27,7 +27,7 @@ import ( func TestCounters(t *testing.T) { clear() - c := NewCountersWithLabels("counter1", "help", "type") + c := NewCountersWithSingleLabel("counter1", "help", "label") c.Add("c1", 1) c.Add("c2", 1) c.Add("c2", 1) @@ -56,14 +56,14 @@ func TestCounters(t *testing.T) { func TestCountersTags(t *testing.T) { clear() - c := NewCountersWithLabels("counterTag1", "help", "label") + c := NewCountersWithSingleLabel("counterTag1", "help", "label") want := map[string]int64{} got := c.Counts() if !reflect.DeepEqual(got, want) { t.Errorf("want %v, got %v", want, got) } - c = NewCountersWithLabels("counterTag2", "help", "label", "tag1", "tag2") + c = NewCountersWithSingleLabel("counterTag2", "help", "label", "tag1", "tag2") want = map[string]int64{"tag1": 0, "tag2": 0} got = c.Counts() if !reflect.DeepEqual(got, want) { @@ -122,14 +122,14 @@ func TestMultiCountersDot(t *testing.T) { func TestCountersHook(t *testing.T) { var gotname string - var gotv *CountersWithLabels + var gotv *CountersWithSingleLabel clear() Register(func(name string, v expvar.Var) { gotname = name - gotv = v.(*CountersWithLabels) + gotv = v.(*CountersWithSingleLabel) }) - v := NewCountersWithLabels("counter2", "help", "type") + v := NewCountersWithSingleLabel("counter2", "help", "label") if gotname != "counter2" { t.Errorf("want counter2, got %s", gotname) } @@ -138,7 +138,7 @@ func TestCountersHook(t *testing.T) { } } -var benchCounter = NewCountersWithLabels("bench", "help", "type") +var benchCounter = NewCountersWithSingleLabel("bench", "help", "label") func BenchmarkCounters(b *testing.B) { clear() diff --git a/go/stats/prometheusbackend/collectors.go b/go/stats/prometheusbackend/collectors.go index bacaa57f369..9cc2254bcf3 100644 --- a/go/stats/prometheusbackend/collectors.go +++ b/go/stats/prometheusbackend/collectors.go @@ -24,20 +24,20 @@ func (mc *metricFuncCollector) Collect(ch chan<- prometheus.Metric) { ch <- prometheus.MustNewConstMetric(mc.desc, mc.vt, float64(mc.f())) } -// countersWithLabelsCollector collects stats.CountersWithLabels -type countersWithLabelsCollector struct { - counters *stats.CountersWithLabels +// countersWithSingleLabelCollector collects stats.CountersWithSingleLabel. +type countersWithSingleLabelCollector struct { + counters *stats.CountersWithSingleLabel desc *prometheus.Desc vt prometheus.ValueType } // Describe implements Collector. -func (c *countersWithLabelsCollector) Describe(ch chan<- *prometheus.Desc) { +func (c *countersWithSingleLabelCollector) Describe(ch chan<- *prometheus.Desc) { ch <- c.desc } // Collect implements Collector. -func (c *countersWithLabelsCollector) Collect(ch chan<- prometheus.Metric) { +func (c *countersWithSingleLabelCollector) Collect(ch chan<- prometheus.Metric) { for tag, val := range c.counters.Counts() { ch <- prometheus.MustNewConstMetric( c.desc, @@ -47,20 +47,20 @@ func (c *countersWithLabelsCollector) Collect(ch chan<- prometheus.Metric) { } } -// gaugesWithLabelsCollector collects stats.GaugesWithLabels -type gaugesWithLabelsCollector struct { - gauges *stats.GaugesWithLabels +// gaugesWithSingleLabelCollector collects stats.GaugesWithSingleLabel. +type gaugesWithSingleLabelCollector struct { + gauges *stats.GaugesWithSingleLabel desc *prometheus.Desc vt prometheus.ValueType } // Describe implements Collector. -func (g *gaugesWithLabelsCollector) Describe(ch chan<- *prometheus.Desc) { +func (g *gaugesWithSingleLabelCollector) Describe(ch chan<- *prometheus.Desc) { ch <- g.desc } // Collect implements Collector. -func (g *gaugesWithLabelsCollector) Collect(ch chan<- prometheus.Metric) { +func (g *gaugesWithSingleLabelCollector) Collect(ch chan<- prometheus.Metric) { for tag, val := range g.gauges.Counts() { ch <- prometheus.MustNewConstMetric( g.desc, diff --git a/go/stats/prometheusbackend/prometheusbackend.go b/go/stats/prometheusbackend/prometheusbackend.go index 79f39b7d5a6..4620aebb087 100644 --- a/go/stats/prometheusbackend/prometheusbackend.go +++ b/go/stats/prometheusbackend/prometheusbackend.go @@ -41,16 +41,16 @@ func (be *PromBackend) publishPrometheusMetric(name string, v expvar.Var) { be.newMetric(st, name, prometheus.GaugeValue, func() float64 { return float64(st.Get()) }) case *stats.GaugeFunc: be.newMetric(st, name, prometheus.GaugeValue, func() float64 { return float64(st.F()) }) - case *stats.CountersWithLabels: - be.newCountersWithLabels(st, name, st.LabelName(), prometheus.CounterValue) + case *stats.CountersWithSingleLabel: + be.newCountersWithSingleLabel(st, name, st.LabelName(), prometheus.CounterValue) case *stats.CountersWithMultiLabels: be.newCountersWithMultiLabels(st, name) case *stats.CountersFuncWithMultiLabels: be.newMetricsFuncWithMultiLabels(st, name, prometheus.CounterValue) case *stats.GaugesFuncWithMultiLabels: be.newMetricsFuncWithMultiLabels(&st.CountersFuncWithMultiLabels, name, prometheus.GaugeValue) - case *stats.GaugesWithLabels: - be.newGaugesWithLabels(st, name, st.LabelName(), prometheus.GaugeValue) + case *stats.GaugesWithSingleLabel: + be.newGaugesWithSingleLabel(st, name, st.LabelName(), prometheus.GaugeValue) case *stats.GaugesWithMultiLabels: be.newGaugesWithMultiLabels(st, name) case *stats.CounterDuration: @@ -70,8 +70,8 @@ func (be *PromBackend) publishPrometheusMetric(name string, v expvar.Var) { } } -func (be *PromBackend) newCountersWithLabels(c *stats.CountersWithLabels, name string, labelName string, vt prometheus.ValueType) { - collector := &countersWithLabelsCollector{ +func (be *PromBackend) newCountersWithSingleLabel(c *stats.CountersWithSingleLabel, name string, labelName string, vt prometheus.ValueType) { + collector := &countersWithSingleLabelCollector{ counters: c, desc: prometheus.NewDesc( be.buildPromName(name), @@ -83,8 +83,8 @@ func (be *PromBackend) newCountersWithLabels(c *stats.CountersWithLabels, name s prometheus.MustRegister(collector) } -func (be *PromBackend) newGaugesWithLabels(g *stats.GaugesWithLabels, name string, labelName string, vt prometheus.ValueType) { - collector := &gaugesWithLabelsCollector{ +func (be *PromBackend) newGaugesWithSingleLabel(g *stats.GaugesWithSingleLabel, name string, labelName string, vt prometheus.ValueType) { + collector := &gaugesWithSingleLabelCollector{ gauges: g, desc: prometheus.NewDesc( be.buildPromName(name), diff --git a/go/stats/prometheusbackend/prometheusbackend_test.go b/go/stats/prometheusbackend/prometheusbackend_test.go index 021b8c4762a..efe6ce8f7b9 100644 --- a/go/stats/prometheusbackend/prometheusbackend_test.go +++ b/go/stats/prometheusbackend/prometheusbackend_test.go @@ -103,41 +103,41 @@ func checkHandlerForMetrics(t *testing.T, metric string, value int) { } } -func TestPrometheusCountersWithLabels(t *testing.T) { - name := "blah_counterswithlabels" - c := stats.NewCountersWithLabels(name, "help", "tag", "tag1", "tag2") +func TestPrometheusCountersWithSingleLabel(t *testing.T) { + name := "blah_counterswithsinglelabel" + c := stats.NewCountersWithSingleLabel(name, "help", "label", "tag1", "tag2") c.Add("tag1", 1) - checkHandlerForMetricWithLabels(t, name, "tag", "tag1", 1) - checkHandlerForMetricWithLabels(t, name, "tag", "tag2", 0) + checkHandlerForMetricWithSingleLabel(t, name, "label", "tag1", 1) + checkHandlerForMetricWithSingleLabel(t, name, "label", "tag2", 0) c.Add("tag2", 41) - checkHandlerForMetricWithLabels(t, name, "tag", "tag1", 1) - checkHandlerForMetricWithLabels(t, name, "tag", "tag2", 41) + checkHandlerForMetricWithSingleLabel(t, name, "label", "tag1", 1) + checkHandlerForMetricWithSingleLabel(t, name, "label", "tag2", 41) c.Reset("tag2") - checkHandlerForMetricWithLabels(t, name, "tag", "tag1", 1) - checkHandlerForMetricWithLabels(t, name, "tag", "tag2", 0) + checkHandlerForMetricWithSingleLabel(t, name, "label", "tag1", 1) + checkHandlerForMetricWithSingleLabel(t, name, "label", "tag2", 0) } -func TestPrometheusGaugesWithLabels(t *testing.T) { - name := "blah_gaugeswithlabels" - c := stats.NewGaugesWithLabels(name, "help", "tag", "tag1", "tag2") +func TestPrometheusGaugesWithSingleLabel(t *testing.T) { + name := "blah_gaugeswithsinglelabel" + c := stats.NewGaugesWithSingleLabel(name, "help", "label", "tag1", "tag2") c.Add("tag1", 1) - checkHandlerForMetricWithLabels(t, name, "tag", "tag1", 1) + checkHandlerForMetricWithSingleLabel(t, name, "label", "tag1", 1) c.Add("tag2", 1) - checkHandlerForMetricWithLabels(t, name, "tag", "tag2", 1) + checkHandlerForMetricWithSingleLabel(t, name, "label", "tag2", 1) c.Set("tag1", -1) - checkHandlerForMetricWithLabels(t, name, "tag", "tag1", -1) + checkHandlerForMetricWithSingleLabel(t, name, "label", "tag1", -1) c.Reset("tag2") - checkHandlerForMetricWithLabels(t, name, "tag", "tag1", -1) - checkHandlerForMetricWithLabels(t, name, "tag", "tag2", 0) + checkHandlerForMetricWithSingleLabel(t, name, "label", "tag1", -1) + checkHandlerForMetricWithSingleLabel(t, name, "label", "tag2", 0) } -func checkHandlerForMetricWithLabels(t *testing.T, metric string, tagName string, tagValue string, value int) { +func checkHandlerForMetricWithSingleLabel(t *testing.T, metric, label, tag string, value int) { response := testMetricsHandler(t) - expected := fmt.Sprintf("%s_%s{%s=\"%s\"} %d", namespace, metric, tagName, tagValue, value) + expected := fmt.Sprintf("%s_%s{%s=\"%s\"} %d", namespace, metric, label, tag, value) if !strings.Contains(response.Body.String(), expected) { t.Fatalf("Expected %s got %s", expected, response.Body.String()) diff --git a/go/stats/rates_test.go b/go/stats/rates_test.go index 7e8cc901a65..ba150bb65fa 100644 --- a/go/stats/rates_test.go +++ b/go/stats/rates_test.go @@ -42,7 +42,7 @@ func TestRates(t *testing.T) { } clear() - c := NewCountersWithLabels("rcounter1", "rcounter help", "type") + c := NewCountersWithSingleLabel("rcounter1", "rcounter help", "label") r := NewRates("rates1", c, 3, -1*time.Second) r.snapshot() now = now.Add(epsilon) @@ -90,7 +90,7 @@ func TestRatesConsistency(t *testing.T) { // covered by rates, the sum of the rates reported must be // equal to the count reported by the counter. clear() - c := NewCountersWithLabels("rcounter4", "rcounter4 help", "type") + c := NewCountersWithSingleLabel("rcounter4", "rcounter4 help", "label") r := NewRates("rates4", c, 100, -1*time.Second) r.snapshot() @@ -123,7 +123,7 @@ func TestRatesConsistency(t *testing.T) { func TestRatesHook(t *testing.T) { clear() - c := NewCountersWithLabels("rcounter2", "rcounter2 help", "type") + c := NewCountersWithSingleLabel("rcounter2", "rcounter2 help", "label") var gotname string var gotv *Rates clear() diff --git a/go/streamlog/streamlog.go b/go/streamlog/streamlog.go index 1db23fa8362..f3fe16c8990 100644 --- a/go/streamlog/streamlog.go +++ b/go/streamlog/streamlog.go @@ -40,7 +40,7 @@ var ( // QueryLogFormat controls the format of the query log (either text or json) QueryLogFormat = flag.String("querylog-format", "text", "format for query logs (\"text\" or \"json\")") - sendCount = stats.NewCountersWithLabels("StreamlogSend", "stream log send count", "logger_names") + sendCount = stats.NewCountersWithSingleLabel("StreamlogSend", "stream log send count", "logger_names") deliveredCount = stats.NewCountersWithMultiLabels( "StreamlogDelivered", "Stream log delivered", diff --git a/go/vt/binlog/binlog_streamer.go b/go/vt/binlog/binlog_streamer.go index 2dcd9999043..ab56eb4d323 100644 --- a/go/vt/binlog/binlog_streamer.go +++ b/go/vt/binlog/binlog_streamer.go @@ -37,7 +37,7 @@ import ( ) var ( - binlogStreamerErrors = stats.NewCountersWithLabels("BinlogStreamerErrors", "error count when streaming binlog", "state") + binlogStreamerErrors = stats.NewCountersWithSingleLabel("BinlogStreamerErrors", "error count when streaming binlog", "state") // ErrClientEOF is returned by Streamer if the stream ended because the // consumer of the stream indicated it doesn't want any more events. diff --git a/go/vt/binlog/updatestreamctl.go b/go/vt/binlog/updatestreamctl.go index 0c5f4bb05f9..3525c28a2b8 100644 --- a/go/vt/binlog/updatestreamctl.go +++ b/go/vt/binlog/updatestreamctl.go @@ -47,8 +47,8 @@ var usStateNames = map[int64]string{ } var ( - streamCount = stats.NewCountersWithLabels("UpdateStreamStreamCount", "update stream count", "type") - updateStreamErrors = stats.NewCountersWithLabels("UpdateStreamErrors", "update stream error count", "type") + streamCount = stats.NewCountersWithSingleLabel("UpdateStreamStreamCount", "update stream count", "type") + updateStreamErrors = stats.NewCountersWithSingleLabel("UpdateStreamErrors", "update stream error count", "type") keyrangeStatements = stats.NewCounter("UpdateStreamKeyRangeStatements", "update stream key range statement count") keyrangeTransactions = stats.NewCounter("UpdateStreamKeyRangeTransactions", "update stream key range transaction count") tablesStatements = stats.NewCounter("UpdateStreamTablesStatements", "update stream table statement count") diff --git a/go/vt/srvtopo/resilient_server.go b/go/vt/srvtopo/resilient_server.go index 44f23f7e720..cbee330b069 100644 --- a/go/vt/srvtopo/resilient_server.go +++ b/go/vt/srvtopo/resilient_server.go @@ -120,7 +120,7 @@ type ResilientServer struct { topoServer *topo.Server cacheTTL time.Duration cacheRefresh time.Duration - counts *stats.CountersWithLabels + counts *stats.CountersWithSingleLabel // mutex protects the cache map itself, not the individual // values in the cache. @@ -215,7 +215,7 @@ func NewResilientServer(base *topo.Server, counterPrefix string) *ResilientServe topoServer: base, cacheTTL: *srvTopoCacheTTL, cacheRefresh: *srvTopoCacheRefresh, - counts: stats.NewCountersWithLabels(counterPrefix+"Counts", "Resilient srvtopo server operations", "type"), + counts: stats.NewCountersWithSingleLabel(counterPrefix+"Counts", "Resilient srvtopo server operations", "type"), srvKeyspaceNamesCache: make(map[string]*srvKeyspaceNamesEntry), srvKeyspaceCache: make(map[string]*srvKeyspaceEntry), diff --git a/go/vt/vtgate/vtgate.go b/go/vt/vtgate/vtgate.go index d8571f50126..52194ecd81a 100644 --- a/go/vt/vtgate/vtgate.go +++ b/go/vt/vtgate/vtgate.go @@ -89,7 +89,7 @@ var ( qpsByKeyspace *stats.Rates qpsByDbType *stats.Rates - vschemaCounters *stats.CountersWithLabels + vschemaCounters *stats.CountersWithSingleLabel errorsByOperation *stats.Rates errorsByKeyspace *stats.Rates @@ -99,7 +99,7 @@ var ( // Error counters should be global so they can be set from anywhere errorCounts *stats.CountersWithMultiLabels - warnings *stats.CountersWithLabels + warnings *stats.CountersWithSingleLabel ) // VTGate is the rpc interface to vtgate. Only one instance @@ -156,7 +156,7 @@ func Init(ctx context.Context, hc discovery.HealthCheck, serv srvtopo.Server, ce // vschemaCounters needs to be initialized before planner to // catch the initial load stats. - vschemaCounters = stats.NewCountersWithLabels("VtgateVSchemaCounts", "Vtgate vschema counts", "changes") + vschemaCounters = stats.NewCountersWithSingleLabel("VtgateVSchemaCounts", "Vtgate vschema counts", "changes") // Build objects from low to high level. // Start with the gateway. If we can't reach the topology service, @@ -239,7 +239,7 @@ func Init(ctx context.Context, hc discovery.HealthCheck, serv srvtopo.Server, ce errorsByDbType = stats.NewRates("ErrorsByDbType", stats.CounterForDimension(errorCounts, "DbType"), 15, 1*time.Minute) errorsByCode = stats.NewRates("ErrorsByCode", stats.CounterForDimension(errorCounts, "Code"), 15, 1*time.Minute) - warnings = stats.NewCountersWithLabels("VtGateWarnings", "Vtgate warnings", "type", "IgnoredSet") + warnings = stats.NewCountersWithSingleLabel("VtGateWarnings", "Vtgate warnings", "type", "IgnoredSet") servenv.OnRun(func() { for _, f := range RegisterVTGates { diff --git a/go/vt/vttablet/tabletserver/tabletenv/tabletenv.go b/go/vt/vttablet/tabletserver/tabletenv/tabletenv.go index 1af3bd76f38..e4803c564c8 100644 --- a/go/vt/vttablet/tabletserver/tabletenv/tabletenv.go +++ b/go/vt/vttablet/tabletserver/tabletenv/tabletenv.go @@ -42,9 +42,9 @@ var ( // WaitStats shows the time histogram for wait operations WaitStats = stats.NewTimings("Waits", "Wait operations") // KillStats shows number of connections being killed. - KillStats = stats.NewCountersWithLabels("Kills", "Number of connections being killed", "query_type", "Transactions", "Queries") + KillStats = stats.NewCountersWithSingleLabel("Kills", "Number of connections being killed", "query_type", "Transactions", "Queries") // ErrorStats shows number of critial errors happened. - ErrorStats = stats.NewCountersWithLabels( + ErrorStats = stats.NewCountersWithSingleLabel( "Errors", "Critical errors", "error_code", @@ -67,11 +67,11 @@ var ( vtrpcpb.Code_DATA_LOSS.String(), ) // InternalErrors shows number of errors from internal components. - InternalErrors = stats.NewCountersWithLabels("InternalErrors", "Internal component errors", "type", "Task", "StrayTransactions", "Panic", "HungQuery", "Schema", "TwopcCommit", "TwopcResurrection", "WatchdogFail", "Messages") + InternalErrors = stats.NewCountersWithSingleLabel("InternalErrors", "Internal component errors", "type", "Task", "StrayTransactions", "Panic", "HungQuery", "Schema", "TwopcCommit", "TwopcResurrection", "WatchdogFail", "Messages") // Warnings shows number of warnings - Warnings = stats.NewCountersWithLabels("Warnings", "Warnings", "type", "ResultsExceeded") + Warnings = stats.NewCountersWithSingleLabel("Warnings", "Warnings", "type", "ResultsExceeded") // Unresolved tracks unresolved items. For now it's just Prepares. - Unresolved = stats.NewGaugesWithLabels("Unresolved", "Unresolved items", "item_type", "Prepares") + Unresolved = stats.NewGaugesWithSingleLabel("Unresolved", "Unresolved items", "item_type", "Prepares") // UserTableQueryCount shows number of queries received for each CallerID/table combination. UserTableQueryCount = stats.NewCountersWithMultiLabels( "UserTableQueryCount", diff --git a/go/vt/vttablet/tabletserver/txlimiter/tx_limiter.go b/go/vt/vttablet/tabletserver/txlimiter/tx_limiter.go index 0a9ec503040..f68d01e7bce 100644 --- a/go/vt/vttablet/tabletserver/txlimiter/tx_limiter.go +++ b/go/vt/vttablet/tabletserver/txlimiter/tx_limiter.go @@ -31,8 +31,8 @@ import ( const unknown string = "unknown" var ( - rejections = stats.NewCountersWithLabels("TxLimiterRejections", "rejections from TxLimiter", "user") - rejectionsDryRun = stats.NewCountersWithLabels("TxLimiterRejectionsDryRun", "rejections from TxLimiter in dry run", "user") + rejections = stats.NewCountersWithSingleLabel("TxLimiterRejections", "rejections from TxLimiter", "user") + rejectionsDryRun = stats.NewCountersWithSingleLabel("TxLimiterRejectionsDryRun", "rejections from TxLimiter in dry run", "user") ) // TxLimiter is the transaction limiter interface. diff --git a/go/vt/vttablet/tabletserver/txserializer/tx_serializer.go b/go/vt/vttablet/tabletserver/txserializer/tx_serializer.go index 15bc1a63258..c4a1768adc3 100644 --- a/go/vt/vttablet/tabletserver/txserializer/tx_serializer.go +++ b/go/vt/vttablet/tabletserver/txserializer/tx_serializer.go @@ -40,27 +40,27 @@ var ( // waits stores how many times a transaction was queued because another // transaction was already in flight for the same row (range). // The key of the map is the table name of the query. - waits = stats.NewCountersWithLabels( + waits = stats.NewCountersWithSingleLabel( "TxSerializerWaits", "Number of times a transaction was queued because another transaction was already in flight for the same row range", "table_name") // waitsDryRun is similar as "waits": In dry-run mode it records how many // transactions would have been queued. // The key of the map is the table name of the query. - waitsDryRun = stats.NewCountersWithLabels( + waitsDryRun = stats.NewCountersWithSingleLabel( "TxSerializerWaitsDryRun", "Dry run number of transactions that would've been queued", "table_name") // queueExceeded counts per table how many transactions were rejected because // the max queue size per row (range) was exceeded. - queueExceeded = stats.NewCountersWithLabels( + queueExceeded = stats.NewCountersWithSingleLabel( "TxSerializerQueueExceeded", "Number of transactions that were rejected because the max queue size per row range was exceeded", "table_name") // queueExceededDryRun counts in dry-run mode how many transactions would have // been rejected due to exceeding the max queue size per row (range). - queueExceededDryRun = stats.NewCountersWithLabels( + queueExceededDryRun = stats.NewCountersWithSingleLabel( "TxSerializerQueueExceededDryRun", "Dry-run Number of transactions that were rejcted because the max queue size was exceeded", "table_name") diff --git a/go/vt/worker/row_aggregator.go b/go/vt/worker/row_aggregator.go index 97726208ddf..9ccd803e4bb 100644 --- a/go/vt/worker/row_aggregator.go +++ b/go/vt/worker/row_aggregator.go @@ -48,9 +48,7 @@ type RowAggregator struct { td *tabletmanagerdatapb.TableDefinition diffType DiffType builder QueryBuilder - // statsCounters has a "diffType" specific stats.CountersWithLabels object to track how - // many rows were changed per table. - statsCounters *stats.CountersWithLabels + statsCounters *stats.CountersWithSingleLabel buffer bytes.Buffer bufferedRows int @@ -60,7 +58,7 @@ type RowAggregator struct { // The index of the elements in statCounters must match the elements // in "DiffTypes" i.e. the first counter is for inserts, second for updates // and the third for deletes. -func NewRowAggregator(ctx context.Context, maxRows, maxSize int, insertChannel chan string, dbName string, td *tabletmanagerdatapb.TableDefinition, diffType DiffType, statsCounters *stats.CountersWithLabels) *RowAggregator { +func NewRowAggregator(ctx context.Context, maxRows, maxSize int, insertChannel chan string, dbName string, td *tabletmanagerdatapb.TableDefinition, diffType DiffType, statsCounters *stats.CountersWithSingleLabel) *RowAggregator { // Construct head and tail base commands for the reconciliation statement. var builder QueryBuilder switch diffType { diff --git a/go/vt/worker/row_differ.go b/go/vt/worker/row_differ.go index 6f1e50b196f..a6be54c2f4f 100644 --- a/go/vt/worker/row_differ.go +++ b/go/vt/worker/row_differ.go @@ -74,7 +74,7 @@ type RowDiffer2 struct { // aggregators are keyed by destination shard and DiffType. aggregators [][]*RowAggregator // equalRowsStatsCounters tracks per table how many rows are equal. - equalRowsStatsCounters *stats.CountersWithLabels + equalRowsStatsCounters *stats.CountersWithSingleLabel // tableName is required to update "equalRowsStatsCounters". tableName string } @@ -89,7 +89,7 @@ func NewRowDiffer2(ctx context.Context, left, right ResultReader, td *tabletmana // Parameters required by RowRouter. destinationShards []*topo.ShardInfo, keyResolver keyspaceIDResolver, // Parameters required by RowAggregator. - insertChannels []chan string, abort <-chan struct{}, dbNames []string, writeQueryMaxRows, writeQueryMaxSize int, statsCounters []*stats.CountersWithLabels) (*RowDiffer2, error) { + insertChannels []chan string, abort <-chan struct{}, dbNames []string, writeQueryMaxRows, writeQueryMaxSize int, statsCounters []*stats.CountersWithSingleLabel) (*RowDiffer2, error) { if len(statsCounters) != len(DiffTypes) { panic(fmt.Sprintf("statsCounter has the wrong number of elements. got = %v, want = %v", len(statsCounters), len(DiffTypes))) diff --git a/go/vt/worker/split_clone.go b/go/vt/worker/split_clone.go index 3dcc884c079..096298a4c92 100644 --- a/go/vt/worker/split_clone.go +++ b/go/vt/worker/split_clone.go @@ -826,14 +826,14 @@ func (scw *SplitCloneWorker) clone(ctx context.Context, state StatusWorkerState) } firstSourceTablet = tablets[0].Tablet } - var statsCounters []*stats.CountersWithLabels + var statsCounters []*stats.CountersWithSingleLabel var tableStatusList *tableStatusList switch state { case WorkerStateCloneOnline: - statsCounters = []*stats.CountersWithLabels{statsOnlineInsertsCounters, statsOnlineUpdatesCounters, statsOnlineDeletesCounters, statsOnlineEqualRowsCounters} + statsCounters = []*stats.CountersWithSingleLabel{statsOnlineInsertsCounters, statsOnlineUpdatesCounters, statsOnlineDeletesCounters, statsOnlineEqualRowsCounters} tableStatusList = scw.tableStatusListOnline case WorkerStateCloneOffline: - statsCounters = []*stats.CountersWithLabels{statsOfflineInsertsCounters, statsOfflineUpdatesCounters, statsOfflineDeletesCounters, statsOfflineEqualRowsCounters} + statsCounters = []*stats.CountersWithSingleLabel{statsOfflineInsertsCounters, statsOfflineUpdatesCounters, statsOfflineDeletesCounters, statsOfflineEqualRowsCounters} tableStatusList = scw.tableStatusListOffline } diff --git a/go/vt/worker/worker.go b/go/vt/worker/worker.go index bec1083785a..aed603e4e10 100644 --- a/go/vt/worker/worker.go +++ b/go/vt/worker/worker.go @@ -59,57 +59,57 @@ var ( statsState = stats.NewString("WorkerState") statsRetryCount = stats.NewCounter("WorkerRetryCount", "Total number of times a query to a vttablet had to be retried") - statsRetryCounters = stats.NewCountersWithLabels("WorkerRetryCounters", "Number of retries grouped by category e.g. TimeoutError or ReadOnly", "category") + statsRetryCounters = stats.NewCountersWithSingleLabel("WorkerRetryCounters", "Number of retries grouped by category e.g. TimeoutError or ReadOnly", "category") statsThrottledCounters = stats.NewCountersWithMultiLabels( "WorkerThrottledCounters", `Number of times a write has been throttled grouped by (keyspace, shard, threadID). Mainly used for testing. If throttling is enabled this should always be non-zero for all threads`, []string{"Keyspace", "ShardName", "ThreadId"}) - statsStateDurationsNs = stats.NewGaugesWithLabels("WorkerStateDurations", "How much time was spent in each state. Mainly used for testing.", "state") + statsStateDurationsNs = stats.NewGaugesWithSingleLabel("WorkerStateDurations", "How much time was spent in each state. Mainly used for testing.", "state") - statsOnlineInsertsCounters = stats.NewCountersWithLabels( + statsOnlineInsertsCounters = stats.NewCountersWithSingleLabel( "WorkerOnlineInsertsCounters", "For every table how many rows were inserted during the online clone (reconciliation) phase", "table") - statsOnlineUpdatesCounters = stats.NewCountersWithLabels( + statsOnlineUpdatesCounters = stats.NewCountersWithSingleLabel( "WorkerOnlineUpdatesCounters", "For every table how many rows were updated", "table") - statsOnlineDeletesCounters = stats.NewCountersWithLabels( + statsOnlineDeletesCounters = stats.NewCountersWithSingleLabel( "WorkerOnlineDeletesCounters", "For every table how many rows were deleted", "table") - statsOnlineEqualRowsCounters = stats.NewCountersWithLabels( + statsOnlineEqualRowsCounters = stats.NewCountersWithSingleLabel( "WorkerOnlineEqualRowsCounters", "For every table how many rows were equal", "table") - statsOfflineInsertsCounters = stats.NewCountersWithLabels( + statsOfflineInsertsCounters = stats.NewCountersWithSingleLabel( "WorkerOfflineInsertsCounters", "For every table how many rows were inserted during the online clone (reconciliation) phase", "table") - statsOfflineUpdatesCounters = stats.NewCountersWithLabels( + statsOfflineUpdatesCounters = stats.NewCountersWithSingleLabel( "WorkerOfflineUpdatesCounters", "For every table how many rows were updated", "table") - statsOfflineDeletesCounters = stats.NewCountersWithLabels( + statsOfflineDeletesCounters = stats.NewCountersWithSingleLabel( "WorkerOfflineDeletesCounters", "For every table how many rows were deleted", "table") - statsOfflineEqualRowsCounters = stats.NewCountersWithLabels( + statsOfflineEqualRowsCounters = stats.NewCountersWithSingleLabel( "WorkerOfflineEqualRowsCounters", "For every table how many rows were equal", "table") - statsStreamingQueryCounters = stats.NewCountersWithLabels( + statsStreamingQueryCounters = stats.NewCountersWithSingleLabel( "StreamingQueryCounters", "For every tablet alias how often a streaming query was successfully established there", "tablet_alias") - statsStreamingQueryErrorsCounters = stats.NewCountersWithLabels( + statsStreamingQueryErrorsCounters = stats.NewCountersWithSingleLabel( "StreamingQueryErrorsCounters", "For every tablet alias how often a (previously successfully established) streaming query did error", "tablet_alias") - statsStreamingQueryRestartsSameTabletCounters = stats.NewCountersWithLabels( + statsStreamingQueryRestartsSameTabletCounters = stats.NewCountersWithSingleLabel( "StreamingQueryRestartsSameTabletCounters", `For every tablet alias how often we successfully restarted a streaming query on the first retry. This kind of restart is usually necessary when our streaming query is idle and MySQL aborts it after a timeout.`, From 8e9d69758d14662532abff1d82563417fd68fc88 Mon Sep 17 00:00:00 2001 From: Michael Berlin Date: Sat, 28 Apr 2018 12:14:51 -0700 Subject: [PATCH 23/41] stats: CountersWithSingleLabel: Rename "labelName" to "label" to be more consistent with the *WithMultiLabels counterparts. Signed-off-by: Michael Berlin --- go/stats/counters.go | 37 ++++++++++--------- .../prometheusbackend/prometheusbackend.go | 4 +- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/go/stats/counters.go b/go/stats/counters.go index 2bcdbdeeab2..11f999f1c6c 100644 --- a/go/stats/counters.go +++ b/go/stats/counters.go @@ -118,25 +118,27 @@ func (c *counters) Help() string { return c.help } -// CountersWithSingleLabel provides a labelName for the tagged values in Counters +// CountersWithSingleLabel allows to publish related counters for a single +// label (aka category). // It provides a Counts method which can be used for tracking rates. type CountersWithSingleLabel struct { counters - labelName string + label string } // NewCountersWithSingleLabel create a new Counters instance. // If name is set, the variable gets published. // The function also accepts an optional list of tags that pre-creates them // initialized to 0. -// labelName is a category name used to organize the tags in Prometheus. -func NewCountersWithSingleLabel(name string, help string, labelName string, tags ...string) *CountersWithSingleLabel { +// label is a category name used to organize the tags. It is currently only +// used by Prometheus, but not by the expvar package. +func NewCountersWithSingleLabel(name, help, label string, tags ...string) *CountersWithSingleLabel { c := &CountersWithSingleLabel{ counters: counters{ counts: make(map[string]*int64), help: help, }, - labelName: labelName, + label: label, } for _, tag := range tags { @@ -148,9 +150,9 @@ func NewCountersWithSingleLabel(name string, help string, labelName string, tags return c } -// LabelName returns the label name. -func (c *CountersWithSingleLabel) LabelName() string { - return c.labelName +// Label returns the label name. +func (c *CountersWithSingleLabel) Label() string { + return c.label } // Add adds a value to a named counter. @@ -202,7 +204,7 @@ type CountersWithMultiLabels struct { // NewCountersWithMultiLabels creates a new CountersWithMultiLabels // instance, and publishes it if name is set. -func NewCountersWithMultiLabels(name string, help string, labels []string) *CountersWithMultiLabels { +func NewCountersWithMultiLabels(name, help string, labels []string) *CountersWithMultiLabels { t := &CountersWithMultiLabels{ counters: counters{ counts: make(map[string]*int64), @@ -251,7 +253,7 @@ func (mc *CountersWithMultiLabels) Counts() map[string]int64 { return mc.counters.Counts() } -// CountersFuncWithMultiLabels is a multidimensional CountersFunc implementation +// CountersFuncWithMultiLabels is a multidimensional counters implementation // where names of categories are compound names made with joining // multiple strings with '.'. Since the map is returned by the // function, we assume it's in the right format (meaning each key is @@ -288,22 +290,23 @@ func NewCountersFuncWithMultiLabels(name string, labels []string, help string, f return t } -// GaugesWithSingleLabel is similar to CountersWithSingleLabel, except its values can -// go up and down. +// GaugesWithSingleLabel is similar to CountersWithSingleLabel, except its +// values can go up and down. type GaugesWithSingleLabel struct { CountersWithSingleLabel } -// NewGaugesWithSingleLabel creates a new GaugesWithSingleLabel and publishes it if -// the name is set. -func NewGaugesWithSingleLabel(name string, help string, labelName string, tags ...string) *GaugesWithSingleLabel { +// NewGaugesWithSingleLabel creates a new GaugesWithSingleLabel and +// publishes it if the name is set. +func NewGaugesWithSingleLabel(name, help, label string, tags ...string) *GaugesWithSingleLabel { g := &GaugesWithSingleLabel{ CountersWithSingleLabel: CountersWithSingleLabel{ counters: counters{ counts: make(map[string]*int64), help: help, }, - labelName: labelName}, + label: label, + }, } for _, tag := range tags { @@ -335,7 +338,7 @@ type GaugesWithMultiLabels struct { // NewGaugesWithMultiLabels creates a new GaugesWithMultiLabels instance, // and publishes it if name is set. -func NewGaugesWithMultiLabels(name string, help string, labels []string) *GaugesWithMultiLabels { +func NewGaugesWithMultiLabels(name, help string, labels []string) *GaugesWithMultiLabels { t := &GaugesWithMultiLabels{ CountersWithMultiLabels: CountersWithMultiLabels{ counters: counters{ diff --git a/go/stats/prometheusbackend/prometheusbackend.go b/go/stats/prometheusbackend/prometheusbackend.go index 4620aebb087..90ed7516dee 100644 --- a/go/stats/prometheusbackend/prometheusbackend.go +++ b/go/stats/prometheusbackend/prometheusbackend.go @@ -42,7 +42,7 @@ func (be *PromBackend) publishPrometheusMetric(name string, v expvar.Var) { case *stats.GaugeFunc: be.newMetric(st, name, prometheus.GaugeValue, func() float64 { return float64(st.F()) }) case *stats.CountersWithSingleLabel: - be.newCountersWithSingleLabel(st, name, st.LabelName(), prometheus.CounterValue) + be.newCountersWithSingleLabel(st, name, st.Label(), prometheus.CounterValue) case *stats.CountersWithMultiLabels: be.newCountersWithMultiLabels(st, name) case *stats.CountersFuncWithMultiLabels: @@ -50,7 +50,7 @@ func (be *PromBackend) publishPrometheusMetric(name string, v expvar.Var) { case *stats.GaugesFuncWithMultiLabels: be.newMetricsFuncWithMultiLabels(&st.CountersFuncWithMultiLabels, name, prometheus.GaugeValue) case *stats.GaugesWithSingleLabel: - be.newGaugesWithSingleLabel(st, name, st.LabelName(), prometheus.GaugeValue) + be.newGaugesWithSingleLabel(st, name, st.Label(), prometheus.GaugeValue) case *stats.GaugesWithMultiLabels: be.newGaugesWithMultiLabels(st, name) case *stats.CounterDuration: From 66747a1ebb2733c44124e00be1628a9507efaf29 Mon Sep 17 00:00:00 2001 From: Michael Berlin Date: Sat, 28 Apr 2018 12:37:43 -0700 Subject: [PATCH 24/41] stats: Change order of "help" parameter in (Gauges|Counters)Func* types. Now the function signatures are consistent with all other constructors. Other changes: - Do not repeat the type in function signatures when it's the same. - Do not use receiver names with more than 2 letters. - Do not use pointer receiver if you don't want to modify the object. Signed-off-by: Michael Berlin --- go/stats/counters.go | 20 +++++++++---------- go/stats/counters_test.go | 2 +- .../prometheusbackend_test.go | 2 +- go/vt/discovery/healthcheck.go | 2 +- go/vt/vtgate/gateway/hybridgateway.go | 2 +- go/vt/vttablet/tabletserver/query_engine.go | 8 ++++---- go/vt/vttablet/tabletserver/schema/engine.go | 10 +++++----- 7 files changed, 23 insertions(+), 23 deletions(-) diff --git a/go/stats/counters.go b/go/stats/counters.go index 11f999f1c6c..d038610685d 100644 --- a/go/stats/counters.go +++ b/go/stats/counters.go @@ -261,27 +261,27 @@ func (mc *CountersWithMultiLabels) Counts() map[string]int64 { // Labels). type CountersFuncWithMultiLabels struct { CountersFunc - labels []string help string + labels []string } // Labels returns the list of labels. -func (mcf *CountersFuncWithMultiLabels) Labels() []string { - return mcf.labels +func (c CountersFuncWithMultiLabels) Labels() []string { + return c.labels } -// Help returns the help string -func (mcf *CountersFuncWithMultiLabels) Help() string { - return mcf.help +// Help returns the help string. +func (c CountersFuncWithMultiLabels) Help() string { + return c.help } // NewCountersFuncWithMultiLabels creates a new CountersFuncWithMultiLabels // mapping to the provided function. -func NewCountersFuncWithMultiLabels(name string, labels []string, help string, f CountersFunc) *CountersFuncWithMultiLabels { +func NewCountersFuncWithMultiLabels(name, help string, labels []string, f CountersFunc) *CountersFuncWithMultiLabels { t := &CountersFuncWithMultiLabels{ CountersFunc: f, - labels: labels, help: help, + labels: labels, } if name != "" { publish(name, t) @@ -383,12 +383,12 @@ type GaugesFuncWithMultiLabels struct { // NewGaugesFuncWithMultiLabels creates a new GaugesFuncWithMultiLabels // mapping to the provided function. -func NewGaugesFuncWithMultiLabels(name string, labels []string, help string, f CountersFunc) *GaugesFuncWithMultiLabels { +func NewGaugesFuncWithMultiLabels(name, help string, labels []string, f CountersFunc) *GaugesFuncWithMultiLabels { t := &GaugesFuncWithMultiLabels{ CountersFuncWithMultiLabels: CountersFuncWithMultiLabels{ CountersFunc: f, - labels: labels, help: help, + labels: labels, }} if name != "" { diff --git a/go/stats/counters_test.go b/go/stats/counters_test.go index bffca623652..509d9c190db 100644 --- a/go/stats/counters_test.go +++ b/go/stats/counters_test.go @@ -89,7 +89,7 @@ func TestMultiCounters(t *testing.T) { if counts["c2a.c2b"] != 2 { t.Errorf("want 2, got %d", counts["c2a.c2b"]) } - f := NewCountersFuncWithMultiLabels("", []string{"aaa", "bbb"}, "help", func() map[string]int64 { + f := NewCountersFuncWithMultiLabels("", "help", []string{"aaa", "bbb"}, func() map[string]int64 { return map[string]int64{ "c1a.c1b": 1, "c2a.c2b": 2, diff --git a/go/stats/prometheusbackend/prometheusbackend_test.go b/go/stats/prometheusbackend/prometheusbackend_test.go index efe6ce8f7b9..ebee87b5c15 100644 --- a/go/stats/prometheusbackend/prometheusbackend_test.go +++ b/go/stats/prometheusbackend/prometheusbackend_test.go @@ -197,7 +197,7 @@ func TestPrometheusCountersFuncWithMultiLabels(t *testing.T) { name := "blah_countersfuncwithmultilabels" labels := []string{"label1", "label2"} - stats.NewCountersFuncWithMultiLabels(name, labels, "help", func() map[string]int64 { + stats.NewCountersFuncWithMultiLabels(name, "help", labels, func() map[string]int64 { m := make(map[string]int64) m["foo.bar"] = 1 m["bar.baz"] = 1 diff --git a/go/vt/discovery/healthcheck.go b/go/vt/discovery/healthcheck.go index 27612dd5675..350cab3222d 100644 --- a/go/vt/discovery/healthcheck.go +++ b/go/vt/discovery/healthcheck.go @@ -388,8 +388,8 @@ func NewHealthCheck(retryDelay, healthCheckTimeout time.Duration) HealthCheck { func (hc *HealthCheckImpl) RegisterStats() { stats.NewCountersFuncWithMultiLabels( "HealthcheckConnections", + "the number of healthcheck connections registered", []string{"Keyspace", "ShardName", "TabletType"}, - "the numb of healthcheck connections registered", hc.servingConnStats) } diff --git a/go/vt/vtgate/gateway/hybridgateway.go b/go/vt/vtgate/gateway/hybridgateway.go index 985f15bc9df..8f908565bc5 100644 --- a/go/vt/vtgate/gateway/hybridgateway.go +++ b/go/vt/vtgate/gateway/hybridgateway.go @@ -92,8 +92,8 @@ func (h *HybridGateway) WaitForTablets(ctx context.Context, tabletTypesToWait [] func (h *HybridGateway) RegisterStats() { stats.NewCountersFuncWithMultiLabels( "L2VtgateConnections", + "number of l2vtgate connection", []string{"Keyspace", "ShardName", "TabletType"}, - "The l2vtgate connection counts", h.servingConnStats) } diff --git a/go/vt/vttablet/tabletserver/query_engine.go b/go/vt/vttablet/tabletserver/query_engine.go index 85490e9d824..79e92d07e17 100644 --- a/go/vt/vttablet/tabletserver/query_engine.go +++ b/go/vt/vttablet/tabletserver/query_engine.go @@ -248,10 +248,10 @@ func NewQueryEngine(checker connpool.MySQLChecker, se *schema.Engine, config tab stats.Publish("QueryCacheOldest", stats.StringFunc(func() string { return fmt.Sprintf("%v", qe.plans.Oldest()) })) - _ = stats.NewCountersFuncWithMultiLabels("QueryCounts", []string{"Table", "Plan"}, "query counts", qe.getQueryCount) - _ = stats.NewCountersFuncWithMultiLabels("QueryTimesNs", []string{"Table", "Plan"}, "query times in ns", qe.getQueryTime) - _ = stats.NewCountersFuncWithMultiLabels("QueryRowCounts", []string{"Table", "Plan"}, "query row counts", qe.getQueryRowCount) - _ = stats.NewCountersFuncWithMultiLabels("QueryErrorCounts", []string{"Table", "Plan"}, "query error counts", qe.getQueryErrorCount) + _ = stats.NewCountersFuncWithMultiLabels("QueryCounts", "query counts", []string{"Table", "Plan"}, qe.getQueryCount) + _ = stats.NewCountersFuncWithMultiLabels("QueryTimesNs", "query times in ns", []string{"Table", "Plan"}, qe.getQueryTime) + _ = stats.NewCountersFuncWithMultiLabels("QueryRowCounts", "query row counts", []string{"Table", "Plan"}, qe.getQueryRowCount) + _ = stats.NewCountersFuncWithMultiLabels("QueryErrorCounts", "query error counts", []string{"Table", "Plan"}, qe.getQueryErrorCount) http.Handle("/debug/hotrows", qe.txSerializer) diff --git a/go/vt/vttablet/tabletserver/schema/engine.go b/go/vt/vttablet/tabletserver/schema/engine.go index ead5d0098bb..944e640227e 100644 --- a/go/vt/vttablet/tabletserver/schema/engine.go +++ b/go/vt/vttablet/tabletserver/schema/engine.go @@ -78,11 +78,11 @@ func NewEngine(checker connpool.MySQLChecker, config tabletenv.TabletConfig) *En } schemaOnce.Do(func() { _ = stats.NewGaugeDurationFunc("SchemaReloadTime", "vttablet keeps table schemas in its own memory and periodically refreshes it from MySQL. This config controls the reload time.", se.ticks.Interval) - _ = stats.NewGaugesFuncWithMultiLabels("TableRows", []string{"Table"}, "table rows created in tabletserver", se.getTableRows) - _ = stats.NewGaugesFuncWithMultiLabels("DataLength", []string{"Table"}, "data length in tabletserver", se.getDataLength) - _ = stats.NewGaugesFuncWithMultiLabels("IndexLength", []string{"Table"}, "index length in tabletserver", se.getIndexLength) - _ = stats.NewGaugesFuncWithMultiLabels("DataFree", []string{"Table"}, "data free in tabletserver", se.getDataFree) - _ = stats.NewGaugesFuncWithMultiLabels("MaxDataLength", []string{"Table"}, "max data length in tabletserver", se.getMaxDataLength) + _ = stats.NewGaugesFuncWithMultiLabels("TableRows", "table rows created in tabletserver", []string{"Table"}, se.getTableRows) + _ = stats.NewGaugesFuncWithMultiLabels("DataLength", "data length in tabletserver", []string{"Table"}, se.getDataLength) + _ = stats.NewGaugesFuncWithMultiLabels("IndexLength", "index length in tabletserver", []string{"Table"}, se.getIndexLength) + _ = stats.NewGaugesFuncWithMultiLabels("DataFree", "data free in tabletserver", []string{"Table"}, se.getDataFree) + _ = stats.NewGaugesFuncWithMultiLabels("MaxDataLength", "max data length in tabletserver", []string{"Table"}, se.getMaxDataLength) http.Handle("/debug/schema", se) http.HandleFunc("/schemaz", func(w http.ResponseWriter, r *http.Request) { From 2388a9b9f499ed496b3a2b38a51052fe395bc99a Mon Sep 17 00:00:00 2001 From: Michael Berlin Date: Sat, 28 Apr 2018 12:55:29 -0700 Subject: [PATCH 25/41] stats: Improve counter documentation. Signed-off-by: Michael Berlin --- go/stats/counter.go | 21 +++++++++++++-------- go/stats/counters.go | 12 ++++++------ 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/go/stats/counter.go b/go/stats/counter.go index 772f1d9d1e1..bf1956089a5 100644 --- a/go/stats/counter.go +++ b/go/stats/counter.go @@ -27,13 +27,15 @@ import ( // logCounterNegative is for throttling adding a negative value to a counter messages in logs var logCounterNegative = logutil.NewThrottledLogger("StatsCounterNegative", 1*time.Minute) -// Counter is expvar.Int+Get+hook +// Counter tracks a cumulative count of a metric. +// For a one-dimensional or multi-dimensional counter, please use +// CountersWithSingleLabel or CountersWithMultiLabels instead. type Counter struct { i sync2.AtomicInt64 help string } -// NewCounter returns a new Counter +// NewCounter returns a new Counter. func NewCounter(name string, help string) *Counter { v := &Counter{help: help} if name != "" { @@ -42,7 +44,7 @@ func NewCounter(name string, help string) *Counter { return v } -// Add adds the provided value to the Counter +// Add adds the provided value to the Counter. func (v *Counter) Add(delta int64) { if delta < 0 { logCounterNegative.Warningf("Adding a negative value to a counter, %v should be a gauge instead", v) @@ -50,22 +52,22 @@ func (v *Counter) Add(delta int64) { v.i.Add(delta) } -// Reset resets the counter value to 0 +// Reset resets the counter value to 0. func (v *Counter) Reset() { v.i.Set(int64(0)) } -// Get returns the value +// Get returns the value. func (v *Counter) Get() int64 { return v.i.Get() } -// String is the implementation of expvar.var +// String implements the expvar.Var interface. func (v *Counter) String() string { return strconv.FormatInt(v.i.Get(), 10) } -// Help returns the help string +// Help returns the help string. func (v *Counter) Help() string { return v.help } @@ -102,7 +104,10 @@ func (cf CounterFunc) String() string { return strconv.FormatInt(cf.F(), 10) } -// Gauge is an unlabeled metric whose values can go up/down. +// Gauge tracks the current value of an integer metric. +// The emphasis here is on *current* i.e. this is not a cumulative counter. +// For a one-dimensional or multi-dimensional gauge, please use +// GaugeWithSingleLabel or GaugesWithMultiLabels instead. type Gauge struct { Counter } diff --git a/go/stats/counters.go b/go/stats/counters.go index d038610685d..99435f6ccef 100644 --- a/go/stats/counters.go +++ b/go/stats/counters.go @@ -118,8 +118,8 @@ func (c *counters) Help() string { return c.help } -// CountersWithSingleLabel allows to publish related counters for a single -// label (aka category). +// CountersWithSingleLabel tracks multiple counter values for a single +// dimension ("label"). // It provides a Counts method which can be used for tracking rates. type CountersWithSingleLabel struct { counters @@ -194,9 +194,9 @@ func (f CountersFunc) String() string { return b.String() } -// CountersWithMultiLabels is a multidimensional counters implementation -// where names of categories are compound names made with joining multiple -// strings with '.'. +// CountersWithMultiLabels is a multidimensional counters implementation. +// Internally, each tuple of dimensions ("labels") is stored as a single +// label value where all label values are joined with ".". type CountersWithMultiLabels struct { counters labels []string @@ -291,7 +291,7 @@ func NewCountersFuncWithMultiLabels(name, help string, labels []string, f Counte } // GaugesWithSingleLabel is similar to CountersWithSingleLabel, except its -// values can go up and down. +// meant to track the current value and not a cumulative count. type GaugesWithSingleLabel struct { CountersWithSingleLabel } From 0bb599459df67649603d30b11dc7164e25e2f024 Mon Sep 17 00:00:00 2001 From: jvaidya Date: Sat, 28 Apr 2018 20:41:08 +0000 Subject: [PATCH 26/41] fix supported data types Signed-off-by: jvaidya --- doc/ServerConfiguration.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/doc/ServerConfiguration.md b/doc/ServerConfiguration.md index 7cd2449bf2d..03ba9670b59 100644 --- a/doc/ServerConfiguration.md +++ b/doc/ServerConfiguration.md @@ -61,7 +61,7 @@ RBR will eventually be supported by Vitess. ### Data types -Vitess supports data types at the MySQL 5.5 level. The newer data types like spatial or JSON are not supported yet. Additionally, the TIMESTAMP data type should not be used in a primary key or sharding column. Otherwise, Vitess cannot predict those values correctly and this may result in data corruption. +Vitess supports all data types including newer data types like spatial and JSON. Additionally, the TIMESTAMP data type should not be used in a primary key or sharding column. Otherwise, Vitess cannot predict those values correctly and this may result in data corruption. ### No side effects @@ -676,4 +676,3 @@ Orchestrator, it also means new instances will be discovered immediately, and the topology will automatically repopulate even if Orchestrator's backing store is wiped out. Note that Orchestrator will forget stale instances after a configurable timeout. - From a6c5e26478d8bfa7ed640e34d08ffbd05a1f42f7 Mon Sep 17 00:00:00 2001 From: Michael Berlin Date: Sat, 28 Apr 2018 14:34:31 -0700 Subject: [PATCH 27/41] stats: Remove CountersFunc type. Instead, all code should use "CountersFuncWithMultiLabels" with a single label instead. There was only one place in the codebase (binlog_players.go) which had to be changed. Signed-off-by: Michael Berlin --- go/stats/counters.go | 80 ++++++++++--------- go/stats/counters_test.go | 45 ++++++++--- go/stats/multidimensional.go | 24 +++--- go/stats/rates.go | 9 +++ .../vttablet/tabletmanager/binlog_players.go | 26 +++--- 5 files changed, 115 insertions(+), 69 deletions(-) diff --git a/go/stats/counters.go b/go/stats/counters.go index 99435f6ccef..bc22dd7a2ca 100644 --- a/go/stats/counters.go +++ b/go/stats/counters.go @@ -164,36 +164,6 @@ func (c *CountersWithSingleLabel) Add(name string, value int64) { atomic.AddInt64(a, value) } -// CountersFunc converts a function that returns -// a map of int64 as an expvar. -type CountersFunc func() map[string]int64 - -// Counts returns a copy of the Counters' map. -func (f CountersFunc) Counts() map[string]int64 { - return f() -} - -// String implements the expvar.Var interface. -func (f CountersFunc) String() string { - m := f() - if m == nil { - return "{}" - } - b := bytes.NewBuffer(make([]byte, 0, 4096)) - fmt.Fprintf(b, "{") - firstValue := true - for k, v := range m { - if firstValue { - firstValue = false - } else { - fmt.Fprintf(b, ", ") - } - fmt.Fprintf(b, "%q: %v", k, v) - } - fmt.Fprintf(b, "}") - return b.String() -} - // CountersWithMultiLabels is a multidimensional counters implementation. // Internally, each tuple of dimensions ("labels") is stored as a single // label value where all label values are joined with ".". @@ -259,8 +229,14 @@ func (mc *CountersWithMultiLabels) Counts() map[string]int64 { // function, we assume it's in the right format (meaning each key is // of the form 'aaa.bbb.ccc' with as many elements as there are in // Labels). +// +// Note that there is no CountersFuncWithSingleLabel object. That this +// because such an object would be identical to this one because these +// function-based counters have no Add() or Set() method which are different +// for the single vs. multiple labels cases. +// If you have only a single label, pass an array with a single element. type CountersFuncWithMultiLabels struct { - CountersFunc + f func() map[string]int64 help string labels []string } @@ -277,11 +253,11 @@ func (c CountersFuncWithMultiLabels) Help() string { // NewCountersFuncWithMultiLabels creates a new CountersFuncWithMultiLabels // mapping to the provided function. -func NewCountersFuncWithMultiLabels(name, help string, labels []string, f CountersFunc) *CountersFuncWithMultiLabels { +func NewCountersFuncWithMultiLabels(name, help string, labels []string, f func() map[string]int64) *CountersFuncWithMultiLabels { t := &CountersFuncWithMultiLabels{ - CountersFunc: f, - help: help, - labels: labels, + f: f, + help: help, + labels: labels, } if name != "" { publish(name, t) @@ -290,6 +266,32 @@ func NewCountersFuncWithMultiLabels(name, help string, labels []string, f Counte return t } +// Counts returns a copy of the counters' map. +func (c CountersFuncWithMultiLabels) Counts() map[string]int64 { + return c.f() +} + +// String implements the expvar.Var interface. +func (c CountersFuncWithMultiLabels) String() string { + m := c.f() + if m == nil { + return "{}" + } + b := bytes.NewBuffer(make([]byte, 0, 4096)) + fmt.Fprintf(b, "{") + firstValue := true + for k, v := range m { + if firstValue { + firstValue = false + } else { + fmt.Fprintf(b, ", ") + } + fmt.Fprintf(b, "%q: %v", k, v) + } + fmt.Fprintf(b, "}") + return b.String() +} + // GaugesWithSingleLabel is similar to CountersWithSingleLabel, except its // meant to track the current value and not a cumulative count. type GaugesWithSingleLabel struct { @@ -383,12 +385,12 @@ type GaugesFuncWithMultiLabels struct { // NewGaugesFuncWithMultiLabels creates a new GaugesFuncWithMultiLabels // mapping to the provided function. -func NewGaugesFuncWithMultiLabels(name, help string, labels []string, f CountersFunc) *GaugesFuncWithMultiLabels { +func NewGaugesFuncWithMultiLabels(name, help string, labels []string, f func() map[string]int64) *GaugesFuncWithMultiLabels { t := &GaugesFuncWithMultiLabels{ CountersFuncWithMultiLabels: CountersFuncWithMultiLabels{ - CountersFunc: f, - help: help, - labels: labels, + f: f, + help: help, + labels: labels, }} if name != "" { diff --git a/go/stats/counters_test.go b/go/stats/counters_test.go index 509d9c190db..be01e5637ce 100644 --- a/go/stats/counters_test.go +++ b/go/stats/counters_test.go @@ -43,15 +43,6 @@ func TestCounters(t *testing.T) { if counts["c2"] != 2 { t.Errorf("want 2, got %d", counts["c2"]) } - f := CountersFunc(func() map[string]int64 { - return map[string]int64{ - "c1": 1, - "c2": 2, - } - }) - if s := f.String(); s != want1 && s != want2 { - t.Errorf("want %s or %s, got %s", want1, want2, s) - } } func TestCountersTags(t *testing.T) { @@ -208,3 +199,39 @@ func BenchmarkCountersTailLatency(b *testing.B) { close(c) <-done } + +func TestCountersFuncWithMultiLabels(t *testing.T) { + clear() + f := NewCountersFuncWithMultiLabels("TestCountersFuncWithMultiLabels", "help", []string{"label1"}, func() map[string]int64 { + return map[string]int64{ + "c1": 1, + "c2": 2, + } + }) + + want1 := `{"c1": 1, "c2": 2}` + want2 := `{"c2": 2, "c1": 1}` + if s := f.String(); s != want1 && s != want2 { + t.Errorf("want %s or %s, got %s", want1, want2, s) + } +} + +func TestCountersFuncWithMultiLabels_Hook(t *testing.T) { + var gotname string + var gotv *CountersFuncWithMultiLabels + clear() + Register(func(name string, v expvar.Var) { + gotname = name + gotv = v.(*CountersFuncWithMultiLabels) + }) + + v := NewCountersFuncWithMultiLabels("TestCountersFuncWithMultiLabels_Hook", "help", []string{"label1"}, func() map[string]int64 { + return map[string]int64{} + }) + if gotname != "TestCountersFuncWithMultiLabels_Hook" { + t.Errorf("want TestCountersFuncWithMultiLabels_Hook, got %s", gotname) + } + if gotv != v { + t.Errorf("want %#v, got %#v", v, gotv) + } +} diff --git a/go/stats/multidimensional.go b/go/stats/multidimensional.go index 007cc0a2216..0d85c073103 100644 --- a/go/stats/multidimensional.go +++ b/go/stats/multidimensional.go @@ -34,19 +34,21 @@ type MultiTracker interface { func CounterForDimension(mt MultiTracker, dimension string) CountTracker { for i, lab := range mt.Labels() { if lab == dimension { - return CountersFunc(func() map[string]int64 { - result := make(map[string]int64) - for k, v := range mt.Counts() { - if k == "All" { - result[k] = v - continue + return wrappedCountTracker{ + f: func() map[string]int64 { + result := make(map[string]int64) + for k, v := range mt.Counts() { + if k == "All" { + result[k] = v + continue + } + result[strings.Split(k, ".")[i]] += v } - result[strings.Split(k, ".")[i]] += v - } - return result - }) + return result + }, + } } } - panic(fmt.Sprintf("label %v is not one of %v", dimension, mt.Labels())) + panic(fmt.Sprintf("label %v is not one of %v", dimension, mt.Labels())) } diff --git a/go/stats/rates.go b/go/stats/rates.go index 5290bec8bfb..7cb7ded97f0 100644 --- a/go/stats/rates.go +++ b/go/stats/rates.go @@ -37,6 +37,15 @@ type CountTracker interface { Counts() map[string]int64 } +// wrappedCountTracker implements the CountTracker interface. +// It is used in multidimensional.go to publish specific, one-dimensional +// counters. +type wrappedCountTracker struct { + f func() map[string]int64 +} + +func (t wrappedCountTracker) Counts() map[string]int64 { return t.f() } + // Rates is capable of reporting the rate (typically QPS) // for any variable that satisfies the CountTracker interface. type Rates struct { diff --git a/go/vt/vttablet/tabletmanager/binlog_players.go b/go/vt/vttablet/tabletmanager/binlog_players.go index 168afea52d0..2baa2e69163 100644 --- a/go/vt/vttablet/tabletmanager/binlog_players.go +++ b/go/vt/vttablet/tabletmanager/binlog_players.go @@ -434,16 +434,22 @@ func RegisterBinlogPlayerMap(blm *BinlogPlayerMap) { defer blm.mu.Unlock() return blm.maxSecondsBehindMasterUNGUARDED() }) - stats.Publish("BinlogPlayerSecondsBehindMasterMap", stats.CountersFunc(func() map[string]int64 { - blm.mu.Lock() - result := make(map[string]int64, len(blm.players)) - for i, bpc := range blm.players { - sbm := bpc.binlogPlayerStats.SecondsBehindMaster.Get() - result[fmt.Sprintf("%v", i)] = sbm - } - blm.mu.Unlock() - return result - })) + stats.NewCountersFuncWithMultiLabels( + "BinlogPlayerSecondsBehindMasterMap", + "Binlog player seconds behind master per player", + // CAUTION: Always keep this label as "counts" because the Google + // internal monitoring may depend on this specific value. + []string{"counts"}, + func() map[string]int64 { + blm.mu.Lock() + result := make(map[string]int64, len(blm.players)) + for i, bpc := range blm.players { + sbm := bpc.binlogPlayerStats.SecondsBehindMaster.Get() + result[fmt.Sprintf("%v", i)] = sbm + } + blm.mu.Unlock() + return result + }) stats.Publish("BinlogPlayerSourceShardNameMap", stats.StringMapFunc(func() map[string]string { blm.mu.Lock() result := make(map[string]string, len(blm.players)) From 2d141ad53dcea274ee644d53392ec6ddf61fd4fa Mon Sep 17 00:00:00 2001 From: jvaidya Date: Mon, 30 Apr 2018 20:18:40 +0000 Subject: [PATCH 28/41] removed explanations of RBR vs SBR, we now support RBR Signed-off-by: jvaidya --- doc/VitessReplication.md | 74 ++++++---------------------------------- 1 file changed, 11 insertions(+), 63 deletions(-) diff --git a/doc/VitessReplication.md b/doc/VitessReplication.md index b69bd5fa9e9..431e72ff33e 100644 --- a/doc/VitessReplication.md +++ b/doc/VitessReplication.md @@ -3,70 +3,18 @@ ## Statement vs Row Based Replication MySQL supports two primary modes of replication in its binary logs: statement or -row based. - -**Statement Based Replication**: - -* The statements executed on the master are copied almost as-is in the master - logs. -* The slaves replay these statements as is. -* If the statements are expensive (especially an update with a complicated WHERE - clause), they will be expensive on the slaves too. -* For current timestamp and auto-increment values, the master also puts - additional SET statements in the logs to make the statement have the same - effect, so the slaves end up with the same values. - -**Row Based Replication**: - -* The statements executed on the master result in updated rows. The new full - values for these rows are copied to the master logs. -* The slaves change their records for the rows they receive. The update is by - primary key, and contains the new values for each column, so usually it’s very - fast. -* Each updated row contains the entire row, not just the columns that were - updated (unless the flag --binlog\_row\_image=minimal is used). -* The replication stream is harder to read, as it contains almost binary data, - that don’t easily map to the original statements. -* There is a configurable limit on how many rows can be affected by one - binlog event, so the master logs are not flooded. -* The format of the logs depends on the master schema: each row has a list of - values, one value for each column. So if the master schema is different from - the slave schema, updates will misbehave (exception being if slave has extra - columns at the end). -* It is possible to revert to statement based replication for some commands to - avoid these drawbacks (for instance for DELETE statements that affect a large - number of rows). -* Schema changes always use statement based replication. -* If comments are added to a statement, they are stripped from the - replication stream (as only rows are transmitted). There is a flag - --binlog\_rows\_query\_log\_events to add the original statement to each row - update, but it is costly in terms of binlog size. - -For the longest time, MySQL replication has been single-threaded: only one -statement is applied by the slaves at a time. Since the master applies more -statements in parallel, replication can fall behind on the slaves fairly easily, -under higher load. Even though the situation has improved (parallel slave -apply), the slave replication speed is still a limiting factor for a lot of -applications. Since row based replication achieves higher update rates on the -slaves in most cases, it has been the only viable option for most performance -sensitive applications. - -Schema changes however are not easy to achieve with row based -replication. Adding columns can be done offline, but removing or changing -columns cannot easily be done (there are multiple ways to achieve this, but they -all have limitations or performance implications, and are not that easy to -setup). - -Vitess helps by using statement based replication (therefore allowing complex -schema changes), while at the same time simplifying the replication stream (so -slaves can be fast), by rewriting Update statements. - -Then, with statement based replication, it becomes easier to perform offline -advanced schema changes, or large data updates. Vitess’s solution is called -schema swap. +row based. Vitess supports both these modes. + +For schema changes, if the number of affected rows is greater > 100k (configurable), we don't allow direct application +of DDLs the recommended tool in such cases is gh-ost -We plan to also support row based replication in the future, and adapt our tools -to provide the same features when possible. See Appendix for our plan. +When using statement based replication, Vitess helps by rewriting Update statements, +therefore allowing complex schema changes, while at the same time simplifying the replication stream (so +slaves can be fast). This is described in detail below. + +Thus, with statement based replication, it becomes easier to perform offline +advanced schema changes, or large data updates. Vitess’s solution is called +schema swap (described below). ## Rewriting Update Statements From f38ace4f378f0e8a8e5501e050b615d31ec37e58 Mon Sep 17 00:00:00 2001 From: jvaidya Date: Mon, 30 Apr 2018 21:42:40 +0000 Subject: [PATCH 29/41] addresed comments Signed-off-by: jvaidya --- doc/VitessReplication.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/doc/VitessReplication.md b/doc/VitessReplication.md index 431e72ff33e..a0c549e4428 100644 --- a/doc/VitessReplication.md +++ b/doc/VitessReplication.md @@ -6,13 +6,11 @@ MySQL supports two primary modes of replication in its binary logs: statement or row based. Vitess supports both these modes. For schema changes, if the number of affected rows is greater > 100k (configurable), we don't allow direct application -of DDLs the recommended tool in such cases is gh-ost +of DDLs. The recommended tool in such cases is [gh-ost]({% link https://github.com/github/gh-ost %}). -When using statement based replication, Vitess helps by rewriting Update statements, -therefore allowing complex schema changes, while at the same time simplifying the replication stream (so -slaves can be fast). This is described in detail below. +Not all statements are safe for Statement Based Replication (SBR): https://dev.mysql.com/doc/refman/8.0/en/replication-rbr-safe-unsafe.html. Vitess rewrites some of these statements to be safe for SBR, and others are explicitly failed. This is described in detail below. -Thus, with statement based replication, it becomes easier to perform offline +With statement based replication, it becomes easier to perform offline advanced schema changes, or large data updates. Vitess’s solution is called schema swap (described below). From 504550ecefce91be6298ff7fafd8ef85d3bab8df Mon Sep 17 00:00:00 2001 From: Michael Demmer Date: Thu, 26 Apr 2018 16:58:02 -0700 Subject: [PATCH 30/41] make the label name customizable for stats.NewTimings Instead of hard-coding the label "Histograms" inside the prometheus exporter, change the stats.NewTimings API to be more like the other labelled metrics in which the label name is part of the constructor. Signed-off-by: Michael Demmer --- go/mysql/server.go | 2 +- .../prometheusbackend/prometheusbackend.go | 2 +- .../prometheusbackend_test.go | 28 +++++++++---------- go/stats/timings.go | 9 +++++- go/stats/timings_test.go | 4 +-- go/vt/binlog/binlogplayer/binlog_player.go | 2 +- .../fakemysqldaemon/fakemysqldaemon.go | 6 ++-- go/vt/mysqlctl/mysqld.go | 6 ++-- go/vt/vttablet/heartbeat/writer.go | 2 +- .../tabletmanager/rpc_external_reparent.go | 2 +- .../tabletserver/tabletenv/tabletenv.go | 6 ++-- go/vt/vttablet/tabletserver/twopc.go | 2 +- go/vt/vttablet/tabletserver/tx_pool.go | 2 +- 13 files changed, 40 insertions(+), 33 deletions(-) diff --git a/go/mysql/server.go b/go/mysql/server.go index 41923172747..10807762c32 100644 --- a/go/mysql/server.go +++ b/go/mysql/server.go @@ -42,7 +42,7 @@ const ( var ( // Metrics - timings = stats.NewTimings("MysqlServerTimings", "MySQL server timings") + timings = stats.NewTimings("MysqlServerTimings", "MySQL server timings", "operation") connCount = stats.NewGauge("MysqlServerConnCount", "Active MySQL server connections") connAccept = stats.NewCounter("MysqlServerConnAccepted", "Connections accepted by MySQL server") connSlow = stats.NewCounter("MysqlServerConnSlow", "Connections that took more than the configured mysql_slow_connect_warn_threshold to establish") diff --git a/go/stats/prometheusbackend/prometheusbackend.go b/go/stats/prometheusbackend/prometheusbackend.go index 90ed7516dee..1bfb822f05b 100644 --- a/go/stats/prometheusbackend/prometheusbackend.go +++ b/go/stats/prometheusbackend/prometheusbackend.go @@ -142,7 +142,7 @@ func (be *PromBackend) newTiming(t *stats.Timings, name string) { desc: prometheus.NewDesc( be.buildPromName(name), t.Help(), - []string{"Histograms"}, // hard coded label key + []string{t.LabelName()}, nil), } diff --git a/go/stats/prometheusbackend/prometheusbackend_test.go b/go/stats/prometheusbackend/prometheusbackend_test.go index ebee87b5c15..61f5dbe12f9 100644 --- a/go/stats/prometheusbackend/prometheusbackend_test.go +++ b/go/stats/prometheusbackend/prometheusbackend_test.go @@ -221,25 +221,25 @@ func checkHandlerForMetricWithMultiLabels(t *testing.T, metric string, labels [] func TestPrometheusTimings(t *testing.T) { name := "blah_timings" cats := []string{"cat1", "cat2"} - timing := stats.NewTimings(name, "help", cats...) + timing := stats.NewTimings(name, "help", "category", cats...) timing.Add("cat1", time.Duration(1000000000)) response := testMetricsHandler(t) var s []string - s = append(s, fmt.Sprintf("%s_%s_bucket{Histograms=\"%s\",le=\"0.0005\"} %d", namespace, name, cats[0], 0)) - s = append(s, fmt.Sprintf("%s_%s_bucket{Histograms=\"%s\",le=\"0.001\"} %d", namespace, name, cats[0], 0)) - s = append(s, fmt.Sprintf("%s_%s_bucket{Histograms=\"%s\",le=\"0.005\"} %d", namespace, name, cats[0], 0)) - s = append(s, fmt.Sprintf("%s_%s_bucket{Histograms=\"%s\",le=\"0.01\"} %d", namespace, name, cats[0], 0)) - s = append(s, fmt.Sprintf("%s_%s_bucket{Histograms=\"%s\",le=\"0.05\"} %d", namespace, name, cats[0], 0)) - s = append(s, fmt.Sprintf("%s_%s_bucket{Histograms=\"%s\",le=\"0.1\"} %d", namespace, name, cats[0], 0)) - s = append(s, fmt.Sprintf("%s_%s_bucket{Histograms=\"%s\",le=\"0.5\"} %d", namespace, name, cats[0], 0)) - s = append(s, fmt.Sprintf("%s_%s_bucket{Histograms=\"%s\",le=\"1\"} %d", namespace, name, cats[0], 1)) - s = append(s, fmt.Sprintf("%s_%s_bucket{Histograms=\"%s\",le=\"5\"} %d", namespace, name, cats[0], 1)) - s = append(s, fmt.Sprintf("%s_%s_bucket{Histograms=\"%s\",le=\"10\"} %d", namespace, name, cats[0], 1)) - s = append(s, fmt.Sprintf("%s_%s_bucket{Histograms=\"%s\",le=\"+Inf\"} %d", namespace, name, cats[0], 1)) - s = append(s, fmt.Sprintf("%s_%s_sum{Histograms=\"%s\"} %d", namespace, name, cats[0], 1)) - s = append(s, fmt.Sprintf("%s_%s_count{Histograms=\"%s\"} %d", namespace, name, cats[0], 1)) + s = append(s, fmt.Sprintf("%s_%s_bucket{category=\"%s\",le=\"0.0005\"} %d", namespace, name, cats[0], 0)) + s = append(s, fmt.Sprintf("%s_%s_bucket{category=\"%s\",le=\"0.001\"} %d", namespace, name, cats[0], 0)) + s = append(s, fmt.Sprintf("%s_%s_bucket{category=\"%s\",le=\"0.005\"} %d", namespace, name, cats[0], 0)) + s = append(s, fmt.Sprintf("%s_%s_bucket{category=\"%s\",le=\"0.01\"} %d", namespace, name, cats[0], 0)) + s = append(s, fmt.Sprintf("%s_%s_bucket{category=\"%s\",le=\"0.05\"} %d", namespace, name, cats[0], 0)) + s = append(s, fmt.Sprintf("%s_%s_bucket{category=\"%s\",le=\"0.1\"} %d", namespace, name, cats[0], 0)) + s = append(s, fmt.Sprintf("%s_%s_bucket{category=\"%s\",le=\"0.5\"} %d", namespace, name, cats[0], 0)) + s = append(s, fmt.Sprintf("%s_%s_bucket{category=\"%s\",le=\"1\"} %d", namespace, name, cats[0], 1)) + s = append(s, fmt.Sprintf("%s_%s_bucket{category=\"%s\",le=\"5\"} %d", namespace, name, cats[0], 1)) + s = append(s, fmt.Sprintf("%s_%s_bucket{category=\"%s\",le=\"10\"} %d", namespace, name, cats[0], 1)) + s = append(s, fmt.Sprintf("%s_%s_bucket{category=\"%s\",le=\"+Inf\"} %d", namespace, name, cats[0], 1)) + s = append(s, fmt.Sprintf("%s_%s_sum{category=\"%s\"} %d", namespace, name, cats[0], 1)) + s = append(s, fmt.Sprintf("%s_%s_count{category=\"%s\"} %d", namespace, name, cats[0], 1)) for _, line := range s { if !strings.Contains(response.Body.String(), line) { diff --git a/go/stats/timings.go b/go/stats/timings.go index ce3cd685e72..37a662eb919 100644 --- a/go/stats/timings.go +++ b/go/stats/timings.go @@ -38,16 +38,18 @@ type Timings struct { histograms map[string]*Histogram hook func(string, time.Duration) help string + labelName string } // NewTimings creates a new Timings object, and publishes it if name is set. // categories is an optional list of categories to initialize to 0. // Categories that aren't initialized will be missing from the map until the // first time they are updated. -func NewTimings(name string, help string, categories ...string) *Timings { +func NewTimings(name, help, labelName string, categories ...string) *Timings { t := &Timings{ histograms: make(map[string]*Histogram), help: help, + labelName: labelName, } for _, cat := range categories { t.histograms[cat] = NewGenericHistogram("", bucketCutoffs, bucketLabels, "Count", "Time") @@ -160,6 +162,11 @@ func (t *Timings) Help() string { return t.help } +// LabelName returns the label name. +func (t *Timings) LabelName() string { + return t.labelName +} + var bucketCutoffs = []int64{5e5, 1e6, 5e6, 1e7, 5e7, 1e8, 5e8, 1e9, 5e9, 1e10} var bucketLabels []string diff --git a/go/stats/timings_test.go b/go/stats/timings_test.go index e5a76426269..9409cc01f7d 100644 --- a/go/stats/timings_test.go +++ b/go/stats/timings_test.go @@ -24,7 +24,7 @@ import ( func TestTimings(t *testing.T) { clear() - tm := NewTimings("timings1", "help") + tm := NewTimings("timings1", "help", "category") tm.Add("tag1", 500*time.Microsecond) tm.Add("tag1", 1*time.Millisecond) tm.Add("tag2", 1*time.Millisecond) @@ -56,7 +56,7 @@ func TestTimingsHook(t *testing.T) { }) name := "timings2" - v := NewTimings(name, "help") + v := NewTimings(name, "help", "") if gotname != name { t.Errorf("got %q, want %q", gotname, name) } diff --git a/go/vt/binlog/binlogplayer/binlog_player.go b/go/vt/binlog/binlogplayer/binlog_player.go index f972e43046f..74010a88f69 100644 --- a/go/vt/binlog/binlogplayer/binlog_player.go +++ b/go/vt/binlog/binlogplayer/binlog_player.go @@ -88,7 +88,7 @@ func (bps *Stats) GetLastPosition() mysql.Position { // NewStats creates a new Stats structure func NewStats() *Stats { bps := &Stats{} - bps.Timings = stats.NewTimings("", "") + bps.Timings = stats.NewTimings("", "", "") bps.Rates = stats.NewRates("", bps.Timings, 15, 60e9) return bps } diff --git a/go/vt/mysqlctl/fakemysqldaemon/fakemysqldaemon.go b/go/vt/mysqlctl/fakemysqldaemon/fakemysqldaemon.go index 7f2d4a76e4c..1ee21d7c057 100644 --- a/go/vt/mysqlctl/fakemysqldaemon/fakemysqldaemon.go +++ b/go/vt/mysqlctl/fakemysqldaemon/fakemysqldaemon.go @@ -146,7 +146,7 @@ func NewFakeMysqlDaemon(db *fakesqldb.DB) *FakeMysqlDaemon { } if db != nil { result.appPool = dbconnpool.NewConnectionPool("AppConnPool", 5, time.Minute) - result.appPool.Open(db.ConnParams(), stats.NewTimings("", "")) + result.appPool.Open(db.ConnParams(), stats.NewTimings("", "", "")) } return result } @@ -410,12 +410,12 @@ func (fmd *FakeMysqlDaemon) GetAppConnection(ctx context.Context) (*dbconnpool.P // GetDbaConnection is part of the MysqlDaemon interface. func (fmd *FakeMysqlDaemon) GetDbaConnection() (*dbconnpool.DBConnection, error) { - return dbconnpool.NewDBConnection(fmd.db.ConnParams(), stats.NewTimings("", "")) + return dbconnpool.NewDBConnection(fmd.db.ConnParams(), stats.NewTimings("", "", "")) } // GetAllPrivsConnection is part of the MysqlDaemon interface. func (fmd *FakeMysqlDaemon) GetAllPrivsConnection() (*dbconnpool.DBConnection, error) { - return dbconnpool.NewDBConnection(fmd.db.ConnParams(), stats.NewTimings("", "")) + return dbconnpool.NewDBConnection(fmd.db.ConnParams(), stats.NewTimings("", "", "")) } // SetSemiSyncEnabled is part of the MysqlDaemon interface. diff --git a/go/vt/mysqlctl/mysqld.go b/go/vt/mysqlctl/mysqld.go index 9902a559876..8880a568484 100644 --- a/go/vt/mysqlctl/mysqld.go +++ b/go/vt/mysqlctl/mysqld.go @@ -73,9 +73,9 @@ var ( // masterConnectRetry is used in 'SET MASTER' commands masterConnectRetry = flag.Duration("master_connect_retry", 10*time.Second, "how long to wait in between slave -> connection attempts. Only precise to the second.") - dbaMysqlStats = stats.NewTimings("MysqlDba", "MySQL DBA stats") - allprivsMysqlStats = stats.NewTimings("MysqlAllPrivs", "MySQl Stats for all privs") - appMysqlStats = stats.NewTimings("MysqlApp", "MySQL app stats") + dbaMysqlStats = stats.NewTimings("MysqlDba", "MySQL DBA stats", "operation") + allprivsMysqlStats = stats.NewTimings("MysqlAllPrivs", "MySQl Stats for all privs", "operation") + appMysqlStats = stats.NewTimings("MysqlApp", "MySQL app stats", "operation") ) // Mysqld is the object that represents a mysqld daemon running on this server. diff --git a/go/vt/vttablet/heartbeat/writer.go b/go/vt/vttablet/heartbeat/writer.go index a007e40809b..bb7b3f2a2ca 100644 --- a/go/vt/vttablet/heartbeat/writer.go +++ b/go/vt/vttablet/heartbeat/writer.go @@ -155,7 +155,7 @@ func (w *Writer) Close() { // and we also execute them with an isolated connection that turns off the binlog and // is closed at the end. func (w *Writer) initializeTables(cp *mysql.ConnParams) error { - conn, err := dbconnpool.NewDBConnection(cp, stats.NewTimings("", "")) + conn, err := dbconnpool.NewDBConnection(cp, stats.NewTimings("", "", "")) if err != nil { return fmt.Errorf("Failed to create connection for heartbeat: %v", err) } diff --git a/go/vt/vttablet/tabletmanager/rpc_external_reparent.go b/go/vt/vttablet/tabletmanager/rpc_external_reparent.go index 02f9b4dc256..63b36602aa1 100644 --- a/go/vt/vttablet/tabletmanager/rpc_external_reparent.go +++ b/go/vt/vttablet/tabletmanager/rpc_external_reparent.go @@ -39,7 +39,7 @@ import ( var ( finalizeReparentTimeout = flag.Duration("finalize_external_reparent_timeout", 30*time.Second, "Timeout for the finalize stage of a fast external reparent reconciliation.") - externalReparentStats = stats.NewTimings("ExternalReparents", "Stats from external reparentings", "NewMasterVisible", "FullRebuild") + externalReparentStats = stats.NewTimings("ExternalReparents", "External reparenting time", "stage", "NewMasterVisible", "FullRebuild") ) // SetReparentFlags changes flag values. It should only be used in tests. diff --git a/go/vt/vttablet/tabletserver/tabletenv/tabletenv.go b/go/vt/vttablet/tabletserver/tabletenv/tabletenv.go index e4803c564c8..cc65b57ce9d 100644 --- a/go/vt/vttablet/tabletserver/tabletenv/tabletenv.go +++ b/go/vt/vttablet/tabletserver/tabletenv/tabletenv.go @@ -34,13 +34,13 @@ import ( var ( // MySQLStats shows the time histogram for operations spent on mysql side. - MySQLStats = stats.NewTimings("Mysql", "MySQl query time") + MySQLStats = stats.NewTimings("Mysql", "MySQl query time", "operation") // QueryStats shows the time histogram for each type of queries. - QueryStats = stats.NewTimings("Queries", "MySQL query timings") + QueryStats = stats.NewTimings("Queries", "MySQL query timings", "plan_type") // QPSRates shows the qps of QueryStats. Sample every 5 seconds and keep samples for up to 15 mins. QPSRates = stats.NewRates("QPS", QueryStats, 15*60/5, 5*time.Second) // WaitStats shows the time histogram for wait operations - WaitStats = stats.NewTimings("Waits", "Wait operations") + WaitStats = stats.NewTimings("Waits", "Wait operations", "type") // KillStats shows number of connections being killed. KillStats = stats.NewCountersWithSingleLabel("Kills", "Number of connections being killed", "query_type", "Transactions", "Queries") // ErrorStats shows number of critial errors happened. diff --git a/go/vt/vttablet/tabletserver/twopc.go b/go/vt/vttablet/tabletserver/twopc.go index b9cb2bfb10c..f1d67496e8d 100644 --- a/go/vt/vttablet/tabletserver/twopc.go +++ b/go/vt/vttablet/tabletserver/twopc.go @@ -130,7 +130,7 @@ func NewTwoPC(readPool *connpool.Pool) *TwoPC { // are not present, they are created. func (tpc *TwoPC) Init(sidecarDBName string, dbaparams *mysql.ConnParams) error { dbname := sqlescape.EscapeID(sidecarDBName) - conn, err := dbconnpool.NewDBConnection(dbaparams, stats.NewTimings("", "")) + conn, err := dbconnpool.NewDBConnection(dbaparams, stats.NewTimings("", "", "")) if err != nil { return err } diff --git a/go/vt/vttablet/tabletserver/tx_pool.go b/go/vt/vttablet/tabletserver/tx_pool.go index 55bb730ea83..8d610becb6d 100644 --- a/go/vt/vttablet/tabletserver/tx_pool.go +++ b/go/vt/vttablet/tabletserver/tx_pool.go @@ -56,7 +56,7 @@ const txLogInterval = time.Duration(1 * time.Minute) var ( txOnce sync.Once - txStats = stats.NewTimings("Transactions", "Transaction stats") + txStats = stats.NewTimings("Transactions", "Transaction stats", "operation") txIsolations = map[querypb.ExecuteOptions_TransactionIsolation]string{ querypb.ExecuteOptions_REPEATABLE_READ: "set transaction isolation level REPEATABLE READ", From 066e88eabc8a3ed180651159fe3f1ce5736a403e Mon Sep 17 00:00:00 2001 From: Michael Demmer Date: Mon, 30 Apr 2018 14:39:26 -0700 Subject: [PATCH 31/41] add prometheus support for stats.NewHistogram Signed-off-by: Michael Demmer --- go/stats/histogram.go | 19 +++++- go/stats/histogram_test.go | 5 +- go/stats/prometheusbackend/collectors.go | 58 ++++++++++++++++--- .../prometheusbackend/prometheusbackend.go | 16 ++++- .../prometheusbackend_test.go | 23 ++++++++ go/stats/timings.go | 4 +- .../tabletserver/tabletenv/tabletenv.go | 4 +- 7 files changed, 110 insertions(+), 19 deletions(-) diff --git a/go/stats/histogram.go b/go/stats/histogram.go index 993f321a74a..b12f3235ff3 100644 --- a/go/stats/histogram.go +++ b/go/stats/histogram.go @@ -27,6 +27,8 @@ import ( // splitting the counts under different buckets // using specified cutoffs. type Histogram struct { + help string + labelName string cutoffs []int64 labels []string countLabel string @@ -41,24 +43,25 @@ type Histogram struct { // based on the cutoffs. The buckets are categorized using the // following criterion: cutoff[i-1] < value <= cutoff[i]. Anything // higher than the highest cutoff is labeled as "inf". -func NewHistogram(name string, cutoffs []int64) *Histogram { +func NewHistogram(name, help string, cutoffs []int64) *Histogram { labels := make([]string, len(cutoffs)+1) for i, v := range cutoffs { labels[i] = fmt.Sprintf("%d", v) } labels[len(labels)-1] = "inf" - return NewGenericHistogram(name, cutoffs, labels, "Count", "Total") + return NewGenericHistogram(name, help, cutoffs, labels, "Count", "Total") } // NewGenericHistogram creates a histogram where all the labels are // supplied by the caller. The number of labels has to be one more than // the number of cutoffs because the last label captures everything that // exceeds the highest cutoff. -func NewGenericHistogram(name string, cutoffs []int64, labels []string, countLabel, totalLabel string) *Histogram { +func NewGenericHistogram(name, help string, cutoffs []int64, labels []string, countLabel, totalLabel string) *Histogram { if len(cutoffs) != len(labels)-1 { panic("mismatched cutoff and label lengths") } h := &Histogram{ + help: help, cutoffs: cutoffs, labels: labels, countLabel: countLabel, @@ -160,3 +163,13 @@ func (h *Histogram) Buckets() []int64 { } return buckets } + +// Help returns the help string. +func (h *Histogram) Help() string { + return h.help +} + +// LabelName returns the label name. +func (h *Histogram) LabelName() string { + return h.labelName +} diff --git a/go/stats/histogram_test.go b/go/stats/histogram_test.go index f0cb07105ed..a0e577e79fe 100644 --- a/go/stats/histogram_test.go +++ b/go/stats/histogram_test.go @@ -23,7 +23,7 @@ import ( func TestHistogram(t *testing.T) { clear() - h := NewHistogram("hist1", []int64{1, 5}) + h := NewHistogram("hist1", "desc1", []int64{1, 5}) for i := 0; i < 10; i++ { h.Add(int64(i)) } @@ -57,6 +57,7 @@ func TestGenericHistogram(t *testing.T) { clear() h := NewGenericHistogram( "histgen", + "generic histogram", []int64{1, 5}, []string{"one", "five", "max"}, "count", @@ -78,7 +79,7 @@ func TestHistogramHook(t *testing.T) { }) name := "hist2" - v := NewHistogram(name, []int64{1}) + v := NewHistogram(name, "", []int64{1}) if gotname != name { t.Errorf("got %v; want %v", gotname, name) } diff --git a/go/stats/prometheusbackend/collectors.go b/go/stats/prometheusbackend/collectors.go index 9cc2254bcf3..b48d9f967cb 100644 --- a/go/stats/prometheusbackend/collectors.go +++ b/go/stats/prometheusbackend/collectors.go @@ -129,8 +129,9 @@ func (c *metricsFuncWithMultiLabelsCollector) Collect(ch chan<- prometheus.Metri } type timingsCollector struct { - t *stats.Timings - desc *prometheus.Desc + t *stats.Timings + cutoffs []float64 + desc *prometheus.Desc } // Describe implements Collector. @@ -145,16 +146,15 @@ func (c *timingsCollector) Collect(ch chan<- prometheus.Metric) { c.desc, uint64(his.Count()), float64(his.Total()), - makePromBucket(his.Cutoffs(), his.Buckets()), + makeCumulativeBuckets(c.cutoffs, his.Buckets()), cat) } } -func makePromBucket(cutoffs []int64, buckets []int64) map[float64]uint64 { +func makeCumulativeBuckets(cutoffs []float64, buckets []int64) map[float64]uint64 { output := make(map[float64]uint64) last := uint64(0) - for i := range cutoffs { - key := float64(cutoffs[i]) / 1000000000 + for i, key := range cutoffs { //TODO(zmagg): int64 => uint64 conversion. error if it overflows? output[key] = uint64(buckets[i]) + last last = output[key] @@ -163,8 +163,9 @@ func makePromBucket(cutoffs []int64, buckets []int64) map[float64]uint64 { } type multiTimingsCollector struct { - mt *stats.MultiTimings - desc *prometheus.Desc + mt *stats.MultiTimings + cutoffs []float64 + desc *prometheus.Desc } // Describe implements Collector. @@ -180,7 +181,46 @@ func (c *multiTimingsCollector) Collect(ch chan<- prometheus.Metric) { c.desc, uint64(his.Count()), float64(his.Total()), - makePromBucket(his.Cutoffs(), his.Buckets()), + makeCumulativeBuckets(c.cutoffs, his.Buckets()), labelValues...) } } + +type histogramCollector struct { + h *stats.Histogram + cutoffs []float64 + desc *prometheus.Desc +} + +func newHistogramCollector(h *stats.Histogram, name string) { + collector := &histogramCollector{ + h: h, + cutoffs: make([]float64, len(h.Cutoffs())), + desc: prometheus.NewDesc( + name, + h.Help(), + []string{}, + nil), + } + + for i, val := range h.Cutoffs() { + collector.cutoffs[i] = float64(val) + } + + prometheus.MustRegister(collector) +} + +// Describe implements Collector. +func (c *histogramCollector) Describe(ch chan<- *prometheus.Desc) { + ch <- c.desc +} + +// Collect implements Collector. +func (c *histogramCollector) Collect(ch chan<- prometheus.Metric) { + ch <- prometheus.MustNewConstHistogram( + c.desc, + uint64(c.h.Count()), + float64(c.h.Total()), + makeCumulativeBuckets(c.cutoffs, c.h.Buckets()), + ) +} diff --git a/go/stats/prometheusbackend/prometheusbackend.go b/go/stats/prometheusbackend/prometheusbackend.go index 1bfb822f05b..bbe00dca82d 100644 --- a/go/stats/prometheusbackend/prometheusbackend.go +++ b/go/stats/prometheusbackend/prometheusbackend.go @@ -65,6 +65,8 @@ func (be *PromBackend) publishPrometheusMetric(name string, v expvar.Var) { be.newTiming(st, name) case *stats.MultiTimings: be.newMultiTiming(st, name) + case *stats.Histogram: + newHistogramCollector(st, be.buildPromName(name)) default: logUnsupported.Infof("Not exporting to Prometheus an unsupported metric type of %T: %s", st, name) } @@ -138,7 +140,8 @@ func (be *PromBackend) newMetricsFuncWithMultiLabels(cfml *stats.CountersFuncWit func (be *PromBackend) newTiming(t *stats.Timings, name string) { collector := &timingsCollector{ - t: t, + t: t, + cutoffs: make([]float64, len(t.Cutoffs())), desc: prometheus.NewDesc( be.buildPromName(name), t.Help(), @@ -146,12 +149,17 @@ func (be *PromBackend) newTiming(t *stats.Timings, name string) { nil), } + for i, val := range t.Cutoffs() { + collector.cutoffs[i] = float64(val) / 1000000000 + } + prometheus.MustRegister(collector) } func (be *PromBackend) newMultiTiming(mt *stats.MultiTimings, name string) { collector := &multiTimingsCollector{ - mt: mt, + mt: mt, + cutoffs: make([]float64, len(mt.Cutoffs())), desc: prometheus.NewDesc( be.buildPromName(name), mt.Help(), @@ -159,6 +167,10 @@ func (be *PromBackend) newMultiTiming(mt *stats.MultiTimings, name string) { nil), } + for i, val := range mt.Cutoffs() { + collector.cutoffs[i] = float64(val) / 1000000000 + } + prometheus.MustRegister(collector) } diff --git a/go/stats/prometheusbackend/prometheusbackend_test.go b/go/stats/prometheusbackend/prometheusbackend_test.go index 61f5dbe12f9..354202c9d97 100644 --- a/go/stats/prometheusbackend/prometheusbackend_test.go +++ b/go/stats/prometheusbackend/prometheusbackend_test.go @@ -290,6 +290,29 @@ func TestPrometheusMultiTimings_PanicWrongLength(t *testing.T) { c.Add([]string{"label1"}, time.Duration(100000000)) } +func TestPrometheusHistogram(t *testing.T) { + name := "blah_hist" + hist := stats.NewHistogram(name, "help", []int64{1, 5, 10}) + hist.Add(2) + hist.Add(3) + hist.Add(6) + + response := testMetricsHandler(t) + var s []string + + s = append(s, fmt.Sprintf("%s_%s_bucket{le=\"1\"} %d", namespace, name, 0)) + s = append(s, fmt.Sprintf("%s_%s_bucket{le=\"5\"} %d", namespace, name, 2)) + s = append(s, fmt.Sprintf("%s_%s_bucket{le=\"10\"} %d", namespace, name, 3)) + s = append(s, fmt.Sprintf("%s_%s_sum %d", namespace, name, 1)) + s = append(s, fmt.Sprintf("%s_%s_count %d", namespace, name, 3)) + + for _, line := range s { + if !strings.Contains(response.Body.String(), line) { + t.Fatalf("Expected result to contain %s, got %s", line, response.Body.String()) + } + } +} + func testMetricsHandler(t *testing.T) *httptest.ResponseRecorder { req, _ := http.NewRequest("GET", "/metrics", nil) response := httptest.NewRecorder() diff --git a/go/stats/timings.go b/go/stats/timings.go index 37a662eb919..1077b4b7db2 100644 --- a/go/stats/timings.go +++ b/go/stats/timings.go @@ -52,7 +52,7 @@ func NewTimings(name, help, labelName string, categories ...string) *Timings { labelName: labelName, } for _, cat := range categories { - t.histograms[cat] = NewGenericHistogram("", bucketCutoffs, bucketLabels, "Count", "Time") + t.histograms[cat] = NewGenericHistogram("", "", bucketCutoffs, bucketLabels, "Count", "Time") } if name != "" { publish(name, t) @@ -74,7 +74,7 @@ func (t *Timings) Add(name string, elapsed time.Duration) { t.mu.Lock() hist, ok = t.histograms[name] if !ok { - hist = NewGenericHistogram("", bucketCutoffs, bucketLabels, "Count", "Time") + hist = NewGenericHistogram("", "", bucketCutoffs, bucketLabels, "Count", "Time") t.histograms[name] = hist } t.mu.Unlock() diff --git a/go/vt/vttablet/tabletserver/tabletenv/tabletenv.go b/go/vt/vttablet/tabletserver/tabletenv/tabletenv.go index cc65b57ce9d..0fd1dfc774b 100644 --- a/go/vt/vttablet/tabletserver/tabletenv/tabletenv.go +++ b/go/vt/vttablet/tabletserver/tabletenv/tabletenv.go @@ -93,7 +93,9 @@ var ( "Total transaction latency for each CallerID", []string{"CallerID", "Conclusion"}) // ResultStats shows the histogram of number of rows returned. - ResultStats = stats.NewHistogram("Results", []int64{0, 1, 5, 10, 50, 100, 500, 1000, 5000, 10000}) + ResultStats = stats.NewHistogram("Results", + "Distribution of rows returned", + []int64{0, 1, 5, 10, 50, 100, 500, 1000, 5000, 10000}) // TableaclAllowed tracks the number allows. TableaclAllowed = stats.NewCountersWithMultiLabels( "TableACLAllowed", From 507655b5cc828401db0102d627a5f22441032f21 Mon Sep 17 00:00:00 2001 From: Michael Demmer Date: Mon, 30 Apr 2018 15:02:25 -0700 Subject: [PATCH 32/41] reorganize all the collector instantiation functions Move the various newXYZ functions from prometheusbackend.go into collectors.go so that the constructor function lives alongside the struct definition itself. As part of this rename the various functions so the constructor function name matches the struct name. Signed-off-by: Michael Demmer --- go/stats/prometheusbackend/collectors.go | 121 +++++++++++++- .../prometheusbackend/prometheusbackend.go | 147 ++---------------- 2 files changed, 134 insertions(+), 134 deletions(-) diff --git a/go/stats/prometheusbackend/collectors.go b/go/stats/prometheusbackend/collectors.go index b48d9f967cb..c261b2169d9 100644 --- a/go/stats/prometheusbackend/collectors.go +++ b/go/stats/prometheusbackend/collectors.go @@ -14,6 +14,19 @@ type metricFuncCollector struct { vt prometheus.ValueType } +func newMetricFuncCollector(v stats.Variable, name string, vt prometheus.ValueType, f func() float64) { + collector := &metricFuncCollector{ + f: f, + desc: prometheus.NewDesc( + name, + v.Help(), + nil, + nil), + vt: vt} + + prometheus.MustRegister(collector) +} + // Describe implements Collector. func (mc *metricFuncCollector) Describe(ch chan<- *prometheus.Desc) { ch <- mc.desc @@ -31,6 +44,19 @@ type countersWithSingleLabelCollector struct { vt prometheus.ValueType } +func newCountersWithSingleLabelCollector(c *stats.CountersWithSingleLabel, name string, labelName string, vt prometheus.ValueType) { + collector := &countersWithSingleLabelCollector{ + counters: c, + desc: prometheus.NewDesc( + name, + c.Help(), + []string{labelName}, + nil), + vt: vt} + + prometheus.MustRegister(collector) +} + // Describe implements Collector. func (c *countersWithSingleLabelCollector) Describe(ch chan<- *prometheus.Desc) { ch <- c.desc @@ -54,6 +80,19 @@ type gaugesWithSingleLabelCollector struct { vt prometheus.ValueType } +func newGaugesWithSingleLabelCollector(g *stats.GaugesWithSingleLabel, name string, labelName string, vt prometheus.ValueType) { + collector := &gaugesWithSingleLabelCollector{ + gauges: g, + desc: prometheus.NewDesc( + name, + g.Help(), + []string{labelName}, + nil), + vt: vt} + + prometheus.MustRegister(collector) +} + // Describe implements Collector. func (g *gaugesWithSingleLabelCollector) Describe(ch chan<- *prometheus.Desc) { ch <- g.desc @@ -75,6 +114,19 @@ type metricWithMultiLabelsCollector struct { desc *prometheus.Desc } +func newMetricWithMultiLabelsCollector(cml *stats.CountersWithMultiLabels, name string) { + c := &metricWithMultiLabelsCollector{ + cml: cml, + desc: prometheus.NewDesc( + name, + cml.Help(), + labelsToSnake(cml.Labels()), + nil), + } + + prometheus.MustRegister(c) +} + // Describe implements Collector. func (c *metricWithMultiLabelsCollector) Describe(ch chan<- *prometheus.Desc) { ch <- c.desc @@ -89,18 +141,31 @@ func (c *metricWithMultiLabelsCollector) Collect(ch chan<- prometheus.Metric) { } } -type multiGaugesCollector struct { +type gaugesWithMultiLabelsCollector struct { gml *stats.GaugesWithMultiLabels desc *prometheus.Desc } +func newGaugesWithMultiLabelsCollector(gml *stats.GaugesWithMultiLabels, name string) { + c := &gaugesWithMultiLabelsCollector{ + gml: gml, + desc: prometheus.NewDesc( + name, + gml.Help(), + labelsToSnake(gml.Labels()), + nil), + } + + prometheus.MustRegister(c) +} + // Describe implements Collector. -func (c *multiGaugesCollector) Describe(ch chan<- *prometheus.Desc) { +func (c *gaugesWithMultiLabelsCollector) Describe(ch chan<- *prometheus.Desc) { ch <- c.desc } // Collect implements Collector. -func (c *multiGaugesCollector) Collect(ch chan<- prometheus.Metric) { +func (c *gaugesWithMultiLabelsCollector) Collect(ch chan<- prometheus.Metric) { for lvs, val := range c.gml.Counts() { labelValues := strings.Split(lvs, ".") value := float64(val) @@ -114,6 +179,20 @@ type metricsFuncWithMultiLabelsCollector struct { vt prometheus.ValueType } +func newMetricsFuncWithMultiLabelsCollector(cfml *stats.CountersFuncWithMultiLabels, name string, vt prometheus.ValueType) { + collector := &metricsFuncWithMultiLabelsCollector{ + cfml: cfml, + desc: prometheus.NewDesc( + name, + cfml.Help(), + labelsToSnake(cfml.Labels()), + nil), + vt: vt, + } + + prometheus.MustRegister(collector) +} + // Describe implements Collector. func (c *metricsFuncWithMultiLabelsCollector) Describe(ch chan<- *prometheus.Desc) { ch <- c.desc @@ -134,6 +213,24 @@ type timingsCollector struct { desc *prometheus.Desc } +func newTimingsCollector(t *stats.Timings, name string) { + collector := &timingsCollector{ + t: t, + cutoffs: make([]float64, len(t.Cutoffs())), + desc: prometheus.NewDesc( + name, + t.Help(), + []string{t.LabelName()}, + nil), + } + + for i, val := range t.Cutoffs() { + collector.cutoffs[i] = float64(val) / 1000000000 + } + + prometheus.MustRegister(collector) +} + // Describe implements Collector. func (c *timingsCollector) Describe(ch chan<- *prometheus.Desc) { ch <- c.desc @@ -168,6 +265,24 @@ type multiTimingsCollector struct { desc *prometheus.Desc } +func newMultiTimingsCollector(mt *stats.MultiTimings, name string) { + collector := &multiTimingsCollector{ + mt: mt, + cutoffs: make([]float64, len(mt.Cutoffs())), + desc: prometheus.NewDesc( + name, + mt.Help(), + labelsToSnake(mt.Labels()), + nil), + } + + for i, val := range mt.Cutoffs() { + collector.cutoffs[i] = float64(val) / 1000000000 + } + + prometheus.MustRegister(collector) +} + // Describe implements Collector. func (c *multiTimingsCollector) Describe(ch chan<- *prometheus.Desc) { ch <- c.desc diff --git a/go/stats/prometheusbackend/prometheusbackend.go b/go/stats/prometheusbackend/prometheusbackend.go index bbe00dca82d..500f1b60476 100644 --- a/go/stats/prometheusbackend/prometheusbackend.go +++ b/go/stats/prometheusbackend/prometheusbackend.go @@ -34,37 +34,37 @@ func Init(namespace string) { func (be *PromBackend) publishPrometheusMetric(name string, v expvar.Var) { switch st := v.(type) { case *stats.Counter: - be.newMetric(st, name, prometheus.CounterValue, func() float64 { return float64(st.Get()) }) + newMetricFuncCollector(st, be.buildPromName(name), prometheus.CounterValue, func() float64 { return float64(st.Get()) }) case *stats.CounterFunc: - be.newMetric(st, name, prometheus.CounterValue, func() float64 { return float64(st.F()) }) + newMetricFuncCollector(st, be.buildPromName(name), prometheus.CounterValue, func() float64 { return float64(st.F()) }) case *stats.Gauge: - be.newMetric(st, name, prometheus.GaugeValue, func() float64 { return float64(st.Get()) }) + newMetricFuncCollector(st, be.buildPromName(name), prometheus.GaugeValue, func() float64 { return float64(st.Get()) }) case *stats.GaugeFunc: - be.newMetric(st, name, prometheus.GaugeValue, func() float64 { return float64(st.F()) }) + newMetricFuncCollector(st, be.buildPromName(name), prometheus.GaugeValue, func() float64 { return float64(st.F()) }) case *stats.CountersWithSingleLabel: - be.newCountersWithSingleLabel(st, name, st.Label(), prometheus.CounterValue) + newCountersWithSingleLabelCollector(st, be.buildPromName(name), st.Label(), prometheus.CounterValue) case *stats.CountersWithMultiLabels: - be.newCountersWithMultiLabels(st, name) + newMetricWithMultiLabelsCollector(st, be.buildPromName(name)) case *stats.CountersFuncWithMultiLabels: - be.newMetricsFuncWithMultiLabels(st, name, prometheus.CounterValue) + newMetricsFuncWithMultiLabelsCollector(st, be.buildPromName(name), prometheus.CounterValue) case *stats.GaugesFuncWithMultiLabels: - be.newMetricsFuncWithMultiLabels(&st.CountersFuncWithMultiLabels, name, prometheus.GaugeValue) + newMetricsFuncWithMultiLabelsCollector(&st.CountersFuncWithMultiLabels, be.buildPromName(name), prometheus.GaugeValue) case *stats.GaugesWithSingleLabel: - be.newGaugesWithSingleLabel(st, name, st.Label(), prometheus.GaugeValue) + newGaugesWithSingleLabelCollector(st, be.buildPromName(name), st.Label(), prometheus.GaugeValue) case *stats.GaugesWithMultiLabels: - be.newGaugesWithMultiLabels(st, name) + newGaugesWithMultiLabelsCollector(st, be.buildPromName(name)) case *stats.CounterDuration: - be.newMetric(st, name, prometheus.CounterValue, func() float64 { return st.Get().Seconds() }) + newMetricFuncCollector(st, be.buildPromName(name), prometheus.CounterValue, func() float64 { return st.Get().Seconds() }) case *stats.CounterDurationFunc: - be.newMetric(st, name, prometheus.CounterValue, func() float64 { return st.F().Seconds() }) + newMetricFuncCollector(st, be.buildPromName(name), prometheus.CounterValue, func() float64 { return st.F().Seconds() }) case *stats.GaugeDuration: - be.newMetric(st, name, prometheus.GaugeValue, func() float64 { return st.Get().Seconds() }) + newMetricFuncCollector(st, be.buildPromName(name), prometheus.GaugeValue, func() float64 { return st.Get().Seconds() }) case *stats.GaugeDurationFunc: - be.newMetric(st, name, prometheus.GaugeValue, func() float64 { return st.F().Seconds() }) + newMetricFuncCollector(st, be.buildPromName(name), prometheus.GaugeValue, func() float64 { return st.F().Seconds() }) case *stats.Timings: - be.newTiming(st, name) + newTimingsCollector(st, be.buildPromName(name)) case *stats.MultiTimings: - be.newMultiTiming(st, name) + newMultiTimingsCollector(st, be.buildPromName(name)) case *stats.Histogram: newHistogramCollector(st, be.buildPromName(name)) default: @@ -72,121 +72,6 @@ func (be *PromBackend) publishPrometheusMetric(name string, v expvar.Var) { } } -func (be *PromBackend) newCountersWithSingleLabel(c *stats.CountersWithSingleLabel, name string, labelName string, vt prometheus.ValueType) { - collector := &countersWithSingleLabelCollector{ - counters: c, - desc: prometheus.NewDesc( - be.buildPromName(name), - c.Help(), - []string{labelName}, - nil), - vt: vt} - - prometheus.MustRegister(collector) -} - -func (be *PromBackend) newGaugesWithSingleLabel(g *stats.GaugesWithSingleLabel, name string, labelName string, vt prometheus.ValueType) { - collector := &gaugesWithSingleLabelCollector{ - gauges: g, - desc: prometheus.NewDesc( - be.buildPromName(name), - g.Help(), - []string{labelName}, - nil), - vt: vt} - - prometheus.MustRegister(collector) -} - -func (be *PromBackend) newCountersWithMultiLabels(cml *stats.CountersWithMultiLabels, name string) { - c := &metricWithMultiLabelsCollector{ - cml: cml, - desc: prometheus.NewDesc( - be.buildPromName(name), - cml.Help(), - labelsToSnake(cml.Labels()), - nil), - } - - prometheus.MustRegister(c) -} - -func (be *PromBackend) newGaugesWithMultiLabels(gml *stats.GaugesWithMultiLabels, name string) { - c := &multiGaugesCollector{ - gml: gml, - desc: prometheus.NewDesc( - be.buildPromName(name), - gml.Help(), - labelsToSnake(gml.Labels()), - nil), - } - - prometheus.MustRegister(c) -} - -func (be *PromBackend) newMetricsFuncWithMultiLabels(cfml *stats.CountersFuncWithMultiLabels, name string, vt prometheus.ValueType) { - collector := &metricsFuncWithMultiLabelsCollector{ - cfml: cfml, - desc: prometheus.NewDesc( - be.buildPromName(name), - cfml.Help(), - labelsToSnake(cfml.Labels()), - nil), - vt: vt, - } - - prometheus.MustRegister(collector) -} - -func (be *PromBackend) newTiming(t *stats.Timings, name string) { - collector := &timingsCollector{ - t: t, - cutoffs: make([]float64, len(t.Cutoffs())), - desc: prometheus.NewDesc( - be.buildPromName(name), - t.Help(), - []string{t.LabelName()}, - nil), - } - - for i, val := range t.Cutoffs() { - collector.cutoffs[i] = float64(val) / 1000000000 - } - - prometheus.MustRegister(collector) -} - -func (be *PromBackend) newMultiTiming(mt *stats.MultiTimings, name string) { - collector := &multiTimingsCollector{ - mt: mt, - cutoffs: make([]float64, len(mt.Cutoffs())), - desc: prometheus.NewDesc( - be.buildPromName(name), - mt.Help(), - labelsToSnake(mt.Labels()), - nil), - } - - for i, val := range mt.Cutoffs() { - collector.cutoffs[i] = float64(val) / 1000000000 - } - - prometheus.MustRegister(collector) -} - -func (be *PromBackend) newMetric(v stats.Variable, name string, vt prometheus.ValueType, f func() float64) { - collector := &metricFuncCollector{ - f: f, - desc: prometheus.NewDesc( - be.buildPromName(name), - v.Help(), - nil, - nil), - vt: vt} - - prometheus.MustRegister(collector) -} - // buildPromName specifies the namespace as a prefix to the metric name func (be *PromBackend) buildPromName(name string) string { s := strings.TrimPrefix(normalizeMetric(name), be.namespace+"_") From fd7b5f84b22691fefeb4b6cc464ad0828fab1e5b Mon Sep 17 00:00:00 2001 From: Michael Demmer Date: Mon, 30 Apr 2018 15:13:05 -0700 Subject: [PATCH 33/41] use a singleton struct instead of a pointer Signed-off-by: Michael Demmer --- go/stats/prometheusbackend/prometheusbackend.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/go/stats/prometheusbackend/prometheusbackend.go b/go/stats/prometheusbackend/prometheusbackend.go index 500f1b60476..00a3b55222b 100644 --- a/go/stats/prometheusbackend/prometheusbackend.go +++ b/go/stats/prometheusbackend/prometheusbackend.go @@ -18,20 +18,20 @@ type PromBackend struct { } var ( - be *PromBackend + be PromBackend logUnsupported *logutil.ThrottledLogger ) // Init initializes the Prometheus be with the given namespace. func Init(namespace string) { http.Handle("/metrics", promhttp.Handler()) - be := &PromBackend{namespace: namespace} + be.namespace = namespace logUnsupported = logutil.NewThrottledLogger("PrometheusUnsupportedMetricType", 1*time.Minute) stats.Register(be.publishPrometheusMetric) } // PublishPromMetric is used to publish the metric to Prometheus. -func (be *PromBackend) publishPrometheusMetric(name string, v expvar.Var) { +func (be PromBackend) publishPrometheusMetric(name string, v expvar.Var) { switch st := v.(type) { case *stats.Counter: newMetricFuncCollector(st, be.buildPromName(name), prometheus.CounterValue, func() float64 { return float64(st.Get()) }) @@ -73,7 +73,7 @@ func (be *PromBackend) publishPrometheusMetric(name string, v expvar.Var) { } // buildPromName specifies the namespace as a prefix to the metric name -func (be *PromBackend) buildPromName(name string) string { +func (be PromBackend) buildPromName(name string) string { s := strings.TrimPrefix(normalizeMetric(name), be.namespace+"_") return prometheus.BuildFQName("", be.namespace, s) } From cafbca845d03360f86f2372471bf542c675d621d Mon Sep 17 00:00:00 2001 From: Michael Demmer Date: Mon, 30 Apr 2018 17:06:58 -0700 Subject: [PATCH 34/41] include the connection id as part of the mysql conn error logs When troubleshooting some production issues, we noticed the slow query killer running on a couple of connections and around the same time ran into some "broken pipe" errors on the local unix socket. While it seems likely that the query killer caused the broken pipe errors, including the connection ID in both logs would help to identify this more reliably. Signed-off-by: Michael Demmer --- go/mysql/conn.go | 14 +++++++------- go/vt/vttablet/tabletserver/connpool/dbconn.go | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/go/mysql/conn.go b/go/mysql/conn.go index 343021eb344..183ae00a80e 100644 --- a/go/mysql/conn.go +++ b/go/mysql/conn.go @@ -579,31 +579,31 @@ func (c *Conn) writeEphemeralPacket(direct bool) error { // Just write c.buffer as a single buffer. // It has both header and data. if n, err := w.Write(c.buffer); err != nil { - return fmt.Errorf("Write(c.buffer) failed: %v", err) + return fmt.Errorf("Conn %v: Write(c.buffer) failed: %v", c.ID(), err) } else if n != len(c.buffer) { - return fmt.Errorf("Write(c.buffer) returned a short write: %v < %v", n, len(c.buffer)) + return fmt.Errorf("Conn %v: Write(c.buffer) returned a short write: %v < %v", c.ID(), n, len(c.buffer)) } case ephemeralWriteSingleBuffer: // Write the allocated buffer as a single buffer. // It has both header and data. if n, err := w.Write(c.currentEphemeralPacket); err != nil { - return fmt.Errorf("Write(c.currentEphemeralPacket) failed: %v", err) + return fmt.Errorf("Conn %v: Write(c.currentEphemeralPacket) failed: %v", c.ID(), err) } else if n != len(c.currentEphemeralPacket) { - return fmt.Errorf("Write(c.currentEphemeralPacket) returned a short write: %v < %v", n, len(c.currentEphemeralPacket)) + return fmt.Errorf("Conn %v: Write(c.currentEphemeralPacket) returned a short write: %v < %v", c.ID(), n, len(c.currentEphemeralPacket)) } case ephemeralWriteBigBuffer: // This is the slower path for big data. // With direct=true, the caller expects a flush, so we call it // manually. if err := c.writePacket(c.currentEphemeralPacket); err != nil { - return err + return fmt.Errorf("Conn %v: %v", c.ID(), err) } if direct { return c.flush() } case ephemeralUnused, ephemeralReadGlobalBuffer, ephemeralReadSingleBuffer, ephemeralReadBigBuffer: // Programming error. - panic(fmt.Errorf("trying to call writeEphemeralPacket while currentEphemeralPolicy is %v", c.currentEphemeralPolicy)) + panic(fmt.Errorf("Conn %v: trying to call writeEphemeralPacket while currentEphemeralPolicy is %v", c.ID(), c.currentEphemeralPolicy)) } return nil @@ -613,7 +613,7 @@ func (c *Conn) writeEphemeralPacket(direct bool) error { // This method returns a generic error, not a SQLError. func (c *Conn) flush() error { if err := c.writer.Flush(); err != nil { - return fmt.Errorf("Flush() failed: %v", err) + return fmt.Errorf("Conn %v: Flush() failed: %v", c.ID(), err) } return nil } diff --git a/go/vt/vttablet/tabletserver/connpool/dbconn.go b/go/vt/vttablet/tabletserver/connpool/dbconn.go index e36b0fce386..5228289ffcc 100644 --- a/go/vt/vttablet/tabletserver/connpool/dbconn.go +++ b/go/vt/vttablet/tabletserver/connpool/dbconn.go @@ -304,7 +304,7 @@ func (dbc *DBConn) Recycle() { // Kill will also not kill a query more than once. func (dbc *DBConn) Kill(reason string, elapsed time.Duration) error { tabletenv.KillStats.Add("Queries", 1) - log.Infof("Due to %s, elapsed time: %v, killing query %s", reason, elapsed, dbc.Current()) + log.Infof("Due to %s, elapsed time: %v, killing query ID %v %s", reason, elapsed, dbc.conn.ID(), dbc.Current()) killConn, err := dbc.dbaPool.Get(context.TODO()) if err != nil { log.Warningf("Failed to get conn from dba pool: %v", err) @@ -314,7 +314,7 @@ func (dbc *DBConn) Kill(reason string, elapsed time.Duration) error { sql := fmt.Sprintf("kill %d", dbc.conn.ID()) _, err = killConn.ExecuteFetch(sql, 10000, false) if err != nil { - log.Errorf("Could not kill query %s: %v", dbc.Current(), err) + log.Errorf("Could not kill query ID %v %s: %v", dbc.conn.ID(), dbc.Current(), err) return err } return nil From f86ede172f3e7431e7271b6e82f7554c6620ab60 Mon Sep 17 00:00:00 2001 From: Michael Demmer Date: Mon, 30 Apr 2018 17:10:42 -0700 Subject: [PATCH 35/41] use "help" uniformly as suggested in PR review Signed-off-by: Michael Demmer --- go/stats/histogram_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/go/stats/histogram_test.go b/go/stats/histogram_test.go index a0e577e79fe..91e340b3b29 100644 --- a/go/stats/histogram_test.go +++ b/go/stats/histogram_test.go @@ -23,7 +23,7 @@ import ( func TestHistogram(t *testing.T) { clear() - h := NewHistogram("hist1", "desc1", []int64{1, 5}) + h := NewHistogram("hist1", "help", []int64{1, 5}) for i := 0; i < 10; i++ { h.Add(int64(i)) } @@ -57,7 +57,7 @@ func TestGenericHistogram(t *testing.T) { clear() h := NewGenericHistogram( "histgen", - "generic histogram", + "help", []int64{1, 5}, []string{"one", "five", "max"}, "count", @@ -79,7 +79,7 @@ func TestHistogramHook(t *testing.T) { }) name := "hist2" - v := NewHistogram(name, "", []int64{1}) + v := NewHistogram(name, "help", []int64{1}) if gotname != name { t.Errorf("got %v; want %v", gotname, name) } From 86a27284ebec0ad0df8d1b64ef15f0358feff03d Mon Sep 17 00:00:00 2001 From: Michael Demmer Date: Mon, 30 Apr 2018 17:12:34 -0700 Subject: [PATCH 36/41] use Label() instead of LabelName() As suggested in PR review this brings Timings in line with the naming used by the various Counter types. Signed-off-by: Michael Demmer --- go/stats/prometheusbackend/collectors.go | 2 +- go/stats/timings.go | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/go/stats/prometheusbackend/collectors.go b/go/stats/prometheusbackend/collectors.go index c261b2169d9..c7f7ad4834a 100644 --- a/go/stats/prometheusbackend/collectors.go +++ b/go/stats/prometheusbackend/collectors.go @@ -220,7 +220,7 @@ func newTimingsCollector(t *stats.Timings, name string) { desc: prometheus.NewDesc( name, t.Help(), - []string{t.LabelName()}, + []string{t.Label()}, nil), } diff --git a/go/stats/timings.go b/go/stats/timings.go index 1077b4b7db2..8ec33a842bd 100644 --- a/go/stats/timings.go +++ b/go/stats/timings.go @@ -38,18 +38,18 @@ type Timings struct { histograms map[string]*Histogram hook func(string, time.Duration) help string - labelName string + label string } // NewTimings creates a new Timings object, and publishes it if name is set. // categories is an optional list of categories to initialize to 0. // Categories that aren't initialized will be missing from the map until the // first time they are updated. -func NewTimings(name, help, labelName string, categories ...string) *Timings { +func NewTimings(name, help, label string, categories ...string) *Timings { t := &Timings{ histograms: make(map[string]*Histogram), help: help, - labelName: labelName, + label: label, } for _, cat := range categories { t.histograms[cat] = NewGenericHistogram("", "", bucketCutoffs, bucketLabels, "Count", "Time") @@ -162,9 +162,9 @@ func (t *Timings) Help() string { return t.help } -// LabelName returns the label name. -func (t *Timings) LabelName() string { - return t.labelName +// Label returns the label name. +func (t *Timings) Label() string { + return t.label } var bucketCutoffs = []int64{5e5, 1e6, 5e6, 1e7, 5e7, 1e8, 5e8, 1e9, 5e9, 1e10} From 213d4468aa1562fdbb3422276a59404b8dfc63ee Mon Sep 17 00:00:00 2001 From: Michael Demmer Date: Mon, 30 Apr 2018 17:14:47 -0700 Subject: [PATCH 37/41] remove the unused LabelName() from the Histogram Signed-off-by: Michael Demmer --- go/stats/histogram.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/go/stats/histogram.go b/go/stats/histogram.go index b12f3235ff3..c6231998bb5 100644 --- a/go/stats/histogram.go +++ b/go/stats/histogram.go @@ -28,7 +28,6 @@ import ( // using specified cutoffs. type Histogram struct { help string - labelName string cutoffs []int64 labels []string countLabel string @@ -168,8 +167,3 @@ func (h *Histogram) Buckets() []int64 { func (h *Histogram) Help() string { return h.help } - -// LabelName returns the label name. -func (h *Histogram) LabelName() string { - return h.labelName -} From 191021c6a0798ad7a83bd449e567b4c64d6269c1 Mon Sep 17 00:00:00 2001 From: Michael Demmer Date: Mon, 30 Apr 2018 17:17:26 -0700 Subject: [PATCH 38/41] clean up cutoffs intitialization As suggested in PR review, move the intitialization of the cutoffs before the struct creation. Signed-off-by: Michael Demmer --- go/stats/prometheusbackend/collectors.go | 33 +++++++++++++----------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/go/stats/prometheusbackend/collectors.go b/go/stats/prometheusbackend/collectors.go index c7f7ad4834a..65293154828 100644 --- a/go/stats/prometheusbackend/collectors.go +++ b/go/stats/prometheusbackend/collectors.go @@ -214,9 +214,14 @@ type timingsCollector struct { } func newTimingsCollector(t *stats.Timings, name string) { + cutoffs := make([]float64, len(t.Cutoffs())) + for i, val := range t.Cutoffs() { + cutoffs[i] = float64(val) / 1000000000 + } + collector := &timingsCollector{ t: t, - cutoffs: make([]float64, len(t.Cutoffs())), + cutoffs: cutoffs, desc: prometheus.NewDesc( name, t.Help(), @@ -224,10 +229,6 @@ func newTimingsCollector(t *stats.Timings, name string) { nil), } - for i, val := range t.Cutoffs() { - collector.cutoffs[i] = float64(val) / 1000000000 - } - prometheus.MustRegister(collector) } @@ -266,9 +267,14 @@ type multiTimingsCollector struct { } func newMultiTimingsCollector(mt *stats.MultiTimings, name string) { + cutoffs := make([]float64, len(mt.Cutoffs())) + for i, val := range mt.Cutoffs() { + cutoffs[i] = float64(val) / 1000000000 + } + collector := &multiTimingsCollector{ mt: mt, - cutoffs: make([]float64, len(mt.Cutoffs())), + cutoffs: cutoffs, desc: prometheus.NewDesc( name, mt.Help(), @@ -276,10 +282,6 @@ func newMultiTimingsCollector(mt *stats.MultiTimings, name string) { nil), } - for i, val := range mt.Cutoffs() { - collector.cutoffs[i] = float64(val) / 1000000000 - } - prometheus.MustRegister(collector) } @@ -308,9 +310,14 @@ type histogramCollector struct { } func newHistogramCollector(h *stats.Histogram, name string) { + cutoffs := make([]float64, len(h.Cutoffs())) + for i, val := range h.Cutoffs() { + cutoffs[i] = float64(val) + } + collector := &histogramCollector{ h: h, - cutoffs: make([]float64, len(h.Cutoffs())), + cutoffs: cutoffs, desc: prometheus.NewDesc( name, h.Help(), @@ -318,10 +325,6 @@ func newHistogramCollector(h *stats.Histogram, name string) { nil), } - for i, val := range h.Cutoffs() { - collector.cutoffs[i] = float64(val) - } - prometheus.MustRegister(collector) } From 5dd4aefe388c7715c8fb7a27521db07a2650f86d Mon Sep 17 00:00:00 2001 From: jvaidya Date: Tue, 1 May 2018 04:09:03 +0000 Subject: [PATCH 39/41] fixed link sytax, added pt-osc Signed-off-by: jvaidya --- doc/VitessReplication.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/VitessReplication.md b/doc/VitessReplication.md index a0c549e4428..fe06568b0cb 100644 --- a/doc/VitessReplication.md +++ b/doc/VitessReplication.md @@ -6,7 +6,7 @@ MySQL supports two primary modes of replication in its binary logs: statement or row based. Vitess supports both these modes. For schema changes, if the number of affected rows is greater > 100k (configurable), we don't allow direct application -of DDLs. The recommended tool in such cases is [gh-ost]({% link https://github.com/github/gh-ost %}). +of DDLs. The recommended tools in such cases are [gh-ost](https://github.com/github/gh-ost) or [pt-osc](https://www.percona.com/doc/percona-toolkit/LATEST/pt-online-schema-change.html). Not all statements are safe for Statement Based Replication (SBR): https://dev.mysql.com/doc/refman/8.0/en/replication-rbr-safe-unsafe.html. Vitess rewrites some of these statements to be safe for SBR, and others are explicitly failed. This is described in detail below. From cce7c615d6a01c80ef28705cfeb6c63d06ff24cc Mon Sep 17 00:00:00 2001 From: Sugu Sougoumarane Date: Sun, 29 Apr 2018 06:09:21 -0700 Subject: [PATCH 40/41] helm: minor fixes Couple of invocations were using keyspaceClean instead of keyspace.name, which is "a-b" vs "a_b". Signed-off-by: Sugu Sougoumarane --- helm/vitess/templates/_vttablet.tpl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/helm/vitess/templates/_vttablet.tpl b/helm/vitess/templates/_vttablet.tpl index 37a8d48d134..751b110b225 100644 --- a/helm/vitess/templates/_vttablet.tpl +++ b/helm/vitess/templates/_vttablet.tpl @@ -194,7 +194,7 @@ spec: fi # check for a master tablet from the GetShard call - master_alias=$(vtctlclient -server $VTCTLD_SVC GetShard {{ $keyspaceClean }}/{{ $shard.name }} | jq '.master_alias.uid') + master_alias=$(vtctlclient -server $VTCTLD_SVC GetShard {{ $keyspace.name }}/{{ $shard.name }} | jq '.master_alias.uid') if [ $master_alias != "null" ]; then echo "'$master_alias' is already the master tablet, exiting without running InitShardMaster" exit @@ -222,7 +222,7 @@ spec: tablet_id=$( echo "$shardTablets" | awk 'substr( $5,1,{{ add (len $shardName) 10 }} ) == "{{ $shardName }}-replica-0" {print $1}') # initialize the shard master - until vtctlclient -server $VTCTLD_SVC InitShardMaster -force {{ $keyspaceClean }}/{{ $shard.name }} $tablet_id; do + until vtctlclient -server $VTCTLD_SVC InitShardMaster -force {{ $keyspace.name }}/{{ $shard.name }} $tablet_id; do if (( $SECONDS > $TIMEOUT_SECONDS )); then echo "timed out waiting for InitShardMaster to succeed" exit 1 From 0b263a80b48a0cde80e61dd0961044ffb730be14 Mon Sep 17 00:00:00 2001 From: David Weitzman Date: Wed, 2 May 2018 02:16:38 -0700 Subject: [PATCH 41/41] Use an alias so goimports doesn't delete a real import goimports gets confused by dashes and dots in import names. Signed-off-by: David Weitzman --- go/mysql/ldapauthserver/auth_server_ldap.go | 2 +- .../ldapauthserver/auth_server_ldap_test.go | 2 +- go/vt/worker/split_diff.go | 10 +++++----- go/vt/worker/vertical_split_diff.go | 18 +++++++++--------- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/go/mysql/ldapauthserver/auth_server_ldap.go b/go/mysql/ldapauthserver/auth_server_ldap.go index 1aeac844e59..a51e8ca3b11 100644 --- a/go/mysql/ldapauthserver/auth_server_ldap.go +++ b/go/mysql/ldapauthserver/auth_server_ldap.go @@ -25,7 +25,7 @@ import ( "sync" "time" - "gopkg.in/ldap.v2" + ldap "gopkg.in/ldap.v2" "vitess.io/vitess/go/mysql" "vitess.io/vitess/go/netutil" "vitess.io/vitess/go/vt/log" diff --git a/go/mysql/ldapauthserver/auth_server_ldap_test.go b/go/mysql/ldapauthserver/auth_server_ldap_test.go index 863df7a06cf..fd9daef65ac 100644 --- a/go/mysql/ldapauthserver/auth_server_ldap_test.go +++ b/go/mysql/ldapauthserver/auth_server_ldap_test.go @@ -20,7 +20,7 @@ import ( "fmt" "testing" - "gopkg.in/ldap.v2" + ldap "gopkg.in/ldap.v2" ) type MockLdapClient struct{} diff --git a/go/vt/worker/split_diff.go b/go/vt/worker/split_diff.go index 47c46a25901..e7b51256146 100644 --- a/go/vt/worker/split_diff.go +++ b/go/vt/worker/split_diff.go @@ -19,6 +19,7 @@ package worker import ( "fmt" "html/template" + "sort" "sync" "golang.org/x/net/context" @@ -34,7 +35,6 @@ import ( tabletmanagerdatapb "vitess.io/vitess/go/vt/proto/tabletmanagerdata" topodatapb "vitess.io/vitess/go/vt/proto/topodata" - "sort" ) // SplitDiffWorker executes a diff between a destination shard and its @@ -219,7 +219,7 @@ func (sdw *SplitDiffWorker) findTargets(ctx context.Context) error { // find an appropriate tablet in destination shard var err error - sdw.destinationAlias, err = FindWorkerTablet(ctx, sdw.wr, sdw.cleaner, nil /* tsc */ , sdw.cell, sdw.keyspace, sdw.shard, sdw.minHealthyRdonlyTablets) + sdw.destinationAlias, err = FindWorkerTablet(ctx, sdw.wr, sdw.cleaner, nil /* tsc */, sdw.cell, sdw.keyspace, sdw.shard, sdw.minHealthyRdonlyTablets) if err != nil { return fmt.Errorf("FindWorkerTablet() failed for %v/%v/%v: %v", sdw.cell, sdw.keyspace, sdw.shard, err) } @@ -227,7 +227,7 @@ func (sdw *SplitDiffWorker) findTargets(ctx context.Context) error { // find an appropriate tablet in the source shard for _, ss := range sdw.shardInfo.SourceShards { if ss.Uid == sdw.sourceUID { - sdw.sourceAlias, err = FindWorkerTablet(ctx, sdw.wr, sdw.cleaner, nil /* tsc */ , sdw.cell, sdw.keyspace, ss.Shard, sdw.minHealthyRdonlyTablets) + sdw.sourceAlias, err = FindWorkerTablet(ctx, sdw.wr, sdw.cleaner, nil /* tsc */, sdw.cell, sdw.keyspace, ss.Shard, sdw.minHealthyRdonlyTablets) if err != nil { return fmt.Errorf("FindWorkerTablet() failed for %v/%v/%v: %v", sdw.cell, sdw.keyspace, ss.Shard, err) } @@ -370,7 +370,7 @@ func (sdw *SplitDiffWorker) diff(ctx context.Context) error { var err error shortCtx, cancel := context.WithTimeout(ctx, *remoteActionsTimeout) sdw.destinationSchemaDefinition, err = sdw.wr.GetSchema( - shortCtx, sdw.destinationAlias, nil /* tables */ , sdw.excludeTables, false /* includeViews */) + shortCtx, sdw.destinationAlias, nil /* tables */, sdw.excludeTables, false /* includeViews */) cancel() rec.RecordError(err) sdw.wr.Logger().Infof("Got schema from destination %v", sdw.destinationAlias) @@ -381,7 +381,7 @@ func (sdw *SplitDiffWorker) diff(ctx context.Context) error { var err error shortCtx, cancel := context.WithTimeout(ctx, *remoteActionsTimeout) sdw.sourceSchemaDefinition, err = sdw.wr.GetSchema( - shortCtx, sdw.sourceAlias, nil /* tables */ , sdw.excludeTables, false /* includeViews */) + shortCtx, sdw.sourceAlias, nil /* tables */, sdw.excludeTables, false /* includeViews */) cancel() rec.RecordError(err) sdw.wr.Logger().Infof("Got schema from source %v", sdw.sourceAlias) diff --git a/go/vt/worker/vertical_split_diff.go b/go/vt/worker/vertical_split_diff.go index a11026fb523..71616408f2f 100644 --- a/go/vt/worker/vertical_split_diff.go +++ b/go/vt/worker/vertical_split_diff.go @@ -63,11 +63,11 @@ type VerticalSplitDiffWorker struct { // NewVerticalSplitDiffWorker returns a new VerticalSplitDiffWorker object. func NewVerticalSplitDiffWorker(wr *wrangler.Wrangler, cell, keyspace, shard string, minHealthyRdonlyTablets, parallelDiffsCount int) Worker { return &VerticalSplitDiffWorker{ - StatusWorker: NewStatusWorker(), - wr: wr, - cell: cell, - keyspace: keyspace, - shard: shard, + StatusWorker: NewStatusWorker(), + wr: wr, + cell: cell, + keyspace: keyspace, + shard: shard, minHealthyRdonlyTablets: minHealthyRdonlyTablets, parallelDiffsCount: parallelDiffsCount, cleaner: &wrangler.Cleaner{}, @@ -206,13 +206,13 @@ func (vsdw *VerticalSplitDiffWorker) findTargets(ctx context.Context) error { // find an appropriate tablet in destination shard var err error - vsdw.destinationAlias, err = FindWorkerTablet(ctx, vsdw.wr, vsdw.cleaner, nil /* tsc */ , vsdw.cell, vsdw.keyspace, vsdw.shard, vsdw.minHealthyRdonlyTablets) + vsdw.destinationAlias, err = FindWorkerTablet(ctx, vsdw.wr, vsdw.cleaner, nil /* tsc */, vsdw.cell, vsdw.keyspace, vsdw.shard, vsdw.minHealthyRdonlyTablets) if err != nil { return fmt.Errorf("FindWorkerTablet() failed for %v/%v/%v: %v", vsdw.cell, vsdw.keyspace, vsdw.shard, err) } // find an appropriate tablet in the source shard - vsdw.sourceAlias, err = FindWorkerTablet(ctx, vsdw.wr, vsdw.cleaner, nil /* tsc */ , vsdw.cell, vsdw.shardInfo.SourceShards[0].Keyspace, vsdw.shardInfo.SourceShards[0].Shard, vsdw.minHealthyRdonlyTablets) + vsdw.sourceAlias, err = FindWorkerTablet(ctx, vsdw.wr, vsdw.cleaner, nil /* tsc */, vsdw.cell, vsdw.shardInfo.SourceShards[0].Keyspace, vsdw.shardInfo.SourceShards[0].Shard, vsdw.minHealthyRdonlyTablets) if err != nil { return fmt.Errorf("FindWorkerTablet() failed for %v/%v/%v: %v", vsdw.cell, vsdw.shardInfo.SourceShards[0].Keyspace, vsdw.shardInfo.SourceShards[0].Shard, err) } @@ -349,7 +349,7 @@ func (vsdw *VerticalSplitDiffWorker) diff(ctx context.Context) error { var err error shortCtx, cancel := context.WithTimeout(ctx, *remoteActionsTimeout) vsdw.destinationSchemaDefinition, err = vsdw.wr.GetSchema( - shortCtx, vsdw.destinationAlias, vsdw.shardInfo.SourceShards[0].Tables, nil /* excludeTables */ , false /* includeViews */) + shortCtx, vsdw.destinationAlias, vsdw.shardInfo.SourceShards[0].Tables, nil /* excludeTables */, false /* includeViews */) cancel() rec.RecordError(err) vsdw.wr.Logger().Infof("Got schema from destination %v", topoproto.TabletAliasString(vsdw.destinationAlias)) @@ -360,7 +360,7 @@ func (vsdw *VerticalSplitDiffWorker) diff(ctx context.Context) error { var err error shortCtx, cancel := context.WithTimeout(ctx, *remoteActionsTimeout) vsdw.sourceSchemaDefinition, err = vsdw.wr.GetSchema( - shortCtx, vsdw.sourceAlias, vsdw.shardInfo.SourceShards[0].Tables, nil /* excludeTables */ , false /* includeViews */) + shortCtx, vsdw.sourceAlias, vsdw.shardInfo.SourceShards[0].Tables, nil /* excludeTables */, false /* includeViews */) cancel() rec.RecordError(err) vsdw.wr.Logger().Infof("Got schema from source %v", topoproto.TabletAliasString(vsdw.sourceAlias))