Files
2026-07-13 12:32:25 +08:00

151 lines
4.6 KiB
Go

// 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 pgcatalog
import (
"io"
"github.com/dolthub/go-mysql-server/sql"
"github.com/dolthub/doltgresql/core/id"
"github.com/dolthub/doltgresql/core/sequences"
"github.com/dolthub/doltgresql/server/functions"
"github.com/dolthub/doltgresql/server/tables"
pgtypes "github.com/dolthub/doltgresql/server/types"
)
// PgSequenceName is a constant to the pg_sequence name.
const PgSequenceName = "pg_sequence"
// InitPgSequence handles registration of the pg_sequence handler.
func InitPgSequence() {
tables.AddHandler(PgCatalogName, PgSequenceName, PgSequenceHandler{})
}
// PgSequenceHandler is the handler for the pg_sequence table.
type PgSequenceHandler struct{}
// pgSequence represents a row in the pg_sequence table and pg_sequences view
type pgSequence struct {
sequence *sequences.Sequence
schema string
oid id.Id
}
var _ tables.Handler = PgSequenceHandler{}
// Name implements the interface tables.Handler.
func (p PgSequenceHandler) Name() string {
return PgSequenceName
}
// RowIter implements the interface tables.Handler.
func (p PgSequenceHandler) RowIter(ctx *sql.Context, _ sql.Partition) (sql.RowIter, error) {
// Use cached data from this process if it exists
pgCatalogCache, err := getPgCatalogCache(ctx)
if err != nil {
return nil, err
}
if pgCatalogCache.sequences == nil {
err = cachePgSequences(ctx, pgCatalogCache)
if err != nil {
return nil, err
}
}
return &pgSequenceRowIter{
sequences: pgCatalogCache.sequences,
idx: 0,
}, nil
}
func cachePgSequences(ctx *sql.Context, pgCatalogCache *pgCatalogCache) error {
var sequences []*pgSequence
err := functions.IterateCurrentDatabase(ctx, functions.Callbacks{
Sequence: func(ctx *sql.Context, schema functions.ItemSchema, sequence functions.ItemSequence) (cont bool, err error) {
pgSeq := &pgSequence{
sequence: sequence.Item,
schema: schema.Item.SchemaName(),
oid: sequence.OID.AsId(),
}
sequences = append(sequences, pgSeq)
return true, nil
},
})
if err != nil {
return err
}
pgCatalogCache.sequences = sequences
return nil
}
// PkSchema implements the interface tables.Handler.
func (p PgSequenceHandler) PkSchema() sql.PrimaryKeySchema {
return sql.PrimaryKeySchema{
Schema: pgSequenceSchema,
PkOrdinals: nil,
}
}
// pgSequenceSchema is the schema for pg_sequence.
var pgSequenceSchema = sql.Schema{
{Name: "seqrelid", Type: pgtypes.Oid, Default: nil, Nullable: false, Source: PgSequenceName},
{Name: "seqtypid", Type: pgtypes.Oid, Default: nil, Nullable: false, Source: PgSequenceName},
{Name: "seqstart", Type: pgtypes.Int64, Default: nil, Nullable: false, Source: PgSequenceName},
{Name: "seqincrement", Type: pgtypes.Int64, Default: nil, Nullable: false, Source: PgSequenceName},
{Name: "seqmax", Type: pgtypes.Int64, Default: nil, Nullable: false, Source: PgSequenceName},
{Name: "seqmin", Type: pgtypes.Int64, Default: nil, Nullable: false, Source: PgSequenceName},
{Name: "seqcache", Type: pgtypes.Int64, Default: nil, Nullable: false, Source: PgSequenceName},
{Name: "seqcycle", Type: pgtypes.Bool, Default: nil, Nullable: false, Source: PgSequenceName},
}
// pgSequenceRowIter is the sql.RowIter for the pg_sequence table.
type pgSequenceRowIter struct {
sequences []*pgSequence
idx int
}
var _ sql.RowIter = (*pgSequenceRowIter)(nil)
// Next implements the interface sql.RowIter.
func (iter *pgSequenceRowIter) Next(ctx *sql.Context) (sql.Row, error) {
if iter.idx >= len(iter.sequences) {
return nil, io.EOF
}
iter.idx++
sequence := iter.sequences[iter.idx-1].sequence
oid := iter.sequences[iter.idx-1].oid
return sql.Row{
oid, // seqrelid
sequence.DataTypeID.AsId(), // seqtypid
int64(sequence.Start), // seqstart
int64(sequence.Increment), // seqincrement
int64(sequence.Maximum), // seqmax
int64(sequence.Minimum), // seqmin
int64(sequence.Cache), // seqcache
bool(sequence.Cycle), // seqcycle
}, nil
}
// Close implements the interface sql.RowIter.
func (iter *pgSequenceRowIter) Close(ctx *sql.Context) error {
return nil
}