Skip to content

Commit 92e7fca

Browse files
authored
Merge pull request #9250 from dolthub/tim/commit-order
Implement commit_order in dolt_log system table and table function
2 parents 27e2e53 + 92991fb commit 92e7fca

File tree

9 files changed

+190
-8
lines changed

9 files changed

+190
-8
lines changed

go/cmd/dolt/commands/utils.go

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -711,14 +711,30 @@ func getCommitInfoWithOptions(queryist cli.Queryist, sqlCtx *sql.Context, ref st
711711
return nil, fmt.Errorf("error parsing timestamp '%s': %v", row[3], err)
712712
}
713713
message := row[4].(string)
714-
parent := row[5].(string)
715-
height := uint64(len(rows))
714+
715+
var commitOrder uint64
716+
switch v := row[5].(type) {
717+
case uint64:
718+
commitOrder = v
719+
case string:
720+
var err error
721+
commitOrder, err = strconv.ParseUint(v, 10, 64)
722+
if err != nil {
723+
return nil, fmt.Errorf("error parsing commit_order '%s': %v", v, err)
724+
}
725+
default:
726+
return nil, fmt.Errorf("unexpected type for commit_order: %T", v)
727+
}
728+
729+
parent := row[6].(string)
730+
height := commitOrder
716731

717732
isHead := commitHash == hashOfHead
718733

719734
var signature string
720-
if len(row) > 7 {
721-
signature = row[7].(string)
735+
if opts.showSignature {
736+
// Signature is always the last column when present
737+
signature = row[len(row)-1].(string)
722738
}
723739

724740
localBranchesForHash, err := getBranchesForHash(queryist, sqlCtx, commitHash, true)

go/libraries/doltcore/sqle/dtablefunctions/dolt_log_table_function.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ var logTableSchema = sql.Schema{
6060
&sql.Column{Name: "email", Type: types.Text},
6161
&sql.Column{Name: "date", Type: types.Datetime},
6262
&sql.Column{Name: "message", Type: types.Text},
63+
&sql.Column{Name: "commit_order", Type: types.Uint64},
6364
}
6465

6566
// NewInstance creates a new instance of TableFunction interface
@@ -764,7 +765,12 @@ func (itr *logTableFunctionRowIter) Next(ctx *sql.Context) (sql.Row, error) {
764765
return nil, err
765766
}
766767

767-
row := sql.NewRow(commitHash.String(), meta.Name, meta.Email, meta.Time(), meta.Description)
768+
height, err := commit.Height()
769+
if err != nil {
770+
return nil, err
771+
}
772+
773+
row := sql.NewRow(commitHash.String(), meta.Name, meta.Email, meta.Time(), meta.Description, height)
768774

769775
if itr.showParents {
770776
prStr, err := getParentsString(ctx, commit)

go/libraries/doltcore/sqle/dtables/log_table.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ func (dt *LogTable) Schema() sql.Schema {
9292
{Name: "email", Type: types.Text, Source: dt.tableName, PrimaryKey: false, DatabaseSource: dt.dbName},
9393
{Name: "date", Type: types.Datetime, Source: dt.tableName, PrimaryKey: false, DatabaseSource: dt.dbName},
9494
{Name: "message", Type: types.Text, Source: dt.tableName, PrimaryKey: false, DatabaseSource: dt.dbName},
95+
{Name: "commit_order", Type: types.Uint64, Source: dt.tableName, PrimaryKey: false, DatabaseSource: dt.dbName},
9596
}
9697
}
9798

@@ -109,7 +110,11 @@ func (dt *LogTable) Partitions(*sql.Context) (sql.PartitionIter, error) {
109110
func (dt *LogTable) PartitionRows(ctx *sql.Context, p sql.Partition) (sql.RowIter, error) {
110111
switch p := p.(type) {
111112
case *doltdb.CommitPart:
112-
return sql.RowsToRowIter(sql.NewRow(p.Hash().String(), p.Meta().Name, p.Meta().Email, p.Meta().Time(), p.Meta().Description)), nil
113+
height, err := p.Commit().Height()
114+
if err != nil {
115+
return nil, err
116+
}
117+
return sql.RowsToRowIter(sql.NewRow(p.Hash().String(), p.Meta().Name, p.Meta().Email, p.Meta().Time(), p.Meta().Description, height)), nil
113118
default:
114119
return NewLogItr(ctx, dt.ddb, dt.head)
115120
}
@@ -246,7 +251,12 @@ func (itr *LogItr) Next(ctx *sql.Context) (sql.Row, error) {
246251
return nil, err
247252
}
248253

249-
return sql.NewRow(h.String(), meta.Name, meta.Email, meta.Time(), meta.Description), nil
254+
height, err := cm.Height()
255+
if err != nil {
256+
return nil, err
257+
}
258+
259+
return sql.NewRow(h.String(), meta.Name, meta.Email, meta.Time(), meta.Description, height), nil
250260
}
251261

252262
// Close closes the iterator.

go/libraries/doltcore/sqle/enginetest/dolt_queries.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4786,6 +4786,65 @@ var LogTableFunctionScriptTests = []queries.ScriptTest{
47864786
},
47874787
},
47884788
},
4789+
{
4790+
Name: "commit_order column in dolt_log system table and function",
4791+
SetUpScript: []string{
4792+
"create table t (pk int primary key);",
4793+
"call dolt_add('.')",
4794+
"set @Commit1 = '';",
4795+
"call dolt_commit_hash_out(@Commit1, '-am', 'commit 1');",
4796+
"call dolt_commit('--allow-empty', '-m', 'commit 2');",
4797+
"call dolt_checkout('-b', 'feature');",
4798+
"call dolt_commit('--allow-empty', '-m', 'feature commit');",
4799+
"call dolt_checkout('main');",
4800+
"call dolt_commit('--allow-empty', '-m', 'main commit');",
4801+
"call dolt_merge('feature', '-m', 'merge feature');",
4802+
},
4803+
Assertions: []queries.ScriptTestAssertion{
4804+
{
4805+
Query: "describe dolt_log;",
4806+
Expected: []sql.Row{
4807+
{"commit_hash", "text", "NO", "PRI", nil, ""},
4808+
{"committer", "text", "NO", "", nil, ""},
4809+
{"email", "text", "NO", "", nil, ""},
4810+
{"date", "datetime", "NO", "", nil, ""},
4811+
{"message", "text", "NO", "", nil, ""},
4812+
{"commit_order", "bigint unsigned", "NO", "", nil, ""},
4813+
},
4814+
},
4815+
{
4816+
Query: "select commit_order from dolt_log where message = 'commit 1';",
4817+
Expected: []sql.Row{
4818+
{uint64(2)},
4819+
},
4820+
},
4821+
{
4822+
Query: "select commit_order from dolt_log() where message = 'commit 1';",
4823+
Expected: []sql.Row{
4824+
{uint64(2)},
4825+
},
4826+
},
4827+
{
4828+
Query: "select (select commit_order from dolt_log where message = 'commit 1') = (select commit_order from dolt_log() where message = 'commit 1') as same_order;",
4829+
Expected: []sql.Row{
4830+
{true},
4831+
},
4832+
},
4833+
{
4834+
Query: "select count(distinct commit_order) = 5 as has_five_orders from dolt_log;",
4835+
Expected: []sql.Row{
4836+
{true},
4837+
},
4838+
},
4839+
// Test that commits on parallel branches can have the same commit_order (height)
4840+
{
4841+
Query: "select count(*) from (select commit_order, count(*) as cnt from dolt_log group by commit_order having cnt > 1) as duplicate_orders;",
4842+
Expected: []sql.Row{
4843+
{1}, // feature and main commits should have same order
4844+
},
4845+
},
4846+
},
4847+
},
47894848
}
47904849

47914850
var LargeJsonObjectScriptTests = []queries.ScriptTest{

go/libraries/doltcore/sqle/sqlselect_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -753,6 +753,7 @@ func BasicSelectTests() []SelectTest {
753753
754754
time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC).In(LoadedLocalLocation()),
755755
"Initialize data repository",
756+
uint64(1), // commit_order for the initial commit
756757
},
757758
},
758759
ExpectedSqlSchema: sql.Schema{
@@ -761,6 +762,7 @@ func BasicSelectTests() []SelectTest {
761762
&sql.Column{Name: "email", Type: gmstypes.Text},
762763
&sql.Column{Name: "date", Type: gmstypes.Datetime},
763764
&sql.Column{Name: "message", Type: gmstypes.Text},
765+
&sql.Column{Name: "commit_order", Type: gmstypes.Uint64},
764766
},
765767
},
766768
{

integration-tests/bats/system-tables.bats

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,86 @@ teardown() {
6767
[[ ! "$output" =~ "Added test table" ]] || false
6868
}
6969

70+
@test "system-tables: dolt_log system table includes commit_order column" {
71+
dolt sql -q "create table test (pk int, c1 int, primary key(pk))"
72+
dolt add test
73+
dolt commit -m "Added test table"
74+
dolt commit --allow-empty -m "Empty commit"
75+
76+
# Test that dolt_log system table has commit_order column
77+
run dolt sql -q "describe dolt_log"
78+
[ $status -eq 0 ]
79+
[[ "$output" =~ "commit_order" ]] || false
80+
81+
# Test that commit_order values are present and numeric
82+
run dolt sql -q "select commit_order from dolt_log where message = 'Added test table'"
83+
[ $status -eq 0 ]
84+
[[ "$output" =~ [0-9]+ ]] || false
85+
86+
# Test that we have 3 distinct commit orders (init commit + 2 new commits)
87+
run dolt sql -q "select count(distinct commit_order) from dolt_log"
88+
[ $status -eq 0 ]
89+
[[ "$output" =~ "3" ]] || false
90+
}
91+
92+
@test "system-tables: dolt_log() table function includes commit_order column" {
93+
dolt sql -q "create table test2 (pk int, c1 int, primary key(pk))"
94+
dolt add test2
95+
dolt commit -m "Added test2 table"
96+
97+
# Test that dolt_log() function has commit_order column
98+
run dolt sql -q "select commit_order from dolt_log() where message = 'Added test2 table'"
99+
[ $status -eq 0 ]
100+
[[ "$output" =~ [0-9]+ ]] || false
101+
102+
# Test that the function and system table return the same commit_order for the same commit
103+
run dolt sql -q "select (select commit_order from dolt_log where message = 'Added test2 table') = (select commit_order from dolt_log() where message = 'Added test2 table') as orders_match"
104+
[ $status -eq 0 ]
105+
[[ "$output" =~ "true" ]] || false
106+
}
107+
108+
@test "system-tables: commit_order reflects topological order for branches" {
109+
if [ "$SQL_ENGINE" = "remote-engine" ]; then
110+
skip "needs checkout which is unsupported for remote-engine"
111+
fi
112+
113+
# Create initial commit
114+
dolt sql -q "create table test (pk int, c1 int, primary key(pk))"
115+
dolt add test
116+
dolt commit -m "initial commit"
117+
118+
# Create a branch
119+
dolt checkout -b feature
120+
dolt commit --allow-empty -m "feature commit"
121+
122+
# Go back to main and make another commit
123+
dolt checkout main
124+
dolt commit --allow-empty -m "main commit"
125+
126+
# Both feature and main commits should have the same commit_order (height)
127+
# since they branched from the same parent
128+
# Get the commit hashes and compare their heights using dolt_log() function
129+
run dolt sql -q "select commit_hash from dolt_commits where message = 'feature commit'"
130+
[ $status -eq 0 ]
131+
feature_hash=$(echo "$output" | tail -n 1 | tr -d ' |')
132+
133+
run dolt sql -q "select commit_hash from dolt_commits where message = 'main commit'"
134+
[ $status -eq 0 ]
135+
main_hash=$(echo "$output" | tail -n 1 | tr -d ' |')
136+
137+
run dolt sql -q "select (select commit_order from dolt_log('$feature_hash') limit 1) = (select commit_order from dolt_log('$main_hash') limit 1) as same_height"
138+
[ $status -eq 0 ]
139+
[[ "$output" =~ "true" ]] || false
140+
141+
# Merge feature into main
142+
dolt merge feature -m "merge feature"
143+
144+
# The merge commit should have a higher commit_order than both branch commits
145+
run dolt sql -q "select (select commit_order from dolt_log where message = 'merge feature') > (select commit_order from dolt_log where message = 'main commit') as merge_higher"
146+
[ $status -eq 0 ]
147+
[[ "$output" =~ "true" ]] || false
148+
}
149+
70150
@test "system-tables: query dolt_branches system table" {
71151
dolt checkout -b create-table-branch
72152
dolt sql -q "create table test (pk int, c1 int, primary key(pk))"

integration-tests/mysql-client-tests/node/workbenchTests/logs.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export const logTests = [
1111
1212
date: "",
1313
message: "Initialize data repository",
14+
commit_order: 1,
1415
parents: [],
1516
},
1617
],
@@ -26,13 +27,15 @@ export const logTests = [
2627
2728
date: "",
2829
message: "Create table test",
30+
commit_order: 2,
2931
},
3032
{
3133
commit_hash: "",
3234
committer: "mysql-test-runner",
3335
3436
date: "",
3537
message: "Initialize data repository",
38+
commit_order: 1,
3639
},
3740
],
3841
matcher: logsMatcher,
@@ -47,6 +50,7 @@ export const logTests = [
4750
4851
date: "",
4952
message: "Create table test",
53+
commit_order: 2,
5054
parents: [""],
5155
},
5256
],

integration-tests/mysql-client-tests/node/workbenchTests/matchers.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ export function branchesMatcher(rows, exp) {
6161
}
6262

6363
export function logsMatcher(rows, exp) {
64-
const exceptionKeys = ["commit_hash", "date", "parents"];
64+
const exceptionKeys = ["commit_hash", "date", "parents", "commit_order"];
6565

6666
function getExceptionIsValid(row, key, expRow) {
6767
const val = row[key];
@@ -75,6 +75,8 @@ export function logsMatcher(rows, exp) {
7575
val.split(", ").filter((v) => !!v.length).length ===
7676
expRow.parents.length
7777
);
78+
case "commit_order":
79+
return typeof val === "number" && val > 0;
7880
default:
7981
return false;
8082
}

integration-tests/mysql-client-tests/node/workbenchTests/merge.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export const mergeTests = [
2727
committer: "dolt",
2828
email: "dolt@%",
2929
date: "",
30+
commit_order: 3,
3031
parents: ["", ""],
3132
},
3233
{
@@ -35,6 +36,7 @@ export const mergeTests = [
3536
committer: "Dolt",
3637
3738
date: "",
39+
commit_order: 2,
3840
parents: [""],
3941
},
4042
{
@@ -43,6 +45,7 @@ export const mergeTests = [
4345
committer: "mysql-test-runner",
4446
4547
date: "",
48+
commit_order: 1,
4649
parents: [],
4750
},
4851
],

0 commit comments

Comments
 (0)