55package sqlc
66
77import (
8+ "cmp"
89 "encoding/json"
10+ "fmt"
911 "os"
12+ "slices"
13+ "strings"
1014)
1115
1216// Catalog represents the root structure of a sqlc catalog file.
@@ -35,7 +39,8 @@ func LoadCatalog(path string) (*Catalog, error) {
3539type Schema struct {
3640 Name string `json:"name"`
3741 Tables []Table `json:"tables,omitempty"`
38- Attrs
42+ // Inherit common attributes
43+ Attributes
3944}
4045
4146// Table represents a database table with its columns, indexes, and constraints.
@@ -45,15 +50,69 @@ type Table struct {
4550 Indexes []Index `json:"indexes,omitempty"`
4651 PrimaryKey * Index `json:"primary_key,omitempty"`
4752 ForeignKeys []ForeignKey `json:"foreign_keys,omitempty"`
48- Attrs
53+ // Inherit common attributes
54+ Attributes
55+ }
56+
57+ // GetColumn retrieves a column by name from the table.
58+ func (x * Table ) GetColumn (name string ) * Column {
59+ for _ , column := range x .Columns {
60+ if column .Name == name {
61+ return & column
62+ }
63+ }
64+
65+ return nil
66+ }
67+
68+ // GetNonUniqueIndexes retrieves all non-unique indexes from the table.
69+ func (x * Table ) GetNonUniqueIndexes () []* Index {
70+ var keys []* Index
71+
72+ for _ , index := range x .Indexes {
73+ if index .HasExpr () {
74+ continue
75+ }
76+
77+ if ! index .Unique {
78+ index .Name = cmp .Or (index .Name , "non-unique key" )
79+ keys = append (keys , & index )
80+ }
81+ }
82+
83+ return keys
84+ }
85+
86+ // GetUniqueKeys retrieves all unique keys (primary key and unique indexes) from the table.
87+ func (x * Table ) GetUniqueKeys () []* Index {
88+ var keys []* Index
89+
90+ if x .PrimaryKey != nil {
91+ x .PrimaryKey .Name = cmp .Or (x .PrimaryKey .Name , "primary key" )
92+ keys = append (keys , x .PrimaryKey )
93+ }
94+
95+ for _ , index := range x .Indexes {
96+ if index .HasExpr () {
97+ continue
98+ }
99+
100+ if index .Unique {
101+ index .Name = cmp .Or (index .Name , "unique key" )
102+ keys = append (keys , & index )
103+ }
104+ }
105+
106+ return keys
49107}
50108
51109// Column represents a table column with its name, data type, and nullability.
52110type Column struct {
53111 Name string `json:"name"`
54112 Type string `json:"type,omitempty"`
55113 Null bool `json:"null,omitempty"`
56- Attrs
114+ // Inherit common attributes
115+ Attributes
57116}
58117
59118// Index represents a database index on one or more columns or expressions.
@@ -63,6 +122,13 @@ type Index struct {
63122 Parts []IndexPart `json:"parts,omitempty"`
64123}
65124
125+ // HasExpr checks if the index contains any expression-based parts.
126+ func (x * Index ) HasExpr () bool {
127+ return slices .ContainsFunc (x .Parts , func (x IndexPart ) bool {
128+ return x .Expr != ""
129+ })
130+ }
131+
66132// IndexPart represents a single part of an index, which can be either a column or an expression.
67133type IndexPart struct {
68134 Desc bool `json:"desc,omitempty"`
@@ -81,9 +147,68 @@ type ForeignKey struct {
81147 } `json:"references"`
82148}
83149
84- // Attrs represents common attributes that can be applied to schemas, tables, and columns.
150+ // Condition represents a simple equality condition between a column and an argument.
151+ type Condition struct {
152+ Column * Column
153+ Argument * Argument
154+ }
155+
156+ // String returns the string representation of the Condition for use in SQL queries.
157+ func (x * Condition ) String () string {
158+ return fmt .Sprintf ("%s = %v" , x .Column .Name , x .Argument )
159+ }
160+
161+ // CompositeCondition represents a combination of multiple conditions using a logical operator (e.g., AND, OR).
162+ type CompositeCondition struct {
163+ Operator string
164+ Conditions []fmt.Stringer
165+ }
166+
167+ // AddColumn adds a new condition for the specified column to the CompositeCondition.
168+ func (x * CompositeCondition ) AddColumn (column * Column ) {
169+ x .Conditions = append (x .Conditions ,
170+ & Condition {
171+ Column : column ,
172+ Argument : & Argument {
173+ Column : column ,
174+ },
175+ },
176+ )
177+ }
178+
179+ // String returns the string representation of the CompositeCondition for use in SQL queries.
180+ func (x * CompositeCondition ) String () string {
181+ var items []string
182+
183+ for _ , condition := range x .Conditions {
184+ if expression := condition .String (); expression != "" {
185+ items = append (items , expression )
186+ }
187+ }
188+
189+ if len (items ) == 0 {
190+ return ""
191+ }
192+
193+ return strings .Join (items , fmt .Sprintf (" %s " , x .Operator ))
194+ }
195+
196+ // Argument represents SQL argument corresponding to a column.
197+ type Argument struct {
198+ Column * Column `json:"column"`
199+ }
200+
201+ // String returns the string representation of the Argument for use in SQL queries.
202+ func (x * Argument ) String () string {
203+ if x .Column .Null {
204+ return fmt .Sprintf ("sqlc.narg(%s)" , x .Column .Name )
205+ }
206+ return fmt .Sprintf ("sqlc.arg(%s)" , x .Column .Name )
207+ }
208+
209+ // Attributes represents common attributes that can be applied to schemas, tables, and columns.
85210// These are typically dialect-specific metadata.
86- type Attrs struct {
211+ type Attributes struct {
87212 Comment string `json:"comment,omitempty"`
88213 Charset string `json:"charset,omitempty"`
89214 Collate string `json:"collate,omitempty"`
0 commit comments