You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: sqldb.go
    path of file: ./repos/encore/v2/parser/infra/sqldb
    
    the code of the file until where you have to start completion: package sqldb

import (
	"bytes"
	"errors"
	"fmt"
	"go/ast"
	"go/token"
	"io/fs"
	"os"
	"path"
	"path/filepath"
	"regexp"
	"sort"
	"strconv"
	"strings"

	"encr.dev/pkg/option"
	"encr.dev/pkg/paths"
	"encr.dev/v2/internals/pkginfo"
	"encr.dev/v2/parser/infra/internal/literals"
	"encr.dev/v2/parser/infra/internal/parseutil"
	"encr.dev/v2/parser/resource"
	"encr.dev/v2/parser/resource/resourceparser"
)

type Database struct {
	AST          *ast.CallExpr
	Pkg          *pkginfo.Package
	Name         string // The database name
	Doc          string
	File         option.Option[*pkginfo.File]
	MigrationDir paths.MainModuleRelSlash
	Migrations   []MigrationFile
}

func (d *Database) Kind() resource.Kind       { return resource.SQLDatabase }
func (d *Database) Package() *pkginfo.Package { return d.Pkg }
func (d *Database) ResourceName() string      { return d.Name }
func (d *Database) Pos() token.Pos            { return token.NoPos }
func (d *Database) End() token.Pos            { return token.NoPos }
func (d *Database) SortKey() string           { return d.Name }

type MigrationFile struct {
	Filename    string
	Number      uint64
	Description string
}

var DatabaseParser = &resourceparser.Parser{
	Name: "SQL Database",

	InterestingImports: []paths.Pkg{"encore.dev/storage/sqldb"},
	Run: func(p *resourceparser.Pass) {
		name := pkginfo.QualifiedName{Pk
    
func parseMigrations(migrationDir paths.FS) ([]MigrationFile, error) {
	files, err := os.ReadDir(migrationDir.ToIO())
	if err != nil {
		return nil, fmt.Errorf("could not read migrations: %v", err)
	}
	migrations := make([]MigrationFile, 0, len(files))
	for _, f := range files {
		if f.IsDir() {
			continue
		}

		// If the file is not an SQL file ignore it, to allow for other files to be present
		// in the migration directory. For SQL files we want to ensure they're properly named
		// so that we complain loudly about potential typos. (It's theoretically possible to
		// typo the filename extension as well, but it's less likely due to syntax highlighting).
		if filepath.Ext(strings.ToLower(f.Name())) != ".sql" {
			continue
		}

		match := migrationRe.FindStringSubmatch(f.Name())
		if match == nil {
			return nil, fmt.Errorf("db migration %s: invalid name (must be of the format '[123]_[description].[up|down].sql')",
				f.Name())
		}
		num, err := strconv.ParseUint(match[1], 10, 64)
		if err != nil {
			return nil, fmt.Errorf("db migration %s: invalid version number %q (must be a positive integer)",
				f.Name(), match[1])
		}

		description := strings.TrimPrefix(match[2], "_")
		if match[3] == "up" {
			migrations = append(migrations, MigrationFile{
				Filename:    f.Name(),
				Number:      num,
				Description: description,
			})
		}
	}
	sort.Slice(migrations, func(i, j int) bool {
		return migrations[i].Number < migrations[j].Number
	})

	// Catch invalid migration numbers.
	seen := make(map[uint64]bool, len(migrations))
	for _, mig := range migrations {
		fn, num := mig.Filename, mig.Number
		if num <= 0 {
			return nil, fmt.Errorf("db migration %s: invalid migration number %d", fn, num)
		} else if seen[num] {
			return nil, fmt.Errorf("db migration %s: duplicate migration with number %d", fn, num)
		}
		seen[num] = true
	}

	return migrations, nil
}