@@ -179,6 +179,29 @@ func (p *Parser) parseCreateTable(temporary bool) (*ast.CreateTableStatement, er
179179 }
180180 stmt .Name = createTableName
181181
182+ // Snowflake: COPY GRANTS modifier before the column list or AS SELECT.
183+ // Consumed but not modeled on the AST.
184+ if strings .EqualFold (p .currentToken .Token .Value , "COPY" ) &&
185+ strings .EqualFold (p .peekToken ().Token .Value , "GRANTS" ) {
186+ p .advance () // COPY
187+ p .advance () // GRANTS
188+ }
189+
190+ // CREATE TABLE ... AS SELECT — no column list, just a query.
191+ if p .isType (models .TokenTypeAs ) {
192+ p .advance () // AS
193+ if p .isType (models .TokenTypeSelect ) || p .isType (models .TokenTypeWith ) {
194+ p .advance () // SELECT / WITH
195+ query , err := p .parseSelectWithSetOperations ()
196+ if err != nil {
197+ return nil , err
198+ }
199+ _ = query // CTAS query not modeled on CreateTableStatement yet
200+ return stmt , nil
201+ }
202+ return nil , p .expectedError ("SELECT after AS" )
203+ }
204+
182205 // Expect opening parenthesis for column definitions
183206 if ! p .isType (models .TokenTypeLParen ) {
184207 return nil , p .expectedError ("(" )
@@ -379,6 +402,19 @@ func (p *Parser) parseCreateTable(temporary bool) (*ast.CreateTableStatement, er
379402 break
380403 }
381404
405+ // Snowflake: CLUSTER BY (expr, ...) — defines the clustering key.
406+ if strings .EqualFold (p .currentToken .Token .Value , "CLUSTER" ) {
407+ p .advance () // CLUSTER
408+ if p .isType (models .TokenTypeBy ) {
409+ p .advance () // BY
410+ }
411+ if p .isType (models .TokenTypeLParen ) {
412+ if err := p .skipClickHouseClauseExpr (); err != nil {
413+ return nil , err
414+ }
415+ }
416+ }
417+
382418 // SQLite: optional WITHOUT ROWID clause
383419 if p .isTokenMatch ("WITHOUT" ) {
384420 p .advance () // Consume WITHOUT
0 commit comments