Skip to content

Commit

Permalink
Merge #69911
Browse files Browse the repository at this point in the history
69911: sql: implement information_schema._pg_index_position r=nvanbenschoten a=nvanbenschoten

Needed for #69010.

This commit implements the `information_schema._pg_index_position` builtin
function. Given an index's OID and an underlying-table column number,
`information_schema._pg_index_position` return the column's position in the
index (or NULL if not there).

The function is implemented as a user-defined function in Postgres here:
https://github.com/postgres/postgres/blob/master/src/backend/catalog/information_schema.sql

Release note (sql change): The `information_schema._pg_index_position`
builtin function is now supported, which improves compatibility with
PostgreSQL.

Release justification: None, waiting for v22.1.

Co-authored-by: Nathan VanBenschoten <nvanbenschoten@gmail.com>
  • Loading branch information
craig[bot] and nvanbenschoten committed Sep 14, 2021
2 parents a355ffe + a459229 commit c7d1ab7
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 0 deletions.
25 changes: 25 additions & 0 deletions pkg/bench/rttanalysis/orm_queries_bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,31 @@ WHERE
Stmt: `SELECT nspname, pg_is_other_temp_schema(oid) FROM
(SELECT * FROM pg_namespace LIMIT 5) n`,
},

{
Name: "information_schema._pg_index_position",
Setup: `CREATE TABLE indexed (
a INT PRIMARY KEY,
b INT,
c INT,
d INT,
INDEX (b, d),
INDEX (c, a)
);
CREATE VIEW indexes AS
SELECT i.relname, indkey::INT2[], indexrelid
FROM pg_catalog.pg_index
JOIN pg_catalog.pg_class AS t ON indrelid = t.oid
JOIN pg_catalog.pg_class AS i ON indexrelid = i.oid
WHERE t.relname = 'indexed'
ORDER BY i.relname`,
Stmt: `SELECT relname,
indkey,
generate_series(1, 4) input,
information_schema._pg_index_position(indexrelid, generate_series(1, 4))
FROM indexes
ORDER BY relname DESC, input`,
},
}

RunRoundTripBenchmark(b, tests)
Expand Down
53 changes: 53 additions & 0 deletions pkg/sql/logictest/testdata/logic_test/pg_builtins
Original file line number Diff line number Diff line change
Expand Up @@ -484,3 +484,56 @@ varchar 64
bit 1
varbit 16
numeric NULL

# information_schema._pg_index_position

statement ok
CREATE TABLE indexed (
a INT PRIMARY KEY,
b INT,
c INT,
d INT,
INDEX (b, d),
INDEX (c, a)
);

# NOTE, we cast indkey to an INT2[], because an INT2VECTOR's formatting appears
# to be dependent on whether the result set spilled to disk or not. It was being
# formatted differently with the "local" test config (and others) than with the
# "fakedist-disk" test config.
statement ok
CREATE TEMPORARY VIEW indexes AS
SELECT i.relname, indkey::INT2[], indexrelid
FROM pg_catalog.pg_index
JOIN pg_catalog.pg_class AS t ON indrelid = t.oid
JOIN pg_catalog.pg_class AS i ON indexrelid = i.oid
WHERE t.relname = 'indexed'
ORDER BY i.relname

query TT
SELECT relname, indkey FROM indexes ORDER BY relname DESC
----
primary {1}
indexed_c_a_idx {3,1}
indexed_b_d_idx {2,4}

query TTII
SELECT relname,
indkey,
generate_series(1, 4) input,
information_schema._pg_index_position(indexrelid, generate_series(1, 4))
FROM indexes
ORDER BY relname DESC, input
----
primary {1} 1 1
primary {1} 2 NULL
primary {1} 3 NULL
primary {1} 4 NULL
indexed_c_a_idx {3,1} 1 2
indexed_c_a_idx {3,1} 2 NULL
indexed_c_a_idx {3,1} 3 1
indexed_c_a_idx {3,1} 4 NULL
indexed_b_d_idx {2,4} 1 NULL
indexed_b_d_idx {2,4} 2 1
indexed_b_d_idx {2,4} 3 NULL
indexed_b_d_idx {2,4} 4 2
46 changes: 46 additions & 0 deletions pkg/sql/sem/builtins/pg_builtins.go
Original file line number Diff line number Diff line change
Expand Up @@ -2082,6 +2082,52 @@ SELECT description
Volatility: tree.VolatilityImmutable,
},
),

// Given an index's OID and an underlying-table column number,
// _pg_index_position return the column's position in the index
// (or NULL if not there).
//
// NOTE: this could be defined as a user-defined function, like
// it is in Postgres:
// https://github.com/postgres/postgres/blob/master/src/backend/catalog/information_schema.sql
//
// CREATE FUNCTION _pg_index_position(oid, smallint) RETURNS int
// LANGUAGE sql STRICT STABLE
// BEGIN ATOMIC
// SELECT (ss.a).n FROM
// (SELECT information_schema._pg_expandarray(indkey) AS a
// FROM pg_catalog.pg_index WHERE indexrelid = $1) ss
// WHERE (ss.a).x = $2;
// END;
//
"information_schema._pg_index_position": makeBuiltin(defProps(),
tree.Overload{
Types: tree.ArgTypes{
{"oid", types.Oid},
{"col", types.Int2},
},
ReturnType: tree.FixedReturnType(types.Int),
Fn: func(ctx *tree.EvalContext, args tree.Datums) (tree.Datum, error) {
r, err := ctx.InternalExecutor.QueryRow(
ctx.Ctx(), "information_schema._pg_index_position",
ctx.Txn,
`SELECT (ss.a).n FROM
(SELECT information_schema._pg_expandarray(indkey) AS a
FROM pg_catalog.pg_index WHERE indexrelid = $1) ss
WHERE (ss.a).x = $2`,
args[0], args[1])
if err != nil {
return nil, err
}
if len(r) == 0 {
return tree.DNull, nil
}
return r[0], nil
},
Info: notUsableInfo,
Volatility: tree.VolatilityStable,
},
),
}

func getSessionVar(ctx *tree.EvalContext, settingName string, missingOk bool) (tree.Datum, error) {
Expand Down

0 comments on commit c7d1ab7

Please sign in to comment.