### Full Usage Example Source: https://github.com/velmie/q2sql/blob/main/readme.md A complete example showing translator setup, builder configuration, query parsing, and SQL generation. ```go translator := q2sql.MapTranslator(map[string]string{ "id": "id", "title": "title", "body": "body", "author": "author", "createdAt": "created_at", }) allowedConditionsByField := q2sql.AllowedConditions{ "id": []string{condition.NameIn}, } builder := q2sql.NewResourceSelectBuilder( "articles", translator, q2sql.AllowSelectFields([]string{"id", "title", "author"}), q2sql.AllowFiltering( allowedConditionsByField, condition.DefaultConditionMap, q2sql.DefaultFilterExpressionParser, ), q2sql.AllowSortingByFields([]string{"created_at", "title"}), q2sql.Extend(extension.LimitOffsetPagination(extension.Unlimited, extension.Unlimited)), ) qstr := "?fields[articles]=id,title,author&filter[id]=in:1,2,3,4,5&sort=-createdAt,title&page[limit]=100" query, _ := qparser.ParseQuery(qstr) sqlizer, err := builder.Build(context.Background(), query) if err != nil { log.Fatal("failed to build query", err) } sqlStr, args, err := sqlizer.ToSql() if err != nil { log.Fatal("failed to build SQL query", err) } fmt.Println(sqlStr) fmt.Println(args) ``` -------------------------------- ### Complete q2sql API Example Source: https://context7.com/velmie/q2sql/llms.txt This example demonstrates setting up a translator, defining filtering rules, creating a configured builder, parsing a complex query string, adding custom conditions, and finally building and generating the SQL query with arguments. It covers field selection, filtering, sorting, and pagination. ```go package main import ( "context" "fmt" "log" "github.com/velmie/qparser" "github.com/velmie/q2sql" "github.com/velmie/q2sql/condition" "github.com/velmie/q2sql/extension" ) func main() { // 1. Setup translator for field name mapping translator := q2sql.MapTranslator(map[string]string{ "id": "id", "title": "title", "body": "body", "author": "author", "status": "status", "views": "view_count", "createdAt": "created_at", "updatedAt": "updated_at", }) // 2. Define filtering rules allowedConditions := q2sql.AllowedConditions{ "id": []string{condition.NameEq, condition.NameIn}, "title": []string{condition.NameContains, condition.NameStartsWith, condition.NameEq}, "author": []string{condition.NameEq, condition.NameIn}, "status": []string{condition.NameEq, condition.NameIn, condition.NameNeq}, "views": []string{condition.NameGt, condition.NameGe, condition.NameLt, condition.NameLe}, } // 3. Create fully configured builder builder := q2sql.NewResourceSelectBuilder( "articles", translator, q2sql.WithDefaultFields([]string{"id", "title", "author", "created_at"}), q2sql.AllowSelectFields([]string{"id", "title", "body", "author", "status", "view_count", "created_at", "updated_at"}), q2sql.AllowFiltering(allowedConditions, condition.DefaultConditionMap, q2sql.DefaultFilterExpressionParser), q2sql.AllowSortingByFields([]string{"created_at", "updated_at", "title", "view_count"}), q2sql.Extend( extension.LimitOffsetPagination(100, 10000), extension.DefaultLimit(20), ), ) // 4. Complex query example queryStr := "?fields[articles]=id,title,author,status,views" + "&filter[status]=in:published,featured" + "&filter[views]=gt:1000" + "&filter[title]=contains:golang" + "&sort=-createdAt,title" + "&page[limit]=25&page[offset]=50" query, err := qparser.ParseQuery(queryStr) if err != nil { log.Fatal("failed to parse query:", err) } // 5. Add custom conditions via SelectBuilder sb := new(q2sql.SelectBuilder) sb.Where(q2sql.IsNull("deleted_at")) // Soft delete filter // 6. Build the query _, err = builder.Build(context.Background(), query, sb) if err != nil { log.Fatal("failed to build query:", err) } // 7. Get final SQL sqlStr, args, err := sb.ToSQL() if err != nil { log.Fatal("failed to generate SQL:", err) } fmt.Println("SQL:", sqlStr) fmt.Println("Args:", args) } ``` -------------------------------- ### Enable Filtering with Custom Rules Source: https://github.com/velmie/q2sql/blob/main/readme.md Configure the builder to allow filtering by specifying allowed conditions per field, defining condition mappings, and providing a custom parser for filter arguments. This example sets up filtering for the 'id' field using the 'In' condition. ```go //... import ( // "github.com/velmie/q2sql" // "github.com/velmie/condition" //) //... // 1. how to create conditions based on the filter names conditions := q2sql.ConditionMap{ "any": condition.In, } // 2. which filters can be applied to which fields allowedConditionsByField := q2sql.AllowedConditions{ "id": []string{"any"}, } // 3. how to parse the filter query string // pseudocode: "filter[id]=any:1,2,3" -> { Field: "id", Filter: "any", Args: ["1", "2", "3"] } parser := q2sql.NewDelimitedArgsParser(':', ',') // use with builder const resourceName = "articles" builder := q2sql.NewResourceSelectBuilder( resourceName, translator, q2sql.WithDefaultFields(defaultFields), q2sql.AllowFiltering(allowedConditionsByField, conditions, parser), ) ``` -------------------------------- ### Initialize ResourceSelectBuilder Source: https://github.com/velmie/q2sql/blob/main/readme.md Create a new query builder for a specific resource. This requires the resource name, a translator, and optionally, default fields. ```go const resourceName = "articles" builder := q2sql.NewResourceSelectBuilder( resourceName, translator, q2sql.WithDefaultFields(defaultFields), ) ``` -------------------------------- ### condition Package: Built-in Conditions and Map Source: https://context7.com/velmie/q2sql/llms.txt Demonstrates the use of pre-built SQL conditions from the condition package and the DefaultConditionMap for creating various comparison operations. ```go package main import ( "fmt" "github.com/velmie/q2sql" "github.com/velmie/q2sql/condition" ) func main() { // Available condition names fmt.Println("Condition names:") fmt.Printf(" eq: %s\n", condition.NameEq) // "eq" fmt.Printf(" neq: %s\n", condition.NameNeq) // "neq" fmt.Printf(" lt: %s\n", condition.NameLt) // "lt" fmt.Printf(" le: %s\n", condition.NameLe) // "le" fmt.Printf(" gt: %s\n", condition.NameGt) // "gt" fmt.Printf(" ge: %s\n", condition.NameGe) // "ge" fmt.Printf(" in: %s\n", condition.NameIn) // "in" fmt.Printf(" null: %s\n", condition.NameIsNull) // "null" fmt.Printf(" notnull: %s\n", condition.NameIsNotNull) // "notnull" fmt.Printf(" contains: %s\n", condition.NameContains) // "contains" fmt.Printf(" startswith: %s\n", condition.NameStartsWith) // "startswith" fmt.Printf(" endswith: %s\n", condition.NameEndsWith) // "endswith" fmt.Printf(" like: %s\n", condition.NameLike) // "like" // Use conditions directly eqCond, _ := condition.Eq("status", "active") sql, args, _ := eqCond.ToSQL() fmt.Printf("Eq: %s %v\n", sql, args) // Output: Eq: status = ? [active] inCond, _ := condition.In("id", 1, 2, 3) sql, args, _ = inCond.ToSQL() fmt.Printf("In: %s %v\n", sql, args) // Output: In: id IN (?,?,?) [1 2 3] containsCond, _ := condition.Contains("title", "golang") sql, args, _ = containsCond.ToSQL() fmt.Printf("Contains: %s %v\n", sql, args) // Output: Contains: title LIKE ? [%golang%] // DefaultConditionMap contains all built-in conditions cm := condition.DefaultConditionMap gtCond, _ := cm.CreateCondition("gt") sqlizer, _ := gtCond("price", 100) sql, args, _ = sqlizer.ToSQL() fmt.Printf("Gt from map: %s %v\n", sql, args) // Output: Gt from map: price > ? [100] } ``` -------------------------------- ### Build SQL Query from URL Parameters Source: https://context7.com/velmie/q2sql/llms.txt Use NewResourceSelectBuilder to create a query builder for a specific database resource. Configure field mapping with a translator and set default fields. Then, parse URL query parameters and use the builder to generate a SQLizer object. ```go package main import ( "context" "fmt" "log" "github.com/velmie/qparser" "github.com/velmie/q2sql" "github.com/velmie/q2sql/condition" ) func main() { // Create a translator to map URL field names to database column names translator := q2sql.MapTranslator(map[string]string{ "id": "id", "title": "title", "body": "body", "author": "author", "createdAt": "created_at", }) // Create builder with resource name and translator builder := q2sql.NewResourceSelectBuilder( "articles", // table name translator, q2sql.WithDefaultFields([]string{"id", "title", "created_at"}), ) // Parse URL query and build SQL query, _ := qparser.ParseQuery("?fields[articles]=id,title") sqlizer, err := builder.Build(context.Background(), query) if err != nil { log.Fatal(err) } sqlStr, args, _ := sqlizer.ToSQL() fmt.Println(sqlStr) // Output: SELECT id, title FROM articles fmt.Println(args) // Output: [] } ``` -------------------------------- ### Initialize Translator Map Source: https://github.com/velmie/q2sql/blob/main/readme.md Create a translator to map URL string terms to SQL terms. This is essential for handling field name differences between the URL and the database schema. ```go translator := q2sql.MapTranslator(map[string]string{ "id": "id", "title": "title", "body": "body", "author": "author", "createdAt": "created_at", }) ``` -------------------------------- ### Extend Builder Functionality Source: https://github.com/velmie/q2sql/blob/main/readme.md Demonstrates extending the builder, such as adding LIMIT/OFFSET pagination support. ```go //... import ( "github.com/velmie/q2sql" "github.com/velmie/extension" ) //... var maxLimit, maxOffset int64 = 10, 1000 builder := q2sql.NewResourceSelectBuilder( resourceName, translator, q2sql.WithDefaultFields(defaultFields), q2sql.Extend(extension.LimitOffsetPagination(maxLimit, maxOffset)), ) ``` -------------------------------- ### Configure Sorting with AllowSortingByFields Source: https://context7.com/velmie/q2sql/llms.txt Defines which fields are valid for sorting. Use a '-' prefix in the URL parameter to indicate descending order. ```go package main import ( "context" "fmt" "github.com/velmie/qparser" "github.com/velmie/q2sql" ) func main() { translator := q2sql.MapTranslator(map[string]string{ "id": "id", "title": "title", "createdAt": "created_at", "views": "view_count", }) builder := q2sql.NewResourceSelectBuilder( "posts", translator, q2sql.AllowSelectFields([]string{"id", "title", "created_at", "view_count"}), q2sql.AllowSortingByFields([]string{"created_at", "title", "view_count"}), ) // Sort by multiple fields: descending createdAt, ascending title query, _ := qparser.ParseQuery("?fields[posts]=id,title&sort=-createdAt,title") sqlizer, _ := builder.Build(context.Background(), query) sqlStr, _, _ := sqlizer.ToSQL() fmt.Println(sqlStr) // Output: SELECT id, title FROM posts ORDER BY created_at DESC, title ASC // Disallowed sort field returns error query2, _ := qparser.ParseQuery("?fields[posts]=id&sort=id") _, err := builder.Build(context.Background(), query2) fmt.Printf("Error: %v\n", err) // Output: Error: field "id" not allowed for sorting criteria } ``` -------------------------------- ### Extend with LimitOffsetPagination Source: https://context7.com/velmie/q2sql/llms.txt Adds LIMIT and OFFSET support to the query builder. Supports setting maximum limits and offsets, or using extension.Unlimited for no restrictions. ```go package main import ( "context" "fmt" "log" "github.com/velmie/qparser" "github.com/velmie/q2sql" "github.com/velmie/q2sql/extension" ) func main() { translator := q2sql.MapTranslator(map[string]string{ "id": "id", "title": "title", }) // Set max limits: 100 items per page, 10000 max offset builder := q2sql.NewResourceSelectBuilder( "items", translator, q2sql.AllowSelectFields([]string{"id", "title"}), q2sql.Extend(extension.LimitOffsetPagination(100, 10000)), ) // Use pagination query, _ := qparser.ParseQuery("?fields[items]=id,title&page[limit]=25&page[offset]=50") sqlizer, _ := builder.Build(context.Background(), query) sqlStr, _, _ := sqlizer.ToSQL() fmt.Println(sqlStr) // Output: SELECT id, title FROM items LIMIT 25 OFFSET 50 // Unlimited pagination with extension.Unlimited (-1) unlimitedBuilder := q2sql.NewResourceSelectBuilder( "items", translator, q2sql.AllowSelectFields([]string{"id", "title"}), q2sql.Extend(extension.LimitOffsetPagination(extension.Unlimited, extension.Unlimited)), ) query2, _ := qparser.ParseQuery("?page[limit]=1000&page[offset]=50000") sqlizer2, _ := unlimitedBuilder.Build(context.Background(), query2) sqlStr2, _, _ := sqlizer2.ToSQL() fmt.Println(sqlStr2) // Output: SELECT id, title FROM items LIMIT 1000 OFFSET 50000 // Exceeding max limit returns error query3, _ := qparser.ParseQuery("?page[limit]=200") _, err := builder.Build(context.Background(), query3) if err != nil { log.Printf("Error: %v", err) // Output: Error: page limit cannot be greater than 100 } } ``` -------------------------------- ### Extend with LimitNumberPagination Source: https://context7.com/velmie/q2sql/llms.txt Provides an alternative pagination strategy using page size and page number parameters, which are internally converted to LIMIT and OFFSET. ```go package main import ( "context" "fmt" "github.com/velmie/qparser" "github.com/velmie/q2sql" "github.com/velmie/q2sql/extension" ) func main() { translator := q2sql.MapTranslator(map[string]string{ "id": "id", "name": "name", }) builder := q2sql.NewResourceSelectBuilder( "products", translator, q2sql.AllowSelectFields([]string{"id", "name"}), // Max 50 items per page q2sql.Extend(extension.LimitNumberPagination(50)), ) // Request page 3 with 20 items per page (offset = 20 * (3-1) = 40) query, _ := qparser.ParseQuery("?fields[products]=id,name&page[limit]=20&page[number]=3") sqlizer, _ := builder.Build(context.Background(), query) sqlStr, _, _ := sqlizer.ToSQL() fmt.Println(sqlStr) // Output: SELECT id, name FROM products LIMIT 20 OFFSET 40 } ``` -------------------------------- ### Enable Filtering with AllowFiltering Source: https://context7.com/velmie/q2sql/llms.txt Configures supported filter conditions for specific fields using a condition factory and expression parser. ```go package main import ( "context" "fmt" "github.com/velmie/qparser" "github.com/velmie/q2sql" "github.com/velmie/q2sql/condition" ) func main() { translator := q2sql.MapTranslator(map[string]string{ "id": "id", "title": "title", "status": "status", "createdAt": "created_at", }) // Define which filters can be applied to which fields allowedConditions := q2sql.AllowedConditions{ "id": []string{condition.NameIn, condition.NameEq}, "title": []string{condition.NameContains, condition.NameStartsWith, condition.NameEq}, "status": []string{condition.NameEq, condition.NameIn}, } builder := q2sql.NewResourceSelectBuilder( "articles", translator, q2sql.AllowSelectFields([]string{"id", "title", "status"}), q2sql.AllowFiltering( allowedConditions, condition.DefaultConditionMap, // Built-in condition factory q2sql.DefaultFilterExpressionParser, // Default parser uses ":" for name:args ), ) // Filter by multiple conditions query, _ := qparser.ParseQuery("?fields[articles]=id,title&filter[id]=in:1,2,3&filter[title]=contains:golang") sqlizer, _ := builder.Build(context.Background(), query) sqlStr, args, _ := sqlizer.ToSQL() fmt.Println(sqlStr) // Output: SELECT id, title FROM articles WHERE id IN (?,?,?) AND title LIKE ? fmt.Println(args) // Output: [1 2 3 %golang%] ``` -------------------------------- ### Build SQL Expressions with Q2SQL Source: https://context7.com/velmie/q2sql/llms.txt Use Q2SQL expression types to construct SQL WHERE clauses. Supports equality, inequality, IN, NOT IN, LIKE, IS NULL, IS NOT NULL, OR, AND, and NOT operators. ```go package main import ( "fmt" "github.com/velmie/q2sql" ) func main() { // Equality eq := &q2sql.Eq{Field: "status", Value: "active"} sql, args, _ := eq.ToSQL() fmt.Printf("Eq: %s %v\n", sql, args) // Output: Eq: status = ? [active] // Not equal neq := &q2sql.Neq{Field: "deleted", Value: true} sql, args, _ = neq.ToSQL() fmt.Printf("Neq: %s %v\n", sql, args) // Output: Neq: deleted != ? [true] // IN clause in := &q2sql.In{Field: "category", Values: []interface{}{"tech", "science", "art"}} sql, args, _ = in.ToSQL() fmt.Printf("In: %s %v\n", sql, args) // Output: In: category IN (?,?,?) [tech science art] // NOT IN clause notIn := &q2sql.NotIn{Field: "status", Values: []interface{}{"deleted", "archived"}} sql, args, _ = notIn.ToSQL() fmt.Printf("NotIn: %s %v\n", sql, args) // Output: NotIn: status NOT IN (?,?) [deleted archived] // LIKE clause like := &q2sql.Like{Field: "email", Value: "%@gmail.com"} sql, args, _ = like.ToSQL() fmt.Printf("Like: %s %v\n", sql, args) // Output: Like: email LIKE ? [%@gmail.com] // IS NULL isNull := q2sql.IsNull("deleted_at") sql, args, _ = isNull.ToSQL() fmt.Printf("IsNull: %s %v\n", sql, args) // Output: IsNull: deleted_at IS NULL [] // IS NOT NULL isNotNull := q2sql.IsNotNull("verified_at") sql, args, _ = isNotNull.ToSQL() fmt.Printf("IsNotNull: %s %v\n", sql, args) // Output: IsNotNull: verified_at IS NOT NULL [] // OR conditions or := q2sql.Or{ &q2sql.Eq{Field: "role", Value: "admin"}, &q2sql.Eq{Field: "role", Value: "moderator"}, } sql, args, _ = or.ToSQL() fmt.Printf("Or: %s %v\n", sql, args) // Output: Or: (role = ? OR role = ?) [admin moderator] // AND conditions and := q2sql.And{ &q2sql.Eq{Field: "active", Value: true}, &q2sql.Gt{Field: "age", Value: 18}, } sql, args, _ = and.ToSQL() fmt.Printf("And: %s %v\n", sql, args) // Output: And: (active = ? AND age > ?) [true 18] // NOT condition not := &q2sql.Not{Expr: &q2sql.Eq{Field: "banned", Value: true}} sql, args, _ = not.ToSQL() fmt.Printf("Not: %s %v\n", sql, args) // Output: Not: NOT (banned = ?) [true] // Raw SQL with arguments raw := &q2sql.RawSQLWithArgs{ SQL: "created_at > NOW() - INTERVAL ? DAY", Args: []interface{}{30}, } sql, args, _ = raw.ToSQL() fmt.Printf("Raw: %s %v\n", sql, args) // Output: Raw: created_at > NOW() - INTERVAL ? DAY [30] } ``` -------------------------------- ### Extend SelectBuilder with DefaultLimit Source: https://context7.com/velmie/q2sql/llms.txt Applies a default LIMIT to queries when no limit is specified by the client. Useful for ensuring a maximum number of results. ```go package main import ( "context" "fmt" "github.com/velmie/qparser" "github.com/velmie/q2sql" "github.com/velmie/q2sql/extension" ) func main() { ranslator := q2sql.MapTranslator(map[string]string{ "id": "id", "name": "name", }) builder := q2sql.NewResourceSelectBuilder( "items", translator, q2sql.AllowSelectFields([]string{"id", "name"}), q2sql.Extend( extension.LimitOffsetPagination(100, 10000), extension.DefaultLimit(20), // Default to 20 items if no limit specified ), ) // No pagination specified - uses default limit query, _ := qparser.ParseQuery("?fields[items]=id,name") sqlizer, _ := builder.Build(context.Background(), query) sqlStr, _, _ := sqlizer.ToSQL() fmt.Println(sqlStr) // Output: SELECT id, name FROM items LIMIT 20 } ``` -------------------------------- ### Configure AlwaysSelectAllFields Source: https://context7.com/velmie/q2sql/llms.txt Ignores client-specified field selections and forces the inclusion of all allowed fields in the SELECT statement. ```go package main import ( "context" "fmt" "github.com/velmie/qparser" "github.com/velmie/q2sql" ) func main() { translator := q2sql.MapTranslator(map[string]string{ "id": "id", "name": "name", "email": "email", "role": "role", }) builder := q2sql.NewResourceSelectBuilder( "users", translator, q2sql.AllowSelectFields([]string{"id", "name", "email", "role"}), q2sql.AlwaysSelectAllFields(true), ) // All allowed fields are selected even if client requests specific ones query, _ := qparser.ParseQuery("?fields[users]=id,name") sqlizer, _ := builder.Build(context.Background(), query) sqlStr, _, _ := sqlizer.ToSQL() fmt.Println(sqlStr) // Output: SELECT id, name, email, role FROM users } ``` -------------------------------- ### Define Default Fields Source: https://github.com/velmie/q2sql/blob/main/readme.md Specify the default fields to be used in the SELECT SQL statement. These fields are used when no fields are specified in the URL query and also serve as the initial list of allowed fields for selection. ```go // the list will be used latter defaultFields := []string{"id", "title", "created_at"} ``` -------------------------------- ### Configure AlwaysSelectAllFields Source: https://github.com/velmie/q2sql/blob/main/readme.md Forces the inclusion of all allowed or default fields in the generated SELECT statement. ```go builder := q2sql.NewResourceSelectBuilder( resourceName, translator, q2sql.AllowSelectFields(defaultFields), q2sql.AlwaysSelectAllFields(true), ) ``` -------------------------------- ### Apply Custom Conditions Source: https://github.com/velmie/q2sql/blob/main/readme.md Pass a custom SelectBuilder to the ResourceSelectBuilder to apply specific WHERE conditions. ```go sb := new(q2sql.SelectBuilder) sb.Where(&q2sql.Eq{"author", "Alan Turing"}) _, err := builder.Build(context.Background(), query, sb) ... ``` -------------------------------- ### Set Default Fields for SELECT Statement Source: https://context7.com/velmie/q2sql/llms.txt Use WithDefaultFields when creating a ResourceSelectBuilder to specify fields that should be included in the SELECT statement when no fields are explicitly requested in the URL query. These fields also serve as the initial set of allowed selection fields. ```go package main import ( "context" "fmt" "github.com/velmie/qparser" "github.com/velmie/q2sql" ) func main() { translator := q2sql.MapTranslator(map[string]string{ "id": "id", "title": "title", "body": "body", "author": "author", }) // Default fields are used when no fields are specified in the query builder := q2sql.NewResourceSelectBuilder( "posts", translator, q2sql.WithDefaultFields([]string{"id", "title", "author"}), ) // Query without fields parameter uses default fields query, _ := qparser.ParseQuery("?sort=title") sqlizer, _ := builder.Build(context.Background(), query) sqlStr, _, _ := sqlizer.ToSQL() fmt.Println(sqlStr) // Output: SELECT id, title, author FROM posts } ``` -------------------------------- ### Configure AlwaysSelectFields Source: https://context7.com/velmie/q2sql/llms.txt Forces specific fields to be included in the SELECT statement regardless of client requests. Useful for ensuring required fields like IDs or versioning columns are always present. ```go package main import ( "context" "fmt" "github.com/velmie/qparser" "github.com/velmie/q2sql" ) func main() { translator := q2sql.MapTranslator(map[string]string{ "id": "id", "title": "title", "status": "status", "version": "version", }) builder := q2sql.NewResourceSelectBuilder( "documents", translator, q2sql.AllowSelectFields([]string{"id", "title", "status", "version"}), // Always include id and version for optimistic locking q2sql.AlwaysSelectFields([]string{"id", "version"}), ) // Even though only title is requested, id and version are included query, _ := qparser.ParseQuery("?fields[documents]=title") sqlizer, _ := builder.Build(context.Background(), query) sqlStr, _, _ := sqlizer.ToSQL() fmt.Println(sqlStr) // Output: SELECT title, id, version FROM documents } ``` -------------------------------- ### Always Include Specific Fields in SELECT Source: https://github.com/velmie/q2sql/blob/main/readme.md Configure the builder to always include a predefined list of fields in the SELECT statement, regardless of whether they are requested by the client. This is useful for fields like 'status' that are always needed. ```go builder := q2sql.NewResourceSelectBuilder( resourceName, translator, q2sql.AllowSelectFields(defaultFields), q2sql.AlwaysSelectFields([]string{"status"}), ) ``` -------------------------------- ### Restrict Selectable Fields with AllowSelectFields Source: https://context7.com/velmie/q2sql/llms.txt Use this to explicitly define which fields are permitted in the SELECT clause. This configuration overrides any default fields set by WithDefaultFields. ```go package main import ( "context" "fmt" "github.com/velmie/qparser" "github.com/velmie/q2sql" ) func main() { translator := q2sql.MapTranslator(map[string]string{ "id": "id", "title": "title", "body": "body", "author": "author", "secret": "secret_data", }) builder := q2sql.NewResourceSelectBuilder( "posts", translator, q2sql.WithDefaultFields([]string{"id", "title"}), // Allow additional fields beyond defaults q2sql.AllowSelectFields([]string{"id", "title", "body", "author"}), // Can chain multiple calls // q2sql.AllowSelectFields([]string{"another_field"}), ) // Request allowed field query, _ := qparser.ParseQuery("?fields[posts]=id,title,body") sqlizer, _ := builder.Build(context.Background(), query) sqlStr, _, _ := sqlizer.ToSQL() fmt.Println(sqlStr) // Output: SELECT id, title, body FROM posts // Request disallowed field returns error query2, _ := qparser.ParseQuery("?fields[posts]=id,secret") _, err := builder.Build(context.Background(), query2) fmt.Printf("Error: %v\n", err) // Output: Error: field "secret" not allowed for selection criteria } ``` -------------------------------- ### Set Allowed Sorting Fields Source: https://github.com/velmie/q2sql/blob/main/readme.md Specify which fields can be used for sorting in the ORDER BY clause. This ensures that only permitted fields are used for sorting requests. ```go builder := q2sql.NewResourceSelectBuilder( resourceName, translator, q2sql.WithDefaultFields(defaultFields), q2sql.AllowSortingByFields([]string{"created_id", "title"}), ) ``` -------------------------------- ### SelectBuilder with Custom WHERE Conditions Source: https://context7.com/velmie/q2sql/llms.txt Adds custom WHERE conditions to a query using a SelectBuilder, which can be combined with URL-based filters. Allows for post-build modifications like removing sorting. ```go package main import ( "context" "fmt" "github.com/velmie/qparser" "github.com/velmie/q2sql" "github.com/velmie/q2sql/condition" "github.com/velmie/q2sql/extension" ) func main() { ranslator := q2sql.MapTranslator(map[string]string{ "id": "id", "title": "title", "author": "author", }) allowedConditions := q2sql.AllowedConditions{ "id": []string{condition.NameIn}, } builder := q2sql.NewResourceSelectBuilder( "articles", translator, q2sql.AllowSelectFields([]string{"id", "title", "author"}), q2sql.AllowFiltering(allowedConditions, condition.DefaultConditionMap, q2sql.DefaultFilterExpressionParser), q2sql.AllowSortingByFields([]string{"created_at", "title"}), q2sql.Extend(extension.LimitOffsetPagination(extension.Unlimited, extension.Unlimited)), ) query, _ := qparser.ParseQuery("?fields[articles]=id,title,author&filter[id]=in:1,2,3,4,5&sort=-createdAt,title&page[limit]=100") // Create SelectBuilder with custom conditions sb := new(q2sql.SelectBuilder) sb.Where(&q2sql.Eq{Field: "author", Value: "Alan Turing"}) // Build combines custom and URL-based conditions _, _ = builder.Build(context.Background(), query, sb) // Optionally modify after build (e.g., remove sorting) sb.OrderByParts = nil sqlStr, args, _ := sb.ToSQL() fmt.Println(sqlStr) // Output: SELECT id, title, author FROM articles WHERE author = ? AND id IN (?,?,?,?,?) LIMIT 100 fmt.Println(args) // Output: [Alan Turing 1 2 3 4 5] } ``` -------------------------------- ### Allow Additional Select Fields Source: https://github.com/velmie/q2sql/blob/main/readme.md Explicitly define additional fields that are permitted in the SELECT statement beyond the default fields. This option can be applied multiple times to add different sets of fields. ```go builder := q2sql.NewResourceSelectBuilder( resourceName, translator, q2sql.WithDefaultFields(defaultFields), q2sql.AllowSelectFields(defaultFields), q2sql.AllowSelectFields([]string{"body", "author"}), ) ``` -------------------------------- ### Create Field Name Translator with MapTranslator Source: https://context7.com/velmie/q2sql/llms.txt Use MapTranslator to create a function that maps URL parameter field names to database column names using a provided map. It returns a TranslationError if a field is not found in the map. This is useful for handling camelCase to snake_case conversions. ```go package main import ( "fmt" "github.com/velmie/q2sql" ) func main() { // Map URL parameter names to database column names translator := q2sql.MapTranslator(map[string]string{ "id": "id", "firstName": "first_name", // camelCase to snake_case "lastName": "last_name", "email": "email_address", "createdAt": "created_at", "isActive": "is_active", }) // Translate field names fields, err := translator([]string{"firstName", "lastName", "email"}) if err != nil { fmt.Printf("Translation error: %v\n", err) return } fmt.Println(fields) // Output: [first_name last_name email_address] // Unknown field returns error _, err = translator([]string{"unknownField"}) fmt.Printf("Error: %v\n", err) // Output: Error: failed to translate format of the "unknownField" entry because translation is not found } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.