mirror of
https://github.com/stashapp/stash.git
synced 2025-12-17 20:34:37 +03:00
File storage rewrite (#2676)
* Restructure data layer part 2 (#2599) * Refactor and separate image model * Refactor image query builder * Handle relationships in image query builder * Remove relationship management methods * Refactor gallery model/query builder * Add scenes to gallery model * Convert scene model * Refactor scene models * Remove unused methods * Add unit tests for gallery * Add image tests * Add scene tests * Convert unnecessary scene value pointers to values * Convert unnecessary pointer values to values * Refactor scene partial * Add scene partial tests * Refactor ImagePartial * Add image partial tests * Refactor gallery partial update * Add partial gallery update tests * Use zero/null package for null values * Add files and scan system * Add sqlite implementation for files/folders * Add unit tests for files/folders * Image refactors * Update image data layer * Refactor gallery model and creation * Refactor scene model * Refactor scenes * Don't set title from filename * Allow galleries to freely add/remove images * Add multiple scene file support to graphql and UI * Add multiple file support for images in graphql/UI * Add multiple file for galleries in graphql/UI * Remove use of some deprecated fields * Remove scene path usage * Remove gallery path usage * Remove path from image * Move funscript to video file * Refactor caption detection * Migrate existing data * Add post commit/rollback hook system * Lint. Comment out import/export tests * Add WithDatabase read only wrapper * Prepend tasks to list * Add 32 pre-migration * Add warnings in release and migration notes
This commit is contained in:
4
vendor/github.com/doug-martin/goqu/v9/.gitignore
generated
vendored
Normal file
4
vendor/github.com/doug-martin/goqu/v9/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
.idea
|
||||
src
|
||||
*.iml
|
||||
coverage.*
|
||||
140
vendor/github.com/doug-martin/goqu/v9/.golangci.yml
generated
vendored
Normal file
140
vendor/github.com/doug-martin/goqu/v9/.golangci.yml
generated
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
linters-settings:
|
||||
funlen:
|
||||
lines: 140
|
||||
statements: 50
|
||||
gci:
|
||||
local-prefixes: github.com/golangci/golangci-lint
|
||||
goconst:
|
||||
min-len: 2
|
||||
min-occurrences: 2
|
||||
gocritic:
|
||||
enabled-tags:
|
||||
- diagnostic
|
||||
- experimental
|
||||
- opinionated
|
||||
- performance
|
||||
- style
|
||||
disabled-checks:
|
||||
- dupImport # https://github.com/go-critic/go-critic/issues/845
|
||||
- ifElseChain
|
||||
- octalLiteral
|
||||
- whyNoLint
|
||||
- wrapperFunc
|
||||
- sqlQuery # used by tests
|
||||
gocyclo:
|
||||
min-complexity: 20
|
||||
goimports:
|
||||
local-prefixes: github.com/golangci/golangci-lint
|
||||
golint:
|
||||
min-confidence: 0
|
||||
gomnd:
|
||||
settings:
|
||||
mnd:
|
||||
# don't include the "operation" and "assign"
|
||||
checks: argument,case,condition,return
|
||||
govet:
|
||||
check-shadowing: true
|
||||
settings:
|
||||
printf:
|
||||
funcs:
|
||||
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Infof
|
||||
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Warnf
|
||||
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Errorf
|
||||
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Fatalf
|
||||
lll:
|
||||
line-length: 140
|
||||
maligned:
|
||||
suggest-new: true
|
||||
misspell:
|
||||
locale: US
|
||||
nolintlint:
|
||||
allow-leading-space: true # don't require machine-readable nolint directives (i.e. with no leading space)
|
||||
allow-unused: false # report any unused nolint directives
|
||||
require-explanation: false # don't require an explanation for nolint directives
|
||||
require-specific: false # don't require nolint directives to be specific about which linter is being skipped
|
||||
exhaustive:
|
||||
default-signifies-exhaustive: true
|
||||
|
||||
linters:
|
||||
# please, do not use `enable-all`: it's deprecated and will be removed soon.
|
||||
# inverted configuration with `enable-all` and `disable` is not scalable during updates of golangci-lint
|
||||
disable-all: true
|
||||
enable:
|
||||
- asciicheck
|
||||
- bodyclose
|
||||
- deadcode
|
||||
- depguard
|
||||
- dogsled
|
||||
- errcheck
|
||||
- exportloopref
|
||||
- exhaustive
|
||||
- errcheck
|
||||
- errorlint
|
||||
- funlen
|
||||
- forbidigo
|
||||
- forcetypeassert
|
||||
- goconst
|
||||
- gocritic
|
||||
- gocyclo
|
||||
- gofmt
|
||||
- goimports
|
||||
- golint
|
||||
- gomnd
|
||||
- goprintffuncname
|
||||
- gosec
|
||||
- gosimple
|
||||
- govet
|
||||
- ifshort
|
||||
- ineffassign
|
||||
- lll
|
||||
- makezero
|
||||
- misspell
|
||||
- nakedret
|
||||
- nilerr
|
||||
- noctx
|
||||
- nolintlint
|
||||
- prealloc
|
||||
- predeclared
|
||||
- rowserrcheck
|
||||
- staticcheck
|
||||
- structcheck
|
||||
- stylecheck
|
||||
- testpackage
|
||||
- typecheck
|
||||
- unconvert
|
||||
- unparam
|
||||
- unused
|
||||
- varcheck
|
||||
- whitespace
|
||||
|
||||
# don't enable:
|
||||
# - gochecknoglobals
|
||||
# - gocognit
|
||||
# - godot
|
||||
# - godox
|
||||
# - goerr113
|
||||
# - interfacer
|
||||
# - maligned
|
||||
# - nestif
|
||||
# - revive
|
||||
# - wsl
|
||||
# - wrapcheck
|
||||
|
||||
issues:
|
||||
# Excluding configuration per-path, per-linter, per-text and per-source
|
||||
exclude-rules:
|
||||
- path: _test\.go
|
||||
linters:
|
||||
- gomnd
|
||||
|
||||
# https://github.com/go-critic/go-critic/issues/926
|
||||
- linters:
|
||||
- gocritic
|
||||
text: "unnecessaryDefer:"
|
||||
|
||||
run:
|
||||
skip-dirs:
|
||||
- test/testdata_etc
|
||||
- internal/cache
|
||||
- internal/renameio
|
||||
- internal/robustio
|
||||
46
vendor/github.com/doug-martin/goqu/v9/CODE_OF_CONDUCT.md
generated
vendored
Normal file
46
vendor/github.com/doug-martin/goqu/v9/CODE_OF_CONDUCT.md
generated
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment include:
|
||||
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and unwelcome sexual attention or advances
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic address, without explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at doug@dougamartin.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
|
||||
|
||||
[homepage]: http://contributor-covenant.org
|
||||
[version]: http://contributor-covenant.org/version/1/4/
|
||||
31
vendor/github.com/doug-martin/goqu/v9/CONTRIBUTING.md
generated
vendored
Normal file
31
vendor/github.com/doug-martin/goqu/v9/CONTRIBUTING.md
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
## Contributions
|
||||
|
||||
I am always welcoming contributions of any type. Please open an issue or create a PR if you find an issue with any of the following.
|
||||
|
||||
* An issue with Documentation
|
||||
* You found the documentation lacking in some way
|
||||
|
||||
If you have an issue with the package please include the following
|
||||
|
||||
* The dialect you are using
|
||||
* A description of the problem
|
||||
* A short example of how to reproduce (if applicable)
|
||||
|
||||
Without those basics it can be difficult to reproduce your issue locally. You may be asked for more information but that is a good starting point.
|
||||
|
||||
### New Features
|
||||
|
||||
New features and/or enhancements are great and I encourage you to either submit a PR or create an issue. In both cases include the following as the need/requirement may not be readily apparent.
|
||||
|
||||
1. The use case
|
||||
2. A short example
|
||||
|
||||
If you are issuing a PR also also include the following
|
||||
|
||||
1. Tests - otherwise the PR will not be merged
|
||||
2. Documentation - otherwise the PR will not be merged
|
||||
3. Examples - [If applicable] see example_test.go for examples
|
||||
|
||||
If you find an issue you want to work on please comment on it letting other people know you are looking at it and I will assign the issue to you.
|
||||
|
||||
If want to work on an issue but dont know where to start just leave a comment and I'll be more than happy to point you in the right direction.
|
||||
404
vendor/github.com/doug-martin/goqu/v9/HISTORY.md
generated
vendored
Normal file
404
vendor/github.com/doug-martin/goqu/v9/HISTORY.md
generated
vendored
Normal file
@@ -0,0 +1,404 @@
|
||||
# v9.18.0
|
||||
* [FEATURE] Add support for aliasing insert datasets to support upsert alias [#306](https://github.com/doug-martin/goqu/pull/306) - [@XIELongDragon](https://github.com/XIELongDragon)
|
||||
* [FEATURE] Add support for aliasing BooleanExpressions [#307](https://github.com/doug-martin/goqu/pull/307) - [@XIELongDragon](https://github.com/XIELongDragon)
|
||||
|
||||
# v9.17.0
|
||||
* [FEATURE] Add support bitwise operations [#303](https://github.com/doug-martin/goqu/pull/303) - [@XIELongDragon](https://github.com/XIELongDragon)
|
||||
* [FEATURE] Add support for specifying tables to be locked in ForUpdate, ForNoKeyUpdate, ForKeyShare, ForShare [#299](https://github.com/doug-martin/goqu/pull/299) - [@jbub](https://github.com/jbub)
|
||||
|
||||
# v9.16.0
|
||||
* [FEATURE] Allow ordering by case expression [#282](https://github.com/doug-martin/goqu/issues/282), [#292](https://github.com/doug-martin/goqu/pull/292)
|
||||
|
||||
# v9.15.1
|
||||
* [FIX] Field indexes in the columnMap getting overridden [290](https://github.com/doug-martin/goqu/issues/290), [#291](https://github.com/doug-martin/goqu/pull/291)
|
||||
|
||||
# v9.15.0
|
||||
* [FEATURE] Add SetDefaultPrepared which controls query value interpolation [#288](https://github.com/doug-martin/goqu/pull/288) - [@Deiz](https://github.com/Deiz)
|
||||
|
||||
# v9.14.0
|
||||
* [FEATURE] GroupByAppend to the SelectDataset and SelectClauses [#276](https://github.com/doug-martin/goqu/pull/276), [#287](https://github.com/doug-martin/goqu/pull/287) - [@ashishkf](https://github.com/ashishkf)
|
||||
* [FEATURE] Allow untagged fields to be ignored [#285](https://github.com/doug-martin/goqu/pull/285) - [@Deiz](https://github.com/Deiz)
|
||||
* [FIX] Nil valuer [#277](https://github.com/doug-martin/goqu/pull/277) - [@benzolium](https://github.com/benzolium), [@Diggs](https://github.com/Diggs)
|
||||
* [FIX] Fix old import URL in doc comments [#286](https://github.com/doug-martin/goqu/pull/286) - [@maito1201](https://github.com/maito1201)
|
||||
|
||||
# v9.13.0
|
||||
|
||||
* [ADDED] ScanStructs, ScanVals to Scanner interface [#273](https://github.com/doug-martin/goqu/issues/273) - [@vlanse](https://github.com/vlanse)
|
||||
|
||||
# v9.12.0
|
||||
|
||||
* Update golangci-lint and updates for all associated linters
|
||||
* Update dependencies
|
||||
* github.com/DATA-DOG/go-sqlmock v1.3.3 -> v1.5.0
|
||||
* github.com/denisenkom/go-mssqldb v0.0.0-20200206145737-bbfc9a55622e -> v0.10.0
|
||||
* github.com/go-sql-driver/mysql v1.4.1 -> v1.6.0
|
||||
* github.com/lib/pq v1.2.0 -> v1.10.1
|
||||
* github.com/mattn/go-sqlite3 v1.11.0 -> v1.14.7
|
||||
* github.com/stretchr/testify -> v1.4.0 -> v1.7.0
|
||||
|
||||
|
||||
# v9.11.1
|
||||
|
||||
* [FIXED] Avoid mutation of join slice for separate datasets when joins slice capacity is not yet reached [#261](https://github.com/doug-martin/goqu/pull/261) - [@fhaifler](https://github.com/fhaifler)
|
||||
|
||||
# v9.11.0
|
||||
|
||||
* [FIXED] Use valid 'IS' operator for sqlserver dialect [#240](https://github.com/doug-martin/goqu/pull/240), [#239](https://github.com/doug-martin/goqu/pull/229) - [@vlanse](https://github.com/vlanse)
|
||||
* [ADDED] Implement Orderable interface for SQL Functions [#251](https://github.com/doug-martin/goqu/pull/251) - [@GlebBeloded](https://github.com/GlebBeloded)
|
||||
* [ADDED] Support for table hint in multi-table MySQL DELETE queries [#252](https://github.com/doug-martin/goqu/pull/252) - [@vlanse](https://github.com/vlanse)
|
||||
|
||||
# v9.10.0
|
||||
|
||||
* [FIXED] SELECT inherits dialect from INSERT in INSERT FROM SELECT. [#229](https://github.com/doug-martin/goqu/pull/229), [#223](https://github.com/doug-martin/goqu/issues/223) - [@vlanse](https://github.com/vlanse)
|
||||
* [FIXED] SQLServer dialect: support prepared statements with TOP. [#230](https://github.com/doug-martin/goqu/pull/230), [#225](https://github.com/doug-martin/goqu/issues/225) - [@vlanse](https://github.com/vlanse)
|
||||
* [ADDED] IsPrepared to SQLExpression interface. [#231](https://github.com/doug-martin/goqu/pull/231) - [@vlanse](https://github.com/vlanse)
|
||||
|
||||
# v9.9.0
|
||||
|
||||
* [FIXED] SQLite do not add FOR UPDATE in SELECT. [#218](https://github.com/doug-martin/goqu/pull/218) - [@vlanse](https://github.com/vlanse)
|
||||
* [ADDED] Support for INSERT ON CONFLICT in SQLite. [#218](https://github.com/doug-martin/goqu/pull/218) - [@vlanse](https://github.com/vlanse)
|
||||
|
||||
# v9.8.0
|
||||
|
||||
* [ADDED] Support for ANY and ALL operators. [#196](https://github.com/doug-martin/goqu/issues/196)
|
||||
* [ADDED] Support for CASE statements [#193](https://github.com/doug-martin/goqu/issues/193)
|
||||
* [ADDED] Support for getting column identifiers from AliasExpressions. [#203](https://github.com/doug-martin/goqu/issues/203)
|
||||
|
||||
# v9.7.1
|
||||
|
||||
* Fix all formatting for golangci-lint
|
||||
* Move to golangci-lint github action
|
||||
|
||||
# v9.7.0
|
||||
|
||||
* [ADDED] Support for sqlserver dialect [#197](https://github.com/doug-martin/goqu/issues/197),[#205](https://github.com/doug-martin/goqu/issues/205) - [@vlanse](https://github.com/vlanse)
|
||||
|
||||
# v9.6.0
|
||||
|
||||
* [ADDED] Support for Lateral queries [#182](https://github.com/doug-martin/goqu/issues/182)
|
||||
|
||||
# v9.5.1
|
||||
|
||||
* [FIXED] WITH clause without a RETURNING clause will panic [#177](https://github.com/doug-martin/goqu/issues/177)
|
||||
* [FIXED] SQlite dialect escapes single quotes wrong, leads to SQL syntax error [#178](https://github.com/doug-martin/goqu/issues/178)
|
||||
* [FIXED] Fix ReturnsColumns() nil pointer panic [#181](https://github.com/doug-martin/goqu/issues/181) - [@yeaha](https://github.com/yeaha)
|
||||
* [FIXED] SelectDataset From with Error [#183](https://github.com/doug-martin/goqu/issues/183)
|
||||
* [FIXED] Unable to execute union with order by expression [#185](https://github.com/doug-martin/goqu/issues/185)
|
||||
|
||||
# v9.5.0
|
||||
|
||||
* [ADDED] Ability to use regexp like, ilike, notlike, and notilike without a regexp [#172](https://github.com/doug-martin/goqu/issues/172)
|
||||
|
||||
# v9.4.0
|
||||
|
||||
* [ADDED] Ability to scan into struct fields from multiple tables [#160](https://github.com/doug-martin/goqu/issues/160)
|
||||
|
||||
# v9.3.0
|
||||
|
||||
* [ADDED] Using Update, Insert, or Delete datasets in sub selects and CTEs [#164](https://github.com/doug-martin/goqu/issues/164)
|
||||
|
||||
# v9.2.0
|
||||
|
||||
* [ADDED] exec.Scanner: New exposed scanner supports iterative scanning [#157](https://github.com/doug-martin/goqu/pull/157) - [@akarl](https://github.com/akarl)
|
||||
|
||||
# v9.1.0
|
||||
|
||||
* [FIXED] ExampleDoUpdate does't work in postgres [#156](https://github.com/doug-martin/goqu/issues/156)
|
||||
* [FIXED] Issue with timezone being lost [#163](https://github.com/doug-martin/goqu/issues/163)
|
||||
|
||||
# v9.0.1
|
||||
|
||||
* [FIXED] Issue where `NULL`, `TRUE` and `FALSE` are interpolated when using an `IS` clause. [#165](https://github.com/doug-martin/goqu/issues/165)
|
||||
|
||||
# v9.0.0
|
||||
|
||||
* Changed `NULL`, `TRUE`, `FALSE` to not be interpolated when creating prepared statements. [#132](https://github.com/doug-martin/goqu/pull/132), [#158](https://github.com/doug-martin/goqu/pull/158) - [@marshallmcmullen](https://github.com/marshallmcmullen)
|
||||
* Updated dependencies
|
||||
* `github.com/lib/pq v1.1.1 -> v1.2.0`
|
||||
* `github.com/mattn/go-sqlite3 v1.10.0 -> v1.11.0`
|
||||
* `github.com/stretchr/testify v1.3.0 -> v1.4.0`
|
||||
|
||||
## v8.6.0
|
||||
|
||||
* [ADDED] `SetError()` and `Error()` to all datasets. [#152](https://github.com/doug-martin/goqu/pull/152) and [#150](https://github.com/doug-martin/goqu/pull/150) - [@marshallmcmullen](https://github.com/marshallmcmullen)
|
||||
|
||||
## v8.5.0
|
||||
|
||||
* [ADDED] Window Function support [#128](https://github.com/doug-martin/goqu/issues/128) - [@Xuyuanp](https://github.com/Xuyuanp)
|
||||
|
||||
## v8.4.1
|
||||
|
||||
* [FIXED] Returning func be able to handle nil [#140](https://github.com/doug-martin/goqu/issues/140)
|
||||
|
||||
## v8.4.0
|
||||
|
||||
* Created new `sqlgen` module to encapsulate sql generation
|
||||
* Broke SQLDialect inti new SQL generators for each statement type.
|
||||
* Test refactor
|
||||
* Moved to a test case pattern to allow for quickly adding new test cases.
|
||||
|
||||
## v8.3.2
|
||||
|
||||
* [FIXED] Data race during query factory initialization [#133](https://github.com/doug-martin/goqu/issues/133) and [#136](https://github.com/doug-martin/goqu/issues/136) - [@o1egl](https://github.com/o1egl)
|
||||
|
||||
## v8.3.1
|
||||
|
||||
* [FIXED] InsertDataset.WithDialect return old dataset [#126](https://github.com/doug-martin/goqu/issues/126) - [@chen56](https://github.com/chen56)
|
||||
* Test clean up and more testing pattern consistency
|
||||
* Changed to use assertion methods off of suite
|
||||
* Updated Equals assertions to have expected output first
|
||||
* Increase overall test coverage.
|
||||
|
||||
## v8.3.0
|
||||
|
||||
* [Added] Support for `DISTINCT ON` clauses [#119](https://github.com/doug-martin/goqu/issues/119)
|
||||
|
||||
## v8.2.2
|
||||
|
||||
* [FIX] Scanner errors on pointers to primitive values [#122](https://github.com/doug-martin/goqu/issues/122)
|
||||
|
||||
## v8.2.1
|
||||
|
||||
* [FIX] Return an error when an empty identifier is encountered [#115](https://github.com/doug-martin/goqu/issues/115)
|
||||
|
||||
## v8.2.0
|
||||
|
||||
* [FIX] Fix reflection errors related to nil pointers and unexported fields [#118](https://github.com/doug-martin/goqu/issues/118)
|
||||
* Unexported fields are ignored when creating a columnMap
|
||||
* Nil embedded pointers will no longer cause a panic
|
||||
* Fields on nil embedded pointers will be ignored when creating update or insert statements.
|
||||
* [ADDED] You can now ingore embedded structs and their fields by using `db:"-"` tag on the embedded struct.
|
||||
|
||||
## v8.1.0
|
||||
|
||||
* [ADDED] Support column DEFAULT when inserting/updating via struct [#27](https://github.com/doug-martin/goqu/issues/27)
|
||||
|
||||
## v8.0.1
|
||||
|
||||
* [ADDED] Multi table update support for `mysql` and `postgres` [#60](https://github.com/doug-martin/goqu/issues/60)
|
||||
* [ADDED] `goqu.V` so values can be used on the LHS of expressions [#104](https://github.com/doug-martin/goqu/issues/104)
|
||||
|
||||
## v8.0.0
|
||||
|
||||
A major change the the API was made in `v8` to seperate concerns between the different SQL statement types.
|
||||
|
||||
**Why the change?**
|
||||
|
||||
1. There were feature requests that could not be cleanly implemented with everything in a single dataset.
|
||||
2. Too much functionality was encapsulated in a single datastructure.
|
||||
* It was unclear what methods could be used for each SQL statement type.
|
||||
* Changing a feature for one statement type had the possiblity of breaking another statement type.
|
||||
* Test coverage was decent but was almost solely concerned about SELECT statements, breaking them up allowed for focused testing on each statement type.
|
||||
* Most the SQL generation methods (`ToInsertSQL`, `ToUpdateSQL` etc.) took arguments which lead to an ugly API that was not uniform for each statement type, and proved to be inflexible.
|
||||
|
||||
**What Changed**
|
||||
|
||||
There are now five dataset types, `SelectDataset`, `InsertDataset`, `UpdateDataset`, `DeleteDataset` and `TruncateDataset`
|
||||
|
||||
Each dataset type has its own entry point.
|
||||
|
||||
* `goqu.From`, `Database#From`, `DialectWrapper#From` - Create SELECT
|
||||
* `goqu.Insert`, `Database#Insert`, `DialectWrapper#Insert` - Create INSERT
|
||||
* `goqu.Update`, `Database#db.Update`, `DialectWrapper#Update` - Create UPDATE
|
||||
* `goqu.Delete`, `Database#Delete`, `DialectWrapper#Delete` - Create DELETE
|
||||
* `goqu.Truncate`, `Database#Truncate`, `DialectWrapper#Truncate` - Create TRUNCATE
|
||||
|
||||
`ToInsertSQL`, `ToUpdateSQL`, `ToDeleteSQL`, and `ToTruncateSQL` (and variations of them) methods have been removed from the `SelectDataset`. Instead use the `ToSQL` methods on each dataset type.
|
||||
|
||||
Each dataset type will have an `Executor` and `ToSQL` method so a common interface can be created for each type.
|
||||
|
||||
|
||||
## v7.4.0
|
||||
|
||||
* [FIXED] literalTime use t.UTC() , This behavior is different from the original sql.DB [#106](https://github.com/doug-martin/goqu/issues/106) - [chen56](https://github.com/chen56)
|
||||
* [ADDED] Add new method WithTx for Database [#108](https://github.com/doug-martin/goqu/issues/108) - [Xuyuanp](https://github.com/Xuyuanp)
|
||||
|
||||
## v7.3.1
|
||||
|
||||
* [ADDED] Exposed `goqu.NewTx` to allow creating a goqu tx directly from a `sql.Tx` instead of using `goqu.Database#Begin` [#95](https://github.com/doug-martin/goqu/issues/95)
|
||||
* [ADDED] `goqu.Database.BeginTx` [#98](https://github.com/doug-martin/goqu/issues/98)
|
||||
|
||||
## v7.3.0
|
||||
|
||||
* [ADDED] UPDATE and INSERT should use struct Field name if db tag is not specified [#57](https://github.com/doug-martin/goqu/issues/57)
|
||||
* [CHANGE] Changed goqu.Database to accept a SQLDatabase interface to allow using goqu.Database with other libraries such as `sqlx` [#95](https://github.com/doug-martin/goqu/issues/95)
|
||||
|
||||
## v7.2.0
|
||||
|
||||
* [FIXED] Sqlite3 does not accept SELECT * UNION (SELECT *) [#79](https://github.com/doug-martin/goqu/issues/79)
|
||||
* [FIXED] Where(Ex{}) causes panics [mysql] [#49](https://github.com/doug-martin/goqu/issues/49)
|
||||
* [ADDED] Support for OrderPrepend [#61](https://github.com/doug-martin/goqu/issues/61)
|
||||
* [DOCS] Added new section about loading a dialect and using it to build SQL [#44](https://github.com/doug-martin/goqu/issues/44)
|
||||
|
||||
## v7.1.0
|
||||
|
||||
* [FIXED] Embedded pointers with property names that duplicate parent struct properties. [#23](https://github.com/doug-martin/goqu/issues/23)
|
||||
* [FIXED] Can't scan values using []byte or []string [#90](https://github.com/doug-martin/goqu/issues/90)
|
||||
* When a slice that is `*sql.RawBytes`, `*[]byte` or `sql.Scanner` no errors will be returned.
|
||||
|
||||
## v7.0.1
|
||||
|
||||
* Fix issue where structs with pointer fields where not set properly [#86](https://github.com/doug-martin/goqu/pull/86) and [#89](https://github.com/doug-martin/goqu/pull/89) - [@efureev](https://github.com/efureev)
|
||||
|
||||
## v7.0.0
|
||||
|
||||
**Linting**
|
||||
* Add linting checks and fixed errors
|
||||
* Renamed all snake_case variables to be camelCase.
|
||||
* Fixed examples to always map to a defined method
|
||||
* Renamed `adapters` to `dialect` to more closely match their intended purpose.
|
||||
|
||||
**API Changes**
|
||||
* Updated all sql generations methods to from `Sql` to `SQL`
|
||||
* `ToSql` -> `ToSQL`
|
||||
* `ToInsertSql` -> `ToInsertSQL`
|
||||
* `ToUpdateSql` -> `ToUpdateSQL`
|
||||
* `ToDeleteSql` -> `ToDeleteSQL`
|
||||
* `ToTruncateSql` -> `ToTruncateSQL`
|
||||
* Abstracted out `dialect_options` from the adapter to make the dialect self contained.
|
||||
* This also removed the dataset<->adapter co dependency making the dialect self contained.
|
||||
* Refactored the `goqu.I` method.
|
||||
* Added new `goqu.S`, `goqu.T` and `goqu.C` methods to clarify why type of identifier you are using.
|
||||
* `goqu.I` should only be used when you have a qualified identifier (e.g. `goqu.I("my_schema.my_table.my_col")
|
||||
* Added new `goqu.Dialect` method to make using `goqu` as an SQL builder easier.
|
||||
|
||||
**Internal Changes**
|
||||
* Pulled expressions into their own package
|
||||
* Broke up expressions.go into multiple files to make working with and defining them easier.
|
||||
* Moved the user facing methods into the main `goqu` to keep the same API as before.
|
||||
* Added more examples
|
||||
* Moved non-user facing structs and interfaces to internal modules to clean up API.
|
||||
* Increased test coverage.
|
||||
|
||||
|
||||
## v6.1.0
|
||||
|
||||
* Handle nil *time.Time Literal [#73](https://github.com/doug-martin/goqu/pull/73) and [#52](https://github.com/doug-martin/goqu/pull/52) - [@RoarkeRandall](https://github.com/RoarkeRandall) and [@quetz](https://github.com/quetz)
|
||||
* Add ability to change column rename function [#66](https://github.com/doug-martin/goqu/pull/66) - [@blainehansen](https://github.com/blainehansen)
|
||||
|
||||
## v6.0.0
|
||||
|
||||
* Updated go support to `1.10`, `1.11` and `1.12`
|
||||
* Change testify dependency from c2fo/testify back to stretchr/testify.
|
||||
* Add support for "FOR UPDATE" and "SKIP LOCKED" [#62](https://github.com/doug-martin/goqu/pull/62) - [@btubbs](https://github.com/btubbs)
|
||||
* Changed to use go modules
|
||||
|
||||
## v5.0.0
|
||||
|
||||
* Drop go 1.6 support, supported versions are `1.8`, `1.9` and latest
|
||||
* Add context support [#64](https://github.com/doug-martin/goqu/pull/64) - [@cmoad](https://github.com/cmoad)
|
||||
|
||||
## v4.2.0
|
||||
|
||||
* Add support for ON CONFLICT when using a dataset [#55](https://github.com/doug-martin/goqu/pull/55) - [@bobrnor](https://github.com/bobrnor)
|
||||
|
||||
## v4.1.0
|
||||
|
||||
* Support for defining WITH clauses for Common Table Expressions (CTE) [#39](https://github.com/doug-martin/goqu/pull/39) - [@Oscil8](https://github.com/Oscil8)
|
||||
|
||||
## v4.0
|
||||
|
||||
* Prepared(true) issues when using IS NULL comparisson operation [#33](https://github.com/doug-martin/goqu/pull/33) - [@danielfbm](https://github.com/danielfbm)
|
||||
|
||||
## v3.3
|
||||
|
||||
* Add `upsert` support via `InsertIgnore` and `InsertConflict` methods - [#25](https://github.com/doug-martin/goqu/pull/28) - [@aheuermann](https://github.com/aheuermann)
|
||||
* Adding vendor dependencies and updating tests to run in docker containers [#29](https://github.com/doug-martin/goqu/pull/29) - [@aheuermann](https://github.com/aheuermann)
|
||||
|
||||
## v3.2
|
||||
|
||||
* Add range clauses ([NOT] BETWEEN) support - [#25](https://github.com/doug-martin/goqu/pull/25) - [@denisvm](https://github.com/denisvm)
|
||||
* Readmefix [#26](https://github.com/doug-martin/goqu/pull/26) - [@tiagopotencia](https://github.com/tiagopotencia)
|
||||
|
||||
## v3.1.3
|
||||
|
||||
* Bugfix for chained Where() [#20](https://github.com/doug-martin/goqu/pull/20) - [@Emreu](https://github.com/Emreu)
|
||||
|
||||
|
||||
## v3.1.2
|
||||
|
||||
* Fixing ScanStruct issue with embedded pointers in crud_exec [#20](https://github.com/doug-martin/goqu/pull/20) - [@ruzz311](https://github.com/ruzz311)
|
||||
|
||||
## v3.1.1
|
||||
|
||||
* Fixing race condition with struct_map_cache in crud_exec [#18](https://github.com/doug-martin/goqu/pull/18) - [@andymoon](https://github.com/andymoon), [@aheuermann](https://github.com/aheuermann)
|
||||
|
||||
## v3.1.0
|
||||
|
||||
* Version 3.1 [#14](https://github.com/doug-martin/goqu/pull/14) - [@andymoon](https://github.com/andymoon)
|
||||
* Fix an issue with a nil pointer access on the inserts and updates.
|
||||
* Allowing ScanStructs to take a struct with an embedded pointer to a struct.
|
||||
* Change to check if struct is Anonymous when recursing through an embedded struct.
|
||||
* Updated to use the latest version of github.com/DATA-DOG/go-sqlmock.
|
||||
|
||||
## v3.0.1
|
||||
|
||||
* Add literal bytes and update to c2fo testify [#15](https://github.com/doug-martin/goqu/pull/15) - [@TechnotronicOz](https://github.com/TechnotronicOz)
|
||||
|
||||
## v3.0.0
|
||||
|
||||
* Added support for embedded structs when inserting or updating. [#13](https://github.com/doug-martin/goqu/pull/13) - [@andymoon](https://github.com/andymoon)
|
||||
|
||||
## v2.0.3
|
||||
|
||||
* Fixed issue with transient columns and the auto select of columns.
|
||||
|
||||
## v2.0.2
|
||||
|
||||
* Changed references to "github.com/doug-martin/goqu" to "gopkg.in/doug-martin/goqu.v2"
|
||||
|
||||
## v2.0.1
|
||||
|
||||
* Fixed issue when `ScanStruct(s)` was used with `SelectDistinct` and caused a panic.
|
||||
|
||||
## v2.0.0
|
||||
|
||||
* When scanning a struct or slice of structs, the struct(s) will be parsed for the column names to select. [#9](https://github.com/doug-martin/goqu/pull/9) - [@technotronicoz](https://github.com/TechnotronicOz)
|
||||
|
||||
## v1.0.0
|
||||
|
||||
* You can now passed an IdentiferExpression to `As` [#8](https://github.com/doug-martin/goqu/pull/8) - [@croachrose](https://github.com/croachrose)
|
||||
* Added info about installation through [gopkg.in](http://labix.org/gopkg.in)
|
||||
|
||||
## v0.3.1
|
||||
|
||||
* Fixed issue setting Logger when starting a new transaction.
|
||||
|
||||
## v0.3.0
|
||||
|
||||
* Changed sql generation methods to use a common naming convention. `To(Sql|Insert|Update|Delete)`
|
||||
* Also changed to have common return values `string, []interface{}, error)`
|
||||
* Added `Dataset.Prepared` which allows a user to specify whether or not SQL should be interpolated. [#7](https://github.com/doug-martin/goqu/issues/7)
|
||||
* Updated Docs
|
||||
* More examples
|
||||
* Increased test coverage.
|
||||
|
||||
## v0.2.0
|
||||
|
||||
* Changed `CrudExec` to not wrap driver errors in a GoquError [#2](https://github.com/doug-martin/goqu/issues/2)
|
||||
* Added ability to use a dataset in an `Ex` map or `Eq` expression without having to use `In` [#3](https://github.com/doug-martin/goqu/issues/3)
|
||||
* `db.From("test").Where(goqu.Ex{"a": db.From("test").Select("b")})`
|
||||
* Updated readme with links to [`DefaultAdapter`](https://godoc.org/github.com/doug-martin/goqu#DefaultAdapter)
|
||||
|
||||
## v0.1.1
|
||||
|
||||
* Added SQLite3 adapter [#1](https://github.com/doug-martin/goqu/pull/1) - [@mattn](https://github.com/mattn)
|
||||
|
||||
## v0.1.0
|
||||
|
||||
* Added:
|
||||
* [`Ex`](https://godoc.org/github.com/doug-martin/goqu#Ex)
|
||||
* [`ExOr`](https://godoc.org/github.com/doug-martin/goqu#ExOr)
|
||||
* [`Op`](https://godoc.org/github.com/doug-martin/goqu#Op)
|
||||
* More tests and examples
|
||||
* Added CONTRIBUTING.md
|
||||
* Added LICENSE information
|
||||
* Removed godoc introduction in favor of just maintaining the README.
|
||||
|
||||
## v0.0.2
|
||||
|
||||
* Fixed issue with goqu.New not returning a pointer to a Database
|
||||
|
||||
## v0.0.1
|
||||
|
||||
* Initial release
|
||||
21
vendor/github.com/doug-martin/goqu/v9/LICENSE
generated
vendored
Normal file
21
vendor/github.com/doug-martin/goqu/v9/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017 Doug Martin
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
6
vendor/github.com/doug-martin/goqu/v9/Makefile
generated
vendored
Normal file
6
vendor/github.com/doug-martin/goqu/v9/Makefile
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
#phony dependency task that does nothing
|
||||
#"make executable" does not run if there is a ./executable directory, unless the task has a dependency
|
||||
phony:
|
||||
|
||||
lint:
|
||||
docker run --rm -v ${CURDIR}:/app -w /app golangci/golangci-lint:v1.23.8 golangci-lint run -v
|
||||
310
vendor/github.com/doug-martin/goqu/v9/README.md
generated
vendored
Normal file
310
vendor/github.com/doug-martin/goqu/v9/README.md
generated
vendored
Normal file
@@ -0,0 +1,310 @@
|
||||
```
|
||||
__ _ ___ __ _ _ _
|
||||
/ _` |/ _ \ / _` | | | |
|
||||
| (_| | (_) | (_| | |_| |
|
||||
\__, |\___/ \__, |\__,_|
|
||||
|___/ |_|
|
||||
```
|
||||
[](https://github.com/doug-martin/goqu/releases)
|
||||
[](https://github.com/doug-martin/goqu/actions?query=workflow%3ATest+and+branch%3Amaster+)
|
||||
[](https://pkg.go.dev/github.com/doug-martin/goqu/v9)
|
||||
[](https://codecov.io/gh/doug-martin/goqu)
|
||||
[](https://goreportcard.com/report/github.com/doug-martin/goqu/v9)
|
||||
|
||||
`goqu` is an expressive SQL builder and executor
|
||||
|
||||
If you are upgrading from an older version please read the [Migrating Between Versions](./docs/version_migration.md) docs.
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
If using go modules.
|
||||
|
||||
```sh
|
||||
go get -u github.com/doug-martin/goqu/v9
|
||||
```
|
||||
|
||||
If you are not using go modules...
|
||||
|
||||
**NOTE** You should still be able to use this package if you are using go version `>v1.10` but, you will need to drop the version from the package. `import "github.com/doug-martin/goqu/v9` -> `import "github.com/doug-martin/goqu"`
|
||||
|
||||
```sh
|
||||
go get -u github.com/doug-martin/goqu
|
||||
```
|
||||
|
||||
### [Migrating Between Versions](./docs/version_migration.md)
|
||||
|
||||
## Features
|
||||
|
||||
`goqu` comes with many features but here are a few of the more notable ones
|
||||
|
||||
* Query Builder
|
||||
* Parameter interpolation (e.g `SELECT * FROM "items" WHERE "id" = ?` -> `SELECT * FROM "items" WHERE "id" = 1`)
|
||||
* Built from the ground up with multiple dialects in mind
|
||||
* Insert, Multi Insert, Update, and Delete support
|
||||
* Scanning of rows to struct[s] or primitive value[s]
|
||||
|
||||
While goqu may support the scanning of rows into structs it is not intended to be used as an ORM if you are looking for common ORM features like associations,
|
||||
or hooks I would recommend looking at some of the great ORM libraries such as:
|
||||
|
||||
* [gorm](https://github.com/jinzhu/gorm)
|
||||
* [hood](https://github.com/eaigner/hood)
|
||||
|
||||
## Why?
|
||||
|
||||
We tried a few other sql builders but each was a thin wrapper around sql fragments that we found error prone. `goqu` was built with the following goals in mind:
|
||||
|
||||
* Make the generation of SQL easy and enjoyable
|
||||
* Create an expressive DSL that would find common errors with SQL at compile time.
|
||||
* Provide a DSL that accounts for the common SQL expressions, NOT every nuance for each database.
|
||||
* Provide developers the ability to:
|
||||
* Use SQL when desired
|
||||
* Easily scan results into primitive values and structs
|
||||
* Use the native sql.Db methods when desired
|
||||
|
||||
## Docs
|
||||
|
||||
* [Dialect](./docs/dialect.md) - Introduction to different dialects (`mysql`, `postgres`, `sqlite3`, `sqlserver` etc)
|
||||
* [Expressions](./docs/expressions.md) - Introduction to `goqu` expressions and common examples.
|
||||
* [Select Dataset](./docs/selecting.md) - Docs and examples about creating and executing SELECT sql statements.
|
||||
* [Insert Dataset](./docs/inserting.md) - Docs and examples about creating and executing INSERT sql statements.
|
||||
* [Update Dataset](./docs/updating.md) - Docs and examples about creating and executing UPDATE sql statements.
|
||||
* [Delete Dataset](./docs/deleting.md) - Docs and examples about creating and executing DELETE sql statements.
|
||||
* [Prepared Statements](./docs/interpolation.md) - Docs about interpolation and prepared statements in `goqu`.
|
||||
* [Database](./docs/database.md) - Docs and examples of using a Database to execute queries in `goqu`
|
||||
* [Working with time.Time](./docs/time.md) - Docs on how to use alternate time locations.
|
||||
|
||||
## Quick Examples
|
||||
|
||||
### Select
|
||||
|
||||
See the [select dataset](./docs/selecting.md) docs for more in depth examples
|
||||
|
||||
```go
|
||||
sql, _, _ := goqu.From("test").ToSQL()
|
||||
fmt.Println(sql)
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
SELECT * FROM "test"
|
||||
```
|
||||
|
||||
```go
|
||||
sql, _, _ := goqu.From("test").Where(goqu.Ex{
|
||||
"d": []string{"a", "b", "c"},
|
||||
}).ToSQL()
|
||||
fmt.Println(sql)
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
SELECT * FROM "test" WHERE ("d" IN ('a', 'b', 'c'))
|
||||
```
|
||||
|
||||
### Insert
|
||||
|
||||
See the [insert dataset](./docs/inserting.md) docs for more in depth examples
|
||||
|
||||
```go
|
||||
ds := goqu.Insert("user").
|
||||
Cols("first_name", "last_name").
|
||||
Vals(
|
||||
goqu.Vals{"Greg", "Farley"},
|
||||
goqu.Vals{"Jimmy", "Stewart"},
|
||||
goqu.Vals{"Jeff", "Jeffers"},
|
||||
)
|
||||
insertSQL, args, _ := ds.ToSQL()
|
||||
fmt.Println(insertSQL, args)
|
||||
```
|
||||
|
||||
Output:
|
||||
```sql
|
||||
INSERT INTO "user" ("first_name", "last_name") VALUES ('Greg', 'Farley'), ('Jimmy', 'Stewart'), ('Jeff', 'Jeffers') []
|
||||
```
|
||||
|
||||
```go
|
||||
ds := goqu.Insert("user").Rows(
|
||||
goqu.Record{"first_name": "Greg", "last_name": "Farley"},
|
||||
goqu.Record{"first_name": "Jimmy", "last_name": "Stewart"},
|
||||
goqu.Record{"first_name": "Jeff", "last_name": "Jeffers"},
|
||||
)
|
||||
insertSQL, args, _ := ds.ToSQL()
|
||||
fmt.Println(insertSQL, args)
|
||||
```
|
||||
|
||||
Output:
|
||||
```
|
||||
INSERT INTO "user" ("first_name", "last_name") VALUES ('Greg', 'Farley'), ('Jimmy', 'Stewart'), ('Jeff', 'Jeffers') []
|
||||
```
|
||||
|
||||
|
||||
```go
|
||||
type User struct {
|
||||
FirstName string `db:"first_name"`
|
||||
LastName string `db:"last_name"`
|
||||
}
|
||||
ds := goqu.Insert("user").Rows(
|
||||
User{FirstName: "Greg", LastName: "Farley"},
|
||||
User{FirstName: "Jimmy", LastName: "Stewart"},
|
||||
User{FirstName: "Jeff", LastName: "Jeffers"},
|
||||
)
|
||||
insertSQL, args, _ := ds.ToSQL()
|
||||
fmt.Println(insertSQL, args)
|
||||
```
|
||||
|
||||
Output:
|
||||
```
|
||||
INSERT INTO "user" ("first_name", "last_name") VALUES ('Greg', 'Farley'), ('Jimmy', 'Stewart'), ('Jeff', 'Jeffers') []
|
||||
```
|
||||
|
||||
```go
|
||||
ds := goqu.Insert("user").Prepared(true).
|
||||
FromQuery(goqu.From("other_table"))
|
||||
insertSQL, args, _ := ds.ToSQL()
|
||||
fmt.Println(insertSQL, args)
|
||||
```
|
||||
|
||||
Output:
|
||||
```
|
||||
INSERT INTO "user" SELECT * FROM "other_table" []
|
||||
```
|
||||
|
||||
```go
|
||||
ds := goqu.Insert("user").Prepared(true).
|
||||
Cols("first_name", "last_name").
|
||||
FromQuery(goqu.From("other_table").Select("fn", "ln"))
|
||||
insertSQL, args, _ := ds.ToSQL()
|
||||
fmt.Println(insertSQL, args)
|
||||
```
|
||||
|
||||
Output:
|
||||
```
|
||||
INSERT INTO "user" ("first_name", "last_name") SELECT "fn", "ln" FROM "other_table" []
|
||||
```
|
||||
|
||||
### Update
|
||||
|
||||
See the [update dataset](./docs/updating.md) docs for more in depth examples
|
||||
|
||||
```go
|
||||
sql, args, _ := goqu.Update("items").Set(
|
||||
goqu.Record{"name": "Test", "address": "111 Test Addr"},
|
||||
).ToSQL()
|
||||
fmt.Println(sql, args)
|
||||
```
|
||||
|
||||
Output:
|
||||
```
|
||||
UPDATE "items" SET "address"='111 Test Addr',"name"='Test' []
|
||||
```
|
||||
|
||||
```go
|
||||
type item struct {
|
||||
Address string `db:"address"`
|
||||
Name string `db:"name" goqu:"skipupdate"`
|
||||
}
|
||||
sql, args, _ := goqu.Update("items").Set(
|
||||
item{Name: "Test", Address: "111 Test Addr"},
|
||||
).ToSQL()
|
||||
fmt.Println(sql, args)
|
||||
```
|
||||
|
||||
Output:
|
||||
```
|
||||
UPDATE "items" SET "address"='111 Test Addr' []
|
||||
```
|
||||
|
||||
```go
|
||||
sql, _, _ := goqu.Update("test").
|
||||
Set(goqu.Record{"foo": "bar"}).
|
||||
Where(goqu.Ex{
|
||||
"a": goqu.Op{"gt": 10}
|
||||
}).ToSQL()
|
||||
fmt.Println(sql)
|
||||
```
|
||||
|
||||
Output:
|
||||
```
|
||||
UPDATE "test" SET "foo"='bar' WHERE ("a" > 10)
|
||||
```
|
||||
|
||||
### Delete
|
||||
|
||||
See the [delete dataset](./docs/deleting.md) docs for more in depth examples
|
||||
|
||||
```go
|
||||
ds := goqu.Delete("items")
|
||||
|
||||
sql, args, _ := ds.ToSQL()
|
||||
fmt.Println(sql, args)
|
||||
```
|
||||
|
||||
```go
|
||||
sql, _, _ := goqu.Delete("test").Where(goqu.Ex{
|
||||
"c": nil
|
||||
}).ToSQL()
|
||||
fmt.Println(sql)
|
||||
```
|
||||
|
||||
Output:
|
||||
```
|
||||
DELETE FROM "test" WHERE ("c" IS NULL)
|
||||
```
|
||||
|
||||
<a name="contributions"></a>
|
||||
## Contributions
|
||||
|
||||
I am always welcoming contributions of any type. Please open an issue or create a PR if you find an issue with any of the following.
|
||||
|
||||
* An issue with Documentation
|
||||
* You found the documentation lacking in some way
|
||||
|
||||
If you have an issue with the package please include the following
|
||||
|
||||
* The dialect you are using
|
||||
* A description of the problem
|
||||
* A short example of how to reproduce (if applicable)
|
||||
|
||||
Without those basics it can be difficult to reproduce your issue locally. You may be asked for more information but that is a good starting point.
|
||||
|
||||
### New Features
|
||||
|
||||
New features and/or enhancements are great and I encourage you to either submit a PR or create an issue. In both cases include the following as the need/requirement may not be readily apparent.
|
||||
|
||||
1. The use case
|
||||
2. A short example
|
||||
|
||||
If you are issuing a PR also include the following
|
||||
|
||||
1. Tests - otherwise the PR will not be merged
|
||||
2. Documentation - otherwise the PR will not be merged
|
||||
3. Examples - [If applicable] see example_test.go for examples
|
||||
|
||||
If you find an issue you want to work on please comment on it letting other people know you are looking at it and I will assign the issue to you.
|
||||
|
||||
If want to work on an issue but dont know where to start just leave a comment and I'll be more than happy to point you in the right direction.
|
||||
|
||||
### Running tests
|
||||
The test suite requires a postgres, mysql and sqlserver databases. You can override the connection strings with the [`MYSQL_URI`, `PG_URI`, `SQLSERVER_URI` environment variables](https://github.com/doug-martin/goqu/blob/2fe3349/docker-compose.yml#L26)*
|
||||
|
||||
```sh
|
||||
go test -v -race ./...
|
||||
```
|
||||
|
||||
You can also run the tests in a container using [docker-compose](https://docs.docker.com/compose/).
|
||||
|
||||
```sh
|
||||
MYSQL_VERSION=8 POSTGRES_VERSION=13.4 SQLSERVER_VERSION=2017-CU8-ubuntu GO_VERSION=latest docker-compose run goqu
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
`goqu` is released under the [MIT License](http://www.opensource.org/licenses/MIT).
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
1
vendor/github.com/doug-martin/goqu/v9/_config.yml
generated
vendored
Normal file
1
vendor/github.com/doug-martin/goqu/v9/_config.yml
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
theme: jekyll-theme-cayman
|
||||
3
vendor/github.com/doug-martin/goqu/v9/codecov.yml
generated
vendored
Normal file
3
vendor/github.com/doug-martin/goqu/v9/codecov.yml
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
ignore:
|
||||
- "**/mocks/**" # glob accepted
|
||||
- "mocks/**" # glob accepted
|
||||
648
vendor/github.com/doug-martin/goqu/v9/database.go
generated
vendored
Normal file
648
vendor/github.com/doug-martin/goqu/v9/database.go
generated
vendored
Normal file
@@ -0,0 +1,648 @@
|
||||
package goqu
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"sync"
|
||||
|
||||
"github.com/doug-martin/goqu/v9/exec"
|
||||
)
|
||||
|
||||
type (
|
||||
Logger interface {
|
||||
Printf(format string, v ...interface{})
|
||||
}
|
||||
// Interface for sql.DB, an interface is used so you can use with other
|
||||
// libraries such as sqlx instead of the native sql.DB
|
||||
SQLDatabase interface {
|
||||
Begin() (*sql.Tx, error)
|
||||
BeginTx(ctx context.Context, opts *sql.TxOptions) (*sql.Tx, error)
|
||||
ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error)
|
||||
PrepareContext(ctx context.Context, query string) (*sql.Stmt, error)
|
||||
QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error)
|
||||
QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row
|
||||
}
|
||||
// This struct is the wrapper for a Db. The struct delegates most calls to either an Exec instance or to the Db
|
||||
// passed into the constructor.
|
||||
Database struct {
|
||||
logger Logger
|
||||
dialect string
|
||||
// nolint: stylecheck // keep for backwards compatibility
|
||||
Db SQLDatabase
|
||||
qf exec.QueryFactory
|
||||
qfOnce sync.Once
|
||||
}
|
||||
)
|
||||
|
||||
// This is the common entry point into goqu.
|
||||
//
|
||||
// dialect: This is the adapter dialect, you should see your database adapter for the string to use. Built in adapters
|
||||
// can be found at https://github.com/doug-martin/goqu/tree/master/adapters
|
||||
//
|
||||
// db: A sql.Db to use for querying the database
|
||||
// import (
|
||||
// "database/sql"
|
||||
// "fmt"
|
||||
// "github.com/doug-martin/goqu/v9"
|
||||
// _ "github.com/doug-martin/goqu/v9/dialect/postgres"
|
||||
// _ "github.com/lib/pq"
|
||||
// )
|
||||
//
|
||||
// func main() {
|
||||
// sqlDb, err := sql.Open("postgres", "user=postgres dbname=goqupostgres sslmode=disable ")
|
||||
// if err != nil {
|
||||
// panic(err.Error())
|
||||
// }
|
||||
// db := goqu.New("postgres", sqlDb)
|
||||
// }
|
||||
// The most commonly used Database method is From, which creates a new Dataset that uses the correct adapter and
|
||||
// supports queries.
|
||||
// var ids []uint32
|
||||
// if err := db.From("items").Where(goqu.I("id").Gt(10)).Pluck("id", &ids); err != nil {
|
||||
// panic(err.Error())
|
||||
// }
|
||||
// fmt.Printf("%+v", ids)
|
||||
func newDatabase(dialect string, db SQLDatabase) *Database {
|
||||
return &Database{
|
||||
logger: nil,
|
||||
dialect: dialect,
|
||||
Db: db,
|
||||
qf: nil,
|
||||
qfOnce: sync.Once{},
|
||||
}
|
||||
}
|
||||
|
||||
// returns this databases dialect
|
||||
func (d *Database) Dialect() string {
|
||||
return d.dialect
|
||||
}
|
||||
|
||||
// Starts a new Transaction.
|
||||
func (d *Database) Begin() (*TxDatabase, error) {
|
||||
sqlTx, err := d.Db.Begin()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tx := NewTx(d.dialect, sqlTx)
|
||||
tx.Logger(d.logger)
|
||||
return tx, nil
|
||||
}
|
||||
|
||||
// Starts a new Transaction. See sql.DB#BeginTx for option description
|
||||
func (d *Database) BeginTx(ctx context.Context, opts *sql.TxOptions) (*TxDatabase, error) {
|
||||
sqlTx, err := d.Db.BeginTx(ctx, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tx := NewTx(d.dialect, sqlTx)
|
||||
tx.Logger(d.logger)
|
||||
return tx, nil
|
||||
}
|
||||
|
||||
// WithTx starts a new transaction and executes it in Wrap method
|
||||
func (d *Database) WithTx(fn func(*TxDatabase) error) error {
|
||||
tx, err := d.Begin()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return tx.Wrap(func() error { return fn(tx) })
|
||||
}
|
||||
|
||||
// Creates a new Dataset that uses the correct adapter and supports queries.
|
||||
// var ids []uint32
|
||||
// if err := db.From("items").Where(goqu.I("id").Gt(10)).Pluck("id", &ids); err != nil {
|
||||
// panic(err.Error())
|
||||
// }
|
||||
// fmt.Printf("%+v", ids)
|
||||
//
|
||||
// from...: Sources for you dataset, could be table names (strings), a goqu.Literal or another goqu.Dataset
|
||||
func (d *Database) From(from ...interface{}) *SelectDataset {
|
||||
return newDataset(d.dialect, d.queryFactory()).From(from...)
|
||||
}
|
||||
|
||||
func (d *Database) Select(cols ...interface{}) *SelectDataset {
|
||||
return newDataset(d.dialect, d.queryFactory()).Select(cols...)
|
||||
}
|
||||
|
||||
func (d *Database) Update(table interface{}) *UpdateDataset {
|
||||
return newUpdateDataset(d.dialect, d.queryFactory()).Table(table)
|
||||
}
|
||||
|
||||
func (d *Database) Insert(table interface{}) *InsertDataset {
|
||||
return newInsertDataset(d.dialect, d.queryFactory()).Into(table)
|
||||
}
|
||||
|
||||
func (d *Database) Delete(table interface{}) *DeleteDataset {
|
||||
return newDeleteDataset(d.dialect, d.queryFactory()).From(table)
|
||||
}
|
||||
|
||||
func (d *Database) Truncate(table ...interface{}) *TruncateDataset {
|
||||
return newTruncateDataset(d.dialect, d.queryFactory()).Table(table...)
|
||||
}
|
||||
|
||||
// Sets the logger for to use when logging queries
|
||||
func (d *Database) Logger(logger Logger) {
|
||||
d.logger = logger
|
||||
}
|
||||
|
||||
// Logs a given operation with the specified sql and arguments
|
||||
func (d *Database) Trace(op, sqlString string, args ...interface{}) {
|
||||
if d.logger != nil {
|
||||
if sqlString != "" {
|
||||
if len(args) != 0 {
|
||||
d.logger.Printf("[goqu] %s [query:=`%s` args:=%+v]", op, sqlString, args)
|
||||
} else {
|
||||
d.logger.Printf("[goqu] %s [query:=`%s`]", op, sqlString)
|
||||
}
|
||||
} else {
|
||||
d.logger.Printf("[goqu] %s", op)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Uses the db to Execute the query with arguments and return the sql.Result
|
||||
//
|
||||
// query: The SQL to execute
|
||||
//
|
||||
// args...: for any placeholder parameters in the query
|
||||
func (d *Database) Exec(query string, args ...interface{}) (sql.Result, error) {
|
||||
return d.ExecContext(context.Background(), query, args...)
|
||||
}
|
||||
|
||||
// Uses the db to Execute the query with arguments and return the sql.Result
|
||||
//
|
||||
// query: The SQL to execute
|
||||
//
|
||||
// args...: for any placeholder parameters in the query
|
||||
func (d *Database) ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error) {
|
||||
d.Trace("EXEC", query, args...)
|
||||
return d.Db.ExecContext(ctx, query, args...)
|
||||
}
|
||||
|
||||
// Can be used to prepare a query.
|
||||
//
|
||||
// You can use this in tandem with a dataset by doing the following.
|
||||
// sql, args, err := db.From("items").Where(goqu.I("id").Gt(10)).ToSQL(true)
|
||||
// if err != nil{
|
||||
// panic(err.Error()) //you could gracefully handle the error also
|
||||
// }
|
||||
// stmt, err := db.Prepare(sql)
|
||||
// if err != nil{
|
||||
// panic(err.Error()) //you could gracefully handle the error also
|
||||
// }
|
||||
// defer stmt.Close()
|
||||
// rows, err := stmt.Query(args)
|
||||
// if err != nil{
|
||||
// panic(err.Error()) //you could gracefully handle the error also
|
||||
// }
|
||||
// defer rows.Close()
|
||||
// for rows.Next(){
|
||||
// //scan your rows
|
||||
// }
|
||||
// if rows.Err() != nil{
|
||||
// panic(err.Error()) //you could gracefully handle the error also
|
||||
// }
|
||||
//
|
||||
// query: The SQL statement to prepare.
|
||||
func (d *Database) Prepare(query string) (*sql.Stmt, error) {
|
||||
return d.PrepareContext(context.Background(), query)
|
||||
}
|
||||
|
||||
// Can be used to prepare a query.
|
||||
//
|
||||
// You can use this in tandem with a dataset by doing the following.
|
||||
// sql, args, err := db.From("items").Where(goqu.I("id").Gt(10)).ToSQL(true)
|
||||
// if err != nil{
|
||||
// panic(err.Error()) //you could gracefully handle the error also
|
||||
// }
|
||||
// stmt, err := db.Prepare(sql)
|
||||
// if err != nil{
|
||||
// panic(err.Error()) //you could gracefully handle the error also
|
||||
// }
|
||||
// defer stmt.Close()
|
||||
// rows, err := stmt.QueryContext(ctx, args)
|
||||
// if err != nil{
|
||||
// panic(err.Error()) //you could gracefully handle the error also
|
||||
// }
|
||||
// defer rows.Close()
|
||||
// for rows.Next(){
|
||||
// //scan your rows
|
||||
// }
|
||||
// if rows.Err() != nil{
|
||||
// panic(err.Error()) //you could gracefully handle the error also
|
||||
// }
|
||||
//
|
||||
// query: The SQL statement to prepare.
|
||||
func (d *Database) PrepareContext(ctx context.Context, query string) (*sql.Stmt, error) {
|
||||
d.Trace("PREPARE", query)
|
||||
return d.Db.PrepareContext(ctx, query)
|
||||
}
|
||||
|
||||
// Used to query for multiple rows.
|
||||
//
|
||||
// You can use this in tandem with a dataset by doing the following.
|
||||
// sql, err := db.From("items").Where(goqu.I("id").Gt(10)).ToSQL()
|
||||
// if err != nil{
|
||||
// panic(err.Error()) //you could gracefully handle the error also
|
||||
// }
|
||||
// rows, err := stmt.Query(args)
|
||||
// if err != nil{
|
||||
// panic(err.Error()) //you could gracefully handle the error also
|
||||
// }
|
||||
// defer rows.Close()
|
||||
// for rows.Next(){
|
||||
// //scan your rows
|
||||
// }
|
||||
// if rows.Err() != nil{
|
||||
// panic(err.Error()) //you could gracefully handle the error also
|
||||
// }
|
||||
//
|
||||
// query: The SQL to execute
|
||||
//
|
||||
// args...: for any placeholder parameters in the query
|
||||
func (d *Database) Query(query string, args ...interface{}) (*sql.Rows, error) {
|
||||
return d.QueryContext(context.Background(), query, args...)
|
||||
}
|
||||
|
||||
// Used to query for multiple rows.
|
||||
//
|
||||
// You can use this in tandem with a dataset by doing the following.
|
||||
// sql, err := db.From("items").Where(goqu.I("id").Gt(10)).ToSQL()
|
||||
// if err != nil{
|
||||
// panic(err.Error()) //you could gracefully handle the error also
|
||||
// }
|
||||
// rows, err := stmt.QueryContext(ctx, args)
|
||||
// if err != nil{
|
||||
// panic(err.Error()) //you could gracefully handle the error also
|
||||
// }
|
||||
// defer rows.Close()
|
||||
// for rows.Next(){
|
||||
// //scan your rows
|
||||
// }
|
||||
// if rows.Err() != nil{
|
||||
// panic(err.Error()) //you could gracefully handle the error also
|
||||
// }
|
||||
//
|
||||
// query: The SQL to execute
|
||||
//
|
||||
// args...: for any placeholder parameters in the query
|
||||
func (d *Database) QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error) {
|
||||
d.Trace("QUERY", query, args...)
|
||||
return d.Db.QueryContext(ctx, query, args...)
|
||||
}
|
||||
|
||||
// Used to query for a single row.
|
||||
//
|
||||
// You can use this in tandem with a dataset by doing the following.
|
||||
// sql, err := db.From("items").Where(goqu.I("id").Gt(10)).Limit(1).ToSQL()
|
||||
// if err != nil{
|
||||
// panic(err.Error()) //you could gracefully handle the error also
|
||||
// }
|
||||
// rows, err := stmt.QueryRow(args)
|
||||
// if err != nil{
|
||||
// panic(err.Error()) //you could gracefully handle the error also
|
||||
// }
|
||||
// //scan your row
|
||||
//
|
||||
// query: The SQL to execute
|
||||
//
|
||||
// args...: for any placeholder parameters in the query
|
||||
func (d *Database) QueryRow(query string, args ...interface{}) *sql.Row {
|
||||
return d.QueryRowContext(context.Background(), query, args...)
|
||||
}
|
||||
|
||||
// Used to query for a single row.
|
||||
//
|
||||
// You can use this in tandem with a dataset by doing the following.
|
||||
// sql, err := db.From("items").Where(goqu.I("id").Gt(10)).Limit(1).ToSQL()
|
||||
// if err != nil{
|
||||
// panic(err.Error()) //you could gracefully handle the error also
|
||||
// }
|
||||
// rows, err := stmt.QueryRowContext(ctx, args)
|
||||
// if err != nil{
|
||||
// panic(err.Error()) //you could gracefully handle the error also
|
||||
// }
|
||||
// //scan your row
|
||||
//
|
||||
// query: The SQL to execute
|
||||
//
|
||||
// args...: for any placeholder parameters in the query
|
||||
func (d *Database) QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row {
|
||||
d.Trace("QUERY ROW", query, args...)
|
||||
return d.Db.QueryRowContext(ctx, query, args...)
|
||||
}
|
||||
|
||||
func (d *Database) queryFactory() exec.QueryFactory {
|
||||
d.qfOnce.Do(func() {
|
||||
d.qf = exec.NewQueryFactory(d)
|
||||
})
|
||||
return d.qf
|
||||
}
|
||||
|
||||
// Queries the database using the supplied query, and args and uses CrudExec.ScanStructs to scan the results into a
|
||||
// slice of structs
|
||||
//
|
||||
// i: A pointer to a slice of structs
|
||||
//
|
||||
// query: The SQL to execute
|
||||
//
|
||||
// args...: for any placeholder parameters in the query
|
||||
func (d *Database) ScanStructs(i interface{}, query string, args ...interface{}) error {
|
||||
return d.ScanStructsContext(context.Background(), i, query, args...)
|
||||
}
|
||||
|
||||
// Queries the database using the supplied context, query, and args and uses CrudExec.ScanStructsContext to scan the
|
||||
// results into a slice of structs
|
||||
//
|
||||
// i: A pointer to a slice of structs
|
||||
//
|
||||
// query: The SQL to execute
|
||||
//
|
||||
// args...: for any placeholder parameters in the query
|
||||
func (d *Database) ScanStructsContext(ctx context.Context, i interface{}, query string, args ...interface{}) error {
|
||||
return d.queryFactory().FromSQL(query, args...).ScanStructsContext(ctx, i)
|
||||
}
|
||||
|
||||
// Queries the database using the supplied query, and args and uses CrudExec.ScanStruct to scan the results into a
|
||||
// struct
|
||||
//
|
||||
// i: A pointer to a struct
|
||||
//
|
||||
// query: The SQL to execute
|
||||
//
|
||||
// args...: for any placeholder parameters in the query
|
||||
func (d *Database) ScanStruct(i interface{}, query string, args ...interface{}) (bool, error) {
|
||||
return d.ScanStructContext(context.Background(), i, query, args...)
|
||||
}
|
||||
|
||||
// Queries the database using the supplied context, query, and args and uses CrudExec.ScanStructContext to scan the
|
||||
// results into a struct
|
||||
//
|
||||
// i: A pointer to a struct
|
||||
//
|
||||
// query: The SQL to execute
|
||||
//
|
||||
// args...: for any placeholder parameters in the query
|
||||
func (d *Database) ScanStructContext(ctx context.Context, i interface{}, query string, args ...interface{}) (bool, error) {
|
||||
return d.queryFactory().FromSQL(query, args...).ScanStructContext(ctx, i)
|
||||
}
|
||||
|
||||
// Queries the database using the supplied query, and args and uses CrudExec.ScanVals to scan the results into a slice
|
||||
// of primitive values
|
||||
//
|
||||
// i: A pointer to a slice of primitive values
|
||||
//
|
||||
// query: The SQL to execute
|
||||
//
|
||||
// args...: for any placeholder parameters in the query
|
||||
func (d *Database) ScanVals(i interface{}, query string, args ...interface{}) error {
|
||||
return d.ScanValsContext(context.Background(), i, query, args...)
|
||||
}
|
||||
|
||||
// Queries the database using the supplied context, query, and args and uses CrudExec.ScanValsContext to scan the
|
||||
// results into a slice of primitive values
|
||||
//
|
||||
// i: A pointer to a slice of primitive values
|
||||
//
|
||||
// query: The SQL to execute
|
||||
//
|
||||
// args...: for any placeholder parameters in the query
|
||||
func (d *Database) ScanValsContext(ctx context.Context, i interface{}, query string, args ...interface{}) error {
|
||||
return d.queryFactory().FromSQL(query, args...).ScanValsContext(ctx, i)
|
||||
}
|
||||
|
||||
// Queries the database using the supplied query, and args and uses CrudExec.ScanVal to scan the results into a
|
||||
// primitive value
|
||||
//
|
||||
// i: A pointer to a primitive value
|
||||
//
|
||||
// query: The SQL to execute
|
||||
//
|
||||
// args...: for any placeholder parameters in the query
|
||||
func (d *Database) ScanVal(i interface{}, query string, args ...interface{}) (bool, error) {
|
||||
return d.ScanValContext(context.Background(), i, query, args...)
|
||||
}
|
||||
|
||||
// Queries the database using the supplied context, query, and args and uses CrudExec.ScanValContext to scan the
|
||||
// results into a primitive value
|
||||
//
|
||||
// i: A pointer to a primitive value
|
||||
//
|
||||
// query: The SQL to execute
|
||||
//
|
||||
// args...: for any placeholder parameters in the query
|
||||
func (d *Database) ScanValContext(ctx context.Context, i interface{}, query string, args ...interface{}) (bool, error) {
|
||||
return d.queryFactory().FromSQL(query, args...).ScanValContext(ctx, i)
|
||||
}
|
||||
|
||||
// A wrapper around a sql.Tx and works the same way as Database
|
||||
type (
|
||||
// Interface for sql.Tx, an interface is used so you can use with other
|
||||
// libraries such as sqlx instead of the native sql.DB
|
||||
SQLTx interface {
|
||||
ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error)
|
||||
PrepareContext(ctx context.Context, query string) (*sql.Stmt, error)
|
||||
QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error)
|
||||
QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row
|
||||
Commit() error
|
||||
Rollback() error
|
||||
}
|
||||
TxDatabase struct {
|
||||
logger Logger
|
||||
dialect string
|
||||
Tx SQLTx
|
||||
qf exec.QueryFactory
|
||||
qfOnce sync.Once
|
||||
}
|
||||
)
|
||||
|
||||
// Creates a new TxDatabase
|
||||
func NewTx(dialect string, tx SQLTx) *TxDatabase {
|
||||
return &TxDatabase{dialect: dialect, Tx: tx}
|
||||
}
|
||||
|
||||
// returns this databases dialect
|
||||
func (td *TxDatabase) Dialect() string {
|
||||
return td.dialect
|
||||
}
|
||||
|
||||
// Creates a new Dataset for querying a Database.
|
||||
func (td *TxDatabase) From(cols ...interface{}) *SelectDataset {
|
||||
return newDataset(td.dialect, td.queryFactory()).From(cols...)
|
||||
}
|
||||
|
||||
func (td *TxDatabase) Select(cols ...interface{}) *SelectDataset {
|
||||
return newDataset(td.dialect, td.queryFactory()).Select(cols...)
|
||||
}
|
||||
|
||||
func (td *TxDatabase) Update(table interface{}) *UpdateDataset {
|
||||
return newUpdateDataset(td.dialect, td.queryFactory()).Table(table)
|
||||
}
|
||||
|
||||
func (td *TxDatabase) Insert(table interface{}) *InsertDataset {
|
||||
return newInsertDataset(td.dialect, td.queryFactory()).Into(table)
|
||||
}
|
||||
|
||||
func (td *TxDatabase) Delete(table interface{}) *DeleteDataset {
|
||||
return newDeleteDataset(td.dialect, td.queryFactory()).From(table)
|
||||
}
|
||||
|
||||
func (td *TxDatabase) Truncate(table ...interface{}) *TruncateDataset {
|
||||
return newTruncateDataset(td.dialect, td.queryFactory()).Table(table...)
|
||||
}
|
||||
|
||||
// Sets the logger
|
||||
func (td *TxDatabase) Logger(logger Logger) {
|
||||
td.logger = logger
|
||||
}
|
||||
|
||||
func (td *TxDatabase) Trace(op, sqlString string, args ...interface{}) {
|
||||
if td.logger != nil {
|
||||
if sqlString != "" {
|
||||
if len(args) != 0 {
|
||||
td.logger.Printf("[goqu - transaction] %s [query:=`%s` args:=%+v] ", op, sqlString, args)
|
||||
} else {
|
||||
td.logger.Printf("[goqu - transaction] %s [query:=`%s`] ", op, sqlString)
|
||||
}
|
||||
} else {
|
||||
td.logger.Printf("[goqu - transaction] %s", op)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// See Database#Exec
|
||||
func (td *TxDatabase) Exec(query string, args ...interface{}) (sql.Result, error) {
|
||||
return td.ExecContext(context.Background(), query, args...)
|
||||
}
|
||||
|
||||
// See Database#ExecContext
|
||||
func (td *TxDatabase) ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error) {
|
||||
td.Trace("EXEC", query, args...)
|
||||
return td.Tx.ExecContext(ctx, query, args...)
|
||||
}
|
||||
|
||||
// See Database#Prepare
|
||||
func (td *TxDatabase) Prepare(query string) (*sql.Stmt, error) {
|
||||
return td.PrepareContext(context.Background(), query)
|
||||
}
|
||||
|
||||
// See Database#PrepareContext
|
||||
func (td *TxDatabase) PrepareContext(ctx context.Context, query string) (*sql.Stmt, error) {
|
||||
td.Trace("PREPARE", query)
|
||||
return td.Tx.PrepareContext(ctx, query)
|
||||
}
|
||||
|
||||
// See Database#Query
|
||||
func (td *TxDatabase) Query(query string, args ...interface{}) (*sql.Rows, error) {
|
||||
return td.QueryContext(context.Background(), query, args...)
|
||||
}
|
||||
|
||||
// See Database#QueryContext
|
||||
func (td *TxDatabase) QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error) {
|
||||
td.Trace("QUERY", query, args...)
|
||||
return td.Tx.QueryContext(ctx, query, args...)
|
||||
}
|
||||
|
||||
// See Database#QueryRow
|
||||
func (td *TxDatabase) QueryRow(query string, args ...interface{}) *sql.Row {
|
||||
return td.QueryRowContext(context.Background(), query, args...)
|
||||
}
|
||||
|
||||
// See Database#QueryRowContext
|
||||
func (td *TxDatabase) QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row {
|
||||
td.Trace("QUERY ROW", query, args...)
|
||||
return td.Tx.QueryRowContext(ctx, query, args...)
|
||||
}
|
||||
|
||||
func (td *TxDatabase) queryFactory() exec.QueryFactory {
|
||||
td.qfOnce.Do(func() {
|
||||
td.qf = exec.NewQueryFactory(td)
|
||||
})
|
||||
return td.qf
|
||||
}
|
||||
|
||||
// See Database#ScanStructs
|
||||
func (td *TxDatabase) ScanStructs(i interface{}, query string, args ...interface{}) error {
|
||||
return td.ScanStructsContext(context.Background(), i, query, args...)
|
||||
}
|
||||
|
||||
// See Database#ScanStructsContext
|
||||
func (td *TxDatabase) ScanStructsContext(ctx context.Context, i interface{}, query string, args ...interface{}) error {
|
||||
return td.queryFactory().FromSQL(query, args...).ScanStructsContext(ctx, i)
|
||||
}
|
||||
|
||||
// See Database#ScanStruct
|
||||
func (td *TxDatabase) ScanStruct(i interface{}, query string, args ...interface{}) (bool, error) {
|
||||
return td.ScanStructContext(context.Background(), i, query, args...)
|
||||
}
|
||||
|
||||
// See Database#ScanStructContext
|
||||
func (td *TxDatabase) ScanStructContext(ctx context.Context, i interface{}, query string, args ...interface{}) (bool, error) {
|
||||
return td.queryFactory().FromSQL(query, args...).ScanStructContext(ctx, i)
|
||||
}
|
||||
|
||||
// See Database#ScanVals
|
||||
func (td *TxDatabase) ScanVals(i interface{}, query string, args ...interface{}) error {
|
||||
return td.ScanValsContext(context.Background(), i, query, args...)
|
||||
}
|
||||
|
||||
// See Database#ScanValsContext
|
||||
func (td *TxDatabase) ScanValsContext(ctx context.Context, i interface{}, query string, args ...interface{}) error {
|
||||
return td.queryFactory().FromSQL(query, args...).ScanValsContext(ctx, i)
|
||||
}
|
||||
|
||||
// See Database#ScanVal
|
||||
func (td *TxDatabase) ScanVal(i interface{}, query string, args ...interface{}) (bool, error) {
|
||||
return td.ScanValContext(context.Background(), i, query, args...)
|
||||
}
|
||||
|
||||
// See Database#ScanValContext
|
||||
func (td *TxDatabase) ScanValContext(ctx context.Context, i interface{}, query string, args ...interface{}) (bool, error) {
|
||||
return td.queryFactory().FromSQL(query, args...).ScanValContext(ctx, i)
|
||||
}
|
||||
|
||||
// COMMIT the transaction
|
||||
func (td *TxDatabase) Commit() error {
|
||||
td.Trace("COMMIT", "")
|
||||
return td.Tx.Commit()
|
||||
}
|
||||
|
||||
// ROLLBACK the transaction
|
||||
func (td *TxDatabase) Rollback() error {
|
||||
td.Trace("ROLLBACK", "")
|
||||
return td.Tx.Rollback()
|
||||
}
|
||||
|
||||
// A helper method that will automatically COMMIT or ROLLBACK once the supplied function is done executing
|
||||
//
|
||||
// tx, err := db.Begin()
|
||||
// if err != nil{
|
||||
// panic(err.Error()) // you could gracefully handle the error also
|
||||
// }
|
||||
// if err := tx.Wrap(func() error{
|
||||
// if _, err := tx.From("test").Insert(Record{"a":1, "b": "b"}).Exec(){
|
||||
// // this error will be the return error from the Wrap call
|
||||
// return err
|
||||
// }
|
||||
// return nil
|
||||
// }); err != nil{
|
||||
// panic(err.Error()) // you could gracefully handle the error also
|
||||
// }
|
||||
func (td *TxDatabase) Wrap(fn func() error) (err error) {
|
||||
defer func() {
|
||||
if p := recover(); p != nil {
|
||||
_ = td.Rollback()
|
||||
panic(p)
|
||||
}
|
||||
if err != nil {
|
||||
if rollbackErr := td.Rollback(); rollbackErr != nil {
|
||||
err = rollbackErr
|
||||
}
|
||||
} else {
|
||||
if commitErr := td.Commit(); commitErr != nil {
|
||||
err = commitErr
|
||||
}
|
||||
}
|
||||
}()
|
||||
return fn()
|
||||
}
|
||||
244
vendor/github.com/doug-martin/goqu/v9/delete_dataset.go
generated
vendored
Normal file
244
vendor/github.com/doug-martin/goqu/v9/delete_dataset.go
generated
vendored
Normal file
@@ -0,0 +1,244 @@
|
||||
package goqu
|
||||
|
||||
import (
|
||||
"github.com/doug-martin/goqu/v9/exec"
|
||||
"github.com/doug-martin/goqu/v9/exp"
|
||||
"github.com/doug-martin/goqu/v9/internal/errors"
|
||||
"github.com/doug-martin/goqu/v9/internal/sb"
|
||||
)
|
||||
|
||||
var ErrBadFromArgument = errors.New("unsupported DeleteDataset#From argument, a string or identifier expression is required")
|
||||
|
||||
type DeleteDataset struct {
|
||||
dialect SQLDialect
|
||||
clauses exp.DeleteClauses
|
||||
isPrepared prepared
|
||||
queryFactory exec.QueryFactory
|
||||
err error
|
||||
}
|
||||
|
||||
// used internally by database to create a database with a specific adapter
|
||||
func newDeleteDataset(d string, queryFactory exec.QueryFactory) *DeleteDataset {
|
||||
return &DeleteDataset{
|
||||
clauses: exp.NewDeleteClauses(),
|
||||
dialect: GetDialect(d),
|
||||
queryFactory: queryFactory,
|
||||
isPrepared: preparedNoPreference,
|
||||
err: nil,
|
||||
}
|
||||
}
|
||||
|
||||
func Delete(table interface{}) *DeleteDataset {
|
||||
return newDeleteDataset("default", nil).From(table)
|
||||
}
|
||||
|
||||
func (dd *DeleteDataset) Expression() exp.Expression {
|
||||
return dd
|
||||
}
|
||||
|
||||
// Clones the dataset
|
||||
func (dd *DeleteDataset) Clone() exp.Expression {
|
||||
return dd.copy(dd.clauses)
|
||||
}
|
||||
|
||||
// Set the parameter interpolation behavior. See examples
|
||||
//
|
||||
// prepared: If true the dataset WILL NOT interpolate the parameters.
|
||||
func (dd *DeleteDataset) Prepared(prepared bool) *DeleteDataset {
|
||||
ret := dd.copy(dd.clauses)
|
||||
ret.isPrepared = preparedFromBool(prepared)
|
||||
return ret
|
||||
}
|
||||
|
||||
// Returns true if Prepared(true) has been called on this dataset
|
||||
func (dd *DeleteDataset) IsPrepared() bool {
|
||||
return dd.isPrepared.Bool()
|
||||
}
|
||||
|
||||
// Sets the adapter used to serialize values and create the SQL statement
|
||||
func (dd *DeleteDataset) WithDialect(dl string) *DeleteDataset {
|
||||
ds := dd.copy(dd.GetClauses())
|
||||
ds.dialect = GetDialect(dl)
|
||||
return ds
|
||||
}
|
||||
|
||||
// Returns the current SQLDialect on the dataset
|
||||
func (dd *DeleteDataset) Dialect() SQLDialect {
|
||||
return dd.dialect
|
||||
}
|
||||
|
||||
// Set the dialect for this dataset.
|
||||
func (dd *DeleteDataset) SetDialect(dialect SQLDialect) *DeleteDataset {
|
||||
cd := dd.copy(dd.GetClauses())
|
||||
cd.dialect = dialect
|
||||
return cd
|
||||
}
|
||||
|
||||
// Returns the current clauses on the dataset.
|
||||
func (dd *DeleteDataset) GetClauses() exp.DeleteClauses {
|
||||
return dd.clauses
|
||||
}
|
||||
|
||||
// used interally to copy the dataset
|
||||
func (dd *DeleteDataset) copy(clauses exp.DeleteClauses) *DeleteDataset {
|
||||
return &DeleteDataset{
|
||||
dialect: dd.dialect,
|
||||
clauses: clauses,
|
||||
isPrepared: dd.isPrepared,
|
||||
queryFactory: dd.queryFactory,
|
||||
err: dd.err,
|
||||
}
|
||||
}
|
||||
|
||||
// Creates a WITH clause for a common table expression (CTE).
|
||||
//
|
||||
// The name will be available to SELECT from in the associated query; and can optionally
|
||||
// contain a list of column names "name(col1, col2, col3)".
|
||||
//
|
||||
// The name will refer to the results of the specified subquery.
|
||||
func (dd *DeleteDataset) With(name string, subquery exp.Expression) *DeleteDataset {
|
||||
return dd.copy(dd.clauses.CommonTablesAppend(exp.NewCommonTableExpression(false, name, subquery)))
|
||||
}
|
||||
|
||||
// Creates a WITH RECURSIVE clause for a common table expression (CTE)
|
||||
//
|
||||
// The name will be available to SELECT from in the associated query; and must
|
||||
// contain a list of column names "name(col1, col2, col3)" for a recursive clause.
|
||||
//
|
||||
// The name will refer to the results of the specified subquery. The subquery for
|
||||
// a recursive query will always end with a UNION or UNION ALL with a clause that
|
||||
// refers to the CTE by name.
|
||||
func (dd *DeleteDataset) WithRecursive(name string, subquery exp.Expression) *DeleteDataset {
|
||||
return dd.copy(dd.clauses.CommonTablesAppend(exp.NewCommonTableExpression(true, name, subquery)))
|
||||
}
|
||||
|
||||
// Adds a FROM clause. This return a new dataset with the original sources replaced. See examples.
|
||||
// You can pass in the following.
|
||||
// string: Will automatically be turned into an identifier
|
||||
// Dataset: Will be added as a sub select. If the Dataset is not aliased it will automatically be aliased
|
||||
// LiteralExpression: (See Literal) Will use the literal SQL
|
||||
func (dd *DeleteDataset) From(table interface{}) *DeleteDataset {
|
||||
switch t := table.(type) {
|
||||
case exp.IdentifierExpression:
|
||||
return dd.copy(dd.clauses.SetFrom(t))
|
||||
case string:
|
||||
return dd.copy(dd.clauses.SetFrom(exp.ParseIdentifier(t)))
|
||||
default:
|
||||
panic(ErrBadFromArgument)
|
||||
}
|
||||
}
|
||||
|
||||
// Adds a WHERE clause. See examples.
|
||||
func (dd *DeleteDataset) Where(expressions ...exp.Expression) *DeleteDataset {
|
||||
return dd.copy(dd.clauses.WhereAppend(expressions...))
|
||||
}
|
||||
|
||||
// Removes the WHERE clause. See examples.
|
||||
func (dd *DeleteDataset) ClearWhere() *DeleteDataset {
|
||||
return dd.copy(dd.clauses.ClearWhere())
|
||||
}
|
||||
|
||||
// Adds a ORDER clause. If the ORDER is currently set it replaces it. See examples.
|
||||
func (dd *DeleteDataset) Order(order ...exp.OrderedExpression) *DeleteDataset {
|
||||
return dd.copy(dd.clauses.SetOrder(order...))
|
||||
}
|
||||
|
||||
// Adds a more columns to the current ORDER BY clause. If no order has be previously specified it is the same as
|
||||
// calling Order. See examples.
|
||||
func (dd *DeleteDataset) OrderAppend(order ...exp.OrderedExpression) *DeleteDataset {
|
||||
return dd.copy(dd.clauses.OrderAppend(order...))
|
||||
}
|
||||
|
||||
// Adds a more columns to the beginning of the current ORDER BY clause. If no order has be previously specified it is the same as
|
||||
// calling Order. See examples.
|
||||
func (dd *DeleteDataset) OrderPrepend(order ...exp.OrderedExpression) *DeleteDataset {
|
||||
return dd.copy(dd.clauses.OrderPrepend(order...))
|
||||
}
|
||||
|
||||
// Removes the ORDER BY clause. See examples.
|
||||
func (dd *DeleteDataset) ClearOrder() *DeleteDataset {
|
||||
return dd.copy(dd.clauses.ClearOrder())
|
||||
}
|
||||
|
||||
// Adds a LIMIT clause. If the LIMIT is currently set it replaces it. See examples.
|
||||
func (dd *DeleteDataset) Limit(limit uint) *DeleteDataset {
|
||||
if limit > 0 {
|
||||
return dd.copy(dd.clauses.SetLimit(limit))
|
||||
}
|
||||
return dd.copy(dd.clauses.ClearLimit())
|
||||
}
|
||||
|
||||
// Adds a LIMIT ALL clause. If the LIMIT is currently set it replaces it. See examples.
|
||||
func (dd *DeleteDataset) LimitAll() *DeleteDataset {
|
||||
return dd.copy(dd.clauses.SetLimit(L("ALL")))
|
||||
}
|
||||
|
||||
// Removes the LIMIT clause.
|
||||
func (dd *DeleteDataset) ClearLimit() *DeleteDataset {
|
||||
return dd.copy(dd.clauses.ClearLimit())
|
||||
}
|
||||
|
||||
// Adds a RETURNING clause to the dataset if the adapter supports it.
|
||||
func (dd *DeleteDataset) Returning(returning ...interface{}) *DeleteDataset {
|
||||
return dd.copy(dd.clauses.SetReturning(exp.NewColumnListExpression(returning...)))
|
||||
}
|
||||
|
||||
// Get any error that has been set or nil if no error has been set.
|
||||
func (dd *DeleteDataset) Error() error {
|
||||
return dd.err
|
||||
}
|
||||
|
||||
// Set an error on the dataset if one has not already been set. This error will be returned by a future call to Error
|
||||
// or as part of ToSQL. This can be used by end users to record errors while building up queries without having to
|
||||
// track those separately.
|
||||
func (dd *DeleteDataset) SetError(err error) *DeleteDataset {
|
||||
if dd.err == nil {
|
||||
dd.err = err
|
||||
}
|
||||
|
||||
return dd
|
||||
}
|
||||
|
||||
// Generates a DELETE sql statement, if Prepared has been called with true then the parameters will not be interpolated.
|
||||
// See examples.
|
||||
//
|
||||
// Errors:
|
||||
// * There is an error generating the SQL
|
||||
func (dd *DeleteDataset) ToSQL() (sql string, params []interface{}, err error) {
|
||||
return dd.deleteSQLBuilder().ToSQL()
|
||||
}
|
||||
|
||||
// Appends this Dataset's DELETE statement to the SQLBuilder
|
||||
// This is used internally when using deletes in CTEs
|
||||
func (dd *DeleteDataset) AppendSQL(b sb.SQLBuilder) {
|
||||
if dd.err != nil {
|
||||
b.SetError(dd.err)
|
||||
return
|
||||
}
|
||||
dd.dialect.ToDeleteSQL(b, dd.GetClauses())
|
||||
}
|
||||
|
||||
func (dd *DeleteDataset) GetAs() exp.IdentifierExpression {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dd *DeleteDataset) ReturnsColumns() bool {
|
||||
return dd.clauses.HasReturning()
|
||||
}
|
||||
|
||||
// Creates an QueryExecutor to execute the query.
|
||||
// db.Delete("test").Exec()
|
||||
//
|
||||
// See Dataset#ToUpdateSQL for arguments
|
||||
func (dd *DeleteDataset) Executor() exec.QueryExecutor {
|
||||
return dd.queryFactory.FromSQLBuilder(dd.deleteSQLBuilder())
|
||||
}
|
||||
|
||||
func (dd *DeleteDataset) deleteSQLBuilder() sb.SQLBuilder {
|
||||
buf := sb.NewSQLBuilder(dd.isPrepared.Bool())
|
||||
if dd.err != nil {
|
||||
return buf.SetError(dd.err)
|
||||
}
|
||||
dd.dialect.ToDeleteSQL(buf, dd.clauses)
|
||||
return buf
|
||||
}
|
||||
76
vendor/github.com/doug-martin/goqu/v9/dialect/sqlite3/sqlite3.go
generated
vendored
Normal file
76
vendor/github.com/doug-martin/goqu/v9/dialect/sqlite3/sqlite3.go
generated
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
package sqlite3
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/doug-martin/goqu/v9"
|
||||
"github.com/doug-martin/goqu/v9/exp"
|
||||
)
|
||||
|
||||
func DialectOptions() *goqu.SQLDialectOptions {
|
||||
opts := goqu.DefaultDialectOptions()
|
||||
|
||||
opts.SupportsReturn = false
|
||||
opts.SupportsOrderByOnUpdate = true
|
||||
opts.SupportsLimitOnUpdate = true
|
||||
opts.SupportsOrderByOnDelete = true
|
||||
opts.SupportsLimitOnDelete = true
|
||||
opts.SupportsConflictUpdateWhere = false
|
||||
opts.SupportsInsertIgnoreSyntax = true
|
||||
opts.SupportsConflictTarget = true
|
||||
opts.SupportsMultipleUpdateTables = false
|
||||
opts.WrapCompoundsInParens = false
|
||||
opts.SupportsDistinctOn = false
|
||||
opts.SupportsWindowFunction = false
|
||||
opts.SupportsLateral = false
|
||||
|
||||
opts.PlaceHolderFragment = []byte("?")
|
||||
opts.IncludePlaceholderNum = false
|
||||
opts.QuoteRune = '`'
|
||||
opts.DefaultValuesFragment = []byte("")
|
||||
opts.True = []byte("1")
|
||||
opts.False = []byte("0")
|
||||
opts.TimeFormat = time.RFC3339Nano
|
||||
opts.BooleanOperatorLookup = map[exp.BooleanOperation][]byte{
|
||||
exp.EqOp: []byte("="),
|
||||
exp.NeqOp: []byte("!="),
|
||||
exp.GtOp: []byte(">"),
|
||||
exp.GteOp: []byte(">="),
|
||||
exp.LtOp: []byte("<"),
|
||||
exp.LteOp: []byte("<="),
|
||||
exp.InOp: []byte("IN"),
|
||||
exp.NotInOp: []byte("NOT IN"),
|
||||
exp.IsOp: []byte("IS"),
|
||||
exp.IsNotOp: []byte("IS NOT"),
|
||||
exp.LikeOp: []byte("LIKE"),
|
||||
exp.NotLikeOp: []byte("NOT LIKE"),
|
||||
exp.ILikeOp: []byte("LIKE"),
|
||||
exp.NotILikeOp: []byte("NOT LIKE"),
|
||||
exp.RegexpLikeOp: []byte("REGEXP"),
|
||||
exp.RegexpNotLikeOp: []byte("NOT REGEXP"),
|
||||
exp.RegexpILikeOp: []byte("REGEXP"),
|
||||
exp.RegexpNotILikeOp: []byte("NOT REGEXP"),
|
||||
}
|
||||
opts.UseLiteralIsBools = false
|
||||
opts.BitwiseOperatorLookup = map[exp.BitwiseOperation][]byte{
|
||||
exp.BitwiseOrOp: []byte("|"),
|
||||
exp.BitwiseAndOp: []byte("&"),
|
||||
exp.BitwiseLeftShiftOp: []byte("<<"),
|
||||
exp.BitwiseRightShiftOp: []byte(">>"),
|
||||
}
|
||||
opts.EscapedRunes = map[rune][]byte{
|
||||
'\'': []byte("''"),
|
||||
}
|
||||
opts.InsertIgnoreClause = []byte("INSERT OR IGNORE INTO ")
|
||||
opts.ConflictFragment = []byte(" ON CONFLICT ")
|
||||
opts.ConflictDoUpdateFragment = []byte(" DO UPDATE SET ")
|
||||
opts.ConflictDoNothingFragment = []byte(" DO NOTHING ")
|
||||
opts.ForUpdateFragment = []byte("")
|
||||
opts.OfFragment = []byte("")
|
||||
opts.NowaitFragment = []byte("")
|
||||
return opts
|
||||
}
|
||||
|
||||
func init() {
|
||||
goqu.RegisterDialect("sqlite3", DialectOptions())
|
||||
}
|
||||
62
vendor/github.com/doug-martin/goqu/v9/docker-compose.yml
generated
vendored
Normal file
62
vendor/github.com/doug-martin/goqu/v9/docker-compose.yml
generated
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
version: "2"
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: "postgres:${POSTGRES_VERSION}"
|
||||
environment:
|
||||
- "POSTGRES_USER=postgres"
|
||||
- "POSTGRES_DB=goqupostgres"
|
||||
- "POSTGRES_HOST_AUTH_METHOD=trust"
|
||||
expose:
|
||||
- "5432"
|
||||
ports:
|
||||
- "5432:5432"
|
||||
|
||||
mysql:
|
||||
image: "mysql:${MYSQL_VERSION}"
|
||||
environment:
|
||||
- "MYSQL_DATABASE=goqumysql"
|
||||
- "MYSQL_ALLOW_EMPTY_PASSWORD=yes"
|
||||
expose:
|
||||
- "3306"
|
||||
ports:
|
||||
- "3306:3306"
|
||||
|
||||
sqlserver:
|
||||
image: "mcr.microsoft.com/mssql/server:${SQLSERVER_VERSION}"
|
||||
environment:
|
||||
- "ACCEPT_EULA=Y"
|
||||
- "SA_PASSWORD=qwe123QWE"
|
||||
expose:
|
||||
- "1433"
|
||||
ports:
|
||||
- "1433:1433"
|
||||
|
||||
goqu:
|
||||
image: "golang:${GO_VERSION}"
|
||||
command: ["./wait-for-it.sh", "postgres:5432", "--", "./wait-for-it.sh", "mysql:3306", "--", "go test -v -race ./..."]
|
||||
working_dir: /go/src/github.com/doug-martin/goqu
|
||||
volumes:
|
||||
- "./:/go/src/github.com/doug-martin/goqu"
|
||||
environment:
|
||||
MYSQL_URI: 'root@tcp(mysql:3306)/goqumysql?parseTime=true'
|
||||
PG_URI: 'postgres://postgres:@postgres:5432/goqupostgres?sslmode=disable'
|
||||
SQLSERVER_URI: 'sqlserver://sa:qwe123QWE@sqlserver:1433?database=master&connection+timeout=30'
|
||||
depends_on:
|
||||
- postgres
|
||||
- mysql
|
||||
- sqlserver
|
||||
goqu-coverage:
|
||||
image: "golang:${GO_VERSION}"
|
||||
command: ["./wait-for-it.sh", "postgres:5432", "--", "./wait-for-it.sh", "mysql:3306", "--", "./go.test.sh"]
|
||||
working_dir: /go/src/github.com/doug-martin/goqu
|
||||
volumes:
|
||||
- "./:/go/src/github.com/doug-martin/goqu"
|
||||
environment:
|
||||
MYSQL_URI: 'root@tcp(mysql:3306)/goqumysql?parseTime=true'
|
||||
PG_URI: 'postgres://postgres:@postgres:5432/goqupostgres?sslmode=disable'
|
||||
SQLSERVER_URI: 'sqlserver://sa:qwe123QWE@sqlserver:1433?database=master&connection+timeout=30'
|
||||
depends_on:
|
||||
- postgres
|
||||
- mysql
|
||||
- sqlserver
|
||||
247
vendor/github.com/doug-martin/goqu/v9/exec/query_executor.go
generated
vendored
Normal file
247
vendor/github.com/doug-martin/goqu/v9/exec/query_executor.go
generated
vendored
Normal file
@@ -0,0 +1,247 @@
|
||||
package exec
|
||||
|
||||
import (
|
||||
"context"
|
||||
gsql "database/sql"
|
||||
"reflect"
|
||||
|
||||
"github.com/doug-martin/goqu/v9/internal/errors"
|
||||
"github.com/doug-martin/goqu/v9/internal/util"
|
||||
)
|
||||
|
||||
type (
|
||||
QueryExecutor struct {
|
||||
de DbExecutor
|
||||
err error
|
||||
query string
|
||||
args []interface{}
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
errUnsupportedScanStructType = errors.New("type must be a pointer to a struct when scanning into a struct")
|
||||
errUnsupportedScanStructsType = errors.New("type must be a pointer to a slice when scanning into structs")
|
||||
errUnsupportedScanValsType = errors.New("type must be a pointer to a slice when scanning into vals")
|
||||
errScanValPointer = errors.New("type must be a pointer when scanning into val")
|
||||
errScanValNonSlice = errors.New("type cannot be a pointer to a slice when scanning into val")
|
||||
)
|
||||
|
||||
func newQueryExecutor(de DbExecutor, err error, query string, args ...interface{}) QueryExecutor {
|
||||
return QueryExecutor{de: de, err: err, query: query, args: args}
|
||||
}
|
||||
|
||||
func (q QueryExecutor) ToSQL() (sql string, args []interface{}, err error) {
|
||||
return q.query, q.args, q.err
|
||||
}
|
||||
|
||||
func (q QueryExecutor) Exec() (gsql.Result, error) {
|
||||
return q.ExecContext(context.Background())
|
||||
}
|
||||
|
||||
func (q QueryExecutor) ExecContext(ctx context.Context) (gsql.Result, error) {
|
||||
if q.err != nil {
|
||||
return nil, q.err
|
||||
}
|
||||
return q.de.ExecContext(ctx, q.query, q.args...)
|
||||
}
|
||||
|
||||
func (q QueryExecutor) Query() (*gsql.Rows, error) {
|
||||
return q.QueryContext(context.Background())
|
||||
}
|
||||
|
||||
func (q QueryExecutor) QueryContext(ctx context.Context) (*gsql.Rows, error) {
|
||||
if q.err != nil {
|
||||
return nil, q.err
|
||||
}
|
||||
return q.de.QueryContext(ctx, q.query, q.args...)
|
||||
}
|
||||
|
||||
// This will execute the SQL and append results to the slice
|
||||
// var myStructs []MyStruct
|
||||
// if err := db.From("test").ScanStructs(&myStructs); err != nil{
|
||||
// panic(err.Error()
|
||||
// }
|
||||
// //use your structs
|
||||
//
|
||||
//
|
||||
// i: A pointer to a slice of structs.
|
||||
func (q QueryExecutor) ScanStructs(i interface{}) error {
|
||||
return q.ScanStructsContext(context.Background(), i)
|
||||
}
|
||||
|
||||
// This will execute the SQL and append results to the slice
|
||||
// var myStructs []MyStruct
|
||||
// if err := db.From("test").ScanStructsContext(ctx, &myStructs); err != nil{
|
||||
// panic(err.Error()
|
||||
// }
|
||||
// //use your structs
|
||||
//
|
||||
//
|
||||
// i: A pointer to a slice of structs.
|
||||
func (q QueryExecutor) ScanStructsContext(ctx context.Context, i interface{}) error {
|
||||
scanner, err := q.ScannerContext(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() { _ = scanner.Close() }()
|
||||
return scanner.ScanStructs(i)
|
||||
}
|
||||
|
||||
// This will execute the SQL and fill out the struct with the fields returned.
|
||||
// This method returns a boolean value that is false if no record was found
|
||||
// var myStruct MyStruct
|
||||
// found, err := db.From("test").Limit(1).ScanStruct(&myStruct)
|
||||
// if err != nil{
|
||||
// panic(err.Error()
|
||||
// }
|
||||
// if !found{
|
||||
// fmt.Println("NOT FOUND")
|
||||
// }
|
||||
//
|
||||
// i: A pointer to a struct
|
||||
func (q QueryExecutor) ScanStruct(i interface{}) (bool, error) {
|
||||
return q.ScanStructContext(context.Background(), i)
|
||||
}
|
||||
|
||||
// This will execute the SQL and fill out the struct with the fields returned.
|
||||
// This method returns a boolean value that is false if no record was found
|
||||
// var myStruct MyStruct
|
||||
// found, err := db.From("test").Limit(1).ScanStructContext(ctx, &myStruct)
|
||||
// if err != nil{
|
||||
// panic(err.Error()
|
||||
// }
|
||||
// if !found{
|
||||
// fmt.Println("NOT FOUND")
|
||||
// }
|
||||
//
|
||||
// i: A pointer to a struct
|
||||
func (q QueryExecutor) ScanStructContext(ctx context.Context, i interface{}) (bool, error) {
|
||||
val := reflect.ValueOf(i)
|
||||
if !util.IsPointer(val.Kind()) {
|
||||
return false, errUnsupportedScanStructType
|
||||
}
|
||||
val = reflect.Indirect(val)
|
||||
if !util.IsStruct(val.Kind()) {
|
||||
return false, errUnsupportedScanStructType
|
||||
}
|
||||
|
||||
scanner, err := q.ScannerContext(ctx)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
defer func() { _ = scanner.Close() }()
|
||||
|
||||
if scanner.Next() {
|
||||
err = scanner.ScanStruct(i)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return true, scanner.Err()
|
||||
}
|
||||
|
||||
return false, scanner.Err()
|
||||
}
|
||||
|
||||
// This will execute the SQL and append results to the slice.
|
||||
// var ids []uint32
|
||||
// if err := db.From("test").Select("id").ScanVals(&ids); err != nil{
|
||||
// panic(err.Error()
|
||||
// }
|
||||
//
|
||||
// i: Takes a pointer to a slice of primitive values.
|
||||
func (q QueryExecutor) ScanVals(i interface{}) error {
|
||||
return q.ScanValsContext(context.Background(), i)
|
||||
}
|
||||
|
||||
// This will execute the SQL and append results to the slice.
|
||||
// var ids []uint32
|
||||
// if err := db.From("test").Select("id").ScanValsContext(ctx, &ids); err != nil{
|
||||
// panic(err.Error()
|
||||
// }
|
||||
//
|
||||
// i: Takes a pointer to a slice of primitive values.
|
||||
func (q QueryExecutor) ScanValsContext(ctx context.Context, i interface{}) error {
|
||||
scanner, err := q.ScannerContext(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() { _ = scanner.Close() }()
|
||||
return scanner.ScanVals(i)
|
||||
}
|
||||
|
||||
// This will execute the SQL and set the value of the primitive. This method will return false if no record is found.
|
||||
// var id uint32
|
||||
// found, err := db.From("test").Select("id").Limit(1).ScanVal(&id)
|
||||
// if err != nil{
|
||||
// panic(err.Error()
|
||||
// }
|
||||
// if !found{
|
||||
// fmt.Println("NOT FOUND")
|
||||
// }
|
||||
//
|
||||
// i: Takes a pointer to a primitive value.
|
||||
func (q QueryExecutor) ScanVal(i interface{}) (bool, error) {
|
||||
return q.ScanValContext(context.Background(), i)
|
||||
}
|
||||
|
||||
// This will execute the SQL and set the value of the primitive. This method will return false if no record is found.
|
||||
// var id uint32
|
||||
// found, err := db.From("test").Select("id").Limit(1).ScanValContext(ctx, &id)
|
||||
// if err != nil{
|
||||
// panic(err.Error()
|
||||
// }
|
||||
// if !found{
|
||||
// fmt.Println("NOT FOUND")
|
||||
// }
|
||||
//
|
||||
// i: Takes a pointer to a primitive value.
|
||||
func (q QueryExecutor) ScanValContext(ctx context.Context, i interface{}) (bool, error) {
|
||||
val := reflect.ValueOf(i)
|
||||
if !util.IsPointer(val.Kind()) {
|
||||
return false, errScanValPointer
|
||||
}
|
||||
val = reflect.Indirect(val)
|
||||
if util.IsSlice(val.Kind()) {
|
||||
switch i.(type) {
|
||||
case *gsql.RawBytes: // do nothing
|
||||
case *[]byte: // do nothing
|
||||
case gsql.Scanner: // do nothing
|
||||
default:
|
||||
return false, errScanValNonSlice
|
||||
}
|
||||
}
|
||||
|
||||
scanner, err := q.ScannerContext(ctx)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
defer func() { _ = scanner.Close() }()
|
||||
|
||||
if scanner.Next() {
|
||||
err = scanner.ScanVal(i)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return true, scanner.Err()
|
||||
}
|
||||
|
||||
return false, scanner.Err()
|
||||
}
|
||||
|
||||
// Scanner will return a Scanner that can be used for manually scanning rows.
|
||||
func (q QueryExecutor) Scanner() (Scanner, error) {
|
||||
return q.ScannerContext(context.Background())
|
||||
}
|
||||
|
||||
// ScannerContext will return a Scanner that can be used for manually scanning rows.
|
||||
func (q QueryExecutor) ScannerContext(ctx context.Context) (Scanner, error) {
|
||||
rows, err := q.QueryContext(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewScanner(rows), nil
|
||||
}
|
||||
36
vendor/github.com/doug-martin/goqu/v9/exec/query_factory.go
generated
vendored
Normal file
36
vendor/github.com/doug-martin/goqu/v9/exec/query_factory.go
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
package exec
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
|
||||
"github.com/doug-martin/goqu/v9/internal/sb"
|
||||
)
|
||||
|
||||
type (
|
||||
// nolint:stylecheck // keep name for backwards compatibility
|
||||
DbExecutor interface {
|
||||
ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error)
|
||||
QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error)
|
||||
}
|
||||
QueryFactory interface {
|
||||
FromSQL(sql string, args ...interface{}) QueryExecutor
|
||||
FromSQLBuilder(b sb.SQLBuilder) QueryExecutor
|
||||
}
|
||||
querySupport struct {
|
||||
de DbExecutor
|
||||
}
|
||||
)
|
||||
|
||||
func NewQueryFactory(de DbExecutor) QueryFactory {
|
||||
return &querySupport{de}
|
||||
}
|
||||
|
||||
func (qs *querySupport) FromSQL(query string, args ...interface{}) QueryExecutor {
|
||||
return newQueryExecutor(qs.de, nil, query, args...)
|
||||
}
|
||||
|
||||
func (qs *querySupport) FromSQLBuilder(b sb.SQLBuilder) QueryExecutor {
|
||||
query, args, err := b.ToSQL()
|
||||
return newQueryExecutor(qs.de, err, query, args...)
|
||||
}
|
||||
168
vendor/github.com/doug-martin/goqu/v9/exec/scanner.go
generated
vendored
Normal file
168
vendor/github.com/doug-martin/goqu/v9/exec/scanner.go
generated
vendored
Normal file
@@ -0,0 +1,168 @@
|
||||
package exec
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"reflect"
|
||||
|
||||
"github.com/doug-martin/goqu/v9/exp"
|
||||
"github.com/doug-martin/goqu/v9/internal/errors"
|
||||
"github.com/doug-martin/goqu/v9/internal/util"
|
||||
)
|
||||
|
||||
type (
|
||||
// Scanner knows how to scan sql.Rows into structs.
|
||||
Scanner interface {
|
||||
Next() bool
|
||||
ScanStruct(i interface{}) error
|
||||
ScanStructs(i interface{}) error
|
||||
ScanVal(i interface{}) error
|
||||
ScanVals(i interface{}) error
|
||||
Close() error
|
||||
Err() error
|
||||
}
|
||||
|
||||
scanner struct {
|
||||
rows *sql.Rows
|
||||
columnMap util.ColumnMap
|
||||
columns []string
|
||||
}
|
||||
)
|
||||
|
||||
func unableToFindFieldError(col string) error {
|
||||
return errors.New(`unable to find corresponding field to column "%s" returned by query`, col)
|
||||
}
|
||||
|
||||
// NewScanner returns a scanner that can be used for scanning rows into structs.
|
||||
func NewScanner(rows *sql.Rows) Scanner {
|
||||
return &scanner{rows: rows}
|
||||
}
|
||||
|
||||
// Next prepares the next row for Scanning. See sql.Rows#Next for more
|
||||
// information.
|
||||
func (s *scanner) Next() bool {
|
||||
return s.rows.Next()
|
||||
}
|
||||
|
||||
// Err returns the error, if any that was encountered during iteration. See
|
||||
// sql.Rows#Err for more information.
|
||||
func (s *scanner) Err() error {
|
||||
return s.rows.Err()
|
||||
}
|
||||
|
||||
// ScanStruct will scan the current row into i.
|
||||
func (s *scanner) ScanStruct(i interface{}) error {
|
||||
// Setup columnMap and columns, but only once.
|
||||
if s.columnMap == nil || s.columns == nil {
|
||||
cm, err := util.GetColumnMap(i)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cols, err := s.rows.Columns()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.columnMap = cm
|
||||
s.columns = cols
|
||||
}
|
||||
|
||||
scans := make([]interface{}, 0, len(s.columns))
|
||||
for _, col := range s.columns {
|
||||
data, ok := s.columnMap[col]
|
||||
switch {
|
||||
case !ok:
|
||||
return unableToFindFieldError(col)
|
||||
default:
|
||||
scans = append(scans, reflect.New(data.GoType).Interface())
|
||||
}
|
||||
}
|
||||
|
||||
if err := s.rows.Scan(scans...); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
record := exp.Record{}
|
||||
for index, col := range s.columns {
|
||||
record[col] = scans[index]
|
||||
}
|
||||
|
||||
util.AssignStructVals(i, record, s.columnMap)
|
||||
|
||||
return s.Err()
|
||||
}
|
||||
|
||||
// ScanStructs scans results in slice of structs
|
||||
func (s *scanner) ScanStructs(i interface{}) error {
|
||||
val, err := checkScanStructsTarget(i)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return s.scanIntoSlice(val, func(i interface{}) error {
|
||||
return s.ScanStruct(i)
|
||||
})
|
||||
}
|
||||
|
||||
// ScanVal will scan the current row and column into i.
|
||||
func (s *scanner) ScanVal(i interface{}) error {
|
||||
if err := s.rows.Scan(i); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return s.Err()
|
||||
}
|
||||
|
||||
// ScanStructs scans results in slice of values
|
||||
func (s *scanner) ScanVals(i interface{}) error {
|
||||
val, err := checkScanValsTarget(i)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return s.scanIntoSlice(val, func(i interface{}) error {
|
||||
return s.ScanVal(i)
|
||||
})
|
||||
}
|
||||
|
||||
// Close closes the Rows, preventing further enumeration. See sql.Rows#Close
|
||||
// for more info.
|
||||
func (s *scanner) Close() error {
|
||||
return s.rows.Close()
|
||||
}
|
||||
|
||||
func (s *scanner) scanIntoSlice(val reflect.Value, it func(i interface{}) error) error {
|
||||
elemType := util.GetSliceElementType(val)
|
||||
|
||||
for s.Next() {
|
||||
row := reflect.New(elemType)
|
||||
if rowErr := it(row.Interface()); rowErr != nil {
|
||||
return rowErr
|
||||
}
|
||||
util.AppendSliceElement(val, row)
|
||||
}
|
||||
|
||||
return s.Err()
|
||||
}
|
||||
|
||||
func checkScanStructsTarget(i interface{}) (reflect.Value, error) {
|
||||
val := reflect.ValueOf(i)
|
||||
if !util.IsPointer(val.Kind()) {
|
||||
return val, errUnsupportedScanStructsType
|
||||
}
|
||||
val = reflect.Indirect(val)
|
||||
if !util.IsSlice(val.Kind()) {
|
||||
return val, errUnsupportedScanStructsType
|
||||
}
|
||||
return val, nil
|
||||
}
|
||||
|
||||
func checkScanValsTarget(i interface{}) (reflect.Value, error) {
|
||||
val := reflect.ValueOf(i)
|
||||
if !util.IsPointer(val.Kind()) {
|
||||
return val, errUnsupportedScanValsType
|
||||
}
|
||||
val = reflect.Indirect(val)
|
||||
if !util.IsSlice(val.Kind()) {
|
||||
return val, errUnsupportedScanValsType
|
||||
}
|
||||
return val, nil
|
||||
}
|
||||
59
vendor/github.com/doug-martin/goqu/v9/exp/alias.go
generated
vendored
Normal file
59
vendor/github.com/doug-martin/goqu/v9/exp/alias.go
generated
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
package exp
|
||||
|
||||
import "fmt"
|
||||
|
||||
type (
|
||||
aliasExpression struct {
|
||||
aliased Expression
|
||||
alias IdentifierExpression
|
||||
}
|
||||
)
|
||||
|
||||
// Creates a new AliasedExpression for the Expression and alias
|
||||
func NewAliasExpression(exp Expression, alias interface{}) AliasedExpression {
|
||||
switch v := alias.(type) {
|
||||
case string:
|
||||
return aliasExpression{aliased: exp, alias: ParseIdentifier(v)}
|
||||
case IdentifierExpression:
|
||||
return aliasExpression{aliased: exp, alias: v}
|
||||
default:
|
||||
panic(fmt.Sprintf("Cannot create alias from %+v", v))
|
||||
}
|
||||
}
|
||||
|
||||
func (ae aliasExpression) Clone() Expression {
|
||||
return NewAliasExpression(ae.aliased, ae.alias.Clone())
|
||||
}
|
||||
|
||||
func (ae aliasExpression) Expression() Expression {
|
||||
return ae
|
||||
}
|
||||
|
||||
func (ae aliasExpression) Aliased() Expression {
|
||||
return ae.aliased
|
||||
}
|
||||
|
||||
func (ae aliasExpression) GetAs() IdentifierExpression {
|
||||
return ae.alias
|
||||
}
|
||||
|
||||
// Returns a new IdentifierExpression with the specified schema
|
||||
func (ae aliasExpression) Schema(schema string) IdentifierExpression {
|
||||
return ae.alias.Schema(schema)
|
||||
}
|
||||
|
||||
// Returns a new IdentifierExpression with the specified table
|
||||
func (ae aliasExpression) Table(table string) IdentifierExpression {
|
||||
return ae.alias.Table(table)
|
||||
}
|
||||
|
||||
// Returns a new IdentifierExpression with the specified column
|
||||
func (ae aliasExpression) Col(col interface{}) IdentifierExpression {
|
||||
return ae.alias.Col(col)
|
||||
}
|
||||
|
||||
// Returns a new IdentifierExpression with the column set to *
|
||||
// I("my_table").As("t").All() //"t".*
|
||||
func (ae aliasExpression) All() IdentifierExpression {
|
||||
return ae.alias.All()
|
||||
}
|
||||
89
vendor/github.com/doug-martin/goqu/v9/exp/bitwise.go
generated
vendored
Normal file
89
vendor/github.com/doug-martin/goqu/v9/exp/bitwise.go
generated
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
package exp
|
||||
|
||||
type bitwise struct {
|
||||
lhs Expression
|
||||
rhs interface{}
|
||||
op BitwiseOperation
|
||||
}
|
||||
|
||||
func NewBitwiseExpression(op BitwiseOperation, lhs Expression, rhs interface{}) BitwiseExpression {
|
||||
return bitwise{op: op, lhs: lhs, rhs: rhs}
|
||||
}
|
||||
|
||||
func (b bitwise) Clone() Expression {
|
||||
return NewBitwiseExpression(b.op, b.lhs.Clone(), b.rhs)
|
||||
}
|
||||
|
||||
func (b bitwise) RHS() interface{} {
|
||||
return b.rhs
|
||||
}
|
||||
|
||||
func (b bitwise) LHS() Expression {
|
||||
return b.lhs
|
||||
}
|
||||
|
||||
func (b bitwise) Op() BitwiseOperation {
|
||||
return b.op
|
||||
}
|
||||
|
||||
func (b bitwise) Expression() Expression { return b }
|
||||
func (b bitwise) As(val interface{}) AliasedExpression { return NewAliasExpression(b, val) }
|
||||
func (b bitwise) Eq(val interface{}) BooleanExpression { return eq(b, val) }
|
||||
func (b bitwise) Neq(val interface{}) BooleanExpression { return neq(b, val) }
|
||||
func (b bitwise) Gt(val interface{}) BooleanExpression { return gt(b, val) }
|
||||
func (b bitwise) Gte(val interface{}) BooleanExpression { return gte(b, val) }
|
||||
func (b bitwise) Lt(val interface{}) BooleanExpression { return lt(b, val) }
|
||||
func (b bitwise) Lte(val interface{}) BooleanExpression { return lte(b, val) }
|
||||
func (b bitwise) Asc() OrderedExpression { return asc(b) }
|
||||
func (b bitwise) Desc() OrderedExpression { return desc(b) }
|
||||
func (b bitwise) Like(i interface{}) BooleanExpression { return like(b, i) }
|
||||
func (b bitwise) NotLike(i interface{}) BooleanExpression { return notLike(b, i) }
|
||||
func (b bitwise) ILike(i interface{}) BooleanExpression { return iLike(b, i) }
|
||||
func (b bitwise) NotILike(i interface{}) BooleanExpression { return notILike(b, i) }
|
||||
func (b bitwise) RegexpLike(val interface{}) BooleanExpression { return regexpLike(b, val) }
|
||||
func (b bitwise) RegexpNotLike(val interface{}) BooleanExpression { return regexpNotLike(b, val) }
|
||||
func (b bitwise) RegexpILike(val interface{}) BooleanExpression { return regexpILike(b, val) }
|
||||
func (b bitwise) RegexpNotILike(val interface{}) BooleanExpression { return regexpNotILike(b, val) }
|
||||
func (b bitwise) In(i ...interface{}) BooleanExpression { return in(b, i...) }
|
||||
func (b bitwise) NotIn(i ...interface{}) BooleanExpression { return notIn(b, i...) }
|
||||
func (b bitwise) Is(i interface{}) BooleanExpression { return is(b, i) }
|
||||
func (b bitwise) IsNot(i interface{}) BooleanExpression { return isNot(b, i) }
|
||||
func (b bitwise) IsNull() BooleanExpression { return is(b, nil) }
|
||||
func (b bitwise) IsNotNull() BooleanExpression { return isNot(b, nil) }
|
||||
func (b bitwise) IsTrue() BooleanExpression { return is(b, true) }
|
||||
func (b bitwise) IsNotTrue() BooleanExpression { return isNot(b, true) }
|
||||
func (b bitwise) IsFalse() BooleanExpression { return is(b, false) }
|
||||
func (b bitwise) IsNotFalse() BooleanExpression { return isNot(b, false) }
|
||||
func (b bitwise) Distinct() SQLFunctionExpression { return NewSQLFunctionExpression("DISTINCT", b) }
|
||||
func (b bitwise) Between(val RangeVal) RangeExpression { return between(b, val) }
|
||||
func (b bitwise) NotBetween(val RangeVal) RangeExpression { return notBetween(b, val) }
|
||||
|
||||
// used internally to create a Bitwise Inversion BitwiseExpression
|
||||
func bitwiseInversion(rhs Expression) BitwiseExpression {
|
||||
return NewBitwiseExpression(BitwiseInversionOp, nil, rhs)
|
||||
}
|
||||
|
||||
// used internally to create a Bitwise OR BitwiseExpression
|
||||
func bitwiseOr(lhs Expression, rhs interface{}) BitwiseExpression {
|
||||
return NewBitwiseExpression(BitwiseOrOp, lhs, rhs)
|
||||
}
|
||||
|
||||
// used internally to create a Bitwise AND BitwiseExpression
|
||||
func bitwiseAnd(lhs Expression, rhs interface{}) BitwiseExpression {
|
||||
return NewBitwiseExpression(BitwiseAndOp, lhs, rhs)
|
||||
}
|
||||
|
||||
// used internally to create a Bitwise XOR BitwiseExpression
|
||||
func bitwiseXor(lhs Expression, rhs interface{}) BitwiseExpression {
|
||||
return NewBitwiseExpression(BitwiseXorOp, lhs, rhs)
|
||||
}
|
||||
|
||||
// used internally to create a Bitwise LEFT SHIFT BitwiseExpression
|
||||
func bitwiseLeftShift(lhs Expression, rhs interface{}) BitwiseExpression {
|
||||
return NewBitwiseExpression(BitwiseLeftShiftOp, lhs, rhs)
|
||||
}
|
||||
|
||||
// used internally to create a Bitwise RIGHT SHIFT BitwiseExpression
|
||||
func bitwiseRightShift(lhs Expression, rhs interface{}) BitwiseExpression {
|
||||
return NewBitwiseExpression(BitwiseRightShiftOp, lhs, rhs)
|
||||
}
|
||||
185
vendor/github.com/doug-martin/goqu/v9/exp/bool.go
generated
vendored
Normal file
185
vendor/github.com/doug-martin/goqu/v9/exp/bool.go
generated
vendored
Normal file
@@ -0,0 +1,185 @@
|
||||
package exp
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
type boolean struct {
|
||||
lhs Expression
|
||||
rhs interface{}
|
||||
op BooleanOperation
|
||||
}
|
||||
|
||||
func NewBooleanExpression(op BooleanOperation, lhs Expression, rhs interface{}) BooleanExpression {
|
||||
return boolean{op: op, lhs: lhs, rhs: rhs}
|
||||
}
|
||||
|
||||
func (b boolean) Clone() Expression {
|
||||
return NewBooleanExpression(b.op, b.lhs.Clone(), b.rhs)
|
||||
}
|
||||
|
||||
func (b boolean) Expression() Expression {
|
||||
return b
|
||||
}
|
||||
|
||||
func (b boolean) RHS() interface{} {
|
||||
return b.rhs
|
||||
}
|
||||
|
||||
func (b boolean) LHS() Expression {
|
||||
return b.lhs
|
||||
}
|
||||
|
||||
func (b boolean) Op() BooleanOperation {
|
||||
return b.op
|
||||
}
|
||||
|
||||
func (b boolean) As(val interface{}) AliasedExpression {
|
||||
return NewAliasExpression(b, val)
|
||||
}
|
||||
|
||||
// used internally to create an equality BooleanExpression
|
||||
func eq(lhs Expression, rhs interface{}) BooleanExpression {
|
||||
return checkBoolExpType(EqOp, lhs, rhs, false)
|
||||
}
|
||||
|
||||
// used internally to create an in-equality BooleanExpression
|
||||
func neq(lhs Expression, rhs interface{}) BooleanExpression {
|
||||
return checkBoolExpType(EqOp, lhs, rhs, true)
|
||||
}
|
||||
|
||||
// used internally to create an gt comparison BooleanExpression
|
||||
func gt(lhs Expression, rhs interface{}) BooleanExpression {
|
||||
return NewBooleanExpression(GtOp, lhs, rhs)
|
||||
}
|
||||
|
||||
// used internally to create an gte comparison BooleanExpression
|
||||
func gte(lhs Expression, rhs interface{}) BooleanExpression {
|
||||
return NewBooleanExpression(GteOp, lhs, rhs)
|
||||
}
|
||||
|
||||
// used internally to create an lt comparison BooleanExpression
|
||||
func lt(lhs Expression, rhs interface{}) BooleanExpression {
|
||||
return NewBooleanExpression(LtOp, lhs, rhs)
|
||||
}
|
||||
|
||||
// used internally to create an lte comparison BooleanExpression
|
||||
func lte(lhs Expression, rhs interface{}) BooleanExpression {
|
||||
return NewBooleanExpression(LteOp, lhs, rhs)
|
||||
}
|
||||
|
||||
// used internally to create an IN BooleanExpression
|
||||
func in(lhs Expression, vals ...interface{}) BooleanExpression {
|
||||
if len(vals) == 1 && reflect.Indirect(reflect.ValueOf(vals[0])).Kind() == reflect.Slice {
|
||||
return NewBooleanExpression(InOp, lhs, vals[0])
|
||||
}
|
||||
return NewBooleanExpression(InOp, lhs, vals)
|
||||
}
|
||||
|
||||
// used internally to create a NOT IN BooleanExpression
|
||||
func notIn(lhs Expression, vals ...interface{}) BooleanExpression {
|
||||
if len(vals) == 1 && reflect.Indirect(reflect.ValueOf(vals[0])).Kind() == reflect.Slice {
|
||||
return NewBooleanExpression(NotInOp, lhs, vals[0])
|
||||
}
|
||||
return NewBooleanExpression(NotInOp, lhs, vals)
|
||||
}
|
||||
|
||||
// used internally to create an IS BooleanExpression
|
||||
func is(lhs Expression, val interface{}) BooleanExpression {
|
||||
return checkBoolExpType(IsOp, lhs, val, false)
|
||||
}
|
||||
|
||||
// used internally to create an IS NOT BooleanExpression
|
||||
func isNot(lhs Expression, val interface{}) BooleanExpression {
|
||||
return checkBoolExpType(IsOp, lhs, val, true)
|
||||
}
|
||||
|
||||
// used internally to create a LIKE BooleanExpression
|
||||
func like(lhs Expression, val interface{}) BooleanExpression {
|
||||
return checkLikeExp(LikeOp, lhs, val, false)
|
||||
}
|
||||
|
||||
// used internally to create an ILIKE BooleanExpression
|
||||
func iLike(lhs Expression, val interface{}) BooleanExpression {
|
||||
return checkLikeExp(ILikeOp, lhs, val, false)
|
||||
}
|
||||
|
||||
// used internally to create a NOT LIKE BooleanExpression
|
||||
func notLike(lhs Expression, val interface{}) BooleanExpression {
|
||||
return checkLikeExp(LikeOp, lhs, val, true)
|
||||
}
|
||||
|
||||
// used internally to create a NOT ILIKE BooleanExpression
|
||||
func notILike(lhs Expression, val interface{}) BooleanExpression {
|
||||
return checkLikeExp(ILikeOp, lhs, val, true)
|
||||
}
|
||||
|
||||
// used internally to create a LIKE BooleanExpression
|
||||
func regexpLike(lhs Expression, val interface{}) BooleanExpression {
|
||||
return checkLikeExp(RegexpLikeOp, lhs, val, false)
|
||||
}
|
||||
|
||||
// used internally to create an ILIKE BooleanExpression
|
||||
func regexpILike(lhs Expression, val interface{}) BooleanExpression {
|
||||
return checkLikeExp(RegexpILikeOp, lhs, val, false)
|
||||
}
|
||||
|
||||
// used internally to create a NOT LIKE BooleanExpression
|
||||
func regexpNotLike(lhs Expression, val interface{}) BooleanExpression {
|
||||
return checkLikeExp(RegexpLikeOp, lhs, val, true)
|
||||
}
|
||||
|
||||
// used internally to create a NOT ILIKE BooleanExpression
|
||||
func regexpNotILike(lhs Expression, val interface{}) BooleanExpression {
|
||||
return checkLikeExp(RegexpILikeOp, lhs, val, true)
|
||||
}
|
||||
|
||||
// checks an like rhs to create the proper like expression for strings or regexps
|
||||
func checkLikeExp(op BooleanOperation, lhs Expression, val interface{}, invert bool) BooleanExpression {
|
||||
rhs := val
|
||||
|
||||
if t, ok := val.(*regexp.Regexp); ok {
|
||||
if op == LikeOp {
|
||||
op = RegexpLikeOp
|
||||
} else if op == ILikeOp {
|
||||
op = RegexpILikeOp
|
||||
}
|
||||
rhs = t.String()
|
||||
}
|
||||
if invert {
|
||||
op = operatorInversions[op]
|
||||
}
|
||||
return NewBooleanExpression(op, lhs, rhs)
|
||||
}
|
||||
|
||||
// checks a boolean operation normalizing the operation based on the RHS (e.g. "a" = true vs "a" IS TRUE
|
||||
func checkBoolExpType(op BooleanOperation, lhs Expression, rhs interface{}, invert bool) BooleanExpression {
|
||||
if rhs == nil {
|
||||
op = IsOp
|
||||
} else {
|
||||
switch reflect.Indirect(reflect.ValueOf(rhs)).Kind() {
|
||||
case reflect.Bool:
|
||||
op = IsOp
|
||||
case reflect.Slice:
|
||||
// if its a slice of bytes dont treat as an IN
|
||||
if _, ok := rhs.([]byte); !ok {
|
||||
op = InOp
|
||||
}
|
||||
case reflect.Struct:
|
||||
switch rhs.(type) {
|
||||
case SQLExpression:
|
||||
op = InOp
|
||||
case AppendableExpression:
|
||||
op = InOp
|
||||
case *regexp.Regexp:
|
||||
return checkLikeExp(LikeOp, lhs, rhs, invert)
|
||||
}
|
||||
default:
|
||||
}
|
||||
}
|
||||
if invert {
|
||||
op = operatorInversions[op]
|
||||
}
|
||||
return NewBooleanExpression(op, lhs, rhs)
|
||||
}
|
||||
78
vendor/github.com/doug-martin/goqu/v9/exp/case.go
generated
vendored
Normal file
78
vendor/github.com/doug-martin/goqu/v9/exp/case.go
generated
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
package exp
|
||||
|
||||
type (
|
||||
caseElse struct {
|
||||
result interface{}
|
||||
}
|
||||
caseWhen struct {
|
||||
caseElse
|
||||
condition interface{}
|
||||
}
|
||||
caseExpression struct {
|
||||
value interface{}
|
||||
whens []CaseWhen
|
||||
elseCondition CaseElse
|
||||
}
|
||||
)
|
||||
|
||||
func NewCaseElse(result interface{}) CaseElse {
|
||||
return caseElse{result: result}
|
||||
}
|
||||
|
||||
func (ce caseElse) Result() interface{} {
|
||||
return ce.result
|
||||
}
|
||||
|
||||
func NewCaseWhen(condition, result interface{}) CaseWhen {
|
||||
return caseWhen{caseElse: caseElse{result: result}, condition: condition}
|
||||
}
|
||||
|
||||
func (cw caseWhen) Condition() interface{} {
|
||||
return cw.condition
|
||||
}
|
||||
|
||||
func NewCaseExpression() CaseExpression {
|
||||
return caseExpression{value: nil, whens: []CaseWhen{}, elseCondition: nil}
|
||||
}
|
||||
|
||||
func (c caseExpression) Expression() Expression {
|
||||
return c
|
||||
}
|
||||
|
||||
func (c caseExpression) Clone() Expression {
|
||||
return caseExpression{value: c.value, whens: c.whens, elseCondition: c.elseCondition}
|
||||
}
|
||||
|
||||
func (c caseExpression) As(alias interface{}) AliasedExpression {
|
||||
return NewAliasExpression(c, alias)
|
||||
}
|
||||
|
||||
func (c caseExpression) GetValue() interface{} {
|
||||
return c.value
|
||||
}
|
||||
|
||||
func (c caseExpression) GetWhens() []CaseWhen {
|
||||
return c.whens
|
||||
}
|
||||
|
||||
func (c caseExpression) GetElse() CaseElse {
|
||||
return c.elseCondition
|
||||
}
|
||||
|
||||
func (c caseExpression) Value(value interface{}) CaseExpression {
|
||||
c.value = value
|
||||
return c
|
||||
}
|
||||
|
||||
func (c caseExpression) When(condition, result interface{}) CaseExpression {
|
||||
c.whens = append(c.whens, NewCaseWhen(condition, result))
|
||||
return c
|
||||
}
|
||||
|
||||
func (c caseExpression) Else(result interface{}) CaseExpression {
|
||||
c.elseCondition = NewCaseElse(result)
|
||||
return c
|
||||
}
|
||||
|
||||
func (c caseExpression) Asc() OrderedExpression { return asc(c) }
|
||||
func (c caseExpression) Desc() OrderedExpression { return desc(c) }
|
||||
56
vendor/github.com/doug-martin/goqu/v9/exp/cast.go
generated
vendored
Normal file
56
vendor/github.com/doug-martin/goqu/v9/exp/cast.go
generated
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
package exp
|
||||
|
||||
type cast struct {
|
||||
casted Expression
|
||||
t LiteralExpression
|
||||
}
|
||||
|
||||
// Creates a new Casted expression
|
||||
// Cast(I("a"), "NUMERIC") -> CAST("a" AS NUMERIC)
|
||||
func NewCastExpression(e Expression, t string) CastExpression {
|
||||
return cast{casted: e, t: NewLiteralExpression(t)}
|
||||
}
|
||||
|
||||
func (c cast) Casted() Expression {
|
||||
return c.casted
|
||||
}
|
||||
|
||||
func (c cast) Type() LiteralExpression {
|
||||
return c.t
|
||||
}
|
||||
|
||||
func (c cast) Clone() Expression {
|
||||
return cast{casted: c.casted.Clone(), t: c.t}
|
||||
}
|
||||
|
||||
func (c cast) Expression() Expression { return c }
|
||||
func (c cast) As(val interface{}) AliasedExpression { return NewAliasExpression(c, val) }
|
||||
func (c cast) Eq(val interface{}) BooleanExpression { return eq(c, val) }
|
||||
func (c cast) Neq(val interface{}) BooleanExpression { return neq(c, val) }
|
||||
func (c cast) Gt(val interface{}) BooleanExpression { return gt(c, val) }
|
||||
func (c cast) Gte(val interface{}) BooleanExpression { return gte(c, val) }
|
||||
func (c cast) Lt(val interface{}) BooleanExpression { return lt(c, val) }
|
||||
func (c cast) Lte(val interface{}) BooleanExpression { return lte(c, val) }
|
||||
func (c cast) Asc() OrderedExpression { return asc(c) }
|
||||
func (c cast) Desc() OrderedExpression { return desc(c) }
|
||||
func (c cast) Like(i interface{}) BooleanExpression { return like(c, i) }
|
||||
func (c cast) NotLike(i interface{}) BooleanExpression { return notLike(c, i) }
|
||||
func (c cast) ILike(i interface{}) BooleanExpression { return iLike(c, i) }
|
||||
func (c cast) NotILike(i interface{}) BooleanExpression { return notILike(c, i) }
|
||||
func (c cast) RegexpLike(val interface{}) BooleanExpression { return regexpLike(c, val) }
|
||||
func (c cast) RegexpNotLike(val interface{}) BooleanExpression { return regexpNotLike(c, val) }
|
||||
func (c cast) RegexpILike(val interface{}) BooleanExpression { return regexpILike(c, val) }
|
||||
func (c cast) RegexpNotILike(val interface{}) BooleanExpression { return regexpNotILike(c, val) }
|
||||
func (c cast) In(i ...interface{}) BooleanExpression { return in(c, i...) }
|
||||
func (c cast) NotIn(i ...interface{}) BooleanExpression { return notIn(c, i...) }
|
||||
func (c cast) Is(i interface{}) BooleanExpression { return is(c, i) }
|
||||
func (c cast) IsNot(i interface{}) BooleanExpression { return isNot(c, i) }
|
||||
func (c cast) IsNull() BooleanExpression { return is(c, nil) }
|
||||
func (c cast) IsNotNull() BooleanExpression { return isNot(c, nil) }
|
||||
func (c cast) IsTrue() BooleanExpression { return is(c, true) }
|
||||
func (c cast) IsNotTrue() BooleanExpression { return isNot(c, true) }
|
||||
func (c cast) IsFalse() BooleanExpression { return is(c, false) }
|
||||
func (c cast) IsNotFalse() BooleanExpression { return isNot(c, false) }
|
||||
func (c cast) Distinct() SQLFunctionExpression { return NewSQLFunctionExpression("DISTINCT", c) }
|
||||
func (c cast) Between(val RangeVal) RangeExpression { return between(c, val) }
|
||||
func (c cast) NotBetween(val RangeVal) RangeExpression { return notBetween(c, val) }
|
||||
84
vendor/github.com/doug-martin/goqu/v9/exp/col.go
generated
vendored
Normal file
84
vendor/github.com/doug-martin/goqu/v9/exp/col.go
generated
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
package exp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/doug-martin/goqu/v9/internal/util"
|
||||
)
|
||||
|
||||
type columnList struct {
|
||||
columns []Expression
|
||||
}
|
||||
|
||||
func NewColumnListExpression(vals ...interface{}) ColumnListExpression {
|
||||
cols := []Expression{}
|
||||
for _, val := range vals {
|
||||
switch t := val.(type) {
|
||||
case nil: // do nothing
|
||||
case string:
|
||||
cols = append(cols, ParseIdentifier(t))
|
||||
case ColumnListExpression:
|
||||
cols = append(cols, t.Columns()...)
|
||||
case Expression:
|
||||
cols = append(cols, t)
|
||||
default:
|
||||
_, valKind := util.GetTypeInfo(val, reflect.Indirect(reflect.ValueOf(val)))
|
||||
|
||||
if valKind == reflect.Struct {
|
||||
cm, err := util.GetColumnMap(val)
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
structCols := cm.Cols()
|
||||
for _, col := range structCols {
|
||||
i := ParseIdentifier(col)
|
||||
var sc Expression = i
|
||||
if i.IsQualified() {
|
||||
sc = i.As(NewIdentifierExpression("", "", col))
|
||||
}
|
||||
cols = append(cols, sc)
|
||||
}
|
||||
} else {
|
||||
panic(fmt.Sprintf("Cannot created expression from %+v", val))
|
||||
}
|
||||
}
|
||||
}
|
||||
return columnList{columns: cols}
|
||||
}
|
||||
|
||||
func NewOrderedColumnList(vals ...OrderedExpression) ColumnListExpression {
|
||||
exps := make([]interface{}, 0, len(vals))
|
||||
for _, col := range vals {
|
||||
exps = append(exps, col.Expression())
|
||||
}
|
||||
return NewColumnListExpression(exps...)
|
||||
}
|
||||
|
||||
func (cl columnList) Clone() Expression {
|
||||
newExps := make([]Expression, 0, len(cl.columns))
|
||||
for _, exp := range cl.columns {
|
||||
newExps = append(newExps, exp.Clone())
|
||||
}
|
||||
return columnList{columns: newExps}
|
||||
}
|
||||
|
||||
func (cl columnList) Expression() Expression {
|
||||
return cl
|
||||
}
|
||||
|
||||
func (cl columnList) IsEmpty() bool {
|
||||
return len(cl.columns) == 0
|
||||
}
|
||||
|
||||
func (cl columnList) Columns() []Expression {
|
||||
return cl.columns
|
||||
}
|
||||
|
||||
func (cl columnList) Append(cols ...Expression) ColumnListExpression {
|
||||
ret := columnList{}
|
||||
exps := append(ret.columns, cl.columns...)
|
||||
exps = append(exps, cols...)
|
||||
ret.columns = exps
|
||||
return ret
|
||||
}
|
||||
19
vendor/github.com/doug-martin/goqu/v9/exp/compound.go
generated
vendored
Normal file
19
vendor/github.com/doug-martin/goqu/v9/exp/compound.go
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
package exp
|
||||
|
||||
type compound struct {
|
||||
t CompoundType
|
||||
rhs AppendableExpression
|
||||
}
|
||||
|
||||
func NewCompoundExpression(ct CompoundType, rhs AppendableExpression) CompoundExpression {
|
||||
return compound{t: ct, rhs: rhs}
|
||||
}
|
||||
|
||||
func (c compound) Expression() Expression { return c }
|
||||
|
||||
func (c compound) Clone() Expression {
|
||||
return compound{t: c.t, rhs: c.rhs.Clone().(AppendableExpression)}
|
||||
}
|
||||
|
||||
func (c compound) Type() CompoundType { return c.t }
|
||||
func (c compound) RHS() AppendableExpression { return c.rhs }
|
||||
86
vendor/github.com/doug-martin/goqu/v9/exp/conflict.go
generated
vendored
Normal file
86
vendor/github.com/doug-martin/goqu/v9/exp/conflict.go
generated
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
package exp
|
||||
|
||||
type (
|
||||
doNothingConflict struct{}
|
||||
// ConflictUpdate is the struct that represents the UPDATE fragment of an
|
||||
// INSERT ... ON CONFLICT/ON DUPLICATE KEY DO UPDATE statement
|
||||
conflictUpdate struct {
|
||||
target string
|
||||
update interface{}
|
||||
whereClause ExpressionList
|
||||
}
|
||||
)
|
||||
|
||||
// Creates a conflict struct to be passed to InsertConflict to ignore constraint errors
|
||||
// InsertConflict(DoNothing(),...) -> INSERT INTO ... ON CONFLICT DO NOTHING
|
||||
func NewDoNothingConflictExpression() ConflictExpression {
|
||||
return &doNothingConflict{}
|
||||
}
|
||||
|
||||
func (c doNothingConflict) Expression() Expression {
|
||||
return c
|
||||
}
|
||||
|
||||
func (c doNothingConflict) Clone() Expression {
|
||||
return c
|
||||
}
|
||||
|
||||
func (c doNothingConflict) Action() ConflictAction {
|
||||
return DoNothingConflictAction
|
||||
}
|
||||
|
||||
// Creates a ConflictUpdate struct to be passed to InsertConflict
|
||||
// Represents a ON CONFLICT DO UPDATE portion of an INSERT statement (ON DUPLICATE KEY UPDATE for mysql)
|
||||
//
|
||||
// InsertConflict(DoUpdate("target_column", update),...) ->
|
||||
// INSERT INTO ... ON CONFLICT DO UPDATE SET a=b
|
||||
// InsertConflict(DoUpdate("target_column", update).Where(Ex{"a": 1},...) ->
|
||||
// INSERT INTO ... ON CONFLICT DO UPDATE SET a=b WHERE a=1
|
||||
func NewDoUpdateConflictExpression(target string, update interface{}) ConflictUpdateExpression {
|
||||
return &conflictUpdate{target: target, update: update}
|
||||
}
|
||||
|
||||
func (c conflictUpdate) Expression() Expression {
|
||||
return c
|
||||
}
|
||||
|
||||
func (c conflictUpdate) Clone() Expression {
|
||||
return &conflictUpdate{
|
||||
target: c.target,
|
||||
update: c.update,
|
||||
whereClause: c.whereClause.Clone().(ExpressionList),
|
||||
}
|
||||
}
|
||||
|
||||
func (c conflictUpdate) Action() ConflictAction {
|
||||
return DoUpdateConflictAction
|
||||
}
|
||||
|
||||
// Returns the target conflict column. Only necessary for Postgres.
|
||||
// Will return an error for mysql/sqlite. Will also return an error if missing from a postgres ConflictUpdate.
|
||||
func (c conflictUpdate) TargetColumn() string {
|
||||
return c.target
|
||||
}
|
||||
|
||||
// Returns the Updates which represent the ON CONFLICT DO UPDATE portion of an insert statement. If nil,
|
||||
// there are no updates.
|
||||
func (c conflictUpdate) Update() interface{} {
|
||||
return c.update
|
||||
}
|
||||
|
||||
// Append to the existing Where clause for an ON CONFLICT DO UPDATE ... WHERE ...
|
||||
// InsertConflict(DoNothing(),...) -> INSERT INTO ... ON CONFLICT DO NOTHING
|
||||
func (c *conflictUpdate) Where(expressions ...Expression) ConflictUpdateExpression {
|
||||
if c.whereClause == nil {
|
||||
c.whereClause = NewExpressionList(AndType, expressions...)
|
||||
} else {
|
||||
c.whereClause = c.whereClause.Append(expressions...)
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// Append to the existing Where clause for an ON CONFLICT DO UPDATE ... WHERE ...
|
||||
// InsertConflict(DoNothing(),...) -> INSERT INTO ... ON CONFLICT DO NOTHING
|
||||
func (c *conflictUpdate) WhereClause() ExpressionList {
|
||||
return c.whereClause
|
||||
}
|
||||
23
vendor/github.com/doug-martin/goqu/v9/exp/cte.go
generated
vendored
Normal file
23
vendor/github.com/doug-martin/goqu/v9/exp/cte.go
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
package exp
|
||||
|
||||
type commonExpr struct {
|
||||
recursive bool
|
||||
name LiteralExpression
|
||||
subQuery Expression
|
||||
}
|
||||
|
||||
// Creates a new WITH common table expression for a SQLExpression, typically Datasets'. This function is used
|
||||
// internally by Dataset when a CTE is added to another Dataset
|
||||
func NewCommonTableExpression(recursive bool, name string, subQuery Expression) CommonTableExpression {
|
||||
return commonExpr{recursive: recursive, name: NewLiteralExpression(name), subQuery: subQuery}
|
||||
}
|
||||
|
||||
func (ce commonExpr) Expression() Expression { return ce }
|
||||
|
||||
func (ce commonExpr) Clone() Expression {
|
||||
return commonExpr{recursive: ce.recursive, name: ce.name, subQuery: ce.subQuery.Clone().(SQLExpression)}
|
||||
}
|
||||
|
||||
func (ce commonExpr) IsRecursive() bool { return ce.recursive }
|
||||
func (ce commonExpr) Name() LiteralExpression { return ce.name }
|
||||
func (ce commonExpr) SubQuery() Expression { return ce.subQuery }
|
||||
177
vendor/github.com/doug-martin/goqu/v9/exp/delete_clauses.go
generated
vendored
Normal file
177
vendor/github.com/doug-martin/goqu/v9/exp/delete_clauses.go
generated
vendored
Normal file
@@ -0,0 +1,177 @@
|
||||
package exp
|
||||
|
||||
type (
|
||||
DeleteClauses interface {
|
||||
HasFrom() bool
|
||||
clone() *deleteClauses
|
||||
|
||||
CommonTables() []CommonTableExpression
|
||||
CommonTablesAppend(cte CommonTableExpression) DeleteClauses
|
||||
|
||||
From() IdentifierExpression
|
||||
SetFrom(table IdentifierExpression) DeleteClauses
|
||||
|
||||
Where() ExpressionList
|
||||
ClearWhere() DeleteClauses
|
||||
WhereAppend(expressions ...Expression) DeleteClauses
|
||||
|
||||
Order() ColumnListExpression
|
||||
HasOrder() bool
|
||||
ClearOrder() DeleteClauses
|
||||
SetOrder(oes ...OrderedExpression) DeleteClauses
|
||||
OrderAppend(...OrderedExpression) DeleteClauses
|
||||
OrderPrepend(...OrderedExpression) DeleteClauses
|
||||
|
||||
Limit() interface{}
|
||||
HasLimit() bool
|
||||
ClearLimit() DeleteClauses
|
||||
SetLimit(limit interface{}) DeleteClauses
|
||||
|
||||
Returning() ColumnListExpression
|
||||
HasReturning() bool
|
||||
SetReturning(cl ColumnListExpression) DeleteClauses
|
||||
}
|
||||
deleteClauses struct {
|
||||
commonTables []CommonTableExpression
|
||||
from IdentifierExpression
|
||||
where ExpressionList
|
||||
order ColumnListExpression
|
||||
limit interface{}
|
||||
returning ColumnListExpression
|
||||
}
|
||||
)
|
||||
|
||||
func NewDeleteClauses() DeleteClauses {
|
||||
return &deleteClauses{}
|
||||
}
|
||||
|
||||
func (dc *deleteClauses) HasFrom() bool {
|
||||
return dc.from != nil
|
||||
}
|
||||
|
||||
func (dc *deleteClauses) clone() *deleteClauses {
|
||||
return &deleteClauses{
|
||||
commonTables: dc.commonTables,
|
||||
from: dc.from,
|
||||
|
||||
where: dc.where,
|
||||
order: dc.order,
|
||||
limit: dc.limit,
|
||||
returning: dc.returning,
|
||||
}
|
||||
}
|
||||
|
||||
func (dc *deleteClauses) CommonTables() []CommonTableExpression {
|
||||
return dc.commonTables
|
||||
}
|
||||
|
||||
func (dc *deleteClauses) CommonTablesAppend(cte CommonTableExpression) DeleteClauses {
|
||||
ret := dc.clone()
|
||||
ret.commonTables = append(ret.commonTables, cte)
|
||||
return ret
|
||||
}
|
||||
|
||||
func (dc *deleteClauses) From() IdentifierExpression {
|
||||
return dc.from
|
||||
}
|
||||
|
||||
func (dc *deleteClauses) SetFrom(table IdentifierExpression) DeleteClauses {
|
||||
ret := dc.clone()
|
||||
ret.from = table
|
||||
return ret
|
||||
}
|
||||
|
||||
func (dc *deleteClauses) Where() ExpressionList {
|
||||
return dc.where
|
||||
}
|
||||
|
||||
func (dc *deleteClauses) ClearWhere() DeleteClauses {
|
||||
ret := dc.clone()
|
||||
ret.where = nil
|
||||
return ret
|
||||
}
|
||||
|
||||
func (dc *deleteClauses) WhereAppend(expressions ...Expression) DeleteClauses {
|
||||
if len(expressions) == 0 {
|
||||
return dc
|
||||
}
|
||||
ret := dc.clone()
|
||||
if ret.where == nil {
|
||||
ret.where = NewExpressionList(AndType, expressions...)
|
||||
} else {
|
||||
ret.where = ret.where.Append(expressions...)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (dc *deleteClauses) Order() ColumnListExpression {
|
||||
return dc.order
|
||||
}
|
||||
|
||||
func (dc *deleteClauses) HasOrder() bool {
|
||||
return dc.order != nil
|
||||
}
|
||||
|
||||
func (dc *deleteClauses) ClearOrder() DeleteClauses {
|
||||
ret := dc.clone()
|
||||
ret.order = nil
|
||||
return ret
|
||||
}
|
||||
|
||||
func (dc *deleteClauses) SetOrder(oes ...OrderedExpression) DeleteClauses {
|
||||
ret := dc.clone()
|
||||
ret.order = NewOrderedColumnList(oes...)
|
||||
return ret
|
||||
}
|
||||
|
||||
func (dc *deleteClauses) OrderAppend(oes ...OrderedExpression) DeleteClauses {
|
||||
if dc.order == nil {
|
||||
return dc.SetOrder(oes...)
|
||||
}
|
||||
ret := dc.clone()
|
||||
ret.order = ret.order.Append(NewOrderedColumnList(oes...).Columns()...)
|
||||
return ret
|
||||
}
|
||||
|
||||
func (dc *deleteClauses) OrderPrepend(oes ...OrderedExpression) DeleteClauses {
|
||||
if dc.order == nil {
|
||||
return dc.SetOrder(oes...)
|
||||
}
|
||||
ret := dc.clone()
|
||||
ret.order = NewOrderedColumnList(oes...).Append(ret.order.Columns()...)
|
||||
return ret
|
||||
}
|
||||
|
||||
func (dc *deleteClauses) Limit() interface{} {
|
||||
return dc.limit
|
||||
}
|
||||
|
||||
func (dc *deleteClauses) HasLimit() bool {
|
||||
return dc.limit != nil
|
||||
}
|
||||
|
||||
func (dc *deleteClauses) ClearLimit() DeleteClauses {
|
||||
ret := dc.clone()
|
||||
ret.limit = nil
|
||||
return ret
|
||||
}
|
||||
|
||||
func (dc *deleteClauses) SetLimit(limit interface{}) DeleteClauses {
|
||||
ret := dc.clone()
|
||||
ret.limit = limit
|
||||
return ret
|
||||
}
|
||||
|
||||
func (dc *deleteClauses) Returning() ColumnListExpression {
|
||||
return dc.returning
|
||||
}
|
||||
|
||||
func (dc *deleteClauses) HasReturning() bool {
|
||||
return dc.returning != nil && !dc.returning.IsEmpty()
|
||||
}
|
||||
|
||||
func (dc *deleteClauses) SetReturning(cl ColumnListExpression) DeleteClauses {
|
||||
ret := dc.clone()
|
||||
ret.returning = cl
|
||||
return ret
|
||||
}
|
||||
734
vendor/github.com/doug-martin/goqu/v9/exp/exp.go
generated
vendored
Normal file
734
vendor/github.com/doug-martin/goqu/v9/exp/exp.go
generated
vendored
Normal file
@@ -0,0 +1,734 @@
|
||||
package exp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/doug-martin/goqu/v9/internal/sb"
|
||||
)
|
||||
|
||||
// Behaviors
|
||||
type (
|
||||
|
||||
// Interface that an expression should implement if it can be aliased.
|
||||
Aliaseable interface {
|
||||
// Returns an AliasedExpression
|
||||
// I("col").As("other_col") //"col" AS "other_col"
|
||||
// I("col").As(I("other_col")) //"col" AS "other_col"
|
||||
As(interface{}) AliasedExpression
|
||||
}
|
||||
|
||||
// Interface that an expression should implement if it can be casted to another SQL type .
|
||||
Castable interface {
|
||||
// Casts an expression to the specified type
|
||||
// I("a").Cast("numeric")//CAST("a" AS numeric)
|
||||
Cast(val string) CastExpression
|
||||
}
|
||||
|
||||
Inable interface {
|
||||
// Creates a Boolean expression for IN clauses
|
||||
// I("col").In([]string{"a", "b", "c"}) //("col" IN ('a', 'b', 'c'))
|
||||
In(...interface{}) BooleanExpression
|
||||
// Creates a Boolean expression for NOT IN clauses
|
||||
// I("col").NotIn([]string{"a", "b", "c"}) //("col" NOT IN ('a', 'b', 'c'))
|
||||
NotIn(...interface{}) BooleanExpression
|
||||
}
|
||||
|
||||
Isable interface {
|
||||
// Creates an Boolean expression IS clauses
|
||||
// ds.Where(I("a").Is(nil)) //("a" IS NULL)
|
||||
// ds.Where(I("a").Is(true)) //("a" IS TRUE)
|
||||
// ds.Where(I("a").Is(false)) //("a" IS FALSE)
|
||||
Is(interface{}) BooleanExpression
|
||||
// Creates an Boolean expression IS NOT clauses
|
||||
// ds.Where(I("a").IsNot(nil)) //("a" IS NOT NULL)
|
||||
// ds.Where(I("a").IsNot(true)) //("a" IS NOT TRUE)
|
||||
// ds.Where(I("a").IsNot(false)) //("a" IS NOT FALSE)
|
||||
IsNot(interface{}) BooleanExpression
|
||||
// Shortcut for Is(nil)
|
||||
IsNull() BooleanExpression
|
||||
// Shortcut for IsNot(nil)
|
||||
IsNotNull() BooleanExpression
|
||||
// Shortcut for Is(true)
|
||||
IsTrue() BooleanExpression
|
||||
// Shortcut for IsNot(true)
|
||||
IsNotTrue() BooleanExpression
|
||||
// Shortcut for Is(false)
|
||||
IsFalse() BooleanExpression
|
||||
// Shortcut for IsNot(false)
|
||||
IsNotFalse() BooleanExpression
|
||||
}
|
||||
|
||||
Likeable interface {
|
||||
// Creates an Boolean expression for LIKE clauses
|
||||
// ds.Where(I("a").Like("a%")) //("a" LIKE 'a%')
|
||||
Like(interface{}) BooleanExpression
|
||||
// Creates an Boolean expression for NOT LIKE clauses
|
||||
// ds.Where(I("a").NotLike("a%")) //("a" NOT LIKE 'a%')
|
||||
NotLike(interface{}) BooleanExpression
|
||||
// Creates an Boolean expression for case insensitive LIKE clauses
|
||||
// ds.Where(I("a").ILike("a%")) //("a" ILIKE 'a%')
|
||||
ILike(interface{}) BooleanExpression
|
||||
// Creates an Boolean expression for case insensitive NOT LIKE clauses
|
||||
// ds.Where(I("a").NotILike("a%")) //("a" NOT ILIKE 'a%')
|
||||
NotILike(interface{}) BooleanExpression
|
||||
|
||||
// Creates an Boolean expression for REGEXP LIKE clauses
|
||||
// ds.Where(I("a").RegexpLike("a%")) //("a" ~ 'a%')
|
||||
RegexpLike(interface{}) BooleanExpression
|
||||
// Creates an Boolean expression for REGEXP NOT LIKE clauses
|
||||
// ds.Where(I("a").RegexpNotLike("a%")) //("a" !~ 'a%')
|
||||
RegexpNotLike(interface{}) BooleanExpression
|
||||
// Creates an Boolean expression for case insensitive REGEXP ILIKE clauses
|
||||
// ds.Where(I("a").RegexpILike("a%")) //("a" ~* 'a%')
|
||||
RegexpILike(interface{}) BooleanExpression
|
||||
// Creates an Boolean expression for case insensitive REGEXP NOT ILIKE clauses
|
||||
// ds.Where(I("a").RegexpNotILike("a%")) //("a" !~* 'a%')
|
||||
RegexpNotILike(interface{}) BooleanExpression
|
||||
}
|
||||
|
||||
// Interface that an expression should implement if it can be compared with other values.
|
||||
Comparable interface {
|
||||
// Creates a Boolean expression comparing equality
|
||||
// I("col").Eq(1) //("col" = 1)
|
||||
Eq(interface{}) BooleanExpression
|
||||
// Creates a Boolean expression comparing in-equality
|
||||
// I("col").Neq(1) //("col" != 1)
|
||||
Neq(interface{}) BooleanExpression
|
||||
// Creates a Boolean expression for greater than comparisons
|
||||
// I("col").Gt(1) //("col" > 1)
|
||||
Gt(interface{}) BooleanExpression
|
||||
// Creates a Boolean expression for greater than or equal to than comparisons
|
||||
// I("col").Gte(1) //("col" >= 1)
|
||||
Gte(interface{}) BooleanExpression
|
||||
// Creates a Boolean expression for less than comparisons
|
||||
// I("col").Lt(1) //("col" < 1)
|
||||
Lt(interface{}) BooleanExpression
|
||||
// Creates a Boolean expression for less than or equal to comparisons
|
||||
// I("col").Lte(1) //("col" <= 1)
|
||||
Lte(interface{}) BooleanExpression
|
||||
}
|
||||
|
||||
// Interface that an expression should implement if it can be used in a DISTINCT epxression.
|
||||
Distinctable interface {
|
||||
// Creates a DISTINCT clause
|
||||
// I("a").Distinct() //DISTINCT("a")
|
||||
Distinct() SQLFunctionExpression
|
||||
}
|
||||
|
||||
// Interface that an expression should implement if it can be ORDERED.
|
||||
Orderable interface {
|
||||
// Creates an Ordered Expression for sql ASC order
|
||||
// ds.Order(I("a").Asc()) //ORDER BY "a" ASC
|
||||
Asc() OrderedExpression
|
||||
// Creates an Ordered Expression for sql DESC order
|
||||
// ds.Order(I("a").Desc()) //ORDER BY "a" DESC
|
||||
Desc() OrderedExpression
|
||||
}
|
||||
|
||||
Rangeable interface {
|
||||
// Creates a Range expression for between comparisons
|
||||
// I("col").Between(RangeVal{Start:1, End:10}) //("col" BETWEEN 1 AND 10)
|
||||
Between(RangeVal) RangeExpression
|
||||
// Creates a Range expression for between comparisons
|
||||
// I("col").NotBetween(RangeVal{Start:1, End:10}) //("col" NOT BETWEEN 1 AND 10)
|
||||
NotBetween(RangeVal) RangeExpression
|
||||
}
|
||||
|
||||
Updateable interface {
|
||||
// Used internally by update sql
|
||||
Set(interface{}) UpdateExpression
|
||||
}
|
||||
|
||||
Bitwiseable interface {
|
||||
// Creates a Bit Operation Expresion for sql ~
|
||||
// I("col").BitiInversion() // (~ "col")
|
||||
BitwiseInversion() BitwiseExpression
|
||||
// Creates a Bit Operation Expresion for sql |
|
||||
// I("col").BitOr(1) // ("col" | 1)
|
||||
BitwiseOr(interface{}) BitwiseExpression
|
||||
// Creates a Bit Operation Expresion for sql &
|
||||
// I("col").BitAnd(1) // ("col" & 1)
|
||||
BitwiseAnd(interface{}) BitwiseExpression
|
||||
// Creates a Bit Operation Expresion for sql ^
|
||||
// I("col").BitXor(1) // ("col" ^ 1)
|
||||
BitwiseXor(interface{}) BitwiseExpression
|
||||
// Creates a Bit Operation Expresion for sql <<
|
||||
// I("col").BitLeftShift(1) // ("col" << 1)
|
||||
BitwiseLeftShift(interface{}) BitwiseExpression
|
||||
// Creates a Bit Operation Expresion for sql >>
|
||||
// I("col").BitRighttShift(1) // ("col" >> 1)
|
||||
BitwiseRightShift(interface{}) BitwiseExpression
|
||||
}
|
||||
)
|
||||
|
||||
type (
|
||||
Vals []interface{}
|
||||
// Parent of all expression types
|
||||
Expression interface {
|
||||
Clone() Expression
|
||||
Expression() Expression
|
||||
}
|
||||
// An Expression that generates its own sql (e.g Dataset)
|
||||
SQLExpression interface {
|
||||
Expression
|
||||
ToSQL() (string, []interface{}, error)
|
||||
IsPrepared() bool
|
||||
}
|
||||
|
||||
AppendableExpression interface {
|
||||
Expression
|
||||
AppendSQL(b sb.SQLBuilder)
|
||||
// Returns the alias value as an identiier expression
|
||||
GetAs() IdentifierExpression
|
||||
|
||||
// Returns true if this expression returns columns.
|
||||
// Used to determine if a Select, Update, Insert, or Delete query returns columns
|
||||
ReturnsColumns() bool
|
||||
}
|
||||
// Expression for Aliased expressions
|
||||
// I("a").As("b") -> "a" AS "b"
|
||||
// SUM("a").As(I("a_sum")) -> SUM("a") AS "a_sum"
|
||||
AliasedExpression interface {
|
||||
Expression
|
||||
// Returns the Epxression being aliased
|
||||
Aliased() Expression
|
||||
// Returns the alias value as an identiier expression
|
||||
GetAs() IdentifierExpression
|
||||
|
||||
// Returns a new IdentifierExpression with the specified schema
|
||||
Schema(string) IdentifierExpression
|
||||
// Returns a new IdentifierExpression with the specified table
|
||||
Table(string) IdentifierExpression
|
||||
// Returns a new IdentifierExpression with the specified column
|
||||
Col(interface{}) IdentifierExpression
|
||||
// Returns a new IdentifierExpression with the column set to *
|
||||
// I("my_table").All() //"my_table".*
|
||||
All() IdentifierExpression
|
||||
}
|
||||
|
||||
BooleanOperation int
|
||||
BooleanExpression interface {
|
||||
Expression
|
||||
Aliaseable
|
||||
// Returns the operator for the expression
|
||||
Op() BooleanOperation
|
||||
// The left hand side of the expression (e.g. I("a")
|
||||
LHS() Expression
|
||||
// The right hand side of the expression could be a primitive value, dataset, or expression
|
||||
RHS() interface{}
|
||||
}
|
||||
|
||||
BitwiseOperation int
|
||||
BitwiseExpression interface {
|
||||
Expression
|
||||
Aliaseable
|
||||
Comparable
|
||||
Isable
|
||||
Inable
|
||||
Likeable
|
||||
Rangeable
|
||||
Orderable
|
||||
Distinctable
|
||||
// Returns the operator for the expression
|
||||
Op() BitwiseOperation
|
||||
// The left hand side of the expression (e.g. I("a")
|
||||
LHS() Expression
|
||||
// The right hand side of the expression could be a primitive value, dataset, or expression
|
||||
RHS() interface{}
|
||||
}
|
||||
|
||||
// An Expression that represents another Expression casted to a SQL type
|
||||
CastExpression interface {
|
||||
Expression
|
||||
Aliaseable
|
||||
Comparable
|
||||
Inable
|
||||
Isable
|
||||
Likeable
|
||||
Orderable
|
||||
Distinctable
|
||||
Rangeable
|
||||
// The exression being casted
|
||||
Casted() Expression
|
||||
// The the SQL type to cast the expression to
|
||||
Type() LiteralExpression
|
||||
}
|
||||
// A list of columns. Typically used internally by Select, Order, From
|
||||
ColumnListExpression interface {
|
||||
Expression
|
||||
// Returns the list of columns
|
||||
Columns() []Expression
|
||||
// Returns true if the column list is empty
|
||||
IsEmpty() bool
|
||||
// Returns a new ColumnListExpression with the columns appended.
|
||||
Append(...Expression) ColumnListExpression
|
||||
}
|
||||
CompoundType int
|
||||
CompoundExpression interface {
|
||||
Expression
|
||||
Type() CompoundType
|
||||
RHS() AppendableExpression
|
||||
}
|
||||
// An Expression that the ON CONFLICT/ON DUPLICATE KEY portion of an INSERT statement
|
||||
ConflictAction int
|
||||
ConflictExpression interface {
|
||||
Expression
|
||||
Action() ConflictAction
|
||||
}
|
||||
ConflictUpdateExpression interface {
|
||||
ConflictExpression
|
||||
TargetColumn() string
|
||||
Where(expressions ...Expression) ConflictUpdateExpression
|
||||
WhereClause() ExpressionList
|
||||
Update() interface{}
|
||||
}
|
||||
CommonTableExpression interface {
|
||||
Expression
|
||||
IsRecursive() bool
|
||||
// Returns the alias name for the extracted expression
|
||||
Name() LiteralExpression
|
||||
// Returns the Expression being extracted
|
||||
SubQuery() Expression
|
||||
}
|
||||
ExpressionListType int
|
||||
// A list of expressions that should be joined together
|
||||
// And(I("a").Eq(10), I("b").Eq(11)) //(("a" = 10) AND ("b" = 11))
|
||||
// Or(I("a").Eq(10), I("b").Eq(11)) //(("a" = 10) OR ("b" = 11))
|
||||
ExpressionList interface {
|
||||
Expression
|
||||
// Returns type (e.g. OR, AND)
|
||||
Type() ExpressionListType
|
||||
// Slice of expressions that should be joined together
|
||||
Expressions() []Expression
|
||||
// Returns a new expression list with the given expressions appended to the current Expressions list
|
||||
Append(...Expression) ExpressionList
|
||||
|
||||
IsEmpty() bool
|
||||
}
|
||||
// An Identifier that can contain schema, table and column identifiers
|
||||
IdentifierExpression interface {
|
||||
Expression
|
||||
Aliaseable
|
||||
Comparable
|
||||
Inable
|
||||
Isable
|
||||
Likeable
|
||||
Rangeable
|
||||
Orderable
|
||||
Updateable
|
||||
Distinctable
|
||||
Castable
|
||||
Bitwiseable
|
||||
// returns true if this identifier has more more than on part (Schema, Table or Col)
|
||||
// "schema" -> true //cant qualify anymore
|
||||
// "schema.table" -> true
|
||||
// "table" -> false
|
||||
// "schema"."table"."col" -> true
|
||||
// "table"."col" -> true
|
||||
// "col" -> false
|
||||
IsQualified() bool
|
||||
// Returns a new IdentifierExpression with the specified schema
|
||||
Schema(string) IdentifierExpression
|
||||
// Returns the current schema
|
||||
GetSchema() string
|
||||
// Returns a new IdentifierExpression with the specified table
|
||||
Table(string) IdentifierExpression
|
||||
// Returns the current table
|
||||
GetTable() string
|
||||
// Returns a new IdentifierExpression with the specified column
|
||||
Col(interface{}) IdentifierExpression
|
||||
// Returns the current column
|
||||
GetCol() interface{}
|
||||
// Returns a new IdentifierExpression with the column set to *
|
||||
// I("my_table").All() //"my_table".*
|
||||
All() IdentifierExpression
|
||||
|
||||
// Returns true if schema table and identifier are all zero values.
|
||||
IsEmpty() bool
|
||||
}
|
||||
InsertExpression interface {
|
||||
Expression
|
||||
IsEmpty() bool
|
||||
IsInsertFrom() bool
|
||||
From() AppendableExpression
|
||||
Cols() ColumnListExpression
|
||||
SetCols(cols ColumnListExpression) InsertExpression
|
||||
Vals() [][]interface{}
|
||||
SetVals([][]interface{}) InsertExpression
|
||||
}
|
||||
|
||||
JoinType int
|
||||
JoinExpression interface {
|
||||
Expression
|
||||
JoinType() JoinType
|
||||
IsConditioned() bool
|
||||
Table() Expression
|
||||
}
|
||||
// Parent type for join expressions
|
||||
ConditionedJoinExpression interface {
|
||||
JoinExpression
|
||||
Condition() JoinCondition
|
||||
IsConditionEmpty() bool
|
||||
}
|
||||
LateralExpression interface {
|
||||
Expression
|
||||
Aliaseable
|
||||
Table() AppendableExpression
|
||||
}
|
||||
|
||||
// Expression for representing "literal" sql.
|
||||
// L("col = 1") -> col = 1)
|
||||
// L("? = ?", I("col"), 1) -> "col" = 1
|
||||
LiteralExpression interface {
|
||||
Expression
|
||||
Aliaseable
|
||||
Comparable
|
||||
Isable
|
||||
Inable
|
||||
Likeable
|
||||
Rangeable
|
||||
Orderable
|
||||
Bitwiseable
|
||||
// Returns the literal sql
|
||||
Literal() string
|
||||
// Arguments to be replaced within the sql
|
||||
Args() []interface{}
|
||||
}
|
||||
|
||||
NullSortType int
|
||||
SortDirection int
|
||||
// An expression for specifying sort order and options
|
||||
OrderedExpression interface {
|
||||
Expression
|
||||
// The expression being sorted
|
||||
SortExpression() Expression
|
||||
// Sort direction (e.g. ASC, DESC)
|
||||
IsAsc() bool
|
||||
// If the adapter supports it null sort type (e.g. NULLS FIRST, NULLS LAST)
|
||||
NullSortType() NullSortType
|
||||
// Returns a new OrderedExpression with NullSortType set to NULLS_FIRST
|
||||
NullsFirst() OrderedExpression
|
||||
// Returns a new OrderedExpression with NullSortType set to NULLS_LAST
|
||||
NullsLast() OrderedExpression
|
||||
}
|
||||
|
||||
RangeOperation int
|
||||
RangeExpression interface {
|
||||
Expression
|
||||
// Returns the operator for the expression
|
||||
Op() RangeOperation
|
||||
// The left hand side of the expression (e.g. I("a")
|
||||
LHS() Expression
|
||||
// The right hand side of the expression could be a primitive value, dataset, or expression
|
||||
RHS() RangeVal
|
||||
}
|
||||
RangeVal interface {
|
||||
Start() interface{}
|
||||
End() interface{}
|
||||
}
|
||||
|
||||
Windowable interface {
|
||||
Over(WindowExpression) SQLWindowFunctionExpression
|
||||
OverName(IdentifierExpression) SQLWindowFunctionExpression
|
||||
}
|
||||
|
||||
// Expression for representing a SQLFunction(e.g. COUNT, SUM, MIN, MAX...)
|
||||
SQLFunctionExpression interface {
|
||||
Expression
|
||||
Aliaseable
|
||||
Rangeable
|
||||
Comparable
|
||||
Orderable
|
||||
Isable
|
||||
Inable
|
||||
Likeable
|
||||
Windowable
|
||||
// The function name
|
||||
Name() string
|
||||
// Arguments to be passed to the function
|
||||
Args() []interface{}
|
||||
}
|
||||
|
||||
UpdateExpression interface {
|
||||
Col() IdentifierExpression
|
||||
Val() interface{}
|
||||
}
|
||||
|
||||
SQLWindowFunctionExpression interface {
|
||||
Expression
|
||||
Aliaseable
|
||||
Rangeable
|
||||
Comparable
|
||||
Orderable
|
||||
Isable
|
||||
Inable
|
||||
Likeable
|
||||
Func() SQLFunctionExpression
|
||||
|
||||
Window() WindowExpression
|
||||
WindowName() IdentifierExpression
|
||||
|
||||
HasWindow() bool
|
||||
HasWindowName() bool
|
||||
}
|
||||
|
||||
WindowExpression interface {
|
||||
Expression
|
||||
|
||||
Name() IdentifierExpression
|
||||
HasName() bool
|
||||
|
||||
Parent() IdentifierExpression
|
||||
HasParent() bool
|
||||
PartitionCols() ColumnListExpression
|
||||
HasPartitionBy() bool
|
||||
OrderCols() ColumnListExpression
|
||||
HasOrder() bool
|
||||
|
||||
Inherit(parent string) WindowExpression
|
||||
PartitionBy(cols ...interface{}) WindowExpression
|
||||
OrderBy(cols ...interface{}) WindowExpression
|
||||
}
|
||||
CaseElse interface {
|
||||
Result() interface{}
|
||||
}
|
||||
CaseWhen interface {
|
||||
Condition() interface{}
|
||||
Result() interface{}
|
||||
}
|
||||
CaseExpression interface {
|
||||
Expression
|
||||
Aliaseable
|
||||
Orderable
|
||||
GetValue() interface{}
|
||||
GetWhens() []CaseWhen
|
||||
GetElse() CaseElse
|
||||
Value(val interface{}) CaseExpression
|
||||
When(condition, result interface{}) CaseExpression
|
||||
Else(result interface{}) CaseExpression
|
||||
}
|
||||
)
|
||||
|
||||
const (
|
||||
UnionCompoundType CompoundType = iota
|
||||
UnionAllCompoundType
|
||||
IntersectCompoundType
|
||||
IntersectAllCompoundType
|
||||
|
||||
DoNothingConflictAction ConflictAction = iota
|
||||
DoUpdateConflictAction
|
||||
|
||||
AndType ExpressionListType = iota
|
||||
OrType
|
||||
|
||||
InnerJoinType JoinType = iota
|
||||
FullOuterJoinType
|
||||
RightOuterJoinType
|
||||
LeftOuterJoinType
|
||||
FullJoinType
|
||||
RightJoinType
|
||||
LeftJoinType
|
||||
NaturalJoinType
|
||||
NaturalLeftJoinType
|
||||
NaturalRightJoinType
|
||||
NaturalFullJoinType
|
||||
CrossJoinType
|
||||
|
||||
UsingJoinCondType JoinConditionType = iota
|
||||
OnJoinCondType
|
||||
|
||||
// Default null sort type with no null sort order
|
||||
NoNullsSortType NullSortType = iota
|
||||
// NULLS FIRST
|
||||
NullsFirstSortType
|
||||
// NULLS LAST
|
||||
NullsLastSortType
|
||||
// ASC
|
||||
AscDir SortDirection = iota
|
||||
// DESC
|
||||
DescSortDir
|
||||
|
||||
// BETWEEN
|
||||
BetweenOp RangeOperation = iota
|
||||
// NOT BETWEEN
|
||||
NotBetweenOp
|
||||
|
||||
// =
|
||||
EqOp BooleanOperation = iota
|
||||
// != or <>
|
||||
NeqOp
|
||||
// IS
|
||||
IsOp
|
||||
// IS NOT
|
||||
IsNotOp
|
||||
// >
|
||||
GtOp
|
||||
// >=
|
||||
GteOp
|
||||
// <
|
||||
LtOp
|
||||
// <=
|
||||
LteOp
|
||||
// IN
|
||||
InOp
|
||||
// NOT IN
|
||||
NotInOp
|
||||
// LIKE, LIKE BINARY...
|
||||
LikeOp
|
||||
// NOT LIKE, NOT LIKE BINARY...
|
||||
NotLikeOp
|
||||
// ILIKE, LIKE
|
||||
ILikeOp
|
||||
// NOT ILIKE, NOT LIKE
|
||||
NotILikeOp
|
||||
// ~, REGEXP BINARY
|
||||
RegexpLikeOp
|
||||
// !~, NOT REGEXP BINARY
|
||||
RegexpNotLikeOp
|
||||
// ~*, REGEXP
|
||||
RegexpILikeOp
|
||||
// !~*, NOT REGEXP
|
||||
RegexpNotILikeOp
|
||||
|
||||
betweenStr = "between"
|
||||
|
||||
BitwiseInversionOp BitwiseOperation = iota
|
||||
BitwiseOrOp
|
||||
BitwiseAndOp
|
||||
BitwiseXorOp
|
||||
BitwiseLeftShiftOp
|
||||
BitwiseRightShiftOp
|
||||
)
|
||||
|
||||
var (
|
||||
ConditionedJoinTypes = map[JoinType]bool{
|
||||
InnerJoinType: true,
|
||||
FullOuterJoinType: true,
|
||||
RightOuterJoinType: true,
|
||||
LeftOuterJoinType: true,
|
||||
FullJoinType: true,
|
||||
RightJoinType: true,
|
||||
LeftJoinType: true,
|
||||
}
|
||||
// used internally for inverting operators
|
||||
operatorInversions = map[BooleanOperation]BooleanOperation{
|
||||
IsOp: IsNotOp,
|
||||
EqOp: NeqOp,
|
||||
GtOp: LteOp,
|
||||
GteOp: LtOp,
|
||||
LtOp: GteOp,
|
||||
LteOp: GtOp,
|
||||
InOp: NotInOp,
|
||||
LikeOp: NotLikeOp,
|
||||
ILikeOp: NotILikeOp,
|
||||
RegexpLikeOp: RegexpNotLikeOp,
|
||||
RegexpILikeOp: RegexpNotILikeOp,
|
||||
IsNotOp: IsOp,
|
||||
NeqOp: EqOp,
|
||||
NotInOp: InOp,
|
||||
NotLikeOp: LikeOp,
|
||||
NotILikeOp: ILikeOp,
|
||||
RegexpNotLikeOp: RegexpLikeOp,
|
||||
RegexpNotILikeOp: RegexpILikeOp,
|
||||
}
|
||||
)
|
||||
|
||||
func (bo BooleanOperation) String() string {
|
||||
switch bo {
|
||||
case EqOp:
|
||||
return "eq"
|
||||
case NeqOp:
|
||||
return "neq"
|
||||
case IsOp:
|
||||
return "is"
|
||||
case IsNotOp:
|
||||
return "isnot"
|
||||
case GtOp:
|
||||
return "gt"
|
||||
case GteOp:
|
||||
return "gte"
|
||||
case LtOp:
|
||||
return "lt"
|
||||
case LteOp:
|
||||
return "lte"
|
||||
case InOp:
|
||||
return "in"
|
||||
case NotInOp:
|
||||
return "notin"
|
||||
case LikeOp:
|
||||
return "like"
|
||||
case NotLikeOp:
|
||||
return "notlike"
|
||||
case ILikeOp:
|
||||
return "ilike"
|
||||
case NotILikeOp:
|
||||
return "notilike"
|
||||
case RegexpLikeOp:
|
||||
return "regexplike"
|
||||
case RegexpNotLikeOp:
|
||||
return "regexpnotlike"
|
||||
case RegexpILikeOp:
|
||||
return "regexpilike"
|
||||
case RegexpNotILikeOp:
|
||||
return "regexpnotilike"
|
||||
}
|
||||
return fmt.Sprintf("%d", bo)
|
||||
}
|
||||
|
||||
func (bi BitwiseOperation) String() string {
|
||||
switch bi {
|
||||
case BitwiseInversionOp:
|
||||
return "Inversion"
|
||||
case BitwiseOrOp:
|
||||
return "OR"
|
||||
case BitwiseAndOp:
|
||||
return "AND"
|
||||
case BitwiseXorOp:
|
||||
return "XOR"
|
||||
case BitwiseLeftShiftOp:
|
||||
return "Left Shift"
|
||||
case BitwiseRightShiftOp:
|
||||
return "Right Shift"
|
||||
}
|
||||
return fmt.Sprintf("%d", bi)
|
||||
}
|
||||
|
||||
func (ro RangeOperation) String() string {
|
||||
switch ro {
|
||||
case BetweenOp:
|
||||
return betweenStr
|
||||
case NotBetweenOp:
|
||||
return "not between"
|
||||
}
|
||||
return fmt.Sprintf("%d", ro)
|
||||
}
|
||||
|
||||
func (jt JoinType) String() string {
|
||||
switch jt {
|
||||
case InnerJoinType:
|
||||
return "InnerJoinType"
|
||||
case FullOuterJoinType:
|
||||
return "FullOuterJoinType"
|
||||
case RightOuterJoinType:
|
||||
return "RightOuterJoinType"
|
||||
case LeftOuterJoinType:
|
||||
return "LeftOuterJoinType"
|
||||
case FullJoinType:
|
||||
return "FullJoinType"
|
||||
case RightJoinType:
|
||||
return "RightJoinType"
|
||||
case LeftJoinType:
|
||||
return "LeftJoinType"
|
||||
case NaturalJoinType:
|
||||
return "NaturalJoinType"
|
||||
case NaturalLeftJoinType:
|
||||
return "NaturalLeftJoinType"
|
||||
case NaturalRightJoinType:
|
||||
return "NaturalRightJoinType"
|
||||
case NaturalFullJoinType:
|
||||
return "NaturalFullJoinType"
|
||||
case CrossJoinType:
|
||||
return "CrossJoinType"
|
||||
}
|
||||
return fmt.Sprintf("%d", jt)
|
||||
}
|
||||
66
vendor/github.com/doug-martin/goqu/v9/exp/exp_list.go
generated
vendored
Normal file
66
vendor/github.com/doug-martin/goqu/v9/exp/exp_list.go
generated
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
package exp
|
||||
|
||||
type (
|
||||
expressionList struct {
|
||||
operator ExpressionListType
|
||||
expressions []Expression
|
||||
}
|
||||
)
|
||||
|
||||
// A list of expressions that should be ORed together
|
||||
// Or(I("a").Eq(10), I("b").Eq(11)) //(("a" = 10) OR ("b" = 11))
|
||||
func NewExpressionList(operator ExpressionListType, expressions ...Expression) ExpressionList {
|
||||
el := expressionList{operator: operator}
|
||||
exps := make([]Expression, 0, len(el.expressions))
|
||||
for _, e := range expressions {
|
||||
switch t := e.(type) {
|
||||
case ExpressionList:
|
||||
if !t.IsEmpty() {
|
||||
exps = append(exps, e)
|
||||
}
|
||||
case Ex:
|
||||
if len(t) > 0 {
|
||||
exps = append(exps, e)
|
||||
}
|
||||
case ExOr:
|
||||
if len(t) > 0 {
|
||||
exps = append(exps, e)
|
||||
}
|
||||
default:
|
||||
exps = append(exps, e)
|
||||
}
|
||||
}
|
||||
el.expressions = exps
|
||||
return el
|
||||
}
|
||||
|
||||
func (el expressionList) Clone() Expression {
|
||||
newExps := make([]Expression, 0, len(el.expressions))
|
||||
for _, exp := range el.expressions {
|
||||
newExps = append(newExps, exp.Clone())
|
||||
}
|
||||
return expressionList{operator: el.operator, expressions: newExps}
|
||||
}
|
||||
|
||||
func (el expressionList) Expression() Expression {
|
||||
return el
|
||||
}
|
||||
|
||||
func (el expressionList) IsEmpty() bool {
|
||||
return len(el.expressions) == 0
|
||||
}
|
||||
|
||||
func (el expressionList) Type() ExpressionListType {
|
||||
return el.operator
|
||||
}
|
||||
|
||||
func (el expressionList) Expressions() []Expression {
|
||||
return el.expressions
|
||||
}
|
||||
|
||||
func (el expressionList) Append(expressions ...Expression) ExpressionList {
|
||||
exps := make([]Expression, 0, len(el.expressions)+len(expressions))
|
||||
exps = append(exps, el.expressions...)
|
||||
exps = append(exps, expressions...)
|
||||
return NewExpressionList(el.operator, exps...)
|
||||
}
|
||||
164
vendor/github.com/doug-martin/goqu/v9/exp/exp_map.go
generated
vendored
Normal file
164
vendor/github.com/doug-martin/goqu/v9/exp/exp_map.go
generated
vendored
Normal file
@@ -0,0 +1,164 @@
|
||||
package exp
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/doug-martin/goqu/v9/internal/errors"
|
||||
)
|
||||
|
||||
type (
|
||||
// A map of expressions to be ANDed together where the keys are string that will be used as Identifiers and values
|
||||
// will be used in a boolean operation.
|
||||
// The Ex map can be used in tandem with Op map to create more complex expression such as LIKE, GT, LT...
|
||||
// See examples.
|
||||
Ex map[string]interface{}
|
||||
// A map of expressions to be ORed together where the keys are string that will be used as Identifiers and values
|
||||
// will be used in a boolean operation.
|
||||
// The Ex map can be used in tandem with Op map to create more complex expression such as LIKE, GT, LT...
|
||||
// See examples.
|
||||
ExOr map[string]interface{}
|
||||
// Used in tandem with the Ex map to create complex comparisons such as LIKE, GT, LT... See examples
|
||||
Op map[string]interface{}
|
||||
)
|
||||
|
||||
func (e Ex) Expression() Expression {
|
||||
return e
|
||||
}
|
||||
|
||||
func (e Ex) Clone() Expression {
|
||||
ret := Ex{}
|
||||
for key, val := range e {
|
||||
ret[key] = val
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (e Ex) IsEmpty() bool {
|
||||
return len(e) == 0
|
||||
}
|
||||
|
||||
func (e Ex) ToExpressions() (ExpressionList, error) {
|
||||
return mapToExpressionList(e, AndType)
|
||||
}
|
||||
|
||||
func (eo ExOr) Expression() Expression {
|
||||
return eo
|
||||
}
|
||||
|
||||
func (eo ExOr) Clone() Expression {
|
||||
ret := ExOr{}
|
||||
for key, val := range eo {
|
||||
ret[key] = val
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (eo ExOr) IsEmpty() bool {
|
||||
return len(eo) == 0
|
||||
}
|
||||
|
||||
func (eo ExOr) ToExpressions() (ExpressionList, error) {
|
||||
return mapToExpressionList(eo, OrType)
|
||||
}
|
||||
|
||||
func getExMapKeys(ex map[string]interface{}) []string {
|
||||
keys := make([]string, 0, len(ex))
|
||||
for key := range ex {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
return keys
|
||||
}
|
||||
|
||||
func mapToExpressionList(ex map[string]interface{}, eType ExpressionListType) (ExpressionList, error) {
|
||||
keys := getExMapKeys(ex)
|
||||
ret := make([]Expression, 0, len(keys))
|
||||
for _, key := range keys {
|
||||
lhs := ParseIdentifier(key)
|
||||
rhs := ex[key]
|
||||
var exp Expression
|
||||
if op, ok := rhs.(Op); ok {
|
||||
ors, err := createOredExpressionFromMap(lhs, op)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
exp = NewExpressionList(OrType, ors...)
|
||||
} else {
|
||||
exp = lhs.Eq(rhs)
|
||||
}
|
||||
ret = append(ret, exp)
|
||||
}
|
||||
if eType == OrType {
|
||||
return NewExpressionList(OrType, ret...), nil
|
||||
}
|
||||
return NewExpressionList(AndType, ret...), nil
|
||||
}
|
||||
|
||||
func createOredExpressionFromMap(lhs IdentifierExpression, op Op) ([]Expression, error) {
|
||||
opKeys := getExMapKeys(op)
|
||||
ors := make([]Expression, 0, len(opKeys))
|
||||
for _, opKey := range opKeys {
|
||||
if exp, err := createExpressionFromOp(lhs, opKey, op); err != nil {
|
||||
return nil, err
|
||||
} else if exp != nil {
|
||||
ors = append(ors, exp)
|
||||
}
|
||||
}
|
||||
return ors, nil
|
||||
}
|
||||
|
||||
// nolint:gocyclo // not complex just long
|
||||
func createExpressionFromOp(lhs IdentifierExpression, opKey string, op Op) (exp Expression, err error) {
|
||||
switch strings.ToLower(opKey) {
|
||||
case EqOp.String():
|
||||
exp = lhs.Eq(op[opKey])
|
||||
case NeqOp.String():
|
||||
exp = lhs.Neq(op[opKey])
|
||||
case IsOp.String():
|
||||
exp = lhs.Is(op[opKey])
|
||||
case IsNotOp.String():
|
||||
exp = lhs.IsNot(op[opKey])
|
||||
case GtOp.String():
|
||||
exp = lhs.Gt(op[opKey])
|
||||
case GteOp.String():
|
||||
exp = lhs.Gte(op[opKey])
|
||||
case LtOp.String():
|
||||
exp = lhs.Lt(op[opKey])
|
||||
case LteOp.String():
|
||||
exp = lhs.Lte(op[opKey])
|
||||
case InOp.String():
|
||||
exp = lhs.In(op[opKey])
|
||||
case NotInOp.String():
|
||||
exp = lhs.NotIn(op[opKey])
|
||||
case LikeOp.String():
|
||||
exp = lhs.Like(op[opKey])
|
||||
case NotLikeOp.String():
|
||||
exp = lhs.NotLike(op[opKey])
|
||||
case ILikeOp.String():
|
||||
exp = lhs.ILike(op[opKey])
|
||||
case NotILikeOp.String():
|
||||
exp = lhs.NotILike(op[opKey])
|
||||
case RegexpLikeOp.String():
|
||||
exp = lhs.RegexpLike(op[opKey])
|
||||
case RegexpNotLikeOp.String():
|
||||
exp = lhs.RegexpNotLike(op[opKey])
|
||||
case RegexpILikeOp.String():
|
||||
exp = lhs.RegexpILike(op[opKey])
|
||||
case RegexpNotILikeOp.String():
|
||||
exp = lhs.RegexpNotILike(op[opKey])
|
||||
case betweenStr:
|
||||
rangeVal, ok := op[opKey].(RangeVal)
|
||||
if ok {
|
||||
exp = lhs.Between(rangeVal)
|
||||
}
|
||||
case "notbetween":
|
||||
rangeVal, ok := op[opKey].(RangeVal)
|
||||
if ok {
|
||||
exp = lhs.NotBetween(rangeVal)
|
||||
}
|
||||
default:
|
||||
err = errors.New("unsupported expression type %s", opKey)
|
||||
}
|
||||
return exp, err
|
||||
}
|
||||
89
vendor/github.com/doug-martin/goqu/v9/exp/func.go
generated
vendored
Normal file
89
vendor/github.com/doug-martin/goqu/v9/exp/func.go
generated
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
package exp
|
||||
|
||||
type (
|
||||
sqlFunctionExpression struct {
|
||||
name string
|
||||
args []interface{}
|
||||
}
|
||||
)
|
||||
|
||||
// Creates a new SQLFunctionExpression with the given name and arguments
|
||||
func NewSQLFunctionExpression(name string, args ...interface{}) SQLFunctionExpression {
|
||||
return sqlFunctionExpression{name: name, args: args}
|
||||
}
|
||||
|
||||
func (sfe sqlFunctionExpression) Clone() Expression {
|
||||
return sqlFunctionExpression{name: sfe.name, args: sfe.args}
|
||||
}
|
||||
|
||||
func (sfe sqlFunctionExpression) Expression() Expression { return sfe }
|
||||
|
||||
func (sfe sqlFunctionExpression) Args() []interface{} { return sfe.args }
|
||||
|
||||
func (sfe sqlFunctionExpression) Name() string { return sfe.name }
|
||||
|
||||
func (sfe sqlFunctionExpression) As(val interface{}) AliasedExpression {
|
||||
return NewAliasExpression(sfe, val)
|
||||
}
|
||||
|
||||
func (sfe sqlFunctionExpression) Eq(val interface{}) BooleanExpression { return eq(sfe, val) }
|
||||
func (sfe sqlFunctionExpression) Neq(val interface{}) BooleanExpression { return neq(sfe, val) }
|
||||
|
||||
func (sfe sqlFunctionExpression) Gt(val interface{}) BooleanExpression { return gt(sfe, val) }
|
||||
func (sfe sqlFunctionExpression) Gte(val interface{}) BooleanExpression { return gte(sfe, val) }
|
||||
func (sfe sqlFunctionExpression) Lt(val interface{}) BooleanExpression { return lt(sfe, val) }
|
||||
func (sfe sqlFunctionExpression) Lte(val interface{}) BooleanExpression { return lte(sfe, val) }
|
||||
|
||||
func (sfe sqlFunctionExpression) Between(val RangeVal) RangeExpression { return between(sfe, val) }
|
||||
|
||||
func (sfe sqlFunctionExpression) NotBetween(val RangeVal) RangeExpression {
|
||||
return notBetween(sfe, val)
|
||||
}
|
||||
|
||||
func (sfe sqlFunctionExpression) Like(val interface{}) BooleanExpression { return like(sfe, val) }
|
||||
func (sfe sqlFunctionExpression) NotLike(val interface{}) BooleanExpression { return notLike(sfe, val) }
|
||||
func (sfe sqlFunctionExpression) ILike(val interface{}) BooleanExpression { return iLike(sfe, val) }
|
||||
|
||||
func (sfe sqlFunctionExpression) NotILike(val interface{}) BooleanExpression {
|
||||
return notILike(sfe, val)
|
||||
}
|
||||
|
||||
func (sfe sqlFunctionExpression) RegexpLike(val interface{}) BooleanExpression {
|
||||
return regexpLike(sfe, val)
|
||||
}
|
||||
|
||||
func (sfe sqlFunctionExpression) RegexpNotLike(val interface{}) BooleanExpression {
|
||||
return regexpNotLike(sfe, val)
|
||||
}
|
||||
|
||||
func (sfe sqlFunctionExpression) RegexpILike(val interface{}) BooleanExpression {
|
||||
return regexpILike(sfe, val)
|
||||
}
|
||||
|
||||
func (sfe sqlFunctionExpression) RegexpNotILike(val interface{}) BooleanExpression {
|
||||
return regexpNotILike(sfe, val)
|
||||
}
|
||||
|
||||
func (sfe sqlFunctionExpression) In(vals ...interface{}) BooleanExpression { return in(sfe, vals...) }
|
||||
func (sfe sqlFunctionExpression) NotIn(vals ...interface{}) BooleanExpression {
|
||||
return notIn(sfe, vals...)
|
||||
}
|
||||
func (sfe sqlFunctionExpression) Is(val interface{}) BooleanExpression { return is(sfe, val) }
|
||||
func (sfe sqlFunctionExpression) IsNot(val interface{}) BooleanExpression { return isNot(sfe, val) }
|
||||
func (sfe sqlFunctionExpression) IsNull() BooleanExpression { return is(sfe, nil) }
|
||||
func (sfe sqlFunctionExpression) IsNotNull() BooleanExpression { return isNot(sfe, nil) }
|
||||
func (sfe sqlFunctionExpression) IsTrue() BooleanExpression { return is(sfe, true) }
|
||||
func (sfe sqlFunctionExpression) IsNotTrue() BooleanExpression { return isNot(sfe, true) }
|
||||
func (sfe sqlFunctionExpression) IsFalse() BooleanExpression { return is(sfe, false) }
|
||||
func (sfe sqlFunctionExpression) IsNotFalse() BooleanExpression { return isNot(sfe, false) }
|
||||
|
||||
func (sfe sqlFunctionExpression) Over(we WindowExpression) SQLWindowFunctionExpression {
|
||||
return NewSQLWindowFunctionExpression(sfe, nil, we)
|
||||
}
|
||||
|
||||
func (sfe sqlFunctionExpression) OverName(windowName IdentifierExpression) SQLWindowFunctionExpression {
|
||||
return NewSQLWindowFunctionExpression(sfe, windowName, nil)
|
||||
}
|
||||
|
||||
func (sfe sqlFunctionExpression) Asc() OrderedExpression { return asc(sfe) }
|
||||
func (sfe sqlFunctionExpression) Desc() OrderedExpression { return desc(sfe) }
|
||||
213
vendor/github.com/doug-martin/goqu/v9/exp/ident.go
generated
vendored
Normal file
213
vendor/github.com/doug-martin/goqu/v9/exp/ident.go
generated
vendored
Normal file
@@ -0,0 +1,213 @@
|
||||
package exp
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
type (
|
||||
identifier struct {
|
||||
schema string
|
||||
table string
|
||||
col interface{}
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
tableAndColumnParts = 2
|
||||
schemaTableAndColumnIdentifierParts = 3
|
||||
)
|
||||
|
||||
func ParseIdentifier(ident string) IdentifierExpression {
|
||||
parts := strings.Split(ident, ".")
|
||||
switch len(parts) {
|
||||
case tableAndColumnParts:
|
||||
return NewIdentifierExpression("", parts[0], parts[1])
|
||||
case schemaTableAndColumnIdentifierParts:
|
||||
return NewIdentifierExpression(parts[0], parts[1], parts[2])
|
||||
}
|
||||
return NewIdentifierExpression("", "", ident)
|
||||
}
|
||||
|
||||
func NewIdentifierExpression(schema, table string, col interface{}) IdentifierExpression {
|
||||
return identifier{}.Schema(schema).Table(table).Col(col)
|
||||
}
|
||||
|
||||
func (i identifier) clone() identifier {
|
||||
return identifier{schema: i.schema, table: i.table, col: i.col}
|
||||
}
|
||||
|
||||
func (i identifier) Clone() Expression {
|
||||
return i.clone()
|
||||
}
|
||||
|
||||
func (i identifier) IsQualified() bool {
|
||||
schema, table, col := i.schema, i.table, i.col
|
||||
switch c := col.(type) {
|
||||
case string:
|
||||
if c != "" {
|
||||
return len(table) > 0 || len(schema) > 0
|
||||
}
|
||||
default:
|
||||
if c != nil {
|
||||
return len(table) > 0 || len(schema) > 0
|
||||
}
|
||||
}
|
||||
if len(table) > 0 {
|
||||
return len(schema) > 0
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Sets the table on the current identifier
|
||||
// I("col").Table("table") -> "table"."col" //postgres
|
||||
// I("col").Table("table") -> `table`.`col` //mysql
|
||||
// I("col").Table("table") -> `table`.`col` //sqlite3
|
||||
func (i identifier) Table(table string) IdentifierExpression {
|
||||
i.table = table
|
||||
return i
|
||||
}
|
||||
|
||||
func (i identifier) GetTable() string {
|
||||
return i.table
|
||||
}
|
||||
|
||||
// Sets the table on the current identifier
|
||||
// I("table").Schema("schema") -> "schema"."table" //postgres
|
||||
// I("col").Schema("table") -> `schema`.`table` //mysql
|
||||
// I("col").Schema("table") -> `schema`.`table` //sqlite3
|
||||
func (i identifier) Schema(schema string) IdentifierExpression {
|
||||
i.schema = schema
|
||||
return i
|
||||
}
|
||||
|
||||
func (i identifier) GetSchema() string {
|
||||
return i.schema
|
||||
}
|
||||
|
||||
// Sets the table on the current identifier
|
||||
// I("table").Col("col") -> "table"."col" //postgres
|
||||
// I("table").Schema("col") -> `table`.`col` //mysql
|
||||
// I("table").Schema("col") -> `table`.`col` //sqlite3
|
||||
func (i identifier) Col(col interface{}) IdentifierExpression {
|
||||
if col == "*" {
|
||||
i.col = Star()
|
||||
} else {
|
||||
i.col = col
|
||||
}
|
||||
return i
|
||||
}
|
||||
|
||||
func (i identifier) Expression() Expression { return i }
|
||||
|
||||
// Qualifies the epression with a * literal (e.g. "table".*)
|
||||
func (i identifier) All() IdentifierExpression { return i.Col("*") }
|
||||
|
||||
func (i identifier) IsEmpty() bool {
|
||||
isEmpty := i.schema == "" && i.table == ""
|
||||
if isEmpty {
|
||||
switch t := i.col.(type) {
|
||||
case nil:
|
||||
return true
|
||||
case string:
|
||||
return t == ""
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
return isEmpty
|
||||
}
|
||||
|
||||
// Gets the column identifier
|
||||
func (i identifier) GetCol() interface{} { return i.col }
|
||||
|
||||
// Used within updates to set a column value
|
||||
func (i identifier) Set(val interface{}) UpdateExpression { return set(i, val) }
|
||||
|
||||
// Alias an identifier (e.g "my_col" AS "other_col")
|
||||
func (i identifier) As(val interface{}) AliasedExpression {
|
||||
if v, ok := val.(string); ok {
|
||||
ident := ParseIdentifier(v)
|
||||
if i.col != nil && i.col != "" {
|
||||
return NewAliasExpression(i, ident)
|
||||
}
|
||||
aliasCol := ident.GetCol()
|
||||
if i.table != "" {
|
||||
return NewAliasExpression(i, NewIdentifierExpression("", aliasCol.(string), nil))
|
||||
} else if i.schema != "" {
|
||||
return NewAliasExpression(i, NewIdentifierExpression(aliasCol.(string), "", nil))
|
||||
}
|
||||
}
|
||||
return NewAliasExpression(i, val)
|
||||
}
|
||||
|
||||
// Returns a BooleanExpression for equality (e.g "my_col" = 1)
|
||||
func (i identifier) Eq(val interface{}) BooleanExpression { return eq(i, val) }
|
||||
|
||||
// Returns a BooleanExpression for in equality (e.g "my_col" != 1)
|
||||
func (i identifier) Neq(val interface{}) BooleanExpression { return neq(i, val) }
|
||||
|
||||
// Returns a BooleanExpression for checking that a identifier is greater than another value (e.g "my_col" > 1)
|
||||
func (i identifier) Gt(val interface{}) BooleanExpression { return gt(i, val) }
|
||||
|
||||
// Returns a BooleanExpression for checking that a identifier is greater than or equal to another value
|
||||
// (e.g "my_col" >= 1)
|
||||
func (i identifier) Gte(val interface{}) BooleanExpression { return gte(i, val) }
|
||||
|
||||
// Returns a BooleanExpression for checking that a identifier is less than another value (e.g "my_col" < 1)
|
||||
func (i identifier) Lt(val interface{}) BooleanExpression { return lt(i, val) }
|
||||
|
||||
// Returns a BooleanExpression for checking that a identifier is less than or equal to another value
|
||||
// (e.g "my_col" <= 1)
|
||||
func (i identifier) Lte(val interface{}) BooleanExpression { return lte(i, val) }
|
||||
|
||||
// Returns a BooleanExpression for bit inversion (e.g ~ "my_col")
|
||||
func (i identifier) BitwiseInversion() BitwiseExpression { return bitwiseInversion(i) }
|
||||
|
||||
// Returns a BooleanExpression for bit OR (e.g "my_col" | 1)
|
||||
func (i identifier) BitwiseOr(val interface{}) BitwiseExpression { return bitwiseOr(i, val) }
|
||||
|
||||
// Returns a BooleanExpression for bit AND (e.g "my_col" & 1)
|
||||
func (i identifier) BitwiseAnd(val interface{}) BitwiseExpression { return bitwiseAnd(i, val) }
|
||||
|
||||
// Returns a BooleanExpression for bit XOR (e.g "my_col" ^ 1)
|
||||
func (i identifier) BitwiseXor(val interface{}) BitwiseExpression { return bitwiseXor(i, val) }
|
||||
|
||||
// Returns a BooleanExpression for bit LEFT shift (e.g "my_col" << 1)
|
||||
func (i identifier) BitwiseLeftShift(val interface{}) BitwiseExpression {
|
||||
return bitwiseLeftShift(i, val)
|
||||
}
|
||||
|
||||
// Returns a BooleanExpression for bit RIGHT shift (e.g "my_col" >> 1)
|
||||
func (i identifier) BitwiseRightShift(val interface{}) BitwiseExpression {
|
||||
return bitwiseRightShift(i, val)
|
||||
}
|
||||
|
||||
// Returns a BooleanExpression for checking that a identifier is in a list of values or (e.g "my_col" > 1)
|
||||
func (i identifier) In(vals ...interface{}) BooleanExpression { return in(i, vals...) }
|
||||
func (i identifier) NotIn(vals ...interface{}) BooleanExpression { return notIn(i, vals...) }
|
||||
func (i identifier) Like(val interface{}) BooleanExpression { return like(i, val) }
|
||||
func (i identifier) NotLike(val interface{}) BooleanExpression { return notLike(i, val) }
|
||||
func (i identifier) ILike(val interface{}) BooleanExpression { return iLike(i, val) }
|
||||
func (i identifier) NotILike(val interface{}) BooleanExpression { return notILike(i, val) }
|
||||
func (i identifier) RegexpLike(val interface{}) BooleanExpression { return regexpLike(i, val) }
|
||||
func (i identifier) RegexpNotLike(val interface{}) BooleanExpression { return regexpNotLike(i, val) }
|
||||
func (i identifier) RegexpILike(val interface{}) BooleanExpression { return regexpILike(i, val) }
|
||||
func (i identifier) RegexpNotILike(val interface{}) BooleanExpression { return regexpNotILike(i, val) }
|
||||
func (i identifier) Is(val interface{}) BooleanExpression { return is(i, val) }
|
||||
func (i identifier) IsNot(val interface{}) BooleanExpression { return isNot(i, val) }
|
||||
func (i identifier) IsNull() BooleanExpression { return is(i, nil) }
|
||||
func (i identifier) IsNotNull() BooleanExpression { return isNot(i, nil) }
|
||||
func (i identifier) IsTrue() BooleanExpression { return is(i, true) }
|
||||
func (i identifier) IsNotTrue() BooleanExpression { return isNot(i, true) }
|
||||
func (i identifier) IsFalse() BooleanExpression { return is(i, false) }
|
||||
func (i identifier) IsNotFalse() BooleanExpression { return isNot(i, false) }
|
||||
func (i identifier) Asc() OrderedExpression { return asc(i) }
|
||||
func (i identifier) Desc() OrderedExpression { return desc(i) }
|
||||
func (i identifier) Distinct() SQLFunctionExpression { return NewSQLFunctionExpression("DISTINCT", i) }
|
||||
func (i identifier) Cast(t string) CastExpression { return NewCastExpression(i, t) }
|
||||
|
||||
// Returns a RangeExpression for checking that a identifier is between two values (e.g "my_col" BETWEEN 1 AND 10)
|
||||
func (i identifier) Between(val RangeVal) RangeExpression { return between(i, val) }
|
||||
|
||||
// Returns a RangeExpression for checking that a identifier is between two values (e.g "my_col" BETWEEN 1 AND 10)
|
||||
func (i identifier) NotBetween(val RangeVal) RangeExpression { return notBetween(i, val) }
|
||||
163
vendor/github.com/doug-martin/goqu/v9/exp/insert.go
generated
vendored
Normal file
163
vendor/github.com/doug-martin/goqu/v9/exp/insert.go
generated
vendored
Normal file
@@ -0,0 +1,163 @@
|
||||
package exp
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"sort"
|
||||
|
||||
"github.com/doug-martin/goqu/v9/internal/errors"
|
||||
"github.com/doug-martin/goqu/v9/internal/util"
|
||||
)
|
||||
|
||||
type (
|
||||
insert struct {
|
||||
from AppendableExpression
|
||||
cols ColumnListExpression
|
||||
vals [][]interface{}
|
||||
}
|
||||
)
|
||||
|
||||
func NewInsertExpression(rows ...interface{}) (insertExpression InsertExpression, err error) {
|
||||
switch len(rows) {
|
||||
case 0:
|
||||
return new(insert), nil
|
||||
case 1:
|
||||
val := reflect.ValueOf(rows[0])
|
||||
if val.Kind() == reflect.Slice {
|
||||
vals := make([]interface{}, 0, val.Len())
|
||||
for i := 0; i < val.Len(); i++ {
|
||||
vals = append(vals, val.Index(i).Interface())
|
||||
}
|
||||
return NewInsertExpression(vals...)
|
||||
}
|
||||
if ae, ok := rows[0].(AppendableExpression); ok {
|
||||
return &insert{from: ae}, nil
|
||||
}
|
||||
}
|
||||
return newInsert(rows...)
|
||||
}
|
||||
|
||||
func (i *insert) Expression() Expression {
|
||||
return i
|
||||
}
|
||||
|
||||
func (i *insert) Clone() Expression {
|
||||
return i.clone()
|
||||
}
|
||||
|
||||
func (i *insert) clone() *insert {
|
||||
return &insert{from: i.from, cols: i.cols, vals: i.vals}
|
||||
}
|
||||
|
||||
func (i *insert) IsEmpty() bool {
|
||||
return i.from == nil && (i.cols == nil || i.cols.IsEmpty())
|
||||
}
|
||||
|
||||
func (i *insert) IsInsertFrom() bool {
|
||||
return i.from != nil
|
||||
}
|
||||
|
||||
func (i *insert) From() AppendableExpression {
|
||||
return i.from
|
||||
}
|
||||
|
||||
func (i *insert) Cols() ColumnListExpression {
|
||||
return i.cols
|
||||
}
|
||||
|
||||
func (i *insert) SetCols(cols ColumnListExpression) InsertExpression {
|
||||
ci := i.clone()
|
||||
ci.cols = cols
|
||||
return ci
|
||||
}
|
||||
|
||||
func (i *insert) Vals() [][]interface{} {
|
||||
return i.vals
|
||||
}
|
||||
|
||||
func (i *insert) SetVals(vals [][]interface{}) InsertExpression {
|
||||
ci := i.clone()
|
||||
ci.vals = vals
|
||||
return ci
|
||||
}
|
||||
|
||||
// parses the rows gathering and sorting unique columns and values for each record
|
||||
func newInsert(rows ...interface{}) (insertExp InsertExpression, err error) {
|
||||
var mapKeys util.ValueSlice
|
||||
rowValue := reflect.Indirect(reflect.ValueOf(rows[0]))
|
||||
rowType := rowValue.Type()
|
||||
rowKind := rowValue.Kind()
|
||||
if rowKind == reflect.Struct {
|
||||
return createStructSliceInsert(rows...)
|
||||
}
|
||||
vals := make([][]interface{}, 0, len(rows))
|
||||
var columns ColumnListExpression
|
||||
for _, row := range rows {
|
||||
if rowType != reflect.Indirect(reflect.ValueOf(row)).Type() {
|
||||
return nil, errors.New(
|
||||
"rows must be all the same type expected %+v got %+v",
|
||||
rowType,
|
||||
reflect.Indirect(reflect.ValueOf(row)).Type(),
|
||||
)
|
||||
}
|
||||
newRowValue := reflect.Indirect(reflect.ValueOf(row))
|
||||
switch rowKind {
|
||||
case reflect.Map:
|
||||
if columns == nil {
|
||||
mapKeys = util.ValueSlice(newRowValue.MapKeys())
|
||||
sort.Sort(mapKeys)
|
||||
colKeys := make([]interface{}, 0, len(mapKeys))
|
||||
for _, key := range mapKeys {
|
||||
colKeys = append(colKeys, key.Interface())
|
||||
}
|
||||
columns = NewColumnListExpression(colKeys...)
|
||||
}
|
||||
newMapKeys := util.ValueSlice(newRowValue.MapKeys())
|
||||
if len(newMapKeys) != len(mapKeys) {
|
||||
return nil, errors.New("rows with different value length expected %d got %d", len(mapKeys), len(newMapKeys))
|
||||
}
|
||||
if !mapKeys.Equal(newMapKeys) {
|
||||
return nil, errors.New("rows with different keys expected %s got %s", mapKeys.String(), newMapKeys.String())
|
||||
}
|
||||
rowVals := make([]interface{}, 0, len(mapKeys))
|
||||
for _, key := range mapKeys {
|
||||
rowVals = append(rowVals, newRowValue.MapIndex(key).Interface())
|
||||
}
|
||||
vals = append(vals, rowVals)
|
||||
default:
|
||||
return nil, errors.New(
|
||||
"unsupported insert must be map, goqu.Record, or struct type got: %T",
|
||||
row,
|
||||
)
|
||||
}
|
||||
}
|
||||
return &insert{cols: columns, vals: vals}, nil
|
||||
}
|
||||
|
||||
func createStructSliceInsert(rows ...interface{}) (insertExp InsertExpression, err error) {
|
||||
rowValue := reflect.Indirect(reflect.ValueOf(rows[0]))
|
||||
rowType := rowValue.Type()
|
||||
recordRows := make([]interface{}, 0, len(rows))
|
||||
for _, row := range rows {
|
||||
if rowType != reflect.Indirect(reflect.ValueOf(row)).Type() {
|
||||
return nil, errors.New(
|
||||
"rows must be all the same type expected %+v got %+v",
|
||||
rowType,
|
||||
reflect.Indirect(reflect.ValueOf(row)).Type(),
|
||||
)
|
||||
}
|
||||
newRowValue := reflect.Indirect(reflect.ValueOf(row))
|
||||
record, err := getFieldsValuesFromStruct(newRowValue)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
recordRows = append(recordRows, record)
|
||||
}
|
||||
return newInsert(recordRows...)
|
||||
}
|
||||
|
||||
func getFieldsValuesFromStruct(value reflect.Value) (row Record, err error) {
|
||||
if value.IsValid() {
|
||||
return NewRecordFromStruct(value.Interface(), true, false)
|
||||
}
|
||||
return
|
||||
}
|
||||
205
vendor/github.com/doug-martin/goqu/v9/exp/insert_clauses.go
generated
vendored
Normal file
205
vendor/github.com/doug-martin/goqu/v9/exp/insert_clauses.go
generated
vendored
Normal file
@@ -0,0 +1,205 @@
|
||||
package exp
|
||||
|
||||
type (
|
||||
InsertClauses interface {
|
||||
CommonTables() []CommonTableExpression
|
||||
CommonTablesAppend(cte CommonTableExpression) InsertClauses
|
||||
|
||||
HasInto() bool
|
||||
clone() *insertClauses
|
||||
|
||||
Cols() ColumnListExpression
|
||||
HasCols() bool
|
||||
ColsAppend(cols ColumnListExpression) InsertClauses
|
||||
SetCols(cols ColumnListExpression) InsertClauses
|
||||
|
||||
Into() Expression
|
||||
SetInto(cl Expression) InsertClauses
|
||||
|
||||
Returning() ColumnListExpression
|
||||
HasReturning() bool
|
||||
SetReturning(cl ColumnListExpression) InsertClauses
|
||||
|
||||
From() AppendableExpression
|
||||
HasFrom() bool
|
||||
SetFrom(ae AppendableExpression) InsertClauses
|
||||
|
||||
Rows() []interface{}
|
||||
HasRows() bool
|
||||
SetRows(rows []interface{}) InsertClauses
|
||||
|
||||
HasAlias() bool
|
||||
Alias() IdentifierExpression
|
||||
SetAlias(ie IdentifierExpression) InsertClauses
|
||||
|
||||
Vals() [][]interface{}
|
||||
HasVals() bool
|
||||
SetVals(vals [][]interface{}) InsertClauses
|
||||
ValsAppend(vals [][]interface{}) InsertClauses
|
||||
|
||||
OnConflict() ConflictExpression
|
||||
SetOnConflict(expression ConflictExpression) InsertClauses
|
||||
}
|
||||
insertClauses struct {
|
||||
commonTables []CommonTableExpression
|
||||
cols ColumnListExpression
|
||||
into Expression
|
||||
returning ColumnListExpression
|
||||
alias IdentifierExpression
|
||||
rows []interface{}
|
||||
values [][]interface{}
|
||||
from AppendableExpression
|
||||
conflict ConflictExpression
|
||||
}
|
||||
)
|
||||
|
||||
func NewInsertClauses() InsertClauses {
|
||||
return &insertClauses{}
|
||||
}
|
||||
|
||||
func (ic *insertClauses) HasInto() bool {
|
||||
return ic.into != nil
|
||||
}
|
||||
|
||||
func (ic *insertClauses) clone() *insertClauses {
|
||||
return &insertClauses{
|
||||
commonTables: ic.commonTables,
|
||||
cols: ic.cols,
|
||||
into: ic.into,
|
||||
returning: ic.returning,
|
||||
alias: ic.alias,
|
||||
rows: ic.rows,
|
||||
values: ic.values,
|
||||
from: ic.from,
|
||||
conflict: ic.conflict,
|
||||
}
|
||||
}
|
||||
|
||||
func (ic *insertClauses) CommonTables() []CommonTableExpression {
|
||||
return ic.commonTables
|
||||
}
|
||||
|
||||
func (ic *insertClauses) CommonTablesAppend(cte CommonTableExpression) InsertClauses {
|
||||
ret := ic.clone()
|
||||
ret.commonTables = append(ret.commonTables, cte)
|
||||
return ret
|
||||
}
|
||||
|
||||
func (ic *insertClauses) Cols() ColumnListExpression {
|
||||
return ic.cols
|
||||
}
|
||||
|
||||
func (ic *insertClauses) HasCols() bool {
|
||||
return ic.cols != nil && !ic.cols.IsEmpty()
|
||||
}
|
||||
|
||||
func (ic *insertClauses) ColsAppend(cl ColumnListExpression) InsertClauses {
|
||||
ret := ic.clone()
|
||||
ret.cols = ret.cols.Append(cl.Columns()...)
|
||||
return ret
|
||||
}
|
||||
|
||||
func (ic *insertClauses) SetCols(cl ColumnListExpression) InsertClauses {
|
||||
ret := ic.clone()
|
||||
ret.cols = cl
|
||||
return ret
|
||||
}
|
||||
|
||||
func (ic *insertClauses) Into() Expression {
|
||||
return ic.into
|
||||
}
|
||||
|
||||
func (ic *insertClauses) SetInto(into Expression) InsertClauses {
|
||||
ret := ic.clone()
|
||||
ret.into = into
|
||||
return ret
|
||||
}
|
||||
|
||||
func (ic *insertClauses) Returning() ColumnListExpression {
|
||||
return ic.returning
|
||||
}
|
||||
|
||||
func (ic *insertClauses) HasReturning() bool {
|
||||
return ic.returning != nil && !ic.returning.IsEmpty()
|
||||
}
|
||||
|
||||
func (ic *insertClauses) HasAlias() bool {
|
||||
return ic.alias != nil
|
||||
}
|
||||
|
||||
func (ic *insertClauses) Alias() IdentifierExpression {
|
||||
return ic.alias
|
||||
}
|
||||
|
||||
func (ic *insertClauses) SetAlias(ie IdentifierExpression) InsertClauses {
|
||||
ret := ic.clone()
|
||||
ret.alias = ie
|
||||
return ret
|
||||
}
|
||||
|
||||
func (ic *insertClauses) SetReturning(cl ColumnListExpression) InsertClauses {
|
||||
ret := ic.clone()
|
||||
ret.returning = cl
|
||||
return ret
|
||||
}
|
||||
|
||||
func (ic *insertClauses) From() AppendableExpression {
|
||||
return ic.from
|
||||
}
|
||||
|
||||
func (ic *insertClauses) HasFrom() bool {
|
||||
return ic.from != nil
|
||||
}
|
||||
|
||||
func (ic *insertClauses) SetFrom(ae AppendableExpression) InsertClauses {
|
||||
ret := ic.clone()
|
||||
ret.from = ae
|
||||
return ret
|
||||
}
|
||||
|
||||
func (ic *insertClauses) Rows() []interface{} {
|
||||
return ic.rows
|
||||
}
|
||||
|
||||
func (ic *insertClauses) HasRows() bool {
|
||||
return ic.rows != nil && len(ic.rows) > 0
|
||||
}
|
||||
|
||||
func (ic *insertClauses) SetRows(rows []interface{}) InsertClauses {
|
||||
ret := ic.clone()
|
||||
ret.rows = rows
|
||||
return ret
|
||||
}
|
||||
|
||||
func (ic *insertClauses) Vals() [][]interface{} {
|
||||
return ic.values
|
||||
}
|
||||
|
||||
func (ic *insertClauses) HasVals() bool {
|
||||
return ic.values != nil && len(ic.values) > 0
|
||||
}
|
||||
|
||||
func (ic *insertClauses) SetVals(vals [][]interface{}) InsertClauses {
|
||||
ret := ic.clone()
|
||||
ret.values = vals
|
||||
return ret
|
||||
}
|
||||
|
||||
func (ic *insertClauses) ValsAppend(vals [][]interface{}) InsertClauses {
|
||||
ret := ic.clone()
|
||||
newVals := make([][]interface{}, 0, len(ic.values)+len(vals))
|
||||
newVals = append(newVals, ic.values...)
|
||||
newVals = append(newVals, vals...)
|
||||
ret.values = newVals
|
||||
return ret
|
||||
}
|
||||
|
||||
func (ic *insertClauses) OnConflict() ConflictExpression {
|
||||
return ic.conflict
|
||||
}
|
||||
|
||||
func (ic *insertClauses) SetOnConflict(expression ConflictExpression) InsertClauses {
|
||||
ret := ic.clone()
|
||||
ret.conflict = expression
|
||||
return ret
|
||||
}
|
||||
139
vendor/github.com/doug-martin/goqu/v9/exp/join.go
generated
vendored
Normal file
139
vendor/github.com/doug-martin/goqu/v9/exp/join.go
generated
vendored
Normal file
@@ -0,0 +1,139 @@
|
||||
package exp
|
||||
|
||||
type (
|
||||
joinExpression struct {
|
||||
isConditioned bool
|
||||
// The JoinType
|
||||
joinType JoinType
|
||||
// The table expressions (e.g. LEFT JOIN "my_table", ON (....))
|
||||
table Expression
|
||||
}
|
||||
// Container for all joins within a dataset
|
||||
conditionedJoin struct {
|
||||
joinExpression
|
||||
// The condition to join (e.g. USING("a", "b"), ON("my_table"."fkey" = "other_table"."id")
|
||||
condition JoinCondition
|
||||
}
|
||||
JoinExpressions []JoinExpression
|
||||
)
|
||||
|
||||
func NewUnConditionedJoinExpression(joinType JoinType, table Expression) JoinExpression {
|
||||
return joinExpression{
|
||||
joinType: joinType,
|
||||
table: table,
|
||||
isConditioned: false,
|
||||
}
|
||||
}
|
||||
|
||||
func (je joinExpression) Clone() Expression {
|
||||
return je
|
||||
}
|
||||
|
||||
func (je joinExpression) Expression() Expression {
|
||||
return je
|
||||
}
|
||||
|
||||
func (je joinExpression) IsConditioned() bool {
|
||||
return je.isConditioned
|
||||
}
|
||||
|
||||
func (je joinExpression) JoinType() JoinType {
|
||||
return je.joinType
|
||||
}
|
||||
|
||||
func (je joinExpression) Table() Expression {
|
||||
return je.table
|
||||
}
|
||||
|
||||
func NewConditionedJoinExpression(joinType JoinType, table Expression, condition JoinCondition) ConditionedJoinExpression {
|
||||
return conditionedJoin{
|
||||
joinExpression: joinExpression{
|
||||
joinType: joinType,
|
||||
table: table,
|
||||
isConditioned: true,
|
||||
},
|
||||
condition: condition,
|
||||
}
|
||||
}
|
||||
|
||||
func (je conditionedJoin) Clone() Expression {
|
||||
return je
|
||||
}
|
||||
|
||||
func (je conditionedJoin) Expression() Expression {
|
||||
return je
|
||||
}
|
||||
|
||||
func (je conditionedJoin) Condition() JoinCondition {
|
||||
return je.condition
|
||||
}
|
||||
|
||||
func (je conditionedJoin) IsConditionEmpty() bool {
|
||||
return je.condition == nil || je.condition.IsEmpty()
|
||||
}
|
||||
|
||||
func (jes JoinExpressions) Clone() JoinExpressions {
|
||||
ret := make(JoinExpressions, 0, len(jes))
|
||||
for _, jc := range jes {
|
||||
ret = append(ret, jc.Clone().(JoinExpression))
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
type (
|
||||
JoinConditionType int
|
||||
JoinCondition interface {
|
||||
Type() JoinConditionType
|
||||
IsEmpty() bool
|
||||
}
|
||||
JoinOnCondition interface {
|
||||
JoinCondition
|
||||
On() ExpressionList
|
||||
}
|
||||
JoinUsingCondition interface {
|
||||
JoinCondition
|
||||
Using() ColumnListExpression
|
||||
}
|
||||
joinOnCondition struct {
|
||||
on ExpressionList
|
||||
}
|
||||
|
||||
joinUsingCondition struct {
|
||||
using ColumnListExpression
|
||||
}
|
||||
)
|
||||
|
||||
// Creates a new ON clause to be used within a join
|
||||
// ds.Join(I("my_table"), On(I("my_table.fkey").Eq(I("other_table.id")))
|
||||
func NewJoinOnCondition(expressions ...Expression) JoinCondition {
|
||||
return joinOnCondition{on: NewExpressionList(AndType, expressions...)}
|
||||
}
|
||||
|
||||
func (joc joinOnCondition) Type() JoinConditionType {
|
||||
return OnJoinCondType
|
||||
}
|
||||
|
||||
func (joc joinOnCondition) On() ExpressionList {
|
||||
return joc.on
|
||||
}
|
||||
|
||||
func (joc joinOnCondition) IsEmpty() bool {
|
||||
return len(joc.on.Expressions()) == 0
|
||||
}
|
||||
|
||||
// Creates a new USING clause to be used within a join
|
||||
func NewJoinUsingCondition(expressions ...interface{}) JoinCondition {
|
||||
return joinUsingCondition{using: NewColumnListExpression(expressions...)}
|
||||
}
|
||||
|
||||
func (juc joinUsingCondition) Type() JoinConditionType {
|
||||
return UsingJoinCondType
|
||||
}
|
||||
|
||||
func (juc joinUsingCondition) Using() ColumnListExpression {
|
||||
return juc.using
|
||||
}
|
||||
|
||||
func (juc joinUsingCondition) IsEmpty() bool {
|
||||
return len(juc.using.Columns()) == 0
|
||||
}
|
||||
24
vendor/github.com/doug-martin/goqu/v9/exp/lateral.go
generated
vendored
Normal file
24
vendor/github.com/doug-martin/goqu/v9/exp/lateral.go
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
package exp
|
||||
|
||||
type (
|
||||
lateral struct {
|
||||
table AppendableExpression
|
||||
}
|
||||
)
|
||||
|
||||
// Creates a new SQL lateral expression
|
||||
// L(From("test")) -> LATERAL (SELECT * FROM "tests")
|
||||
func NewLateralExpression(table AppendableExpression) LateralExpression {
|
||||
return lateral{table: table}
|
||||
}
|
||||
|
||||
func (l lateral) Clone() Expression {
|
||||
return NewLateralExpression(l.table)
|
||||
}
|
||||
|
||||
func (l lateral) Table() AppendableExpression {
|
||||
return l.table
|
||||
}
|
||||
|
||||
func (l lateral) Expression() Expression { return l }
|
||||
func (l lateral) As(val interface{}) AliasedExpression { return NewAliasExpression(l, val) }
|
||||
80
vendor/github.com/doug-martin/goqu/v9/exp/literal.go
generated
vendored
Normal file
80
vendor/github.com/doug-martin/goqu/v9/exp/literal.go
generated
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
package exp
|
||||
|
||||
type (
|
||||
literal struct {
|
||||
literal string
|
||||
args []interface{}
|
||||
}
|
||||
)
|
||||
|
||||
// Creates a new SQL literal with the provided arguments.
|
||||
// L("a = 1") -> a = 1
|
||||
// You can also you placeholders. All placeholders within a Literal are represented by '?'
|
||||
// L("a = ?", "b") -> a = 'b'
|
||||
// Literals can also contain placeholders for other expressions
|
||||
// L("(? AND ?) OR (?)", I("a").Eq(1), I("b").Eq("b"), I("c").In([]string{"a", "b", "c"}))
|
||||
func NewLiteralExpression(sql string, args ...interface{}) LiteralExpression {
|
||||
return literal{literal: sql, args: args}
|
||||
}
|
||||
|
||||
// Returns a literal for the '*' operator
|
||||
func Star() LiteralExpression {
|
||||
return NewLiteralExpression("*")
|
||||
}
|
||||
|
||||
// Returns a literal for the 'DEFAULT'
|
||||
func Default() LiteralExpression {
|
||||
return NewLiteralExpression("DEFAULT")
|
||||
}
|
||||
|
||||
func (l literal) Clone() Expression {
|
||||
return NewLiteralExpression(l.literal, l.args...)
|
||||
}
|
||||
|
||||
func (l literal) Literal() string {
|
||||
return l.literal
|
||||
}
|
||||
|
||||
func (l literal) Args() []interface{} {
|
||||
return l.args
|
||||
}
|
||||
|
||||
func (l literal) Expression() Expression { return l }
|
||||
func (l literal) As(val interface{}) AliasedExpression { return NewAliasExpression(l, val) }
|
||||
func (l literal) Eq(val interface{}) BooleanExpression { return eq(l, val) }
|
||||
func (l literal) Neq(val interface{}) BooleanExpression { return neq(l, val) }
|
||||
func (l literal) Gt(val interface{}) BooleanExpression { return gt(l, val) }
|
||||
func (l literal) Gte(val interface{}) BooleanExpression { return gte(l, val) }
|
||||
func (l literal) Lt(val interface{}) BooleanExpression { return lt(l, val) }
|
||||
func (l literal) Lte(val interface{}) BooleanExpression { return lte(l, val) }
|
||||
func (l literal) Asc() OrderedExpression { return asc(l) }
|
||||
func (l literal) Desc() OrderedExpression { return desc(l) }
|
||||
func (l literal) Between(val RangeVal) RangeExpression { return between(l, val) }
|
||||
func (l literal) NotBetween(val RangeVal) RangeExpression { return notBetween(l, val) }
|
||||
func (l literal) Like(val interface{}) BooleanExpression { return like(l, val) }
|
||||
func (l literal) NotLike(val interface{}) BooleanExpression { return notLike(l, val) }
|
||||
func (l literal) ILike(val interface{}) BooleanExpression { return iLike(l, val) }
|
||||
func (l literal) NotILike(val interface{}) BooleanExpression { return notILike(l, val) }
|
||||
func (l literal) RegexpLike(val interface{}) BooleanExpression { return regexpLike(l, val) }
|
||||
func (l literal) RegexpNotLike(val interface{}) BooleanExpression { return regexpNotLike(l, val) }
|
||||
func (l literal) RegexpILike(val interface{}) BooleanExpression { return regexpILike(l, val) }
|
||||
func (l literal) RegexpNotILike(val interface{}) BooleanExpression { return regexpNotILike(l, val) }
|
||||
func (l literal) In(vals ...interface{}) BooleanExpression { return in(l, vals...) }
|
||||
func (l literal) NotIn(vals ...interface{}) BooleanExpression { return notIn(l, vals...) }
|
||||
func (l literal) Is(val interface{}) BooleanExpression { return is(l, val) }
|
||||
func (l literal) IsNot(val interface{}) BooleanExpression { return isNot(l, val) }
|
||||
func (l literal) IsNull() BooleanExpression { return is(l, nil) }
|
||||
func (l literal) IsNotNull() BooleanExpression { return isNot(l, nil) }
|
||||
func (l literal) IsTrue() BooleanExpression { return is(l, true) }
|
||||
func (l literal) IsNotTrue() BooleanExpression { return isNot(l, true) }
|
||||
func (l literal) IsFalse() BooleanExpression { return is(l, false) }
|
||||
func (l literal) IsNotFalse() BooleanExpression { return isNot(l, false) }
|
||||
|
||||
func (l literal) BitwiseInversion() BitwiseExpression { return bitwiseInversion(l) }
|
||||
func (l literal) BitwiseOr(val interface{}) BitwiseExpression { return bitwiseOr(l, val) }
|
||||
func (l literal) BitwiseAnd(val interface{}) BitwiseExpression { return bitwiseAnd(l, val) }
|
||||
func (l literal) BitwiseXor(val interface{}) BitwiseExpression { return bitwiseXor(l, val) }
|
||||
func (l literal) BitwiseLeftShift(val interface{}) BitwiseExpression { return bitwiseLeftShift(l, val) }
|
||||
func (l literal) BitwiseRightShift(val interface{}) BitwiseExpression {
|
||||
return bitwiseRightShift(l, val)
|
||||
}
|
||||
48
vendor/github.com/doug-martin/goqu/v9/exp/lock.go
generated
vendored
Normal file
48
vendor/github.com/doug-martin/goqu/v9/exp/lock.go
generated
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
package exp
|
||||
|
||||
type (
|
||||
LockStrength int
|
||||
WaitOption int
|
||||
Lock interface {
|
||||
Strength() LockStrength
|
||||
WaitOption() WaitOption
|
||||
Of() []IdentifierExpression
|
||||
}
|
||||
lock struct {
|
||||
strength LockStrength
|
||||
waitOption WaitOption
|
||||
of []IdentifierExpression
|
||||
}
|
||||
)
|
||||
|
||||
const (
|
||||
ForNolock LockStrength = iota
|
||||
ForUpdate
|
||||
ForNoKeyUpdate
|
||||
ForShare
|
||||
ForKeyShare
|
||||
|
||||
Wait WaitOption = iota
|
||||
NoWait
|
||||
SkipLocked
|
||||
)
|
||||
|
||||
func NewLock(strength LockStrength, option WaitOption, of ...IdentifierExpression) Lock {
|
||||
return lock{
|
||||
strength: strength,
|
||||
waitOption: option,
|
||||
of: of,
|
||||
}
|
||||
}
|
||||
|
||||
func (l lock) Strength() LockStrength {
|
||||
return l.strength
|
||||
}
|
||||
|
||||
func (l lock) WaitOption() WaitOption {
|
||||
return l.waitOption
|
||||
}
|
||||
|
||||
func (l lock) Of() []IdentifierExpression {
|
||||
return l.of
|
||||
}
|
||||
52
vendor/github.com/doug-martin/goqu/v9/exp/order.go
generated
vendored
Normal file
52
vendor/github.com/doug-martin/goqu/v9/exp/order.go
generated
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
package exp
|
||||
|
||||
type (
|
||||
orderedExpression struct {
|
||||
sortExpression Expression
|
||||
direction SortDirection
|
||||
nullSortType NullSortType
|
||||
}
|
||||
)
|
||||
|
||||
// used internally to create a new SORT_ASC OrderedExpression
|
||||
func asc(exp Expression) OrderedExpression {
|
||||
return NewOrderedExpression(exp, AscDir, NoNullsSortType)
|
||||
}
|
||||
|
||||
// used internally to create a new SORT_DESC OrderedExpression
|
||||
func desc(exp Expression) OrderedExpression {
|
||||
return NewOrderedExpression(exp, DescSortDir, NoNullsSortType)
|
||||
}
|
||||
|
||||
// used internally to create a new SORT_ASC OrderedExpression
|
||||
func NewOrderedExpression(exp Expression, direction SortDirection, sortType NullSortType) OrderedExpression {
|
||||
return orderedExpression{sortExpression: exp, direction: direction, nullSortType: sortType}
|
||||
}
|
||||
|
||||
func (oe orderedExpression) Clone() Expression {
|
||||
return NewOrderedExpression(oe.sortExpression, oe.direction, oe.nullSortType)
|
||||
}
|
||||
|
||||
func (oe orderedExpression) Expression() Expression {
|
||||
return oe
|
||||
}
|
||||
|
||||
func (oe orderedExpression) SortExpression() Expression {
|
||||
return oe.sortExpression
|
||||
}
|
||||
|
||||
func (oe orderedExpression) IsAsc() bool {
|
||||
return oe.direction == AscDir
|
||||
}
|
||||
|
||||
func (oe orderedExpression) NullSortType() NullSortType {
|
||||
return oe.nullSortType
|
||||
}
|
||||
|
||||
func (oe orderedExpression) NullsFirst() OrderedExpression {
|
||||
return NewOrderedExpression(oe.sortExpression, oe.direction, NullsFirstSortType)
|
||||
}
|
||||
|
||||
func (oe orderedExpression) NullsLast() OrderedExpression {
|
||||
return NewOrderedExpression(oe.sortExpression, oe.direction, NullsLastSortType)
|
||||
}
|
||||
61
vendor/github.com/doug-martin/goqu/v9/exp/range.go
generated
vendored
Normal file
61
vendor/github.com/doug-martin/goqu/v9/exp/range.go
generated
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
package exp
|
||||
|
||||
type (
|
||||
ranged struct {
|
||||
lhs Expression
|
||||
rhs RangeVal
|
||||
op RangeOperation
|
||||
}
|
||||
rangeVal struct {
|
||||
start interface{}
|
||||
end interface{}
|
||||
}
|
||||
)
|
||||
|
||||
// used internally to create an BETWEEN comparison RangeExpression
|
||||
func between(lhs Expression, rhs RangeVal) RangeExpression {
|
||||
return NewRangeExpression(BetweenOp, lhs, rhs)
|
||||
}
|
||||
|
||||
// used internally to create an NOT BETWEEN comparison RangeExpression
|
||||
func notBetween(lhs Expression, rhs RangeVal) RangeExpression {
|
||||
return NewRangeExpression(NotBetweenOp, lhs, rhs)
|
||||
}
|
||||
|
||||
func NewRangeExpression(op RangeOperation, lhs Expression, rhs RangeVal) RangeExpression {
|
||||
return ranged{op: op, lhs: lhs, rhs: rhs}
|
||||
}
|
||||
|
||||
func (r ranged) Clone() Expression {
|
||||
return NewRangeExpression(r.op, r.lhs.Clone(), r.rhs)
|
||||
}
|
||||
|
||||
func (r ranged) Expression() Expression {
|
||||
return r
|
||||
}
|
||||
|
||||
func (r ranged) RHS() RangeVal {
|
||||
return r.rhs
|
||||
}
|
||||
|
||||
func (r ranged) LHS() Expression {
|
||||
return r.lhs
|
||||
}
|
||||
|
||||
func (r ranged) Op() RangeOperation {
|
||||
return r.op
|
||||
}
|
||||
|
||||
// Creates a new Range to be used with a Between expression
|
||||
// exp.C("col").Between(exp.Range(1, 10))
|
||||
func NewRangeVal(start, end interface{}) RangeVal {
|
||||
return rangeVal{start: start, end: end}
|
||||
}
|
||||
|
||||
func (rv rangeVal) Start() interface{} {
|
||||
return rv.start
|
||||
}
|
||||
|
||||
func (rv rangeVal) End() interface{} {
|
||||
return rv.end
|
||||
}
|
||||
59
vendor/github.com/doug-martin/goqu/v9/exp/record.go
generated
vendored
Normal file
59
vendor/github.com/doug-martin/goqu/v9/exp/record.go
generated
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
package exp
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"sort"
|
||||
|
||||
"github.com/doug-martin/goqu/v9/internal/util"
|
||||
)
|
||||
|
||||
// Alternative to writing map[string]interface{}. Can be used for Inserts, Updates or Deletes
|
||||
type Record map[string]interface{}
|
||||
|
||||
func (r Record) Cols() []string {
|
||||
cols := make([]string, 0, len(r))
|
||||
for col := range r {
|
||||
cols = append(cols, col)
|
||||
}
|
||||
sort.Strings(cols)
|
||||
return cols
|
||||
}
|
||||
|
||||
func NewRecordFromStruct(i interface{}, forInsert, forUpdate bool) (r Record, err error) {
|
||||
value := reflect.ValueOf(i)
|
||||
if value.IsValid() {
|
||||
cm, err := util.GetColumnMap(value.Interface())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cols := cm.Cols()
|
||||
r = make(map[string]interface{}, len(cols))
|
||||
for _, col := range cols {
|
||||
f := cm[col]
|
||||
if !shouldSkipField(f, forInsert, forUpdate) {
|
||||
if ok, fieldVal := getFieldValue(value, f); ok {
|
||||
r[f.ColumnName] = fieldVal
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func shouldSkipField(f util.ColumnData, forInsert, forUpdate bool) bool {
|
||||
shouldSkipInsert := forInsert && !f.ShouldInsert
|
||||
shouldSkipUpdate := forUpdate && !f.ShouldUpdate
|
||||
return shouldSkipInsert || shouldSkipUpdate
|
||||
}
|
||||
|
||||
func getFieldValue(val reflect.Value, f util.ColumnData) (ok bool, fieldVal interface{}) {
|
||||
if v, isAvailable := util.SafeGetFieldByIndex(val, f.FieldIndex); !isAvailable {
|
||||
return false, nil
|
||||
} else if f.DefaultIfEmpty && util.IsEmptyValue(v) {
|
||||
return true, Default()
|
||||
} else if v.IsValid() {
|
||||
return true, v.Interface()
|
||||
} else {
|
||||
return true, reflect.Zero(f.GoType).Interface()
|
||||
}
|
||||
}
|
||||
379
vendor/github.com/doug-martin/goqu/v9/exp/select_clauses.go
generated
vendored
Normal file
379
vendor/github.com/doug-martin/goqu/v9/exp/select_clauses.go
generated
vendored
Normal file
@@ -0,0 +1,379 @@
|
||||
package exp
|
||||
|
||||
type (
|
||||
SelectClauses interface {
|
||||
HasSources() bool
|
||||
IsDefaultSelect() bool
|
||||
clone() *selectClauses
|
||||
|
||||
Select() ColumnListExpression
|
||||
SelectAppend(cl ColumnListExpression) SelectClauses
|
||||
SetSelect(cl ColumnListExpression) SelectClauses
|
||||
|
||||
Distinct() ColumnListExpression
|
||||
SetDistinct(cle ColumnListExpression) SelectClauses
|
||||
|
||||
From() ColumnListExpression
|
||||
SetFrom(cl ColumnListExpression) SelectClauses
|
||||
|
||||
HasAlias() bool
|
||||
Alias() IdentifierExpression
|
||||
SetAlias(ie IdentifierExpression) SelectClauses
|
||||
|
||||
Joins() JoinExpressions
|
||||
JoinsAppend(jc JoinExpression) SelectClauses
|
||||
|
||||
Where() ExpressionList
|
||||
ClearWhere() SelectClauses
|
||||
WhereAppend(expressions ...Expression) SelectClauses
|
||||
|
||||
Having() ExpressionList
|
||||
ClearHaving() SelectClauses
|
||||
HavingAppend(expressions ...Expression) SelectClauses
|
||||
|
||||
Order() ColumnListExpression
|
||||
HasOrder() bool
|
||||
ClearOrder() SelectClauses
|
||||
SetOrder(oes ...OrderedExpression) SelectClauses
|
||||
OrderAppend(...OrderedExpression) SelectClauses
|
||||
OrderPrepend(...OrderedExpression) SelectClauses
|
||||
|
||||
GroupBy() ColumnListExpression
|
||||
SetGroupBy(cl ColumnListExpression) SelectClauses
|
||||
GroupByAppend(cl ColumnListExpression) SelectClauses
|
||||
|
||||
Limit() interface{}
|
||||
HasLimit() bool
|
||||
ClearLimit() SelectClauses
|
||||
SetLimit(limit interface{}) SelectClauses
|
||||
|
||||
Offset() uint
|
||||
ClearOffset() SelectClauses
|
||||
SetOffset(offset uint) SelectClauses
|
||||
|
||||
Compounds() []CompoundExpression
|
||||
CompoundsAppend(ce CompoundExpression) SelectClauses
|
||||
|
||||
Lock() Lock
|
||||
SetLock(l Lock) SelectClauses
|
||||
|
||||
CommonTables() []CommonTableExpression
|
||||
CommonTablesAppend(cte CommonTableExpression) SelectClauses
|
||||
|
||||
Windows() []WindowExpression
|
||||
SetWindows(ws []WindowExpression) SelectClauses
|
||||
WindowsAppend(ws ...WindowExpression) SelectClauses
|
||||
ClearWindows() SelectClauses
|
||||
}
|
||||
selectClauses struct {
|
||||
commonTables []CommonTableExpression
|
||||
selectColumns ColumnListExpression
|
||||
distinct ColumnListExpression
|
||||
from ColumnListExpression
|
||||
joins JoinExpressions
|
||||
where ExpressionList
|
||||
alias IdentifierExpression
|
||||
groupBy ColumnListExpression
|
||||
having ExpressionList
|
||||
order ColumnListExpression
|
||||
limit interface{}
|
||||
offset uint
|
||||
compounds []CompoundExpression
|
||||
lock Lock
|
||||
windows []WindowExpression
|
||||
}
|
||||
)
|
||||
|
||||
func NewSelectClauses() SelectClauses {
|
||||
return &selectClauses{
|
||||
selectColumns: NewColumnListExpression(Star()),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *selectClauses) HasSources() bool {
|
||||
return c.from != nil && len(c.from.Columns()) > 0
|
||||
}
|
||||
|
||||
func (c *selectClauses) IsDefaultSelect() bool {
|
||||
ret := false
|
||||
if c.selectColumns != nil {
|
||||
selects := c.selectColumns.Columns()
|
||||
if len(selects) == 1 {
|
||||
if l, ok := selects[0].(LiteralExpression); ok && l.Literal() == "*" {
|
||||
ret = true
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (c *selectClauses) clone() *selectClauses {
|
||||
return &selectClauses{
|
||||
commonTables: c.commonTables,
|
||||
selectColumns: c.selectColumns,
|
||||
distinct: c.distinct,
|
||||
from: c.from,
|
||||
joins: c.joins[0:len(c.joins):len(c.joins)],
|
||||
where: c.where,
|
||||
alias: c.alias,
|
||||
groupBy: c.groupBy,
|
||||
having: c.having,
|
||||
order: c.order,
|
||||
limit: c.limit,
|
||||
offset: c.offset,
|
||||
compounds: c.compounds,
|
||||
lock: c.lock,
|
||||
windows: c.windows,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *selectClauses) CommonTables() []CommonTableExpression {
|
||||
return c.commonTables
|
||||
}
|
||||
|
||||
func (c *selectClauses) CommonTablesAppend(cte CommonTableExpression) SelectClauses {
|
||||
ret := c.clone()
|
||||
ret.commonTables = append(ret.commonTables, cte)
|
||||
return ret
|
||||
}
|
||||
|
||||
func (c *selectClauses) Select() ColumnListExpression {
|
||||
return c.selectColumns
|
||||
}
|
||||
|
||||
func (c *selectClauses) SelectAppend(cl ColumnListExpression) SelectClauses {
|
||||
ret := c.clone()
|
||||
ret.selectColumns = ret.selectColumns.Append(cl.Columns()...)
|
||||
return ret
|
||||
}
|
||||
|
||||
func (c *selectClauses) SetSelect(cl ColumnListExpression) SelectClauses {
|
||||
ret := c.clone()
|
||||
ret.selectColumns = cl
|
||||
return ret
|
||||
}
|
||||
|
||||
func (c *selectClauses) Distinct() ColumnListExpression {
|
||||
return c.distinct
|
||||
}
|
||||
|
||||
func (c *selectClauses) SetDistinct(cle ColumnListExpression) SelectClauses {
|
||||
ret := c.clone()
|
||||
ret.distinct = cle
|
||||
return ret
|
||||
}
|
||||
|
||||
func (c *selectClauses) From() ColumnListExpression {
|
||||
return c.from
|
||||
}
|
||||
|
||||
func (c *selectClauses) SetFrom(cl ColumnListExpression) SelectClauses {
|
||||
ret := c.clone()
|
||||
ret.from = cl
|
||||
return ret
|
||||
}
|
||||
|
||||
func (c *selectClauses) HasAlias() bool {
|
||||
return c.alias != nil
|
||||
}
|
||||
|
||||
func (c *selectClauses) Alias() IdentifierExpression {
|
||||
return c.alias
|
||||
}
|
||||
|
||||
func (c *selectClauses) SetAlias(ie IdentifierExpression) SelectClauses {
|
||||
ret := c.clone()
|
||||
ret.alias = ie
|
||||
return ret
|
||||
}
|
||||
|
||||
func (c *selectClauses) Joins() JoinExpressions {
|
||||
return c.joins
|
||||
}
|
||||
|
||||
func (c *selectClauses) JoinsAppend(jc JoinExpression) SelectClauses {
|
||||
ret := c.clone()
|
||||
ret.joins = append(ret.joins, jc)
|
||||
return ret
|
||||
}
|
||||
|
||||
func (c *selectClauses) Where() ExpressionList {
|
||||
return c.where
|
||||
}
|
||||
|
||||
func (c *selectClauses) ClearWhere() SelectClauses {
|
||||
ret := c.clone()
|
||||
ret.where = nil
|
||||
return ret
|
||||
}
|
||||
|
||||
func (c *selectClauses) WhereAppend(expressions ...Expression) SelectClauses {
|
||||
if len(expressions) == 0 {
|
||||
return c
|
||||
}
|
||||
ret := c.clone()
|
||||
if ret.where == nil {
|
||||
ret.where = NewExpressionList(AndType, expressions...)
|
||||
} else {
|
||||
ret.where = ret.where.Append(expressions...)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (c *selectClauses) Having() ExpressionList {
|
||||
return c.having
|
||||
}
|
||||
|
||||
func (c *selectClauses) ClearHaving() SelectClauses {
|
||||
ret := c.clone()
|
||||
ret.having = nil
|
||||
return ret
|
||||
}
|
||||
|
||||
func (c *selectClauses) HavingAppend(expressions ...Expression) SelectClauses {
|
||||
if len(expressions) == 0 {
|
||||
return c
|
||||
}
|
||||
ret := c.clone()
|
||||
if ret.having == nil {
|
||||
ret.having = NewExpressionList(AndType, expressions...)
|
||||
} else {
|
||||
ret.having = ret.having.Append(expressions...)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (c *selectClauses) Lock() Lock {
|
||||
return c.lock
|
||||
}
|
||||
|
||||
func (c *selectClauses) SetLock(l Lock) SelectClauses {
|
||||
ret := c.clone()
|
||||
ret.lock = l
|
||||
return ret
|
||||
}
|
||||
|
||||
func (c *selectClauses) Order() ColumnListExpression {
|
||||
return c.order
|
||||
}
|
||||
|
||||
func (c *selectClauses) HasOrder() bool {
|
||||
return c.order != nil
|
||||
}
|
||||
|
||||
func (c *selectClauses) ClearOrder() SelectClauses {
|
||||
ret := c.clone()
|
||||
ret.order = nil
|
||||
return ret
|
||||
}
|
||||
|
||||
func (c *selectClauses) SetOrder(oes ...OrderedExpression) SelectClauses {
|
||||
ret := c.clone()
|
||||
ret.order = NewOrderedColumnList(oes...)
|
||||
return ret
|
||||
}
|
||||
|
||||
func (c *selectClauses) OrderAppend(oes ...OrderedExpression) SelectClauses {
|
||||
if c.order == nil {
|
||||
return c.SetOrder(oes...)
|
||||
}
|
||||
ret := c.clone()
|
||||
ret.order = ret.order.Append(NewOrderedColumnList(oes...).Columns()...)
|
||||
return ret
|
||||
}
|
||||
|
||||
func (c *selectClauses) OrderPrepend(oes ...OrderedExpression) SelectClauses {
|
||||
if c.order == nil {
|
||||
return c.SetOrder(oes...)
|
||||
}
|
||||
ret := c.clone()
|
||||
ret.order = NewOrderedColumnList(oes...).Append(ret.order.Columns()...)
|
||||
return ret
|
||||
}
|
||||
|
||||
func (c *selectClauses) GroupBy() ColumnListExpression {
|
||||
return c.groupBy
|
||||
}
|
||||
|
||||
func (c *selectClauses) GroupByAppend(cl ColumnListExpression) SelectClauses {
|
||||
if c.groupBy == nil {
|
||||
return c.SetGroupBy(cl)
|
||||
}
|
||||
ret := c.clone()
|
||||
ret.groupBy = ret.groupBy.Append(cl.Columns()...)
|
||||
return ret
|
||||
}
|
||||
|
||||
func (c *selectClauses) SetGroupBy(cl ColumnListExpression) SelectClauses {
|
||||
ret := c.clone()
|
||||
ret.groupBy = cl
|
||||
return ret
|
||||
}
|
||||
|
||||
func (c *selectClauses) Limit() interface{} {
|
||||
return c.limit
|
||||
}
|
||||
|
||||
func (c *selectClauses) HasLimit() bool {
|
||||
return c.limit != nil
|
||||
}
|
||||
|
||||
func (c *selectClauses) ClearLimit() SelectClauses {
|
||||
ret := c.clone()
|
||||
ret.limit = nil
|
||||
return ret
|
||||
}
|
||||
|
||||
func (c *selectClauses) SetLimit(limit interface{}) SelectClauses {
|
||||
ret := c.clone()
|
||||
ret.limit = limit
|
||||
return ret
|
||||
}
|
||||
|
||||
func (c *selectClauses) Offset() uint {
|
||||
return c.offset
|
||||
}
|
||||
|
||||
func (c *selectClauses) ClearOffset() SelectClauses {
|
||||
ret := c.clone()
|
||||
ret.offset = 0
|
||||
return ret
|
||||
}
|
||||
|
||||
func (c *selectClauses) SetOffset(offset uint) SelectClauses {
|
||||
ret := c.clone()
|
||||
ret.offset = offset
|
||||
return ret
|
||||
}
|
||||
|
||||
func (c *selectClauses) Compounds() []CompoundExpression {
|
||||
return c.compounds
|
||||
}
|
||||
|
||||
func (c *selectClauses) CompoundsAppend(ce CompoundExpression) SelectClauses {
|
||||
ret := c.clone()
|
||||
ret.compounds = append(ret.compounds, ce)
|
||||
return ret
|
||||
}
|
||||
|
||||
func (c *selectClauses) Windows() []WindowExpression {
|
||||
return c.windows
|
||||
}
|
||||
|
||||
func (c *selectClauses) SetWindows(ws []WindowExpression) SelectClauses {
|
||||
ret := c.clone()
|
||||
ret.windows = ws
|
||||
return ret
|
||||
}
|
||||
|
||||
func (c *selectClauses) WindowsAppend(ws ...WindowExpression) SelectClauses {
|
||||
ret := c.clone()
|
||||
ret.windows = append(ret.windows, ws...)
|
||||
return ret
|
||||
}
|
||||
|
||||
func (c *selectClauses) ClearWindows() SelectClauses {
|
||||
ret := c.clone()
|
||||
ret.windows = nil
|
||||
return ret
|
||||
}
|
||||
11
vendor/github.com/doug-martin/goqu/v9/exp/truncate.go
generated
vendored
Normal file
11
vendor/github.com/doug-martin/goqu/v9/exp/truncate.go
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
package exp
|
||||
|
||||
// Options to use when generating a TRUNCATE statement
|
||||
type TruncateOptions struct {
|
||||
// Set to true to add CASCADE to the TRUNCATE statement
|
||||
Cascade bool
|
||||
// Set to true to add RESTRICT to the TRUNCATE statement
|
||||
Restrict bool
|
||||
// Set to true to specify IDENTITY options, (e.g. RESTART, CONTINUE) to the TRUNCATE statement
|
||||
Identity string
|
||||
}
|
||||
50
vendor/github.com/doug-martin/goqu/v9/exp/truncate_clauses.go
generated
vendored
Normal file
50
vendor/github.com/doug-martin/goqu/v9/exp/truncate_clauses.go
generated
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
package exp
|
||||
|
||||
type (
|
||||
TruncateClauses interface {
|
||||
HasTable() bool
|
||||
clone() *truncateClauses
|
||||
|
||||
Table() ColumnListExpression
|
||||
SetTable(tables ColumnListExpression) TruncateClauses
|
||||
|
||||
Options() TruncateOptions
|
||||
SetOptions(opts TruncateOptions) TruncateClauses
|
||||
}
|
||||
truncateClauses struct {
|
||||
tables ColumnListExpression
|
||||
options TruncateOptions
|
||||
}
|
||||
)
|
||||
|
||||
func NewTruncateClauses() TruncateClauses {
|
||||
return &truncateClauses{}
|
||||
}
|
||||
|
||||
func (tc *truncateClauses) HasTable() bool {
|
||||
return tc.tables != nil
|
||||
}
|
||||
|
||||
func (tc *truncateClauses) clone() *truncateClauses {
|
||||
return &truncateClauses{
|
||||
tables: tc.tables,
|
||||
}
|
||||
}
|
||||
|
||||
func (tc *truncateClauses) Table() ColumnListExpression {
|
||||
return tc.tables
|
||||
}
|
||||
func (tc *truncateClauses) SetTable(tables ColumnListExpression) TruncateClauses {
|
||||
ret := tc.clone()
|
||||
ret.tables = tables
|
||||
return ret
|
||||
}
|
||||
|
||||
func (tc *truncateClauses) Options() TruncateOptions {
|
||||
return tc.options
|
||||
}
|
||||
func (tc *truncateClauses) SetOptions(opts TruncateOptions) TruncateClauses {
|
||||
ret := tc.clone()
|
||||
ret.options = opts
|
||||
return ret
|
||||
}
|
||||
69
vendor/github.com/doug-martin/goqu/v9/exp/update.go
generated
vendored
Normal file
69
vendor/github.com/doug-martin/goqu/v9/exp/update.go
generated
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
package exp
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"sort"
|
||||
|
||||
"github.com/doug-martin/goqu/v9/internal/errors"
|
||||
"github.com/doug-martin/goqu/v9/internal/util"
|
||||
)
|
||||
|
||||
type (
|
||||
update struct {
|
||||
col IdentifierExpression
|
||||
val interface{}
|
||||
}
|
||||
)
|
||||
|
||||
func set(col IdentifierExpression, val interface{}) UpdateExpression {
|
||||
return update{col: col, val: val}
|
||||
}
|
||||
|
||||
func NewUpdateExpressions(update interface{}) (updates []UpdateExpression, err error) {
|
||||
if u, ok := update.(UpdateExpression); ok {
|
||||
updates = append(updates, u)
|
||||
return updates, nil
|
||||
}
|
||||
updateValue := reflect.Indirect(reflect.ValueOf(update))
|
||||
switch updateValue.Kind() {
|
||||
case reflect.Map:
|
||||
keys := util.ValueSlice(updateValue.MapKeys())
|
||||
sort.Sort(keys)
|
||||
for _, key := range keys {
|
||||
updates = append(updates, ParseIdentifier(key.String()).Set(updateValue.MapIndex(key).Interface()))
|
||||
}
|
||||
case reflect.Struct:
|
||||
return getUpdateExpressionsStruct(updateValue)
|
||||
default:
|
||||
return nil, errors.New("unsupported update interface type %+v", updateValue.Type())
|
||||
}
|
||||
return updates, nil
|
||||
}
|
||||
|
||||
func getUpdateExpressionsStruct(value reflect.Value) (updates []UpdateExpression, err error) {
|
||||
r, err := NewRecordFromStruct(value.Interface(), false, true)
|
||||
if err != nil {
|
||||
return updates, err
|
||||
}
|
||||
cols := r.Cols()
|
||||
for _, col := range cols {
|
||||
updates = append(updates, ParseIdentifier(col).Set(r[col]))
|
||||
}
|
||||
return updates, nil
|
||||
}
|
||||
|
||||
func (u update) Expression() Expression {
|
||||
return u
|
||||
}
|
||||
|
||||
func (u update) Clone() Expression {
|
||||
return update{col: u.col.Clone().(IdentifierExpression), val: u.val}
|
||||
}
|
||||
|
||||
func (u update) Col() IdentifierExpression {
|
||||
return u.col
|
||||
}
|
||||
|
||||
func (u update) Val() interface{} {
|
||||
return u.val
|
||||
}
|
||||
216
vendor/github.com/doug-martin/goqu/v9/exp/update_clauses.go
generated
vendored
Normal file
216
vendor/github.com/doug-martin/goqu/v9/exp/update_clauses.go
generated
vendored
Normal file
@@ -0,0 +1,216 @@
|
||||
package exp
|
||||
|
||||
type (
|
||||
UpdateClauses interface {
|
||||
HasTable() bool
|
||||
clone() *updateClauses
|
||||
|
||||
CommonTables() []CommonTableExpression
|
||||
CommonTablesAppend(cte CommonTableExpression) UpdateClauses
|
||||
|
||||
Table() Expression
|
||||
SetTable(table Expression) UpdateClauses
|
||||
|
||||
SetValues() interface{}
|
||||
HasSetValues() bool
|
||||
SetSetValues(values interface{}) UpdateClauses
|
||||
|
||||
From() ColumnListExpression
|
||||
HasFrom() bool
|
||||
SetFrom(tables ColumnListExpression) UpdateClauses
|
||||
|
||||
Where() ExpressionList
|
||||
ClearWhere() UpdateClauses
|
||||
WhereAppend(expressions ...Expression) UpdateClauses
|
||||
|
||||
Order() ColumnListExpression
|
||||
HasOrder() bool
|
||||
ClearOrder() UpdateClauses
|
||||
SetOrder(oes ...OrderedExpression) UpdateClauses
|
||||
OrderAppend(...OrderedExpression) UpdateClauses
|
||||
OrderPrepend(...OrderedExpression) UpdateClauses
|
||||
|
||||
Limit() interface{}
|
||||
HasLimit() bool
|
||||
ClearLimit() UpdateClauses
|
||||
SetLimit(limit interface{}) UpdateClauses
|
||||
|
||||
Returning() ColumnListExpression
|
||||
HasReturning() bool
|
||||
SetReturning(cl ColumnListExpression) UpdateClauses
|
||||
}
|
||||
updateClauses struct {
|
||||
commonTables []CommonTableExpression
|
||||
table Expression
|
||||
setValues interface{}
|
||||
from ColumnListExpression
|
||||
where ExpressionList
|
||||
order ColumnListExpression
|
||||
limit interface{}
|
||||
returning ColumnListExpression
|
||||
}
|
||||
)
|
||||
|
||||
func NewUpdateClauses() UpdateClauses {
|
||||
return &updateClauses{}
|
||||
}
|
||||
|
||||
func (uc *updateClauses) HasTable() bool {
|
||||
return uc.table != nil
|
||||
}
|
||||
|
||||
func (uc *updateClauses) clone() *updateClauses {
|
||||
return &updateClauses{
|
||||
commonTables: uc.commonTables,
|
||||
table: uc.table,
|
||||
setValues: uc.setValues,
|
||||
from: uc.from,
|
||||
where: uc.where,
|
||||
order: uc.order,
|
||||
limit: uc.limit,
|
||||
returning: uc.returning,
|
||||
}
|
||||
}
|
||||
|
||||
func (uc *updateClauses) CommonTables() []CommonTableExpression {
|
||||
return uc.commonTables
|
||||
}
|
||||
|
||||
func (uc *updateClauses) CommonTablesAppend(cte CommonTableExpression) UpdateClauses {
|
||||
ret := uc.clone()
|
||||
ret.commonTables = append(ret.commonTables, cte)
|
||||
return ret
|
||||
}
|
||||
|
||||
func (uc *updateClauses) Table() Expression {
|
||||
return uc.table
|
||||
}
|
||||
|
||||
func (uc *updateClauses) SetTable(table Expression) UpdateClauses {
|
||||
ret := uc.clone()
|
||||
ret.table = table
|
||||
return ret
|
||||
}
|
||||
|
||||
func (uc *updateClauses) SetValues() interface{} {
|
||||
return uc.setValues
|
||||
}
|
||||
|
||||
func (uc *updateClauses) HasSetValues() bool {
|
||||
return uc.setValues != nil
|
||||
}
|
||||
|
||||
func (uc *updateClauses) SetSetValues(values interface{}) UpdateClauses {
|
||||
ret := uc.clone()
|
||||
ret.setValues = values
|
||||
return ret
|
||||
}
|
||||
|
||||
func (uc *updateClauses) From() ColumnListExpression {
|
||||
return uc.from
|
||||
}
|
||||
|
||||
func (uc *updateClauses) HasFrom() bool {
|
||||
return uc.from != nil && !uc.from.IsEmpty()
|
||||
}
|
||||
|
||||
func (uc *updateClauses) SetFrom(from ColumnListExpression) UpdateClauses {
|
||||
ret := uc.clone()
|
||||
ret.from = from
|
||||
return ret
|
||||
}
|
||||
|
||||
func (uc *updateClauses) Where() ExpressionList {
|
||||
return uc.where
|
||||
}
|
||||
|
||||
func (uc *updateClauses) ClearWhere() UpdateClauses {
|
||||
ret := uc.clone()
|
||||
ret.where = nil
|
||||
return ret
|
||||
}
|
||||
|
||||
func (uc *updateClauses) WhereAppend(expressions ...Expression) UpdateClauses {
|
||||
if len(expressions) == 0 {
|
||||
return uc
|
||||
}
|
||||
ret := uc.clone()
|
||||
if ret.where == nil {
|
||||
ret.where = NewExpressionList(AndType, expressions...)
|
||||
} else {
|
||||
ret.where = ret.where.Append(expressions...)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (uc *updateClauses) Order() ColumnListExpression {
|
||||
return uc.order
|
||||
}
|
||||
|
||||
func (uc *updateClauses) HasOrder() bool {
|
||||
return uc.order != nil
|
||||
}
|
||||
|
||||
func (uc *updateClauses) ClearOrder() UpdateClauses {
|
||||
ret := uc.clone()
|
||||
ret.order = nil
|
||||
return ret
|
||||
}
|
||||
|
||||
func (uc *updateClauses) SetOrder(oes ...OrderedExpression) UpdateClauses {
|
||||
ret := uc.clone()
|
||||
ret.order = NewOrderedColumnList(oes...)
|
||||
return ret
|
||||
}
|
||||
|
||||
func (uc *updateClauses) OrderAppend(oes ...OrderedExpression) UpdateClauses {
|
||||
if uc.order == nil {
|
||||
return uc.SetOrder(oes...)
|
||||
}
|
||||
ret := uc.clone()
|
||||
ret.order = ret.order.Append(NewOrderedColumnList(oes...).Columns()...)
|
||||
return ret
|
||||
}
|
||||
|
||||
func (uc *updateClauses) OrderPrepend(oes ...OrderedExpression) UpdateClauses {
|
||||
if uc.order == nil {
|
||||
return uc.SetOrder(oes...)
|
||||
}
|
||||
ret := uc.clone()
|
||||
ret.order = NewOrderedColumnList(oes...).Append(ret.order.Columns()...)
|
||||
return ret
|
||||
}
|
||||
|
||||
func (uc *updateClauses) Limit() interface{} {
|
||||
return uc.limit
|
||||
}
|
||||
|
||||
func (uc *updateClauses) HasLimit() bool {
|
||||
return uc.limit != nil
|
||||
}
|
||||
|
||||
func (uc *updateClauses) ClearLimit() UpdateClauses {
|
||||
ret := uc.clone()
|
||||
ret.limit = nil
|
||||
return ret
|
||||
}
|
||||
|
||||
func (uc *updateClauses) SetLimit(limit interface{}) UpdateClauses {
|
||||
ret := uc.clone()
|
||||
ret.limit = limit
|
||||
return ret
|
||||
}
|
||||
|
||||
func (uc *updateClauses) Returning() ColumnListExpression {
|
||||
return uc.returning
|
||||
}
|
||||
|
||||
func (uc *updateClauses) HasReturning() bool {
|
||||
return uc.returning != nil && !uc.returning.IsEmpty()
|
||||
}
|
||||
|
||||
func (uc *updateClauses) SetReturning(cl ColumnListExpression) UpdateClauses {
|
||||
ret := uc.clone()
|
||||
ret.returning = cl
|
||||
return ret
|
||||
}
|
||||
90
vendor/github.com/doug-martin/goqu/v9/exp/window.go
generated
vendored
Normal file
90
vendor/github.com/doug-martin/goqu/v9/exp/window.go
generated
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
package exp
|
||||
|
||||
type sqlWindowExpression struct {
|
||||
name IdentifierExpression
|
||||
parent IdentifierExpression
|
||||
partitionCols ColumnListExpression
|
||||
orderCols ColumnListExpression
|
||||
}
|
||||
|
||||
func NewWindowExpression(window, parent IdentifierExpression, partitionCols, orderCols ColumnListExpression) WindowExpression {
|
||||
if partitionCols == nil {
|
||||
partitionCols = NewColumnListExpression()
|
||||
}
|
||||
if orderCols == nil {
|
||||
orderCols = NewColumnListExpression()
|
||||
}
|
||||
return sqlWindowExpression{
|
||||
name: window,
|
||||
parent: parent,
|
||||
partitionCols: partitionCols,
|
||||
orderCols: orderCols,
|
||||
}
|
||||
}
|
||||
|
||||
func (we sqlWindowExpression) clone() sqlWindowExpression {
|
||||
return sqlWindowExpression{
|
||||
name: we.name,
|
||||
parent: we.parent,
|
||||
partitionCols: we.partitionCols.Clone().(ColumnListExpression),
|
||||
orderCols: we.orderCols.Clone().(ColumnListExpression),
|
||||
}
|
||||
}
|
||||
|
||||
func (we sqlWindowExpression) Clone() Expression {
|
||||
return we.clone()
|
||||
}
|
||||
|
||||
func (we sqlWindowExpression) Expression() Expression {
|
||||
return we
|
||||
}
|
||||
|
||||
func (we sqlWindowExpression) Name() IdentifierExpression {
|
||||
return we.name
|
||||
}
|
||||
|
||||
func (we sqlWindowExpression) HasName() bool {
|
||||
return we.name != nil
|
||||
}
|
||||
|
||||
func (we sqlWindowExpression) Parent() IdentifierExpression {
|
||||
return we.parent
|
||||
}
|
||||
|
||||
func (we sqlWindowExpression) HasParent() bool {
|
||||
return we.parent != nil
|
||||
}
|
||||
|
||||
func (we sqlWindowExpression) PartitionCols() ColumnListExpression {
|
||||
return we.partitionCols
|
||||
}
|
||||
|
||||
func (we sqlWindowExpression) HasPartitionBy() bool {
|
||||
return we.partitionCols != nil && !we.partitionCols.IsEmpty()
|
||||
}
|
||||
|
||||
func (we sqlWindowExpression) OrderCols() ColumnListExpression {
|
||||
return we.orderCols
|
||||
}
|
||||
|
||||
func (we sqlWindowExpression) HasOrder() bool {
|
||||
return we.orderCols != nil && !we.orderCols.IsEmpty()
|
||||
}
|
||||
|
||||
func (we sqlWindowExpression) PartitionBy(cols ...interface{}) WindowExpression {
|
||||
ret := we.clone()
|
||||
ret.partitionCols = NewColumnListExpression(cols...)
|
||||
return ret
|
||||
}
|
||||
|
||||
func (we sqlWindowExpression) OrderBy(cols ...interface{}) WindowExpression {
|
||||
ret := we.clone()
|
||||
ret.orderCols = NewColumnListExpression(cols...)
|
||||
return ret
|
||||
}
|
||||
|
||||
func (we sqlWindowExpression) Inherit(parent string) WindowExpression {
|
||||
ret := we.clone()
|
||||
ret.parent = ParseIdentifier(parent)
|
||||
return ret
|
||||
}
|
||||
124
vendor/github.com/doug-martin/goqu/v9/exp/window_func.go
generated
vendored
Normal file
124
vendor/github.com/doug-martin/goqu/v9/exp/window_func.go
generated
vendored
Normal file
@@ -0,0 +1,124 @@
|
||||
package exp
|
||||
|
||||
type sqlWindowFunctionExpression struct {
|
||||
fn SQLFunctionExpression
|
||||
windowName IdentifierExpression
|
||||
window WindowExpression
|
||||
}
|
||||
|
||||
func NewSQLWindowFunctionExpression(
|
||||
fn SQLFunctionExpression,
|
||||
windowName IdentifierExpression,
|
||||
window WindowExpression) SQLWindowFunctionExpression {
|
||||
return sqlWindowFunctionExpression{
|
||||
fn: fn,
|
||||
windowName: windowName,
|
||||
window: window,
|
||||
}
|
||||
}
|
||||
|
||||
func (swfe sqlWindowFunctionExpression) clone() sqlWindowFunctionExpression {
|
||||
return sqlWindowFunctionExpression{
|
||||
fn: swfe.fn.Clone().(SQLFunctionExpression),
|
||||
windowName: swfe.windowName,
|
||||
window: swfe.window,
|
||||
}
|
||||
}
|
||||
|
||||
func (swfe sqlWindowFunctionExpression) Clone() Expression {
|
||||
return swfe.clone()
|
||||
}
|
||||
|
||||
func (swfe sqlWindowFunctionExpression) Expression() Expression {
|
||||
return swfe
|
||||
}
|
||||
|
||||
func (swfe sqlWindowFunctionExpression) As(val interface{}) AliasedExpression {
|
||||
return NewAliasExpression(swfe, val)
|
||||
}
|
||||
func (swfe sqlWindowFunctionExpression) Eq(val interface{}) BooleanExpression { return eq(swfe, val) }
|
||||
func (swfe sqlWindowFunctionExpression) Neq(val interface{}) BooleanExpression { return neq(swfe, val) }
|
||||
func (swfe sqlWindowFunctionExpression) Gt(val interface{}) BooleanExpression { return gt(swfe, val) }
|
||||
func (swfe sqlWindowFunctionExpression) Gte(val interface{}) BooleanExpression { return gte(swfe, val) }
|
||||
func (swfe sqlWindowFunctionExpression) Lt(val interface{}) BooleanExpression { return lt(swfe, val) }
|
||||
func (swfe sqlWindowFunctionExpression) Lte(val interface{}) BooleanExpression { return lte(swfe, val) }
|
||||
func (swfe sqlWindowFunctionExpression) Between(val RangeVal) RangeExpression {
|
||||
return between(swfe, val)
|
||||
}
|
||||
|
||||
func (swfe sqlWindowFunctionExpression) NotBetween(val RangeVal) RangeExpression {
|
||||
return notBetween(swfe, val)
|
||||
}
|
||||
|
||||
func (swfe sqlWindowFunctionExpression) Like(val interface{}) BooleanExpression {
|
||||
return like(swfe, val)
|
||||
}
|
||||
|
||||
func (swfe sqlWindowFunctionExpression) NotLike(val interface{}) BooleanExpression {
|
||||
return notLike(swfe, val)
|
||||
}
|
||||
|
||||
func (swfe sqlWindowFunctionExpression) ILike(val interface{}) BooleanExpression {
|
||||
return iLike(swfe, val)
|
||||
}
|
||||
|
||||
func (swfe sqlWindowFunctionExpression) NotILike(val interface{}) BooleanExpression {
|
||||
return notILike(swfe, val)
|
||||
}
|
||||
|
||||
func (swfe sqlWindowFunctionExpression) RegexpLike(val interface{}) BooleanExpression {
|
||||
return regexpLike(swfe, val)
|
||||
}
|
||||
|
||||
func (swfe sqlWindowFunctionExpression) RegexpNotLike(val interface{}) BooleanExpression {
|
||||
return regexpNotLike(swfe, val)
|
||||
}
|
||||
|
||||
func (swfe sqlWindowFunctionExpression) RegexpILike(val interface{}) BooleanExpression {
|
||||
return regexpILike(swfe, val)
|
||||
}
|
||||
|
||||
func (swfe sqlWindowFunctionExpression) RegexpNotILike(val interface{}) BooleanExpression {
|
||||
return regexpNotILike(swfe, val)
|
||||
}
|
||||
|
||||
func (swfe sqlWindowFunctionExpression) In(vals ...interface{}) BooleanExpression {
|
||||
return in(swfe, vals...)
|
||||
}
|
||||
|
||||
func (swfe sqlWindowFunctionExpression) NotIn(vals ...interface{}) BooleanExpression {
|
||||
return notIn(swfe, vals...)
|
||||
}
|
||||
func (swfe sqlWindowFunctionExpression) Is(val interface{}) BooleanExpression { return is(swfe, val) }
|
||||
func (swfe sqlWindowFunctionExpression) IsNot(val interface{}) BooleanExpression {
|
||||
return isNot(swfe, val)
|
||||
}
|
||||
func (swfe sqlWindowFunctionExpression) IsNull() BooleanExpression { return is(swfe, nil) }
|
||||
func (swfe sqlWindowFunctionExpression) IsNotNull() BooleanExpression { return isNot(swfe, nil) }
|
||||
func (swfe sqlWindowFunctionExpression) IsTrue() BooleanExpression { return is(swfe, true) }
|
||||
func (swfe sqlWindowFunctionExpression) IsNotTrue() BooleanExpression { return isNot(swfe, true) }
|
||||
func (swfe sqlWindowFunctionExpression) IsFalse() BooleanExpression { return is(swfe, false) }
|
||||
func (swfe sqlWindowFunctionExpression) IsNotFalse() BooleanExpression { return isNot(swfe, false) }
|
||||
|
||||
func (swfe sqlWindowFunctionExpression) Asc() OrderedExpression { return asc(swfe) }
|
||||
func (swfe sqlWindowFunctionExpression) Desc() OrderedExpression { return desc(swfe) }
|
||||
|
||||
func (swfe sqlWindowFunctionExpression) Func() SQLFunctionExpression {
|
||||
return swfe.fn
|
||||
}
|
||||
|
||||
func (swfe sqlWindowFunctionExpression) Window() WindowExpression {
|
||||
return swfe.window
|
||||
}
|
||||
|
||||
func (swfe sqlWindowFunctionExpression) WindowName() IdentifierExpression {
|
||||
return swfe.windowName
|
||||
}
|
||||
|
||||
func (swfe sqlWindowFunctionExpression) HasWindow() bool {
|
||||
return swfe.window != nil
|
||||
}
|
||||
|
||||
func (swfe sqlWindowFunctionExpression) HasWindowName() bool {
|
||||
return swfe.windowName != nil
|
||||
}
|
||||
303
vendor/github.com/doug-martin/goqu/v9/expressions.go
generated
vendored
Normal file
303
vendor/github.com/doug-martin/goqu/v9/expressions.go
generated
vendored
Normal file
@@ -0,0 +1,303 @@
|
||||
package goqu
|
||||
|
||||
import (
|
||||
"github.com/doug-martin/goqu/v9/exp"
|
||||
)
|
||||
|
||||
type (
|
||||
Expression = exp.Expression
|
||||
Ex = exp.Ex
|
||||
ExOr = exp.ExOr
|
||||
Op = exp.Op
|
||||
Record = exp.Record
|
||||
Vals = exp.Vals
|
||||
// Options to use when generating a TRUNCATE statement
|
||||
TruncateOptions = exp.TruncateOptions
|
||||
)
|
||||
|
||||
// emptyWindow is an empty WINDOW clause without name
|
||||
var emptyWindow = exp.NewWindowExpression(nil, nil, nil, nil)
|
||||
|
||||
const (
|
||||
Wait = exp.Wait
|
||||
NoWait = exp.NoWait
|
||||
SkipLocked = exp.SkipLocked
|
||||
)
|
||||
|
||||
// Creates a new Casted expression
|
||||
// Cast(I("a"), "NUMERIC") -> CAST("a" AS NUMERIC)
|
||||
func Cast(e exp.Expression, t string) exp.CastExpression {
|
||||
return exp.NewCastExpression(e, t)
|
||||
}
|
||||
|
||||
// Creates a conflict struct to be passed to InsertConflict to ignore constraint errors
|
||||
// InsertConflict(DoNothing(),...) -> INSERT INTO ... ON CONFLICT DO NOTHING
|
||||
func DoNothing() exp.ConflictExpression {
|
||||
return exp.NewDoNothingConflictExpression()
|
||||
}
|
||||
|
||||
// Creates a ConflictUpdate struct to be passed to InsertConflict
|
||||
// Represents a ON CONFLICT DO UPDATE portion of an INSERT statement (ON DUPLICATE KEY UPDATE for mysql)
|
||||
//
|
||||
// InsertConflict(DoUpdate("target_column", update),...) ->
|
||||
// INSERT INTO ... ON CONFLICT DO UPDATE SET a=b
|
||||
// InsertConflict(DoUpdate("target_column", update).Where(Ex{"a": 1},...) ->
|
||||
// INSERT INTO ... ON CONFLICT DO UPDATE SET a=b WHERE a=1
|
||||
func DoUpdate(target string, update interface{}) exp.ConflictUpdateExpression {
|
||||
return exp.NewDoUpdateConflictExpression(target, update)
|
||||
}
|
||||
|
||||
// A list of expressions that should be ORed together
|
||||
// Or(I("a").Eq(10), I("b").Eq(11)) //(("a" = 10) OR ("b" = 11))
|
||||
func Or(expressions ...exp.Expression) exp.ExpressionList {
|
||||
return exp.NewExpressionList(exp.OrType, expressions...)
|
||||
}
|
||||
|
||||
// A list of expressions that should be ANDed together
|
||||
// And(I("a").Eq(10), I("b").Eq(11)) //(("a" = 10) AND ("b" = 11))
|
||||
func And(expressions ...exp.Expression) exp.ExpressionList {
|
||||
return exp.NewExpressionList(exp.AndType, expressions...)
|
||||
}
|
||||
|
||||
// Creates a new SQLFunctionExpression with the given name and arguments
|
||||
func Func(name string, args ...interface{}) exp.SQLFunctionExpression {
|
||||
return exp.NewSQLFunctionExpression(name, args...)
|
||||
}
|
||||
|
||||
// used internally to normalize the column name if passed in as a string it should be turned into an identifier
|
||||
func newIdentifierFunc(name string, col interface{}) exp.SQLFunctionExpression {
|
||||
if s, ok := col.(string); ok {
|
||||
col = I(s)
|
||||
}
|
||||
return Func(name, col)
|
||||
}
|
||||
|
||||
// Creates a new DISTINCT sql function
|
||||
// DISTINCT("a") -> DISTINCT("a")
|
||||
// DISTINCT(I("a")) -> DISTINCT("a")
|
||||
func DISTINCT(col interface{}) exp.SQLFunctionExpression { return newIdentifierFunc("DISTINCT", col) }
|
||||
|
||||
// Creates a new COUNT sql function
|
||||
// COUNT("a") -> COUNT("a")
|
||||
// COUNT("*") -> COUNT("*")
|
||||
// COUNT(I("a")) -> COUNT("a")
|
||||
func COUNT(col interface{}) exp.SQLFunctionExpression { return newIdentifierFunc("COUNT", col) }
|
||||
|
||||
// Creates a new MIN sql function
|
||||
// MIN("a") -> MIN("a")
|
||||
// MIN(I("a")) -> MIN("a")
|
||||
func MIN(col interface{}) exp.SQLFunctionExpression { return newIdentifierFunc("MIN", col) }
|
||||
|
||||
// Creates a new MAX sql function
|
||||
// MAX("a") -> MAX("a")
|
||||
// MAX(I("a")) -> MAX("a")
|
||||
func MAX(col interface{}) exp.SQLFunctionExpression { return newIdentifierFunc("MAX", col) }
|
||||
|
||||
// Creates a new AVG sql function
|
||||
// AVG("a") -> AVG("a")
|
||||
// AVG(I("a")) -> AVG("a")
|
||||
func AVG(col interface{}) exp.SQLFunctionExpression { return newIdentifierFunc("AVG", col) }
|
||||
|
||||
// Creates a new FIRST sql function
|
||||
// FIRST("a") -> FIRST("a")
|
||||
// FIRST(I("a")) -> FIRST("a")
|
||||
func FIRST(col interface{}) exp.SQLFunctionExpression { return newIdentifierFunc("FIRST", col) }
|
||||
|
||||
// Creates a new LAST sql function
|
||||
// LAST("a") -> LAST("a")
|
||||
// LAST(I("a")) -> LAST("a")
|
||||
func LAST(col interface{}) exp.SQLFunctionExpression { return newIdentifierFunc("LAST", col) }
|
||||
|
||||
// Creates a new SUM sql function
|
||||
// SUM("a") -> SUM("a")
|
||||
// SUM(I("a")) -> SUM("a")
|
||||
func SUM(col interface{}) exp.SQLFunctionExpression { return newIdentifierFunc("SUM", col) }
|
||||
|
||||
// Creates a new COALESCE sql function
|
||||
// COALESCE(I("a"), "a") -> COALESCE("a", 'a')
|
||||
// COALESCE(I("a"), I("b"), nil) -> COALESCE("a", "b", NULL)
|
||||
func COALESCE(vals ...interface{}) exp.SQLFunctionExpression {
|
||||
return Func("COALESCE", vals...)
|
||||
}
|
||||
|
||||
//nolint:stylecheck,golint // sql function name
|
||||
func ROW_NUMBER() exp.SQLFunctionExpression {
|
||||
return Func("ROW_NUMBER")
|
||||
}
|
||||
|
||||
func RANK() exp.SQLFunctionExpression {
|
||||
return Func("RANK")
|
||||
}
|
||||
|
||||
//nolint:stylecheck,golint // sql function name
|
||||
func DENSE_RANK() exp.SQLFunctionExpression {
|
||||
return Func("DENSE_RANK")
|
||||
}
|
||||
|
||||
//nolint:stylecheck,golint // sql function name
|
||||
func PERCENT_RANK() exp.SQLFunctionExpression {
|
||||
return Func("PERCENT_RANK")
|
||||
}
|
||||
|
||||
//nolint:stylecheck,golint //sql function name
|
||||
func CUME_DIST() exp.SQLFunctionExpression {
|
||||
return Func("CUME_DIST")
|
||||
}
|
||||
|
||||
func NTILE(n int) exp.SQLFunctionExpression {
|
||||
return Func("NTILE", n)
|
||||
}
|
||||
|
||||
//nolint:stylecheck,golint //sql function name
|
||||
func FIRST_VALUE(val interface{}) exp.SQLFunctionExpression {
|
||||
return newIdentifierFunc("FIRST_VALUE", val)
|
||||
}
|
||||
|
||||
//nolint:stylecheck,golint //sql function name
|
||||
func LAST_VALUE(val interface{}) exp.SQLFunctionExpression {
|
||||
return newIdentifierFunc("LAST_VALUE", val)
|
||||
}
|
||||
|
||||
//nolint:stylecheck,golint //sql function name
|
||||
func NTH_VALUE(val interface{}, nth int) exp.SQLFunctionExpression {
|
||||
if s, ok := val.(string); ok {
|
||||
val = I(s)
|
||||
}
|
||||
return Func("NTH_VALUE", val, nth)
|
||||
}
|
||||
|
||||
// Creates a new Identifier, the generated sql will use adapter specific quoting or '"' by default, this ensures case
|
||||
// sensitivity and in certain databases allows for special characters, (e.g. "curr-table", "my table").
|
||||
//
|
||||
// The identifier will be split by '.'
|
||||
//
|
||||
// Table and Column example
|
||||
// I("table.column") -> "table"."column" //A Column and table
|
||||
// Schema table and column
|
||||
// I("schema.table.column") -> "schema"."table"."column"
|
||||
// Table with star
|
||||
// I("table.*") -> "table".*
|
||||
func I(ident string) exp.IdentifierExpression {
|
||||
return exp.ParseIdentifier(ident)
|
||||
}
|
||||
|
||||
// Creates a new Column Identifier, the generated sql will use adapter specific quoting or '"' by default, this ensures case
|
||||
// sensitivity and in certain databases allows for special characters, (e.g. "curr-table", "my table").
|
||||
// An Identifier can represent a one or a combination of schema, table, and/or column.
|
||||
// C("column") -> "column" //A Column
|
||||
// C("column").Table("table") -> "table"."column" //A Column and table
|
||||
// C("column").Table("table").Schema("schema") //Schema table and column
|
||||
// C("*") //Also handles the * operator
|
||||
func C(col string) exp.IdentifierExpression {
|
||||
return exp.NewIdentifierExpression("", "", col)
|
||||
}
|
||||
|
||||
// Creates a new Schema Identifier, the generated sql will use adapter specific quoting or '"' by default, this ensures case
|
||||
// sensitivity and in certain databases allows for special characters, (e.g. "curr-schema", "my schema").
|
||||
// S("schema") -> "schema" //A Schema
|
||||
// S("schema").Table("table") -> "schema"."table" //A Schema and table
|
||||
// S("schema").Table("table").Col("col") //Schema table and column
|
||||
// S("schema").Table("table").Col("*") //Schema table and all columns
|
||||
func S(schema string) exp.IdentifierExpression {
|
||||
return exp.NewIdentifierExpression(schema, "", "")
|
||||
}
|
||||
|
||||
// Creates a new Table Identifier, the generated sql will use adapter specific quoting or '"' by default, this ensures case
|
||||
// sensitivity and in certain databases allows for special characters, (e.g. "curr-table", "my table").
|
||||
// T("table") -> "table" //A Column
|
||||
// T("table").Col("col") -> "table"."column" //A Column and table
|
||||
// T("table").Schema("schema").Col("col) -> "schema"."table"."column" //Schema table and column
|
||||
// T("table").Schema("schema").Col("*") -> "schema"."table".* //Also handles the * operator
|
||||
func T(table string) exp.IdentifierExpression {
|
||||
return exp.NewIdentifierExpression("", table, "")
|
||||
}
|
||||
|
||||
// Create a new WINDOW clause
|
||||
// W() -> ()
|
||||
// W().PartitionBy("a") -> (PARTITION BY "a")
|
||||
// W().PartitionBy("a").OrderBy("b") -> (PARTITION BY "a" ORDER BY "b")
|
||||
// W().PartitionBy("a").OrderBy("b").Inherit("w1") -> ("w1" PARTITION BY "a" ORDER BY "b")
|
||||
// W().PartitionBy("a").OrderBy(I("b").Desc()).Inherit("w1") -> ("w1" PARTITION BY "a" ORDER BY "b" DESC)
|
||||
// W("w") -> "w" AS ()
|
||||
// W("w", "w1") -> "w" AS ("w1")
|
||||
// W("w").Inherit("w1") -> "w" AS ("w1")
|
||||
// W("w").PartitionBy("a") -> "w" AS (PARTITION BY "a")
|
||||
// W("w", "w1").PartitionBy("a") -> "w" AS ("w1" PARTITION BY "a")
|
||||
// W("w", "w1").PartitionBy("a").OrderBy("b") -> "w" AS ("w1" PARTITION BY "a" ORDER BY "b")
|
||||
func W(ws ...string) exp.WindowExpression {
|
||||
switch len(ws) {
|
||||
case 0:
|
||||
return emptyWindow
|
||||
case 1:
|
||||
return exp.NewWindowExpression(I(ws[0]), nil, nil, nil)
|
||||
default:
|
||||
return exp.NewWindowExpression(I(ws[0]), I(ws[1]), nil, nil)
|
||||
}
|
||||
}
|
||||
|
||||
// Creates a new ON clause to be used within a join
|
||||
// ds.Join(goqu.T("my_table"), goqu.On(
|
||||
// goqu.I("my_table.fkey").Eq(goqu.I("other_table.id")),
|
||||
// ))
|
||||
func On(expressions ...exp.Expression) exp.JoinCondition {
|
||||
return exp.NewJoinOnCondition(expressions...)
|
||||
}
|
||||
|
||||
// Creates a new USING clause to be used within a join
|
||||
// ds.Join(goqu.T("my_table"), goqu.Using("fkey"))
|
||||
func Using(columns ...interface{}) exp.JoinCondition {
|
||||
return exp.NewJoinUsingCondition(columns...)
|
||||
}
|
||||
|
||||
// Creates a new SQL literal with the provided arguments.
|
||||
// L("a = 1") -> a = 1
|
||||
// You can also you placeholders. All placeholders within a Literal are represented by '?'
|
||||
// L("a = ?", "b") -> a = 'b'
|
||||
// Literals can also contain placeholders for other expressions
|
||||
// L("(? AND ?) OR (?)", I("a").Eq(1), I("b").Eq("b"), I("c").In([]string{"a", "b", "c"}))
|
||||
func L(sql string, args ...interface{}) exp.LiteralExpression {
|
||||
return Literal(sql, args...)
|
||||
}
|
||||
|
||||
// Alias for goqu.L
|
||||
func Literal(sql string, args ...interface{}) exp.LiteralExpression {
|
||||
return exp.NewLiteralExpression(sql, args...)
|
||||
}
|
||||
|
||||
// Create a new SQL value ( alias for goqu.L("?", val) ). The prrimary use case for this would be in selects.
|
||||
// See examples.
|
||||
func V(val interface{}) exp.LiteralExpression {
|
||||
return exp.NewLiteralExpression("?", val)
|
||||
}
|
||||
|
||||
// Creates a new Range to be used with a Between expression
|
||||
// exp.C("col").Between(exp.Range(1, 10))
|
||||
func Range(start, end interface{}) exp.RangeVal {
|
||||
return exp.NewRangeVal(start, end)
|
||||
}
|
||||
|
||||
// Creates a literal *
|
||||
func Star() exp.LiteralExpression { return exp.Star() }
|
||||
|
||||
// Returns a literal for DEFAULT sql keyword
|
||||
func Default() exp.LiteralExpression {
|
||||
return exp.Default()
|
||||
}
|
||||
|
||||
func Lateral(table exp.AppendableExpression) exp.LateralExpression {
|
||||
return exp.NewLateralExpression(table)
|
||||
}
|
||||
|
||||
// Create a new ANY comparison
|
||||
func Any(val interface{}) exp.SQLFunctionExpression {
|
||||
return Func("ANY ", val)
|
||||
}
|
||||
|
||||
// Create a new ALL comparison
|
||||
func All(val interface{}) exp.SQLFunctionExpression {
|
||||
return Func("ALL ", val)
|
||||
}
|
||||
|
||||
func Case() exp.CaseExpression {
|
||||
return exp.NewCaseExpression()
|
||||
}
|
||||
6
vendor/github.com/doug-martin/goqu/v9/go.test.sh
generated
vendored
Normal file
6
vendor/github.com/doug-martin/goqu/v9/go.test.sh
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
echo "" > coverage.txt
|
||||
|
||||
go test -race -coverprofile=coverage.txt -coverpkg=./... ./...
|
||||
86
vendor/github.com/doug-martin/goqu/v9/goqu.go
generated
vendored
Normal file
86
vendor/github.com/doug-martin/goqu/v9/goqu.go
generated
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
goqu an idiomatch SQL builder, and query package.
|
||||
|
||||
__ _ ___ __ _ _ _
|
||||
/ _` |/ _ \ / _` | | | |
|
||||
| (_| | (_) | (_| | |_| |
|
||||
\__, |\___/ \__, |\__,_|
|
||||
|___/ |_|
|
||||
|
||||
|
||||
Please see https://github.com/doug-martin/goqu for an introduction to goqu.
|
||||
*/
|
||||
package goqu
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/doug-martin/goqu/v9/internal/util"
|
||||
"github.com/doug-martin/goqu/v9/sqlgen"
|
||||
)
|
||||
|
||||
type DialectWrapper struct {
|
||||
dialect string
|
||||
}
|
||||
|
||||
// Creates a new DialectWrapper to create goqu.Datasets or goqu.Databases with the specified dialect.
|
||||
func Dialect(dialect string) DialectWrapper {
|
||||
return DialectWrapper{dialect: dialect}
|
||||
}
|
||||
|
||||
// Create a new dataset for creating SELECT sql statements
|
||||
func (dw DialectWrapper) From(table ...interface{}) *SelectDataset {
|
||||
return From(table...).WithDialect(dw.dialect)
|
||||
}
|
||||
|
||||
// Create a new dataset for creating SELECT sql statements
|
||||
func (dw DialectWrapper) Select(cols ...interface{}) *SelectDataset {
|
||||
return newDataset(dw.dialect, nil).Select(cols...)
|
||||
}
|
||||
|
||||
// Create a new dataset for creating UPDATE sql statements
|
||||
func (dw DialectWrapper) Update(table interface{}) *UpdateDataset {
|
||||
return Update(table).WithDialect(dw.dialect)
|
||||
}
|
||||
|
||||
// Create a new dataset for creating INSERT sql statements
|
||||
func (dw DialectWrapper) Insert(table interface{}) *InsertDataset {
|
||||
return Insert(table).WithDialect(dw.dialect)
|
||||
}
|
||||
|
||||
// Create a new dataset for creating DELETE sql statements
|
||||
func (dw DialectWrapper) Delete(table interface{}) *DeleteDataset {
|
||||
return Delete(table).WithDialect(dw.dialect)
|
||||
}
|
||||
|
||||
// Create a new dataset for creating TRUNCATE sql statements
|
||||
func (dw DialectWrapper) Truncate(table ...interface{}) *TruncateDataset {
|
||||
return Truncate(table...).WithDialect(dw.dialect)
|
||||
}
|
||||
|
||||
func (dw DialectWrapper) DB(db SQLDatabase) *Database {
|
||||
return newDatabase(dw.dialect, db)
|
||||
}
|
||||
|
||||
func New(dialect string, db SQLDatabase) *Database {
|
||||
return newDatabase(dialect, db)
|
||||
}
|
||||
|
||||
// Set the behavior when encountering struct fields that do not have a db tag.
|
||||
// By default this is false; if set to true any field without a db tag will not
|
||||
// be targeted by Select or Scan operations.
|
||||
func SetIgnoreUntaggedFields(ignore bool) {
|
||||
util.SetIgnoreUntaggedFields(ignore)
|
||||
}
|
||||
|
||||
// Set the column rename function. This is used for struct fields that do not have a db tag to specify the column name
|
||||
// By default all struct fields that do not have a db tag will be converted lowercase
|
||||
func SetColumnRenameFunction(renameFunc func(string) string) {
|
||||
util.SetColumnRenameFunction(renameFunc)
|
||||
}
|
||||
|
||||
// Set the location to use when interpolating time.Time instances. See https://golang.org/pkg/time/#LoadLocation
|
||||
// NOTE: This has no effect when using prepared statements.
|
||||
func SetTimeLocation(loc *time.Location) {
|
||||
sqlgen.SetTimeLocation(loc)
|
||||
}
|
||||
271
vendor/github.com/doug-martin/goqu/v9/insert_dataset.go
generated
vendored
Normal file
271
vendor/github.com/doug-martin/goqu/v9/insert_dataset.go
generated
vendored
Normal file
@@ -0,0 +1,271 @@
|
||||
package goqu
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/doug-martin/goqu/v9/exec"
|
||||
"github.com/doug-martin/goqu/v9/exp"
|
||||
"github.com/doug-martin/goqu/v9/internal/errors"
|
||||
"github.com/doug-martin/goqu/v9/internal/sb"
|
||||
)
|
||||
|
||||
type InsertDataset struct {
|
||||
dialect SQLDialect
|
||||
clauses exp.InsertClauses
|
||||
isPrepared prepared
|
||||
queryFactory exec.QueryFactory
|
||||
err error
|
||||
}
|
||||
|
||||
var ErrUnsupportedIntoType = errors.New("unsupported table type, a string or identifier expression is required")
|
||||
|
||||
// used internally by database to create a database with a specific adapter
|
||||
func newInsertDataset(d string, queryFactory exec.QueryFactory) *InsertDataset {
|
||||
return &InsertDataset{
|
||||
clauses: exp.NewInsertClauses(),
|
||||
dialect: GetDialect(d),
|
||||
queryFactory: queryFactory,
|
||||
}
|
||||
}
|
||||
|
||||
// Creates a new InsertDataset for the provided table. Using this method will only allow you
|
||||
// to create SQL user Database#From to create an InsertDataset with query capabilities
|
||||
func Insert(table interface{}) *InsertDataset {
|
||||
return newInsertDataset("default", nil).Into(table)
|
||||
}
|
||||
|
||||
// Set the parameter interpolation behavior. See examples
|
||||
//
|
||||
// prepared: If true the dataset WILL NOT interpolate the parameters.
|
||||
func (id *InsertDataset) Prepared(prepared bool) *InsertDataset {
|
||||
ret := id.copy(id.clauses)
|
||||
ret.isPrepared = preparedFromBool(prepared)
|
||||
return ret
|
||||
}
|
||||
|
||||
func (id *InsertDataset) IsPrepared() bool {
|
||||
return id.isPrepared.Bool()
|
||||
}
|
||||
|
||||
// Sets the adapter used to serialize values and create the SQL statement
|
||||
func (id *InsertDataset) WithDialect(dl string) *InsertDataset {
|
||||
ds := id.copy(id.GetClauses())
|
||||
ds.dialect = GetDialect(dl)
|
||||
return ds
|
||||
}
|
||||
|
||||
// Returns the current adapter on the dataset
|
||||
func (id *InsertDataset) Dialect() SQLDialect {
|
||||
return id.dialect
|
||||
}
|
||||
|
||||
// Returns the current adapter on the dataset
|
||||
func (id *InsertDataset) SetDialect(dialect SQLDialect) *InsertDataset {
|
||||
cd := id.copy(id.GetClauses())
|
||||
cd.dialect = dialect
|
||||
return cd
|
||||
}
|
||||
|
||||
func (id *InsertDataset) Expression() exp.Expression {
|
||||
return id
|
||||
}
|
||||
|
||||
// Clones the dataset
|
||||
func (id *InsertDataset) Clone() exp.Expression {
|
||||
return id.copy(id.clauses)
|
||||
}
|
||||
|
||||
// Returns the current clauses on the dataset.
|
||||
func (id *InsertDataset) GetClauses() exp.InsertClauses {
|
||||
return id.clauses
|
||||
}
|
||||
|
||||
// used interally to copy the dataset
|
||||
func (id *InsertDataset) copy(clauses exp.InsertClauses) *InsertDataset {
|
||||
return &InsertDataset{
|
||||
dialect: id.dialect,
|
||||
clauses: clauses,
|
||||
isPrepared: id.isPrepared,
|
||||
queryFactory: id.queryFactory,
|
||||
err: id.err,
|
||||
}
|
||||
}
|
||||
|
||||
// Creates a WITH clause for a common table expression (CTE).
|
||||
//
|
||||
// The name will be available to SELECT from in the associated query; and can optionally
|
||||
// contain a list of column names "name(col1, col2, col3)".
|
||||
//
|
||||
// The name will refer to the results of the specified subquery.
|
||||
func (id *InsertDataset) With(name string, subquery exp.Expression) *InsertDataset {
|
||||
return id.copy(id.clauses.CommonTablesAppend(exp.NewCommonTableExpression(false, name, subquery)))
|
||||
}
|
||||
|
||||
// Creates a WITH RECURSIVE clause for a common table expression (CTE)
|
||||
//
|
||||
// The name will be available to SELECT from in the associated query; and must
|
||||
// contain a list of column names "name(col1, col2, col3)" for a recursive clause.
|
||||
//
|
||||
// The name will refer to the results of the specified subquery. The subquery for
|
||||
// a recursive query will always end with a UNION or UNION ALL with a clause that
|
||||
// refers to the CTE by name.
|
||||
func (id *InsertDataset) WithRecursive(name string, subquery exp.Expression) *InsertDataset {
|
||||
return id.copy(id.clauses.CommonTablesAppend(exp.NewCommonTableExpression(true, name, subquery)))
|
||||
}
|
||||
|
||||
// Sets the table to insert INTO. This return a new dataset with the original table replaced. See examples.
|
||||
// You can pass in the following.
|
||||
// string: Will automatically be turned into an identifier
|
||||
// Expression: Any valid expression (IdentifierExpression, AliasedExpression, Literal, etc.)
|
||||
func (id *InsertDataset) Into(into interface{}) *InsertDataset {
|
||||
switch t := into.(type) {
|
||||
case exp.Expression:
|
||||
return id.copy(id.clauses.SetInto(t))
|
||||
case string:
|
||||
return id.copy(id.clauses.SetInto(exp.ParseIdentifier(t)))
|
||||
default:
|
||||
panic(ErrUnsupportedIntoType)
|
||||
}
|
||||
}
|
||||
|
||||
// Sets the Columns to insert into
|
||||
func (id *InsertDataset) Cols(cols ...interface{}) *InsertDataset {
|
||||
return id.copy(id.clauses.SetCols(exp.NewColumnListExpression(cols...)))
|
||||
}
|
||||
|
||||
// Clears the Columns to insert into
|
||||
func (id *InsertDataset) ClearCols() *InsertDataset {
|
||||
return id.copy(id.clauses.SetCols(nil))
|
||||
}
|
||||
|
||||
// Adds columns to the current list of columns clause. See examples
|
||||
func (id *InsertDataset) ColsAppend(cols ...interface{}) *InsertDataset {
|
||||
return id.copy(id.clauses.ColsAppend(exp.NewColumnListExpression(cols...)))
|
||||
}
|
||||
|
||||
// Adds a subquery to the insert. See examples.
|
||||
func (id *InsertDataset) FromQuery(from exp.AppendableExpression) *InsertDataset {
|
||||
if sds, ok := from.(*SelectDataset); ok {
|
||||
if sds.dialect != GetDialect("default") && id.Dialect() != sds.dialect {
|
||||
panic(
|
||||
fmt.Errorf(
|
||||
"incompatible dialects for INSERT (%q) and SELECT (%q)",
|
||||
id.dialect.Dialect(), sds.dialect.Dialect(),
|
||||
),
|
||||
)
|
||||
}
|
||||
sds.dialect = id.dialect
|
||||
}
|
||||
return id.copy(id.clauses.SetFrom(from))
|
||||
}
|
||||
|
||||
// Manually set values to insert See examples.
|
||||
func (id *InsertDataset) Vals(vals ...[]interface{}) *InsertDataset {
|
||||
return id.copy(id.clauses.ValsAppend(vals))
|
||||
}
|
||||
|
||||
// Clears the values. See examples.
|
||||
func (id *InsertDataset) ClearVals() *InsertDataset {
|
||||
return id.copy(id.clauses.SetVals(nil))
|
||||
}
|
||||
|
||||
// Insert rows. Rows can be a map, goqu.Record or struct. See examples.
|
||||
func (id *InsertDataset) Rows(rows ...interface{}) *InsertDataset {
|
||||
return id.copy(id.clauses.SetRows(rows))
|
||||
}
|
||||
|
||||
// Clears the rows for this insert dataset. See examples.
|
||||
func (id *InsertDataset) ClearRows() *InsertDataset {
|
||||
return id.copy(id.clauses.SetRows(nil))
|
||||
}
|
||||
|
||||
// Adds a RETURNING clause to the dataset if the adapter supports it See examples.
|
||||
func (id *InsertDataset) Returning(returning ...interface{}) *InsertDataset {
|
||||
return id.copy(id.clauses.SetReturning(exp.NewColumnListExpression(returning...)))
|
||||
}
|
||||
|
||||
// Adds an (ON CONFLICT/ON DUPLICATE KEY) clause to the dataset if the dialect supports it. See examples.
|
||||
func (id *InsertDataset) OnConflict(conflict exp.ConflictExpression) *InsertDataset {
|
||||
return id.copy(id.clauses.SetOnConflict(conflict))
|
||||
}
|
||||
|
||||
// Clears the on conflict clause. See example
|
||||
func (id *InsertDataset) ClearOnConflict() *InsertDataset {
|
||||
return id.OnConflict(nil)
|
||||
}
|
||||
|
||||
// Get any error that has been set or nil if no error has been set.
|
||||
func (id *InsertDataset) Error() error {
|
||||
return id.err
|
||||
}
|
||||
|
||||
// Set an error on the dataset if one has not already been set. This error will be returned by a future call to Error
|
||||
// or as part of ToSQL. This can be used by end users to record errors while building up queries without having to
|
||||
// track those separately.
|
||||
func (id *InsertDataset) SetError(err error) *InsertDataset {
|
||||
if id.err == nil {
|
||||
id.err = err
|
||||
}
|
||||
|
||||
return id
|
||||
}
|
||||
|
||||
// Generates the default INSERT statement. If Prepared has been called with true then the statement will not be
|
||||
// interpolated. See examples. When using structs you may specify a column to be skipped in the insert, (e.g. id) by
|
||||
// specifying a goqu tag with `skipinsert`
|
||||
// type Item struct{
|
||||
// Id uint32 `db:"id" goqu:"skipinsert"`
|
||||
// Name string `db:"name"`
|
||||
// }
|
||||
//
|
||||
// rows: variable number arguments of either map[string]interface, Record, struct, or a single slice argument of the
|
||||
// accepted types.
|
||||
//
|
||||
// Errors:
|
||||
// * There is no INTO clause
|
||||
// * Different row types passed in, all rows must be of the same type
|
||||
// * Maps with different numbers of K/V pairs
|
||||
// * Rows of different lengths, (i.e. (Record{"name": "a"}, Record{"name": "a", "age": 10})
|
||||
// * Error generating SQL
|
||||
func (id *InsertDataset) ToSQL() (sql string, params []interface{}, err error) {
|
||||
return id.insertSQLBuilder().ToSQL()
|
||||
}
|
||||
|
||||
// Appends this Dataset's INSERT statement to the SQLBuilder
|
||||
// This is used internally when using inserts in CTEs
|
||||
func (id *InsertDataset) AppendSQL(b sb.SQLBuilder) {
|
||||
if id.err != nil {
|
||||
b.SetError(id.err)
|
||||
return
|
||||
}
|
||||
id.dialect.ToInsertSQL(b, id.GetClauses())
|
||||
}
|
||||
|
||||
func (id *InsertDataset) GetAs() exp.IdentifierExpression {
|
||||
return id.clauses.Alias()
|
||||
}
|
||||
|
||||
// Sets the alias for this dataset. This is typically used when using a Dataset as MySQL upsert
|
||||
func (id *InsertDataset) As(alias string) *InsertDataset {
|
||||
return id.copy(id.clauses.SetAlias(T(alias)))
|
||||
}
|
||||
|
||||
func (id *InsertDataset) ReturnsColumns() bool {
|
||||
return id.clauses.HasReturning()
|
||||
}
|
||||
|
||||
// Generates the INSERT sql, and returns an QueryExecutor struct with the sql set to the INSERT statement
|
||||
// db.Insert("test").Rows(Record{"name":"Bob"}).Executor().Exec()
|
||||
//
|
||||
func (id *InsertDataset) Executor() exec.QueryExecutor {
|
||||
return id.queryFactory.FromSQLBuilder(id.insertSQLBuilder())
|
||||
}
|
||||
|
||||
func (id *InsertDataset) insertSQLBuilder() sb.SQLBuilder {
|
||||
buf := sb.NewSQLBuilder(id.isPrepared.Bool())
|
||||
if id.err != nil {
|
||||
return buf.SetError(id.err)
|
||||
}
|
||||
id.dialect.ToInsertSQL(buf, id.clauses)
|
||||
return buf
|
||||
}
|
||||
19
vendor/github.com/doug-martin/goqu/v9/internal/errors/error.go
generated
vendored
Normal file
19
vendor/github.com/doug-martin/goqu/v9/internal/errors/error.go
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
package errors
|
||||
|
||||
import "fmt"
|
||||
|
||||
type Error struct {
|
||||
err string
|
||||
}
|
||||
|
||||
func New(message string, args ...interface{}) error {
|
||||
return Error{err: "goqu: " + fmt.Sprintf(message, args...)}
|
||||
}
|
||||
|
||||
func NewEncodeError(t interface{}) error {
|
||||
return Error{err: "goqu_encode_error: " + fmt.Sprintf("Unable to encode value %+v", t)}
|
||||
}
|
||||
|
||||
func (e Error) Error() string {
|
||||
return e.err
|
||||
}
|
||||
101
vendor/github.com/doug-martin/goqu/v9/internal/sb/sql_builder.go
generated
vendored
Normal file
101
vendor/github.com/doug-martin/goqu/v9/internal/sb/sql_builder.go
generated
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
package sb
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
)
|
||||
|
||||
// Builder that is composed of a bytes.Buffer. It is used internally and by adapters to build SQL statements
|
||||
type (
|
||||
SQLBuilder interface {
|
||||
Error() error
|
||||
SetError(err error) SQLBuilder
|
||||
WriteArg(i ...interface{}) SQLBuilder
|
||||
Write(p []byte) SQLBuilder
|
||||
WriteStrings(ss ...string) SQLBuilder
|
||||
WriteRunes(r ...rune) SQLBuilder
|
||||
IsPrepared() bool
|
||||
CurrentArgPosition() int
|
||||
ToSQL() (sql string, args []interface{}, err error)
|
||||
}
|
||||
sqlBuilder struct {
|
||||
buf *bytes.Buffer
|
||||
// True if the sql should not be interpolated
|
||||
isPrepared bool
|
||||
// Current Number of arguments, used by adapters that need positional placeholders
|
||||
currentArgPosition int
|
||||
args []interface{}
|
||||
err error
|
||||
}
|
||||
)
|
||||
|
||||
func NewSQLBuilder(isPrepared bool) SQLBuilder {
|
||||
return &sqlBuilder{
|
||||
buf: &bytes.Buffer{},
|
||||
isPrepared: isPrepared,
|
||||
args: make([]interface{}, 0),
|
||||
currentArgPosition: 1,
|
||||
}
|
||||
}
|
||||
|
||||
func (b *sqlBuilder) Error() error {
|
||||
return b.err
|
||||
}
|
||||
|
||||
func (b *sqlBuilder) SetError(err error) SQLBuilder {
|
||||
if b.err == nil {
|
||||
b.err = err
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *sqlBuilder) Write(bs []byte) SQLBuilder {
|
||||
if b.err == nil {
|
||||
b.buf.Write(bs)
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *sqlBuilder) WriteStrings(ss ...string) SQLBuilder {
|
||||
if b.err == nil {
|
||||
for _, s := range ss {
|
||||
b.buf.WriteString(s)
|
||||
}
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *sqlBuilder) WriteRunes(rs ...rune) SQLBuilder {
|
||||
if b.err == nil {
|
||||
for _, r := range rs {
|
||||
b.buf.WriteRune(r)
|
||||
}
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
// Returns true if the sql is a prepared statement
|
||||
func (b *sqlBuilder) IsPrepared() bool {
|
||||
return b.isPrepared
|
||||
}
|
||||
|
||||
// Returns true if the sql is a prepared statement
|
||||
func (b *sqlBuilder) CurrentArgPosition() int {
|
||||
return b.currentArgPosition
|
||||
}
|
||||
|
||||
// Adds an argument to the builder, used when IsPrepared is false
|
||||
func (b *sqlBuilder) WriteArg(i ...interface{}) SQLBuilder {
|
||||
if b.err == nil {
|
||||
b.currentArgPosition += len(i)
|
||||
b.args = append(b.args, i...)
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
// Returns the sql string, and arguments.
|
||||
func (b *sqlBuilder) ToSQL() (sql string, args []interface{}, err error) {
|
||||
if b.err != nil {
|
||||
return sql, args, b.err
|
||||
}
|
||||
return b.buf.String(), b.args, nil
|
||||
}
|
||||
51
vendor/github.com/doug-martin/goqu/v9/internal/tag/tags.go
generated
vendored
Normal file
51
vendor/github.com/doug-martin/goqu/v9/internal/tag/tags.go
generated
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
package tag
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// tagOptions is the string following a comma in a struct field's "json"
|
||||
// tag, or the empty string. It does not include the leading comma.
|
||||
type Options string
|
||||
|
||||
func New(tagName string, st reflect.StructTag) Options {
|
||||
return Options(st.Get(tagName))
|
||||
}
|
||||
|
||||
func (o Options) Values() []string {
|
||||
if string(o) == "" {
|
||||
return []string{}
|
||||
}
|
||||
return strings.Split(string(o), ",")
|
||||
}
|
||||
|
||||
// Contains reports whether a comma-separated list of options
|
||||
// contains a particular substr flag. substr must be surrounded by a
|
||||
// string boundary or commas.
|
||||
func (o Options) Contains(optionName string) bool {
|
||||
if o.IsEmpty() {
|
||||
return false
|
||||
}
|
||||
values := o.Values()
|
||||
for _, s := range values {
|
||||
if s == optionName {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Contains reports whether a comma-separated list of options
|
||||
// contains a particular substr flag. substr must be surrounded by a
|
||||
// string boundary or commas.
|
||||
func (o Options) Equals(val string) bool {
|
||||
if len(o) == 0 {
|
||||
return false
|
||||
}
|
||||
return string(o) == val
|
||||
}
|
||||
|
||||
func (o Options) IsEmpty() bool {
|
||||
return len(o) == 0
|
||||
}
|
||||
130
vendor/github.com/doug-martin/goqu/v9/internal/util/column_map.go
generated
vendored
Normal file
130
vendor/github.com/doug-martin/goqu/v9/internal/util/column_map.go
generated
vendored
Normal file
@@ -0,0 +1,130 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/doug-martin/goqu/v9/internal/tag"
|
||||
)
|
||||
|
||||
type (
|
||||
ColumnData struct {
|
||||
ColumnName string
|
||||
FieldIndex []int
|
||||
ShouldInsert bool
|
||||
ShouldUpdate bool
|
||||
DefaultIfEmpty bool
|
||||
GoType reflect.Type
|
||||
}
|
||||
ColumnMap map[string]ColumnData
|
||||
)
|
||||
|
||||
func newColumnMap(t reflect.Type, fieldIndex []int, prefixes []string) ColumnMap {
|
||||
cm, n := ColumnMap{}, t.NumField()
|
||||
var subColMaps []ColumnMap
|
||||
for i := 0; i < n; i++ {
|
||||
f := t.Field(i)
|
||||
if f.Anonymous && (f.Type.Kind() == reflect.Struct || f.Type.Kind() == reflect.Ptr) {
|
||||
goquTag := tag.New("db", f.Tag)
|
||||
if !goquTag.Contains("-") {
|
||||
subColMaps = append(subColMaps, getStructColumnMap(&f, fieldIndex, goquTag.Values(), prefixes))
|
||||
}
|
||||
} else if f.PkgPath == "" {
|
||||
dbTag := tag.New("db", f.Tag)
|
||||
// if PkgPath is empty then it is an exported field
|
||||
columnName := getColumnName(&f, dbTag)
|
||||
if !shouldIgnoreField(dbTag) {
|
||||
if !implementsScanner(f.Type) {
|
||||
subCm := getStructColumnMap(&f, fieldIndex, []string{columnName}, prefixes)
|
||||
if len(subCm) != 0 {
|
||||
subColMaps = append(subColMaps, subCm)
|
||||
continue
|
||||
}
|
||||
}
|
||||
goquTag := tag.New("goqu", f.Tag)
|
||||
columnName = strings.Join(append(prefixes, columnName), ".")
|
||||
cm[columnName] = newColumnData(&f, columnName, fieldIndex, goquTag)
|
||||
}
|
||||
}
|
||||
}
|
||||
return cm.Merge(subColMaps)
|
||||
}
|
||||
|
||||
func (cm ColumnMap) Cols() []string {
|
||||
structCols := make([]string, 0, len(cm))
|
||||
for key := range cm {
|
||||
structCols = append(structCols, key)
|
||||
}
|
||||
sort.Strings(structCols)
|
||||
return structCols
|
||||
}
|
||||
|
||||
func (cm ColumnMap) Merge(colMaps []ColumnMap) ColumnMap {
|
||||
for _, subCm := range colMaps {
|
||||
for key, val := range subCm {
|
||||
if _, ok := cm[key]; !ok {
|
||||
cm[key] = val
|
||||
}
|
||||
}
|
||||
}
|
||||
return cm
|
||||
}
|
||||
|
||||
func implementsScanner(t reflect.Type) bool {
|
||||
if IsPointer(t.Kind()) {
|
||||
t = t.Elem()
|
||||
}
|
||||
if reflect.PtrTo(t).Implements(scannerType) {
|
||||
return true
|
||||
}
|
||||
if !IsStruct(t.Kind()) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func newColumnData(f *reflect.StructField, columnName string, fieldIndex []int, goquTag tag.Options) ColumnData {
|
||||
return ColumnData{
|
||||
ColumnName: columnName,
|
||||
ShouldInsert: !goquTag.Contains(skipInsertTagName),
|
||||
ShouldUpdate: !goquTag.Contains(skipUpdateTagName),
|
||||
DefaultIfEmpty: goquTag.Contains(defaultIfEmptyTagName),
|
||||
FieldIndex: concatFieldIndexes(fieldIndex, f.Index),
|
||||
GoType: f.Type,
|
||||
}
|
||||
}
|
||||
|
||||
func getStructColumnMap(f *reflect.StructField, fieldIndex []int, fieldNames, prefixes []string) ColumnMap {
|
||||
subFieldIndexes := concatFieldIndexes(fieldIndex, f.Index)
|
||||
subPrefixes := append(prefixes, fieldNames...)
|
||||
if f.Type.Kind() == reflect.Ptr {
|
||||
return newColumnMap(f.Type.Elem(), subFieldIndexes, subPrefixes)
|
||||
}
|
||||
return newColumnMap(f.Type, subFieldIndexes, subPrefixes)
|
||||
}
|
||||
|
||||
func getColumnName(f *reflect.StructField, dbTag tag.Options) string {
|
||||
if dbTag.IsEmpty() {
|
||||
return columnRenameFunction(f.Name)
|
||||
}
|
||||
return dbTag.Values()[0]
|
||||
}
|
||||
|
||||
func shouldIgnoreField(dbTag tag.Options) bool {
|
||||
if dbTag.Equals("-") {
|
||||
return true
|
||||
} else if dbTag.IsEmpty() && ignoreUntaggedFields {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// safely concat two fieldIndex slices into one.
|
||||
func concatFieldIndexes(fieldIndexPath, fieldIndex []int) []int {
|
||||
fieldIndexes := make([]int, 0, len(fieldIndexPath)+len(fieldIndex))
|
||||
fieldIndexes = append(fieldIndexes, fieldIndexPath...)
|
||||
return append(fieldIndexes, fieldIndex...)
|
||||
}
|
||||
220
vendor/github.com/doug-martin/goqu/v9/internal/util/reflect.go
generated
vendored
Normal file
220
vendor/github.com/doug-martin/goqu/v9/internal/util/reflect.go
generated
vendored
Normal file
@@ -0,0 +1,220 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"reflect"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/doug-martin/goqu/v9/internal/errors"
|
||||
)
|
||||
|
||||
const (
|
||||
skipUpdateTagName = "skipupdate"
|
||||
skipInsertTagName = "skipinsert"
|
||||
defaultIfEmptyTagName = "defaultifempty"
|
||||
)
|
||||
|
||||
var scannerType = reflect.TypeOf((*sql.Scanner)(nil)).Elem()
|
||||
|
||||
func IsUint(k reflect.Kind) bool {
|
||||
return (k == reflect.Uint) ||
|
||||
(k == reflect.Uint8) ||
|
||||
(k == reflect.Uint16) ||
|
||||
(k == reflect.Uint32) ||
|
||||
(k == reflect.Uint64)
|
||||
}
|
||||
|
||||
func IsInt(k reflect.Kind) bool {
|
||||
return (k == reflect.Int) ||
|
||||
(k == reflect.Int8) ||
|
||||
(k == reflect.Int16) ||
|
||||
(k == reflect.Int32) ||
|
||||
(k == reflect.Int64)
|
||||
}
|
||||
|
||||
func IsFloat(k reflect.Kind) bool {
|
||||
return (k == reflect.Float32) ||
|
||||
(k == reflect.Float64)
|
||||
}
|
||||
|
||||
func IsString(k reflect.Kind) bool {
|
||||
return k == reflect.String
|
||||
}
|
||||
|
||||
func IsBool(k reflect.Kind) bool {
|
||||
return k == reflect.Bool
|
||||
}
|
||||
|
||||
func IsSlice(k reflect.Kind) bool {
|
||||
return k == reflect.Slice
|
||||
}
|
||||
|
||||
func IsStruct(k reflect.Kind) bool {
|
||||
return k == reflect.Struct
|
||||
}
|
||||
|
||||
func IsInvalid(k reflect.Kind) bool {
|
||||
return k == reflect.Invalid
|
||||
}
|
||||
|
||||
func IsPointer(k reflect.Kind) bool {
|
||||
return k == reflect.Ptr
|
||||
}
|
||||
|
||||
func IsEmptyValue(v reflect.Value) bool {
|
||||
switch v.Kind() {
|
||||
case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
|
||||
return v.Len() == 0
|
||||
case reflect.Bool:
|
||||
return !v.Bool()
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return v.Int() == 0
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
return v.Uint() == 0
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return v.Float() == 0
|
||||
case reflect.Interface, reflect.Ptr:
|
||||
return v.IsNil()
|
||||
case reflect.Invalid:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
structMapCache = make(map[interface{}]ColumnMap)
|
||||
structMapCacheLock = sync.Mutex{}
|
||||
)
|
||||
|
||||
var (
|
||||
DefaultColumnRenameFunction = strings.ToLower
|
||||
columnRenameFunction = DefaultColumnRenameFunction
|
||||
ignoreUntaggedFields = false
|
||||
)
|
||||
|
||||
func SetIgnoreUntaggedFields(ignore bool) {
|
||||
// If the value here is changing, reset the struct map cache
|
||||
if ignore != ignoreUntaggedFields {
|
||||
ignoreUntaggedFields = ignore
|
||||
|
||||
structMapCacheLock.Lock()
|
||||
defer structMapCacheLock.Unlock()
|
||||
|
||||
structMapCache = make(map[interface{}]ColumnMap)
|
||||
}
|
||||
}
|
||||
|
||||
func SetColumnRenameFunction(newFunction func(string) string) {
|
||||
columnRenameFunction = newFunction
|
||||
}
|
||||
|
||||
// GetSliceElementType returns the type for a slices elements.
|
||||
func GetSliceElementType(val reflect.Value) reflect.Type {
|
||||
elemType := val.Type().Elem()
|
||||
if elemType.Kind() == reflect.Ptr {
|
||||
elemType = elemType.Elem()
|
||||
}
|
||||
|
||||
return elemType
|
||||
}
|
||||
|
||||
// AppendSliceElement will append val to slice. Handles slice of pointers and
|
||||
// not pointers. Val needs to be a pointer.
|
||||
func AppendSliceElement(slice, val reflect.Value) {
|
||||
if slice.Type().Elem().Kind() == reflect.Ptr {
|
||||
slice.Set(reflect.Append(slice, val))
|
||||
} else {
|
||||
slice.Set(reflect.Append(slice, reflect.Indirect(val)))
|
||||
}
|
||||
}
|
||||
|
||||
func GetTypeInfo(i interface{}, val reflect.Value) (reflect.Type, reflect.Kind) {
|
||||
var t reflect.Type
|
||||
valKind := val.Kind()
|
||||
if valKind == reflect.Slice {
|
||||
if reflect.ValueOf(i).Kind() == reflect.Ptr {
|
||||
t = reflect.TypeOf(i).Elem().Elem()
|
||||
} else {
|
||||
t = reflect.TypeOf(i).Elem()
|
||||
}
|
||||
if t.Kind() == reflect.Ptr {
|
||||
t = t.Elem()
|
||||
}
|
||||
valKind = t.Kind()
|
||||
} else {
|
||||
t = val.Type()
|
||||
}
|
||||
return t, valKind
|
||||
}
|
||||
|
||||
func SafeGetFieldByIndex(v reflect.Value, fieldIndex []int) (result reflect.Value, isAvailable bool) {
|
||||
switch len(fieldIndex) {
|
||||
case 0:
|
||||
return v, true
|
||||
case 1:
|
||||
return v.FieldByIndex(fieldIndex), true
|
||||
default:
|
||||
if f := reflect.Indirect(v.Field(fieldIndex[0])); f.IsValid() {
|
||||
return SafeGetFieldByIndex(f, fieldIndex[1:])
|
||||
}
|
||||
}
|
||||
return reflect.ValueOf(nil), false
|
||||
}
|
||||
|
||||
func SafeSetFieldByIndex(v reflect.Value, fieldIndex []int, src interface{}) (result reflect.Value) {
|
||||
v = reflect.Indirect(v)
|
||||
switch len(fieldIndex) {
|
||||
case 0:
|
||||
return v
|
||||
case 1:
|
||||
f := v.FieldByIndex(fieldIndex)
|
||||
srcVal := reflect.ValueOf(src)
|
||||
f.Set(reflect.Indirect(srcVal))
|
||||
default:
|
||||
f := v.Field(fieldIndex[0])
|
||||
switch f.Kind() {
|
||||
case reflect.Ptr:
|
||||
s := f
|
||||
if f.IsNil() || !f.IsValid() {
|
||||
s = reflect.New(f.Type().Elem())
|
||||
f.Set(s)
|
||||
}
|
||||
SafeSetFieldByIndex(reflect.Indirect(s), fieldIndex[1:], src)
|
||||
case reflect.Struct:
|
||||
SafeSetFieldByIndex(f, fieldIndex[1:], src)
|
||||
default: // use the original value
|
||||
}
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
type rowData = map[string]interface{}
|
||||
|
||||
// AssignStructVals will assign the data from rd to i.
|
||||
func AssignStructVals(i interface{}, rd rowData, cm ColumnMap) {
|
||||
val := reflect.Indirect(reflect.ValueOf(i))
|
||||
|
||||
for name, data := range cm {
|
||||
src, ok := rd[name]
|
||||
if ok {
|
||||
SafeSetFieldByIndex(val, data.FieldIndex, src)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func GetColumnMap(i interface{}) (ColumnMap, error) {
|
||||
val := reflect.Indirect(reflect.ValueOf(i))
|
||||
t, valKind := GetTypeInfo(i, val)
|
||||
if valKind != reflect.Struct {
|
||||
return nil, errors.New("cannot scan into this type: %v", t) // #nosec
|
||||
}
|
||||
|
||||
structMapCacheLock.Lock()
|
||||
defer structMapCacheLock.Unlock()
|
||||
if _, ok := structMapCache[t]; !ok {
|
||||
structMapCache[t] = newColumnMap(t, []int{}, []string{})
|
||||
}
|
||||
return structMapCache[t], nil
|
||||
}
|
||||
33
vendor/github.com/doug-martin/goqu/v9/internal/util/value_slice.go
generated
vendored
Normal file
33
vendor/github.com/doug-martin/goqu/v9/internal/util/value_slice.go
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type ValueSlice []reflect.Value
|
||||
|
||||
func (vs ValueSlice) Len() int { return len(vs) }
|
||||
func (vs ValueSlice) Less(i, j int) bool { return vs[i].String() < vs[j].String() }
|
||||
func (vs ValueSlice) Swap(i, j int) { vs[i], vs[j] = vs[j], vs[i] }
|
||||
|
||||
func (vs ValueSlice) Equal(other ValueSlice) bool {
|
||||
sort.Sort(other)
|
||||
for i, key := range vs {
|
||||
if other[i].String() != key.String() {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (vs ValueSlice) String() string {
|
||||
vals := make([]string, vs.Len())
|
||||
for i, key := range vs {
|
||||
vals[i] = fmt.Sprintf(`"%s"`, key.String())
|
||||
}
|
||||
sort.Strings(vals)
|
||||
return fmt.Sprintf("[%s]", strings.Join(vals, ","))
|
||||
}
|
||||
48
vendor/github.com/doug-martin/goqu/v9/prepared.go
generated
vendored
Normal file
48
vendor/github.com/doug-martin/goqu/v9/prepared.go
generated
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
package goqu
|
||||
|
||||
var (
|
||||
// defaultPrepared is controlled by SetDefaultPrepared
|
||||
defaultPrepared bool
|
||||
)
|
||||
|
||||
type prepared int
|
||||
|
||||
const (
|
||||
// zero value that defers to defaultPrepared
|
||||
preparedNoPreference prepared = iota
|
||||
|
||||
// explicitly enabled via Prepared(true) on a dataset
|
||||
preparedEnabled
|
||||
|
||||
// explicitly disabled via Prepared(false) on a dataset
|
||||
preparedDisabled
|
||||
)
|
||||
|
||||
// Bool converts the ternary prepared state into a boolean. If the prepared
|
||||
// state is preparedNoPreference, the value depends on the last value that
|
||||
// SetDefaultPrepared was called with which is false by default.
|
||||
func (p prepared) Bool() bool {
|
||||
if p == preparedNoPreference {
|
||||
return defaultPrepared
|
||||
} else if p == preparedEnabled {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// preparedFromBool converts a bool from e.g. Prepared(true) into a prepared
|
||||
// const.
|
||||
func preparedFromBool(prepared bool) prepared {
|
||||
if prepared {
|
||||
return preparedEnabled
|
||||
}
|
||||
|
||||
return preparedDisabled
|
||||
}
|
||||
|
||||
// SetDefaultPrepared controls the default Prepared state of all datasets. If
|
||||
// set to true, any new dataset will use prepared queries by default.
|
||||
func SetDefaultPrepared(prepared bool) {
|
||||
defaultPrepared = prepared
|
||||
}
|
||||
695
vendor/github.com/doug-martin/goqu/v9/select_dataset.go
generated
vendored
Normal file
695
vendor/github.com/doug-martin/goqu/v9/select_dataset.go
generated
vendored
Normal file
@@ -0,0 +1,695 @@
|
||||
package goqu
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/doug-martin/goqu/v9/exec"
|
||||
"github.com/doug-martin/goqu/v9/exp"
|
||||
"github.com/doug-martin/goqu/v9/internal/errors"
|
||||
"github.com/doug-martin/goqu/v9/internal/sb"
|
||||
)
|
||||
|
||||
// Dataset for creating and/or executing SELECT SQL statements.
|
||||
type SelectDataset struct {
|
||||
dialect SQLDialect
|
||||
clauses exp.SelectClauses
|
||||
isPrepared prepared
|
||||
queryFactory exec.QueryFactory
|
||||
err error
|
||||
}
|
||||
|
||||
var ErrQueryFactoryNotFoundError = errors.New(
|
||||
"unable to execute query did you use goqu.Database#From to create the dataset",
|
||||
)
|
||||
|
||||
// used internally by database to create a database with a specific adapter
|
||||
func newDataset(d string, queryFactory exec.QueryFactory) *SelectDataset {
|
||||
return &SelectDataset{
|
||||
clauses: exp.NewSelectClauses(),
|
||||
dialect: GetDialect(d),
|
||||
queryFactory: queryFactory,
|
||||
}
|
||||
}
|
||||
|
||||
func From(table ...interface{}) *SelectDataset {
|
||||
return newDataset("default", nil).From(table...)
|
||||
}
|
||||
|
||||
func Select(cols ...interface{}) *SelectDataset {
|
||||
return newDataset("default", nil).Select(cols...)
|
||||
}
|
||||
|
||||
// Sets the adapter used to serialize values and create the SQL statement
|
||||
func (sd *SelectDataset) WithDialect(dl string) *SelectDataset {
|
||||
ds := sd.copy(sd.GetClauses())
|
||||
ds.dialect = GetDialect(dl)
|
||||
return ds
|
||||
}
|
||||
|
||||
// Set the parameter interpolation behavior. See examples
|
||||
//
|
||||
// prepared: If true the dataset WILL NOT interpolate the parameters.
|
||||
func (sd *SelectDataset) Prepared(prepared bool) *SelectDataset {
|
||||
ret := sd.copy(sd.clauses)
|
||||
ret.isPrepared = preparedFromBool(prepared)
|
||||
return ret
|
||||
}
|
||||
|
||||
func (sd *SelectDataset) IsPrepared() bool {
|
||||
return sd.isPrepared.Bool()
|
||||
}
|
||||
|
||||
// Returns the current adapter on the dataset
|
||||
func (sd *SelectDataset) Dialect() SQLDialect {
|
||||
return sd.dialect
|
||||
}
|
||||
|
||||
// Returns the current adapter on the dataset
|
||||
func (sd *SelectDataset) SetDialect(dialect SQLDialect) *SelectDataset {
|
||||
cd := sd.copy(sd.GetClauses())
|
||||
cd.dialect = dialect
|
||||
return cd
|
||||
}
|
||||
|
||||
func (sd *SelectDataset) Expression() exp.Expression {
|
||||
return sd
|
||||
}
|
||||
|
||||
// Clones the dataset
|
||||
func (sd *SelectDataset) Clone() exp.Expression {
|
||||
return sd.copy(sd.clauses)
|
||||
}
|
||||
|
||||
// Returns the current clauses on the dataset.
|
||||
func (sd *SelectDataset) GetClauses() exp.SelectClauses {
|
||||
return sd.clauses
|
||||
}
|
||||
|
||||
// used interally to copy the dataset
|
||||
func (sd *SelectDataset) copy(clauses exp.SelectClauses) *SelectDataset {
|
||||
return &SelectDataset{
|
||||
dialect: sd.dialect,
|
||||
clauses: clauses,
|
||||
isPrepared: sd.isPrepared,
|
||||
queryFactory: sd.queryFactory,
|
||||
err: sd.err,
|
||||
}
|
||||
}
|
||||
|
||||
// Creates a new UpdateDataset using the FROM of this dataset. This method will also copy over the `WITH`, `WHERE`,
|
||||
// `ORDER , and `LIMIT`
|
||||
func (sd *SelectDataset) Update() *UpdateDataset {
|
||||
u := newUpdateDataset(sd.dialect.Dialect(), sd.queryFactory).
|
||||
Prepared(sd.isPrepared.Bool())
|
||||
if sd.clauses.HasSources() {
|
||||
u = u.Table(sd.GetClauses().From().Columns()[0])
|
||||
}
|
||||
c := u.clauses
|
||||
for _, ce := range sd.clauses.CommonTables() {
|
||||
c = c.CommonTablesAppend(ce)
|
||||
}
|
||||
if sd.clauses.Where() != nil {
|
||||
c = c.WhereAppend(sd.clauses.Where())
|
||||
}
|
||||
if sd.clauses.HasLimit() {
|
||||
c = c.SetLimit(sd.clauses.Limit())
|
||||
}
|
||||
if sd.clauses.HasOrder() {
|
||||
for _, oe := range sd.clauses.Order().Columns() {
|
||||
c = c.OrderAppend(oe.(exp.OrderedExpression))
|
||||
}
|
||||
}
|
||||
u.clauses = c
|
||||
return u
|
||||
}
|
||||
|
||||
// Creates a new InsertDataset using the FROM of this dataset. This method will also copy over the `WITH` clause to the
|
||||
// insert.
|
||||
func (sd *SelectDataset) Insert() *InsertDataset {
|
||||
i := newInsertDataset(sd.dialect.Dialect(), sd.queryFactory).
|
||||
Prepared(sd.isPrepared.Bool())
|
||||
if sd.clauses.HasSources() {
|
||||
i = i.Into(sd.GetClauses().From().Columns()[0])
|
||||
}
|
||||
c := i.clauses
|
||||
for _, ce := range sd.clauses.CommonTables() {
|
||||
c = c.CommonTablesAppend(ce)
|
||||
}
|
||||
i.clauses = c
|
||||
return i
|
||||
}
|
||||
|
||||
// Creates a new DeleteDataset using the FROM of this dataset. This method will also copy over the `WITH`, `WHERE`,
|
||||
// `ORDER , and `LIMIT`
|
||||
func (sd *SelectDataset) Delete() *DeleteDataset {
|
||||
d := newDeleteDataset(sd.dialect.Dialect(), sd.queryFactory).
|
||||
Prepared(sd.isPrepared.Bool())
|
||||
if sd.clauses.HasSources() {
|
||||
d = d.From(sd.clauses.From().Columns()[0])
|
||||
}
|
||||
c := d.clauses
|
||||
for _, ce := range sd.clauses.CommonTables() {
|
||||
c = c.CommonTablesAppend(ce)
|
||||
}
|
||||
if sd.clauses.Where() != nil {
|
||||
c = c.WhereAppend(sd.clauses.Where())
|
||||
}
|
||||
if sd.clauses.HasLimit() {
|
||||
c = c.SetLimit(sd.clauses.Limit())
|
||||
}
|
||||
if sd.clauses.HasOrder() {
|
||||
for _, oe := range sd.clauses.Order().Columns() {
|
||||
c = c.OrderAppend(oe.(exp.OrderedExpression))
|
||||
}
|
||||
}
|
||||
d.clauses = c
|
||||
return d
|
||||
}
|
||||
|
||||
// Creates a new TruncateDataset using the FROM of this dataset.
|
||||
func (sd *SelectDataset) Truncate() *TruncateDataset {
|
||||
td := newTruncateDataset(sd.dialect.Dialect(), sd.queryFactory)
|
||||
if sd.clauses.HasSources() {
|
||||
td = td.Table(sd.clauses.From())
|
||||
}
|
||||
return td
|
||||
}
|
||||
|
||||
// Creates a WITH clause for a common table expression (CTE).
|
||||
//
|
||||
// The name will be available to SELECT from in the associated query; and can optionally
|
||||
// contain a list of column names "name(col1, col2, col3)".
|
||||
//
|
||||
// The name will refer to the results of the specified subquery.
|
||||
func (sd *SelectDataset) With(name string, subquery exp.Expression) *SelectDataset {
|
||||
return sd.copy(sd.clauses.CommonTablesAppend(exp.NewCommonTableExpression(false, name, subquery)))
|
||||
}
|
||||
|
||||
// Creates a WITH RECURSIVE clause for a common table expression (CTE)
|
||||
//
|
||||
// The name will be available to SELECT from in the associated query; and must
|
||||
// contain a list of column names "name(col1, col2, col3)" for a recursive clause.
|
||||
//
|
||||
// The name will refer to the results of the specified subquery. The subquery for
|
||||
// a recursive query will always end with a UNION or UNION ALL with a clause that
|
||||
// refers to the CTE by name.
|
||||
func (sd *SelectDataset) WithRecursive(name string, subquery exp.Expression) *SelectDataset {
|
||||
return sd.copy(sd.clauses.CommonTablesAppend(exp.NewCommonTableExpression(true, name, subquery)))
|
||||
}
|
||||
|
||||
// Adds columns to the SELECT clause. See examples
|
||||
// You can pass in the following.
|
||||
// string: Will automatically be turned into an identifier
|
||||
// Dataset: Will use the SQL generated from that Dataset. If the dataset is aliased it will use that alias as the
|
||||
// column name.
|
||||
// LiteralExpression: (See Literal) Will use the literal SQL
|
||||
// SQLFunction: (See Func, MIN, MAX, COUNT....)
|
||||
// Struct: If passing in an instance of a struct, we will parse the struct for the column names to select.
|
||||
// See examples
|
||||
func (sd *SelectDataset) Select(selects ...interface{}) *SelectDataset {
|
||||
if len(selects) == 0 {
|
||||
return sd.ClearSelect()
|
||||
}
|
||||
return sd.copy(sd.clauses.SetSelect(exp.NewColumnListExpression(selects...)))
|
||||
}
|
||||
|
||||
// Adds columns to the SELECT DISTINCT clause. See examples
|
||||
// You can pass in the following.
|
||||
// string: Will automatically be turned into an identifier
|
||||
// Dataset: Will use the SQL generated from that Dataset. If the dataset is aliased it will use that alias as the
|
||||
// column name.
|
||||
// LiteralExpression: (See Literal) Will use the literal SQL
|
||||
// SQLFunction: (See Func, MIN, MAX, COUNT....)
|
||||
// Struct: If passing in an instance of a struct, we will parse the struct for the column names to select.
|
||||
// See examples
|
||||
// Deprecated: Use Distinct() instead.
|
||||
func (sd *SelectDataset) SelectDistinct(selects ...interface{}) *SelectDataset {
|
||||
if len(selects) == 0 {
|
||||
cleared := sd.ClearSelect()
|
||||
return cleared.copy(cleared.clauses.SetDistinct(nil))
|
||||
}
|
||||
return sd.copy(sd.clauses.SetSelect(exp.NewColumnListExpression(selects...)).SetDistinct(exp.NewColumnListExpression()))
|
||||
}
|
||||
|
||||
// Resets to SELECT *. If the SelectDistinct or Distinct was used the returned Dataset will have the the dataset set to SELECT *.
|
||||
// See examples.
|
||||
func (sd *SelectDataset) ClearSelect() *SelectDataset {
|
||||
return sd.copy(sd.clauses.SetSelect(exp.NewColumnListExpression(exp.Star())).SetDistinct(nil))
|
||||
}
|
||||
|
||||
// Adds columns to the SELECT clause. See examples
|
||||
// You can pass in the following.
|
||||
// string: Will automatically be turned into an identifier
|
||||
// Dataset: Will use the SQL generated from that Dataset. If the dataset is aliased it will use that alias as the
|
||||
// column name.
|
||||
// LiteralExpression: (See Literal) Will use the literal SQL
|
||||
// SQLFunction: (See Func, MIN, MAX, COUNT....)
|
||||
func (sd *SelectDataset) SelectAppend(selects ...interface{}) *SelectDataset {
|
||||
return sd.copy(sd.clauses.SelectAppend(exp.NewColumnListExpression(selects...)))
|
||||
}
|
||||
|
||||
func (sd *SelectDataset) Distinct(on ...interface{}) *SelectDataset {
|
||||
return sd.copy(sd.clauses.SetDistinct(exp.NewColumnListExpression(on...)))
|
||||
}
|
||||
|
||||
// Adds a FROM clause. This return a new dataset with the original sources replaced. See examples.
|
||||
// You can pass in the following.
|
||||
// string: Will automatically be turned into an identifier
|
||||
// Dataset: Will be added as a sub select. If the Dataset is not aliased it will automatically be aliased
|
||||
// LiteralExpression: (See Literal) Will use the literal SQL
|
||||
func (sd *SelectDataset) From(from ...interface{}) *SelectDataset {
|
||||
var sources []interface{}
|
||||
numSources := 0
|
||||
for _, source := range from {
|
||||
if ds, ok := source.(*SelectDataset); ok && !ds.clauses.HasAlias() {
|
||||
numSources++
|
||||
sources = append(sources, ds.As(fmt.Sprintf("t%d", numSources)))
|
||||
} else {
|
||||
sources = append(sources, source)
|
||||
}
|
||||
}
|
||||
return sd.copy(sd.clauses.SetFrom(exp.NewColumnListExpression(sources...)))
|
||||
}
|
||||
|
||||
// Returns a new Dataset with the current one as an source. If the current Dataset is not aliased (See Dataset#As) then
|
||||
// it will automatically be aliased. See examples.
|
||||
func (sd *SelectDataset) FromSelf() *SelectDataset {
|
||||
return sd.copy(exp.NewSelectClauses()).From(sd)
|
||||
}
|
||||
|
||||
// Alias to InnerJoin. See examples.
|
||||
func (sd *SelectDataset) Join(table exp.Expression, condition exp.JoinCondition) *SelectDataset {
|
||||
return sd.InnerJoin(table, condition)
|
||||
}
|
||||
|
||||
// Adds an INNER JOIN clause. See examples.
|
||||
func (sd *SelectDataset) InnerJoin(table exp.Expression, condition exp.JoinCondition) *SelectDataset {
|
||||
return sd.joinTable(exp.NewConditionedJoinExpression(exp.InnerJoinType, table, condition))
|
||||
}
|
||||
|
||||
// Adds a FULL OUTER JOIN clause. See examples.
|
||||
func (sd *SelectDataset) FullOuterJoin(table exp.Expression, condition exp.JoinCondition) *SelectDataset {
|
||||
return sd.joinTable(exp.NewConditionedJoinExpression(exp.FullOuterJoinType, table, condition))
|
||||
}
|
||||
|
||||
// Adds a RIGHT OUTER JOIN clause. See examples.
|
||||
func (sd *SelectDataset) RightOuterJoin(table exp.Expression, condition exp.JoinCondition) *SelectDataset {
|
||||
return sd.joinTable(exp.NewConditionedJoinExpression(exp.RightOuterJoinType, table, condition))
|
||||
}
|
||||
|
||||
// Adds a LEFT OUTER JOIN clause. See examples.
|
||||
func (sd *SelectDataset) LeftOuterJoin(table exp.Expression, condition exp.JoinCondition) *SelectDataset {
|
||||
return sd.joinTable(exp.NewConditionedJoinExpression(exp.LeftOuterJoinType, table, condition))
|
||||
}
|
||||
|
||||
// Adds a FULL JOIN clause. See examples.
|
||||
func (sd *SelectDataset) FullJoin(table exp.Expression, condition exp.JoinCondition) *SelectDataset {
|
||||
return sd.joinTable(exp.NewConditionedJoinExpression(exp.FullJoinType, table, condition))
|
||||
}
|
||||
|
||||
// Adds a RIGHT JOIN clause. See examples.
|
||||
func (sd *SelectDataset) RightJoin(table exp.Expression, condition exp.JoinCondition) *SelectDataset {
|
||||
return sd.joinTable(exp.NewConditionedJoinExpression(exp.RightJoinType, table, condition))
|
||||
}
|
||||
|
||||
// Adds a LEFT JOIN clause. See examples.
|
||||
func (sd *SelectDataset) LeftJoin(table exp.Expression, condition exp.JoinCondition) *SelectDataset {
|
||||
return sd.joinTable(exp.NewConditionedJoinExpression(exp.LeftJoinType, table, condition))
|
||||
}
|
||||
|
||||
// Adds a NATURAL JOIN clause. See examples.
|
||||
func (sd *SelectDataset) NaturalJoin(table exp.Expression) *SelectDataset {
|
||||
return sd.joinTable(exp.NewUnConditionedJoinExpression(exp.NaturalJoinType, table))
|
||||
}
|
||||
|
||||
// Adds a NATURAL LEFT JOIN clause. See examples.
|
||||
func (sd *SelectDataset) NaturalLeftJoin(table exp.Expression) *SelectDataset {
|
||||
return sd.joinTable(exp.NewUnConditionedJoinExpression(exp.NaturalLeftJoinType, table))
|
||||
}
|
||||
|
||||
// Adds a NATURAL RIGHT JOIN clause. See examples.
|
||||
func (sd *SelectDataset) NaturalRightJoin(table exp.Expression) *SelectDataset {
|
||||
return sd.joinTable(exp.NewUnConditionedJoinExpression(exp.NaturalRightJoinType, table))
|
||||
}
|
||||
|
||||
// Adds a NATURAL FULL JOIN clause. See examples.
|
||||
func (sd *SelectDataset) NaturalFullJoin(table exp.Expression) *SelectDataset {
|
||||
return sd.joinTable(exp.NewUnConditionedJoinExpression(exp.NaturalFullJoinType, table))
|
||||
}
|
||||
|
||||
// Adds a CROSS JOIN clause. See examples.
|
||||
func (sd *SelectDataset) CrossJoin(table exp.Expression) *SelectDataset {
|
||||
return sd.joinTable(exp.NewUnConditionedJoinExpression(exp.CrossJoinType, table))
|
||||
}
|
||||
|
||||
// Joins this Datasets table with another
|
||||
func (sd *SelectDataset) joinTable(join exp.JoinExpression) *SelectDataset {
|
||||
return sd.copy(sd.clauses.JoinsAppend(join))
|
||||
}
|
||||
|
||||
// Adds a WHERE clause. See examples.
|
||||
func (sd *SelectDataset) Where(expressions ...exp.Expression) *SelectDataset {
|
||||
return sd.copy(sd.clauses.WhereAppend(expressions...))
|
||||
}
|
||||
|
||||
// Removes the WHERE clause. See examples.
|
||||
func (sd *SelectDataset) ClearWhere() *SelectDataset {
|
||||
return sd.copy(sd.clauses.ClearWhere())
|
||||
}
|
||||
|
||||
// Adds a FOR UPDATE clause. See examples.
|
||||
func (sd *SelectDataset) ForUpdate(waitOption exp.WaitOption, of ...exp.IdentifierExpression) *SelectDataset {
|
||||
return sd.withLock(exp.ForUpdate, waitOption, of...)
|
||||
}
|
||||
|
||||
// Adds a FOR NO KEY UPDATE clause. See examples.
|
||||
func (sd *SelectDataset) ForNoKeyUpdate(waitOption exp.WaitOption, of ...exp.IdentifierExpression) *SelectDataset {
|
||||
return sd.withLock(exp.ForNoKeyUpdate, waitOption, of...)
|
||||
}
|
||||
|
||||
// Adds a FOR KEY SHARE clause. See examples.
|
||||
func (sd *SelectDataset) ForKeyShare(waitOption exp.WaitOption, of ...exp.IdentifierExpression) *SelectDataset {
|
||||
return sd.withLock(exp.ForKeyShare, waitOption, of...)
|
||||
}
|
||||
|
||||
// Adds a FOR SHARE clause. See examples.
|
||||
func (sd *SelectDataset) ForShare(waitOption exp.WaitOption, of ...exp.IdentifierExpression) *SelectDataset {
|
||||
return sd.withLock(exp.ForShare, waitOption, of...)
|
||||
}
|
||||
|
||||
func (sd *SelectDataset) withLock(strength exp.LockStrength, option exp.WaitOption, of ...exp.IdentifierExpression) *SelectDataset {
|
||||
return sd.copy(sd.clauses.SetLock(exp.NewLock(strength, option, of...)))
|
||||
}
|
||||
|
||||
// Adds a GROUP BY clause. See examples.
|
||||
func (sd *SelectDataset) GroupBy(groupBy ...interface{}) *SelectDataset {
|
||||
return sd.copy(sd.clauses.SetGroupBy(exp.NewColumnListExpression(groupBy...)))
|
||||
}
|
||||
|
||||
// Adds more columns to the current GROUP BY clause. See examples.
|
||||
func (sd *SelectDataset) GroupByAppend(groupBy ...interface{}) *SelectDataset {
|
||||
return sd.copy(sd.clauses.GroupByAppend(exp.NewColumnListExpression(groupBy...)))
|
||||
}
|
||||
|
||||
// Adds a HAVING clause. See examples.
|
||||
func (sd *SelectDataset) Having(expressions ...exp.Expression) *SelectDataset {
|
||||
return sd.copy(sd.clauses.HavingAppend(expressions...))
|
||||
}
|
||||
|
||||
// Adds a ORDER clause. If the ORDER is currently set it replaces it. See examples.
|
||||
func (sd *SelectDataset) Order(order ...exp.OrderedExpression) *SelectDataset {
|
||||
return sd.copy(sd.clauses.SetOrder(order...))
|
||||
}
|
||||
|
||||
// Adds a more columns to the current ORDER BY clause. If no order has be previously specified it is the same as
|
||||
// calling Order. See examples.
|
||||
func (sd *SelectDataset) OrderAppend(order ...exp.OrderedExpression) *SelectDataset {
|
||||
return sd.copy(sd.clauses.OrderAppend(order...))
|
||||
}
|
||||
|
||||
// Adds a more columns to the beginning of the current ORDER BY clause. If no order has be previously specified it is the same as
|
||||
// calling Order. See examples.
|
||||
func (sd *SelectDataset) OrderPrepend(order ...exp.OrderedExpression) *SelectDataset {
|
||||
return sd.copy(sd.clauses.OrderPrepend(order...))
|
||||
}
|
||||
|
||||
// Removes the ORDER BY clause. See examples.
|
||||
func (sd *SelectDataset) ClearOrder() *SelectDataset {
|
||||
return sd.copy(sd.clauses.ClearOrder())
|
||||
}
|
||||
|
||||
// Adds a LIMIT clause. If the LIMIT is currently set it replaces it. See examples.
|
||||
func (sd *SelectDataset) Limit(limit uint) *SelectDataset {
|
||||
if limit > 0 {
|
||||
return sd.copy(sd.clauses.SetLimit(limit))
|
||||
}
|
||||
return sd.copy(sd.clauses.ClearLimit())
|
||||
}
|
||||
|
||||
// Adds a LIMIT ALL clause. If the LIMIT is currently set it replaces it. See examples.
|
||||
func (sd *SelectDataset) LimitAll() *SelectDataset {
|
||||
return sd.copy(sd.clauses.SetLimit(L("ALL")))
|
||||
}
|
||||
|
||||
// Removes the LIMIT clause.
|
||||
func (sd *SelectDataset) ClearLimit() *SelectDataset {
|
||||
return sd.copy(sd.clauses.ClearLimit())
|
||||
}
|
||||
|
||||
// Adds an OFFSET clause. If the OFFSET is currently set it replaces it. See examples.
|
||||
func (sd *SelectDataset) Offset(offset uint) *SelectDataset {
|
||||
return sd.copy(sd.clauses.SetOffset(offset))
|
||||
}
|
||||
|
||||
// Removes the OFFSET clause from the Dataset
|
||||
func (sd *SelectDataset) ClearOffset() *SelectDataset {
|
||||
return sd.copy(sd.clauses.ClearOffset())
|
||||
}
|
||||
|
||||
// Creates an UNION statement with another dataset.
|
||||
// If this or the other dataset has a limit or offset it will use that dataset as a subselect in the FROM clause.
|
||||
// See examples.
|
||||
func (sd *SelectDataset) Union(other *SelectDataset) *SelectDataset {
|
||||
return sd.withCompound(exp.UnionCompoundType, other.CompoundFromSelf())
|
||||
}
|
||||
|
||||
// Creates an UNION ALL statement with another dataset.
|
||||
// If this or the other dataset has a limit or offset it will use that dataset as a subselect in the FROM clause.
|
||||
// See examples.
|
||||
func (sd *SelectDataset) UnionAll(other *SelectDataset) *SelectDataset {
|
||||
return sd.withCompound(exp.UnionAllCompoundType, other.CompoundFromSelf())
|
||||
}
|
||||
|
||||
// Creates an INTERSECT statement with another dataset.
|
||||
// If this or the other dataset has a limit or offset it will use that dataset as a subselect in the FROM clause.
|
||||
// See examples.
|
||||
func (sd *SelectDataset) Intersect(other *SelectDataset) *SelectDataset {
|
||||
return sd.withCompound(exp.IntersectCompoundType, other.CompoundFromSelf())
|
||||
}
|
||||
|
||||
// Creates an INTERSECT ALL statement with another dataset.
|
||||
// If this or the other dataset has a limit or offset it will use that dataset as a subselect in the FROM clause.
|
||||
// See examples.
|
||||
func (sd *SelectDataset) IntersectAll(other *SelectDataset) *SelectDataset {
|
||||
return sd.withCompound(exp.IntersectAllCompoundType, other.CompoundFromSelf())
|
||||
}
|
||||
|
||||
func (sd *SelectDataset) withCompound(ct exp.CompoundType, other exp.AppendableExpression) *SelectDataset {
|
||||
ce := exp.NewCompoundExpression(ct, other)
|
||||
ret := sd.CompoundFromSelf()
|
||||
ret.clauses = ret.clauses.CompoundsAppend(ce)
|
||||
return ret
|
||||
}
|
||||
|
||||
// Used internally to determine if the dataset needs to use iteself as a source.
|
||||
// If the dataset has an order or limit it will select from itself
|
||||
func (sd *SelectDataset) CompoundFromSelf() *SelectDataset {
|
||||
if sd.clauses.HasOrder() || sd.clauses.HasLimit() {
|
||||
return sd.FromSelf()
|
||||
}
|
||||
return sd.copy(sd.clauses)
|
||||
}
|
||||
|
||||
// Sets the alias for this dataset. This is typically used when using a Dataset as a subselect. See examples.
|
||||
func (sd *SelectDataset) As(alias string) *SelectDataset {
|
||||
return sd.copy(sd.clauses.SetAlias(T(alias)))
|
||||
}
|
||||
|
||||
// Returns the alias value as an identiier expression
|
||||
func (sd *SelectDataset) GetAs() exp.IdentifierExpression {
|
||||
return sd.clauses.Alias()
|
||||
}
|
||||
|
||||
// Sets the WINDOW clauses
|
||||
func (sd *SelectDataset) Window(ws ...exp.WindowExpression) *SelectDataset {
|
||||
return sd.copy(sd.clauses.SetWindows(ws))
|
||||
}
|
||||
|
||||
// Sets the WINDOW clauses
|
||||
func (sd *SelectDataset) WindowAppend(ws ...exp.WindowExpression) *SelectDataset {
|
||||
return sd.copy(sd.clauses.WindowsAppend(ws...))
|
||||
}
|
||||
|
||||
// Sets the WINDOW clauses
|
||||
func (sd *SelectDataset) ClearWindow() *SelectDataset {
|
||||
return sd.copy(sd.clauses.ClearWindows())
|
||||
}
|
||||
|
||||
// Get any error that has been set or nil if no error has been set.
|
||||
func (sd *SelectDataset) Error() error {
|
||||
return sd.err
|
||||
}
|
||||
|
||||
// Set an error on the dataset if one has not already been set. This error will be returned by a future call to Error
|
||||
// or as part of ToSQL. This can be used by end users to record errors while building up queries without having to
|
||||
// track those separately.
|
||||
func (sd *SelectDataset) SetError(err error) *SelectDataset {
|
||||
if sd.err == nil {
|
||||
sd.err = err
|
||||
}
|
||||
|
||||
return sd
|
||||
}
|
||||
|
||||
// Generates a SELECT sql statement, if Prepared has been called with true then the parameters will not be interpolated.
|
||||
// See examples.
|
||||
//
|
||||
// Errors:
|
||||
// * There is an error generating the SQL
|
||||
func (sd *SelectDataset) ToSQL() (sql string, params []interface{}, err error) {
|
||||
return sd.selectSQLBuilder().ToSQL()
|
||||
}
|
||||
|
||||
// Generates the SELECT sql, and returns an Exec struct with the sql set to the SELECT statement
|
||||
// db.From("test").Select("col").Executor()
|
||||
//
|
||||
// See Dataset#ToUpdateSQL for arguments
|
||||
func (sd *SelectDataset) Executor() exec.QueryExecutor {
|
||||
return sd.queryFactory.FromSQLBuilder(sd.selectSQLBuilder())
|
||||
}
|
||||
|
||||
// Appends this Dataset's SELECT statement to the SQLBuilder
|
||||
// This is used internally for sub-selects by the dialect
|
||||
func (sd *SelectDataset) AppendSQL(b sb.SQLBuilder) {
|
||||
if sd.err != nil {
|
||||
b.SetError(sd.err)
|
||||
return
|
||||
}
|
||||
sd.dialect.ToSelectSQL(b, sd.GetClauses())
|
||||
}
|
||||
|
||||
func (sd *SelectDataset) ReturnsColumns() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// Generates the SELECT sql for this dataset and uses Exec#ScanStructs to scan the results into a slice of structs.
|
||||
//
|
||||
// ScanStructs will only select the columns that can be scanned in to the struct unless you have explicitly selected
|
||||
// certain columns. See examples.
|
||||
//
|
||||
// i: A pointer to a slice of structs
|
||||
func (sd *SelectDataset) ScanStructs(i interface{}) error {
|
||||
return sd.ScanStructsContext(context.Background(), i)
|
||||
}
|
||||
|
||||
// Generates the SELECT sql for this dataset and uses Exec#ScanStructsContext to scan the results into a slice of
|
||||
// structs.
|
||||
//
|
||||
// ScanStructsContext will only select the columns that can be scanned in to the struct unless you have explicitly
|
||||
// selected certain columns. See examples.
|
||||
//
|
||||
// i: A pointer to a slice of structs
|
||||
func (sd *SelectDataset) ScanStructsContext(ctx context.Context, i interface{}) error {
|
||||
if sd.queryFactory == nil {
|
||||
return ErrQueryFactoryNotFoundError
|
||||
}
|
||||
ds := sd
|
||||
if sd.GetClauses().IsDefaultSelect() {
|
||||
ds = sd.Select(i)
|
||||
}
|
||||
return ds.Executor().ScanStructsContext(ctx, i)
|
||||
}
|
||||
|
||||
// Generates the SELECT sql for this dataset and uses Exec#ScanStruct to scan the result into a slice of structs
|
||||
//
|
||||
// ScanStruct will only select the columns that can be scanned in to the struct unless you have explicitly selected
|
||||
// certain columns. See examples.
|
||||
//
|
||||
// i: A pointer to a structs
|
||||
func (sd *SelectDataset) ScanStruct(i interface{}) (bool, error) {
|
||||
return sd.ScanStructContext(context.Background(), i)
|
||||
}
|
||||
|
||||
// Generates the SELECT sql for this dataset and uses Exec#ScanStructContext to scan the result into a slice of structs
|
||||
//
|
||||
// ScanStructContext will only select the columns that can be scanned in to the struct unless you have explicitly
|
||||
// selected certain columns. See examples.
|
||||
//
|
||||
// i: A pointer to a structs
|
||||
func (sd *SelectDataset) ScanStructContext(ctx context.Context, i interface{}) (bool, error) {
|
||||
if sd.queryFactory == nil {
|
||||
return false, ErrQueryFactoryNotFoundError
|
||||
}
|
||||
ds := sd
|
||||
if sd.GetClauses().IsDefaultSelect() {
|
||||
ds = sd.Select(i)
|
||||
}
|
||||
return ds.Limit(1).Executor().ScanStructContext(ctx, i)
|
||||
}
|
||||
|
||||
// Generates the SELECT sql for this dataset and uses Exec#ScanVals to scan the results into a slice of primitive values
|
||||
//
|
||||
// i: A pointer to a slice of primitive values
|
||||
func (sd *SelectDataset) ScanVals(i interface{}) error {
|
||||
return sd.ScanValsContext(context.Background(), i)
|
||||
}
|
||||
|
||||
// Generates the SELECT sql for this dataset and uses Exec#ScanValsContext to scan the results into a slice of primitive
|
||||
// values
|
||||
//
|
||||
// i: A pointer to a slice of primitive values
|
||||
func (sd *SelectDataset) ScanValsContext(ctx context.Context, i interface{}) error {
|
||||
if sd.queryFactory == nil {
|
||||
return ErrQueryFactoryNotFoundError
|
||||
}
|
||||
return sd.Executor().ScanValsContext(ctx, i)
|
||||
}
|
||||
|
||||
// Generates the SELECT sql for this dataset and uses Exec#ScanVal to scan the result into a primitive value
|
||||
//
|
||||
// i: A pointer to a primitive value
|
||||
func (sd *SelectDataset) ScanVal(i interface{}) (bool, error) {
|
||||
return sd.ScanValContext(context.Background(), i)
|
||||
}
|
||||
|
||||
// Generates the SELECT sql for this dataset and uses Exec#ScanValContext to scan the result into a primitive value
|
||||
//
|
||||
// i: A pointer to a primitive value
|
||||
func (sd *SelectDataset) ScanValContext(ctx context.Context, i interface{}) (bool, error) {
|
||||
if sd.queryFactory == nil {
|
||||
return false, ErrQueryFactoryNotFoundError
|
||||
}
|
||||
return sd.Limit(1).Executor().ScanValContext(ctx, i)
|
||||
}
|
||||
|
||||
// Generates the SELECT COUNT(*) sql for this dataset and uses Exec#ScanVal to scan the result into an int64.
|
||||
func (sd *SelectDataset) Count() (int64, error) {
|
||||
return sd.CountContext(context.Background())
|
||||
}
|
||||
|
||||
// Generates the SELECT COUNT(*) sql for this dataset and uses Exec#ScanValContext to scan the result into an int64.
|
||||
func (sd *SelectDataset) CountContext(ctx context.Context) (int64, error) {
|
||||
var count int64
|
||||
_, err := sd.Select(COUNT(Star()).As("count")).ScanValContext(ctx, &count)
|
||||
return count, err
|
||||
}
|
||||
|
||||
// Generates the SELECT sql only selecting the passed in column and uses Exec#ScanVals to scan the result into a slice
|
||||
// of primitive values.
|
||||
//
|
||||
// i: A slice of primitive values
|
||||
//
|
||||
// col: The column to select when generative the SQL
|
||||
func (sd *SelectDataset) Pluck(i interface{}, col string) error {
|
||||
return sd.PluckContext(context.Background(), i, col)
|
||||
}
|
||||
|
||||
// Generates the SELECT sql only selecting the passed in column and uses Exec#ScanValsContext to scan the result into a
|
||||
// slice of primitive values.
|
||||
//
|
||||
// i: A slice of primitive values
|
||||
//
|
||||
// col: The column to select when generative the SQL
|
||||
func (sd *SelectDataset) PluckContext(ctx context.Context, i interface{}, col string) error {
|
||||
return sd.Select(col).ScanValsContext(ctx, i)
|
||||
}
|
||||
|
||||
func (sd *SelectDataset) selectSQLBuilder() sb.SQLBuilder {
|
||||
buf := sb.NewSQLBuilder(sd.isPrepared.Bool())
|
||||
if sd.err != nil {
|
||||
return buf.SetError(sd.err)
|
||||
}
|
||||
sd.dialect.ToSelectSQL(buf, sd.GetClauses())
|
||||
return buf
|
||||
}
|
||||
103
vendor/github.com/doug-martin/goqu/v9/sql_dialect.go
generated
vendored
Normal file
103
vendor/github.com/doug-martin/goqu/v9/sql_dialect.go
generated
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
package goqu
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/doug-martin/goqu/v9/exp"
|
||||
"github.com/doug-martin/goqu/v9/internal/sb"
|
||||
"github.com/doug-martin/goqu/v9/sqlgen"
|
||||
)
|
||||
|
||||
type (
|
||||
SQLDialectOptions = sqlgen.SQLDialectOptions
|
||||
// An adapter interface to be used by a Dataset to generate SQL for a specific dialect.
|
||||
// See DefaultAdapter for a concrete implementation and examples.
|
||||
SQLDialect interface {
|
||||
Dialect() string
|
||||
ToSelectSQL(b sb.SQLBuilder, clauses exp.SelectClauses)
|
||||
ToUpdateSQL(b sb.SQLBuilder, clauses exp.UpdateClauses)
|
||||
ToInsertSQL(b sb.SQLBuilder, clauses exp.InsertClauses)
|
||||
ToDeleteSQL(b sb.SQLBuilder, clauses exp.DeleteClauses)
|
||||
ToTruncateSQL(b sb.SQLBuilder, clauses exp.TruncateClauses)
|
||||
}
|
||||
// The default adapter. This class should be used when building a new adapter. When creating a new adapter you can
|
||||
// either override methods, or more typically update default values.
|
||||
// See (github.com/doug-martin/goqu/dialect/postgres)
|
||||
sqlDialect struct {
|
||||
dialect string
|
||||
dialectOptions *SQLDialectOptions
|
||||
selectGen sqlgen.SelectSQLGenerator
|
||||
updateGen sqlgen.UpdateSQLGenerator
|
||||
insertGen sqlgen.InsertSQLGenerator
|
||||
deleteGen sqlgen.DeleteSQLGenerator
|
||||
truncateGen sqlgen.TruncateSQLGenerator
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
dialects = make(map[string]SQLDialect)
|
||||
DefaultDialectOptions = sqlgen.DefaultDialectOptions
|
||||
dialectsMu sync.RWMutex
|
||||
)
|
||||
|
||||
func init() {
|
||||
RegisterDialect("default", DefaultDialectOptions())
|
||||
}
|
||||
|
||||
func RegisterDialect(name string, do *SQLDialectOptions) {
|
||||
dialectsMu.Lock()
|
||||
defer dialectsMu.Unlock()
|
||||
lowerName := strings.ToLower(name)
|
||||
dialects[lowerName] = newDialect(lowerName, do)
|
||||
}
|
||||
|
||||
func DeregisterDialect(name string) {
|
||||
dialectsMu.Lock()
|
||||
defer dialectsMu.Unlock()
|
||||
delete(dialects, strings.ToLower(name))
|
||||
}
|
||||
|
||||
func GetDialect(name string) SQLDialect {
|
||||
name = strings.ToLower(name)
|
||||
if d, ok := dialects[name]; ok {
|
||||
return d
|
||||
}
|
||||
return newDialect("default", DefaultDialectOptions())
|
||||
}
|
||||
|
||||
func newDialect(dialect string, do *SQLDialectOptions) SQLDialect {
|
||||
return &sqlDialect{
|
||||
dialect: dialect,
|
||||
dialectOptions: do,
|
||||
selectGen: sqlgen.NewSelectSQLGenerator(dialect, do),
|
||||
updateGen: sqlgen.NewUpdateSQLGenerator(dialect, do),
|
||||
insertGen: sqlgen.NewInsertSQLGenerator(dialect, do),
|
||||
deleteGen: sqlgen.NewDeleteSQLGenerator(dialect, do),
|
||||
truncateGen: sqlgen.NewTruncateSQLGenerator(dialect, do),
|
||||
}
|
||||
}
|
||||
|
||||
func (d *sqlDialect) Dialect() string {
|
||||
return d.dialect
|
||||
}
|
||||
|
||||
func (d *sqlDialect) ToSelectSQL(b sb.SQLBuilder, clauses exp.SelectClauses) {
|
||||
d.selectGen.Generate(b, clauses)
|
||||
}
|
||||
|
||||
func (d *sqlDialect) ToUpdateSQL(b sb.SQLBuilder, clauses exp.UpdateClauses) {
|
||||
d.updateGen.Generate(b, clauses)
|
||||
}
|
||||
|
||||
func (d *sqlDialect) ToInsertSQL(b sb.SQLBuilder, clauses exp.InsertClauses) {
|
||||
d.insertGen.Generate(b, clauses)
|
||||
}
|
||||
|
||||
func (d *sqlDialect) ToDeleteSQL(b sb.SQLBuilder, clauses exp.DeleteClauses) {
|
||||
d.deleteGen.Generate(b, clauses)
|
||||
}
|
||||
|
||||
func (d *sqlDialect) ToTruncateSQL(b sb.SQLBuilder, clauses exp.TruncateClauses) {
|
||||
d.truncateGen.Generate(b, clauses)
|
||||
}
|
||||
155
vendor/github.com/doug-martin/goqu/v9/sqlgen/common_sql_generator.go
generated
vendored
Normal file
155
vendor/github.com/doug-martin/goqu/v9/sqlgen/common_sql_generator.go
generated
vendored
Normal file
@@ -0,0 +1,155 @@
|
||||
package sqlgen
|
||||
|
||||
import (
|
||||
"github.com/doug-martin/goqu/v9/exp"
|
||||
"github.com/doug-martin/goqu/v9/internal/errors"
|
||||
"github.com/doug-martin/goqu/v9/internal/sb"
|
||||
)
|
||||
|
||||
var ErrNoUpdatedValuesProvided = errors.New("no update values provided")
|
||||
|
||||
func ErrCTENotSupported(dialect string) error {
|
||||
return errors.New("dialect does not support CTE WITH clause [dialect=%s]", dialect)
|
||||
}
|
||||
|
||||
func ErrRecursiveCTENotSupported(dialect string) error {
|
||||
return errors.New("dialect does not support CTE WITH RECURSIVE clause [dialect=%s]", dialect)
|
||||
}
|
||||
|
||||
func ErrReturnNotSupported(dialect string) error {
|
||||
return errors.New("dialect does not support RETURNING clause [dialect=%s]", dialect)
|
||||
}
|
||||
|
||||
func ErrNotSupportedFragment(sqlType string, f SQLFragmentType) error {
|
||||
return errors.New("unsupported %s SQL fragment %s", sqlType, f)
|
||||
}
|
||||
|
||||
type (
|
||||
CommonSQLGenerator interface {
|
||||
Dialect() string
|
||||
DialectOptions() *SQLDialectOptions
|
||||
ExpressionSQLGenerator() ExpressionSQLGenerator
|
||||
ReturningSQL(b sb.SQLBuilder, returns exp.ColumnListExpression)
|
||||
FromSQL(b sb.SQLBuilder, from exp.ColumnListExpression)
|
||||
SourcesSQL(b sb.SQLBuilder, from exp.ColumnListExpression)
|
||||
WhereSQL(b sb.SQLBuilder, where exp.ExpressionList)
|
||||
OrderSQL(b sb.SQLBuilder, order exp.ColumnListExpression)
|
||||
OrderWithOffsetFetchSQL(b sb.SQLBuilder, order exp.ColumnListExpression, offset uint, limit interface{})
|
||||
LimitSQL(b sb.SQLBuilder, limit interface{})
|
||||
UpdateExpressionSQL(b sb.SQLBuilder, updates ...exp.UpdateExpression)
|
||||
}
|
||||
commonSQLGenerator struct {
|
||||
dialect string
|
||||
esg ExpressionSQLGenerator
|
||||
dialectOptions *SQLDialectOptions
|
||||
}
|
||||
)
|
||||
|
||||
func NewCommonSQLGenerator(dialect string, do *SQLDialectOptions) CommonSQLGenerator {
|
||||
return &commonSQLGenerator{dialect: dialect, esg: NewExpressionSQLGenerator(dialect, do), dialectOptions: do}
|
||||
}
|
||||
|
||||
func (csg *commonSQLGenerator) Dialect() string {
|
||||
return csg.dialect
|
||||
}
|
||||
|
||||
func (csg *commonSQLGenerator) DialectOptions() *SQLDialectOptions {
|
||||
return csg.dialectOptions
|
||||
}
|
||||
|
||||
func (csg *commonSQLGenerator) ExpressionSQLGenerator() ExpressionSQLGenerator {
|
||||
return csg.esg
|
||||
}
|
||||
|
||||
func (csg *commonSQLGenerator) ReturningSQL(b sb.SQLBuilder, returns exp.ColumnListExpression) {
|
||||
if returns != nil && len(returns.Columns()) > 0 {
|
||||
if csg.dialectOptions.SupportsReturn {
|
||||
b.Write(csg.dialectOptions.ReturningFragment)
|
||||
csg.esg.Generate(b, returns)
|
||||
} else {
|
||||
b.SetError(ErrReturnNotSupported(csg.dialect))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Adds the FROM clause and tables to an sql statement
|
||||
func (csg *commonSQLGenerator) FromSQL(b sb.SQLBuilder, from exp.ColumnListExpression) {
|
||||
if from != nil && !from.IsEmpty() {
|
||||
b.Write(csg.dialectOptions.FromFragment)
|
||||
csg.SourcesSQL(b, from)
|
||||
}
|
||||
}
|
||||
|
||||
// Adds the generates the SQL for a column list
|
||||
func (csg *commonSQLGenerator) SourcesSQL(b sb.SQLBuilder, from exp.ColumnListExpression) {
|
||||
b.WriteRunes(csg.dialectOptions.SpaceRune)
|
||||
csg.esg.Generate(b, from)
|
||||
}
|
||||
|
||||
// Generates the WHERE clause for an SQL statement
|
||||
func (csg *commonSQLGenerator) WhereSQL(b sb.SQLBuilder, where exp.ExpressionList) {
|
||||
if where != nil && !where.IsEmpty() {
|
||||
b.Write(csg.dialectOptions.WhereFragment)
|
||||
csg.esg.Generate(b, where)
|
||||
}
|
||||
}
|
||||
|
||||
// Generates the ORDER BY clause for an SQL statement
|
||||
func (csg *commonSQLGenerator) OrderSQL(b sb.SQLBuilder, order exp.ColumnListExpression) {
|
||||
if order != nil && len(order.Columns()) > 0 {
|
||||
b.Write(csg.dialectOptions.OrderByFragment)
|
||||
csg.esg.Generate(b, order)
|
||||
}
|
||||
}
|
||||
|
||||
func (csg *commonSQLGenerator) OrderWithOffsetFetchSQL(
|
||||
b sb.SQLBuilder,
|
||||
order exp.ColumnListExpression,
|
||||
offset uint,
|
||||
limit interface{},
|
||||
) {
|
||||
if order == nil {
|
||||
return
|
||||
}
|
||||
|
||||
csg.OrderSQL(b, order)
|
||||
if offset > 0 {
|
||||
b.Write(csg.dialectOptions.OffsetFragment)
|
||||
csg.esg.Generate(b, offset)
|
||||
b.Write([]byte(" ROWS"))
|
||||
|
||||
if limit != nil {
|
||||
b.Write(csg.dialectOptions.FetchFragment)
|
||||
csg.esg.Generate(b, limit)
|
||||
b.Write([]byte(" ROWS ONLY"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Generates the LIMIT clause for an SQL statement
|
||||
func (csg *commonSQLGenerator) LimitSQL(b sb.SQLBuilder, limit interface{}) {
|
||||
if limit != nil {
|
||||
b.Write(csg.dialectOptions.LimitFragment)
|
||||
if csg.dialectOptions.SurroundLimitWithParentheses {
|
||||
b.WriteRunes(csg.dialectOptions.LeftParenRune)
|
||||
}
|
||||
csg.esg.Generate(b, limit)
|
||||
if csg.dialectOptions.SurroundLimitWithParentheses {
|
||||
b.WriteRunes(csg.dialectOptions.RightParenRune)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (csg *commonSQLGenerator) UpdateExpressionSQL(b sb.SQLBuilder, updates ...exp.UpdateExpression) {
|
||||
if len(updates) == 0 {
|
||||
b.SetError(ErrNoUpdatedValuesProvided)
|
||||
return
|
||||
}
|
||||
updateLen := len(updates)
|
||||
for i, update := range updates {
|
||||
csg.esg.Generate(b, update)
|
||||
if i < updateLen-1 {
|
||||
b.WriteRunes(csg.dialectOptions.CommaRune)
|
||||
}
|
||||
}
|
||||
}
|
||||
72
vendor/github.com/doug-martin/goqu/v9/sqlgen/delete_sql_generator.go
generated
vendored
Normal file
72
vendor/github.com/doug-martin/goqu/v9/sqlgen/delete_sql_generator.go
generated
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
package sqlgen
|
||||
|
||||
import (
|
||||
"github.com/doug-martin/goqu/v9/exp"
|
||||
"github.com/doug-martin/goqu/v9/internal/errors"
|
||||
"github.com/doug-martin/goqu/v9/internal/sb"
|
||||
)
|
||||
|
||||
type (
|
||||
// An adapter interface to be used by a Dataset to generate SQL for a specific dialect.
|
||||
// See DefaultAdapter for a concrete implementation and examples.
|
||||
DeleteSQLGenerator interface {
|
||||
Dialect() string
|
||||
Generate(b sb.SQLBuilder, clauses exp.DeleteClauses)
|
||||
}
|
||||
// The default adapter. This class should be used when building a new adapter. When creating a new adapter you can
|
||||
// either override methods, or more typically update default values.
|
||||
// See (github.com/doug-martin/goqu/dialect/postgres)
|
||||
deleteSQLGenerator struct {
|
||||
CommonSQLGenerator
|
||||
}
|
||||
)
|
||||
|
||||
var ErrNoSourceForDelete = errors.New("no source found when generating delete sql")
|
||||
|
||||
func NewDeleteSQLGenerator(dialect string, do *SQLDialectOptions) DeleteSQLGenerator {
|
||||
return &deleteSQLGenerator{NewCommonSQLGenerator(dialect, do)}
|
||||
}
|
||||
|
||||
func (dsg *deleteSQLGenerator) Generate(b sb.SQLBuilder, clauses exp.DeleteClauses) {
|
||||
if !clauses.HasFrom() {
|
||||
b.SetError(ErrNoSourceForDelete)
|
||||
return
|
||||
}
|
||||
for _, f := range dsg.DialectOptions().DeleteSQLOrder {
|
||||
if b.Error() != nil {
|
||||
return
|
||||
}
|
||||
switch f {
|
||||
case CommonTableSQLFragment:
|
||||
dsg.ExpressionSQLGenerator().Generate(b, clauses.CommonTables())
|
||||
case DeleteBeginSQLFragment:
|
||||
dsg.DeleteBeginSQL(
|
||||
b, exp.NewColumnListExpression(clauses.From()), !(clauses.HasLimit() || clauses.HasOrder()),
|
||||
)
|
||||
case FromSQLFragment:
|
||||
dsg.FromSQL(b, exp.NewColumnListExpression(clauses.From()))
|
||||
case WhereSQLFragment:
|
||||
dsg.WhereSQL(b, clauses.Where())
|
||||
case OrderSQLFragment:
|
||||
if dsg.DialectOptions().SupportsOrderByOnDelete {
|
||||
dsg.OrderSQL(b, clauses.Order())
|
||||
}
|
||||
case LimitSQLFragment:
|
||||
if dsg.DialectOptions().SupportsLimitOnDelete {
|
||||
dsg.LimitSQL(b, clauses.Limit())
|
||||
}
|
||||
case ReturningSQLFragment:
|
||||
dsg.ReturningSQL(b, clauses.Returning())
|
||||
default:
|
||||
b.SetError(ErrNotSupportedFragment("DELETE", f))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Adds the correct fragment to being an DELETE statement
|
||||
func (dsg *deleteSQLGenerator) DeleteBeginSQL(b sb.SQLBuilder, from exp.ColumnListExpression, multiTable bool) {
|
||||
b.Write(dsg.DialectOptions().DeleteClause)
|
||||
if multiTable && dsg.DialectOptions().SupportsDeleteTableHint {
|
||||
dsg.SourcesSQL(b, from)
|
||||
}
|
||||
}
|
||||
733
vendor/github.com/doug-martin/goqu/v9/sqlgen/expression_sql_generator.go
generated
vendored
Normal file
733
vendor/github.com/doug-martin/goqu/v9/sqlgen/expression_sql_generator.go
generated
vendored
Normal file
@@ -0,0 +1,733 @@
|
||||
package sqlgen
|
||||
|
||||
import (
|
||||
"database/sql/driver"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/doug-martin/goqu/v9/exp"
|
||||
"github.com/doug-martin/goqu/v9/internal/errors"
|
||||
"github.com/doug-martin/goqu/v9/internal/sb"
|
||||
"github.com/doug-martin/goqu/v9/internal/util"
|
||||
)
|
||||
|
||||
type (
|
||||
// An adapter interface to be used by a Dataset to generate SQL for a specific dialect.
|
||||
// See DefaultAdapter for a concrete implementation and examples.
|
||||
ExpressionSQLGenerator interface {
|
||||
Dialect() string
|
||||
Generate(b sb.SQLBuilder, val interface{})
|
||||
}
|
||||
// The default adapter. This class should be used when building a new adapter. When creating a new adapter you can
|
||||
// either override methods, or more typically update default values.
|
||||
// See (github.com/doug-martin/goqu/dialect/postgres)
|
||||
expressionSQLGenerator struct {
|
||||
dialect string
|
||||
dialectOptions *SQLDialectOptions
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
replacementRune = '?'
|
||||
TrueLiteral = exp.NewLiteralExpression("TRUE")
|
||||
FalseLiteral = exp.NewLiteralExpression("FALSE")
|
||||
|
||||
ErrEmptyIdentifier = errors.New(
|
||||
`a empty identifier was encountered, please specify a "schema", "table" or "column"`,
|
||||
)
|
||||
ErrUnexpectedNamedWindow = errors.New(`unexpected named window function`)
|
||||
ErrEmptyCaseWhens = errors.New(`when conditions not found for case statement`)
|
||||
)
|
||||
|
||||
func errUnsupportedExpressionType(e exp.Expression) error {
|
||||
return errors.New("unsupported expression type %T", e)
|
||||
}
|
||||
|
||||
func errUnsupportedIdentifierExpression(t interface{}) error {
|
||||
return errors.New("unexpected col type must be string or LiteralExpression received %T", t)
|
||||
}
|
||||
|
||||
func errUnsupportedBooleanExpressionOperator(op exp.BooleanOperation) error {
|
||||
return errors.New("boolean operator '%+v' not supported", op)
|
||||
}
|
||||
|
||||
func errUnsupportedBitwiseExpressionOperator(op exp.BitwiseOperation) error {
|
||||
return errors.New("bitwise operator '%+v' not supported", op)
|
||||
}
|
||||
|
||||
func errUnsupportedRangeExpressionOperator(op exp.RangeOperation) error {
|
||||
return errors.New("range operator %+v not supported", op)
|
||||
}
|
||||
|
||||
func errLateralNotSupported(dialect string) error {
|
||||
return errors.New("dialect does not support lateral expressions [dialect=%s]", dialect)
|
||||
}
|
||||
|
||||
func NewExpressionSQLGenerator(dialect string, do *SQLDialectOptions) ExpressionSQLGenerator {
|
||||
return &expressionSQLGenerator{dialect: dialect, dialectOptions: do}
|
||||
}
|
||||
|
||||
func (esg *expressionSQLGenerator) Dialect() string {
|
||||
return esg.dialect
|
||||
}
|
||||
|
||||
var valuerReflectType = reflect.TypeOf((*driver.Valuer)(nil)).Elem()
|
||||
|
||||
func (esg *expressionSQLGenerator) Generate(b sb.SQLBuilder, val interface{}) {
|
||||
if b.Error() != nil {
|
||||
return
|
||||
}
|
||||
if val == nil {
|
||||
esg.literalNil(b)
|
||||
return
|
||||
}
|
||||
switch v := val.(type) {
|
||||
case exp.Expression:
|
||||
esg.expressionSQL(b, v)
|
||||
case int:
|
||||
esg.literalInt(b, int64(v))
|
||||
case int32:
|
||||
esg.literalInt(b, int64(v))
|
||||
case int64:
|
||||
esg.literalInt(b, v)
|
||||
case float32:
|
||||
esg.literalFloat(b, float64(v))
|
||||
case float64:
|
||||
esg.literalFloat(b, v)
|
||||
case string:
|
||||
esg.literalString(b, v)
|
||||
case bool:
|
||||
esg.literalBool(b, v)
|
||||
case time.Time:
|
||||
esg.literalTime(b, v)
|
||||
case *time.Time:
|
||||
if v == nil {
|
||||
esg.literalNil(b)
|
||||
return
|
||||
}
|
||||
esg.literalTime(b, *v)
|
||||
case driver.Valuer:
|
||||
// See https://github.com/golang/go/commit/0ce1d79a6a771f7449ec493b993ed2a720917870
|
||||
if rv := reflect.ValueOf(val); rv.Kind() == reflect.Ptr &&
|
||||
rv.IsNil() &&
|
||||
rv.Type().Elem().Implements(valuerReflectType) {
|
||||
esg.literalNil(b)
|
||||
return
|
||||
}
|
||||
dVal, err := v.Value()
|
||||
if err != nil {
|
||||
b.SetError(err)
|
||||
return
|
||||
}
|
||||
esg.Generate(b, dVal)
|
||||
default:
|
||||
esg.reflectSQL(b, val)
|
||||
}
|
||||
}
|
||||
|
||||
func (esg *expressionSQLGenerator) reflectSQL(b sb.SQLBuilder, val interface{}) {
|
||||
v := reflect.Indirect(reflect.ValueOf(val))
|
||||
valKind := v.Kind()
|
||||
switch {
|
||||
case util.IsInvalid(valKind):
|
||||
esg.literalNil(b)
|
||||
case util.IsSlice(valKind):
|
||||
switch t := val.(type) {
|
||||
case []byte:
|
||||
esg.literalBytes(b, t)
|
||||
case []exp.CommonTableExpression:
|
||||
esg.commonTablesSliceSQL(b, t)
|
||||
default:
|
||||
esg.sliceValueSQL(b, v)
|
||||
}
|
||||
case util.IsInt(valKind):
|
||||
esg.Generate(b, v.Int())
|
||||
case util.IsUint(valKind):
|
||||
esg.Generate(b, int64(v.Uint()))
|
||||
case util.IsFloat(valKind):
|
||||
esg.Generate(b, v.Float())
|
||||
case util.IsString(valKind):
|
||||
esg.Generate(b, v.String())
|
||||
case util.IsBool(valKind):
|
||||
esg.Generate(b, v.Bool())
|
||||
default:
|
||||
b.SetError(errors.NewEncodeError(val))
|
||||
}
|
||||
}
|
||||
|
||||
// nolint:gocyclo // not complex just long
|
||||
func (esg *expressionSQLGenerator) expressionSQL(b sb.SQLBuilder, expression exp.Expression) {
|
||||
switch e := expression.(type) {
|
||||
case exp.ColumnListExpression:
|
||||
esg.columnListSQL(b, e)
|
||||
case exp.ExpressionList:
|
||||
esg.expressionListSQL(b, e)
|
||||
case exp.LiteralExpression:
|
||||
esg.literalExpressionSQL(b, e)
|
||||
case exp.IdentifierExpression:
|
||||
esg.identifierExpressionSQL(b, e)
|
||||
case exp.LateralExpression:
|
||||
esg.lateralExpressionSQL(b, e)
|
||||
case exp.AliasedExpression:
|
||||
esg.aliasedExpressionSQL(b, e)
|
||||
case exp.BooleanExpression:
|
||||
esg.booleanExpressionSQL(b, e)
|
||||
case exp.BitwiseExpression:
|
||||
esg.bitwiseExpressionSQL(b, e)
|
||||
case exp.RangeExpression:
|
||||
esg.rangeExpressionSQL(b, e)
|
||||
case exp.OrderedExpression:
|
||||
esg.orderedExpressionSQL(b, e)
|
||||
case exp.UpdateExpression:
|
||||
esg.updateExpressionSQL(b, e)
|
||||
case exp.SQLFunctionExpression:
|
||||
esg.sqlFunctionExpressionSQL(b, e)
|
||||
case exp.SQLWindowFunctionExpression:
|
||||
esg.sqlWindowFunctionExpression(b, e)
|
||||
case exp.WindowExpression:
|
||||
esg.windowExpressionSQL(b, e)
|
||||
case exp.CastExpression:
|
||||
esg.castExpressionSQL(b, e)
|
||||
case exp.AppendableExpression:
|
||||
esg.appendableExpressionSQL(b, e)
|
||||
case exp.CommonTableExpression:
|
||||
esg.commonTableExpressionSQL(b, e)
|
||||
case exp.CompoundExpression:
|
||||
esg.compoundExpressionSQL(b, e)
|
||||
case exp.CaseExpression:
|
||||
esg.caseExpressionSQL(b, e)
|
||||
case exp.Ex:
|
||||
esg.expressionMapSQL(b, e)
|
||||
case exp.ExOr:
|
||||
esg.expressionOrMapSQL(b, e)
|
||||
default:
|
||||
b.SetError(errUnsupportedExpressionType(e))
|
||||
}
|
||||
}
|
||||
|
||||
// Generates a placeholder (e.g. ?, $1)
|
||||
func (esg *expressionSQLGenerator) placeHolderSQL(b sb.SQLBuilder, i interface{}) {
|
||||
b.Write(esg.dialectOptions.PlaceHolderFragment)
|
||||
if esg.dialectOptions.IncludePlaceholderNum {
|
||||
b.WriteStrings(strconv.FormatInt(int64(b.CurrentArgPosition()), 10))
|
||||
}
|
||||
b.WriteArg(i)
|
||||
}
|
||||
|
||||
// Generates creates the sql for a sub select on a Dataset
|
||||
func (esg *expressionSQLGenerator) appendableExpressionSQL(b sb.SQLBuilder, a exp.AppendableExpression) {
|
||||
b.WriteRunes(esg.dialectOptions.LeftParenRune)
|
||||
a.AppendSQL(b)
|
||||
b.WriteRunes(esg.dialectOptions.RightParenRune)
|
||||
if a.GetAs() != nil {
|
||||
b.Write(esg.dialectOptions.AsFragment)
|
||||
esg.Generate(b, a.GetAs())
|
||||
}
|
||||
}
|
||||
|
||||
// Quotes an identifier (e.g. "col", "table"."col"
|
||||
func (esg *expressionSQLGenerator) identifierExpressionSQL(b sb.SQLBuilder, ident exp.IdentifierExpression) {
|
||||
if ident.IsEmpty() {
|
||||
b.SetError(ErrEmptyIdentifier)
|
||||
return
|
||||
}
|
||||
schema, table, col := ident.GetSchema(), ident.GetTable(), ident.GetCol()
|
||||
if schema != esg.dialectOptions.EmptyString {
|
||||
b.WriteRunes(esg.dialectOptions.QuoteRune).
|
||||
WriteStrings(schema).
|
||||
WriteRunes(esg.dialectOptions.QuoteRune)
|
||||
}
|
||||
if table != esg.dialectOptions.EmptyString {
|
||||
if schema != esg.dialectOptions.EmptyString {
|
||||
b.WriteRunes(esg.dialectOptions.PeriodRune)
|
||||
}
|
||||
b.WriteRunes(esg.dialectOptions.QuoteRune).
|
||||
WriteStrings(table).
|
||||
WriteRunes(esg.dialectOptions.QuoteRune)
|
||||
}
|
||||
switch t := col.(type) {
|
||||
case nil:
|
||||
case string:
|
||||
if col != esg.dialectOptions.EmptyString {
|
||||
if table != esg.dialectOptions.EmptyString || schema != esg.dialectOptions.EmptyString {
|
||||
b.WriteRunes(esg.dialectOptions.PeriodRune)
|
||||
}
|
||||
b.WriteRunes(esg.dialectOptions.QuoteRune).
|
||||
WriteStrings(t).
|
||||
WriteRunes(esg.dialectOptions.QuoteRune)
|
||||
}
|
||||
case exp.LiteralExpression:
|
||||
if table != esg.dialectOptions.EmptyString || schema != esg.dialectOptions.EmptyString {
|
||||
b.WriteRunes(esg.dialectOptions.PeriodRune)
|
||||
}
|
||||
esg.Generate(b, t)
|
||||
default:
|
||||
b.SetError(errUnsupportedIdentifierExpression(col))
|
||||
}
|
||||
}
|
||||
|
||||
func (esg *expressionSQLGenerator) lateralExpressionSQL(b sb.SQLBuilder, le exp.LateralExpression) {
|
||||
if !esg.dialectOptions.SupportsLateral {
|
||||
b.SetError(errLateralNotSupported(esg.dialect))
|
||||
return
|
||||
}
|
||||
b.Write(esg.dialectOptions.LateralFragment)
|
||||
esg.Generate(b, le.Table())
|
||||
}
|
||||
|
||||
// Generates SQL NULL value
|
||||
func (esg *expressionSQLGenerator) literalNil(b sb.SQLBuilder) {
|
||||
if b.IsPrepared() {
|
||||
esg.placeHolderSQL(b, nil)
|
||||
return
|
||||
}
|
||||
b.Write(esg.dialectOptions.Null)
|
||||
}
|
||||
|
||||
// Generates SQL bool literal, (e.g. TRUE, FALSE, mysql 1, 0, sqlite3 1, 0)
|
||||
func (esg *expressionSQLGenerator) literalBool(b sb.SQLBuilder, bl bool) {
|
||||
if b.IsPrepared() {
|
||||
esg.placeHolderSQL(b, bl)
|
||||
return
|
||||
}
|
||||
if bl {
|
||||
b.Write(esg.dialectOptions.True)
|
||||
} else {
|
||||
b.Write(esg.dialectOptions.False)
|
||||
}
|
||||
}
|
||||
|
||||
// Generates SQL for a time.Time value
|
||||
func (esg *expressionSQLGenerator) literalTime(b sb.SQLBuilder, t time.Time) {
|
||||
if b.IsPrepared() {
|
||||
esg.placeHolderSQL(b, t)
|
||||
return
|
||||
}
|
||||
esg.Generate(b, t.In(timeLocation).Format(esg.dialectOptions.TimeFormat))
|
||||
}
|
||||
|
||||
// Generates SQL for a Float Value
|
||||
func (esg *expressionSQLGenerator) literalFloat(b sb.SQLBuilder, f float64) {
|
||||
if b.IsPrepared() {
|
||||
esg.placeHolderSQL(b, f)
|
||||
return
|
||||
}
|
||||
b.WriteStrings(strconv.FormatFloat(f, 'f', -1, 64))
|
||||
}
|
||||
|
||||
// Generates SQL for an int value
|
||||
func (esg *expressionSQLGenerator) literalInt(b sb.SQLBuilder, i int64) {
|
||||
if b.IsPrepared() {
|
||||
esg.placeHolderSQL(b, i)
|
||||
return
|
||||
}
|
||||
b.WriteStrings(strconv.FormatInt(i, 10))
|
||||
}
|
||||
|
||||
// Generates SQL for a string
|
||||
func (esg *expressionSQLGenerator) literalString(b sb.SQLBuilder, s string) {
|
||||
if b.IsPrepared() {
|
||||
esg.placeHolderSQL(b, s)
|
||||
return
|
||||
}
|
||||
b.WriteRunes(esg.dialectOptions.StringQuote)
|
||||
for _, char := range s {
|
||||
if e, ok := esg.dialectOptions.EscapedRunes[char]; ok {
|
||||
b.Write(e)
|
||||
} else {
|
||||
b.WriteRunes(char)
|
||||
}
|
||||
}
|
||||
|
||||
b.WriteRunes(esg.dialectOptions.StringQuote)
|
||||
}
|
||||
|
||||
// Generates SQL for a slice of bytes
|
||||
func (esg *expressionSQLGenerator) literalBytes(b sb.SQLBuilder, bs []byte) {
|
||||
if b.IsPrepared() {
|
||||
esg.placeHolderSQL(b, bs)
|
||||
return
|
||||
}
|
||||
b.WriteRunes(esg.dialectOptions.StringQuote)
|
||||
i := 0
|
||||
for len(bs) > 0 {
|
||||
char, l := utf8.DecodeRune(bs)
|
||||
if e, ok := esg.dialectOptions.EscapedRunes[char]; ok {
|
||||
b.Write(e)
|
||||
} else {
|
||||
b.WriteRunes(char)
|
||||
}
|
||||
i++
|
||||
bs = bs[l:]
|
||||
}
|
||||
b.WriteRunes(esg.dialectOptions.StringQuote)
|
||||
}
|
||||
|
||||
// Generates SQL for a slice of values (e.g. []int64{1,2,3,4} -> (1,2,3,4)
|
||||
func (esg *expressionSQLGenerator) sliceValueSQL(b sb.SQLBuilder, slice reflect.Value) {
|
||||
b.WriteRunes(esg.dialectOptions.LeftParenRune)
|
||||
for i, l := 0, slice.Len(); i < l; i++ {
|
||||
esg.Generate(b, slice.Index(i).Interface())
|
||||
if i < l-1 {
|
||||
b.WriteRunes(esg.dialectOptions.CommaRune, esg.dialectOptions.SpaceRune)
|
||||
}
|
||||
}
|
||||
b.WriteRunes(esg.dialectOptions.RightParenRune)
|
||||
}
|
||||
|
||||
// Generates SQL for an AliasedExpression (e.g. I("a").As("b") -> "a" AS "b")
|
||||
func (esg *expressionSQLGenerator) aliasedExpressionSQL(b sb.SQLBuilder, aliased exp.AliasedExpression) {
|
||||
esg.Generate(b, aliased.Aliased())
|
||||
b.Write(esg.dialectOptions.AsFragment)
|
||||
esg.Generate(b, aliased.GetAs())
|
||||
}
|
||||
|
||||
// Generates SQL for a BooleanExpresion (e.g. I("a").Eq(2) -> "a" = 2)
|
||||
func (esg *expressionSQLGenerator) booleanExpressionSQL(b sb.SQLBuilder, operator exp.BooleanExpression) {
|
||||
b.WriteRunes(esg.dialectOptions.LeftParenRune)
|
||||
esg.Generate(b, operator.LHS())
|
||||
b.WriteRunes(esg.dialectOptions.SpaceRune)
|
||||
operatorOp := operator.Op()
|
||||
if val, ok := esg.dialectOptions.BooleanOperatorLookup[operatorOp]; ok {
|
||||
b.Write(val)
|
||||
} else {
|
||||
b.SetError(errUnsupportedBooleanExpressionOperator(operatorOp))
|
||||
return
|
||||
}
|
||||
rhs := operator.RHS()
|
||||
|
||||
if (operatorOp == exp.IsOp || operatorOp == exp.IsNotOp) && rhs != nil && !esg.dialectOptions.BooleanDataTypeSupported {
|
||||
b.SetError(errors.New("boolean data type is not supported by dialect %q", esg.dialect))
|
||||
return
|
||||
}
|
||||
|
||||
if (operatorOp == exp.IsOp || operatorOp == exp.IsNotOp) && esg.dialectOptions.UseLiteralIsBools {
|
||||
// these values must be interpolated because preparing them generates invalid SQL
|
||||
switch rhs {
|
||||
case true:
|
||||
rhs = TrueLiteral
|
||||
case false:
|
||||
rhs = FalseLiteral
|
||||
case nil:
|
||||
rhs = exp.NewLiteralExpression(string(esg.dialectOptions.Null))
|
||||
}
|
||||
}
|
||||
b.WriteRunes(esg.dialectOptions.SpaceRune)
|
||||
|
||||
if (operatorOp == exp.IsOp || operatorOp == exp.IsNotOp) && rhs == nil && !esg.dialectOptions.BooleanDataTypeSupported {
|
||||
// e.g. for SQL server dialect which does not support "IS @p1" for "IS NULL"
|
||||
b.Write(esg.dialectOptions.Null)
|
||||
} else {
|
||||
esg.Generate(b, rhs)
|
||||
}
|
||||
|
||||
b.WriteRunes(esg.dialectOptions.RightParenRune)
|
||||
}
|
||||
|
||||
// Generates SQL for a BitwiseExpresion (e.g. I("a").BitwiseOr(2) - > "a" | 2)
|
||||
func (esg *expressionSQLGenerator) bitwiseExpressionSQL(b sb.SQLBuilder, operator exp.BitwiseExpression) {
|
||||
b.WriteRunes(esg.dialectOptions.LeftParenRune)
|
||||
|
||||
if operator.LHS() != nil {
|
||||
esg.Generate(b, operator.LHS())
|
||||
b.WriteRunes(esg.dialectOptions.SpaceRune)
|
||||
}
|
||||
|
||||
operatorOp := operator.Op()
|
||||
if val, ok := esg.dialectOptions.BitwiseOperatorLookup[operatorOp]; ok {
|
||||
b.Write(val)
|
||||
} else {
|
||||
b.SetError(errUnsupportedBitwiseExpressionOperator(operatorOp))
|
||||
return
|
||||
}
|
||||
|
||||
b.WriteRunes(esg.dialectOptions.SpaceRune)
|
||||
esg.Generate(b, operator.RHS())
|
||||
b.WriteRunes(esg.dialectOptions.RightParenRune)
|
||||
}
|
||||
|
||||
// Generates SQL for a RangeExpresion (e.g. I("a").Between(RangeVal{Start:2,End:5}) -> "a" BETWEEN 2 AND 5)
|
||||
func (esg *expressionSQLGenerator) rangeExpressionSQL(b sb.SQLBuilder, operator exp.RangeExpression) {
|
||||
b.WriteRunes(esg.dialectOptions.LeftParenRune)
|
||||
esg.Generate(b, operator.LHS())
|
||||
b.WriteRunes(esg.dialectOptions.SpaceRune)
|
||||
operatorOp := operator.Op()
|
||||
if val, ok := esg.dialectOptions.RangeOperatorLookup[operatorOp]; ok {
|
||||
b.Write(val)
|
||||
} else {
|
||||
b.SetError(errUnsupportedRangeExpressionOperator(operatorOp))
|
||||
return
|
||||
}
|
||||
rhs := operator.RHS()
|
||||
b.WriteRunes(esg.dialectOptions.SpaceRune)
|
||||
esg.Generate(b, rhs.Start())
|
||||
b.Write(esg.dialectOptions.AndFragment)
|
||||
esg.Generate(b, rhs.End())
|
||||
b.WriteRunes(esg.dialectOptions.RightParenRune)
|
||||
}
|
||||
|
||||
// Generates SQL for an OrderedExpression (e.g. I("a").Asc() -> "a" ASC)
|
||||
func (esg *expressionSQLGenerator) orderedExpressionSQL(b sb.SQLBuilder, order exp.OrderedExpression) {
|
||||
esg.Generate(b, order.SortExpression())
|
||||
if order.IsAsc() {
|
||||
b.Write(esg.dialectOptions.AscFragment)
|
||||
} else {
|
||||
b.Write(esg.dialectOptions.DescFragment)
|
||||
}
|
||||
switch order.NullSortType() {
|
||||
case exp.NoNullsSortType:
|
||||
return
|
||||
case exp.NullsFirstSortType:
|
||||
b.Write(esg.dialectOptions.NullsFirstFragment)
|
||||
case exp.NullsLastSortType:
|
||||
b.Write(esg.dialectOptions.NullsLastFragment)
|
||||
}
|
||||
}
|
||||
|
||||
// Generates SQL for an ExpressionList (e.g. And(I("a").Eq("a"), I("b").Eq("b")) -> (("a" = 'a') AND ("b" = 'b')))
|
||||
func (esg *expressionSQLGenerator) expressionListSQL(b sb.SQLBuilder, expressionList exp.ExpressionList) {
|
||||
if expressionList.IsEmpty() {
|
||||
return
|
||||
}
|
||||
var op []byte
|
||||
if expressionList.Type() == exp.AndType {
|
||||
op = esg.dialectOptions.AndFragment
|
||||
} else {
|
||||
op = esg.dialectOptions.OrFragment
|
||||
}
|
||||
exps := expressionList.Expressions()
|
||||
expLen := len(exps) - 1
|
||||
if expLen > 0 {
|
||||
b.WriteRunes(esg.dialectOptions.LeftParenRune)
|
||||
} else {
|
||||
esg.Generate(b, exps[0])
|
||||
return
|
||||
}
|
||||
for i, e := range exps {
|
||||
esg.Generate(b, e)
|
||||
if i < expLen {
|
||||
b.Write(op)
|
||||
}
|
||||
}
|
||||
b.WriteRunes(esg.dialectOptions.RightParenRune)
|
||||
}
|
||||
|
||||
// Generates SQL for a ColumnListExpression
|
||||
func (esg *expressionSQLGenerator) columnListSQL(b sb.SQLBuilder, columnList exp.ColumnListExpression) {
|
||||
cols := columnList.Columns()
|
||||
colLen := len(cols)
|
||||
for i, col := range cols {
|
||||
esg.Generate(b, col)
|
||||
if i < colLen-1 {
|
||||
b.WriteRunes(esg.dialectOptions.CommaRune, esg.dialectOptions.SpaceRune)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Generates SQL for an UpdateEpxresion
|
||||
func (esg *expressionSQLGenerator) updateExpressionSQL(b sb.SQLBuilder, update exp.UpdateExpression) {
|
||||
esg.Generate(b, update.Col())
|
||||
b.WriteRunes(esg.dialectOptions.SetOperatorRune)
|
||||
esg.Generate(b, update.Val())
|
||||
}
|
||||
|
||||
// Generates SQL for a LiteralExpression
|
||||
// L("a + b") -> a + b
|
||||
// L("a = ?", 1) -> a = 1
|
||||
func (esg *expressionSQLGenerator) literalExpressionSQL(b sb.SQLBuilder, literal exp.LiteralExpression) {
|
||||
l := literal.Literal()
|
||||
args := literal.Args()
|
||||
if argsLen := len(args); argsLen > 0 {
|
||||
currIndex := 0
|
||||
for _, char := range l {
|
||||
if char == replacementRune && currIndex < argsLen {
|
||||
esg.Generate(b, args[currIndex])
|
||||
currIndex++
|
||||
} else {
|
||||
b.WriteRunes(char)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
b.WriteStrings(l)
|
||||
}
|
||||
|
||||
// Generates SQL for a SQLFunctionExpression
|
||||
// COUNT(I("a")) -> COUNT("a")
|
||||
func (esg *expressionSQLGenerator) sqlFunctionExpressionSQL(b sb.SQLBuilder, sqlFunc exp.SQLFunctionExpression) {
|
||||
b.WriteStrings(sqlFunc.Name())
|
||||
esg.Generate(b, sqlFunc.Args())
|
||||
}
|
||||
|
||||
func (esg *expressionSQLGenerator) sqlWindowFunctionExpression(b sb.SQLBuilder, sqlWinFunc exp.SQLWindowFunctionExpression) {
|
||||
if !esg.dialectOptions.SupportsWindowFunction {
|
||||
b.SetError(ErrWindowNotSupported(esg.dialect))
|
||||
return
|
||||
}
|
||||
esg.Generate(b, sqlWinFunc.Func())
|
||||
b.Write(esg.dialectOptions.WindowOverFragment)
|
||||
switch {
|
||||
case sqlWinFunc.HasWindowName():
|
||||
esg.Generate(b, sqlWinFunc.WindowName())
|
||||
case sqlWinFunc.HasWindow():
|
||||
if sqlWinFunc.Window().HasName() {
|
||||
b.SetError(ErrUnexpectedNamedWindow)
|
||||
return
|
||||
}
|
||||
esg.Generate(b, sqlWinFunc.Window())
|
||||
default:
|
||||
esg.Generate(b, exp.NewWindowExpression(nil, nil, nil, nil))
|
||||
}
|
||||
}
|
||||
|
||||
func (esg *expressionSQLGenerator) windowExpressionSQL(b sb.SQLBuilder, we exp.WindowExpression) {
|
||||
if !esg.dialectOptions.SupportsWindowFunction {
|
||||
b.SetError(ErrWindowNotSupported(esg.dialect))
|
||||
return
|
||||
}
|
||||
if we.HasName() {
|
||||
esg.Generate(b, we.Name())
|
||||
b.Write(esg.dialectOptions.AsFragment)
|
||||
}
|
||||
b.WriteRunes(esg.dialectOptions.LeftParenRune)
|
||||
|
||||
hasPartition := we.HasPartitionBy()
|
||||
hasOrder := we.HasOrder()
|
||||
|
||||
if we.HasParent() {
|
||||
esg.Generate(b, we.Parent())
|
||||
if hasPartition || hasOrder {
|
||||
b.WriteRunes(esg.dialectOptions.SpaceRune)
|
||||
}
|
||||
}
|
||||
|
||||
if hasPartition {
|
||||
b.Write(esg.dialectOptions.WindowPartitionByFragment)
|
||||
esg.Generate(b, we.PartitionCols())
|
||||
if hasOrder {
|
||||
b.WriteRunes(esg.dialectOptions.SpaceRune)
|
||||
}
|
||||
}
|
||||
if hasOrder {
|
||||
b.Write(esg.dialectOptions.WindowOrderByFragment)
|
||||
esg.Generate(b, we.OrderCols())
|
||||
}
|
||||
|
||||
b.WriteRunes(esg.dialectOptions.RightParenRune)
|
||||
}
|
||||
|
||||
// Generates SQL for a CastExpression
|
||||
// I("a").Cast("NUMERIC") -> CAST("a" AS NUMERIC)
|
||||
func (esg *expressionSQLGenerator) castExpressionSQL(b sb.SQLBuilder, cast exp.CastExpression) {
|
||||
b.Write(esg.dialectOptions.CastFragment).WriteRunes(esg.dialectOptions.LeftParenRune)
|
||||
esg.Generate(b, cast.Casted())
|
||||
b.Write(esg.dialectOptions.AsFragment)
|
||||
esg.Generate(b, cast.Type())
|
||||
b.WriteRunes(esg.dialectOptions.RightParenRune)
|
||||
}
|
||||
|
||||
// Generates the sql for the WITH clauses for common table expressions (CTE)
|
||||
func (esg *expressionSQLGenerator) commonTablesSliceSQL(b sb.SQLBuilder, ctes []exp.CommonTableExpression) {
|
||||
l := len(ctes)
|
||||
if l == 0 {
|
||||
return
|
||||
}
|
||||
if !esg.dialectOptions.SupportsWithCTE {
|
||||
b.SetError(ErrCTENotSupported(esg.dialect))
|
||||
return
|
||||
}
|
||||
b.Write(esg.dialectOptions.WithFragment)
|
||||
anyRecursive := false
|
||||
for _, cte := range ctes {
|
||||
anyRecursive = anyRecursive || cte.IsRecursive()
|
||||
}
|
||||
if anyRecursive {
|
||||
if !esg.dialectOptions.SupportsWithCTERecursive {
|
||||
b.SetError(ErrRecursiveCTENotSupported(esg.dialect))
|
||||
return
|
||||
}
|
||||
b.Write(esg.dialectOptions.RecursiveFragment)
|
||||
}
|
||||
for i, cte := range ctes {
|
||||
esg.Generate(b, cte)
|
||||
if i < l-1 {
|
||||
b.WriteRunes(esg.dialectOptions.CommaRune, esg.dialectOptions.SpaceRune)
|
||||
}
|
||||
}
|
||||
b.WriteRunes(esg.dialectOptions.SpaceRune)
|
||||
}
|
||||
|
||||
// Generates SQL for a CommonTableExpression
|
||||
func (esg *expressionSQLGenerator) commonTableExpressionSQL(b sb.SQLBuilder, cte exp.CommonTableExpression) {
|
||||
esg.Generate(b, cte.Name())
|
||||
b.Write(esg.dialectOptions.AsFragment)
|
||||
esg.Generate(b, cte.SubQuery())
|
||||
}
|
||||
|
||||
// Generates SQL for a CompoundExpression
|
||||
func (esg *expressionSQLGenerator) compoundExpressionSQL(b sb.SQLBuilder, compound exp.CompoundExpression) {
|
||||
switch compound.Type() {
|
||||
case exp.UnionCompoundType:
|
||||
b.Write(esg.dialectOptions.UnionFragment)
|
||||
case exp.UnionAllCompoundType:
|
||||
b.Write(esg.dialectOptions.UnionAllFragment)
|
||||
case exp.IntersectCompoundType:
|
||||
b.Write(esg.dialectOptions.IntersectFragment)
|
||||
case exp.IntersectAllCompoundType:
|
||||
b.Write(esg.dialectOptions.IntersectAllFragment)
|
||||
}
|
||||
if esg.dialectOptions.WrapCompoundsInParens {
|
||||
b.WriteRunes(esg.dialectOptions.LeftParenRune)
|
||||
compound.RHS().AppendSQL(b)
|
||||
b.WriteRunes(esg.dialectOptions.RightParenRune)
|
||||
} else {
|
||||
compound.RHS().AppendSQL(b)
|
||||
}
|
||||
}
|
||||
|
||||
// Generates SQL for a CaseExpression
|
||||
func (esg *expressionSQLGenerator) caseExpressionSQL(b sb.SQLBuilder, caseExpression exp.CaseExpression) {
|
||||
caseVal := caseExpression.GetValue()
|
||||
whens := caseExpression.GetWhens()
|
||||
elseResult := caseExpression.GetElse()
|
||||
|
||||
if len(whens) == 0 {
|
||||
b.SetError(ErrEmptyCaseWhens)
|
||||
return
|
||||
}
|
||||
b.Write(esg.dialectOptions.CaseFragment)
|
||||
if caseVal != nil {
|
||||
esg.Generate(b, caseVal)
|
||||
}
|
||||
for _, when := range whens {
|
||||
b.Write(esg.dialectOptions.WhenFragment)
|
||||
esg.Generate(b, when.Condition())
|
||||
b.Write(esg.dialectOptions.ThenFragment)
|
||||
esg.Generate(b, when.Result())
|
||||
}
|
||||
if elseResult != nil {
|
||||
b.Write(esg.dialectOptions.ElseFragment)
|
||||
esg.Generate(b, elseResult.Result())
|
||||
}
|
||||
b.Write(esg.dialectOptions.EndFragment)
|
||||
}
|
||||
|
||||
func (esg *expressionSQLGenerator) expressionMapSQL(b sb.SQLBuilder, ex exp.Ex) {
|
||||
expressionList, err := ex.ToExpressions()
|
||||
if err != nil {
|
||||
b.SetError(err)
|
||||
return
|
||||
}
|
||||
esg.Generate(b, expressionList)
|
||||
}
|
||||
|
||||
func (esg *expressionSQLGenerator) expressionOrMapSQL(b sb.SQLBuilder, ex exp.ExOr) {
|
||||
expressionList, err := ex.ToExpressions()
|
||||
if err != nil {
|
||||
b.SetError(err)
|
||||
return
|
||||
}
|
||||
esg.Generate(b, expressionList)
|
||||
}
|
||||
203
vendor/github.com/doug-martin/goqu/v9/sqlgen/insert_sql_generator.go
generated
vendored
Normal file
203
vendor/github.com/doug-martin/goqu/v9/sqlgen/insert_sql_generator.go
generated
vendored
Normal file
@@ -0,0 +1,203 @@
|
||||
package sqlgen
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/doug-martin/goqu/v9/exp"
|
||||
"github.com/doug-martin/goqu/v9/internal/errors"
|
||||
"github.com/doug-martin/goqu/v9/internal/sb"
|
||||
)
|
||||
|
||||
type (
|
||||
// An adapter interface to be used by a Dataset to generate SQL for a specific dialect.
|
||||
// See DefaultAdapter for a concrete implementation and examples.
|
||||
InsertSQLGenerator interface {
|
||||
Dialect() string
|
||||
Generate(b sb.SQLBuilder, clauses exp.InsertClauses)
|
||||
}
|
||||
// The default adapter. This class should be used when building a new adapter. When creating a new adapter you can
|
||||
// either override methods, or more typically update default values.
|
||||
// See (github.com/doug-martin/goqu/dialect/postgres)
|
||||
insertSQLGenerator struct {
|
||||
CommonSQLGenerator
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
ErrConflictUpdateValuesRequired = errors.New("values are required for on conflict update expression")
|
||||
ErrNoSourceForInsert = errors.New("no source found when generating insert sql")
|
||||
)
|
||||
|
||||
func errMisMatchedRowLength(expectedL, actualL int) error {
|
||||
return errors.New("rows with different value length expected %d got %d", expectedL, actualL)
|
||||
}
|
||||
|
||||
func errUpsertWithWhereNotSupported(dialect string) error {
|
||||
return errors.New("dialect does not support upsert with where clause [dialect=%s]", dialect)
|
||||
}
|
||||
|
||||
func NewInsertSQLGenerator(dialect string, do *SQLDialectOptions) InsertSQLGenerator {
|
||||
return &insertSQLGenerator{NewCommonSQLGenerator(dialect, do)}
|
||||
}
|
||||
|
||||
func (isg *insertSQLGenerator) Generate(
|
||||
b sb.SQLBuilder,
|
||||
clauses exp.InsertClauses,
|
||||
) {
|
||||
if !clauses.HasInto() {
|
||||
b.SetError(ErrNoSourceForInsert)
|
||||
return
|
||||
}
|
||||
for _, f := range isg.DialectOptions().InsertSQLOrder {
|
||||
if b.Error() != nil {
|
||||
return
|
||||
}
|
||||
switch f {
|
||||
case CommonTableSQLFragment:
|
||||
isg.ExpressionSQLGenerator().Generate(b, clauses.CommonTables())
|
||||
case InsertBeingSQLFragment:
|
||||
isg.InsertBeginSQL(b, clauses.OnConflict())
|
||||
case IntoSQLFragment:
|
||||
b.WriteRunes(isg.DialectOptions().SpaceRune)
|
||||
isg.ExpressionSQLGenerator().Generate(b, clauses.Into())
|
||||
case InsertSQLFragment:
|
||||
isg.InsertSQL(b, clauses)
|
||||
case ReturningSQLFragment:
|
||||
isg.ReturningSQL(b, clauses.Returning())
|
||||
default:
|
||||
b.SetError(ErrNotSupportedFragment("INSERT", f))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Adds the correct fragment to being an INSERT statement
|
||||
func (isg *insertSQLGenerator) InsertBeginSQL(b sb.SQLBuilder, o exp.ConflictExpression) {
|
||||
if isg.DialectOptions().SupportsInsertIgnoreSyntax && o != nil {
|
||||
b.Write(isg.DialectOptions().InsertIgnoreClause)
|
||||
} else {
|
||||
b.Write(isg.DialectOptions().InsertClause)
|
||||
}
|
||||
}
|
||||
|
||||
// Adds the columns list to an insert statement
|
||||
func (isg *insertSQLGenerator) InsertSQL(b sb.SQLBuilder, ic exp.InsertClauses) {
|
||||
switch {
|
||||
case ic.HasRows():
|
||||
ie, err := exp.NewInsertExpression(ic.Rows()...)
|
||||
if err != nil {
|
||||
b.SetError(err)
|
||||
return
|
||||
}
|
||||
isg.InsertExpressionSQL(b, ie)
|
||||
case ic.HasCols() && ic.HasVals():
|
||||
isg.insertColumnsSQL(b, ic.Cols())
|
||||
isg.insertValuesSQL(b, ic.Vals())
|
||||
case ic.HasCols() && ic.HasFrom():
|
||||
isg.insertColumnsSQL(b, ic.Cols())
|
||||
isg.insertFromSQL(b, ic.From())
|
||||
case ic.HasFrom():
|
||||
isg.insertFromSQL(b, ic.From())
|
||||
default:
|
||||
isg.defaultValuesSQL(b)
|
||||
}
|
||||
if ic.HasAlias() {
|
||||
b.Write(isg.DialectOptions().AsFragment)
|
||||
isg.ExpressionSQLGenerator().Generate(b, ic.Alias())
|
||||
}
|
||||
isg.onConflictSQL(b, ic.OnConflict())
|
||||
}
|
||||
|
||||
func (isg *insertSQLGenerator) InsertExpressionSQL(b sb.SQLBuilder, ie exp.InsertExpression) {
|
||||
switch {
|
||||
case ie.IsInsertFrom():
|
||||
isg.insertFromSQL(b, ie.From())
|
||||
case ie.IsEmpty():
|
||||
isg.defaultValuesSQL(b)
|
||||
default:
|
||||
isg.insertColumnsSQL(b, ie.Cols())
|
||||
isg.insertValuesSQL(b, ie.Vals())
|
||||
}
|
||||
}
|
||||
|
||||
// Adds the DefaultValuesFragment to an SQL statement
|
||||
func (isg *insertSQLGenerator) defaultValuesSQL(b sb.SQLBuilder) {
|
||||
b.Write(isg.DialectOptions().DefaultValuesFragment)
|
||||
}
|
||||
|
||||
func (isg *insertSQLGenerator) insertFromSQL(b sb.SQLBuilder, ae exp.AppendableExpression) {
|
||||
b.WriteRunes(isg.DialectOptions().SpaceRune)
|
||||
ae.AppendSQL(b)
|
||||
}
|
||||
|
||||
// Adds the columns list to an insert statement
|
||||
func (isg *insertSQLGenerator) insertColumnsSQL(b sb.SQLBuilder, cols exp.ColumnListExpression) {
|
||||
b.WriteRunes(isg.DialectOptions().SpaceRune, isg.DialectOptions().LeftParenRune)
|
||||
isg.ExpressionSQLGenerator().Generate(b, cols)
|
||||
b.WriteRunes(isg.DialectOptions().RightParenRune)
|
||||
}
|
||||
|
||||
// Adds the values clause to an SQL statement
|
||||
func (isg *insertSQLGenerator) insertValuesSQL(b sb.SQLBuilder, values [][]interface{}) {
|
||||
b.Write(isg.DialectOptions().ValuesFragment)
|
||||
rowLen := len(values[0])
|
||||
valueLen := len(values)
|
||||
for i, row := range values {
|
||||
if len(row) != rowLen {
|
||||
b.SetError(errMisMatchedRowLength(rowLen, len(row)))
|
||||
return
|
||||
}
|
||||
isg.ExpressionSQLGenerator().Generate(b, row)
|
||||
if i < valueLen-1 {
|
||||
b.WriteRunes(isg.DialectOptions().CommaRune, isg.DialectOptions().SpaceRune)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Adds the DefaultValuesFragment to an SQL statement
|
||||
func (isg *insertSQLGenerator) onConflictSQL(b sb.SQLBuilder, o exp.ConflictExpression) {
|
||||
if o == nil {
|
||||
return
|
||||
}
|
||||
b.Write(isg.DialectOptions().ConflictFragment)
|
||||
switch t := o.(type) {
|
||||
case exp.ConflictUpdateExpression:
|
||||
target := t.TargetColumn()
|
||||
if isg.DialectOptions().SupportsConflictTarget && target != "" {
|
||||
wrapParens := !strings.HasPrefix(strings.ToLower(target), "on constraint")
|
||||
|
||||
b.WriteRunes(isg.DialectOptions().SpaceRune)
|
||||
if wrapParens {
|
||||
b.WriteRunes(isg.DialectOptions().LeftParenRune).
|
||||
WriteStrings(target).
|
||||
WriteRunes(isg.DialectOptions().RightParenRune)
|
||||
} else {
|
||||
b.Write([]byte(target))
|
||||
}
|
||||
}
|
||||
isg.onConflictDoUpdateSQL(b, t)
|
||||
default:
|
||||
b.Write(isg.DialectOptions().ConflictDoNothingFragment)
|
||||
}
|
||||
}
|
||||
|
||||
func (isg *insertSQLGenerator) onConflictDoUpdateSQL(b sb.SQLBuilder, o exp.ConflictUpdateExpression) {
|
||||
b.Write(isg.DialectOptions().ConflictDoUpdateFragment)
|
||||
update := o.Update()
|
||||
if update == nil {
|
||||
b.SetError(ErrConflictUpdateValuesRequired)
|
||||
return
|
||||
}
|
||||
ue, err := exp.NewUpdateExpressions(update)
|
||||
if err != nil {
|
||||
b.SetError(err)
|
||||
return
|
||||
}
|
||||
isg.UpdateExpressionSQL(b, ue...)
|
||||
if b.Error() == nil && o.WhereClause() != nil {
|
||||
if !isg.DialectOptions().SupportsConflictUpdateWhere {
|
||||
b.SetError(errUpsertWithWhereNotSupported(isg.Dialect()))
|
||||
return
|
||||
}
|
||||
isg.WhereSQL(b, o.WhereClause())
|
||||
}
|
||||
}
|
||||
266
vendor/github.com/doug-martin/goqu/v9/sqlgen/select_sql_generator.go
generated
vendored
Normal file
266
vendor/github.com/doug-martin/goqu/v9/sqlgen/select_sql_generator.go
generated
vendored
Normal file
@@ -0,0 +1,266 @@
|
||||
package sqlgen
|
||||
|
||||
import (
|
||||
"github.com/doug-martin/goqu/v9/exp"
|
||||
"github.com/doug-martin/goqu/v9/internal/errors"
|
||||
"github.com/doug-martin/goqu/v9/internal/sb"
|
||||
)
|
||||
|
||||
type (
|
||||
// An adapter interface to be used by a Dataset to generate SQL for a specific dialect.
|
||||
// See DefaultAdapter for a concrete implementation and examples.
|
||||
SelectSQLGenerator interface {
|
||||
Dialect() string
|
||||
Generate(b sb.SQLBuilder, clauses exp.SelectClauses)
|
||||
}
|
||||
// The default adapter. This class should be used when building a new adapter. When creating a new adapter you can
|
||||
// either override methods, or more typically update default values.
|
||||
// See (github.com/doug-martin/goqu/dialect/postgres)
|
||||
selectSQLGenerator struct {
|
||||
CommonSQLGenerator
|
||||
}
|
||||
)
|
||||
|
||||
func ErrNotSupportedJoinType(j exp.JoinExpression) error {
|
||||
return errors.New("dialect does not support %v", j.JoinType())
|
||||
}
|
||||
|
||||
func ErrJoinConditionRequired(j exp.JoinExpression) error {
|
||||
return errors.New("join condition required for conditioned join %v", j.JoinType())
|
||||
}
|
||||
|
||||
func ErrDistinctOnNotSupported(dialect string) error {
|
||||
return errors.New("dialect does not support DISTINCT ON clause [dialect=%s]", dialect)
|
||||
}
|
||||
|
||||
func ErrWindowNotSupported(dialect string) error {
|
||||
return errors.New("dialect does not support WINDOW clause [dialect=%s]", dialect)
|
||||
}
|
||||
|
||||
var ErrNoWindowName = errors.New("window expresion has no valid name")
|
||||
|
||||
func NewSelectSQLGenerator(dialect string, do *SQLDialectOptions) SelectSQLGenerator {
|
||||
return &selectSQLGenerator{NewCommonSQLGenerator(dialect, do)}
|
||||
}
|
||||
|
||||
func (ssg *selectSQLGenerator) Generate(b sb.SQLBuilder, clauses exp.SelectClauses) {
|
||||
for _, f := range ssg.DialectOptions().SelectSQLOrder {
|
||||
if b.Error() != nil {
|
||||
return
|
||||
}
|
||||
switch f {
|
||||
case CommonTableSQLFragment:
|
||||
ssg.ExpressionSQLGenerator().Generate(b, clauses.CommonTables())
|
||||
case SelectSQLFragment:
|
||||
ssg.SelectSQL(b, clauses)
|
||||
case SelectWithLimitSQLFragment:
|
||||
ssg.SelectWithLimitSQL(b, clauses)
|
||||
case FromSQLFragment:
|
||||
ssg.FromSQL(b, clauses.From())
|
||||
case JoinSQLFragment:
|
||||
ssg.JoinSQL(b, clauses.Joins())
|
||||
case WhereSQLFragment:
|
||||
ssg.WhereSQL(b, clauses.Where())
|
||||
case GroupBySQLFragment:
|
||||
ssg.GroupBySQL(b, clauses.GroupBy())
|
||||
case HavingSQLFragment:
|
||||
ssg.HavingSQL(b, clauses.Having())
|
||||
case WindowSQLFragment:
|
||||
ssg.WindowSQL(b, clauses.Windows())
|
||||
case CompoundsSQLFragment:
|
||||
ssg.CompoundsSQL(b, clauses.Compounds())
|
||||
case OrderSQLFragment:
|
||||
ssg.OrderSQL(b, clauses.Order())
|
||||
case OrderWithOffsetFetchSQLFragment:
|
||||
ssg.OrderWithOffsetFetchSQL(b, clauses.Order(), clauses.Offset(), clauses.Limit())
|
||||
case LimitSQLFragment:
|
||||
ssg.LimitSQL(b, clauses.Limit())
|
||||
case OffsetSQLFragment:
|
||||
ssg.OffsetSQL(b, clauses.Offset())
|
||||
case ForSQLFragment:
|
||||
ssg.ForSQL(b, clauses.Lock())
|
||||
default:
|
||||
b.SetError(ErrNotSupportedFragment("SELECT", f))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (ssg *selectSQLGenerator) selectSQLCommon(b sb.SQLBuilder, clauses exp.SelectClauses) {
|
||||
dc := clauses.Distinct()
|
||||
if dc != nil {
|
||||
b.Write(ssg.DialectOptions().DistinctFragment)
|
||||
if !dc.IsEmpty() {
|
||||
if ssg.DialectOptions().SupportsDistinctOn {
|
||||
b.Write(ssg.DialectOptions().OnFragment).WriteRunes(ssg.DialectOptions().LeftParenRune)
|
||||
ssg.ExpressionSQLGenerator().Generate(b, dc)
|
||||
b.WriteRunes(ssg.DialectOptions().RightParenRune, ssg.DialectOptions().SpaceRune)
|
||||
} else {
|
||||
b.SetError(ErrDistinctOnNotSupported(ssg.Dialect()))
|
||||
return
|
||||
}
|
||||
} else {
|
||||
b.WriteRunes(ssg.DialectOptions().SpaceRune)
|
||||
}
|
||||
}
|
||||
|
||||
if cols := clauses.Select(); clauses.IsDefaultSelect() || len(cols.Columns()) == 0 {
|
||||
b.WriteRunes(ssg.DialectOptions().StarRune)
|
||||
} else {
|
||||
ssg.ExpressionSQLGenerator().Generate(b, cols)
|
||||
}
|
||||
}
|
||||
|
||||
// Adds the SELECT clause and columns to a sql statement
|
||||
func (ssg *selectSQLGenerator) SelectSQL(b sb.SQLBuilder, clauses exp.SelectClauses) {
|
||||
b.Write(ssg.DialectOptions().SelectClause).WriteRunes(ssg.DialectOptions().SpaceRune)
|
||||
ssg.selectSQLCommon(b, clauses)
|
||||
}
|
||||
|
||||
// Adds the SELECT clause along with LIMIT to a SQL statement (e.g. MSSQL dialect: SELECT TOP 10 ...)
|
||||
func (ssg *selectSQLGenerator) SelectWithLimitSQL(b sb.SQLBuilder, clauses exp.SelectClauses) {
|
||||
b.Write(ssg.DialectOptions().SelectClause).WriteRunes(ssg.DialectOptions().SpaceRune)
|
||||
if clauses.Offset() == 0 && clauses.Limit() != nil {
|
||||
ssg.LimitSQL(b, clauses.Limit())
|
||||
b.WriteRunes(ssg.DialectOptions().SpaceRune)
|
||||
}
|
||||
ssg.selectSQLCommon(b, clauses)
|
||||
}
|
||||
|
||||
// Generates the JOIN clauses for an SQL statement
|
||||
func (ssg *selectSQLGenerator) JoinSQL(b sb.SQLBuilder, joins exp.JoinExpressions) {
|
||||
if len(joins) > 0 {
|
||||
for _, j := range joins {
|
||||
joinType, ok := ssg.DialectOptions().JoinTypeLookup[j.JoinType()]
|
||||
if !ok {
|
||||
b.SetError(ErrNotSupportedJoinType(j))
|
||||
return
|
||||
}
|
||||
b.Write(joinType)
|
||||
ssg.ExpressionSQLGenerator().Generate(b, j.Table())
|
||||
if t, ok := j.(exp.ConditionedJoinExpression); ok {
|
||||
if t.IsConditionEmpty() {
|
||||
b.SetError(ErrJoinConditionRequired(j))
|
||||
return
|
||||
}
|
||||
ssg.joinConditionSQL(b, t.Condition())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Generates the GROUP BY clause for an SQL statement
|
||||
func (ssg *selectSQLGenerator) GroupBySQL(b sb.SQLBuilder, groupBy exp.ColumnListExpression) {
|
||||
if groupBy != nil && len(groupBy.Columns()) > 0 {
|
||||
b.Write(ssg.DialectOptions().GroupByFragment)
|
||||
ssg.ExpressionSQLGenerator().Generate(b, groupBy)
|
||||
}
|
||||
}
|
||||
|
||||
// Generates the HAVING clause for an SQL statement
|
||||
func (ssg *selectSQLGenerator) HavingSQL(b sb.SQLBuilder, having exp.ExpressionList) {
|
||||
if having != nil && len(having.Expressions()) > 0 {
|
||||
b.Write(ssg.DialectOptions().HavingFragment)
|
||||
ssg.ExpressionSQLGenerator().Generate(b, having)
|
||||
}
|
||||
}
|
||||
|
||||
// Generates the OFFSET clause for an SQL statement
|
||||
func (ssg *selectSQLGenerator) OffsetSQL(b sb.SQLBuilder, offset uint) {
|
||||
if offset > 0 {
|
||||
b.Write(ssg.DialectOptions().OffsetFragment)
|
||||
ssg.ExpressionSQLGenerator().Generate(b, offset)
|
||||
}
|
||||
}
|
||||
|
||||
// Generates the compound sql clause for an SQL statement (e.g. UNION, INTERSECT)
|
||||
func (ssg *selectSQLGenerator) CompoundsSQL(b sb.SQLBuilder, compounds []exp.CompoundExpression) {
|
||||
for _, compound := range compounds {
|
||||
ssg.ExpressionSQLGenerator().Generate(b, compound)
|
||||
}
|
||||
}
|
||||
|
||||
// Generates the FOR (aka "locking") clause for an SQL statement
|
||||
func (ssg *selectSQLGenerator) ForSQL(b sb.SQLBuilder, lockingClause exp.Lock) {
|
||||
if lockingClause == nil {
|
||||
return
|
||||
}
|
||||
switch lockingClause.Strength() {
|
||||
case exp.ForNolock:
|
||||
return
|
||||
case exp.ForUpdate:
|
||||
b.Write(ssg.DialectOptions().ForUpdateFragment)
|
||||
case exp.ForNoKeyUpdate:
|
||||
b.Write(ssg.DialectOptions().ForNoKeyUpdateFragment)
|
||||
case exp.ForShare:
|
||||
b.Write(ssg.DialectOptions().ForShareFragment)
|
||||
case exp.ForKeyShare:
|
||||
b.Write(ssg.DialectOptions().ForKeyShareFragment)
|
||||
}
|
||||
|
||||
of := lockingClause.Of()
|
||||
if ofLen := len(of); ofLen > 0 {
|
||||
if ofFragment := ssg.DialectOptions().OfFragment; len(ofFragment) > 0 {
|
||||
b.Write(ofFragment)
|
||||
for i, table := range of {
|
||||
ssg.ExpressionSQLGenerator().Generate(b, table)
|
||||
if i < ofLen-1 {
|
||||
b.WriteRunes(ssg.DialectOptions().CommaRune, ssg.DialectOptions().SpaceRune)
|
||||
}
|
||||
}
|
||||
b.WriteRunes(ssg.DialectOptions().SpaceRune)
|
||||
}
|
||||
}
|
||||
|
||||
// the WAIT case is the default in Postgres, and is what you get if you don't specify NOWAIT or
|
||||
// SKIP LOCKED. There's no special syntax for it in PG, so we don't do anything for it here
|
||||
switch lockingClause.WaitOption() {
|
||||
case exp.Wait:
|
||||
return
|
||||
case exp.NoWait:
|
||||
b.Write(ssg.DialectOptions().NowaitFragment)
|
||||
case exp.SkipLocked:
|
||||
b.Write(ssg.DialectOptions().SkipLockedFragment)
|
||||
}
|
||||
}
|
||||
|
||||
func (ssg *selectSQLGenerator) WindowSQL(b sb.SQLBuilder, windows []exp.WindowExpression) {
|
||||
weLen := len(windows)
|
||||
if weLen == 0 {
|
||||
return
|
||||
}
|
||||
if !ssg.DialectOptions().SupportsWindowFunction {
|
||||
b.SetError(ErrWindowNotSupported(ssg.Dialect()))
|
||||
return
|
||||
}
|
||||
b.Write(ssg.DialectOptions().WindowFragment)
|
||||
for i, we := range windows {
|
||||
if !we.HasName() {
|
||||
b.SetError(ErrNoWindowName)
|
||||
}
|
||||
ssg.ExpressionSQLGenerator().Generate(b, we)
|
||||
if i < weLen-1 {
|
||||
b.WriteRunes(ssg.DialectOptions().CommaRune, ssg.DialectOptions().SpaceRune)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (ssg *selectSQLGenerator) joinConditionSQL(b sb.SQLBuilder, jc exp.JoinCondition) {
|
||||
switch t := jc.(type) {
|
||||
case exp.JoinOnCondition:
|
||||
ssg.joinOnConditionSQL(b, t)
|
||||
case exp.JoinUsingCondition:
|
||||
ssg.joinUsingConditionSQL(b, t)
|
||||
}
|
||||
}
|
||||
|
||||
func (ssg *selectSQLGenerator) joinUsingConditionSQL(b sb.SQLBuilder, jc exp.JoinUsingCondition) {
|
||||
b.Write(ssg.DialectOptions().UsingFragment).
|
||||
WriteRunes(ssg.DialectOptions().LeftParenRune)
|
||||
ssg.ExpressionSQLGenerator().Generate(b, jc.Using())
|
||||
b.WriteRunes(ssg.DialectOptions().RightParenRune)
|
||||
}
|
||||
|
||||
func (ssg *selectSQLGenerator) joinOnConditionSQL(b sb.SQLBuilder, jc exp.JoinOnCondition) {
|
||||
b.Write(ssg.DialectOptions().OnFragment)
|
||||
ssg.ExpressionSQLGenerator().Generate(b, jc.On())
|
||||
}
|
||||
607
vendor/github.com/doug-martin/goqu/v9/sqlgen/sql_dialect_options.go
generated
vendored
Normal file
607
vendor/github.com/doug-martin/goqu/v9/sqlgen/sql_dialect_options.go
generated
vendored
Normal file
@@ -0,0 +1,607 @@
|
||||
package sqlgen
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/doug-martin/goqu/v9/exp"
|
||||
)
|
||||
|
||||
type (
|
||||
SQLFragmentType int
|
||||
SQLDialectOptions struct {
|
||||
// Set to true if the dialect supports ORDER BY expressions in DELETE statements (DEFAULT=false)
|
||||
SupportsOrderByOnDelete bool
|
||||
// Set to true if the dialect supports table hint for DELETE statements (DELETE t FROM t ...), DEFAULT=false
|
||||
SupportsDeleteTableHint bool
|
||||
// Set to true if the dialect supports ORDER BY expressions in UPDATE statements (DEFAULT=false)
|
||||
SupportsOrderByOnUpdate bool
|
||||
// Set to true if the dialect supports LIMIT expressions in DELETE statements (DEFAULT=false)
|
||||
SupportsLimitOnDelete bool
|
||||
// Set to true if the dialect supports LIMIT expressions in UPDATE statements (DEFAULT=false)
|
||||
SupportsLimitOnUpdate bool
|
||||
// Set to true if the dialect supports RETURN expressions (DEFAULT=true)
|
||||
SupportsReturn bool
|
||||
// Set to true if the dialect supports Conflict Target (DEFAULT=true)
|
||||
SupportsConflictTarget bool
|
||||
// Set to true if the dialect supports Conflict Target (DEFAULT=true)
|
||||
SupportsConflictUpdateWhere bool
|
||||
// Set to true if the dialect supports Insert Ignore syntax (DEFAULT=false)
|
||||
SupportsInsertIgnoreSyntax bool
|
||||
// Set to true if the dialect supports Common Table Expressions (DEFAULT=true)
|
||||
SupportsWithCTE bool
|
||||
// Set to true if the dialect supports recursive Common Table Expressions (DEFAULT=true)
|
||||
SupportsWithCTERecursive bool
|
||||
// Set to true if multiple tables are supported in UPDATE statement. (DEFAULT=true)
|
||||
SupportsMultipleUpdateTables bool
|
||||
// Set to true if DISTINCT ON is supported (DEFAULT=true)
|
||||
SupportsDistinctOn bool
|
||||
// Set to true if LATERAL queries are supported (DEFAULT=true)
|
||||
SupportsLateral bool
|
||||
// Set to false if the dialect does not require expressions to be wrapped in parens (DEFAULT=true)
|
||||
WrapCompoundsInParens bool
|
||||
|
||||
// Set to true if window function are supported in SELECT statement. (DEFAULT=true)
|
||||
SupportsWindowFunction bool
|
||||
|
||||
// Set to true if the dialect requires join tables in UPDATE to be in a FROM clause (DEFAULT=true).
|
||||
UseFromClauseForMultipleUpdateTables bool
|
||||
|
||||
// Surround LIMIT parameter with parentheses, like in MSSQL: SELECT TOP (10) ...
|
||||
SurroundLimitWithParentheses bool
|
||||
|
||||
// The UPDATE fragment to use when generating sql. (DEFAULT=[]byte("UPDATE"))
|
||||
UpdateClause []byte
|
||||
// The INSERT fragment to use when generating sql. (DEFAULT=[]byte("INSERT INTO"))
|
||||
InsertClause []byte
|
||||
// The INSERT IGNORE INTO fragment to use when generating sql. (DEFAULT=[]byte("INSERT IGNORE INTO"))
|
||||
InsertIgnoreClause []byte
|
||||
// The SELECT fragment to use when generating sql. (DEFAULT=[]byte("SELECT"))
|
||||
SelectClause []byte
|
||||
// The DELETE fragment to use when generating sql. (DEFAULT=[]byte("DELETE"))
|
||||
DeleteClause []byte
|
||||
// The TRUNCATE fragment to use when generating sql. (DEFAULT=[]byte("TRUNCATE"))
|
||||
TruncateClause []byte
|
||||
// The WITH fragment to use when generating sql. (DEFAULT=[]byte("WITH "))
|
||||
WithFragment []byte
|
||||
// The RECURSIVE fragment to use when generating sql (after WITH). (DEFAULT=[]byte("RECURSIVE "))
|
||||
RecursiveFragment []byte
|
||||
// The CASCADE fragment to use when generating sql. (DEFAULT=[]byte(" CASCADE"))
|
||||
CascadeFragment []byte
|
||||
// The RESTRICT fragment to use when generating sql. (DEFAULT=[]byte(" RESTRICT"))
|
||||
RestrictFragment []byte
|
||||
// The SQL fragment to use when generating insert sql and using
|
||||
// DEFAULT VALUES (e.g. postgres="DEFAULT VALUES", mysql="", sqlite3=""). (DEFAULT=[]byte(" DEFAULT VALUES"))
|
||||
DefaultValuesFragment []byte
|
||||
// The SQL fragment to use when generating insert sql and listing columns using a VALUES clause
|
||||
// (DEFAULT=[]byte(" VALUES "))
|
||||
ValuesFragment []byte
|
||||
// The SQL fragment to use when generating truncate sql and using the IDENTITY clause
|
||||
// (DEFAULT=[]byte(" IDENTITY"))
|
||||
IdentityFragment []byte
|
||||
// The SQL fragment to use when generating update sql and using the SET clause (DEFAULT=[]byte(" SET "))
|
||||
SetFragment []byte
|
||||
// The SQL DISTINCT keyword (DEFAULT=[]byte(" DISTINCT "))
|
||||
DistinctFragment []byte
|
||||
// The SQL RETURNING clause (DEFAULT=[]byte(" RETURNING "))
|
||||
ReturningFragment []byte
|
||||
// The SQL FROM clause fragment (DEFAULT=[]byte(" FROM"))
|
||||
FromFragment []byte
|
||||
// The SQL USING join clause fragment (DEFAULT=[]byte(" USING "))
|
||||
UsingFragment []byte
|
||||
// The SQL ON join clause fragment (DEFAULT=[]byte(" ON "))
|
||||
OnFragment []byte
|
||||
// The SQL WHERE clause fragment (DEFAULT=[]byte(" WHERE "))
|
||||
WhereFragment []byte
|
||||
// The SQL GROUP BY clause fragment(DEFAULT=[]byte(" GROUP BY "))
|
||||
GroupByFragment []byte
|
||||
// The SQL HAVING clause fragment(DEFAULT=[]byte(" HAVING "))
|
||||
HavingFragment []byte
|
||||
// The SQL WINDOW clause fragment(DEFAULT=[]byte(" WINDOW "))
|
||||
WindowFragment []byte
|
||||
// The SQL WINDOW clause PARTITION BY fragment(DEFAULT=[]byte("PARTITION BY "))
|
||||
WindowPartitionByFragment []byte
|
||||
// The SQL WINDOW clause ORDER BY fragment(DEFAULT=[]byte("ORDER BY "))
|
||||
WindowOrderByFragment []byte
|
||||
// The SQL WINDOW clause OVER fragment(DEFAULT=[]byte(" OVER "))
|
||||
WindowOverFragment []byte
|
||||
// The SQL ORDER BY clause fragment(DEFAULT=[]byte(" ORDER BY "))
|
||||
OrderByFragment []byte
|
||||
// The SQL FETCH fragment(DEFAULT=[]byte(" "))
|
||||
FetchFragment []byte
|
||||
// The SQL LIMIT BY clause fragment(DEFAULT=[]byte(" LIMIT "))
|
||||
LimitFragment []byte
|
||||
// The SQL OFFSET BY clause fragment(DEFAULT=[]byte(" OFFSET "))
|
||||
OffsetFragment []byte
|
||||
// The SQL FOR UPDATE fragment(DEFAULT=[]byte(" FOR UPDATE "))
|
||||
ForUpdateFragment []byte
|
||||
// The SQL FOR NO KEY UPDATE fragment(DEFAULT=[]byte(" FOR NO KEY UPDATE "))
|
||||
ForNoKeyUpdateFragment []byte
|
||||
// The SQL FOR SHARE fragment(DEFAULT=[]byte(" FOR SHARE "))
|
||||
ForShareFragment []byte
|
||||
// The SQL OF fragment(DEFAULT=[]byte("OF "))
|
||||
OfFragment []byte
|
||||
// The SQL FOR KEY SHARE fragment(DEFAULT=[]byte(" FOR KEY SHARE "))
|
||||
ForKeyShareFragment []byte
|
||||
// The SQL NOWAIT fragment(DEFAULT=[]byte("NOWAIT"))
|
||||
NowaitFragment []byte
|
||||
// The SQL SKIP LOCKED fragment(DEFAULT=[]byte("SKIP LOCKED"))
|
||||
SkipLockedFragment []byte
|
||||
// The SQL AS fragment when aliasing an Expression(DEFAULT=[]byte(" AS "))
|
||||
AsFragment []byte
|
||||
// The SQL LATERAL fragment used for LATERAL joins
|
||||
LateralFragment []byte
|
||||
// The quote rune to use when quoting identifiers(DEFAULT='"')
|
||||
QuoteRune rune
|
||||
// The NULL literal to use when interpolating nulls values (DEFAULT=[]byte("NULL"))
|
||||
Null []byte
|
||||
// The TRUE literal to use when interpolating bool true values (DEFAULT=[]byte("TRUE"))
|
||||
True []byte
|
||||
// The FALSE literal to use when interpolating bool false values (DEFAULT=[]byte("FALSE"))
|
||||
False []byte
|
||||
// The ASC fragment when specifying column order (DEFAULT=[]byte(" ASC"))
|
||||
AscFragment []byte
|
||||
// The DESC fragment when specifying column order (DEFAULT=[]byte(" DESC"))
|
||||
DescFragment []byte
|
||||
// The NULLS FIRST fragment when specifying column order (DEFAULT=[]byte(" NULLS FIRST"))
|
||||
NullsFirstFragment []byte
|
||||
// The NULLS LAST fragment when specifying column order (DEFAULT=[]byte(" NULLS LAST"))
|
||||
NullsLastFragment []byte
|
||||
// The AND keyword used when joining ExpressionLists (DEFAULT=[]byte(" AND "))
|
||||
AndFragment []byte
|
||||
// The OR keyword used when joining ExpressionLists (DEFAULT=[]byte(" OR "))
|
||||
OrFragment []byte
|
||||
// The UNION keyword used when creating compound statements (DEFAULT=[]byte(" UNION "))
|
||||
UnionFragment []byte
|
||||
// The UNION ALL keyword used when creating compound statements (DEFAULT=[]byte(" UNION ALL "))
|
||||
UnionAllFragment []byte
|
||||
// The INTERSECT keyword used when creating compound statements (DEFAULT=[]byte(" INTERSECT "))
|
||||
IntersectFragment []byte
|
||||
// The INTERSECT ALL keyword used when creating compound statements (DEFAULT=[]byte(" INTERSECT ALL "))
|
||||
IntersectAllFragment []byte
|
||||
// The CAST keyword to use when casting a value (DEFAULT=[]byte("CAST"))
|
||||
CastFragment []byte
|
||||
// The CASE keyword to use when when creating a CASE statement (DEFAULT=[]byte("CASE "))
|
||||
CaseFragment []byte
|
||||
// The WHEN keyword to use when when creating a CASE statement (DEFAULT=[]byte(" WHEN "))
|
||||
WhenFragment []byte
|
||||
// The THEN keyword to use when when creating a CASE statement (DEFAULT=[]byte(" THEN "))
|
||||
ThenFragment []byte
|
||||
// The ELSE keyword to use when when creating a CASE statement (DEFAULT=[]byte(" ELSE "))
|
||||
ElseFragment []byte
|
||||
// The End keyword to use when when creating a CASE statement (DEFAULT=[]byte(" END"))
|
||||
EndFragment []byte
|
||||
// The quote rune to use when quoting string literals (DEFAULT='\'')
|
||||
StringQuote rune
|
||||
// The operator to use when setting values in an update statement (DEFAULT='=')
|
||||
SetOperatorRune rune
|
||||
// The placeholder fragment to use when generating a non interpolated statement (DEFAULT=[]byte"?")
|
||||
PlaceHolderFragment []byte
|
||||
// Empty string (DEFAULT="")
|
||||
EmptyString string
|
||||
// Comma rune (DEFAULT=',')
|
||||
CommaRune rune
|
||||
// Space rune (DEFAULT=' ')
|
||||
SpaceRune rune
|
||||
// Left paren rune (DEFAULT='(')
|
||||
LeftParenRune rune
|
||||
// Right paren rune (DEFAULT=')')
|
||||
RightParenRune rune
|
||||
// Star rune (DEFAULT='*')
|
||||
StarRune rune
|
||||
// Period rune (DEFAULT='.')
|
||||
PeriodRune rune
|
||||
// Set to true to include positional argument numbers when creating a prepared statement (Default=false)
|
||||
IncludePlaceholderNum bool
|
||||
// The time format to use when serializing time.Time (DEFAULT=time.RFC3339Nano)
|
||||
TimeFormat string
|
||||
// A map used to look up BooleanOperations and their SQL equivalents
|
||||
// (Default= map[exp.BooleanOperation][]byte{
|
||||
// exp.EqOp: []byte("="),
|
||||
// exp.NeqOp: []byte("!="),
|
||||
// exp.GtOp: []byte(">"),
|
||||
// exp.GteOp: []byte(">="),
|
||||
// exp.LtOp: []byte("<"),
|
||||
// exp.LteOp: []byte("<="),
|
||||
// exp.InOp: []byte("IN"),
|
||||
// exp.NotInOp: []byte("NOT IN"),
|
||||
// exp.IsOp: []byte("IS"),
|
||||
// exp.IsNotOp: []byte("IS NOT"),
|
||||
// exp.LikeOp: []byte("LIKE"),
|
||||
// exp.NotLikeOp: []byte("NOT LIKE"),
|
||||
// exp.ILikeOp: []byte("ILIKE"),
|
||||
// exp.NotILikeOp: []byte("NOT ILIKE"),
|
||||
// exp.RegexpLikeOp: []byte("~"),
|
||||
// exp.RegexpNotLikeOp: []byte("!~"),
|
||||
// exp.RegexpILikeOp: []byte("~*"),
|
||||
// exp.RegexpNotILikeOp: []byte("!~*"),
|
||||
// })
|
||||
BooleanOperatorLookup map[exp.BooleanOperation][]byte
|
||||
// A map used to look up BitwiseOperations and their SQL equivalents
|
||||
// (Default=map[exp.BitwiseOperation][]byte{
|
||||
// exp.BitwiseInversionOp: []byte("~"),
|
||||
// exp.BitwiseOrOp: []byte("|"),
|
||||
// exp.BitwiseAndOp: []byte("&"),
|
||||
// exp.BitwiseXorOp: []byte("#"),
|
||||
// exp.BitwiseLeftShiftOp: []byte("<<"),
|
||||
// exp.BitwiseRightShiftOp: []byte(">>"),
|
||||
// }),
|
||||
BitwiseOperatorLookup map[exp.BitwiseOperation][]byte
|
||||
// A map used to look up RangeOperations and their SQL equivalents
|
||||
// (Default=map[exp.RangeOperation][]byte{
|
||||
// exp.BetweenOp: []byte("BETWEEN"),
|
||||
// exp.NotBetweenOp: []byte("NOT BETWEEN"),
|
||||
// })
|
||||
RangeOperatorLookup map[exp.RangeOperation][]byte
|
||||
// A map used to look up JoinTypes and their SQL equivalents
|
||||
// (Default= map[exp.JoinType][]byte{
|
||||
// exp.InnerJoinType: []byte(" INNER JOIN "),
|
||||
// exp.FullOuterJoinType: []byte(" FULL OUTER JOIN "),
|
||||
// exp.RightOuterJoinType: []byte(" RIGHT OUTER JOIN "),
|
||||
// exp.LeftOuterJoinType: []byte(" LEFT OUTER JOIN "),
|
||||
// exp.FullJoinType: []byte(" FULL JOIN "),
|
||||
// exp.RightJoinType: []byte(" RIGHT JOIN "),
|
||||
// exp.LeftJoinType: []byte(" LEFT JOIN "),
|
||||
// exp.NaturalJoinType: []byte(" NATURAL JOIN "),
|
||||
// exp.NaturalLeftJoinType: []byte(" NATURAL LEFT JOIN "),
|
||||
// exp.NaturalRightJoinType: []byte(" NATURAL RIGHT JOIN "),
|
||||
// exp.NaturalFullJoinType: []byte(" NATURAL FULL JOIN "),
|
||||
// exp.CrossJoinType: []byte(" CROSS JOIN "),
|
||||
// })
|
||||
JoinTypeLookup map[exp.JoinType][]byte
|
||||
// Whether or not boolean data type is supported
|
||||
BooleanDataTypeSupported bool
|
||||
// Whether or not to use literal TRUE or FALSE for IS statements (e.g. IS TRUE or IS 0)
|
||||
UseLiteralIsBools bool
|
||||
// EscapedRunes is a map of a rune and the corresponding escape sequence in bytes. Used when escaping text
|
||||
// types.
|
||||
// (Default= map[rune][]byte{
|
||||
// '\'': []byte("''"),
|
||||
// })
|
||||
EscapedRunes map[rune][]byte
|
||||
|
||||
// The SQL fragment to use for CONFLICT (Default=[]byte(" ON CONFLICT"))
|
||||
ConflictFragment []byte
|
||||
// The SQL fragment to use for CONFLICT DO NOTHING (Default=[]byte(" DO NOTHING"))
|
||||
ConflictDoNothingFragment []byte
|
||||
// The SQL fragment to use for CONFLICT DO UPDATE (Default=[]byte(" DO UPDATE SET"))
|
||||
ConflictDoUpdateFragment []byte
|
||||
|
||||
// The order of SQL fragments when creating a SELECT statement
|
||||
// (Default=[]SQLFragmentType{
|
||||
// CommonTableSQLFragment,
|
||||
// SelectSQLFragment,
|
||||
// FromSQLFragment,
|
||||
// JoinSQLFragment,
|
||||
// WhereSQLFragment,
|
||||
// GroupBySQLFragment,
|
||||
// HavingSQLFragment,
|
||||
// CompoundsSQLFragment,
|
||||
// OrderSQLFragment,
|
||||
// LimitSQLFragment,
|
||||
// OffsetSQLFragment,
|
||||
// ForSQLFragment,
|
||||
// })
|
||||
SelectSQLOrder []SQLFragmentType
|
||||
|
||||
// The order of SQL fragments when creating an UPDATE statement
|
||||
// (Default=[]SQLFragmentType{
|
||||
// CommonTableSQLFragment,
|
||||
// UpdateBeginSQLFragment,
|
||||
// SourcesSQLFragment,
|
||||
// UpdateSQLFragment,
|
||||
// WhereSQLFragment,
|
||||
// OrderSQLFragment,
|
||||
// LimitSQLFragment,
|
||||
// ReturningSQLFragment,
|
||||
// })
|
||||
UpdateSQLOrder []SQLFragmentType
|
||||
|
||||
// The order of SQL fragments when creating an INSERT statement
|
||||
// (Default=[]SQLFragmentType{
|
||||
// CommonTableSQLFragment,
|
||||
// InsertBeingSQLFragment,
|
||||
// SourcesSQLFragment,
|
||||
// InsertSQLFragment,
|
||||
// ReturningSQLFragment,
|
||||
// })
|
||||
InsertSQLOrder []SQLFragmentType
|
||||
|
||||
// The order of SQL fragments when creating a DELETE statement
|
||||
// (Default=[]SQLFragmentType{
|
||||
// CommonTableSQLFragment,
|
||||
// DeleteBeginSQLFragment,
|
||||
// FromSQLFragment,
|
||||
// WhereSQLFragment,
|
||||
// OrderSQLFragment,
|
||||
// LimitSQLFragment,
|
||||
// ReturningSQLFragment,
|
||||
// })
|
||||
DeleteSQLOrder []SQLFragmentType
|
||||
|
||||
// The order of SQL fragments when creating a TRUNCATE statement
|
||||
// (Default=[]SQLFragmentType{
|
||||
// TruncateSQLFragment,
|
||||
// })
|
||||
TruncateSQLOrder []SQLFragmentType
|
||||
}
|
||||
)
|
||||
|
||||
const (
|
||||
CommonTableSQLFragment = iota
|
||||
SelectSQLFragment
|
||||
SelectWithLimitSQLFragment
|
||||
FromSQLFragment
|
||||
JoinSQLFragment
|
||||
WhereSQLFragment
|
||||
GroupBySQLFragment
|
||||
HavingSQLFragment
|
||||
CompoundsSQLFragment
|
||||
OrderSQLFragment
|
||||
OrderWithOffsetFetchSQLFragment
|
||||
LimitSQLFragment
|
||||
OffsetSQLFragment
|
||||
ForSQLFragment
|
||||
UpdateBeginSQLFragment
|
||||
SourcesSQLFragment
|
||||
IntoSQLFragment
|
||||
UpdateSQLFragment
|
||||
UpdateFromSQLFragment
|
||||
ReturningSQLFragment
|
||||
InsertBeingSQLFragment
|
||||
InsertSQLFragment
|
||||
DeleteBeginSQLFragment
|
||||
TruncateSQLFragment
|
||||
WindowSQLFragment
|
||||
)
|
||||
|
||||
// nolint:gocyclo // simple type to string conversion
|
||||
func (sf SQLFragmentType) String() string {
|
||||
switch sf {
|
||||
case CommonTableSQLFragment:
|
||||
return "CommonTableSQLFragment"
|
||||
case SelectSQLFragment:
|
||||
return "SelectSQLFragment"
|
||||
case FromSQLFragment:
|
||||
return "FromSQLFragment"
|
||||
case JoinSQLFragment:
|
||||
return "JoinSQLFragment"
|
||||
case WhereSQLFragment:
|
||||
return "WhereSQLFragment"
|
||||
case GroupBySQLFragment:
|
||||
return "GroupBySQLFragment"
|
||||
case HavingSQLFragment:
|
||||
return "HavingSQLFragment"
|
||||
case CompoundsSQLFragment:
|
||||
return "CompoundsSQLFragment"
|
||||
case OrderSQLFragment:
|
||||
return "OrderSQLFragment"
|
||||
case LimitSQLFragment:
|
||||
return "LimitSQLFragment"
|
||||
case OffsetSQLFragment:
|
||||
return "OffsetSQLFragment"
|
||||
case ForSQLFragment:
|
||||
return "ForSQLFragment"
|
||||
case UpdateBeginSQLFragment:
|
||||
return "UpdateBeginSQLFragment"
|
||||
case SourcesSQLFragment:
|
||||
return "SourcesSQLFragment"
|
||||
case IntoSQLFragment:
|
||||
return "IntoSQLFragment"
|
||||
case UpdateSQLFragment:
|
||||
return "UpdateSQLFragment"
|
||||
case UpdateFromSQLFragment:
|
||||
return "UpdateFromSQLFragment"
|
||||
case ReturningSQLFragment:
|
||||
return "ReturningSQLFragment"
|
||||
case InsertBeingSQLFragment:
|
||||
return "InsertBeingSQLFragment"
|
||||
case DeleteBeginSQLFragment:
|
||||
return "DeleteBeginSQLFragment"
|
||||
case TruncateSQLFragment:
|
||||
return "TruncateSQLFragment"
|
||||
case WindowSQLFragment:
|
||||
return "WindowSQLFragment"
|
||||
}
|
||||
return fmt.Sprintf("%d", sf)
|
||||
}
|
||||
|
||||
//nolint:funlen
|
||||
func DefaultDialectOptions() *SQLDialectOptions {
|
||||
return &SQLDialectOptions{
|
||||
SupportsOrderByOnDelete: false,
|
||||
SupportsDeleteTableHint: false,
|
||||
SupportsOrderByOnUpdate: false,
|
||||
SupportsLimitOnDelete: false,
|
||||
SupportsLimitOnUpdate: false,
|
||||
SupportsReturn: true,
|
||||
SupportsConflictUpdateWhere: true,
|
||||
SupportsInsertIgnoreSyntax: false,
|
||||
SupportsConflictTarget: true,
|
||||
SupportsWithCTE: true,
|
||||
SupportsWithCTERecursive: true,
|
||||
SupportsDistinctOn: true,
|
||||
WrapCompoundsInParens: true,
|
||||
SupportsWindowFunction: true,
|
||||
SupportsLateral: true,
|
||||
|
||||
SupportsMultipleUpdateTables: true,
|
||||
UseFromClauseForMultipleUpdateTables: true,
|
||||
|
||||
UpdateClause: []byte("UPDATE"),
|
||||
InsertClause: []byte("INSERT INTO"),
|
||||
InsertIgnoreClause: []byte("INSERT IGNORE INTO"),
|
||||
SelectClause: []byte("SELECT"),
|
||||
DeleteClause: []byte("DELETE"),
|
||||
TruncateClause: []byte("TRUNCATE"),
|
||||
WithFragment: []byte("WITH "),
|
||||
RecursiveFragment: []byte("RECURSIVE "),
|
||||
CascadeFragment: []byte(" CASCADE"),
|
||||
RestrictFragment: []byte(" RESTRICT"),
|
||||
DefaultValuesFragment: []byte(" DEFAULT VALUES"),
|
||||
ValuesFragment: []byte(" VALUES "),
|
||||
IdentityFragment: []byte(" IDENTITY"),
|
||||
SetFragment: []byte(" SET "),
|
||||
DistinctFragment: []byte("DISTINCT"),
|
||||
ReturningFragment: []byte(" RETURNING "),
|
||||
FromFragment: []byte(" FROM"),
|
||||
UsingFragment: []byte(" USING "),
|
||||
OnFragment: []byte(" ON "),
|
||||
WhereFragment: []byte(" WHERE "),
|
||||
GroupByFragment: []byte(" GROUP BY "),
|
||||
HavingFragment: []byte(" HAVING "),
|
||||
WindowFragment: []byte(" WINDOW "),
|
||||
WindowPartitionByFragment: []byte("PARTITION BY "),
|
||||
WindowOrderByFragment: []byte("ORDER BY "),
|
||||
WindowOverFragment: []byte(" OVER "),
|
||||
OrderByFragment: []byte(" ORDER BY "),
|
||||
FetchFragment: []byte(" "),
|
||||
LimitFragment: []byte(" LIMIT "),
|
||||
OffsetFragment: []byte(" OFFSET "),
|
||||
ForUpdateFragment: []byte(" FOR UPDATE "),
|
||||
ForNoKeyUpdateFragment: []byte(" FOR NO KEY UPDATE "),
|
||||
ForShareFragment: []byte(" FOR SHARE "),
|
||||
ForKeyShareFragment: []byte(" FOR KEY SHARE "),
|
||||
OfFragment: []byte("OF "),
|
||||
NowaitFragment: []byte("NOWAIT"),
|
||||
SkipLockedFragment: []byte("SKIP LOCKED"),
|
||||
LateralFragment: []byte("LATERAL "),
|
||||
AsFragment: []byte(" AS "),
|
||||
AscFragment: []byte(" ASC"),
|
||||
DescFragment: []byte(" DESC"),
|
||||
NullsFirstFragment: []byte(" NULLS FIRST"),
|
||||
NullsLastFragment: []byte(" NULLS LAST"),
|
||||
AndFragment: []byte(" AND "),
|
||||
OrFragment: []byte(" OR "),
|
||||
UnionFragment: []byte(" UNION "),
|
||||
UnionAllFragment: []byte(" UNION ALL "),
|
||||
IntersectFragment: []byte(" INTERSECT "),
|
||||
IntersectAllFragment: []byte(" INTERSECT ALL "),
|
||||
ConflictFragment: []byte(" ON CONFLICT"),
|
||||
ConflictDoUpdateFragment: []byte(" DO UPDATE SET "),
|
||||
ConflictDoNothingFragment: []byte(" DO NOTHING"),
|
||||
CastFragment: []byte("CAST"),
|
||||
CaseFragment: []byte("CASE "),
|
||||
WhenFragment: []byte(" WHEN "),
|
||||
ThenFragment: []byte(" THEN "),
|
||||
ElseFragment: []byte(" ELSE "),
|
||||
EndFragment: []byte(" END"),
|
||||
Null: []byte("NULL"),
|
||||
True: []byte("TRUE"),
|
||||
False: []byte("FALSE"),
|
||||
|
||||
PlaceHolderFragment: []byte("?"),
|
||||
QuoteRune: '"',
|
||||
StringQuote: '\'',
|
||||
SetOperatorRune: '=',
|
||||
CommaRune: ',',
|
||||
SpaceRune: ' ',
|
||||
LeftParenRune: '(',
|
||||
RightParenRune: ')',
|
||||
StarRune: '*',
|
||||
PeriodRune: '.',
|
||||
EmptyString: "",
|
||||
|
||||
BooleanOperatorLookup: map[exp.BooleanOperation][]byte{
|
||||
exp.EqOp: []byte("="),
|
||||
exp.NeqOp: []byte("!="),
|
||||
exp.GtOp: []byte(">"),
|
||||
exp.GteOp: []byte(">="),
|
||||
exp.LtOp: []byte("<"),
|
||||
exp.LteOp: []byte("<="),
|
||||
exp.InOp: []byte("IN"),
|
||||
exp.NotInOp: []byte("NOT IN"),
|
||||
exp.IsOp: []byte("IS"),
|
||||
exp.IsNotOp: []byte("IS NOT"),
|
||||
exp.LikeOp: []byte("LIKE"),
|
||||
exp.NotLikeOp: []byte("NOT LIKE"),
|
||||
exp.ILikeOp: []byte("ILIKE"),
|
||||
exp.NotILikeOp: []byte("NOT ILIKE"),
|
||||
exp.RegexpLikeOp: []byte("~"),
|
||||
exp.RegexpNotLikeOp: []byte("!~"),
|
||||
exp.RegexpILikeOp: []byte("~*"),
|
||||
exp.RegexpNotILikeOp: []byte("!~*"),
|
||||
},
|
||||
BitwiseOperatorLookup: map[exp.BitwiseOperation][]byte{
|
||||
exp.BitwiseInversionOp: []byte("~"),
|
||||
exp.BitwiseOrOp: []byte("|"),
|
||||
exp.BitwiseAndOp: []byte("&"),
|
||||
exp.BitwiseXorOp: []byte("#"),
|
||||
exp.BitwiseLeftShiftOp: []byte("<<"),
|
||||
exp.BitwiseRightShiftOp: []byte(">>"),
|
||||
},
|
||||
RangeOperatorLookup: map[exp.RangeOperation][]byte{
|
||||
exp.BetweenOp: []byte("BETWEEN"),
|
||||
exp.NotBetweenOp: []byte("NOT BETWEEN"),
|
||||
},
|
||||
JoinTypeLookup: map[exp.JoinType][]byte{
|
||||
exp.InnerJoinType: []byte(" INNER JOIN "),
|
||||
exp.FullOuterJoinType: []byte(" FULL OUTER JOIN "),
|
||||
exp.RightOuterJoinType: []byte(" RIGHT OUTER JOIN "),
|
||||
exp.LeftOuterJoinType: []byte(" LEFT OUTER JOIN "),
|
||||
exp.FullJoinType: []byte(" FULL JOIN "),
|
||||
exp.RightJoinType: []byte(" RIGHT JOIN "),
|
||||
exp.LeftJoinType: []byte(" LEFT JOIN "),
|
||||
exp.NaturalJoinType: []byte(" NATURAL JOIN "),
|
||||
exp.NaturalLeftJoinType: []byte(" NATURAL LEFT JOIN "),
|
||||
exp.NaturalRightJoinType: []byte(" NATURAL RIGHT JOIN "),
|
||||
exp.NaturalFullJoinType: []byte(" NATURAL FULL JOIN "),
|
||||
exp.CrossJoinType: []byte(" CROSS JOIN "),
|
||||
},
|
||||
|
||||
TimeFormat: time.RFC3339Nano,
|
||||
|
||||
BooleanDataTypeSupported: true,
|
||||
UseLiteralIsBools: true,
|
||||
|
||||
EscapedRunes: map[rune][]byte{
|
||||
'\'': []byte("''"),
|
||||
},
|
||||
|
||||
SelectSQLOrder: []SQLFragmentType{
|
||||
CommonTableSQLFragment,
|
||||
SelectSQLFragment,
|
||||
FromSQLFragment,
|
||||
JoinSQLFragment,
|
||||
WhereSQLFragment,
|
||||
GroupBySQLFragment,
|
||||
HavingSQLFragment,
|
||||
WindowSQLFragment,
|
||||
CompoundsSQLFragment,
|
||||
OrderSQLFragment,
|
||||
LimitSQLFragment,
|
||||
OffsetSQLFragment,
|
||||
ForSQLFragment,
|
||||
},
|
||||
UpdateSQLOrder: []SQLFragmentType{
|
||||
CommonTableSQLFragment,
|
||||
UpdateBeginSQLFragment,
|
||||
SourcesSQLFragment,
|
||||
UpdateSQLFragment,
|
||||
UpdateFromSQLFragment,
|
||||
WhereSQLFragment,
|
||||
OrderSQLFragment,
|
||||
LimitSQLFragment,
|
||||
ReturningSQLFragment,
|
||||
},
|
||||
InsertSQLOrder: []SQLFragmentType{
|
||||
CommonTableSQLFragment,
|
||||
InsertBeingSQLFragment,
|
||||
IntoSQLFragment,
|
||||
InsertSQLFragment,
|
||||
ReturningSQLFragment,
|
||||
},
|
||||
DeleteSQLOrder: []SQLFragmentType{
|
||||
CommonTableSQLFragment,
|
||||
DeleteBeginSQLFragment,
|
||||
FromSQLFragment,
|
||||
WhereSQLFragment,
|
||||
OrderSQLFragment,
|
||||
LimitSQLFragment,
|
||||
ReturningSQLFragment,
|
||||
},
|
||||
TruncateSQLOrder: []SQLFragmentType{
|
||||
TruncateSQLFragment,
|
||||
},
|
||||
}
|
||||
}
|
||||
15
vendor/github.com/doug-martin/goqu/v9/sqlgen/sqlgen.go
generated
vendored
Normal file
15
vendor/github.com/doug-martin/goqu/v9/sqlgen/sqlgen.go
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
package sqlgen
|
||||
|
||||
import "time"
|
||||
|
||||
var timeLocation = time.UTC
|
||||
|
||||
// Set the location to use when interpolating time.Time instances. See https://golang.org/pkg/time/#LoadLocation
|
||||
// NOTE: This has no effect when using prepared statements.
|
||||
func SetTimeLocation(loc *time.Location) {
|
||||
timeLocation = loc
|
||||
}
|
||||
|
||||
func GetTimeLocation() *time.Location {
|
||||
return timeLocation
|
||||
}
|
||||
64
vendor/github.com/doug-martin/goqu/v9/sqlgen/truncate_sql_generator.go
generated
vendored
Normal file
64
vendor/github.com/doug-martin/goqu/v9/sqlgen/truncate_sql_generator.go
generated
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
package sqlgen
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/doug-martin/goqu/v9/exp"
|
||||
"github.com/doug-martin/goqu/v9/internal/errors"
|
||||
"github.com/doug-martin/goqu/v9/internal/sb"
|
||||
)
|
||||
|
||||
type (
|
||||
// An adapter interface to be used by a Dataset to generate SQL for a specific dialect.
|
||||
// See DefaultAdapter for a concrete implementation and examples.
|
||||
TruncateSQLGenerator interface {
|
||||
Dialect() string
|
||||
Generate(b sb.SQLBuilder, clauses exp.TruncateClauses)
|
||||
}
|
||||
// The default adapter. This class should be used when building a new adapter. When creating a new adapter you can
|
||||
// either override methods, or more typically update default values.
|
||||
// See (github.com/doug-martin/goqu/dialect/postgres)
|
||||
truncateSQLGenerator struct {
|
||||
CommonSQLGenerator
|
||||
}
|
||||
)
|
||||
|
||||
var errNoSourceForTruncate = errors.New("no source found when generating truncate sql")
|
||||
|
||||
func NewTruncateSQLGenerator(dialect string, do *SQLDialectOptions) TruncateSQLGenerator {
|
||||
return &truncateSQLGenerator{NewCommonSQLGenerator(dialect, do)}
|
||||
}
|
||||
|
||||
func (tsg *truncateSQLGenerator) Generate(b sb.SQLBuilder, clauses exp.TruncateClauses) {
|
||||
if !clauses.HasTable() {
|
||||
b.SetError(errNoSourceForTruncate)
|
||||
return
|
||||
}
|
||||
for _, f := range tsg.DialectOptions().TruncateSQLOrder {
|
||||
if b.Error() != nil {
|
||||
return
|
||||
}
|
||||
switch f {
|
||||
case TruncateSQLFragment:
|
||||
tsg.TruncateSQL(b, clauses.Table(), clauses.Options())
|
||||
default:
|
||||
b.SetError(ErrNotSupportedFragment("TRUNCATE", f))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Generates a TRUNCATE statement
|
||||
func (tsg *truncateSQLGenerator) TruncateSQL(b sb.SQLBuilder, from exp.ColumnListExpression, opts exp.TruncateOptions) {
|
||||
b.Write(tsg.DialectOptions().TruncateClause)
|
||||
tsg.SourcesSQL(b, from)
|
||||
if opts.Identity != tsg.DialectOptions().EmptyString {
|
||||
b.WriteRunes(tsg.DialectOptions().SpaceRune).
|
||||
WriteStrings(strings.ToUpper(opts.Identity)).
|
||||
Write(tsg.DialectOptions().IdentityFragment)
|
||||
}
|
||||
if opts.Cascade {
|
||||
b.Write(tsg.DialectOptions().CascadeFragment)
|
||||
} else if opts.Restrict {
|
||||
b.Write(tsg.DialectOptions().RestrictFragment)
|
||||
}
|
||||
}
|
||||
112
vendor/github.com/doug-martin/goqu/v9/sqlgen/update_sql_generator.go
generated
vendored
Normal file
112
vendor/github.com/doug-martin/goqu/v9/sqlgen/update_sql_generator.go
generated
vendored
Normal file
@@ -0,0 +1,112 @@
|
||||
package sqlgen
|
||||
|
||||
import (
|
||||
"github.com/doug-martin/goqu/v9/exp"
|
||||
"github.com/doug-martin/goqu/v9/internal/errors"
|
||||
"github.com/doug-martin/goqu/v9/internal/sb"
|
||||
)
|
||||
|
||||
type (
|
||||
// An adapter interface to be used by a Dataset to generate SQL for a specific dialect.
|
||||
// See DefaultAdapter for a concrete implementation and examples.
|
||||
UpdateSQLGenerator interface {
|
||||
Dialect() string
|
||||
Generate(b sb.SQLBuilder, clauses exp.UpdateClauses)
|
||||
}
|
||||
// The default adapter. This class should be used when building a new adapter. When creating a new adapter you can
|
||||
// either override methods, or more typically update default values.
|
||||
// See (github.com/doug-martin/goqu/dialect/postgres)
|
||||
updateSQLGenerator struct {
|
||||
CommonSQLGenerator
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
ErrNoSourceForUpdate = errors.New("no source found when generating update sql")
|
||||
ErrNoSetValuesForUpdate = errors.New("no set values found when generating UPDATE sql")
|
||||
)
|
||||
|
||||
func NewUpdateSQLGenerator(dialect string, do *SQLDialectOptions) UpdateSQLGenerator {
|
||||
return &updateSQLGenerator{NewCommonSQLGenerator(dialect, do)}
|
||||
}
|
||||
|
||||
func (usg *updateSQLGenerator) Generate(b sb.SQLBuilder, clauses exp.UpdateClauses) {
|
||||
if !clauses.HasTable() {
|
||||
b.SetError(ErrNoSourceForUpdate)
|
||||
return
|
||||
}
|
||||
if !clauses.HasSetValues() {
|
||||
b.SetError(ErrNoSetValuesForUpdate)
|
||||
return
|
||||
}
|
||||
if !usg.DialectOptions().SupportsMultipleUpdateTables && clauses.HasFrom() {
|
||||
b.SetError(errors.New("%s dialect does not support multiple tables in UPDATE", usg.Dialect()))
|
||||
}
|
||||
updates, err := exp.NewUpdateExpressions(clauses.SetValues())
|
||||
if err != nil {
|
||||
b.SetError(err)
|
||||
return
|
||||
}
|
||||
for _, f := range usg.DialectOptions().UpdateSQLOrder {
|
||||
if b.Error() != nil {
|
||||
return
|
||||
}
|
||||
switch f {
|
||||
case CommonTableSQLFragment:
|
||||
usg.ExpressionSQLGenerator().Generate(b, clauses.CommonTables())
|
||||
case UpdateBeginSQLFragment:
|
||||
usg.UpdateBeginSQL(b)
|
||||
case SourcesSQLFragment:
|
||||
usg.updateTableSQL(b, clauses)
|
||||
case UpdateSQLFragment:
|
||||
usg.UpdateExpressionsSQL(b, updates...)
|
||||
case UpdateFromSQLFragment:
|
||||
usg.updateFromSQL(b, clauses.From())
|
||||
case WhereSQLFragment:
|
||||
usg.WhereSQL(b, clauses.Where())
|
||||
case OrderSQLFragment:
|
||||
if usg.DialectOptions().SupportsOrderByOnUpdate {
|
||||
usg.OrderSQL(b, clauses.Order())
|
||||
}
|
||||
case LimitSQLFragment:
|
||||
if usg.DialectOptions().SupportsLimitOnUpdate {
|
||||
usg.LimitSQL(b, clauses.Limit())
|
||||
}
|
||||
case ReturningSQLFragment:
|
||||
usg.ReturningSQL(b, clauses.Returning())
|
||||
default:
|
||||
b.SetError(ErrNotSupportedFragment("UPDATE", f))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Adds the correct fragment to being an UPDATE statement
|
||||
func (usg *updateSQLGenerator) UpdateBeginSQL(b sb.SQLBuilder) {
|
||||
b.Write(usg.DialectOptions().UpdateClause)
|
||||
}
|
||||
|
||||
// Adds column setters in an update SET clause
|
||||
func (usg *updateSQLGenerator) UpdateExpressionsSQL(b sb.SQLBuilder, updates ...exp.UpdateExpression) {
|
||||
b.Write(usg.DialectOptions().SetFragment)
|
||||
usg.UpdateExpressionSQL(b, updates...)
|
||||
}
|
||||
|
||||
func (usg *updateSQLGenerator) updateTableSQL(b sb.SQLBuilder, uc exp.UpdateClauses) {
|
||||
b.WriteRunes(usg.DialectOptions().SpaceRune)
|
||||
usg.ExpressionSQLGenerator().Generate(b, uc.Table())
|
||||
if uc.HasFrom() {
|
||||
if !usg.DialectOptions().UseFromClauseForMultipleUpdateTables {
|
||||
b.WriteRunes(usg.DialectOptions().CommaRune)
|
||||
usg.ExpressionSQLGenerator().Generate(b, uc.From())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (usg *updateSQLGenerator) updateFromSQL(b sb.SQLBuilder, ce exp.ColumnListExpression) {
|
||||
if ce == nil || ce.IsEmpty() {
|
||||
return
|
||||
}
|
||||
if usg.DialectOptions().UseFromClauseForMultipleUpdateTables {
|
||||
usg.FromSQL(b, ce)
|
||||
}
|
||||
}
|
||||
169
vendor/github.com/doug-martin/goqu/v9/truncate_dataset.go
generated
vendored
Normal file
169
vendor/github.com/doug-martin/goqu/v9/truncate_dataset.go
generated
vendored
Normal file
@@ -0,0 +1,169 @@
|
||||
package goqu
|
||||
|
||||
import (
|
||||
"github.com/doug-martin/goqu/v9/exec"
|
||||
"github.com/doug-martin/goqu/v9/exp"
|
||||
"github.com/doug-martin/goqu/v9/internal/sb"
|
||||
)
|
||||
|
||||
type TruncateDataset struct {
|
||||
dialect SQLDialect
|
||||
clauses exp.TruncateClauses
|
||||
isPrepared prepared
|
||||
queryFactory exec.QueryFactory
|
||||
err error
|
||||
}
|
||||
|
||||
// used internally by database to create a database with a specific adapter
|
||||
func newTruncateDataset(d string, queryFactory exec.QueryFactory) *TruncateDataset {
|
||||
return &TruncateDataset{
|
||||
clauses: exp.NewTruncateClauses(),
|
||||
dialect: GetDialect(d),
|
||||
queryFactory: queryFactory,
|
||||
}
|
||||
}
|
||||
|
||||
func Truncate(table ...interface{}) *TruncateDataset {
|
||||
return newTruncateDataset("default", nil).Table(table...)
|
||||
}
|
||||
|
||||
// Sets the adapter used to serialize values and create the SQL statement
|
||||
func (td *TruncateDataset) WithDialect(dl string) *TruncateDataset {
|
||||
ds := td.copy(td.GetClauses())
|
||||
ds.dialect = GetDialect(dl)
|
||||
return ds
|
||||
}
|
||||
|
||||
// Set the parameter interpolation behavior. See examples
|
||||
//
|
||||
// prepared: If true the dataset WILL NOT interpolate the parameters.
|
||||
func (td *TruncateDataset) Prepared(prepared bool) *TruncateDataset {
|
||||
ret := td.copy(td.clauses)
|
||||
ret.isPrepared = preparedFromBool(prepared)
|
||||
return ret
|
||||
}
|
||||
|
||||
func (td *TruncateDataset) IsPrepared() bool {
|
||||
return td.isPrepared.Bool()
|
||||
}
|
||||
|
||||
// Returns the current adapter on the dataset
|
||||
func (td *TruncateDataset) Dialect() SQLDialect {
|
||||
return td.dialect
|
||||
}
|
||||
|
||||
// Returns the current adapter on the dataset
|
||||
func (td *TruncateDataset) SetDialect(dialect SQLDialect) *TruncateDataset {
|
||||
cd := td.copy(td.GetClauses())
|
||||
cd.dialect = dialect
|
||||
return cd
|
||||
}
|
||||
|
||||
func (td *TruncateDataset) Expression() exp.Expression {
|
||||
return td
|
||||
}
|
||||
|
||||
// Clones the dataset
|
||||
func (td *TruncateDataset) Clone() exp.Expression {
|
||||
return td.copy(td.clauses)
|
||||
}
|
||||
|
||||
// Returns the current clauses on the dataset.
|
||||
func (td *TruncateDataset) GetClauses() exp.TruncateClauses {
|
||||
return td.clauses
|
||||
}
|
||||
|
||||
// used interally to copy the dataset
|
||||
func (td *TruncateDataset) copy(clauses exp.TruncateClauses) *TruncateDataset {
|
||||
return &TruncateDataset{
|
||||
dialect: td.dialect,
|
||||
clauses: clauses,
|
||||
isPrepared: td.isPrepared,
|
||||
queryFactory: td.queryFactory,
|
||||
err: td.err,
|
||||
}
|
||||
}
|
||||
|
||||
// Adds a FROM clause. This return a new dataset with the original sources replaced. See examples.
|
||||
// You can pass in the following.
|
||||
// string: Will automatically be turned into an identifier
|
||||
// IdentifierExpression
|
||||
// LiteralExpression: (See Literal) Will use the literal SQL
|
||||
func (td *TruncateDataset) Table(table ...interface{}) *TruncateDataset {
|
||||
return td.copy(td.clauses.SetTable(exp.NewColumnListExpression(table...)))
|
||||
}
|
||||
|
||||
// Adds a CASCADE clause
|
||||
func (td *TruncateDataset) Cascade() *TruncateDataset {
|
||||
opts := td.clauses.Options()
|
||||
opts.Cascade = true
|
||||
return td.copy(td.clauses.SetOptions(opts))
|
||||
}
|
||||
|
||||
// Clears the CASCADE clause
|
||||
func (td *TruncateDataset) NoCascade() *TruncateDataset {
|
||||
opts := td.clauses.Options()
|
||||
opts.Cascade = false
|
||||
return td.copy(td.clauses.SetOptions(opts))
|
||||
}
|
||||
|
||||
// Adds a RESTRICT clause
|
||||
func (td *TruncateDataset) Restrict() *TruncateDataset {
|
||||
opts := td.clauses.Options()
|
||||
opts.Restrict = true
|
||||
return td.copy(td.clauses.SetOptions(opts))
|
||||
}
|
||||
|
||||
// Clears the RESTRICT clause
|
||||
func (td *TruncateDataset) NoRestrict() *TruncateDataset {
|
||||
opts := td.clauses.Options()
|
||||
opts.Restrict = false
|
||||
return td.copy(td.clauses.SetOptions(opts))
|
||||
}
|
||||
|
||||
// Add a IDENTITY clause (e.g. RESTART)
|
||||
func (td *TruncateDataset) Identity(identity string) *TruncateDataset {
|
||||
opts := td.clauses.Options()
|
||||
opts.Identity = identity
|
||||
return td.copy(td.clauses.SetOptions(opts))
|
||||
}
|
||||
|
||||
// Get any error that has been set or nil if no error has been set.
|
||||
func (td *TruncateDataset) Error() error {
|
||||
return td.err
|
||||
}
|
||||
|
||||
// Set an error on the dataset if one has not already been set. This error will be returned by a future call to Error
|
||||
// or as part of ToSQL. This can be used by end users to record errors while building up queries without having to
|
||||
// track those separately.
|
||||
func (td *TruncateDataset) SetError(err error) *TruncateDataset {
|
||||
if td.err == nil {
|
||||
td.err = err
|
||||
}
|
||||
|
||||
return td
|
||||
}
|
||||
|
||||
// Generates a TRUNCATE sql statement, if Prepared has been called with true then the parameters will not be interpolated.
|
||||
// See examples.
|
||||
//
|
||||
// Errors:
|
||||
// * There is an error generating the SQL
|
||||
func (td *TruncateDataset) ToSQL() (sql string, params []interface{}, err error) {
|
||||
return td.truncateSQLBuilder().ToSQL()
|
||||
}
|
||||
|
||||
// Generates the TRUNCATE sql, and returns an Exec struct with the sql set to the TRUNCATE statement
|
||||
// db.From("test").Truncate().Executor().Exec()
|
||||
func (td *TruncateDataset) Executor() exec.QueryExecutor {
|
||||
return td.queryFactory.FromSQLBuilder(td.truncateSQLBuilder())
|
||||
}
|
||||
|
||||
func (td *TruncateDataset) truncateSQLBuilder() sb.SQLBuilder {
|
||||
buf := sb.NewSQLBuilder(td.isPrepared.Bool())
|
||||
if td.err != nil {
|
||||
return buf.SetError(td.err)
|
||||
}
|
||||
td.dialect.ToTruncateSQL(buf, td.clauses)
|
||||
return buf
|
||||
}
|
||||
245
vendor/github.com/doug-martin/goqu/v9/update_dataset.go
generated
vendored
Normal file
245
vendor/github.com/doug-martin/goqu/v9/update_dataset.go
generated
vendored
Normal file
@@ -0,0 +1,245 @@
|
||||
package goqu
|
||||
|
||||
import (
|
||||
"github.com/doug-martin/goqu/v9/exec"
|
||||
"github.com/doug-martin/goqu/v9/exp"
|
||||
"github.com/doug-martin/goqu/v9/internal/errors"
|
||||
"github.com/doug-martin/goqu/v9/internal/sb"
|
||||
)
|
||||
|
||||
type UpdateDataset struct {
|
||||
dialect SQLDialect
|
||||
clauses exp.UpdateClauses
|
||||
isPrepared prepared
|
||||
queryFactory exec.QueryFactory
|
||||
err error
|
||||
}
|
||||
|
||||
var ErrUnsupportedUpdateTableType = errors.New("unsupported table type, a string or identifier expression is required")
|
||||
|
||||
// used internally by database to create a database with a specific adapter
|
||||
func newUpdateDataset(d string, queryFactory exec.QueryFactory) *UpdateDataset {
|
||||
return &UpdateDataset{
|
||||
clauses: exp.NewUpdateClauses(),
|
||||
dialect: GetDialect(d),
|
||||
queryFactory: queryFactory,
|
||||
}
|
||||
}
|
||||
|
||||
func Update(table interface{}) *UpdateDataset {
|
||||
return newUpdateDataset("default", nil).Table(table)
|
||||
}
|
||||
|
||||
// Set the parameter interpolation behavior. See examples
|
||||
//
|
||||
// prepared: If true the dataset WILL NOT interpolate the parameters.
|
||||
func (ud *UpdateDataset) Prepared(prepared bool) *UpdateDataset {
|
||||
ret := ud.copy(ud.clauses)
|
||||
ret.isPrepared = preparedFromBool(prepared)
|
||||
return ret
|
||||
}
|
||||
|
||||
func (ud *UpdateDataset) IsPrepared() bool {
|
||||
return ud.isPrepared.Bool()
|
||||
}
|
||||
|
||||
// Sets the adapter used to serialize values and create the SQL statement
|
||||
func (ud *UpdateDataset) WithDialect(dl string) *UpdateDataset {
|
||||
ds := ud.copy(ud.GetClauses())
|
||||
ds.dialect = GetDialect(dl)
|
||||
return ds
|
||||
}
|
||||
|
||||
// Returns the current adapter on the dataset
|
||||
func (ud *UpdateDataset) Dialect() SQLDialect {
|
||||
return ud.dialect
|
||||
}
|
||||
|
||||
// Returns the current adapter on the dataset
|
||||
func (ud *UpdateDataset) SetDialect(dialect SQLDialect) *UpdateDataset {
|
||||
cd := ud.copy(ud.GetClauses())
|
||||
cd.dialect = dialect
|
||||
return cd
|
||||
}
|
||||
|
||||
func (ud *UpdateDataset) Expression() exp.Expression {
|
||||
return ud
|
||||
}
|
||||
|
||||
// Clones the dataset
|
||||
func (ud *UpdateDataset) Clone() exp.Expression {
|
||||
return ud.copy(ud.clauses)
|
||||
}
|
||||
|
||||
// Returns the current clauses on the dataset.
|
||||
func (ud *UpdateDataset) GetClauses() exp.UpdateClauses {
|
||||
return ud.clauses
|
||||
}
|
||||
|
||||
// used internally to copy the dataset
|
||||
func (ud *UpdateDataset) copy(clauses exp.UpdateClauses) *UpdateDataset {
|
||||
return &UpdateDataset{
|
||||
dialect: ud.dialect,
|
||||
clauses: clauses,
|
||||
isPrepared: ud.isPrepared,
|
||||
queryFactory: ud.queryFactory,
|
||||
err: ud.err,
|
||||
}
|
||||
}
|
||||
|
||||
// Creates a WITH clause for a common table expression (CTE).
|
||||
//
|
||||
// The name will be available to use in the UPDATE from in the associated query; and can optionally
|
||||
// contain a list of column names "name(col1, col2, col3)".
|
||||
//
|
||||
// The name will refer to the results of the specified subquery.
|
||||
func (ud *UpdateDataset) With(name string, subquery exp.Expression) *UpdateDataset {
|
||||
return ud.copy(ud.clauses.CommonTablesAppend(exp.NewCommonTableExpression(false, name, subquery)))
|
||||
}
|
||||
|
||||
// Creates a WITH RECURSIVE clause for a common table expression (CTE)
|
||||
//
|
||||
// The name will be available to use in the UPDATE from in the associated query; and must
|
||||
// contain a list of column names "name(col1, col2, col3)" for a recursive clause.
|
||||
//
|
||||
// The name will refer to the results of the specified subquery. The subquery for
|
||||
// a recursive query will always end with a UNION or UNION ALL with a clause that
|
||||
// refers to the CTE by name.
|
||||
func (ud *UpdateDataset) WithRecursive(name string, subquery exp.Expression) *UpdateDataset {
|
||||
return ud.copy(ud.clauses.CommonTablesAppend(exp.NewCommonTableExpression(true, name, subquery)))
|
||||
}
|
||||
|
||||
// Sets the table to update.
|
||||
func (ud *UpdateDataset) Table(table interface{}) *UpdateDataset {
|
||||
switch t := table.(type) {
|
||||
case exp.Expression:
|
||||
return ud.copy(ud.clauses.SetTable(t))
|
||||
case string:
|
||||
return ud.copy(ud.clauses.SetTable(exp.ParseIdentifier(t)))
|
||||
default:
|
||||
panic(ErrUnsupportedUpdateTableType)
|
||||
}
|
||||
}
|
||||
|
||||
// Sets the values to use in the SET clause. See examples.
|
||||
func (ud *UpdateDataset) Set(values interface{}) *UpdateDataset {
|
||||
return ud.copy(ud.clauses.SetSetValues(values))
|
||||
}
|
||||
|
||||
// Allows specifying other tables to reference in your update (If your dialect supports it). See examples.
|
||||
func (ud *UpdateDataset) From(tables ...interface{}) *UpdateDataset {
|
||||
return ud.copy(ud.clauses.SetFrom(exp.NewColumnListExpression(tables...)))
|
||||
}
|
||||
|
||||
// Adds a WHERE clause. See examples.
|
||||
func (ud *UpdateDataset) Where(expressions ...exp.Expression) *UpdateDataset {
|
||||
return ud.copy(ud.clauses.WhereAppend(expressions...))
|
||||
}
|
||||
|
||||
// Removes the WHERE clause. See examples.
|
||||
func (ud *UpdateDataset) ClearWhere() *UpdateDataset {
|
||||
return ud.copy(ud.clauses.ClearWhere())
|
||||
}
|
||||
|
||||
// Adds a ORDER clause. If the ORDER is currently set it replaces it. See examples.
|
||||
func (ud *UpdateDataset) Order(order ...exp.OrderedExpression) *UpdateDataset {
|
||||
return ud.copy(ud.clauses.SetOrder(order...))
|
||||
}
|
||||
|
||||
// Adds a more columns to the current ORDER BY clause. If no order has be previously specified it is the same as
|
||||
// calling Order. See examples.
|
||||
func (ud *UpdateDataset) OrderAppend(order ...exp.OrderedExpression) *UpdateDataset {
|
||||
return ud.copy(ud.clauses.OrderAppend(order...))
|
||||
}
|
||||
|
||||
// Adds a more columns to the beginning of the current ORDER BY clause. If no order has be previously specified it is the same as
|
||||
// calling Order. See examples.
|
||||
func (ud *UpdateDataset) OrderPrepend(order ...exp.OrderedExpression) *UpdateDataset {
|
||||
return ud.copy(ud.clauses.OrderPrepend(order...))
|
||||
}
|
||||
|
||||
// Removes the ORDER BY clause. See examples.
|
||||
func (ud *UpdateDataset) ClearOrder() *UpdateDataset {
|
||||
return ud.copy(ud.clauses.ClearOrder())
|
||||
}
|
||||
|
||||
// Adds a LIMIT clause. If the LIMIT is currently set it replaces it. See examples.
|
||||
func (ud *UpdateDataset) Limit(limit uint) *UpdateDataset {
|
||||
if limit > 0 {
|
||||
return ud.copy(ud.clauses.SetLimit(limit))
|
||||
}
|
||||
return ud.copy(ud.clauses.ClearLimit())
|
||||
}
|
||||
|
||||
// Adds a LIMIT ALL clause. If the LIMIT is currently set it replaces it. See examples.
|
||||
func (ud *UpdateDataset) LimitAll() *UpdateDataset {
|
||||
return ud.copy(ud.clauses.SetLimit(L("ALL")))
|
||||
}
|
||||
|
||||
// Removes the LIMIT clause.
|
||||
func (ud *UpdateDataset) ClearLimit() *UpdateDataset {
|
||||
return ud.copy(ud.clauses.ClearLimit())
|
||||
}
|
||||
|
||||
// Adds a RETURNING clause to the dataset if the adapter supports it. See examples.
|
||||
func (ud *UpdateDataset) Returning(returning ...interface{}) *UpdateDataset {
|
||||
return ud.copy(ud.clauses.SetReturning(exp.NewColumnListExpression(returning...)))
|
||||
}
|
||||
|
||||
// Get any error that has been set or nil if no error has been set.
|
||||
func (ud *UpdateDataset) Error() error {
|
||||
return ud.err
|
||||
}
|
||||
|
||||
// Set an error on the dataset if one has not already been set. This error will be returned by a future call to Error
|
||||
// or as part of ToSQL. This can be used by end users to record errors while building up queries without having to
|
||||
// track those separately.
|
||||
func (ud *UpdateDataset) SetError(err error) *UpdateDataset {
|
||||
if ud.err == nil {
|
||||
ud.err = err
|
||||
}
|
||||
|
||||
return ud
|
||||
}
|
||||
|
||||
// Generates an UPDATE sql statement, if Prepared has been called with true then the parameters will not be interpolated.
|
||||
// See examples.
|
||||
//
|
||||
// Errors:
|
||||
// * There is an error generating the SQL
|
||||
func (ud *UpdateDataset) ToSQL() (sql string, params []interface{}, err error) {
|
||||
return ud.updateSQLBuilder().ToSQL()
|
||||
}
|
||||
|
||||
// Appends this Dataset's UPDATE statement to the SQLBuilder
|
||||
// This is used internally when using updates in CTEs
|
||||
func (ud *UpdateDataset) AppendSQL(b sb.SQLBuilder) {
|
||||
if ud.err != nil {
|
||||
b.SetError(ud.err)
|
||||
return
|
||||
}
|
||||
ud.dialect.ToUpdateSQL(b, ud.GetClauses())
|
||||
}
|
||||
|
||||
func (ud *UpdateDataset) GetAs() exp.IdentifierExpression {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ud *UpdateDataset) ReturnsColumns() bool {
|
||||
return ud.clauses.HasReturning()
|
||||
}
|
||||
|
||||
// Generates the UPDATE sql, and returns an exec.QueryExecutor with the sql set to the UPDATE statement
|
||||
// db.Update("test").Set(Record{"name":"Bob", update: time.Now()}).Executor()
|
||||
func (ud *UpdateDataset) Executor() exec.QueryExecutor {
|
||||
return ud.queryFactory.FromSQLBuilder(ud.updateSQLBuilder())
|
||||
}
|
||||
|
||||
func (ud *UpdateDataset) updateSQLBuilder() sb.SQLBuilder {
|
||||
buf := sb.NewSQLBuilder(ud.isPrepared.Bool())
|
||||
if ud.err != nil {
|
||||
return buf.SetError(ud.err)
|
||||
}
|
||||
ud.dialect.ToUpdateSQL(buf, ud.clauses)
|
||||
return buf
|
||||
}
|
||||
182
vendor/github.com/doug-martin/goqu/v9/wait-for-it.sh
generated
vendored
Normal file
182
vendor/github.com/doug-martin/goqu/v9/wait-for-it.sh
generated
vendored
Normal file
@@ -0,0 +1,182 @@
|
||||
#!/usr/bin/env bash
|
||||
# Use this script to test if a given TCP host/port are available
|
||||
|
||||
WAITFORIT_cmdname=${0##*/}
|
||||
|
||||
echoerr() { if [[ $WAITFORIT_QUIET -ne 1 ]]; then echo "$@" 1>&2; fi }
|
||||
|
||||
usage()
|
||||
{
|
||||
cat << USAGE >&2
|
||||
Usage:
|
||||
$WAITFORIT_cmdname host:port [-s] [-t timeout] [-- command args]
|
||||
-h HOST | --host=HOST Host or IP under test
|
||||
-p PORT | --port=PORT TCP port under test
|
||||
Alternatively, you specify the host and port as host:port
|
||||
-s | --strict Only execute subcommand if the test succeeds
|
||||
-q | --quiet Don't output any status messages
|
||||
-t TIMEOUT | --timeout=TIMEOUT
|
||||
Timeout in seconds, zero for no timeout
|
||||
-- COMMAND ARGS Execute command with args after the test finishes
|
||||
USAGE
|
||||
exit 1
|
||||
}
|
||||
|
||||
wait_for()
|
||||
{
|
||||
if [[ $WAITFORIT_TIMEOUT -gt 0 ]]; then
|
||||
echoerr "$WAITFORIT_cmdname: waiting $WAITFORIT_TIMEOUT seconds for $WAITFORIT_HOST:$WAITFORIT_PORT"
|
||||
else
|
||||
echoerr "$WAITFORIT_cmdname: waiting for $WAITFORIT_HOST:$WAITFORIT_PORT without a timeout"
|
||||
fi
|
||||
WAITFORIT_start_ts=$(date +%s)
|
||||
while :
|
||||
do
|
||||
if [[ $WAITFORIT_ISBUSY -eq 1 ]]; then
|
||||
nc -z $WAITFORIT_HOST $WAITFORIT_PORT
|
||||
WAITFORIT_result=$?
|
||||
else
|
||||
(echo > /dev/tcp/$WAITFORIT_HOST/$WAITFORIT_PORT) >/dev/null 2>&1
|
||||
WAITFORIT_result=$?
|
||||
fi
|
||||
if [[ $WAITFORIT_result -eq 0 ]]; then
|
||||
WAITFORIT_end_ts=$(date +%s)
|
||||
echoerr "$WAITFORIT_cmdname: $WAITFORIT_HOST:$WAITFORIT_PORT is available after $((WAITFORIT_end_ts - WAITFORIT_start_ts)) seconds"
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
return $WAITFORIT_result
|
||||
}
|
||||
|
||||
wait_for_wrapper()
|
||||
{
|
||||
# In order to support SIGINT during timeout: http://unix.stackexchange.com/a/57692
|
||||
if [[ $WAITFORIT_QUIET -eq 1 ]]; then
|
||||
timeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0 --quiet --child --host=$WAITFORIT_HOST --port=$WAITFORIT_PORT --timeout=$WAITFORIT_TIMEOUT &
|
||||
else
|
||||
timeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0 --child --host=$WAITFORIT_HOST --port=$WAITFORIT_PORT --timeout=$WAITFORIT_TIMEOUT &
|
||||
fi
|
||||
WAITFORIT_PID=$!
|
||||
trap "kill -INT -$WAITFORIT_PID" INT
|
||||
wait $WAITFORIT_PID
|
||||
WAITFORIT_RESULT=$?
|
||||
if [[ $WAITFORIT_RESULT -ne 0 ]]; then
|
||||
echoerr "$WAITFORIT_cmdname: timeout occurred after waiting $WAITFORIT_TIMEOUT seconds for $WAITFORIT_HOST:$WAITFORIT_PORT"
|
||||
fi
|
||||
return $WAITFORIT_RESULT
|
||||
}
|
||||
|
||||
# process arguments
|
||||
while [[ $# -gt 0 ]]
|
||||
do
|
||||
case "$1" in
|
||||
*:* )
|
||||
WAITFORIT_hostport=(${1//:/ })
|
||||
WAITFORIT_HOST=${WAITFORIT_hostport[0]}
|
||||
WAITFORIT_PORT=${WAITFORIT_hostport[1]}
|
||||
shift 1
|
||||
;;
|
||||
--child)
|
||||
WAITFORIT_CHILD=1
|
||||
shift 1
|
||||
;;
|
||||
-q | --quiet)
|
||||
WAITFORIT_QUIET=1
|
||||
shift 1
|
||||
;;
|
||||
-s | --strict)
|
||||
WAITFORIT_STRICT=1
|
||||
shift 1
|
||||
;;
|
||||
-h)
|
||||
WAITFORIT_HOST="$2"
|
||||
if [[ $WAITFORIT_HOST == "" ]]; then break; fi
|
||||
shift 2
|
||||
;;
|
||||
--host=*)
|
||||
WAITFORIT_HOST="${1#*=}"
|
||||
shift 1
|
||||
;;
|
||||
-p)
|
||||
WAITFORIT_PORT="$2"
|
||||
if [[ $WAITFORIT_PORT == "" ]]; then break; fi
|
||||
shift 2
|
||||
;;
|
||||
--port=*)
|
||||
WAITFORIT_PORT="${1#*=}"
|
||||
shift 1
|
||||
;;
|
||||
-t)
|
||||
WAITFORIT_TIMEOUT="$2"
|
||||
if [[ $WAITFORIT_TIMEOUT == "" ]]; then break; fi
|
||||
shift 2
|
||||
;;
|
||||
--timeout=*)
|
||||
WAITFORIT_TIMEOUT="${1#*=}"
|
||||
shift 1
|
||||
;;
|
||||
--)
|
||||
shift
|
||||
WAITFORIT_CLI=("$@")
|
||||
break
|
||||
;;
|
||||
--help)
|
||||
usage
|
||||
;;
|
||||
*)
|
||||
echoerr "Unknown argument: $1"
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ "$WAITFORIT_HOST" == "" || "$WAITFORIT_PORT" == "" ]]; then
|
||||
echoerr "Error: you need to provide a host and port to test."
|
||||
usage
|
||||
fi
|
||||
|
||||
WAITFORIT_TIMEOUT=${WAITFORIT_TIMEOUT:-15}
|
||||
WAITFORIT_STRICT=${WAITFORIT_STRICT:-0}
|
||||
WAITFORIT_CHILD=${WAITFORIT_CHILD:-0}
|
||||
WAITFORIT_QUIET=${WAITFORIT_QUIET:-0}
|
||||
|
||||
# Check to see if timeout is from busybox?
|
||||
WAITFORIT_TIMEOUT_PATH=$(type -p timeout)
|
||||
WAITFORIT_TIMEOUT_PATH=$(realpath $WAITFORIT_TIMEOUT_PATH 2>/dev/null || readlink -f $WAITFORIT_TIMEOUT_PATH)
|
||||
|
||||
WAITFORIT_BUSYTIMEFLAG=""
|
||||
if [[ $WAITFORIT_TIMEOUT_PATH =~ "busybox" ]]; then
|
||||
WAITFORIT_ISBUSY=1
|
||||
# Check if busybox timeout uses -t flag
|
||||
# (recent Alpine versions don't support -t anymore)
|
||||
if timeout &>/dev/stdout | grep -q -e '-t '; then
|
||||
WAITFORIT_BUSYTIMEFLAG="-t"
|
||||
fi
|
||||
else
|
||||
WAITFORIT_ISBUSY=0
|
||||
fi
|
||||
|
||||
if [[ $WAITFORIT_CHILD -gt 0 ]]; then
|
||||
wait_for
|
||||
WAITFORIT_RESULT=$?
|
||||
exit $WAITFORIT_RESULT
|
||||
else
|
||||
if [[ $WAITFORIT_TIMEOUT -gt 0 ]]; then
|
||||
wait_for_wrapper
|
||||
WAITFORIT_RESULT=$?
|
||||
else
|
||||
wait_for
|
||||
WAITFORIT_RESULT=$?
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ $WAITFORIT_CLI != "" ]]; then
|
||||
if [[ $WAITFORIT_RESULT -ne 0 && $WAITFORIT_STRICT -eq 1 ]]; then
|
||||
echoerr "$WAITFORIT_cmdname: strict mode, refusing to execute subprocess"
|
||||
exit $WAITFORIT_RESULT
|
||||
fi
|
||||
exec "${WAITFORIT_CLI[@]}"
|
||||
else
|
||||
exit $WAITFORIT_RESULT
|
||||
fi
|
||||
11815
vendor/github.com/mattn/go-sqlite3/sqlite3-binding.c
generated
vendored
11815
vendor/github.com/mattn/go-sqlite3/sqlite3-binding.c
generated
vendored
File diff suppressed because it is too large
Load Diff
61
vendor/github.com/mattn/go-sqlite3/sqlite3-binding.h
generated
vendored
61
vendor/github.com/mattn/go-sqlite3/sqlite3-binding.h
generated
vendored
@@ -124,9 +124,9 @@ extern "C" {
|
||||
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
|
||||
** [sqlite_version()] and [sqlite_source_id()].
|
||||
*/
|
||||
#define SQLITE_VERSION "3.34.0"
|
||||
#define SQLITE_VERSION_NUMBER 3034000
|
||||
#define SQLITE_SOURCE_ID "2020-12-01 16:14:00 a26b6597e3ae272231b96f9982c3bcc17ddec2f2b6eb4df06a224b91089fed5b"
|
||||
#define SQLITE_VERSION "3.35.4"
|
||||
#define SQLITE_VERSION_NUMBER 3035004
|
||||
#define SQLITE_SOURCE_ID "2021-04-02 15:20:15 5d4c65779dab868b285519b19e4cf9d451d50c6048f06f653aa701ec212df45e"
|
||||
|
||||
/*
|
||||
** CAPI3REF: Run-Time Library Version Numbers
|
||||
@@ -2116,7 +2116,13 @@ struct sqlite3_mem_methods {
|
||||
** The second parameter is a pointer to an integer into which
|
||||
** is written 0 or 1 to indicate whether triggers are disabled or enabled
|
||||
** following this call. The second parameter may be a NULL pointer, in
|
||||
** which case the trigger setting is not reported back. </dd>
|
||||
** which case the trigger setting is not reported back.
|
||||
**
|
||||
** <p>Originally this option disabled all triggers. ^(However, since
|
||||
** SQLite version 3.35.0, TEMP triggers are still allowed even if
|
||||
** this option is off. So, in other words, this option now only disables
|
||||
** triggers in the main database schema or in the schemas of ATTACH-ed
|
||||
** databases.)^ </dd>
|
||||
**
|
||||
** [[SQLITE_DBCONFIG_ENABLE_VIEW]]
|
||||
** <dt>SQLITE_DBCONFIG_ENABLE_VIEW</dt>
|
||||
@@ -2127,7 +2133,13 @@ struct sqlite3_mem_methods {
|
||||
** The second parameter is a pointer to an integer into which
|
||||
** is written 0 or 1 to indicate whether views are disabled or enabled
|
||||
** following this call. The second parameter may be a NULL pointer, in
|
||||
** which case the view setting is not reported back. </dd>
|
||||
** which case the view setting is not reported back.
|
||||
**
|
||||
** <p>Originally this option disabled all views. ^(However, since
|
||||
** SQLite version 3.35.0, TEMP views are still allowed even if
|
||||
** this option is off. So, in other words, this option now only disables
|
||||
** views in the main database schema or in the schemas of ATTACH-ed
|
||||
** databases.)^ </dd>
|
||||
**
|
||||
** [[SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER]]
|
||||
** <dt>SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER</dt>
|
||||
@@ -3500,6 +3512,7 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
|
||||
** that uses dot-files in place of posix advisory locking.
|
||||
** <tr><td> file:data.db?mode=readonly <td>
|
||||
** An error. "readonly" is not a valid option for the "mode" parameter.
|
||||
** Use "ro" instead: "file:data.db?mode=ro".
|
||||
** </table>
|
||||
**
|
||||
** ^URI hexadecimal escape sequences (%HH) are supported within the path and
|
||||
@@ -3698,7 +3711,7 @@ SQLITE_API sqlite3_file *sqlite3_database_file_object(const char*);
|
||||
** If the Y parameter to sqlite3_free_filename(Y) is anything other
|
||||
** than a NULL pointer or a pointer previously acquired from
|
||||
** sqlite3_create_filename(), then bad things such as heap
|
||||
** corruption or segfaults may occur. The value Y should be
|
||||
** corruption or segfaults may occur. The value Y should not be
|
||||
** used again after sqlite3_free_filename(Y) has been called. This means
|
||||
** that if the [sqlite3_vfs.xOpen()] method of a VFS has been called using Y,
|
||||
** then the corresponding [sqlite3_module.xClose() method should also be
|
||||
@@ -7766,7 +7779,8 @@ SQLITE_API int sqlite3_test_control(int op, ...);
|
||||
#define SQLITE_TESTCTRL_PRNG_SEED 28
|
||||
#define SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS 29
|
||||
#define SQLITE_TESTCTRL_SEEK_COUNT 30
|
||||
#define SQLITE_TESTCTRL_LAST 30 /* Largest TESTCTRL */
|
||||
#define SQLITE_TESTCTRL_TRACEFLAGS 31
|
||||
#define SQLITE_TESTCTRL_LAST 31 /* Largest TESTCTRL */
|
||||
|
||||
/*
|
||||
** CAPI3REF: SQL Keyword Checking
|
||||
@@ -10439,6 +10453,14 @@ SQLITE_API int sqlite3session_patchset(
|
||||
*/
|
||||
SQLITE_API int sqlite3session_isempty(sqlite3_session *pSession);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Query for the amount of heap memory used by a session object.
|
||||
**
|
||||
** This API returns the total amount of heap memory in bytes currently
|
||||
** used by the session object passed as the only argument.
|
||||
*/
|
||||
SQLITE_API sqlite3_int64 sqlite3session_memory_used(sqlite3_session *pSession);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Create An Iterator To Traverse A Changeset
|
||||
** CONSTRUCTOR: sqlite3_changeset_iter
|
||||
@@ -10541,18 +10563,23 @@ SQLITE_API int sqlite3changeset_next(sqlite3_changeset_iter *pIter);
|
||||
** call to [sqlite3changeset_next()] must have returned [SQLITE_ROW]. If this
|
||||
** is not the case, this function returns [SQLITE_MISUSE].
|
||||
**
|
||||
** If argument pzTab is not NULL, then *pzTab is set to point to a
|
||||
** nul-terminated utf-8 encoded string containing the name of the table
|
||||
** affected by the current change. The buffer remains valid until either
|
||||
** sqlite3changeset_next() is called on the iterator or until the
|
||||
** conflict-handler function returns. If pnCol is not NULL, then *pnCol is
|
||||
** set to the number of columns in the table affected by the change. If
|
||||
** pbIndirect is not NULL, then *pbIndirect is set to true (1) if the change
|
||||
** Arguments pOp, pnCol and pzTab may not be NULL. Upon return, three
|
||||
** outputs are set through these pointers:
|
||||
**
|
||||
** *pOp is set to one of [SQLITE_INSERT], [SQLITE_DELETE] or [SQLITE_UPDATE],
|
||||
** depending on the type of change that the iterator currently points to;
|
||||
**
|
||||
** *pnCol is set to the number of columns in the table affected by the change; and
|
||||
**
|
||||
** *pzTab is set to point to a nul-terminated utf-8 encoded string containing
|
||||
** the name of the table affected by the current change. The buffer remains
|
||||
** valid until either sqlite3changeset_next() is called on the iterator
|
||||
** or until the conflict-handler function returns.
|
||||
**
|
||||
** If pbIndirect is not NULL, then *pbIndirect is set to true (1) if the change
|
||||
** is an indirect change, or false (0) otherwise. See the documentation for
|
||||
** [sqlite3session_indirect()] for a description of direct and indirect
|
||||
** changes. Finally, if pOp is not NULL, then *pOp is set to one of
|
||||
** [SQLITE_INSERT], [SQLITE_DELETE] or [SQLITE_UPDATE], depending on the
|
||||
** type of change that the iterator currently points to.
|
||||
** changes.
|
||||
**
|
||||
** If no error occurs, SQLITE_OK is returned. If an error does occur, an
|
||||
** SQLite error code is returned. The values of the output variables may not
|
||||
|
||||
9
vendor/github.com/mattn/go-sqlite3/sqlite3.go
generated
vendored
9
vendor/github.com/mattn/go-sqlite3/sqlite3.go
generated
vendored
@@ -1676,7 +1676,7 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
|
||||
//
|
||||
// Because default is NORMAL this statement is always executed
|
||||
if err := exec(fmt.Sprintf("PRAGMA synchronous = %s;", synchronousMode)); err != nil {
|
||||
C.sqlite3_close_v2(db)
|
||||
conn.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -2007,6 +2007,13 @@ func (s *SQLiteStmt) execSync(args []namedValue) (driver.Result, error) {
|
||||
return &SQLiteResult{id: int64(rowid), changes: int64(changes)}, nil
|
||||
}
|
||||
|
||||
// Readonly reports if this statement is considered readonly by SQLite.
|
||||
//
|
||||
// See: https://sqlite.org/c3ref/stmt_readonly.html
|
||||
func (s *SQLiteStmt) Readonly() bool {
|
||||
return C.sqlite3_stmt_readonly(s.s) == 1
|
||||
}
|
||||
|
||||
// Close the rows.
|
||||
func (rc *SQLiteRows) Close() error {
|
||||
rc.s.mu.Lock()
|
||||
|
||||
21
vendor/github.com/mattn/go-sqlite3/sqlite3_opt_column_metadata.go
generated
vendored
Normal file
21
vendor/github.com/mattn/go-sqlite3/sqlite3_opt_column_metadata.go
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
// +build sqlite_column_metadata
|
||||
|
||||
package sqlite3
|
||||
|
||||
/*
|
||||
#ifndef USE_LIBSQLITE3
|
||||
#cgo CFLAGS: -DSQLITE_ENABLE_COLUMN_METADATA
|
||||
#include <sqlite3-binding.h>
|
||||
#else
|
||||
#include <sqlite3.h>
|
||||
#endif
|
||||
*/
|
||||
import "C"
|
||||
|
||||
// ColumnTableName returns the table that is the origin of a particular result
|
||||
// column in a SELECT statement.
|
||||
//
|
||||
// See https://www.sqlite.org/c3ref/column_database_name.html
|
||||
func (s *SQLiteStmt) ColumnTableName(n int) string {
|
||||
return C.GoString(C.sqlite3_column_table_name(s.s, C.int(n)))
|
||||
}
|
||||
Reference in New Issue
Block a user