diff --git a/doc/docs/en/architecture/test_framework.md b/doc/docs/en/architecture/test_framework.md
deleted file mode 100644
index 6f5dfd1..0000000
--- a/doc/docs/en/architecture/test_framework.md
+++ /dev/null
@@ -1 +0,0 @@
-# Test Framework
\ No newline at end of file
diff --git a/doc/docs/en/getting-started/quick_start.md b/doc/docs/en/getting-started/quick_start.md
index ff5ffca..f0150fe 100644
--- a/doc/docs/en/getting-started/quick_start.md
+++ b/doc/docs/en/getting-started/quick_start.md
@@ -100,7 +100,7 @@ SELECT synchdb_add_conninfo('mysqlconn',
'mysqluser',
'mysqlpwd',
'inventory',
- 'postgres',
+ 'null',
'null',
'null',
'mysql');
@@ -115,7 +115,7 @@ SELECT synchdb_add_conninfo('sqlserverconn',
'sa',
'Password!',
'testDB',
- 'postgres',
+ 'dbo',
'null',
'null',
'sqlserver');
@@ -130,7 +130,7 @@ SELECT synchdb_add_conninfo('oracleconn',
'c##dbzuser',
'dbz',
'FREE',
- 'postgres',
+ 'c##dbzuser',
'null',
'null',
'oracle');
@@ -145,7 +145,7 @@ SELECT synchdb_add_conninfo('ora19cconn',
'DBZUSER',
'dbz',
'FREE',
- 'postgres',
+ 'DBZUSER',
'null',
'null',
'oracle');
@@ -160,7 +160,7 @@ SELECT synchdb_add_conninfo('olrconn',
'DBZUSER',
'dbz',
'FREE',
- 'postgres',
+ 'DBZUSER',
'null',
'null',
'olr');
diff --git a/doc/docs/en/getting-started/remote_database_setups.md b/doc/docs/en/getting-started/remote_database_setups.md
index d2155a3..57d22ca 100644
--- a/doc/docs/en/getting-started/remote_database_setups.md
+++ b/doc/docs/en/getting-started/remote_database_setups.md
@@ -272,9 +272,22 @@ ALTER TABLE products ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;
... etc
```
-## **Additional Oracle Setups for Openlog Replicator Support**
+## **Set up Native Openlog Replicator Connector for SynchDB**
-Openlog Replicator requires additional permissions to stream Oracle changes:
+### **Requirements**
+
+- **Openlog Replicator Version**: `1.3.0` ~ `1.8.5` (verified compatibility for Debezium 2.7.x)
+- Oracle instance with redo logs accessible to OLR
+- Additional permissions must be granted for OLR (see below)
+- Openlog Replicator must be configured and running
+- An existing Oracle connector in SynchDB (created using `synchdb_add_conninfo()`)
+- <<<**IMPORTANT**>>> **SynchDB must be compiled and built with flag (WITH_OLR=1) to support native openlog replicator connector.**
+
+Refer to this [external guide](https://highgo.atlassian.net/wiki/external/OTUzY2Q2OWFkNzUzNGVkM2EyZGIyMDE1YzVhMDdkNWE) for details on deploying Openlog Replicator via Docker.
+
+### **Additional Oracle Permissions**
+
+In addition to the settings required for Oracle connector, Openlog Replicator requires additional permissions as below:
```sql
@@ -318,6 +331,127 @@ BEGIN
END;
```
+## **Openlog Replicator Configuration Example**
+
+SynchDB's OLR support is built against the configuration example below.
+
+**Version 1.3.0**
+```json
+{
+ "version": "1.3.0",
+ "source": [
+ {
+ "alias": "SOURCE",
+ "name": "ORACLE",
+ "reader": {
+ "type": "online",
+ "user": "DBZUSER",
+ "password": "dbz",
+ "server": "//ora19c:1521/FREE"
+ },
+ "format": {
+ "type": "json",
+ "column": 2,
+ "db": 3,
+ "interval-dts": 9,
+ "interval-ytm": 4,
+ "message": 2,
+ "rid": 1,
+ "schema": 7,
+ "timestamp-all": 1,
+ "scn-all": 1
+ },
+ "memory": {
+ "min-mb": 64,
+ "max-mb": 1024
+ },
+ "filter": {
+ "table": [
+ {"owner": "DBZUSER", "table": ".*"}
+ ]
+ },
+ "flags": 32
+ }
+ ],
+ "target": [
+ {
+ "alias": "SYNCHDB",
+ "source": "SOURCE",
+ "writer": {
+ "type": "network",
+ "uri": "0.0.0.0:7070"
+ }
+ }
+ ]
+}
+
+```
+
+**Version 1.8.5**
+```json
+{
+ "version": "1.8.5",
+ "source": [
+ {
+ "alias": "SOURCE",
+ "name": "ORACLE",
+ "reader": {
+ "type": "online",
+ "user": "DBZUSER",
+ "password": "dbz",
+ "server": "//ora19c:1521/FREE"
+ },
+ "format": {
+ "type": "json",
+ "column": 2,
+ "db": 3,
+ "interval-dts": 9,
+ "interval-ytm": 4,
+ "message": 2,
+ "rid": 1,
+ "schema": 7,
+ "timestamp-all": 1,
+ "scn-type": 1
+ },
+ "memory": {
+ "min-mb": 64,
+ "max-mb": 1024,
+ "swap-path": "/opt/OpenLogReplicator/olrswap"
+ },
+ "filter": {
+ "table": [
+ {"owner": "DBZUSER", "table": ".*"}
+ ]
+ },
+ "flags": 32
+ }
+ ],
+ "target": [
+ {
+ "alias": "DEBEZIUM",
+ "source": "SOURCE",
+ "writer": {
+ "type": "network",
+ "uri": "0.0.0.0:7070"
+ }
+ }
+ ]
+}
+
+```
+
+Please note the following:
+
+- "source"."name": "ORACLE" -> this should match the `olr_source` value when defining OLR parameters via `synchdb_add_olr_conninfo()` (See below)
+- "source"."reader"."user" -> this should match the `username` value when creating a connector via `synchdb_add_conninfo()`
+- "source"."reader"."password" -> this should match the `password` value when creating a connector via `synchdb_add_conninfo()`
+- "source"."reader"."server" -> this should contain the values of `hostname`, `port` and `source database` values when creating a connector via `synchdb_add_conninfo()`
+- "source"."filter"."table":[] -> this filters the change events that Openlog Replicator captures. <<<**IMPORTANT**>>>: This is currently the only way to filter change events from Oracle as OLR implementations in SynchDB does not do any filtering at this moment. (The `table` and `snapshot table` values are ignored when creating a connector via `synchdb_add_conninfo()`)
+- "format":{} -> the specific paylod format ingested by Debezium based or native Openlog Replicator connector. Use these values as specified.
+- "memory"."swap-path" -> this tells OLR where to write swap files in low memory scenario.
+- "target".[0]."writer"."type": -> this must specify `network` as both Debezium and native Openlog Replicator connector communicate with Openlog Replicator via network
+- "target".[0]."writer"."uri": -> this is the bind host and port Openlog Replicator listens on that SynchDB should be able to access via `olr_host` and `olr_port` when defining OLR parameters via `synchdb_add_olr_conninfo()`.
+
## **Set up Postgres Connector for SynchDB**
PostgreSQL server needs to be configured to be used as a database source to SynchDB
diff --git a/doc/docs/en/tutorial/mysql_cdc_to_postgresql.md b/doc/docs/en/tutorial/mysql_cdc_to_postgresql.md
index 78b6701..8f9cd74 100644
--- a/doc/docs/en/tutorial/mysql_cdc_to_postgresql.md
+++ b/doc/docs/en/tutorial/mysql_cdc_to_postgresql.md
@@ -1,4 +1,4 @@
-# MySQL -> PostgreSQL
+# MySQL Connector
## **Prepare MySQL Database for SynchDB**
@@ -153,7 +153,164 @@ After the initial snapshot, CDC will begin. Restarting a connector in `always` m
## **Preview Source and Destination Table Relationships with schemasync mode**
-Before attempting to do an initial snapshot of current table and data, which may be huge, it is possible to "preview" all the tables and data type mappings between source and destination tables before the actual data migration. This gives you an opportunity to modify a data type mapping, or an object name before actual migration happens. This can be done with the special "schemasync" initial snapshot mode. Refer to [object mapping workflow](../../tutorial/object_mapping_workflow/) for a detailed example.
+Before attempting to do an initial snapshot of current table and data, which may be huge, it is possible to "preview" all the tables and data type mappings between source and destination tables before the actual data migration. This gives you an opportunity to modify a data type mapping, or an object name before actual migration happens. This can be done with the special "schemasync" initial snapshot mode.
+
+Please note that you must set `synchdb.olr_snapshot_engine` to 'fdw' in order to use `schemasync` mode to preview the tables.
+
+### **Create a Connector and Start it in `schemasync` Mode**
+
+`schemasync` is a special mode that makes the connector connects to remote database and attempt to sync only the schema of designated tables. After this is done, the connector is put to `paused` state and user is able to review all the tables and data types created using the default rules and make change if needed.
+
+```sql
+SELECT synchdb_add_conninfo(
+ 'mysqlconn',
+ '127.0.0.1',
+ 3306,
+ 'mysqluser',
+ 'mysqlpwd',
+ 'inventory',
+ 'null',
+ 'null',
+ 'null',
+ 'mysql'
+);
+
+SELECT synchdb_start_engine_bgw('mysqlconn', 'schemasync');
+```
+
+### **Ensure the connector is put to paused state**
+
+```sql
+SELECT name, connector_type, pid, stage, state FROM synchdb_state_view WHERE name = 'mysqlconn';
+ name | connector_type | pid | stage | state
+-----------+----------------+---------+---------------------+--------
+ mysqlconn | mysql | 1644218 | change data capture | paused
+
+```
+
+### **Review the Tables Created by Default Mapping Rules**
+
+```sql
+SELECT * FROM synchdb_att_view WHERE name = 'mysqlconn';
+ name | type | attnum | ext_tbname | pg_tbname | ext_attname | pg_attname | ext_atttypename | pg_atttypename | transform
+
+-----------+----------+--------+----------------------------+----------------------------+--------------+--------------+-------------------+-------------------+----------------------
+------
+ mysqlconn | mysql | 1 | inventory.addresses | inventory.addresses | id | id | int | integer |
+ mysqlconn | mysql | 2 | inventory.addresses | inventory.addresses | customer_id | customer_id | int | integer |
+ mysqlconn | mysql | 3 | inventory.addresses | inventory.addresses | street | street | varchar | character varying |
+ mysqlconn | mysql | 4 | inventory.addresses | inventory.addresses | city | city | varchar | character varying |
+ mysqlconn | mysql | 5 | inventory.addresses | inventory.addresses | state | state | varchar | character varying |
+ mysqlconn | mysql | 6 | inventory.addresses | inventory.addresses | zip | zip | varchar | character varying |
+ mysqlconn | mysql | 7 | inventory.addresses | inventory.addresses | type | type | enum | text |
+ mysqlconn | mysql | 1 | inventory.customers | inventory.customers | id | id | int | integer |
+ mysqlconn | mysql | 2 | inventory.customers | inventory.customers | first_name | first_name | varchar | character varying |
+ mysqlconn | mysql | 3 | inventory.customers | inventory.customers | last_name | last_name | varchar | character varying |
+ mysqlconn | mysql | 4 | inventory.customers | inventory.customers | email | email | varchar | character varying |
+ mysqlconn | mysql | 1 | inventory.geom | inventory.geom | id | id | int | integer |
+ mysqlconn | mysql | 2 | inventory.geom | inventory.geom | g | g | geometry | text |
+ mysqlconn | mysql | 3 | inventory.geom | inventory.geom | h | h | geometry | text |
+ mysqlconn | mysql | 1 | inventory.orders | inventory.orders | order_number | order_number | int | integer |
+ mysqlconn | mysql | 2 | inventory.orders | inventory.orders | order_date | order_date | date | date |
+ mysqlconn | mysql | 3 | inventory.orders | inventory.orders | purchaser | purchaser | int | integer |
+ mysqlconn | mysql | 4 | inventory.orders | inventory.orders | quantity | quantity | int | integer |
+ mysqlconn | mysql | 5 | inventory.orders | inventory.orders | product_id | product_id | int | integer |
+ mysqlconn | mysql | 1 | inventory.products | inventory.products | id | id | int | integer |
+ mysqlconn | mysql | 2 | inventory.products | inventory.products | name | name | varchar | character varying |
+ mysqlconn | mysql | 3 | inventory.products | inventory.products | description | description | varchar | character varying |
+ mysqlconn | mysql | 4 | inventory.products | inventory.products | weight | weight | float | real |
+ mysqlconn | mysql | 1 | inventory.products_on_hand | inventory.products_on_hand | product_id | product_id | int | integer |
+ mysqlconn | mysql | 2 | inventory.products_on_hand | inventory.products_on_hand | quantity | quantity | int | integer |
+
+```
+
+### **Define Custom Mapping (If Needed)**
+
+```sql
+SELECT synchdb_add_objmap('mysqlconn','table','inventory.products','inventory.myproducts');
+SELECT synchdb_add_objmap('mysqlconn','column','inventory.customers.email','contact');
+SELECT synchdb_add_objmap('mysqlconn','datatype','inventory.orders.quantity','bigint|0');
+SELECT synchdb_add_objmap('mysqlconn','transform','inventory.products.name','''>>>>>'' || ''%d'' || ''<<<<<''');
+```
+The above means:
+
+* source table 'inventory.products' will be mapped to 'inventory.myproducts' in destination
+* source column 'inventory.customers.email' will be mapped to 'contact' in destination
+* source data type for column 'inventory.orders.quantity' will be mapped to 'bigint'
+* source column data 'inventory.products.name' will be transformed accoring to the expression where %d is the data placeholder
+
+### **Review All Object Mapping Rules Created So Far**
+
+```sql
+SELECT * FROM synchdb_objmap WHERE name = 'mysqlconn';
+ name | objtype | enabled | srcobj | dstobj
+-----------+-----------+---------+---------------------------+----------------------------
+ mysqlconn | table | t | inventory.products | inventory.myproducts
+ mysqlconn | column | t | inventory.customers.email | contact
+ mysqlconn | datatype | t | inventory.orders.quantity | bigint|0
+ mysqlconn | transform | t | inventory.products.name | '>>>>>' || '%d' || '<<<<<'
+
+```
+
+### **Reload the Object Mapping Rules**
+
+Once all custom rules have been defined, we need to signal the connector to load them. This will cause the connector to read and apply the object mapping rules. If it sees a discrepancy between current PostgreSQL values and the object mapping values, it will attempt to correct the mapping.
+
+```sql
+SELECT synchdb_reload_objmap('mysqlconn');
+
+```
+
+### **Review `synchdb_att_view` Again for Changes**
+
+```sql
+ name | type | attnum | ext_tbname | pg_tbname | ext_attname | pg_attname | ext_atttypename | pg_atttypename | transform
+
+-----------+-------+--------+----------------------------+----------------------------+--------------+--------------+-----------------+-------------------+---------------------------
+-
+ mysqlconn | mysql | 1 | inventory.addresses | inventory.addresses | id | id | int | integer |
+ mysqlconn | mysql | 2 | inventory.addresses | inventory.addresses | customer_id | customer_id | int | integer |
+ mysqlconn | mysql | 3 | inventory.addresses | inventory.addresses | street | street | varchar | character varying |
+ mysqlconn | mysql | 4 | inventory.addresses | inventory.addresses | city | city | varchar | character varying |
+ mysqlconn | mysql | 5 | inventory.addresses | inventory.addresses | state | state | varchar | character varying |
+ mysqlconn | mysql | 6 | inventory.addresses | inventory.addresses | zip | zip | varchar | character varying |
+ mysqlconn | mysql | 7 | inventory.addresses | inventory.addresses | type | type | enum | text |
+ mysqlconn | mysql | 1 | inventory.customers | inventory.customers | id | id | int | integer |
+ mysqlconn | mysql | 2 | inventory.customers | inventory.customers | first_name | first_name | varchar | character varying |
+ mysqlconn | mysql | 3 | inventory.customers | inventory.customers | last_name | last_name | varchar | character varying |
+ mysqlconn | mysql | 4 | inventory.customers | inventory.customers | email | contact | varchar | character varying |
+ mysqlconn | mysql | 1 | inventory.geom | inventory.geom | id | id | int | integer |
+ mysqlconn | mysql | 2 | inventory.geom | inventory.geom | g | g | geometry | text |
+ mysqlconn | mysql | 3 | inventory.geom | inventory.geom | h | h | geometry | text |
+ mysqlconn | mysql | 1 | inventory.orders | inventory.orders | order_number | order_number | int | integer |
+ mysqlconn | mysql | 2 | inventory.orders | inventory.orders | order_date | order_date | date | date |
+ mysqlconn | mysql | 3 | inventory.orders | inventory.orders | purchaser | purchaser | int | integer |
+ mysqlconn | mysql | 4 | inventory.orders | inventory.orders | quantity | quantity | int | bigint |
+ mysqlconn | mysql | 5 | inventory.orders | inventory.orders | product_id | product_id | int | integer |
+ mysqlconn | mysql | 1 | inventory.products | inventory.myproducts | id | id | int | integer |
+ mysqlconn | mysql | 2 | inventory.products | inventory.myproducts | name | name | varchar | character varying | '>>>>>' || '%d' || '<<<<<'
+ mysqlconn | mysql | 3 | inventory.products | inventory.myproducts | description | description | varchar | character varying |
+ mysqlconn | mysql | 4 | inventory.products | inventory.myproducts | weight | weight | float | real |
+ mysqlconn | mysql | 1 | inventory.products_on_hand | inventory.products_on_hand | product_id | product_id | int | integer |
+ mysqlconn | mysql | 2 | inventory.products_on_hand | inventory.products_on_hand | quantity | quantity | int | integer |
+
+
+```
+
+### **Resume the Connector or Redo the Entire Snapshot**
+
+Once the object mappings have been confirmed correct, we can resume the connector. Please note that, resume will proceed to streaming only the new table changes. The existing data of the tables will not be copied.
+
+```sql
+SELECT synchdb_resume_engine('mysqlconn');
+```
+
+To capture the table's existing data, we can also redo the entire snapshot with the new object mapping rules.
+
+```sql
+SELECT synchdb_stop_engine_bgw('mysqlconn');
+SELECT synchdb_start_engine_bgw('mysqlconn', 'always');
+```
## **Selective Table Sync**
@@ -241,3 +398,90 @@ postgres=# \dt inventory.*
inventory | products | table | ubuntu
```
+
+## Secured Connection
+
+### **Configure Secured Connection**
+
+to secure the connection to remote database, we need to configure additional SSL related parameters to a connector that has been created by `synchdb_add_conninfo`. The SSL certificates and private keys must be packaged as Java keystore file with a passphrase. These information is then passed to SynchDB via synchdb_add_extra_conninfo().
+
+### **synchdb_add_extra_conninfo**
+
+**Purpose**: Configures extra connector parameters to an existing connector created by `synchdb_add_conninfo`
+
+| Parameter | Description | Required | Example | Notes |
+|:-:|:-|:-:|:-|:-|
+| `name` | Unique identifier for this connector | ✓ | `'mysqlconn'` | Must be unique across all connectors |
+| `ssl_mode` | SSL mode | ☐ | `'verify_ca'` | can be one of:
- "disabled" - no SSL is used.
- "preferred" - SSL is used if server supports it.
- "required" - SSL must be used to establish a connection.
- "verify_ca" - connector establishes TLS with the server and will also verify server's TLS certificate against configured truststore.
- "verify_identity" - same behavior as verify_ca but it also checks the server certificate's common name to match the hostname of the system. |
+| `ssl_keystore` | keystore path | ☐ | `/path/to/keystore` | path to the keystore file |
+| `ssl_keystore_pass` | keystore password | ☐ | `'mykeystorepass'` | password to access the keystore file |
+| `ssl_truststore` | trust store path | ☐ | `'/path/to/truststore'` | path to the truststore file |
+| `ssl_truststore_pass` | trust store password | ☐ | `'mytruststorepass'` | password to access the truststore file |
+
+
+```sql
+SELECT synchdb_add_extra_conninfo('mysqlconn', 'verify_ca', '/path/to/keystore', 'mykeystorepass', '/path/to/truststore', 'mytruststorepass');
+```
+
+### **synchdb_del_extra_conninfo**
+
+**Purpose**: Deletes extra connector paramters created by `synchdb_add_extra_conninfo`
+```sql
+SELECT synchdb_del_extra_conninfo('mysqlconn');
+```
+
+## Custom Start Offset Values
+
+A start offset value represents a point to start replication from in the similar way as PostgreSQL's resume LSN. When Debezium runner engine starts, it will start the replication from this offset value. Setting this offset value to a earlier value will cause Debezium runner engine to start replication from earlier records, possibly replicating duplicate data records. We should be extra cautious when setting start offset values on Debezium.
+
+### **Record Settable Offset Values**
+
+During operation, new offsets will be generated nd flushed to disk by Debezium runner engine. The last flushed offset can be retrieved from `synchdb_state_view()` utility command:
+
+```sql
+postgres=# select name, last_dbz_offset from synchdb_state_view;
+ name | last_dbz_offset
+---------------+------------------------------------------------------------------------------------------------------
+ mysqlconn | {"ts_sec":1741301103,"file":"mysql-bin.000009","pos":574318212,"row":1,"server_id":223344,"event":2}
+
+```
+
+Depending on the connector type, this offset value differs. From the example above, the `mysql` connector's last flushed offset is `{"ts_sec":1741301103,"file":"mysql-bin.000009","pos":574318212,"row":1,"server_id":223344,"event":2}` and `sqlserver`'s last flushed offset is `{"commit_lsn":"0000006a:00006608:0003","snapshot":true,"snapshot_completed":false}`.
+
+We should save this values regularly, so in case we run into a problem, we know the offset location in the past that can be set to resume the replication operation.
+
+
+### **Pause the Connector**
+
+A connector must be in a `paused` state before a new offset value can be set.
+
+Use `synchdb_pause_engine()` SQL function to pause a runnng connector. This will halt the Debezium runner engine from replicating from the heterogeneous database. When paused, it is possible to alter the Debezium connector's offset value to replicate from a specific point in the past using `synchdb_set_offset()` SQL routine. It takes `conninfo_name` as its argument which can be found from the output of `synchdb_get_state()` view.
+
+For example:
+
+```sql
+SELECT synchdb_pause_engine('mysqlconn');
+```
+
+### **Set the new Offset**
+
+Use `synchdb_set_offset()` SQL function to change a connector worker's starting offset. This can only be done when the connector is put into `paused` state. The function takes 2 parameters, `conninfo_name` and `a valid offset string`, both of which can be found from the output of `synchdb_get_state()` view.
+
+For example:
+
+```sql
+SELECT
+ synchdb_set_offset(
+ 'mysqlconn', '{"ts_sec":1741301103,"file":"mysql-bin.000009","pos":574318212,"row":1,"server_id":223344,"event":2}'
+ );
+```
+
+### **Resume the Connector**
+
+Use `synchdb_resume_engine()` SQL function to resume Debezium operation from a paused state. This function takes `connector name` as its only parameter, which can be found from the output of `synchdb_get_state()` view. The resumed Debezium runner engine will start the replication from the newly set offset value.
+
+For example:
+
+```sql
+SELECT synchdb_resume_engine('mysqlconn');
+```
diff --git a/doc/docs/en/tutorial/native_olr_cdc_to_postgresql.md b/doc/docs/en/tutorial/native_olr_cdc_to_postgresql.md
new file mode 100644
index 0000000..4adc18e
--- /dev/null
+++ b/doc/docs/en/tutorial/native_olr_cdc_to_postgresql.md
@@ -0,0 +1,397 @@
+# Native Openlog Replicator Connector
+
+## **Prepare MySQL Database for SynchDB**
+
+Before SynchDB can be used to replicate from Native Openlog Replicator (OLR) Connector, Both OLR and Oracle database itself need to be configured according to the procedure outlined [here](../../getting-started/remote_database_setups/)
+
+## **Behavior Notes for Native based Openlog Replicator Connector**
+
+* SynchDB manages connections to Openlog Replicator and streams changes without using Debezium.
+* Requires OLR configuration or connector will error on startup.
+* Relies on Debezium's oracle connector to complete initial snapshot and shuts down when done, subsequent CDC is done natively within SynchDB against Openlog Replicator.
+* Relies on IvorySQL's oracle parser to handle DDL events. This must be compiled and installed prior to using native openlog replicator connector.
+* Visit [here](https://github.com/bersler/OpenLogReplicator) for more information about Openlog Replicator.
+
+## **Create a Native Openlog Replicator Connector**
+
+Create a connector that targets all the tables under `FREE` database and schema `DBZUSER` via native Openlog Replicator Connector.
+```sql
+SELECT synchdb_add_conninfo(
+ 'olrconn', '127.0.0.1', 1521, 'DBZUSER',
+ 'dbz', 'FREE', 'DBZUSER',
+ 'null', 'null', 'olr');
+
+SELECT synchdb_add_olr_conninfo(
+ 'olrconn',
+ '127.0.0.1',
+ 7070,
+ 'ORACLE');
+
+```
+
+## **Initial Snapshot**
+"Initial snapshot" (or table snapshot) in SynchDB means to copy table schema plus initial data for all designated tables. This is similar to the term "table sync" in PostgreSQL logical replication. When a connector is started using the default `initial` mode, it will automatically perform the initial snapshot before going to Change Data Capture (CDC) stage. This can be partially omitted with mode `no_data`. See [here](../../user-guide/start_stop_connector/) for all snapshot options.
+
+Once the initial snapshot is completed, the connector will not do it again upon subsequent restarts and will just resume with CDC since the last incomplete offset. This behavior is controled by the metadata files managed by Debezium engine. See [here](../../architecture/metadata_files/) for more about metadata files.
+
+## **Different Connector Launch Modes**
+
+### **Initial Snapshot + CDC**
+
+Start the connector using `initial` mode will perform the initial snapshot of all designated tables (all in this case). After this is completed, the change data capture (CDC) process will begin to stream for new changes.
+
+```sql
+SELECT synchdb_start_engine_bgw('olrconn', 'initial');
+
+or
+
+SELECT synchdb_start_engine_bgw('olrconn');
+```
+
+The stage of this connector should be in `initial snapshot` or `change data capture` if it has processed at least one change event in CDC
+
+```sql
+postgres=# select * from synchdb_state_view;
+ name | connector_type | pid | stage | state | err | last_dbz_offset
+---------+----------------+---------+------------------+---------+----------+-----------------
+ olrconn | olr | 1702522 | initial snapshot | polling | no error | no offset
+
+
+
+```
+
+A new schema called `free` will be created and all tables streamed by the connector will be replicated under that schema.
+```sql
+postgres=# \dt free.*
+ List of tables
+ Schema | Name | Type | Owner
+--------+-----------+-------+--------
+ free | customers | table | ubuntu
+ free | orders | table | ubuntu
+
+```
+
+After the initial snapshot is completed, and at least one subsequent changes is received and processed, the connector stage shall change from `initial snapshot` to `Change Data Capture`.
+```sql
+postgres=# select * from synchdb_state_view;
+ name | connector_type | pid | stage | state | err | last_dbz_offset
+---------+----------------+---------+---------------------+---------+----------+---------------------------------------------
+ olrconn | olr | 1702522 | change data capture | polling | no error | {"scn":5031082, "c_scn":5031085, "c_idx":3}
+
+```
+
+This means that the connector is now streaming for new changes of the designated tables. Restarting the connector in `initial` mode will proceed replication since the last successful point and initial snapshot will not be re-run.
+
+### **Initial Snapshot Only and no CDC**
+
+Start the connector using `initial_only` mode will perform the initial snapshot of all designated tables (all in this case) only and will not perform CDC after.
+
+```sql
+SELECT synchdb_start_engine_bgw('olrconn', 'initial_only');
+
+```
+
+### **Capture Table Schema Only + CDC**
+
+Start the connector using `no_data` mode will perform the schema capture only, build the corresponding tables in PostgreSQL and it does not replicate existing table data (skip initial snapshot). After the schema capture is completed, the connector goes into CDC mode and will start capture subsequent changes to the tables.
+
+```sql
+SELECT synchdb_start_engine_bgw('olrconn', 'no_data');
+
+```
+
+Restarting the connector in `no_data` mode will not rebuild the schema again, and it will resume CDC since the last successful point.
+
+### **CDC only**
+
+Start the connector using `never` will skip schema capture and initial snapshot entirely and will go to CDC mode to capture subsequent changes. Please note that the connector expects all the capture tables have been created in PostgreSQL prior to starting in `never` mode. If the tables do not exist, the connector will encounter an error when it tries to apply a CDC change to a non-existent table.
+
+```sql
+SELECT synchdb_start_engine_bgw('olrconn', 'never');
+
+```
+
+Restarting the connector in `never` mode will resume CDC since the last successful point.
+
+### **Always do Initial Snapahot + CDC**
+
+Start the connector using `always` mode will always capture the schemas of capture tables, always redo the initial snapshot and then go to CDC. This is similar to a reset button because everything will be rebuilt using this mode. Use it with caution especially when you have large number of tables being captured, which could take a long time to finish. After the rebuild, CDC resumes as normal.
+
+```sql
+SELECT synchdb_start_engine_bgw('olrconn', 'always');
+
+```
+
+After the initial snapshot, CDC will begin. Restarting a connector in `always` mode will repeat the same process described above.
+
+## **Possible Snapshot Modes for MySQL Connector**
+
+* initial (default)
+* initial_only
+* no_data
+* never
+* always
+* schemasync
+
+## **Preview Source and Destination Table Relationships with schemasync mode**
+
+Before attempting to do an initial snapshot of current table and data, which may be huge, it is possible to "preview" all the tables and data type mappings between source and destination tables before the actual data migration. This gives you an opportunity to modify a data type mapping, or an object name before actual migration happens. This can be done with the special "schemasync" initial snapshot mode.
+
+Please note that you must set `synchdb.olr_snapshot_engine` to 'fdw' in order to use `schemasync` mode to preview the tables.
+
+### **Create a Connector and Start it in `schemasync` Mode**
+
+`schemasync` is a special mode that makes the connector connects to remote database and attempt to sync only the schema of designated tables. After this is done, the connector is put to `paused` state and user is able to review all the tables and data types created using the default rules and make change if needed.
+
+```sql
+SELECT synchdb_add_conninfo(
+ 'oracleconn',
+ '127.0.0.1',
+ 1521,
+ 'DBZUSER',
+ 'dbz',
+ 'FREE',
+ 'DBZUSER',
+ 'null',
+ 'null',
+ 'oracle'
+);
+
+SELECT synchdb_add_olr_conninfo(
+ 'olrconn',
+ '127.0.0.1',
+ 7070,
+ 'ORACLE');
+
+SELECT synchdb_start_engine_bgw('olrconn', 'schemasync');
+```
+
+### **Ensure the Connector is Put to Paused State**
+
+```sql
+SELECT name, connector_type, pid, stage, state FROM synchdb_state_view WHERE name = 'olrconn';
+ name | connector_type | pid | stage | state
+---------+----------------+---------+---------------------+--------
+ olrconn | olr | 1703430 | change data capture | paused
+
+```
+
+### **Review the Tables Created by Default Mapping Rules**
+
+```sql
+SELECT * FROM synchdb_att_view WHERE name = 'olrconn';
+ name | type | attnum | ext_tbname | pg_tbname | ext_attname | pg_attname | ext_atttypename | pg_atttypename | transform
+---------+--------+--------+------------------------+----------------+--------------+--------------+-----------------+-----------------------------+-----------
+ olrconn | oracle | 1 | FREE.DBZUSER.CUSTOMERS | free.customers | ID | id | number | numeric |
+ olrconn | oracle | 2 | FREE.DBZUSER.CUSTOMERS | free.customers | NAME | name | varchar2 | character varying |
+ olrconn | oracle | 1 | FREE.DBZUSER.ORDERS | free.orders | ORDER_NUMBER | order_number | number | numeric |
+ olrconn | oracle | 2 | FREE.DBZUSER.ORDERS | free.orders | ORDER_DATE | order_date | date | timestamp without time zone |
+ olrconn | oracle | 3 | FREE.DBZUSER.ORDERS | free.orders | PURCHASER | purchaser | number | numeric |
+ olrconn | oracle | 4 | FREE.DBZUSER.ORDERS | free.orders | QUANTITY | quantity | number | numeric |
+ olrconn | oracle | 5 | FREE.DBZUSER.ORDERS | free.orders | PRODUCT_ID | product_id | number | numeric |
+
+```
+
+### **Define Custom Mapping Rules (If Needed)**
+
+User can use `synchdb_add_objmap` function to create custom mapping rules. It can be used to map table name, column name, data types and defines a data transform expression rule
+
+```sql
+SELECT synchdb_add_objmap('olrconn','table','FREE.DBZUSER.ORDERS','free.myorders');
+SELECT synchdb_add_objmap('olrconn','column','FREE.DBZUSER.ORDERS.PURCHASER','who');
+SELECT synchdb_add_objmap('olrconn','datatype','FREE.DBZUSER.ORDERS.QUANTITY','bigint|0');
+SELECT synchdb_add_objmap('olrconn','transform','FREE.DBZUSER.CUSTOMERS.NAME','''>>>>>'' || ''%d'' || ''<<<<<''');
+```
+The above means:
+
+* source table 'FREE.DBZUSER.ORDERS' will be mapped to 'free.myorders' in destination
+* source column 'FREE.DBZUSER.ORDERS.PURCHASE' will be mapped to 'who' in destination
+* source data type for column 'FREE.DBZUSER.ORDERS.QUANTITY' will be mapped to 'bigint'
+* source column data 'FREE.DBZUSER.CUSTOMERS.NAME' will be transformed accoring to the expression where %d is the data placeholder
+
+### **Review All Object Mapping Rules Created So Far**
+
+```sql
+SELECT * FROM synchdb_objmap WHERE name = 'olrconn';
+ name | objtype | enabled | srcobj | dstobj
+---------+-----------+---------+-------------------------------+----------------------------
+ olrconn | table | t | FREE.DBZUSER.ORDERS | free.myorders
+ olrconn | column | t | FREE.DBZUSER.ORDERS.PURCHASER | who
+ olrconn | datatype | t | FREE.DBZUSER.ORDERS.QUANTITY | bigint|0
+ olrconn | transform | t | FREE.DBZUSER.CUSTOMERS.NAME | '>>>>>' || '%d' || '<<<<<'
+
+```
+
+### **Reload the Object Mapping Rules**
+
+Once all custom rules have been defined, we need to signal the connector to load them. This will cause the connector to read and apply the object mapping rules. If it sees a discrepancy between current PostgreSQL values and the object mapping values, it will attempt to correct the mapping.
+
+```sql
+SELECT synchdb_reload_objmap('olrconn');
+
+```
+
+### **Review `synchdb_att_view` Again for Changes**
+
+```sql
+SELECT * from synchdb_att_view WHERE name = 'olrconn';
+ name | type | attnum | ext_tbname | pg_tbname | ext_attname | pg_attname | ext_atttypename | pg_atttypename | transform
+---------+------+--------+------------------------+----------------+--------------+--------------+-----------------+-----------------------------+----------------------------
+ olrconn | olr | 1 | FREE.DBZUSER.CUSTOMERS | free.customers | ID | id | number | numeric |
+ olrconn | olr | 2 | FREE.DBZUSER.CUSTOMERS | free.customers | NAME | name | varchar2 | character varying | '>>>>>' || '%d' || '<<<<<'
+ olrconn | olr | 1 | FREE.DBZUSER.ORDERS | free.myorders | ORDER_NUMBER | order_number | number | numeric |
+ olrconn | olr | 2 | FREE.DBZUSER.ORDERS | free.myorders | ORDER_DATE | order_date | date | timestamp without time zone |
+ olrconn | olr | 3 | FREE.DBZUSER.ORDERS | free.myorders | PURCHASER | who | number | numeric |
+ olrconn | olr | 4 | FREE.DBZUSER.ORDERS | free.myorders | QUANTITY | quantity | number | bigint |
+ olrconn | olr | 5 | FREE.DBZUSER.ORDERS | free.myorders | PRODUCT_ID | product_id | number | numeric |
+
+```
+
+### **Resume the Connector or Redo the Entire Snapshot**
+
+Once the object mappings have been confirmed correct, we can resume the connector. Please note that, resume will proceed to streaming only the new table changes. The existing data of the tables will not be copied.
+
+```sql
+SELECT synchdb_resume_engine('olrconn');
+```
+
+To capture the table's existing data, we can also redo the entire snapshot with the new object mapping rules.
+
+```sql
+SELECT synchdb_stop_engine_bgw('olrconn');
+SELECT synchdb_start_engine_bgw('olrconn', 'always');
+```
+
+## **Selective Table Sync**
+
+### **Select Desired Tables and Start it for the First Time**
+
+Table selection is done during connector creation phase via `synchdb_add_conninfo()` where we specify a list of tables (expressed in FQN, separated by a comma) to replicate from.
+
+For example, the following command creates a connector that only replicates change from `FREE.ORDERS` tables from Oracle.
+
+```sql
+SELECT synchdb_add_conninfo(
+ 'olrconn',
+ '127.0.0.1',
+ 1521,
+ 'DBZUSER',
+ 'dbz',
+ 'FREE',
+ 'DBZUSER',
+ 'DBZUSER.ORDERS',
+ 'null',
+ 'oracle'
+);
+
+SELECT synchdb_add_olr_conninfo(
+ 'olrconn',
+ '127.0.0.1',
+ 7070,
+ 'ORACLE');
+```
+
+Starting this connector for the very first time will trigger an initial snapshot being performed and selected tables' schema and data will be replicated.
+
+```sql
+SELECT synchdb_start_engine_bgw('olrconn');
+```
+
+### **Verify the Connector State and Tables**
+
+Examine the connector state and the new tables:
+
+```sql
+postgres=# Select name, state, err from synchdb_state_view;
+ name | state | err
+---------+---------+----------
+ olrconn | polling | no error
+
+postgres=# \dt free.*
+ List of tables
+ Schema | Name | Type | Owner
+--------+--------+-------+--------
+ free | orders | table | ubuntu
+
+```
+
+By default, source database name is mapped to a schema in destination with letter casing strategy = lowercase, so `FREE.ORDERS` becomes `free.orders` in postgreSQL. Once the tables have done the initial snapshot, the connector will start CDC to stream subsequent changes for these tables.
+
+### **Add More Tables to Replicate During Run Time.**
+
+The `olrconn` from previous section has already completed the initial snapshot and obtained the table schemas of the selected table. If we would like to add more tables to replicate from, we will need to notify the Debezium engine about the updated table section and perform the initial snapshot again. Here's how it is done:
+
+1. Update the `synchdb_conninfo` table to include additional tables.
+2. In this example, we add the `DBZUSER.CUSTOMERS` table to the sync list:
+
+```sql
+UPDATE synchdb_conninfo
+SET data = jsonb_set(data, '{table}', '"DBZUSER.ORDERS,DBZUSER.CUSTOMERS"')
+WHERE name = 'olrconn';
+```
+
+3. Restart the connector with the snapshot mode set to `always` to perform another initial snapshot:
+
+```sql
+DROP table free.orders;
+SELECT synchdb_restart_connector('olrconn', 'always');
+```
+
+This forces Debezium to re-snapshot all the tables again, including the existing tables `free.orders` and the new `free.customers` before going to CDC streaming. This means, to add a new table, the existing tables have to be dropped (to prevent duplicate table and primary key errors) and do the entire initial snapshot again. This is quite redundant and Debezium suggests using incremental snasphot to add the addition tables without re-snapshotting. We will update this procedure once we add the incremental snapshot support to SynchDB.
+
+### **Filter Openlog Replicator Tables (IMPORTANT)**
+
+For initial snapshot (via Debezium or FDW), we are able to select desired tables to replicate, but once the connector enters CDC stage via Openlog Replicator, the selected table filter does not automatically apply to Openlog Replicator. The user is required to configure Openlog Replicator service to output change events only for selected tables. If there is a discrepancy between SynchDB and Openlog Replicator's table filter, it is possible for SynchDB to receive a change event that it has not created a table for, causing an error. Therefore, it is a good practice to configure both SynchDB and Openlog Replicator to the same table filters.
+
+## Custom Start Offset Values
+
+A start offset value represents a point to start replication from in the similar way as PostgreSQL's resume LSN. When Debezium runner engine starts, it will start the replication from this offset value. Setting this offset value to a earlier value will cause Debezium runner engine to start replication from earlier records, possibly replicating duplicate data records. We should be extra cautious when setting start offset values on Debezium.
+
+### **Record Settable Offset Values**
+
+During operation, new offsets will be generated and flushed to disk by Debezium runner engine. The last flushed offset can be retrieved from `synchdb_state_view()` utility command:
+
+```sql
+postgres=# select name, last_dbz_offset from synchdb_state_view;
+ name | last_dbz_offset
+---------+---------------------------------------------
+ olrconn | {"scn":5044305, "c_scn":5044300, "c_idx":3}
+
+```
+
+We should save this values regularly, so in case we run into a problem, we know the offset location in the past that can be set to resume the replication operation.
+
+### **Pause the Connector**
+
+A connector must be in a `paused` state before a new offset value can be set.
+
+Use `synchdb_pause_engine()` SQL function to pause a runnng connector. This will halt the Debezium runner engine from replicating from the heterogeneous database. When paused, it is possible to alter the Debezium connector's offset value to replicate from a specific point in the past using `synchdb_set_offset()` SQL routine. It takes `conninfo_name` as its argument which can be found from the output of `synchdb_get_state()` view.
+
+For example:
+
+```sql
+SELECT synchdb_pause_engine('olrconn');
+```
+
+### **Set the new Offset**
+
+Use `synchdb_set_offset()` SQL function to change a connector worker's starting offset. This can only be done when the connector is put into `paused` state. The function takes 2 parameters, `conninfo_name` and `a valid offset string`, both of which can be found from the output of `synchdb_get_state()` view.
+
+For example:
+
+```sql
+SELECT
+ synchdb_set_offset(
+ 'olrconn', '{"scn":5044305, "c_scn":5044300, "c_idx":3}'
+ );
+```
+
+### **Resume the Connector**
+
+Use `synchdb_resume_engine()` SQL function to resume Debezium operation from a paused state. This function takes `connector name` as its only parameter, which can be found from the output of `synchdb_get_state()` view. The resumed Debezium runner engine will start the replication from the newly set offset value.
+
+For example:
+
+```sql
+SELECT synchdb_resume_engine('olrconn');
+```
\ No newline at end of file
diff --git a/doc/docs/en/tutorial/object_mapping_workflow.md b/doc/docs/en/tutorial/object_mapping_workflow.md
deleted file mode 100644
index 29a646e..0000000
--- a/doc/docs/en/tutorial/object_mapping_workflow.md
+++ /dev/null
@@ -1,132 +0,0 @@
-# Object Mapping Workflow
-
-## **Create a Connector and Start it in `schemasync` Mode**
-
-`schemasync` is a special mode that makes the connector connects to remote database and attempt to sync only the schema of designated tables. After this is done, the connector is put to `paused` state and user is able to review all the tables and data types created using the default rules and make change if needed.
-
-```sql
-SELECT synchdb_add_conninfo(
- 'mysqlconn',
- '127.0.0.1',
- 3306,
- 'mysqluser',
- 'mysqlpwd',
- 'inventory',
- 'null',
- 'null',
- 'mysql');
-
-SELECT synchdb_start_engine_bgw('mysqlconn', 'schemasync');
-```
-## **Ensure the connector is put to paused state**
-```sql
-SELECT name, connector_type, pid, stage, state FROM synchdb_state_view;
- name | connector_type | pid | stage | state
----------------+----------------+--------+-------------+---------
- mysqlconn | mysql | 579845 | schema sync | polling
-
-```
-
-## **Review the tables created by default mapping rules**
-
-```sql
-postgres=# select * from synchdb_att_view;
- name | type | attnum | ext_tbname | pg_tbname | ext_attname | pg_attname | ext_atttypename | pg_atttypename | transform
------------+-------+--------+----------------------------+----------------------------+-------------+-------------+-----------------+----------------+-----------
- mysqlconn | mysql | 1 | inventory.addresses | inventory.addresses | id | id | INT | int4 |
- mysqlconn | mysql | 2 | inventory.addresses | inventory.addresses | customer_id | customer_id | INT | int4 |
- mysqlconn | mysql | 3 | inventory.addresses | inventory.addresses | street | street | VARCHAR | varchar |
- mysqlconn | mysql | 4 | inventory.addresses | inventory.addresses | city | city | VARCHAR | varchar |
- mysqlconn | mysql | 5 | inventory.addresses | inventory.addresses | state | state | VARCHAR | varchar |
- mysqlconn | mysql | 6 | inventory.addresses | inventory.addresses | zip | zip | VARCHAR | varchar |
- mysqlconn | mysql | 7 | inventory.addresses | inventory.addresses | type | type | ENUM | text |
- mysqlconn | mysql | 1 | inventory.customers | inventory.customers | id | id | INT | int4 |
- mysqlconn | mysql | 2 | inventory.customers | inventory.customers | first_name | first_name | VARCHAR | varchar |
- mysqlconn | mysql | 3 | inventory.customers | inventory.customers | last_name | last_name | VARCHAR | varchar |
- mysqlconn | mysql | 4 | inventory.customers | inventory.customers | email | email | VARCHAR | varchar |
- mysqlconn | mysql | 1 | inventory.geom | inventory.geom | id | id | INT | int4 |
- mysqlconn | mysql | 2 | inventory.geom | inventory.geom | g | g | GEOMETRY | text |
- mysqlconn | mysql | 3 | inventory.geom | inventory.geom | h | h | GEOMETRY | text |
- mysqlconn | mysql | 1 | inventory.products | inventory.products | id | id | INT | int4 |
- mysqlconn | mysql | 2 | inventory.products | inventory.products | name | name | VARCHAR | varchar |
- mysqlconn | mysql | 3 | inventory.products | inventory.products | description | description | VARCHAR | varchar |
- mysqlconn | mysql | 4 | inventory.products | inventory.products | weight | weight | FLOAT | float4 |
- mysqlconn | mysql | 1 | inventory.products_on_hand | inventory.products_on_hand | product_id | product_id | INT | int4 |
- mysqlconn | mysql | 2 | inventory.products_on_hand | inventory.products_on_hand | quantity | quantity | INT | int4 |
-(20 rows)
-
-```
-
-## **Define custom mapping rules**
-User can use `synchdb_add_objmap` function to create custom mapping rules. It can be used to map table name, column name, data types and defines a data transform expression rule
-
-```sql
-SELECT synchdb_add_objmap('mysqlconn','table','inventory.products','stuff');
-SELECT synchdb_add_objmap('mysqlconn','table','inventory.customers','schema1.people');
-SELECT synchdb_add_objmap('mysqlconn','column','inventory.customers.last_name','family_name');
-SELECT synchdb_add_objmap('mysqlconn','column','inventory.customers.email','contact');
-SELECT synchdb_add_objmap('mysqlconn','datatype','inventory.geom.g','geometry|0');
-SELECT synchdb_add_objmap('mysqlconn','datatype','inventory.orders.quantity','bigint|0');
-SELECT synchdb_add_objmap('mysqlconn','transform','inventory.products.name','''>>>>>'' || ''%d'' || ''<<<<<''');
-```
-
-## **Review all object mapping rules created so far**
-```sql
-postgres=# select * from synchdb_objmap;
- name | objtype | enabled | srcobj | dstobj
------------+-----------+---------+-------------------------------+----------------------------
- mysqlconn | table | t | inventory.products | stuff
- mysqlconn | column | t | inventory.customers.last_name | family_name
- mysqlconn | column | t | inventory.customers.email | contact
- mysqlconn | table | t | inventory.customers | schema1.people
- mysqlconn | transform | t | inventory.products.name | '>>>>>' || '%d' || '<<<<<'
- mysqlconn | datatype | t | inventory.geom.g | geometry|0
- mysqlconn | datatype | t | inventory.orders.quantity | bigint|0
-(7 rows)
-
-```
-
-## **Reload the object mapping rules**
-Once all custom rules have been defined, we need to signal the connector to load them. This will cause the connector to read and apply the object mapping rules. If it sees a discrepancy between current PostgreSQL values and the object mapping values, it will attempt to correct the mapping.
-```sql
-SELECT synchdb_reload_objmap('mysqlconn');
-
-```
-
-## **Review `synchdb_att_view` again for changes**
-```sql
-SELECT * from synchdb_att_view;
- name | type | attnum | ext_tbname | pg_tbname | ext_attname | pg_attname | ext_atttypename | pg_atttypename | transform
------------+-------+--------+----------------------------+----------------------------+-------------+-------------+-----------------+----------------+----------------------------
- mysqlconn | mysql | 1 | inventory.addresses | inventory.addresses | id | id | INT | int4 |
- mysqlconn | mysql | 2 | inventory.addresses | inventory.addresses | customer_id | customer_id | INT | int4 |
- mysqlconn | mysql | 3 | inventory.addresses | inventory.addresses | street | street | VARCHAR | varchar |
- mysqlconn | mysql | 4 | inventory.addresses | inventory.addresses | city | city | VARCHAR | varchar |
- mysqlconn | mysql | 5 | inventory.addresses | inventory.addresses | state | state | VARCHAR | varchar |
- mysqlconn | mysql | 6 | inventory.addresses | inventory.addresses | zip | zip | VARCHAR | varchar |
- mysqlconn | mysql | 7 | inventory.addresses | inventory.addresses | type | type | ENUM | text |
- mysqlconn | mysql | 1 | inventory.customers | schema1.people | id | id | INT | int4 |
- mysqlconn | mysql | 2 | inventory.customers | schema1.people | first_name | first_name | VARCHAR | varchar |
- mysqlconn | mysql | 3 | inventory.customers | schema1.people | last_name | family_name | VARCHAR | varchar |
- mysqlconn | mysql | 4 | inventory.customers | schema1.people | email | contact | VARCHAR | varchar |
- mysqlconn | mysql | 1 | inventory.geom | inventory.geom | id | id | INT | int4 |
- mysqlconn | mysql | 2 | inventory.geom | inventory.geom | g | g | GEOMETRY | geometry |
- mysqlconn | mysql | 3 | inventory.geom | inventory.geom | h | h | GEOMETRY | text |
- mysqlconn | mysql | 1 | inventory.products | public.stuff | id | id | INT | int4 |
- mysqlconn | mysql | 2 | inventory.products | public.stuff | name | name | VARCHAR | varchar | '>>>>>' || '%d' || '<<<<<'
- mysqlconn | mysql | 3 | inventory.products | public.stuff | description | description | VARCHAR | varchar |
- mysqlconn | mysql | 4 | inventory.products | public.stuff | weight | weight | FLOAT | float4 |
- mysqlconn | mysql | 1 | inventory.products_on_hand | inventory.products_on_hand | product_id | product_id | INT | int4 |
- mysqlconn | mysql | 2 | inventory.products_on_hand | inventory.products_on_hand | quantity | quantity | INT | int8 |
-```
-
-## **Resume the connector or redo the entire snapshot**
-Once the object mappings have been confirmed correct, we can resume the connector. Please note that, resume will proceed to streaming only the new table changes. The existing data of the tables will not be copied.
-```sql
-SELECT synchdb_resume_engine('mysqlconn');
-```
-
-To capture the table's existing data, we can also redo the entire snapshot with the new object mapping rules:
-```sql
-SELECT synchdb_restart_connector('mysqlconn', 'always');
-```
diff --git a/doc/docs/en/tutorial/oracle_cdc_to_postgresql.md b/doc/docs/en/tutorial/oracle_cdc_to_postgresql.md
index e48e156..1b820f9 100644
--- a/doc/docs/en/tutorial/oracle_cdc_to_postgresql.md
+++ b/doc/docs/en/tutorial/oracle_cdc_to_postgresql.md
@@ -1,4 +1,4 @@
-# Oracle -> PostgreSQL
+# Oracle Connector
## **Prepare Oracle Database for SynchDB**
@@ -121,7 +121,125 @@ After the initial snapshot, CDC will begin. Restarting a connector in `always` m
## **Preview Source and Destination Table Relationships with schemasync mode**
-Before attempting to do an initial snapshot of current table and data, which may be huge, it is possible to "preview" all the tables and data type mappings between source and destination tables before the actual data migration. This gives you an opportunity to modify a data type mapping, or an object name before actual migration happens. This can be done with the special "schemasync" initial snapshot mode. Refer to [object mapping workflow](../../tutorial/object_mapping_workflow/) for a detailed example.
+Before attempting to do an initial snapshot of current table and data, which may be huge, it is possible to "preview" all the tables and data type mappings between source and destination tables before the actual data migration. This gives you an opportunity to modify a data type mapping, or an object name before actual migration happens. This can be done with the special "schemasync" initial snapshot mode.
+
+### **Create a Connector and Start it in `schemasync` Mode**
+
+`schemasync` is a special mode that makes the connector connects to remote database and attempt to sync only the schema of designated tables. After this is done, the connector is put to `paused` state and user is able to review all the tables and data types created using the default rules and make change if needed.
+
+```sql
+SELECT synchdb_add_conninfo(
+ 'oracleconn',
+ '127.0.0.1',
+ 1521,
+ 'DBZUSER',
+ 'dbz',
+ 'FREE',
+ 'DBZUSER',
+ 'null',
+ 'null',
+ 'oracle'
+);
+
+SELECT synchdb_start_engine_bgw('oracleconn', 'schemasync');
+```
+
+### **Ensure the Connector is Put to Paused State**
+
+```sql
+SELECT name, connector_type, pid, stage, state FROM synchdb_state_view WHERE name = 'oracleconn';
+ name | connector_type | pid | stage | state
+------------+----------------+---------+---------------------+--------
+ oracleconn | oracle | 1648935 | change data capture | paused
+
+
+```
+
+### **Review the Tables Created by Default Mapping Rules**
+
+```sql
+SELECT * FROM synchdb_att_view WHERE name = 'oracleconn';
+ name | type | attnum | ext_tbname | pg_tbname | ext_attname | pg_attname | ext_atttypename | pg_atttypename | transform
+------------+--------+--------+------------------------+----------------+--------------+--------------+-----------------+-----------------------------+-----------
+ oracleconn | oracle | 1 | FREE.DBZUSER.CUSTOMERS | free.customers | ID | id | number | numeric |
+ oracleconn | oracle | 2 | FREE.DBZUSER.CUSTOMERS | free.customers | NAME | name | varchar2 | character varying |
+ oracleconn | oracle | 1 | FREE.DBZUSER.ORDERS | free.orders | ORDER_NUMBER | order_number | number | numeric |
+ oracleconn | oracle | 2 | FREE.DBZUSER.ORDERS | free.orders | ORDER_DATE | order_date | date | timestamp without time zone |
+ oracleconn | oracle | 3 | FREE.DBZUSER.ORDERS | free.orders | PURCHASER | purchaser | number | numeric |
+ oracleconn | oracle | 4 | FREE.DBZUSER.ORDERS | free.orders | QUANTITY | quantity | number | numeric |
+ oracleconn | oracle | 5 | FREE.DBZUSER.ORDERS | free.orders | PRODUCT_ID | product_id | number | numeric |
+
+```
+
+### **Define Custom Mapping Rules (If Needed)**
+
+User can use `synchdb_add_objmap` function to create custom mapping rules. It can be used to map table name, column name, data types and defines a data transform expression rule
+
+```sql
+SELECT synchdb_add_objmap('oracleconn','table','FREE.DBZUSER.ORDERS','free.myorders');
+SELECT synchdb_add_objmap('oracleconn','column','FREE.DBZUSER.ORDERS.PURCHASER','who');
+SELECT synchdb_add_objmap('oracleconn','datatype','FREE.DBZUSER.ORDERS.QUANTITY','bigint|0');
+SELECT synchdb_add_objmap('oracleconn','transform','FREE.DBZUSER.CUSTOMERS.NAME','''>>>>>'' || ''%d'' || ''<<<<<''');
+```
+The above means:
+
+* source table 'FREE.DBZUSER.ORDERS' will be mapped to 'free.myorders' in destination
+* source column 'FREE.DBZUSER.ORDERS.PURCHASE' will be mapped to 'who' in destination
+* source data type for column 'FREE.DBZUSER.ORDERS.QUANTITY' will be mapped to 'bigint'
+* source column data 'FREE.DBZUSER.CUSTOMERS.NAME' will be transformed accoring to the expression where %d is the data placeholder
+
+### **Review All Object Mapping Rules Created So Far**
+
+```sql
+SELECT * FROM synchdb_objmap WHERE name = 'oracleconn';
+ name | objtype | enabled | srcobj | dstobj
+------------+-----------+---------+-------------------------------+----------------------------
+ oracleconn | table | t | FREE.DBZUSER.ORDERS | free.myorders
+ oracleconn | column | t | FREE.DBZUSER.ORDERS.PURCHASER | who
+ oracleconn | datatype | t | FREE.DBZUSER.ORDERS.QUANTITY | bigint|0
+ oracleconn | transform | t | FREE.DBZUSER.CUSTOMERS.NAME | '>>>>>' || '%d' || '<<<<<'
+
+```
+
+### **Reload the Object Mapping Rules**
+
+Once all custom rules have been defined, we need to signal the connector to load them. This will cause the connector to read and apply the object mapping rules. If it sees a discrepancy between current PostgreSQL values and the object mapping values, it will attempt to correct the mapping.
+
+```sql
+SELECT synchdb_reload_objmap('oracleconn');
+
+```
+
+### **Review `synchdb_att_view` Again for Changes**
+
+```sql
+SELECT * from synchdb_att_view WHERE name = 'oracleconn';
+ name | type | attnum | ext_tbname | pg_tbname | ext_attname | pg_attname | ext_atttypename | pg_atttypename | transform
+------------+--------+--------+------------------------+----------------+--------------+--------------+-----------------+-----------------------------+----------------------------
+ oracleconn | oracle | 1 | FREE.DBZUSER.CUSTOMERS | free.customers | ID | id | number | numeric |
+ oracleconn | oracle | 2 | FREE.DBZUSER.CUSTOMERS | free.customers | NAME | name | varchar2 | character varying | '>>>>>' || '%d' || '<<<<<'
+ oracleconn | oracle | 1 | FREE.DBZUSER.ORDERS | free.myorders | ORDER_NUMBER | order_number | number | numeric |
+ oracleconn | oracle | 2 | FREE.DBZUSER.ORDERS | free.myorders | ORDER_DATE | order_date | date | timestamp without time zone |
+ oracleconn | oracle | 3 | FREE.DBZUSER.ORDERS | free.myorders | PURCHASER | who | number | numeric |
+ oracleconn | oracle | 4 | FREE.DBZUSER.ORDERS | free.myorders | QUANTITY | quantity | number | bigint |
+ oracleconn | oracle | 5 | FREE.DBZUSER.ORDERS | free.myorders | PRODUCT_ID | product_id | number | numeric |
+
+```
+
+### **Resume the Connector or Redo the Entire Snapshot**
+
+Once the object mappings have been confirmed correct, we can resume the connector. Please note that, resume will proceed to streaming only the new table changes. The existing data of the tables will not be copied.
+
+```sql
+SELECT synchdb_resume_engine('oracleconn');
+```
+
+To capture the table's existing data, we can also redo the entire snapshot with the new object mapping rules.
+
+```sql
+SELECT synchdb_stop_engine_bgw('oracleconn');
+SELECT synchdb_start_engine_bgw('oracleconn', 'always');
+```
## **Selective Table Sync**
@@ -129,7 +247,8 @@ Before attempting to do an initial snapshot of current table and data, which may
Table selection is done during connector creation phase via `synchdb_add_conninfo()` where we specify a list of tables (expressed in FQN, separated by a comma) to replicate from.
-For example, the following command creates a connector that only replicates change from `inventory.orders` and `inventory.products` tables from remote MySQL database.
+For example, the following command creates a connector that only replicates change from `FREE.ORDERS` tables from Oracle.
+
```sql
SELECT synchdb_add_conninfo(
'oracleconn',
@@ -154,6 +273,7 @@ SELECT synchdb_start_engine_bgw('oracleconn');
### **Verify the Connector State and Tables**
Examine the connector state and the new tables:
+
```sql
postgres=# Select name, state, err from synchdb_state_view;
name | state | err
@@ -175,21 +295,26 @@ The `oracleconn` from previous section has already completed the initial snapsho
1. Update the `synchdb_conninfo` table to include additional tables.
2. In this example, we add the `DBZUSER.CUSTOMERS` table to the sync list:
+
```sql
UPDATE synchdb_conninfo
SET data = jsonb_set(data, '{table}', '"DBZUSER.ORDERS,DBZUSER.CUSTOMERS"')
WHERE name = 'oracleconn';
```
+
3. Restart the connector with the snapshot mode set to `always` to perform another initial snapshot:
+
```sql
DROP table free.orders;
SELECT synchdb_restart_connector('oracleconn', 'always');
```
+
This forces Debezium to re-snapshot all the tables again, including the existing tables `free.orders` and the new `free.customers` before going to CDC streaming. This means, to add a new table, the existing tables have to be dropped (to prevent duplicate table and primary key errors) and do the entire initial snapshot again. This is quite redundant and Debezium suggests using incremental snasphot to add the addition tables without re-snapshotting. We will update this procedure once we add the incremental snapshot support to SynchDB.
### **Verify the Updated Tables**
Now, we can examine our tables again:
+
```sql
postgres=# \dt free.*
List of tables
@@ -198,4 +323,246 @@ postgres=# \dt free.*
free | orders | table | ubuntu
customers | orders | table | ubuntu
-```
\ No newline at end of file
+```
+
+## **Configure Infinispan for Oracle Connector**
+
+By default, Debezium's Oracle connector uses the JVM heap to cache incoming change events before passing them to SynchDB for processing. The maximum heap size is controlled via the `synchdb.jvm_max_heap_size` GUC. When the JVM heap runs out of memory (especially under large transactions or schemas with many columns), the connector may fail with OutOfMemoryError, making heap sizing a critical tuning challenge.
+
+As an alternative, Debezium can be configured to use Infinispan as its caching layer. Infinispan supports memory storage on both the JVM heap and off-heap (direct memory), offering more flexibility. Additionally, it supports passivation, allowing excess data to be spilled to disk when memory limits are reached. This makes it far more resilient under heavy workloads and ensures large transactions or schema changes can be handled gracefully without running out of memory.
+
+### **`synchdb_add_infinispan()`**
+
+**Signature:**
+
+```sql
+synchdb_add_infinispan(
+ connectorName NAME, -- Name of the connector
+ memoryType NAME, -- memory type, can be "heap" or "off heap"
+ memorySize INT -- size of memory in MB to reserve as cache
+)
+```
+
+Registers an Infinispan-backed caching configuration for a given connector. This allows the connector to use Infinispan for buffering change events, supporting both heap-based and off-heap memory allocation with spill-to-disk (passivation).
+
+**Note:**
+
+- If called on a connector that is currently running, the setting will take effect on next restart.
+- If an Infinispan cache already exists for the connector, it will be replaced.
+- memoryType='off_heap' utilizes native (direct) memory and is not limited by JVM heap, but should be sized carefully.
+- The cache will automatically support passivation to disk when memory fills.
+
+**Example:**
+``` sql
+SELECT synchdb_add_infinispan('oracleconn', 'off_heap', 2048);
+
+
+
+```
+
+### **`synchdb_del_infinispan()`**
+
+**Signature:**
+
+```sql
+synchdb_add_infinispan(
+ connectorName NAME -- Name of the connector
+)
+```
+
+Removes the Infinispan cache configuration and associated on-disk metadata for a given connector. This operation will delete:
+
+- All cache files
+- Any passivated (spilled-to-disk) state
+- The associated Infinispan configuration
+
+**Note:**
+
+- This function can only be executed when the connector is stopped.
+- Attempting to run it while the connector is active will result in an error.
+- Use this command to clean up after permanently disabling or reconfiguring a connector’s cache backend.
+
+**Example:**
+``` sql
+SELECT synchdb_del_infinispan('oracleconn');
+
+```
+
+### **`Passivation`**
+
+Passivation simply means infinispan will eject and write data on disk if cache memory is full. As long as there is space in memory to hold change events, disk write will not occur. The data is written to `$PGDATA/pg_synchdb/ispn_[connector name]_[destination database name]`
+
+
+### **Example Oracle SQLs to test Infinispan with a Large Transaction**
+
+**Create a test table in Oracle:**
+```sql
+CREATE TABLE big_tx_test (
+ id NUMBER PRIMARY KEY,
+ payload VARCHAR2(4000),
+ created DATE DEFAULT SYSDATE
+);
+
+```
+
+**Create a relatively large transaction:**
+```sql
+BEGIN
+ FOR i IN 1..100000 LOOP
+ INSERT INTO big_tx_test (id, payload)
+ VALUES (i, RPAD('x', 4000, 'x'));
+ END LOOP;
+ COMMIT;
+END;
+/
+
+```
+
+**Behaviors Under Large Transaction**
+
+no infinispan setting + low JVM heap (synchdb.jvm_max_heap_size=128)
+
+* --> OutOfMemory error will occur
+
+low JVM heap (128) + high infinispan off heap (2048)
+
+* --> large transaction handled successfully
+
+low JVM heap (128) + low infinispan off heap (128)
+
+* --> passivation will occur
+* --> `ispn_[connector name]_[destination database name]` size will grow during processing and reduce once large transaction finished processing
+* --> large transaction handled successfully but at slower speed.
+
+low JVM heap (128) + high infinispan heap (2048)
+
+* --> OutOfMemory error will occur
+* --> do not configure infinispan to use more heap memory than JVM max heap.
+
+low JVM heap (128) + low infinispan heap (64)
+
+* --> passivation will occur
+* --> `ispn_[connector name]_[destination database name]` size will grow during processing and reduce once large transaction finished processing
+* --> not recommended as half of the JVM heap can potentially be used by infinispan and may not have enough left for other Debezium operations
+
+low JVM heap (128) + same infinispan heap (128)
+
+* --> not recommended as all of the JVM heap can potentially be used by infinispan and eventually causing OutOfMemory error
+
+high JVM heap (2048) + low infinispan heap (128)
+
+* --> passivation will occur
+* --> `ispn_[connector name]_[destination database name]` size will grow during processing and reduce once large transaction finished processing
+* --> large transaction handled successfully
+* --> not efficient - as only a small portion of JVM heap is used as cache + unnessary passivation.
+
+## Custom Start Offset Values
+
+A start offset value represents a point to start replication from in the similar way as PostgreSQL's resume LSN. When Debezium runner engine starts, it will start the replication from this offset value. Setting this offset value to a earlier value will cause Debezium runner engine to start replication from earlier records, possibly replicating duplicate data records. We should be extra cautious when setting start offset values on Debezium.
+
+### **Record Settable Offset Values**
+
+During operation, new offsets will be generated and flushed to disk by Debezium runner engine. The last flushed offset can be retrieved from `synchdb_state_view()` utility command:
+
+```sql
+postgres=# select name, last_dbz_offset from synchdb_state_view;
+ name | last_dbz_offset
+---------------+------------------------------------------------------------------------------------------------------
+ oracleconn | {"commit_scn":"2311579","snapshot_scn":"2311578","scn":"2311578"}
+
+```
+
+We should save this values regularly, so in case we run into a problem, we know the offset location in the past that can be set to resume the replication operation.
+
+### **Pause the Connector**
+
+A connector must be in a `paused` state before a new offset value can be set.
+
+Use `synchdb_pause_engine()` SQL function to pause a runnng connector. This will halt the Debezium runner engine from replicating from the heterogeneous database. When paused, it is possible to alter the Debezium connector's offset value to replicate from a specific point in the past using `synchdb_set_offset()` SQL routine. It takes `conninfo_name` as its argument which can be found from the output of `synchdb_get_state()` view.
+
+For example:
+
+```sql
+SELECT synchdb_pause_engine('oracleconn');
+```
+
+### **Set the new Offset**
+
+Use `synchdb_set_offset()` SQL function to change a connector worker's starting offset. This can only be done when the connector is put into `paused` state. The function takes 2 parameters, `conninfo_name` and `a valid offset string`, both of which can be found from the output of `synchdb_get_state()` view.
+
+For example:
+
+```sql
+SELECT
+ synchdb_set_offset(
+ 'oracleconn', '{"commit_scn":"2311579","snapshot_scn":"2311578","scn":"2311578"}'
+ );
+```
+
+### **Resume the Connector**
+
+Use `synchdb_resume_engine()` SQL function to resume Debezium operation from a paused state. This function takes `connector name` as its only parameter, which can be found from the output of `synchdb_get_state()` view. The resumed Debezium runner engine will start the replication from the newly set offset value.
+
+For example:
+
+```sql
+SELECT synchdb_resume_engine('oracleconn');
+```
+
+## Configure Debezium Oracle Connector to Use Openlog Replicator (non-native)
+
+Though not recommended, it is possible to configure a Debezium based Oracle Connector to stream from Openlog Replicator instead of logminer. It is different from [Native Openlog Replicator](../../tutorial/native_olr_cdc_to_postgresql), which is built natively within SynchDB without the use of Debezium and is the recommended way to use OLR.
+
+To create a **Debezium-based** OLR connector (use `type` = 'oracle'):
+
+```sql
+SELECT synchdb_add_conninfo('olrconn',
+ 'ora19c',
+ 1521,
+ 'DBZUSER',
+ 'dbz',
+ 'FREE',
+ 'postgres',
+ 'null',
+ 'null',
+ 'oracle');
+
+```
+
+Then, attach Openlog Replicator information with `synchdb_add_olr_conninfo` with signature:
+
+```sql
+synchdb_add_olr_conninfo(
+ conn_name TEXT, -- Name of the connector
+ olr_host TEXT, -- Hostname or IP of the OLR instance
+ olr_port INT, -- Port number exposed by OLR (typically 7070)
+ olr_source TEXT -- Oracle source name as configured in OLR
+)
+```
+
+**Example:**
+
+```sql
+SELECT synchdb_add_olr_conninfo('olrconn', '127.0.0.1', 7070, 'ORACLE');
+
+```
+
+To removes the OLR configuration from a specific connector and revert back to Logminer, use `synchdb_del_olr_conninfo` with signature:
+
+```sql
+synchdb_del_olr_conninfo(conn_name TEXT)
+
+```
+
+**Example:**
+
+```sql
+SELECT synchdb_del_olr_conninfo('olrconn');
+
+```
+
+**Behavior Notes for Debezium based Openlog Replicator Connector**
+
+* When both LogMiner and OLR configurations exist, SynchDB defaults to using Openlog Replicator for change capture.
+* If OLR configurations are absent, SynchDB uses logmining strategy to stream changes.
+* Restarting the connector is required after modifying its OLR configuration.
\ No newline at end of file
diff --git a/doc/docs/en/tutorial/postgresql_cdc_to_postgresql.md b/doc/docs/en/tutorial/postgresql_cdc_to_postgresql.md
index 101e1a8..15dbfbb 100644
--- a/doc/docs/en/tutorial/postgresql_cdc_to_postgresql.md
+++ b/doc/docs/en/tutorial/postgresql_cdc_to_postgresql.md
@@ -1,4 +1,4 @@
-# Postgres -> Postgres
+# Postgres Connector
## **Prepare PostgreSQL Database for SynchDB**
@@ -150,10 +150,143 @@ After the initial snapshot, CDC will begin. Restarting a connector in `always` m
## **Preview Source and Destination Table Relationships with schemasync mode**
-Before attempting to do an initial snapshot of current table and data, which may be huge, it is possible to "preview" all the tables and data type mappings between source and destination tables before the actual data migration. This gives you an opportunity to modify a data type mapping, or an object name before actual migration happens. This can be done with the special "schemasync" initial snapshot mode. Refer to [object mapping workflow](../../tutorial/object_mapping_workflow/) for a detailed example.
+Before attempting to do an initial snapshot of current table and data, which may be huge, it is possible to "preview" all the tables and data type mappings between source and destination tables before the actual data migration. This gives you an opportunity to modify a data type mapping, or an object name before actual migration happens. This can be done with the special "schemasync" initial snapshot mode.
Please note that you must set `synchdb.olr_snapshot_engine` to 'fdw' in order to use `schemasync` mode to preview the tables.
+### **Create a Connector and Start it in `schemasync` Mode**
+
+`schemasync` is a special mode that makes the connector connects to remote database and attempt to sync only the schema of designated tables. After this is done, the connector is put to `paused` state and user is able to review all the tables and data types created using the default rules and make change if needed.
+
+```sql
+SELECT synchdb_add_conninfo(
+ 'pgconn',
+ '127.0.0.1',
+ 5433,
+ 'pguser',
+ 'pgpass',
+ 'postgres',
+ 'public',
+ 'null',
+ 'null',
+ 'postgres'
+);
+
+SELECT synchdb_start_engine_bgw('pgconn', 'schemasync');
+```
+
+### **Ensure the connector is put to paused state**
+
+```sql
+SELECT name, connector_type, pid, stage, state FROM synchdb_state_view WHERE name = 'pgconn';;
+ name | connector_type | pid | stage | state
+--------+----------------+---------+---------------------+--------
+ pgconn | postgres | 1643157 | change data capture | paused
+
+```
+
+### **Review the Tables Created by Default Mapping Rules**
+
+```sql
+SELECT * FROM synchdb_att_view WHERE name = 'pgconn';
+ name | type | attnum | ext_tbname | pg_tbname | ext_attname | pg_attname | ext_atttypename | pg_atttypename | transform
+--------+----------+--------+-------------------------+------------------+-------------+------------+-------------------+-------------------+-----------
+ pgconn | postgres | 1 | postgres.public.mytble | postgres.mytble | a | a | numeric | numeric |
+ pgconn | postgres | 2 | postgres.public.mytble | postgres.mytble | b | b | numeric | numeric |
+ pgconn | postgres | 3 | postgres.public.mytble | postgres.mytble | c | c | numeric | numeric |
+ pgconn | postgres | 1 | postgres.public.testing | postgres.testing | a | a | integer | integer |
+ pgconn | postgres | 2 | postgres.public.testing | postgres.testing | b | b | text | text |
+ pgconn | postgres | 3 | postgres.public.testing | postgres.testing | c | c | character varying | character varying |
+ pgconn | postgres | 4 | postgres.public.testing | postgres.testing | d | d | bigint | bigint |
+ pgconn | postgres | 1 | postgres.public.xyz | postgres.xyz | bbb | bbb | character varying | character varying |
+ pgconn | postgres | 2 | postgres.public.xyz | postgres.xyz | ccc | ccc | bytea | bytea |
+ pgconn | postgres | 3 | postgres.public.xyz | postgres.xyz | ddd | ddd | numeric | numeric |
+ pgconn | postgres | 4 | postgres.public.xyz | postgres.xyz | eee | eee | numeric | numeric |
+ pgconn | postgres | 5 | postgres.public.xyz | postgres.xyz | fff | fff | numeric | numeric |
+ pgconn | postgres | 6 | postgres.public.xyz | postgres.xyz | ggg | ggg | bigint | bigint |
+ pgconn | postgres | 7 | postgres.public.xyz | postgres.xyz | aaa | aaa | integer | integer |
+
+
+```
+
+### **Define Custom Mapping Rules (If Needed)**
+
+User can use `synchdb_add_objmap` function to create custom mapping rules. It can be used to map table name, column name, data types and defines a data transform expression rule
+
+```sql
+SELECT synchdb_add_objmap('pgconn','table','postgres.public.mytble','postgres.thetable');
+SELECT synchdb_add_objmap('pgconn','column','postgres.public.testing.c','ccc');
+SELECT synchdb_add_objmap('pgconn','datatype','postgres.public.xyz.ggg','int|0');
+SELECT synchdb_add_objmap('pgconn','transform','postgres.public.xyz.bbb','''>>>>>'' || ''%d'' || ''<<<<<''');
+```
+
+The above means:
+
+* source table 'postgres.public.mytble' will be mapped to 'postgres.thetable' in destination
+* source column 'postgres.public.testing.c'will be mapped to 'ccc' in destination
+* source data type for column 'postgres.public.xyz.ggg' will be mapped to 'int'
+* source column data 'postgres.public.xyz.bbb' will be transformed accoring to the expression where %d is the data placeholder
+
+### **Review All Object Mapping Rules Created So Far**
+
+```sql
+SELECT * FROM synchdb_objmap WHERE name = 'pgconn';
+ name | objtype | enabled | srcobj | dstobj
+--------+-----------+---------+---------------------------+----------------------------
+ pgconn | table | t | postgres.public.mytble | postgres.thetable
+ pgconn | column | t | postgres.public.testing.c | ccc
+ pgconn | datatype | t | postgres.public.xyz.ggg | int|0
+ pgconn | transform | t | postgres.public.xyz.bbb | '>>>>>' || '%d' || '<<<<<'
+
+
+```
+
+### **Reload the Object Mapping Rules**
+
+Once all custom rules have been defined, we need to signal the connector to load them. This will cause the connector to read and apply the object mapping rules. If it sees a discrepancy between current PostgreSQL values and the object mapping values, it will attempt to correct the mapping.
+
+```sql
+SELECT synchdb_reload_objmap('pgconn');
+
+```
+
+### **Review `synchdb_att_view` Again for Changes**
+
+```sql
+SELECT * from synchdb_att_view WHERE name = 'pgconn';;
+ name | type | attnum | ext_tbname | pg_tbname | ext_attname | pg_attname | ext_atttypename | pg_atttypename | transform
+--------+----------+--------+-------------------------+-------------------+-------------+------------+-------------------+-------------------+----------------------------
+ pgconn | postgres | 1 | postgres.public.mytble | postgres.thetable | a | a | numeric | numeric |
+ pgconn | postgres | 2 | postgres.public.mytble | postgres.thetable | b | b | numeric | numeric |
+ pgconn | postgres | 3 | postgres.public.mytble | postgres.thetable | c | c | numeric | numeric |
+ pgconn | postgres | 1 | postgres.public.testing | postgres.testing | a | a | integer | integer |
+ pgconn | postgres | 2 | postgres.public.testing | postgres.testing | b | b | text | text |
+ pgconn | postgres | 3 | postgres.public.testing | postgres.testing | c | ccc | character varying | character varying |
+ pgconn | postgres | 4 | postgres.public.testing | postgres.testing | d | d | bigint | bigint |
+ pgconn | postgres | 1 | postgres.public.xyz | postgres.xyz | bbb | bbb | character varying | character varying | '>>>>>' || '%d' || '<<<<<'
+ pgconn | postgres | 2 | postgres.public.xyz | postgres.xyz | ccc | ccc | bytea | bytea |
+ pgconn | postgres | 3 | postgres.public.xyz | postgres.xyz | ddd | ddd | numeric | numeric |
+ pgconn | postgres | 4 | postgres.public.xyz | postgres.xyz | eee | eee | numeric | numeric |
+ pgconn | postgres | 5 | postgres.public.xyz | postgres.xyz | fff | fff | numeric | numeric |
+ pgconn | postgres | 6 | postgres.public.xyz | postgres.xyz | ggg | ggg | bigint | integer |
+ pgconn | postgres | 7 | postgres.public.xyz | postgres.xyz | aaa | aaa | integer | integer |
+
+```
+
+### **Resume the Connector or Redo the Entire Snapshot**
+
+Once the object mappings have been confirmed correct, we can resume the connector. Please note that, resume will proceed to streaming only the new table changes. The existing data of the tables will not be copied.
+
+```sql
+SELECT synchdb_resume_engine('pgconn');
+```
+
+To capture the table's existing data, we can also redo the entire snapshot with the new object mapping rules.
+
+```sql
+SELECT synchdb_stop_engine_bgw('pgconn');
+SELECT synchdb_start_engine_bgw('pgconn', 'always');
+```
## **Selective Table Sync**
diff --git a/doc/docs/en/tutorial/sqlserver_cdc_to_postgresql.md b/doc/docs/en/tutorial/sqlserver_cdc_to_postgresql.md
index 7f57c55..19f9721 100644
--- a/doc/docs/en/tutorial/sqlserver_cdc_to_postgresql.md
+++ b/doc/docs/en/tutorial/sqlserver_cdc_to_postgresql.md
@@ -1,4 +1,4 @@
-# SQL Server -> PostgreSQL
+# SQL Server Connector
## **Prepare SQL Server Database for SynchDB**
@@ -132,7 +132,146 @@ After the initial snapshot, CDC will begin. Restarting a connector in `always` m
## **Preview Source and Destination Table Relationships with schemasync mode**
-Before attempting to do an initial snapshot of current table and data, which may be huge, it is possible to "preview" all the tables and data type mappings between source and destination tables before the actual data migration. This gives you an opportunity to modify a data type mapping, or an object name before actual migration happens. This can be done with the special "schemasync" initial snapshot mode. Refer to [object mapping workflow](../../tutorial/object_mapping_workflow/) for a detailed example.
+Before attempting to do an initial snapshot of current table and data, which may be huge, it is possible to "preview" all the tables and data type mappings between source and destination tables before the actual data migration. This gives you an opportunity to modify a data type mapping, or an object name before actual migration happens. This can be done with the special "schemasync" initial snapshot mode.
+
+Please note that you must set `synchdb.olr_snapshot_engine` to 'fdw' in order to use `schemasync` mode to preview the tables.
+
+### **Create a Connector and Start it in `schemasync` Mode**
+
+`schemasync` is a special mode that makes the connector connects to remote database and attempt to sync only the schema of designated tables. After this is done, the connector is put to `paused` state and user is able to review all the tables and data types created using the default rules and make change if needed.
+
+```sql
+SELECT synchdb_add_conninfo(
+ 'sqlserverconn',
+ '127.0.0.1',
+ 1433,
+ 'sa',
+ 'Password!',
+ 'testDB',
+ 'dbo',
+ 'null',
+ 'null',
+ 'sqlserver'
+);
+
+SELECT synchdb_start_engine_bgw('sqlserverconn', 'schemasync');
+```
+
+### **Ensure the connector is put to paused state**
+
+```sql
+SELECT name, connector_type, pid, stage, state FROM synchdb_state_view WHERE name = 'sqlserverconn';
+ name | connector_type | pid | stage | state
+---------------+----------------+---------+---------------------+--------
+ sqlserverconn | sqlserver | 1647884 | change data capture | paused
+
+```
+
+### **Review the Tables Created by Default Mapping Rules**
+
+```sql
+SELECT * FROM synchdb_att_view WHERE name = 'sqlserverconn';
+ name | type | attnum | ext_tbname | pg_tbname | ext_attname | pg_attname | ext_atttypename | pg_atttypename | transform
+---------------+-----------+--------+-----------------------------+-------------------------+--------------+--------------+-----------------+-------------------+-----------
+ sqlserverconn | sqlserver | 1 | testDB.dbo.customers | testdb.customers | id | id | int identity | integer |
+ sqlserverconn | sqlserver | 2 | testDB.dbo.customers | testdb.customers | first_name | first_name | varchar | character varying |
+ sqlserverconn | sqlserver | 3 | testDB.dbo.customers | testdb.customers | last_name | last_name | varchar | character varying |
+ sqlserverconn | sqlserver | 4 | testDB.dbo.customers | testdb.customers | email | email | varchar | character varying |
+ sqlserverconn | sqlserver | 1 | testDB.dbo.orders | testdb.orders | order_number | order_number | int identity | integer |
+ sqlserverconn | sqlserver | 2 | testDB.dbo.orders | testdb.orders | order_date | order_date | date | date |
+ sqlserverconn | sqlserver | 3 | testDB.dbo.orders | testdb.orders | purchaser | purchaser | int | integer |
+ sqlserverconn | sqlserver | 4 | testDB.dbo.orders | testdb.orders | quantity | quantity | int | integer |
+ sqlserverconn | sqlserver | 5 | testDB.dbo.orders | testdb.orders | product_id | product_id | int | integer |
+ sqlserverconn | sqlserver | 1 | testDB.dbo.products | testdb.products | id | id | int identity | integer |
+ sqlserverconn | sqlserver | 2 | testDB.dbo.products | testdb.products | name | name | varchar | character varying |
+ sqlserverconn | sqlserver | 3 | testDB.dbo.products | testdb.products | description | description | varchar | character varying |
+ sqlserverconn | sqlserver | 4 | testDB.dbo.products | testdb.products | weight | weight | float | real |
+ sqlserverconn | sqlserver | 1 | testDB.dbo.products_on_hand | testdb.products_on_hand | product_id | product_id | int | integer |
+ sqlserverconn | sqlserver | 2 | testDB.dbo.products_on_hand | testdb.products_on_hand | quantity | quantity | int | integer |
+
+```
+
+### **Define Custom Mapping Rules (If Needed)**
+
+User can use `synchdb_add_objmap` function to create custom mapping rules. It can be used to map table name, column name, data types and defines a data transform expression rule
+
+```sql
+SELECT synchdb_add_objmap('sqlserverconn','table','testDB.dbo.products','testdb.myproducts');
+SELECT synchdb_add_objmap('sqlserverconn','column','testDB.dbo.customers.email','contact');
+SELECT synchdb_add_objmap('sqlserverconn','datatype','testDB.dbo.products_on_hand.quantity','bigint|0');
+SELECT synchdb_add_objmap('sqlserverconn','transform','testDB.dbo.products.name','''>>>>>'' || ''%d'' || ''<<<<<''');
+```
+The above means:
+
+* source table 'testDB.dbo.product' will be mapped to 'testdb.myproducts' in destination
+* source column 'testDB.dbo.customers.email' will be mapped to 'contact' in destination
+* source data type for column 'testDB.dbo.products_on_hand.quantity' will be mapped to 'bigint'
+* source column data 'testDB.dbo.products.name' will be transformed accoring to the expression where %d is the data placeholder
+
+### **Review All Object Mapping Rules Created So Far**
+
+```sql
+SELECT * FROM synchdb_objmap WHERE name = 'sqlserverconn';
+ name | objtype | enabled | srcobj | dstobj
+---------------+-----------+---------+--------------------------------------+----------------------------
+ sqlserverconn | table | t | testDB.dbo.products | testdb.myproducts
+ sqlserverconn | column | t | testDB.dbo.customers.email | contact
+ sqlserverconn | datatype | t | testDB.dbo.products_on_hand.quantity | bigint|0
+ sqlserverconn | transform | t | testDB.dbo.product.name | '>>>>>' || '%d' || '<<<<<'
+
+```
+
+### **Reload the Object Mapping Rules**
+
+Once all custom rules have been defined, we need to signal the connector to load them. This will cause the connector to read and apply the object mapping rules. If it sees a discrepancy between current PostgreSQL values and the object mapping values, it will attempt to correct the mapping.
+
+```sql
+SELECT synchdb_reload_objmap('sqlserverconn');
+
+```
+
+### **Review `synchdb_att_view` Again for Changes**
+
+```sql
+SELECT * from synchdb_att_view WHERE name = 'sqlserverconn';
+ name | type | attnum | ext_tbname | pg_tbname | ext_attname | pg_attname | ext_atttypename | pg_atttypename | transform
+
+---------------+-----------+--------+-----------------------------+-------------------------+--------------+--------------+-----------------+-------------------+---------------------
+-------
+ sqlserverconn | sqlserver | 1 | testDB.dbo.customers | testdb.customers | id | id | int identity | integer |
+ sqlserverconn | sqlserver | 2 | testDB.dbo.customers | testdb.customers | first_name | first_name | varchar | character varying |
+ sqlserverconn | sqlserver | 3 | testDB.dbo.customers | testdb.customers | last_name | last_name | varchar | character varying |
+ sqlserverconn | sqlserver | 4 | testDB.dbo.customers | testdb.customers | email | contact | varchar | character varying |
+ sqlserverconn | sqlserver | 1 | testDB.dbo.orders | testdb.orders | order_number | order_number | int identity | integer |
+ sqlserverconn | sqlserver | 2 | testDB.dbo.orders | testdb.orders | order_date | order_date | date | date |
+ sqlserverconn | sqlserver | 3 | testDB.dbo.orders | testdb.orders | purchaser | purchaser | int | integer |
+ sqlserverconn | sqlserver | 4 | testDB.dbo.orders | testdb.orders | quantity | quantity | int | integer |
+ sqlserverconn | sqlserver | 5 | testDB.dbo.orders | testdb.orders | product_id | product_id | int | integer |
+ sqlserverconn | sqlserver | 1 | testDB.dbo.products | testdb.products | id | id | int identity | integer |
+ sqlserverconn | sqlserver | 2 | testDB.dbo.products | testdb.products | name | name | varchar | character varying | '>>>>>' || '%d' || '
+<<<<<'
+ sqlserverconn | sqlserver | 3 | testDB.dbo.products | testdb.products | description | description | varchar | character varying |
+ sqlserverconn | sqlserver | 4 | testDB.dbo.products | testdb.products | weight | weight | float | real |
+ sqlserverconn | sqlserver | 1 | testDB.dbo.products_on_hand | testdb.products_on_hand | product_id | product_id | int | integer |
+ sqlserverconn | sqlserver | 2 | testDB.dbo.products_on_hand | testdb.products_on_hand | quantity | quantity | int | bigint |
+
+
+```
+
+### **Resume the Connector or Redo the Entire Snapshot**
+
+Once the object mappings have been confirmed correct, we can resume the connector. Please note that, resume will proceed to streaming only the new table changes. The existing data of the tables will not be copied.
+
+```sql
+SELECT synchdb_resume_engine('sqlserverconn');
+```
+
+To capture the table's existing data, we can also redo the entire snapshot with the new object mapping rules.
+
+```sql
+SELECT synchdb_stop_engine_bgw('sqlserverconn');
+SELECT synchdb_start_engine_bgw('sqlserverconn', 'always');
+```
## **Selective Table Sync**
@@ -212,4 +351,88 @@ postgres=# \dt "testDB".*
testDB | orders | table | ubuntu
testDB | products | table | ubuntu
+```
+
+## Secured Connection
+
+### **Configure Secured Connection**
+
+to secure the connection to remote database, we need to configure additional SSL related parameters to a connector that has been created by `synchdb_add_conninfo`. The SSL certificates and private keys must be packaged as Java keystore file with a passphrase. These information is then passed to SynchDB via synchdb_add_extra_conninfo().
+
+### **synchdb_add_extra_conninfo**
+
+**Purpose**: Configures extra connector parameters to an existing connector created by `synchdb_add_conninfo`
+
+| Parameter | Description | Required | Example | Notes |
+|:-:|:-|:-:|:-|:-|
+| `name` | Unique identifier for this connector | ✓ | `'mysqlconn'` | Must be unique across all connectors |
+| `ssl_mode` | SSL mode | ☐ | `'verify_ca'` | can be one of:
- "disabled" - no SSL is used.
- "preferred" - SSL is used if server supports it.
- "required" - SSL must be used to establish a connection.
- "verify_ca" - connector establishes TLS with the server and will also verify server's TLS certificate against configured truststore.
- "verify_identity" - same behavior as verify_ca but it also checks the server certificate's common name to match the hostname of the system. |
+| `ssl_keystore` | keystore path | ☐ | `/path/to/keystore` | path to the keystore file |
+| `ssl_keystore_pass` | keystore password | ☐ | `'mykeystorepass'` | password to access the keystore file |
+| `ssl_truststore` | trust store path | ☐ | `'/path/to/truststore'` | path to the truststore file |
+| `ssl_truststore_pass` | trust store password | ☐ | `'mytruststorepass'` | password to access the truststore file |
+
+
+```sql
+SELECT synchdb_add_extra_conninfo('sqlserverconn', 'verify_ca', '/path/to/keystore', 'mykeystorepass', '/path/to/truststore', 'mytruststorepass');
+```
+
+### **synchdb_del_extra_conninfo**
+
+**Purpose**: Deletes extra connector paramters created by `synchdb_add_extra_conninfo`
+```sql
+SELECT synchdb_del_extra_conninfo('sqlserverconn');
+```
+
+## Custom Start Offset Values
+
+A start offset value represents a point to start replication from in the similar way as PostgreSQL's resume LSN. When Debezium runner engine starts, it will start the replication from this offset value. Setting this offset value to a earlier value will cause Debezium runner engine to start replication from earlier records, possibly replicating duplicate data records. We should be extra cautious when setting start offset values on Debezium.
+
+### **Record Settable Offset Values**
+
+During operation, new offsets will be generated and flushed to disk by Debezium runner engine. The last flushed offset can be retrieved from `synchdb_state_view()` utility command:
+
+```sql
+postgres=# select name, last_dbz_offset from synchdb_state_view;
+ name | last_dbz_offset
+---------------+------------------------------------------------------------------------------------------------------
+ sqlserverconn | {"commit_lsn":"0000006a:00006608:0003","snapshot":true,"snapshot_completed":false}
+
+```
+
+We should save this values regularly, so in case we run into a problem, we know the offset location in the past that can be set to resume the replication operation.
+
+### **Pause the Connector**
+
+A connector must be in a `paused` state before a new offset value can be set.
+
+Use `synchdb_pause_engine()` SQL function to pause a runnng connector. This will halt the Debezium runner engine from replicating from the heterogeneous database. When paused, it is possible to alter the Debezium connector's offset value to replicate from a specific point in the past using `synchdb_set_offset()` SQL routine. It takes `conninfo_name` as its argument which can be found from the output of `synchdb_get_state()` view.
+
+For example:
+
+```sql
+SELECT synchdb_pause_engine('sqlserverconn');
+```
+
+### **Set the new Offset**
+
+Use `synchdb_set_offset()` SQL function to change a connector worker's starting offset. This can only be done when the connector is put into `paused` state. The function takes 2 parameters, `conninfo_name` and `a valid offset string`, both of which can be found from the output of `synchdb_get_state()` view.
+
+For example:
+
+```sql
+SELECT
+ synchdb_set_offset(
+ 'sqlserverconn', '{"commit_lsn":"0000006a:00006608:0003","snapshot":true,"snapshot_completed":false}'
+ );
+```
+
+### **Resume the Connector**
+
+Use `synchdb_resume_engine()` SQL function to resume Debezium operation from a paused state. This function takes `connector name` as its only parameter, which can be found from the output of `synchdb_get_state()` view. The resumed Debezium runner engine will start the replication from the newly set offset value.
+
+For example:
+
+```sql
+SELECT synchdb_resume_engine('sqlserverconn');
```
\ No newline at end of file
diff --git a/doc/docs/en/user-guide/configure_infinispan.md b/doc/docs/en/user-guide/configure_infinispan.md
deleted file mode 100644
index c61ffcf..0000000
--- a/doc/docs/en/user-guide/configure_infinispan.md
+++ /dev/null
@@ -1,132 +0,0 @@
-# Configure Infinispan for Oracle Connector
-
-## **Overview**
-
-By default, Debezium's Oracle connector uses the JVM heap to cache incoming change events before passing them to SynchDB for processing. The maximum heap size is controlled via the `synchdb.jvm_max_heap_size` GUC. When the JVM heap runs out of memory (especially under large transactions or schemas with many columns), the connector may fail with OutOfMemoryError, making heap sizing a critical tuning challenge.
-
-As an alternative, Debezium can be configured to use Infinispan as its caching layer. Infinispan supports memory storage on both the JVM heap and off-heap (direct memory), offering more flexibility. Additionally, it supports passivation, allowing excess data to be spilled to disk when memory limits are reached. This makes it far more resilient under heavy workloads and ensures large transactions or schema changes can be handled gracefully without running out of memory.
-
-## **`synchdb_add_infinispan()`**
-
-**Signature:**
-
-```sql
-synchdb_add_infinispan(
- connectorName NAME, -- Name of the connector
- memoryType NAME, -- memory type, can be "heap" or "off heap"
- memorySize INT -- size of memory in MB to reserve as cache
-)
-```
-
-Registers an Infinispan-backed caching configuration for a given connector. This allows the connector to use Infinispan for buffering change events, supporting both heap-based and off-heap memory allocation with spill-to-disk (passivation).
-
-**Note:**
-
-- If called on a connector that is currently running, the setting will take effect on next restart.
-- If an Infinispan cache already exists for the connector, it will be replaced.
-- memoryType='off_heap' utilizes native (direct) memory and is not limited by JVM heap, but should be sized carefully.
-- The cache will automatically support passivation to disk when memory fills.
-
-**Example:**
-``` sql
-SELECT synchdb_add_infinispan('oracleconn', 'off_heap', 2048);
-
-
-
-```
-
-## **`synchdb_del_infinispan()`**
-
-**Signature:**
-
-```sql
-synchdb_add_infinispan(
- connectorName NAME -- Name of the connector
-)
-```
-
-Removes the Infinispan cache configuration and associated on-disk metadata for a given connector. This operation will delete:
-
-- All cache files
-- Any passivated (spilled-to-disk) state
-- The associated Infinispan configuration
-
-**Note:**
-
-- This function can only be executed when the connector is stopped.
-- Attempting to run it while the connector is active will result in an error.
-- Use this command to clean up after permanently disabling or reconfiguring a connector’s cache backend.
-
-**Example:**
-``` sql
-SELECT synchdb_del_infinispan('oracleconn');
-
-```
-
-## **`Passivation`**
-
-Passivation simply means infinispan will eject and write data on disk if cache memory is full. As long as there is space in memory to hold change events, disk write will not occur. The data is written to `$PGDATA/pg_synchdb/ispn_[connector name]_[destination database name]`
-
-
-## **Example Oracle SQLs to test Infinispan with a Large Transaction**
-
-**Create a test table in Oracle:**
-```sql
-CREATE TABLE big_tx_test (
- id NUMBER PRIMARY KEY,
- payload VARCHAR2(4000),
- created DATE DEFAULT SYSDATE
-);
-
-```
-
-**Create a relatively large transaction:**
-```sql
-BEGIN
- FOR i IN 1..100000 LOOP
- INSERT INTO big_tx_test (id, payload)
- VALUES (i, RPAD('x', 4000, 'x'));
- END LOOP;
- COMMIT;
-END;
-/
-
-```
-
-**Behaviors Under Large Transaction**
-
-no infinispan setting + low JVM heap (synchdb.jvm_max_heap_size=128)
-
-* --> OutOfMemory error will occur
-
-low JVM heap (128) + high infinispan off heap (2048)
-
-* --> large transaction handled successfully
-
-low JVM heap (128) + low infinispan off heap (128)
-
-* --> passivation will occur
-* --> `ispn_[connector name]_[destination database name]` size will grow during processing and reduce once large transaction finished processing
-* --> large transaction handled successfully but at slower speed.
-
-low JVM heap (128) + high infinispan heap (2048)
-
-* --> OutOfMemory error will occur
-* --> do not configure infinispan to use more heap memory than JVM max heap.
-
-low JVM heap (128) + low infinispan heap (64)
-
-* --> passivation will occur
-* --> `ispn_[connector name]_[destination database name]` size will grow during processing and reduce once large transaction finished processing
-* --> not recommended as half of the JVM heap can potentially be used by infinispan and may not have enough left for other Debezium operations
-
-low JVM heap (128) + same infinispan heap (128)
-
-* --> not recommended as all of the JVM heap can potentially be used by infinispan and eventually causing OutOfMemory error
-
-high JVM heap (2048) + low infinispan heap (128)
-
-* --> passivation will occur
-* --> `ispn_[connector name]_[destination database name]` size will grow during processing and reduce once large transaction finished processing
-* --> large transaction handled successfully
-* --> not efficient - as only a small portion of JVM heap is used as cache + unnessary passivation.
\ No newline at end of file
diff --git a/doc/docs/en/user-guide/configure_olr.md b/doc/docs/en/user-guide/configure_olr.md
deleted file mode 100644
index 1a067dc..0000000
--- a/doc/docs/en/user-guide/configure_olr.md
+++ /dev/null
@@ -1,239 +0,0 @@
-# Configure Openlog Replicator for Oracle
-
-## **Overview**
-
-In addition to LogMiner-based Oracle replication, **SynchDB** also supports **Openlog Replicator (OLR)** to stream from Oracle databases. There are 2 types of Openlog Replicator supported in SynchDB:
-
-1. Debezium based Openlog Replicator
-2. Native Openlog Replicator (not via Debezium) - at BETA
-
-Both require Openlog Replicator to be configured according to the setup example below and connected to Oracle prior to streaming in SynchDB.
-
-## **Requirements**
-
-- **Openlog Replicator Version**: `1.3.0` (verified compatibility for Debezium 2.7.x)
-- Oracle instance with redo logs accessible to OLR
-- Additional permissions must be granted for OLR. Refer to [here](../../getting-started/remote_database_setups/) for exact permission requirement.
-- Openlog Replicator must be configured and running
-- An existing Oracle connector in SynchDB (created using `synchdb_add_conninfo()`)
-
-Refer to this [external guide](https://highgo.atlassian.net/wiki/external/OTUzY2Q2OWFkNzUzNGVkM2EyZGIyMDE1YzVhMDdkNWE) for details on deploying Openlog Replicator via Docker.
-
-## **Openlog Replicator Configuration Example**
-
-SynchDB's OLR support is built against the configuration example below.
-
-**Version 1.3.0**
-```json
-{
- "version": "1.3.0",
- "source": [
- {
- "alias": "SOURCE",
- "name": "ORACLE",
- "reader": {
- "type": "online",
- "user": "DBZUSER",
- "password": "dbz",
- "server": "//ora19c:1521/FREE"
- },
- "format": {
- "type": "json",
- "column": 2,
- "db": 3,
- "interval-dts": 9,
- "interval-ytm": 4,
- "message": 2,
- "rid": 1,
- "schema": 7,
- "timestamp-all": 1,
- "scn-all": 1
- },
- "memory": {
- "min-mb": 64,
- "max-mb": 1024
- },
- "filter": {
- "table": [
- {"owner": "DBZUSER", "table": ".*"}
- ]
- },
- "flags": 32
- }
- ],
- "target": [
- {
- "alias": "SYNCHDB",
- "source": "SOURCE",
- "writer": {
- "type": "network",
- "uri": "0.0.0.0:7070"
- }
- }
- ]
-}
-
-```
-
-**Version 1.8.5**
-```json
-{
- "version": "1.8.5",
- "source": [
- {
- "alias": "SOURCE",
- "name": "ORACLE",
- "reader": {
- "type": "online",
- "user": "DBZUSER",
- "password": "dbz",
- "server": "//ora19c:1521/FREE"
- },
- "format": {
- "type": "json",
- "column": 2,
- "db": 3,
- "interval-dts": 9,
- "interval-ytm": 4,
- "message": 2,
- "rid": 1,
- "schema": 7,
- "timestamp-all": 1,
- "scn-type": 1
- },
- "memory": {
- "min-mb": 64,
- "max-mb": 1024,
- "swap-path": "/opt/OpenLogReplicator/olrswap"
- },
- "filter": {
- "table": [
- {"owner": "DBZUSER", "table": ".*"}
- ]
- },
- "flags": 32
- }
- ],
- "target": [
- {
- "alias": "DEBEZIUM",
- "source": "SOURCE",
- "writer": {
- "type": "network",
- "uri": "0.0.0.0:7070"
- }
- }
- ]
-}
-
-```
-
-Please note the following:
-
-- "source"."name": "ORACLE" -> this should match the `olr_source` value when defining OLR parameters via `synchdb_add_olr_conninfo()` (See below)
-- "source"."reader"."user" -> this should match the `username` value when creating a connector via `synchdb_add_conninfo()`
-- "source"."reader"."password" -> this should match the `password` value when creating a connector via `synchdb_add_conninfo()`
-- "source"."reader"."server" -> this should contain the values of `hostname`, `port` and `source database` values when creating a connector via `synchdb_add_conninfo()`
-- "source"."filter"."table":[] -> this filters the change events that Openlog Replicator captures. <<<**IMPORTANT**>>>: This is currently the only way to filter change events from Oracle as OLR implementations in SynchDB does not do any filtering at this moment. (The `table` and `snapshot table` values are ignored when creating a connector via `synchdb_add_conninfo()`)
-- "format":{} -> the specific paylod format ingested by Debezium based or native Openlog Replicator connector. Use these values as specified.
-- "memory"."swap-path" -> this tells OLR where to write swap files in low memory scenario.
-- "target".[0]."writer"."type": -> this must specify `network` as both Debezium and native Openlog Replicator connector communicate with Openlog Replicator via network
-- "target".[0]."writer"."uri": -> this is the bind host and port Openlog Replicator listens on that SynchDB should be able to access via `olr_host` and `olr_port` when defining OLR parameters via `synchdb_add_olr_conninfo()`.
-
-## **`synchdb_add_conninfo()`**
-
-To create a **Debezium-based** OLR connector (use `type` = 'oracle'):
-
-```sql
-SELECT synchdb_add_conninfo('olrconn',
- 'ora19c',
- 1521,
- 'DBZUSER',
- 'dbz',
- 'FREE',
- 'postgres',
- 'null',
- 'null',
- 'oracle');
-
-```
-
-To create a **Native** OLR connector (use `type` = 'olr'):
-
-```sql
-SELECT synchdb_add_conninfo('olrconn',
- 'ora19c',
- 1521,
- 'DBZUSER',
- 'dbz',
- 'FREE',
- 'postgres',
- 'null',
- 'null',
- 'olr');
-
-```
-
-<<<**IMPORTANT**>>> **SynchDB must be compiled and built with flag (WITH_OLR=1) to support native openlog replicator connector.**
-
-More on creating a connector can be found [here](../../user-guide/create_a_connector/)
-
-## **`synchdb_add_olr_conninfo()`**
-
-With a connector created, the user then registers an Openlog Replicator endpoint for an existing Oracle connector.
-
-**Signature:**
-
-```sql
-synchdb_add_olr_conninfo(
- conn_name TEXT, -- Name of the connector
- olr_host TEXT, -- Hostname or IP of the OLR instance
- olr_port INT, -- Port number exposed by OLR (typically 7070)
- olr_source TEXT -- Oracle source name as configured in OLR
-)
-```
-
-**Example:**
-
-This instructs SynchDB to stream changes for the connector `olrconn` from the Openlog Replicator instance running at olrhost:7070, using the Oracle source identifier ORACLE. Call `synchdb_start_engine_bgw` to start this connector.
-
-```sql
-SELECT synchdb_add_olr_conninfo('olrconn', 'olrhost', 7070, 'ORACLE');
-
-```
-
-## **synchdb_del_olr_conninfo**
-
-Removes the OLR configuration for a specific connector, reverting it to use LogMiner.
-
-**Signature:**
-
-```sql
-synchdb_del_olr_conninfo(conn_name TEXT)
-
-```
-
-**Example:**
-
-This command disables the use of OLR for oracleconn. Starting the connector with `synchdb_start_engine_bgw` will fall back to the default logmining strategy (Debezium based OLR connector). If using native Openlog Replicator connector, the absense of OLR configuration will result in error at connector startup.
-
-```sql
-SELECT synchdb_del_olr_conninfo('olrconn');
-
-```
-
-## **Behavior Notes for Debezium based Openlog Replicator Connector**
-
-* When both LogMiner and OLR configurations exist, SynchDB defaults to using Openlog Replicator for change capture.
-* If OLR configurations are absent, SynchDB uses logmining strategy to stream changes.
-* Restarting the connector is required after modifying its OLR configuration.
-
-## **Behavior Notes for Native based Openlog Replicator Connector**
-
-* Currently at BETA version.
-* SynchDB manages connections to Openlog Replicator and streams changes without using Debezium.
-* Requires OLR configuration or connector will error on startup.
-* Relies on Debezium's oracle connector to complete initial snapshot and shuts down when done, subsequent CDC is done natively within SynchDB against Openlog Replicator.
-* Relies on IvorySQL's oracle parser to handle DDL events. This must be compiled and installed prior to using native openlog replicator connector.
-* Visit [here](https://github.com/bersler/OpenLogReplicator) for more information about Openlog Replicator.
-
diff --git a/doc/docs/en/user-guide/configure_snapshot_engine.md b/doc/docs/en/user-guide/configure_snapshot_engine.md
index 107df09..48aff28 100644
--- a/doc/docs/en/user-guide/configure_snapshot_engine.md
+++ b/doc/docs/en/user-guide/configure_snapshot_engine.md
@@ -4,28 +4,37 @@
Initial snapshot refers to the process of migrating both the table schema and the initial data from remote database to SynchDB. For most connector types, this is done only once on first connector start via embedded Debezium runner as the only engine that can perform initial snapshot. After the initial snapshot completes, the Change Data Capture will begin to stream live changes to SynchDB. The "snapshot modes" can further control the behavior of initial snapshot and CDC. Refer to [here](../../user-guide/start_stop_connector/) for more information.
-In addition to Debezium based initial snapshot, which may be slow when there is a huge number of tables, SynchdB provides an alternative FDW-based native initial snapshot engine. FDW based snapshot is only supported in native Openlog Replicator (OLR) connector as of now. All other connectors still rely on debezium to carry out the snapshot.
+SynchDB supports 2 snapshot engines, each supports various connector types:
+**Debezium based snapshot:**
-## **FDW Based Initial Snapshot**
+* MySQL
+* SQL Server
+* Oracle
+* Openlog Replicator
-* Enabled in `postgresql.conf` by setting "synchdb.olr_snapshot_engine" to "fdw"
-* Start a OLR connector with a snapshot mode that requires doing a snapshot. For example:
+**FDW based snapshot:**
-```sql
-SELECT synchdb_start_engine_bgw('olrconn', 'no_data');
+* MySQL (uses mysql_fdw)
+* Oracle (uses oracle_fdw)
+* Openlog Replicator (uses oracle_fdw)
+* Postgres (uses postgres_fdw)
--- or
-SELECT synchdb_start_engine_bgw('olrconn', 'always');
+## **Debezium Based Initial Snapshot**
--- or
-SELECT synchdb_start_engine_bgw('olrconn', 'schemasync');
+This is the default snapshot engine (synchdb.olr_snapshot_engine='debezium') that relies of Debezium engine via JNI to initiate the snapshot process. In most cases, it works fine, but may suffer from performance issues if the number of tables included in snapshot is high (thousands or more). Debezium will first go through an analaysis stage that visits each table once to learn its structure and estimates number of rows to snapshot. This is done entirely by a single worker and during this time, the engine may appear to be "hanging" and will not emit any change events. This process itself could take hours to complete in large number of tables. Once done, it will then start emitting change events to SynchDB.
-```
+Triggered automatically upon `synchdb_start_engine_bgw()` with a snapshot mode that requires doing a snapshot and will not repeat again if completed.
-## **Build and Install oracle_fdw**
+## **FDW Based Initial Snapshot**
-If "fdw" is selected as snapshot engine, you need to ensure the corresponding Foreign Data Wrapper has been installed or available for synchdb. For your reference, below is a brief procedure to build and install oracle_fdw from source code.
+* Enabled in `postgresql.conf` by setting "synchdb.olr_snapshot_engine" to "fdw"
+* Triggered automatically upon `synchdb_start_engine_bgw()` with a snapshot mode that requires doing a snapshot and will not repeat again if completed.
+* Corresponding FDWs must be available.
+
+## **FDW Snapshot for Oracle and OLR Connectors**
+
+It is possible to use oracle_fdw to perform initial snapshot for Oracle and OLR connectors which is significantly faster than Debezium counterpart. SynchDB integrates with [oracle_fdw](https://github.com/laurenz/oracle_fdw) version 2.8.0 with OCI v23.9.0 as its underlying driver. This is just the version tested, older or newer versions may still work.
### **Install OCI**
@@ -58,7 +67,7 @@ You can also add $OCI_HOME to `/etc/ld.so.conf.d/x86_64-linux-gnu.conf` (ubuntu
You should do a ldconfig so your linker knows where to find shared libraries:
-### **Build oracle_fdw 2.8.0**
+### **Build and Install oracle_fdw 2.8.0**
```bash
git clone https://github.com/laurenz/oracle_fdw.git --branch ORACLE_FDW_2_8_0
@@ -81,7 +90,57 @@ sudo make install PG_CONFIG=/usr/local/pgsql/bin/pg_config
```
-Oralce_fdw is ready to go.
+Oralce_fdw is ready to go. Start a connector normally with synchdb.olr_snapshot_engine set to 'fdw'. If a snapshot is required, SynchDB will complete it via FDW. You do not have to run `CREATE EXTENSION oracle_fdw` prior to using FDW based initial snapshot, nor do you have to `CREATE SERVER` or `CREATE USER MAPPING`. SynchDB takes care of all of these when it performs the snapshot..
+
+
+## **FDW Snapshot for MySQL Connectors**
+
+It is possible to use mysql_fdw to perform initial snapshot for MySQL connectors which is significantly faster than Debezium counterpart. SynchDB integrates with [mysql_fdw](https://github.com/EnterpriseDB/mysql_fdw) version 2.9.3 with libmysqlclient v8 as its underlying driver. This is just the version tested, older or newer versions may still work.
+
+### **Install MySQL Client Development Package**
+
+You may download and install MySQL client development package [here](https://packages.debian.org/sid/libmysqlclient-dev). If you are on Ubuntu, it can be installed using package manager:
+
+```bash
+sudo apt update
+sudo apt install libmysqlclient-dev
+
+```
+
+### **Build and Install mysql_fdw 2.9.3**
+
+```bash
+git clone https://github.com/EnterpriseDB/mysql_fdw.git --branch REL-2_9_3
+
+```
+
+Build and install mysql_fdw:
+
+```bash
+make PG_CONFIG=/usr/local/pgsql/bin/pg_config
+sudo make install PG_CONFIG=/usr/local/pgsql/bin/pg_config
+
+```
+
+mysql_fdw is ready to go. Start a connector normally with synchdb.olr_snapshot_engine set to 'fdw'. If a snapshot is required, SynchDB will complete it via FDW. You do not have to run `CREATE EXTENSION mysql_fdw` prior to using FDW based initial snapshot, nor do you have to `CREATE SERVER` or `CREATE USER MAPPING`. SynchDB takes care of all of these when it performs the snapshot..
+
+## **FDW Snapshot for Postgres Connectors**
+
+It is possible to use postgres_fdw to perform initial snapshot for Postgres connectors which is significantly faster than Debezium counterpart. SynchDB integrates with [postgres_fdw](https://github.com/postgres/postgres/tree/master/contrib/postgres_fdw) based on postgresql 18. This is just the version tested, older or newer versions may still work.
+
+### **Build and Install postgres_fdw**
-**<>** You do not have to run `CREATE EXTENSION oracle_fdw` prior to using FDW based initial snapshot, nor do you have to `CREATE SERVER` or `CREATE USER MAPPING`. SynchDB takes care of all of these when it performs the snapshot..
+```bash
+git clone https://github.com/postgres/postgres.git --branch REL_18_0
+cd postgres
+./configure
+make
+sudo make install
+
+cd contrib/postgres_fdw
+make
+sudo make install
+
+```
+postgre is reasdy to go. Start a connector normally with synchdb.olr_snapshot_engine set to 'fdw'. If a snapshot is required, SynchDB will complete it via FDW. You do not have to run `CREATE EXTENSION mysql_fdw` prior to using FDW based initial snapshot, nor do you have to `CREATE SERVER` or `CREATE USER MAPPING`. SynchDB takes care of all of these when it performs the snapshot..
\ No newline at end of file
diff --git a/doc/docs/en/user-guide/create_a_connector.md b/doc/docs/en/user-guide/create_a_connector.md
index 7dc5a92..110d51b 100644
--- a/doc/docs/en/user-guide/create_a_connector.md
+++ b/doc/docs/en/user-guide/create_a_connector.md
@@ -2,7 +2,7 @@
## **Create a Connector**
-A connector represents a connection to a particular source database, replicate one set of tables and apply to PostgreSQL. If you have multiple source databases that need replication, multiple connectors are required (one for each). It is also possible to create multiple connectors that connect to the same source database but replicate different sets of tables.
+A connector represents a connection to a particular source database, replicate one set of tables and apply to PostgreSQL. If you have multiple source databases that need replication, multiple connectors are required (one for each). It is also possible to create multiple connectors that connect to the same source database but replicate different or same sets of tables.
Creating a connector can be done with utility SQL function `synchdb_add_conninfo()`.
@@ -15,13 +15,13 @@ synchdb_add_conninfo takes these arguments:
| port | the port number to connect to the heterogeneous database. |
| username | user name to use to authenticate with heterogeneous database.|
| password | password to authenticate the username |
-| source database | this is the name of source database in heterogeneous database that we want to replicate changes from.|
-| destination database | (deprecated) always defaults to the same database as where synchDB is installed |
-| table | (optional) - expressed in the form of `[database].[table]` or `[database].[schema].[table]` that must exists in heterogeneous database so the engine will only replicate the specified tables. If left empty, all tables are replicated. Alternatively, a table list file can be specified with `file:` prefix |
-| snapshot table | (optional) - expressed in the form of `[database].[table]` or `[database].[schema].[table]` that must exists in the `table` setting above, so the engine will only rebuild the snapshot of these tables if snapshot mode is set to `always`. If left empty or null, all tables specified in `table` setting above will be rebuilt when snapshot mode is set to `always`. Alternatively, a snapshot table list file can be specified with `file:` prefix|
+| source database | this is the name of source database that we want to replicate changes from.|
+| source schema | this is the name of source schema under source database that we want to replicate changes from |
+| table | (optional) - expressed in the form of `[database].[table]` or `[schema].[table]` that must exists in source database / schema so the engine will only replicate the specified tables. If left empty, all tables are replicated. Alternatively, a table list file can be specified with `file:` prefix |
+| snapshot table | (optional) - expressed in the form of `[database].[table]` or `[schema].[table]` that must exists in the `table` setting above, so the engine will only rebuild the snapshot of these tables if snapshot mode is set to `always`. If left empty or null, all tables specified in `table` setting above will be rebuilt when snapshot mode is set to `always`. Alternatively, a snapshot table list file can be specified with `file:` prefix|
| connector | the connector type (See below) |
-<<**Note**>> If connector type is `olr`, SynchDB will still use Debezium to perform an initial snapshot with tables and snapshot tables as specified in `table` and `snapshot table` parameters. After this is done, SynchDB will connect to Openlog Replicator for replication without filtering desired tables specified in `table` parameter. The table filtering is instead done on the Openlog Replicator's configuration. So, please ensure that both Openlog Replicator and SynchDB connector's `table` filtering parameters are configured consistently to avoid potential descrepancies
+<<**NOTE**>> `source database`, `source schema`, `username`, `password`, `table` and `snapshot table` are case sensitive, and you must specify the names exactly as appeared in your source database, so keep in mind the letter casing of these names.
## **Connector Types**
@@ -30,7 +30,8 @@ SynchDb supports these connector types:
* mysql -> MySQL database
* sqlserver -> Microsoft SQL Server database
* oracle -> Oracle database
-* olr -> Native Openlog Replicator (BETA)
+* olr -> Native Openlog Replicator
+* postgres -> PostgreSQL database
## **Check Created Connectors**
@@ -44,21 +45,19 @@ postgres=# select * from synchdb_conninfo;
-[ RECORD 1 ]-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
name | sqlserverconn
isactive | t
-data | {"pwd": "\\xc30d0407030245ca4a983b6304c079d23a0191c6dabc1683e4f66fc538db65b9ab2788257762438961f8201e6bcefafa60460fbf441e55d844e7f27b31745f04e7251c0123a159540676c4", "port": 1433, "user": "sa", "dstdb": "postgres", "srcdb": "testDB", "table": "null", "hostname": "192.168.1.86", "connector": "sqlserver"}
+data | {"pwd": "\\xc30d0407030245ca4a983b6304c079d23a0191c6dabc1683e4f66fc538db65b9ab2788257762438961f8201e6bcefafa60460fbf441e55d844e7f27b31745f04e7251c0123a159540676c4", "port": 1433, "user": "sa", "srcschema": "dbo", "srcdb": "testDB", "table": null, "snapshottable": null, "hostname": "192.168.1.86", "connector": "sqlserver"}
-[ RECORD 2 ]-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
name | mysqlconn
isactive | t
-data | {"pwd": "\\xc30d04070302986aff858065e96b62d23901b418a1f0bfdf874ea9143ec096cd648a1588090ee840de58fb6ba5a04c6430d8fe7f7d466b70a930597d48b8d31e736e77032cb34c86354e", "port": 3306, "user": "mysqluser", "dstdb": "postgres", "srcdb": "inventory", "table": "null", "hostname": "192.168.1.86", "connector": "mysql"}
+data | {"pwd": "\\xc30d04070302986aff858065e96b62d23901b418a1f0bfdf874ea9143ec096cd648a1588090ee840de58fb6ba5a04c6430d8fe7f7d466b70a930597d48b8d31e736e77032cb34c86354e", "port": 3306, "user": "mysqluser", "srcschema": null, "srcdb": "inventory", "table": null, "snapshottable": null, "hostname": "192.168.1.86", "connector": "mysql"}
-[ RECORD 3 ]-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
name | oracleconn
isactive | t
-data | {"pwd": "\\xc30d04070302e3baf1293d0d553066d234014f6fc52e6eea425884b1f65f1955bf504b85062dfe538ca2e22bfd6db9916662406fc45a3a530b7bf43ce4cfaa2b049a1c9af8", "port": 1528, "user": "c##dbzuser", "dstdb": "postgres", "srcdb": "FREE", "table": "null", "hostname": "192.168.1.86", "connector": "oracle"}
+data | {"pwd": "\\xc30d04070302e3baf1293d0d553066d234014f6fc52e6eea425884b1f65f1955bf504b85062dfe538ca2e22bfd6db9916662406fc45a3a530b7bf43ce4cfaa2b049a1c9af8", "port": 1528, "user": "DBZUSER", "srcschema": "DBZUSER", "srcdb": "FREE", "table": null, "snapshottable": null, "hostname": "192.168.1.86", "connector": "oracle"}
```
-<<<**IMPORTANT**>>> Native Openlog Replicator connector currently does not support specifying whitelist tables via `table` and `snapshot tables` parameters so the sections below do not apply to Native Openlog Replicator connector.
-
## **Use a Table List File to Specify Tables**
If there is a large number of tables to replicate, it is possible to use a table list file to specifiy the tables. The list must be formatted as JSON like below:
@@ -67,15 +66,15 @@ If there is a large number of tables to replicate, it is possible to use a table
{
"table_list":
[
- "mydb.myschema.mytable1",
- "mydb.myschema.mytable2",
+ "myschema.mytable1",
+ "myschema.mytable2",
...
...
],
"snapshot_table_list":
[
- "mydb.myschema.mytable1",
- "mydb.myschema.mytable2",
+ "myschema.mytable1",
+ "myschema.mytable2",
...
...
]
@@ -94,41 +93,41 @@ We can normally leave `snapshot table list` parameter to either empty or as `nul
## **Example: Create a Connector for each Supported Source Database to Replicate All Tables**
-1. Create a MySQL connector called `mysqlconn` to replicate all tables under `inventory` in MySQL to destination database `postgres` in PostgreSQL:
+1. Create a MySQL connector called `mysqlconn` to replicate all tables under `inventory` in MySQL. Source schema can be put as 'null' because MySQL does not support it.
```sql
SELECT synchdb_add_conninfo(
'mysqlconn', '127.0.0.1', 3306, 'mysqluser',
- 'mysqlpwd', 'inventory', 'postgres',
+ 'mysqlpwd', 'inventory', 'null',
'null', 'null', 'mysql');
```
-2. Create a SQLServer connector called `sqlserverconn` to replicate all tables under `testDB` to destination database 'postgres' in PostgreSQL:
+2. Create a SQLServer connector called `sqlserverconn` to replicate all tables under `testDB` database and `dbo` schema.
```sql
SELECT
synchdb_add_conninfo(
'sqlserverconn', '127.0.0.1', 1433,
- 'sa', 'Password!', 'testDB', 'postgres',
+ 'sa', 'Password!', 'testDB', 'dbo',
'null', 'null', 'sqlserver');
```
-3. Create a Oracle connector called `oracleconn` to replicate all tables under `FREE` to destination database 'postgres' in PostgreSQL:
+3. Create a Oracle connector called `oracleconn` to replicate all tables under `FREE` database and `DBZUSER` schema:
```sql
SELECT
synchdb_add_conninfo(
'oracleconn', '127.0.0.1', 1521,
- 'c##dbzuser', 'dbz', 'FREE', 'postgres',
+ 'DBZUSER', 'dbz', 'FREE', 'DBZUSER',
'null', 'null', 'oracle');
```
## **Example: Create a Connector to Replicate Specified Tables**
-Note that the tables must be specified in fully-qualified names such as `[database].[table]` or `[database].[schema].[table]` and exist in the source database.
+Note that the tables must be specified in fully-qualified names such as `[database].[table]` or `[schema].[table]` and exist in the source database.
Create a MySQL connector called `mysqlconn` to replicate `orders` and `customers` tables under `inventory` in MySQL to destination database `postgres` in PostgreSQL:
```sql
SELECT synchdb_add_conninfo(
'mysqlconn', '127.0.0.1', 3306, 'mysqluser',
- 'mysqlpwd', 'inventory', 'postgres',
+ 'mysqlpwd', 'inventory', 'null',
'inventory.orders,inventory.customers', 'null', 'mysql');
```
@@ -139,7 +138,7 @@ Create a MySQL connector called `mysqlconn` to replicate the tables specified in
```sql
SELECT synchdb_add_conninfo(
'mysqlconn', '127.0.0.1', 3306, 'mysqluser',
- 'mysqlpwd', 'inventory', 'postgres',
+ 'mysqlpwd', 'inventory', 'null',
'file:/path/to/mytablefile.json', 'file:/path/to/mytablefile.json', 'mysql');
```
diff --git a/doc/docs/en/user-guide/customize_transform.md b/doc/docs/en/user-guide/customize_transform.md
deleted file mode 100644
index ed6f192..0000000
--- a/doc/docs/en/user-guide/customize_transform.md
+++ /dev/null
@@ -1 +0,0 @@
-# Customize Transformation Rules
\ No newline at end of file
diff --git a/doc/docs/en/user-guide/default_datatype_mapping.md b/doc/docs/en/user-guide/default_datatype_mapping.md
index 3907875..2be9ba1 100644
--- a/doc/docs/en/user-guide/default_datatype_mapping.md
+++ b/doc/docs/en/user-guide/default_datatype_mapping.md
@@ -22,9 +22,15 @@ The default data type mapping entries can be overwritten by defining a object ma
DatatypeHashEntry mysql_defaultTypeMappings[] =
{
{{"int", true}, "serial", 0},
+ {{"int unsigned", true}, "serial", 0},
{{"bigint", true}, "bigserial", 0},
+ {{"bigint unsigned", true}, "bigserial", 0},
{{"smallint", true}, "smallserial", 0},
+ {{"smallint unsigned", true}, "smallserial", 0},
{{"mediumint", true}, "serial", 0},
+ {{"mediumint unsigned", true}, "serial", 0},
+ {{"tinyint", true}, "smallserial", 0},
+ {{"tinyint unsigned", true}, "smallserial", 0},
{{"enum", false}, "text", 0},
{{"set", false}, "text", 0},
{{"bigint", false}, "bigint", 0},
@@ -65,20 +71,20 @@ DatatypeHashEntry mysql_defaultTypeMappings[] =
{{"mediumblob", false}, "bytea", 0},
{{"longblob", false}, "bytea", 0},
{{"tinyblob", false}, "bytea", 0},
- {{"long varchar", false}, "text", -1},
- {{"longtext", false}, "text", -1},
- {{"mediumtext", false}, "text", -1},
- {{"tinytext", false}, "text", -1},
+ {{"long varchar", false}, "text", 0},
+ {{"longtext", false}, "text", 0},
+ {{"mediumtext", false}, "text", 0},
+ {{"tinytext", false}, "text", 0},
{{"json", false}, "jsonb", -1},
- {{"geometry", false}, "text", -1},
- {{"geometrycollection", false}, "text", -1},
- {{"geomcollection", false}, "text", -1},
- {{"linestring", false}, "text", -1},
- {{"multilinestring", false}, "text", -1},
- {{"multipoint", false}, "text", -1},
- {{"multipolygon", false}, "text", -1},
- {{"point", false}, "text", -1},
- {{"polygon", false}, "text", -1}
+ {{"geometry", false}, "text", 0},
+ {{"geometrycollection", false}, "text", 0},
+ {{"geomcollection", false}, "text", 0},
+ {{"linestring", false}, "text", 0},
+ {{"multilinestring", false}, "text", 0},
+ {{"multipoint", false}, "text", 0},
+ {{"multipolygon", false}, "text", 0},
+ {{"point", false}, "text", 0},
+ {{"polygon", false}, "text", 0}
};
```
@@ -209,3 +215,80 @@ DatatypeHashEntry oracle_defaultTypeMappings[] =
{{"anydataset", false}, "text", 0},
};
```
+
+## **Postgres Default Data Type Mapping**
+
+```c
+DatatypeHashEntry postgres_defaultTypeMappings[] =
+{
+ {{"bigint", false}, "bigint", 0},
+ {{"bigserial", false}, "bigserial", 0},
+ {{"bigserial", true}, "bigserial", 0},
+ {{"bit", false}, "bit", -1},
+ {{"bit varying", false}, "bit varying", -1},
+ {{"bool", false}, "bool", 0},
+ {{"boolean", false}, "boolean", 0},
+ {{"box", false}, "box", 0},
+ {{"bytea", false}, "bytea", 0},
+ {{"char", false}, "char", -1},
+ {{"character", false}, "character", -1},
+ {{"character varying", false}, "character varying", -1},
+ {{"cidr", false}, "cidr", 0},
+ {{"circle", false}, "circle", 0},
+ {{"date", false}, "date", 0},
+ {{"decimal", false}, "dedcimal", -1},
+ {{"double precision", false}, "double precision", 0},
+ {{"float", false}, "float", 0},
+ {{"float4", false}, "float4", 0},
+ {{"float8", false}, "float8", 0},
+ {{"inet", false}, "inet", 0},
+ {{"int", false}, "int", 0},
+ {{"int2", false}, "int2", 0},
+ {{"int4", false}, "int4", 0},
+ {{"int8", false}, "int8", 0},
+ {{"integer", false}, "integer", 0},
+ {{"interval", false}, "interval", -1},
+ {{"json", false}, "json", 0},
+ {{"jsonb", false}, "jsonb", 0},
+ {{"line", false}, "line", 0},
+ {{"lseg", false}, "lseg", 0},
+ {{"macaddr", false}, "macaddr", 0},
+ {{"macaddr8", false}, "macaddr8", 0},
+ {{"money", false}, "money", 0},
+ {{"numeric", false}, "numeric", -1},
+ {{"path", false}, "path", 0},
+ {{"pg_lsn", false}, "pg_lsn", 0},
+ {{"pg_snapshot", false}, "pg_snapshot", 0},
+ {{"point", false}, "point", 0},
+ {{"polygon", false}, "polygon", 0},
+ {{"real", false}, "real", 0},
+ {{"smallint", false}, "smallint", 0},
+ {{"smallserial", false}, "smallserial", 0},
+ {{"smallserial", true}, "smallserial", 0},
+ {{"serial", false}, "serial", 0},
+ {{"serial", true}, "serial", 0},
+ {{"serial2", false}, "serial2", 0},
+ {{"serial2", true}, "serial2", 0},
+ {{"serial4", false}, "serial4", 0},
+ {{"serial4", true}, "serial4", 0},
+ {{"serial8", false}, "serial8", 0},
+ {{"serial8", true}, "serial8", 0},
+ {{"text", false}, "text", 0},
+ {{"time without time zone", false}, "time without time zone", -1},
+ {{"time with time zone", false}, "time with time zone", -1},
+ {{"time", false}, "time", -1},
+ {{"timetz", false}, "timetz", -1},
+ {{"timestamp without time zone", false}, "timestamp without time zone", -1},
+ {{"timestamp with time zone", false}, "timestamp with time zone", -1},
+ {{"timestamp", false}, "timestamp", -1},
+ {{"timestamptz", false}, "timestamptz", -1},
+ {{"tsquery", false}, "tsquery", 0},
+ {{"tsvector", false}, "tsvector", 0},
+ {{"txid_snapshot", false}, "txid_snapshot", 0},
+ {{"uuid", false}, "uuid", 0},
+ {{"varbit", false}, "varbit", -1},
+ {{"varchar", false}, "varchar", -1},
+ {{"xml", false}, "xml", 0},
+ /* ... */
+};
+```
diff --git a/doc/docs/en/user-guide/letter_casing_strategy.md b/doc/docs/en/user-guide/letter_casing_strategy.md
new file mode 100644
index 0000000..ccfd41a
--- /dev/null
+++ b/doc/docs/en/user-guide/letter_casing_strategy.md
@@ -0,0 +1,30 @@
+# Letter Casing Strategy
+
+## Configure Letter Casing Strategy
+
+Letter casing strategy represents how SynchDB should normalize source object names before applying them to destination. MySQL, SQL Server and PostgreSQL default all object names to lower case letters while Oracle defaults to upper case. MySQL, Oracle and PostgreSQL allow object names to contain a mixture of upper and lower case letters, and consider each variant different while SQL Server treats them as all the same.
+
+It is possible to tell SynchDB how to handle the object names using `synchdb.letter_casing_strategy` GUC parameter with these possible values:
+
+* lowercase: normalize all object names (table and column names) to lower case letters
+* uppercase: normalize all object names (table and column names) to upper case letters
+* asis: do not normalize, keep object names(table and column names) as is.
+
+<> synchdb.letter_casing_strategy does not affect data type names. It is always normalized to lower case in SynchDB. Connectors like SQL Server and Oracle express data type in upper case letters, so these are stored and displayed as lower case in SynchDB.
+
+## How does Letter Casing Strategy Affect Transformation
+
+You may wonder if SynchDB normalizes object names according to `synchdb.letter_casing_strategy`, how shall [object transformation](../../user-guide/object_mapping_rules/) be configured correctly to identify a foreign table or column to transform?
+
+Object transformation identifies the original name from source database for transformation, so you have to configure the object name exactly as they appear in the source database, not the one normalized by SynchDB.
+
+If a match is found, SynchDB will prioritize the new value as identified by the object transformation and will not proceed to normalize it according to the letter casing strategy. Normalization occurs when there is no particular transformation rule defined for an object
+
+For example, for an Oracle table 'TEST_TABLE' under database 'FREE' and schema 'DBZUSER', let's say we want to map it to "MY_TEST_TABLE" (all capital) in PostgreSQL and current synchdb.letter_casing_strategy is 'lowercase'. You will write the transform rule like this:
+
+```sql
+
+SELECT synchdb_add_objmap('mysqlconn','table','FREE.DBZUSER.TEST_TABLE','MY_TEST_TABLE');
+```
+
+Since we have transformation rule specifically for "FREE.DBZUSER.TEST_TABLE", this transformation will take precedence and transform it to 'MY_TEST_TABLE` as instructed. The letter casing strategy (lowercase) will not normalize it to lowercase.
diff --git a/doc/docs/en/user-guide/secured_connection.md b/doc/docs/en/user-guide/secured_connection.md
deleted file mode 100644
index b4520ff..0000000
--- a/doc/docs/en/user-guide/secured_connection.md
+++ /dev/null
@@ -1,32 +0,0 @@
-# Secured Connection
-
-## **Configure Secured Connection**
-
-to secure the connection to remote database, we need to configure additional SSL related parameters to a connector that has been created by `synchdb_add_conninfo`. The SSL certificates and private keys must be packaged as Java keystore file with a passphrase. These information is then passed to SynchDB via synchdb_add_extra_conninfo().
-
-<<**IMPORTANT**>> Secured connection is not available for Openlog Replicator Connector
-
-## **synchdb_add_extra_conninfo**
-
-**Purpose**: Configures extra connector parameters to an existing connector created by `synchdb_add_conninfo`
-
-| Parameter | Description | Required | Example | Notes |
-|:-:|:-|:-:|:-|:-|
-| `name` | Unique identifier for this connector | ✓ | `'mysqlconn'` | Must be unique across all connectors |
-| `ssl_mode` | SSL mode | ☐ | `'verify_ca'` | can be one of:
- "disabled" - no SSL is used.
- "preferred" - SSL is used if server supports it.
- "required" - SSL must be used to establish a connection.
- "verify_ca" - connector establishes TLS with the server and will also verify server's TLS certificate against configured truststore.
- "verify_identity" - same behavior as verify_ca but it also checks the server certificate's common name to match the hostname of the system. |
-| `ssl_keystore` | keystore path | ☐ | `/path/to/keystore` | path to the keystore file |
-| `ssl_keystore_pass` | keystore password | ☐ | `'mykeystorepass'` | password to access the keystore file |
-| `ssl_truststore` | trust store path | ☐ | `'/path/to/truststore'` | path to the truststore file |
-| `ssl_truststore_pass` | trust store password | ☐ | `'mytruststorepass'` | password to access the truststore file |
-
-
-```sql
-SELECT synchdb_add_extra_conninfo('mysqlconn', 'verify_ca', '/path/to/keystore', 'mykeystorepass', '/path/to/truststore', 'mytruststorepass');
-```
-
-## **synchdb_del_extra_conninfo**
-
-**Purpose**: Deletes extra connector paramters created by `synchdb_add_extra_conninfo`
-```sql
-SELECT synchdb_del_extra_conninfo('mysqlconn');
-```
\ No newline at end of file
diff --git a/doc/docs/en/user-guide/set_offset.md b/doc/docs/en/user-guide/set_offset.md
deleted file mode 100644
index 4be1212..0000000
--- a/doc/docs/en/user-guide/set_offset.md
+++ /dev/null
@@ -1,58 +0,0 @@
----
-weight: 100
----
-# Custom Start Offset Values
-
-A start offset value represents a point to start replication from in the similar way as PostgreSQL's resume LSN. When Debezium runner engine starts, it will start the replication from this offset value. Setting this offset value to a earlier value will cause Debezium runner engine to start replication from earlier records, possibly replicating duplicate data records. We should be extra cautious when setting start offset values on Debezium.
-
-## **Record Settable Offset Values**
-
-During operation, new offsets will be generated nd flushed to disk by Debezium runner engine. The last flushed offset can be retrieved from `synchdb_state_view()` utility command:
-
-```sql
-postgres=# select name, last_dbz_offset from synchdb_state_view;
- name | last_dbz_offset
----------------+------------------------------------------------------------------------------------------------------
- sqlserverconn | {"commit_lsn":"0000006a:00006608:0003","snapshot":true,"snapshot_completed":false}
- mysqlconn | {"ts_sec":1741301103,"file":"mysql-bin.000009","pos":574318212,"row":1,"server_id":223344,"event":2}
- oracleconn | {"commit_scn":"2311579","snapshot_scn":"2311578","scn":"2311578"}
-(3 rows)
-
-```
-
-Depending on the connector type, this offset value differs. From the example above, the `mysql` connector's last flushed offset is `{"ts_sec":1741301103,"file":"mysql-bin.000009","pos":574318212,"row":1,"server_id":223344,"event":2}` and `sqlserver`'s last flushed offset is `{"commit_lsn":"0000006a:00006608:0003","snapshot":true,"snapshot_completed":false}`.
-
-We should save this values regularly, so in case we run into a problem, we know the offset location in the past that can be set to resume the replication operation.
-
-
-## **Pause the Connector**
-
-A connector must be in a `paused` state before a new offset value can be set.
-
-Use `synchdb_pause_engine()` SQL function to pause a runnng connector. This will halt the Debezium runner engine from replicating from the heterogeneous database. When paused, it is possible to alter the Debezium connector's offset value to replicate from a specific point in the past using `synchdb_set_offset()` SQL routine. It takes `conninfo_name` as its argument which can be found from the output of `synchdb_get_state()` view.
-
-For example:
-```sql
-SELECT synchdb_pause_engine('mysqlconn');
-```
-
-## **Set the new Offset**
-
-Use `synchdb_set_offset()` SQL function to change a connector worker's starting offset. This can only be done when the connector is put into `paused` state. The function takes 2 parameters, `conninfo_name` and `a valid offset string`, both of which can be found from the output of `synchdb_get_state()` view.
-
-For example:
-```sql
-SELECT
- synchdb_set_offset(
- 'mysqlconn', '{"ts_sec":1741301103,"file":"mysql-bin.000009","pos":574318212,"row":1,"server_id":223344,"event":2}'
- );
-```
-
-## **Resume the Connector**
-
-Use `synchdb_resume_engine()` SQL function to resume Debezium operation from a paused state. This function takes `connector name` as its only parameter, which can be found from the output of `synchdb_get_state()` view. The resumed Debezium runner engine will start the replication from the newly set offset value.
-
-For example:
-```sql
-SELECT synchdb_resume_engine('mysqlconn');
-```
diff --git a/doc/docs/en/user-guide/start_stop_connector.md b/doc/docs/en/user-guide/start_stop_connector.md
index e5006d9..9daabb0 100644
--- a/doc/docs/en/user-guide/start_stop_connector.md
+++ b/doc/docs/en/user-guide/start_stop_connector.md
@@ -33,8 +33,6 @@ SELECT synchdb_start_engine_bgw('mysqlconn', 'always');
| `initial_only` | One-time snapshot, then stop | Data migration |
| `no_data` | Structure only, no data | Schema synchronization |
| `never` | Skip snapshot, stream only | Real-time updates |
-| `recovery` | Rebuilds from source | Disaster recovery |
-| `when_needed` | Conditional snapshot | Automatic recovery |
| `schemasync` | Structure only, no data, no CDC | normal operations |
diff --git a/doc/docs/en/user-guide/utility_functions.md b/doc/docs/en/user-guide/utility_functions.md
deleted file mode 100644
index fa2a653..0000000
--- a/doc/docs/en/user-guide/utility_functions.md
+++ /dev/null
@@ -1,382 +0,0 @@
----
-weight: 110
----
-# Function Reference
-
-This page documents all the SQL functions / views added by SynchDB.
-
-## **Connector Management**
-
-### **synchdb_add_conninfo**
-
-**Purpose**: Creates a new connector configuration
-
-**Parameters**:
-
-| Parameter | Description | Required | Example | Notes |
-|:-:|:-|:-:|:-|:-|
-| `name` | Unique identifier for this connector | ✓ | `'mysqlconn'` | Must be unique across all connectors |
-| `hostname` | IP/hostname of heterogeneous database | ✓ | `'127.0.0.1'` | Support IPv4, IPv6, and hostnames |
-| `port` | Port number for database connection | ✓ | `3306` | Default: MySQL(3306), SQLServer(1433) |
-| `username` | Authentication username | ✓ | `'mysqluser'` | Requires appropriate permissions |
-| `password` | Authentication password | ✓ | `'mysqlpwd'` | Stored securely |
-| `source database` | Source database name | ✓ | `'inventory'` | Must exist in source system |
-| `destination database` | Target PostgreSQL database | ✓ | `'postgres'` | (deprecated) will always be adjusted to the same database where SynchDB is installed |
-| `table` | Table specification pattern | ☐ | `'[db].[table]'` | Empty = replicate all tables, support regular expressions (for example, mydb.testtable*), use `file:` prefix to make connector read table list from a JSON file (for example, file:/path/to/filelist.json). See below for file format |
-| `connector` | Connector type (`mysql`/`sqlserver`) | ✓ | `'mysql'` | See supported connectors above |
-
-**Tablelist File Example**:
-```json
-{
- "table_list":
- [
- "mydb.table1",
- "mydb.table2",
- "mydb.table3",
- "mydb.table4"
- ]
-}
-```
-
-**Example Usage**:
-```sql
--- MySQL Example
-SELECT synchdb_add_conninfo(
- 'mysqlconn', -- Connector name
- '127.0.0.1', -- Host
- 3306, -- Port
- 'mysqluser', -- Username
- 'mysqlpwd', -- Password
- 'inventory', -- Source DB
- 'postgres', -- Target DB
- '', -- Tables (empty for all)
- 'mysql' -- Connector type
-);
-
--- SQL Server Example
-SELECT synchdb_add_conninfo(
- 'sqlserverconn',
- '127.0.0.1',
- 1433,
- 'sa',
- 'MyPassword123',
- 'testDB',
- 'postgres',
- 'dbo.orders', -- Specific table
- 'sqlserver'
-);
-
--- Oracle Example
-SELECT synchdb_add_conninfo(
- 'oracleconn',
- '127.0.0.1',
- 1521,
- 'c##dbzuser',
- 'dbz',
- 'mydb',
- 'postgres',
- '', -- all tables
- 'oracle'
-);
-```
-
-### **synchdb_add_objmap**
-
-**Purpose**: Adds an object mapping rule per connector
-
-| Parameter | Description | Required | Example | Notes |
-|:-:|:-|:-:|:-|:-|
-| `name` | Unique identifier for this connector | ✓ | `'mysqlconn'` | Must be unique across all connectors |
-| `object type` | type of object mapping | ✓ | `'table'` | can be `table` to map a table name, `column` to map a column name, `datatype` to map a data type, or `transform` to run a data transform expression |
-| `source object` | source object represented as fully-qualified name | ✓ | `inventory.customers` | the object name as represented in the remote database |
-| `destination object` | destination object name | ✓ | `'schema1.people'` | The destination object name in PostgreSQL side. Can be a fully-qualified table name, a column name, a data type or transform expression |
-
-```sql
-SELECT synchdb_add_objmap('mysqlconn','table','inventory.customers','schema1.people');
-SELECT synchdb_add_objmap('mysqlconn','column','inventory.customers.email','contact');
-SELECT synchdb_add_objmap('mysqlconn','datatype','point|false','text|0');
-SELECT synchdb_add_objmap('mysqlconn','datatype','inventory.geom.g','geometry|0');
-SELECT synchdb_add_objmap('mysqlconn','transform','inventory.products.name','''>>>>>'' || ''%d'' || ''<<<<<''');
-```
-**Ways to represent a `table` mapping:**
-* `source object` represents the table in fully-qualified name in remote database
-* `destination object` represents the table name in PostgreSQL. It can be just a name (default to public schema) or in schema.name format.
-
-**Ways to represent a `column` mapping:**
-* `source object` represents the column in fully-qualified name in remote database
-* `destination object` represents the column name in PostgreSQL. No need to format it as fully-qualified column name.
-
-**Ways to represent a `datatype` mapping:**
-* `source object` can be expressed as one of:
- * a fully-qualified column (inventory.geom.g). This means the data type mapping applies to this particular column only.
- * a general data type string (int). Use a pipe (|) to add if it is a autoincrement data type (int|true for autoincremented int) or (int|false for a non-autoincremented int). This means data type mapping applies to all data type with the matching condition.
-
-* `destination object` should be expressed as a general data type string that exists in PostgreSQL. Use a pipe (|) to overwrite the size (text|0 to overwrite the size to 0 because text is variable size) or (varchar|-1 to use whatever size that comes with the change event)
-
-**Ways to represent a `transform` mapping:**
-* `source object` represents the column to be transformed
-* `destination object` represents an expression to be run on the column data before it is applied to PostgreSQL. Use %d as a placeholder for input column data. In case of geometry type, use %w for WKB and %s for SRID.
-
-### **synchdb_add_extra_conninfo**
-
-**Purpose**: Configures extra connector parameters to an existing connector created by `synchdb_add_conninfo`
-
-| Parameter | Description | Required | Example | Notes |
-|:-:|:-|:-:|:-|:-|
-| `name` | Unique identifier for this connector | ✓ | `'mysqlconn'` | Must be unique across all connectors |
-| `ssl_mode` | SSL mode | ☐ | `'verify_ca'` | can be one of:
- "disabled" - no SSL is used.
- "preferred" - SSL is used if server supports it.
- "required" - SSL must be used to establish a connection.
- "verify_ca" - connector establishes TLS with the server and will also verify server's TLS certificate against configured truststore.
- "verify_identity" - same behavior as verify_ca but it also checks the server certificate's common name to match the hostname of the system. |
-| `ssl_keystore` | keystore path | ☐ | `/path/to/keystore` | path to the keystore file |
-| `ssl_keystore_pass` | keystore password | ☐ | `'mykeystorepass'` | password to access the keystore file |
-| `ssl_truststore` | trust store path | ☐ | `'/path/to/truststore'` | path to the truststore file |
-| `ssl_truststore_pass` | trust store password | ☐ | `'mytruststorepass'` | password to access the truststore file |
-
-
-```sql
-SELECT synchdb_add_extra_conninfo('mysqlconn', 'verify_ca', '/path/to/keystore', 'mykeystorepass', '/path/to/truststore', 'mytruststorepass');
-```
-
-### **synchdb_del_extra_conninfo**
-
-**Purpose**: Deletes extra connector paramters created by `synchdb_add_extra_conninfo`
-```sql
-SELECT synchdb_del_extra_conninfo('mysqlconn');
-```
-
-### **synchdb_del_conninfo**
-
-**Purpose**: Deletes connector information created by `synchdb_add_conninfo`
-```sql
-SELECT synchdb_del_extra_conninfo('mysqlconn');
-```
-
-### **synchdb_del_objmap**
-
-**Purpose**: Disables object mapping records created by `synchdb_add_objmap`
-
-| Parameter | Description | Required | Example | Notes |
-|:-:|:-|:-:|:-|:-|
-| `name` | Unique identifier for this connector | ✓ | `'mysqlconn'` | Must be unique across all connectors |
-| `object type` | type of object mapping | ✓ | `'table'` | can be `table` to map a table name, `column` to map a column name, `datatype` to map a data type, or `transform` to run a data transform expression |
-| `source object` | source object represented as fully-qualified name | ✓ | `inventory.customers` | the object name as represented in the remote database |
-
-```sql
-SELECT synchdb_del_extra_conninfo('mysqlconn', 'transform', 'inventory.products.name');
-```
-
-## **Basic Control Functions**
-
-### **synchdb_start_engine_bgw**
-
-**Purpose**: Starts a connector
-```sql
-SELECT synchdb_start_engine_bgw('mysqlconn');
-```
-You may also include snapshot mode to start the connector with, otherwise the `initial` mode will be used by default. See below for list of different snapshot modes.
-```sql
--- capture table schema and proceed to stream new changes
-SELECT synchdb_start_engine_bgw('mysqlconn', 'no_data');
-
--- always re-capture table schema, existing data and proceed to stream new changes
-SELECT synchdb_start_engine_bgw('mysqlconn', 'always');
-```
-
-### **synchdb_pause_engine**
-
-**Purpose**: Temporarily halts a running connector
-```sql
-SELECT synchdb_pause_engine_bgw('mysqlconn');
-```
-
-### **synchdb_resume_engine**
-
-**Purpose**: Resumes a paused connector
-```sql
-SELECT synchdb_resume_engine('mysqlconn');
-```
-
-### **synchdb_stop_engine_bgw**
-
-**Purpose**: Terminates a connector
-```sql
-SELECT synchdb_stop_engine('mysqlconn');
-```
-
-### **synchdb_reload_objmap**
-
-**Purpose**: Causes a connector to load object mapping rules again
-```sql
-SELECT synchdb_reload_objmap('mysqlconn');
-```
-
-## **State Management**
-
-### **synchdb_state_view**
-
-**Purpose**: Monitors connector states and status
-
-```sql
-SELECT * FROM synchdb_state_view();
-```
-
-**Return Fields**:
-
-| Field | Description | Type |
-|-|-|-|
-| `name` | Associated connector name | Text |
-| `connector_type` | Connector type (`mysql` or `sqlserver`) | Text |
-| `pid` | Worker process ID | Integer |
-| `stage` | Current connector stage | Text |
-| `state` | Current connector state | Text |
-| `err` | Latest error message | Text |
-| `last_dbz_offset` | Last recorded Debezium offset | JSON |
-
-**Possible States**:
-
-- 🔴 `stopped` - Inactive
-- 🟡 `initializing` - Starting up
-- 🟠 `paused` - Temporarily halted
-- 🟢 `syncing` - Actively polling
-- 🔵 `parsing` - Processing events
-- 🟣 `converting` - Transforming data
-- ⚪ `executing` - Applying changes
-- 🟤 `updating offset` - Updating checkpoint
-- 🟨 `restarting` - Reinitializing
-- ⚪ `dumping memory` - JVM is prepaaring to dump memory info in log file
-- ⚫ `unknown` - Indeterminate state
-
-**Possible Stages**:
-
-- `initial snapshot` - connector is performing initial snapshot (building table schema and optionally the initial data)
-- `change data capture` - connector is streaming subsequent table changes (CDC)
-- `schema sync` - connector is copying table schema only
-
-### **synchdb_stats_view**
-
-**Purpose**: Collects connector processing statistics cumulatiely
-
-```sql
-SELECT * FROM synchdb_stats_view();
-```
-
-| Field | Description | Type |
-|-|-|-|
-| name | Associated connector name | Text |
-| ddls | Number of DDLs operations completed | Bigint |
-| dmls | Number of DMLs operations completed | Bigint |
-| reads | Number of READ events completed during initial snapshot stage | Bigint |
-| creates | Number of CREATES events completed during CDC stage | Bigint |
-| updates | Number of UPDATES events completed during CDC stage | Bigint |
-| deletes | Number of DELETES events completed during CDC stage | Bigint |
-| bad_events | Number of bad events ignored (such as empty events, unsupported DDL events..etc) | Bigint |
-| total_events | Total number of events processed (including bad_events) | Bigint |
-| batches_done | Number of batches completed | Bigint |
-| avg_batch_size | Average batch size (total_events / batches_done) | Bigint |
-
-### **synchdb_reset_stats**
-
-**Purpose**: Resets all statistic information of given connector name
-
-```sql
-SELECT synchdb_reset_stats('mysqlconn');
-```
-
-### **synchdb_set_offset**
-
-**Purpose**: Configures custom start position
-
-**Example for MySQL**:
-```sql
-SELECT synchdb_set_offset(
- 'mysqlconn',
- '{"ts_sec":1725644339,"file":"mysql-bin.000004","pos":138466,"row":1,"server_id":223344,"event":2}'
-);
-```
-
-**Example for SQL Server**:
-```sql
-SELECT synchdb_set_offset(
- 'sqlserverconn',
- '{"event_serial_no":1,"commit_lsn":"00000100:00000c00:0003","change_lsn":"00000100:00000c00:0002"}'
-);
-```
-
-### **synchdb_log_jvm_meminfo**
-
-**Purpose**: Cause the Java Virtual Machine (JVM) to log the current heap and non-heap usages statistics.
-```sql
-SELECT synchdb_log_jvm_meminfo('mysqlconn');
-```
-
-Check the PostgreSQL log file:
-```
-2024-12-09 14:34:21.910 PST [25491] LOG: Requesting memdump for mysqlconn connector
-2024-12-09 14:34:21 WARN DebeziumRunner:297 - Heap Memory:
-2024-12-09 14:34:21 WARN DebeziumRunner:298 - Used: 19272600 bytes
-2024-12-09 14:34:21 WARN DebeziumRunner:299 - Committed: 67108864 bytes
-2024-12-09 14:34:21 WARN DebeziumRunner:300 - Max: 2147483648 bytes
-2024-12-09 14:34:21 WARN DebeziumRunner:302 - Non-Heap Memory:
-2024-12-09 14:34:21 WARN DebeziumRunner:303 - Used: 42198864 bytes
-2024-12-09 14:34:21 WARN DebeziumRunner:304 - Committed: 45023232 bytes
-2024-12-09 14:34:21 WARN DebeziumRunner:305 - Max: -1 bytes
-
-```
-
-### **synchdb_att_view**
-
-**Purpose**: Displays a side-by-side view of a connector's data type, name mapping and transform rule relationships between foreign and local tables.
-
-```sql
-SELECT * FROM synchdb_att_view();
-```
-
-**Return Fields**:
-
-| Field | Description | Type |
-|-|-|-|
-| `name` | Connector identifier | Text |
-| `attnum` | Attribute number | Integer |
-| `ext_tbname` | table name as appeared remotely | Text |
-| `pg_tbname` | mapped table name in PostgreSQL | Text |
-| `ext_attname` | column name as appeared remotely | Text |
-| `pg_attname` | mapped column name in PostgreSQL | Text |
-| `ext_atttypename` | data type as appeared remotely | Text |
-| `pg_atttypename` | mapped data type in PostgreSQL | Text |
-| `transform` | transform expression | Text |
-
-## **Snapshot Management**
-
-### **synchdb_restart_connector**
-
-**Purpose**: Reinitializes connector with specified snapshot mode
-
-**Snapshot Modes**:
-
-| Mode | Description | Use Case |
-|:-:|-|-|
-| `always` | Full snapshot on every start | Complete data verification |
-| `initial` | First-time snapshot only | Normal operations |
-| `initial_only` | One-time snapshot, then stop | Data migration |
-| `no_data` | Structure only, no data | Schema synchronization |
-| `never` | Skip snapshot, stream only | Real-time updates |
-| `recovery` | Rebuilds from source | Disaster recovery |
-| `when_needed` | Conditional snapshot | Automatic recovery |
-| `schemasync` | Structure only, no data, no CDC | normal operations |
-
-**Example**:
-```sql
--- Restart with specific snapshot mode
-SELECT synchdb_restart_connector('mysqlconn', 'initial');
-
--- Start with specific snapshot mode
-SELECT synchdb_start_engine_bgw('mysqlconn', 'always');
-```
-
----
-📝 **Additional Notes**:
-
-- Always validate connector configuration before starting
-- Monitor system resources during snapshot operations
-- Back up PostgreSQL destination database before major operations
-- Test connectivity from PostgreSQL server to source database
-- Ensure source database has required permissions configured
-- Regular monitoring of error logs recommended
\ No newline at end of file
diff --git a/doc/docs/zh/architecture/test_framework.md b/doc/docs/zh/architecture/test_framework.md
deleted file mode 100644
index 714b65f..0000000
--- a/doc/docs/zh/architecture/test_framework.md
+++ /dev/null
@@ -1 +0,0 @@
-# 测试框架
\ No newline at end of file
diff --git a/doc/docs/zh/getting-started/quick_start.md b/doc/docs/zh/getting-started/quick_start.md
index a45462b..0935c8d 100644
--- a/doc/docs/zh/getting-started/quick_start.md
+++ b/doc/docs/zh/getting-started/quick_start.md
@@ -101,7 +101,7 @@ SELECT synchdb_add_conninfo('mysqlconn',
'mysqluser',
'mysqlpwd',
'inventory',
- 'postgres',
+ 'null',
'null',
'null',
'mysql');
@@ -116,7 +116,7 @@ SELECT synchdb_add_conninfo('sqlserverconn',
'sa',
'Password!',
'testDB',
- 'postgres',
+ 'dbo',
'null',
'null',
'sqlserver');
@@ -131,7 +131,7 @@ SELECT synchdb_add_conninfo('oracleconn',
'c##dbzuser',
'dbz',
'FREE',
- 'postgres',
+ 'c##dbzuser',
'null',
'null',
'oracle');
@@ -146,7 +146,7 @@ SELECT synchdb_add_conninfo('ora19cconn',
'DBZUSER',
'dbz',
'FREE',
- 'postgres',
+ 'DBZUSER',
'null',
'null',
'oracle');
@@ -161,7 +161,7 @@ SELECT synchdb_add_conninfo('olrconn',
'DBZUSER',
'dbz',
'FREE',
- 'postgres',
+ 'DBZUSER',
'null',
'null',
'olr');
diff --git a/doc/docs/zh/getting-started/remote_database_setups.md b/doc/docs/zh/getting-started/remote_database_setups.md
index 20df888..2fc0975 100644
--- a/doc/docs/zh/getting-started/remote_database_setups.md
+++ b/doc/docs/zh/getting-started/remote_database_setups.md
@@ -272,9 +272,22 @@ ALTER TABLE products ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;
... etc
```
-## **Openlog Replicator 支持的其他 Oracle 设置**
+## **為 SynchDB 設定原生 Openlog Replicator 連接器**
-Openlog Replicator 需要额外权限才能流式传输 Oracle 更改:
+### **要求**
+
+- **Openlog Replicator 版本**:`1.3.0` ~ `1.8.5`(已驗證與 Debezium 2.7.x 相容)
+- 具有可供 OLR 存取的重做日誌的 Oracle 實例
+- 必須授予 OLR 額外的權限(見下文)
+- Openlog Replicator 必須已設定並正在執行
+- SynchDB 中已存在 Oracle 連接器(使用 `synchdb_add_conninfo()` 建立)
+- <<<**重要**>>> **SynchDB 必須使用標誌 (WITH_OLR=1) 編譯和構建,才能支援原生 Openlog Replicator 連接器**
+
+請參閱此[外部指南](https://highgo.atlassian.net/wiki/external/OTUzY2Q2OWFkNzUzNGVkM2EyZGIyMDE1YzVhMDdkNWE)有關透過 Docker 部署 Openlog Replicator 的詳細信息,請參閱相關文件。
+
+### **額外的 Oracle 權限**
+
+除了 Oracle 連接器所需的設定外,Openlog Replicator 還需要以下額外權限:
```sql
@@ -318,6 +331,129 @@ BEGIN
END;
```
+## **Openlog Replicator 設定範例**
+
+SynchDB 的 OLR 支援基於以下組態範例建置。
+
+
+**Version 1.3.0**
+```json
+{
+ "version": "1.3.0",
+ "source": [
+ {
+ "alias": "SOURCE",
+ "name": "ORACLE",
+ "reader": {
+ "type": "online",
+ "user": "DBZUSER",
+ "password": "dbz",
+ "server": "//ora19c:1521/FREE"
+ },
+ "format": {
+ "type": "json",
+ "column": 2,
+ "db": 3,
+ "interval-dts": 9,
+ "interval-ytm": 4,
+ "message": 2,
+ "rid": 1,
+ "schema": 7,
+ "timestamp-all": 1,
+ "scn-all": 1
+ },
+ "memory": {
+ "min-mb": 64,
+ "max-mb": 1024
+ },
+ "filter": {
+ "table": [
+ {"owner": "DBZUSER", "table": ".*"}
+ ]
+ },
+ "flags": 32
+ }
+ ],
+ "target": [
+ {
+ "alias": "SYNCHDB",
+ "source": "SOURCE",
+ "writer": {
+ "type": "network",
+ "uri": "0.0.0.0:7070"
+ }
+ }
+ ]
+}
+
+```
+
+**Version 1.8.5**
+```json
+{
+ "version": "1.8.5",
+ "source": [
+ {
+ "alias": "SOURCE",
+ "name": "ORACLE",
+ "reader": {
+ "type": "online",
+ "user": "DBZUSER",
+ "password": "dbz",
+ "server": "//ora19c:1521/FREE"
+ },
+ "format": {
+ "type": "json",
+ "column": 2,
+ "db": 3,
+ "interval-dts": 9,
+ "interval-ytm": 4,
+ "message": 2,
+ "rid": 1,
+ "schema": 7,
+ "timestamp-all": 1,
+ "scn-type": 1
+ },
+ "memory": {
+ "min-mb": 64,
+ "max-mb": 1024,
+ "swap-path": "/opt/OpenLogReplicator/olrswap"
+ },
+ "filter": {
+ "table": [
+ {"owner": "DBZUSER", "table": ".*"}
+ ]
+ },
+ "flags": 32
+ }
+ ],
+ "target": [
+ {
+ "alias": "DEBEZIUM",
+ "source": "SOURCE",
+ "writer": {
+ "type": "network",
+ "uri": "0.0.0.0:7070"
+ }
+ }
+ ]
+}
+
+```
+
+請注意以下事項:
+
+- "source".name": "ORACLE" -> 使用 `synchdb_add_olr_conninfo()` 定義 OLR 參數時,此項目應與 `olr_source` 值相符(請參閱下文)。
+- "source".reader".user" -> 使用 `synchdb_add_conninfo()` 建立連接器時,此項目應與 `username` 值相符。
+- "source".reader".password" -> 使用 `synchdb_add_conninfo()` 建立連接器時,此項目應與 `password` 值相符。
+- "source".reader".server" -> 使用 `synchdb_add_conninfo()` 建立連接器時,此項目應包含 `hostname`、`port` 和 `source database` 的值。
+- "source".filter".table":[] -> 此項目用於篩選 Openlog Replicator 擷取的變更事件。 <<<**重要提示**>>>:目前這是過濾來自 Oracle 的變更事件的唯一方法,因為 SynchDB 中的 OLR 實作目前不進行任何過濾。 (透過 `synchdb_add_conninfo()` 建立連接器時,`table` 和 `snapshot table` 的值將被忽略。)
+- "format":{} -> Debezium 或原生 Openlog Replicator 連接器接收的特定有效負載格式。請按指定方式使用這些值。
+- "memory".swap-path" -> 這告訴 OLR 在記憶體不足的情況下將交換檔案寫入何處。
+- "target".[0].."writer"."type": -> 此項目必須指定“network”,因為 Debezium 和原生 Openlog Replicator 連接器都透過網路與 Openlog Replicator 通訊。
+- "target".[0].."writer"."uri": -> 這是 Openlog Replicator 監聽的綁定主機和端口,SynchDB 應該能夠在透過 `synchdb_add_olr_conninfo()` 定義 OLR 參數時,透過 `olr_host` 和 `olrport` 存取它們。
+
+
## **設定 SynchDB 的 Postgres 連接器**
需要配置 PostgreSQL 伺服器,使其用作 SynchDB 的資料庫來源。
diff --git a/doc/docs/zh/tutorial/mysql_cdc_to_postgresql.md b/doc/docs/zh/tutorial/mysql_cdc_to_postgresql.md
index 2929112..efd0121 100644
--- a/doc/docs/zh/tutorial/mysql_cdc_to_postgresql.md
+++ b/doc/docs/zh/tutorial/mysql_cdc_to_postgresql.md
@@ -1,4 +1,4 @@
-# MySQL -> PostgreSQL
+# MySQL 连接器
## **为 SynchDB 准备 MySQL 数据库**
@@ -153,7 +153,165 @@ WHERE name = 'mysqlconn';
## **使用 schemasync 模式預覽來源表和目標表關係**
-在嘗試對當前表和資料(可能非常龐大)進行初始快照之前,可以在實際資料遷移之前「預覽」來源表和目標表之間的所有表和資料類型對應。這樣,您就有機會在實際遷移之前修改資料類型對應或物件名稱。這可以透過特殊的「schemasync」初始快照模式來實現。有關詳細範例,請參閱[对象映射工作流程](../../tutorial/object_mapping_workflow/)。
+在嘗試對當前表和資料(可能非常龐大)進行初始快照之前,可以在實際資料遷移之前「預覽」來源表和目標表之間的所有表和資料類型對應。這樣,您有機會在實際遷移之前修改資料類型對應或物件名稱。這可以透過特殊的「schemasync」初始快照模式來實現。
+
+請注意,您必須將 `synchdb.olr_snapshot_engine` 設定為 'fdw' 才能使用 `schemasync` 模式預覽表。
+
+### **建立連接器並以 `schemasync` 模式啟動它**
+
+`schemasync` 是一種特殊模式,它使連接器連接到遠端資料庫並嘗試僅同步指定表的模式。完成後,連接器將處於「暫停」狀態,使用者可以查看使用預設規則建立的所有資料表和資料類型,並根據需要進行變更。
+
+```sql
+SELECT synchdb_add_conninfo(
+ 'mysqlconn',
+ '127.0.0.1',
+ 3306,
+ 'mysqluser',
+ 'mysqlpwd',
+ 'inventory',
+ 'null',
+ 'null',
+ 'null',
+ 'mysql'
+);
+
+SELECT synchdb_start_engine_bgw('mysqlconn', 'schemasync');
+```
+### **確保連接器處於暫停狀態**
+
+```sql
+SELECT name, connector_type, pid, stage, state FROM synchdb_state_view WHERE name = 'mysqlconn';
+ name | connector_type | pid | stage | state
+-----------+----------------+---------+---------------------+--------
+ mysqlconn | mysql | 1644218 | change data capture | paused
+
+```
+
+### **查看預設映射規則所建立的表**
+
+```sql
+SELECT * FROM synchdb_att_view WHERE name = 'mysqlconn';
+ name | type | attnum | ext_tbname | pg_tbname | ext_attname | pg_attname | ext_atttypename | pg_atttypename | transform
+
+-----------+----------+--------+----------------------------+----------------------------+--------------+--------------+-------------------+-------------------+----------------------
+------
+ mysqlconn | mysql | 1 | inventory.addresses | inventory.addresses | id | id | int | integer |
+ mysqlconn | mysql | 2 | inventory.addresses | inventory.addresses | customer_id | customer_id | int | integer |
+ mysqlconn | mysql | 3 | inventory.addresses | inventory.addresses | street | street | varchar | character varying |
+ mysqlconn | mysql | 4 | inventory.addresses | inventory.addresses | city | city | varchar | character varying |
+ mysqlconn | mysql | 5 | inventory.addresses | inventory.addresses | state | state | varchar | character varying |
+ mysqlconn | mysql | 6 | inventory.addresses | inventory.addresses | zip | zip | varchar | character varying |
+ mysqlconn | mysql | 7 | inventory.addresses | inventory.addresses | type | type | enum | text |
+ mysqlconn | mysql | 1 | inventory.customers | inventory.customers | id | id | int | integer |
+ mysqlconn | mysql | 2 | inventory.customers | inventory.customers | first_name | first_name | varchar | character varying |
+ mysqlconn | mysql | 3 | inventory.customers | inventory.customers | last_name | last_name | varchar | character varying |
+ mysqlconn | mysql | 4 | inventory.customers | inventory.customers | email | email | varchar | character varying |
+ mysqlconn | mysql | 1 | inventory.geom | inventory.geom | id | id | int | integer |
+ mysqlconn | mysql | 2 | inventory.geom | inventory.geom | g | g | geometry | text |
+ mysqlconn | mysql | 3 | inventory.geom | inventory.geom | h | h | geometry | text |
+ mysqlconn | mysql | 1 | inventory.orders | inventory.orders | order_number | order_number | int | integer |
+ mysqlconn | mysql | 2 | inventory.orders | inventory.orders | order_date | order_date | date | date |
+ mysqlconn | mysql | 3 | inventory.orders | inventory.orders | purchaser | purchaser | int | integer |
+ mysqlconn | mysql | 4 | inventory.orders | inventory.orders | quantity | quantity | int | integer |
+ mysqlconn | mysql | 5 | inventory.orders | inventory.orders | product_id | product_id | int | integer |
+ mysqlconn | mysql | 1 | inventory.products | inventory.products | id | id | int | integer |
+ mysqlconn | mysql | 2 | inventory.products | inventory.products | name | name | varchar | character varying |
+ mysqlconn | mysql | 3 | inventory.products | inventory.products | description | description | varchar | character varying |
+ mysqlconn | mysql | 4 | inventory.products | inventory.products | weight | weight | float | real |
+ mysqlconn | mysql | 1 | inventory.products_on_hand | inventory.products_on_hand | product_id | product_id | int | integer |
+ mysqlconn | mysql | 2 | inventory.products_on_hand | inventory.products_on_hand | quantity | quantity | int | integer |
+
+```
+### **定義自訂映射(如有需要)**
+
+```sql
+SELECT synchdb_add_objmap('mysqlconn','table','inventory.products','inventory.myproducts');
+SELECT synchdb_add_objmap('mysqlconn','column','inventory.customers.email','contact');
+SELECT synchdb_add_objmap('mysqlconn','datatype','inventory.orders.quantity','bigint|0');
+SELECT synchdb_add_objmap('mysqlconn','transform','inventory.products.name','''>>>>>'' || ''%d'' || ''<<<<<''');
+```
+
+以上內容意味著:
+
+* 來源表“inventory.products”將會對應到目標表“inventory.myproducts”
+* 來源列“inventory.customers.email”將會對應到目標表“contact”
+* 來源列“inventory.orders.quantity”的資料類型將會對應到“bigint”
+* 來源列「inventory.products.name」的資料將根據表達式進行轉換,其中 %d 為資料佔位符
+
+### **回顧所有已建立的物件映射規則**
+
+```sql
+SELECT * FROM synchdb_objmap WHERE name = 'mysqlconn';
+ name | objtype | enabled | srcobj | dstobj
+-----------+-----------+---------+---------------------------+----------------------------
+ mysqlconn | table | t | inventory.products | inventory.myproducts
+ mysqlconn | column | t | inventory.customers.email | contact
+ mysqlconn | datatype | t | inventory.orders.quantity | bigint|0
+ mysqlconn | transform | t | inventory.products.name | '>>>>>' || '%d' || '<<<<<'
+
+```
+
+### **重新載入物件映射規則**
+
+所有自訂規則定義完畢後,我們需要通知連接器載入這些規則。這將使連接器讀取並應用物件映射規則。如果連接器發現目前 PostgreSQL 值與物件對應值之間存在差異,它將嘗試修正映射。
+
+```sql
+SELECT synchdb_reload_objmap('mysqlconn');
+
+```
+
+### **再次檢查 `synchdb_att_view` 是否有更改**
+
+```sql
+ name | type | attnum | ext_tbname | pg_tbname | ext_attname | pg_attname | ext_atttypename | pg_atttypename | transform
+
+-----------+-------+--------+----------------------------+----------------------------+--------------+--------------+-----------------+-------------------+---------------------------
+-
+ mysqlconn | mysql | 1 | inventory.addresses | inventory.addresses | id | id | int | integer |
+ mysqlconn | mysql | 2 | inventory.addresses | inventory.addresses | customer_id | customer_id | int | integer |
+ mysqlconn | mysql | 3 | inventory.addresses | inventory.addresses | street | street | varchar | character varying |
+ mysqlconn | mysql | 4 | inventory.addresses | inventory.addresses | city | city | varchar | character varying |
+ mysqlconn | mysql | 5 | inventory.addresses | inventory.addresses | state | state | varchar | character varying |
+ mysqlconn | mysql | 6 | inventory.addresses | inventory.addresses | zip | zip | varchar | character varying |
+ mysqlconn | mysql | 7 | inventory.addresses | inventory.addresses | type | type | enum | text |
+ mysqlconn | mysql | 1 | inventory.customers | inventory.customers | id | id | int | integer |
+ mysqlconn | mysql | 2 | inventory.customers | inventory.customers | first_name | first_name | varchar | character varying |
+ mysqlconn | mysql | 3 | inventory.customers | inventory.customers | last_name | last_name | varchar | character varying |
+ mysqlconn | mysql | 4 | inventory.customers | inventory.customers | email | contact | varchar | character varying |
+ mysqlconn | mysql | 1 | inventory.geom | inventory.geom | id | id | int | integer |
+ mysqlconn | mysql | 2 | inventory.geom | inventory.geom | g | g | geometry | text |
+ mysqlconn | mysql | 3 | inventory.geom | inventory.geom | h | h | geometry | text |
+ mysqlconn | mysql | 1 | inventory.orders | inventory.orders | order_number | order_number | int | integer |
+ mysqlconn | mysql | 2 | inventory.orders | inventory.orders | order_date | order_date | date | date |
+ mysqlconn | mysql | 3 | inventory.orders | inventory.orders | purchaser | purchaser | int | integer |
+ mysqlconn | mysql | 4 | inventory.orders | inventory.orders | quantity | quantity | int | bigint |
+ mysqlconn | mysql | 5 | inventory.orders | inventory.orders | product_id | product_id | int | integer |
+ mysqlconn | mysql | 1 | inventory.products | inventory.myproducts | id | id | int | integer |
+ mysqlconn | mysql | 2 | inventory.products | inventory.myproducts | name | name | varchar | character varying | '>>>>>' || '%d' || '<<<<<'
+ mysqlconn | mysql | 3 | inventory.products | inventory.myproducts | description | description | varchar | character varying |
+ mysqlconn | mysql | 4 | inventory.products | inventory.myproducts | weight | weight | float | real |
+ mysqlconn | mysql | 1 | inventory.products_on_hand | inventory.products_on_hand | product_id | product_id | int | integer |
+ mysqlconn | mysql | 2 | inventory.products_on_hand | inventory.products_on_hand | quantity | quantity | int | integer |
+
+
+```
+
+### **恢復連接器或重新建立整個快照**
+
+確認物件映射正確後,我們可以恢復連接器。請注意,復原操作只會傳輸新的表更改,不會複製表中的現有資料。
+
+```sql
+SELECT synchdb_resume_engine('mysqlconn');
+
+```
+
+要擷取表中的現有數據,我們也可以使用新的物件映射規則重新建立整個快照。
+
+```sql
+SELECT synchdb_stop_engine_bgw('mysqlconn');
+SELECT synchdb_start_engine_bgw('mysqlconn', 'always');
+
+```
## **選擇性表同步**
@@ -241,4 +399,84 @@ postgres=# \dt inventory.*
inventory | orders | table | ubuntu
inventory | products | table | ubuntu
+```
+
+## 安全连接
+
+### **配置安全连接**
+
+为了确保与远程数据库的连接安全,我们需要为 `synchdb_add_conninfo` 创建的连接器配置额外的 SSL 相关参数。SSL 证书和私钥必须打包为 Java 密钥库文件,并附带密码。这些信息随后会通过 synchdb_add_extra_conninfo() 传递给 SynchDB。
+
+### **synchdb_add_extra_conninfo**
+
+**用途**:为 `synchdb_add_conninfo` 创建的现有连接器配置额外的连接器参数
+
+| 参数 | 描述 | 必需 | 示例 | 备注 |
+|:-:|:-|:-:|:-|:-|
+| `name` | 此连接器的唯一标识符 | ✓ | `'mysqlconn'` | 必须在所有连接器中唯一 |
+| `ssl_mode` | SSL 模式 | ☐ | `'verify_ca'` |可以是以下之一:
- “disabled”- 不使用 SSL。
- “preferred”- 如果服务器支持,则使用 SSL。
- “required”- 必须使用 SSL 建立连接。
- “verify_ca”- 连接器与服务器建立 TLS,并将根据配置的信任库验证服务器的 TLS 证书。
- “verify_identity”- 与 verify_ca 行为相同,但它还会检查服务器证书的通用名称以匹配系统的主机名。|
+| `ssl_keystore` | 密钥库路径 | ☐ | `/path/to/keystore` | 密钥库文件的路径 |
+| `ssl_keystore_pass` | 密钥库密码 | ☐ | `'mykeystorepass'` | 访问密钥库文件的密码 |
+| `ssl_truststore` | 信任库路径 | ☐ | `'/path/to/truststore'` | 信任库文件路径 |
+| `ssl_truststore_pass` | 信任库密码 | ☐ | `'mytruststorepass'` | 访问信任库文件的密码 |
+
+```sql
+SELECT synchdb_add_extra_conninfo('mysqlconn', 'verify_ca', '/path/to/keystore', 'mykeystorepass', '/path/to/truststore', 'mytruststorepass');
+```
+
+### **synchdb_del_extra_conninfo**
+
+**用途**:删除由 `synchdb_add_extra_conninfo` 创建的额外连接器参数
+```sql
+SELECT synchdb_del_extra_conninfo('mysqlconn');
+```
+
+## 自定义起始偏移量值
+
+起始偏移量值代表开始复制的点,类似于 PostgreSQL 的恢复 LSN。当 Debezium 运行引擎启动时,它将从这个偏移量值开始复制。将此偏移量值设置为较早的值将导致 Debezium 运行引擎从较早的记录开始复制,可能会复制重复的数据记录。在设置 Debezium 的起始偏移量值时,我们应该格外谨慎。
+
+### **记录可设置的偏移量值**
+
+在操作过程中,Debezium 运行引擎将生成新的偏移量并将其刷新到磁盘。最后刷新的偏移量可以通过 `synchdb_state_view()` 实用命令检索:
+
+```
+postgres=# select name, last_dbz_offset from synchdb_state_view;
+ name | last_dbz_offset
+---------------+------------------------------------------------------------------------------------------------------
+ mysqlconn | {"ts_sec":1741301103,"file":"mysql-bin.000009","pos":574318212,"row":1,"server_id":223344,"event":2}
+
+```
+
+我们应该定期保存这些值,这样如果遇到问题,我们就知道过去可以设置的偏移量位置,以恢复复制操作。
+
+### **暂停连接器**
+
+在设置新的偏移量值之前,连接器必须处于 `paused`(暂停)状态。
+
+使用 `synchdb_pause_engine()` SQL 函数暂停正在运行的连接器。这将停止 Debezium 运行引擎从异构数据库复制。当暂停时,可以使用 `synchdb_set_offset()` SQL 例程更改 Debezium 连接器的偏移量值,以从过去的特定点开始复制。它以 `conninfo_name` 作为参数,可以从 `synchdb_get_state()` 视图的输出中找到。
+
+例如:
+
+```sql
+SELECT synchdb_pause_engine('mysqlconn');
+```
+
+### **设置新的偏移量**
+
+使用 `synchdb_set_offset()` SQL 函数更改连接器工作进程的起始偏移量。只有当连接器处于 `paused` 状态时才能执行此操作。该函数接受两个参数,`conninfo_name` 和 `有效的偏移量字符串`,这两个参数都可以从 `synchdb_get_state()` 视图的输出中找到。
+
+例如:
+
+```sql
+SELECT synchdb_set_offset('mysqlconn', '{"ts_sec":1741301103,"file":"mysql-bin.000009","pos":574318212,"row":1,"server_id":223344,"event":2}');
+```
+
+### **恢复连接器**
+
+使用 `synchdb_resume_engine()` SQL 函数从暂停状态恢复 Debezium 操作。此函数以 `连接器名称` 作为其唯一参数,可以从 `synchdb_get_state()` 视图的输出中找到。恢复的 Debezium 运行引擎将从新设置的偏移量值开始复制。
+
+例如:
+
+```sql
+SELECT synchdb_resume_engine('mysqlconn');
```
\ No newline at end of file
diff --git a/doc/docs/zh/tutorial/native_olr_cdc_to_postgresql.md b/doc/docs/zh/tutorial/native_olr_cdc_to_postgresql.md
new file mode 100644
index 0000000..45751b6
--- /dev/null
+++ b/doc/docs/zh/tutorial/native_olr_cdc_to_postgresql.md
@@ -0,0 +1,355 @@
+#原生 Openlog Replicator 連接器
+
+## **準備用於 SynchDB 的 MySQL 資料庫**
+
+在使用 SynchDB 透過原生 Openlog Replicator (OLR) 連接器進行複製之前,OLR 和 Oracle 資料庫本身都需要按照[此處](../../getting-started/remote_database_setups/)中概述的步驟進行設定。
+
+## **原生的 Openlog Replicator 连接器的行为说明**
+
+* 目前为 BETA 版本。
+* SynchDB 管理与 Openlog Replicator 的连接,并在不使用 Debezium 的情况下流式传输变更。
+* 需要 OLR 配置,否则连接器启动时会出错。
+* 依赖 Debezium 的 Oracle 连接器完成初始快照,并在完成后关闭,后续的 CDC 由 SynchDB 内部针对 Openlog Replicator 原生完成。
+* 依赖 IvorySQL 的 Oracle 解析器来处理 DDL 事件。在使用原生 openlog replicator 连接器之前,必须先编译并安装它。
+* 访问[此处](https://github.com/bersler/OpenLogReplicator) 了解有关 Openlog Replicator 的更多信息。
+
+## **建立原生 Openlog Replicator 連接器**
+
+建立一個連接器,該連接器透過原生 Openlog Replicator 連接器指向 `FREE` 資料庫和 `DBZUSER` 模式下的所有表。
+
+```sql
+SELECT synchdb_add_conninfo(
+ 'olrconn', '127.0.0.1', 1521, 'DBZUSER',
+ 'dbz', 'FREE', 'DBZUSER',
+ 'null', 'null', 'olr');
+
+SELECT synchdb_add_olr_conninfo(
+ 'olrconn',
+ '127.0.0.1',
+ 7070,
+ 'ORACLE');
+
+```
+## **初始快照**
+
+SynchDB 中的「初始快照」(或表快照)是指複製所有指定表的表結構以及初始資料。這類似於 PostgreSQL 邏輯複製中的「表同步」。當使用預設的 `initial` 模式啟動連接器時,它會在進入變更資料擷取 (CDC) 階段之前自動執行初始快照。可以使用 `no_data` 模式部分省略此步驟。有關所有快照選項,請參閱[此處](../../user-guide/start_stop_connector/)。
+
+初始快照完成後,連接器在後續重新啟動時不會再次執行初始快照,而是直接從上次未完成的偏移量處恢復 CDC。此行為由 Debezium 引擎管理的元資料檔案控制。有關元資料檔案的更多信息,請參閱[此處](../../architecture/metadata_files/)。
+
+## **不同的連接器啟動模式**
+
+### **初始快照 + CDC**
+
+使用 `initial` 模式啟動連接器將對所有指定表(本例中為所有表)執行初始快照。完成後,變更資料擷取 (CDC) 流程將開始收集新的變更資料。
+
+```sql
+SELECT synchdb_start_engine_bgw('olrconn', 'initial');
+
+or
+
+SELECT synchdb_start_engine_bgw('olrconn');
+```
+
+如果此連接器已處理 CDC 中的至少一個變更事件,則其階段應為「初始快照」或「變更資料擷取」。
+
+```sql
+postgres=# select * from synchdb_state_view;
+ name | connector_type | pid | stage | state | err | last_dbz_offset
+---------+----------------+---------+------------------+---------+----------+-----------------
+ olrconn | olr | 1702522 | initial snapshot | polling | no error | no offset
+
+
+
+```
+
+將建立一個名為「free」的新模式,連接器傳輸的所有表都將在該模式下進行複製。
+
+```sql
+postgres=# \dt free.*
+ List of tables
+ Schema | Name | Type | Owner
+--------+-----------+-------+--------
+ free | customers | table | ubuntu
+ free | orders | table | ubuntu
+
+```
+
+初始快照完成後,並且至少收到並處理了一個後續更改,連接器階段應從“初始快照”更改為“變更資料擷取”。
+
+```sql
+postgres=# select * from synchdb_state_view;
+ name | connector_type | pid | stage | state | err | last_dbz_offset
+---------+----------------+---------+---------------------+---------+----------+---------------------------------------------
+ olrconn | olr | 1702522 | change data capture | polling | no error | {"scn":5031082, "c_scn":5031085, "c_idx":3}
+
+```
+
+這意味著連接器現在正在檢測指定表的新變更。以「初始」模式重新啟動連接器將從上次成功複製點開始繼續複製,不會重新執行初始快照。
+
+### **僅初始快照,不執行 CDC**
+
+使用 `initial_only` 模式啟動連接器,將僅對所有指定資料表(本例中為所有資料表)執行初始快照,之後不會執行 CDC。
+
+```sql
+SELECT synchdb_start_engine_bgw('olrconn', 'initial_only');
+
+```
+
+### **僅捕獲表架構 + CDC**
+
+使用 `no_data` 模式啟動連接器將僅執行架構捕獲,並在 PostgreSQL 中建立相應的表,但不會複製現有表資料(跳過初始快照)。架構擷取完成後,連接器將進入 CDC 模式,並開始擷取表的後續變更。
+
+```sql
+SELECT synchdb_start_engine_bgw('olrconn', 'no_data');
+
+```
+
+以 `no_data` 模式重新啟動連接器不會再次重建架構,而是從上次成功捕獲的位置繼續 CDC 擷取。
+
+### **僅 CDC**
+
+使用 `never` 模式啟動連接器將完全跳過架構擷取和初始快照,直接進入 CDC 模式擷取後續變更。請注意,連接器要求所有擷取表在以 `never` 模式啟動之前已在 PostgreSQL 中建立。如果表不存在,連接器在嘗試將 CDC 變更套用到不存在的表時會遇到錯誤。
+
+```sql
+SELECT synchdb_start_engine_bgw('olrconn', 'never');
+
+```
+
+以 `never` 模式重新啟動連接器將從上次成功點恢復 CDC。
+
+### **始終執行初始快照 + CDC**
+
+使用 `always` 模式啟動連接器將始終擷取擷取表的模式,始終重新執行初始快照,然後再進行 CDC。這類似於重置按鈕,因為使用此模式將重建所有內容。請謹慎使用此模式,尤其是在捕獲大量表時,這可能需要很長時間才能完成。重建完成後,CDC 將照常恢復。
+
+```sql
+SELECT synchdb_start_engine_bgw('olrconn', 'always');
+
+```
+
+初始快照完成後,CDC 將開始。在 `always` 模式下重新啟動連接器將重複上述過程。
+
+## **MySQL 連接器的可用快照模式**
+
+* initial(預設)
+* initial_only
+* no_data
+* never
+* always
+* schemasync
+
+## **使用 schemasync 模式預覽來源表和目標表關係**
+
+在嘗試對當前表和資料(可能非常龐大)進行初始快照之前,可以在當前資料遷移之前「預覽」來源表和目標表之間的所有表和資料類型對應。這樣,您有機會在實際遷移之前修改資料類型對應或物件名稱。這可以透過特殊的「schemasync」初始快照模式來實現。
+
+請注意,您必須將 `synchdb.olr_snapshot_engine` 設定為 'fdw' 才能使用 `schemasync` 模式預覽表。
+
+### **建立連接器並以 `schemasync` 模式啟動它**
+
+`schemasync` 是一種特殊模式,它使連接器連接到遠端資料庫,並嘗試僅同步指定表的模式。完成後,連接器將處於「暫停」狀態,使用者可以查看使用預設規則建立的所有資料表和資料類型,並根據需要進行變更。
+
+```sql
+SELECT synchdb_add_conninfo(
+ 'oracleconn',
+ '127.0.0.1',
+ 1521,
+ 'DBZUSER',
+ 'dbz',
+ 'FREE',
+ 'DBZUSER',
+ 'null',
+ 'null',
+ 'oracle'
+);
+
+SELECT synchdb_add_olr_conninfo(
+ 'olrconn',
+ '127.0.0.1',
+ 7070,
+ 'ORACLE');
+
+SELECT synchdb_start_engine_bgw('olrconn', 'schemasync');
+```
+
+### **確保連接器處於暫停狀態**
+
+```sql
+SELECT name, connector_type, pid, stage, state FROM synchdb_state_view WHERE name = 'olrconn';
+ name | connector_type | pid | stage | state
+---------+----------------+---------+---------------------+--------
+ olrconn | olr | 1703430 | change data capture | paused
+
+```
+
+### **查看預設映射規則所建立的表**
+
+```sql
+SELECT * FROM synchdb_att_view WHERE name = 'olrconn';
+ name | type | attnum | ext_tbname | pg_tbname | ext_attname | pg_attname | ext_atttypename | pg_atttypename | transform
+---------+--------+--------+------------------------+----------------+--------------+--------------+-----------------+-----------------------------+-----------
+ olrconn | oracle | 1 | FREE.DBZUSER.CUSTOMERS | free.customers | ID | id | number | numeric |
+ olrconn | oracle | 2 | FREE.DBZUSER.CUSTOMERS | free.customers | NAME | name | varchar2 | character varying |
+ olrconn | oracle | 1 | FREE.DBZUSER.ORDERS | free.orders | ORDER_NUMBER | order_number | number | numeric |
+ olrconn | oracle | 2 | FREE.DBZUSER.ORDERS | free.orders | ORDER_DATE | order_date | date | timestamp without time zone |
+ olrconn | oracle | 3 | FREE.DBZUSER.ORDERS | free.orders | PURCHASER | purchaser | number | numeric |
+ olrconn | oracle | 4 | FREE.DBZUSER.ORDERS | free.orders | QUANTITY | quantity | number | numeric |
+ olrconn | oracle | 5 | FREE.DBZUSER.ORDERS | free.orders | PRODUCT_ID | product_id | number | numeric |
+
+```
+
+### **定義自訂映射規則(如有需要)**
+
+使用者可以使用 `synchdb_add_objmap` 函數建立自訂映射規則。此函數可用於對應表名、列名、資料類型,並定義資料轉換表達式規則。
+
+```sql
+SELECT synchdb_add_objmap('olrconn','table','FREE.DBZUSER.ORDERS','free.myorders');
+SELECT synchdb_add_objmap('olrconn','column','FREE.DBZUSER.ORDERS.PURCHASER','who');
+SELECT synchdb_add_objmap('olrconn','datatype','FREE.DBZUSER.ORDERS.QUANTITY','bigint|0');
+SELECT synchdb_add_objmap('olrconn','transform','FREE.DBZUSER.CUSTOMERS.NAME','''>>>>>'' || ''%d'' || ''<<<<<''');
+```
+
+The above means:
+
+* source table 'FREE.DBZUSER.ORDERS' will be mapped to 'free.myorders' in destination
+* source column 'FREE.DBZUSER.ORDERS.PURCHASE' will be mapped to 'who' in destination
+* source data type for column 'FREE.DBZUSER.ORDERS.QUANTITY' will be mapped to 'bigint'
+* source column data 'FREE.DBZUSER.CUSTOMERS.NAME' will be transformed accoring to the expression where %d is the data placeholder
+
+### **回顧所有已建立的物件映射規則**
+
+```sql
+SELECT * FROM synchdb_objmap WHERE name = 'olrconn';
+ name | objtype | enabled | srcobj | dstobj
+---------+-----------+---------+-------------------------------+----------------------------
+ olrconn | table | t | FREE.DBZUSER.ORDERS | free.myorders
+ olrconn | column | t | FREE.DBZUSER.ORDERS.PURCHASER | who
+ olrconn | datatype | t | FREE.DBZUSER.ORDERS.QUANTITY | bigint|0
+ olrconn | transform | t | FREE.DBZUSER.CUSTOMERS.NAME | '>>>>>' || '%d' || '<<<<<'
+
+```
+
+### **重新載入物件映射規則**
+
+定義完所有自訂規則後,我們需要通知連接器載入這些規則。這將使連接器讀取並應用物件映射規則。如果連接器發現目前 PostgreSQL 值與物件對應值之間存在差異,它將嘗試修正映射。
+
+```sql
+SELECT synchdb_reload_objmap('olrconn');
+
+```
+
+### **再次檢查 `synchdb_att_view` 是否有更改**
+
+```sql
+SELECT * from synchdb_att_view WHERE name = 'olrconn';
+ name | type | attnum | ext_tbname | pg_tbname | ext_attname | pg_attname | ext_atttypename | pg_atttypename | transform
+---------+------+--------+------------------------+----------------+--------------+--------------+-----------------+-----------------------------+----------------------------
+ olrconn | olr | 1 | FREE.DBZUSER.CUSTOMERS | free.customers | ID | id | number | numeric |
+ olrconn | olr | 2 | FREE.DBZUSER.CUSTOMERS | free.customers | NAME | name | varchar2 | character varying | '>>>>>' || '%d' || '<<<<<'
+ olrconn | olr | 1 | FREE.DBZUSER.ORDERS | free.myorders | ORDER_NUMBER | order_number | number | numeric |
+ olrconn | olr | 2 | FREE.DBZUSER.ORDERS | free.myorders | ORDER_DATE | order_date | date | timestamp without time zone |
+ olrconn | olr | 3 | FREE.DBZUSER.ORDERS | free.myorders | PURCHASER | who | number | numeric |
+ olrconn | olr | 4 | FREE.DBZUSER.ORDERS | free.myorders | QUANTITY | quantity | number | bigint |
+ olrconn | olr | 5 | FREE.DBZUSER.ORDERS | free.myorders | PRODUCT_ID | product_id | number | numeric |
+
+```
+
+### **恢復連接器或重新執行整個快照**
+
+確認物件映射正確後,即可對連接器進行匯總。請注意,復原操作只會傳輸新的表更改,不會複製表中的現有資料。
+
+```sql
+SELECT synchdb_resume_engine('olrconn');
+```
+
+為了捕獲表中的現有數據,我們還可以使用新的物件映射規則重新建立整個快照。
+
+```sql
+SELECT synchdb_stop_engine_bgw('olrconn');
+SELECT synchdb_start_engine_bgw('olrconn', 'always');
+```
+
+## **選擇性表同步**
+
+### **選擇所需表並首次啟動同步**
+
+表格選擇在連接器建立階段透過 `synchdb_add_conninfo()` 函數完成,該函數用於指定要從中複製的表列表(以完全限定名稱 (FQN) 表示,並以逗號分隔)。
+
+例如,以下命令建立一個連接器,該連接器僅從遠端 Oracle 資料庫複製 `FREE.ORDERS` 表中的變更。
+```sql
+SELECT synchdb_add_conninfo(
+ 'olrconn',
+ '127.0.0.1',
+ 1521,
+ 'DBZUSER',
+ 'dbz',
+ 'FREE',
+ 'DBZUSER',
+ 'DBZUSER.ORDERS',
+ 'null',
+ 'oracle'
+);
+```
+
+首次啟動此連接器時,將觸發執行初始快照,並複製選定的表的架構和資料。
+
+```sql
+SELECT synchdb_start_engine_bgw('olrconn');
+```
+
+### **驗證連接器狀態和表格**
+
+檢查連接器狀態和新表格:
+```sql
+postgres=# Select name, state, err from synchdb_state_view;
+ name | state | err
+---------+---------+----------
+ olrconn | polling | no error
+
+postgres=# \dt free.*
+ List of tables
+ Schema | Name | Type | Owner
+--------+--------+-------+--------
+ free | orders | table | ubuntu
+
+```
+
+預設情況下,來源資料庫名稱會對應到目標資料庫的模式,並且字母大小寫策略為小寫,因此 `FREE.ORDERS` 在 PostgreSQL 中會變成 `free.orders`。表完成初始快照後,連接器將啟動 CDC 以串流傳輸這些表的後續變更。
+
+### **運行時加入更多要複製的表**
+
+上一節中的 `olrconn` 已完成初始快照並取得了所選表格的表格模式。如果我們想要新增更多要複製的表,則需要通知 Debezium 引擎更新後的表格部分,並再次執行初始快照。具體操作如下:
+
+1. 更新 `synchdb_conninfo` 表以包含其他表。
+
+2. 在本例中,我們將 `DBZUSER.CUSTOMERS` 表加入同步清單:
+
+```sql
+UPDATE synchdb_conninfo
+SET data = jsonb_set(data, '{table}', '"DBZUSER.ORDERS,DBZUSER.CUSTOMERS"')
+WHERE name = 'olrconn';
+```
+
+3. 將快照模式設為“始終”,然後重新啟動連接器,以執行另一次初始快照:
+
+```sql
+DROP table free.orders;
+SELECT synchdb_restart_connector('olrconn', 'always');
+```
+
+這迫使 Debezium 在進行 CDC 串流之前,重新建立所有表格的快照,包括現有的 `free.orders` 表和新的 `free.customers` 表。這意味著,要新增表,必須刪除現有表(以防止重複表和主鍵錯誤),並重新建立整個初始快照。這相當冗餘,Debezium 建議使用增量快照來新增資料表,而無需重新建立快照。一旦我們將增量快照支援新增至 SynchDB,我們將更新此流程。
+
+### **驗證更新後的表格**
+
+現在,我們可以再次檢查我們的表:
+```sql
+postgres=# \dt free.*
+ List of tables
+ Schema | Name | Type | Owner
+-------------+--------+-------+--------
+ free | orders | table | ubuntu
+ customers | orders | table | ubuntu
+
+```
+
+### **篩選 Openlog Replicator 表(重要)**
+
+對於初始快照(透過 Debezium 或 FDW),我們可以選擇要複製的表。但是,一旦連接器通過 Openlog Replicator 進入 CDC 階段,所選的表格篩選器不會自動應用於 Openlog Replicator。使用者需要配置 Openlog Replicator 服務,使其僅輸出所選表的變更事件。如果 SynchDB 和 Openlog Replicator 的表格篩選器不一致,SynchDB 可能會收到它尚未建立對應表的變更事件,從而導致錯誤。 因此,將 SynchDB 和 Openlog Replicator 配置為使用相同的表格過濾器是一種很好的做法。
\ No newline at end of file
diff --git a/doc/docs/zh/tutorial/object_mapping_workflow.md b/doc/docs/zh/tutorial/object_mapping_workflow.md
deleted file mode 100644
index b899a90..0000000
--- a/doc/docs/zh/tutorial/object_mapping_workflow.md
+++ /dev/null
@@ -1,142 +0,0 @@
-# 对象映射工作流程
-
-SynchDB 具有默认名称和数据类型映射规则来处理传入的更改事件。在大多数情况下,默认规则都可以正常工作。但是,如果您有特定的转换要求,或者默认规则不适合您,则可以将自己的对象映射规则配置到特定连接器。请按照以下工作流程查看和调整任何特定的对象映射规则。
-
-## **创建连接器并以 `schemasync` 模式启动它**
-
-`schemasync` 是一种特殊模式,它使连接器连接到远程数据库并尝试仅同步指定表的架构。完成此操作后,连接器将处于 `暂停` 状态,用户可以查看使用默认规则创建的所有表和数据类型,并在需要时进行更改。
-
-```sql
-SELECT synchdb_add_conninfo(
- 'mysqlconn',
- '127.0.0.1',
- 3306,
- 'mysqluser',
- 'mysqlpwd',
- 'inventory',
- 'null',
- 'null',
- 'mysql');
-
-SELECT synchdb_start_engine_bgw('mysqlconn', 'schemasync');
-```
-
-## **确保连接器处于暂停状态**
-
-```sql
-SELECT name, connector_type, pid, stage, state FROM synchdb_state_view;
- name | connector_type | pid | stage | state
----------------+----------------+--------+-------------+---------
- mysqlconn | mysql | 579845 | schema sync | polling
-
-```
-
-## **查看默认创建的表的映射规则**
-
-```sql
-postgres=# select * from synchdb_att_view;
- name | type | attnum | ext_tbname | pg_tbname | ext_attname | pg_attname | ext_atttypename | pg_atttypename | transform
------------+-------+--------+----------------------------+----------------------------+-------------+-------------+-----------------+----------------+-----------
- mysqlconn | mysql | 1 | inventory.addresses | inventory.addresses | id | id | INT | int4 |
- mysqlconn | mysql | 2 | inventory.addresses | inventory.addresses | customer_id | customer_id | INT | int4 |
- mysqlconn | mysql | 3 | inventory.addresses | inventory.addresses | street | street | VARCHAR | varchar |
- mysqlconn | mysql | 4 | inventory.addresses | inventory.addresses | city | city | VARCHAR | varchar |
- mysqlconn | mysql | 5 | inventory.addresses | inventory.addresses | state | state | VARCHAR | varchar |
- mysqlconn | mysql | 6 | inventory.addresses | inventory.addresses | zip | zip | VARCHAR | varchar |
- mysqlconn | mysql | 7 | inventory.addresses | inventory.addresses | type | type | ENUM | text |
- mysqlconn | mysql | 1 | inventory.customers | inventory.customers | id | id | INT | int4 |
- mysqlconn | mysql | 2 | inventory.customers | inventory.customers | first_name | first_name | VARCHAR | varchar |
- mysqlconn | mysql | 3 | inventory.customers | inventory.customers | last_name | last_name | VARCHAR | varchar |
- mysqlconn | mysql | 4 | inventory.customers | inventory.customers | email | email | VARCHAR | varchar |
- mysqlconn | mysql | 1 | inventory.geom | inventory.geom | id | id | INT | int4 |
- mysqlconn | mysql | 2 | inventory.geom | inventory.geom | g | g | GEOMETRY | text |
- mysqlconn | mysql | 3 | inventory.geom | inventory.geom | h | h | GEOMETRY | text |
- mysqlconn | mysql | 1 | inventory.products | inventory.products | id | id | INT | int4 |
- mysqlconn | mysql | 2 | inventory.products | inventory.products | name | name | VARCHAR | varchar |
- mysqlconn | mysql | 3 | inventory.products | inventory.products | description | description | VARCHAR | varchar |
- mysqlconn | mysql | 4 | inventory.products | inventory.products | weight | weight | FLOAT | float4 |
- mysqlconn | mysql | 1 | inventory.products_on_hand | inventory.products_on_hand | product_id | product_id | INT | int4 |
- mysqlconn | mysql | 2 | inventory.products_on_hand | inventory.products_on_hand | quantity | quantity | INT | int4 |
-(20 rows)
-
-```
-
-## **定义自定义映射规则**
-
-用户可以使用`synchdb_add_objmap`函数创建自定义映射规则。它可用于映射表名、列名、数据类型并定义数据转换表达式规则
-
-```sql
-SELECT synchdb_add_objmap('mysqlconn','table','inventory.products','stuff');
-SELECT synchdb_add_objmap('mysqlconn','table','inventory.customers','schema1.people');
-SELECT synchdb_add_objmap('mysqlconn','column','inventory.customers.last_name','family_name');
-SELECT synchdb_add_objmap('mysqlconn','column','inventory.customers.email','contact');
-SELECT synchdb_add_objmap('mysqlconn','datatype','inventory.geom.g','geometry|0');
-SELECT synchdb_add_objmap('mysqlconn','datatype','inventory.orders.quantity','bigint|0');
-SELECT synchdb_add_objmap('mysqlconn','transform','inventory.products.name','''>>>>>'' || ''%d'' || ''<<<<<''');
-```
-
-## **审查迄今为止创建的所有对象映射规则**
-
-```sql
-postgres=# select * from synchdb_objmap;
- name | objtype | enabled | srcobj | dstobj
------------+-----------+---------+-------------------------------+----------------------------
- mysqlconn | table | t | inventory.products | stuff
- mysqlconn | column | t | inventory.customers.last_name | family_name
- mysqlconn | column | t | inventory.customers.email | contact
- mysqlconn | table | t | inventory.customers | schema1.people
- mysqlconn | transform | t | inventory.products.name | '>>>>>' || '%d' || '<<<<<'
- mysqlconn | datatype | t | inventory.geom.g | geometry|0
- mysqlconn | datatype | t | inventory.orders.quantity | bigint|0
-(7 rows)
-
-```
-
-## **重新加载对象映射规则**
-
-一旦定义了所有自定义规则,我们就需要向连接器发出信号来加载它们。这将导致连接器读取并应用对象映射规则。如果它发现当前 PostgreSQL 值与对象映射值之间存在差异,它将尝试更正映射。
-
-```sql
-SELECT synchdb_reload_objmap('mysqlconn');
-
-```
-
-## **再次检查 `synchdb_att_view` 是否有变化**
-
-```sql
-SELECT * from synchdb_att_view;
- name | type | attnum | ext_tbname | pg_tbname | ext_attname | pg_attname | ext_atttypename | pg_atttypename | transform
------------+-------+--------+----------------------------+----------------------------+-------------+-------------+-----------------+----------------+----------------------------
- mysqlconn | mysql | 1 | inventory.addresses | inventory.addresses | id | id | INT | int4 |
- mysqlconn | mysql | 2 | inventory.addresses | inventory.addresses | customer_id | customer_id | INT | int4 |
- mysqlconn | mysql | 3 | inventory.addresses | inventory.addresses | street | street | VARCHAR | varchar |
- mysqlconn | mysql | 4 | inventory.addresses | inventory.addresses | city | city | VARCHAR | varchar |
- mysqlconn | mysql | 5 | inventory.addresses | inventory.addresses | state | state | VARCHAR | varchar |
- mysqlconn | mysql | 6 | inventory.addresses | inventory.addresses | zip | zip | VARCHAR | varchar |
- mysqlconn | mysql | 7 | inventory.addresses | inventory.addresses | type | type | ENUM | text |
- mysqlconn | mysql | 1 | inventory.customers | schema1.people | id | id | INT | int4 |
- mysqlconn | mysql | 2 | inventory.customers | schema1.people | first_name | first_name | VARCHAR | varchar |
- mysqlconn | mysql | 3 | inventory.customers | schema1.people | last_name | family_name | VARCHAR | varchar |
- mysqlconn | mysql | 4 | inventory.customers | schema1.people | email | contact | VARCHAR | varchar |
- mysqlconn | mysql | 1 | inventory.geom | inventory.geom | id | id | INT | int4 |
- mysqlconn | mysql | 2 | inventory.geom | inventory.geom | g | g | GEOMETRY | geometry |
- mysqlconn | mysql | 3 | inventory.geom | inventory.geom | h | h | GEOMETRY | text |
- mysqlconn | mysql | 1 | inventory.products | public.stuff | id | id | INT | int4 |
- mysqlconn | mysql | 2 | inventory.products | public.stuff | name | name | VARCHAR | varchar | '>>>>>' || '%d' || '<<<<<'
- mysqlconn | mysql | 3 | inventory.products | public.stuff | description | description | VARCHAR | varchar |
- mysqlconn | mysql | 4 | inventory.products | public.stuff | weight | weight | FLOAT | float4 |
- mysqlconn | mysql | 1 | inventory.products_on_hand | inventory.products_on_hand | product_id | product_id | INT | int4 |
- mysqlconn | mysql | 2 | inventory.products_on_hand | inventory.products_on_hand | quantity | quantity | INT | int8 |
-```
-
-## **恢复连接器或重做整个快照**
-
-一旦确认对象映射正确,我们就可以恢复连接器。请注意,恢复只会继续流式传输新的表更改。不会复制表的现有数据。
-```sql
-SELECT synchdb_resume_engine('mysqlconn');
-```
-
-要捕获表的现有数据,我们还可以使用新的对象映射规则重做整个快照:
-```sql
-SELECT synchdb_restart_connector('mysqlconn', 'always');
-```
\ No newline at end of file
diff --git a/doc/docs/zh/tutorial/oracle_cdc_to_postgresql.md b/doc/docs/zh/tutorial/oracle_cdc_to_postgresql.md
index 74d493d..e702ae7 100644
--- a/doc/docs/zh/tutorial/oracle_cdc_to_postgresql.md
+++ b/doc/docs/zh/tutorial/oracle_cdc_to_postgresql.md
@@ -1,4 +1,4 @@
-# Oracle -> PostgreSQL
+# Oracle 连接器
## **为 SynchDB 准备 Oracle 数据库**
@@ -122,7 +122,125 @@ SELECT synchdb_start_engine_bgw('oracleconn', 'always');
## **使用 schemasync 模式預覽來源表和目標表關係**
-在嘗試對當前表和資料(可能非常龐大)進行初始快照之前,可以在實際資料遷移之前「預覽」來源表和目標表之間的所有表和資料類型對應。這樣,您就有機會在實際遷移之前修改資料類型對應或物件名稱。這可以透過特殊的「schemasync」初始快照模式來實現。有關詳細範例,請參閱[对象映射工作流程](../../tutorial/object_mapping_workflow/)。
+在嘗試對當前表和資料(可能非常龐大)進行初始快照之前,可以在實際資料遷移之前「預覽」來源表和目標表之間的所有表和資料類型對應。這樣,您有機會在實際遷移之前修改資料類型對應或物件名稱。這可以透過特殊的「schemasync」初始快照模式來實現。
+
+### **建立連接器並以 `schemasync` 模式啟動它**
+
+`schemasync` 是一種特殊模式,它使連接器連接到遠端資料庫並嘗試僅同步指定表的模式。完成後,連接器將處於「暫停」狀態,使用者可以查看使用預設規則建立的所有資料表和資料類型,並根據需要進行變更。
+
+```sql
+SELECT synchdb_add_conninfo(
+ 'oracleconn',
+ '127.0.0.1',
+ 1521,
+ 'DBZUSER',
+ 'dbz',
+ 'FREE',
+ 'DBZUSER',
+ 'null',
+ 'null',
+ 'oracle'
+);
+
+SELECT synchdb_start_engine_bgw('oracleconn', 'schemasync');
+```
+### **確保連接器處於暫停狀態**
+
+```sql
+SELECT name, connector_type, pid, stage, state FROM synchdb_state_view WHERE name = 'oracleconn';
+ name | connector_type | pid | stage | state
+------------+----------------+---------+---------------------+--------
+ oracleconn | oracle | 1648935 | change data capture | paused
+
+
+```
+### **查看預設映射規則所建立的表**
+
+```sql
+SELECT * FROM synchdb_att_view WHERE name = 'oracleconn';
+ name | type | attnum | ext_tbname | pg_tbname | ext_attname | pg_attname | ext_atttypename | pg_atttypename | transform
+------------+--------+--------+------------------------+----------------+--------------+--------------+-----------------+-----------------------------+-----------
+ oracleconn | oracle | 1 | FREE.DBZUSER.CUSTOMERS | free.customers | ID | id | number | numeric |
+ oracleconn | oracle | 2 | FREE.DBZUSER.CUSTOMERS | free.customers | NAME | name | varchar2 | character varying |
+ oracleconn | oracle | 1 | FREE.DBZUSER.ORDERS | free.orders | ORDER_NUMBER | order_number | number | numeric |
+ oracleconn | oracle | 2 | FREE.DBZUSER.ORDERS | free.orders | ORDER_DATE | order_date | date | timestamp without time zone |
+ oracleconn | oracle | 3 | FREE.DBZUSER.ORDERS | free.orders | PURCHASER | purchaser | number | numeric |
+ oracleconn | oracle | 4 | FREE.DBZUSER.ORDERS | free.orders | QUANTITY | quantity | number | numeric |
+ oracleconn | oracle | 5 | FREE.DBZUSER.ORDERS | free.orders | PRODUCT_ID | product_id | number | numeric |
+
+```
+### **定義自訂映射規則(如有需要)**
+
+使用者可以使用 `synchdb_add_objmap` 函數建立自訂映射規則。此函數可用於對應表名、列名、資料類型,並定義資料轉換表達式規則。
+
+```sql
+SELECT synchdb_add_objmap('oracleconn','table','FREE.DBZUSER.ORDERS','free.myorders');
+SELECT synchdb_add_objmap('oracleconn','column','FREE.DBZUSER.ORDERS.PURCHASER','who');
+SELECT synchdb_add_objmap('oracleconn','datatype','FREE.DBZUSER.ORDERS.QUANTITY','bigint|0');
+SELECT synchdb_add_objmap('oracleconn','transform','FREE.DBZUSER.CUSTOMERS.NAME','''>>>>>'' || ''%d'' || ''<<<<<''');
+```
+
+以上內容意味著:
+
+* 來源表“FREE.DBZUSER.ORDERS”將對應到目標表“free.myorders”
+* 來源列“FREE.DBZUSER.ORDERS.PURCHASE”將對應到目標表“who”
+* 來源列“FREE.DBZUSER.ORDERS.QUANTITY”的資料類型將會對應到“bigint”
+* 來源列「FREE.DBZUSER.CUSTOMERS.NAME」的資料將根據表達式進行轉換,其中 %d 為資料佔位符
+
+### **回顧所有已建立的物件映射規則**
+
+```sql
+SELECT * FROM synchdb_objmap WHERE name = 'oracleconn';
+ name | objtype | enabled | srcobj | dstobj
+------------+-----------+---------+-------------------------------+----------------------------
+ oracleconn | table | t | FREE.DBZUSER.ORDERS | free.myorders
+ oracleconn | column | t | FREE.DBZUSER.ORDERS.PURCHASER | who
+ oracleconn | datatype | t | FREE.DBZUSER.ORDERS.QUANTITY | bigint|0
+ oracleconn | transform | t | FREE.DBZUSER.CUSTOMERS.NAME | '>>>>>' || '%d' || '<<<<<'
+
+```
+
+### **重新載入物件映射規則**
+
+定義完所有自訂規則後,我們需要通知連接器載入這些規則。這將使連接器讀取並應用物件映射規則。如果連接器發現目前 PostgreSQL 值與物件對應值之間存在差異,它將嘗試修正映射。
+
+```sql
+SELECT synchdb_reload_objmap('oracleconn');
+
+```
+
+### **再次檢查 `synchdb_att_view` 是否有更改**
+
+```sql
+SELECT * from synchdb_att_view WHERE name = 'oracleconn';
+ name | type | attnum | ext_tbname | pg_tbname | ext_attname | pg_attname | ext_atttypename | pg_atttypename | transform
+------------+--------+--------+------------------------+----------------+--------------+--------------+-----------------+-----------------------------+----------------------------
+ oracleconn | oracle | 1 | FREE.DBZUSER.CUSTOMERS | free.customers | ID | id | number | numeric |
+ oracleconn | oracle | 2 | FREE.DBZUSER.CUSTOMERS | free.customers | NAME | name | varchar2 | character varying | '>>>>>' || '%d' || '<<<<<'
+ oracleconn | oracle | 1 | FREE.DBZUSER.ORDERS | free.myorders | ORDER_NUMBER | order_number | number | numeric |
+ oracleconn | oracle | 2 | FREE.DBZUSER.ORDERS | free.myorders | ORDER_DATE | order_date | date | timestamp without time zone |
+ oracleconn | oracle | 3 | FREE.DBZUSER.ORDERS | free.myorders | PURCHASER | who | number | numeric |
+ oracleconn | oracle | 4 | FREE.DBZUSER.ORDERS | free.myorders | QUANTITY | quantity | number | bigint |
+ oracleconn | oracle | 5 | FREE.DBZUSER.ORDERS | free.myorders | PRODUCT_ID | product_id | number | numeric |
+
+```
+
+### **恢復連接器或重新建立整個快照**
+
+確認物件映射正確後,我們可以恢復連接器。請注意,復原操作只會傳輸新的表更改,不會複製表中的現有資料。
+
+```sql
+SELECT synchdb_resume_engine('oracleconn');
+
+```
+
+要擷取表中的現有數據,我們也可以使用新的物件映射規則重新建立整個快照。
+
+```sql
+SELECT synchdb_stop_engine_bgw('oracleconn');
+SELECT synchdb_start_engine_bgw('oracleconn', 'always');
+
+```
## **選擇性表同步**
@@ -130,7 +248,7 @@ SELECT synchdb_start_engine_bgw('oracleconn', 'always');
表格選擇在連接器建立階段透過 `synchdb_add_conninfo()` 函數完成,該函數用於指定要從中複製的表列表(以完全限定名稱 (FQN) 表示,並以逗號分隔)。
-例如,以下命令建立一個連接器,該連接器僅從遠端 MySQL 資料庫複製 `inventory.orders` 和 `inventory.products` 表中的變更。
+例如,以下命令建立一個連接器,該連接器僅從遠端 Oracle 資料庫複製 `FREE.ORDERS` 表中的變更。
```sql
SELECT synchdb_add_conninfo(
'oracleconn',
@@ -155,6 +273,7 @@ SELECT synchdb_start_engine_bgw('oracleconn');
### **驗證連接器狀態和表格**
檢查連接器狀態和新表格:
+
```sql
postgres=# Select name, state, err from synchdb_state_view;
name | state | err
@@ -178,21 +297,25 @@ postgres=# \dt free.*
1. 更新 `synchdb_conninfo` 表以包含其他表。
2. 在本例中,我們將 `DBZUSER.CUSTOMERS` 表加入同步清單:
+
```sql
UPDATE synchdb_conninfo
SET data = jsonb_set(data, '{table}', '"DBZUSER.ORDERS,DBZUSER.CUSTOMERS"')
WHERE name = 'oracleconn';
```
3. 將快照模式設為“始終”,然後重新啟動連接器,以執行另一次初始快照:
+
```sql
DROP table free.orders;
SELECT synchdb_restart_connector('oracleconn', 'always');
```
+
這迫使 Debezium 在進行 CDC 串流之前,重新建立所有表格的快照,包括現有的 `free.orders` 表和新的 `free.customers` 表。這意味著,要新增表,必須刪除現有表(以防止重複表和主鍵錯誤),並重新建立整個初始快照。這相當冗餘,Debezium 建議使用增量快照來新增資料表,而無需重新建立快照。一旦我們將增量快照支援新增至 SynchDB,我們將更新此流程。
### **驗證更新後的表格**
現在,我們可以再次檢查我們的表:
+
```sql
postgres=# \dt free.*
List of tables
@@ -201,4 +324,243 @@ postgres=# \dt free.*
free | orders | table | ubuntu
customers | orders | table | ubuntu
-```
\ No newline at end of file
+```
+
+## **配置 Infinispan功能**
+
+默认情况下,Debezium 的 Oracle 连接器使用 JVM 堆缓存传入的变更事件,然后再将它们传递给 SynchDB 进行处理。最大堆大小通过 `synchdb.jvm_max_heap_size` GUC 控制。当 JVM 堆内存不足时(尤其是在处理大型事务或包含大量列的模式时),连接器可能会出现 OutOfMemoryError 错误,这使得堆大小调整成为一项关键的调优挑战。
+
+作为替代方案,Debezium 可以配置使用 Infinispan 作为其缓存层。Infinispan 支持 JVM 堆和堆外(直接内存)的内存存储,从而提供更大的灵活性。此外,它还支持钝化功能,允许在达到内存限制时将多余的数据溢出到磁盘。这使得它在高负载下更具弹性,并确保能够优雅地处理大型事务或模式变更,而不会耗尽内存。
+
+### **`synchdb_add_infinispan()`**
+
+**签名:**
+
+```sql
+synchdb_add_infinispan(
+ connectorName NAME, -- 连接器名称
+ memoryType NAME, -- 内存类型,可以是“堆”或“非堆”
+ memorySize INT -- 预留为缓存的内存大小(以 MB 为单位)
+)
+```
+
+为给定的连接器注册一个由 Infinispan 支持的缓存配置。这允许连接器使用 Infinispan 缓冲更改事件,并支持基于堆和堆外内存分配以及溢出到磁盘(钝化)。
+
+**注意:**
+
+- 如果在当前正在运行的连接器上调用,则该设置将在下次重启时生效。
+- 如果连接器已存在 Infinispan 缓存,它将被替换。
+- memoryType='off_heap' 使用本机(直接)内存,不受 JVM 堆限制,但应谨慎调整大小。
+- 当内存填满时,缓存将自动支持钝化到磁盘。
+
+**示例:**
+``` sql
+SELECT synchdb_add_infinispan('oracleconn', 'off_heap', 2048);
+
+```
+
+### **`synchdb_del_infinispan()`**
+
+**签名:**
+
+```sql
+synchdb_add_infinispan(
+ connectorName NAME -- 连接器名称
+)
+```
+
+删除指定连接器的 Infinispan 缓存配置及其相关的磁盘元数据。此操作将删除:
+
+- 所有缓存文件
+- 所有钝化(溢出到磁盘)状态
+- 相关的 Infinispan 配置
+
+**注意:**
+
+- 此函数只能在连接器停止时执行。
+- 在连接器处于活动状态时尝试运行此函数将导致错误。
+- 永久禁用或重新配置连接器的缓存后端后,使用此命令进行清理。
+
+**Example:**
+``` sql
+SELECT synchdb_del_infinispan('oracleconn');
+
+```
+
+### **`钝化`**
+
+钝化简单来说就是,如果缓存已满,infinispan 会弹出并将数据写入磁盘。只要内存中有足够的空间来保存更改事件,就不会发生磁盘写入。数据将写入 `$PGDATA/pg_synchdb/ispn_[连接器名称]_[目标数据库名称]`
+
+### **用于测试 Infinispan 大型事务的 Oracle SQL 示例**
+
+**在 Oracle 中创建测试表:**
+
+```sql
+CREATE TABLE big_tx_test (
+ id NUMBER PRIMARY KEY,
+ payload VARCHAR2(4000),
+ created DATE DEFAULT SYSDATE
+);
+
+```
+
+**创建一个相对较大的交易:**
+```sql
+BEGIN
+ FOR i IN 1..100000 LOOP
+ INSERT INTO big_tx_test (id, payload)
+ VALUES (i, RPAD('x', 4000, 'x'));
+ END LOOP;
+ COMMIT;
+END;
+/
+
+```
+
+**大事务下的行为**
+
+未设置 infinispan + 低 JVM heap size (128)
+
+* --> 将发生 OutOfMemory 错误
+
+低 JVM heap size (128) + 高 infinispan heap size (2048)
+
+* --> 大型事务成功处理
+
+低 JVM heap size (128) + 低 infinispan heap size (128)
+
+* --> 将发生钝化
+* --> `ispn_[连接器名称]_[目标数据库名称]` 大小在处理过程中会增加,大型事务处理完成后会减小
+* --> 大型事务已成功处理,但速度较慢。
+
+低 JVM heap size (128) + 高 infinispan heap size (2048)
+
+* --> 将发生 OutOfMemory 错误
+* --> 请勿将 infinispan 配置 heap size 超过 JVM 最大 heap 内存
+
+较低的 JVM heap size (128) + 较低的 infinispan heap size (64)
+
+* --> 将发生钝化
+* --> `ispn_[连接器名称]_[目标数据库名称]` 的大小将在处理过程中增加,并在大型事务处理完成后减小。
+* --> 不建议使用,因为 infinispan 可能会占用一半的 JVM heap,而剩余空间可能不足以用于其他 Debezium 操作。
+
+低 JVM heap size (128) + 相同的 infinispan heap size (128)
+
+* --> 不建议使用,因为 infinispan 可能会占用所有 JVM 堆空间,最终导致 OutOfMemory 错误。
+
+高 JVM heap size (2048) + 低 infinispan heap size (128)
+
+* --> 将发生钝化。
+* --> `ispn_[连接器名称]_[目标数据库名称]` 的大小在处理过程中会增加,并在大型事务处理完成后减小。
+* --> 大型事务处理成功。
+* --> 效率低下 - 因为只有一小部分 JVM heap 空间用作缓存 + 不必要的钝化。
+
+
+## 自定义起始偏移量值
+
+起始偏移量值代表开始复制的点,类似于 PostgreSQL 的恢复 LSN。当 Debezium 运行引擎启动时,它将从这个偏移量值开始复制。将此偏移量值设置为较早的值将导致 Debezium 运行引擎从较早的记录开始复制,可能会复制重复的数据记录。在设置 Debezium 的起始偏移量值时,我们应该格外谨慎。
+
+### **记录可设置的偏移量值**
+
+在操作过程中,Debezium 运行引擎将生成新的偏移量并将其刷新到磁盘。最后刷新的偏移量可以通过 `synchdb_state_view()` 实用命令检索:
+
+```
+postgres=# select name, last_dbz_offset from synchdb_state_view;
+ name | last_dbz_offset
+---------------+------------------------------------------------------------------------------------------------------
+ oracleconn | {"commit_scn":"2311579","snapshot_scn":"2311578","scn":"2311578"}
+
+```
+
+我们应该定期保存这些值,这样如果遇到问题,我们就知道过去可以设置的偏移量位置,以恢复复制操作。
+
+### **暂停连接器**
+
+在设置新的偏移量值之前,连接器必须处于 `paused`(暂停)状态。
+
+使用 `synchdb_pause_engine()` SQL 函数暂停正在运行的连接器。这将停止 Debezium 运行引擎从异构数据库复制。当暂停时,可以使用 `synchdb_set_offset()` SQL 例程更改 Debezium 连接器的偏移量值,以从过去的特定点开始复制。它以 `conninfo_name` 作为参数,可以从 `synchdb_get_state()` 视图的输出中找到。
+
+例如:
+
+```sql
+SELECT synchdb_pause_engine('oracleconn');
+```
+
+### **设置新的偏移量**
+
+使用 `synchdb_set_offset()` SQL 函数更改连接器工作进程的起始偏移量。只有当连接器处于 `paused` 状态时才能执行此操作。该函数接受两个参数,`conninfo_name` 和 `有效的偏移量字符串`,这两个参数都可以从 `synchdb_get_state()` 视图的输出中找到。
+
+例如:
+
+```sql
+SELECT synchdb_set_offset('oracleconn', '{"commit_scn":"2311579","snapshot_scn":"2311578","scn":"2311578"}');
+```
+
+### **恢复连接器**
+
+使用 `synchdb_resume_engine()` SQL 函数从暂停状态恢复 Debezium 操作。此函数以 `连接器名称` 作为其唯一参数,可以从 `synchdb_get_state()` 视图的输出中找到。恢复的 Debezium 运行引擎将从新设置的偏移量值开始复制。
+
+例如:
+
+```sql
+SELECT synchdb_resume_engine('oracleconn');
+```
+
+## 設定 Debezium Oracle 連接器以使用 Openlog Replicator(非原生)
+
+雖然不建議,但可以配置基於 Debezium 的 Oracle 連接器,使其從 Openlog Replicator 而非 Logminer 串流傳輸資料。這與 [原生 Openlog Replicator](../../tutorial/native_olr_cdc_to_postgresql) 不同,後者是 SynchDB 內部原生建構的,無需使用 Debezium,也是使用 OLR 的建議方式。
+
+要建立**基於 Debezium**的 OLR 連接器(使用 `type` = 'oracle'):
+
+```sql
+SELECT synchdb_add_conninfo('olrconn',
+ 'ora19c',
+ 1521,
+ 'DBZUSER',
+ 'dbz',
+ 'FREE',
+ 'postgres',
+ 'null',
+ 'null',
+ 'oracle');
+
+```
+
+然後,使用帶有簽署的 `synchdb_add_olr_conninfo` 函數附加 Openlog Replicator 資訊:
+
+```sql
+synchdb_add_olr_conninfo(
+ conn_name TEXT, -- Name of the connector
+ olr_host TEXT, -- Hostname or IP of the OLR instance
+ olr_port INT, -- Port number exposed by OLR (typically 7070)
+ olr_source TEXT -- Oracle source name as configured in OLR
+)
+```
+
+**範例:**
+
+```sql
+SELECT synchdb_add_olr_conninfo('olrconn', '127.0.0.1', 7070, 'ORACLE');
+
+```
+
+若要從特定連接器移除 OLR 設定並還原至 Logminer,請使用具有下列簽章的 `synchdb_del_olr_conninfo` 函數:
+
+```sql
+synchdb_del_olr_conninfo(conn_name TEXT)
+
+```
+
+**範例:**
+
+```sql
+
+SELECT synchdb_del_olr_conninfo('olrconn');
+
+```
+
+**基於 Debezium 的 Openlog Replicator 連接器的行為說明**
+
+* 當 LogMiner 和 OLR 配置同時存在時,SynchDB 預設使用 Openlog Replicator 進行變更擷取。
+* 如果 OLR 設定缺失,SynchDB 將使用日誌原則來傳輸變更。
+* 修改 OLR 配置後,需要重新啟動連接器。
\ No newline at end of file
diff --git a/doc/docs/zh/tutorial/postgresql_cdc_to_postgresql.md b/doc/docs/zh/tutorial/postgresql_cdc_to_postgresql.md
index 91b539f..9ef6926 100644
--- a/doc/docs/zh/tutorial/postgresql_cdc_to_postgresql.md
+++ b/doc/docs/zh/tutorial/postgresql_cdc_to_postgresql.md
@@ -1,4 +1,4 @@
-# Postgres -> Postgres
+# Postgres 连接器
## **為 SynchDB 準備 PostgreSQL 資料庫**
@@ -155,10 +155,146 @@ WHERE name = 'pgconn';
## **使用 schemasync 模式預覽來源表和目標表關係**
-在嘗試對當前表和資料(可能非常龐大)進行初始快照之前,可以在實際資料遷移之前「預覽」來源表和目標表之間的所有表和資料類型對應。這使您可以在實際遷移之前修改資料類型對應或物件名稱。這可以透過特殊的「schemasync」初始快照模式來實現。有關詳細範例,請參閱[物件對映工作流程](../../tutorial/object_mapping_workflow/)。
+在嘗試對當前表和資料(可能非常龐大)進行初始快照之前,可以在實際資料遷移之前「預覽」來源表和目標表之間的所有表和資料類型對應。這樣,您有機會在實際遷移之前修改資料類型對應或物件名稱。這可以透過特殊的「schemasync」初始快照模式來實現。
請注意,您必須將 `synchdb.olr_snapshot_engine` 設定為 'fdw' 才能使用 `schemasync` 模式預覽表。
+### **建立連接器並以 `schemasync` 模式啟動它**
+
+`schemasync` 是一種特殊模式,它使連接器連接到遠端資料庫並嘗試僅同步指定表的模式。完成後,連接器將處於「暫停」狀態,使用者可以查看使用預設規則建立的所有資料表和資料類型,並根據需要進行變更。
+
+```sql
+SELECT synchdb_add_conninfo(
+ 'pgconn',
+ '127.0.0.1',
+ 5433,
+ 'pguser',
+ 'pgpass',
+ 'postgres',
+ 'public',
+ 'null',
+ 'null',
+ 'postgres'
+);
+
+SELECT synchdb_start_engine_bgw('pgconn', 'schemasync');
+```
+
+### **確保連接器處於暫停狀態**
+
+```sql
+SELECT name, connector_type, pid, stage, state FROM synchdb_state_view WHERE name = 'pgconn';;
+ name | connector_type | pid | stage | state
+--------+----------------+---------+---------------------+--------
+ pgconn | postgres | 1643157 | change data capture | paused
+
+```
+
+### **查看預設映射規則所建立的表**
+
+```sql
+SELECT * FROM synchdb_att_view WHERE name = 'pgconn';
+ name | type | attnum | ext_tbname | pg_tbname | ext_attname | pg_attname | ext_atttypename | pg_atttypename | transform
+--------+----------+--------+-------------------------+------------------+-------------+------------+-------------------+-------------------+-----------
+ pgconn | postgres | 1 | postgres.public.mytble | postgres.mytble | a | a | numeric | numeric |
+ pgconn | postgres | 2 | postgres.public.mytble | postgres.mytble | b | b | numeric | numeric |
+ pgconn | postgres | 3 | postgres.public.mytble | postgres.mytble | c | c | numeric | numeric |
+ pgconn | postgres | 1 | postgres.public.testing | postgres.testing | a | a | integer | integer |
+ pgconn | postgres | 2 | postgres.public.testing | postgres.testing | b | b | text | text |
+ pgconn | postgres | 3 | postgres.public.testing | postgres.testing | c | c | character varying | character varying |
+ pgconn | postgres | 4 | postgres.public.testing | postgres.testing | d | d | bigint | bigint |
+ pgconn | postgres | 1 | postgres.public.xyz | postgres.xyz | bbb | bbb | character varying | character varying |
+ pgconn | postgres | 2 | postgres.public.xyz | postgres.xyz | ccc | ccc | bytea | bytea |
+ pgconn | postgres | 3 | postgres.public.xyz | postgres.xyz | ddd | ddd | numeric | numeric |
+ pgconn | postgres | 4 | postgres.public.xyz | postgres.xyz | eee | eee | numeric | numeric |
+ pgconn | postgres | 5 | postgres.public.xyz | postgres.xyz | fff | fff | numeric | numeric |
+ pgconn | postgres | 6 | postgres.public.xyz | postgres.xyz | ggg | ggg | bigint | bigint |
+ pgconn | postgres | 7 | postgres.public.xyz | postgres.xyz | aaa | aaa | integer | integer |
+
+
+```
+
+### **定義自訂映射規則(如有需要)**
+
+使用者可以使用 `synchdb_add_objmap` 函數建立自訂映射規則。此函數可用於對應表名、列名、資料類型,並定義資料轉換表達式規則。
+
+```sql
+SELECT synchdb_add_objmap('pgconn','table','postgres.public.mytble','postgres.thetable');
+SELECT synchdb_add_objmap('pgconn','column','postgres.public.testing.c','ccc');
+SELECT synchdb_add_objmap('pgconn','datatype','postgres.public.xyz.ggg','int|0');
+SELECT synchdb_add_objmap('pgconn','transform','postgres.public.xyz.bbb','''>>>>>'' || ''%d'' || ''<<<<<''');
+```
+
+以上內容意味著:
+
+* 來源表 'postgres.public.mytble' 將會對應到目標表 'postgres.thetable'
+* 來源列 'postgres.public.testing.c' 將會對應到目標列 'ccc'
+* 來源列 'postgres.public.xyz.ggg' 的資料型別將會對應到 'int'
+* 來源列資料 'postgres.public.xyz.bbb' 將根據表達式進行轉換,其中 %d 為資料佔位符
+
+### **回顧所有已建立的物件映射規則**
+
+```sql
+SELECT * FROM synchdb_objmap WHERE name = 'pgconn';
+ name | objtype | enabled | srcobj | dstobj
+--------+-----------+---------+---------------------------+----------------------------
+ pgconn | table | t | postgres.public.mytble | postgres.thetable
+ pgconn | column | t | postgres.public.testing.c | ccc
+ pgconn | datatype | t | postgres.public.xyz.ggg | int|0
+ pgconn | transform | t | postgres.public.xyz.bbb | '>>>>>' || '%d' || '<<<<<'
+
+
+```
+
+### **重新載入物件映射規則**
+
+定義完所有自訂規則後,我們需要通知連接器載入這些規則。這將使連接器讀取並應用物件映射規則。如果連接器發現目前 PostgreSQL 值與物件對應值之間存在差異,它將嘗試修正映射。
+
+```sql
+SELECT synchdb_reload_objmap('pgconn');
+
+```
+
+### **再次檢查 `synchdb_att_view` 是否有更改**
+
+```sql
+SELECT * from synchdb_att_view WHERE name = 'pgconn';;
+ name | type | attnum | ext_tbname | pg_tbname | ext_attname | pg_attname | ext_atttypename | pg_atttypename | transform
+--------+----------+--------+-------------------------+-------------------+-------------+------------+-------------------+-------------------+----------------------------
+ pgconn | postgres | 1 | postgres.public.mytble | postgres.thetable | a | a | numeric | numeric |
+ pgconn | postgres | 2 | postgres.public.mytble | postgres.thetable | b | b | numeric | numeric |
+ pgconn | postgres | 3 | postgres.public.mytble | postgres.thetable | c | c | numeric | numeric |
+ pgconn | postgres | 1 | postgres.public.testing | postgres.testing | a | a | integer | integer |
+ pgconn | postgres | 2 | postgres.public.testing | postgres.testing | b | b | text | text |
+ pgconn | postgres | 3 | postgres.public.testing | postgres.testing | c | ccc | character varying | character varying |
+ pgconn | postgres | 4 | postgres.public.testing | postgres.testing | d | d | bigint | bigint |
+ pgconn | postgres | 1 | postgres.public.xyz | postgres.xyz | bbb | bbb | character varying | character varying | '>>>>>' || '%d' || '<<<<<'
+ pgconn | postgres | 2 | postgres.public.xyz | postgres.xyz | ccc | ccc | bytea | bytea |
+ pgconn | postgres | 3 | postgres.public.xyz | postgres.xyz | ddd | ddd | numeric | numeric |
+ pgconn | postgres | 4 | postgres.public.xyz | postgres.xyz | eee | eee | numeric | numeric |
+ pgconn | postgres | 5 | postgres.public.xyz | postgres.xyz | fff | fff | numeric | numeric |
+ pgconn | postgres | 6 | postgres.public.xyz | postgres.xyz | ggg | ggg | bigint | integer |
+ pgconn | postgres | 7 | postgres.public.xyz | postgres.xyz | aaa | aaa | integer | integer |
+
+```
+
+### **恢復連接器或重新建立整個快照**
+
+確認物件映射正確後,我們可以恢復連接器。請注意,復原操作只會傳輸新的表更改,不會複製表中的現有資料。
+
+```sql
+SELECT synchdb_resume_engine('pgconn');
+
+```
+
+要擷取表中的現有數據,我們也可以使用新的物件映射規則重新建立整個快照。
+
+```sql
+SELECT synchdb_stop_engine_bgw('pgconn');
+SELECT synchdb_start_engine_bgw('pgconn', 'always');
+
+```
+
## **選擇性表同步**
### **選擇所需表並首次啟動**
diff --git a/doc/docs/zh/tutorial/sqlserver_cdc_to_postgresql.md b/doc/docs/zh/tutorial/sqlserver_cdc_to_postgresql.md
index 4566854..4edec7f 100644
--- a/doc/docs/zh/tutorial/sqlserver_cdc_to_postgresql.md
+++ b/doc/docs/zh/tutorial/sqlserver_cdc_to_postgresql.md
@@ -1,4 +1,4 @@
-# SQL Server -> PostgreSQL
+# SQL Server 连接器
## **为 SynchDB 准备 SQL Server 数据库**
@@ -148,7 +148,149 @@ WHERE name = 'sqlserverconn';
## **使用 schemasync 模式預覽來源表和目標表關係**
-在嘗試對當前表和資料(可能非常龐大)進行初始快照之前,可以在實際資料遷移之前「預覽」來源表和目標表之間的所有表和資料類型對應。這樣,您就有機會在實際遷移之前修改資料類型對應或物件名稱。這可以透過特殊的「schemasync」初始快照模式來實現。有關詳細範例,請參閱[对象映射工作流程](../../tutorial/object_mapping_workflow/)。
+在嘗試對當前表和資料(可能非常龐大)進行初始快照之前,可以在實際資料遷移之前「預覽」來源表和目標表之間的所有表和資料類型對應。這樣,您有機會在實際遷移之前修改資料類型對應或物件名稱。這可以透過特殊的「schemasync」初始快照模式來實現。
+
+請注意,您必須將 `synchdb.olr_snapshot_engine` 設定為 'fdw' 才能使用 `schemasync` 模式預覽表。
+
+### **建立連接器並以 `schemasync` 模式啟動它**
+
+`schemasync` 是一種特殊模式,它使連接器連接到遠端資料庫並嘗試僅同步指定表的模式。完成後,連接器將處於「暫停」狀態,使用者可以查看使用預設規則建立的所有資料表和資料類型,並根據需要進行變更。
+
+```sql
+SELECT synchdb_add_conninfo(
+ 'sqlserverconn',
+ '127.0.0.1',
+ 1433,
+ 'sa',
+ 'Password!',
+ 'testDB',
+ 'dbo',
+ 'null',
+ 'null',
+ 'sqlserver'
+);
+
+SELECT synchdb_start_engine_bgw('sqlserverconn', 'schemasync');
+```
+
+### **確保連接器處於暫停狀態**
+
+```sql
+SELECT name, connector_type, pid, stage, state FROM synchdb_state_view WHERE name = 'sqlserverconn';
+ name | connector_type | pid | stage | state
+---------------+----------------+---------+---------------------+--------
+ sqlserverconn | sqlserver | 1647884 | change data capture | paused
+
+```
+
+### **查看預設映射規則所建立的表**
+
+```sql
+SELECT * FROM synchdb_att_view WHERE name = 'sqlserverconn';
+ name | type | attnum | ext_tbname | pg_tbname | ext_attname | pg_attname | ext_atttypename | pg_atttypename | transform
+---------------+-----------+--------+-----------------------------+-------------------------+--------------+--------------+-----------------+-------------------+-----------
+ sqlserverconn | sqlserver | 1 | testDB.dbo.customers | testdb.customers | id | id | int identity | integer |
+ sqlserverconn | sqlserver | 2 | testDB.dbo.customers | testdb.customers | first_name | first_name | varchar | character varying |
+ sqlserverconn | sqlserver | 3 | testDB.dbo.customers | testdb.customers | last_name | last_name | varchar | character varying |
+ sqlserverconn | sqlserver | 4 | testDB.dbo.customers | testdb.customers | email | email | varchar | character varying |
+ sqlserverconn | sqlserver | 1 | testDB.dbo.orders | testdb.orders | order_number | order_number | int identity | integer |
+ sqlserverconn | sqlserver | 2 | testDB.dbo.orders | testdb.orders | order_date | order_date | date | date |
+ sqlserverconn | sqlserver | 3 | testDB.dbo.orders | testdb.orders | purchaser | purchaser | int | integer |
+ sqlserverconn | sqlserver | 4 | testDB.dbo.orders | testdb.orders | quantity | quantity | int | integer |
+ sqlserverconn | sqlserver | 5 | testDB.dbo.orders | testdb.orders | product_id | product_id | int | integer |
+ sqlserverconn | sqlserver | 1 | testDB.dbo.products | testdb.products | id | id | int identity | integer |
+ sqlserverconn | sqlserver | 2 | testDB.dbo.products | testdb.products | name | name | varchar | character varying |
+ sqlserverconn | sqlserver | 3 | testDB.dbo.products | testdb.products | description | description | varchar | character varying |
+ sqlserverconn | sqlserver | 4 | testDB.dbo.products | testdb.products | weight | weight | float | real |
+ sqlserverconn | sqlserver | 1 | testDB.dbo.products_on_hand | testdb.products_on_hand | product_id | product_id | int | integer |
+ sqlserverconn | sqlserver | 2 | testDB.dbo.products_on_hand | testdb.products_on_hand | quantity | quantity | int | integer |
+
+```
+
+### **定義自訂映射規則(如有需要)**
+
+使用者可以使用 `synchdb_add_objmap` 函數建立自訂映射規則。此函數可用於對應表名、列名、資料類型,並定義資料轉換表達式規則。
+
+```sql
+SELECT synchdb_add_objmap('sqlserverconn','table','testDB.dbo.products','testdb.myproducts');
+SELECT synchdb_add_objmap('sqlserverconn','column','testDB.dbo.customers.email','contact');
+SELECT synchdb_add_objmap('sqlserverconn','datatype','testDB.dbo.products_on_hand.quantity','bigint|0');
+SELECT synchdb_add_objmap('sqlserverconn','transform','testDB.dbo.products.name','''>>>>>'' || ''%d'' || ''<<<<<''');
+```
+
+以上內容意味著:
+
+* 來源表“testDB.dbo.product”將會對應到目標表“testdb.myproducts”
+* 來源列“testDB.dbo.customers.email”將會對應到目標表“contact”
+* 來源列“testDB.dbo.products_on_hand.quantity”的資料型別將會對應到“bigint”
+* 來源列「testDB.dbo.products.name」的資料將根據表達式進行轉換,其中 %d 為資料佔位符
+
+### **回顧所有已建立的物件映射規則**
+
+```sql
+SELECT * FROM synchdb_objmap WHERE name = 'sqlserverconn';
+ name | objtype | enabled | srcobj | dstobj
+---------------+-----------+---------+--------------------------------------+----------------------------
+ sqlserverconn | table | t | testDB.dbo.products | testdb.myproducts
+ sqlserverconn | column | t | testDB.dbo.customers.email | contact
+ sqlserverconn | datatype | t | testDB.dbo.products_on_hand.quantity | bigint|0
+ sqlserverconn | transform | t | testDB.dbo.product.name | '>>>>>' || '%d' || '<<<<<'
+
+```
+
+### **重新載入物件映射規則**
+
+定義完所有自訂規則後,我們需要通知連接器載入這些規則。這將使連接器讀取並應用物件映射規則。如果連接器發現目前 PostgreSQL 值與物件對應值之間存在差異,它將嘗試修正映射。
+
+```sql
+SELECT synchdb_reload_objmap('sqlserverconn');
+
+```
+
+### **再次檢查 `synchdb_att_view` 是否有更改**
+
+```sql
+SELECT * from synchdb_att_view WHERE name = 'sqlserverconn';
+ name | type | attnum | ext_tbname | pg_tbname | ext_attname | pg_attname | ext_atttypename | pg_atttypename | transform
+
+---------------+-----------+--------+-----------------------------+-------------------------+--------------+--------------+-----------------+-------------------+---------------------
+-------
+ sqlserverconn | sqlserver | 1 | testDB.dbo.customers | testdb.customers | id | id | int identity | integer |
+ sqlserverconn | sqlserver | 2 | testDB.dbo.customers | testdb.customers | first_name | first_name | varchar | character varying |
+ sqlserverconn | sqlserver | 3 | testDB.dbo.customers | testdb.customers | last_name | last_name | varchar | character varying |
+ sqlserverconn | sqlserver | 4 | testDB.dbo.customers | testdb.customers | email | contact | varchar | character varying |
+ sqlserverconn | sqlserver | 1 | testDB.dbo.orders | testdb.orders | order_number | order_number | int identity | integer |
+ sqlserverconn | sqlserver | 2 | testDB.dbo.orders | testdb.orders | order_date | order_date | date | date |
+ sqlserverconn | sqlserver | 3 | testDB.dbo.orders | testdb.orders | purchaser | purchaser | int | integer |
+ sqlserverconn | sqlserver | 4 | testDB.dbo.orders | testdb.orders | quantity | quantity | int | integer |
+ sqlserverconn | sqlserver | 5 | testDB.dbo.orders | testdb.orders | product_id | product_id | int | integer |
+ sqlserverconn | sqlserver | 1 | testDB.dbo.products | testdb.products | id | id | int identity | integer |
+ sqlserverconn | sqlserver | 2 | testDB.dbo.products | testdb.products | name | name | varchar | character varying | '>>>>>' || '%d' || '
+<<<<<'
+ sqlserverconn | sqlserver | 3 | testDB.dbo.products | testdb.products | description | description | varchar | character varying |
+ sqlserverconn | sqlserver | 4 | testDB.dbo.products | testdb.products | weight | weight | float | real |
+ sqlserverconn | sqlserver | 1 | testDB.dbo.products_on_hand | testdb.products_on_hand | product_id | product_id | int | integer |
+ sqlserverconn | sqlserver | 2 | testDB.dbo.products_on_hand | testdb.products_on_hand | quantity | quantity | int | bigint |
+
+
+```
+
+### **恢復連接器或重新建立整個快照**
+
+確認物件映射正確後,我們可以恢復連接器。請注意,復原操作只會傳輸新的表更改,不會複製表中的現有資料。
+
+```sql
+SELECT synchdb_resume_engine('sqlserverconn');
+
+```
+
+要擷取表中的現有數據,我們也可以使用新的物件映射規則重新建立整個快照。
+
+```sql
+SELECT synchdb_stop_engine_bgw('sqlserverconn');
+SELECT synchdb_start_engine_bgw('sqlserverconn', 'always');
+
+```
## **選擇性表同步**
@@ -230,4 +372,84 @@ postgres=# \dt "testDB".*
testDB | orders | table | ubuntu
testDB | products | table | ubuntu
+```
+
+## 安全连接
+
+### **配置安全连接**
+
+为了确保与远程数据库的连接安全,我们需要为 `synchdb_add_conninfo` 创建的连接器配置额外的 SSL 相关参数。SSL 证书和私钥必须打包为 Java 密钥库文件,并附带密码。这些信息随后会通过 synchdb_add_extra_conninfo() 传递给 SynchDB。
+
+### **synchdb_add_extra_conninfo**
+
+**用途**:为 `synchdb_add_conninfo` 创建的现有连接器配置额外的连接器参数
+
+| 参数 | 描述 | 必需 | 示例 | 备注 |
+|:-:|:-|:-:|:-|:-|
+| `name` | 此连接器的唯一标识符 | ✓ | `'mysqlconn'` | 必须在所有连接器中唯一 |
+| `ssl_mode` | SSL 模式 | ☐ | `'verify_ca'` |可以是以下之一:
- “disabled”- 不使用 SSL。
- “preferred”- 如果服务器支持,则使用 SSL。
- “required”- 必须使用 SSL 建立连接。
- “verify_ca”- 连接器与服务器建立 TLS,并将根据配置的信任库验证服务器的 TLS 证书。
- “verify_identity”- 与 verify_ca 行为相同,但它还会检查服务器证书的通用名称以匹配系统的主机名。|
+| `ssl_keystore` | 密钥库路径 | ☐ | `/path/to/keystore` | 密钥库文件的路径 |
+| `ssl_keystore_pass` | 密钥库密码 | ☐ | `'mykeystorepass'` | 访问密钥库文件的密码 |
+| `ssl_truststore` | 信任库路径 | ☐ | `'/path/to/truststore'` | 信任库文件路径 |
+| `ssl_truststore_pass` | 信任库密码 | ☐ | `'mytruststorepass'` | 访问信任库文件的密码 |
+
+```sql
+SELECT synchdb_add_extra_conninfo('sqlserverconn', 'verify_ca', '/path/to/keystore', 'mykeystorepass', '/path/to/truststore', 'mytruststorepass');
+```
+
+### **synchdb_del_extra_conninfo**
+
+**用途**:删除由 `synchdb_add_extra_conninfo` 创建的额外连接器参数
+```sql
+SELECT synchdb_del_extra_conninfo('sqlserverconn');
+```
+
+## 自定义起始偏移量值
+
+起始偏移量值代表开始复制的点,类似于 PostgreSQL 的恢复 LSN。当 Debezium 运行引擎启动时,它将从这个偏移量值开始复制。将此偏移量值设置为较早的值将导致 Debezium 运行引擎从较早的记录开始复制,可能会复制重复的数据记录。在设置 Debezium 的起始偏移量值时,我们应该格外谨慎。
+
+### **记录可设置的偏移量值**
+
+在操作过程中,Debezium 运行引擎将生成新的偏移量并将其刷新到磁盘。最后刷新的偏移量可以通过 `synchdb_state_view()` 实用命令检索:
+
+```
+postgres=# select name, last_dbz_offset from synchdb_state_view;
+ name | last_dbz_offset
+---------------+------------------------------------------------------------------------------------------------------
+ sqlserverconn | {"commit_lsn":"0000006a:00006608:0003","snapshot":true,"snapshot_completed":false}
+
+```
+
+我们应该定期保存这些值,这样如果遇到问题,我们就知道过去可以设置的偏移量位置,以恢复复制操作。
+
+### **暂停连接器**
+
+在设置新的偏移量值之前,连接器必须处于 `paused`(暂停)状态。
+
+使用 `synchdb_pause_engine()` SQL 函数暂停正在运行的连接器。这将停止 Debezium 运行引擎从异构数据库复制。当暂停时,可以使用 `synchdb_set_offset()` SQL 例程更改 Debezium 连接器的偏移量值,以从过去的特定点开始复制。它以 `conninfo_name` 作为参数,可以从 `synchdb_get_state()` 视图的输出中找到。
+
+例如:
+
+```sql
+SELECT synchdb_pause_engine('sqlserverconn');
+```
+
+### **设置新的偏移量**
+
+使用 `synchdb_set_offset()` SQL 函数更改连接器工作进程的起始偏移量。只有当连接器处于 `paused` 状态时才能执行此操作。该函数接受两个参数,`conninfo_name` 和 `有效的偏移量字符串`,这两个参数都可以从 `synchdb_get_state()` 视图的输出中找到。
+
+例如:
+
+```sql
+SELECT synchdb_set_offset('sqlserverconn', '{"commit_lsn":"0000006a:00006608:0003","snapshot":true,"snapshot_completed":false}');
+```
+
+### **恢复连接器**
+
+使用 `synchdb_resume_engine()` SQL 函数从暂停状态恢复 Debezium 操作。此函数以 `连接器名称` 作为其唯一参数,可以从 `synchdb_get_state()` 视图的输出中找到。恢复的 Debezium 运行引擎将从新设置的偏移量值开始复制。
+
+例如:
+
+```sql
+SELECT synchdb_resume_engine('sqlserverconn');
```
\ No newline at end of file
diff --git a/doc/docs/zh/user-guide/configure_infinispan.md b/doc/docs/zh/user-guide/configure_infinispan.md
deleted file mode 100644
index 4d9ec83..0000000
--- a/doc/docs/zh/user-guide/configure_infinispan.md
+++ /dev/null
@@ -1,130 +0,0 @@
-# 配置 Infinispan 的 Oracle 连接器
-
-## **概述**
-
-默认情况下,Debezium 的 Oracle 连接器使用 JVM 堆缓存传入的变更事件,然后再将它们传递给 SynchDB 进行处理。最大堆大小通过 `synchdb.jvm_max_heap_size` GUC 控制。当 JVM 堆内存不足时(尤其是在处理大型事务或包含大量列的模式时),连接器可能会出现 OutOfMemoryError 错误,这使得堆大小调整成为一项关键的调优挑战。
-
-作为替代方案,Debezium 可以配置使用 Infinispan 作为其缓存层。Infinispan 支持 JVM 堆和堆外(直接内存)的内存存储,从而提供更大的灵活性。此外,它还支持钝化功能,允许在达到内存限制时将多余的数据溢出到磁盘。这使得它在高负载下更具弹性,并确保能够优雅地处理大型事务或模式变更,而不会耗尽内存。
-
-## **`synchdb_add_infinispan()`**
-
-**签名:**
-
-```sql
-synchdb_add_infinispan(
- connectorName NAME, -- 连接器名称
- memoryType NAME, -- 内存类型,可以是“堆”或“非堆”
- memorySize INT -- 预留为缓存的内存大小(以 MB 为单位)
-)
-```
-
-为给定的连接器注册一个由 Infinispan 支持的缓存配置。这允许连接器使用 Infinispan 缓冲更改事件,并支持基于堆和堆外内存分配以及溢出到磁盘(钝化)。
-
-**注意:**
-
-- 如果在当前正在运行的连接器上调用,则该设置将在下次重启时生效。
-- 如果连接器已存在 Infinispan 缓存,它将被替换。
-- memoryType='off_heap' 使用本机(直接)内存,不受 JVM 堆限制,但应谨慎调整大小。
-- 当内存填满时,缓存将自动支持钝化到磁盘。
-
-**示例:**
-``` sql
-SELECT synchdb_add_infinispan('oracleconn', 'off_heap', 2048);
-
-```
-
-## **`synchdb_del_infinispan()`**
-
-**签名:**
-
-```sql
-synchdb_add_infinispan(
- connectorName NAME -- 连接器名称
-)
-```
-
-删除指定连接器的 Infinispan 缓存配置及其相关的磁盘元数据。此操作将删除:
-
-- 所有缓存文件
-- 所有钝化(溢出到磁盘)状态
-- 相关的 Infinispan 配置
-
-**注意:**
-
-- 此函数只能在连接器停止时执行。
-- 在连接器处于活动状态时尝试运行此函数将导致错误。
-- 永久禁用或重新配置连接器的缓存后端后,使用此命令进行清理。
-
-**Example:**
-``` sql
-SELECT synchdb_del_infinispan('oracleconn');
-
-```
-
-## **`钝化`**
-
-钝化简单来说就是,如果缓存已满,infinispan 会弹出并将数据写入磁盘。只要内存中有足够的空间来保存更改事件,就不会发生磁盘写入。数据将写入 `$PGDATA/pg_synchdb/ispn_[连接器名称]_[目标数据库名称]`
-
-## **用于测试 Infinispan 大型事务的 Oracle SQL 示例**
-
-**在 Oracle 中创建测试表:**
-
-```sql
-CREATE TABLE big_tx_test (
- id NUMBER PRIMARY KEY,
- payload VARCHAR2(4000),
- created DATE DEFAULT SYSDATE
-);
-
-```
-
-**创建一个相对较大的交易:**
-```sql
-BEGIN
- FOR i IN 1..100000 LOOP
- INSERT INTO big_tx_test (id, payload)
- VALUES (i, RPAD('x', 4000, 'x'));
- END LOOP;
- COMMIT;
-END;
-/
-
-```
-
-**大事务下的行为**
-
-未设置 infinispan + 低 JVM heap size (128)
-
-* --> 将发生 OutOfMemory 错误
-
-低 JVM heap size (128) + 高 infinispan heap size (2048)
-
-* --> 大型事务成功处理
-
-低 JVM heap size (128) + 低 infinispan heap size (128)
-
-* --> 将发生钝化
-* --> `ispn_[连接器名称]_[目标数据库名称]` 大小在处理过程中会增加,大型事务处理完成后会减小
-* --> 大型事务已成功处理,但速度较慢。
-
-低 JVM heap size (128) + 高 infinispan heap size (2048)
-
-* --> 将发生 OutOfMemory 错误
-* --> 请勿将 infinispan 配置 heap size 超过 JVM 最大 heap 内存
-
-较低的 JVM heap size (128) + 较低的 infinispan heap size (64)
-
-* --> 将发生钝化
-* --> `ispn_[连接器名称]_[目标数据库名称]` 的大小将在处理过程中增加,并在大型事务处理完成后减小。
-* --> 不建议使用,因为 infinispan 可能会占用一半的 JVM heap,而剩余空间可能不足以用于其他 Debezium 操作。
-
-低 JVM heap size (128) + 相同的 infinispan heap size (128)
-
-* --> 不建议使用,因为 infinispan 可能会占用所有 JVM 堆空间,最终导致 OutOfMemory 错误。
-
-高 JVM heap size (2048) + 低 infinispan heap size (128)
-
-* --> 将发生钝化。
-* --> `ispn_[连接器名称]_[目标数据库名称]` 的大小在处理过程中会增加,并在大型事务处理完成后减小。
-* --> 大型事务处理成功。
-* --> 效率低下 - 因为只有一小部分 JVM heap 空间用作缓存 + 不必要的钝化。
\ No newline at end of file
diff --git a/doc/docs/zh/user-guide/configure_olr.md b/doc/docs/zh/user-guide/configure_olr.md
deleted file mode 100644
index 6277217..0000000
--- a/doc/docs/zh/user-guide/configure_olr.md
+++ /dev/null
@@ -1,238 +0,0 @@
-# 为 Oracle 配置 Openlog Replicator
-
-## **概述**
-
-除了基于 LogMiner 的 Oracle 复制功能外,**SynchDB** 还支持使用 **Openlog Replicator (OLR)** 从 Oracle 数据库进行流式传输。SynchDB 支持两种类型的 Openlog Replicator:
-
-1. 基于 Debezium 的 Openlog Replicator
-2. 原生 Openlog Replicator(不通过 Debezium)- BETA 版
-
-这两种 Openlog Replicator 都需要根据以下设置示例进行配置,并在 SynchDB 进行流式传输之前连接到 Oracle。
-
-## **要求**
-
-- **Openlog Replicator 版本**:`1.3.0`(已验证与 Debezium 2.7.x 的兼容性)
-- 具有可供 OLR 访问的重做日志的 Oracle 实例
-- 必须为 OLR 授予额外权限。有关具体的权限要求,请参阅[此处](../../getting-started/remote_database_setups/)。
-- Openlog Replicator 必须已配置并正在运行
-- SynchDB 中现有的 Oracle 连接器(使用 `synchdb_add_conninfo()` 创建)
-
-有关通过 Docker 部署 Openlog Replicator 的详细信息,请参阅此[外部指南](https://highgo.atlassian.net/wiki/external/OTUzY2Q2OWFkNzUzNGVkM2EyZGIyMDE1YzVhMDdkNWE)。
-
-## **Openlog Replicator 配置示例**
-
-SynchDB 的 OLR 支持基于以下配置示例构建。
-
-**Version 1.3.0**
-```json
-{
- "version": "1.3.0",
- "source": [
- {
- "alias": "SOURCE",
- "name": "ORACLE",
- "reader": {
- "type": "online",
- "user": "DBZUSER",
- "password": "dbz",
- "server": "//ora19c:1521/FREE"
- },
- "format": {
- "type": "json",
- "column": 2,
- "db": 3,
- "interval-dts": 9,
- "interval-ytm": 4,
- "message": 2,
- "rid": 1,
- "schema": 7,
- "timestamp-all": 1,
- "scn-all": 1
- },
- "memory": {
- "min-mb": 64,
- "max-mb": 1024
- },
- "filter": {
- "table": [
- {"owner": "DBZUSER", "table": ".*"}
- ]
- },
- "flags": 32
- }
- ],
- "target": [
- {
- "alias": "SYNCHDB",
- "source": "SOURCE",
- "writer": {
- "type": "network",
- "uri": "0.0.0.0:7070"
- }
- }
- ]
-}
-
-```
-
-**Version 1.8.5**
-```json
-{
- "version": "1.8.5",
- "source": [
- {
- "alias": "SOURCE",
- "name": "ORACLE",
- "reader": {
- "type": "online",
- "user": "DBZUSER",
- "password": "dbz",
- "server": "//ora19c:1521/FREE"
- },
- "format": {
- "type": "json",
- "column": 2,
- "db": 3,
- "interval-dts": 9,
- "interval-ytm": 4,
- "message": 2,
- "rid": 1,
- "schema": 7,
- "timestamp-all": 1,
- "scn-type": 1
- },
- "memory": {
- "min-mb": 64,
- "max-mb": 1024,
- "swap-path": "/opt/OpenLogReplicator/olrswap"
- },
- "filter": {
- "table": [
- {"owner": "DBZUSER", "table": ".*"}
- ]
- },
- "flags": 32
- }
- ],
- "target": [
- {
- "alias": "DEBEZIUM",
- "source": "SOURCE",
- "writer": {
- "type": "network",
- "uri": "0.0.0.0:7070"
- }
- }
- ]
-}
-
-```
-
-请注意以下几点:
-
-- "source"."name": "ORACLE" -> 通过 `synchdb_add_olr_conninfo()` 定义 OLR 参数时,此字段应与 `olr_source` 值匹配(见下文)
-- "source"."reader"."user" -> 通过 `synchdb_add_conninfo()` 创建连接器时,此字段应与 `username` 值匹配
-- "source"."reader"."password" -> 通过 `synchdb_add_conninfo()` 创建连接器时,此字段应与 `password` 值匹配
-- "source"."reader"."server" -> 通过 `synchdb_add_conninfo()` 创建连接器时,此字段应包含 `hostname`、`port` 和 `source database` 的值
-- "source"."filter"."table":[] -> 这会过滤 Openlog Replicator 捕获的变更事件。<<<**重要**>>>:这是目前从 Oracle 过滤变更事件的唯一方法,因为 SynchDB 中的 OLR 实现目前不进行任何过滤。(通过 `synchdb_add_conninfo()` 创建连接器时,`table` 和 `snapshot table` 的值会被忽略。)
-- "format":{} -> 基于 Debezium 或原生 Openlog Replicator 连接器提取的特定 Paylod 格式。请按照指定的方式使用这些值。
-- “memory”.“swap-path” -> 这告诉 OLR 在内存不足的情况下将交换文件写入哪里。
-- "target".[0].."writer"."type": -> 必须指定 `network`,因为 Debezium 和原生 Openlog Replicator 连接器都通过网络与 Openlog Replicator 通信。
-- "target".[0].."writer"."uri": -> 这是 Openlog Replicator 监听的绑定主机和端口,SynchDB 应该能够在通过 `synchdb_add_olr_conninfo()` 定义 OLR 参数时通过 `olr_host` 和 `olr_port` 访问该主机和端口。
-
-## **`synchdb_add_conninfo()`**
-
-要创建**原生** OLR 连接器(使用 `type` = 'olr'):
-
-```sql
-SELECT synchdb_add_conninfo('olrconn',
- 'ora19c',
- 1521,
- 'DBZUSER',
- 'dbz',
- 'FREE',
- 'postgres',
- 'null',
- 'null',
- 'oracle');
-
-```
-
-要创建**基于 Debezium 的** OLR 连接器(使用 `type` = 'oracle'):
-
-```sql
-SELECT synchdb_add_conninfo('olrconn',
- 'ora19c',
- 1521,
- 'DBZUSER',
- 'dbz',
- 'FREE',
- 'postgres',
- 'null',
- 'null',
- 'olr');
-
-```
-
-<<<**重要**>>> **SynchDB 必须使用标志 (WITH_OLR=1) 进行编译和构建,以支持本机 openlog 复制器连接器。**
-
-更多关于创建连接器的信息,请访问[此处](../../user-guide/create_a_connector/)
-
-## **`synchdb_add_olr_conninfo()`**
-
-创建连接器后,用户可以为现有的 Oracle 连接器注册一个 Openlog Replicator 端点。
-
-**签名:**
-
-```sql
-synchdb_add_olr_conninfo(
- conn_name TEXT, -- 连接器名称
- olr_host TEXT, -- OLR 实例的主机名或 IP
- olr_port INT, -- OLR 公开的端口号(通常为 7070)
- olr_source TEXT -- OLR 中配置的 Oracle 源名称
-)
-```
-
-**示例:**
-
-这将指示 SynchDB 使用 Oracle 源标识符 ORACLE,从运行于 olrhost:7070 的 Openlog Replicator 实例流式传输连接器 `olrconn` 的变更。调用 `synchdb_start_engine_bgw` 启动此连接器。
-
-```sql
-SELECT synchdb_add_olr_conninfo('olrconn', 'olrhost', 7070, 'ORACLE');
-
-```
-
-## **synchdb_del_olr_conninfo**
-
-删除特定连接器的 OLR 配置,将其恢复为使用 LogMiner。
-
-**签名:**
-
-```sql
-synchdb_del_olr_conninfo(conn_name TEXT)
-
-```
-
-**示例:**
-
-此命令禁用 oracleconn 的 OLR 使用。使用 `synchdb_start_engine_bgw` 启动连接器将回退到默认的日志挖掘策略(基于 Debezium 的 OLR 连接器)。如果使用原生 Openlog Replicator 连接器,缺少 OLR 配置将导致连接器启动时出错。
-
-```sql
-SELECT synchdb_del_olr_conninfo('olrconn');
-
-```
-
-## **基于 Debezium 的 Openlog Replicator 连接器的行为说明**
-
-* 当 LogMiner 和 OLR 配置都存在时,SynchDB 默认使用 Openlog Replicator 进行变更捕获。
-* 如果 OLR 配置缺失,SynchDB 将使用日志挖掘策略来流式传输变更。
-* 修改 OLR 配置后,需要重新启动连接器。
-
-## **原生的 Openlog Replicator 连接器的行为说明**
-
-* 目前为 BETA 版本。
-* SynchDB 管理与 Openlog Replicator 的连接,并在不使用 Debezium 的情况下流式传输变更。
-* 需要 OLR 配置,否则连接器启动时会出错。
-* 依赖 Debezium 的 Oracle 连接器完成初始快照,并在完成后关闭,后续的 CDC 由 SynchDB 内部针对 Openlog Replicator 原生完成。
-* 依赖 IvorySQL 的 Oracle 解析器来处理 DDL 事件。在使用原生 openlog replicator 连接器之前,必须先编译并安装它。
-* 访问[此处](https://github.com/bersler/OpenLogReplicator) 了解有关 Openlog Replicator 的更多信息。
\ No newline at end of file
diff --git a/doc/docs/zh/user-guide/configure_snapshot_engine.md b/doc/docs/zh/user-guide/configure_snapshot_engine.md
index fc130b0..6702ec5 100644
--- a/doc/docs/zh/user-guide/configure_snapshot_engine.md
+++ b/doc/docs/zh/user-guide/configure_snapshot_engine.md
@@ -2,45 +2,55 @@
## **初始快照與變更資料擷取 (CDC)**
-初始快照是指將表格結構和初始資料從遠端資料庫遷移到 SynchDB 的過程。對於大多數連接器類型,此操作僅在首次啟動連接器時透過嵌入式 Debezium 運行器執行一次,因為只有 Debezium 引擎才能執行初始快照。初始快照完成後,變更資料擷取將開始將即時變更串流傳輸到 SynchDB。 「快照模式」可以進一步控制初始快照和 CDC 的行為。更多信息,請參閱[此處](../../user-guide/start_stop_connector/)。
+初始快照是指將表格結構和初始資料從遠端資料庫遷移到 SynchDB 的過程。對於大多數連接器類型,此程序僅在首次啟動連接器時透過嵌入式 Debezium 運行器執行一次,因為只有 Debezium 運行器才能執行初始快照。初始快照完成後,變更資料擷取將開始向 SynchDB 即時傳輸變更。 「快照模式」可以進一步控制初始快照和 CDC 的行為。有關更多信息,請參閱[此處](../../user-guide/start_stop_connector/)。
-除了基於 Debezium 的初始快照(當表數量眾多時可能會很慢)之外,SynchdB 還提供了另一個基於 FDW 的原生初始快照引擎。目前,只有原生 Openlog Replicator (OLR) 連接器支援基於 FDW 的快照。所有其他連接器仍然依賴 Debezium 來執行快照。
+SynchDB 支援兩種快照引擎,每種引擎支援多種連接器類型:
-## **基於 FDW 的初始快照**
+**基於 Debezium 的快照:**
-* 在 `postgresql.conf` 中將 "synchdb.olr_snapshot_engine" 設為 "fdw" 即可啟用。
-* 啟動需要快照的 OLR 連接器,並設定為快照模式。例如:
+* MySQL
+* SQL Server
+* Oracle
+* Openlog Replicator
-```sql
-SELECT synchdb_start_engine_bgw('olrconn', 'no_data');
+**基於 FDW 的快照:**
--- 或
-SELECT synchdb_start_engine_bgw('olrconn', 'always');
+* MySQL(使用 mysql_fdw)
+* Oracle(使用 oracle_fdw)
+* Openlog Replicator(使用 oracle_fdw)
+* Postgres(使用 postgres_fdw)
--- 或
-SELECT synchdb_start_engine_bgw('olrconn', 'schemasync');
+## **基於 Debezium 的初始快照**
-```
+這是預設的快照引擎(synchdb.olr_snapshot_engine='debezium'),它透過 JNI 依賴 Debezium 引擎來啟動快照過程。在大多數情況下,它都能正常工作,但如果快照中包含的表數量很多(數千個或更多),則可能會出現效能問題。 Debezium 首先會進行分析,存取每個表格一次以了解其結構並估算要快照的行數。此過程完全由單一工作流程完成,在此期間,引擎可能看似“掛起”,不會發出任何變更事件。對於大量表,此過程本身可能需要數小時才能完成。完成後,它將開始向 SynchDB 發送變更事件。
+
+在呼叫 `synchdb_start_engine_bgw()` 時自動觸發,快照模式要求執行快照,完成後不會再執行。
+
+## **基於 FDW 的初始快照**
-## **编译並安裝 oracle_fdw**
+* 在 `postgresql.conf` 中透過將「synchdb.olr_snapshot_engine」設為「fdw」來啟用。
+* 在呼叫 `synchdb_start_engine_bgw()` 時自動觸發,快照模式要求執行快照,完成後不會再執行。
+* 必須有對應的 FDW 可用。
-如果選擇 "fdw" 作為快照引擎,您需要確保相應的外部資料包裝器已安裝或可用於 synchdb。以下是從原始碼建置並安裝 oracle_fdw 的簡要步驟供您參考。
+## **Oracle 和 OLR 連接器的 FDW 快照**
+
+可以使用 oracle_fdw 為 Oracle 和 OLR 連接器執行初始快照,速度比 Debezium 的同類工具快得多。 SynchDB 整合了 [oracle_fdw](https://github.com/laurenz/oracle_fdw) 2.8.0 版本,其底層驅動程式為 OCI v23.9.0。這只是測試版本,更舊或更新的版本可能也適用。
### **安裝 OCI**
-建置和運行 oracle_fdw 需要 OCI。在此範例中,我使用的是 23.9.0 版本:
+建置和運行 oracle_fdw 需要 OCI。本範例使用的是 23.9.0 版本:
```bash
-# 取得預編譯軟體包:
+# Get the pre-build packages:
wget https://download.oracle.com/otn_software/linux/instantclient/2390000/instantclient-basic-linux.x64-23.9.0.25.07.zip
wget https://download.oracle.com/otn_software/linux/instantclient/2390000/instantclient-sdk-linux.x64-23.9.0.25.07.zip
-# 解壓縮:選擇「Y」以覆寫元資料文件
+# unzip them: Select 'Y' to overwrite metadata files
unzip instantclient-basic-linux.x64-23.9.0.25.07.zip
unzip instantclient-sdk-linux.x64-23.9.0.25.07.zip
```
-更新環境變量,以便系統知道在哪裡找到 OCI 頭檔和庫。
+更新環境變量,以便系統知道在哪裡可以找到 OCI 頭檔和庫。
```bash
export OCI_HOME=/home/$USER/instantclient_23_9
@@ -51,20 +61,20 @@ export PATH=$OCI_HOME:$PATH
```
-您可以將上述命令新增至 `~/.bashrc` 的末尾,以便每次登入系統時自動設定 PATH。
+您可以將上述命令新增至 `~/.bashrc` 檔案的末尾,以便在每次登入系統時自動設定 PATH 環境變數。
-您也可以將 $OCI_HOME 新增至 `/etc/ld.so.conf.d/x86_64-linux-gnu.conf`(以 Ubuntu 為例),作為尋找共用程式庫的新路徑。
+您也可以將 `$OCI_HOME` 新增至 `/etc/ld.so.conf.d/x86_64-linux-gnu.conf` 檔案(以 Ubuntu 為例),作為尋找共享庫的新路徑。
-您應該執行 ldconfig 命令,以便連結器知道在哪裡找到共用程式庫:
+您應該執行 `ldconfig` 命令,以便連結器知道在哪裡可以找到共用程式庫:
-### **建置 oracle_fdw 2.8.0**
+### **建置並安裝 oracle_fdw 2.8.0**
```bash
git clone https://github.com/laurenz/oracle_fdw.git --branch ORACLE_FDW_2_8_0
```
-透過調整 Makefile 中的以下兩行,確保 oracle_fdw 的 Makefile 能夠找到 OCI 包含檔案和函式庫:
+請確保 oracle_fdw 的 Makefile 可以找到 OCI 頭檔和函式庫,方法是調整 Makefile 中的這兩行:
```bash
FIND_INCLUDE := $(wildcard /usr/include/oracle/*/client64 /usr/include/oracle/*/client /home/$USER/instantclient_23_9/sdk/include)
@@ -72,7 +82,7 @@ FIND_LIBDIRS := $(wildcard /usr/lib/oracle/*/client64/lib /usr/lib/oracle/*/clie
```
-建置並安裝 oracle_fdw:
+建置並安裝oracle_fdw:
```bash
make PG_CONFIG=/usr/local/pgsql/bin/pg_config
@@ -80,6 +90,56 @@ sudo make install PG_CONFIG=/usr/local/pgsql/bin/pg_config
```
-Oralce_fdw 已準備就緒。
+oracle_fdw 已準備就緒。正常啟動連接器,並將 synchdb.olr_snapshot_engine 設定為 'fdw'。如果需要快照,SynchDB 將透過 FDW 完成。您無需在使用基於 FDW 的初始快照之前執行 `CREATE EXTENSION oracle_fdw`,也無需執行 `CREATE SERVER` 或 `CREATE USER MAPPING`。 SynchDB 在執行快照時會自動處理所有這些操作。
+
+## **MySQL 連接器的 FDW 快照**
+
+可以使用 mysql_fdw 為 MySQL 連接器執行初始快照,其速度遠遠超過 Debezium 的同類工具。 SynchDB 整合了 [mysql_fdw](https://github.com/EnterpriseDB/mysql_fdw) 2.9.3 版本,並以 libmysqlclient v8 作為其底層驅動程式。這只是經過測試的版本,更舊或更新的版本可能也適用。
+
+### **安裝 MySQL 用戶端開發套件**
+
+您可以從[此處](https://packages.debian.org/sid/libmysqlclient-dev)下載並安裝 MySQL 用戶端開發套件。如果您使用的是 Ubuntu 系統,則可以使用套件管理器進行安裝:
+
+```bash
+sudo apt update
+sudo apt install libmysqlclient-dev
+
+```
+
+### **建置並安裝 mysql_fdw 2.9.3**
+
+```bash
+git clone https://github.com/EnterpriseDB/mysql_fdw.git --branch REL-2_9_3
+
+```
+
+建置並安裝 mysql_fdw:
+
+```bash
+make PG_CONFIG=/usr/local/pgsql/bin/pg_config
+sudo make install PG_CONFIG=/usr/local/pgsql/bin/pg_config
+
+```
+
+mysql_fdw 已準備就緒。正常啟動連接器,並將 synchdb.olr_snapshot_engine 設定為 'fdw'。如果需要快照,SynchDB 將透過 FDW 完成。您無需在使用基於 FDW 的初始快照之前執行 `CREATE EXTENSION mysql_fdw`,也無需執行 `CREATE SERVER` 或 `CREATE USER MAPPING`。 SynchDB 會在執行快照時處理所有這些操作。
+
+## **Postgres 連接器的 FDW 快照**
+
+可以使用 postgres_fdw 為 Postgres 連接器執行初始快照,這比 Debezium 的同類方法速度快得多。 SynchDB 與基於 PostgreSQL 18 的 [postgres_fdw](https://github.com/postgres/postgres/tree/master/contrib/postgres_fdw) 整合。這只是經過測試的版本,更舊或更新的版本可能也適用。
+
+### **建置與安裝 postgres_fdw**
+
+```bash
+git clone https://github.com/postgres/postgres.git --branch REL_18_0
+cd postgres
+./configure
+make
+sudo make install
+
+cd contrib/postgres_fdw
+make
+sudo make install
+
+```
-**<<重要>>** 在使用基於 FDW 的初始快照之前,您無需執行“CREATE EXTENSION oracle_fdw”,也無需執行“CREATE SERVER”或“CREATE USER MAPPING”。 SynchDB 在執行快照時會處理所有這些操作。
\ No newline at end of file
+postgres_fdw 已準備就緒。正常啟動連接器,並將 synchdb.olr_snapshot_engine 設定為 'fdw'。如果需要快照,SynchDB 將透過 FDW 完成。您無需在使用基於 FDW 的初始快照之前執行 `CREATE EXTENSION postgres_fdw`,也無需執行 `CREATE SERVER` 或 `CREATE USER MAPPING`。 SynchDB 在執行快照時會自動處理所有這些操作。
\ No newline at end of file
diff --git a/doc/docs/zh/user-guide/create_a_connector.md b/doc/docs/zh/user-guide/create_a_connector.md
index 74c2480..9f9fdab 100644
--- a/doc/docs/zh/user-guide/create_a_connector.md
+++ b/doc/docs/zh/user-guide/create_a_connector.md
@@ -2,7 +2,7 @@
## **创建连接器**
-连接器代表与特定源数据库的连接,复制一组表并应用于 PostgreSQL。如果您有多个需要复制的源数据库,则需要多个连接器(每个连接器一个)。也可以创建多个连接到同一源数据库但复制不同表集的连接器。
+连接器代表与特定源数据库的连接,复制一组表并应用于 PostgreSQL。如果您有多个需要复制的源数据库,则需要多个连接器(每个连接器一个)。也可以创建多个连接到同一源数据库但复制不同或相同表集的连接器。
可以使用实用 SQL 函数 `synchdb_add_conninfo()` 创建连接器。
@@ -15,22 +15,23 @@ synchdb_add_conninfo 接受以下参数:
| port | 连接到异构数据库的端口号。|
| username | 用于与异构数据库进行身份验证的用户名。|
| password | 用于验证用户名的密码 |
-| 源数据库 | 这是我们要从中复制更改的异构数据库中的源数据库的名称。|
-| 目标数据库 | (已弃用)始终默认使用与 synchDB 安装位置相同的数据库 |
-| 表 |(可选)- 以 `[database].[table]` 或 `[database].[schema].[table]` 的形式表示,该参数必须存在于异构数据库中,因此引擎将仅复制指定的表。如果留空,则复制所有表。或者,可以使用 `file:` 前缀指定表列表文件 |
-| 快照表 |(可选)- 以 `[database].[table]` 或 `[database].[schema].[table]` 的形式表示,该参数必须存在于上述 `table` 设置中,因此引擎仅在快照模式设置为 `always` 时才会重建这些表的快照。如果留空或为 null,则当快照模式设置为 `always` 时,将重建上述 `table` 设置中指定的所有表。或者,可以使用 `file:` 前缀指定快照表列表文件 |
-| 连接器 | 要使用的连接器类型(如下)。|
+| source database | 这是我们要从中复制更改的异构数据库中的源数据库的名称。|
+| source schema | 這是來源資料庫中來源模式的名稱,我們要從中複製變更。 |
+| table |(可选)- 以 `[database].[table]` 或 `[database].[schema].[table]` 的形式表示,该参数必须存在于异构数据库中,因此引擎将仅复制指定的表。如果留空,则复制所有表。或者,可以使用 `file:` 前缀指定表列表文件 |
+| snapshot table |(可选)- 以 `[database].[table]` 或 `[database].[schema].[table]` 的形式表示,该参数必须存在于上述 `table` 设置中,因此引擎仅在快照模式设置为 `always` 时才会重建这些表的快照。如果留空或为 null,则当快照模式设置为 `always` 时,将重建上述 `table` 设置中指定的所有表。或者,可以使用 `file:` 前缀指定快照表列表文件 |
+| connector | 要使用的连接器类型(如下)。|
-<<**注意**>> 如果連接器類型為“olr”,SynchDB 仍將使用 Debezium 執行初始快照,初始快照包含“table”和“snapshot table”參數中指定的表和快照表。完成後,SynchDB 將連接到 Openlog Replicator 進行複製,而不會過濾「table」參數中指定的所需表。表過濾是在 Openlog Replicator 的配置中完成的。因此,請確保 Openlog Replicator 和 SynchDB 連接器的「table」過濾參數配置一致,以避免潛在的差異。
+<<**注意**>> `來源資料庫`、`來源模式`、`使用者名稱`、`密碼`、`表`和`快照表`區分大小寫,您必須按照來源資料庫中的名稱準確指定它們,因此請記住這些名稱的字母大小寫。
## **连接器类型**
SynchDb 支持以下连接器类型:
-* mysql -> MySQL 数据库
-* sqlserver -> Microsoft SQL Server 数据库
-* oracle -> Oracle 数据库
-* olr -> 原生 Openlog Replicator (BETA)
+* mysql -> MySQL 数据库
+* sqlserver -> Microsoft SQL Server 数据库
+* oracle -> Oracle 数据库
+* olr -> 原生 Openlog Replicator
+* postgres -> PostgreSQL 数据库
## **检查已创建的连接器**
@@ -44,15 +45,15 @@ postgres=# select * from synchdb_conninfo;
-[ RECORD 1 ]-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
name | sqlserverconn
isactive | t
-data | {"pwd": "\\xc30d0407030245ca4a983b6304c079d23a0191c6dabc1683e4f66fc538db65b9ab2788257762438961f8201e6bcefafa60460fbf441e55d844e7f27b31745f04e7251c0123a159540676c4", "port": 1433, "user": "sa", "dstdb": "postgres", "srcdb": "testDB", "table": "null", "hostname": "192.168.1.86", "connector": "sqlserver"}
+data | {"pwd": "\\xc30d0407030245ca4a983b6304c079d23a0191c6dabc1683e4f66fc538db65b9ab2788257762438961f8201e6bcefafa60460fbf441e55d844e7f27b31745f04e7251c0123a159540676c4", "port": 1433, "user": "sa", "srcschema": "dbo", "srcdb": "testDB", "table": null, "snapshottable": null, "hostname": "192.168.1.86", "connector": "sqlserver"}
-[ RECORD 2 ]-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
name | mysqlconn
isactive | t
-data | {"pwd": "\\xc30d04070302986aff858065e96b62d23901b418a1f0bfdf874ea9143ec096cd648a1588090ee840de58fb6ba5a04c6430d8fe7f7d466b70a930597d48b8d31e736e77032cb34c86354e", "port": 3306, "user": "mysqluser", "dstdb": "postgres", "srcdb": "inventory", "table": "null", "hostname": "192.168.1.86", "connector": "mysql"}
+data | {"pwd": "\\xc30d04070302986aff858065e96b62d23901b418a1f0bfdf874ea9143ec096cd648a1588090ee840de58fb6ba5a04c6430d8fe7f7d466b70a930597d48b8d31e736e77032cb34c86354e", "port": 3306, "user": "mysqluser", "srcschema": null, "srcdb": "inventory", "table": null, "snapshottable": null, "hostname": "192.168.1.86", "connector": "mysql"}
-[ RECORD 3 ]-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
name | oracleconn
isactive | t
-data | {"pwd": "\\xc30d04070302e3baf1293d0d553066d234014f6fc52e6eea425884b1f65f1955bf504b85062dfe538ca2e22bfd6db9916662406fc45a3a530b7bf43ce4cfaa2b049a1c9af8", "port": 1528, "user": "c##dbzuser", "dstdb": "postgres", "srcdb": "FREE", "table": "null", "hostname": "192.168.1.86", "connector": "oracle"}
+data | {"pwd": "\\xc30d04070302e3baf1293d0d553066d234014f6fc52e6eea425884b1f65f1955bf504b85062dfe538ca2e22bfd6db9916662406fc45a3a530b7bf43ce4cfaa2b049a1c9af8", "port": 1528, "user": "DBZUSER", "srcschema": "DBZUSER", "srcdb": "FREE", "table": null, "snapshottable": null, "hostname": "192.168.1.86", "connector": "oracle"}
```
@@ -67,15 +68,15 @@ data | {"pwd": "\\xc30d04070302e3baf1293d0d553066d234014f6fc52e6eea425884b1f
{
"table_list":
[
- "mydb.myschema.mytable1",
- "mydb.myschema.mytable2",
+ "myschema.mytable1",
+ "myschema.mytable2",
...
...
],
"snapshot_table_list":
[
- "mydb.myschema.mytable1",
- "mydb.myschema.mytable2",
+ "myschema.mytable1",
+ "myschema.mytable2",
...
...
]
@@ -94,29 +95,29 @@ SynchDB 通过名称查找以下关键 JSON 数组:
## **示例:为每个支持的源数据库创建一个连接器以复制所有表**
-1. 创建一个名为“mysqlconn”的 MySQL 连接器,将 MySQL 中“inventory”下的所有表复制到 PostgreSQL 中目标数据库“postgres”:
+1. 建立一個名為 `mysqlconn` 的 MySQL 連接器,用於複製 MySQL 中 `inventory` 下的所有表。來源模式可以設定為 'null',因為 MySQL 不支援空值。
```sql
SELECT synchdb_add_conninfo(
'mysqlconn', '127.0.0.1', 3306, 'mysqluser',
- 'mysqlpwd', 'inventory', 'postgres',
+ 'mysqlpwd', 'inventory', 'null',
'null', 'null', 'mysql');
```
-2. 创建一个名为“sqlserverconn”的SQLServer连接器,将“testDB”下的所有表复制到PostgreSQL中的目标数据库“postgres”:
+2. 建立一個名為 `sqlserver conn` 的 SQL Server 連接器,以複製 `testDB` 資料庫和 `dbo` 架構下的所有資料表。
```sql
SELECT
synchdb_add_conninfo(
'sqlserverconn', '127.0.0.1', 1433,
- 'sa', 'Password!', 'testDB', 'postgres',
+ 'sa', 'Password!', 'testDB', 'dbo',
'null', 'null', 'sqlserver');
```
-3. 创建一个名为“oracleconn”的 Oracle 连接器,将“FREE”下的所有表复制到 PostgreSQL 中的目标数据库“postgres”:
+3. 建立一個名為 `oracleconn` 的 Oracle 連接器,用於複製 `FREE` 資料庫和 `DBZUSER` 模式下的所有表:
```sql
SELECT
synchdb_add_conninfo(
'oracleconn', '127.0.0.1', 1521,
- 'c##dbzuser', 'dbz', 'FREE', 'postgres',
+ 'DBZUSER', 'dbz', 'FREE', 'DBZUSER',
'null', 'null', 'oracle');
```
@@ -128,7 +129,7 @@ SELECT
```sql
SELECT synchdb_add_conninfo(
'mysqlconn', '127.0.0.1', 3306, 'mysqluser',
- 'mysqlpwd', 'inventory', 'postgres',
+ 'mysqlpwd', 'inventory', 'null',
'inventory.orders,inventory.customers', 'null', 'mysql');
```
@@ -139,7 +140,7 @@ SELECT synchdb_add_conninfo(
```sql
SELECT synchdb_add_conninfo(
'mysqlconn', '127.0.0.1', 3306, 'mysqluser',
- 'mysqlpwd', 'inventory', 'postgres',
+ 'mysqlpwd', 'inventory', 'null',
'file:/path/to/mytablefile.json', 'file:/path/to/mytablefile.json', 'mysql');
```
diff --git a/doc/docs/zh/user-guide/customize_transform.md b/doc/docs/zh/user-guide/customize_transform.md
deleted file mode 100644
index ed6f192..0000000
--- a/doc/docs/zh/user-guide/customize_transform.md
+++ /dev/null
@@ -1 +0,0 @@
-# Customize Transformation Rules
\ No newline at end of file
diff --git a/doc/docs/zh/user-guide/default_datatype_mapping.md b/doc/docs/zh/user-guide/default_datatype_mapping.md
index cae73b4..8c3e1ae 100644
--- a/doc/docs/zh/user-guide/default_datatype_mapping.md
+++ b/doc/docs/zh/user-guide/default_datatype_mapping.md
@@ -19,9 +19,15 @@ weight: 50
DatatypeHashEntry mysql_defaultTypeMappings[] =
{
{{"int", true}, "serial", 0},
+ {{"int unsigned", true}, "serial", 0},
{{"bigint", true}, "bigserial", 0},
+ {{"bigint unsigned", true}, "bigserial", 0},
{{"smallint", true}, "smallserial", 0},
+ {{"smallint unsigned", true}, "smallserial", 0},
{{"mediumint", true}, "serial", 0},
+ {{"mediumint unsigned", true}, "serial", 0},
+ {{"tinyint", true}, "smallserial", 0},
+ {{"tinyint unsigned", true}, "smallserial", 0},
{{"enum", false}, "text", 0},
{{"set", false}, "text", 0},
{{"bigint", false}, "bigint", 0},
@@ -62,22 +68,21 @@ DatatypeHashEntry mysql_defaultTypeMappings[] =
{{"mediumblob", false}, "bytea", 0},
{{"longblob", false}, "bytea", 0},
{{"tinyblob", false}, "bytea", 0},
- {{"long varchar", false}, "text", -1},
- {{"longtext", false}, "text", -1},
- {{"mediumtext", false}, "text", -1},
- {{"tinytext", false}, "text", -1},
+ {{"long varchar", false}, "text", 0},
+ {{"longtext", false}, "text", 0},
+ {{"mediumtext", false}, "text", 0},
+ {{"tinytext", false}, "text", 0},
{{"json", false}, "jsonb", -1},
- {{"geometry", false}, "text", -1},
- {{"geometrycollection", false}, "text", -1},
- {{"geomcollection", false}, "text", -1},
- {{"linestring", false}, "text", -1},
- {{"multilinestring", false}, "text", -1},
- {{"multipoint", false}, "text", -1},
- {{"multipolygon", false}, "text", -1},
- {{"point", false}, "text", -1},
- {{"polygon", false}, "text", -1}
+ {{"geometry", false}, "text", 0},
+ {{"geometrycollection", false}, "text", 0},
+ {{"geomcollection", false}, "text", 0},
+ {{"linestring", false}, "text", 0},
+ {{"multilinestring", false}, "text", 0},
+ {{"multipoint", false}, "text", 0},
+ {{"multipolygon", false}, "text", 0},
+ {{"point", false}, "text", 0},
+ {{"polygon", false}, "text", 0}
};
-
```
## **SQL Server 默认数据类型映射**
@@ -205,4 +210,81 @@ DatatypeHashEntry oracle_defaultTypeMappings[] =
{{"anydata", false}, "text", 0},
{{"anydataset", false}, "text", 0},
};
+```
+
+## **Postgres 默认数据类型映射**
+
+```c
+DatatypeHashEntry postgres_defaultTypeMappings[] =
+{
+ {{"bigint", false}, "bigint", 0},
+ {{"bigserial", false}, "bigserial", 0},
+ {{"bigserial", true}, "bigserial", 0},
+ {{"bit", false}, "bit", -1},
+ {{"bit varying", false}, "bit varying", -1},
+ {{"bool", false}, "bool", 0},
+ {{"boolean", false}, "boolean", 0},
+ {{"box", false}, "box", 0},
+ {{"bytea", false}, "bytea", 0},
+ {{"char", false}, "char", -1},
+ {{"character", false}, "character", -1},
+ {{"character varying", false}, "character varying", -1},
+ {{"cidr", false}, "cidr", 0},
+ {{"circle", false}, "circle", 0},
+ {{"date", false}, "date", 0},
+ {{"decimal", false}, "dedcimal", -1},
+ {{"double precision", false}, "double precision", 0},
+ {{"float", false}, "float", 0},
+ {{"float4", false}, "float4", 0},
+ {{"float8", false}, "float8", 0},
+ {{"inet", false}, "inet", 0},
+ {{"int", false}, "int", 0},
+ {{"int2", false}, "int2", 0},
+ {{"int4", false}, "int4", 0},
+ {{"int8", false}, "int8", 0},
+ {{"integer", false}, "integer", 0},
+ {{"interval", false}, "interval", -1},
+ {{"json", false}, "json", 0},
+ {{"jsonb", false}, "jsonb", 0},
+ {{"line", false}, "line", 0},
+ {{"lseg", false}, "lseg", 0},
+ {{"macaddr", false}, "macaddr", 0},
+ {{"macaddr8", false}, "macaddr8", 0},
+ {{"money", false}, "money", 0},
+ {{"numeric", false}, "numeric", -1},
+ {{"path", false}, "path", 0},
+ {{"pg_lsn", false}, "pg_lsn", 0},
+ {{"pg_snapshot", false}, "pg_snapshot", 0},
+ {{"point", false}, "point", 0},
+ {{"polygon", false}, "polygon", 0},
+ {{"real", false}, "real", 0},
+ {{"smallint", false}, "smallint", 0},
+ {{"smallserial", false}, "smallserial", 0},
+ {{"smallserial", true}, "smallserial", 0},
+ {{"serial", false}, "serial", 0},
+ {{"serial", true}, "serial", 0},
+ {{"serial2", false}, "serial2", 0},
+ {{"serial2", true}, "serial2", 0},
+ {{"serial4", false}, "serial4", 0},
+ {{"serial4", true}, "serial4", 0},
+ {{"serial8", false}, "serial8", 0},
+ {{"serial8", true}, "serial8", 0},
+ {{"text", false}, "text", 0},
+ {{"time without time zone", false}, "time without time zone", -1},
+ {{"time with time zone", false}, "time with time zone", -1},
+ {{"time", false}, "time", -1},
+ {{"timetz", false}, "timetz", -1},
+ {{"timestamp without time zone", false}, "timestamp without time zone", -1},
+ {{"timestamp with time zone", false}, "timestamp with time zone", -1},
+ {{"timestamp", false}, "timestamp", -1},
+ {{"timestamptz", false}, "timestamptz", -1},
+ {{"tsquery", false}, "tsquery", 0},
+ {{"tsvector", false}, "tsvector", 0},
+ {{"txid_snapshot", false}, "txid_snapshot", 0},
+ {{"uuid", false}, "uuid", 0},
+ {{"varbit", false}, "varbit", -1},
+ {{"varchar", false}, "varchar", -1},
+ {{"xml", false}, "xml", 0},
+ /* ... */
+};
```
\ No newline at end of file
diff --git a/doc/docs/zh/user-guide/letter_casing_strategy.md b/doc/docs/zh/user-guide/letter_casing_strategy.md
new file mode 100644
index 0000000..08c4222
--- /dev/null
+++ b/doc/docs/zh/user-guide/letter_casing_strategy.md
@@ -0,0 +1,33 @@
+# 字母大小寫策略
+
+## 設定字母大小寫策略
+
+字母大小寫策略決定了 SynchDB 在將來源物件名稱套用到目標資料庫之前應如何標準化。 MySQL、SQL Server 和 PostgreSQL 預設將所有物件名稱轉換為小寫字母,而 Oracle 預設轉換為大寫字母。 MySQL、Oracle 和 PostgreSQL 允許物件名稱包含大小寫字母混合,並將每種變體視為不同的名稱,而 SQL Server 則將它們視為相同的名稱。
+
+可以使用 `synchdb.letter_casing_strategy` GUC 參數來告訴 SynchDB 如何處理物件名稱,其值如下:
+
+* lowercase:將所有物件名稱(表名和列名)標準化為小寫字母
+
+* uppercase:將所有物件名稱(表名和列名)規範化為大寫字母
+
+* asis:不進行規範化,保持物件名稱(表名和列名)不變。
+
+<<重要>> synchdb.letter_casing_strategy 不會影響資料型別名稱。在 SynchDB 中,資料類型名稱始終規範化為小寫字母。像 SQL Server 和 Oracle Express 這樣的連接器使用大寫字母作為資料類型,因此 SynchDB 會將其儲存和顯示為小寫。
+
+## 字母大小寫策略如何影響轉換
+
+您可能想知道,如果 SynchDB 根據 `synchdb.letter_casing_strategy` 對物件名稱進行規範化,那麼如何正確配置 [物件轉換](../../user-guide/object_mapping_rules/) 以識別要轉換的外部表或列?
+
+物件轉換會識別來源資料庫中用於轉換的原始名稱,因此您必須按照來源資料庫中的名稱配置物件名稱,而不是 SynchDB 規範化後的名稱。
+
+如果找到匹配項,SynchDB 將優先使用物件轉換識別出的新值,而不會根據字母大小寫策略對其進行規範化。當沒有為物件定義特定的轉換規則時,就會發生規範化。
+
+例如,對於 Oracle 資料庫“FREE”下模式“DBZUSER”中的表“TEST_TABLE”,假設我們要將其對應到 PostgreSQL 中的“MY_TEST_TABLE”(全部大寫),而目前的 synchdb.letter_casing_strategy 設定為“lowercase”。您可以這樣寫轉換規則:
+
+```sql
+
+SELECT synchdb_add_objmap('mysqlconn','table','FREE.DBZUSER.TEST_TABLE','MY_TEST_TABLE');
+
+```
+
+由於我們已經為「FREE.DBZUSER.TEST_TABLE」定義了轉換規則,因此該轉換規則將優先執行,並按照指示將其轉換為「MY_TEST_TABLE」。字母大小寫策略(lowercase)不會將其標準化為小寫。
\ No newline at end of file
diff --git a/doc/docs/zh/user-guide/secured_connection.md b/doc/docs/zh/user-guide/secured_connection.md
deleted file mode 100644
index f6706ea..0000000
--- a/doc/docs/zh/user-guide/secured_connection.md
+++ /dev/null
@@ -1,31 +0,0 @@
-# 安全连接
-
-## **配置安全连接**
-
-为了确保与远程数据库的连接安全,我们需要为 `synchdb_add_conninfo` 创建的连接器配置额外的 SSL 相关参数。SSL 证书和私钥必须打包为 Java 密钥库文件,并附带密码。这些信息随后会通过 synchdb_add_extra_conninfo() 传递给 SynchDB。
-
-<<**重要提示**>> Openlog Replicator 連接器不支援安全連接
-
-## **synchdb_add_extra_conninfo**
-
-**用途**:为 `synchdb_add_conninfo` 创建的现有连接器配置额外的连接器参数
-
-| 参数 | 描述 | 必需 | 示例 | 备注 |
-|:-:|:-|:-:|:-|:-|
-| `name` | 此连接器的唯一标识符 | ✓ | `'mysqlconn'` | 必须在所有连接器中唯一 |
-| `ssl_mode` | SSL 模式 | ☐ | `'verify_ca'` |可以是以下之一:
- “disabled”- 不使用 SSL。
- “preferred”- 如果服务器支持,则使用 SSL。
- “required”- 必须使用 SSL 建立连接。
- “verify_ca”- 连接器与服务器建立 TLS,并将根据配置的信任库验证服务器的 TLS 证书。
- “verify_identity”- 与 verify_ca 行为相同,但它还会检查服务器证书的通用名称以匹配系统的主机名。|
-| `ssl_keystore` | 密钥库路径 | ☐ | `/path/to/keystore` | 密钥库文件的路径 |
-| `ssl_keystore_pass` | 密钥库密码 | ☐ | `'mykeystorepass'` | 访问密钥库文件的密码 |
-| `ssl_truststore` | 信任库路径 | ☐ | `'/path/to/truststore'` | 信任库文件路径 |
-| `ssl_truststore_pass` | 信任库密码 | ☐ | `'mytruststorepass'` | 访问信任库文件的密码 |
-
-```sql
-SELECT synchdb_add_extra_conninfo('mysqlconn', 'verify_ca', '/path/to/keystore', 'mykeystorepass', '/path/to/truststore', 'mytruststorepass');
-```
-
-## **synchdb_del_extra_conninfo**
-
-**用途**:删除由 `synchdb_add_extra_conninfo` 创建的额外连接器参数
-```sql
-SELECT synchdb_del_extra_conninfo('mysqlconn');
-```
\ No newline at end of file
diff --git a/doc/docs/zh/user-guide/set_offset.md b/doc/docs/zh/user-guide/set_offset.md
deleted file mode 100644
index 0bbb071..0000000
--- a/doc/docs/zh/user-guide/set_offset.md
+++ /dev/null
@@ -1,53 +0,0 @@
----
-weight: 100
----
-# 自定义起始偏移量值
-
-起始偏移量值代表开始复制的点,类似于 PostgreSQL 的恢复 LSN。当 Debezium 运行引擎启动时,它将从这个偏移量值开始复制。将此偏移量值设置为较早的值将导致 Debezium 运行引擎从较早的记录开始复制,可能会复制重复的数据记录。在设置 Debezium 的起始偏移量值时,我们应该格外谨慎。
-
-## **记录可设置的偏移量值**
-
-在操作过程中,Debezium 运行引擎将生成新的偏移量并将其刷新到磁盘。最后刷新的偏移量可以通过 `synchdb_state_view()` 实用命令检索:
-```
-postgres=# select name, last_dbz_offset from synchdb_state_view;
- name | last_dbz_offset
----------------+------------------------------------------------------------------------------------------------------
- sqlserverconn | {"commit_lsn":"0000006a:00006608:0003","snapshot":true,"snapshot_completed":false}
- mysqlconn | {"ts_sec":1741301103,"file":"mysql-bin.000009","pos":574318212,"row":1,"server_id":223344,"event":2}
- oracleconn | {"commit_scn":"2311579","snapshot_scn":"2311578","scn":"2311578"}
-(3 rows)
-
-```
-
-根据连接器类型的不同,这个偏移量值也不同。从上面的示例中,`mysql` 连接器的最后刷新偏移量是 `{"ts_sec":1741301103,"file":"mysql-bin.000009","pos":574318212,"row":1,"server_id":223344,"event":2}`,而 `sqlserver` 的最后刷新偏移量是 `{"commit_lsn":"0000006a:00006608:0003","snapshot":true,"snapshot_completed":false}`。
-
-我们应该定期保存这些值,这样如果遇到问题,我们就知道过去可以设置的偏移量位置,以恢复复制操作。
-
-## **暂停连接器**
-
-在设置新的偏移量值之前,连接器必须处于 `paused`(暂停)状态。
-
-使用 `synchdb_pause_engine()` SQL 函数暂停正在运行的连接器。这将停止 Debezium 运行引擎从异构数据库复制。当暂停时,可以使用 `synchdb_set_offset()` SQL 例程更改 Debezium 连接器的偏移量值,以从过去的特定点开始复制。它以 `conninfo_name` 作为参数,可以从 `synchdb_get_state()` 视图的输出中找到。
-
-例如:
-```
-SELECT synchdb_pause_engine('mysqlconn');
-```
-
-## **设置新的偏移量**
-
-使用 `synchdb_set_offset()` SQL 函数更改连接器工作进程的起始偏移量。只有当连接器处于 `paused` 状态时才能执行此操作。该函数接受两个参数,`conninfo_name` 和 `有效的偏移量字符串`,这两个参数都可以从 `synchdb_get_state()` 视图的输出中找到。
-
-例如:
-```
-SELECT synchdb_set_offset('mysqlconn', '{"ts_sec":1741301103,"file":"mysql-bin.000009","pos":574318212,"row":1,"server_id":223344,"event":2}');
-```
-
-## **恢复连接器**
-
-使用 `synchdb_resume_engine()` SQL 函数从暂停状态恢复 Debezium 操作。此函数以 `连接器名称` 作为其唯一参数,可以从 `synchdb_get_state()` 视图的输出中找到。恢复的 Debezium 运行引擎将从新设置的偏移量值开始复制。
-
-例如:
-```
-SELECT synchdb_resume_engine('mysqlconn');
-```
\ No newline at end of file
diff --git a/doc/docs/zh/user-guide/start_stop_connector.md b/doc/docs/zh/user-guide/start_stop_connector.md
index fe80065..e6d2e03 100644
--- a/doc/docs/zh/user-guide/start_stop_connector.md
+++ b/doc/docs/zh/user-guide/start_stop_connector.md
@@ -33,8 +33,6 @@ SELECT synchdb_start_engine_bgw('mysqlconn', 'always');
| `initial_only` | 一次性快照,然后停止 | 数据迁移 |
| `no_data` | 仅结构,无数据 | 结构同步 |
| `never` | 跳过快照,仅流式传输 | 实时更新 |
-| `recovery` | 从源重建 | 灾难恢复 |
-| `when_needed` | 条件快照 | 自动恢复 |
| `schemasync` | 仅结构,无数据,无 CDC | 正常操作 |
**请参阅[教程](../../tutorial/selective_table_sync/),了解何时使用何种模式**
diff --git a/doc/docs/zh/user-guide/utility_functions.md b/doc/docs/zh/user-guide/utility_functions.md
deleted file mode 100644
index 9f28e95..0000000
--- a/doc/docs/zh/user-guide/utility_functions.md
+++ /dev/null
@@ -1,383 +0,0 @@
----
-weight: 110
----
-# 函数参考
-
-此页面记录了 SynchDB 添加的所有 SQL 函数/视图。
-
-## **连接器管理**
-
-### **synchdb_add_conninfo**
-
-**用途**: 创建新的连接器配置
-
-**参数**:
-
-| 参数 | 说明 | 必填 | 示例 | 注意事项 |
-|:-:|:-|:-:|:-|:-|
-| `name` | 此连接器的唯一标识符 | ✓ | `'mysqlconn'` | 必须在所有连接器中唯一 |
-| `hostname` | 异构数据库的IP地址或主机名 | ✓ | `'127.0.0.1'` | 支持IPv4、IPv6和主机名 |
-| `port` | 数据库连接端口号 | ✓ | `3306` | 默认值: MySQL(3306), SQLServer(1433) |
-| `username` | 身份验证用户名 | ✓ | `'mysqluser'` | 需要适当的权限 |
-| `password` | 身份验证密码 | ✓ | `'mysqlpwd'` | 安全存储 |
-| `source database` | 源数据库名称 | ✓ | `'inventory'` | 必须存在于源系统中 |
-| `destination database` | 目标PostgreSQL数据库 | ✓ | `'postgres'` | (已弃用)将始终调整为 SynchDB 安装的同一数据库 |
-| `table` | 表规范模式 | ☐ | `'[db].[table]'` | 空=复制所有表,支持正则表达式(例如,mydb.testtable*),使用 `file:` 前缀使连接器从 JSON 文件读取表列表(例如,file:/path/to/filelist.json)。文件格式见下文 |
-| `connector` | 连接器类型(`mysql`/`sqlserver`) | ✓ | `'mysql'` | 参见上述支持的连接器 |
-
-**Table列表文件示例**:
-```json
-{
- "table_list":
- [
- "mydb.table1",
- "mydb.table2",
- "mydb.table3",
- "mydb.table4"
- ]
-}
-```
-
-**使用示例**:
-```sql
--- MySQL 示例
-SELECT synchdb_add_conninfo(
- 'mysqlconn', -- 连接器名称
- '127.0.0.1', -- 主机
- 3306, -- 端口
- 'mysqluser', -- 用户名
- 'mysqlpwd', -- 密码
- 'inventory', -- 源数据库
- 'postgres', -- 目标数据库
- '', -- 表(空表示全部)
- 'mysql', -- 连接器类型
- 'myrule.json' -- 规则文件
-);
-
--- SQL Server 示例
-SELECT synchdb_add_conninfo(
- 'sqlserverconn',
- '127.0.0.1',
- 1433,
- 'sa',
- 'MyPassword123',
- 'testDB',
- 'postgres',
- 'dbo.orders', -- 指定表
- 'sqlserver',
- 'mssql_rules.json'
-);
-
--- Oracle 示例
-SELECT synchdb_add_conninfo(
- 'oracleconn',
- '127.0.0.1',
- 1521,
- 'c##dbzuser',
- 'dbz',
- 'mydb',
- 'postgres',
- '', -- all tables
- 'oracle'
-);
-```
-
-### **synchdb_add_objmap**
-
-**目的**:为每个连接器添加一个对象映射规则
-
-| 参数 | 说明 | 必需 | 示例 | 注释 |
-|:-:|:-:|:-:|:-|:-|
-| `name` | 此连接器的唯一标识符 | ✓ | `'mysqlconn'` | 必须在所有连接器中唯一 |
-| `object type` | 对象映射的类型 | ✓ | `'table'` | 可以是 `table` 以映射表名、`column` 以映射列名、`datatype` 以映射数据类型或 `transform` 以运行数据转换表达式 |
-| `source object` | 以完全限定名称表示的源对象 | ✓ | `inventory.customers` | 远程数据库中表示的对象名称 |
-| `destination object` | 目标对象名称 | ✓ | `'schema1.people'` | PostgreSQL 端的目标对象名称。可以是完全限定的表名、列名、数据类型或转换表达式 |
-
-```sql
-SELECT synchdb_add_objmap('mysqlconn','table','inventory.customers','schema1.people');
-SELECT synchdb_add_objmap('mysqlconn','column','inventory.customers.email','contact');
-SELECT synchdb_add_objmap('mysqlconn','datatype','point|false','text|0');
-SELECT synchdb_add_objmap('mysqlconn','datatype','inventory.geom.g','geometry|0');
-SELECT synchdb_add_objmap('mysqlconn','transform','inventory.products.name','''>>>>'' || ''%d'' || ''<<<<<''');
-```
-**表示 `table` 映射的方式:**
-* `source object` 表示远程数据库中的完全限定名称的表
-* `destination object` 表示 PostgreSQL 中的表名。它可以只是一个名称(默认为公共架构)或 schema.name 格式。
-
-**表示 `column` 映射的方式:**
-* `source object` 表示远程数据库中的完全限定名称的列
-* `destination object` 表示 PostgreSQL 中的列名。无需将其格式化为完全限定的列名。
-
-**表示 `数据类型` 映射的方式:**
-* `源对象` 可以表示为以下之一:
-* 完全限定的列 (inventory.geom.g)。这意味着数据类型映射仅适用于此特定列。
-* 通用数据类型字符串 (int)。如果它是自动增量数据类型 (int|true 表示自动增量 int) 或 (int|false 表示非自动增量 int),请使用管道 (|) 添加。这意味着数据类型映射适用于具有匹配条件的所有数据类型。
-
-* `目标对象` 应表示为 PostgreSQL 中存在的通用数据类型字符串。使用管道 (|) 覆盖大小(text|0 将大小覆盖为 0,因为文本是可变大小)或(varchar|-1 使用更改事件附带的任何大小)
-
-**表示 `transform` 映射的方式:**
-* `source object` 表示要转换的列
-* `destination object` 表示在将列数据应用于 PostgreSQL 之前要在列数据上运行的表达式。使用 %d 作为输入列数据的占位符。如果是几何类型,则使用 %w 表示 WKB,使用 %s 表示 SRID。
-
-### **synchdb_add_extra_conninfo**
-
-**用途**:为由 `synchdb_add_conninfo` 创建的现有连接器配置额外的连接器参数
-
-| 参数 | 说明 | 必需 | 示例 | 注释 |
-|:-:|:-|:-:|:-|:-|
-| `name` | 此连接器的唯一标识符 | ✓ | `'mysqlconn'` | 必须在所有连接器中唯一 |
-| `ssl_mode` | SSL 模式 | ☐ | `'verify_ca'` | 可以是以下之一:
- “disabled” - 不使用 SSL。
- “preferred” - 如果服务器支持,则使用 SSL。
- “required” - 必须使用 SSL 来建立连接。
- “verify_ca” - 连接器与服务器建立 TLS,并将根据配置的信任库验证服务器的 TLS 证书。
- “verify_identity” - 与 verify_ca 行为相同,但它还会检查服务器证书的通用名称是否与系统的主机名匹配。 |
-| `ssl_keystore` | 密钥库路径 | ☐ | `/path/to/keystore` | 密钥库文件的路径 |
-| `ssl_keystore_pass` | 密钥库密码 | ☐ | `'mykeystorepass'` | 访问密钥库文件的密码 |
-| `ssl_truststore` | 信任库路径 | ☐ | `'/path/to/truststore'` | 信任库文件的路径 |
-| `ssl_truststore_pass` | 信任库密码 | ☐ | `'mytruststorepass'` | 访问信任库文件的密码 |
-
-```sql
-SELECT synchdb_add_extra_conninfo('mysqlconn', 'verify_ca', '/path/to/keystore', 'mykeystorepass', '/path/to/truststore', 'mytruststorepass');
-```
-
-### **synchdb_del_extra_conninfo**
-
-**用途**:删除由 `synchdb_add_extra_conninfo` 创建的额外连接器参数
-```sql
-SELECT synchdb_del_extra_conninfo('mysqlconn');
-```
-
-### **synchdb_del_conninfo**
-
-**用途**:删除由 `synchdb_add_conninfo` 创建的连接器信息
-```sql
-SELECT synchdb_del_extra_conninfo('mysqlconn');
-```
-
-### **synchdb_del_objmap**
-
-**用途**:禁用由 `synchdb_add_objmap` 创建的对象映射记录
-
-| 参数 | 说明 | 必需 | 示例 | 注释 |
-|:-:|:-|:-:|:-|:-|:-|
-| `name` | 此连接器的唯一标识符 | ✓ | `'mysqlconn'` |必须在所有连接器中保持唯一 |
-| `object type` | 对象映射的类型 | ✓ | `'table'` | 可以是 `table` 来映射表名、`column` 来映射列名、`datatype` 来映射数据类型或 `transform` 来运行数据转换表达式 |
-| `source object` | 以完全限定名称表示的源对象 | ✓ | `inventory.customers` | 远程数据库中表示的对象名称 |
-
-```sql
-SELECT synchdb_del_extra_conninfo('mysqlconn', 'transform', 'inventory.products.name');
-```
-
-## **基本控制函数**
-
-### **synchdb_start_engine_bgw**
-
-**用途**: 启动连接器
-```sql
-SELECT synchdb_start_engine_bgw('mysqlconn');
-```
-
-您还可以包含快照模式来启动连接器,否则将默认使用“initial”模式。请参阅下面的不同快照模式列表。
-```sql
--- 捕获表架构并继续传输新的更改
-SELECT synchdb_start_engine_bgw('mysqlconn', 'no_data');
-
--- 始终重新捕获表架构、现有数据并继续传输新的更改
-SELECT synchdb_start_engine_bgw('mysqlconn', 'always');
-```
-
-### **synchdb_pause_engine**
-
-**用途**: 暂停运行中的连接器
-```sql
-SELECT synchdb_pause_engine_bgw('mysqlconn');
-```
-
-### **synchdb_resume_engine**
-
-**用途**: 恢复已暂停的连接器
-```sql
-SELECT synchdb_resume_engine('mysqlconn');
-```
-
-### **synchdb_stop_engine_bgw**
-
-**用途**: 终止连接器
-```sql
-SELECT synchdb_stop_engine('mysqlconn');
-```
-
-### **synchdb_reload_objmap**
-
-**目的**:使连接器再次加载对象映射规则
-```sql
-SELECT synchdb_reload_objmap('mysqlconn');
-```
-
-## **状态管理**
-
-### **synchdb_state_view**
-
-**用途**: 监控连接器状态
-
-```sql
-SELECT * FROM synchdb_state_view();
-```
-
-**返回字段**:
-
-| 字段 | 说明 | 类型 |
-|-|-|-|
-| `name` | 关联的连接器名称 | Text |
-| `connector_type` | 连接器类型(`mysql`或`sqlserver`) | Text |
-| `pid` | 工作进程ID | Integer |
-| `stage` | 当前连接器阶段 | Text |
-| `state` | 当前连接器状态 | Text |
-| `err` | 最新错误消息 | Text |
-| `last_dbz_offset` | 最后记录的Debezium偏移量 | JSON |
-
-**可能的状态**:
-
-- 🔴 `stopped` - 已停止
-- 🟡 `initializing` - 初始化中
-- 🟠 `paused` - 已暂停
-- 🟢 `syncing` - 主动轮询中
-- 🔵 `parsing` - 解析事件中
-- 🟣 `converting` - 转换数据中
-- ⚪ `executing` - 应用更改中
-- 🟤 `updating offset` - 更新检查点中
-- 🟨 `restarting` - 重启中
-- ⚪ `dumping memory` - 正在输出 JVM 内存信息到 log 文件
-- ⚫ `unknown` - 未知状态
-
-**可能的阶段**:
-
-- `initial snapshot` - 连接器正在执行初始快照(构建表架构和可选的初始数据)
-- `change data capture` - 连接器正在流式传输后续表变更(CDC)
-- `schema sync` - 连接器仅复制表架构
-
-### **synchdb_stats_view**
-
-**用途**:累计收集连接器处理统计信息
-
-```sql
-SELECT * FROM synchdb_stats_view();
-```
-
-| 字段 | 说明 | 类型 |
-|-|-|-|
-| name | 关联的连接器名称 | Text |
-| ddls | 已完成的 DDL 操作数 | Bigint |
-| dmls | 已完成的 DML 操作数 | Bigint |
-| reads | 初始快照阶段完成的 READ 事件数 | Bigint |
-| creating | CDC 阶段完成的 CREATES 事件数 | Bigint |
-| updates | CDC 阶段完成的 UPDATES 事件数 | Bigint |
-| deletes | CDC 阶段完成的 DELETES 事件数 | Bigint |
-| bad_events | 忽略的坏事件数(例如空事件、不支持的 DDL 事件等)| Bigint |
-| total_events |处理的事件总数(包括 bad_events) | Bigint |
-| batches_done | 完成的批次数 | Bigint |
-| avg_batch_size | 平均批次大小(total_events / batches_done) | Bigint |
-
-### **synchdb_reset_stats**
-
-**用途**:重置指定连接器的所有统计信息
-
-```sql
-SELECT synchdb_reset_stats('mysqlconn');
-```
-
-### **synchdb_set_offset**
-
-**用途**: 配置自定义起始位置
-
-**MySQL示例**:
-```sql
-SELECT synchdb_set_offset(
- 'mysqlconn',
- '{"ts_sec":1725644339,"file":"mysql-bin.000004","pos":138466,"row":1,"server_id":223344,"event":2}'
-);
-```
-
-**SQL Server示例**:
-```sql
-SELECT synchdb_set_offset(
- 'sqlserverconn',
- '{"event_serial_no":1,"commit_lsn":"00000100:00000c00:0003","change_lsn":"00000100:00000c00:0002"}'
-);
-```
-### **synchdb_log_jvm_meminfo**
-
-**用途**: 使 Java 虚拟机 (JVM) 输出当前heap和non-heap使用情况统计信息到 PostgreSQL log 文件。
-```sql
-SELECT synchdb_log_jvm_meminfo('mysqlconn');
-```
-
-检查 PostgreSQL 日志文件:
-```
-2024-12-09 14:34:21.910 PST [25491] LOG: Requesting memdump for mysqlconn connector
-2024-12-09 14:34:21 WARN DebeziumRunner:297 - Heap Memory:
-2024-12-09 14:34:21 WARN DebeziumRunner:298 - Used: 19272600 bytes
-2024-12-09 14:34:21 WARN DebeziumRunner:299 - Committed: 67108864 bytes
-2024-12-09 14:34:21 WARN DebeziumRunner:300 - Max: 2147483648 bytes
-2024-12-09 14:34:21 WARN DebeziumRunner:302 - Non-Heap Memory:
-2024-12-09 14:34:21 WARN DebeziumRunner:303 - Used: 42198864 bytes
-2024-12-09 14:34:21 WARN DebeziumRunner:304 - Committed: 45023232 bytes
-2024-12-09 14:34:21 WARN DebeziumRunner:305 - Max: -1 bytes
-
-```
-
-### **synchdb_att_view**
-
-**用途**:并排显示连接器的数据类型、名称映射和外部表与本地表之间的转换规则关系。
-
-```sql
-SELECT * FROM synchdb_att_view();
-```
-
-**返回字段**:
-
-| 字段 | 描述 | 类型 |
-|-|-|-|
-|`name` | 连接器标识符 | 文本 |
-|`attnum` | 属性编号 | 整数 |
-|`ext_tbname` | 远程显示的表名 | 文本 |
-|`pg_tbname` | PostgreSQL 中的映射表名 | 文本 |
-|`ext_attname` | 远程显示的列名 | 文本 |
-|`pg_attname` | PostgreSQL 中的映射列名 | 文本 |
-|`ext_atttypename` | 远程显示的数据类型 | 文本 |
-|`pg_atttypename` | PostgreSQL 中的映射数据类型 |文本 |
-| `transform` | 转换表达式 | 文本 |
-
-## **快照管理**
-
-### **synchdb_restart_connector**
-
-**用途**: 使用指定的快照模式重新初始化连接器
-
-**快照模式**:
-
-| 模式 | 说明 | 使用场景 |
-|:-:|-|-|
-| `always` | 每次启动时执行完整快照 | 完整数据验证 |
-| `initial` | 仅首次快照 | 正常操作 |
-| `initial_only` | 执行一次快照后停止 | 数据迁移 |
-| `no_data` | 仅捕获表结构,不含数据 | 架构同步 |
-| `never` | 跳过快照,直接开始流式传输 | 实时更新 |
-| `recovery` | 从源表重建主题 | 灾难恢复 |
-| `when_needed` | 按需执行快照 | 自动恢复 |
-| `schemasync` | 仅结构,无数据,无 CDC | 正常操作 |
-
-**示例**:
-```sql
--- 使用特定快照模式重启
-SELECT synchdb_restart_connector('mysqlconn', 'initial');
-
--- 使用特定快照模式启动
-SELECT synchdb_start_engine_bgw('mysqlconn', 'always');
-```
-
----
-📝 **附加说明**:
-
-- 启动前始终验证连接器配置
-- 在快照操作期间监控系统资源
-- 在进行重要操作前备份PostgreSQL目标数据库
-- 测试从PostgreSQL服务器到源数据库的连接性
-- 确保源数据库已配置所需权限
-- 建议定期监控错误日志
diff --git a/doc/mkdocs.yml b/doc/mkdocs.yml
index 76493f1..b592a40 100644
--- a/doc/mkdocs.yml
+++ b/doc/mkdocs.yml
@@ -64,37 +64,35 @@ plugins:
Quick Start: Inicio Rápido
SynchDB Configuration: SynchDB Configuración
Default Data Type Mapping: Mapeo de Tipos de Datos Predeterminado
- Customize Object Mapping and Transformation: Personalizar la asignación y transformación de objetos
+ Object Transformation: Personalizar la asignación y transformación de objetos
Automatic Connector Launcher: Lanzador Automático de Conectores
DDL Replication: Replicación DDL
- Selective Table Replication: Sincronización Selectiva de Tablas
Set Offset: Establecer Desplazamiento
Utility Functions: Funciones de Utilidad
Changelog: Registro de Cambios
- Configure Error Strategies: Configurar estrategias de error
+ Error Strategies: estrategias de error
Create a Connector: Crear un conector
Statistic View: Vista de estadísticas
State View: Vista de estado
Start/Stop a Connector: Iniciar/Detener un conector
Object Mapping Workflow: Flujo de trabajo de mapeo de objetos
- MySQL CDC to PostgreSQL: CDC de MySQL a PostgreSQL
- SQL Server CDC to PostgreSQL: CDC de SQL Server a PostgreSQL
- Oracle CDC to PostgreSQL: CDC de Oracle a PostgreSQL
- Table Snapshot and Re-snapshot: Instantánea de tabla y nueva instantánea
+ MySQL Connector: Conector MySQL
+ SQL Server Connector: Conector SQL Server
+ Oracle Connector: Conector Oracle
+ Postgres Connector: Conector Postgres
JMX Monitor Settings: Configuración del monitor JMX
JVM Memory Usage: Uso de memoria de JVM
Attribute View: Vista de atributos
JMX Exporter Settings: Configuración del exportador JMX
- Configure Openlog Replicator for Oracle Connector: Configurar Openlog Replicator para Oracle Connector
+ Openlog Replicator: Configurar Openlog Replicator
Openlog Replicator Event Processor: Procesador de eventos del replicador Openlog
Getting Started: Empezando
Monitoring: escucha
Tutorial: Tutorial
- Secured Connection: Conexión segura
- Configure Replication Offset: Configurar el desplazamiento de replicación
- Configure Infinispan: Configurar Infinispan
- Configure Snapshot Engine: Configurar el motor de instantáneas
+ Snapshot Engine: Configurar el motor de instantáneas
FDW Based Snapshot: Instantánea basada en FDW
+ Letter Casing Strategy: Estrategia de mayúsculas y minúsculas
+ Native Openlog Replicator Connector: Conector nativo de replicador Openlog
- locale: zh
name: 中文
site_name: SynchDB 文档
@@ -118,38 +116,36 @@ plugins:
Quick Start: 快速入门
SynchDB Configuration: SynchDB 配置
Default Data Type Mapping: 默认数据类型映射
- Customize Object Mapping and Transformation: 自定义对象映射和转换
+ Object Transformation: 对象映射和转换
Automatic Connector Launcher: 连接器自动启动器
DDL Replication: DDL复制
- Selective Table Replication: 选择性表同步
Set Offset: 设置偏移量
Utility Functions: 实用函数
Changelog: 变更日志
- Configure Error Strategies: 配置错误处理策略
+ Error Strategies: 错误处理策略
Create a Connector: 创建连接器
Statistic View: 统计视图
State View: 状态视图
Start/Stop a Connector: 启动/停止连接器
Object Mapping Workflow: 对象映射工作流程
- MySQL -> PostgreSQL: MySQL CDC -> PostgreSQL
- SQL Server -> PostgreSQL: SQL Server CDC -> PostgreSQL
- Oracle -> PostgreSQL: Oracle CDC -> PostgreSQL
- Table Snapshot and Re-snapshot: 表快照和重新快照
+ MySQL Connector: MySQL 連接器
+ SQL Server Connector: SQL Server 連接器
+ Oracle Connector: Oracle 連接器
+ Postgres Connector: Postgres 連接器
JMX Monitor Settings: JMX 监视器设置
JVM Memory Usage: JVM 内存使用情况
Attribute View: 属性视图
JMX Exporter Settings: JMX exporter 设置
- Configure Openlog Replicator for Oracle Connector: 为 Oracle 连接器配置 Openlog Replicator
+ Openlog Replicator: Openlog Replicator 设置
Openlog Replicator Event Processor: Openlog Replicator 事件处理器
Debezium Event Processor: Debezium 事件处理器
Getting Started: 快速入门
Monitoring: 监控
Tutorial: 教程
- Secured Connection: 安全连接
- Configure Replication Offset: 配置复制偏移
- Configure Infinispan: 配置 infinispan
- Configure Snapshot Engine: 配置快照引擎
+ Snapshot Engine: 配置快照引擎
FDW Based Snapshot: 基於FDW的快照
+ Letter Casing Strategy: 字母大小寫規則
+ Native Openlog Replicator Connector: 原生 Openlog Replicator 连接器
- mike:
version_selector: true
css_dir: css
@@ -175,12 +171,10 @@ nav:
- Debezium Metadata Files: architecture/metadata_files.md
- DDL Replication: architecture/ddl_replication.md
- FDW Based Snapshot: architecture/fdw_based_snapshot.md
- # - Test Framework: architecture/test_framework.md
- Getting Started:
- Installation: getting-started/installation.md
- Source Database Setup: getting-started/remote_database_setups.md
- SynchDB Configuration: getting-started/configuration.md
- #- Prepare Sample Databases: getting-started/prepare_tests_env.md
- Quick Start: getting-started/quick_start.md
- Monitoring:
- Statistic View: monitoring/stats_view.md
@@ -190,28 +184,21 @@ nav:
- JMX Monitor Settings: monitoring/jmx_monitor.md
- JMX Exporter Settings: monitoring/jmx_exporter.md
- Tutorial:
- - MySQL -> PostgreSQL: tutorial/mysql_cdc_to_postgresql.md
- - SQL Server -> PostgreSQL: tutorial/sqlserver_cdc_to_postgresql.md
- - Oracle -> PostgreSQL: tutorial/oracle_cdc_to_postgresql.md
- # - Selective Table Replication: tutorial/selective_table_sync.md
- # - Data Transformation: tutorial/data_transformation.md
- # - Table Snapshot and Re-snapshot: tutorial/table_snapshot_resnapshot.md
- # - Schema Only Synchronization: tutorial/schema_only_sync.md
- # - Multi Source Replication: tutorial/multi_source_replication.md
- - Object Mapping Workflow: tutorial/object_mapping_workflow.md
+ - MySQL Connector: tutorial/mysql_cdc_to_postgresql.md
+ - SQL Server Connector: tutorial/sqlserver_cdc_to_postgresql.md
+ - Oracle Connector: tutorial/oracle_cdc_to_postgresql.md
+ - Postgres Connector: tutorial/postgresql_cdc_to_postgresql.md
+ - Native Openlog Replicator Connector: tutorial/native_olr_cdc_to_postgresql.md
- User guide:
- Create a Connector: user-guide/create_a_connector.md
- Start/Stop a Connector: user-guide/start_stop_connector.md
- Automatic Connector Launcher: user-guide/connector_auto_launcher.md
- Default Data Type Mapping: user-guide/default_datatype_mapping.md
- - Customize Object Mapping and Transformation: user-guide/object_mapping_rules.md
- - Secured Connection: user-guide/secured_connection.md
- - Configure Error Strategies: user-guide/configure_error_strategies.md
- - Configure Replication Offset: user-guide/set_offset.md
- - Configure Openlog Replicator for Oracle Connector: user-guide/configure_olr.md
- - Configure Infinispan: user-guide/configure_infinispan.md
- - Configure Snapshot Engine: user-guide/configure_snapshot_engine.md
- # - Utility Functions: user-guide/utility_functions.md
+ - Object Transformation: user-guide/object_mapping_rules.md
+ - Letter Casing Strategy: user-guide/letter_casing_strategy.md
+ - Error Strategies: user-guide/configure_error_strategies.md
+ - Openlog Replicator: user-guide/configure_olr.md
+ - Snapshot Engine: user-guide/configure_snapshot_engine.md
- Changelog: changelog.md
# - Homepage: https://www.synchdb.com
diff --git a/src/backend/executor/replication_agent.c b/src/backend/executor/replication_agent.c
index e6d8361..bc9ea06 100644
--- a/src/backend/executor/replication_agent.c
+++ b/src/backend/executor/replication_agent.c
@@ -1443,7 +1443,13 @@ ra_run_orafdw_initial_snapshot_spi(ConnectorType connType, ConnectionInfo * conn
values[3] = DirectFunctionCall1(namein, CStringGetDatum("ora_stage"));
values[4] = DirectFunctionCall1(namein, CStringGetDatum(dstdb));
values[5] = CStringGetTextDatum(conninfo->srcdb);
- values[6] = DirectFunctionCall1(namein, CStringGetDatum(conninfo->srcschema));
+
+ /* we srcschema is not available, we put srcdb -> in the case of MySQL */
+ if (strlen(conninfo->srcschema) == 0 || !strcmp(conninfo->srcschema, "null"))
+ values[6] = DirectFunctionCall1(namein, CStringGetDatum(conninfo->srcdb));
+ else
+ values[6] = DirectFunctionCall1(namein, CStringGetDatum(conninfo->srcschema));
+
values[7] = BoolGetDatum(true);
values[8] = CStringGetTextDatum("replace");
diff --git a/src/backend/synchdb/synchdb.c b/src/backend/synchdb/synchdb.c
index 76e12f2..852d6e0 100644
--- a/src/backend/synchdb/synchdb.c
+++ b/src/backend/synchdb/synchdb.c
@@ -2395,6 +2395,10 @@ main_loop(ConnectorType connectorType, ConnectionInfo *connInfo, char * snapshot
}
case TYPE_SQLSERVER:
{
+ /* SQLSERVER does not support FDW based snapshot yet. */
+ if (connInfo->snapengine == ENGINE_FDW)
+ connInfo->snapengine = ENGINE_DEBEZIUM;
+
/* Debezium based snapshot, schema and CDC processing logics here */
myBatchInfo.batchId = SYNCHDB_INVALID_BATCH_ID;
myBatchInfo.batchSize = 0;
diff --git a/synchdb--1.0.sql b/synchdb--1.0.sql
index bd3d524..ede4b37 100644
--- a/synchdb--1.0.sql
+++ b/synchdb--1.0.sql
@@ -2776,7 +2776,7 @@ BEGIN
%L::name,
%L::name,
%s::oid,
- c.position::smallint,
+ row_number() OVER (ORDER BY c.position)::smallint,
%L::name,
c.column_name::name,
lower(c.type_name)::name
@@ -3304,7 +3304,8 @@ CREATE OR REPLACE FUNCTION synchdb_apply_column_mappings(
p_src_schema name, -- e.g. 'psql_stage'
p_connector_name name, -- connector name to filter objmap
p_desired_db name, -- e.g. 'free' or 'wrongdb'
- p_desired_schema name DEFAULT NULL -- optional: e.g. 'dbzuser'; NULL = don't enforce
+ p_desired_schema name DEFAULT NULL, -- optional: e.g. 'dbzuser'; NULL = don't enforce
+ p_case_strategy text DEFAULT 'asis'
) RETURNS void
LANGUAGE plpgsql
AS $$
@@ -3357,6 +3358,17 @@ BEGIN
CONTINUE;
END IF;
+ IF p_case_strategy = 'lower' THEN
+ s_col := lower(s_col);
+ s_table := lower(s_table);
+ ELSIF p_case_strategy = 'upper' THEN
+ s_col := upper(s_col);
+ s_table := upper(s_table);
+ ELSE
+ -- 'asis' → leave untouched
+ NULL;
+ END IF;
+
IF p_desired_db IS NOT NULL AND s_db IS DISTINCT FROM p_desired_db THEN
CONTINUE;
END IF;
@@ -3423,6 +3435,17 @@ BEGIN
CONTINUE;
END IF;
+ IF p_case_strategy = 'lower' THEN
+ s_col := lower(s_col);
+ s_table := lower(s_table);
+ ELSIF p_case_strategy = 'upper' THEN
+ s_col := upper(s_col);
+ s_table := upper(s_table);
+ ELSE
+ -- 'asis' → leave untouched
+ NULL;
+ END IF;
+
IF p_desired_db IS NOT NULL AND dt_db IS DISTINCT FROM p_desired_db THEN
CONTINUE;
END IF;
@@ -3502,15 +3525,16 @@ BEGIN
END;
$$;
-COMMENT ON FUNCTION synchdb_apply_column_mappings(name, name, name, name) IS
+COMMENT ON FUNCTION synchdb_apply_column_mappings(name, name, name, name, text) IS
'transform column name mappings based on synchdb_objmap';
CREATE OR REPLACE FUNCTION synchdb_migrate_data_with_transforms(
- p_src_schema name, -- e.g. 'ora_stage'
+ p_src_schema name, -- e.g. 'ora_stage' (foreign tables)
p_connector_name name, -- connector for stats + objmap filter
- p_dst_schema name, -- e.g. 'psql_stage'
+ p_dst_schema name, -- e.g. 'psql_stage' (real tables)
p_desired_db name, -- e.g. 'free'
p_offset text, -- offset value (lsn, scn, binlog pos..etc)
+ p_case_strategy text, -- 'lower' | 'upper' | 'as_is' (or others treated as as_is)
p_desired_schema name DEFAULT NULL, -- e.g. 'dbzuser'
p_do_truncate boolean DEFAULT false,
p_rows_per_tick integer DEFAULT 0, -- 0/NULL = no batching; >0 = stats every N rows
@@ -3544,7 +3568,6 @@ DECLARE
v_err_count bigint; -- summary count at end
v_any_batch_failed boolean; -- tracks data failures in batching mode
-
BEGIN
-- sanitize connector name to identifier suffix
v_err_tbl_ident :=
@@ -3564,11 +3587,18 @@ BEGIN
----------------------------------------------------------------------
-- Iterate all source FTs that have a same-named real table in dst
- -- Case-insensitive match, but keep actual relnames for SQL.
+ -- NOTE: we still join by relname equality; under your flow both sides
+ -- are already created with the same normalized names.
----------------------------------------------------------------------
FOR r IN
SELECT
- c.relname AS tbl_canon, -- canonical name for matching
+ -- canonical table name for mapping/transform matching
+ CASE
+ WHEN p_case_strategy = 'lower' THEN lower(c.relname)
+ WHEN p_case_strategy = 'upper' THEN upper(c.relname)
+ ELSE c.relname
+ END AS tbl_canon,
+
c.relname AS src_tbl_name, -- actual FT name in p_src_schema
c2.relname AS dst_tbl_name -- actual table name in p_dst_schema
FROM pg_foreign_table ft
@@ -3581,64 +3611,132 @@ BEGIN
AND c2.relkind = 'r'
LOOP
------------------------------------------------------------------
- -- Error-table identity:
+ -- Error-table identity (display only)
------------------------------------------------------------------
IF p_desired_schema IS NULL OR btrim(p_desired_schema::text) = '' THEN
- v_tbl_display :=
- p_desired_db::text || '.' || r.src_tbl_name;
+ v_tbl_display := p_desired_db::text || '.' || r.src_tbl_name;
ELSE
- v_tbl_display :=
- p_desired_db::text || '.'
- || p_desired_schema::text || '.'
- || r.src_tbl_name;
+ v_tbl_display := p_desired_db::text || '.'
+ || p_desired_schema::text || '.'
+ || r.src_tbl_name;
END IF;
v_any_batch_failed := false;
BEGIN
------------------------------------------------------------------
- -- Build column/expr lists, using canonical names for matching and
- -- actual identifiers for SQL and transforms.
+ -- Build column/expr lists.
+ -- FIX: Canonicalize all objmap matching based on p_case_strategy,
+ -- while still using actual identifiers for SQL.
------------------------------------------------------------------
- RAISE NOTICE 'Migrating table: v_tbl_display = %', v_tbl_display;
+ RAISE NOTICE 'Migrating table: %', v_tbl_display;
WITH dst_cols AS (
SELECT
c.ordinal_position,
- c.column_name AS dst_col_canon,
- c.column_name AS dst_col_ident
+ -- canonical for matching
+ CASE
+ WHEN p_case_strategy = 'lower' THEN lower(c.column_name)
+ WHEN p_case_strategy = 'upper' THEN upper(c.column_name)
+ ELSE c.column_name
+ END AS dst_col_canon,
+ -- actual identifier for SQL
+ c.column_name AS dst_col_ident
FROM information_schema.columns c
WHERE c.table_schema = p_dst_schema
AND c.table_name = r.dst_tbl_name
),
+
colmap AS (
- -- A) schema-qualified rules: p_src_schema.table.column ->
+ ----------------------------------------------------------------
+ -- COLUMN rename rules:
+ -- A) schema-qualified: .
. ->
+ -- B) db-prefixed: db[.schema].table.col ->
+ -- FIX: canonicalize tbl/src_col/dst_col on output.
+ ----------------------------------------------------------------
+
+ -- A) schema-qualified
SELECT
- split_part(m.srcobj,'.',2) AS tbl,
- split_part(m.srcobj,'.',3) AS src_col,
- (regexp_split_to_array(m.dstobj, '\.'))[
- array_length(regexp_split_to_array(m.dstobj, '\.'),1)
- ] AS dst_col
+ CASE
+ WHEN p_case_strategy='lower' THEN lower(split_part(m.srcobj,'.',2))
+ WHEN p_case_strategy='upper' THEN upper(split_part(m.srcobj,'.',2))
+ ELSE split_part(m.srcobj,'.',2)
+ END AS tbl,
+
+ CASE
+ WHEN p_case_strategy='lower' THEN lower(split_part(m.srcobj,'.',3))
+ WHEN p_case_strategy='upper' THEN upper(split_part(m.srcobj,'.',3))
+ ELSE split_part(m.srcobj,'.',3)
+ END AS src_col,
+
+ CASE
+ WHEN p_case_strategy='lower' THEN lower(
+ (regexp_split_to_array(m.dstobj, '\.'))[
+ array_length(regexp_split_to_array(m.dstobj, '\.'),1)
+ ]
+ )
+ WHEN p_case_strategy='upper' THEN upper(
+ (regexp_split_to_array(m.dstobj, '\.'))[
+ array_length(regexp_split_to_array(m.dstobj, '\.'),1)
+ ]
+ )
+ ELSE
+ (regexp_split_to_array(m.dstobj, '\.'))[
+ array_length(regexp_split_to_array(m.dstobj, '\.'),1)
+ ]
+ END AS dst_col
FROM synchdb_objmap AS m
- WHERE m.objtype='column' AND m.enabled
+ WHERE m.objtype='column'
+ AND m.enabled
AND m.name = p_connector_name
AND split_part(m.srcobj,'.',1) = p_src_schema
AND m.dstobj IS NOT NULL AND btrim(m.dstobj) <> ''
UNION ALL
- -- B) db-prefixed rules: db.schema.table.column OR db.table.column ->
+ -- B) db-prefixed
SELECT
- CASE WHEN array_length(arr,1)=4 THEN arr[3]
- WHEN array_length(arr,1)=3 THEN arr[2] END AS tbl,
- arr[array_length(arr,1)] AS src_col,
- (regexp_split_to_array(m2.dstobj, '\.'))[
- array_length(regexp_split_to_array(m2.dstobj, '\.'),1)
- ] AS dst_col
+ CASE
+ WHEN p_case_strategy='lower' THEN lower(
+ CASE WHEN array_length(arr,1)=4 THEN arr[3]
+ WHEN array_length(arr,1)=3 THEN arr[2] END
+ )
+ WHEN p_case_strategy='upper' THEN upper(
+ CASE WHEN array_length(arr,1)=4 THEN arr[3]
+ WHEN array_length(arr,1)=3 THEN arr[2] END
+ )
+ ELSE
+ CASE WHEN array_length(arr,1)=4 THEN arr[3]
+ WHEN array_length(arr,1)=3 THEN arr[2] END
+ END AS tbl,
+
+ CASE
+ WHEN p_case_strategy='lower' THEN lower(arr[array_length(arr,1)])
+ WHEN p_case_strategy='upper' THEN upper(arr[array_length(arr,1)])
+ ELSE arr[array_length(arr,1)]
+ END AS src_col,
+
+ CASE
+ WHEN p_case_strategy='lower' THEN lower(
+ (regexp_split_to_array(m2.dstobj, '\.'))[
+ array_length(regexp_split_to_array(m2.dstobj, '\.'),1)
+ ]
+ )
+ WHEN p_case_strategy='upper' THEN upper(
+ (regexp_split_to_array(m2.dstobj, '\.'))[
+ array_length(regexp_split_to_array(m2.dstobj, '\.'),1)
+ ]
+ )
+ ELSE
+ (regexp_split_to_array(m2.dstobj, '\.'))[
+ array_length(regexp_split_to_array(m2.dstobj, '\.'),1)
+ ]
+ END AS dst_col
FROM (
SELECT regexp_split_to_array(srcobj, '\.') AS arr, dstobj
FROM synchdb_objmap
- WHERE objtype='column' AND enabled
+ WHERE objtype='column'
+ AND enabled
AND name = p_connector_name
AND dstobj IS NOT NULL AND btrim(dstobj) <> ''
) m2
@@ -3649,59 +3747,117 @@ BEGIN
OR arr[2] = p_desired_schema
)
),
+
col_map AS (
- -- Map destination columns (canonical) to canonical source columns
+ ----------------------------------------------------------------
+ -- Map destination columns -> canonical source column names
+ -- using canonical matching (tbl + dst_col).
+ ----------------------------------------------------------------
SELECT
d.ordinal_position,
d.dst_col_ident,
d.dst_col_canon,
COALESCE(
(SELECT cm.src_col
- FROM colmap cm
- WHERE cm.tbl = r.tbl_canon
- AND cm.dst_col = d.dst_col_canon
- LIMIT 1),
+ FROM colmap cm
+ WHERE cm.tbl = r.tbl_canon
+ AND cm.dst_col = d.dst_col_canon
+ LIMIT 1),
d.dst_col_canon
) AS src_col_canon
FROM dst_cols d
),
+
src_presence AS (
----------------------------------------------------------------
- -- FIX: collapse duplicate source columns per (table, canon name)
- -- so "A" and "a" become exactly ONE mapping for canon 'a'
+ -- Source FT column inventory:
+ -- FIX: canonicalize column_name for matching, but keep actual ident.
+ -- DISTINCT ON avoids duplicates if case variants exist.
----------------------------------------------------------------
- SELECT DISTINCT ON (table_name, column_name)
- table_name AS src_tbl_ident,
- column_name AS src_col_canon,
- column_name AS src_col_ident
+ SELECT DISTINCT ON (table_name,
+ CASE
+ WHEN p_case_strategy='lower' THEN lower(column_name)
+ WHEN p_case_strategy='upper' THEN upper(column_name)
+ ELSE column_name
+ END)
+ table_name AS src_tbl_ident,
+ CASE
+ WHEN p_case_strategy='lower' THEN lower(column_name)
+ WHEN p_case_strategy='upper' THEN upper(column_name)
+ ELSE column_name
+ END AS src_col_canon,
+ column_name AS src_col_ident
FROM information_schema.columns
WHERE table_schema = p_src_schema
- ORDER BY table_name, column_name, ordinal_position
+ ORDER BY table_name,
+ CASE
+ WHEN p_case_strategy='lower' THEN lower(column_name)
+ WHEN p_case_strategy='upper' THEN upper(column_name)
+ ELSE column_name
+ END,
+ ordinal_position
),
+
tmap AS (
- -- Transform rules
+ ----------------------------------------------------------------
+ -- TRANSFORM rules:
+ -- A) schema-qualified: .. ->
+ -- B) db-prefixed: db[.schema].table.col ->
+ -- FIX: canonicalize tbl/src_col for matching.
+ ----------------------------------------------------------------
+
-- A) schema-qualified
SELECT
- split_part(mt.srcobj,'.',2) AS tbl,
- split_part(mt.srcobj,'.',3) AS src_col,
- mt.dstobj AS expr
+ CASE
+ WHEN p_case_strategy='lower' THEN lower(split_part(mt.srcobj,'.',2))
+ WHEN p_case_strategy='upper' THEN upper(split_part(mt.srcobj,'.',2))
+ ELSE split_part(mt.srcobj,'.',2)
+ END AS tbl,
+
+ CASE
+ WHEN p_case_strategy='lower' THEN lower(split_part(mt.srcobj,'.',3))
+ WHEN p_case_strategy='upper' THEN upper(split_part(mt.srcobj,'.',3))
+ ELSE split_part(mt.srcobj,'.',3)
+ END AS src_col,
+
+ mt.dstobj AS expr
FROM synchdb_objmap AS mt
- WHERE mt.objtype='transform' AND mt.enabled
+ WHERE mt.objtype='transform'
+ AND mt.enabled
AND mt.name = p_connector_name
AND split_part(mt.srcobj,'.',1) = p_src_schema
+ AND mt.dstobj IS NOT NULL AND btrim(mt.dstobj) <> ''
UNION ALL
-- B) db-prefixed
SELECT
- CASE WHEN array_length(arr,1)=4 THEN arr[3]
- WHEN array_length(arr,1)=3 THEN arr[2] END AS tbl,
- arr[array_length(arr,1)] AS src_col,
- t.dstobj AS expr
+ CASE
+ WHEN p_case_strategy='lower' THEN lower(
+ CASE WHEN array_length(arr,1)=4 THEN arr[3]
+ WHEN array_length(arr,1)=3 THEN arr[2] END
+ )
+ WHEN p_case_strategy='upper' THEN upper(
+ CASE WHEN array_length(arr,1)=4 THEN arr[3]
+ WHEN array_length(arr,1)=3 THEN arr[2] END
+ )
+ ELSE
+ CASE WHEN array_length(arr,1)=4 THEN arr[3]
+ WHEN array_length(arr,1)=3 THEN arr[2] END
+ END AS tbl,
+
+ CASE
+ WHEN p_case_strategy='lower' THEN lower(arr[array_length(arr,1)])
+ WHEN p_case_strategy='upper' THEN upper(arr[array_length(arr,1)])
+ ELSE arr[array_length(arr,1)]
+ END AS src_col,
+
+ t.dstobj AS expr
FROM (
SELECT regexp_split_to_array(srcobj, '\.') AS arr, dstobj
FROM synchdb_objmap
- WHERE objtype='transform' AND enabled
+ WHERE objtype='transform'
+ AND enabled
AND name = p_connector_name
AND dstobj IS NOT NULL AND btrim(dstobj) <> ''
) t
@@ -3712,8 +3868,12 @@ BEGIN
OR arr[2] = p_desired_schema
)
),
+
exprs AS (
- -- Build source expressions using *actual* source column identifiers
+ ----------------------------------------------------------------
+ -- Build source expressions using actual source column identifiers.
+ -- Matching for transform uses canonicalized tbl + src_col.
+ ----------------------------------------------------------------
SELECT
m.ordinal_position,
m.dst_col_ident,
@@ -3722,10 +3882,10 @@ BEGIN
'NULL'
ELSE COALESCE(
(SELECT replace(tt.expr, '%d', quote_ident(sp.src_col_ident))
- FROM tmap tt
- WHERE tt.tbl = r.tbl_canon
- AND tt.src_col = m.src_col_canon
- LIMIT 1),
+ FROM tmap tt
+ WHERE tt.tbl = r.tbl_canon
+ AND tt.src_col = m.src_col_canon
+ LIMIT 1),
quote_ident(sp.src_col_ident)
)
END AS src_expr
@@ -3734,6 +3894,7 @@ BEGIN
ON sp.src_tbl_ident = r.src_tbl_name -- exact FT name
AND sp.src_col_canon = m.src_col_canon
)
+
SELECT
string_agg(quote_ident(dst_col_ident), ', ' ORDER BY ordinal_position),
string_agg(src_expr, ', ' ORDER BY ordinal_position)
@@ -3745,6 +3906,10 @@ BEGIN
CONTINUE;
END IF;
+ -- Optional debug while validating:
+ -- RAISE NOTICE 'dst_list=%', dst_list;
+ -- RAISE NOTICE 'src_list=%', src_list;
+
------------------------------------------------------------------
-- Optional truncate
------------------------------------------------------------------
@@ -3752,7 +3917,6 @@ BEGIN
BEGIN
EXECUTE format('TRUNCATE %I.%I', p_dst_schema, r.dst_tbl_name);
EXCEPTION WHEN OTHERS THEN
- -- record failure (UPSERT)
IF NOT v_err_tbl_created THEN
EXECUTE format(
'CREATE TABLE IF NOT EXISTS %I.%I (
@@ -3771,19 +3935,19 @@ BEGIN
v_err_tbl_exists := true;
END IF;
- GET STACKED DIAGNOSTICS err_state = RETURNED_SQLSTATE,
- err_msg = MESSAGE_TEXT,
- err_detail = PG_EXCEPTION_DETAIL;
+ GET STACKED DIAGNOSTICS err_state = RETURNED_SQLSTATE,
+ err_msg = MESSAGE_TEXT,
+ err_detail = PG_EXCEPTION_DETAIL;
EXECUTE format(
'INSERT INTO %I.%I (connector_name, tbl, err_state, err_msg, err_detail, err_offset)
VALUES ($1,$2,$3,$4,$5,$6)
ON CONFLICT (connector_name, tbl)
- DO UPDATE SET err_state = EXCLUDED.err_state,
- err_msg = EXCLUDED.err_msg,
- err_detail= EXCLUDED.err_detail,
- err_offset= EXCLUDED.err_offset,
- ts = now()',
+ DO UPDATE SET err_state = EXCLUDED.err_state,
+ err_msg = EXCLUDED.err_msg,
+ err_detail = EXCLUDED.err_detail,
+ err_offset = EXCLUDED.err_offset,
+ ts = now()',
'public', v_err_tbl_ident
)
USING p_connector_name, v_tbl_display, err_state, err_msg, err_detail, p_offset;
@@ -3807,14 +3971,16 @@ BEGIN
src_list,
p_src_schema, r.src_tbl_name
);
+
GET DIAGNOSTICS v_rows = ROW_COUNT;
PERFORM synchdb_set_snapstats(p_connector_name, 0::bigint, v_rows::bigint, 0::bigint, 0::bigint);
+
RAISE NOTICE 'Loaded %.% from %.% (rows=%)',
p_dst_schema, r.dst_tbl_name,
p_src_schema, r.src_tbl_name,
v_rows;
- -- success for the whole table (non-batch): delete error row if table exists
+ -- success for whole table: delete error row if table exists
IF v_err_tbl_exists THEN
EXECUTE format(
'DELETE FROM %I.%I WHERE connector_name = $1 AND tbl = $2',
@@ -3878,19 +4044,19 @@ BEGIN
v_err_tbl_exists := true;
END IF;
- GET STACKED DIAGNOSTICS err_state = RETURNED_SQLSTATE,
- err_msg = MESSAGE_TEXT,
- err_detail = PG_EXCEPTION_DETAIL;
+ GET STACKED DIAGNOSTICS err_state = RETURNED_SQLSTATE,
+ err_msg = MESSAGE_TEXT,
+ err_detail = PG_EXCEPTION_DETAIL;
EXECUTE format(
'INSERT INTO %I.%I (connector_name, tbl, err_state, err_msg, err_detail, err_offset)
VALUES ($1,$2,$3,$4,$5,$6)
ON CONFLICT (connector_name, tbl)
- DO UPDATE SET err_state = EXCLUDED.err_state,
- err_msg = EXCLUDED.err_msg,
- err_detail= EXCLUDED.err_detail,
- err_offset= EXCLUDED.err_offset,
- ts = now()',
+ DO UPDATE SET err_state = EXCLUDED.err_state,
+ err_msg = EXCLUDED.err_msg,
+ err_detail = EXCLUDED.err_detail,
+ err_offset = EXCLUDED.err_offset,
+ ts = now()',
'public', v_err_tbl_ident
)
USING p_connector_name, v_tbl_display, err_state, err_msg, err_detail, p_offset;
@@ -3919,7 +4085,7 @@ BEGIN
v_off := v_off + p_rows_per_tick;
END LOOP;
- -- If no batch failed, delete error row for this table (if the table exists)
+ -- If no batch failed, delete error row for this table (if it exists)
IF NOT v_any_batch_failed AND v_err_tbl_exists THEN
EXECUTE format(
'DELETE FROM %I.%I WHERE connector_name = $1 AND tbl = $2',
@@ -3931,8 +4097,7 @@ BEGIN
EXCEPTION
WHEN OTHERS THEN
-
- RAISE WARNING 'an error has occured while migrating a table';
+ RAISE WARNING 'An error has occurred while migrating a table (%).', v_tbl_display;
-- record failure (UPSERT) for this table
IF NOT v_err_tbl_created THEN
@@ -3953,19 +4118,19 @@ BEGIN
v_err_tbl_exists := true;
END IF;
- GET STACKED DIAGNOSTICS err_state = RETURNED_SQLSTATE,
- err_msg = MESSAGE_TEXT,
- err_detail = PG_EXCEPTION_DETAIL;
+ GET STACKED DIAGNOSTICS err_state = RETURNED_SQLSTATE,
+ err_msg = MESSAGE_TEXT,
+ err_detail = PG_EXCEPTION_DETAIL;
EXECUTE format(
'INSERT INTO %I.%I (connector_name, tbl, err_state, err_msg, err_detail, err_offset)
VALUES ($1,$2,$3,$4,$5,$6)
ON CONFLICT (connector_name, tbl)
- DO UPDATE SET err_state = EXCLUDED.err_state,
- err_msg = EXCLUDED.err_msg,
- err_detail= EXCLUDED.err_detail,
- err_offset= EXCLUDED.err_offset,
- ts = now()',
+ DO UPDATE SET err_state = EXCLUDED.err_state,
+ err_msg = EXCLUDED.err_msg,
+ err_detail = EXCLUDED.err_detail,
+ err_offset = EXCLUDED.err_offset,
+ ts = now()',
'public', v_err_tbl_ident
)
USING p_connector_name, v_tbl_display, err_state, err_msg, err_detail, p_offset;
@@ -3979,7 +4144,9 @@ BEGIN
END; -- end per-table block
END LOOP;
+ ----------------------------------------------------------------------
-- Final summary (only if we created the error table this run OR it pre-existed)
+ ----------------------------------------------------------------------
IF v_err_tbl_created OR v_err_tbl_exists THEN
EXECUTE format(
'SELECT count(*)
@@ -3997,8 +4164,8 @@ BEGIN
END IF;
END;
$$;
-
-COMMENT ON FUNCTION synchdb_migrate_data_with_transforms(name, name, name, name, text, name, boolean, int, boolean, boolean) IS
+
+COMMENT ON FUNCTION synchdb_migrate_data_with_transforms(name, name, name, name, text, text, name, boolean, int, boolean, boolean) IS
'migrate data while applying transform expressions if available - sub-transaction mode';
CREATE OR REPLACE FUNCTION synchdb_migrate_data_with_transforms_nosubs(
@@ -4276,7 +4443,8 @@ CREATE OR REPLACE FUNCTION synchdb_apply_table_mappings(
p_src_schema name, -- e.g. 'psql_stage'
p_connector_name name, -- filter objmap rows by connector name
p_desired_db name, -- e.g. 'free' (must match the db token in srcobj)
- p_desired_schema name DEFAULT NULL -- e.g. 'dbzuser' (only enforced if srcobj includes a schema)
+ p_desired_schema name DEFAULT NULL, -- e.g. 'dbzuser' (only enforced if srcobj includes a schema)
+ p_case_strategy text DEFAULT 'asis'
) RETURNS void
LANGUAGE plpgsql
AS $$
@@ -4311,6 +4479,15 @@ BEGIN
CONTINUE; -- unsupported form
END IF;
+ IF p_case_strategy = 'lower' THEN
+ s_table := lower(s_table);
+ ELSIF p_case_strategy = 'upper' THEN
+ s_table := upper(s_table);
+ ELSE
+ -- 'asis' → leave untouched
+ NULL;
+ END IF;
+
-- Require matching database
IF p_desired_db IS NOT NULL AND s_db IS DISTINCT FROM p_desired_db THEN
CONTINUE;
@@ -4356,8 +4533,9 @@ BEGIN
AND c.relkind = 'r'
AND c.relname = d_table
) THEN
- RAISE NOTICE 'Skipping % -> %.%: destination exists', s_table, d_schema, d_table;
- CONTINUE;
+ RAISE NOTICE 'dropping % -> %.%: destination exists', s_table, d_schema, d_table;
+ EXECUTE format('DROP TABLE %I.%I', d_schema, d_table);
+ -- CONTINUE;
END IF;
-- Same-schema rename vs. cross-schema move (rename first to avoid collisions)
@@ -4377,7 +4555,7 @@ BEGIN
END;
$$;
-COMMENT ON FUNCTION synchdb_apply_table_mappings(name, name, name, name) IS
+COMMENT ON FUNCTION synchdb_apply_table_mappings(name, name, name, name, text) IS
'transform table names according to synchdb_objmap';
CREATE OR REPLACE FUNCTION synchdb_finalize_initial_snapshot(
@@ -4753,7 +4931,7 @@ BEGIN
RAISE NOTICE 'Step 7: Applying column mappings to schema "%" using objmap %.% for connector %',
p_dest_schema, p_lookup_db, p_lookup_schema, p_connector_name;
- PERFORM synchdb_apply_column_mappings(p_dest_schema, p_connector_name, p_lookup_db, p_lookup_schema);
+ PERFORM synchdb_apply_column_mappings(p_dest_schema, p_connector_name, p_lookup_db, p_lookup_schema, p_case_strategy);
RAISE NOTICE 'Step 8: Migrating data with transforms from "%" to "%" (lookup: %.% for connector %)',
p_stage_schema, p_dest_schema, p_lookup_db, p_lookup_schema, p_connector_name;
@@ -4768,6 +4946,7 @@ BEGIN
p_dest_schema,
p_lookup_db,
json_build_object('scn', v_scn)::text,
+ p_case_strategy,
p_lookup_schema,
false, 0,
true,
@@ -4780,6 +4959,7 @@ BEGIN
p_dest_schema,
p_lookup_db,
json_build_object('file', v_binlog_file, 'pos', v_binlog_pos, 'ts_sec', floor(extract(epoch from clock_timestamp())))::text,
+ p_case_strategy,
null,
false, 0,
true,
@@ -4792,6 +4972,7 @@ BEGIN
p_dest_schema,
p_lookup_db,
json_build_object('lsn', v_lsn)::text,
+ p_case_strategy,
p_lookup_schema,
false, 0,
true,
@@ -4816,7 +4997,7 @@ BEGIN
RAISE NOTICE 'Step 9: Applying table mappings on destination schema "%" (lookup: %.% for connector %)',
p_dest_schema, p_lookup_db, p_lookup_schema, p_connector_name;
- PERFORM synchdb_apply_table_mappings(p_dest_schema, p_connector_name, p_lookup_db, p_lookup_schema);
+ PERFORM synchdb_apply_table_mappings(p_dest_schema, p_connector_name, p_lookup_db, p_lookup_schema, p_case_strategy);
-- Connector-specific completion notice + return value
IF v_connector IN ('oracle', 'olr') THEN
@@ -5097,14 +5278,14 @@ BEGIN
RAISE NOTICE 'Step 7: Applying column mappings to schema "%" using objmap %.% for connector %',
p_dest_schema, p_lookup_db, p_lookup_schema, p_connector_name;
- PERFORM synchdb_apply_column_mappings(p_dest_schema, p_connector_name, p_lookup_db, p_lookup_schema);
+ PERFORM synchdb_apply_column_mappings(p_dest_schema, p_connector_name, p_lookup_db, p_lookup_schema, p_case_strategy);
RAISE NOTICE 'Step 8: Migrating data with transforms from "%" to "%" (lookup: %.% for connector %)',
p_stage_schema, p_dest_schema, p_lookup_db, p_lookup_schema, p_connector_name;
RAISE NOTICE 'Step 9: Applying table mappings on destination schema "%" (lookup: %.% for connector %)',
p_dest_schema, p_lookup_db, p_lookup_schema, p_connector_name;
- PERFORM synchdb_apply_table_mappings(p_dest_schema, p_connector_name, p_lookup_db, p_lookup_schema);
+ PERFORM synchdb_apply_table_mappings(p_dest_schema, p_connector_name, p_lookup_db, p_lookup_schema, p_case_strategy);
-- Connector-specific completion notice + return value
IF v_connector IN ('oracle', 'olr') THEN