fix: postgres columns with timezone

Add timezone for the columns creation_date and update_date, otherwise
it's difficult to compare the times correctly in the unit test.

Furthermore the default value of the creation_date will now be defined
by the postgres implementation of the database interface.
This commit is contained in:
Markus Pesch 2020-10-07 23:38:27 +02:00
parent 3a090d190e
commit 0fc4aa7c28
Signed by: volker.raschek
GPG Key ID: 852BCC170D81A982
11 changed files with 75 additions and 36 deletions

View File

@ -6,7 +6,7 @@ services:
- PGTZ=Europe/Berlin
- POSTGRES_PASSWORD=postgres
- TZ=Europe/Berlin
image: postgres:11.5-alpine
image: postgres:13-alpine
ports:
- 5432:5432
restart: always

3
go.mod
View File

@ -14,6 +14,7 @@ require (
github.com/docker/docker v1.13.1
github.com/docker/go-connections v0.4.0
github.com/docker/go-units v0.4.0 // indirect
github.com/go-bindata/go-bindata v3.1.2+incompatible // indirect
github.com/lib/pq v1.7.0
github.com/mattn/go-sqlite3 v2.0.3+incompatible
github.com/opencontainers/go-digest v1.0.0 // indirect
@ -21,4 +22,6 @@ require (
github.com/spf13/cobra v1.0.0
github.com/stretchr/testify v1.6.1
golang.org/x/net v0.0.0-20200602114024-627f9648deb9 // indirect
gorm.io/driver/sqlite v1.1.3 // indirect
gorm.io/gorm v1.20.1 // indirect
)

13
go.sum
View File

@ -44,6 +44,9 @@ github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-bindata/go-bindata v1.0.0 h1:DZ34txDXWn1DyWa+vQf7V9ANc2ILTtrEjtlsdJRF26M=
github.com/go-bindata/go-bindata v3.1.2+incompatible h1:5vjJMVhowQdPzjE1LdxyFF7YFTXg5IgGVW4gBr5IbvE=
github.com/go-bindata/go-bindata v3.1.2+incompatible/go.mod h1:xK8Dsgwmeed+BBsSy2XTopBn/8uK2HWuGSnA11C3Joo=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
@ -64,6 +67,10 @@ github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.1 h1:g39TucaRWyV3dwDO++eEc6qf8TVIQ/Da48WmqjZ3i7E=
github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
@ -78,6 +85,8 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/lib/pq v1.7.0 h1:h93mCPfUSkaul3Ka/VG8uZdmW1uMHDGxzu0NWHuJmHY=
github.com/lib/pq v1.7.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mattn/go-sqlite3 v1.14.3 h1:j7a/xn1U6TKA/PHHxqZuzh64CdtRc7rU9M+AvkOl5bA=
github.com/mattn/go-sqlite3 v1.14.3/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI=
github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U=
github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
@ -180,6 +189,10 @@ gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/driver/sqlite v1.1.3 h1:BYfdVuZB5He/u9dt4qDpZqiqDJ6KhPqs5QUqsr/Eeuc=
gorm.io/driver/sqlite v1.1.3/go.mod h1:AKDgRWk8lcSQSw+9kxCJnX/yySj8G3rdwYlU57cB45c=
gorm.io/gorm v1.20.1 h1:+hOwlHDqvqmBIMflemMVPLJH7tZYK4RxFDBHEfJTup0=
gorm.io/gorm v1.20.1/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
periph.io/x/periph v3.6.4+incompatible h1:8FyXTbu9lcMVofz8mf+cj1pzTLN4V6EuPY2EF+DoJF4=
periph.io/x/periph v3.6.4+incompatible/go.mod h1:EWr+FCIU2dBWz5/wSWeiIUJTriYv9v2j2ENBmgYyy7Y=

View File

@ -28,7 +28,7 @@ func (postgres *Postgres) DeleteDevices(ctx context.Context, deviceIDs ...string
queryFile := "deleteDevice.sql"
query, present := postgres.queries[queryFile]
if !present {
return fmt.Errorf("SQLite-Backend: File %v not found", queryFile)
return fmt.Errorf("Postgres-Backend: File %v not found", queryFile)
}
tx, err := postgres.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: false})
@ -58,7 +58,7 @@ func (postgres *Postgres) DeleteSensors(ctx context.Context, sensorIDs ...string
queryFile := "deleteSensor.sql"
query, present := postgres.queries[queryFile]
if !present {
return fmt.Errorf("SQLite-Backend: File %v not found", queryFile)
return fmt.Errorf("Postgres-Backend: File %v not found", queryFile)
}
tx, err := postgres.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: false})
@ -88,7 +88,7 @@ func (postgres *Postgres) InsertDevices(ctx context.Context, devices ...*types.D
queryFile := "insertDevice.sql"
query, present := postgres.queries[queryFile]
if !present {
return fmt.Errorf("SQLite-Backend: File %v not found", queryFile)
return fmt.Errorf("Postgres-Backend: File %v not found", queryFile)
}
tx, err := postgres.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: false})
@ -103,7 +103,18 @@ func (postgres *Postgres) InsertDevices(ctx context.Context, devices ...*types.D
defer stmt.Close()
for _, device := range devices {
_, err = stmt.Exec(&device.ID, &device.Name, &device.Location, &device.CreationDate, &device.UpdateDate)
if device.CreationDate.Equal(time.Time{}) {
device.CreationDate = time.Now()
}
_, err = stmt.Exec(
&device.ID,
&device.Name,
&device.Location,
&device.CreationDate,
&device.UpdateDate,
)
if err != nil {
tx.Rollback()
return fmt.Errorf("Failed to execute statement: %v", err)
@ -133,7 +144,7 @@ func (postgres *Postgres) InsertMeasuredValues(ctx context.Context, measuredValu
insert := func(tx *sql.Tx, queryFile string, measuredValues []*types.MeasuredValue) error {
query, present := postgres.queries[queryFile]
if !present {
return fmt.Errorf("SQLite-Backend: File %v not found", queryFile)
return fmt.Errorf("Postgres-Backend: File %v not found", queryFile)
}
stmt, err := tx.Prepare(query)
@ -143,6 +154,11 @@ func (postgres *Postgres) InsertMeasuredValues(ctx context.Context, measuredValu
defer stmt.Close()
for _, measuredValue := range measuredValues {
if measuredValue.CreationDate.Equal(time.Time{}) {
measuredValue.CreationDate = time.Now()
}
_, err := stmt.Exec(
&measuredValue.ID,
&measuredValue.Value,
@ -190,7 +206,7 @@ func (postgres *Postgres) InsertSensors(ctx context.Context, sensors ...*types.S
queryFile := "insertSensor.sql"
query, present := postgres.queries[queryFile]
if !present {
return fmt.Errorf("SQLite-Backend: File %v not found", queryFile)
return fmt.Errorf("Postgres-Backend: File %v not found", queryFile)
}
tx, err := postgres.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: false})
@ -205,6 +221,11 @@ func (postgres *Postgres) InsertSensors(ctx context.Context, sensors ...*types.S
defer stmt.Close()
for _, sensor := range sensors {
if sensor.CreationDate.Equal(time.Time{}) {
sensor.CreationDate = time.Now()
}
_, err = stmt.Exec(
&sensor.ID,
&sensor.Name,
@ -251,7 +272,7 @@ func (postgres *Postgres) SelectDevice(ctx context.Context, id string) (*types.D
queryFile := "selectDevice.sql"
query, present := postgres.queries[queryFile]
if !present {
return nil, fmt.Errorf("SQLite-Backend: File %v not found", queryFile)
return nil, fmt.Errorf("Postgres-Backend: File %v not found", queryFile)
}
tx, err := postgres.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: true})
@ -281,7 +302,7 @@ func (postgres *Postgres) SelectDevices(ctx context.Context) ([]*types.Device, e
queryFile := "selectDevices.sql"
query, present := postgres.queries[queryFile]
if !present {
return nil, fmt.Errorf("SQLite-Backend: File %v not found", queryFile)
return nil, fmt.Errorf("Postgres-Backend: File %v not found", queryFile)
}
tx, err := postgres.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: true})
@ -338,7 +359,7 @@ func (postgres *Postgres) SelectHumidity(ctx context.Context, id string) (*types
queryFile := "selectHumidity.sql"
query, present := postgres.queries[queryFile]
if !present {
return nil, fmt.Errorf("SQLite-Backend: File %v not found", queryFile)
return nil, fmt.Errorf("Postgres-Backend: File %v not found", queryFile)
}
tx, err := postgres.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: true})
@ -372,7 +393,7 @@ func (postgres *Postgres) SelectHumidities(ctx context.Context) ([]*types.Measur
queryFile := "selectHumidities.sql"
query, present := postgres.queries[queryFile]
if !present {
return nil, fmt.Errorf("SQLite-Backend: File %v not found", queryFile)
return nil, fmt.Errorf("Postgres-Backend: File %v not found", queryFile)
}
tx, err := postgres.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: true})
@ -439,7 +460,7 @@ func (postgres *Postgres) SelectPressure(ctx context.Context, id string) (*types
queryFile := "selectPressure.sql"
query, present := postgres.queries[queryFile]
if !present {
return nil, fmt.Errorf("SQLite-Backend: File %v not found", queryFile)
return nil, fmt.Errorf("Postgres-Backend: File %v not found", queryFile)
}
tx, err := postgres.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: true})
@ -473,7 +494,7 @@ func (postgres *Postgres) SelectPressures(ctx context.Context) ([]*types.Measure
queryFile := "selectPressures.sql"
query, present := postgres.queries[queryFile]
if !present {
return nil, fmt.Errorf("SQLite-Backend: File %v not found", queryFile)
return nil, fmt.Errorf("Postgres-Backend: File %v not found", queryFile)
}
tx, err := postgres.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: true})
@ -503,7 +524,7 @@ func (postgres *Postgres) SelectSensor(ctx context.Context, id string) (*types.S
queryFile := "selectSensor.sql"
query, present := postgres.queries[queryFile]
if !present {
return nil, fmt.Errorf("SQLite-Backend: File %v not found", queryFile)
return nil, fmt.Errorf("Postgres-Backend: File %v not found", queryFile)
}
tx, err := postgres.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: true})
@ -533,7 +554,7 @@ func (postgres *Postgres) SelectSensors(ctx context.Context) ([]*types.Sensor, e
queryFile := "selectSensors.sql"
query, present := postgres.queries[queryFile]
if !present {
return nil, fmt.Errorf("SQLite-Backend: File %v not found", queryFile)
return nil, fmt.Errorf("Postgres-Backend: File %v not found", queryFile)
}
tx, err := postgres.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: true})
@ -599,7 +620,7 @@ func (postgres *Postgres) SelectTemperature(ctx context.Context, id string) (*ty
queryFile := "selectTemperature.sql"
query, present := postgres.queries[queryFile]
if !present {
return nil, fmt.Errorf("SQLite-Backend: File %v not found", queryFile)
return nil, fmt.Errorf("Postgres-Backend: File %v not found", queryFile)
}
tx, err := postgres.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: true})
@ -633,7 +654,7 @@ func (postgres *Postgres) SelectTemperatures(ctx context.Context) ([]*types.Meas
queryFile := "selectTemperatures.sql"
query, present := postgres.queries[queryFile]
if !present {
return nil, fmt.Errorf("SQLite-Backend: File %v not found", queryFile)
return nil, fmt.Errorf("Postgres-Backend: File %v not found", queryFile)
}
tx, err := postgres.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: true})
@ -663,7 +684,7 @@ func (postgres *Postgres) UpdateDevices(ctx context.Context, devices ...*types.D
queryFile := "updateDevice.sql"
query, present := postgres.queries[queryFile]
if !present {
return fmt.Errorf("SQLite-Backend: File %v not found", queryFile)
return fmt.Errorf("Postgres-Backend: File %v not found", queryFile)
}
tx, err := postgres.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: false})
@ -703,7 +724,7 @@ func (postgres *Postgres) UpdateSensors(ctx context.Context, sensors ...*types.S
queryFile := "updateSensor.sql"
query, present := postgres.queries[queryFile]
if !present {
return fmt.Errorf("SQLite-Backend: File %v not found", queryFile)
return fmt.Errorf("Postgres-Backend: File %v not found", queryFile)
}
tx, err := postgres.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: false})

View File

@ -2,6 +2,6 @@ CREATE TABLE IF NOT EXISTS devices (
device_id CHAR(36) CONSTRAINT pk_devices PRIMARY KEY,
device_name VARCHAR(64) NOT NULL,
device_location VARCHAR(64),
creation_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
update_date TIMESTAMP
creation_date TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL,
update_date TIMESTAMP WITH TIME ZONE
);

View File

@ -1,10 +1,10 @@
CREATE TABLE IF NOT EXISTS humidities (
id CHAR(36) CONSTRAINT pk_humidities PRIMARY KEY,
value NUMERIC(10,3) NOT NULL,
date TIMESTAMP NOT NULL,
date TIMESTAMP WITH TIME ZONE NOT NULL,
sensor_id CHAR(36) NOT NULL,
creation_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
update_date TIMESTAMP
creation_date TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL,
update_date TIMESTAMP WITH TIME ZONE
);
ALTER TABLE humidities

View File

@ -1,10 +1,10 @@
CREATE TABLE IF NOT EXISTS pressures (
id CHAR(36) CONSTRAINT pk_pressures PRIMARY KEY,
value NUMERIC(10,3) NOT NULL,
date TIMESTAMP NOT NULL,
date TIMESTAMP WITH TIME ZONE NOT NULL,
sensor_id CHAR(36) NOT NULL,
creation_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
update_date TIMESTAMP
creation_date TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL,
update_date TIMESTAMP WITH TIME ZONE
);
ALTER TABLE pressures

View File

@ -10,8 +10,8 @@ CREATE TABLE IF NOT EXISTS sensors (
sensor_enabled BOOLEAN DEFAULT TRUE NOT NULL,
tick_duration VARCHAR(6) NOT NULL,
device_id CHAR(36) NOT NULL,
creation_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
update_date TIMESTAMP
creation_date TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL,
update_date TIMESTAMP WITH TIME ZONE
);
ALTER TABLE sensors

View File

@ -1,10 +1,10 @@
CREATE TABLE IF NOT EXISTS temperatures (
id CHAR(36) CONSTRAINT pk_temperatures PRIMARY KEY,
value NUMERIC(10,3) NOT NULL,
date TIMESTAMP NOT NULL,
date TIMESTAMP WITH TIME ZONE NOT NULL,
sensor_id CHAR(36) NOT NULL,
creation_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
update_date TIMESTAMP
creation_date TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL,
update_date TIMESTAMP WITH TIME ZONE
);
ALTER TABLE temperatures

View File

@ -15,4 +15,6 @@ SELECT
FROM
sensors
WHERE
sensor_id = $1;
sensor_id = $1
ORDER BY
sensor_name ASC;

View File

@ -144,7 +144,7 @@ func testBackend(t *testing.T, repo *repository.Repository) {
expectedSensors = []*types.Sensor{
{
ID: "0f8b88b0-c20d-42b2-ab51-b09ca99c0752",
Name: "e1fbdbe9-cebf-42ed-8065-bf4882ccf76b",
Name: "01fbdbe9-cebf-42ed-8065-bf4882ccf76b",
Location: "6d5b5450-1f87-47cb-b185-f64c35fae3c1",
GPIONumber: "GPIO14",
Model: "DHT11",
@ -206,7 +206,7 @@ func testBackend(t *testing.T, repo *repository.Repository) {
sensors, err = repo.GetSensors("DHT11", "DS18B20")
require.NoError(err)
require.Len(sensors, 2)
require.ElementsMatch(expectedSensors[0:2], sensors)
require.JSONEq(jsonEncoder(expectedSensors[0:2]), jsonEncoder(sensors[0:2]))
// Test: GetSensor
sensor, err := repo.GetSensor(expectedSensors[0].ID)
@ -340,7 +340,7 @@ func jsonEncoder(v interface{}) string {
}
func timeNow(require *require.Assertions) *time.Time {
now, err := time.Parse("2006-01-02 15:04:05.999999Z", time.Now().Format("2006-01-02 15:04:05.999999Z"))
now, err := time.Parse("2006-01-02 15:04:05.999999-07", time.Now().Format("2006-01-02 15:04:05.999999-07"))
require.NoError(err)
return &now
}