From d14360d1f8371bf33b7312567063f7b9fb3b4e70 Mon Sep 17 00:00:00 2001 From: Oliver Tan Date: Tue, 19 Nov 2019 15:23:31 -0800 Subject: [PATCH 1/2] builtins: support current_timestamp with precision 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)`. --- docs/generated/sql/bnf/stmt_block.bnf | 1 + docs/generated/sql/functions.md | 15 ++++ .../logictest/testdata/logic_test/timestamp | 5 ++ pkg/sql/parser/parse_test.go | 2 + pkg/sql/parser/sql.y | 4 + pkg/sql/sem/builtins/builtins.go | 73 ++++++++++++++++--- pkg/sql/sem/tree/normalize_test.go | 1 + 7 files changed, 92 insertions(+), 9 deletions(-) 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 74f09850f92f..14c8dbec563c 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/sql/logictest/testdata/logic_test/timestamp b/pkg/sql/logictest/testdata/logic_test/timestamp index d83ecfdc7ebf..68d0f675e8e2 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 1ccce519f87d..cf6634edc04a 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( @@ -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, @@ -3510,7 +3506,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) { @@ -3518,12 +3514,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()`}, From 2664b00de29c207089f33b047ffc3478fc27626a Mon Sep 17 00:00:00 2001 From: Andrei Matei Date: Thu, 21 Nov 2019 15:34:10 -0500 Subject: [PATCH 2/2] roachprod: fix use of GCE_PROJECT That env var was supposed to allow one to set the project to use, but it got broken a while ago. Release note: None --- pkg/cmd/roachprod/vm/gce/gcloud.go | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) 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"