cql

package module
v0.7.1 Latest Latest
Warning

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

Go to latest
Published: Nov 25, 2025 License: MPL-2.0 Imports: 12 Imported by: 4

README

CQL: Compiled Query Language

Build Status Go Report Card Quality Gate Status Coverage Awesome

Go.Dev reference Documentation Status

What is cql?

CQL is a SQL query language that allows easy and safe persistence and querying of objects, with the following characteristics:

  • Is compile-time safe: queries are validated at compile time to avoid errors such as comparing attributes that are of different types, trying to use attributes or navigate relationships that do not exist, using information from tables that are not included in the query, etc.; ensuring that a runtime error will not be raised.
  • Is easy to use: the use of its query system does not require knowledge of databases, SQL languages or complex concepts. Writing queries only requires programming in Go and the result is easy to read.
  • Is designed for real applications: the query system is designed to work well in real-world cases where queries are complex, require navigating multiple relationships, performing multiple comparisons, etc.
  • Is designed so that developers can focus on the business model: its queries allow easy retrieval of model relationships to apply business logic to the model and it provides mechanisms to avoid errors in the business logic due to mistakes in loading information from the database.
  • It is designed for high performance: the query system avoids as much as possible the use of reflection and aims that all the necessary model data can be retrieved in a single query to the database.
Language Query
SQL SELECT cities.* FROM cities
INNER JOIN countries ON
   countries.id = cities.country_id AND
   countries.name = "France"
WHERE cities.name = "Paris"
GORM db.Where(
 "cities.name = ?",
 "Paris",
).Joins(
 "Country",
 db.Where(
   "Country.name = ?",
   "France",
  ),
).Find(&cities)
CQL cql.Query[models.City](
  db,
  conditions.City.Name.Is().Eq(cql.String("Paris")),
  conditions.City.Country(
   conditions.Country.Name.Is().Eq(cql.String("France")),
  ),
).FindOne()

Is cql an ORM?

CQL built on top of gorm, a library that actually provides the functionality of an ORM: mapping objects to tables in the SQL database. While gorm does this job well with its automatic migration then performing queries on these objects is somewhat limited, forcing us to write SQL queries directly when they are complex.

CQL uses gorm for connecting to the database, generating queries in SQL format, and mapping values to structures in Go. On this basis, CQL builds a query language rather than an ORM, allowing us to work with both business entities and independent values.

Is cql a copy of gorm-gen?

It is true that its aim seems to be the same:

100% Type-safe DAO API without interface{}

Although gorm-gen provides a more structured API than gorm for performing queries, providing methods like:

Where(conds ...gen.Condition) IUserDo

we can see from this signatures that, for example, the Where method receives parameters of type gen.Condition. In this way, conditions from different models could be mixed without generating a compilation error:

u := query.User
c := query.Company
user, err := u.Where(c.Name.Eq("franco")).First()

which would generate a runtime error during the execution of the generated SQL:

SELECT * FROM `users` WHERE `companies`.`name` = "franco"
no such column: companies.name

Because of this, cql decides to go further in type safety and check that the conditions are of the correct model, that the compared values are of the same type, that the models are included in the query and more, ensuring that a runtime error will not be raised.

Documentation

https://compiledquerylenguage.readthedocs.io/en/latest/

Contributing

See this section to view the cql contribution guidelines.

License

CQL is Licensed under the Mozilla Public License Version 2.0.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrFieldModelNotConcerned   = condition.ErrFieldModelNotConcerned
	ErrAppearanceMustBeSelected = condition.ErrAppearanceMustBeSelected
	ErrAppearanceOutOfRange     = condition.ErrAppearanceOutOfRange

	ErrMoreThanOneObjectFound = condition.ErrMoreThanOneObjectFound
	ErrObjectNotFound         = condition.ErrObjectNotFound

	ErrUnsupportedByDatabase = condition.ErrUnsupportedByDatabase
	ErrOrderByMustBeCalled   = condition.ErrOrderByMustBeCalled

	ErrOnlyPreloadsAllowed = condition.ErrOnlyPreloadsAllowed
	ErrRelationNotLoaded   = preload.ErrRelationNotLoaded

	ErrPreloadsInDeleteReturningNotAllowed = condition.ErrPreloadsInDeleteReturningNotAllowed
)

Functions

func And

func And[T model.Model](firstCondition condition.WhereCondition[T], conditions ...condition.WhereCondition[T]) condition.WhereCondition[T]

And allows the connection of multiple conditions by the AND logical connector.

Its use is optional as it is the default connector.

Example:

cql.And(conditions.City.Name.Is().Eq("Paris"), conditions.City.ZipCode.Is().Eq("75000"))

func AndHaving added in v0.1.3

AndHaving allows the connection of multiple conditions by the AND logical connector.

Its use is optional as it is the default connector.

func Bool added in v0.1.3

func Bool(value bool) condition.BoolValue

func ByteArray added in v0.2.0

func ByteArray(value []byte) condition.Value[[]byte]

func CountAll added in v0.1.3

CountAll is an Aggregation that returns the number of values (including nulls)

Example:

cql.Query[models.Product](db).GroupBy(conditions.Product.Int).SelectValue(cql.CountAll(), "aggregation").Into(&results)

func Delete

func Delete[T model.Model](ctx context.Context, tx *DB, conditions ...condition.Condition[T]) *condition.Delete[T]

Create a Delete to which the conditions are applied inside transaction tx.

At least one condition is required to avoid deleting all values in a table. In case this is the desired behavior, use cql.True.

For details see https://compiledquerylenguage.readthedocs.io/en/latest/cql/delete.html

func Float32 added in v0.1.3

func Float32(value float32) condition.NumericValue[float32]

func Float64 added in v0.1.3

func Float64(value float64) condition.NumericValue[float64]

func Insert added in v0.4.0

func Insert[T model.Model](ctx context.Context, tx *DB, models ...*T) *condition.Insert[T]

Insert creates an INSERT statement that will allow to create the models received by parameter in the db and apply on conflict clauses

func Int added in v0.1.3

func Int(value int) condition.NumericValue[int]

func Int16 added in v0.1.3

func Int16(value int16) condition.NumericValue[int16]

func Int32 added in v0.1.3

func Int32(value int32) condition.NumericValue[int32]

func Int64 added in v0.1.3

func Int64(value int64) condition.NumericValue[int64]

func Int8 added in v0.1.3

func Int8(value int8) condition.NumericValue[int8]

func Not

func Not[T model.Model](firstCondition condition.WhereCondition[T], conditions ...condition.WhereCondition[T]) condition.WhereCondition[T]

Not allows the negation of the conditions within it. Multiple conditions are connected by an AND by default.

Example:

cql.Not(conditions.City.Name.Is().Eq("Paris"), conditions.City.Name.Is().Eq("Buenos Aires"))

translates as

NOT (name = "Paris" AND name = "Buenos Aires")

func NotHaving added in v0.1.3

NotHaving allows the negation of the conditions within it. Multiple conditions are connected by an AND by default.

func Or

func Or[T model.Model](firstCondition condition.WhereCondition[T], conditions ...condition.WhereCondition[T]) condition.WhereCondition[T]

Or allows the connection of multiple conditions by the OR logical connector.

Example:

cql.Or(conditions.City.Name.Is().Eq("Paris"), conditions.City.Name.Is().Eq("Buenos Aires"))

func OrHaving added in v0.1.3

OrHaving allows the connection of multiple conditions by the OR logical connector.

func Query

func Query[T model.Model](ctx context.Context, tx *DB, conditions ...condition.Condition[T]) *condition.Query[T]

Create a Query to which the conditions are applied inside transaction tx

For details see https://compiledquerylenguage.readthedocs.io/en/latest/cql/query.html

func Select added in v0.3.0

func Select[TResults any](
	query condition.IQuery,
	selections ...condition.Selection[TResults],
) ([]TResults, error)

Select specify fields that you want when querying.

Use Select when you only want a subset of the fields, not all the fields of a model

Use cql.ValueInto to generate the selections, for example:

// Select only sale.Code into a []Result
results, err := cql.Select(
	cql.Query[models.Sale](ts.db),
	cql.ValueInto(conditions.Sale.Code, func(value float64, result *Result) {
		result.Code = int(value)
	}),
)

func String added in v0.1.3

func String(value string) condition.Value[string]

func Time added in v0.2.0

func Time(value time.Time) condition.Value[time.Time]

func True added in v0.0.12

func True[T model.Model]() condition.Condition[T]

True represents a condition that is always true.

In general, it should not be used. It can only be useful in case you want to perform an operation on all models in a table.

func UInt added in v0.1.3

func UInt(value uint) condition.NumericValue[uint]

func UInt16 added in v0.1.3

func UInt16(value uint16) condition.NumericValue[uint16]

func UInt32 added in v0.1.3

func UInt32(value uint32) condition.NumericValue[uint32]

func UInt64 added in v0.1.3

func UInt64(value uint64) condition.NumericValue[uint64]

func UInt8 added in v0.1.3

func UInt8(value uint8) condition.NumericValue[uint8]

func UUID added in v0.2.0

func UUID(value model.UUID) condition.Value[model.UUID]

func Update

func Update[T model.Model](ctx context.Context, tx *DB, conditions ...condition.Condition[T]) *condition.Update[T]

Create a Update to which the conditions are applied inside transaction tx.

At least one condition is required to avoid updating all values in a table. In case this is the desired behavior, use cql.True.

For details see https://compiledquerylenguage.readthedocs.io/en/latest/cql/update.html

Types

type Config added in v0.5.0

type Config = gorm.Config

type DB added in v0.5.0

type DB struct {
	GormDB *gorm.DB
	// contains filtered or unexported fields
}

func (*DB) Transaction added in v0.6.0

func (db *DB) Transaction(
	ctx context.Context,
	toExec func(*DB) error,
	opts ...*sql.TxOptions,
) error

Transaction executes the function "toExec" inside a transaction The transaction is automatically rolled back in case "toExec" returns an error opts can be used to pass arguments to the transaction

type Dialector added in v0.5.0

type Dialector = gorm.Dialector

type LoggerFromContext added in v0.5.0

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

func WithLoggerFromContext added in v0.5.0

func WithLoggerFromContext(getLoggerFunc func(context.Context) logger.Interface) *LoggerFromContext

WithLoggerFromContext allows to set a way cql does all the logs from a logger that is in the context

func (*LoggerFromContext) AfterInitialize added in v0.5.0

func (*LoggerFromContext) AfterInitialize(*gorm.DB) error

func (*LoggerFromContext) Apply added in v0.5.0

func (*LoggerFromContext) Apply(*Config) error

type Option added in v0.5.0

type Option = gorm.Option

type ValueIntoSelection added in v0.3.0

type ValueIntoSelection[TValue any, TResults any] struct {
	// contains filtered or unexported fields
}

func ValueInto added in v0.3.0

func ValueInto[TValue any, TResults any](
	value condition.ValueOfType[TValue],
	selector func(TValue, *TResults),
) *ValueIntoSelection[TValue, TResults]

ValueInto allows the definition of a selection of a value into an attribute of the results

For example, to select sale.Code into result.Code:

cql.ValueInto(conditions.Sale.Code, func(value float64, result *Result) {
	result.Code = int(value)
})

func (ValueIntoSelection[TValue, TResults]) Apply added in v0.3.0

func (selection ValueIntoSelection[TValue, TResults]) Apply(value any, result *TResults) error

func (ValueIntoSelection[TValue, TResults]) ToSQL added in v0.3.0

func (selection ValueIntoSelection[TValue, TResults]) ToSQL(query *condition.CQLQuery) (string, []any, error)

func (ValueIntoSelection[TValue, TResults]) ValueType added in v0.3.0

func (selection ValueIntoSelection[TValue, TResults]) ValueType() any

Directories

Path Synopsis
cli module
cql-cli module
cql-gen module
cqllint module
conditions
Code generated by cql-gen v0.1.0, DO NOT EDIT.
Code generated by cql-gen v0.1.0, DO NOT EDIT.
models
Code generated by cql-gen v0.1.0, DO NOT EDIT.
Code generated by cql-gen v0.1.0, DO NOT EDIT.

Jump to

Keyboard shortcuts

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