You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@seatunnel.apache.org by ga...@apache.org on 2023/01/16 13:38:33 UTC

[incubator-seatunnel] branch dev updated: [Improve][Connector-V2][Fake] Improve fake connector (#3932)

This is an automated email from the ASF dual-hosted git repository.

gaojun2048 pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/incubator-seatunnel.git


The following commit(s) were added to refs/heads/dev by this push:
     new 31f12431d [Improve][Connector-V2][Fake] Improve fake connector (#3932)
31f12431d is described below

commit 31f12431d917fef76794db802f388bb7246a759d
Author: Tyrantlucifer <Ty...@gmail.com>
AuthorDate: Mon Jan 16 21:38:25 2023 +0800

    [Improve][Connector-V2][Fake] Improve fake connector (#3932)
    
    * [Improve][Connector-V2][Fake] Improve fake connector
    
    * [Improve][Connector-V2][Fake] Support setting template and range for data types
---
 docs/en/connector-v2/source/FakeSource.md          | 221 +++++++++++++++-
 .../seatunnel/fake/config/FakeConfig.java          | 283 +++++++++++++++++++++
 .../seatunnel/fake/config/FakeOption.java          | 217 ++++++++++++++--
 .../seatunnel/fake/source/FakeDataGenerator.java   |  47 ++--
 .../seatunnel/fake/source/FakeSourceFactory.java   |  59 ++++-
 .../fake/source/FakeSourceSplitEnumerator.java     |  14 +-
 .../seatunnel/fake/utils/FakeDataRandomUtils.java  | 167 ++++++++++++
 .../fake/{ => source}/FakeFactoryTest.java         |   4 +-
 .../seatunnel/e2e/connector/fake/FakeIT.java       |   4 +
 .../test/resources/fake_to_assert_with_range.conf  | 165 ++++++++++++
 .../resources/fake_to_assert_with_template.conf    | 166 ++++++++++++
 11 files changed, 1264 insertions(+), 83 deletions(-)

diff --git a/docs/en/connector-v2/source/FakeSource.md b/docs/en/connector-v2/source/FakeSource.md
index d3d93bd2b..665605b33 100644
--- a/docs/en/connector-v2/source/FakeSource.md
+++ b/docs/en/connector-v2/source/FakeSource.md
@@ -18,18 +18,43 @@ just for some test cases such as type conversion or connector new feature testin
 
 ## Options
 
-| name                | type   | required | default value |
-|---------------------|--------|----------|---------------|
-| schema              | config | yes      | -             |
-| rows                | config | no       | -             |
-| row.num             | int    | no       | 5             |
-| split.num           | int    | no       | 1             |
-| split.read-interval | long   | no       | 1             |
-| map.size            | int    | no       | 5             |
-| array.size          | int    | no       | 5             |
-| bytes.length        | int    | no       | 5             |
-| string.length       | int    | no       | 5             |
-| common-options      |        | no       | -             |
+| name                | type     | required | default value           |
+|---------------------|----------|----------|-------------------------|
+| schema              | config   | yes      | -                       |
+| rows                | config   | no       | -                       |
+| row.num             | int      | no       | 5                       |
+| split.num           | int      | no       | 1                       |
+| split.read-interval | long     | no       | 1                       |
+| map.size            | int      | no       | 5                       |
+| array.size          | int      | no       | 5                       |
+| bytes.length        | int      | no       | 5                       |
+| string.length       | int      | no       | 5                       |
+| string.fake.mode    | string   | no       | range                   |
+| tinyint.fake.mode   | string   | no       | range                   |
+| tinyint.min         | tinyint  | no       | 0                       |
+| tinyint.max         | tinyint  | no       | 127                     |
+| tinyint.template    | list     | no       | -                       |
+| smallint.fake.mode  | string   | no       | range                   |
+| smallint.min        | smallint | no       | 0                       |
+| smallint.max        | smallint | no       | 32767                   |
+| smallint.template   | list     | no       | -                       |
+| int.fake.template   | string   | no       | range                   |
+| int.min             | int      | no       | 0                       |
+| int.max             | int      | no       | 0x7fffffff              |
+| int.template        | list     | no       | -                       |
+| bigint.fake.mode    | string   | no       | range                   |
+| bigint.min          | bigint   | no       | 0                       |
+| bigint.max          | bigint   | no       | 0x7fffffffffffffff      |
+| bigint.template     | list     | no       | -                       |
+| float.fake.mode     | string   | no       | range                   |
+| float.min           | float    | no       | 0                       |
+| float.max           | float    | no       | 0x1.fffffeP+127         |
+| float.template      | list     | no       | -                       |
+| double.fake.mode    | string   | no       | range                   |
+| double.min          | double   | no       | 0                       |
+| double.max          | double   | no       | 0x1.fffffffffffffP+1023 |
+| double.template     | list     | no       | -                       |
+| common-options      |          | no       | -                       |
 
 ### schema [config]
 
@@ -133,6 +158,110 @@ The length of `bytes` type that connector generated
 
 The length of `string` type that connector generated
 
+### string.fake.mode
+
+The fake mode of generating string data, support `range` and `template`, default `range`,if use configured it to `template`, user should also configured `string.template` option
+
+### string.template
+
+The template list of string type that connector generated, if user configured it, connector will randomly select an item from the template list
+
+### tinyint.fake.mode
+
+The fake mode of generating tinyint data, support `range` and `template`, default `range`,if use configured it to `template`, user should also configured `tinyint.template` option
+
+### tinyint.min
+
+The min value of tinyint data that connector generated
+
+### tinyint.max
+
+The max value of tinyint data that connector generated
+
+### tinyint.template
+
+The template list of tinyint type that connector generated, if user configured it, connector will randomly select an item from the template list
+
+### smallint.fake.mode
+
+The fake mode of generating smallint data, support `range` and `template`, default `range`,if use configured it to `template`, user should also configured `smallint.template` option
+
+### smallint.min
+
+The min value of smallint data that connector generated
+
+### smallint.max
+
+The max value of smallint data that connector generated
+
+### smallint.template
+
+The template list of smallint type that connector generated, if user configured it, connector will randomly select an item from the template list
+
+### int.fake.mode
+
+The fake mode of generating int data, support `range` and `template`, default `range`,if use configured it to `template`, user should also configured `int.template` option
+
+### int.min
+
+The min value of int data that connector generated
+
+### int.max
+
+The max value of int data that connector generated
+
+### int.template
+
+The template list of int type that connector generated, if user configured it, connector will randomly select an item from the template list
+
+### bigint.fake.mode
+
+The fake mode of generating bigint data, support `range` and `template`, default `range`,if use configured it to `template`, user should also configured `bigint.template` option
+
+### bigint.min
+
+The min value of bigint data that connector generated
+
+### bigint.max
+
+The max value of bigint data that connector generated
+
+### bigint.template
+
+The template list of bigint type that connector generated, if user configured it, connector will randomly select an item from the template list
+
+### float.fake.mode
+
+The fake mode of generating float data, support `range` and `template`, default `range`,if use configured it to `template`, user should also configured `float.template` option
+
+### float.min
+
+The min value of float data that connector generated
+
+### float.max
+
+The max value of float data that connector generated
+
+### float.template
+
+The template list of float type that connector generated, if user configured it, connector will randomly select an item from the template list
+
+### double.fake.mode
+
+The fake mode of generating float data, support `range` and `template`, default `range`,if use configured it to `template`, user should also configured `double.template` option
+
+### double.min
+
+The min value of double data that connector generated
+
+### double.max
+
+The max value of double data that connector generated
+
+### double.template
+
+The template list of double type that connector generated, if user configured it, connector will randomly select an item from the template list
+
 ### common options
 
 Source plugin common parameters, please refer to [Source Common Options](common-options.md) for details
@@ -227,6 +356,71 @@ FakeSource {
 }
 ```
 
+Using template
+
+```hocon
+FakeSource {
+  row.num = 5
+  string.fake.mode = "template"
+  string.template = ["tyrantlucifer", "hailin", "kris", "fanjia", "zongwen", "gaojun"]
+  tinyint.fake.mode = "template"
+  tinyint.template = [1, 2, 3, 4, 5, 6, 7, 8, 9]
+  smalling.fake.mode = "template"
+  smallint.template = [10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
+  int.fake.mode = "template"
+  int.template = [20, 21, 22, 23, 24, 25, 26, 27, 28, 29]
+  bigint.fake.mode = "template"
+  bigint.template = [30, 31, 32, 33, 34, 35, 36, 37, 38, 39]
+  float.fake.mode = "template"
+  float.template = [40.0, 41.0, 42.0, 43.0]
+  double.fake.mode = "template"
+  double.template = [44.0, 45.0, 46.0, 47.0]
+  schema {
+    fields {
+      c_string = string
+      c_tinyint = tinyint
+      c_smallint = smallint
+      c_int = int
+      c_bigint = bigint
+      c_float = float
+      c_double = double
+    }
+  }
+}
+```
+
+Use range
+
+```hocon
+FakeSource {
+  row.num = 5
+  string.template = ["tyrantlucifer", "hailin", "kris", "fanjia", "zongwen", "gaojun"]
+  tinyint.min = 1
+  tinyint.max = 9
+  smallint.min = 10
+  smallint.max = 19
+  int.min = 20
+  int.max = 29
+  bigint.min = 30
+  bigint.max = 39
+  float.min = 40.0
+  float.max = 43.0
+  double.min = 44.0
+  double.max = 47.0
+  schema {
+    fields {
+      c_string = string
+      c_tinyint = tinyint
+      c_smallint = smallint
+      c_int = int
+      c_bigint = bigint
+      c_float = float
+      c_double = double
+    }
+  }
+}
+```
+
 ## Changelog
 
 ### 2.2.0-beta 2022-09-26
@@ -246,4 +440,5 @@ FakeSource {
 
 ### next version
 
-- [Feature] Support config fake data rows [3865](https://github.com/apache/incubator-seatunnel/pull/3865)
\ No newline at end of file
+- [Feature] Support config fake data rows [3865](https://github.com/apache/incubator-seatunnel/pull/3865)
+- [Feature] Support config template or range for fake data [3932](https://github.com/apache/incubator-seatunnel/pull/3932)
\ No newline at end of file
diff --git a/seatunnel-connectors-v2/connector-fake/src/main/java/org/apache/seatunnel/connectors/seatunnel/fake/config/FakeConfig.java b/seatunnel-connectors-v2/connector-fake/src/main/java/org/apache/seatunnel/connectors/seatunnel/fake/config/FakeConfig.java
index 035b755c7..5804ed027 100644
--- a/seatunnel-connectors-v2/connector-fake/src/main/java/org/apache/seatunnel/connectors/seatunnel/fake/config/FakeConfig.java
+++ b/seatunnel-connectors-v2/connector-fake/src/main/java/org/apache/seatunnel/connectors/seatunnel/fake/config/FakeConfig.java
@@ -18,13 +18,48 @@
 package org.apache.seatunnel.connectors.seatunnel.fake.config;
 
 import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.ARRAY_SIZE;
+import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.BIGINT_FAKE_MODE;
+import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.BIGINT_MAX;
+import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.BIGINT_MIN;
+import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.BIGINT_TEMPLATE;
 import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.BYTES_LENGTH;
+import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.DATE_DAY_TEMPLATE;
+import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.DATE_MONTH_TEMPLATE;
+import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.DATE_YEAR_TEMPLATE;
+import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.DOUBLE_FAKE_MODE;
+import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.DOUBLE_MAX;
+import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.DOUBLE_MIN;
+import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.DOUBLE_TEMPLATE;
+import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.FLOAT_FAKE_MODE;
+import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.FLOAT_MAX;
+import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.FLOAT_MIN;
+import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.FLOAT_TEMPLATE;
+import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.INT_FAKE_MODE;
+import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.INT_MAX;
+import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.INT_MIN;
+import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.INT_TEMPLATE;
 import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.MAP_SIZE;
 import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.ROWS;
 import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.ROW_NUM;
+import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.SMALLINT_FAKE_MODE;
+import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.SMALLINT_MAX;
+import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.SMALLINT_MIN;
+import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.SMALLINT_TEMPLATE;
 import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.SPLIT_NUM;
 import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.SPLIT_READ_INTERVAL;
+import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.STRING_FAKE_MODE;
 import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.STRING_LENGTH;
+import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.STRING_TEMPLATE;
+import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.TIME_HOUR_TEMPLATE;
+import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.TIME_MINUTE_TEMPLATE;
+import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.TIME_SECOND_TEMPLATE;
+import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.TINYINT_FAKE_MODE;
+import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.TINYINT_MAX;
+import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.TINYINT_MIN;
+import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.TINYINT_TEMPLATE;
+
+import org.apache.seatunnel.common.exception.CommonErrorCode;
+import org.apache.seatunnel.connectors.seatunnel.fake.exception.FakeConnectorException;
 
 import org.apache.seatunnel.shade.com.typesafe.config.Config;
 import org.apache.seatunnel.shade.com.typesafe.config.ConfigRenderOptions;
@@ -42,18 +77,98 @@ import java.util.List;
 public class FakeConfig implements Serializable {
     @Builder.Default
     private int rowNum = ROW_NUM.defaultValue();
+
     @Builder.Default
     private int splitNum = SPLIT_NUM.defaultValue();
+
     @Builder.Default
     private int splitReadInterval = SPLIT_READ_INTERVAL.defaultValue();
+
     @Builder.Default
     private int mapSize = MAP_SIZE.defaultValue();
+
     @Builder.Default
     private int arraySize = ARRAY_SIZE.defaultValue();
+
     @Builder.Default
     private int bytesLength = BYTES_LENGTH.defaultValue();
+
     @Builder.Default
     private int stringLength = STRING_LENGTH.defaultValue();
+
+    @Builder.Default
+    private int tinyintMin = TINYINT_MIN.defaultValue();
+
+    @Builder.Default
+    private int tinyintMax = TINYINT_MAX.defaultValue();
+
+    @Builder.Default
+    private int smallintMin = SMALLINT_MIN.defaultValue();
+
+    @Builder.Default
+    private int smallintMax = SMALLINT_MAX.defaultValue();
+
+    @Builder.Default
+    private int intMin = INT_MIN.defaultValue();
+
+    @Builder.Default
+    private int intMax = INT_MAX.defaultValue();
+
+    @Builder.Default
+    private long bigintMin = BIGINT_MIN.defaultValue();
+
+    @Builder.Default
+    private long bigintMax = BIGINT_MAX.defaultValue();
+
+    @Builder.Default
+    private double floatMin = FLOAT_MIN.defaultValue();
+
+    @Builder.Default
+    private double floatMax = FLOAT_MAX.defaultValue();
+
+    @Builder.Default
+    private double doubleMin = DOUBLE_MIN.defaultValue();
+
+    @Builder.Default
+    private double doubleMax = DOUBLE_MAX.defaultValue();
+
+    @Builder.Default
+    private FakeOption.FakeMode stringFakeMode = STRING_FAKE_MODE.defaultValue();
+
+    @Builder.Default
+    private FakeOption.FakeMode tinyintFakeMode = TINYINT_FAKE_MODE.defaultValue();
+
+    @Builder.Default
+    private FakeOption.FakeMode smallintFakeMode = SMALLINT_FAKE_MODE.defaultValue();
+
+    @Builder.Default
+    private FakeOption.FakeMode intFakeMode = INT_FAKE_MODE.defaultValue();
+
+    @Builder.Default
+    private FakeOption.FakeMode bigintFakeMode = BIGINT_FAKE_MODE.defaultValue();
+
+    @Builder.Default
+    private FakeOption.FakeMode floatFakeMode = FLOAT_FAKE_MODE.defaultValue();
+
+    @Builder.Default
+    private FakeOption.FakeMode doubleFakeMode = DOUBLE_FAKE_MODE.defaultValue();
+
+    private List<String> stringTemplate;
+    private List<Integer> tinyintTemplate;
+    private List<Integer> smallintTemplate;
+    private List<Integer> intTemplate;
+    private List<Long> bigTemplate;
+    private List<Double> floatTemplate;
+    private List<Double> doubleTemplate;
+
+    private List<Integer> dateYearTemplate;
+    private List<Integer> dateMonthTemplate;
+    private List<Integer> dateDayTemplate;
+
+    private List<Integer> timeHourTemplate;
+    private List<Integer> timeMinuteTemplate;
+    private List<Integer> timeSecondTemplate;
+
     private List<RowData> fakeRows;
 
     public static FakeConfig buildWithConfig(Config config) {
@@ -90,6 +205,174 @@ public class FakeConfig implements Serializable {
             }
             builder.fakeRows(rows);
         }
+        if (config.hasPath(STRING_TEMPLATE.key())) {
+            builder.stringTemplate(config.getStringList(STRING_TEMPLATE.key()));
+        }
+        if (config.hasPath(TINYINT_TEMPLATE.key())) {
+            builder.tinyintTemplate(config.getIntList(TINYINT_TEMPLATE.key()));
+        }
+        if (config.hasPath(SMALLINT_TEMPLATE.key())) {
+            builder.smallintTemplate(config.getIntList(SMALLINT_TEMPLATE.key()));
+        }
+        if (config.hasPath(INT_TEMPLATE.key())) {
+            builder.intTemplate(config.getIntList(INT_TEMPLATE.key()));
+        }
+        if (config.hasPath(BIGINT_TEMPLATE.key())) {
+            builder.bigTemplate(config.getLongList(BIGINT_TEMPLATE.key()));
+        }
+        if (config.hasPath(FLOAT_TEMPLATE.key())) {
+            builder.floatTemplate(config.getDoubleList(FLOAT_TEMPLATE.key()));
+        }
+        if (config.hasPath(DOUBLE_TEMPLATE.key())) {
+            builder.doubleTemplate(config.getDoubleList(DOUBLE_TEMPLATE.key()));
+        }
+        if (config.hasPath(DATE_YEAR_TEMPLATE.key())) {
+            builder.dateYearTemplate(config.getIntList(DATE_YEAR_TEMPLATE.key()));
+        }
+        if (config.hasPath(DATE_MONTH_TEMPLATE.key())) {
+            builder.dateMonthTemplate(config.getIntList(DATE_MONTH_TEMPLATE.key()));
+        }
+        if (config.hasPath(DATE_DAY_TEMPLATE.key())) {
+            builder.dateDayTemplate(config.getIntList(DATE_DAY_TEMPLATE.key()));
+        }
+        if (config.hasPath(TIME_HOUR_TEMPLATE.key())) {
+            builder.timeHourTemplate(config.getIntList(TIME_HOUR_TEMPLATE.key()));
+        }
+        if (config.hasPath(TIME_MINUTE_TEMPLATE.key())) {
+            builder.timeMinuteTemplate(config.getIntList(TIME_MINUTE_TEMPLATE.key()));
+        }
+        if (config.hasPath(TIME_SECOND_TEMPLATE.key())) {
+            builder.timeSecondTemplate(config.getIntList(TIME_SECOND_TEMPLATE.key()));
+        }
+        if (config.hasPath(TINYINT_MIN.key())) {
+            int tinyintMin = config.getInt(TINYINT_MIN.key());
+            if (tinyintMin < TINYINT_MIN.defaultValue() || tinyintMin > TINYINT_MAX.defaultValue()) {
+                throw new FakeConnectorException(CommonErrorCode.ILLEGAL_ARGUMENT,
+                        TINYINT_MIN.key() + " should >= " + TINYINT_MIN.defaultValue() +
+                                " and <= " + TINYINT_MAX.defaultValue());
+            }
+            builder.tinyintMin(tinyintMin);
+        }
+        if (config.hasPath(TINYINT_MAX.key())) {
+            int tinyintMax = config.getInt(TINYINT_MAX.key());
+            if (tinyintMax < TINYINT_MIN.defaultValue() || tinyintMax > TINYINT_MAX.defaultValue()) {
+                throw new FakeConnectorException(CommonErrorCode.ILLEGAL_ARGUMENT,
+                        TINYINT_MAX.key() + " should >= " + TINYINT_MIN.defaultValue() +
+                                " and <= " + TINYINT_MAX.defaultValue());
+            }
+            builder.tinyintMax(tinyintMax);
+        }
+        if (config.hasPath(SMALLINT_MIN.key())) {
+            int smallintMin = config.getInt(SMALLINT_MIN.key());
+            if (smallintMin < SMALLINT_MIN.defaultValue() || smallintMin > SMALLINT_MAX.defaultValue()) {
+                throw new FakeConnectorException(CommonErrorCode.ILLEGAL_ARGUMENT,
+                        SMALLINT_MIN.key() + " should >= " + SMALLINT_MIN.defaultValue() +
+                                " and <= " + SMALLINT_MAX.defaultValue());
+            }
+            builder.smallintMin(smallintMin);
+        }
+        if (config.hasPath(SMALLINT_MAX.key())) {
+            int smallintMax = config.getInt(SMALLINT_MAX.key());
+            if (smallintMax < SMALLINT_MIN.defaultValue() || smallintMax > SMALLINT_MAX.defaultValue()) {
+                throw new FakeConnectorException(CommonErrorCode.ILLEGAL_ARGUMENT,
+                        SMALLINT_MAX.key() + " should >= " + SMALLINT_MIN.defaultValue() +
+                                " and <= " + SMALLINT_MAX.defaultValue());
+            }
+            builder.smallintMax(smallintMax);
+        }
+        if (config.hasPath(INT_MIN.key())) {
+            int intMin = config.getInt(INT_MIN.key());
+            if (intMin < INT_MIN.defaultValue() || intMin > INT_MAX.defaultValue()) {
+                throw new FakeConnectorException(CommonErrorCode.ILLEGAL_ARGUMENT,
+                        INT_MIN.key() + " should >= " + INT_MIN.defaultValue() +
+                                " and <= " + INT_MAX.defaultValue());
+            }
+            builder.intMin(intMin);
+        }
+        if (config.hasPath(INT_MAX.key())) {
+            int intMax = config.getInt(INT_MAX.key());
+            if (intMax < INT_MIN.defaultValue() || intMax > INT_MAX.defaultValue()) {
+                throw new FakeConnectorException(CommonErrorCode.ILLEGAL_ARGUMENT,
+                        INT_MAX.key() + " should >= " + INT_MIN.defaultValue() +
+                                " and <= " + INT_MAX.defaultValue());
+            }
+            builder.intMax(intMax);
+        }
+        if (config.hasPath(BIGINT_MIN.key())) {
+            long bigintMin = config.getLong(BIGINT_MIN.key());
+            if (bigintMin < BIGINT_MIN.defaultValue() || bigintMin > BIGINT_MAX.defaultValue()) {
+                throw new FakeConnectorException(CommonErrorCode.ILLEGAL_ARGUMENT,
+                        BIGINT_MIN.key() + " should >= " + BIGINT_MIN.defaultValue() +
+                                " and <= " + BIGINT_MAX.defaultValue());
+            }
+            builder.bigintMin(bigintMin);
+        }
+        if (config.hasPath(BIGINT_MAX.key())) {
+            long bigintMax = config.getLong(BIGINT_MAX.key());
+            if (bigintMax < BIGINT_MIN.defaultValue() || bigintMax > BIGINT_MAX.defaultValue()) {
+                throw new FakeConnectorException(CommonErrorCode.ILLEGAL_ARGUMENT,
+                        BIGINT_MAX.key() + " should >= " + BIGINT_MIN.defaultValue() +
+                                " and <= " + BIGINT_MAX.defaultValue());
+            }
+            builder.bigintMax(bigintMax);
+        }
+        if (config.hasPath(FLOAT_MIN.key())) {
+            double floatMin = config.getDouble(FLOAT_MIN.key());
+            if (floatMin < FLOAT_MIN.defaultValue() || floatMin > FLOAT_MAX.defaultValue()) {
+                throw new FakeConnectorException(CommonErrorCode.ILLEGAL_ARGUMENT,
+                        FLOAT_MIN.key() + " should >= " + FLOAT_MIN.defaultValue() +
+                                " and <= " + FLOAT_MAX.defaultValue());
+            }
+            builder.floatMin(floatMin);
+        }
+        if (config.hasPath(FLOAT_MAX.key())) {
+            double floatMax = config.getDouble(FLOAT_MAX.key());
+            if (floatMax < FLOAT_MIN.defaultValue() || floatMax > FLOAT_MAX.defaultValue()) {
+                throw new FakeConnectorException(CommonErrorCode.ILLEGAL_ARGUMENT,
+                        FLOAT_MAX.key() + " should >= " + FLOAT_MIN.defaultValue() +
+                                " and <= " + FLOAT_MAX.defaultValue());
+            }
+            builder.floatMax(floatMax);
+        }
+        if (config.hasPath(DOUBLE_MIN.key())) {
+            double doubleMin = config.getDouble(DOUBLE_MIN.key());
+            if (doubleMin < DOUBLE_MIN.defaultValue() || doubleMin > DOUBLE_MAX.defaultValue()) {
+                throw new FakeConnectorException(CommonErrorCode.ILLEGAL_ARGUMENT,
+                        DOUBLE_MIN.key() + " should >= " + DOUBLE_MIN.defaultValue() +
+                                " and <= " + DOUBLE_MAX.defaultValue());
+            }
+            builder.doubleMin(doubleMin);
+        }
+        if (config.hasPath(DOUBLE_MAX.key())) {
+            double doubleMax = config.getDouble(DOUBLE_MAX.key());
+            if (doubleMax < DOUBLE_MIN.defaultValue() || doubleMax > DOUBLE_MAX.defaultValue()) {
+                throw new FakeConnectorException(CommonErrorCode.ILLEGAL_ARGUMENT,
+                        DOUBLE_MAX.key() + " should >= " + DOUBLE_MIN.defaultValue() +
+                                " and <= " + DOUBLE_MAX.defaultValue());
+            }
+            builder.doubleMax(doubleMax);
+        }
+        if (config.hasPath(STRING_FAKE_MODE.key())) {
+            builder.stringFakeMode(FakeOption.FakeMode.parse(config.getString(STRING_FAKE_MODE.key())));
+        }
+        if (config.hasPath(TINYINT_FAKE_MODE.key())) {
+            builder.tinyintFakeMode(FakeOption.FakeMode.parse(config.getString(TINYINT_FAKE_MODE.key())));
+        }
+        if (config.hasPath(SMALLINT_FAKE_MODE.key())) {
+            builder.smallintFakeMode(FakeOption.FakeMode.parse(config.getString(SMALLINT_FAKE_MODE.key())));
+        }
+        if (config.hasPath(INT_FAKE_MODE.key())) {
+            builder.intFakeMode(FakeOption.FakeMode.parse(config.getString(INT_FAKE_MODE.key())));
+        }
+        if (config.hasPath(BIGINT_FAKE_MODE.key())) {
+            builder.bigintFakeMode(FakeOption.FakeMode.parse(config.getString(BIGINT_FAKE_MODE.key())));
+        }
+        if (config.hasPath(FLOAT_FAKE_MODE.key())) {
+            builder.floatFakeMode(FakeOption.FakeMode.parse(config.getString(FLOAT_FAKE_MODE.key())));
+        }
+        if (config.hasPath(DOUBLE_FAKE_MODE.key())) {
+            builder.doubleFakeMode(FakeOption.FakeMode.parse(config.getString(DOUBLE_FAKE_MODE.key())));
+        }
         return builder.build();
     }
 
diff --git a/seatunnel-connectors-v2/connector-fake/src/main/java/org/apache/seatunnel/connectors/seatunnel/fake/config/FakeOption.java b/seatunnel-connectors-v2/connector-fake/src/main/java/org/apache/seatunnel/connectors/seatunnel/fake/config/FakeOption.java
index c50ed0078..9c123cdf3 100644
--- a/seatunnel-connectors-v2/connector-fake/src/main/java/org/apache/seatunnel/connectors/seatunnel/fake/config/FakeOption.java
+++ b/seatunnel-connectors-v2/connector-fake/src/main/java/org/apache/seatunnel/connectors/seatunnel/fake/config/FakeOption.java
@@ -26,21 +26,206 @@ import java.util.List;
 @SuppressWarnings("checkstyle:MagicNumber")
 public class FakeOption {
 
-    public static final Option<List<SeaTunnelRow>> ROWS = Options.key("rows").listType(SeaTunnelRow.class).noDefaultValue()
-        .withDescription("The row list of fake data output per degree of parallelism");
-    public static final Option<Integer> ROW_NUM = Options.key("row.num").intType().defaultValue(5)
-        .withDescription("The total number of data generated per degree of parallelism");
-    public static final Option<Integer> SPLIT_NUM = Options.key("split.num").intType().defaultValue(1)
-        .withDescription("The number of splits generated by the enumerator for each degree of parallelism");
-    public static final Option<Integer> SPLIT_READ_INTERVAL = Options.key("split.read-interval").intType().defaultValue(1)
-        .withDescription("The interval(mills) between two split reads in a reader");
-    public static final Option<Integer> MAP_SIZE = Options.key("map.size").intType().defaultValue(5)
-        .withDescription("The size of map type that connector generated");
-    public static final Option<Integer> ARRAY_SIZE = Options.key("array.size").intType().defaultValue(5)
-        .withDescription("The size of array type that connector generated");
-    public static final Option<Integer> BYTES_LENGTH = Options.key("bytes.length").intType().defaultValue(5)
-        .withDescription("The length of bytes type that connector generated");
-    public static final Option<Integer> STRING_LENGTH = Options.key("string.length").intType().defaultValue(5)
-        .withDescription("The length of string type that connector generated");
+    public static final Option<List<SeaTunnelRow>> ROWS = Options.key("rows")
+            .listType(SeaTunnelRow.class)
+            .noDefaultValue()
+            .withDescription("The row list of fake data output per degree of parallelism");
+    public static final Option<Integer> ROW_NUM = Options.key("row.num")
+            .intType()
+            .defaultValue(5)
+            .withDescription("The total number of data generated per degree of parallelism");
+    public static final Option<Integer> SPLIT_NUM = Options.key("split.num")
+            .intType()
+            .defaultValue(1)
+            .withDescription("The number of splits generated by the enumerator for each degree of parallelism");
+    public static final Option<Integer> SPLIT_READ_INTERVAL = Options.key("split.read-interval")
+            .intType()
+            .defaultValue(1)
+            .withDescription("The interval(mills) between two split reads in a reader");
+    public static final Option<Integer> MAP_SIZE = Options.key("map.size")
+            .intType()
+            .defaultValue(5)
+            .withDescription("The size of map type that connector generated");
+    public static final Option<Integer> ARRAY_SIZE = Options.key("array.size")
+            .intType()
+            .defaultValue(5)
+            .withDescription("The size of array type that connector generated");
+    public static final Option<Integer> BYTES_LENGTH = Options.key("bytes.length")
+            .intType()
+            .defaultValue(5)
+            .withDescription("The length of bytes type that connector generated");
+    public static final Option<Integer> STRING_LENGTH = Options.key("string.length")
+            .intType()
+            .defaultValue(5)
+            .withDescription("The length of string type that connector generated");
 
+    public static final Option<List<String>> STRING_TEMPLATE = Options.key("string.template")
+            .listType()
+            .noDefaultValue()
+            .withDescription("The template list of string type that connector generated, if user configured it, connector will randomly select an item from the template list");
+
+    public static final Option<List<Integer>> TINYINT_TEMPLATE = Options.key("tinyint.template")
+            .listType(Integer.class)
+            .noDefaultValue()
+            .withDescription("The template list of tinyint type, if user configured it, connector will randomly select an item from the template list");
+
+    public static final Option<List<Integer>> SMALLINT_TEMPLATE = Options.key("smallint.template")
+            .listType(Integer.class)
+            .noDefaultValue()
+            .withDescription("The template list of smallint type, if user configured it, connector will randomly select an item from the template list");
+
+    public static final Option<List<Integer>> INT_TEMPLATE = Options.key("int.template")
+            .listType(Integer.class)
+            .noDefaultValue()
+            .withDescription("The template list of int type, if user configured it, connector will randomly select an item from the template list");
+
+    public static final Option<List<Long>> BIGINT_TEMPLATE = Options.key("bigint.template")
+            .listType(Long.class)
+            .noDefaultValue()
+            .withDescription("The template list of bigint type, if user configured it, connector will randomly select an item from the template list");
+
+    public static final Option<List<Double>> FLOAT_TEMPLATE = Options.key("float.template")
+            .listType(Double.class)
+            .noDefaultValue()
+            .withDescription("The template list of float type, if user configured it, connector will randomly select an item from the template list");
+
+    public static final Option<List<Double>> DOUBLE_TEMPLATE = Options.key("double.template")
+            .listType(Double.class)
+            .noDefaultValue()
+            .withDescription("The template list of double type, if user configured it, connector will randomly select an item from the template list");
+
+    public static final Option<List<Integer>> DATE_YEAR_TEMPLATE = Options.key("date.year.template")
+            .listType(Integer.class)
+            .noDefaultValue()
+            .withDescription("The template list of year of date like 'yyyy', if user configured it, connector will randomly select an item from the template list");
+
+    public static final Option<List<Integer>> DATE_MONTH_TEMPLATE = Options.key("date.month.template")
+            .listType(Integer.class)
+            .noDefaultValue()
+            .withDescription("The template list of month of date like 'MM', if user configured it, connector will randomly select an item from the template list");
+
+    public static final Option<List<Integer>> DATE_DAY_TEMPLATE = Options.key("date.day.template")
+            .listType(Integer.class)
+            .noDefaultValue()
+            .withDescription("The template list of day of date like 'dd', if user configured it, connector will randomly select an item from the template list");
+
+    public static final Option<List<Integer>> TIME_HOUR_TEMPLATE = Options.key("time.hour.template")
+            .listType(Integer.class)
+            .noDefaultValue()
+            .withDescription("The template list of hour of time like 'HH', if user configured it, connector will randomly select an item from the template list");
+
+    public static final Option<List<Integer>> TIME_MINUTE_TEMPLATE = Options.key("time.minute.template")
+            .listType(Integer.class)
+            .noDefaultValue()
+            .withDescription("The template list of minute of time like 'mm', if user configured it, connector will randomly select an item from the template list");
+
+    public static final Option<List<Integer>> TIME_SECOND_TEMPLATE = Options.key("time.second.template")
+            .listType(Integer.class)
+            .noDefaultValue()
+            .withDescription("The template list of second of time like 'ss', if user configured it, connector will randomly select an item from the template list");
+
+    public static final Option<Integer> TINYINT_MIN = Options.key("tinyint.min")
+            .intType()
+            .defaultValue(0)
+            .withDescription("The min value of tinyint type data");
+
+    public static final Option<Integer> TINYINT_MAX = Options.key("tinyint.max")
+            .intType()
+            .defaultValue((int) Byte.MAX_VALUE)
+            .withDescription("The min value of tinyint type data");
+
+    public static final Option<Integer> SMALLINT_MIN = Options.key("smallint.min")
+            .intType()
+            .defaultValue(0)
+            .withDescription("The min value of smallint type data");
+
+    public static final Option<Integer> SMALLINT_MAX = Options.key("smallint.max")
+            .intType()
+            .defaultValue((int) Short.MAX_VALUE)
+            .withDescription("The max value of smallint type data");
+
+    public static final Option<Integer> INT_MIN = Options.key("int.min")
+            .intType()
+            .defaultValue(0)
+            .withDescription("The min value of int type data");
+
+    public static final Option<Integer> INT_MAX = Options.key("int.max")
+            .intType()
+            .defaultValue(Integer.MAX_VALUE)
+            .withDescription("The max value of int type data");
+
+    public static final Option<Long> BIGINT_MIN = Options.key("bigint.min")
+            .longType()
+            .defaultValue(0L)
+            .withDescription("The min value of bigint type data");
+
+    public static final Option<Long> BIGINT_MAX = Options.key("bigint.max")
+            .longType()
+            .defaultValue(Long.MAX_VALUE)
+            .withDescription("The max value of bigint type data");
+
+    public static final Option<Float> FLOAT_MIN = Options.key("float.min")
+            .floatType()
+            .defaultValue(0F)
+            .withDescription("The min value of float type data");
+
+    public static final Option<Float> FLOAT_MAX = Options.key("float.max")
+            .floatType()
+            .defaultValue(Float.MAX_VALUE)
+            .withDescription("The max value of float type data");
+
+    public static final Option<Double> DOUBLE_MIN = Options.key("double.min")
+            .doubleType()
+            .defaultValue(0D)
+            .withDescription("The min value of double type data");
+
+    public static final Option<Double> DOUBLE_MAX = Options.key("double.max")
+            .doubleType()
+            .defaultValue(Double.MAX_VALUE)
+            .withDescription("The max value of double type data");
+
+    public static final Option<FakeMode> STRING_FAKE_MODE = Options.key("string.fake.mode")
+            .enumType(FakeMode.class)
+            .defaultValue(FakeMode.RANGE)
+            .withDescription("The fake mode of generating string data");
+
+    public static final Option<FakeMode> TINYINT_FAKE_MODE = Options.key("tinyint.fake.mode")
+            .enumType(FakeMode.class)
+            .defaultValue(FakeMode.RANGE)
+            .withDescription("The fake mode of generating tinyint data");
+
+
+    public static final Option<FakeMode> SMALLINT_FAKE_MODE = Options.key("smallint.fake.mode")
+            .enumType(FakeMode.class)
+            .defaultValue(FakeMode.RANGE)
+            .withDescription("The fake mode of generating smallint data");
+
+    public static final Option<FakeMode> INT_FAKE_MODE = Options.key("int.fake.mode")
+            .enumType(FakeMode.class)
+            .defaultValue(FakeMode.RANGE)
+            .withDescription("The fake mode of generating int data");
+
+    public static final Option<FakeMode> BIGINT_FAKE_MODE = Options.key("bigint.fake.mode")
+            .enumType(FakeMode.class)
+            .defaultValue(FakeMode.RANGE)
+            .withDescription("The fake mode of generating bigint data");
+
+    public static final Option<FakeMode> FLOAT_FAKE_MODE = Options.key("float.fake.mode")
+            .enumType(FakeMode.class)
+            .defaultValue(FakeMode.RANGE)
+            .withDescription("The fake mode of generating float data");
+
+    public static final Option<FakeMode> DOUBLE_FAKE_MODE = Options.key("double.fake.mode")
+            .enumType(FakeMode.class)
+            .defaultValue(FakeMode.RANGE)
+            .withDescription("The fake mode of generating double data");
+
+    public enum FakeMode {
+        RANGE,
+        TEMPLATE;
+
+        public static FakeMode parse(String s) {
+            return FakeMode.valueOf(s.toUpperCase());
+        }
+    }
 }
diff --git a/seatunnel-connectors-v2/connector-fake/src/main/java/org/apache/seatunnel/connectors/seatunnel/fake/source/FakeDataGenerator.java b/seatunnel-connectors-v2/connector-fake/src/main/java/org/apache/seatunnel/connectors/seatunnel/fake/source/FakeDataGenerator.java
index 5848bf3d6..3f44bf821 100644
--- a/seatunnel-connectors-v2/connector-fake/src/main/java/org/apache/seatunnel/connectors/seatunnel/fake/source/FakeDataGenerator.java
+++ b/seatunnel-connectors-v2/connector-fake/src/main/java/org/apache/seatunnel/connectors/seatunnel/fake/source/FakeDataGenerator.java
@@ -29,24 +29,20 @@ import org.apache.seatunnel.common.exception.CommonErrorCode;
 import org.apache.seatunnel.connectors.seatunnel.common.schema.SeaTunnelSchema;
 import org.apache.seatunnel.connectors.seatunnel.fake.config.FakeConfig;
 import org.apache.seatunnel.connectors.seatunnel.fake.exception.FakeConnectorException;
+import org.apache.seatunnel.connectors.seatunnel.fake.utils.FakeDataRandomUtils;
 import org.apache.seatunnel.format.json.JsonDeserializationSchema;
 
-import org.apache.commons.lang3.RandomStringUtils;
-import org.apache.commons.lang3.RandomUtils;
-
 import java.io.IOException;
 import java.lang.reflect.Array;
-import java.math.BigDecimal;
-import java.time.LocalDateTime;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 
 public class FakeDataGenerator {
-    public static final String SCHEMA = "schema";
     private final SeaTunnelSchema schema;
     private final FakeConfig fakeConfig;
     private final JsonDeserializationSchema jsonDeserializationSchema;
+    private final FakeDataRandomUtils fakeDataRandomUtils;
 
     public FakeDataGenerator(SeaTunnelSchema schema, FakeConfig fakeConfig) {
         this.schema = schema;
@@ -55,6 +51,7 @@ public class FakeDataGenerator {
             null :
             new JsonDeserializationSchema(
                 false, false, schema.getSeaTunnelRowType());
+        this.fakeDataRandomUtils = new FakeDataRandomUtils(fakeConfig);
     }
 
     private SeaTunnelRow convertRow(FakeConfig.RowData rowData) {
@@ -121,35 +118,34 @@ public class FakeDataGenerator {
                 }
                 return objectMap;
             case STRING:
-                return RandomStringUtils.randomAlphabetic(fakeConfig.getStringLength());
+                return fakeDataRandomUtils.randomString();
             case BOOLEAN:
-                return RandomUtils.nextInt(0, 2) == 1;
+                return fakeDataRandomUtils.randomBoolean();
             case TINYINT:
-                return (byte) RandomUtils.nextInt(0, 255);
+                return fakeDataRandomUtils.randomTinyint();
             case SMALLINT:
-                return (short) RandomUtils.nextInt(Byte.MAX_VALUE, Short.MAX_VALUE);
+                return fakeDataRandomUtils.randomSmallint();
             case INT:
-                return RandomUtils.nextInt(Short.MAX_VALUE, Integer.MAX_VALUE);
+                return fakeDataRandomUtils.randomInt();
             case BIGINT:
-                return RandomUtils.nextLong(Integer.MAX_VALUE, Long.MAX_VALUE);
+                return fakeDataRandomUtils.randomBigint();
             case FLOAT:
-                return RandomUtils.nextFloat(Float.MIN_VALUE, Float.MAX_VALUE);
+                return fakeDataRandomUtils.randomFloat();
             case DOUBLE:
-                return RandomUtils.nextDouble(Float.MAX_VALUE, Double.MAX_VALUE);
+                return fakeDataRandomUtils.randomDouble();
             case DECIMAL:
                 DecimalType decimalType = (DecimalType) fieldType;
-                return new BigDecimal(RandomStringUtils.randomNumeric(decimalType.getPrecision() - decimalType.getScale()) + "." +
-                        RandomStringUtils.randomNumeric(decimalType.getScale()));
+                return fakeDataRandomUtils.randomBigDecimal(decimalType.getPrecision(), decimalType.getScale());
             case NULL:
                 return null;
             case BYTES:
-                return RandomStringUtils.randomAlphabetic(fakeConfig.getBytesLength()).getBytes();
+                return fakeDataRandomUtils.randomBytes();
             case DATE:
-                return randomLocalDateTime().toLocalDate();
+                return fakeDataRandomUtils.randomLocalDate();
             case TIME:
-                return randomLocalDateTime().toLocalTime();
+                return fakeDataRandomUtils.randomLocalTime();
             case TIMESTAMP:
-                return randomLocalDateTime();
+                return fakeDataRandomUtils.randomLocalDateTime();
             case ROW:
                 SeaTunnelDataType<?>[] fieldTypes = ((SeaTunnelRowType) fieldType).getFieldTypes();
                 Object[] objects = new Object[fieldTypes.length];
@@ -164,15 +160,4 @@ public class FakeDataGenerator {
                         "SeaTunnel Fake source connector not support this data type");
         }
     }
-
-    @SuppressWarnings("magicnumber")
-    private LocalDateTime randomLocalDateTime() {
-        return LocalDateTime.of(
-            LocalDateTime.now().getYear(),
-            RandomUtils.nextInt(1, 12),
-            RandomUtils.nextInt(1, 28),
-            RandomUtils.nextInt(0, 24),
-            RandomUtils.nextInt(0, 59)
-        );
-    }
 }
diff --git a/seatunnel-connectors-v2/connector-fake/src/main/java/org/apache/seatunnel/connectors/seatunnel/fake/source/FakeSourceFactory.java b/seatunnel-connectors-v2/connector-fake/src/main/java/org/apache/seatunnel/connectors/seatunnel/fake/source/FakeSourceFactory.java
index f4822ea56..a0726d6cb 100644
--- a/seatunnel-connectors-v2/connector-fake/src/main/java/org/apache/seatunnel/connectors/seatunnel/fake/source/FakeSourceFactory.java
+++ b/seatunnel-connectors-v2/connector-fake/src/main/java/org/apache/seatunnel/connectors/seatunnel/fake/source/FakeSourceFactory.java
@@ -18,19 +18,39 @@
 package org.apache.seatunnel.connectors.seatunnel.fake.source;
 
 import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.ARRAY_SIZE;
+import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.BIGINT_FAKE_MODE;
+import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.BIGINT_TEMPLATE;
 import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.BYTES_LENGTH;
+import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.DATE_DAY_TEMPLATE;
+import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.DATE_MONTH_TEMPLATE;
+import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.DATE_YEAR_TEMPLATE;
+import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.DOUBLE_FAKE_MODE;
+import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.DOUBLE_TEMPLATE;
+import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.FLOAT_FAKE_MODE;
+import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.FLOAT_TEMPLATE;
+import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.INT_FAKE_MODE;
+import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.INT_TEMPLATE;
 import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.MAP_SIZE;
 import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.ROWS;
 import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.ROW_NUM;
+import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.SMALLINT_FAKE_MODE;
+import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.SMALLINT_TEMPLATE;
 import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.SPLIT_NUM;
 import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.SPLIT_READ_INTERVAL;
-import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.STRING_LENGTH;
+import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.STRING_FAKE_MODE;
+import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.STRING_TEMPLATE;
+import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.TIME_HOUR_TEMPLATE;
+import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.TIME_MINUTE_TEMPLATE;
+import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.TIME_SECOND_TEMPLATE;
+import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.TINYINT_FAKE_MODE;
+import static org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption.TINYINT_TEMPLATE;
 
 import org.apache.seatunnel.api.configuration.util.OptionRule;
 import org.apache.seatunnel.api.source.SeaTunnelSource;
 import org.apache.seatunnel.api.table.factory.Factory;
 import org.apache.seatunnel.api.table.factory.TableSourceFactory;
 import org.apache.seatunnel.connectors.seatunnel.common.schema.SeaTunnelSchema;
+import org.apache.seatunnel.connectors.seatunnel.fake.config.FakeOption;
 
 import com.google.auto.service.AutoService;
 
@@ -44,17 +64,32 @@ public class FakeSourceFactory implements TableSourceFactory {
     @Override
     public OptionRule optionRule() {
         return OptionRule.builder()
-            .required(SeaTunnelSchema.SCHEMA)
-            .optional(
-                ROWS,
-                ROW_NUM,
-                SPLIT_NUM,
-                SPLIT_READ_INTERVAL,
-                MAP_SIZE,
-                ARRAY_SIZE,
-                BYTES_LENGTH,
-                STRING_LENGTH)
-            .build();
+                .required(SeaTunnelSchema.SCHEMA)
+                .optional(STRING_FAKE_MODE)
+                .conditional(STRING_FAKE_MODE, FakeOption.FakeMode.TEMPLATE, STRING_TEMPLATE)
+                .optional(TINYINT_FAKE_MODE)
+                .conditional(TINYINT_FAKE_MODE, FakeOption.FakeMode.TEMPLATE, TINYINT_TEMPLATE)
+                .optional(SMALLINT_FAKE_MODE)
+                .conditional(SMALLINT_FAKE_MODE, FakeOption.FakeMode.TEMPLATE, SMALLINT_TEMPLATE)
+                .optional(INT_FAKE_MODE)
+                .conditional(INT_FAKE_MODE, FakeOption.FakeMode.TEMPLATE, INT_TEMPLATE)
+                .optional(BIGINT_FAKE_MODE)
+                .conditional(BIGINT_FAKE_MODE, FakeOption.FakeMode.TEMPLATE, BIGINT_TEMPLATE)
+                .optional(FLOAT_FAKE_MODE)
+                .conditional(FLOAT_FAKE_MODE, FakeOption.FakeMode.TEMPLATE, FLOAT_TEMPLATE)
+                .optional(DOUBLE_FAKE_MODE)
+                .conditional(DOUBLE_FAKE_MODE, FakeOption.FakeMode.TEMPLATE, DOUBLE_TEMPLATE)
+                .optional(
+                        ROWS,
+                        ROW_NUM,
+                        SPLIT_NUM,
+                        SPLIT_READ_INTERVAL,
+                        MAP_SIZE,
+                        ARRAY_SIZE,
+                        BYTES_LENGTH,
+                        DATE_YEAR_TEMPLATE, DATE_MONTH_TEMPLATE, DATE_DAY_TEMPLATE,
+                        TIME_HOUR_TEMPLATE, TIME_MINUTE_TEMPLATE, TIME_SECOND_TEMPLATE)
+                .build();
     }
 
     @Override
diff --git a/seatunnel-connectors-v2/connector-fake/src/main/java/org/apache/seatunnel/connectors/seatunnel/fake/source/FakeSourceSplitEnumerator.java b/seatunnel-connectors-v2/connector-fake/src/main/java/org/apache/seatunnel/connectors/seatunnel/fake/source/FakeSourceSplitEnumerator.java
index 04144834b..3c703825e 100644
--- a/seatunnel-connectors-v2/connector-fake/src/main/java/org/apache/seatunnel/connectors/seatunnel/fake/source/FakeSourceSplitEnumerator.java
+++ b/seatunnel-connectors-v2/connector-fake/src/main/java/org/apache/seatunnel/connectors/seatunnel/fake/source/FakeSourceSplitEnumerator.java
@@ -21,8 +21,7 @@ import org.apache.seatunnel.api.source.SourceSplitEnumerator;
 import org.apache.seatunnel.connectors.seatunnel.fake.config.FakeConfig;
 import org.apache.seatunnel.connectors.seatunnel.fake.state.FakeSourceState;
 
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import lombok.extern.slf4j.Slf4j;
 
 import java.io.IOException;
 import java.util.ArrayList;
@@ -33,9 +32,8 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+@Slf4j
 public class FakeSourceSplitEnumerator implements SourceSplitEnumerator<FakeSourceSplit, FakeSourceState> {
-
-    private static final Logger LOG = LoggerFactory.getLogger(FakeSourceSplitEnumerator.class);
     private final SourceSplitEnumerator.Context<FakeSourceSplit> enumeratorContext;
     private final Map<Integer, Set<FakeSourceSplit>> pendingSplits;
 
@@ -102,7 +100,7 @@ public class FakeSourceSplitEnumerator implements SourceSplitEnumerator<FakeSour
 
     private void discoverySplits() {
         Set<FakeSourceSplit> allSplit = new HashSet<>();
-        LOG.info("Starting to calculate splits.");
+        log.info("Starting to calculate splits.");
         int numReaders = enumeratorContext.currentParallelism();
         int readerRowNum = fakeConfig.getRowNum();
         int splitNum  = fakeConfig.getSplitNum();
@@ -116,8 +114,8 @@ public class FakeSourceSplitEnumerator implements SourceSplitEnumerator<FakeSour
 
         assignedSplits.forEach(allSplit::remove);
         addSplitChangeToPendingAssignments(allSplit);
-        LOG.debug("Assigned {} to {} readers.", allSplit, numReaders);
-        LOG.info("Calculated splits successfully, the size of splits is {}.", allSplit.size());
+        log.debug("Assigned {} to {} readers.", allSplit, numReaders);
+        log.info("Calculated splits successfully, the size of splits is {}.", allSplit.size());
     }
 
     private void addSplitChangeToPendingAssignments(Collection<FakeSourceSplit> newSplits) {
@@ -139,7 +137,7 @@ public class FakeSourceSplitEnumerator implements SourceSplitEnumerator<FakeSour
                 // Mark pending splits as already assigned
                 assignedSplits.addAll(pendingAssignmentForReader);
                 // Assign pending splits to reader
-                LOG.info("Assigning splits to readers {} {}", pendingReader, pendingAssignmentForReader);
+                log.info("Assigning splits to readers {} {}", pendingReader, pendingAssignmentForReader);
                 enumeratorContext.assignSplit(pendingReader, new ArrayList<>(pendingAssignmentForReader));
                 enumeratorContext.signalNoMoreSplits(pendingReader);
             }
diff --git a/seatunnel-connectors-v2/connector-fake/src/main/java/org/apache/seatunnel/connectors/seatunnel/fake/utils/FakeDataRandomUtils.java b/seatunnel-connectors-v2/connector-fake/src/main/java/org/apache/seatunnel/connectors/seatunnel/fake/utils/FakeDataRandomUtils.java
new file mode 100644
index 000000000..7ad5eedc6
--- /dev/null
+++ b/seatunnel-connectors-v2/connector-fake/src/main/java/org/apache/seatunnel/connectors/seatunnel/fake/utils/FakeDataRandomUtils.java
@@ -0,0 +1,167 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.seatunnel.connectors.seatunnel.fake.utils;
+
+import org.apache.seatunnel.connectors.seatunnel.fake.config.FakeConfig;
+
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.RandomStringUtils;
+import org.apache.commons.lang3.RandomUtils;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.util.List;
+
+public class FakeDataRandomUtils {
+    private final FakeConfig fakeConfig;
+
+    public FakeDataRandomUtils(FakeConfig fakeConfig) {
+        this.fakeConfig = fakeConfig;
+    }
+
+    private static <T> T randomFromList(List<T> list) {
+        int index = RandomUtils.nextInt(0, list.size() - 1);
+        return list.get(index);
+    }
+
+    public Boolean randomBoolean() {
+        return RandomUtils.nextInt(0, 2) == 1;
+    }
+
+    public BigDecimal randomBigDecimal(int precision, int scale) {
+        return new BigDecimal(RandomStringUtils.randomNumeric(precision - scale) + "." +
+                RandomStringUtils.randomNumeric(scale));
+    }
+
+    public byte[] randomBytes() {
+        return RandomStringUtils.randomAlphabetic(fakeConfig.getBytesLength()).getBytes();
+    }
+
+    public String randomString() {
+        List<String> stringTemplate = fakeConfig.getStringTemplate();
+        if (!CollectionUtils.isEmpty(stringTemplate)) {
+            return randomFromList(stringTemplate);
+        }
+        return RandomStringUtils.randomAlphabetic(fakeConfig.getStringLength());
+    }
+
+    public Byte randomTinyint() {
+        List<Integer> tinyintTemplate = fakeConfig.getTinyintTemplate();
+        if (!CollectionUtils.isEmpty(tinyintTemplate)) {
+            return randomFromList(tinyintTemplate).byteValue();
+        }
+        return (byte) RandomUtils.nextInt(fakeConfig.getTinyintMin(), fakeConfig.getTinyintMax());
+    }
+
+    public Short randomSmallint() {
+        List<Integer> smallintTemplate = fakeConfig.getSmallintTemplate();
+        if (!CollectionUtils.isEmpty(smallintTemplate)) {
+            return randomFromList(smallintTemplate).shortValue();
+        }
+        return (short) RandomUtils.nextInt(fakeConfig.getSmallintMin(), fakeConfig.getSmallintMax());
+    }
+
+    public Integer randomInt() {
+        List<Integer> intTemplate = fakeConfig.getIntTemplate();
+        if (!CollectionUtils.isEmpty(intTemplate)) {
+            return randomFromList(intTemplate);
+        }
+        return RandomUtils.nextInt(fakeConfig.getIntMin(), fakeConfig.getIntMax());
+    }
+
+    public Long randomBigint() {
+        List<Long> bigTemplate = fakeConfig.getBigTemplate();
+        if (!CollectionUtils.isEmpty(bigTemplate)) {
+            return randomFromList(bigTemplate);
+        }
+        return RandomUtils.nextLong(fakeConfig.getBigintMin(), fakeConfig.getBigintMax());
+    }
+
+    public Float randomFloat() {
+        List<Double> floatTemplate = fakeConfig.getFloatTemplate();
+        if (!CollectionUtils.isEmpty(floatTemplate)) {
+            return randomFromList(floatTemplate).floatValue();
+        }
+        return RandomUtils.nextFloat((float) fakeConfig.getFloatMin(), (float) fakeConfig.getFloatMax());
+    }
+
+    public Double randomDouble() {
+        List<Double> doubleTemplate = fakeConfig.getDoubleTemplate();
+        if (!CollectionUtils.isEmpty(doubleTemplate)) {
+            return randomFromList(doubleTemplate);
+        }
+        return RandomUtils.nextDouble(fakeConfig.getDoubleMin(), fakeConfig.getDoubleMax());
+    }
+
+    public LocalDate randomLocalDate() {
+        return randomLocalDateTime().toLocalDate();
+    }
+
+    public LocalTime randomLocalTime() {
+        return randomLocalDateTime().toLocalTime();
+    }
+
+    @SuppressWarnings("checkstyle:MagicNumber")
+    public LocalDateTime randomLocalDateTime() {
+        int year;
+        int month;
+        int day;
+        int hour;
+        int minute;
+        int second;
+        // init year
+        if (!CollectionUtils.isEmpty(fakeConfig.getDateYearTemplate())) {
+            year = randomFromList(fakeConfig.getDateYearTemplate());
+        } else {
+            year = LocalDateTime.now().getYear();
+        }
+        // init month
+        if (!CollectionUtils.isEmpty(fakeConfig.getDateMonthTemplate())) {
+            month = randomFromList(fakeConfig.getDateMonthTemplate());
+        } else {
+            month = RandomUtils.nextInt(1, 13);
+        }
+        // init day
+        if (!CollectionUtils.isEmpty(fakeConfig.getDateDayTemplate())) {
+            day = randomFromList(fakeConfig.getDateDayTemplate());
+        } else {
+            day = RandomUtils.nextInt(1, 29);
+        }
+        // init hour
+        if (!CollectionUtils.isEmpty(fakeConfig.getTimeHourTemplate())) {
+            hour = randomFromList(fakeConfig.getTimeHourTemplate());
+        } else {
+            hour = RandomUtils.nextInt(0, 24);
+        }
+        // init minute
+        if (!CollectionUtils.isEmpty(fakeConfig.getTimeMinuteTemplate())) {
+            minute = randomFromList(fakeConfig.getTimeMinuteTemplate());
+        } else {
+            minute = RandomUtils.nextInt(0, 60);
+        }
+        // init second
+        if (!CollectionUtils.isEmpty(fakeConfig.getTimeSecondTemplate())) {
+            second = randomFromList(fakeConfig.getTimeSecondTemplate());
+        } else {
+            second = RandomUtils.nextInt(0, 60);
+        }
+        return LocalDateTime.of(year, month, day, hour, minute, second);
+    }
+}
diff --git a/seatunnel-connectors-v2/connector-fake/src/test/java/org/apache/seatunnel/connectors/seatunnel/fake/FakeFactoryTest.java b/seatunnel-connectors-v2/connector-fake/src/test/java/org/apache/seatunnel/connectors/seatunnel/fake/source/FakeFactoryTest.java
similarity index 88%
rename from seatunnel-connectors-v2/connector-fake/src/test/java/org/apache/seatunnel/connectors/seatunnel/fake/FakeFactoryTest.java
rename to seatunnel-connectors-v2/connector-fake/src/test/java/org/apache/seatunnel/connectors/seatunnel/fake/source/FakeFactoryTest.java
index 175fc6230..6dd59e7c3 100644
--- a/seatunnel-connectors-v2/connector-fake/src/test/java/org/apache/seatunnel/connectors/seatunnel/fake/FakeFactoryTest.java
+++ b/seatunnel-connectors-v2/connector-fake/src/test/java/org/apache/seatunnel/connectors/seatunnel/fake/source/FakeFactoryTest.java
@@ -15,9 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.seatunnel.connectors.seatunnel.fake;
-
-import org.apache.seatunnel.connectors.seatunnel.fake.source.FakeSourceFactory;
+package org.apache.seatunnel.connectors.seatunnel.fake.source;
 
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
diff --git a/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-fake-e2e/src/test/java/org/apache/seatunnel/e2e/connector/fake/FakeIT.java b/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-fake-e2e/src/test/java/org/apache/seatunnel/e2e/connector/fake/FakeIT.java
index 51d4decce..9df613f6d 100644
--- a/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-fake-e2e/src/test/java/org/apache/seatunnel/e2e/connector/fake/FakeIT.java
+++ b/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-fake-e2e/src/test/java/org/apache/seatunnel/e2e/connector/fake/FakeIT.java
@@ -31,5 +31,9 @@ public class FakeIT extends TestSuiteBase {
     public void testFakeConnector(TestContainer container) throws IOException, InterruptedException {
         Container.ExecResult textWriteResult = container.executeJob("/fake_to_assert.conf");
         Assertions.assertEquals(0, textWriteResult.getExitCode());
+        Container.ExecResult fakeWithRange = container.executeJob("/fake_to_assert_with_range.conf");
+        Assertions.assertEquals(0, fakeWithRange.getExitCode());
+        Container.ExecResult fakeWithTemplate = container.executeJob("/fake_to_assert_with_template.conf");
+        Assertions.assertEquals(0, fakeWithTemplate.getExitCode());
     }
 }
diff --git a/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-fake-e2e/src/test/resources/fake_to_assert_with_range.conf b/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-fake-e2e/src/test/resources/fake_to_assert_with_range.conf
new file mode 100644
index 000000000..2045fe677
--- /dev/null
+++ b/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-fake-e2e/src/test/resources/fake_to_assert_with_range.conf
@@ -0,0 +1,165 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+env {
+  execution.parallelism = 1
+  job.mode = "BATCH"
+  spark.master = local
+}
+
+source {
+  FakeSource {
+    row.num = 5
+    string.template = ["tyrantlucifer", "hailin", "kris", "fanjia", "zongwen", "gaojun"]
+    tinyint.min = 1
+    tinyint.max = 9
+    smallint.min = 10
+    smallint.max = 19
+    int.min = 20
+    int.max = 29
+    bigint.min = 30
+    bigint.max = 39
+    float.min = 40.0
+    float.max = 43.0
+    double.min = 44.0
+    double.max = 47.0
+    schema {
+      fields {
+        c_string = string
+        c_tinyint = tinyint
+        c_smallint = smallint
+        c_int = int
+        c_bigint = bigint
+        c_float = float
+        c_double = double
+      }
+    }
+  }
+}
+
+sink {
+  Assert {
+    rules {
+      rule_ruls = [
+        {
+          rule_type = MAX_ROW
+          rule_value = 5
+        }
+      ],
+      field_rules = [
+        {
+          field_name = c_string
+          field_type = string
+          field_value = [
+            {
+              rule_type = MIN_LENGTH
+              rule_value = 4
+            },
+            {
+              rule_type = MAX_LENGTH
+              rule_value = 13
+            }
+          ]
+        },
+        {
+          field_name = c_tinyint
+          field_type = byte
+          field_value = [
+            {
+              rule_type = MIN
+              rule_value = 1
+            },
+            {
+              rule_type = MAX
+              rule_value = 9
+            }
+          ]
+        },
+        {
+          field_name = c_smallint
+          field_type = short
+          field_value = [
+            {
+              rule_type = MIN
+              rule_value = 10
+            },
+            {
+              rule_type = MAX
+              rule_value = 19
+            }
+          ]
+        },
+        {
+          field_name = c_int
+          field_type = int
+          field_value = [
+            {
+              rule_type = MIN
+              rule_value = 20
+            },
+            {
+              rule_type = MAX
+              rule_value = 29
+            }
+          ]
+        },
+        {
+          field_name = c_bigint
+          field_type = long
+          field_value = [
+            {
+              rule_type = MIN
+              rule_value = 30
+            },
+            {
+              rule_type = MAX
+              rule_value = 39
+            }
+          ]
+        },
+        {
+          field_name = c_float
+          field_type = float
+          field_value = [
+            {
+              rule_type = MIN
+              rule_value = 40
+            },
+            {
+              rule_type = MAX
+              rule_value = 43
+            }
+          ]
+        },
+        {
+          field_name = c_double
+          field_type = double
+          field_value = [
+            {
+              rule_type = MIN
+              rule_value = 44
+            },
+            {
+              rule_type = MAX
+              rule_value = 47
+            }
+          ]
+        }
+      ]
+    }
+  }
+}
\ No newline at end of file
diff --git a/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-fake-e2e/src/test/resources/fake_to_assert_with_template.conf b/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-fake-e2e/src/test/resources/fake_to_assert_with_template.conf
new file mode 100644
index 000000000..41d449a8b
--- /dev/null
+++ b/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-fake-e2e/src/test/resources/fake_to_assert_with_template.conf
@@ -0,0 +1,166 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+env {
+  execution.parallelism = 1
+  job.mode = "BATCH"
+  spark.master = local
+}
+
+source {
+  FakeSource {
+    row.num = 5
+    string.fake.mode = "template"
+    string.template = ["tyrantlucifer", "hailin", "kris", "fanjia", "zongwen", "gaojun"]
+    tinyint.fake.mode = "template"
+    tinyint.template = [1, 2, 3, 4, 5, 6, 7, 8, 9]
+    smalling.fake.mode = "template"
+    smallint.template = [10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
+    int.fake.mode = "template"
+    int.template = [20, 21, 22, 23, 24, 25, 26, 27, 28, 29]
+    bigint.fake.mode = "template"
+    bigint.template = [30, 31, 32, 33, 34, 35, 36, 37, 38, 39]
+    float.fake.mode = "template"
+    float.template = [40.0, 41.0, 42.0, 43.0]
+    double.fake.mode = "template"
+    double.template = [44.0, 45.0, 46.0, 47.0]
+    schema {
+      fields {
+        c_string = string
+        c_tinyint = tinyint
+        c_smallint = smallint
+        c_int = int
+        c_bigint = bigint
+        c_float = float
+        c_double = double
+      }
+    }
+  }
+}
+
+sink {
+  Assert {
+    rules {
+      rule_ruls = [
+        {
+          rule_type = MAX_ROW
+          rule_value = 5
+        }
+      ],
+      field_rules = [
+        {
+          field_name = c_string
+          field_type = string
+          field_value = [
+            {
+              rule_type = MIN_LENGTH
+              rule_value = 4
+            },
+            {
+              rule_type = MAX_LENGTH
+              rule_value = 13
+            }
+          ]
+        },
+        {
+          field_name = c_tinyint
+          field_type = byte
+          field_value = [
+            {
+              rule_type = MIN
+              rule_value = 1
+            },
+            {
+              rule_type = MAX
+              rule_value = 9
+            }
+          ]
+        },
+        {
+          field_name = c_smallint
+          field_type = short
+          field_value = [
+            {
+              rule_type = MIN
+              rule_value = 10
+            },
+            {
+              rule_type = MAX
+              rule_value = 19
+            }
+          ]
+        },
+        {
+          field_name = c_int
+          field_type = int
+          field_value = [
+            {
+              rule_type = MIN
+              rule_value = 20
+            },
+            {
+              rule_type = MAX
+              rule_value = 29
+            }
+          ]
+        },
+        {
+          field_name = c_bigint
+          field_type = long
+          field_value = [
+            {
+              rule_type = MIN
+              rule_value = 30
+            },
+            {
+              rule_type = MAX
+              rule_value = 39
+            }
+          ]
+        },
+        {
+          field_name = c_float
+          field_type = float
+          field_value = [
+            {
+              rule_type = MIN
+              rule_value = 40
+            },
+            {
+              rule_type = MAX
+              rule_value = 43
+            }
+          ]
+        },
+        {
+          field_name = c_double
+          field_type = double
+          field_value = [
+            {
+              rule_type = MIN
+              rule_value = 44
+            },
+            {
+              rule_type = MAX
+              rule_value = 47
+            }
+          ]
+        }
+      ]
+    }
+  }
+}
\ No newline at end of file