Skip to content

Commit

Permalink
builtins: support current_timestamp with precision
Browse files Browse the repository at this point in the history
Release note (sql change): This PR adds new functionality that allows
users to use CURRENT_TIMESTAMP with a given precision from 0-6, e.g.
`SELECT CURRENT_TIMESTAMP(4)`.
  • Loading branch information
otan committed Nov 21, 2019
1 parent 0410017 commit d14360d
Show file tree
Hide file tree
Showing 7 changed files with 92 additions and 9 deletions.
1 change: 1 addition & 0 deletions docs/generated/sql/bnf/stmt_block.bnf
Original file line number Diff line number Diff line change
Expand Up @@ -2304,6 +2304,7 @@ special_function ::=
'CURRENT_DATE' '(' ')'
| 'CURRENT_SCHEMA' '(' ')'
| 'CURRENT_TIMESTAMP' '(' ')'
| 'CURRENT_TIMESTAMP' '(' a_expr ')'
| 'CURRENT_USER' '(' ')'
| 'EXTRACT' '(' extract_list ')'
| 'EXTRACT_DURATION' '(' extract_list ')'
Expand Down
15 changes: 15 additions & 0 deletions docs/generated/sql/functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,21 @@ has no relationship with the commit order of concurrent transactions.</p>
and which stays constant throughout the transaction. This timestamp
has no relationship with the commit order of concurrent transactions.</p>
</span></td></tr>
<tr><td><a name="current_timestamp"></a><code>current_timestamp(precision: <a href="int.html">int</a>) &rarr; <a href="date.html">date</a></code></td><td><span class="funcdesc"><p>Returns the time of the current transaction.</p>
<p>The value is based on a timestamp picked when the transaction starts
and which stays constant throughout the transaction. This timestamp
has no relationship with the commit order of concurrent transactions.</p>
</span></td></tr>
<tr><td><a name="current_timestamp"></a><code>current_timestamp(precision: <a href="int.html">int</a>) &rarr; <a href="timestamp.html">timestamp</a></code></td><td><span class="funcdesc"><p>Returns the time of the current transaction.</p>
<p>The value is based on a timestamp picked when the transaction starts
and which stays constant throughout the transaction. This timestamp
has no relationship with the commit order of concurrent transactions.</p>
</span></td></tr>
<tr><td><a name="current_timestamp"></a><code>current_timestamp(precision: <a href="int.html">int</a>) &rarr; <a href="timestamp.html">timestamptz</a></code></td><td><span class="funcdesc"><p>Returns the time of the current transaction.</p>
<p>The value is based on a timestamp picked when the transaction starts
and which stays constant throughout the transaction. This timestamp
has no relationship with the commit order of concurrent transactions.</p>
</span></td></tr>
<tr><td><a name="date_trunc"></a><code>date_trunc(element: <a href="string.html">string</a>, input: <a href="date.html">date</a>) &rarr; <a href="timestamp.html">timestamptz</a></code></td><td><span class="funcdesc"><p>Truncates <code>input</code> to precision <code>element</code>. Sets all fields that are less
significant than <code>element</code> to zero (or one, for day and month)</p>
<p>Compatible elements: millennium, century, decade, year, quarter, month,
Expand Down
5 changes: 5 additions & 0 deletions pkg/sql/logictest/testdata/logic_test/timestamp
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@ select '1-1-18 1:00:00.001-8':::TIMESTAMPTZ(6)
----
2001-01-18 01:00:00.001 -0800 PST

query B
select current_timestamp(3) - current_timestamp <= '1ms'::interval
----
true

statement ok
CREATE TABLE timestamp_test (
id integer PRIMARY KEY,
Expand Down
2 changes: 2 additions & 0 deletions pkg/sql/parser/parse_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1553,6 +1553,8 @@ func TestParse2(t *testing.T) {
`SELECT current_database()`},
{`SELECT CURRENT_TIMESTAMP`,
`SELECT current_timestamp()`},
{`SELECT current_timestamp(6)`,
`SELECT current_timestamp(6)`},
{`SELECT CURRENT_DATE`,
`SELECT current_date()`},
{`SELECT POSITION(a IN b)`,
Expand Down
4 changes: 4 additions & 0 deletions pkg/sql/parser/sql.y
Original file line number Diff line number Diff line change
Expand Up @@ -8238,6 +8238,10 @@ special_function:
{
$$.val = &tree.FuncExpr{Func: tree.WrapFunction($1)}
}
| CURRENT_TIMESTAMP '(' a_expr ')'
{
$$.val = &tree.FuncExpr{Func: tree.WrapFunction($1), Exprs: tree.Exprs{$3.expr()}}
}
| CURRENT_TIMESTAMP '(' error { return helpWithFunctionByName(sqllex, $1) }
| CURRENT_TIME '(' ')'
{
Expand Down
73 changes: 64 additions & 9 deletions pkg/sql/sem/builtins/builtins.go
Original file line number Diff line number Diff line change
Expand Up @@ -1675,7 +1675,7 @@ CockroachDB supports the following flags:
),

"now": txnTSImpl,
"current_timestamp": txnTSImpl,
"current_timestamp": txnTSWithPrecisionImpl,
"transaction_timestamp": txnTSImpl,

"statement_timestamp": makeBuiltin(
Expand Down Expand Up @@ -3496,12 +3496,8 @@ has no relationship with the commit order of concurrent transactions.`

var txnTSDoc = `Returns the time of the current transaction.` + txnTSContextDoc

var txnTSImpl = makeBuiltin(
tree.FunctionProperties{
Category: categoryDateAndTime,
Impure: true,
},
tree.Overload{
var txnTSOverloads = []tree.Overload{
{
Types: tree.ArgTypes{},
ReturnType: tree.FixedReturnType(types.TimestampTZ),
PreferredOverload: true,
Expand All @@ -3510,20 +3506,79 @@ var txnTSImpl = makeBuiltin(
},
Info: txnTSDoc,
},
tree.Overload{
{
Types: tree.ArgTypes{},
ReturnType: tree.FixedReturnType(types.Timestamp),
Fn: func(ctx *tree.EvalContext, args tree.Datums) (tree.Datum, error) {
return ctx.GetTxnTimestampNoZone(time.Microsecond), nil
},
Info: txnTSDoc,
},
tree.Overload{
{
Types: tree.ArgTypes{},
ReturnType: tree.FixedReturnType(types.Date),
Fn: currentDate,
Info: txnTSDoc,
},
}

var txnTSWithPrecisionOverloads = append(
[]tree.Overload{
{
Types: tree.ArgTypes{{"precision", types.Int}},
ReturnType: tree.FixedReturnType(types.TimestampTZ),
PreferredOverload: true,
Fn: func(ctx *tree.EvalContext, args tree.Datums) (tree.Datum, error) {
prec := int32(tree.MustBeDInt(args[0]))
if prec < 0 || prec > 6 {
return nil, pgerror.Newf(pgcode.NumericValueOutOfRange, "precision %d out of range", prec)
}
return ctx.GetTxnTimestamp(tree.TimeFamilyPrecisionToRoundDuration(prec)), nil
},
Info: txnTSDoc,
},
{
Types: tree.ArgTypes{{"precision", types.Int}},
ReturnType: tree.FixedReturnType(types.Timestamp),
Fn: func(ctx *tree.EvalContext, args tree.Datums) (tree.Datum, error) {
prec := int32(tree.MustBeDInt(args[0]))
if prec < 0 || prec > 6 {
return nil, pgerror.Newf(pgcode.NumericValueOutOfRange, "precision %d out of range", prec)
}
return ctx.GetTxnTimestampNoZone(tree.TimeFamilyPrecisionToRoundDuration(prec)), nil
},
Info: txnTSDoc,
},
{
Types: tree.ArgTypes{{"precision", types.Int}},
ReturnType: tree.FixedReturnType(types.Date),
Fn: func(ctx *tree.EvalContext, args tree.Datums) (tree.Datum, error) {
prec := int32(tree.MustBeDInt(args[0]))
if prec < 0 || prec > 6 {
return nil, pgerror.Newf(pgcode.NumericValueOutOfRange, "precision %d out of range", prec)
}
return currentDate(ctx, args)
},
Info: txnTSDoc,
},
},
txnTSOverloads...,
)

var txnTSImpl = makeBuiltin(
tree.FunctionProperties{
Category: categoryDateAndTime,
Impure: true,
},
txnTSOverloads...,
)

var txnTSWithPrecisionImpl = makeBuiltin(
tree.FunctionProperties{
Category: categoryDateAndTime,
Impure: true,
},
txnTSWithPrecisionOverloads...,
)

func currentDate(ctx *tree.EvalContext, args tree.Datums) (tree.Datum, error) {
Expand Down
1 change: 1 addition & 0 deletions pkg/sql/sem/tree/normalize_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ func TestNormalizeExpr(t *testing.T) {
{`clock_timestamp()`, `clock_timestamp()`},
{`now()`, `now()`},
{`current_timestamp()`, `current_timestamp()`},
{`current_timestamp(5)`, `current_timestamp(5)`},
{`transaction_timestamp()`, `transaction_timestamp()`},
{`statement_timestamp()`, `statement_timestamp()`},
{`cluster_logical_timestamp()`, `cluster_logical_timestamp()`},
Expand Down

0 comments on commit d14360d

Please sign in to comment.