• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

supabase / cli / 21442698789

28 Jan 2026 02:43PM UTC coverage: 51.225% (-5.0%) from 56.176%
21442698789

Pull #4770

github

web-flow
Merge 0b92817a1 into 3fe548f00
Pull Request #4770: feat: add `supabase dev` command

8 of 1187 new or added lines in 10 files covered. (0.67%)

5 existing lines in 1 file now uncovered.

6857 of 13386 relevant lines covered (51.23%)

5.76 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/internal/dev/validator.go
1
package dev
2

3
import (
4
        "fmt"
5

6
        "github.com/go-errors/errors"
7
        pg_query "github.com/pganalyze/pg_query_go/v6"
8
        "github.com/spf13/afero"
9
        "github.com/supabase/cli/internal/utils"
10
)
11

12
// ValidationError represents a SQL syntax error with location info
13
type ValidationError struct {
14
        File    string
15
        Line    int
16
        Column  int
17
        Message string
18
}
19

NEW
20
func (e *ValidationError) Error() string {
×
NEW
21
        return fmt.Sprintf("Syntax error in %s\n    Line %d, Column %d: %s\n    Waiting for valid SQL...",
×
NEW
22
                e.File, e.Line, e.Column, e.Message)
×
NEW
23
}
×
24

25
// ValidateSchemaFiles validates the SQL syntax of all schema files
26
// Returns nil if all files are valid, or the first error encountered
NEW
27
func ValidateSchemaFiles(files []string, fsys afero.Fs) error {
×
NEW
28
        for _, file := range files {
×
NEW
29
                if err := validateFile(file, fsys); err != nil {
×
NEW
30
                        return err
×
NEW
31
                }
×
32
        }
NEW
33
        return nil
×
34
}
35

36
// validateFile validates a single SQL file using pg_query (Postgres's actual parser)
NEW
37
func validateFile(path string, fsys afero.Fs) error {
×
NEW
38
        content, err := afero.ReadFile(fsys, path)
×
NEW
39
        if err != nil {
×
NEW
40
                return errors.Errorf("failed to read %s: %w", path, err)
×
NEW
41
        }
×
42

43
        // Empty files are valid
NEW
44
        if len(content) == 0 {
×
NEW
45
                return nil
×
NEW
46
        }
×
47

48
        // Parse the SQL using pg_query (Postgres's actual parser)
NEW
49
        _, err = pg_query.Parse(string(content))
×
NEW
50
        if err != nil {
×
NEW
51
                return parseError(path, string(content), err)
×
NEW
52
        }
×
53

NEW
54
        fmt.Fprintf(utils.GetDebugLogger(), "Validated: %s\n", path)
×
NEW
55
        return nil
×
56
}
57

58
// parseError converts a pg_query error into a ValidationError with location info
NEW
59
func parseError(file, content string, err error) error {
×
NEW
60
        errMsg := err.Error()
×
NEW
61

×
NEW
62
        // Default to line 1, column 1 if we can't parse the position
×
NEW
63
        line := 1
×
NEW
64
        column := 1
×
NEW
65

×
NEW
66
        // Try to extract position from error message
×
NEW
67
        // pg_query errors look like: "syntax error at or near \"xyz\" at position 123"
×
NEW
68
        var pos int
×
NEW
69
        if n, _ := fmt.Sscanf(errMsg, "syntax error at or near %*s at position %d", &pos); n == 1 && pos > 0 {
×
NEW
70
                line, column = offsetToLineCol(content, pos)
×
NEW
71
        }
×
72

NEW
73
        return &ValidationError{
×
NEW
74
                File:    file,
×
NEW
75
                Line:    line,
×
NEW
76
                Column:  column,
×
NEW
77
                Message: errMsg,
×
NEW
78
        }
×
79
}
80

81
// offsetToLineCol converts a byte offset to line and column numbers (1-indexed)
NEW
82
func offsetToLineCol(content string, offset int) (line, col int) {
×
NEW
83
        line = 1
×
NEW
84
        col = 1
×
NEW
85
        for i := 0; i < len(content) && i < offset; i++ {
×
NEW
86
                if content[i] == '\n' {
×
NEW
87
                        line++
×
NEW
88
                        col = 1
×
NEW
89
                } else {
×
NEW
90
                        col++
×
NEW
91
                }
×
92
        }
NEW
93
        return line, col
×
94
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc