@@ -4451,6 +4451,10 @@ func TestChangefeedEnrichedSourceWithDataAvro(t *testing.T) {
4451
4451
4452
4452
sqlDB .Exec (t , `CREATE TABLE foo (i INT PRIMARY KEY)` )
4453
4453
sqlDB .Exec (t , `INSERT INTO foo values (0)` )
4454
+
4455
+ var tableID int
4456
+ sqlDB .QueryRow (t , `SELECT table_id FROM crdb_internal.tables WHERE name = 'foo' AND database_name = 'd'` ).Scan (& tableID )
4457
+
4454
4458
stmt := `CREATE CHANGEFEED FOR foo WITH envelope=enriched, enriched_properties='source', format=avro`
4455
4459
if withMVCCTS {
4456
4460
stmt += ", mvcc_timestamp"
@@ -4488,12 +4492,13 @@ func TestChangefeedEnrichedSourceWithDataAvro(t *testing.T) {
4488
4492
var assertion string
4489
4493
assertionMap := map [string ]any {
4490
4494
"source" : map [string ]any {
4491
- "changefeed_sink" : map [string ]any {"string" : sink },
4492
- "cluster_id" : map [string ]any {"string" : clusterID },
4493
- "cluster_name" : map [string ]any {"string" : clusterName },
4494
- "database_name" : map [string ]any {"string" : "d" },
4495
- "db_version" : map [string ]any {"string" : dbVersion },
4496
- "job_id" : map [string ]any {"string" : jobIDStr },
4495
+ "changefeed_sink" : map [string ]any {"string" : sink },
4496
+ "cluster_id" : map [string ]any {"string" : clusterID },
4497
+ "cluster_name" : map [string ]any {"string" : clusterName },
4498
+ "crdb_internal_table_id" : map [string ]any {"int" : tableID },
4499
+ "database_name" : map [string ]any {"string" : "d" },
4500
+ "db_version" : map [string ]any {"string" : dbVersion },
4501
+ "job_id" : map [string ]any {"string" : jobIDStr },
4497
4502
// Note that the field is still present in the avro schema, so it appears here as nil.
4498
4503
"mvcc_timestamp" : nil ,
4499
4504
"node_id" : map [string ]any {"string" : nodeID },
@@ -4569,6 +4574,7 @@ func TestChangefeedEnrichedSourceWithDataJSON(t *testing.T) {
4569
4574
4570
4575
sqlDB .Exec (t , `CREATE TABLE foo (i INT PRIMARY KEY)` )
4571
4576
sqlDB .Exec (t , `INSERT INTO foo values (0)` )
4577
+
4572
4578
stmt := `CREATE CHANGEFEED FOR foo WITH envelope=enriched, enriched_properties='source', format=json`
4573
4579
if withMVCCTS {
4574
4580
stmt += ", mvcc_timestamp"
@@ -4581,11 +4587,14 @@ func TestChangefeedEnrichedSourceWithDataJSON(t *testing.T) {
4581
4587
4582
4588
var jobID int64
4583
4589
var nodeName string
4590
+ var tableID int
4591
+
4584
4592
var sourceAssertion func (actualSource map [string ]any )
4585
4593
if ef , ok := testFeed .(cdctest.EnterpriseTestFeed ); ok {
4586
4594
jobID = int64 (ef .JobID ())
4587
4595
}
4588
4596
sqlDB .QueryRow (t , `SELECT value FROM crdb_internal.node_runtime_info where component = 'DB' and field = 'Host'` ).Scan (& nodeName )
4597
+ sqlDB .QueryRow (t , `SELECT table_id FROM crdb_internal.tables WHERE name = 'foo' AND database_name = 'd'` ).Scan (& tableID )
4589
4598
4590
4599
sourceAssertion = func (actualSource map [string ]any ) {
4591
4600
nodeID := actualSource ["node_id" ]
@@ -4607,19 +4616,20 @@ func TestChangefeedEnrichedSourceWithDataJSON(t *testing.T) {
4607
4616
4608
4617
var assertion string
4609
4618
assertionMap := map [string ]any {
4610
- "cluster_id" : clusterID ,
4611
- "cluster_name" : clusterName ,
4612
- "db_version" : dbVersion ,
4613
- "job_id" : jobIDStr ,
4614
- "node_id" : nodeID ,
4615
- "node_name" : nodeName ,
4616
- "origin" : "cockroachdb" ,
4617
- "changefeed_sink" : sink ,
4618
- "source_node_locality" : sourceNodeLocality ,
4619
- "database_name" : "d" ,
4620
- "schema_name" : "public" ,
4621
- "table_name" : "foo" ,
4622
- "primary_keys" : []any {"i" },
4619
+ "cluster_id" : clusterID ,
4620
+ "cluster_name" : clusterName ,
4621
+ "crdb_internal_table_id" : tableID ,
4622
+ "db_version" : dbVersion ,
4623
+ "job_id" : jobIDStr ,
4624
+ "node_id" : nodeID ,
4625
+ "node_name" : nodeName ,
4626
+ "origin" : "cockroachdb" ,
4627
+ "changefeed_sink" : sink ,
4628
+ "source_node_locality" : sourceNodeLocality ,
4629
+ "database_name" : "d" ,
4630
+ "schema_name" : "public" ,
4631
+ "table_name" : "foo" ,
4632
+ "primary_keys" : []any {"i" },
4623
4633
}
4624
4634
if withMVCCTS {
4625
4635
assertReasonableMVCCTimestamp (t , actualSource ["mvcc_timestamp" ].(string ))
@@ -4680,6 +4690,10 @@ func TestChangefeedEnrichedSourceWithDataJSONWebhook(t *testing.T) {
4680
4690
4681
4691
sqlDB .Exec (t , `CREATE TABLE foo (i INT PRIMARY KEY)` )
4682
4692
sqlDB .Exec (t , `INSERT INTO foo values (0)` )
4693
+
4694
+ var tableID int
4695
+ sqlDB .QueryRow (t , `SELECT table_id FROM crdb_internal.tables WHERE name = 'foo' AND database_name = 'd'` ).Scan (& tableID )
4696
+
4683
4697
stmt := `CREATE CHANGEFEED FOR foo WITH envelope=enriched, enriched_properties='source', format=json`
4684
4698
if withMVCCTS {
4685
4699
stmt += ", mvcc_timestamp"
@@ -4713,19 +4727,20 @@ func TestChangefeedEnrichedSourceWithDataJSONWebhook(t *testing.T) {
4713
4727
4714
4728
var assertion string
4715
4729
assertionMap := map [string ]any {
4716
- "cluster_id" : clusterID ,
4717
- "cluster_name" : clusterName ,
4718
- "db_version" : dbVersion ,
4719
- "job_id" : jobIDStr ,
4720
- "node_id" : nodeID ,
4721
- "node_name" : nodeName ,
4722
- "origin" : "cockroachdb" ,
4723
- "changefeed_sink" : sink ,
4724
- "source_node_locality" : sourceNodeLocality ,
4725
- "database_name" : "d" ,
4726
- "schema_name" : "public" ,
4727
- "table_name" : "foo" ,
4728
- "primary_keys" : []any {"i" },
4730
+ "cluster_id" : clusterID ,
4731
+ "cluster_name" : clusterName ,
4732
+ "crdb_internal_table_id" : tableID ,
4733
+ "db_version" : dbVersion ,
4734
+ "job_id" : jobIDStr ,
4735
+ "node_id" : nodeID ,
4736
+ "node_name" : nodeName ,
4737
+ "origin" : "cockroachdb" ,
4738
+ "changefeed_sink" : sink ,
4739
+ "source_node_locality" : sourceNodeLocality ,
4740
+ "database_name" : "d" ,
4741
+ "schema_name" : "public" ,
4742
+ "table_name" : "foo" ,
4743
+ "primary_keys" : []any {"i" },
4729
4744
}
4730
4745
if withMVCCTS {
4731
4746
assertReasonableMVCCTimestamp (t , actualSource ["mvcc_timestamp" ].(string ))
@@ -4797,6 +4812,9 @@ func TestChangefeedEnrichedSourceSchemaInfo(t *testing.T) {
4797
4812
for _ , testCase := range cases {
4798
4813
t .Run (testCase .name , func (t * testing.T ) {
4799
4814
testFn := func (t * testing.T , s TestServer , f cdctest.TestFeedFactory ) {
4815
+
4816
+ var originalTableID int
4817
+
4800
4818
sqlDB := sqlutils .MakeSQLRunner (s .DB )
4801
4819
4802
4820
sqlDB .Exec (t , `CREATE TABLE foo (a INT, b STRING, c INT, PRIMARY KEY (a, b))` )
@@ -4813,11 +4831,21 @@ func TestChangefeedEnrichedSourceSchemaInfo(t *testing.T) {
4813
4831
require .Equal (t , map [string ]any {"string" : "public" }, actualSourceValue ["schema_name" ])
4814
4832
require .Equal (t , map [string ]any {"string" : "d" }, actualSourceValue ["database_name" ])
4815
4833
require .Equal (t , map [string ]any {"array" : []any {"a" , "b" }}, actualSourceValue ["primary_keys" ])
4834
+
4835
+ num := actualSourceValue ["crdb_internal_table_id" ].(map [string ]any )["int" ].(gojson.Number )
4836
+ idInt , err := num .Int64 ()
4837
+ require .NoError (t , err )
4838
+ originalTableID = int (idInt )
4816
4839
} else {
4817
4840
require .Equal (t , "foo" , actualSource ["table_name" ])
4818
4841
require .Equal (t , "public" , actualSource ["schema_name" ])
4819
4842
require .Equal (t , "d" , actualSource ["database_name" ])
4820
4843
require .Equal (t , []any {"a" , "b" }, actualSource ["primary_keys" ])
4844
+
4845
+ num := actualSource ["crdb_internal_table_id" ].(gojson.Number )
4846
+ idInt , err := num .Int64 ()
4847
+ require .NoError (t , err )
4848
+ originalTableID = int (idInt )
4821
4849
}
4822
4850
}
4823
4851
assertPayloadsEnriched (t , foo , []string {testCase .expectedRow }, sourceAssertion )
@@ -4832,11 +4860,21 @@ func TestChangefeedEnrichedSourceSchemaInfo(t *testing.T) {
4832
4860
require .Equal (t , map [string ]any {"string" : "public" }, actualSourceValue ["schema_name" ])
4833
4861
require .Equal (t , map [string ]any {"string" : "d" }, actualSourceValue ["database_name" ])
4834
4862
require .Equal (t , map [string ]any {"array" : []any {"a" , "b" }}, actualSourceValue ["primary_keys" ])
4863
+
4864
+ num := actualSourceValue ["crdb_internal_table_id" ].(map [string ]any )["int" ].(gojson.Number )
4865
+ idInt , err := num .Int64 ()
4866
+ require .NoError (t , err )
4867
+ require .Equal (t , originalTableID , int (idInt ))
4835
4868
} else {
4836
4869
require .Equal (t , "foo" , actualSource ["table_name" ])
4837
4870
require .Equal (t , "public" , actualSource ["schema_name" ])
4838
4871
require .Equal (t , "d" , actualSource ["database_name" ])
4839
4872
require .Equal (t , []any {"a" , "b" }, actualSource ["primary_keys" ])
4873
+
4874
+ num := actualSource ["crdb_internal_table_id" ].(gojson.Number )
4875
+ idInt , err := num .Int64 ()
4876
+ require .NoError (t , err )
4877
+ require .Equal (t , originalTableID , int (idInt ))
4840
4878
}
4841
4879
}
4842
4880
assertPayloadsEnriched (t , foo , testCase .expectedRowsAfterSchemaChange , sourceAssertionAfterSchemaChange )
@@ -4874,6 +4912,9 @@ func TestChangefeedEnrichedSourceSchemaInfoOnPrimaryKeyChange(t *testing.T) {
4874
4912
for _ , testCase := range cases {
4875
4913
t .Run (testCase .name , func (t * testing.T ) {
4876
4914
testFn := func (t * testing.T , s TestServer , f cdctest.TestFeedFactory ) {
4915
+
4916
+ var originalTableID int
4917
+
4877
4918
sqlDB := sqlutils .MakeSQLRunner (s .DB )
4878
4919
4879
4920
sqlDB .Exec (t , `CREATE TABLE foo (a INT PRIMARY KEY, b STRING)` )
@@ -4890,11 +4931,21 @@ func TestChangefeedEnrichedSourceSchemaInfoOnPrimaryKeyChange(t *testing.T) {
4890
4931
require .Equal (t , map [string ]any {"string" : "public" }, actualSourceValue ["schema_name" ])
4891
4932
require .Equal (t , map [string ]any {"string" : "d" }, actualSourceValue ["database_name" ])
4892
4933
require .Equal (t , map [string ]any {"array" : []any {"a" }}, actualSourceValue ["primary_keys" ])
4934
+
4935
+ num := actualSourceValue ["crdb_internal_table_id" ].(map [string ]any )["int" ].(gojson.Number )
4936
+ idInt , err := num .Int64 ()
4937
+ require .NoError (t , err )
4938
+ originalTableID = int (idInt )
4893
4939
} else {
4894
4940
require .Equal (t , "foo" , actualSource ["table_name" ])
4895
4941
require .Equal (t , "public" , actualSource ["schema_name" ])
4896
4942
require .Equal (t , "d" , actualSource ["database_name" ])
4897
4943
require .Equal (t , []any {"a" }, actualSource ["primary_keys" ])
4944
+
4945
+ num := actualSource ["crdb_internal_table_id" ].(gojson.Number )
4946
+ idInt , err := num .Int64 ()
4947
+ require .NoError (t , err )
4948
+ originalTableID = int (idInt )
4898
4949
}
4899
4950
}
4900
4951
if testCase .format == "json" {
@@ -4914,11 +4965,21 @@ func TestChangefeedEnrichedSourceSchemaInfoOnPrimaryKeyChange(t *testing.T) {
4914
4965
require .Equal (t , map [string ]any {"string" : "public" }, actualSourceValue ["schema_name" ])
4915
4966
require .Equal (t , map [string ]any {"string" : "d" }, actualSourceValue ["database_name" ])
4916
4967
require .Equal (t , map [string ]any {"array" : []any {"b" }}, actualSourceValue ["primary_keys" ])
4968
+
4969
+ num := actualSourceValue ["crdb_internal_table_id" ].(map [string ]any )["int" ].(gojson.Number )
4970
+ idInt , err := num .Int64 ()
4971
+ require .NoError (t , err )
4972
+ require .Equal (t , originalTableID , int (idInt ))
4917
4973
} else {
4918
4974
require .Equal (t , "foo" , actualSource ["table_name" ])
4919
4975
require .Equal (t , "public" , actualSource ["schema_name" ])
4920
4976
require .Equal (t , "d" , actualSource ["database_name" ])
4921
4977
require .Equal (t , []any {"b" }, actualSource ["primary_keys" ])
4978
+
4979
+ num := actualSource ["crdb_internal_table_id" ].(gojson.Number )
4980
+ idInt , err := num .Int64 ()
4981
+ require .NoError (t , err )
4982
+ require .Equal (t , originalTableID , int (idInt ))
4922
4983
}
4923
4984
}
4924
4985
assertPayloadsEnriched (t , foo , []string {testCase .expectedRowAfter }, sourceAssertionAfterPKChange )
@@ -4929,6 +4990,47 @@ func TestChangefeedEnrichedSourceSchemaInfoOnPrimaryKeyChange(t *testing.T) {
4929
4990
}
4930
4991
}
4931
4992
4993
+ func TestChangefeedEnrichedTableIDStableOnRename (t * testing.T ) {
4994
+ defer leaktest .AfterTest (t )()
4995
+ defer log .Scope (t ).Close (t )
4996
+
4997
+ testFn := func (t * testing.T , s TestServer , f cdctest.TestFeedFactory ) {
4998
+ sqlDB := sqlutils .MakeSQLRunner (s .DB )
4999
+
5000
+ sqlDB .Exec (t , `CREATE TABLE foo (i INT PRIMARY KEY)` )
5001
+ sqlDB .Exec (t , `INSERT INTO foo VALUES (1)` )
5002
+
5003
+ foo := feed (t , f , `CREATE CHANGEFEED FOR foo WITH envelope=enriched, enriched_properties='source'` )
5004
+ defer closeFeed (t , foo )
5005
+
5006
+ var originalTableID int
5007
+
5008
+ // Capture first row (before rename)
5009
+ sourceAssertionBefore := func (actualSource map [string ]any ) {
5010
+ num := actualSource ["crdb_internal_table_id" ].(gojson.Number )
5011
+ id , err := num .Int64 ()
5012
+ require .NoError (t , err )
5013
+ originalTableID = int (id )
5014
+ }
5015
+ assertPayloadsEnriched (t , foo , []string {`foo: {"i": 1}->{"after": {"i": 1}, "op": "c"}` }, sourceAssertionBefore )
5016
+
5017
+ // Rename table
5018
+ sqlDB .Exec (t , `ALTER TABLE foo RENAME TO bar` )
5019
+ sqlDB .Exec (t , `INSERT INTO bar VALUES (2)` )
5020
+
5021
+ // Capture second row (after rename)
5022
+ sourceAssertionAfter := func (actualSource map [string ]any ) {
5023
+ num := actualSource ["crdb_internal_table_id" ].(gojson.Number )
5024
+ id , err := num .Int64 ()
5025
+ require .NoError (t , err )
5026
+ require .Equal (t , originalTableID , int (id ))
5027
+ }
5028
+ assertPayloadsEnriched (t , foo , []string {`foo: {"i": 2}->{"after": {"i": 2}, "op": "c"}` }, sourceAssertionAfter )
5029
+ }
5030
+
5031
+ cdcTest (t , testFn , feedTestForceSink ("kafka" ))
5032
+ }
5033
+
4932
5034
func TestChangefeedExpressionUsesSerializedSessionData (t * testing.T ) {
4933
5035
defer leaktest .AfterTest (t )()
4934
5036
defer log .Scope (t ).Close (t )
0 commit comments