Skip to content

Commit c5c6148

Browse files
authored
feat: Store numeric value in numeric type (#5232)
To improve disk consumption by storing numeric values rather than strings. Closes #5231 Signed-off-by: bruce <[email protected]>
1 parent b3d597d commit c5c6148

File tree

5 files changed

+68
-7
lines changed

5 files changed

+68
-7
lines changed

internal/core/data/embed/sql/versions/4.1.0-dev/00-tables.sql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@ ALTER TABLE core_data.device_info ADD COLUMN IF NOT EXISTS mark_deleted BOOLEAN
77

88
-- create index on reading(event_id) to enhance the query performance
99
CREATE INDEX IF NOT EXISTS idx_reading_event_id ON core_data.reading(event_id);
10+
11+
ALTER TABLE core_data.reading ADD COLUMN IF NOT EXISTS numeric_value NUMERIC;

internal/pkg/infrastructure/postgres/consts.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ const (
6868
eventIdFKCol = "event_id"
6969
deviceInfoIdFKCol = "device_info_id"
7070
valueCol = "value"
71+
numericValueCol = "numeric_value"
7172
binaryValueCol = "binaryvalue"
7273
mediaTypeCol = "mediatype"
7374
objectValueCol = "objectvalue"

internal/pkg/infrastructure/postgres/models/reading.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
//
2-
// Copyright (C) 2024 IOTech Ltd
2+
// Copyright (C) 2024-2025 IOTech Ltd
33
//
44
// SPDX-License-Identifier: Apache-2.0
55

66
package models
77

8-
import "github.com/edgexfoundry/go-mod-core-contracts/v4/models"
8+
import (
9+
"github.com/jackc/pgx/v5/pgtype"
10+
11+
"github.com/edgexfoundry/go-mod-core-contracts/v4/models"
12+
)
913

1014
// Reading struct contains the columns of the core_data.reading table in Postgres db relates to a reading
1115
// which includes all the fields in BaseReading, BinaryReading, SimpleReading and ObjectReading
@@ -18,7 +22,8 @@ type Reading struct {
1822
}
1923

2024
type SimpleReading struct {
21-
Value *string
25+
Value *string
26+
NumericValue *pgtype.Numeric
2227
}
2328

2429
type BinaryReading struct {

internal/pkg/infrastructure/postgres/reading.go

Lines changed: 56 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,24 @@ import (
99
"context"
1010
"encoding/json"
1111
"fmt"
12+
"strconv"
1213
"strings"
1314

1415
pgClient "github.com/edgexfoundry/edgex-go/internal/pkg/db/postgres"
1516
dbModels "github.com/edgexfoundry/edgex-go/internal/pkg/infrastructure/postgres/models"
17+
"github.com/edgexfoundry/go-mod-core-contracts/v4/common"
1618
"github.com/edgexfoundry/go-mod-core-contracts/v4/errors"
1719
model "github.com/edgexfoundry/go-mod-core-contracts/v4/models"
1820

1921
"github.com/google/uuid"
2022
"github.com/jackc/pgx/v5"
23+
"github.com/jackc/pgx/v5/pgtype"
2124
"github.com/jackc/pgx/v5/pgxpool"
2225
)
2326

2427
var (
2528
// insertReadingCols defines the reading table columns in slice used in inserting readings
26-
insertReadingCols = []string{eventIdFKCol, deviceInfoIdFKCol, originCol, valueCol, binaryValueCol, objectValueCol}
29+
insertReadingCols = []string{eventIdFKCol, deviceInfoIdFKCol, originCol, valueCol, numericValueCol, binaryValueCol, objectValueCol}
2730
)
2831

2932
func (c *Client) ReadingTotalCount() (uint32, errors.EdgeX) {
@@ -279,6 +282,33 @@ func queryReadings(ctx context.Context, connPool *pgxpool.Pool, sql string, args
279282
Value: *readingDBModel.Value,
280283
}
281284
reading = simpleReading
285+
} else if readingDBModel.NumericValue != nil {
286+
// reading type is numeric SimpleReading
287+
var val string
288+
switch baseReading.ValueType {
289+
case common.ValueTypeFloat32:
290+
numericVal, err := readingDBModel.NumericValue.Float64Value()
291+
if err != nil {
292+
return nil, pgClient.WrapDBError("failed to read the float value", err)
293+
}
294+
val = strconv.FormatFloat(numericVal.Float64, 'e', -1, 32)
295+
case common.ValueTypeFloat64:
296+
numericVal, err := readingDBModel.NumericValue.Float64Value()
297+
if err != nil {
298+
return nil, pgClient.WrapDBError("failed to read the float value", err)
299+
}
300+
val = strconv.FormatFloat(numericVal.Float64, 'e', -1, 64)
301+
default:
302+
numericVal, err := readingDBModel.NumericValue.Value() // NumericValue.Value() return value in string
303+
if err != nil {
304+
return nil, pgClient.WrapDBError("failed to read the float value", err)
305+
}
306+
val = fmt.Sprintf("%v", numericVal)
307+
}
308+
reading = model.SimpleReading{
309+
BaseReading: baseReading,
310+
Value: val,
311+
}
282312
} else {
283313
// reading type is NullReading
284314
nullReading := model.NullReading{
@@ -373,8 +403,30 @@ func (c *Client) addReadingsInTx(tx pgx.Tx, readings []model.Reading, eventId st
373403
case model.SimpleReading:
374404
// convert SimpleReading struct to Reading DB model
375405
readingDBModel = dbModels.Reading{
376-
BaseReading: baseReading,
377-
SimpleReading: dbModels.SimpleReading{Value: &contractReadingModel.Value},
406+
BaseReading: baseReading,
407+
}
408+
switch contractReadingModel.ValueType {
409+
case common.ValueTypeFloat32:
410+
var numericVal pgtype.Numeric
411+
if err := numericVal.ScanScientific(contractReadingModel.Value); err != nil {
412+
return errors.NewCommonEdgeX(errors.KindContractInvalid, fmt.Sprintf("invalid numeric value '%s'", contractReadingModel.Value), err)
413+
}
414+
readingDBModel.SimpleReading = dbModels.SimpleReading{NumericValue: &numericVal}
415+
case common.ValueTypeFloat64:
416+
var numericVal pgtype.Numeric
417+
if err := numericVal.ScanScientific(contractReadingModel.Value); err != nil {
418+
return errors.NewCommonEdgeX(errors.KindContractInvalid, fmt.Sprintf("invalid numeric value '%s'", contractReadingModel.Value), err)
419+
}
420+
readingDBModel.SimpleReading = dbModels.SimpleReading{NumericValue: &numericVal}
421+
case common.ValueTypeUint8, common.ValueTypeUint16, common.ValueTypeUint32, common.ValueTypeUint64,
422+
common.ValueTypeInt8, common.ValueTypeInt16, common.ValueTypeInt32, common.ValueTypeInt64:
423+
var val pgtype.Numeric
424+
if err := val.Scan(contractReadingModel.Value); err != nil {
425+
return errors.NewCommonEdgeX(errors.KindContractInvalid, fmt.Sprintf("invalid numeric value '%s'", contractReadingModel.Value), err)
426+
}
427+
readingDBModel.SimpleReading = dbModels.SimpleReading{NumericValue: &val}
428+
default:
429+
readingDBModel.SimpleReading = dbModels.SimpleReading{Value: &contractReadingModel.Value}
378430
}
379431
case model.NullReading:
380432
readingDBModel = dbModels.Reading{
@@ -413,6 +465,7 @@ func (c *Client) addReadingsInTx(tx pgx.Tx, readings []model.Reading, eventId st
413465
deviceInfoId,
414466
r.Origin,
415467
r.Value,
468+
r.NumericValue,
416469
r.BinaryValue,
417470
objectValueBytes,
418471
}, nil

internal/pkg/infrastructure/postgres/sql.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import (
1616

1717
const (
1818
eventColumns = "event.id, devicename, profilename, sourcename, origin, tags"
19-
readingColumns = "event_id, origin, value, binaryvalue, objectvalue, devicename, profilename, resourcename, valuetype, units, mediatype, tags"
19+
readingColumns = "event_id, origin, value, numeric_value, binaryvalue, objectvalue, devicename, profilename, resourcename, valuetype, units, mediatype, tags"
2020
)
2121

2222
// ----------------------------------------------------------------------------------

0 commit comments

Comments
 (0)