parseTypeArgsString consumes a balanced parenthesised type-argument list and returns it as a string (including the outer parens). Supports nested types like Array(Nullable(String)), Map(String, Array(UInt32)), Tuple(a UInt8, b String), DateTime64(3, 'UTC'), and engine arguments like ReplicatedMergeT
()
| 495 | // Tuple(a UInt8, b String), DateTime64(3, 'UTC'), and engine arguments like |
| 496 | // ReplicatedMergeTree('/path', '{replica}'). The current token must be '('. |
| 497 | func (p *Parser) parseTypeArgsString() (string, error) { |
| 498 | if !p.isType(models.TokenTypeLParen) { |
| 499 | return "", p.expectedError("(") |
| 500 | } |
| 501 | |
| 502 | var buf strings.Builder |
| 503 | depth := 0 |
| 504 | prevWasIdent := false // for inserting spaces between adjacent tokens (e.g. "a UInt8") |
| 505 | |
| 506 | for { |
| 507 | tok := p.currentToken.Token |
| 508 | switch tok.Type { |
| 509 | case models.TokenTypeEOF: |
| 510 | return "", p.expectedError(") to close type arguments") |
| 511 | case models.TokenTypeLParen: |
| 512 | buf.WriteByte('(') |
| 513 | depth++ |
| 514 | prevWasIdent = false |
| 515 | p.advance() |
| 516 | continue |
| 517 | case models.TokenTypeRParen: |
| 518 | buf.WriteByte(')') |
| 519 | depth-- |
| 520 | p.advance() |
| 521 | if depth == 0 { |
| 522 | return buf.String(), nil |
| 523 | } |
| 524 | prevWasIdent = false |
| 525 | continue |
| 526 | case models.TokenTypeComma: |
| 527 | buf.WriteString(", ") |
| 528 | prevWasIdent = false |
| 529 | p.advance() |
| 530 | continue |
| 531 | } |
| 532 | |
| 533 | // Render leaf token. Quote string literals; everything else is rendered |
| 534 | // by its raw value (numbers, identifiers, keywords like Nullable / Array). |
| 535 | val := tok.Value |
| 536 | if val == "" { |
| 537 | return "", p.expectedError("type argument") |
| 538 | } |
| 539 | |
| 540 | // Insert a space when two adjacent leaf tokens both look like identifiers |
| 541 | // or numbers — this preserves "name Type" pairs in named tuple elements. |
| 542 | if prevWasIdent { |
| 543 | buf.WriteByte(' ') |
| 544 | } |
| 545 | |
| 546 | switch tok.Type { |
| 547 | case models.TokenTypeString, models.TokenTypeSingleQuotedString, |
| 548 | models.TokenTypeDoubleQuotedString: |
| 549 | buf.WriteByte('\'') |
| 550 | buf.WriteString(val) |
| 551 | buf.WriteByte('\'') |
| 552 | prevWasIdent = false |
| 553 | default: |
| 554 | buf.WriteString(val) |
no test coverage detected