github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/parser/help_test.go (about)

     1  // Copyright 2017 The Cockroach Authors.
     2  //
     3  // Use of this software is governed by the Business Source License
     4  // included in the file licenses/BSL.txt.
     5  //
     6  // As of the Change Date specified in that file, in accordance with
     7  // the Business Source License, use of this software will be governed
     8  // by the Apache License, Version 2.0, included in the file
     9  // licenses/APL.txt.
    10  
    11  package parser
    12  
    13  import (
    14  	"strings"
    15  	"testing"
    16  
    17  	"github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgerror"
    18  )
    19  
    20  func TestHelpMessagesDefined(t *testing.T) {
    21  	var emptyBody HelpMessageBody
    22  	// Note: expectedHelpStrings is generated externally
    23  	// from the grammar by help_gen_test.sh.
    24  	for _, expKey := range expectedHelpStrings {
    25  		expectedMsg := HelpMessages[expKey]
    26  		if expectedMsg == emptyBody {
    27  			t.Errorf("no message defined for %q", expKey)
    28  		}
    29  	}
    30  }
    31  
    32  func TestContextualHelp(t *testing.T) {
    33  	testData := []struct {
    34  		input string
    35  		key   string
    36  	}{
    37  		{`ALTER ??`, `ALTER`},
    38  
    39  		{`ALTER TABLE IF ??`, `ALTER TABLE`},
    40  		{`ALTER TABLE blah ??`, `ALTER TABLE`},
    41  		{`ALTER TABLE blah ADD ??`, `ALTER TABLE`},
    42  		{`ALTER TABLE blah ALTER x DROP ??`, `ALTER TABLE`},
    43  		{`ALTER TABLE blah RENAME TO ??`, `ALTER TABLE`},
    44  		{`ALTER TABLE blah RENAME TO blih ??`, `ALTER TABLE`},
    45  		{`ALTER TABLE blah SPLIT AT (SELECT 1) ??`, `ALTER TABLE`},
    46  
    47  		{`ALTER TYPE ??`, `ALTER TYPE`},
    48  		{`ALTER TYPE t ??`, `ALTER TYPE`},
    49  		{`ALTER TYPE t ADD VALUE ??`, `ALTER TYPE`},
    50  		{`ALTER TYPE t SET ??`, `ALTER TYPE`},
    51  		{`ALTER TYPE t RENAME ??`, `ALTER TYPE`},
    52  
    53  		{`ALTER INDEX foo@bar RENAME ??`, `ALTER INDEX`},
    54  		{`ALTER INDEX foo@bar RENAME TO blih ??`, `ALTER INDEX`},
    55  		{`ALTER INDEX foo@bar SPLIT ??`, `ALTER INDEX`},
    56  		{`ALTER INDEX foo@bar SPLIT AT (SELECT 1) ??`, `ALTER INDEX`},
    57  
    58  		{`ALTER DATABASE foo ??`, `ALTER DATABASE`},
    59  		{`ALTER DATABASE foo RENAME ??`, `ALTER DATABASE`},
    60  		{`ALTER DATABASE foo RENAME TO bar ??`, `ALTER DATABASE`},
    61  
    62  		{`ALTER VIEW IF ??`, `ALTER VIEW`},
    63  		{`ALTER VIEW blah ??`, `ALTER VIEW`},
    64  		{`ALTER VIEW blah RENAME ??`, `ALTER VIEW`},
    65  		{`ALTER VIEW blah RENAME TO blih ??`, `ALTER VIEW`},
    66  
    67  		{`ALTER SEQUENCE IF ??`, `ALTER SEQUENCE`},
    68  		{`ALTER SEQUENCE blah ??`, `ALTER SEQUENCE`},
    69  		{`ALTER SEQUENCE blah RENAME ??`, `ALTER SEQUENCE`},
    70  		{`ALTER SEQUENCE blah RENAME TO blih ??`, `ALTER SEQUENCE`},
    71  
    72  		{`ALTER USER IF ??`, `ALTER ROLE`},
    73  		{`ALTER USER foo WITH PASSWORD ??`, `ALTER ROLE`},
    74  
    75  		{`ALTER ROLE bleh ?? WITH NOCREATEROLE`, `ALTER ROLE`},
    76  
    77  		{`ALTER RANGE foo CONFIGURE ??`, `ALTER RANGE`},
    78  		{`ALTER RANGE ??`, `ALTER RANGE`},
    79  
    80  		{`ALTER PARTITION ??`, `ALTER PARTITION`},
    81  		{`ALTER PARTITION p OF INDEX tbl@idx ??`, `ALTER PARTITION`},
    82  
    83  		{`CANCEL ??`, `CANCEL`},
    84  		{`CANCEL JOB ??`, `CANCEL JOBS`},
    85  		{`CANCEL JOBS ??`, `CANCEL JOBS`},
    86  		{`CANCEL QUERY ??`, `CANCEL QUERIES`},
    87  		{`CANCEL QUERY IF ??`, `CANCEL QUERIES`},
    88  		{`CANCEL QUERY IF EXISTS ??`, `CANCEL QUERIES`},
    89  		{`CANCEL QUERIES ??`, `CANCEL QUERIES`},
    90  		{`CANCEL QUERIES IF ??`, `CANCEL QUERIES`},
    91  		{`CANCEL QUERIES IF EXISTS ??`, `CANCEL QUERIES`},
    92  		{`CANCEL SESSION ??`, `CANCEL SESSIONS`},
    93  		{`CANCEL SESSION IF ??`, `CANCEL SESSIONS`},
    94  		{`CANCEL SESSION IF EXISTS ??`, `CANCEL SESSIONS`},
    95  		{`CANCEL SESSIONS ??`, `CANCEL SESSIONS`},
    96  		{`CANCEL SESSIONS IF ??`, `CANCEL SESSIONS`},
    97  		{`CANCEL SESSIONS IF EXISTS ??`, `CANCEL SESSIONS`},
    98  
    99  		{`CREATE UNIQUE ??`, `CREATE`},
   100  		{`CREATE UNIQUE INDEX ??`, `CREATE INDEX`},
   101  		{`CREATE INDEX IF NOT ??`, `CREATE INDEX`},
   102  		{`CREATE INDEX blah ??`, `CREATE INDEX`},
   103  		{`CREATE INDEX blah ON bloh (??`, `CREATE INDEX`},
   104  		{`CREATE INDEX blah ON bloh (x,y) STORING ??`, `CREATE INDEX`},
   105  		{`CREATE INDEX blah ON bloh (x) ??`, `CREATE INDEX`},
   106  
   107  		{`CREATE DATABASE IF ??`, `CREATE DATABASE`},
   108  		{`CREATE DATABASE IF NOT ??`, `CREATE DATABASE`},
   109  		{`CREATE DATABASE blih ??`, `CREATE DATABASE`},
   110  
   111  		{`CREATE USER blih ??`, `CREATE ROLE`},
   112  		{`CREATE USER blih WITH ??`, `CREATE ROLE`},
   113  
   114  		{`CREATE ROLE bleh ??`, `CREATE ROLE`},
   115  		{`CREATE ROLE bleh ?? WITH CREATEROLE`, `CREATE ROLE`},
   116  
   117  		{`CREATE VIEW blah (??`, `CREATE VIEW`},
   118  		{`CREATE VIEW blah AS (SELECT c FROM x) ??`, `CREATE VIEW`},
   119  		{`CREATE VIEW blah AS SELECT c FROM x ??`, `SELECT`},
   120  		{`CREATE VIEW blah AS (??`, `<SELECTCLAUSE>`},
   121  
   122  		{`CREATE SEQUENCE ??`, `CREATE SEQUENCE`},
   123  
   124  		{`CREATE STATISTICS ??`, `CREATE STATISTICS`},
   125  
   126  		{`CREATE TABLE blah (??`, `CREATE TABLE`},
   127  		{`CREATE TABLE IF NOT ??`, `CREATE TABLE`},
   128  		{`CREATE TABLE blah (x, y) AS ??`, `CREATE TABLE`},
   129  		{`CREATE TABLE blah (x INT) ??`, `CREATE TABLE`},
   130  		{`CREATE TABLE blah AS ??`, `CREATE TABLE`},
   131  		{`CREATE TABLE blah AS (SELECT 1) ??`, `CREATE TABLE`},
   132  		{`CREATE TABLE blah AS SELECT 1 ??`, `SELECT`},
   133  
   134  		{`CREATE TYPE blah AS ENUM ??`, `CREATE TYPE`},
   135  		{`DROP TYPE ??`, `DROP TYPE`},
   136  
   137  		{`CREATE SCHEMA IF ??`, `CREATE SCHEMA`},
   138  		{`CREATE SCHEMA IF NOT ??`, `CREATE SCHEMA`},
   139  		{`CREATE SCHEMA bli ??`, `CREATE SCHEMA`},
   140  
   141  		{`DELETE FROM ??`, `DELETE`},
   142  		{`DELETE FROM blah ??`, `DELETE`},
   143  		{`DELETE FROM blah WHERE ??`, `DELETE`},
   144  		{`DELETE FROM blah WHERE x > 3 ??`, `DELETE`},
   145  
   146  		{`DISCARD ALL ??`, `DISCARD`},
   147  		{`DISCARD ??`, `DISCARD`},
   148  
   149  		{`DROP ??`, `DROP`},
   150  
   151  		{`DROP DATABASE IF ??`, `DROP DATABASE`},
   152  		{`DROP DATABASE IF EXISTS blah ??`, `DROP DATABASE`},
   153  
   154  		{`DROP INDEX blah, ??`, `DROP INDEX`},
   155  		{`DROP INDEX blah@blih ??`, `DROP INDEX`},
   156  
   157  		{`DROP USER ??`, `DROP ROLE`},
   158  		{`DROP USER IF ??`, `DROP ROLE`},
   159  		{`DROP USER IF EXISTS bluh ??`, `DROP ROLE`},
   160  
   161  		{`DROP ROLE ??`, `DROP ROLE`},
   162  		{`DROP ROLE IF ??`, `DROP ROLE`},
   163  		{`DROP ROLE IF EXISTS bluh ??`, `DROP ROLE`},
   164  
   165  		{`DROP SEQUENCE blah ??`, `DROP SEQUENCE`},
   166  		{`DROP SEQUENCE IF ??`, `DROP SEQUENCE`},
   167  		{`DROP SEQUENCE IF EXISTS blih, bloh ??`, `DROP SEQUENCE`},
   168  
   169  		{`DROP TABLE blah ??`, `DROP TABLE`},
   170  		{`DROP TABLE IF ??`, `DROP TABLE`},
   171  		{`DROP TABLE IF EXISTS blih, bloh ??`, `DROP TABLE`},
   172  
   173  		{`DROP VIEW blah ??`, `DROP VIEW`},
   174  		{`DROP VIEW IF ??`, `DROP VIEW`},
   175  		{`DROP VIEW IF EXISTS blih, bloh ??`, `DROP VIEW`},
   176  
   177  		{`EXPLAIN (??`, `EXPLAIN`},
   178  		{`EXPLAIN SELECT 1 ??`, `SELECT`},
   179  		{`EXPLAIN INSERT INTO xx (SELECT 1) ??`, `INSERT`},
   180  		{`EXPLAIN UPSERT INTO xx (SELECT 1) ??`, `UPSERT`},
   181  		{`EXPLAIN DELETE FROM xx ??`, `DELETE`},
   182  		{`EXPLAIN UPDATE xx SET x = y ??`, `UPDATE`},
   183  		{`SELECT * FROM [EXPLAIN ??`, `EXPLAIN`},
   184  
   185  		{`PREPARE foo ??`, `PREPARE`},
   186  		{`PREPARE foo (??`, `PREPARE`},
   187  		{`PREPARE foo AS SELECT 1 ??`, `SELECT`},
   188  		{`PREPARE foo AS (SELECT 1) ??`, `PREPARE`},
   189  		{`PREPARE foo AS INSERT INTO xx (SELECT 1) ??`, `INSERT`},
   190  		{`PREPARE foo AS UPSERT INTO xx (SELECT 1) ??`, `UPSERT`},
   191  		{`PREPARE foo AS DELETE FROM xx ??`, `DELETE`},
   192  		{`PREPARE foo AS UPDATE xx SET x = y ??`, `UPDATE`},
   193  
   194  		{`EXECUTE foo ??`, `EXECUTE`},
   195  		{`EXECUTE foo (??`, `EXECUTE`},
   196  
   197  		{`DEALLOCATE foo ??`, `DEALLOCATE`},
   198  		{`DEALLOCATE ALL ??`, `DEALLOCATE`},
   199  		{`DEALLOCATE PREPARE ??`, `DEALLOCATE`},
   200  
   201  		{`INSERT INTO ??`, `INSERT`},
   202  		{`INSERT INTO blah (??`, `<SELECTCLAUSE>`},
   203  		{`INSERT INTO blah VALUES (1) RETURNING ??`, `INSERT`},
   204  		{`INSERT INTO blah (VALUES (1)) ??`, `INSERT`},
   205  		{`INSERT INTO blah VALUES (1) ??`, `VALUES`},
   206  		{`INSERT INTO blah TABLE foo ??`, `TABLE`},
   207  
   208  		{`UPSERT INTO ??`, `UPSERT`},
   209  		{`UPSERT INTO blah (??`, `<SELECTCLAUSE>`},
   210  		{`UPSERT INTO blah VALUES (1) RETURNING ??`, `UPSERT`},
   211  		{`UPSERT INTO blah (VALUES (1)) ??`, `UPSERT`},
   212  		{`UPSERT INTO blah VALUES (1) ??`, `VALUES`},
   213  		{`UPSERT INTO blah TABLE foo ??`, `TABLE`},
   214  
   215  		{`UPDATE blah ??`, `UPDATE`},
   216  		{`UPDATE blah SET ??`, `UPDATE`},
   217  		{`UPDATE blah SET x = 3 WHERE true ??`, `UPDATE`},
   218  		{`UPDATE blah SET x = 3 ??`, `UPDATE`},
   219  		{`UPDATE blah SET x = 3 WHERE ??`, `UPDATE`},
   220  
   221  		{`GRANT ALL ??`, `GRANT`},
   222  		{`GRANT ALL ON foo TO ??`, `GRANT`},
   223  		{`GRANT ALL ON foo TO bar ??`, `GRANT`},
   224  
   225  		{`PAUSE ??`, `PAUSE JOBS`},
   226  
   227  		{`RESUME ??`, `RESUME JOBS`},
   228  
   229  		{`REVOKE ALL ??`, `REVOKE`},
   230  		{`REVOKE ALL ON foo FROM ??`, `REVOKE`},
   231  		{`REVOKE ALL ON foo FROM bar ??`, `REVOKE`},
   232  
   233  		{`SELECT * FROM ??`, `<SOURCE>`},
   234  		{`SELECT * FROM (??`, `<SOURCE>`}, // not <selectclause>! joins are allowed.
   235  		{`SELECT * FROM [SHOW ??`, `SHOW`},
   236  
   237  		{`SHOW blah ??`, `SHOW SESSION`},
   238  		{`SHOW database ??`, `SHOW SESSION`},
   239  		{`SHOW TIME ??`, `SHOW SESSION`},
   240  		{`SHOW all ??`, `SHOW SESSION`},
   241  		{`SHOW SESSION_USER ??`, `SHOW SESSION`},
   242  		{`SHOW SESSION blah ??`, `SHOW SESSION`},
   243  		{`SHOW SESSION database ??`, `SHOW SESSION`},
   244  		{`SHOW SESSION TIME ZONE ??`, `SHOW SESSION`},
   245  		{`SHOW SESSION all ??`, `SHOW SESSION`},
   246  		{`SHOW SESSION SESSION_USER ??`, `SHOW SESSION`},
   247  
   248  		{`SHOW SESSIONS ??`, `SHOW SESSIONS`},
   249  		{`SHOW LOCAL SESSIONS ??`, `SHOW SESSIONS`},
   250  
   251  		{`SHOW STATISTICS ??`, `SHOW STATISTICS`},
   252  		{`SHOW STATISTICS FOR TABLE ??`, `SHOW STATISTICS`},
   253  
   254  		{`SHOW HISTOGRAM ??`, `SHOW HISTOGRAM`},
   255  
   256  		{`SHOW QUERIES ??`, `SHOW QUERIES`},
   257  		{`SHOW LOCAL QUERIES ??`, `SHOW QUERIES`},
   258  
   259  		{`SHOW TRACE ??`, `SHOW TRACE`},
   260  		{`SHOW TRACE FOR SESSION ??`, `SHOW TRACE`},
   261  		{`SHOW TRACE FOR ??`, `SHOW TRACE`},
   262  
   263  		{`SHOW JOB ??`, `SHOW JOBS`},
   264  		{`SHOW JOBS ??`, `SHOW JOBS`},
   265  		{`SHOW AUTOMATIC JOBS ??`, `SHOW JOBS`},
   266  
   267  		{`SHOW BACKUP 'foo' ??`, `SHOW BACKUP`},
   268  
   269  		{`SHOW CLUSTER SETTING all ??`, `SHOW CLUSTER SETTING`},
   270  		{`SHOW ALL CLUSTER ??`, `SHOW CLUSTER SETTING`},
   271  
   272  		{`SHOW COLUMNS FROM ??`, `SHOW COLUMNS`},
   273  		{`SHOW COLUMNS FROM foo ??`, `SHOW COLUMNS`},
   274  
   275  		{`SHOW CONSTRAINTS FROM ??`, `SHOW CONSTRAINTS`},
   276  		{`SHOW CONSTRAINTS FROM foo ??`, `SHOW CONSTRAINTS`},
   277  
   278  		{`SHOW CREATE ??`, `SHOW CREATE`},
   279  		{`SHOW CREATE TABLE blah ??`, `SHOW CREATE`},
   280  		{`SHOW CREATE VIEW blah ??`, `SHOW CREATE`},
   281  		{`SHOW CREATE SEQUENCE blah ??`, `SHOW CREATE`},
   282  
   283  		{`SHOW DATABASES ??`, `SHOW DATABASES`},
   284  
   285  		{`SHOW GRANTS ON ??`, `SHOW GRANTS`},
   286  		{`SHOW GRANTS ON foo FOR ??`, `SHOW GRANTS`},
   287  		{`SHOW GRANTS ON foo FOR bar ??`, `SHOW GRANTS`},
   288  
   289  		{`SHOW GRANTS ON ROLE ??`, `SHOW GRANTS`},
   290  		{`SHOW GRANTS ON ROLE foo FOR ??`, `SHOW GRANTS`},
   291  		{`SHOW GRANTS ON ROLE foo FOR bar ??`, `SHOW GRANTS`},
   292  
   293  		{`SHOW KEYS ??`, `SHOW INDEXES`},
   294  		{`SHOW INDEX ??`, `SHOW INDEXES`},
   295  		{`SHOW INDEXES FROM ??`, `SHOW INDEXES`},
   296  		{`SHOW INDEXES FROM blah ??`, `SHOW INDEXES`},
   297  
   298  		{`SHOW PARTITIONS FROM ??`, `SHOW PARTITIONS`},
   299  
   300  		{`SHOW ROLES ??`, `SHOW ROLES`},
   301  
   302  		{`SHOW SCHEMAS FROM ??`, `SHOW SCHEMAS`},
   303  		{`SHOW SCHEMAS FROM blah ??`, `SHOW SCHEMAS`},
   304  
   305  		{`SHOW SEQUENCES FROM ??`, `SHOW SEQUENCES`},
   306  		{`SHOW SEQUENCES FROM blah ??`, `SHOW SEQUENCES`},
   307  
   308  		{`SHOW TABLES FROM ??`, `SHOW TABLES`},
   309  		{`SHOW TABLES FROM blah ??`, `SHOW TABLES`},
   310  
   311  		{`SHOW TRANSACTION PRIORITY ??`, `SHOW TRANSACTION`},
   312  		{`SHOW TRANSACTION STATUS ??`, `SHOW TRANSACTION`},
   313  		{`SHOW TRANSACTION ISOLATION ??`, `SHOW TRANSACTION`},
   314  		{`SHOW TRANSACTION ISOLATION LEVEL ??`, `SHOW TRANSACTION`},
   315  		{`SHOW SYNTAX ??`, `SHOW SYNTAX`},
   316  		{`SHOW SYNTAX 'foo' ??`, `SHOW SYNTAX`},
   317  		{`SHOW SAVEPOINT STATUS ??`, `SHOW SAVEPOINT`},
   318  
   319  		{`SHOW RANGE ??`, `SHOW RANGE`},
   320  
   321  		{`SHOW RANGES ??`, `SHOW RANGES`},
   322  
   323  		{`SHOW USERS ??`, `SHOW USERS`},
   324  
   325  		{`TRUNCATE foo ??`, `TRUNCATE`},
   326  		{`TRUNCATE foo, ??`, `TRUNCATE`},
   327  
   328  		{`SELECT 1 ??`, `SELECT`},
   329  		{`SELECT * FROM ??`, `<SOURCE>`},
   330  		{`SELECT 1 FROM foo ??`, `SELECT`},
   331  		{`SELECT 1 FROM foo WHERE ??`, `SELECT`},
   332  		{`SELECT 1 FROM (SELECT ??`, `SELECT`},
   333  		{`SELECT 1 FROM (VALUES ??`, `VALUES`},
   334  		{`SELECT 1 FROM (TABLE ??`, `TABLE`},
   335  		{`SELECT 1 FROM (SELECT 2 ??`, `SELECT`},
   336  		{`SELECT 1 FROM (??`, `<SOURCE>`},
   337  
   338  		{`TABLE blah ??`, `TABLE`},
   339  
   340  		{`VALUES (??`, `VALUES`},
   341  
   342  		{`VALUES (1) ??`, `VALUES`},
   343  
   344  		{`SET SESSION TRANSACTION ??`, `SET TRANSACTION`},
   345  		{`SET SESSION TRANSACTION ISOLATION LEVEL SNAPSHOT ??`, `SET TRANSACTION`},
   346  		{`SET SESSION TIME ??`, `SET SESSION`},
   347  		{`SET SESSION TIME ZONE 'UTC' ??`, `SET SESSION`},
   348  		{`SET SESSION blah TO ??`, `SET SESSION`},
   349  		{`SET SESSION blah TO 42 ??`, `SET SESSION`},
   350  
   351  		{`SET TRANSACTION ??`, `SET TRANSACTION`},
   352  		{`SET TRANSACTION ISOLATION LEVEL SNAPSHOT ??`, `SET TRANSACTION`},
   353  		{`SET TIME ??`, `SET SESSION`},
   354  		{`SET TIME ZONE 'UTC' ??`, `SET SESSION`},
   355  		{`SET blah TO ??`, `SET SESSION`},
   356  		{`SET blah TO 42 ??`, `SET SESSION`},
   357  
   358  		{`SET CLUSTER ??`, `SET CLUSTER SETTING`},
   359  		{`SET CLUSTER SETTING blah = 42 ??`, `SET CLUSTER SETTING`},
   360  
   361  		{`USE ??`, `USE`},
   362  
   363  		{`RESET blah ??`, `RESET`},
   364  		{`RESET SESSION ??`, `RESET`},
   365  		{`RESET CLUSTER SETTING ??`, `RESET CLUSTER SETTING`},
   366  
   367  		{`BEGIN TRANSACTION ??`, `BEGIN`},
   368  		{`BEGIN TRANSACTION ISOLATION ??`, `BEGIN`},
   369  		{`BEGIN TRANSACTION ISOLATION LEVEL SNAPSHOT, ??`, `BEGIN`},
   370  		{`START ??`, `BEGIN`},
   371  
   372  		{`COMMIT TRANSACTION ??`, `COMMIT`},
   373  		{`END ??`, `COMMIT`},
   374  
   375  		{`ROLLBACK TRANSACTION ??`, `ROLLBACK`},
   376  		{`ROLLBACK TO ??`, `ROLLBACK`},
   377  
   378  		{`SAVEPOINT blah ??`, `SAVEPOINT`},
   379  
   380  		{`RELEASE blah ??`, `RELEASE`},
   381  		{`RELEASE SAVEPOINT blah ??`, `RELEASE`},
   382  
   383  		{`EXPERIMENTAL SCRUB ??`, `SCRUB`},
   384  		{`EXPERIMENTAL SCRUB TABLE ??`, `SCRUB TABLE`},
   385  		{`EXPERIMENTAL SCRUB DATABASE ??`, `SCRUB DATABASE`},
   386  
   387  		{`BACKUP foo TO 'bar' ??`, `BACKUP`},
   388  		{`BACKUP DATABASE ??`, `BACKUP`},
   389  		{`BACKUP foo TO 'bar' AS OF ??`, `BACKUP`},
   390  
   391  		{`RESTORE foo FROM 'bar' ??`, `RESTORE`},
   392  		{`RESTORE DATABASE ??`, `RESTORE`},
   393  
   394  		{`IMPORT TABLE foo CREATE USING 'foo.sql' CSV DATA ('foo') ??`, `IMPORT`},
   395  		{`IMPORT TABLE ??`, `IMPORT`},
   396  
   397  		{`EXPORT ??`, `EXPORT`},
   398  		{`EXPORT INTO CSV 'a' ??`, `EXPORT`},
   399  		{`EXPORT INTO CSV 'a' FROM SELECT a ??`, `SELECT`},
   400  	}
   401  
   402  	// The following checks that the test definition above exercises all
   403  	// the help texts mentioned in the grammar.
   404  	t.Run("coverage", func(t *testing.T) {
   405  		testedStrings := make(map[string]struct{})
   406  		for _, test := range testData {
   407  			testedStrings[test.key] = struct{}{}
   408  		}
   409  		// Note: expectedHelpStrings is generated externally
   410  		// from the grammar by help_gen_test.sh.
   411  		for _, expKey := range expectedHelpStrings {
   412  			if _, ok := testedStrings[expKey]; !ok {
   413  				t.Errorf("test missing for: %q", expKey)
   414  			}
   415  		}
   416  	})
   417  
   418  	// The following checks that the grammar rules properly report help.
   419  	for _, test := range testData {
   420  		t.Run(test.input, func(t *testing.T) {
   421  			_, err := Parse(test.input)
   422  			if err == nil {
   423  				t.Fatalf("parser didn't trigger error")
   424  			}
   425  
   426  			if !strings.HasPrefix(err.Error(), "help token in input") {
   427  				t.Fatal(err)
   428  			}
   429  			pgerr := pgerror.Flatten(err)
   430  			help := pgerr.Hint
   431  			msg := HelpMessage{Command: test.key, HelpMessageBody: HelpMessages[test.key]}
   432  			expected := msg.String()
   433  			if help != expected {
   434  				t.Errorf("unexpected help message: got:\n%s\nexpected:\n%s", help, expected)
   435  			}
   436  		})
   437  	}
   438  }
   439  
   440  func TestHelpKeys(t *testing.T) {
   441  	// This test checks that if a help key is a valid prefix for '?',
   442  	// then it is also present in the rendered help message.  It also
   443  	// checks that the parser renders the correct help message.
   444  	for key, body := range HelpMessages {
   445  		t.Run(key, func(t *testing.T) {
   446  			_, err := Parse(key + " ??")
   447  			if err == nil {
   448  				t.Errorf("parser didn't trigger error")
   449  				return
   450  			}
   451  			help := err.Error()
   452  			if !strings.HasPrefix(help, "help: ") {
   453  				// Not a valid help prefix -- e.g. "<source>"
   454  				return
   455  			}
   456  
   457  			msg := HelpMessage{Command: key, HelpMessageBody: body}
   458  			expected := msg.String()
   459  			if help != expected {
   460  				t.Errorf("unexpected help message: got:\n%s\nexpected:\n%s", help, expected)
   461  				return
   462  			}
   463  			if !strings.Contains(help, " "+key+"\n") {
   464  				t.Errorf("help text does not contain key %q:\n%s", key, help)
   465  			}
   466  		})
   467  	}
   468  }