Skip to content

Commit b76d81c

Browse files
author
Miguel Molina
authored
Merge pull request #152 from erizocosmico/enhancement/custom-ops
api to create custom operators and docs on custom operators
2 parents 46982dc + dbffffa commit b76d81c

File tree

3 files changed

+168
-38
lines changed

3 files changed

+168
-38
lines changed

README.md

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ Support for arrays of all basic Go types and all JSON and arrays operators is pr
3434
* [Query with relationships](#query-with-relationships)
3535
* [Querying JSON](#querying-json)
3636
* [Transactions](#transactions)
37+
* [Caveats](#caveats)
38+
* [Custom operators](#custom-operators)
3739
* [Debug SQL queries](#debug-sql-queries)
3840
* [Benchmarks](#benchmarks)
3941
* [Acknowledgements](#acknowledgements)
@@ -604,6 +606,67 @@ store.Transaction(func(s *UserStore) error {
604606
* `time.Time` fields will be truncated to remove its nanoseconds on `Save`, `Insert` or `Update`, since PostgreSQL will not be able to store them. PostgreSQL stores times with timezones as UTC internally. So, times will come back as UTC (you can use `Local` method to convert them back to the local timezone). You can change the timezone that will be used to bring times back from the database in [the PostgreSQL configuration](https://www.postgresql.org/docs/9.6/static/datatype-datetime.html).
605607
* Multidimensional arrays or slices are **not supported** except inside a JSON field.
606608

609+
## Custom operators
610+
611+
You can create custom operators with kallax using the `NewOperator` and `NewMultiOperator` functions.
612+
613+
`NewOperator` creates an operator with the specified format. It returns a function that given a schema field and a value returns a condition.
614+
615+
The format is a string in which `:col:` will get replaced with the schema field and `:arg:` will be replaced with the value.
616+
617+
```go
618+
var Gt = kallax.NewOperator(":col: > :arg:")
619+
620+
// can be used like this:
621+
query.Where(Gt(SomeSchemaField, 9000))
622+
```
623+
624+
`NewMultiOperator` does exactly the same as the previous one, but it accepts a variable number of values.
625+
626+
```go
627+
var In = kallax.NewMultiOperator(":col: IN :arg:")
628+
629+
// can be used like this:
630+
query.Where(In(SomeSchemaField, 4, 5, 6))
631+
```
632+
633+
This function already takes care of wrapping `:arg:` with parenthesis.
634+
635+
### Further customization
636+
637+
If you need further customization, you can create your own custom operator.
638+
639+
You need these things:
640+
641+
* A condition constructor (the operator itself) that takes the field and the values to create the proper SQL expression.
642+
* A `ToSqler` that yields your SQL expression.
643+
644+
Imagine we want a greater than operator that only works with integers.
645+
646+
```go
647+
func GtInt(col kallax.SchemaField, n int) kallax.Condition {
648+
return func(schema kallax.Schema) kallax.ToSqler {
649+
// it is VERY important that all SchemaFields
650+
// are qualified using the schema
651+
return &gtInt{col.QualifiedName(schema), n}
652+
}
653+
}
654+
655+
type gtInt struct {
656+
col string
657+
val int
658+
}
659+
660+
func (g *gtInt) ToSql() (sql string, params []interface{}, err error) {
661+
return fmt.Sprintf("%s > ?", g.col), []interface{}{g.val}, nil
662+
}
663+
664+
// can be used like this:
665+
query.Where(GtInt(SomeSchemaField, 9000))
666+
```
667+
668+
With most of the operators, `NewOperator` and `NewMultiOperator` are enough, so the usage of these functions is preferred over the completely custom approach. Use it only if there is no other way to build your custom operator.
669+
607670
## Debug SQL queries
608671

609672
It is possible to debug the SQL queries being executed with kallax. To do that, you just need to call the `Debug` method of a store. This returns a new store with debugging enabled.

0 commit comments

Comments
 (0)