@@ -123,12 +123,28 @@ func (p *Parser) parseStatement() ast.Statement {
123123 case token .CREATE :
124124 return p .parseCreate ()
125125 case token .DROP :
126+ // Check for DROP SETTINGS PROFILE
127+ if p .peekIs (token .SETTINGS ) {
128+ return p .parseDropSettingsProfile ()
129+ }
130+ // Check for DROP PROFILE
131+ if p .peek .Token == token .IDENT && strings .ToUpper (p .peek .Value ) == "PROFILE" {
132+ return p .parseDropSettingsProfile ()
133+ }
126134 return p .parseDrop ()
127135 case token .ALTER :
128136 // Check for ALTER USER
129137 if p .peekIs (token .USER ) {
130138 return p .parseAlterUser ()
131139 }
140+ // Check for ALTER SETTINGS PROFILE
141+ if p .peekIs (token .SETTINGS ) {
142+ return p .parseAlterSettingsProfile ()
143+ }
144+ // Check for ALTER PROFILE
145+ if p .peek .Token == token .IDENT && strings .ToUpper (p .peek .Value ) == "PROFILE" {
146+ return p .parseAlterSettingsProfile ()
147+ }
132148 return p .parseAlter ()
133149 case token .TRUNCATE :
134150 return p .parseTruncate ()
@@ -1314,6 +1330,9 @@ func (p *Parser) parseCreate() ast.Statement {
13141330 create .CreateUser = true
13151331 p .nextToken ()
13161332 p .parseCreateUser (create )
1333+ case token .SETTINGS :
1334+ // CREATE SETTINGS PROFILE
1335+ return p .parseCreateSettingsProfile (pos )
13171336 case token .IDENT :
13181337 // Handle CREATE DICTIONARY, CREATE RESOURCE, CREATE WORKLOAD, CREATE NAMED COLLECTION, etc.
13191338 identUpper := strings .ToUpper (p .current .Value )
@@ -1330,7 +1349,10 @@ func (p *Parser) parseCreate() ast.Statement {
13301349 p .nextToken ()
13311350 }
13321351 p .parseCreateGeneric (create )
1333- case "RESOURCE" , "WORKLOAD" , "POLICY" , "ROLE" , "QUOTA" , "PROFILE" :
1352+ case "PROFILE" :
1353+ // CREATE PROFILE (without SETTINGS keyword)
1354+ return p .parseCreateSettingsProfile (pos )
1355+ case "RESOURCE" , "WORKLOAD" , "POLICY" , "ROLE" , "QUOTA" :
13341356 // Skip these statements - just consume tokens until semicolon
13351357 p .parseCreateGeneric (create )
13361358 default :
@@ -1866,6 +1888,182 @@ func (p *Parser) parseCreateGeneric(create *ast.CreateQuery) {
18661888 }
18671889}
18681890
1891+ func (p * Parser ) parseCreateSettingsProfile (pos token.Position ) * ast.CreateSettingsProfileQuery {
1892+ query := & ast.CreateSettingsProfileQuery {
1893+ Position : pos ,
1894+ }
1895+
1896+ // Skip SETTINGS if present (CREATE SETTINGS PROFILE vs CREATE PROFILE)
1897+ if p .currentIs (token .SETTINGS ) {
1898+ p .nextToken ()
1899+ }
1900+
1901+ // Skip PROFILE
1902+ if p .currentIs (token .IDENT ) && strings .ToUpper (p .current .Value ) == "PROFILE" {
1903+ p .nextToken ()
1904+ }
1905+
1906+ // Handle IF NOT EXISTS
1907+ if p .currentIs (token .IF ) {
1908+ p .nextToken ()
1909+ if p .currentIs (token .NOT ) {
1910+ p .nextToken ()
1911+ }
1912+ if p .currentIs (token .EXISTS ) {
1913+ p .nextToken ()
1914+ }
1915+ }
1916+
1917+ // Parse profile names (can be multiple: s1, s2, s3)
1918+ for {
1919+ name := p .parseIdentifierName ()
1920+ if name != "" {
1921+ query .Names = append (query .Names , name )
1922+ }
1923+ if p .currentIs (token .COMMA ) {
1924+ p .nextToken ()
1925+ continue
1926+ }
1927+ break
1928+ }
1929+
1930+ // Skip the rest of the statement (SETTINGS, TO, etc.)
1931+ for ! p .currentIs (token .EOF ) && ! p .currentIs (token .SEMICOLON ) {
1932+ p .nextToken ()
1933+ }
1934+
1935+ return query
1936+ }
1937+
1938+ func (p * Parser ) parseDropSettingsProfile () * ast.DropSettingsProfileQuery {
1939+ query := & ast.DropSettingsProfileQuery {
1940+ Position : p .current .Pos ,
1941+ }
1942+
1943+ p .nextToken () // skip DROP
1944+
1945+ // Skip SETTINGS if present (DROP SETTINGS PROFILE vs DROP PROFILE)
1946+ if p .currentIs (token .SETTINGS ) {
1947+ p .nextToken ()
1948+ }
1949+
1950+ // Skip PROFILE
1951+ if p .currentIs (token .IDENT ) && strings .ToUpper (p .current .Value ) == "PROFILE" {
1952+ p .nextToken ()
1953+ }
1954+
1955+ // Handle IF EXISTS
1956+ if p .currentIs (token .IF ) {
1957+ p .nextToken ()
1958+ if p .currentIs (token .EXISTS ) {
1959+ query .IfExists = true
1960+ p .nextToken ()
1961+ }
1962+ }
1963+
1964+ // Parse profile names (can be multiple: s1, s2, s3)
1965+ for {
1966+ name := p .parseIdentifierName ()
1967+ if name != "" {
1968+ query .Names = append (query .Names , name )
1969+ }
1970+ if p .currentIs (token .COMMA ) {
1971+ p .nextToken ()
1972+ continue
1973+ }
1974+ break
1975+ }
1976+
1977+ // Skip the rest of the statement
1978+ for ! p .currentIs (token .EOF ) && ! p .currentIs (token .SEMICOLON ) {
1979+ p .nextToken ()
1980+ }
1981+
1982+ return query
1983+ }
1984+
1985+ func (p * Parser ) parseAlterSettingsProfile () * ast.AlterSettingsProfileQuery {
1986+ query := & ast.AlterSettingsProfileQuery {
1987+ Position : p .current .Pos ,
1988+ }
1989+
1990+ p .nextToken () // skip ALTER
1991+
1992+ // Skip SETTINGS if present (ALTER SETTINGS PROFILE vs ALTER PROFILE)
1993+ if p .currentIs (token .SETTINGS ) {
1994+ p .nextToken ()
1995+ }
1996+
1997+ // Skip PROFILE
1998+ if p .currentIs (token .IDENT ) && strings .ToUpper (p .current .Value ) == "PROFILE" {
1999+ p .nextToken ()
2000+ }
2001+
2002+ // Handle IF EXISTS
2003+ if p .currentIs (token .IF ) {
2004+ p .nextToken ()
2005+ if p .currentIs (token .EXISTS ) {
2006+ p .nextToken ()
2007+ }
2008+ }
2009+
2010+ // Parse profile names (can be multiple: s1, s2, s3)
2011+ for {
2012+ name := p .parseIdentifierName ()
2013+ if name != "" {
2014+ query .Names = append (query .Names , name )
2015+ }
2016+ if p .currentIs (token .COMMA ) {
2017+ p .nextToken ()
2018+ continue
2019+ }
2020+ break
2021+ }
2022+
2023+ // Skip the rest of the statement (SETTINGS, RENAME TO, etc.)
2024+ for ! p .currentIs (token .EOF ) && ! p .currentIs (token .SEMICOLON ) {
2025+ p .nextToken ()
2026+ }
2027+
2028+ return query
2029+ }
2030+
2031+ func (p * Parser ) parseShowCreateSettingsProfile (pos token.Position ) * ast.ShowCreateSettingsProfileQuery {
2032+ query := & ast.ShowCreateSettingsProfileQuery {
2033+ Position : pos ,
2034+ }
2035+
2036+ // Skip SETTINGS if present (SHOW CREATE SETTINGS PROFILE vs SHOW CREATE PROFILE)
2037+ if p .currentIs (token .SETTINGS ) {
2038+ p .nextToken ()
2039+ }
2040+
2041+ // Skip PROFILE
2042+ if p .currentIs (token .IDENT ) && strings .ToUpper (p .current .Value ) == "PROFILE" {
2043+ p .nextToken ()
2044+ }
2045+
2046+ // Parse profile names (can be multiple: s1, s2, s3)
2047+ for {
2048+ name := p .parseIdentifierName ()
2049+ if name != "" {
2050+ query .Names = append (query .Names , name )
2051+ }
2052+ if p .currentIs (token .COMMA ) {
2053+ p .nextToken ()
2054+ continue
2055+ }
2056+ break
2057+ }
2058+
2059+ // Skip the rest of the statement
2060+ for ! p .currentIs (token .EOF ) && ! p .currentIs (token .SEMICOLON ) {
2061+ p .nextToken ()
2062+ }
2063+
2064+ return query
2065+ }
2066+
18692067func (p * Parser ) parseCreateDictionary (create * ast.CreateQuery ) {
18702068 // Handle IF NOT EXISTS
18712069 if p .currentIs (token .IF ) {
@@ -3358,6 +3556,9 @@ func (p *Parser) parseShow() ast.Statement {
33583556 p .nextToken ()
33593557 }
33603558 return & ast.ShowCreateQuotaQuery {Position : pos , Name : name }
3559+ } else if p .currentIs (token .SETTINGS ) || (p .currentIs (token .IDENT ) && strings .ToUpper (p .current .Value ) == "PROFILE" ) {
3560+ // SHOW CREATE SETTINGS PROFILE or SHOW CREATE PROFILE
3561+ return p .parseShowCreateSettingsProfile (pos )
33613562 } else if p .currentIs (token .IDENT ) && strings .ToUpper (p .current .Value ) == "DICTIONARY" {
33623563 show .ShowType = ast .ShowCreateDictionary
33633564 p .nextToken ()
0 commit comments