Skip to content

Commit

Permalink
Merge pull request #614 from dolthub/taylor/schemata
Browse files Browse the repository at this point in the history
Implement information_schema.schemata
  • Loading branch information
tbantle22 authored Aug 14, 2024
2 parents 333fcfc + 98e12f0 commit 28b2ca5
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 33 deletions.
55 changes: 29 additions & 26 deletions server/tables/information_schema/columns_table.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import (
const maxCharacterOctetLength = 1073741824

// typeToNumericPrecision is a map of sqltypes to their respective numeric precision.
var typeToNumericPrecision = map[query.Type]int{
var typeToNumericPrecision = map[query.Type]int32{
sqltypes.Int8: 3,
sqltypes.Int16: 16,
sqltypes.Int32: 32,
Expand All @@ -41,11 +41,14 @@ var typeToNumericPrecision = map[query.Type]int{
sqltypes.Float64: 53,
}

// information_schema columns are one of these 5 types https://www.postgresql.org/docs/current/infoschema-datatypes.html
var cardinal_number = types.Uint32
var character_data = pgtypes.Text
var sql_identifier = pgtypes.VarCharType{Length: 64}
var yes_or_no = pgtypes.VarCharType{Length: 3}
// newColumnsTable creates a new information_schema.COLUMNS table.
func newColumnsTable() *information_schema.ColumnsTable {
return &information_schema.ColumnsTable{
TableName: information_schema.ColumnsTableName,
TableSchema: columnsSchema,
RowIter: columnsRowIter,
}
}

// columnsSchema is the schema for the information_schema.columns table.
var columnsSchema = sql.Schema{
Expand Down Expand Up @@ -126,7 +129,7 @@ func columnsRowIter(ctx *sql.Context, catalog sql.Catalog, allColsWithDefaultVal
// object, database name, and table name.
func getRowFromColumn(ctx *sql.Context, curOrdPos int, col *sql.Column, catName, schName, tblName string) sql.Row {
var (
ordinalPos = uint32(curOrdPos + 1)
ordinalPos = int32(curOrdPos + 1)
nullable = "NO"
isGenerated = "NEVER"
)
Expand All @@ -141,7 +144,7 @@ func getRowFromColumn(ctx *sql.Context, curOrdPos int, col *sql.Column, catName,
}

charName, collName, charMaxLen, charOctetLen := getCharAndCollNamesAndCharMaxAndOctetLens(ctx, col.Type)
numericPrecision, numericPrecisionRadix, numericScale := getColumnPrecisionAndScale(col.Type, col.Name)
numericPrecision, numericPrecisionRadix, numericScale := getColumnPrecisionAndScale(col.Type)
datetimePrecision := getDatetimePrecision(col.Type)

columnDefault := information_schema.GetColumnDefault(ctx, col.Default)
Expand Down Expand Up @@ -226,7 +229,7 @@ func getRowsFromViews(ctx *sql.Context, db information_schema.DbWithNames) ([]sq
db.SchemaName, // table_schema
view.Name, // table_name
"", // column_name
uint32(0), // ordinal_position
int32(0), // ordinal_position
nil, // column_default
"YES", // is_nullable
nil, // data_type
Expand Down Expand Up @@ -319,25 +322,25 @@ func getDataAndUdtType(colType sql.Type, colName string) (string, string) {

// getColumnPrecisionAndScale returns the precision or a number of postgres type. For non-numeric or decimal types this
// function should return nil,nil.
func getColumnPrecisionAndScale(colType sql.Type, name string) (interface{}, interface{}, interface{}) {
func getColumnPrecisionAndScale(colType sql.Type) (interface{}, interface{}, interface{}) {
dgt, ok := colType.(pgtypes.DoltgresType)
if ok {
switch t := dgt.(type) {
// TODO: BitType
case pgtypes.Float32Type, pgtypes.Float64Type:
return typeToNumericPrecision[colType.Type()], 2, nil
return typeToNumericPrecision[colType.Type()], int32(2), nil
case pgtypes.Int16Type, pgtypes.Int32Type, pgtypes.Int64Type:
return typeToNumericPrecision[colType.Type()], 2, 0
return typeToNumericPrecision[colType.Type()], int32(2), int32(0)
case pgtypes.NumericType:
var precision interface{}
var scale interface{}
if t.Precision >= 0 {
precision = int(t.Precision)
precision = int32(t.Precision)
}
if t.Scale >= 0 {
scale = int(t.Scale)
scale = int32(t.Scale)
}
return precision, 10, scale
return precision, int32(10), scale
default:
return nil, nil, nil
}
Expand All @@ -360,27 +363,27 @@ func getCharAndCollNamesAndCharMaxAndOctetLens(ctx *sql.Context, colType sql.Typ
collName = colColl.Name()
charName = colColl.CharacterSet().String()
if types.IsEnum(colType) || types.IsSet(colType) {
charOctetLen = int64(colType.MaxTextResponseByteLength(ctx))
charMaxLen = int64(colType.MaxTextResponseByteLength(ctx)) / colColl.CharacterSet().MaxLength()
charOctetLen = int32(colType.MaxTextResponseByteLength(ctx))
charMaxLen = int32(colType.MaxTextResponseByteLength(ctx)) / int32(colColl.CharacterSet().MaxLength())
}
}

switch t := colType.(type) {
case pgtypes.TextType:
charOctetLen = maxCharacterOctetLength
charOctetLen = int32(maxCharacterOctetLength)
case pgtypes.VarCharType:
if t.IsUnbounded() {
charOctetLen = maxCharacterOctetLength
charOctetLen = int32(maxCharacterOctetLength)
} else {
charOctetLen = int64(t.Length) * 4
charMaxLen = t.Length
charOctetLen = int32(t.Length) * 4
charMaxLen = int32(t.Length)
}
case pgtypes.CharType:
if t.IsUnbounded() {
charOctetLen = maxCharacterOctetLength
charOctetLen = int32(maxCharacterOctetLength)
} else {
charOctetLen = int64(t.Length) * 4
charMaxLen = t.Length
charOctetLen = int32(t.Length) * 4
charMaxLen = int32(t.Length)
}
}

Expand All @@ -391,10 +394,10 @@ func getDatetimePrecision(colType sql.Type) interface{} {
if dgType, ok := colType.(pgtypes.DoltgresType); ok {
switch dgType.(type) {
case pgtypes.DateType:
return 0
return int32(0)
case pgtypes.TimeType, pgtypes.TimeTZType, pgtypes.TimestampType, pgtypes.TimestampTZType:
// TODO: TIME length not yet supported
return 6
return int32(6)
default:
return nil
}
Expand Down
9 changes: 2 additions & 7 deletions server/tables/information_schema/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,6 @@ import (

// Init handles initialization of all Postgres-specific and Doltgres-specific information_schema tables.
func Init() {
information_schema.NewColumnsTable = func() *information_schema.ColumnsTable {
return &information_schema.ColumnsTable{
TableName: information_schema.ColumnsTableName,
TableSchema: columnsSchema,
RowIter: columnsRowIter,
}
}
information_schema.NewColumnsTable = newColumnsTable
information_schema.NewSchemataTable = newSchemataTable
}
64 changes: 64 additions & 0 deletions server/tables/information_schema/schemata_table.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Copyright 2024 Dolthub, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package information_schema

import (
"github.com/dolthub/go-mysql-server/sql"
"github.com/dolthub/go-mysql-server/sql/information_schema"
)

// newSchemataTable creates a new information_schema.SCHEMATA table.
func newSchemataTable() *information_schema.InformationSchemaTable {
return &information_schema.InformationSchemaTable{
TableName: information_schema.SchemataTableName,
TableSchema: schemataSchema,
Reader: schemataRowIter,
}
}

// schemataSchema is the schema for the information_schema.SCHEMATA table.
var schemataSchema = sql.Schema{
{Name: "catalog_name", Type: sql_identifier, Default: nil, Nullable: true, Source: information_schema.SchemataTableName},
{Name: "schema_name", Type: sql_identifier, Default: nil, Nullable: true, Source: information_schema.SchemataTableName},
{Name: "schema_owner", Type: sql_identifier, Default: nil, Nullable: true, Source: information_schema.SchemataTableName},
{Name: "default_character_set_catalog", Type: sql_identifier, Default: nil, Nullable: true, Source: information_schema.SchemataTableName},
{Name: "default_character_set_schema", Type: sql_identifier, Default: nil, Nullable: true, Source: information_schema.SchemataTableName},
{Name: "default_character_set_name", Type: sql_identifier, Default: nil, Nullable: true, Source: information_schema.SchemataTableName},
{Name: "sql_path", Type: character_data, Default: nil, Nullable: true, Source: information_schema.SchemataTableName},
}

// schemataRowIter implements the sql.RowIter for the information_schema.SCHEMATA table.
func schemataRowIter(ctx *sql.Context, c sql.Catalog) (sql.RowIter, error) {
dbs, err := information_schema.AllDatabases(ctx, c, false)
if err != nil {
return nil, err
}

var rows []sql.Row

for _, db := range dbs {
rows = append(rows, sql.Row{
db.CatalogName, // catalog_name
db.SchemaName, // schema_name
"", // schema_owner
nil, // default_character_set_catalog
nil, // default_character_set_schema
nil, // default_character_set_name
nil, // sql_path
})
}

return sql.RowsToRowIter(rows...), nil
}
25 changes: 25 additions & 0 deletions server/tables/information_schema/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright 2024 Dolthub, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package information_schema

import (
pgtypes "github.com/dolthub/doltgresql/server/types"
)

// information_schema columns are one of these 5 types https://www.postgresql.org/docs/current/infoschema-datatypes.html
var cardinal_number = pgtypes.Int32
var character_data = pgtypes.Text
var sql_identifier = pgtypes.VarCharType{Length: 64}
var yes_or_no = pgtypes.VarCharType{Length: 3}
9 changes: 9 additions & 0 deletions testing/go/information_schema_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,15 @@ func TestInfoSchemaSchemata(t *testing.T) {
{"newdb", "test_schema"},
},
},
{
Query: `SELECT * FROM information_schema.schemata order by schema_name;`,
Expected: []sql.Row{
{"newdb", "information_schema", "", nil, nil, nil, nil},
{"newdb", "pg_catalog", "", nil, nil, nil, nil},
{"newdb", "public", "", nil, nil, nil, nil},
{"newdb", "test_schema", "", nil, nil, nil, nil},
},
},
},
},
})
Expand Down

0 comments on commit 28b2ca5

Please sign in to comment.