diff --git a/go.mod b/go.mod index 7cf60ea2dc..5fdac329bb 100644 --- a/go.mod +++ b/go.mod @@ -202,3 +202,5 @@ require ( gopkg.in/go-jose/go-jose.v2 v2.6.3 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) + +replace github.com/dolthub/dolt/go => github.com/codeaucafe/dolt/go v0.0.0-20260112072202-5155e81a0941 diff --git a/go.sum b/go.sum index 659cd46fc2..358d8c525f 100644 --- a/go.sum +++ b/go.sum @@ -201,6 +201,8 @@ github.com/cockroachdb/redact v1.0.6 h1:W34uRRyNR4dlZFd0MibhNELsZSgMkl52uRV/tA1x github.com/cockroachdb/redact v1.0.6/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= github.com/cockroachdb/sentry-go v0.6.1-cockroachdb.2 h1:IKgmqgMQlVJIZj19CdocBeSfSaiCbEBZGKODaixqtHM= github.com/cockroachdb/sentry-go v0.6.1-cockroachdb.2/go.mod h1:8BT+cPK6xvFOcRlk0R8eg+OTkcqI6baNH4xAkpiYVvQ= +github.com/codeaucafe/dolt/go v0.0.0-20260112072202-5155e81a0941 h1:97xLoYXXXgsPUk0EpUF97VxISn16kEWwnpld+X2Srjc= +github.com/codeaucafe/dolt/go v0.0.0-20260112072202-5155e81a0941/go.mod h1:JqA5M1sKCGWpeXiLaap4JUGRloJ8KGVec6C6A2K6ZrY= github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM= github.com/colinmarc/hdfs/v2 v2.1.1/go.mod h1:M3x+k8UKKmxtFu++uAZ0OtDU8jR3jnaZIAc6yK4Ue0c= github.com/containerd/continuity v0.0.0-20190827140505-75bee3e2ccb6/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= @@ -228,8 +230,6 @@ github.com/dolthub/aws-sdk-go-ini-parser v0.0.0-20250305001723-2821c37f6c12 h1:I github.com/dolthub/aws-sdk-go-ini-parser v0.0.0-20250305001723-2821c37f6c12/go.mod h1:rN7X8BHwkjPcfMQQ2QTAq/xM3leUSGLfb+1Js7Y6TVo= github.com/dolthub/dolt-mcp v0.2.2 h1:bpROmam74n95uU4EA3BpOIVlTDT0pzeFMBwe/YRq2mI= github.com/dolthub/dolt-mcp v0.2.2/go.mod h1:S++DJ4QWTAXq+0TNzFa7Oq3IhoT456DJHwAINFAHgDQ= -github.com/dolthub/dolt/go v0.40.5-0.20260108000424-ed62ee89285b h1:2DTDLbZwltHrge1NSe8EWkv9f+oCs4QCAE1OVVEF1gw= -github.com/dolthub/dolt/go v0.40.5-0.20260108000424-ed62ee89285b/go.mod h1:z5e06zwixH1wM1gOwBsp4yMllZyZ8PnmXKdnjTf1Vcs= github.com/dolthub/eventsapi_schema v0.0.0-20250915094920-eadfd39051ca h1:BGFz/0OlKIuC6qHIZQbvPapFvdAJkeEyGXWVgL5clmE= github.com/dolthub/eventsapi_schema v0.0.0-20250915094920-eadfd39051ca/go.mod h1:CoDLfgPqHyBtth0Cp+fi/CmC4R81zJNX4wPjShdZ+Bw= github.com/dolthub/flatbuffers/v23 v23.3.3-dh.2 h1:u3PMzfF8RkKd3lB9pZ2bfn0qEG+1Gms9599cr0REMww= diff --git a/server/tables/dtables/init.go b/server/tables/dtables/init.go index ac99bfe963..fbc418653c 100644 --- a/server/tables/dtables/init.go +++ b/server/tables/dtables/init.go @@ -26,6 +26,7 @@ import ( // Init handles initialization of all Postgres-specific and Doltgres-specific Dolt system tables. func Init() { adapters.DoltTableAdapterRegistry.AddAdapter(doltdb.StatusTableName, DoltgresDoltStatusTableAdapter{}, DoltgresDoltStatusTableName) + adapters.DoltTableAdapterRegistry.AddAdapter(doltdb.StatusIgnoredTableName, DoltgresDoltStatusIgnoredTableAdapter{}, DoltgresDoltStatusIgnoredTableName) // Table names doltdb.GetBranchesTableName = getBranchesTableName diff --git a/server/tables/dtables/status_ignored.go b/server/tables/dtables/status_ignored.go new file mode 100644 index 0000000000..fc44b5494b --- /dev/null +++ b/server/tables/dtables/status_ignored.go @@ -0,0 +1,145 @@ +// Copyright 2026 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 dtables + +import ( + "fmt" + + "github.com/dolthub/dolt/go/libraries/doltcore/doltdb" + "github.com/dolthub/dolt/go/libraries/doltcore/env" + "github.com/dolthub/dolt/go/libraries/doltcore/sqle/adapters" + doltdtables "github.com/dolthub/dolt/go/libraries/doltcore/sqle/dtables" + "github.com/dolthub/go-mysql-server/sql" + + pgtypes "github.com/dolthub/doltgresql/server/types" +) + +// DoltgresDoltStatusIgnoredTableAdapter adapts the [doltdtables.StatusIgnoredTable] into a Doltgres-compatible version. +// +// DoltgresDoltStatusIgnoredTableAdapter implements the [adapters.TableAdapter] interface. +type DoltgresDoltStatusIgnoredTableAdapter struct{} + +var _ adapters.TableAdapter = DoltgresDoltStatusIgnoredTableAdapter{} + +// NewTable returns a new [sql.Table] for Doltgres' version of [doltdtables.StatusIgnoredTable]. +func (a DoltgresDoltStatusIgnoredTableAdapter) NewTable(ctx *sql.Context, tableName string, ddb *doltdb.DoltDB, ws *doltdb.WorkingSet, rp env.RootsProvider[*sql.Context]) sql.Table { + doltTable := doltdtables.NewStatusIgnoredTableWithNoAdapter(ctx, tableName, ddb, ws, rp) + return &doltgresDoltStatusIgnoredTable{ + srcDoltStatusIgnored: doltTable.(*doltdtables.StatusIgnoredTable), + } +} + +// TableName returns the table name for Doltgres' version of [doltdtables.StatusIgnoredTable]. +func (a DoltgresDoltStatusIgnoredTableAdapter) TableName() string { + return DoltgresDoltStatusIgnoredTableName +} + +// DoltgresDoltStatusIgnoredTableName is the name of Dolt's status_ignored table following Doltgres' naming conventions. +const DoltgresDoltStatusIgnoredTableName = "status_ignored" + +// doltgresDoltStatusIgnoredTable translates the [doltdtables.StatusIgnoredTable] into a Doltgres-compatible version. +// +// doltgresDoltStatusIgnoredTable implements the [sql.Table] and [sql.StatisticsTable] interfaces. +type doltgresDoltStatusIgnoredTable struct { + srcDoltStatusIgnored *doltdtables.StatusIgnoredTable +} + +var _ sql.Table = (*doltgresDoltStatusIgnoredTable)(nil) +var _ sql.StatisticsTable = (*doltgresDoltStatusIgnoredTable)(nil) + +// Name returns the name of Doltgres' version of the Dolt status_ignored table. +func (w *doltgresDoltStatusIgnoredTable) Name() string { + return w.srcDoltStatusIgnored.Name() +} + +// Schema returns the schema for Doltgres' version of the Dolt status_ignored table. +func (w *doltgresDoltStatusIgnoredTable) Schema() sql.Schema { + return []*sql.Column{ + {Name: "table_name", Type: pgtypes.Text, Source: DoltgresDoltStatusIgnoredTableName, PrimaryKey: true, Nullable: false}, + {Name: "staged", Type: pgtypes.Bool, Source: DoltgresDoltStatusIgnoredTableName, PrimaryKey: true, Nullable: false}, + {Name: "status", Type: pgtypes.Text, Source: DoltgresDoltStatusIgnoredTableName, PrimaryKey: true, Nullable: false}, + {Name: "ignored", Type: pgtypes.Bool, Source: DoltgresDoltStatusIgnoredTableName, PrimaryKey: false, Nullable: false}, + } +} + +// String returns the string representation of [doltdtables.StatusIgnoredTable]. +func (w *doltgresDoltStatusIgnoredTable) String() string { + return w.srcDoltStatusIgnored.String() +} + +// Collation returns the [sql.CollationID] from [doltdtables.StatusIgnoredTable]. +func (w *doltgresDoltStatusIgnoredTable) Collation() sql.CollationID { + return w.srcDoltStatusIgnored.Collation() +} + +// Partitions returns a [sql.PartitionIter] on the partitions of [doltdtables.StatusIgnoredTable]. +func (w *doltgresDoltStatusIgnoredTable) Partitions(ctx *sql.Context) (sql.PartitionIter, error) { + return w.srcDoltStatusIgnored.Partitions(ctx) +} + +// PartitionRows returns a wrapped [sql.RowIter] for the rows in |partition| from +// [doltdtables.StatusIgnoredTable.PartitionRows] to later apply column transformations that match Doltgres' version of the +// Dolt status_ignored table schema. +func (w *doltgresDoltStatusIgnoredTable) PartitionRows(ctx *sql.Context, partition sql.Partition) (sql.RowIter, error) { + iter, err := w.srcDoltStatusIgnored.PartitionRows(ctx, partition) + if err != nil { + return nil, err + } + return &doltgresDoltStatusIgnoredRowIter{w, iter}, nil +} + +// DataLength returns the length of the data in bytes from [doltdtables.StatusIgnoredTable]. +func (w *doltgresDoltStatusIgnoredTable) DataLength(ctx *sql.Context) (uint64, error) { + return w.srcDoltStatusIgnored.DataLength(ctx) +} + +// RowCount returns exact (true) or estimate (false) number of rows from [doltdtables.StatusIgnoredTable]. +func (w *doltgresDoltStatusIgnoredTable) RowCount(ctx *sql.Context) (uint64, bool, error) { + return w.srcDoltStatusIgnored.RowCount(ctx) +} + +// doltgresDoltStatusIgnoredRowIter wraps [doltdtables.StatusIgnoredTable] [sql.RowIter] and applies transformations before returning +// its rows to make sure they're compatible with Doltgres' version of Dolt's status_ignored table. +type doltgresDoltStatusIgnoredRowIter struct { + doltStatusIgnoredTable sql.Table + rowIter sql.RowIter +} + +var _ sql.RowIter = (*doltgresDoltStatusIgnoredRowIter)(nil) + +// Next converts the 'staged' column from [doltdtables.StatusIgnoredTable.Schema] from byte into bool since, +// unlike the MySQL wire protocol, Doltgres has a real bool type. +func (i *doltgresDoltStatusIgnoredRowIter) Next(ctx *sql.Context) (sql.Row, error) { + row, err := i.rowIter.Next(ctx) + if err != nil { + return nil, err + } + + // Dolt uses byte to avoid MySQL wire protocol ambiguity on tinyint(1) and bool. + // See: https://github.com/dolthub/dolt/pull/10117 + stagedIndex := i.doltStatusIgnoredTable.Schema().IndexOfColName("staged") + stagedVal, ok := row[stagedIndex].(byte) + if !ok { + return nil, fmt.Errorf("expected staged column at index %d to be byte, got %T", stagedIndex, row[stagedIndex]) + } + row[stagedIndex] = stagedVal != 0 + + return row, nil +} + +// Close closes the wrapped [doltdtables.StatusIgnoredTable] [sql.RowIter]. +func (i *doltgresDoltStatusIgnoredRowIter) Close(ctx *sql.Context) error { + return i.rowIter.Close(ctx) +} diff --git a/testing/go/pgcatalog_test.go b/testing/go/pgcatalog_test.go index 33e7ef75fd..d6ba3b5a03 100644 --- a/testing/go/pgcatalog_test.go +++ b/testing/go/pgcatalog_test.go @@ -4318,6 +4318,7 @@ func TestPgTables(t *testing.T) { {"public", "dolt_remotes"}, {"public", "dolt_schema_conflicts"}, {"public", "dolt_status"}, + {"public", "dolt_status_ignored"}, {"public", "dolt_tags"}, {"public", "dolt_workspace_t1"}, {"public", "dolt_workspace_t2"}, @@ -4341,6 +4342,7 @@ func TestPgTables(t *testing.T) { {"dolt", "remote_branches"}, {"dolt", "remotes"}, {"dolt", "status"}, + {"dolt", "status_ignored"}, }, }, }, @@ -5698,6 +5700,7 @@ func TestSystemTablesInPgcatalog(t *testing.T) { {"dolt", "remote_branches", "postgres", nil, "f", "f", "f", "f"}, {"dolt", "remotes", "postgres", nil, "f", "f", "f", "f"}, {"dolt", "status", "postgres", nil, "f", "f", "f", "f"}, + {"dolt", "status_ignored", "postgres", nil, "f", "f", "f", "f"}, {"public", "dolt_branches", "postgres", nil, "f", "f", "f", "f"}, {"public", "dolt_column_diff", "postgres", nil, "f", "f", "f", "f"}, {"public", "dolt_commit_ancestors", "postgres", nil, "f", "f", "f", "f"}, @@ -5711,6 +5714,7 @@ func TestSystemTablesInPgcatalog(t *testing.T) { {"public", "dolt_remotes", "postgres", nil, "f", "f", "f", "f"}, {"public", "dolt_schema_conflicts", "postgres", nil, "f", "f", "f", "f"}, {"public", "dolt_status", "postgres", nil, "f", "f", "f", "f"}, + {"public", "dolt_status_ignored", "postgres", nil, "f", "f", "f", "f"}, {"public", "dolt_tags", "postgres", nil, "f", "f", "f", "f"}, {"s1", "dolt_branches", "postgres", nil, "f", "f", "f", "f"}, {"s1", "dolt_column_diff", "postgres", nil, "f", "f", "f", "f"}, @@ -5730,6 +5734,7 @@ func TestSystemTablesInPgcatalog(t *testing.T) { {"s1", "dolt_remotes", "postgres", nil, "f", "f", "f", "f"}, {"s1", "dolt_schema_conflicts", "postgres", nil, "f", "f", "f", "f"}, {"s1", "dolt_status", "postgres", nil, "f", "f", "f", "f"}, + {"s1", "dolt_status_ignored", "postgres", nil, "f", "f", "f", "f"}, {"s1", "dolt_tags", "postgres", nil, "f", "f", "f", "f"}, {"s1", "dolt_workspace_t1", "postgres", nil, "f", "f", "f", "f"}, {"s1", "t1", "postgres", nil, "t", "f", "f", "f"}, @@ -5761,6 +5766,7 @@ func TestSystemTablesInPgcatalog(t *testing.T) { {341706375, "dolt_remotes", 2200, "r"}, {3210116770, "dolt_schema_conflicts", 2200, "r"}, {1060579466, "dolt_status", 2200, "r"}, + {1523309269, "dolt_status_ignored", 2200, "r"}, {1807684176, "dolt_tags", 2200, "r"}, {1763579892, "dolt_branches", 1634633383, "r"}, {1212681264, "dolt_column_diff", 1634633383, "r"}, @@ -5780,6 +5786,7 @@ func TestSystemTablesInPgcatalog(t *testing.T) { {373092098, "dolt_remotes", 1634633383, "r"}, {225426095, "dolt_schema_conflicts", 1634633383, "r"}, {3554775706, "dolt_status", 1634633383, "r"}, + {1227149778, "dolt_status_ignored", 1634633383, "r"}, {3246414078, "dolt_tags", 1634633383, "r"}, {1640933374, "dolt_workspace_t1", 1634633383, "r"}, {2849341124, "t1", 1634633383, "r"}, @@ -5797,6 +5804,7 @@ func TestSystemTablesInPgcatalog(t *testing.T) { {148630507, "remote_branches", 1882653564, "r"}, {1670572237, "remotes", 1882653564, "r"}, {3431637196, "status", 1882653564, "r"}, + {3418072419, "status_ignored", 1882653564, "r"}, }, }, }, @@ -5921,6 +5929,10 @@ func TestSystemTablesInPgcatalog(t *testing.T) { {1212681264, "diff_type", 25, 8, "t", "f", "f"}, {1218627310, "table", 25, 1, "t", "f", "f"}, {1218627310, "num_conflicts", 20, 2, "t", "f", "f"}, + {1227149778, "table_name", 25, 1, "t", "f", "f"}, + {1227149778, "staged", 16, 2, "t", "f", "f"}, + {1227149778, "status", 25, 3, "t", "f", "f"}, + {1227149778, "ignored", 16, 4, "t", "f", "f"}, {1322753784, "table", 25, 1, "t", "f", "f"}, {1322753784, "num_violations", 20, 2, "t", "f", "f"}, {1384122262, "name", 25, 1, "t", "f", "f"}, @@ -5928,6 +5940,10 @@ func TestSystemTablesInPgcatalog(t *testing.T) { {1384122262, "branch", 25, 3, "t", "f", "f"}, {1384122262, "hash", 25, 4, "t", "f", "f"}, {1384122262, "commit_message", 25, 5, "f", "f", "f"}, + {1523309269, "table_name", 25, 1, "t", "f", "f"}, + {1523309269, "staged", 16, 2, "t", "f", "f"}, + {1523309269, "status", 25, 3, "t", "f", "f"}, + {1523309269, "ignored", 16, 4, "t", "f", "f"}, {1555944102, "commit_hash", 25, 1, "t", "f", "f"}, {1555944102, "parent_hash", 25, 2, "t", "f", "f"}, {1555944102, "parent_index", 23, 3, "t", "f", "f"}, @@ -6023,6 +6039,10 @@ func TestSystemTablesInPgcatalog(t *testing.T) { {3390577184, "pk", 23, 3, "t", "f", "f"}, {3390577184, "v1", 23, 4, "f", "f", "f"}, {3390577184, "violation_info", 114, 5, "f", "f", "f"}, + {3418072419, "table_name", 25, 1, "t", "f", "f"}, + {3418072419, "staged", 16, 2, "t", "f", "f"}, + {3418072419, "status", 25, 3, "t", "f", "f"}, + {3418072419, "ignored", 16, 4, "t", "f", "f"}, {3422698383, "pk", 23, 1, "t", "f", "f"}, {3422698383, "v1", 23, 2, "f", "f", "f"}, {3422698383, "commit_hash", 25, 3, "t", "f", "f"}, diff --git a/testing/go/sequences_test.go b/testing/go/sequences_test.go index 4bf6b1583a..7d801a64e0 100644 --- a/testing/go/sequences_test.go +++ b/testing/go/sequences_test.go @@ -1234,6 +1234,7 @@ ORDER BY 1,2;`, {"public", "dolt_remotes", "table", "postgres"}, {"public", "dolt_schema_conflicts", "table", "postgres"}, {"public", "dolt_status", "table", "postgres"}, + {"public", "dolt_status_ignored", "table", "postgres"}, {"public", "dolt_tags", "table", "postgres"}, {"public", "dolt_workspace_call", "table", "postgres"}, {"public", "dolt_workspace_user", "table", "postgres"},