sqldocument

package
v2.0.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 11, 2026 License: MIT Imports: 7 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var CreateTypeMapping = map[string]CreateType{
	"procedure": SQLProcedure,
	"function":  SQLFunction,
	"type":      SQLType,
}
View Source
var CycleError = errors.New("Detected a dependency cycle")

Functions

func CopyToken

func CopyToken(s Scanner, target *[]Unparsed)

func NextTokenCopyingWhitespace

func NextTokenCopyingWhitespace(s Scanner, target *[]Unparsed)

NextTokenCopyingWhitespace is like s.NextToken(), but if whitespace is encountered it is simply copied into `target`. Upon return, the scanner is located at a non-whitespace token, and target is either unmodified or filled with some whitespace nodes.

func RecoverToNextStatement

func RecoverToNextStatement(s Scanner, StatementTokens []string)

func RecoverToNextStatementCopying

func RecoverToNextStatementCopying(s Scanner, target *[]Unparsed, StatementTokens []string)

func TopologicalSort

func TopologicalSort(input []Create) (output []Create, errpos Pos, err error)

Types

type Batch

type Batch struct {
	// Nodes contains all unparsed tokens accumulated before a statement.
	// These are prepended to CREATE statement bodies to preserve
	// leading whitespace and comments in the output.
	Nodes []Unparsed

	// DocString holds single-line comments that precede a statement.
	// These comments form the documentation for procedures/functions.
	// Reset when non-comment, non-whitespace tokens are encountered.
	DocString []PosString

	// TokenCalls tracks how many Token handlers have been
	// called in this batch. Can be used to enforce the validation rules
	// that procedures and functions must be alone in their batch.
	TokenCalls map[string]int

	// TokenHandlers maps reserved words to their processing functions.
	// When a ReservedWordToken is encountered, its lowercase form is
	// looked up here. If found, the handler is called with the scanner
	// and batch.
	// The handler returns 1 if parsing should continue
	// with a new batch (e.g., after processing a batch separator).
	// 		1 = break and parse a new batch
	// 		0 = continue (no return)
	//  	-1 = return false (stop parsing)
	TokenHandlers map[string]func(Scanner, *Batch) int

	// Errors accumulates parsing errors encountered during batch processing.
	// Errors are collected rather than stopping parsing immediately,
	// allowing partial results even with syntax errors.
	Errors []Error

	// BatchSeparatorHandler is called when a token is encountered.
	BatchSeparatorHandler func(Scanner, *Batch)
}

Batch represents a single SQL batch during parsing.

A batch is a sequence of SQL statements separated by a token in SQL. The Batch struct accumulates tokens and metadata while parsing, allowing handlers to process specific statement types (CREATE, DECLARE, etc.).

The parsing flow:

  1. Tokens are read sequentially via Parse()
  2. Whitespace and comments are accumulated in Nodes
  3. Single-line comments build up the DocString for documentation
  4. When a reserved word is encountered, its handler is invoked
  5. Handlers can consume additional tokens and update the batch state

func NewBatch

func NewBatch() *Batch

func (*Batch) Create

func (n *Batch) Create(s Scanner)

func (*Batch) HasErrors

func (n *Batch) HasErrors() bool

func (*Batch) Parse

func (n *Batch) Parse(s Scanner) bool

Parse processes tokens from the scanner and builds the batch's node list.

type Create

type Create struct {
	// CreateType specifies the type of object being created.
	// Valid values are "procedure", "function", or "type".
	CreateType CreateType

	// QuotedName is the name of the object being created, including square brackets.
	// For example: [MyProcedure].
	QuotedName PosString

	// Body contains the full body of the CREATE statement, including all tokens.
	// This includes the CREATE keyword, object definition, and any trailing comments.
	Body []Unparsed

	// DependsOn lists other objects that this CREATE statement depends on.
	// Each dependency is represented as a PosString.
	DependsOn []PosString

	// Docstring contains comments that precede the CREATE statement.
	// These comments are typically used for documentation purposes.
	Docstring []PosString

	// Driver specifies the SQL driver associated with this CREATE statement.
	// This is used to determine dialect-specific behavior.
	Driver driver.Driver
}

Create represents a SQL CREATE statement, such as a procedure, function, or type.

This struct captures the metadata and body of the CREATE statement, including:

  • The type of object being created (procedure, function, or type)
  • The quoted name of the object
  • The full body of the CREATE statement
  • Any dependencies on other objects
  • Docstring comments preceding the CREATE statement
  • The SQL driver associated with the statement

func (Create) DependsOnStrings

func (c Create) DependsOnStrings() (result []string)

func (Create) DocstringAsString

func (c Create) DocstringAsString() string

func (Create) DocstringYamldoc

func (c Create) DocstringYamldoc() (string, error)

func (Create) ParseYamlInDocstring

func (c Create) ParseYamlInDocstring(out any) error

func (Create) Serialize

func (c Create) Serialize(w io.StringWriter) error

func (Create) SerializeBytes

func (c Create) SerializeBytes(w io.Writer) error

func (Create) String

func (c Create) String() string

type CreateType

type CreateType int
const (
	SQLProcedure CreateType = iota
	SQLFunction
	SQLType
)

type Declare

type Declare struct {
	Start        Pos
	Stop         Pos
	VariableName string
	Datatype     Type
	Literal      Unparsed
}

func (Declare) String

func (d Declare) String() string

type Document

type Document interface {
	// Parse parses the input SQL document and populates the Document structure.
	Parse(input []byte, file FileRef) error
	// Returns true if the document contains no create statements or declarations
	Empty() bool
	// Returns true if the document contains any parsing errors
	HasErrors() bool
	// Returns the list of create statements in the document
	Creates() []Create
	// Returns the list of variable declarations in the document
	Declares() []Declare
	// Returns the list of parsing errors in the document
	Errors() []Error
	// Returns the list of pragma include-if statements in the document
	PragmaIncludeIf() []string
	// Includes the content of another Document into this one
	Include(other Document)
	// Performs a topological sort of the create statements based on their dependencies
	Sort()
}

Document represents a SQL document that needs to be deployed. It will contain declarations, create statements, pragmas, and errors. It provides methods to access and manipulate these components for supported database drivers

type Error

type Error struct {
	Pos     Pos
	Message string
}

func (Error) Error

func (e Error) Error() string

func (Error) WithoutPos

func (e Error) WithoutPos() Error

type FileRef

type FileRef string

FileRef is a dedicated type for file references, allowing future refactoring of how files are identified without changing the API.

type NotFoundError

type NotFoundError struct {
	Name string
}

func (NotFoundError) Error

func (n NotFoundError) Error() string

type Pos

type Pos struct {
	File      FileRef
	Line, Col int
}

Pos represents a position in a source file with line and column numbers. Line and column are 1-indexed for human-readable error messages.

type PosString

type PosString struct {
	Pos
	Value string
}

A string that has a Pos-ition in a source document

func ParseCodeschemaName

func ParseCodeschemaName(s Scanner, target *[]Unparsed, statementTokens []string) (PosString, error)

parseCodeschemaName parses `[code] . something`, and returns `something` in quoted form (`[something]`). Also copy to `target`. Empty string on error. Note: To follow conventions, consume one extra token at the end even if we know it fill not be consumed by this function...

func (PosString) String

func (p PosString) String() string

type Pragma

type Pragma struct {
	// contains filtered or unexported fields
}

func (*Pragma) ParsePragmas

func (d *Pragma) ParsePragmas(s Scanner) error

func (Pragma) PragmaIncludeIf

func (d Pragma) PragmaIncludeIf() []string

type Scanner

type Scanner interface {
	// TokenType returns the type of the current token.
	// This may return dialect-specific token types.
	TokenType() TokenType

	// Token returns the text of the current token.
	Token() string

	// File returns a reference to the source file being scanned.
	File() FileRef

	// TokenLower returns the current token text converted to lowercase.
	TokenLower() string

	// ReservedWord returns the lowercase reserved word if the current token
	// is a ReservedWordToken, or an empty string otherwise.
	ReservedWord() string

	// Start returns the position where the current token begins.
	Start() Pos

	// Stop returns the position where the current token ends.
	Stop() Pos

	// NextToken scans the next token and advances the scanner's position.
	NextToken() TokenType

	// NextNonWhitespaceToken advances to the next non-whitespace token.
	NextNonWhitespaceToken() TokenType

	// NextNonWhitespaceCommentToken advances to the next significant token.
	NextNonWhitespaceCommentToken() TokenType

	// SkipWhitespace advances past any whitespace tokens.
	SkipWhitespace()

	// SkipWhitespaceComments advances past any whitespace and comment tokens.
	SkipWhitespaceComments()

	// Set the scanner's input to the given byte slice.
	SetInput([]byte)

	// Set the scanner's input file reference.
	SetFile(FileRef)
}

Scanner defines the interface for lexical scanning of SQL source code.

This interface abstracts the Scanner implementation, enabling:

  • Unit testing with mock scanners
  • Alternative scanner implementations for different SQL dialects
  • Easier dependency injection in parsers

Implementations should return dialect-specific tokens from TokenType(), but CommonTokenType() should map these to common tokens for dialect-agnostic code.

type TokenType

type TokenType int

TokenType represents the type of a lexical token. Common tokens are defined in the range 1-999. Dialect-specific tokens use ranges starting at 1000, 2000, etc.

const (
	// CommonTokenStart is the start of common token range (1-999)
	CommonTokenStart TokenType = 1
	// TSQLTokenStart is the start of T-SQL specific tokens (1000-1999)
	TSQLTokenStart TokenType = 1000
	// PGSQLTokenStart is the start of PostgreSQL specific tokens (2000-2999)
	PGSQLTokenStart TokenType = 2000
)

Token range constants for dialect-specific extensions.

const (
	// Structural tokens
	EOFToken TokenType = iota + 1
	WhitespaceToken
	LeftParenToken
	RightParenToken
	SemicolonToken
	EqualToken
	CommaToken
	DotToken

	// Literals
	StringLiteralToken // Generic string literal (dialect determines quote style)
	NumberToken

	// Comments
	MultilineCommentToken
	SinglelineCommentToken

	// Identifiers
	ReservedWordToken
	IdentifierToken // Generic identifier (quoted or unquoted)
	QuotedIdentifierToken
	UnquotedIdentifierToken
	VariableIdentifierToken

	// Special
	OtherToken

	// Errors
	UnterminatedStringErrorToken
	UnterminatedIdentifierErrorToken
	NonUTF8ErrorToken

	// Batch/statement separation (common concept, dialect-specific syntax)
	BatchSeparatorToken
	MalformedBatchSeparatorToken

	// Pragma (sqlcode-specific)
	PragmaToken
)

Common tokens shared across all SQL dialects. These represent fundamental SQL constructs.

type Type

type Type struct {
	BaseType string
	Args     []string
}

func (Type) String

func (t Type) String() (result string)

type Unparsed

type Unparsed struct {
	Type        TokenType
	Start, Stop Pos
	RawValue    string
}

func CreateUnparsed

func CreateUnparsed(s Scanner) Unparsed

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL