diff --git a/docs/generated/sql/bnf/stmt_block.bnf b/docs/generated/sql/bnf/stmt_block.bnf index 8c4e6745081c..bd64caf107d6 100644 --- a/docs/generated/sql/bnf/stmt_block.bnf +++ b/docs/generated/sql/bnf/stmt_block.bnf @@ -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 ')' diff --git a/docs/generated/sql/functions.md b/docs/generated/sql/functions.md index 61ffa4328cfa..6001ea647ce8 100644 --- a/docs/generated/sql/functions.md +++ b/docs/generated/sql/functions.md @@ -312,6 +312,21 @@ has no relationship with the commit order of concurrent transactions.
and which stays constant throughout the transaction. This timestamp has no relationship with the commit order of concurrent transactions. +current_timestamp(precision: int) → date
Returns the time of the current transaction.
+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.
+current_timestamp(precision: int) → timestamp
Returns the time of the current transaction.
+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.
+current_timestamp(precision: int) → timestamptz
Returns the time of the current transaction.
+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.
+date_trunc(element: string, input: date) → timestamptz
Truncates input
to precision element
. Sets all fields that are less
significant than element
to zero (or one, for day and month)
Compatible elements: millennium, century, decade, year, quarter, month, diff --git a/pkg/cmd/roachprod/vm/gce/gcloud.go b/pkg/cmd/roachprod/vm/gce/gcloud.go index 23417c59f2a0..31b64599c99b 100644 --- a/pkg/cmd/roachprod/vm/gce/gcloud.go +++ b/pkg/cmd/roachprod/vm/gce/gcloud.go @@ -221,10 +221,14 @@ func (v projectsVal) String() string { } func makeProviderOpts() providerOpts { + project := os.Getenv("GCE_PROJECT") + if project == "" { + project = defaultProject + } return providerOpts{ // projects needs space for one project, which is set by the flags for // commands that accept a single project. - projects: []string{defaultProject}, + projects: []string{project}, } } @@ -264,11 +268,6 @@ func (o *providerOpts) ConfigureCreateFlags(flags *pflag.FlagSet) { } func (o *providerOpts) ConfigureClusterFlags(flags *pflag.FlagSet, opt vm.MultipleProjectsOption) { - project := os.Getenv("GCE_PROJECT") - if project == "" { - project = defaultProject - } - var usage string if opt == vm.SingleProject { usage = "GCE project to manage" diff --git a/pkg/sql/logictest/testdata/logic_test/timestamp b/pkg/sql/logictest/testdata/logic_test/timestamp index b0624a5c54b5..0e48ec81ad07 100644 --- a/pkg/sql/logictest/testdata/logic_test/timestamp +++ b/pkg/sql/logictest/testdata/logic_test/timestamp @@ -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, diff --git a/pkg/sql/parser/parse_test.go b/pkg/sql/parser/parse_test.go index 17e5674eed07..a0743a46380f 100644 --- a/pkg/sql/parser/parse_test.go +++ b/pkg/sql/parser/parse_test.go @@ -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)`, diff --git a/pkg/sql/parser/sql.y b/pkg/sql/parser/sql.y index 0a2a905432bf..0a16e681f97f 100644 --- a/pkg/sql/parser/sql.y +++ b/pkg/sql/parser/sql.y @@ -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 '(' ')' { diff --git a/pkg/sql/sem/builtins/builtins.go b/pkg/sql/sem/builtins/builtins.go index 1742c9d63758..c311221aa503 100644 --- a/pkg/sql/sem/builtins/builtins.go +++ b/pkg/sql/sem/builtins/builtins.go @@ -1675,7 +1675,7 @@ CockroachDB supports the following flags: ), "now": txnTSImpl, - "current_timestamp": txnTSImpl, + "current_timestamp": txnTSWithPrecisionImpl, "transaction_timestamp": txnTSImpl, "statement_timestamp": makeBuiltin( @@ -3497,12 +3497,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, @@ -3511,7 +3507,7 @@ 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) { @@ -3519,12 +3515,71 @@ var txnTSImpl = makeBuiltin( }, 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) { diff --git a/pkg/sql/sem/tree/normalize_test.go b/pkg/sql/sem/tree/normalize_test.go index d52a612104ba..dbdd05294474 100644 --- a/pkg/sql/sem/tree/normalize_test.go +++ b/pkg/sql/sem/tree/normalize_test.go @@ -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()`},