parseTableConstraint parses a table constraint (PRIMARY KEY, FOREIGN KEY, UNIQUE, CHECK)
()
| 340 | |
| 341 | // parseTableConstraint parses a table constraint (PRIMARY KEY, FOREIGN KEY, UNIQUE, CHECK) |
| 342 | func (p *Parser) parseTableConstraint() (*ast.TableConstraint, error) { |
| 343 | constraint := &ast.TableConstraint{} |
| 344 | |
| 345 | // Check for optional CONSTRAINT keyword (may already be consumed by caller) |
| 346 | if p.isType(models.TokenTypeConstraint) { |
| 347 | p.advance() // Consume CONSTRAINT |
| 348 | } |
| 349 | |
| 350 | // Check for optional constraint name (identifier that isn't a constraint type keyword) |
| 351 | // Constraint name comes before the constraint type (PRIMARY, FOREIGN, UNIQUE, CHECK) |
| 352 | if p.isType(models.TokenTypeIdentifier) && |
| 353 | !p.isAnyType(models.TokenTypePrimary, models.TokenTypeForeign, models.TokenTypeUnique, models.TokenTypeCheck) { |
| 354 | constraint.Name = p.currentToken.Token.Value |
| 355 | p.advance() |
| 356 | } |
| 357 | |
| 358 | // PRIMARY KEY (column_list) |
| 359 | if p.isType(models.TokenTypePrimary) { |
| 360 | p.advance() // Consume PRIMARY |
| 361 | if !p.isType(models.TokenTypeKey) { |
| 362 | return nil, p.expectedError("KEY after PRIMARY") |
| 363 | } |
| 364 | p.advance() // Consume KEY |
| 365 | constraint.Type = "PRIMARY KEY" |
| 366 | |
| 367 | // Parse column list |
| 368 | columns, err := p.parseConstraintColumnList() |
| 369 | if err != nil { |
| 370 | return nil, err |
| 371 | } |
| 372 | constraint.Columns = columns |
| 373 | return constraint, nil |
| 374 | } |
| 375 | |
| 376 | // FOREIGN KEY (column_list) REFERENCES table(column_list) |
| 377 | if p.isType(models.TokenTypeForeign) { |
| 378 | p.advance() // Consume FOREIGN |
| 379 | if !p.isType(models.TokenTypeKey) { |
| 380 | return nil, p.expectedError("KEY after FOREIGN") |
| 381 | } |
| 382 | p.advance() // Consume KEY |
| 383 | constraint.Type = "FOREIGN KEY" |
| 384 | |
| 385 | // Parse column list |
| 386 | columns, err := p.parseConstraintColumnList() |
| 387 | if err != nil { |
| 388 | return nil, err |
| 389 | } |
| 390 | constraint.Columns = columns |
| 391 | |
| 392 | // Expect REFERENCES |
| 393 | if !p.isType(models.TokenTypeReferences) { |
| 394 | return nil, p.expectedError("REFERENCES after FOREIGN KEY columns") |
| 395 | } |
| 396 | p.advance() // Consume REFERENCES |
| 397 | |
| 398 | // Parse referenced table (supports double-quoted identifiers) |
| 399 | if !p.isIdentifier() { |
no test coverage detected