UniStore: Use epoch with microsecond resolution as RV (#92638)

* Use epoch with microsecond resolution as RV

* fix backend tests

* Add solution for when the clock goes back

* Add solution for when the clock goes back

* generate mocks

* go lint

* remove comment

* Use Greatest instead of max in msyql and postgres

* update tests

* Update pkg/storage/unified/sql/sqltemplate/dialect_sqlite.go

Co-authored-by: Diego Augusto Molina <diegoaugustomolina@gmail.com>

* cast to bigint

* add additional round trip

* increment the RV using 2 sql round trips instead of 3

* cleanup comments

* cast unix timestamp to integer

* fix postgres query

* remove old increment test data

* remove greatest

* cast unix_timestamp to signed

* Use statement_timestamp instead of clock_timestamp

---------

Co-authored-by: Diego Augusto Molina <diegoaugustomolina@gmail.com>
This commit is contained in:
Georges Chaudy
2024-10-11 12:11:33 +03:00
committed by GitHub
co-authored by Diego Augusto Molina
parent 0bd3ad1d5a
commit d999b415df
35 changed files with 391 additions and 225 deletions
@@ -62,6 +62,9 @@ type Dialect interface {
// WHERE id = ?
// {{ .SelectFor "Update NoWait" }}; -- will be uppercased
SelectFor(...string) (string, error)
// CurrentEpoch returns the current epoch value for the database in microseconds.
CurrentEpoch() string
}
// RowLockingClause represents a row-locking clause in a SELECT statement.
@@ -33,3 +33,7 @@ func (backtickIdent) Ident(s string) (string, error) {
return s
})
}
func (mysql) CurrentEpoch() string {
return "CAST(FLOOR(UNIX_TIMESTAMP(NOW(6)) * 1000000) AS SIGNED)"
}
@@ -35,3 +35,7 @@ func (p postgresql) Ident(s string) (string, error) {
return p.standardIdent.Ident(s)
}
func (postgresql) CurrentEpoch() string {
return "(EXTRACT(EPOCH FROM statement_timestamp()) * 1000000)::BIGINT"
}
@@ -16,3 +16,8 @@ type sqlite struct {
argPlaceholderFunc
name
}
func (sqlite) CurrentEpoch() string {
// Alternative approaches like `unixepoch('subsecond') * 1000000` returns millisecond precision.
return "CAST((julianday('now') - 2440587.5) * 86400000000.0 AS BIGINT)"
}
@@ -171,6 +171,51 @@ func (_c *SQLTemplate_ArgPlaceholder_Call) RunAndReturn(run func(int) string) *S
return _c
}
// CurrentEpoch provides a mock function with given fields:
func (_m *SQLTemplate) CurrentEpoch() string {
ret := _m.Called()
if len(ret) == 0 {
panic("no return value specified for CurrentEpoch")
}
var r0 string
if rf, ok := ret.Get(0).(func() string); ok {
r0 = rf()
} else {
r0 = ret.Get(0).(string)
}
return r0
}
// SQLTemplate_CurrentEpoch_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CurrentEpoch'
type SQLTemplate_CurrentEpoch_Call struct {
*mock.Call
}
// CurrentEpoch is a helper method to define mock.On call
func (_e *SQLTemplate_Expecter) CurrentEpoch() *SQLTemplate_CurrentEpoch_Call {
return &SQLTemplate_CurrentEpoch_Call{Call: _e.mock.On("CurrentEpoch")}
}
func (_c *SQLTemplate_CurrentEpoch_Call) Run(run func()) *SQLTemplate_CurrentEpoch_Call {
_c.Call.Run(func(args mock.Arguments) {
run()
})
return _c
}
func (_c *SQLTemplate_CurrentEpoch_Call) Return(_a0 string) *SQLTemplate_CurrentEpoch_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *SQLTemplate_CurrentEpoch_Call) RunAndReturn(run func() string) *SQLTemplate_CurrentEpoch_Call {
_c.Call.Return(run)
return _c
}
// DialectName provides a mock function with given fields:
func (_m *SQLTemplate) DialectName() string {
ret := _m.Called()
@@ -171,6 +171,51 @@ func (_c *WithResults_ArgPlaceholder_Call[T]) RunAndReturn(run func(int) string)
return _c
}
// CurrentEpoch provides a mock function with given fields:
func (_m *WithResults[T]) CurrentEpoch() string {
ret := _m.Called()
if len(ret) == 0 {
panic("no return value specified for CurrentEpoch")
}
var r0 string
if rf, ok := ret.Get(0).(func() string); ok {
r0 = rf()
} else {
r0 = ret.Get(0).(string)
}
return r0
}
// WithResults_CurrentEpoch_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CurrentEpoch'
type WithResults_CurrentEpoch_Call[T interface{}] struct {
*mock.Call
}
// CurrentEpoch is a helper method to define mock.On call
func (_e *WithResults_Expecter[T]) CurrentEpoch() *WithResults_CurrentEpoch_Call[T] {
return &WithResults_CurrentEpoch_Call[T]{Call: _e.mock.On("CurrentEpoch")}
}
func (_c *WithResults_CurrentEpoch_Call[T]) Run(run func()) *WithResults_CurrentEpoch_Call[T] {
_c.Call.Run(func(args mock.Arguments) {
run()
})
return _c
}
func (_c *WithResults_CurrentEpoch_Call[T]) Return(_a0 string) *WithResults_CurrentEpoch_Call[T] {
_c.Call.Return(_a0)
return _c
}
func (_c *WithResults_CurrentEpoch_Call[T]) RunAndReturn(run func() string) *WithResults_CurrentEpoch_Call[T] {
_c.Call.Return(run)
return _c
}
// DialectName provides a mock function with given fields:
func (_m *WithResults[T]) DialectName() string {
ret := _m.Called()