Skip to content

Commit efef378

Browse files
authored
feat: parse PostgreSQL VACUUM, ANALYZE, CLUSTER and CHECKPOINT with shared utility options (#2890)
PostgreSQL maintenance scripts failed to parse: VACUUM, CLUSTER and CHECKPOINT had no statement, and ANALYZE accepted only the MySQL form, so option lists, ANALYZE VERBOSE, column lists and a bare ANALYZE failed. Add UtilityOption, one name [value] element of PostgreSQL's utility_option_list with a typed value, and the shared UtilityOptionList()/UtilityOptionArgument() productions. VACUUM, ANALYZE and CLUSTER use them and, like PostgreSQL's grammar, accept any option name and value but PostgreSQL's reserved words; the server checks them when it runs the statement, and getKind() maps known names to each statement's OptionKind. EXPLAIN reads its options through the same production and accepts no more than before. The unparenthesized keywords (VACUUM FULL, ANALYZE VERBOSE, CLUSTER VERBOSE) are kept as options with isParenthesizedOptions() false. Add VacuumStatement, ClusterStatement (also the pre-8.3 CLUSTER index ON table) and CheckpointStatement, and extend Analyze with options, the ANALYSE spelling and MaintenanceTarget tables ([ONLY] t [*] [(columns)]). Analyze keeps its MySQL form with the whole histogram clause (bucket count, AUTO/MANUAL UPDATE, USING DATA); the MySQL clauses and the PostgreSQL options and targets exclude each other, and getTables() is derived from the targets. The statements, options and targets carry AST nodes spanning their source. VACUUM and CLUSTER become non-reserved keywords. The PostgreSQL forms are read with Dialect.POSTGRESQL and without a dialect; other dialects are unchanged. Wire the statements into the deparser, visitors, table finder, validation (vacuum, cluster, checkpoint; analyze is now in the MySQL, MariaDB and PostgreSQL capabilities) and feature analysis. Signed-off-by: minleejae <mmj9808@gmail.com>
1 parent aba25a4 commit efef378

32 files changed

Lines changed: 2879 additions & 38 deletions

‎README.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ and missing syntax gets added on demand — [open an issue](https://github.com/J
148148
| **Oracle vector types** | `VECTOR(*, *)` · `VECTOR(*, FLOAT32)` · `VECTOR(3, *)`, including dense and sparse storage formats |
149149
| **PostgreSQL ownership** | `DROP OWNED` · `REASSIGN OWNED` |
150150
| **MySQL table maintenance** | `ANALYZE` · `CHECK` · `CHECKSUM` · `OPTIMIZE` · `REPAIR TABLE` |
151+
| **PostgreSQL maintenance** | `VACUUM` · `ANALYZE` · `CLUSTER` · `CHECKPOINT` |
151152
| **MySQL account management** | `CREATE`/`ALTER`/`RENAME USER` · `CREATE ROLE` · `SET ROLE` · `SET DEFAULT ROLE` · `SET PASSWORD` |
152153
| **Tablespaces** | MySQL and PostgreSQL `CREATE TABLESPACE` · `ALTER TABLESPACE` |
153154
| **PostgreSQL RLS** | `CREATE POLICY` · `ALTER TABLE … ENABLE`/`DISABLE`/`FORCE`/`NO FORCE ROW LEVEL SECURITY` |

‎src/main/java/net/sf/jsqlparser/parser/feature/Feature.java‎

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@
3232
import net.sf.jsqlparser.statement.alter.AlterEventTrigger;
3333
import net.sf.jsqlparser.statement.alter.sequence.AlterSequence;
3434
import net.sf.jsqlparser.statement.analyze.Analyze;
35+
import net.sf.jsqlparser.statement.maintenance.CheckpointStatement;
36+
import net.sf.jsqlparser.statement.maintenance.ClusterStatement;
37+
import net.sf.jsqlparser.statement.maintenance.VacuumStatement;
3538
import net.sf.jsqlparser.statement.comment.Comment;
3639
import net.sf.jsqlparser.statement.create.database.CreateDatabase;
3740
import net.sf.jsqlparser.statement.create.function.CreateFunction;
@@ -485,6 +488,27 @@ public enum Feature {
485488
*/
486489
tableMaintenance,
487490

491+
/**
492+
* PostgreSQL "VACUUM" statement is allowed
493+
*
494+
* @see VacuumStatement
495+
*/
496+
vacuum,
497+
498+
/**
499+
* PostgreSQL "CLUSTER" statement is allowed
500+
*
501+
* @see ClusterStatement
502+
*/
503+
cluster,
504+
505+
/**
506+
* PostgreSQL "CHECKPOINT" statement is allowed
507+
*
508+
* @see CheckpointStatement
509+
*/
510+
checkpoint,
511+
488512
/**
489513
* SQL "TRUNCATE" statement is allowed
490514
*

‎src/main/java/net/sf/jsqlparser/statement/StatementFeatureVisitor.java‎

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,9 @@
9999
import net.sf.jsqlparser.statement.insert.InsertBulk;
100100
import net.sf.jsqlparser.statement.load.LoadDataStatement;
101101
import net.sf.jsqlparser.statement.lock.LockStatement;
102+
import net.sf.jsqlparser.statement.maintenance.CheckpointStatement;
103+
import net.sf.jsqlparser.statement.maintenance.ClusterStatement;
104+
import net.sf.jsqlparser.statement.maintenance.VacuumStatement;
102105
import net.sf.jsqlparser.statement.merge.Merge;
103106
import net.sf.jsqlparser.statement.oracle.OracleAssignment;
104107
import net.sf.jsqlparser.statement.oracle.OracleBlock;
@@ -778,6 +781,30 @@ public <S> Void visit(TableMaintenanceStatement statement, S context) {
778781
return null;
779782
}
780783

784+
@Override
785+
public <S> Void visit(VacuumStatement vacuum, S context) {
786+
// reclaims storage and, with ANALYZE, rewrites statistics; FULL rewrites the tables
787+
analysis.claimTopLevel();
788+
analysis.certain(StmtFeature.MODIFIES_SCHEMA, StmtFeature.READS_DATA);
789+
return null;
790+
}
791+
792+
@Override
793+
public <S> Void visit(ClusterStatement cluster, S context) {
794+
// rewrites the table in index order
795+
analysis.claimTopLevel();
796+
analysis.certain(StmtFeature.MODIFIES_SCHEMA, StmtFeature.READS_DATA);
797+
return null;
798+
}
799+
800+
@Override
801+
public <S> Void visit(CheckpointStatement checkpoint, S context) {
802+
// a server operation like ALTER SYSTEM CHECKPOINT; no data or schema changes
803+
analysis.claimTopLevel();
804+
analysis.certain(StmtFeature.MODIFIES_SESSION);
805+
return null;
806+
}
807+
781808
private Void schemaOnly() {
782809
analysis.claimTopLevel();
783810
analysis.certain(StmtFeature.MODIFIES_SCHEMA);

‎src/main/java/net/sf/jsqlparser/statement/StatementVisitor.java‎

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,9 @@
9191
import net.sf.jsqlparser.statement.insert.InsertBulk;
9292
import net.sf.jsqlparser.statement.insert.ParenthesedInsert;
9393
import net.sf.jsqlparser.statement.lock.LockStatement;
94+
import net.sf.jsqlparser.statement.maintenance.CheckpointStatement;
95+
import net.sf.jsqlparser.statement.maintenance.ClusterStatement;
96+
import net.sf.jsqlparser.statement.maintenance.VacuumStatement;
9497
import net.sf.jsqlparser.statement.merge.Merge;
9598
import net.sf.jsqlparser.statement.refresh.RefreshMaterializedViewStatement;
9699
import net.sf.jsqlparser.statement.reindex.Reindex;
@@ -371,6 +374,30 @@ default void visit(TableMaintenanceStatement statement) {
371374
this.visit(statement, null);
372375
}
373376

377+
default <S> T visit(VacuumStatement vacuum, S context) {
378+
return null;
379+
}
380+
381+
default void visit(VacuumStatement vacuum) {
382+
this.visit(vacuum, null);
383+
}
384+
385+
default <S> T visit(ClusterStatement cluster, S context) {
386+
return null;
387+
}
388+
389+
default void visit(ClusterStatement cluster) {
390+
this.visit(cluster, null);
391+
}
392+
393+
default <S> T visit(CheckpointStatement checkpoint, S context) {
394+
return null;
395+
}
396+
397+
default void visit(CheckpointStatement checkpoint) {
398+
this.visit(checkpoint, null);
399+
}
400+
374401
default void visit(Execute execute) {
375402
this.visit(execute, null);
376403
}

‎src/main/java/net/sf/jsqlparser/statement/StatementVisitorAdapter.java‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,9 @@
9494
import net.sf.jsqlparser.statement.insert.InsertConflictAction;
9595
import net.sf.jsqlparser.statement.insert.ParenthesedInsert;
9696
import net.sf.jsqlparser.statement.lock.LockStatement;
97+
import net.sf.jsqlparser.statement.maintenance.CheckpointStatement;
98+
import net.sf.jsqlparser.statement.maintenance.ClusterStatement;
99+
import net.sf.jsqlparser.statement.maintenance.VacuumStatement;
97100
import net.sf.jsqlparser.statement.merge.Merge;
98101
import net.sf.jsqlparser.statement.merge.MergeOperationVisitor;
99102
import net.sf.jsqlparser.statement.merge.MergeOperationVisitorAdapter;
@@ -708,6 +711,21 @@ public <S> T visit(TableMaintenanceStatement statement, S context) {
708711
return null;
709712
}
710713

714+
@Override
715+
public <S> T visit(VacuumStatement vacuum, S context) {
716+
return null;
717+
}
718+
719+
@Override
720+
public <S> T visit(ClusterStatement cluster, S context) {
721+
return null;
722+
}
723+
724+
@Override
725+
public <S> T visit(CheckpointStatement checkpoint, S context) {
726+
return null;
727+
}
728+
711729
@Override
712730
public <S> T visit(SavepointStatement savepointStatement, S context) {
713731
// @todo: do something usefully here

0 commit comments

Comments
 (0)