diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..c0fb2d2
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,27 @@
+# Compiled class file
+*.class
+
+# Log file
+*.log
+
+# BlueJ files
+*.ctxt
+
+# Mobile Tools for Java (J2ME)
+.mtj.tmp/
+
+# Package Files #
+*.jar
+*.war
+*.nar
+*.ear
+*.zip
+*.tar.gz
+*.rar
+
+*.idea
+*.iml
+target
+# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
+hs_err_pid*
+replay_pid*
diff --git a/hsweb-incubator-easyorm-clickhouse.iml b/hsweb-incubator-easyorm-clickhouse.iml
new file mode 100644
index 0000000..4cb7b15
--- /dev/null
+++ b/hsweb-incubator-easyorm-clickhouse.iml
@@ -0,0 +1,86 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..0ab5a5f
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,90 @@
+
+
+ 4.0.0
+
+ org.hswebframework
+ hsweb-incubator-easyorm-clickhouse
+ 1.0-SNAPSHOT
+
+
+ 8
+ 8
+ 4.0.17-SNAPSHOT
+
+
+
+
+ org.hswebframework.web
+ hsweb-commons-crud
+ ${hsweb.framework.version}
+
+
+ org.springframework
+ spring-webflux
+ 5.3.25
+
+
+
+
+ aliyun-nexus
+ aliyun
+ https://maven.aliyun.com/nexus/content/groups/public/
+
+ false
+
+
+
+
+ hsweb-nexus
+ Nexus Release Repository
+ https://nexus.jetlinks.cn/content/groups/public/
+
+ false
+
+
+ true
+ always
+
+
+
+
+
+
+ sct-releases
+ Nexus Release Repository
+ http://192.168.9.91:81/repository/maven-releases/
+
+
+ sct-snapshots
+ Nexus Snapshot Repository
+ http://192.168.9.91:81/repository/maven-snapshots/
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-deploy-plugin
+ 2.8.2
+
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+ 2.1.2
+
+
+ package
+
+ jar
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/java/org/hswebframework/ezorm/rdb/supports/clickhouse/ClickhouseDataType.java b/src/main/java/org/hswebframework/ezorm/rdb/supports/clickhouse/ClickhouseDataType.java
new file mode 100644
index 0000000..ad3c289
--- /dev/null
+++ b/src/main/java/org/hswebframework/ezorm/rdb/supports/clickhouse/ClickhouseDataType.java
@@ -0,0 +1,54 @@
+package org.hswebframework.ezorm.rdb.supports.clickhouse;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import org.hswebframework.web.dict.EnumDict;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.sql.Array;
+
+/**
+ * @author dengpengyu
+ * @date 2023/10/12 15:16
+ */
+@AllArgsConstructor
+@Getter
+public enum ClickhouseDataType implements EnumDict> {
+
+ INT8(Byte.class),
+ INT16(Short.class),
+ INT32(Integer.class),
+ INT64(Long.class),
+ INT128(BigInteger.class),
+ INT256(BigInteger.class),
+ UINT8(Short.class),
+ UINT16(Integer.class),
+ UINT32(Long.class),
+ UINT64(BigInteger.class),
+ NULLABLE_UINT64(BigInteger.class),
+ FLOAT32(Float.class),
+ FLOAT64(Double.class),
+ STRING(String.class),
+ UUID(String.class),
+ BOOLEAN(Boolean.class),
+ DATE(java.sql.Date.class),
+ DATETIME(java.sql.Timestamp.class),
+ DATETIME64(java.time.LocalDateTime.class),
+ ARRAY(Array.class), // This would be a placeholder, actual implementation depends on the array type
+ ENUM(String.class), // Enums in Clickhouse are typically represented as strings in Java
+ DECIMAL(BigDecimal.class),
+ IP(String.class); // IP address types can be represented as strings
+
+ private final Class> javaType;
+
+ @Override
+ public Class> getValue() {
+ return javaType;
+ }
+
+ @Override
+ public String getText() {
+ return name();
+ }
+}
diff --git a/src/main/java/org/hswebframework/ezorm/rdb/supports/clickhouse/ClickhouseDefaultRepository.java b/src/main/java/org/hswebframework/ezorm/rdb/supports/clickhouse/ClickhouseDefaultRepository.java
new file mode 100644
index 0000000..93e75a3
--- /dev/null
+++ b/src/main/java/org/hswebframework/ezorm/rdb/supports/clickhouse/ClickhouseDefaultRepository.java
@@ -0,0 +1,262 @@
+package org.hswebframework.ezorm.rdb.supports.clickhouse;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.hswebframework.ezorm.core.GlobalConfig;
+import org.hswebframework.ezorm.core.ObjectPropertyOperator;
+import org.hswebframework.ezorm.rdb.events.ContextKeyValue;
+import org.hswebframework.ezorm.rdb.events.ContextKeys;
+import org.hswebframework.ezorm.rdb.executor.wrapper.ResultWrapper;
+import org.hswebframework.ezorm.rdb.mapping.EntityColumnMapping;
+import org.hswebframework.ezorm.rdb.mapping.LazyEntityColumnMapping;
+import org.hswebframework.ezorm.rdb.mapping.MappingFeatureType;
+import org.hswebframework.ezorm.rdb.mapping.events.EventResultOperator;
+import org.hswebframework.ezorm.rdb.mapping.events.MappingContextKeys;
+import org.hswebframework.ezorm.rdb.mapping.events.MappingEventTypes;
+import org.hswebframework.ezorm.rdb.metadata.RDBColumnMetadata;
+import org.hswebframework.ezorm.rdb.metadata.RDBTableMetadata;
+import org.hswebframework.ezorm.rdb.operator.DatabaseOperator;
+import org.hswebframework.ezorm.rdb.operator.builder.fragments.NativeSql;
+import org.hswebframework.ezorm.rdb.operator.dml.insert.InsertOperator;
+import org.hswebframework.ezorm.rdb.operator.dml.insert.InsertResultOperator;
+import org.hswebframework.ezorm.rdb.operator.dml.upsert.SaveResultOperator;
+import org.hswebframework.ezorm.rdb.operator.dml.upsert.UpsertOperator;
+
+import java.util.*;
+import java.util.function.BiConsumer;
+import java.util.function.Supplier;
+import java.util.stream.Stream;
+
+import static org.hswebframework.ezorm.rdb.events.ContextKeys.tableMetadata;
+import static org.hswebframework.ezorm.rdb.mapping.events.MappingContextKeys.*;
+import static org.hswebframework.ezorm.rdb.mapping.events.MappingContextKeys.insert;
+
+/**
+ * @className ClickhouseDefaultRepository
+ * @Description TODO
+ * @Author zhong
+ * @Date 2024/1/19 9:32
+ * @Vesion 1.0
+ */
+public abstract class ClickhouseDefaultRepository {
+ protected DatabaseOperator operator;
+
+ protected ResultWrapper wrapper;
+
+ private volatile String idColumn;
+
+ @Getter
+ protected EntityColumnMapping mapping;
+
+ @Setter
+ protected volatile String[] properties;
+
+ protected Supplier tableSupplier;
+
+ protected final List> defaultContextKeyValue = new ArrayList<>();
+
+ public ClickhouseDefaultRepository(DatabaseOperator operator, Supplier supplier, ResultWrapper wrapper) {
+ this.operator = operator;
+ this.wrapper = wrapper;
+ this.tableSupplier = supplier;
+ defaultContextKeyValue.add(repository.value(this));
+ defaultContextKeyValue.add(ContextKeys.database.value(operator));
+
+ }
+
+ protected RDBTableMetadata getTable() {
+ return tableSupplier.get();
+ }
+
+ protected ContextKeyValue>[] getDefaultContextKeyValue(ContextKeyValue>... kv) {
+ if (kv.length == 0) {
+ return defaultContextKeyValue.toArray(new ContextKeyValue[0]);
+ }
+ List> keyValues = new ArrayList<>(defaultContextKeyValue);
+ keyValues.addAll(Arrays.asList(kv));
+ return keyValues.toArray(new ContextKeyValue[0]);
+ }
+
+ public String[] getProperties() {
+ if (properties == null) {
+ properties = mapping
+ .getColumnPropertyMapping()
+ .entrySet()
+ .stream()
+ .filter(kv -> getTable().getColumn(kv.getKey()).isPresent())
+ .map(Map.Entry::getValue)
+ .toArray(String[]::new);
+ }
+ return properties;
+ }
+
+ protected String getIdColumn() {
+ if (idColumn == null) {
+ this.idColumn = getTable()
+ .getColumns()
+ .stream()
+ .filter(RDBColumnMetadata::isPrimaryKey)
+ .findFirst()
+ .map(RDBColumnMetadata::getName)
+ .orElseThrow(() -> new UnsupportedOperationException("id column not exists"));
+ }
+ return idColumn;
+ }
+
+ protected void initMapping(Class entityType) {
+
+ this.mapping = LazyEntityColumnMapping.of(() -> getTable()
+ .findFeature(MappingFeatureType.columnPropertyMapping.createFeatureId(entityType))
+ .orElseThrow(() -> new UnsupportedOperationException("unsupported columnPropertyMapping feature")));
+ defaultContextKeyValue.add(MappingContextKeys.columnMapping(mapping));
+ }
+
+ protected Collection tryMergeDuplicate(Collection data) {
+ if (data.isEmpty()) {
+ return data;
+ }
+ Map