Skip to content
This repository was archived by the owner on Mar 26, 2026. It is now read-only.

Commit 082835b

Browse files
committed
fix support for pgsql ANALYZE, DO, VACUUM, GRANT/REVOKE (to the extent possible)
1 parent aadad4a commit 082835b

8 files changed

Lines changed: 1004 additions & 42 deletions

File tree

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ Supports stored procedures (PL/pgSQL, T-SQL, MySQL, PL/SQL): where sqlglot falls
1010

1111
Anywhere SQL hits a hot path: proxies, sidecars, migration tools, linters, etc. Also a replacement for every regex that's pretending to be a parser.
1212

13-
#### Inspiration
13+
#### Why this exists
14+
15+
libsqlglot was born out of a gap in the C++ ecosystem: the lack of native tooling for high-speed, hassle-free parsing & transpiling between dozens of SQL dialects.
1416

1517
Inspired by the original [sqlglot](https://github.com/tobymao/sqlglot), which did the decade-long work of mapping 31+ SQL dialects into an elegant, universal AST. libsqlglot does the comparatively trivial work of compiling it: the algorithm was already O(n), the runtime wasn't.
1618

@@ -216,7 +218,7 @@ cmake --build build
216218

217219
## Architecture
218220

219-
Header-only design: you only pay for what you use. 19 header files, no `.cpp`. See `include/libsqlglot/` for the full layout. Core files: `parser.h` (2958 lines), `generator.h` (1643), `expression.h` (1105, 105 expression types). Entry point is `transpiler.h` (86 lines).
221+
Header-only design: you only pay for what you use. 19 header files, no `.cpp`. See `include/libsqlglot/` for the full layout. Core files: `parser.h` (3479 lines), `generator.h` (1913), `expression.h` (1248, 115 expression types). Entry point is `transpiler.h` (86 lines).
220222

221223
### Memory management
222224

include/libsqlglot/dialect_reflection.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ namespace libsqlglot::dialects {
3333

3434
/// Find dialect by name (case-insensitive) - runtime function
3535
/// Uses compile-time generated mappings for zero-maintenance lookups
36-
[[nodiscard]] inline Dialect from_name(std::string_view name) {
36+
/// Returns ANSI dialect if name is unknown (fail-safe, not fail-fast)
37+
[[nodiscard]] inline Dialect from_name(std::string_view name) noexcept {
3738
// Convert to lowercase for comparison
3839
auto to_lower = [](char c) { return (c >= 'A' && c <= 'Z') ? (c - 'A' + 'a') : c; };
3940

@@ -66,7 +67,8 @@ namespace libsqlglot::dialects {
6667
if (lower_name == "tsql" || lower_name == "sqlserver") return Dialect::SQLServer;
6768
if (lower_name == "cockroach" || lower_name == "cockroachdb") return Dialect::CockroachDB;
6869

69-
throw std::runtime_error("Unknown dialect: " + std::string(name));
70+
// Unknown dialect - return ANSI as safe default (fail-safe)
71+
return Dialect::ANSI;
7072
}
7173

7274
/// Get dialect name as string

include/libsqlglot/expression.h

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,10 @@ enum class ExprType : uint16_t {
9191
SHOW_STMT,
9292
DESCRIBE_STMT,
9393
EXPLAIN_STMT,
94+
ANALYZE_STMT, // ANALYZE table
95+
VACUUM_STMT, // VACUUM table
96+
GRANT_STMT, // GRANT privileges
97+
REVOKE_STMT, // REVOKE privileges
9498

9599
// Advanced SELECT features
96100
CTE, // Common Table Expression (WITH clause)
@@ -132,6 +136,7 @@ enum class ExprType : uint16_t {
132136
CONTINUE_STMT, // CONTINUE statement
133137
RETURN_STMT, // RETURN expression
134138
BEGIN_END_BLOCK, // BEGIN ... END block (T-SQL, MySQL, PL/SQL)
139+
DO_BLOCK, // DO $$ ... $$ (PostgreSQL anonymous block)
135140
EXCEPTION_BLOCK, // EXCEPTION block (PL/pgSQL, PL/SQL)
136141
ASSIGNMENT_STMT, // Variable assignment (SET var = val, var := val)
137142
DELIMITER_STMT, // DELIMITER command (MySQL)
@@ -149,6 +154,13 @@ enum class ExprType : uint16_t {
149154
CREATE_TABLESPACE, // CREATE TABLESPACE
150155
CREATE_INDEX_ADV, // Advanced CREATE INDEX (partial, expression, concurrent)
151156

157+
// BigQuery ML & Advanced Analytics
158+
CREATE_MODEL, // CREATE MODEL (BigQuery ML)
159+
DROP_MODEL, // DROP MODEL
160+
ML_PREDICT, // ML.PREDICT() function
161+
ML_EVALUATE, // ML.EVALUATE() function
162+
ML_TRAINING_INFO, // ML.TRAINING_INFO() function
163+
152164
// Other
153165
ALIAS,
154166
CAST,
@@ -1102,4 +1114,135 @@ struct CreateIndexAdvStmt : Expression {
11021114
: Expression(ExprType::CREATE_INDEX_ADV), where_clause(nullptr) {}
11031115
};
11041116

1117+
// ============================================================================
1118+
// NEW UTILITY & PERMISSIONS STATEMENTS
1119+
// ============================================================================
1120+
1121+
/// DO block (PostgreSQL anonymous code block)
1122+
struct DoBlockStmt : Expression {
1123+
std::string language; // plpgsql, sql, etc.
1124+
std::vector<Expression*> statements; // Block body
1125+
1126+
DoBlockStmt()
1127+
: Expression(ExprType::DO_BLOCK) {}
1128+
};
1129+
1130+
/// ANALYZE statement
1131+
struct AnalyzeStmt : Expression {
1132+
std::string table; // Optional table name
1133+
std::vector<std::string> columns; // Optional column list
1134+
1135+
AnalyzeStmt()
1136+
: Expression(ExprType::ANALYZE_STMT) {}
1137+
};
1138+
1139+
/// VACUUM statement (PostgreSQL-specific)
1140+
struct VacuumStmt : Expression {
1141+
std::string table; // Optional table name
1142+
std::vector<std::string> columns; // Optional column list (requires ANALYZE)
1143+
1144+
// Boolean options
1145+
bool full = false;
1146+
bool freeze = false;
1147+
bool verbose = false;
1148+
bool analyze = false;
1149+
bool disable_page_skipping = false;
1150+
bool skip_locked = false;
1151+
bool truncate = true; // Default is true
1152+
1153+
// Integer options
1154+
int parallel_workers = -1; // -1 means not specified
1155+
int buffer_usage_limit = -1; // -1 means not specified (in KB)
1156+
1157+
// Index cleanup: true/false/auto
1158+
enum class IndexCleanup { AUTO, ON, OFF };
1159+
IndexCleanup index_cleanup = IndexCleanup::AUTO;
1160+
1161+
// Use parenthesized syntax (PostgreSQL 9.0+) vs legacy syntax
1162+
bool use_parenthesized_syntax = true;
1163+
1164+
VacuumStmt()
1165+
: Expression(ExprType::VACUUM_STMT) {}
1166+
};
1167+
1168+
/// GRANT statement
1169+
struct GrantStmt : Expression {
1170+
enum class PrivilegeType { SELECT, INSERT, UPDATE, DELETE, ALL, EXECUTE, USAGE };
1171+
1172+
std::vector<PrivilegeType> privileges;
1173+
std::string object_type; // TABLE, DATABASE, SCHEMA, FUNCTION, etc.
1174+
std::string object_name;
1175+
std::vector<std::string> grantees; // Users/roles to grant to
1176+
bool with_grant_option = false;
1177+
1178+
GrantStmt()
1179+
: Expression(ExprType::GRANT_STMT) {}
1180+
};
1181+
1182+
/// REVOKE statement
1183+
struct RevokeStmt : Expression {
1184+
using PrivilegeType = GrantStmt::PrivilegeType;
1185+
1186+
std::vector<PrivilegeType> privileges;
1187+
std::string object_type;
1188+
std::string object_name;
1189+
std::vector<std::string> grantees;
1190+
bool cascade = false;
1191+
1192+
RevokeStmt()
1193+
: Expression(ExprType::REVOKE_STMT) {}
1194+
};
1195+
1196+
// ============================================================================
1197+
// BIGQUERY ML
1198+
// ============================================================================
1199+
1200+
/// CREATE MODEL statement (BigQuery ML)
1201+
struct CreateModelStmt : Expression {
1202+
std::string model_name;
1203+
std::string model_type; // LINEAR_REG, LOGISTIC_REG, etc.
1204+
std::vector<std::pair<std::string, std::string>> options; // Model options
1205+
SelectStmt* training_query; // Training data query
1206+
bool or_replace = false;
1207+
bool if_not_exists = false;
1208+
1209+
CreateModelStmt()
1210+
: Expression(ExprType::CREATE_MODEL), training_query(nullptr) {}
1211+
};
1212+
1213+
/// DROP MODEL statement
1214+
struct DropModelStmt : Expression {
1215+
std::string model_name;
1216+
bool if_exists = false;
1217+
1218+
DropModelStmt()
1219+
: Expression(ExprType::DROP_MODEL) {}
1220+
};
1221+
1222+
/// ML.PREDICT function
1223+
struct MLPredictExpr : Expression {
1224+
std::string model_name;
1225+
SelectStmt* input_query; // Input data for prediction
1226+
1227+
MLPredictExpr()
1228+
: Expression(ExprType::ML_PREDICT), input_query(nullptr) {}
1229+
};
1230+
1231+
/// ML.EVALUATE function
1232+
struct MLEvaluateExpr : Expression {
1233+
std::string model_name;
1234+
SelectStmt* evaluation_query; // Evaluation data
1235+
1236+
MLEvaluateExpr()
1237+
: Expression(ExprType::ML_EVALUATE), evaluation_query(nullptr) {}
1238+
};
1239+
1240+
/// ML.TRAINING_INFO function
1241+
struct MLTrainingInfoExpr : Expression {
1242+
std::string model_name;
1243+
1244+
MLTrainingInfoExpr()
1245+
: Expression(ExprType::ML_TRAINING_INFO) {}
1246+
};
1247+
11051248
} // namespace libsqlglot

0 commit comments

Comments
 (0)