init
This commit is contained in:
commit
7cd59395fb
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
.idea
|
32
Makefile
Normal file
32
Makefile
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
GOOS=$(shell go env GOOS)
|
||||||
|
GOARCH=$(shell go env GOARCH)
|
||||||
|
GOBIN=$(shell go env GOBIN)
|
||||||
|
ifeq ($(GOBIN),)
|
||||||
|
GOBIN := $(shell go env GOPATH)/bin
|
||||||
|
endif
|
||||||
|
OSARCH=$(shell uname -m)
|
||||||
|
SQLC_PATH=$(GOBIN)/sqlc
|
||||||
|
GOOSE_PATH=$(GOBIN)/goose
|
||||||
|
|
||||||
|
.PHONY: install-goose
|
||||||
|
install-goose:
|
||||||
|
@echo "Installing github.com/pressly/goose..."
|
||||||
|
@(test -f $(GOOSE_PATH) && echo "github.com/pressly/goose is already installed. Skipping...") || (wget -q -O $(GOOSE_PATH) https://github.com/pressly/goose/releases/download/v3.15.0/goose_$(GOOS)_$(OSARCH) && chmod u+x $(GOOSE_PATH))
|
||||||
|
|
||||||
|
.PHONY: install-sqlc
|
||||||
|
install-sqlc:
|
||||||
|
@echo "Installing github.com/sqlc-dev/sqlc..."
|
||||||
|
@(test -f $(SQLC_PATH) && echo "github.com/sqlc-dev/sqlc is already installed. Skipping...") || (wget -qO- https://github.com/sqlc-dev/sqlc/releases/download/v1.20.0/sqlc_1.20.0_$(GOOS)_$(GOARCH).tar.gz | tar -xz -C $(GOBIN)/)
|
||||||
|
|
||||||
|
.PHONY: generate
|
||||||
|
generate: install-sqlc
|
||||||
|
@echo "Running go generate..."
|
||||||
|
go generate ./...
|
||||||
|
|
||||||
|
.PHONY: create-sql-migration
|
||||||
|
create-sql-migration: install-goose
|
||||||
|
@goose -dir migrations create $(name) sql
|
||||||
|
|
||||||
|
.PHONY: validate-migrations
|
||||||
|
validate-migrations: install-goose
|
||||||
|
@goose -dir migrations -v validate
|
12
docker-compose.yml
Normal file
12
docker-compose.yml
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
version: "3.6"
|
||||||
|
|
||||||
|
services:
|
||||||
|
db:
|
||||||
|
image: postgres:12.1
|
||||||
|
restart: no
|
||||||
|
ports:
|
||||||
|
- "5432:5432"
|
||||||
|
environment:
|
||||||
|
- POSTGRES_USER=sqlc
|
||||||
|
- POSTGRES_PASSWORD=sqlcdemo
|
||||||
|
- POSTGRES_DB=sqlc
|
18
go.mod
Normal file
18
go.mod
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
module sqlc-demo
|
||||||
|
|
||||||
|
go 1.21
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/google/uuid v1.3.0
|
||||||
|
github.com/jackc/pgx/v5 v5.4.3
|
||||||
|
github.com/pressly/goose/v3 v3.15.0
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||||
|
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
|
||||||
|
github.com/jackc/puddle/v2 v2.2.1 // indirect
|
||||||
|
golang.org/x/crypto v0.10.0 // indirect
|
||||||
|
golang.org/x/sync v0.1.0 // indirect
|
||||||
|
golang.org/x/text v0.11.0 // indirect
|
||||||
|
)
|
66
go.sum
Normal file
66
go.sum
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||||
|
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||||
|
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||||
|
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||||
|
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||||
|
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
|
||||||
|
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
||||||
|
github.com/jackc/pgx/v5 v5.4.3 h1:cxFyXhxlvAifxnkKKdlxv8XqUf59tDlYjnV5YYfsJJY=
|
||||||
|
github.com/jackc/pgx/v5 v5.4.3/go.mod h1:Ig06C2Vu0t5qXC60W8sqIthScaEnFvojjj9dSljmHRA=
|
||||||
|
github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk=
|
||||||
|
github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
|
||||||
|
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
|
||||||
|
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
||||||
|
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
|
||||||
|
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/pressly/goose/v3 v3.15.0 h1:6tY5aDqFknY6VZkorFGgZtWygodZQxfmmEF4rqyJW9k=
|
||||||
|
github.com/pressly/goose/v3 v3.15.0/go.mod h1:LlIo3zGccjb/YUgG+Svdb9Er14vefRdlDI7URCDrwYo=
|
||||||
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||||
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||||
|
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
|
golang.org/x/crypto v0.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM=
|
||||||
|
golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I=
|
||||||
|
golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
|
||||||
|
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
|
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
||||||
|
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
|
||||||
|
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4=
|
||||||
|
golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||||
|
golang.org/x/tools v0.10.0 h1:tvDr/iQoUqNdohiYm0LmmKcBk+q86lb9EprIUFhHHGg=
|
||||||
|
golang.org/x/tools v0.10.0/go.mod h1:UJwyiVBsOA2uwvK/e5OY3GTpDUJriEd+/YlqAwLPmyM=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
lukechampine.com/uint128 v1.3.0 h1:cDdUVfRwDUDovz610ABgFD17nXD4/uDgVHl2sC3+sbo=
|
||||||
|
lukechampine.com/uint128 v1.3.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
|
||||||
|
modernc.org/cc/v3 v3.41.0 h1:QoR1Sn3YWlmA1T4vLaKZfawdVtSiGx8H+cEojbC7v1Q=
|
||||||
|
modernc.org/cc/v3 v3.41.0/go.mod h1:Ni4zjJYJ04CDOhG7dn640WGfwBzfE0ecX8TyMB0Fv0Y=
|
||||||
|
modernc.org/ccgo/v3 v3.16.14 h1:af6KNtFgsVmnDYrWk3PQCS9XT6BXe7o3ZFJKkIKvXNQ=
|
||||||
|
modernc.org/ccgo/v3 v3.16.14/go.mod h1:mPDSujUIaTNWQSG4eqKw+atqLOEbma6Ncsa94WbC9zo=
|
||||||
|
modernc.org/libc v1.24.1 h1:uvJSeCKL/AgzBo2yYIPPTy82v21KgGnizcGYfBHaNuM=
|
||||||
|
modernc.org/libc v1.24.1/go.mod h1:FmfO1RLrU3MHJfyi9eYYmZBfi/R+tqZ6+hQ3yQQUkak=
|
||||||
|
modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=
|
||||||
|
modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo=
|
||||||
|
modernc.org/memory v1.6.0 h1:i6mzavxrE9a30whzMfwf7XWVODx2r5OYXvU46cirX7o=
|
||||||
|
modernc.org/memory v1.6.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU=
|
||||||
|
modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4=
|
||||||
|
modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
|
||||||
|
modernc.org/sqlite v1.25.0 h1:AFweiwPNd/b3BoKnBOfFm+Y260guGMF+0UFk0savqeA=
|
||||||
|
modernc.org/sqlite v1.25.0/go.mod h1:FL3pVXie73rg3Rii6V/u5BoHlSoyeZeIgKZEgHARyCU=
|
||||||
|
modernc.org/strutil v1.1.3 h1:fNMm+oJklMGYfU9Ylcywl0CO5O6nTfaowNsh2wpPjzY=
|
||||||
|
modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw=
|
||||||
|
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
|
||||||
|
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
|
3
internal/.gitignore
vendored
Normal file
3
internal/.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
*.sql.go
|
||||||
|
models.go
|
||||||
|
db.go
|
51
internal/building_info.go
Normal file
51
internal/building_info.go
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
package internal
|
||||||
|
|
||||||
|
import "encoding/json"
|
||||||
|
|
||||||
|
type Building struct {
|
||||||
|
MaxLevel int
|
||||||
|
MinLevel int
|
||||||
|
Wood int
|
||||||
|
Stone int
|
||||||
|
Iron int
|
||||||
|
Pop int
|
||||||
|
WoodFactor float64
|
||||||
|
StoneFactor float64
|
||||||
|
IronFactor float64
|
||||||
|
PopFactor float64
|
||||||
|
BuildTime float64
|
||||||
|
BuildTimeFactor float64
|
||||||
|
}
|
||||||
|
|
||||||
|
type BuildingInfo struct {
|
||||||
|
Main Building
|
||||||
|
}
|
||||||
|
|
||||||
|
type NullBuildingInfo struct {
|
||||||
|
Value BuildingInfo
|
||||||
|
Valid bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b NullBuildingInfo) MarshalJSON() ([]byte, error) {
|
||||||
|
if !b.Valid {
|
||||||
|
return []byte("null"), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return json.Marshal(b.Value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *NullBuildingInfo) UnmarshalJSON(data []byte) error {
|
||||||
|
// Ignore null, like in the main JSON package.
|
||||||
|
if string(data) == "null" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := json.Unmarshal(data, &b.Value); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
b.Valid = true
|
||||||
|
|
||||||
|
return nil
|
||||||
|
|
||||||
|
}
|
43
internal/server.sql
Normal file
43
internal/server.sql
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
-- name: CreateOrUpdateServers :many
|
||||||
|
INSERT INTO servers (key, url, open, version_code, config, building_info, unit_info)
|
||||||
|
VALUES (UNNEST(@key::varchar(100)[]), UNNEST(@url::varchar(255)[]), UNNEST(@open::boolean[]),
|
||||||
|
UNNEST(@version_code::varchar(6)[]), UNNEST(@config::jsonb[]), UNNEST(@building_info::jsonb[]),
|
||||||
|
UNNEST(@unit_info::jsonb[]))
|
||||||
|
ON CONFLICT ON CONSTRAINT servers_pkey DO UPDATE SET url = EXCLUDED.url,
|
||||||
|
open = EXCLUDED.open,
|
||||||
|
config = EXCLUDED.config,
|
||||||
|
building_info = EXCLUDED.building_info,
|
||||||
|
unit_info = EXCLUDED.unit_info
|
||||||
|
RETURNING *;
|
||||||
|
|
||||||
|
-- name: ListServers :many
|
||||||
|
SELECT sqlc.embed(server), sqlc.embed(version)
|
||||||
|
from servers server
|
||||||
|
INNER JOIN public.versions version on version.code = server.version_code
|
||||||
|
WHERE (server.version_code = ANY (sqlc.narg(version_code)::varchar(6)[]) OR sqlc.narg(version_code) IS NULL)
|
||||||
|
AND (server.open = sqlc.narg(open)::boolean OR sqlc.narg(open) IS NULL)
|
||||||
|
AND (server.special = sqlc.narg(special)::boolean OR sqlc.narg(special) IS NULL)
|
||||||
|
AND (server.key = ANY (sqlc.narg(key)::varchar(100)[]) OR sqlc.narg(key) IS NULL)
|
||||||
|
ORDER BY CASE WHEN (@sort::text[])[1] = 'KEY_ASC' THEN server.key END ASC,
|
||||||
|
CASE WHEN (@sort::text[])[1] = 'KEY_DESC' THEN server.key END DESC,
|
||||||
|
CASE WHEN (@sort::text[])[1] = 'OPEN_ASC' THEN server.open END ASC,
|
||||||
|
CASE WHEN (@sort::text[])[1] = 'OPEN_DESC' THEN server.open END DESC,
|
||||||
|
CASE WHEN (@sort::text[])[2] = 'KEY_ASC' THEN server.key END ASC,
|
||||||
|
CASE WHEN (@sort::text[])[2] = 'KEY_DESC' THEN server.key END DESC,
|
||||||
|
CASE WHEN (@sort::text[])[2] = 'OPEN_ASC' THEN server.open END ASC,
|
||||||
|
CASE WHEN (@sort::text[])[2] = 'OPEN_DESC' THEN server.open END DESC
|
||||||
|
LIMIT @pag_limit OFFSET @pag_offset;
|
||||||
|
|
||||||
|
-- name: CountServersByVersionCode :many
|
||||||
|
SELECT version_code, count(key), min(server.num_players)::bigint
|
||||||
|
FROM servers server
|
||||||
|
GROUP BY version_code;
|
||||||
|
|
||||||
|
-- name: UpdateServer :one
|
||||||
|
UPDATE servers
|
||||||
|
SET
|
||||||
|
config = coalesce(sqlc.narg('config'), config),
|
||||||
|
building_info = coalesce(sqlc.narg('building_info'), building_info),
|
||||||
|
unit_info = coalesce(sqlc.narg('unit_info'), unit_info)
|
||||||
|
WHERE key = sqlc.arg('key')
|
||||||
|
RETURNING *;
|
38
internal/server_config.go
Normal file
38
internal/server_config.go
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
package internal
|
||||||
|
|
||||||
|
import "encoding/json"
|
||||||
|
|
||||||
|
type ServerConfig struct {
|
||||||
|
Speed float64
|
||||||
|
UnitSpeed float64
|
||||||
|
Moral int
|
||||||
|
}
|
||||||
|
|
||||||
|
type NullServerConfig struct {
|
||||||
|
Value ServerConfig
|
||||||
|
Valid bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s NullServerConfig) MarshalJSON() ([]byte, error) {
|
||||||
|
if !s.Valid {
|
||||||
|
return []byte("null"), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return json.Marshal(s.Value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *NullServerConfig) UnmarshalJSON(data []byte) error {
|
||||||
|
// Ignore null, like in the main JSON package.
|
||||||
|
if string(data) == "null" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := json.Unmarshal(data, &s.Value); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
s.Valid = true
|
||||||
|
|
||||||
|
return nil
|
||||||
|
|
||||||
|
}
|
3
internal/sqlc.go
Normal file
3
internal/sqlc.go
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
package internal
|
||||||
|
|
||||||
|
//go:generate sqlc generate --experimental
|
23
internal/sqlc.yaml
Normal file
23
internal/sqlc.yaml
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
version: "2"
|
||||||
|
sql:
|
||||||
|
- engine: "postgresql"
|
||||||
|
queries: "./"
|
||||||
|
schema: "../migrations/"
|
||||||
|
gen:
|
||||||
|
go:
|
||||||
|
package: "internal"
|
||||||
|
out: "."
|
||||||
|
sql_package: pgx/v5
|
||||||
|
overrides:
|
||||||
|
- column: "servers.config"
|
||||||
|
go_type:
|
||||||
|
type: "NullServerConfig"
|
||||||
|
- column: "servers.config"
|
||||||
|
go_type:
|
||||||
|
type: "NullServerConfig"
|
||||||
|
- column: "servers.building_info"
|
||||||
|
go_type:
|
||||||
|
type: "NullBuildingInfo"
|
||||||
|
- column: "servers.unit_info"
|
||||||
|
go_type:
|
||||||
|
type: "NullUnitInfo"
|
47
internal/unit_info.go
Normal file
47
internal/unit_info.go
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
package internal
|
||||||
|
|
||||||
|
import "encoding/json"
|
||||||
|
|
||||||
|
type Unit struct {
|
||||||
|
BuildTime float64
|
||||||
|
Pop int
|
||||||
|
Speed float64
|
||||||
|
Attack int
|
||||||
|
Defense int
|
||||||
|
DefenseCavalry int
|
||||||
|
DefenseArcher int
|
||||||
|
Carry int
|
||||||
|
}
|
||||||
|
|
||||||
|
type UnitInfo struct {
|
||||||
|
Spear Unit
|
||||||
|
}
|
||||||
|
|
||||||
|
type NullUnitInfo struct {
|
||||||
|
Value UnitInfo
|
||||||
|
Valid bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u NullUnitInfo) MarshalJSON() ([]byte, error) {
|
||||||
|
if !u.Valid {
|
||||||
|
return []byte("null"), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return json.Marshal(u.Value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *NullUnitInfo) UnmarshalJSON(data []byte) error {
|
||||||
|
// Ignore null, like in the main JSON package.
|
||||||
|
if string(data) == "null" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := json.Unmarshal(data, &u.Value); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
u.Valid = true
|
||||||
|
|
||||||
|
return nil
|
||||||
|
|
||||||
|
}
|
10
internal/version.sql
Normal file
10
internal/version.sql
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
-- name: CreateVersion :one
|
||||||
|
INSERT INTO versions (code, name, host, timezone) VALUES ($1, $2, $3, $4) RETURNING *;
|
||||||
|
|
||||||
|
-- name: ListVersions :many
|
||||||
|
SELECT *
|
||||||
|
from versions
|
||||||
|
ORDER BY code ASC;
|
||||||
|
|
||||||
|
-- name: GetVersion :one
|
||||||
|
SELECT * from versions WHERE code = $1 LIMIT 1;
|
202
main.go
Normal file
202
main.go
Normal file
|
@ -0,0 +1,202 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"sqlc-demo/internal"
|
||||||
|
"sqlc-demo/migrations"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"github.com/jackc/pgx/v5"
|
||||||
|
"github.com/jackc/pgx/v5/pgtype"
|
||||||
|
"github.com/jackc/pgx/v5/pgxpool"
|
||||||
|
_ "github.com/jackc/pgx/v5/stdlib"
|
||||||
|
"github.com/pressly/goose/v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
const envPostgresConnString = "POSTGRES_CONNECTION_STRING"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var demoName string
|
||||||
|
flag.StringVar(&demoName, "demo", "listVersions", "one of: listVersions, listOpenServers, createVersionAndServers")
|
||||||
|
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
if err := runMigrations(); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
pool, err := newPgxPool()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
defer pool.Close()
|
||||||
|
|
||||||
|
queries := internal.New(pool)
|
||||||
|
|
||||||
|
if err = (demo{queries: queries, pool: pool}).run(demoName); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func runMigrations() error {
|
||||||
|
goose.SetLogger(goose.NopLogger())
|
||||||
|
goose.SetBaseFS(migrations.Migrations)
|
||||||
|
_ = goose.SetDialect("postgres")
|
||||||
|
|
||||||
|
db, err := goose.OpenDBWithDriver("pgx", os.Getenv(envPostgresConnString))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
_ = db.Close()
|
||||||
|
}()
|
||||||
|
db.SetMaxOpenConns(1)
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
return goose.UpContext(ctx, db, ".")
|
||||||
|
}
|
||||||
|
|
||||||
|
func newPgxPool() (*pgxpool.Pool, error) {
|
||||||
|
pool, err := pgxpool.New(context.Background(), os.Getenv(envPostgresConnString))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
pingCtx, cancel := context.WithTimeout(context.Background(), time.Second)
|
||||||
|
defer cancel()
|
||||||
|
if err = pool.Ping(pingCtx); err != nil {
|
||||||
|
return nil, fmt.Errorf("couldn't ping db: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return pool, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type demo struct {
|
||||||
|
pool *pgxpool.Pool
|
||||||
|
queries *internal.Queries
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d demo) run(name string) error {
|
||||||
|
switch name {
|
||||||
|
case "listVersions":
|
||||||
|
return d.listVersions()
|
||||||
|
case "listOpenServers":
|
||||||
|
return d.listOpenServers()
|
||||||
|
case "createVersionAndServers":
|
||||||
|
return d.createVersionAndServers()
|
||||||
|
default:
|
||||||
|
return errors.New("unknown demo")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d demo) listVersions() error {
|
||||||
|
versions, err := d.queries.ListVersions(context.Background())
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("couldn't list versions: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, v := range versions {
|
||||||
|
printVersion(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d demo) listOpenServers() error {
|
||||||
|
servers, err := d.queries.ListServers(context.Background(), internal.ListServersParams{
|
||||||
|
Open: pgtype.Bool{
|
||||||
|
Bool: true,
|
||||||
|
Valid: true,
|
||||||
|
},
|
||||||
|
Special: pgtype.Bool{},
|
||||||
|
Key: nil,
|
||||||
|
Sort: []string{"KEY_ASC", "OPEN_ASC"},
|
||||||
|
PagOffset: 0,
|
||||||
|
PagLimit: 10,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("couldn't list versions: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, s := range servers {
|
||||||
|
printServer(s.Server, s.Version)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d demo) createVersionAndServers() error {
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
tx, err := d.pool.BeginTx(ctx, pgx.TxOptions{})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("couldn't start transaction: %w", err)
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
_ = tx.Rollback(ctx)
|
||||||
|
}()
|
||||||
|
|
||||||
|
queries := d.queries.WithTx(tx)
|
||||||
|
|
||||||
|
v, err := queries.CreateVersion(ctx, internal.CreateVersionParams{
|
||||||
|
Code: uuid.NewString()[:6],
|
||||||
|
Name: uuid.NewString(),
|
||||||
|
Host: uuid.NewString(),
|
||||||
|
Timezone: time.UTC.String(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("couldn't create version: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
configBytes, _ := json.Marshal(internal.ServerConfig{})
|
||||||
|
buildingInfoBytes, _ := json.Marshal(internal.BuildingInfo{})
|
||||||
|
unitInfoBytes, _ := json.Marshal(internal.UnitInfo{})
|
||||||
|
|
||||||
|
servers, err := queries.CreateOrUpdateServers(ctx, internal.CreateOrUpdateServersParams{
|
||||||
|
Key: []string{uuid.NewString()[:10], uuid.NewString()[:10]},
|
||||||
|
Url: []string{uuid.NewString(), uuid.NewString()},
|
||||||
|
Open: []bool{true, true},
|
||||||
|
VersionCode: []string{v.Code, v.Code},
|
||||||
|
Config: [][]byte{configBytes, configBytes},
|
||||||
|
BuildingInfo: [][]byte{buildingInfoBytes, buildingInfoBytes},
|
||||||
|
UnitInfo: [][]byte{unitInfoBytes, unitInfoBytes},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("couldn't create servers: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
printVersion(v)
|
||||||
|
|
||||||
|
for _, s := range servers {
|
||||||
|
printServer(s, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
return tx.Commit(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
func printServer(s internal.Server, v internal.Version) {
|
||||||
|
fmt.Printf(
|
||||||
|
"---%s---\nOpen: %v\nConfig: %v\nBuildingInfo: %v\nUnit info: %v\nCreated at: %s\nVersion: %s (%s)\n",
|
||||||
|
s.Key,
|
||||||
|
s.Open.Bool,
|
||||||
|
s.Config,
|
||||||
|
s.BuildingInfo,
|
||||||
|
s.UnitInfo,
|
||||||
|
s.CreatedAt.Time,
|
||||||
|
v.Name,
|
||||||
|
v.Code,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func printVersion(v internal.Version) {
|
||||||
|
fmt.Printf("---%s---\nCode: %s\nHost: %s\nTimezone: %s\n", v.Name, v.Code, v.Host, v.Timezone)
|
||||||
|
}
|
13
migrations/20230610071306_create_versions_table.sql
Normal file
13
migrations/20230610071306_create_versions_table.sql
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
-- +goose Up
|
||||||
|
create table if not exists versions
|
||||||
|
(
|
||||||
|
code varchar(6) not null
|
||||||
|
primary key,
|
||||||
|
name varchar(150) not null,
|
||||||
|
host varchar(150) not null
|
||||||
|
unique,
|
||||||
|
timezone varchar(150) not null
|
||||||
|
);
|
||||||
|
|
||||||
|
-- +goose Down
|
||||||
|
drop table if exists versions CASCADE;
|
30
migrations/20230610071720_create_servers_table.sql
Normal file
30
migrations/20230610071720_create_servers_table.sql
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
-- +goose Up
|
||||||
|
create table if not exists servers
|
||||||
|
(
|
||||||
|
key varchar(100) not null
|
||||||
|
primary key,
|
||||||
|
url varchar(255) not null,
|
||||||
|
open boolean default false,
|
||||||
|
special boolean default false,
|
||||||
|
num_players bigint default 0,
|
||||||
|
num_tribes bigint default 0,
|
||||||
|
num_villages bigint default 0,
|
||||||
|
config jsonb,
|
||||||
|
building_info jsonb,
|
||||||
|
unit_info jsonb,
|
||||||
|
created_at timestamp with time zone default CURRENT_TIMESTAMP not null,
|
||||||
|
player_data_updated_at timestamp with time zone,
|
||||||
|
tribe_data_updated_at timestamp with time zone,
|
||||||
|
village_data_updated_at timestamp with time zone,
|
||||||
|
version_code varchar(6) not null
|
||||||
|
references versions,
|
||||||
|
player_snapshots_created_at timestamp with time zone,
|
||||||
|
tribe_snapshots_created_at timestamp with time zone,
|
||||||
|
ennoblement_data_updated_at timestamp with time zone,
|
||||||
|
num_player_villages bigint default 0,
|
||||||
|
num_barbarian_villages bigint default 0,
|
||||||
|
num_bonus_villages bigint default 0
|
||||||
|
);
|
||||||
|
|
||||||
|
-- +goose Down
|
||||||
|
drop table if exists servers cascade;
|
36
migrations/20230829071145_fixtures.sql
Normal file
36
migrations/20230829071145_fixtures.sql
Normal file
File diff suppressed because one or more lines are too long
6
migrations/migrations.go
Normal file
6
migrations/migrations.go
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
package migrations
|
||||||
|
|
||||||
|
import "embed"
|
||||||
|
|
||||||
|
//go:embed *.sql
|
||||||
|
var Migrations embed.FS
|
Loading…
Reference in New Issue
Block a user