@@ -4437,6 +4437,10 @@ func TestChangefeedEnrichedSourceWithDataAvro(t *testing.T) {
4437
4437
4438
4438
sqlDB .Exec (t , `CREATE TABLE foo (i INT PRIMARY KEY)` )
4439
4439
sqlDB .Exec (t , `INSERT INTO foo values (0)` )
4440
+
4441
+ var tableID int
4442
+ sqlDB .QueryRow (t , `SELECT table_id FROM crdb_internal.tables WHERE name = 'foo' AND database_name = 'd'` ).Scan (& tableID )
4443
+
4440
4444
stmt := `CREATE CHANGEFEED FOR foo WITH envelope=enriched, enriched_properties='source', format=avro`
4441
4445
if withMVCCTS {
4442
4446
stmt += ", mvcc_timestamp"
@@ -4474,12 +4478,13 @@ func TestChangefeedEnrichedSourceWithDataAvro(t *testing.T) {
4474
4478
var assertion string
4475
4479
assertionMap := map [string ]any {
4476
4480
"source" : map [string ]any {
4477
- "changefeed_sink" : map [string ]any {"string" : sink },
4478
- "cluster_id" : map [string ]any {"string" : clusterID },
4479
- "cluster_name" : map [string ]any {"string" : clusterName },
4480
- "database_name" : map [string ]any {"string" : "d" },
4481
- "db_version" : map [string ]any {"string" : dbVersion },
4482
- "job_id" : map [string ]any {"string" : jobIDStr },
4481
+ "changefeed_sink" : map [string ]any {"string" : sink },
4482
+ "cluster_id" : map [string ]any {"string" : clusterID },
4483
+ "cluster_name" : map [string ]any {"string" : clusterName },
4484
+ "crdb_internal_table_id" : map [string ]any {"int" : tableID },
4485
+ "database_name" : map [string ]any {"string" : "d" },
4486
+ "db_version" : map [string ]any {"string" : dbVersion },
4487
+ "job_id" : map [string ]any {"string" : jobIDStr },
4483
4488
// Note that the field is still present in the avro schema, so it appears here as nil.
4484
4489
"mvcc_timestamp" : nil ,
4485
4490
"node_id" : map [string ]any {"string" : nodeID },
@@ -4555,6 +4560,7 @@ func TestChangefeedEnrichedSourceWithDataJSON(t *testing.T) {
4555
4560
4556
4561
sqlDB .Exec (t , `CREATE TABLE foo (i INT PRIMARY KEY)` )
4557
4562
sqlDB .Exec (t , `INSERT INTO foo values (0)` )
4563
+
4558
4564
stmt := `CREATE CHANGEFEED FOR foo WITH envelope=enriched, enriched_properties='source', format=json`
4559
4565
if withMVCCTS {
4560
4566
stmt += ", mvcc_timestamp"
@@ -4567,11 +4573,14 @@ func TestChangefeedEnrichedSourceWithDataJSON(t *testing.T) {
4567
4573
4568
4574
var jobID int64
4569
4575
var nodeName string
4576
+ var tableID int
4577
+
4570
4578
var sourceAssertion func (actualSource map [string ]any )
4571
4579
if ef , ok := testFeed .(cdctest.EnterpriseTestFeed ); ok {
4572
4580
jobID = int64 (ef .JobID ())
4573
4581
}
4574
4582
sqlDB .QueryRow (t , `SELECT value FROM crdb_internal.node_runtime_info where component = 'DB' and field = 'Host'` ).Scan (& nodeName )
4583
+ sqlDB .QueryRow (t , `SELECT table_id FROM crdb_internal.tables WHERE name = 'foo' AND database_name = 'd'` ).Scan (& tableID )
4575
4584
4576
4585
sourceAssertion = func (actualSource map [string ]any ) {
4577
4586
nodeID := actualSource ["node_id" ]
@@ -4593,19 +4602,20 @@ func TestChangefeedEnrichedSourceWithDataJSON(t *testing.T) {
4593
4602
4594
4603
var assertion string
4595
4604
assertionMap := map [string ]any {
4596
- "cluster_id" : clusterID ,
4597
- "cluster_name" : clusterName ,
4598
- "db_version" : dbVersion ,
4599
- "job_id" : jobIDStr ,
4600
- "node_id" : nodeID ,
4601
- "node_name" : nodeName ,
4602
- "origin" : "cockroachdb" ,
4603
- "changefeed_sink" : sink ,
4604
- "source_node_locality" : sourceNodeLocality ,
4605
- "database_name" : "d" ,
4606
- "schema_name" : "public" ,
4607
- "table_name" : "foo" ,
4608
- "primary_keys" : []any {"i" },
4605
+ "cluster_id" : clusterID ,
4606
+ "cluster_name" : clusterName ,
4607
+ "crdb_internal_table_id" : tableID ,
4608
+ "db_version" : dbVersion ,
4609
+ "job_id" : jobIDStr ,
4610
+ "node_id" : nodeID ,
4611
+ "node_name" : nodeName ,
4612
+ "origin" : "cockroachdb" ,
4613
+ "changefeed_sink" : sink ,
4614
+ "source_node_locality" : sourceNodeLocality ,
4615
+ "database_name" : "d" ,
4616
+ "schema_name" : "public" ,
4617
+ "table_name" : "foo" ,
4618
+ "primary_keys" : []any {"i" },
4609
4619
}
4610
4620
if withMVCCTS {
4611
4621
assertReasonableMVCCTimestamp (t , actualSource ["mvcc_timestamp" ].(string ))
@@ -4666,6 +4676,10 @@ func TestChangefeedEnrichedSourceWithDataJSONWebhook(t *testing.T) {
4666
4676
4667
4677
sqlDB .Exec (t , `CREATE TABLE foo (i INT PRIMARY KEY)` )
4668
4678
sqlDB .Exec (t , `INSERT INTO foo values (0)` )
4679
+
4680
+ var tableID int
4681
+ sqlDB .QueryRow (t , `SELECT table_id FROM crdb_internal.tables WHERE name = 'foo' AND database_name = 'd'` ).Scan (& tableID )
4682
+
4669
4683
stmt := `CREATE CHANGEFEED FOR foo WITH envelope=enriched, enriched_properties='source', format=json`
4670
4684
if withMVCCTS {
4671
4685
stmt += ", mvcc_timestamp"
@@ -4699,19 +4713,20 @@ func TestChangefeedEnrichedSourceWithDataJSONWebhook(t *testing.T) {
4699
4713
4700
4714
var assertion string
4701
4715
assertionMap := map [string ]any {
4702
- "cluster_id" : clusterID ,
4703
- "cluster_name" : clusterName ,
4704
- "db_version" : dbVersion ,
4705
- "job_id" : jobIDStr ,
4706
- "node_id" : nodeID ,
4707
- "node_name" : nodeName ,
4708
- "origin" : "cockroachdb" ,
4709
- "changefeed_sink" : sink ,
4710
- "source_node_locality" : sourceNodeLocality ,
4711
- "database_name" : "d" ,
4712
- "schema_name" : "public" ,
4713
- "table_name" : "foo" ,
4714
- "primary_keys" : []any {"i" },
4716
+ "cluster_id" : clusterID ,
4717
+ "cluster_name" : clusterName ,
4718
+ "crdb_internal_table_id" : tableID ,
4719
+ "db_version" : dbVersion ,
4720
+ "job_id" : jobIDStr ,
4721
+ "node_id" : nodeID ,
4722
+ "node_name" : nodeName ,
4723
+ "origin" : "cockroachdb" ,
4724
+ "changefeed_sink" : sink ,
4725
+ "source_node_locality" : sourceNodeLocality ,
4726
+ "database_name" : "d" ,
4727
+ "schema_name" : "public" ,
4728
+ "table_name" : "foo" ,
4729
+ "primary_keys" : []any {"i" },
4715
4730
}
4716
4731
if withMVCCTS {
4717
4732
assertReasonableMVCCTimestamp (t , actualSource ["mvcc_timestamp" ].(string ))
@@ -4783,6 +4798,9 @@ func TestChangefeedEnrichedSourceSchemaInfo(t *testing.T) {
4783
4798
for _ , testCase := range cases {
4784
4799
t .Run (testCase .name , func (t * testing.T ) {
4785
4800
testFn := func (t * testing.T , s TestServer , f cdctest.TestFeedFactory ) {
4801
+
4802
+ var originalTableID int
4803
+
4786
4804
sqlDB := sqlutils .MakeSQLRunner (s .DB )
4787
4805
4788
4806
sqlDB .Exec (t , `CREATE TABLE foo (a INT, b STRING, c INT, PRIMARY KEY (a, b))` )
@@ -4799,11 +4817,21 @@ func TestChangefeedEnrichedSourceSchemaInfo(t *testing.T) {
4799
4817
require .Equal (t , map [string ]any {"string" : "public" }, actualSourceValue ["schema_name" ])
4800
4818
require .Equal (t , map [string ]any {"string" : "d" }, actualSourceValue ["database_name" ])
4801
4819
require .Equal (t , map [string ]any {"array" : []any {"a" , "b" }}, actualSourceValue ["primary_keys" ])
4820
+
4821
+ num := actualSourceValue ["crdb_internal_table_id" ].(map [string ]any )["int" ].(gojson.Number )
4822
+ idInt , err := num .Int64 ()
4823
+ require .NoError (t , err )
4824
+ originalTableID = int (idInt )
4802
4825
} else {
4803
4826
require .Equal (t , "foo" , actualSource ["table_name" ])
4804
4827
require .Equal (t , "public" , actualSource ["schema_name" ])
4805
4828
require .Equal (t , "d" , actualSource ["database_name" ])
4806
4829
require .Equal (t , []any {"a" , "b" }, actualSource ["primary_keys" ])
4830
+
4831
+ num := actualSource ["crdb_internal_table_id" ].(gojson.Number )
4832
+ idInt , err := num .Int64 ()
4833
+ require .NoError (t , err )
4834
+ originalTableID = int (idInt )
4807
4835
}
4808
4836
}
4809
4837
assertPayloadsEnriched (t , foo , []string {testCase .expectedRow }, sourceAssertion )
@@ -4818,11 +4846,21 @@ func TestChangefeedEnrichedSourceSchemaInfo(t *testing.T) {
4818
4846
require .Equal (t , map [string ]any {"string" : "public" }, actualSourceValue ["schema_name" ])
4819
4847
require .Equal (t , map [string ]any {"string" : "d" }, actualSourceValue ["database_name" ])
4820
4848
require .Equal (t , map [string ]any {"array" : []any {"a" , "b" }}, actualSourceValue ["primary_keys" ])
4849
+
4850
+ num := actualSourceValue ["crdb_internal_table_id" ].(map [string ]any )["int" ].(gojson.Number )
4851
+ idInt , err := num .Int64 ()
4852
+ require .NoError (t , err )
4853
+ require .Equal (t , originalTableID , int (idInt ))
4821
4854
} else {
4822
4855
require .Equal (t , "foo" , actualSource ["table_name" ])
4823
4856
require .Equal (t , "public" , actualSource ["schema_name" ])
4824
4857
require .Equal (t , "d" , actualSource ["database_name" ])
4825
4858
require .Equal (t , []any {"a" , "b" }, actualSource ["primary_keys" ])
4859
+
4860
+ num := actualSource ["crdb_internal_table_id" ].(gojson.Number )
4861
+ idInt , err := num .Int64 ()
4862
+ require .NoError (t , err )
4863
+ require .Equal (t , originalTableID , int (idInt ))
4826
4864
}
4827
4865
}
4828
4866
assertPayloadsEnriched (t , foo , testCase .expectedRowsAfterSchemaChange , sourceAssertionAfterSchemaChange )
@@ -4860,6 +4898,9 @@ func TestChangefeedEnrichedSourceSchemaInfoOnPrimaryKeyChange(t *testing.T) {
4860
4898
for _ , testCase := range cases {
4861
4899
t .Run (testCase .name , func (t * testing.T ) {
4862
4900
testFn := func (t * testing.T , s TestServer , f cdctest.TestFeedFactory ) {
4901
+
4902
+ var originalTableID int
4903
+
4863
4904
sqlDB := sqlutils .MakeSQLRunner (s .DB )
4864
4905
4865
4906
sqlDB .Exec (t , `CREATE TABLE foo (a INT PRIMARY KEY, b STRING)` )
@@ -4876,11 +4917,21 @@ func TestChangefeedEnrichedSourceSchemaInfoOnPrimaryKeyChange(t *testing.T) {
4876
4917
require .Equal (t , map [string ]any {"string" : "public" }, actualSourceValue ["schema_name" ])
4877
4918
require .Equal (t , map [string ]any {"string" : "d" }, actualSourceValue ["database_name" ])
4878
4919
require .Equal (t , map [string ]any {"array" : []any {"a" }}, actualSourceValue ["primary_keys" ])
4920
+
4921
+ num := actualSourceValue ["crdb_internal_table_id" ].(map [string ]any )["int" ].(gojson.Number )
4922
+ idInt , err := num .Int64 ()
4923
+ require .NoError (t , err )
4924
+ originalTableID = int (idInt )
4879
4925
} else {
4880
4926
require .Equal (t , "foo" , actualSource ["table_name" ])
4881
4927
require .Equal (t , "public" , actualSource ["schema_name" ])
4882
4928
require .Equal (t , "d" , actualSource ["database_name" ])
4883
4929
require .Equal (t , []any {"a" }, actualSource ["primary_keys" ])
4930
+
4931
+ num := actualSource ["crdb_internal_table_id" ].(gojson.Number )
4932
+ idInt , err := num .Int64 ()
4933
+ require .NoError (t , err )
4934
+ originalTableID = int (idInt )
4884
4935
}
4885
4936
}
4886
4937
if testCase .format == "json" {
@@ -4900,11 +4951,21 @@ func TestChangefeedEnrichedSourceSchemaInfoOnPrimaryKeyChange(t *testing.T) {
4900
4951
require .Equal (t , map [string ]any {"string" : "public" }, actualSourceValue ["schema_name" ])
4901
4952
require .Equal (t , map [string ]any {"string" : "d" }, actualSourceValue ["database_name" ])
4902
4953
require .Equal (t , map [string ]any {"array" : []any {"b" }}, actualSourceValue ["primary_keys" ])
4954
+
4955
+ num := actualSourceValue ["crdb_internal_table_id" ].(map [string ]any )["int" ].(gojson.Number )
4956
+ idInt , err := num .Int64 ()
4957
+ require .NoError (t , err )
4958
+ require .Equal (t , originalTableID , int (idInt ))
4903
4959
} else {
4904
4960
require .Equal (t , "foo" , actualSource ["table_name" ])
4905
4961
require .Equal (t , "public" , actualSource ["schema_name" ])
4906
4962
require .Equal (t , "d" , actualSource ["database_name" ])
4907
4963
require .Equal (t , []any {"b" }, actualSource ["primary_keys" ])
4964
+
4965
+ num := actualSource ["crdb_internal_table_id" ].(gojson.Number )
4966
+ idInt , err := num .Int64 ()
4967
+ require .NoError (t , err )
4968
+ require .Equal (t , originalTableID , int (idInt ))
4908
4969
}
4909
4970
}
4910
4971
assertPayloadsEnriched (t , foo , []string {testCase .expectedRowAfter }, sourceAssertionAfterPKChange )
@@ -4915,6 +4976,47 @@ func TestChangefeedEnrichedSourceSchemaInfoOnPrimaryKeyChange(t *testing.T) {
4915
4976
}
4916
4977
}
4917
4978
4979
+ func TestChangefeedEnrichedTableIDStableOnRename (t * testing.T ) {
4980
+ defer leaktest .AfterTest (t )()
4981
+ defer log .Scope (t ).Close (t )
4982
+
4983
+ testFn := func (t * testing.T , s TestServer , f cdctest.TestFeedFactory ) {
4984
+ sqlDB := sqlutils .MakeSQLRunner (s .DB )
4985
+
4986
+ sqlDB .Exec (t , `CREATE TABLE foo (i INT PRIMARY KEY)` )
4987
+ sqlDB .Exec (t , `INSERT INTO foo VALUES (1)` )
4988
+
4989
+ foo := feed (t , f , `CREATE CHANGEFEED FOR foo WITH envelope=enriched, enriched_properties='source'` )
4990
+ defer closeFeed (t , foo )
4991
+
4992
+ var originalTableID int
4993
+
4994
+ // Capture first row (before rename)
4995
+ sourceAssertionBefore := func (actualSource map [string ]any ) {
4996
+ num := actualSource ["crdb_internal_table_id" ].(gojson.Number )
4997
+ id , err := num .Int64 ()
4998
+ require .NoError (t , err )
4999
+ originalTableID = int (id )
5000
+ }
5001
+ assertPayloadsEnriched (t , foo , []string {`foo: {"i": 1}->{"after": {"i": 1}, "op": "c"}` }, sourceAssertionBefore )
5002
+
5003
+ // Rename table
5004
+ sqlDB .Exec (t , `ALTER TABLE foo RENAME TO bar` )
5005
+ sqlDB .Exec (t , `INSERT INTO bar VALUES (2)` )
5006
+
5007
+ // Capture second row (after rename)
5008
+ sourceAssertionAfter := func (actualSource map [string ]any ) {
5009
+ num := actualSource ["crdb_internal_table_id" ].(gojson.Number )
5010
+ id , err := num .Int64 ()
5011
+ require .NoError (t , err )
5012
+ require .Equal (t , originalTableID , int (id ))
5013
+ }
5014
+ assertPayloadsEnriched (t , foo , []string {`foo: {"i": 2}->{"after": {"i": 2}, "op": "c"}` }, sourceAssertionAfter )
5015
+ }
5016
+
5017
+ cdcTest (t , testFn , feedTestForceSink ("kafka" ))
5018
+ }
5019
+
4918
5020
func TestChangefeedExpressionUsesSerializedSessionData (t * testing.T ) {
4919
5021
defer leaktest .AfterTest (t )()
4920
5022
defer log .Scope (t ).Close (t )
0 commit comments