github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/pg_extension.go (about) 1 // Copyright 2017 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 package sql 12 13 import ( 14 "context" 15 "strings" 16 17 "github.com/cockroachdb/cockroach/pkg/geo/geopb" 18 "github.com/cockroachdb/cockroach/pkg/sql/sem/tree" 19 "github.com/cockroachdb/cockroach/pkg/sql/sessiondata" 20 "github.com/cockroachdb/cockroach/pkg/sql/sqlbase" 21 "github.com/cockroachdb/cockroach/pkg/sql/types" 22 "github.com/cockroachdb/errors" 23 ) 24 25 // pgExtension is virtual schema which contains virtual tables and/or views 26 // which are used by postgres extensions. Postgres extensions typically install 27 // these tables and views on the public schema, but we instead do it in 28 // our own defined virtual table / schema. 29 var pgExtension = virtualSchema{ 30 name: sessiondata.PgExtensionSchemaName, 31 tableDefs: map[sqlbase.ID]virtualSchemaDef{ 32 sqlbase.PgExtensionGeographyColumnsTableID: pgExtensionGeographyColumnsTable, 33 sqlbase.PgExtensionGeometryColumnsTableID: pgExtensionGeometryColumnsTable, 34 sqlbase.PgExtensionSpatialRefSysTableID: pgExtensionSpatialRefSysTable, 35 }, 36 validWithNoDatabaseContext: false, 37 } 38 39 func postgisColumnsTablePopulator( 40 matchingFamily types.Family, 41 ) func(context.Context, *planner, *DatabaseDescriptor, func(...tree.Datum) error) error { 42 return func(ctx context.Context, p *planner, dbContext *DatabaseDescriptor, addRow func(...tree.Datum) error) error { 43 return forEachTableDesc( 44 ctx, 45 p, 46 dbContext, 47 hideVirtual, 48 func(db *sqlbase.DatabaseDescriptor, scName string, table *sqlbase.TableDescriptor) error { 49 if !table.IsPhysicalTable() { 50 return nil 51 } 52 if p.CheckAnyPrivilege(ctx, table) != nil { 53 return nil 54 } 55 for _, colDesc := range table.Columns { 56 if colDesc.Type.Family() != matchingFamily { 57 continue 58 } 59 m, err := colDesc.Type.GeoMetadata() 60 if err != nil { 61 return err 62 } 63 64 var datumNDims tree.Datum 65 switch m.Shape { 66 case geopb.Shape_Point, geopb.Shape_LineString, geopb.Shape_Polygon, 67 geopb.Shape_MultiPoint, geopb.Shape_MultiLineString, geopb.Shape_MultiPolygon, 68 geopb.Shape_GeometryCollection: 69 datumNDims = tree.NewDInt(2) 70 case geopb.Shape_Geometry, geopb.Shape_Unset: 71 // For geometry_columns, the query in PostGIS COALESCES the value to 2. 72 // Otherwise, the value is NULL. 73 if matchingFamily == types.GeometryFamily { 74 datumNDims = tree.NewDInt(2) 75 } else { 76 datumNDims = tree.DNull 77 } 78 } 79 80 shapeName := m.Shape.String() 81 if m.Shape == geopb.Shape_Unset { 82 shapeName = geopb.Shape_Geometry.String() 83 } 84 85 if err := addRow( 86 tree.NewDString(db.GetName()), 87 tree.NewDString(scName), 88 tree.NewDString(table.GetName()), 89 tree.NewDString(colDesc.Name), 90 datumNDims, 91 tree.NewDInt(tree.DInt(m.SRID)), 92 tree.NewDString(strings.ToUpper(shapeName)), 93 ); err != nil { 94 return err 95 } 96 } 97 return nil 98 }, 99 ) 100 } 101 } 102 103 var pgExtensionGeographyColumnsTable = virtualSchemaTable{ 104 comment: `Shows all defined geography columns. Matches PostGIS' geography_columns functionality.`, 105 schema: ` 106 CREATE TABLE pg_extension.geography_columns ( 107 f_table_catalog name, 108 f_table_schema name, 109 f_table_name name, 110 f_geography_column name, 111 coord_dimension integer, 112 srid integer, 113 type text 114 )`, 115 populate: postgisColumnsTablePopulator(types.GeographyFamily), 116 } 117 118 var pgExtensionGeometryColumnsTable = virtualSchemaTable{ 119 comment: `Shows all defined geometry columns. Matches PostGIS' geometry_columns functionality.`, 120 schema: ` 121 CREATE TABLE pg_extension.geometry_columns ( 122 f_table_catalog name, 123 f_table_schema name, 124 f_table_name name, 125 f_geometry_column name, 126 coord_dimension integer, 127 srid integer, 128 type text 129 )`, 130 populate: postgisColumnsTablePopulator(types.GeometryFamily), 131 } 132 133 var pgExtensionSpatialRefSysTable = virtualSchemaTable{ 134 comment: `Shows all defined Spatial Reference Identifiers (SRIDs). Matches PostGIS' spatial_ref_sys table.`, 135 schema: ` 136 CREATE TABLE pg_extension.spatial_ref_sys ( 137 srid integer, 138 auth_name varchar(256), 139 auth_srid integer, 140 srtext varchar(2048), 141 proj4text varchar(2048) 142 )`, 143 generator: func(ctx context.Context, p *planner, db *DatabaseDescriptor) (virtualTableGenerator, cleanupFunc, error) { 144 return nil, func() {}, errors.Newf("not yet implemented") 145 }, 146 }