Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
70332: sql: allow array builtins to operate on tuples  r=yuzefovich a=rafiss

fixes #70029

DistSQL does not support this because the DArray operations in eval.go
all result in arrays of AnyTuple, which cannot be decoded.

Release note (sql change): The array builtins (array_agg, array_cat,
array_position, etc) now operate on record types.

70363: ui: fixes clock offset rendering on multi-store nodes r=rimadeodhar a=dhartunian

Previously, the clock offset metric was retrieved on a "per-store" basis
for each node which did not match its storage model in the tsdb which is
node-based. This would cause incorrect data to be displayed in the
Runtime dashboard's "Clock Offset" graph when a node contained multiple
stores. We would use `store_id`s to query when we should have been
asking for `node_id`s in the `sources` list in the query.

This change modifies the Clock Offset metric component to request
metrics by `node_id` instead which correctly renders the "Clock Offset"
graph for nodes with multiple stores.

Resolves #69652

Release note (ui change): fix bug where Clock Offset graph rendered
incorrectly on nodes with multiple stores.

70369: sql: hide enable_drop_enum_value session/cluster setting  r=otan,postamar a=rafiss

fixes #61594 

Release note (sql change): The enable_drop_enum_value session variable
has been removed, along with the corresponding cluter setting. The
functionality of being able to drop enum values is now enabled
automatically. Queries that refer to the session/cluster setting will
still work but will have no effect.


Co-authored-by: Rafi Shamim <[email protected]>
Co-authored-by: David Hartunian <[email protected]>
  • Loading branch information
3 people committed Sep 21, 2021
4 parents af8d186 + 7341b5b + f100107 + 2ecbdf2 commit 16ea3e8
Show file tree
Hide file tree
Showing 33 changed files with 371 additions and 248 deletions.
1 change: 0 additions & 1 deletion docs/generated/settings/settings-for-tenants.txt
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@ sql.defaults.datestyle.enabled boolean false default value for datestyle_enabled
sql.defaults.default_int_size integer 8 the size, in bytes, of an INT type
sql.defaults.disallow_full_table_scans.enabled boolean false setting to true rejects queries that have planned a full table scan
sql.defaults.distsql enumeration auto default distributed SQL execution mode [off = 0, auto = 1, on = 2]
sql.defaults.drop_enum_value.enabled boolean false default value for enable_drop_enum_value; allows for dropping enum values
sql.defaults.experimental_alter_column_type.enabled boolean false default value for experimental_alter_column_type session setting; enables the use of ALTER COLUMN TYPE for general conversions
sql.defaults.experimental_auto_rehoming.enabled boolean false default value for experimental_enable_auto_rehoming; allows for rows in REGIONAL BY ROW tables to be auto-rehomed on UPDATE
sql.defaults.experimental_distsql_planning enumeration off default experimental_distsql_planning mode; enables experimental opt-driven DistSQL planning [off = 0, on = 1]
Expand Down
1 change: 0 additions & 1 deletion docs/generated/settings/settings.html
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,6 @@
<tr><td><code>sql.defaults.default_int_size</code></td><td>integer</td><td><code>8</code></td><td>the size, in bytes, of an INT type</td></tr>
<tr><td><code>sql.defaults.disallow_full_table_scans.enabled</code></td><td>boolean</td><td><code>false</code></td><td>setting to true rejects queries that have planned a full table scan</td></tr>
<tr><td><code>sql.defaults.distsql</code></td><td>enumeration</td><td><code>auto</code></td><td>default distributed SQL execution mode [off = 0, auto = 1, on = 2]</td></tr>
<tr><td><code>sql.defaults.drop_enum_value.enabled</code></td><td>boolean</td><td><code>false</code></td><td>default value for enable_drop_enum_value; allows for dropping enum values</td></tr>
<tr><td><code>sql.defaults.experimental_alter_column_type.enabled</code></td><td>boolean</td><td><code>false</code></td><td>default value for experimental_alter_column_type session setting; enables the use of ALTER COLUMN TYPE for general conversions</td></tr>
<tr><td><code>sql.defaults.experimental_auto_rehoming.enabled</code></td><td>boolean</td><td><code>false</code></td><td>default value for experimental_enable_auto_rehoming; allows for rows in REGIONAL BY ROW tables to be auto-rehomed on UPDATE</td></tr>
<tr><td><code>sql.defaults.experimental_distsql_planning</code></td><td>enumeration</td><td><code>off</code></td><td>default experimental_distsql_planning mode; enables experimental opt-driven DistSQL planning [off = 0, on = 1]</td></tr>
Expand Down
2 changes: 2 additions & 0 deletions docs/generated/sql/aggregates.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
</span></td></tr>
<tr><td><a name="array_agg"></a><code>array_agg(arg1: timetz) &rarr; timetz[]</code></td><td><span class="funcdesc"><p>Aggregates the selected values into an array.</p>
</span></td></tr>
<tr><td><a name="array_agg"></a><code>array_agg(arg1: tuple) &rarr; tuple[]</code></td><td><span class="funcdesc"><p>Aggregates the selected values into an array.</p>
</span></td></tr>
<tr><td><a name="array_agg"></a><code>array_agg(arg1: varbit) &rarr; varbit[]</code></td><td><span class="funcdesc"><p>Aggregates the selected values into an array.</p>
</span></td></tr>
<tr><td><a name="avg"></a><code>avg(arg1: <a href="decimal.html">decimal</a>) &rarr; <a href="decimal.html">decimal</a></code></td><td><span class="funcdesc"><p>Calculates the average of the selected values.</p>
Expand Down
14 changes: 14 additions & 0 deletions docs/generated/sql/functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@
</span></td></tr>
<tr><td><a name="array_append"></a><code>array_append(array: timetz[], elem: timetz) &rarr; timetz[]</code></td><td><span class="funcdesc"><p>Appends <code>elem</code> to <code>array</code>, returning the result.</p>
</span></td></tr>
<tr><td><a name="array_append"></a><code>array_append(array: tuple[], elem: tuple) &rarr; tuple[]</code></td><td><span class="funcdesc"><p>Appends <code>elem</code> to <code>array</code>, returning the result.</p>
</span></td></tr>
<tr><td><a name="array_append"></a><code>array_append(array: varbit[], elem: varbit) &rarr; varbit[]</code></td><td><span class="funcdesc"><p>Appends <code>elem</code> to <code>array</code>, returning the result.</p>
</span></td></tr>
<tr><td><a name="array_cat"></a><code>array_cat(left: <a href="bool.html">bool</a>[], right: <a href="bool.html">bool</a>[]) &rarr; <a href="bool.html">bool</a>[]</code></td><td><span class="funcdesc"><p>Appends two arrays.</p>
Expand Down Expand Up @@ -81,6 +83,8 @@
</span></td></tr>
<tr><td><a name="array_cat"></a><code>array_cat(left: timetz[], right: timetz[]) &rarr; timetz[]</code></td><td><span class="funcdesc"><p>Appends two arrays.</p>
</span></td></tr>
<tr><td><a name="array_cat"></a><code>array_cat(left: tuple[], right: tuple[]) &rarr; tuple[]</code></td><td><span class="funcdesc"><p>Appends two arrays.</p>
</span></td></tr>
<tr><td><a name="array_cat"></a><code>array_cat(left: varbit[], right: varbit[]) &rarr; varbit[]</code></td><td><span class="funcdesc"><p>Appends two arrays.</p>
</span></td></tr>
<tr><td><a name="array_length"></a><code>array_length(input: anyelement[], array_dimension: <a href="int.html">int</a>) &rarr; <a href="int.html">int</a></code></td><td><span class="funcdesc"><p>Calculates the length of <code>input</code> on the provided <code>array_dimension</code>. However, because CockroachDB doesn’t yet support multi-dimensional arrays, the only supported <code>array_dimension</code> is <strong>1</strong>.</p>
Expand Down Expand Up @@ -125,6 +129,8 @@
</span></td></tr>
<tr><td><a name="array_position"></a><code>array_position(array: timetz[], elem: timetz) &rarr; <a href="int.html">int</a></code></td><td><span class="funcdesc"><p>Return the index of the first occurrence of <code>elem</code> in <code>array</code>.</p>
</span></td></tr>
<tr><td><a name="array_position"></a><code>array_position(array: tuple[], elem: tuple) &rarr; <a href="int.html">int</a></code></td><td><span class="funcdesc"><p>Return the index of the first occurrence of <code>elem</code> in <code>array</code>.</p>
</span></td></tr>
<tr><td><a name="array_position"></a><code>array_position(array: varbit[], elem: varbit) &rarr; <a href="int.html">int</a></code></td><td><span class="funcdesc"><p>Return the index of the first occurrence of <code>elem</code> in <code>array</code>.</p>
</span></td></tr>
<tr><td><a name="array_positions"></a><code>array_positions(array: <a href="bool.html">bool</a>[], elem: <a href="bool.html">bool</a>) &rarr; <a href="int.html">int</a>[]</code></td><td><span class="funcdesc"><p>Returns and array of indexes of all occurrences of <code>elem</code> in <code>array</code>.</p>
Expand Down Expand Up @@ -165,6 +171,8 @@
</span></td></tr>
<tr><td><a name="array_positions"></a><code>array_positions(array: timetz[], elem: timetz) &rarr; <a href="int.html">int</a>[]</code></td><td><span class="funcdesc"><p>Returns and array of indexes of all occurrences of <code>elem</code> in <code>array</code>.</p>
</span></td></tr>
<tr><td><a name="array_positions"></a><code>array_positions(array: tuple[], elem: tuple) &rarr; <a href="int.html">int</a>[]</code></td><td><span class="funcdesc"><p>Returns and array of indexes of all occurrences of <code>elem</code> in <code>array</code>.</p>
</span></td></tr>
<tr><td><a name="array_positions"></a><code>array_positions(array: varbit[], elem: varbit) &rarr; <a href="int.html">int</a>[]</code></td><td><span class="funcdesc"><p>Returns and array of indexes of all occurrences of <code>elem</code> in <code>array</code>.</p>
</span></td></tr>
<tr><td><a name="array_prepend"></a><code>array_prepend(elem: <a href="bool.html">bool</a>, array: <a href="bool.html">bool</a>[]) &rarr; <a href="bool.html">bool</a>[]</code></td><td><span class="funcdesc"><p>Prepends <code>elem</code> to <code>array</code>, returning the result.</p>
Expand Down Expand Up @@ -205,6 +213,8 @@
</span></td></tr>
<tr><td><a name="array_prepend"></a><code>array_prepend(elem: timetz, array: timetz[]) &rarr; timetz[]</code></td><td><span class="funcdesc"><p>Prepends <code>elem</code> to <code>array</code>, returning the result.</p>
</span></td></tr>
<tr><td><a name="array_prepend"></a><code>array_prepend(elem: tuple, array: tuple[]) &rarr; tuple[]</code></td><td><span class="funcdesc"><p>Prepends <code>elem</code> to <code>array</code>, returning the result.</p>
</span></td></tr>
<tr><td><a name="array_prepend"></a><code>array_prepend(elem: varbit, array: varbit[]) &rarr; varbit[]</code></td><td><span class="funcdesc"><p>Prepends <code>elem</code> to <code>array</code>, returning the result.</p>
</span></td></tr>
<tr><td><a name="array_remove"></a><code>array_remove(array: <a href="bool.html">bool</a>[], elem: <a href="bool.html">bool</a>) &rarr; <a href="bool.html">bool</a>[]</code></td><td><span class="funcdesc"><p>Remove from <code>array</code> all elements equal to <code>elem</code>.</p>
Expand Down Expand Up @@ -245,6 +255,8 @@
</span></td></tr>
<tr><td><a name="array_remove"></a><code>array_remove(array: timetz[], elem: timetz) &rarr; timetz[]</code></td><td><span class="funcdesc"><p>Remove from <code>array</code> all elements equal to <code>elem</code>.</p>
</span></td></tr>
<tr><td><a name="array_remove"></a><code>array_remove(array: tuple[], elem: tuple) &rarr; tuple[]</code></td><td><span class="funcdesc"><p>Remove from <code>array</code> all elements equal to <code>elem</code>.</p>
</span></td></tr>
<tr><td><a name="array_remove"></a><code>array_remove(array: varbit[], elem: varbit) &rarr; varbit[]</code></td><td><span class="funcdesc"><p>Remove from <code>array</code> all elements equal to <code>elem</code>.</p>
</span></td></tr>
<tr><td><a name="array_replace"></a><code>array_replace(array: <a href="bool.html">bool</a>[], toreplace: <a href="bool.html">bool</a>, replacewith: <a href="bool.html">bool</a>) &rarr; <a href="bool.html">bool</a>[]</code></td><td><span class="funcdesc"><p>Replace all occurrences of <code>toreplace</code> in <code>array</code> with <code>replacewith</code>.</p>
Expand Down Expand Up @@ -285,6 +297,8 @@
</span></td></tr>
<tr><td><a name="array_replace"></a><code>array_replace(array: timetz[], toreplace: timetz, replacewith: timetz) &rarr; timetz[]</code></td><td><span class="funcdesc"><p>Replace all occurrences of <code>toreplace</code> in <code>array</code> with <code>replacewith</code>.</p>
</span></td></tr>
<tr><td><a name="array_replace"></a><code>array_replace(array: tuple[], toreplace: tuple, replacewith: tuple) &rarr; tuple[]</code></td><td><span class="funcdesc"><p>Replace all occurrences of <code>toreplace</code> in <code>array</code> with <code>replacewith</code>.</p>
</span></td></tr>
<tr><td><a name="array_replace"></a><code>array_replace(array: varbit[], toreplace: varbit, replacewith: varbit) &rarr; varbit[]</code></td><td><span class="funcdesc"><p>Replace all occurrences of <code>toreplace</code> in <code>array</code> with <code>replacewith</code>.</p>
</span></td></tr>
<tr><td><a name="array_to_string"></a><code>array_to_string(input: anyelement[], delim: <a href="string.html">string</a>) &rarr; <a href="string.html">string</a></code></td><td><span class="funcdesc"><p>Join an array into a string with a delimiter.</p>
Expand Down
2 changes: 0 additions & 2 deletions pkg/ccl/backupccl/backup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3007,8 +3007,6 @@ func TestBackupRestoreDuringUserDefinedTypeChange(t *testing.T) {

// Create a database with a type.
sqlDB.Exec(t, `
SET CLUSTER SETTING sql.defaults.drop_enum_value.enabled = true;
SET enable_drop_enum_value = true;
CREATE DATABASE d;
CREATE TYPE d.greeting AS ENUM ('hello', 'howdy', 'hi');
`)
Expand Down
2 changes: 0 additions & 2 deletions pkg/ccl/importccl/import_stmt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7318,8 +7318,6 @@ func TestUDTChangeDuringImport(t *testing.T) {

// Create a database with a type.
sqlDB.Exec(t, `
SET CLUSTER SETTING sql.defaults.drop_enum_value.enabled = true;
SET enable_drop_enum_value = true;
CREATE DATABASE d;
USE d;
CREATE TYPE d.greeting AS ENUM ('hello', 'howdy', 'hi');
Expand Down
3 changes: 0 additions & 3 deletions pkg/ccl/logictestccl/testdata/logic_test/partitioning_enum
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ subtest drop_enum_partitioning_value
statement ok
drop table if exists tbl;
drop type if exists t;
set enable_drop_enum_value = true;
create type t as enum('a', 'b', 'c');
create table tbl (pk t PRIMARY KEY) PARTITION BY LIST (pk) (PARTITION "a" VALUES IN ('a'))

Expand All @@ -72,7 +71,6 @@ alter type t drop value 'a'
statement ok
drop table if exists tbl;
drop type if exists t;
set enable_drop_enum_value = true;
create type t as enum('a', 'b', 'c');
create table tbl (i INT, k t, PRIMARY KEY (i, k)) PARTITION BY LIST (i) (PARTITION "one" VALUES IN (1) PARTITION BY RANGE (k) (PARTITION "a" VALUES FROM ('a') TO ('b')))

Expand All @@ -82,7 +80,6 @@ alter type t drop value 'a'
statement ok
drop table if exists tbl;
drop type if exists t;
set enable_drop_enum_value = true;
create type t as enum('a', 'b', 'c');
create table tbl (i INT, k t, PRIMARY KEY (i, k), INDEX idx (k) PARTITION BY RANGE (k) (PARTITION "a" VALUES FROM ('a') TO ('b')))

Expand Down
4 changes: 0 additions & 4 deletions pkg/internal/sqlsmith/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,6 @@ func wrapCommonSetup(setupFn Setup) Setup {
return func(r *rand.Rand) string {
s := setupFn(r)
var sb strings.Builder
sb.WriteString(`
SET CLUSTER SETTING sql.defaults.drop_enum_value.enabled = true;
SET enable_drop_enum_value = true;
`)
sb.WriteString(s)
return sb.String()
}
Expand Down
3 changes: 3 additions & 0 deletions pkg/settings/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@ var retiredSettings = map[string]struct{}{
"sql.distsql.prefer_local_execution.enabled": {},
"kv.follower_read.target_multiple": {},
"kv.closed_timestamp.close_fraction": {},

// removed as of 22.1.
"sql.defaults.drop_enum_value.enabled": {},
}

// register adds a setting to the registry.
Expand Down
13 changes: 0 additions & 13 deletions pkg/sql/alter_type.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ package sql
import (
"context"

"github.com/cockroachdb/cockroach/pkg/build"
"github.com/cockroachdb/cockroach/pkg/security"
"github.com/cockroachdb/cockroach/pkg/server/telemetry"
"github.com/cockroachdb/cockroach/pkg/sql/catalog"
Expand Down Expand Up @@ -117,18 +116,6 @@ func (n *alterTypeNode) startExec(params runParams) error {
}
eventLogDone = true // done inside alterTypeOwner().
case *tree.AlterTypeDropValue:
if !params.p.SessionData().DropEnumValueEnabled {
return pgerror.WithCandidateCode(
errors.WithHint(
errors.WithIssueLink(
errors.New("ALTER TYPE ... DROP VALUE ... is only supported as an alpha feature "+
"since view, default, or computed expressions will stop working if they reference the "+
"ENUM value"),
errors.IssueLink{IssueURL: build.MakeIssueURL(61594)}),
"you can enable alter type drop value by running "+
"`SET enable_drop_enum_value = true`"),
pgcode.FeatureNotSupported)
}
err = params.p.dropEnumValue(params.ctx, n.desc, t.Val)
default:
err = errors.AssertionFailedf("unknown alter type cmd %s", t)
Expand Down
8 changes: 8 additions & 0 deletions pkg/sql/distsql_physical_planner.go
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,14 @@ func (v *distSQLExprCheckVisitor) VisitPre(expr tree.Expr) (recurse bool, newExp
v.err = newQueryNotSupportedErrorf("cast to %s is not supported by distsql", t.Type)
return false, expr
}
case *tree.DArray:
// We need to check for arrays of untyped tuples here since constant-folding
// on builtin functions sometimes produces this.
if t.ResolvedType().ArrayContents() == types.AnyTuple {
v.err = newQueryNotSupportedErrorf("array %s cannot be executed with distsql", t)
return false, expr
}

}
return true, expr
}
Expand Down
10 changes: 0 additions & 10 deletions pkg/sql/exec_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -279,12 +279,6 @@ var implicitColumnPartitioningEnabledClusterMode = settings.RegisterBoolSetting(
false,
).WithPublic()

var dropEnumValueEnabledClusterMode = settings.RegisterBoolSetting(
"sql.defaults.drop_enum_value.enabled",
"default value for enable_drop_enum_value; allows for dropping enum values",
false,
).WithPublic()

var overrideMultiRegionZoneConfigClusterMode = settings.RegisterBoolSetting(
"sql.defaults.override_multi_region_zone_config.enabled",
"default value for override_multi_region_zone_config; "+
Expand Down Expand Up @@ -2844,10 +2838,6 @@ func (m *sessionDataMutator) SetImplicitColumnPartitioningEnabled(val bool) {
m.data.ImplicitColumnPartitioningEnabled = val
}

func (m *sessionDataMutator) SetDropEnumValueEnabled(val bool) {
m.data.DropEnumValueEnabled = val
}

func (m *sessionDataMutator) SetOverrideMultiRegionZoneConfigEnabled(val bool) {
m.data.OverrideMultiRegionZoneConfigEnabled = val
}
Expand Down
6 changes: 0 additions & 6 deletions pkg/sql/logictest/testdata/logic_test/alter_type
Original file line number Diff line number Diff line change
Expand Up @@ -269,12 +269,6 @@ SELECT 'lru'::store
statement ok
CREATE TYPE greetings AS ENUM('hi', 'hello', 'howdy', 'yo')

statement error pq: ALTER TYPE ... DROP VALUE ... is only supported as an alpha feature
ALTER TYPE greetings DROP VALUE 'hi'

statement ok
SET enable_drop_enum_value = true;

statement ok
ALTER TYPE greetings DROP VALUE 'hi'

Expand Down
157 changes: 157 additions & 0 deletions pkg/sql/logictest/testdata/logic_test/array
Original file line number Diff line number Diff line change
Expand Up @@ -1746,6 +1746,8 @@ INSERT INTO t VALUES (
'{0101, 11}',
'{12.34, 45.67}');

subtest array_tuples

# Test for #32715: able to distribute queries with arrays of tuples.

statement ok
Expand Down Expand Up @@ -1781,3 +1783,158 @@ SELECT ARRAY[(k, 'foo'), (1, v)] FROM kv
{"(3,foo)","(1,three)"}
{"(4,foo)","(1,four)"}
{"(5,foo)","(1,)"}

# Test array builtins on record types

query T rowsort
SELECT array_cat(ARRAY[ROW(10,'fish')], ARRAY[(k,v)]) FROM kv
----
{"(10,fish)","(1,one)"}
{"(10,fish)","(2,two)"}
{"(10,fish)","(3,three)"}
{"(10,fish)","(4,four)"}
{"(10,fish)","(5,)"}

query T rowsort
SELECT array_cat(ARRAY[ROW(1,NULL)], ARRAY[(k,v)]) FROM kv
----
{"(1,)","(1,one)"}
{"(1,)","(2,two)"}
{"(1,)","(3,three)"}
{"(1,)","(4,four)"}
{"(1,)","(5,)"}

query T rowsort
SELECT array_cat(ARRAY[NULL::record], ARRAY[(k,v)]) FROM kv
----
{NULL,"(1,one)"}
{NULL,"(2,two)"}
{NULL,"(3,three)"}
{NULL,"(4,four)"}
{NULL,"(5,)"}

query T
SELECT array_cat(ARRAY[ROW(1,2)], ARRAY[NULL::record])
----
{"(1,2)",NULL}

query T
SELECT array_agg(ROW(1, 2))
----
{"(1,2)"}

query T
SELECT array_agg(ROW(k,v) ORDER BY k) FROM kv
----
{"(1,one)","(2,two)","(3,three)","(4,four)","(5,)"}

query T rowsort
SELECT array_append(ARRAY[ROW(10,'fish')], (k,v)) FROM kv
----
{"(10,fish)","(1,one)"}
{"(10,fish)","(2,two)"}
{"(10,fish)","(3,three)"}
{"(10,fish)","(4,four)"}
{"(10,fish)","(5,)"}

query T
SELECT array_append(ARRAY[ROW(1,2)], NULL::record)
----
{"(1,2)",NULL}

query T rowsort
SELECT array_append(NULL::record[], (k,v)) FROM kv
----
{"(1,one)"}
{"(2,two)"}
{"(3,three)"}
{"(4,four)"}
{"(5,)"}

query T
SELECT array_append(NULL::record[], NULL::record)
----
{NULL}

query T rowsort
SELECT array_prepend((k,v), ARRAY[ROW(10,'fish'), ROW(11,'zebra')]) FROM kv
----
{"(1,one)","(10,fish)","(11,zebra)"}
{"(2,two)","(10,fish)","(11,zebra)"}
{"(3,three)","(10,fish)","(11,zebra)"}
{"(4,four)","(10,fish)","(11,zebra)"}
{"(5,)","(10,fish)","(11,zebra)"}

query T
SELECT array_prepend(NULL::record, ARRAY[ROW(10,'fish'), ROW(11,'zebra')])
----
{NULL,"(10,fish)","(11,zebra)"}

query T
SELECT array_prepend(ROW(1,2), NULL::record[])
----
{"(1,2)"}

query T
SELECT array_prepend(NULL::record, NULL::record[])
----
{NULL}

query T
SELECT array_remove(ARRAY[ROW(1,'cat'), ROW(10,'fish'), ROW(11,'zebra')], ROW(10,'fish'))
----
{"(1,cat)","(11,zebra)"}

query T
SELECT array_remove(ARRAY[ROW(1,'cat'), ROW(10,'fish'), ROW(11,'zebra'), NULL], NULL::record)
----
{"(1,cat)","(10,fish)","(11,zebra)"}

query T
SELECT array_remove(NULL::record[], NULL::record)
----
NULL

query T
SELECT array_replace(ARRAY[ROW(1,'cat'), ROW(10,'fish'), ROW(11,'zebra')], ROW(10,'fish'), ROW(2,'dog'))
----
{"(1,cat)","(2,dog)","(11,zebra)"}

query TT
SELECT array_replace(ARRAY[ROW(1,'cat'), NULL, ROW(11,'zebra')], NULL::record, ROW(2,'dog')), array_replace(NULL::record[], ROW(10,'fish'), ROW(2,'dog'))
----
{"(1,cat)","(2,dog)","(11,zebra)"} NULL

# ARRAY_POSITION function

query I
SELECT array_position(ARRAY[ROW(1,'cat'), ROW(10,'fish'), ROW(11,'zebra')], ROW(11,'zebra'))
----
3

query I
SELECT array_position(ARRAY[ROW(1,'cat'), ROW(10,'fish'), ROW(11,'zebra')], ROW(33,'hippo'))
----
NULL

query I
SELECT array_position(NULL::record[], ROW(33,'hippo'))
----
NULL

# ARRAY_POSITIONS function

query T
SELECT array_positions(ARRAY[ROW(1,'cat'), ROW(11,'zebra'), ROW(10,'fish'), ROW(11,'zebra')], ROW(11,'zebra'))
----
{2,4}

query T
SELECT array_positions(ARRAY[ROW(1,'cat'), ROW(11,'zebra'), ROW(10,'fish'), ROW(11,'zebra')], ROW(33,'hippo'))
----
{}

query T
SELECT array_positions(NULL::record[], ROW(33,'hippo'))
----
NULL
Loading

0 comments on commit 16ea3e8

Please sign in to comment.