Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sql: more Postgres compatibility measures for ActiveRecord #13429

Merged
merged 8 commits into from
Feb 10, 2017
Merged
50 changes: 49 additions & 1 deletion pkg/sql/parser/builtins.go
Original file line number Diff line number Diff line change
Expand Up @@ -1401,7 +1401,7 @@ var Builtins = map[string][]Builtin{
},
},

"current_schema": {
"current_database": {
Builtin{
Types: ArgTypes{},
ReturnType: fixedReturnType(TypeString),
Expand All @@ -1416,6 +1416,23 @@ var Builtins = map[string][]Builtin{
},
},

"current_schema": {
Builtin{
Types: ArgTypes{},
ReturnType: fixedReturnType(TypeString),
category: categorySystemInfo,
fn: func(ctx *EvalContext, args Datums) (Datum, error) {
if len(ctx.Database) == 0 {
return DNull, nil
}
return NewDString(ctx.Database), nil
},
Info: "Returns the current schema. This function is provided for " +
"compatibility with PostgreSQL. For a new CockroachDB application, " +
"consider using current_database() instead.",
},
},

// For now, schemas are the same as databases. So, current_schemas
// returns the current database (if one has been set by the user)
// and the session's database search path.
Expand Down Expand Up @@ -1634,6 +1651,15 @@ var Builtins = map[string][]Builtin{
category: categoryCompatibility,
Info: "Not usable; exposed only for ORM compatibility with PostgreSQL.",
},
Builtin{
Types: ArgTypes{{"object_oid", TypeInt}, {"catalog_name", TypeString}},
ReturnType: fixedReturnType(TypeString),
fn: func(_ *EvalContext, _ Datums) (Datum, error) {
return DNull, nil
},
category: categoryCompatibility,
Info: "Not usable; exposed only for ORM compatibility.",
},
},
"shobj_description": {
Builtin{
Expand All @@ -1646,6 +1672,28 @@ var Builtins = map[string][]Builtin{
Info: "Not usable; exposed only for ORM compatibility with PostgreSQL.",
},
},
"pg_try_advisory_lock": {
Builtin{
Types: ArgTypes{{"int", TypeInt}},
ReturnType: fixedReturnType(TypeBool),
fn: func(_ *EvalContext, _ Datums) (Datum, error) {
return DBoolTrue, nil
},
category: categoryCompatibility,
Info: "Not usable; exposed only for ORM compatibility.",
},
},
"pg_advisory_unlock": {
Builtin{
Types: ArgTypes{{"int", TypeInt}},
ReturnType: fixedReturnType(TypeBool),
fn: func(_ *EvalContext, _ Datums) (Datum, error) {
return DBoolTrue, nil
},
category: categoryCompatibility,
Info: "Not usable; exposed only for ORM compatibility.",
},
},
"array_in": {
Builtin{
Types: ArgTypes{{"string", TypeString}, {"element_oid", TypeInt}, {"element_typmod", TypeInt}},
Expand Down
6 changes: 6 additions & 0 deletions pkg/sql/parser/eval.go
Original file line number Diff line number Diff line change
Expand Up @@ -2246,6 +2246,12 @@ func (expr *CastExpr) Eval(ctx *EvalContext) (Datum, error) {
return results[0], nil
}
s := string(*v)
// Trim whitespace and unwrap outer quotes if necessary.
// This is required to mimic postgres.
s = strings.TrimSpace(s)
if len(s) > 1 && s[0] == '"' && s[len(s)-1] == '"' {
s = s[1 : len(s)-1]
}

switch typ {
case oidPseudoTypeRegClass:
Expand Down
86 changes: 53 additions & 33 deletions pkg/sql/pg_catalog.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ var pgCatalog = virtualSchema{
pgCatalogDependTable,
pgCatalogDescriptionTable,
pgCatalogEnumTable,
pgCatalogExtensionTable,
pgCatalogForeignServerTable,
pgCatalogForeignTableTable,
pgCatalogIndexTable,
Expand Down Expand Up @@ -271,7 +272,7 @@ CREATE TABLE pg_catalog.pg_class (
if err := addRow(
h.TableOid(db, table), // oid
parser.NewDName(table.Name), // relname
pgNamespaceForDB(db).Oid, // relnamespace
pgNamespaceForDB(db, h).Oid, // relnamespace
oidZero, // reltype (PG creates a composite type in pg_type for each table)
parser.DNull, // relowner
parser.DNull, // relam
Expand Down Expand Up @@ -304,7 +305,7 @@ CREATE TABLE pg_catalog.pg_class (
return addRow(
h.IndexOid(db, table, index), // oid
parser.NewDName(index.Name), // relname
pgNamespaceForDB(db).Oid, // relnamespace
pgNamespaceForDB(db, h).Oid, // relnamespace
oidZero, // reltype
parser.DNull, // relowner
parser.DNull, // relam
Expand Down Expand Up @@ -517,7 +518,7 @@ CREATE TABLE pg_catalog.pg_constraint (
if err := addRow(
oid, // oid
dNameOrNull(name), // conname
pgNamespaceForDB(db).Oid, // connamespace
pgNamespaceForDB(db, h).Oid, // connamespace
contype, // contype
parser.MakeDBool(false), // condeferrable
parser.MakeDBool(false), // condeferred
Expand Down Expand Up @@ -746,6 +747,25 @@ CREATE TABLE pg_catalog.pg_enum (
},
}

// See: https://www.postgresql.org/docs/9.6/static/catalog-pg-extension.html.
var pgCatalogExtensionTable = virtualSchemaTable{
schema: `
CREATE TABLE pg_catalog.pg_extension (
extname NAME,
extowner OID,
extnamespace OID,
extrelocatable BOOL,
extversion STRING,
extconfig STRING,
extcondition STRING
);
`,
populate: func(p *planner, addRow func(...parser.Datum) error) error {
// Extensions are not supported.
return nil
},
}

// See: https://www.postgresql.org/docs/9.6/static/catalog-pg-foreign-server.html.
var pgCatalogForeignServerTable = virtualSchemaTable{
schema: `
Expand Down Expand Up @@ -881,12 +901,12 @@ CREATE TABLE pg_catalog.pg_indexes (
return err
}
return addRow(
h.IndexOid(db, table, index), // oid
pgNamespaceForDB(db).NameStr, // schemaname
parser.NewDName(table.Name), // tablename
parser.NewDName(index.Name), // indexname
parser.DNull, // tablespace
parser.NewDString(def), // indexdef
h.IndexOid(db, table, index), // oid
pgNamespaceForDB(db, h).NameStr, // schemaname
parser.NewDName(table.Name), // tablename
parser.NewDName(index.Name), // indexname
parser.DNull, // tablespace
parser.NewDString(def), // indexdef
)
})
},
Expand Down Expand Up @@ -981,17 +1001,15 @@ CREATE TABLE pg_catalog.pg_namespace (
);
`,
populate: func(p *planner, addRow func(...parser.Datum) error) error {
for _, nsp := range pgNamespaces {
if err := addRow(
nsp.Oid, // oid
nsp.NameStr, // nspname
parser.DNull, // nspowner
parser.DNull, // aclitem
); err != nil {
return err
}
}
return nil
h := makeOidHasher()
return forEachDatabaseDesc(p, func(db *sqlbase.DatabaseDescriptor) error {
return addRow(
h.NamespaceOid(db.Name), // oid
parser.NewDString(db.Name), // nspname
parser.DNull, // nspowner
parser.DNull, // aclitem
)
})
},
}

Expand Down Expand Up @@ -1051,7 +1069,7 @@ CREATE TABLE pg_catalog.pg_proc (
if err != nil {
return err
}
nspOid := pgNamespaceForDB(dbDesc).Oid
nspOid := pgNamespaceForDB(dbDesc, h).Oid
for name, builtins := range parser.Builtins {
// parser.Builtins contains duplicate uppercase and lowercase keys.
// Only return the lowercase ones for compatibility with postgres.
Expand Down Expand Up @@ -1463,14 +1481,18 @@ CREATE TABLE pg_catalog.pg_type (
// for these OIDs will override the type name of the corresponding type when
// looking up the display name for an OID.
var aliasedOidToName = map[oid.Oid]string{
oid.T_float4: "float4",
oid.T_float8: "float8",
oid.T_int2: "int2",
oid.T_int4: "int4",
oid.T_int8: "int8",
oid.T__int2: "int2[]",
oid.T__int4: "int4[]",
oid.T__int8: "int8[]",
oid.T_float4: "float4",
oid.T_float8: "float8",
oid.T_int2: "int2",
oid.T_int4: "int4",
oid.T_int8: "int8",
oid.T_text: "text",
oid.T_varchar: "varchar",
oid.T_numeric: "numeric",
oid.T__int2: "int2[]",
oid.T__int4: "int4[]",
oid.T__int8: "int8[]",
oid.T__text: "text[]",
}

// typOid is the only OID generation approach that does not use oidHasher, because
Expand Down Expand Up @@ -1789,13 +1811,11 @@ type pgNamespace struct {
}

var (
pgNamespacePublic = &pgNamespace{name: "public"}
pgNamespaceSystem = &pgNamespace{name: "system"}
pgNamespacePGCatalog = &pgNamespace{name: "pg_catalog"}
pgNamespaceInformationSchema = &pgNamespace{name: "information_schema"}

pgNamespaces = []*pgNamespace{
pgNamespacePublic,
pgNamespaceSystem,
pgNamespacePGCatalog,
pgNamespaceInformationSchema,
Expand All @@ -1812,7 +1832,7 @@ func init() {

// pgNamespaceForDB maps a DatabaseDescriptor to its corresponding pgNamespace.
// See the comment above pgNamespace for more details.
func pgNamespaceForDB(db *sqlbase.DatabaseDescriptor) *pgNamespace {
func pgNamespaceForDB(db *sqlbase.DatabaseDescriptor, h oidHasher) *pgNamespace {
switch db.Name {
case sqlbase.SystemDB.Name:
return pgNamespaceSystem
Expand All @@ -1821,6 +1841,6 @@ func pgNamespaceForDB(db *sqlbase.DatabaseDescriptor) *pgNamespace {
case informationSchemaName:
return pgNamespaceInformationSchema
default:
return pgNamespacePublic
return &pgNamespace{name: db.Name, NameStr: parser.NewDName(db.Name), Oid: h.NamespaceOid(db.Name)}
}
}
6 changes: 3 additions & 3 deletions pkg/sql/testdata/builtin_function
Original file line number Diff line number Diff line change
Expand Up @@ -1374,7 +1374,7 @@ VALUES (format_type('anyelement'::regtype, -1)),
(format_type('bool'::regtype, -1)),
(format_type('bytes'::regtype, -1)),
(format_type('date'::regtype, -1)),
(format_type('decimal'::regtype, -1)),
(format_type('numeric'::regtype, -1)),
(format_type('interval'::regtype, -1)),
(format_type('timestamp'::regtype, -1)),
(format_type('timestamptz'::regtype, -1)),
Expand All @@ -1391,7 +1391,7 @@ timestamp with time zone
record

query T
SELECT format_type(oid, -1) FROM pg_type WHERE typname='string' LIMIT 1
SELECT format_type(oid, -1) FROM pg_type WHERE typname='text' LIMIT 1
----
text

Expand All @@ -1411,7 +1411,7 @@ SELECT format_type(oid, -1) FROM pg_type WHERE typname='int8[]' LIMIT 1
bigint[]

query T
SELECT format_type(oid, -1) FROM pg_type WHERE typname='string[]' LIMIT 1
SELECT format_type(oid, -1) FROM pg_type WHERE typname='text[]' LIMIT 1
----
text[]

Expand Down
5 changes: 5 additions & 0 deletions pkg/sql/testdata/information_schema
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ pg_database
pg_depend
pg_description
pg_enum
pg_extension
pg_foreign_server
pg_foreign_table
pg_index
Expand Down Expand Up @@ -275,6 +276,7 @@ pg_indexes
pg_index
pg_foreign_table
pg_foreign_server
pg_extension
pg_enum
pg_description
pg_depend
Expand Down Expand Up @@ -312,6 +314,7 @@ def pg_catalog pg_database SYSTEM VIEW 1
def pg_catalog pg_depend SYSTEM VIEW 1
def pg_catalog pg_description SYSTEM VIEW 1
def pg_catalog pg_enum SYSTEM VIEW 1
def pg_catalog pg_extension SYSTEM VIEW 1
def pg_catalog pg_foreign_server SYSTEM VIEW 1
def pg_catalog pg_foreign_table SYSTEM VIEW 1
def pg_catalog pg_index SYSTEM VIEW 1
Expand Down Expand Up @@ -369,6 +372,7 @@ def pg_catalog pg_database SYSTEM VIEW 1
def pg_catalog pg_depend SYSTEM VIEW 1
def pg_catalog pg_description SYSTEM VIEW 1
def pg_catalog pg_enum SYSTEM VIEW 1
def pg_catalog pg_extension SYSTEM VIEW 1
def pg_catalog pg_foreign_server SYSTEM VIEW 1
def pg_catalog pg_foreign_table SYSTEM VIEW 1
def pg_catalog pg_index SYSTEM VIEW 1
Expand Down Expand Up @@ -417,6 +421,7 @@ def pg_catalog pg_database SYSTEM VIEW 1
def pg_catalog pg_depend SYSTEM VIEW 1
def pg_catalog pg_description SYSTEM VIEW 1
def pg_catalog pg_enum SYSTEM VIEW 1
def pg_catalog pg_extension SYSTEM VIEW 1
def pg_catalog pg_foreign_server SYSTEM VIEW 1
def pg_catalog pg_foreign_table SYSTEM VIEW 1
def pg_catalog pg_index SYSTEM VIEW 1
Expand Down
6 changes: 3 additions & 3 deletions pkg/sql/testdata/join
Original file line number Diff line number Diff line change
Expand Up @@ -740,7 +740,7 @@ SELECT * FROM [EXPLAIN SELECT
AND pkic.relkind = 'i'
AND dep.classid = 'pg_constraint'::regclass::oid
AND dep.refclassid = 'pg_class'::regclass::oid
AND fkn.nspname = 'public'
AND fkn.nspname = 'test'
AND fkc.relname = 'orders'
ORDER BY pkn.nspname,
pkc.relname,
Expand Down Expand Up @@ -858,14 +858,14 @@ SELECT NULL::text AS pktable_cat,
AND pkic.relkind = 'i'
AND dep.classid = 'pg_constraint'::regclass::oid
AND dep.refclassid = 'pg_class'::regclass::oid
AND fkn.nspname = 'public'
AND fkn.nspname = 'test'
AND fkc.relname = 'orders'
ORDER BY pkn.nspname,
pkc.relname,
con.conname,
pos.n
----
NULL public customers id NULL public orders cust 1 3 3 fk_cust_ref_customers primary 7
NULL test customers id NULL test orders cust 1 3 3 fk_cust_ref_customers primary 7


# Tests for filter propagation through joins.
Expand Down
Loading