├── booster └── src │ ├── main │ ├── bin │ │ ├── restart.sh │ │ ├── startup.bat │ │ ├── stop.sh │ │ └── startup.sh │ ├── resources │ │ ├── application.yml │ │ └── banner.txt │ ├── java │ │ └── com │ │ │ └── jimmy │ │ │ └── hulk │ │ │ └── booster │ │ │ ├── base │ │ │ └── Action.java │ │ │ ├── App.java │ │ │ ├── action │ │ │ ├── CompareAction.java │ │ │ ├── RollbackAction.java │ │ │ ├── JobAction.java │ │ │ ├── FlushAction.java │ │ │ ├── DeleteAction.java │ │ │ ├── UpdateAction.java │ │ │ ├── CacheAction.java │ │ │ ├── InsertAction.java │ │ │ ├── NativeAction.java │ │ │ ├── UseAction.java │ │ │ ├── DropTableAction.java │ │ │ ├── AlterAction.java │ │ │ └── CreateTableAction.java │ │ │ ├── handler │ │ │ ├── SessionHandler.java │ │ │ ├── ExceptionHandler.java │ │ │ └── HandlerInitializer.java │ │ │ ├── support │ │ │ ├── SessionPool.java │ │ │ └── DatabaseServer.java │ │ │ ├── protocol │ │ │ └── MySqlPacketDecoder.java │ │ │ └── core │ │ │ └── SystemVariable.java │ └── assembly │ │ └── release.xml │ └── test │ └── java │ └── com │ └── jimmy │ └── hulk │ └── booster │ ├── DataTest.java │ ├── ParseTest.java │ └── BoosterTest.java ├── canal ├── src │ └── main │ │ └── java │ │ └── com │ │ └── jimmy │ │ └── hulk │ │ └── canal │ │ ├── enums │ │ └── InstanceTypeEnum.java │ │ ├── base │ │ ├── LifeCycle.java │ │ └── Instance.java │ │ ├── core │ │ ├── CanalPosition.java │ │ ├── CanalMessage.java │ │ ├── CanalConfiguration.java │ │ └── CanalRowData.java │ │ └── instance │ │ └── AbstractInstance.java └── pom.xml ├── common ├── src │ └── main │ │ └── java │ │ └── com │ │ └── jimmy │ │ └── hulk │ │ └── common │ │ ├── base │ │ ├── LineHandle.java │ │ ├── PriKeyStrategy.java │ │ ├── Initialize.java │ │ └── IntObjectMap.java │ │ ├── enums │ │ ├── ModuleEnum.java │ │ ├── JoinTypeEnum.java │ │ ├── AggregateEnum.java │ │ ├── RoleEnum.java │ │ ├── ColumnTypeEnum.java │ │ ├── SqlTypeEnum.java │ │ ├── ConditionEnum.java │ │ ├── ConditionTypeEnum.java │ │ ├── AlterTypeEnum.java │ │ ├── IndexTypeEnum.java │ │ ├── OracleConnectTypeEnum.java │ │ └── DatasourceEnum.java │ │ ├── core │ │ ├── Database.java │ │ ├── Alter.java │ │ ├── Index.java │ │ ├── Table.java │ │ └── Column.java │ │ └── exception │ │ └── HulkException.java └── pom.xml ├── data └── src │ └── main │ ├── resources │ └── META-INF │ │ └── spring.factories │ └── java │ └── com │ └── jimmy │ └── hulk │ └── data │ ├── notify │ └── ImportNotify.java │ ├── base │ ├── Convert.java │ ├── ConditionParse.java │ ├── DmlParse.java │ ├── FieldMapper.java │ ├── Connection.java │ ├── DataSource.java │ ├── DataMapper.java │ └── Data.java │ ├── core │ ├── Order.java │ ├── Dump.java │ ├── AggregateFunction.java │ ├── PageResult.java │ ├── Page.java │ ├── ConditionGroup.java │ ├── ParseResult.java │ ├── Condition.java │ └── QueryPlus.java │ ├── annotation │ ├── ConnectionType.java │ ├── TableField.java │ ├── TableId.java │ ├── DS.java │ └── Mapper.java │ ├── config │ ├── ServerProperty.java │ ├── DataProperties.java │ ├── DataConfig.java │ └── DataSourceProperty.java │ ├── other │ ├── ExecuteBody.java │ ├── ConditionPart.java │ ├── ConnectionContext.java │ ├── ExcelProperties.java │ ├── In.java │ ├── NotIn.java │ └── MapComparator.java │ ├── convert │ ├── DefaultConvert.java │ └── HumpConvert.java │ ├── condition │ ├── MySQLCondition.java │ ├── ExcelCondition.java │ ├── Neo4jCondition.java │ ├── OracleCondition.java │ ├── MongoDBCondition.java │ ├── ClickHouseCondition.java │ ├── SqlServerCondition.java │ └── ElasticsearchCondition.java │ ├── support │ └── DataInitialize.java │ ├── field │ ├── MySQLFieldMapper.java │ ├── ElasticsearchMapper.java │ ├── SqlServerFieldMapper.java │ ├── OracleMapper.java │ └── ClickHouseMapper.java │ ├── parse │ └── dml │ │ ├── ClickHouseDmlParse.java │ │ ├── SqlServerDmlParse.java │ │ ├── MySQLDmlParse.java │ │ └── OracleDmlParse.java │ ├── datasource │ ├── ExcelDatasource.java │ └── BaseDatasource.java │ ├── transaction │ └── Transaction.java │ ├── connection │ └── Neo4jConnection.java │ ├── utils │ └── ClickHouseUtil.java │ └── data │ └── TransactionData.java ├── parse └── src │ └── main │ ├── resources │ └── META-INF │ │ └── spring.factories │ ├── java │ ├── com │ │ └── jimmy │ │ │ └── hulk │ │ │ └── parse │ │ │ ├── enums │ │ │ └── ResultTypeEnum.java │ │ │ ├── core │ │ │ ├── element │ │ │ │ ├── OrderNode.java │ │ │ │ ├── PrepareParamNode.java │ │ │ │ ├── ConditionGroupNode.java │ │ │ │ ├── RelationNode.java │ │ │ │ ├── ConditionNode.java │ │ │ │ ├── IndexNode.java │ │ │ │ ├── AlterNode.java │ │ │ │ └── TableNode.java │ │ │ └── result │ │ │ │ ├── ExtraNode.java │ │ │ │ └── ParseResultNode.java │ │ │ └── config │ │ │ └── ParseConfig.java │ └── org │ │ └── apache │ │ └── calcite │ │ └── sql │ │ ├── SqlCompare.java │ │ ├── SqlCacheQuery.java │ │ ├── SqlNative.java │ │ ├── SqlJob.java │ │ └── SqlFlush.java │ └── codegen │ └── includes │ ├── parserImpls.ftl │ └── compoundIdentifier.ftl ├── route ├── src │ └── main │ │ ├── resources │ │ └── META-INF │ │ │ └── spring.factories │ │ └── java │ │ └── com │ │ └── jimmy │ │ └── hulk │ │ └── route │ │ ├── base │ │ └── Mod.java │ │ ├── partition │ │ ├── LongMod.java │ │ └── HashMod.java │ │ ├── support │ │ └── RouteInitialize.java │ │ └── config │ │ └── RouteConfig.java └── pom.xml ├── config ├── src │ └── main │ │ ├── resources │ │ └── META-INF │ │ │ └── spring.factories │ │ └── java │ │ └── com │ │ └── jimmy │ │ └── hulk │ │ └── config │ │ ├── properties │ │ ├── TableConfigProperty.java │ │ ├── PartitionTableConfigProperty.java │ │ ├── UserConfigProperty.java │ │ ├── PartitionConfigProperty.java │ │ ├── AuthenticationTableConfigProperty.java │ │ ├── SchemaConfigProperty.java │ │ └── DatasourceConfigProperty.java │ │ ├── support │ │ ├── DatabaseConfig.java │ │ ├── ConfigInitialize.java │ │ └── SystemVariableContext.java │ │ └── config │ │ └── ConfigConfig.java └── pom.xml ├── actuator └── src │ └── main │ ├── resources │ └── META-INF │ │ └── spring.factories │ └── java │ └── com │ └── jimmy │ └── hulk │ └── actuator │ ├── base │ ├── Operate.java │ ├── Segment.java │ ├── Serializer.java │ └── Join.java │ ├── enums │ ├── FlushTypeEnum.java │ ├── QueryMethodTypeEnum.java │ ├── PriKeyStrategyTypeEnum.java │ └── SerializerTypeEnum.java │ ├── core │ ├── Null.java │ ├── Row.java │ ├── InsertResult.java │ ├── Fragment.java │ └── ConditionPart.java │ ├── memory │ ├── BaseSegment.java │ ├── HeapMemorySegment.java │ └── DirectMemorySegment.java │ ├── support │ └── ActuatorInitialize.java │ ├── function │ └── IdGenerator.java │ ├── sql │ ├── Native.java │ └── Job.java │ └── config │ └── ActuatorConfig.java ├── authority ├── src │ └── main │ │ ├── resources │ │ └── META-INF │ │ │ └── spring.factories │ │ └── java │ │ └── com │ │ └── jimmy │ │ └── hulk │ │ └── authority │ │ ├── core │ │ ├── UserDetail.java │ │ ├── AuthenticationSchema.java │ │ └── AuthenticationTable.java │ │ ├── config │ │ └── AuthorityConfig.java │ │ ├── base │ │ └── AuthenticationManager.java │ │ └── datasource │ │ └── DatasourcePoint.java └── pom.xml ├── protocol ├── src │ └── main │ │ └── java │ │ └── com │ │ └── jimmy │ │ └── hulk │ │ └── protocol │ │ ├── utils │ │ ├── constant │ │ │ ├── Version.java │ │ │ └── Fields.java │ │ ├── RandomUtil.java │ │ └── CharTypes.java │ │ ├── reponse │ │ ├── ErrorResponse.java │ │ ├── select │ │ │ ├── PreparedStmtResponse.java │ │ │ ├── SelectVersion.java │ │ │ └── SelectDatabase.java │ │ └── OkResponse.java │ │ ├── core │ │ ├── PreparedStatement.java │ │ ├── BindValue.java │ │ └── Context.java │ │ └── packages │ │ ├── BinaryPacket.java │ │ ├── ResultSetHeaderPacket.java │ │ ├── CommandPacket.java │ │ ├── EOFPacket.java │ │ └── PreparedOkPacket.java └── pom.xml └── .gitignore /booster/src/main/bin/restart.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | sh stop.sh 4 | sh startup.sh 5 | -------------------------------------------------------------------------------- /booster/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | # 开发环境配置 2 | server: 3 | # 服务端口 4 | port: 6006 5 | servlet: 6 | # 项目contextPath 7 | context-path: / 8 | -------------------------------------------------------------------------------- /canal/src/main/java/com/jimmy/hulk/canal/enums/InstanceTypeEnum.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.canal.enums; 2 | 3 | public enum InstanceTypeEnum { 4 | 5 | MYSQL, 6 | } 7 | -------------------------------------------------------------------------------- /common/src/main/java/com/jimmy/hulk/common/base/LineHandle.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.common.base; 2 | 3 | public interface LineHandle { 4 | void handle(String line); 5 | } 6 | -------------------------------------------------------------------------------- /data/src/main/resources/META-INF/spring.factories: -------------------------------------------------------------------------------- 1 | # Auto Configure 2 | org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ 3 | com.jimmy.hulk.data.config.DataConfig 4 | -------------------------------------------------------------------------------- /common/src/main/java/com/jimmy/hulk/common/base/PriKeyStrategy.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.common.base; 2 | 3 | public interface PriKeyStrategy { 4 | 5 | Object generate(); 6 | } 7 | -------------------------------------------------------------------------------- /parse/src/main/resources/META-INF/spring.factories: -------------------------------------------------------------------------------- 1 | # Auto Configure 2 | org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ 3 | com.jimmy.hulk.parse.config.ParseConfig 4 | -------------------------------------------------------------------------------- /route/src/main/resources/META-INF/spring.factories: -------------------------------------------------------------------------------- 1 | # Auto Configure 2 | org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ 3 | com.jimmy.hulk.route.config.RouteConfig 4 | -------------------------------------------------------------------------------- /config/src/main/resources/META-INF/spring.factories: -------------------------------------------------------------------------------- 1 | # Auto Configure 2 | org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ 3 | com.jimmy.hulk.config.config.ConfigConfig 4 | -------------------------------------------------------------------------------- /actuator/src/main/resources/META-INF/spring.factories: -------------------------------------------------------------------------------- 1 | # Auto Configure 2 | org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ 3 | com.jimmy.hulk.actuator.config.ActuatorConfig 4 | -------------------------------------------------------------------------------- /authority/src/main/resources/META-INF/spring.factories: -------------------------------------------------------------------------------- 1 | # Auto Configure 2 | org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ 3 | com.jimmy.hulk.authority.config.AuthorityConfig 4 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/notify/ImportNotify.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.notify; 2 | 3 | public interface ImportNotify { 4 | 5 | void callback(Long sum, Long current); 6 | } 7 | -------------------------------------------------------------------------------- /common/src/main/java/com/jimmy/hulk/common/base/Initialize.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.common.base; 2 | 3 | public interface Initialize { 4 | 5 | void init() throws Exception; 6 | 7 | int sort(); 8 | } 9 | -------------------------------------------------------------------------------- /route/src/main/java/com/jimmy/hulk/route/base/Mod.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.route.base; 2 | 3 | public interface Mod { 4 | 5 | int calculate(T columnValue, Integer threshold); 6 | 7 | String name(); 8 | } 9 | -------------------------------------------------------------------------------- /common/src/main/java/com/jimmy/hulk/common/enums/ModuleEnum.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.common.enums; 2 | 3 | public enum ModuleEnum { 4 | 5 | ACTUATOR, BOOSTER, CONFIG, DATA, PARSE, PROTOCOL, ROUTE, AUTHORITY, CANAL 6 | } 7 | -------------------------------------------------------------------------------- /canal/src/main/java/com/jimmy/hulk/canal/base/LifeCycle.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.canal.base; 2 | 3 | public interface LifeCycle { 4 | 5 | void start(); 6 | 7 | void stop(); 8 | 9 | boolean isStart(); 10 | } 11 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/base/Convert.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.base; 2 | 3 | public interface Convert { 4 | 5 | String convertToBean(String key); 6 | 7 | String convertToMap(String key); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /actuator/src/main/java/com/jimmy/hulk/actuator/base/Operate.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.actuator.base; 2 | 3 | import com.jimmy.hulk.parse.core.result.ParseResultNode; 4 | 5 | public interface Operate { 6 | 7 | T execute(ParseResultNode parseResultNode); 8 | } 9 | -------------------------------------------------------------------------------- /actuator/src/main/java/com/jimmy/hulk/actuator/base/Segment.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.actuator.base; 2 | 3 | public interface Segment { 4 | 5 | boolean write(byte[] bytes); 6 | 7 | byte[] read(); 8 | 9 | void free(); 10 | 11 | boolean isFree(); 12 | } 13 | -------------------------------------------------------------------------------- /common/src/main/java/com/jimmy/hulk/common/enums/JoinTypeEnum.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.common.enums; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | 6 | @Getter 7 | @AllArgsConstructor 8 | public enum JoinTypeEnum { 9 | 10 | INNER, LEFT, RIGHT 11 | } 12 | -------------------------------------------------------------------------------- /common/src/main/java/com/jimmy/hulk/common/enums/AggregateEnum.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.common.enums; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | 6 | @Getter 7 | @AllArgsConstructor 8 | public enum AggregateEnum { 9 | 10 | COUNT, SUM, AVG, MIN, MAX 11 | } 12 | -------------------------------------------------------------------------------- /common/src/main/java/com/jimmy/hulk/common/enums/RoleEnum.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.common.enums; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | 6 | @Getter 7 | @AllArgsConstructor 8 | public enum RoleEnum { 9 | 10 | ADMINISTRATOR, ORDINARY_USER, GUEST 11 | } 12 | -------------------------------------------------------------------------------- /actuator/src/main/java/com/jimmy/hulk/actuator/base/Serializer.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.actuator.base; 2 | 3 | import java.util.Map; 4 | 5 | public interface Serializer { 6 | 7 | byte[] serialize(Map map); 8 | 9 | Map deserialize(byte[] bytes); 10 | } 11 | -------------------------------------------------------------------------------- /booster/src/main/java/com/jimmy/hulk/booster/base/Action.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.booster.base; 2 | 3 | import com.jimmy.hulk.booster.core.Session; 4 | 5 | public interface Action { 6 | 7 | void action(String sql, Session session, int offset) throws Exception; 8 | 9 | int type(); 10 | } 11 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/base/ConditionParse.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.base; 2 | 3 | 4 | import com.jimmy.hulk.data.core.Condition; 5 | 6 | import java.util.List; 7 | 8 | public interface ConditionParse { 9 | 10 | T parse(Condition condition, List param); 11 | } 12 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/core/Order.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.core; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | 7 | @Data 8 | public class Order implements Serializable { 9 | 10 | private String fieldName; 11 | 12 | private Boolean isDesc = false; 13 | } 14 | -------------------------------------------------------------------------------- /actuator/src/main/java/com/jimmy/hulk/actuator/enums/FlushTypeEnum.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.actuator.enums; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | 6 | @Getter 7 | @AllArgsConstructor 8 | public enum FlushTypeEnum { 9 | 10 | INSERT, 11 | UPDATE, 12 | REPLACE 13 | } 14 | -------------------------------------------------------------------------------- /common/src/main/java/com/jimmy/hulk/common/enums/ColumnTypeEnum.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.common.enums; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | 6 | @Getter 7 | @AllArgsConstructor 8 | public enum ColumnTypeEnum { 9 | 10 | AGGREGATE, FUNCTION, FIELD, CONSTANT, EXPRESSION 11 | } 12 | -------------------------------------------------------------------------------- /common/src/main/java/com/jimmy/hulk/common/enums/SqlTypeEnum.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.common.enums; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | 6 | @Getter 7 | @AllArgsConstructor 8 | public enum SqlTypeEnum { 9 | SELECT, 10 | INSERT, 11 | UPDATE, 12 | DELETE 13 | } 14 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/annotation/ConnectionType.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.annotation; 2 | 3 | import java.lang.annotation.*; 4 | 5 | @Target({ElementType.TYPE}) 6 | @Retention(RetentionPolicy.RUNTIME) 7 | @Documented 8 | public @interface ConnectionType { 9 | 10 | DS[] dsType(); 11 | } 12 | -------------------------------------------------------------------------------- /actuator/src/main/java/com/jimmy/hulk/actuator/enums/QueryMethodTypeEnum.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.actuator.enums; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | 6 | @Getter 7 | @AllArgsConstructor 8 | public enum QueryMethodTypeEnum { 9 | 10 | SINGER, 11 | PAGE, 12 | ALL 13 | } 14 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/annotation/TableField.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.annotation; 2 | 3 | import java.lang.annotation.*; 4 | 5 | @Documented 6 | @Retention(RetentionPolicy.RUNTIME) 7 | @Target({ElementType.FIELD}) 8 | public @interface TableField { 9 | 10 | String alias() default ""; 11 | } 12 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/annotation/TableId.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.annotation; 2 | 3 | import java.lang.annotation.*; 4 | 5 | @Documented 6 | @Retention(RetentionPolicy.RUNTIME) 7 | @Target({ElementType.FIELD}) 8 | public @interface TableId { 9 | 10 | String alias() default ""; 11 | } 12 | -------------------------------------------------------------------------------- /parse/src/main/java/com/jimmy/hulk/parse/enums/ResultTypeEnum.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.parse.enums; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | 6 | @Getter 7 | @AllArgsConstructor 8 | public enum ResultTypeEnum { 9 | 10 | SELECT, INSERT, UPDATE, DELETE, JOB, FLUSH, NATIVE, CACHE 11 | 12 | } 13 | -------------------------------------------------------------------------------- /common/src/main/java/com/jimmy/hulk/common/enums/ConditionEnum.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.common.enums; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | 6 | @Getter 7 | @AllArgsConstructor 8 | public enum ConditionEnum { 9 | 10 | EQ, GT, GE, LE, LT, IN, NOT_IN, LIKE, NULL, NOT_NULL,NE,NOT_LIKE,RANGER 11 | } 12 | -------------------------------------------------------------------------------- /common/src/main/java/com/jimmy/hulk/common/enums/ConditionTypeEnum.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.common.enums; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | 6 | @Getter 7 | @AllArgsConstructor 8 | public enum ConditionTypeEnum { 9 | 10 | AND("&&"), OR("||"); 11 | 12 | private String expression; 13 | } 14 | -------------------------------------------------------------------------------- /parse/src/main/java/com/jimmy/hulk/parse/core/element/OrderNode.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.parse.core.element; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | 7 | @Data 8 | public class OrderNode implements Serializable { 9 | 10 | private ColumnNode columnNode; 11 | 12 | private Boolean isDesc = false; 13 | } 14 | -------------------------------------------------------------------------------- /protocol/src/main/java/com/jimmy/hulk/protocol/utils/constant/Version.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.protocol.utils.constant; 2 | 3 | public interface Version { 4 | 5 | /** 6 | * 协议版本 7 | */ 8 | byte PROTOCOL_VERSION = 10; 9 | 10 | /** 11 | * 服务器版本 12 | */ 13 | byte[] SERVER_VERSION = "5.7.24-hulk".getBytes(); 14 | } 15 | -------------------------------------------------------------------------------- /actuator/src/main/java/com/jimmy/hulk/actuator/core/Null.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.actuator.core; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | 7 | @Data 8 | public class Null implements Serializable { 9 | 10 | private Null() { 11 | 12 | } 13 | 14 | public static Null build() { 15 | return null; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/base/DmlParse.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.base; 2 | 3 | import java.util.List; 4 | import java.util.Map; 5 | 6 | public interface DmlParse { 7 | 8 | String insert(Map data, List param, String tableName); 9 | 10 | String update(Map data, List param, String tableName); 11 | } 12 | -------------------------------------------------------------------------------- /common/src/main/java/com/jimmy/hulk/common/enums/AlterTypeEnum.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.common.enums; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | 6 | @Getter 7 | @AllArgsConstructor 8 | public enum AlterTypeEnum { 9 | 10 | ADD_COLUMN, 11 | MODIFY_COLUMN, 12 | DROP_COLUMN, 13 | CHANGE_COLUMN, 14 | ADD_INDEX, 15 | DROP_INDEX 16 | } 17 | -------------------------------------------------------------------------------- /canal/src/main/java/com/jimmy/hulk/canal/core/CanalPosition.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.canal.core; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | 7 | @Data 8 | public class CanalPosition implements Serializable { 9 | 10 | private Long timestamp; 11 | 12 | private Long position; 13 | 14 | private String gtid; 15 | 16 | private String journalName; 17 | } 18 | -------------------------------------------------------------------------------- /parse/src/main/java/com/jimmy/hulk/parse/core/element/PrepareParamNode.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.parse.core.element; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | 7 | @Data 8 | public class PrepareParamNode implements Serializable { 9 | 10 | private Integer index; 11 | 12 | private ColumnNode columnNode; 13 | 14 | private ConditionNode conditionNode; 15 | } 16 | -------------------------------------------------------------------------------- /common/src/main/java/com/jimmy/hulk/common/enums/IndexTypeEnum.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.common.enums; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | 6 | @Getter 7 | @AllArgsConstructor 8 | public enum IndexTypeEnum { 9 | 10 | NORMAL("NORMAL", "普通索引"), 11 | UNIQUE("UNIQUE KEY", "唯一索引"); 12 | 13 | private String code; 14 | 15 | private String message; 16 | } 17 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/config/ServerProperty.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.config; 2 | 3 | import lombok.Data; 4 | import lombok.experimental.Accessors; 5 | 6 | @Data 7 | @Accessors(chain = true) 8 | public class ServerProperty { 9 | 10 | private String ip; 11 | 12 | private String username; 13 | 14 | private String password; 15 | 16 | private Integer port; 17 | } 18 | -------------------------------------------------------------------------------- /common/src/main/java/com/jimmy/hulk/common/core/Database.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.common.core; 2 | 3 | import com.jimmy.hulk.common.enums.DatasourceEnum; 4 | import lombok.Data; 5 | 6 | import java.io.Serializable; 7 | 8 | @Data 9 | public class Database implements Serializable { 10 | 11 | private String title; 12 | 13 | private String dsName; 14 | 15 | private DatasourceEnum ds; 16 | } 17 | -------------------------------------------------------------------------------- /authority/src/main/java/com/jimmy/hulk/authority/core/UserDetail.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.authority.core; 2 | 3 | import com.jimmy.hulk.common.enums.RoleEnum; 4 | import lombok.Data; 5 | 6 | import java.io.Serializable; 7 | 8 | @Data 9 | public class UserDetail implements Serializable { 10 | 11 | private String username; 12 | 13 | private String password; 14 | 15 | private RoleEnum role; 16 | } 17 | -------------------------------------------------------------------------------- /booster/src/test/java/com/jimmy/hulk/booster/DataTest.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.booster; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @SpringBootTest(classes = App.class) 9 | @RunWith(SpringRunner.class) 10 | @Slf4j 11 | public class DataTest { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/other/ExecuteBody.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.other; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | import java.util.Map; 7 | 8 | @Data 9 | public class ExecuteBody implements Serializable { 10 | 11 | private String sql; 12 | 13 | private Object[] objects; 14 | 15 | private String tableName; 16 | 17 | private Map doc; 18 | } 19 | -------------------------------------------------------------------------------- /actuator/src/main/java/com/jimmy/hulk/actuator/core/Row.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.actuator.core; 2 | 3 | import com.google.common.collect.Maps; 4 | import com.jimmy.hulk.parse.core.element.TableNode; 5 | import lombok.Data; 6 | 7 | import java.io.Serializable; 8 | import java.util.Map; 9 | 10 | @Data 11 | public class Row implements Serializable { 12 | 13 | private Map rowData = Maps.newHashMap(); 14 | } 15 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/convert/DefaultConvert.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.convert; 2 | 3 | import com.jimmy.hulk.data.base.Convert; 4 | 5 | public class DefaultConvert implements Convert { 6 | 7 | @Override 8 | public String convertToBean(String key) { 9 | return key; 10 | } 11 | 12 | @Override 13 | public String convertToMap(String key) { 14 | return key; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /booster/src/test/java/com/jimmy/hulk/booster/ParseTest.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.booster; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | 9 | @SpringBootTest(classes = App.class) 10 | @RunWith(SpringRunner.class) 11 | @Slf4j 12 | public class ParseTest { 13 | 14 | } 15 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/core/Dump.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.core; 2 | 3 | import com.jimmy.hulk.data.notify.ImportNotify; 4 | import lombok.Data; 5 | 6 | import java.io.File; 7 | import java.io.Serializable; 8 | 9 | @Data 10 | public class Dump implements Serializable { 11 | 12 | private File file; 13 | 14 | private String alias; 15 | 16 | private String table; 17 | 18 | private ImportNotify notify; 19 | } 20 | -------------------------------------------------------------------------------- /canal/src/main/java/com/jimmy/hulk/canal/core/CanalMessage.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.canal.core; 2 | 3 | import com.google.common.collect.Lists; 4 | import lombok.Data; 5 | 6 | import java.io.Serializable; 7 | import java.util.List; 8 | import java.util.Map; 9 | 10 | @Data 11 | public class CanalMessage implements Serializable { 12 | 13 | private Long id; 14 | 15 | private List canalRowDataList = Lists.newArrayList(); 16 | } 17 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/base/FieldMapper.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.base; 2 | 3 | import com.jimmy.hulk.common.enums.DatasourceEnum; 4 | import com.jimmy.hulk.common.enums.FieldTypeEnum; 5 | 6 | public interface FieldMapper { 7 | 8 | FieldTypeEnum getFieldType(); 9 | 10 | String getMapperType(); 11 | 12 | DatasourceEnum type(); 13 | 14 | String[] getAllMapperTypes(); 15 | 16 | boolean isNeedLength(); 17 | } 18 | -------------------------------------------------------------------------------- /route/src/main/java/com/jimmy/hulk/route/partition/LongMod.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.route.partition; 2 | 3 | import com.jimmy.hulk.route.base.Mod; 4 | 5 | public class LongMod implements Mod { 6 | 7 | @Override 8 | public int calculate(Long columnValue, Integer threshold) { 9 | return (int) (columnValue % threshold); 10 | } 11 | 12 | @Override 13 | public String name() { 14 | return "long-mod"; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /actuator/src/main/java/com/jimmy/hulk/actuator/core/InsertResult.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.actuator.core; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | 7 | @Data 8 | public class InsertResult implements Serializable { 9 | 10 | private Integer row = 0; 11 | 12 | private Long priValue; 13 | 14 | public InsertResult(Integer row) { 15 | this.row = row; 16 | } 17 | 18 | public InsertResult() { 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /actuator/src/main/java/com/jimmy/hulk/actuator/memory/BaseSegment.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.actuator.memory; 2 | 3 | import com.jimmy.hulk.actuator.base.Segment; 4 | 5 | import java.util.concurrent.atomic.AtomicBoolean; 6 | 7 | public abstract class BaseSegment implements Segment { 8 | 9 | protected AtomicBoolean free = new AtomicBoolean(true); 10 | 11 | @Override 12 | public boolean isFree() { 13 | return free.get(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /config/src/main/java/com/jimmy/hulk/config/properties/TableConfigProperty.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.config.properties; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | 7 | @Data 8 | public class TableConfigProperty implements Serializable { 9 | 10 | private String priKeyName; 11 | 12 | private String priKeyStrategy; 13 | 14 | private Boolean isNeedReturnKey; 15 | 16 | private String tableName; 17 | 18 | private String dsName; 19 | } 20 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/core/AggregateFunction.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.core; 2 | 3 | import com.jimmy.hulk.common.enums.AggregateEnum; 4 | import lombok.Data; 5 | 6 | import java.io.Serializable; 7 | 8 | @Data 9 | public class AggregateFunction implements Serializable { 10 | 11 | private AggregateEnum aggregateType; 12 | 13 | private String column; 14 | 15 | private String alias; 16 | 17 | private Boolean isIncludeAlias = false; 18 | } 19 | -------------------------------------------------------------------------------- /common/src/main/java/com/jimmy/hulk/common/core/Alter.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.common.core; 2 | 3 | import com.jimmy.hulk.common.enums.AlterTypeEnum; 4 | import lombok.Data; 5 | 6 | import java.io.Serializable; 7 | 8 | @Data 9 | public class Alter implements Serializable { 10 | 11 | private String table; 12 | 13 | private Index index; 14 | 15 | private Column column; 16 | 17 | private Column oldColumn; 18 | 19 | private AlterTypeEnum alterType; 20 | 21 | } 22 | -------------------------------------------------------------------------------- /config/src/main/java/com/jimmy/hulk/config/support/DatabaseConfig.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.config.support; 2 | 3 | import com.google.common.collect.Lists; 4 | import com.jimmy.hulk.common.core.Database; 5 | import lombok.Getter; 6 | 7 | import java.util.List; 8 | 9 | public class DatabaseConfig { 10 | 11 | @Getter 12 | private List databases = Lists.newArrayList(); 13 | 14 | void add(Database database) { 15 | databases.add(database); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/annotation/DS.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.annotation; 2 | 3 | import com.jimmy.hulk.common.enums.DatasourceEnum; 4 | import org.springframework.context.annotation.Condition; 5 | 6 | import java.lang.annotation.*; 7 | 8 | @Target({ElementType.TYPE}) 9 | @Retention(RetentionPolicy.RUNTIME) 10 | @Documented 11 | public @interface DS { 12 | 13 | DatasourceEnum type(); 14 | 15 | Class[] condition() default {}; 16 | } 17 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/core/PageResult.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.core; 2 | 3 | import com.google.common.collect.Lists; 4 | import lombok.Data; 5 | 6 | import java.io.Serializable; 7 | import java.util.List; 8 | 9 | @Data 10 | public class PageResult implements Serializable { 11 | 12 | private Integer pageNo; 13 | 14 | private Integer pageSize; 15 | 16 | private Long total = 0L; 17 | 18 | private List records = Lists.newArrayList(); 19 | } 20 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/core/Page.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.core; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | 7 | @Data 8 | public class Page implements Serializable { 9 | 10 | private Integer pageNo; 11 | 12 | private Integer pageSize; 13 | 14 | public Page(Integer pageNo, Integer pageSize) { 15 | this.pageNo = pageNo; 16 | this.pageSize = pageSize; 17 | } 18 | 19 | public Page() { 20 | 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/other/ConditionPart.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.other; 2 | 3 | import com.google.common.collect.Lists; 4 | import com.google.common.collect.Maps; 5 | import lombok.Data; 6 | 7 | import java.io.Serializable; 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | @Data 12 | public class ConditionPart implements Serializable { 13 | 14 | private String conditionExp; 15 | 16 | private List param = Lists.newArrayList(); 17 | } 18 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/other/ConnectionContext.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.other; 2 | 3 | import cn.hutool.core.map.MapUtil; 4 | 5 | import java.util.HashMap; 6 | 7 | public class ConnectionContext extends HashMap { 8 | 9 | public String getString(String key) { 10 | return MapUtil.getStr(this, key); 11 | } 12 | 13 | public T get(String key, Class clazz) { 14 | return MapUtil.get(this, key, clazz); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /booster/src/main/resources/banner.txt: -------------------------------------------------------------------------------- 1 | ${AnsiColor.BRIGHT_BLUE} 2 | _ _ 3 | | | | | 4 | ___ _ _ _ __ ___ ___| | __ _ ___| | __ 5 | / __| | | | '_ ` _ \/ __| |/ _` |/ __| |/ / 6 | \__ \ |_| | | | | | \__ \ | (_| | (__| < 7 | |___/\__,_|_| |_| |_|___/_|\__,_|\___|_|\_\ 8 | 9 | ${AnsiColor.BRIGHT_GREEN} 10 | Jeecg Boot Version: 2.1.2 11 | Spring Boot Version: ${spring-boot.version}${spring-boot.formatted-version} 12 | ${AnsiColor.BLACK} 13 | -------------------------------------------------------------------------------- /common/src/main/java/com/jimmy/hulk/common/core/Index.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.common.core; 2 | 3 | import com.google.common.collect.Lists; 4 | import com.jimmy.hulk.common.enums.IndexTypeEnum; 5 | import lombok.Data; 6 | 7 | import java.io.Serializable; 8 | import java.util.List; 9 | 10 | @Data 11 | public class Index implements Serializable { 12 | 13 | private String name; 14 | 15 | private IndexTypeEnum indexType; 16 | 17 | private List fields = Lists.newArrayList(); 18 | } 19 | -------------------------------------------------------------------------------- /parse/src/main/java/com/jimmy/hulk/parse/core/result/ExtraNode.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.parse.core.result; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | 7 | @Data 8 | public class ExtraNode implements Serializable { 9 | 10 | private String cron; 11 | 12 | private String name; 13 | 14 | private String mapper; 15 | 16 | private String index; 17 | 18 | private String dsName; 19 | 20 | private String expire; 21 | 22 | private Boolean isExecute; 23 | } 24 | -------------------------------------------------------------------------------- /route/src/main/java/com/jimmy/hulk/route/partition/HashMod.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.route.partition; 2 | 3 | import com.jimmy.hulk.route.base.Mod; 4 | 5 | public class HashMod implements Mod { 6 | 7 | @Override 8 | public int calculate(Object columnValue, Integer threshold) { 9 | int ss = columnValue.hashCode() & Integer.MAX_VALUE; 10 | return ss % threshold; 11 | } 12 | 13 | @Override 14 | public String name() { 15 | return "hash-mod"; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /actuator/src/main/java/com/jimmy/hulk/actuator/core/Fragment.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.actuator.core; 2 | 3 | import com.google.common.collect.Lists; 4 | import com.google.common.collect.Maps; 5 | import lombok.Data; 6 | 7 | import java.io.Serializable; 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | @Data 12 | public class Fragment implements Serializable { 13 | 14 | private List index = Lists.newArrayList(); 15 | 16 | private Map key = Maps.newHashMap(); 17 | } 18 | -------------------------------------------------------------------------------- /booster/src/main/java/com/jimmy/hulk/booster/App.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.booster; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; 6 | 7 | @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}) 8 | public class App { 9 | public static void main(String[] args) { 10 | SpringApplication.run(App.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/** 5 | !**/src/test/** 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | *.log 22 | 23 | ### NetBeans ### 24 | /nbproject/private/ 25 | /nbbuild/ 26 | /dist/ 27 | /nbdist/ 28 | /.nb-gradle/ 29 | build/ 30 | 31 | ### VS Code ### 32 | .vscode/ 33 | dependency-reduced-pom.xml 34 | -------------------------------------------------------------------------------- /actuator/src/main/java/com/jimmy/hulk/actuator/core/ConditionPart.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.actuator.core; 2 | 3 | import com.google.common.collect.Maps; 4 | import com.jimmy.hulk.data.core.Wrapper; 5 | import lombok.Data; 6 | 7 | import java.util.Map; 8 | 9 | @Data 10 | public class ConditionPart { 11 | 12 | private Wrapper wrapper; 13 | 14 | private String conditionExp; 15 | 16 | private Boolean includeColumnCondition = false; 17 | 18 | private Map param = Maps.newHashMap(); 19 | } 20 | -------------------------------------------------------------------------------- /authority/src/main/java/com/jimmy/hulk/authority/core/AuthenticationSchema.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.authority.core; 2 | 3 | import com.google.common.collect.Lists; 4 | import lombok.Data; 5 | 6 | import java.io.Serializable; 7 | import java.util.List; 8 | 9 | @Data 10 | public class AuthenticationSchema implements Serializable { 11 | 12 | private String dsName; 13 | 14 | private Boolean isAllAllow = false; 15 | 16 | private List authenticationTables = Lists.newArrayList(); 17 | } 18 | -------------------------------------------------------------------------------- /authority/src/main/java/com/jimmy/hulk/authority/core/AuthenticationTable.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.authority.core; 2 | 3 | import com.google.common.collect.Lists; 4 | import lombok.Data; 5 | 6 | import java.io.Serializable; 7 | import java.util.List; 8 | 9 | @Data 10 | public class AuthenticationTable implements Serializable { 11 | 12 | private String table; 13 | 14 | private List filterFields = Lists.newArrayList(); 15 | 16 | private List dmlAllowMethods = Lists.newArrayList(); 17 | } 18 | -------------------------------------------------------------------------------- /common/src/main/java/com/jimmy/hulk/common/core/Table.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.common.core; 2 | 3 | import com.google.common.collect.Lists; 4 | import lombok.Data; 5 | 6 | import java.io.Serializable; 7 | import java.util.List; 8 | 9 | @Data 10 | public class Table implements Serializable { 11 | 12 | private String tableName; 13 | 14 | private String charset = "UTF8"; 15 | 16 | private List columns = Lists.newArrayList(); 17 | 18 | private List indices = Lists.newArrayList(); 19 | } 20 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/core/ConditionGroup.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.core; 2 | 3 | import com.google.common.collect.Lists; 4 | import com.jimmy.hulk.common.enums.ConditionTypeEnum; 5 | import lombok.Data; 6 | 7 | import java.io.Serializable; 8 | import java.util.List; 9 | 10 | @Data 11 | public class ConditionGroup implements Serializable { 12 | 13 | private List conditions = Lists.newArrayList(); 14 | 15 | private ConditionTypeEnum conditionTypeEnum = ConditionTypeEnum.AND; 16 | } 17 | -------------------------------------------------------------------------------- /config/src/main/java/com/jimmy/hulk/config/properties/PartitionTableConfigProperty.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.config.properties; 2 | 3 | import com.google.common.collect.Sets; 4 | import lombok.Data; 5 | 6 | import java.io.Serializable; 7 | import java.util.Set; 8 | 9 | @Data 10 | public class PartitionTableConfigProperty implements Serializable { 11 | 12 | private String range; 13 | 14 | private String prefix; 15 | 16 | private String dsName; 17 | 18 | private Set tables = Sets.newHashSet(); 19 | } 20 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/other/ExcelProperties.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.other; 2 | 3 | import com.google.common.collect.Lists; 4 | import lombok.Data; 5 | 6 | import java.util.List; 7 | 8 | @Data 9 | public class ExcelProperties { 10 | 11 | private String fileName; 12 | 13 | private List> head = Lists.newArrayList(); 14 | 15 | public ExcelProperties(String fileName, List> head) { 16 | this.fileName = fileName; 17 | this.head = head; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /route/src/main/java/com/jimmy/hulk/route/support/RouteInitialize.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.route.support; 2 | 3 | import com.jimmy.hulk.common.base.Initialize; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | 6 | public class RouteInitialize implements Initialize { 7 | 8 | @Autowired 9 | private ModProxy modProxy; 10 | 11 | @Override 12 | public void init() throws Exception { 13 | modProxy.init(); 14 | } 15 | 16 | @Override 17 | public int sort() { 18 | return 0; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /booster/src/main/java/com/jimmy/hulk/booster/action/CompareAction.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.booster.action; 2 | 3 | import com.jimmy.hulk.booster.core.Session; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.stereotype.Component; 6 | 7 | @Slf4j 8 | @Component 9 | public class CompareAction extends BaseAction{ 10 | 11 | @Override 12 | public void action(String sql, Session session, int offset) throws Exception { 13 | 14 | } 15 | 16 | @Override 17 | public int type() { 18 | return 0; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /common/src/main/java/com/jimmy/hulk/common/base/IntObjectMap.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.common.base; 2 | 3 | import java.util.Map; 4 | 5 | public interface IntObjectMap extends Map { 6 | 7 | interface PrimitiveEntry { 8 | int key(); 9 | 10 | V value(); 11 | 12 | void setValue(V value); 13 | } 14 | 15 | V get(int key); 16 | 17 | V put(int key, V value); 18 | 19 | V remove(int key); 20 | 21 | Iterable> entries(); 22 | 23 | boolean containsKey(int key); 24 | } 25 | -------------------------------------------------------------------------------- /config/src/main/java/com/jimmy/hulk/config/support/ConfigInitialize.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.config.support; 2 | 3 | import com.jimmy.hulk.common.base.Initialize; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | 6 | public class ConfigInitialize implements Initialize { 7 | 8 | @Autowired 9 | private XmlParse xmlParse; 10 | 11 | @Override 12 | public void init() throws Exception { 13 | xmlParse.parse(); 14 | } 15 | 16 | @Override 17 | public int sort() { 18 | return 2; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /parse/src/main/java/com/jimmy/hulk/parse/core/element/ConditionGroupNode.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.parse.core.element; 2 | 3 | import com.google.common.collect.Lists; 4 | import com.jimmy.hulk.common.enums.ConditionTypeEnum; 5 | import lombok.Data; 6 | 7 | import java.io.Serializable; 8 | import java.util.List; 9 | 10 | @Data 11 | public class ConditionGroupNode implements Serializable { 12 | 13 | private ConditionTypeEnum conditionType = ConditionTypeEnum.AND; 14 | 15 | private List conditionNodeList = Lists.newArrayList(); 16 | } 17 | -------------------------------------------------------------------------------- /parse/src/main/java/com/jimmy/hulk/parse/core/element/RelationNode.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.parse.core.element; 2 | 3 | import com.google.common.collect.Lists; 4 | import com.jimmy.hulk.common.enums.JoinTypeEnum; 5 | import lombok.Data; 6 | 7 | import java.io.Serializable; 8 | import java.util.List; 9 | 10 | @Data 11 | public class RelationNode implements Serializable { 12 | 13 | private TableNode targetTable; 14 | 15 | private JoinTypeEnum joinType; 16 | 17 | private List relConditionNodes = Lists.newArrayList(); 18 | } 19 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/base/Connection.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.base; 2 | 3 | import com.jimmy.hulk.data.other.ConnectionContext; 4 | 5 | import java.util.List; 6 | 7 | public interface Connection { 8 | 9 | T getConnection(); 10 | 11 | void commit(); 12 | 13 | void rollback(); 14 | 15 | void setSource(S s); 16 | 17 | void close(); 18 | 19 | void setContext(ConnectionContext context); 20 | 21 | void batchExecute(List sql) throws Exception; 22 | 23 | int execute(V sql) throws Exception; 24 | 25 | } 26 | -------------------------------------------------------------------------------- /parse/src/main/java/com/jimmy/hulk/parse/config/ParseConfig.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.parse.config; 2 | 3 | import com.jimmy.hulk.parse.support.AlterParser; 4 | import com.jimmy.hulk.parse.support.SQLParser; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | @Configuration 9 | public class ParseConfig { 10 | 11 | @Bean 12 | public SQLParser sqlParser() { 13 | return new SQLParser(); 14 | } 15 | 16 | @Bean 17 | public AlterParser alterParser() { 18 | return new AlterParser(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /actuator/src/main/java/com/jimmy/hulk/actuator/base/Join.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.actuator.base; 2 | 3 | import com.jimmy.hulk.actuator.core.Fragment; 4 | import com.jimmy.hulk.actuator.core.Row; 5 | import com.jimmy.hulk.common.enums.JoinTypeEnum; 6 | import com.jimmy.hulk.parse.core.element.ConditionGroupNode; 7 | import com.jimmy.hulk.parse.core.element.TableNode; 8 | 9 | import java.util.List; 10 | 11 | public interface Join { 12 | 13 | List join(List master, List slave, TableNode tableNode, List conditionGroupNodes); 14 | 15 | JoinTypeEnum type(); 16 | } 17 | -------------------------------------------------------------------------------- /parse/src/main/java/com/jimmy/hulk/parse/core/element/ConditionNode.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.parse.core.element; 2 | 3 | import com.jimmy.hulk.common.enums.ConditionEnum; 4 | import com.jimmy.hulk.common.enums.ConditionTypeEnum; 5 | import lombok.Data; 6 | 7 | import java.io.Serializable; 8 | 9 | @Data 10 | public class ConditionNode implements Serializable { 11 | 12 | private ColumnNode column; 13 | 14 | private ConditionEnum condition; 15 | 16 | private Object value; 17 | 18 | private ColumnNode targetColumn; 19 | 20 | private ConditionTypeEnum conditionType = ConditionTypeEnum.AND; 21 | } 22 | -------------------------------------------------------------------------------- /route/src/main/java/com/jimmy/hulk/route/config/RouteConfig.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.route.config; 2 | 3 | import com.jimmy.hulk.route.support.ModProxy; 4 | import com.jimmy.hulk.route.support.RouteInitialize; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | @Configuration 9 | public class RouteConfig { 10 | 11 | @Bean 12 | public ModProxy modFactory() { 13 | return new ModProxy(); 14 | } 15 | 16 | @Bean 17 | public RouteInitialize routeInitialize() { 18 | return new RouteInitialize(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /actuator/src/main/java/com/jimmy/hulk/actuator/support/ActuatorInitialize.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.actuator.support; 2 | 3 | import com.jimmy.hulk.actuator.part.PartSupport; 4 | import com.jimmy.hulk.common.base.Initialize; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | 7 | public class ActuatorInitialize implements Initialize { 8 | 9 | @Autowired 10 | private PartSupport partSupport; 11 | 12 | @Override 13 | public void init() throws Exception { 14 | partSupport.init(); 15 | } 16 | 17 | @Override 18 | public int sort() { 19 | return 1; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /common/src/main/java/com/jimmy/hulk/common/core/Column.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.common.core; 2 | 3 | import com.jimmy.hulk.common.enums.FieldTypeEnum; 4 | import lombok.Data; 5 | 6 | import java.io.Serializable; 7 | 8 | @Data 9 | public class Column implements Serializable { 10 | 11 | private String name; 12 | 13 | private String length; 14 | 15 | private String notes; 16 | 17 | private Boolean isAllowNull = true; 18 | 19 | private String defaultValue; 20 | 21 | private FieldTypeEnum fieldTypeEnum; 22 | 23 | private Boolean isPrimary = false; 24 | 25 | private String tokenizer; 26 | } 27 | -------------------------------------------------------------------------------- /canal/src/main/java/com/jimmy/hulk/canal/base/Instance.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.canal.base; 2 | 3 | import com.jimmy.hulk.canal.core.CanalMessage; 4 | import com.jimmy.hulk.canal.core.CanalPosition; 5 | 6 | import java.util.List; 7 | import java.util.concurrent.TimeUnit; 8 | 9 | public interface Instance extends LifeCycle { 10 | 11 | void subscribe(); 12 | 13 | void unsubscribe(); 14 | 15 | void point(CanalPosition canalPosition); 16 | 17 | void ack(long batchId); 18 | 19 | void rollback(); 20 | 21 | void destroy(); 22 | 23 | CanalMessage get(int batchSize, Long timeout, TimeUnit unit); 24 | } 25 | -------------------------------------------------------------------------------- /protocol/src/main/java/com/jimmy/hulk/protocol/reponse/ErrorResponse.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.protocol.reponse; 2 | 3 | import cn.hutool.core.util.StrUtil; 4 | import com.jimmy.hulk.protocol.core.Context; 5 | import com.jimmy.hulk.protocol.packages.ErrorPacket; 6 | 7 | public class ErrorResponse { 8 | 9 | public static void response(Context context, String errMsg) { 10 | if (StrUtil.isNotEmpty(errMsg)) { 11 | ErrorPacket errorPacket = new ErrorPacket(); 12 | errorPacket.message = errMsg.getBytes(); 13 | errorPacket.write(context.getChannelHandlerContext()); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/config/DataProperties.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.config; 2 | 3 | import com.google.common.collect.Maps; 4 | import lombok.Data; 5 | import org.springframework.boot.context.properties.ConfigurationProperties; 6 | 7 | import java.util.Map; 8 | 9 | @Data 10 | @ConfigurationProperties(prefix = "jimmy.data") 11 | public class DataProperties { 12 | 13 | private String scanPath; 14 | 15 | private String fileStorePath = "/tmp/"; 16 | 17 | private Map datasource = Maps.newHashMap(); 18 | 19 | private Map server = Maps.newHashMap(); 20 | } 21 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/annotation/Mapper.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.annotation; 2 | 3 | import com.jimmy.hulk.data.base.Convert; 4 | import com.jimmy.hulk.data.convert.DefaultConvert; 5 | import com.jimmy.hulk.common.enums.DatasourceEnum; 6 | 7 | import java.lang.annotation.*; 8 | 9 | @Documented 10 | @Retention(RetentionPolicy.RUNTIME) 11 | @Target({ElementType.FIELD}) 12 | @Inherited 13 | public @interface Mapper { 14 | 15 | DatasourceEnum dsType(); 16 | 17 | String dsName(); 18 | 19 | String indexName(); 20 | 21 | Class convert() default DefaultConvert.class; 22 | 23 | String priKeyName() default "id"; 24 | } 25 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/convert/HumpConvert.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.convert; 2 | 3 | import cn.hutool.core.util.StrUtil; 4 | import com.jimmy.hulk.data.base.Convert; 5 | 6 | public class HumpConvert implements Convert { 7 | 8 | @Override 9 | public String convertToBean(String key) { 10 | if (key.equalsIgnoreCase("_id")) { 11 | return key; 12 | } 13 | return StrUtil.toCamelCase(key); 14 | } 15 | 16 | @Override 17 | public String convertToMap(String key) { 18 | if (key.equalsIgnoreCase("_id")) { 19 | return key; 20 | } 21 | 22 | return StrUtil.toUnderlineCase(key); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/condition/MySQLCondition.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.condition; 2 | 3 | import org.springframework.context.annotation.Condition; 4 | import org.springframework.context.annotation.ConditionContext; 5 | import org.springframework.core.type.AnnotatedTypeMetadata; 6 | 7 | public class MySQLCondition implements Condition { 8 | 9 | @Override 10 | public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { 11 | try { 12 | boolean b = null != Class.forName("com.mysql.jdbc.Driver"); 13 | return b; 14 | } catch (ClassNotFoundException e) { 15 | return false; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /actuator/src/main/java/com/jimmy/hulk/actuator/function/IdGenerator.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.actuator.function; 2 | 3 | import cn.hutool.core.util.IdUtil; 4 | import com.googlecode.aviator.runtime.function.AbstractFunction; 5 | import com.googlecode.aviator.runtime.type.AviatorObject; 6 | import com.googlecode.aviator.runtime.type.AviatorString; 7 | 8 | import java.util.Map; 9 | 10 | public class IdGenerator extends AbstractFunction { 11 | 12 | @Override 13 | public AviatorObject call(Map env) { 14 | return new AviatorString(IdUtil.simpleUUID()); 15 | } 16 | 17 | @Override 18 | public String getName() { 19 | return "idGenerator"; 20 | } 21 | } 22 | 23 | -------------------------------------------------------------------------------- /booster/src/main/java/com/jimmy/hulk/booster/action/RollbackAction.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.booster.action; 2 | 3 | import com.jimmy.hulk.booster.core.Session; 4 | import com.jimmy.hulk.protocol.utils.parse.QueryParse; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.springframework.stereotype.Component; 7 | 8 | @Slf4j 9 | @Component 10 | public class RollbackAction extends BaseAction { 11 | 12 | @Override 13 | public void action(String sql, Session session, int offset) throws Exception { 14 | session.getWaitTransactionSQL().clear(); 15 | session.writeOk(); 16 | } 17 | 18 | @Override 19 | public int type() { 20 | return QueryParse.ROLLBACK; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/condition/ExcelCondition.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.condition; 2 | 3 | import org.springframework.context.annotation.Condition; 4 | import org.springframework.context.annotation.ConditionContext; 5 | import org.springframework.core.type.AnnotatedTypeMetadata; 6 | 7 | public class ExcelCondition implements Condition { 8 | 9 | @Override 10 | public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { 11 | try { 12 | boolean b = null != Class.forName("com.alibaba.excel.EasyExcel"); 13 | return b; 14 | } catch (ClassNotFoundException e) { 15 | return false; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/condition/Neo4jCondition.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.condition; 2 | 3 | import org.springframework.context.annotation.Condition; 4 | import org.springframework.context.annotation.ConditionContext; 5 | import org.springframework.core.type.AnnotatedTypeMetadata; 6 | 7 | public class Neo4jCondition implements Condition { 8 | 9 | @Override 10 | public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { 11 | try { 12 | boolean b = null != Class.forName("org.neo4j.driver.Session"); 13 | return b; 14 | } catch (ClassNotFoundException e) { 15 | return false; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/condition/OracleCondition.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.condition; 2 | 3 | import org.springframework.context.annotation.Condition; 4 | import org.springframework.context.annotation.ConditionContext; 5 | import org.springframework.core.type.AnnotatedTypeMetadata; 6 | 7 | public class OracleCondition implements Condition { 8 | 9 | @Override 10 | public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { 11 | try { 12 | boolean b = null != Class.forName("oracle.jdbc.driver.OracleDriver"); 13 | return b; 14 | } catch (ClassNotFoundException e) { 15 | return false; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /actuator/src/main/java/com/jimmy/hulk/actuator/enums/PriKeyStrategyTypeEnum.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.actuator.enums; 2 | 3 | import cn.hutool.core.util.IdUtil; 4 | import com.jimmy.hulk.common.base.PriKeyStrategy; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Getter; 7 | 8 | @Getter 9 | @AllArgsConstructor 10 | public enum PriKeyStrategyTypeEnum { 11 | 12 | AUTO(() -> null), 13 | SNOWFLAKE(() -> IdUtil.createSnowflake(1, 1).nextId()), 14 | UID(() -> { 15 | Long snowId = IdUtil.createSnowflake(1, 1).nextId(); 16 | String ssid = Long.toString(snowId, Character.MAX_RADIX).toLowerCase(); 17 | return ssid; 18 | }); 19 | 20 | private PriKeyStrategy priKeyStrategy; 21 | } 22 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/condition/MongoDBCondition.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.condition; 2 | 3 | import org.springframework.context.annotation.Condition; 4 | import org.springframework.context.annotation.ConditionContext; 5 | import org.springframework.core.type.AnnotatedTypeMetadata; 6 | 7 | public class MongoDBCondition implements Condition { 8 | 9 | @Override 10 | public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { 11 | try { 12 | boolean b = null != Class.forName("com.mongodb.MongoClientSettings"); 13 | return b; 14 | } catch (ClassNotFoundException e) { 15 | return false; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /booster/src/main/bin/startup.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | @if not "%ECHO%" == "" echo %ECHO% 4 | @if "%OS%" == "Windows_NT" setlocal 5 | 6 | set ENV_PATH=.\ 7 | if "%OS%" == "Windows_NT" set ENV_PATH=%~dp0% 8 | 9 | set conf_dir=%ENV_PATH%\..\conf 10 | set CLASSPATH=%conf_dir% 11 | set CLASSPATH=%conf_dir%\..\lib\*;%CLASSPATH% 12 | 13 | set JAVA_MEM_OPTS= -Xms256m -Xmx1g -XX:PermSize=128m 14 | set JAVA_OPTS_EXT= -Djava.awt.headless=true -Djava.net.preferIPv4Stack=true -Dapplication.codeset=UTF-8 -Dfile.encoding=UTF-8 15 | set ADAPTER_OPTS= -DappName=ss-booster-0.0.1-SNAPSHOT 16 | 17 | set CMD_STR= java %JAVA_OPTS% -classpath "%CLASSPATH%" App 18 | echo start cmd : %CMD_STR% 19 | 20 | java %JAVA_OPTS% -classpath "%CLASSPATH%" App 21 | 22 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/condition/ClickHouseCondition.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.condition; 2 | 3 | import org.springframework.context.annotation.Condition; 4 | import org.springframework.context.annotation.ConditionContext; 5 | import org.springframework.core.type.AnnotatedTypeMetadata; 6 | 7 | public class ClickHouseCondition implements Condition { 8 | 9 | @Override 10 | public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { 11 | try { 12 | boolean b = null != Class.forName("ru.yandex.clickhouse.ClickHouseDriver"); 13 | return b; 14 | } catch (ClassNotFoundException e) { 15 | return false; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/condition/SqlServerCondition.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.condition; 2 | 3 | import org.springframework.context.annotation.Condition; 4 | import org.springframework.context.annotation.ConditionContext; 5 | import org.springframework.core.type.AnnotatedTypeMetadata; 6 | 7 | public class SqlServerCondition implements Condition { 8 | 9 | @Override 10 | public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { 11 | try { 12 | boolean b = null != Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); 13 | return b; 14 | } catch (ClassNotFoundException e) { 15 | return false; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/condition/ElasticsearchCondition.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.condition; 2 | 3 | import org.springframework.context.annotation.Condition; 4 | import org.springframework.context.annotation.ConditionContext; 5 | import org.springframework.core.type.AnnotatedTypeMetadata; 6 | 7 | public class ElasticsearchCondition implements Condition { 8 | 9 | @Override 10 | public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { 11 | try { 12 | boolean b = null != Class.forName("org.elasticsearch.client.RestHighLevelClient"); 13 | return b; 14 | } catch (ClassNotFoundException e) { 15 | return false; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /config/src/main/java/com/jimmy/hulk/config/properties/UserConfigProperty.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.config.properties; 2 | 3 | import com.jimmy.hulk.authority.core.UserDetail; 4 | import com.jimmy.hulk.common.enums.RoleEnum; 5 | import lombok.Data; 6 | 7 | import java.io.Serializable; 8 | 9 | @Data 10 | public class UserConfigProperty implements Serializable { 11 | 12 | private String username; 13 | 14 | private String password; 15 | 16 | private RoleEnum role; 17 | 18 | public UserDetail buildUserDetail() { 19 | UserDetail userDetail = new UserDetail(); 20 | userDetail.setPassword(this.password); 21 | userDetail.setUsername(this.username); 22 | userDetail.setRole(this.role); 23 | return userDetail; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /authority/src/main/java/com/jimmy/hulk/authority/config/AuthorityConfig.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.authority.config; 2 | 3 | import com.jimmy.hulk.authority.base.AuthenticationManager; 4 | import com.jimmy.hulk.authority.datasource.DatasourceCenter; 5 | import com.jimmy.hulk.authority.support.AuthenticationManagerDelegator; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.context.annotation.Configuration; 8 | 9 | @Configuration 10 | public class AuthorityConfig { 11 | 12 | @Bean 13 | public AuthenticationManager authenticationManager() { 14 | return new AuthenticationManagerDelegator(); 15 | } 16 | 17 | @Bean 18 | public DatasourceCenter datasourceCenter() { 19 | return new DatasourceCenter(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /parse/src/main/java/com/jimmy/hulk/parse/core/element/IndexNode.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.parse.core.element; 2 | 3 | import com.google.common.collect.Lists; 4 | import com.jimmy.hulk.common.core.Index; 5 | import com.jimmy.hulk.common.enums.IndexTypeEnum; 6 | import lombok.Data; 7 | 8 | import java.io.Serializable; 9 | import java.util.List; 10 | 11 | @Data 12 | public class IndexNode implements Serializable { 13 | 14 | private String name; 15 | 16 | private IndexTypeEnum indexType; 17 | 18 | private List columns = Lists.newArrayList(); 19 | 20 | public Index build() { 21 | Index index = new Index(); 22 | index.setIndexType(indexType); 23 | index.setName(name); 24 | index.setFields(columns); 25 | return index; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /config/src/main/java/com/jimmy/hulk/config/properties/PartitionConfigProperty.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.config.properties; 2 | 3 | import com.google.common.collect.Lists; 4 | import com.jimmy.hulk.common.enums.DatasourceEnum; 5 | import lombok.Data; 6 | 7 | import java.io.Serializable; 8 | import java.util.List; 9 | 10 | @Data 11 | public class PartitionConfigProperty implements Serializable { 12 | 13 | private String mod = "hash-mod"; 14 | 15 | private String table; 16 | 17 | private String dsName; 18 | 19 | private String priKeyColumn; 20 | 21 | private String partitionColumn; 22 | 23 | private Boolean isReadOnly = false; 24 | 25 | private DatasourceEnum datasourceEnum; 26 | 27 | private List tableConfigProperties = Lists.newArrayList(); 28 | } 29 | -------------------------------------------------------------------------------- /actuator/src/main/java/com/jimmy/hulk/actuator/enums/SerializerTypeEnum.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.actuator.enums; 2 | 3 | import com.jimmy.hulk.actuator.base.Serializer; 4 | import com.jimmy.hulk.actuator.part.serializer.KryoSerializer; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Getter; 7 | 8 | @Getter 9 | @AllArgsConstructor 10 | public enum SerializerTypeEnum { 11 | 12 | KRYO("kryo", new KryoSerializer()); 13 | 14 | private String name; 15 | 16 | private Serializer serializer; 17 | 18 | public static SerializerTypeEnum getByName(String name) { 19 | for (SerializerTypeEnum value : SerializerTypeEnum.values()) { 20 | if (value.name.equalsIgnoreCase(name)) { 21 | return value; 22 | } 23 | } 24 | 25 | return null; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/support/DataInitialize.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.support; 2 | 3 | import com.googlecode.aviator.AviatorEvaluator; 4 | import com.jimmy.hulk.common.base.Initialize; 5 | import com.jimmy.hulk.data.other.In; 6 | import com.jimmy.hulk.data.other.NotIn; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | 9 | public class DataInitialize implements Initialize { 10 | 11 | @Autowired 12 | private DataSourceFactory dataSourceFactory; 13 | 14 | @Override 15 | public void init() throws Exception { 16 | dataSourceFactory.init(); 17 | //注入函数 18 | AviatorEvaluator.addFunction(new In()); 19 | AviatorEvaluator.addFunction(new NotIn()); 20 | } 21 | 22 | @Override 23 | public int sort() { 24 | return 0; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /common/src/main/java/com/jimmy/hulk/common/enums/OracleConnectTypeEnum.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.common.enums; 2 | 3 | import cn.hutool.core.util.StrUtil; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Getter; 6 | 7 | @Getter 8 | @AllArgsConstructor 9 | public enum OracleConnectTypeEnum { 10 | 11 | SID("0", "SID"), SERVICE_NAME("1", "serviceName"); 12 | 13 | private String connectType; 14 | 15 | private String connectParam; 16 | 17 | public static OracleConnectTypeEnum getByCode(String code) { 18 | if (StrUtil.isEmpty(code)) { 19 | return null; 20 | } 21 | 22 | switch (code) { 23 | case "0": 24 | return SID; 25 | case "1": 26 | return SERVICE_NAME; 27 | default: 28 | return null; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /booster/src/main/java/com/jimmy/hulk/booster/action/JobAction.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.booster.action; 2 | 3 | import com.jimmy.hulk.actuator.sql.Job; 4 | import com.jimmy.hulk.booster.core.Session; 5 | import com.jimmy.hulk.parse.core.result.ParseResultNode; 6 | import com.jimmy.hulk.protocol.utils.parse.QueryParse; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Component; 9 | 10 | @Component 11 | public class JobAction extends BaseAction { 12 | 13 | @Autowired 14 | private Job job; 15 | 16 | @Override 17 | public void action(String sql, Session session, int offset) throws Exception { 18 | //正常SQL执行 19 | ParseResultNode parse = sqlParser.parse(sql); 20 | this.success(session, job.execute(parse)); 21 | } 22 | 23 | @Override 24 | public int type() { 25 | return QueryParse.JOB; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /protocol/src/main/java/com/jimmy/hulk/protocol/reponse/select/PreparedStmtResponse.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.protocol.reponse.select; 2 | 3 | import com.jimmy.hulk.protocol.core.Context; 4 | import com.jimmy.hulk.protocol.core.PreparedStatement; 5 | import com.jimmy.hulk.protocol.packages.PreparedOkPacket; 6 | 7 | public class PreparedStmtResponse { 8 | 9 | public static void response(PreparedStatement preparedStatement, Context c) { 10 | byte packetId = 0; 11 | // write preparedOk packet 12 | PreparedOkPacket preparedOk = new PreparedOkPacket(); 13 | preparedOk.packetId = ++packetId; 14 | preparedOk.statementId = preparedStatement.getId(); 15 | preparedOk.columnsNumber = preparedStatement.getColumnsNumber(); 16 | preparedOk.parametersNumber = preparedStatement.getParametersNumber(); 17 | preparedOk.write(c.getChannelHandlerContext()); 18 | } 19 | } -------------------------------------------------------------------------------- /authority/src/main/java/com/jimmy/hulk/authority/base/AuthenticationManager.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.authority.base; 2 | 3 | import com.jimmy.hulk.authority.core.UserDetail; 4 | import com.jimmy.hulk.authority.core.AuthenticationSchema; 5 | import com.jimmy.hulk.authority.core.AuthenticationTable; 6 | 7 | import java.util.Set; 8 | 9 | public interface AuthenticationManager { 10 | 11 | void registerUser(UserDetail userDetail); 12 | 13 | boolean allowExecuteSQL(String username, String dsName, String tableName); 14 | 15 | UserDetail getUserDetail(String username); 16 | 17 | void configSchema(String username, AuthenticationSchema authenticationSchema); 18 | 19 | boolean checkConfigSchemaByUsername(String username, String schema); 20 | 21 | Set getSchema(String username); 22 | 23 | AuthenticationTable getAuthenticationTable(String username, String dsName, String tableName); 24 | } 25 | -------------------------------------------------------------------------------- /booster/src/main/java/com/jimmy/hulk/booster/action/FlushAction.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.booster.action; 2 | 3 | import com.jimmy.hulk.actuator.sql.Flush; 4 | import com.jimmy.hulk.booster.core.Session; 5 | import com.jimmy.hulk.parse.core.result.ParseResultNode; 6 | import com.jimmy.hulk.protocol.utils.parse.QueryParse; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Component; 9 | 10 | @Component 11 | public class FlushAction extends BaseAction { 12 | 13 | @Autowired 14 | private Flush flush; 15 | 16 | @Override 17 | public void action(String sql, Session session, int offset) throws Exception { 18 | //正常SQL执行 19 | ParseResultNode parse = sqlParser.parse(sql); 20 | this.success(session, flush.execute(parse)); 21 | } 22 | 23 | @Override 24 | public int type() { 25 | return QueryParse.FLUSH; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/core/ParseResult.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.core; 2 | 3 | import com.google.common.collect.Lists; 4 | import com.google.common.collect.Maps; 5 | import com.jimmy.hulk.common.enums.SqlTypeEnum; 6 | import lombok.Data; 7 | 8 | import java.io.Serializable; 9 | import java.util.List; 10 | import java.util.Map; 11 | 12 | @Data 13 | public class ParseResult implements Serializable { 14 | 15 | private String table; 16 | 17 | private String tableAlias; 18 | 19 | private SqlTypeEnum sqlType; 20 | 21 | private Boolean isAllFields = false; 22 | 23 | private Integer offset; 24 | 25 | private Integer fetch; 26 | 27 | private Wrapper wrapper = Wrapper.build(); 28 | 29 | private List fields = Lists.newArrayList(); 30 | 31 | private Map alias = Maps.newHashMap(); 32 | 33 | private Map data = Maps.newHashMap(); 34 | } 35 | -------------------------------------------------------------------------------- /parse/src/main/java/com/jimmy/hulk/parse/core/element/AlterNode.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.parse.core.element; 2 | 3 | import com.jimmy.hulk.common.core.Alter; 4 | import com.jimmy.hulk.common.enums.AlterTypeEnum; 5 | import lombok.Data; 6 | 7 | import java.io.Serializable; 8 | 9 | @Data 10 | public class AlterNode implements Serializable { 11 | 12 | private String table; 13 | 14 | private IndexNode indexNode; 15 | 16 | private ColumnNode columnNode; 17 | 18 | private ColumnNode oldColumnNode; 19 | 20 | private AlterTypeEnum alterTypeEnum; 21 | 22 | public Alter build() { 23 | Alter alter = new Alter(); 24 | alter.setAlterType(this.alterTypeEnum); 25 | alter.setTable(this.table); 26 | alter.setColumn(columnNode.build()); 27 | alter.setOldColumn(oldColumnNode.build()); 28 | alter.setIndex(indexNode.build()); 29 | return alter; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /config/src/main/java/com/jimmy/hulk/config/config/ConfigConfig.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.config.config; 2 | 3 | import com.jimmy.hulk.config.support.*; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | @Configuration 8 | public class ConfigConfig { 9 | 10 | @Bean 11 | public TableConfig partitionContext() { 12 | return new TableConfig(); 13 | } 14 | 15 | @Bean 16 | public DatabaseConfig databaseConfig(){ 17 | return new DatabaseConfig(); 18 | } 19 | 20 | @Bean 21 | public XmlParse xmlParse() { 22 | return new XmlParse(); 23 | } 24 | 25 | @Bean 26 | public ConfigInitialize configInitialize() { 27 | return new ConfigInitialize(); 28 | } 29 | 30 | @Bean 31 | public SystemVariableContext systemVariableContext() { 32 | return new SystemVariableContext(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /canal/src/main/java/com/jimmy/hulk/canal/core/CanalConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.canal.core; 2 | 3 | import com.jimmy.hulk.canal.enums.InstanceTypeEnum; 4 | import lombok.Data; 5 | 6 | import java.io.Serializable; 7 | import java.util.concurrent.TimeUnit; 8 | 9 | @Data 10 | public class CanalConfiguration implements Serializable { 11 | 12 | private InstanceTypeEnum instanceTypeEnum; 13 | 14 | private String fileDataDir; 15 | 16 | private String destination; 17 | 18 | private Long slaveId; 19 | 20 | private String host; 21 | 22 | private Integer port; 23 | 24 | private String username; 25 | 26 | private String password; 27 | 28 | private String defaultDatabaseName; 29 | 30 | private String filterExpression; 31 | 32 | private String blacklistExpression; 33 | 34 | private boolean isGTIDMode; 35 | 36 | private Integer batchSize; 37 | 38 | private Long timeout; 39 | 40 | private TimeUnit timeUnit; 41 | } 42 | -------------------------------------------------------------------------------- /config/src/main/java/com/jimmy/hulk/config/properties/AuthenticationTableConfigProperty.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.config.properties; 2 | 3 | import com.google.common.collect.Lists; 4 | import com.jimmy.hulk.authority.core.AuthenticationTable; 5 | import lombok.Data; 6 | 7 | import java.io.Serializable; 8 | import java.util.List; 9 | 10 | @Data 11 | public class AuthenticationTableConfigProperty implements Serializable { 12 | 13 | private String table; 14 | 15 | private List filterFields = Lists.newArrayList(); 16 | 17 | private List dmlAllowMethods = Lists.newArrayList(); 18 | 19 | public AuthenticationTable buildAuthenticationTable() { 20 | AuthenticationTable authenticationTable = new AuthenticationTable(); 21 | authenticationTable.setTable(this.table); 22 | authenticationTable.setFilterFields(this.filterFields); 23 | authenticationTable.setDmlAllowMethods(this.dmlAllowMethods); 24 | return authenticationTable; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /booster/src/test/java/com/jimmy/hulk/booster/BoosterTest.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.booster; 2 | 3 | import com.jimmy.hulk.authority.support.AuthenticationManagerDelegator; 4 | import com.jimmy.hulk.booster.support.DatabaseServer; 5 | import com.jimmy.hulk.booster.support.SessionPool; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.boot.test.context.SpringBootTest; 11 | import org.springframework.test.context.junit4.SpringRunner; 12 | 13 | @SpringBootTest(classes = App.class) 14 | @RunWith(SpringRunner.class) 15 | @Slf4j 16 | public class BoosterTest { 17 | 18 | @Autowired 19 | private SessionPool sessionPool; 20 | 21 | @Autowired 22 | private AuthenticationManagerDelegator authenticationManagerDelegator; 23 | 24 | @Test 25 | public void ggg() { 26 | new DatabaseServer(1113, sessionPool, authenticationManagerDelegator).startServer(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /canal/src/main/java/com/jimmy/hulk/canal/core/CanalRowData.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.canal.core; 2 | 3 | import com.google.common.collect.Lists; 4 | import com.google.common.collect.Maps; 5 | import lombok.Data; 6 | 7 | import java.io.Serializable; 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | @Data 12 | public class CanalRowData implements Serializable { 13 | 14 | private long id; 15 | 16 | private String database; 17 | 18 | private String table; 19 | 20 | private Boolean isDdl = false; 21 | 22 | private String type; 23 | 24 | private Long es; 25 | 26 | private Long ts; 27 | 28 | private String sql; 29 | 30 | private List pkNames = Lists.newArrayList(); 31 | 32 | private Map sqlType = Maps.newHashMap(); 33 | 34 | private Map mysqlType = Maps.newHashMap(); 35 | 36 | private List> data = Lists.newArrayList(); 37 | 38 | private List> old = Lists.newArrayList(); 39 | 40 | } 41 | -------------------------------------------------------------------------------- /booster/src/main/java/com/jimmy/hulk/booster/handler/SessionHandler.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.booster.handler; 2 | 3 | import com.jimmy.hulk.booster.core.Session; 4 | import com.jimmy.hulk.booster.support.SessionPool; 5 | import io.netty.channel.ChannelHandlerAdapter; 6 | import io.netty.channel.ChannelHandlerContext; 7 | 8 | public class SessionHandler extends ChannelHandlerAdapter { 9 | 10 | private Session session; 11 | 12 | private SessionPool sessionPool; 13 | 14 | public SessionHandler(Session session, SessionPool sessionPool) { 15 | this.session = session; 16 | this.sessionPool = sessionPool; 17 | } 18 | 19 | @Override 20 | public void channelActive(ChannelHandlerContext ctx) throws Exception { 21 | sessionPool.put(session); 22 | ctx.fireChannelActive(); 23 | } 24 | 25 | @Override 26 | public void channelInactive(ChannelHandlerContext ctx) throws Exception { 27 | sessionPool.remove(session.getId()); 28 | session.close(); 29 | ctx.fireChannelActive(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /common/src/main/java/com/jimmy/hulk/common/enums/DatasourceEnum.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.common.enums; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | 6 | @Getter 7 | @AllArgsConstructor 8 | public enum DatasourceEnum { 9 | ELASTICSEARCH("1", "elasticsearch", false, false), 10 | MYSQL("0", "mysql", true, true), 11 | ORACLE("2", "oracle", true, true), 12 | CLICK_HOUSE("3", "clickhouse", true, true), 13 | NEO4J("4", "neo4j", true, false), 14 | EXCEL("5", "excel", false, false), 15 | SQL_SERVER("6", "sqlServer", true, false), 16 | MONGODB("7", "mongoDB", false, false); 17 | 18 | private String code; 19 | 20 | private String message; 21 | 22 | private Boolean isTransaction; 23 | 24 | private Boolean isSupportSql; 25 | 26 | public static DatasourceEnum getByMessage(String message) { 27 | for (DatasourceEnum value : DatasourceEnum.values()) { 28 | if (value.message.equalsIgnoreCase(message)) { 29 | return value; 30 | } 31 | } 32 | 33 | return null; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /booster/src/main/java/com/jimmy/hulk/booster/action/DeleteAction.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.booster.action; 2 | 3 | import com.jimmy.hulk.actuator.sql.Delete; 4 | import com.jimmy.hulk.booster.core.Session; 5 | import com.jimmy.hulk.parse.core.result.ParseResultNode; 6 | import com.jimmy.hulk.protocol.utils.parse.QueryParse; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Component; 9 | 10 | @Component 11 | public class DeleteAction extends BaseAction { 12 | 13 | @Autowired 14 | private Delete delete; 15 | 16 | @Override 17 | public void action(String sql, Session session, int offset) throws Exception { 18 | //手动提交 19 | if (!session.isAutocommit()) { 20 | session.addSQL(sql); 21 | this.success(session, 1); 22 | return; 23 | } 24 | //正常SQL执行 25 | ParseResultNode parse = sqlParser.parse(sql); 26 | this.success(session, delete.execute(parse)); 27 | } 28 | 29 | @Override 30 | public int type() { 31 | return QueryParse.DELETE; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /booster/src/main/java/com/jimmy/hulk/booster/action/UpdateAction.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.booster.action; 2 | 3 | import com.jimmy.hulk.actuator.sql.Update; 4 | import com.jimmy.hulk.booster.core.Session; 5 | import com.jimmy.hulk.parse.core.result.ParseResultNode; 6 | import com.jimmy.hulk.protocol.utils.parse.QueryParse; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Component; 9 | 10 | @Component 11 | public class UpdateAction extends BaseAction { 12 | 13 | @Autowired 14 | private Update update; 15 | 16 | @Override 17 | public void action(String sql, Session session, int offset) throws Exception { 18 | //手动提交 19 | if (!session.isAutocommit()) { 20 | session.addSQL(sql); 21 | this.success(session, 1); 22 | return; 23 | } 24 | //正常SQL执行 25 | ParseResultNode parse = sqlParser.parse(sql); 26 | this.success(session, update.execute(parse)); 27 | } 28 | 29 | @Override 30 | public int type() { 31 | return QueryParse.UPDATE; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/config/DataConfig.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.config; 2 | 3 | import com.jimmy.hulk.data.support.DataSourceFactory; 4 | import com.jimmy.hulk.data.mapper.MapperRegistered; 5 | import com.jimmy.hulk.data.support.DataInitialize; 6 | import com.jimmy.hulk.data.support.SessionFactory; 7 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 8 | import org.springframework.context.annotation.Bean; 9 | import org.springframework.context.annotation.Configuration; 10 | 11 | @Configuration 12 | @EnableConfigurationProperties(DataProperties.class) 13 | public class DataConfig { 14 | 15 | @Bean 16 | public DataSourceFactory dsFactory() { 17 | return new DataSourceFactory(); 18 | } 19 | 20 | @Bean 21 | public MapperRegistered mapperRegistered() { 22 | return new MapperRegistered(); 23 | } 24 | 25 | @Bean 26 | public SessionFactory sessionFactory() { 27 | return new SessionFactory(); 28 | } 29 | 30 | @Bean 31 | public DataInitialize dataInitialize() { 32 | return new DataInitialize(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/base/DataSource.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.base; 2 | 3 | import com.jimmy.hulk.data.core.Dump; 4 | import com.jimmy.hulk.data.actuator.Actuator; 5 | import com.jimmy.hulk.data.config.DataSourceProperty; 6 | import com.jimmy.hulk.data.config.DataProperties; 7 | import com.jimmy.hulk.common.enums.DatasourceEnum; 8 | import com.jimmy.hulk.common.enums.FieldTypeEnum; 9 | import com.jimmy.hulk.data.other.ConnectionContext; 10 | 11 | import java.io.Closeable; 12 | import java.util.Map; 13 | 14 | public interface DataSource extends Closeable { 15 | 16 | DatasourceEnum type(); 17 | 18 | Actuator getActuator(); 19 | 20 | T getDataSource(); 21 | 22 | T getDataSource(Long timeout); 23 | 24 | boolean testConnect(); 25 | 26 | void dump(Dump dump) throws Exception; 27 | 28 | T getDataSourceWithoutCache(Long timeout); 29 | 30 | Map getFieldTypeMapper(); 31 | 32 | DataSourceProperty getDataSourceProperty(); 33 | 34 | Connection getConnection(ConnectionContext context); 35 | 36 | void init(DataProperties dataProperties); 37 | } 38 | -------------------------------------------------------------------------------- /canal/src/main/java/com/jimmy/hulk/canal/instance/AbstractInstance.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.canal.instance; 2 | 3 | import com.jimmy.hulk.canal.base.Instance; 4 | import com.jimmy.hulk.common.enums.ModuleEnum; 5 | import com.jimmy.hulk.common.exception.HulkException; 6 | 7 | public abstract class AbstractInstance implements Instance { 8 | 9 | protected final String destination; 10 | 11 | protected volatile boolean running = false; // 是否处于运行中 12 | 13 | protected AbstractInstance(String destination) { 14 | this.destination = destination; 15 | } 16 | 17 | public boolean isStart() { 18 | return running; 19 | } 20 | 21 | public void start() { 22 | if (running) { 23 | throw new HulkException(this.getClass().getName() + " has startup , don't repeat start", ModuleEnum.CANAL); 24 | } 25 | 26 | running = true; 27 | } 28 | 29 | public void stop() { 30 | if (!running) { 31 | throw new HulkException(this.getClass().getName() + " isn't start , please check", ModuleEnum.CANAL); 32 | } 33 | 34 | running = false; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /protocol/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | com.jimmy 7 | hulk 8 | 0.0.1-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | protocol 13 | jar 14 | 15 | 16 | io.netty 17 | netty-all 18 | 19 | 20 | com.jimmy 21 | common 22 | 0.0.1-SNAPSHOT 23 | 24 | 25 | org.projectlombok 26 | lombok 27 | provided 28 | 29 | 30 | -------------------------------------------------------------------------------- /canal/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | com.jimmy 7 | hulk 8 | 0.0.1-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | canal 13 | jar 14 | 15 | 16 | com.alibaba.otter 17 | canal.parse 18 | 19 | 20 | com.jimmy 21 | common 22 | 0.0.1-SNAPSHOT 23 | 24 | 25 | org.projectlombok 26 | lombok 27 | provided 28 | 29 | 30 | -------------------------------------------------------------------------------- /protocol/src/main/java/com/jimmy/hulk/protocol/core/PreparedStatement.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.protocol.core; 2 | 3 | import com.google.common.collect.Maps; 4 | import lombok.Data; 5 | 6 | import java.io.ByteArrayOutputStream; 7 | import java.util.Map; 8 | 9 | @Data 10 | public class PreparedStatement { 11 | 12 | private long id; 13 | private String sql; 14 | private int columnsNumber; 15 | private int parametersNumber = 0; 16 | private int[] parametersType; 17 | //存放COM_STMT_SEND_LONG_DATA命令发送过来的字节数据 18 | private Map longDataMap; 19 | 20 | public PreparedStatement(long id, String sql, int columnsNumber, int parametersNumber) { 21 | this.id = id; 22 | this.sql = sql; 23 | this.columnsNumber = columnsNumber; 24 | this.longDataMap = Maps.newHashMap(); 25 | 26 | if (parametersNumber > 0) { 27 | this.parametersNumber = parametersNumber; 28 | this.parametersType = new int[parametersNumber]; 29 | } 30 | } 31 | 32 | public ByteArrayOutputStream getLongData(long paramId) { 33 | return longDataMap.get(paramId); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/base/DataMapper.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.base; 2 | 3 | import com.jimmy.hulk.data.core.PageResult; 4 | import com.jimmy.hulk.data.core.Page; 5 | import com.jimmy.hulk.data.core.Wrapper; 6 | 7 | import java.io.Serializable; 8 | import java.util.List; 9 | 10 | public interface DataMapper { 11 | 12 | PageResult queryPage(Wrapper wrapper, Page page); 13 | 14 | int delete(Serializable id); 15 | 16 | T queryById(Serializable id); 17 | 18 | int add(T doc, Serializable id); 19 | 20 | int add(T doc); 21 | 22 | int addBatch(List docs); 23 | 24 | int updateBatch(List docs, Wrapper wrapper); 25 | 26 | int updateBatchById(List docs); 27 | 28 | int update(T doc, Wrapper wrapper); 29 | 30 | int delete(Wrapper wrapper); 31 | 32 | int updateById(T doc, Serializable id); 33 | 34 | List queryList(Wrapper wrapper); 35 | 36 | List queryList(); 37 | 38 | T queryOne(Wrapper wrapper); 39 | 40 | int count(Wrapper wrapper); 41 | 42 | boolean queryIsExist(Wrapper wrapper); 43 | 44 | List queryRange(Wrapper wrapper, Integer start, Integer end); 45 | } 46 | -------------------------------------------------------------------------------- /booster/src/main/java/com/jimmy/hulk/booster/handler/ExceptionHandler.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.booster.handler; 2 | 3 | import com.jimmy.hulk.booster.core.Session; 4 | import com.jimmy.hulk.booster.support.SessionPool; 5 | import com.jimmy.hulk.common.constant.ErrorCode; 6 | import io.netty.channel.ChannelHandlerAdapter; 7 | import io.netty.channel.ChannelHandlerContext; 8 | import lombok.extern.slf4j.Slf4j; 9 | 10 | import java.io.IOException; 11 | 12 | @Slf4j 13 | public class ExceptionHandler extends ChannelHandlerAdapter { 14 | 15 | private Session session; 16 | 17 | private SessionPool sessionPool; 18 | 19 | public ExceptionHandler(Session session, SessionPool sessionPool) { 20 | this.session = session; 21 | this.sessionPool = sessionPool; 22 | } 23 | 24 | @Override 25 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { 26 | if (!(cause instanceof IOException)) { 27 | log.error("通信异常", cause); 28 | } 29 | 30 | sessionPool.remove(session.getId()); 31 | session.writeErrMessage(ErrorCode.ERR_EXCEPTION_CAUGHT, cause.getMessage()); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /protocol/src/main/java/com/jimmy/hulk/protocol/reponse/OkResponse.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.protocol.reponse; 2 | 3 | import com.jimmy.hulk.protocol.packages.OkPacket; 4 | import com.jimmy.hulk.protocol.core.Context; 5 | import io.netty.channel.ChannelHandlerContext; 6 | 7 | public class OkResponse { 8 | 9 | public static void response(Context c) { 10 | OkPacket okPacket = new OkPacket(); 11 | ChannelHandlerContext ctx = c.getChannelHandlerContext(); 12 | okPacket.write(ctx); 13 | } 14 | 15 | public static void responseWithAffectedRows(Context c, long affectedRows) { 16 | OkPacket okPacket = new OkPacket(); 17 | okPacket.affectedRows = affectedRows; 18 | ChannelHandlerContext ctx = c.getChannelHandlerContext(); 19 | okPacket.write(ctx); 20 | } 21 | 22 | public static void responseWithAffectedRows(Context c, long affectedRows, int insertId) { 23 | OkPacket okPacket = new OkPacket(); 24 | okPacket.affectedRows = affectedRows; 25 | okPacket.insertId = insertId; 26 | ChannelHandlerContext ctx = c.getChannelHandlerContext(); 27 | okPacket.write(ctx); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/core/Condition.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.core; 2 | 3 | import com.jimmy.hulk.common.enums.ConditionEnum; 4 | import com.jimmy.hulk.common.enums.ConditionTypeEnum; 5 | import lombok.Data; 6 | 7 | import java.io.Serializable; 8 | 9 | @Data 10 | public class Condition implements Serializable { 11 | 12 | private ConditionEnum conditionEnum; 13 | 14 | private String fieldName; 15 | 16 | private Object fieldValue; 17 | 18 | private Object start; 19 | 20 | private Object end; 21 | 22 | private ConditionTypeEnum conditionTypeEnum = ConditionTypeEnum.AND; 23 | 24 | public Condition() { 25 | 26 | } 27 | 28 | public Condition(ConditionEnum conditionEnum, String fieldName, Object fieldValue) { 29 | this.conditionEnum = conditionEnum; 30 | this.fieldName = fieldName; 31 | this.fieldValue = fieldValue; 32 | } 33 | 34 | public Condition(ConditionEnum conditionEnum, String fieldName, Object start, Object end) { 35 | this.conditionEnum = conditionEnum; 36 | this.fieldName = fieldName; 37 | this.start = start; 38 | this.end = end; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /parse/src/main/java/org/apache/calcite/sql/SqlCompare.java: -------------------------------------------------------------------------------- 1 | package org.apache.calcite.sql; 2 | 3 | import org.apache.calcite.sql.parser.SqlParserPos; 4 | import org.apache.calcite.sql.util.SqlVisitor; 5 | import org.apache.calcite.sql.validate.SqlValidator; 6 | import org.apache.calcite.sql.validate.SqlValidatorScope; 7 | import org.apache.calcite.util.Litmus; 8 | 9 | public class SqlCompare extends SqlNode { 10 | 11 | 12 | /** 13 | * Creates a node. 14 | * 15 | * @param pos Parser position, must not be null. 16 | */ 17 | SqlCompare(SqlParserPos pos) { 18 | super(pos); 19 | } 20 | 21 | @Override 22 | public SqlNode clone(SqlParserPos pos) { 23 | return null; 24 | } 25 | 26 | @Override 27 | public void unparse(SqlWriter writer, int leftPrec, int rightPrec) { 28 | 29 | } 30 | 31 | @Override 32 | public void validate(SqlValidator validator, SqlValidatorScope scope) { 33 | 34 | } 35 | 36 | @Override 37 | public R accept(SqlVisitor visitor) { 38 | return null; 39 | } 40 | 41 | @Override 42 | public boolean equalsDeep(SqlNode node, Litmus litmus) { 43 | return false; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /route/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | com.jimmy 7 | hulk 8 | 0.0.1-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | route 13 | jar 14 | 15 | 16 | com.jimmy 17 | config 18 | 0.0.1-SNAPSHOT 19 | 20 | 21 | com.jimmy 22 | common 23 | 0.0.1-SNAPSHOT 24 | 25 | 26 | org.projectlombok 27 | lombok 28 | provided 29 | 30 | 31 | -------------------------------------------------------------------------------- /authority/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | com.jimmy 7 | hulk 8 | 0.0.1-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | authority 13 | jar 14 | 15 | 16 | com.jimmy 17 | common 18 | 0.0.1-SNAPSHOT 19 | 20 | 21 | com.jimmy 22 | data 23 | 0.0.1-SNAPSHOT 24 | 25 | 26 | org.projectlombok 27 | lombok 28 | provided 29 | 30 | 31 | -------------------------------------------------------------------------------- /config/src/main/java/com/jimmy/hulk/config/properties/SchemaConfigProperty.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.config.properties; 2 | 3 | import com.google.common.collect.Lists; 4 | import com.jimmy.hulk.authority.core.AuthenticationSchema; 5 | import lombok.Data; 6 | 7 | import java.io.Serializable; 8 | import java.util.List; 9 | 10 | @Data 11 | public class SchemaConfigProperty implements Serializable { 12 | 13 | private String dsName; 14 | 15 | private Boolean isAllAllow = false; 16 | 17 | private List authenticationTableConfigProperties = Lists.newArrayList(); 18 | 19 | public AuthenticationSchema buildAuthenticationSchema() { 20 | AuthenticationSchema authenticationSchema = new AuthenticationSchema(); 21 | authenticationSchema.setDsName(this.dsName); 22 | authenticationSchema.setIsAllAllow(this.isAllAllow); 23 | 24 | for (AuthenticationTableConfigProperty authenticationTableConfigProperty : this.authenticationTableConfigProperties) { 25 | authenticationSchema.getAuthenticationTables().add(authenticationTableConfigProperty.buildAuthenticationTable()); 26 | } 27 | 28 | return authenticationSchema; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /config/src/main/java/com/jimmy/hulk/config/properties/DatasourceConfigProperty.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.config.properties; 2 | 3 | import com.jimmy.hulk.common.enums.DatasourceEnum; 4 | import com.jimmy.hulk.data.config.DataSourceProperty; 5 | import lombok.Data; 6 | 7 | import java.io.Serializable; 8 | 9 | @Data 10 | public class DatasourceConfigProperty implements Serializable { 11 | 12 | private DatasourceEnum ds; 13 | 14 | private String url; 15 | 16 | private String username; 17 | 18 | private String password; 19 | 20 | private String schema; 21 | 22 | private String clusterName; 23 | 24 | private String name; 25 | 26 | public DataSourceProperty getDataSourceProperty() { 27 | DataSourceProperty dataSourceProperty = new DataSourceProperty(); 28 | dataSourceProperty.setUrl(this.url); 29 | dataSourceProperty.setSchema(this.schema); 30 | dataSourceProperty.setClusterName(this.clusterName); 31 | dataSourceProperty.setDs(this.ds); 32 | dataSourceProperty.setPassword(this.password); 33 | dataSourceProperty.setUsername(this.username); 34 | dataSourceProperty.setName(this.name); 35 | return dataSourceProperty; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /protocol/src/main/java/com/jimmy/hulk/protocol/core/BindValue.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.protocol.core; 2 | 3 | public class BindValue { 4 | 5 | public boolean isNull; /* NULL indicator */ 6 | public boolean isLongData; /* long data indicator */ 7 | public boolean isSet; /* has this parameter been set */ 8 | 9 | public long length; /* Default length of data */ 10 | public int type; /* data type */ 11 | public byte scale; 12 | 13 | /** 14 | * 数据值 15 | **/ 16 | public byte byteBinding; 17 | public short shortBinding; 18 | public int intBinding; 19 | public float floatBinding; 20 | public long longBinding; 21 | public double doubleBinding; 22 | public Object value; /* Other value to store */ 23 | 24 | public void reset() { 25 | this.isNull = false; 26 | this.isLongData = false; 27 | this.isSet = false; 28 | 29 | this.length = 0; 30 | this.type = 0; 31 | this.scale = 0; 32 | 33 | this.byteBinding = 0; 34 | this.shortBinding = 0; 35 | this.intBinding = 0; 36 | this.floatBinding = 0; 37 | this.longBinding = 0L; 38 | this.doubleBinding = 0D; 39 | this.value = null; 40 | } 41 | 42 | } -------------------------------------------------------------------------------- /parse/src/main/codegen/includes/parserImpls.ftl: -------------------------------------------------------------------------------- 1 | <#-- 2 | // Licensed to the Apache Software Foundation (ASF) under one or more 3 | // contributor license agreements. See the NOTICE file distributed with 4 | // this work for additional information regarding copyright ownership. 5 | // The ASF licenses this file to you under the Apache License, Version 2.0 6 | // (the "License"); you may not use this file except in compliance with 7 | // the License. You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | --> 17 | 18 | <#-- 19 | Add implementations of additional parser statements, literals or 20 | data types. 21 | 22 | Example of SqlShowTables() implementation: 23 | SqlNode SqlShowTables() 24 | { 25 | ...local variables... 26 | } 27 | { 28 | 29 | ... 30 | { 31 | return SqlShowTables(...) 32 | } 33 | } 34 | --> 35 | -------------------------------------------------------------------------------- /parse/src/main/codegen/includes/compoundIdentifier.ftl: -------------------------------------------------------------------------------- 1 | <#-- 2 | // Licensed to the Apache Software Foundation (ASF) under one or more 3 | // contributor license agreements. See the NOTICE file distributed with 4 | // this work for additional information regarding copyright ownership. 5 | // The ASF licenses this file to you under the Apache License, Version 2.0 6 | // (the "License"); you may not use this file except in compliance with 7 | // the License. You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | --> 17 | 18 | <#-- 19 | Add implementations of additional parser statements, literals or 20 | data types. 21 | 22 | Example of SqlShowTables() implementation: 23 | SqlNode SqlShowTables() 24 | { 25 | ...local variables... 26 | } 27 | { 28 | 29 | ... 30 | { 31 | return SqlShowTables(...) 32 | } 33 | } 34 | --> 35 | -------------------------------------------------------------------------------- /protocol/src/main/java/com/jimmy/hulk/protocol/packages/BinaryPacket.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.protocol.packages; 2 | 3 | import com.jimmy.hulk.protocol.utils.BufferUtil; 4 | import io.netty.buffer.ByteBuf; 5 | import io.netty.channel.ChannelHandlerContext; 6 | 7 | /** 8 | * MySql包 外层结构 9 | */ 10 | public class BinaryPacket extends MySQLPacket { 11 | public static final byte OK = 1; 12 | public static final byte ERROR = 2; 13 | public static final byte HEADER = 3; 14 | public static final byte FIELD = 4; 15 | public static final byte FIELD_EOF = 5; 16 | public static final byte ROW = 6; 17 | public static final byte PACKET_EOF = 7; 18 | 19 | public byte[] data; 20 | 21 | @Override 22 | public int calcPacketSize() { 23 | return data == null ? 0 : data.length; 24 | } 25 | 26 | @Override 27 | public void write(ChannelHandlerContext ctx) { 28 | ByteBuf byteBuf = ctx.alloc().buffer(); 29 | BufferUtil.writeUB3(byteBuf, packetLength); 30 | byteBuf.writeByte(packetId); 31 | byteBuf.writeBytes(data); 32 | ctx.writeAndFlush(byteBuf); 33 | } 34 | 35 | @Override 36 | protected String getPacketInfo() { 37 | return "MySQL Binary Packet"; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /authority/src/main/java/com/jimmy/hulk/authority/datasource/DatasourcePoint.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.authority.datasource; 2 | 3 | import cn.hutool.core.collection.CollUtil; 4 | import com.google.common.collect.Lists; 5 | import com.jimmy.hulk.data.base.DataSource; 6 | import org.springframework.util.Assert; 7 | 8 | import java.util.List; 9 | 10 | public class DatasourcePoint { 11 | 12 | private String name; 13 | 14 | private Boolean isReadOnly; 15 | 16 | private DataSource write; 17 | 18 | private DatasourcePool readPool; 19 | 20 | public DatasourcePoint(String name, DataSource write, List read, boolean isReadOnly) { 21 | Assert.isTrue(write != null, "写数据源不允许为空"); 22 | 23 | this.name = name; 24 | this.write = write; 25 | this.isReadOnly = isReadOnly; 26 | 27 | if (CollUtil.isEmpty(read)) { 28 | read = Lists.newArrayList(write); 29 | } 30 | 31 | readPool = new DatasourcePool(read); 32 | } 33 | 34 | public DataSource getWrite() { 35 | return this.write; 36 | } 37 | 38 | public DataSource getRead() { 39 | return readPool.getDataSource(); 40 | } 41 | 42 | public Boolean getReadOnly() { 43 | return isReadOnly; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /parse/src/main/java/com/jimmy/hulk/parse/core/result/ParseResultNode.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.parse.core.result; 2 | 3 | import com.google.common.collect.Lists; 4 | import com.jimmy.hulk.parse.core.element.*; 5 | import com.jimmy.hulk.parse.enums.ResultTypeEnum; 6 | import lombok.Data; 7 | 8 | import java.io.Serializable; 9 | import java.util.List; 10 | 11 | @Data 12 | public class ParseResultNode implements Serializable { 13 | 14 | private String sql; 15 | 16 | private Integer fetch; 17 | 18 | private Integer offset; 19 | 20 | private ResultTypeEnum resultType; 21 | 22 | private ExtraNode extraNode; 23 | 24 | private List columns = Lists.newArrayList(); 25 | 26 | private List tableNodes = Lists.newArrayList(); 27 | 28 | private List orderNodes = Lists.newArrayList(); 29 | 30 | private List relationNodes = Lists.newArrayList(); 31 | 32 | private List whereConditionNodes = Lists.newArrayList(); 33 | 34 | private List prepareParamNodes = Lists.newArrayList(); 35 | 36 | private List groupBy = Lists.newArrayList(); 37 | 38 | public ParseResultNode() { 39 | this.setResultType(ResultTypeEnum.SELECT); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /actuator/src/main/java/com/jimmy/hulk/actuator/memory/HeapMemorySegment.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.actuator.memory; 2 | 3 | import org.springframework.util.Assert; 4 | 5 | import java.nio.ByteBuffer; 6 | 7 | public class HeapMemorySegment extends BaseSegment { 8 | 9 | private final ByteBuffer byteBuffer; 10 | 11 | HeapMemorySegment(int capacity) { 12 | this.byteBuffer = ByteBuffer.allocate(capacity); 13 | } 14 | 15 | @Override 16 | public boolean write(byte[] bytes) { 17 | if (!free.compareAndSet(true, false)) { 18 | return false; 19 | } 20 | 21 | this.byteBuffer.put(bytes); 22 | return true; 23 | } 24 | 25 | @Override 26 | public byte[] read() { 27 | Assert.isTrue(!free.get(), "该内存块空闲"); 28 | 29 | this.byteBuffer.flip(); 30 | int len = this.byteBuffer.limit() - this.byteBuffer.position(); 31 | 32 | byte[] bytes = new byte[len]; 33 | 34 | for (int i = 0; i < bytes.length; i++) { 35 | bytes[i] = this.byteBuffer.get(); 36 | } 37 | 38 | return bytes; 39 | } 40 | 41 | @Override 42 | public void free() { 43 | Assert.isTrue(free.compareAndSet(false, true), "该内存块空闲"); 44 | byteBuffer.clear(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /actuator/src/main/java/com/jimmy/hulk/actuator/sql/Native.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.actuator.sql; 2 | 3 | import cn.hutool.core.util.StrUtil; 4 | import com.jimmy.hulk.actuator.support.ExecuteHolder; 5 | import com.jimmy.hulk.data.actuator.Actuator; 6 | import com.jimmy.hulk.parse.core.result.ExtraNode; 7 | import com.jimmy.hulk.parse.core.result.ParseResultNode; 8 | 9 | import java.util.List; 10 | import java.util.Map; 11 | 12 | public class Native extends SQL>> { 13 | 14 | @Override 15 | public List> process(ParseResultNode parseResultNode) throws Exception { 16 | ExtraNode extraNode = parseResultNode.getExtraNode(); 17 | String sql = parseResultNode.getSql(); 18 | //是否查询 19 | Boolean isExecute = extraNode.getIsExecute(); 20 | //数据源判断 21 | String dsName = extraNode.getDsName(); 22 | if (StrUtil.isEmpty(dsName)) { 23 | dsName = ExecuteHolder.getDatasourceName(); 24 | } 25 | //获取执行器 26 | Actuator actuator = partSupport.getActuator(ExecuteHolder.getUsername(), dsName, false); 27 | 28 | if (isExecute) { 29 | actuator.execute(sql); 30 | return null; 31 | } 32 | 33 | return actuator.queryForList(sql); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /booster/src/main/java/com/jimmy/hulk/booster/action/CacheAction.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.booster.action; 2 | 3 | import cn.hutool.core.collection.CollUtil; 4 | import com.google.common.collect.Lists; 5 | import com.jimmy.hulk.actuator.sql.Cache; 6 | import com.jimmy.hulk.booster.core.Session; 7 | import com.jimmy.hulk.parse.core.result.ParseResultNode; 8 | import com.jimmy.hulk.protocol.utils.parse.QueryParse; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.stereotype.Component; 11 | 12 | import java.util.List; 13 | import java.util.Map; 14 | 15 | @Component 16 | public class CacheAction extends BaseAction { 17 | 18 | @Autowired 19 | private Cache cache; 20 | 21 | @Override 22 | public void action(String sql, Session session, int offset) throws Exception { 23 | //正常SQL执行 24 | ParseResultNode parse = sqlParser.parse(sql); 25 | List> process = cache.execute(parse); 26 | if (CollUtil.isNotEmpty(process)) { 27 | this.response(session, process); 28 | return; 29 | } 30 | //默认返回空字段 31 | this.responseEmptyResult(session, Lists.newArrayList("result")); 32 | } 33 | 34 | @Override 35 | public int type() { 36 | return QueryParse.CACHE; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /config/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | com.jimmy 7 | hulk 8 | 0.0.1-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | config 13 | jar 14 | 15 | 16 | dom4j 17 | dom4j 18 | 19 | 20 | com.jimmy 21 | authority 22 | 0.0.1-SNAPSHOT 23 | 24 | 25 | com.jimmy 26 | common 27 | 0.0.1-SNAPSHOT 28 | 29 | 30 | org.projectlombok 31 | lombok 32 | provided 33 | 34 | 35 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/other/In.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.other; 2 | 3 | import com.googlecode.aviator.runtime.function.AbstractFunction; 4 | import com.googlecode.aviator.runtime.function.FunctionUtils; 5 | import com.googlecode.aviator.runtime.type.AviatorBoolean; 6 | import com.googlecode.aviator.runtime.type.AviatorObject; 7 | import com.jimmy.hulk.common.enums.ModuleEnum; 8 | import com.jimmy.hulk.common.exception.HulkException; 9 | 10 | import java.util.Collection; 11 | import java.util.Map; 12 | 13 | public class In extends AbstractFunction { 14 | 15 | @Override 16 | public AviatorObject call(final Map env, final AviatorObject str, final AviatorObject list) { 17 | Object javaObject = FunctionUtils.getJavaObject(str, env); 18 | Object value = FunctionUtils.getJavaObject(list, env); 19 | 20 | if (javaObject == null) { 21 | throw new HulkException("字段值为空", ModuleEnum.DATA); 22 | } 23 | 24 | if (!(value instanceof Collection)) { 25 | throw new HulkException("非集合数据", ModuleEnum.DATA); 26 | } 27 | 28 | Collection collection = (Collection) value; 29 | return AviatorBoolean.valueOf(collection.contains(javaObject)); 30 | } 31 | 32 | @Override 33 | public String getName() { 34 | return "in"; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/other/NotIn.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.other; 2 | 3 | import com.googlecode.aviator.runtime.function.AbstractFunction; 4 | import com.googlecode.aviator.runtime.function.FunctionUtils; 5 | import com.googlecode.aviator.runtime.type.AviatorBoolean; 6 | import com.googlecode.aviator.runtime.type.AviatorObject; 7 | import com.jimmy.hulk.common.enums.ModuleEnum; 8 | import com.jimmy.hulk.common.exception.HulkException; 9 | 10 | import java.util.Collection; 11 | import java.util.Map; 12 | 13 | public class NotIn extends AbstractFunction { 14 | 15 | @Override 16 | public AviatorObject call(final Map env, final AviatorObject str, final AviatorObject list) { 17 | Object javaObject = FunctionUtils.getJavaObject(str, env); 18 | Object value = FunctionUtils.getJavaObject(list, env); 19 | 20 | if (javaObject == null) { 21 | throw new HulkException("字段值为空", ModuleEnum.DATA); 22 | } 23 | 24 | if (!(value instanceof Collection)) { 25 | throw new HulkException("非集合数据",ModuleEnum.DATA); 26 | } 27 | 28 | Collection collection = (Collection) value; 29 | return AviatorBoolean.valueOf(!collection.contains(javaObject)); 30 | } 31 | 32 | @Override 33 | public String getName() { 34 | return "notIn"; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /actuator/src/main/java/com/jimmy/hulk/actuator/memory/DirectMemorySegment.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.actuator.memory; 2 | 3 | import org.springframework.util.Assert; 4 | import sun.nio.ch.DirectBuffer; 5 | 6 | import java.nio.ByteBuffer; 7 | 8 | public class DirectMemorySegment extends BaseSegment { 9 | 10 | private final ByteBuffer byteBuffer; 11 | 12 | DirectMemorySegment(int capacity) { 13 | this.byteBuffer = ByteBuffer.allocateDirect(capacity); 14 | } 15 | 16 | @Override 17 | public boolean write(byte[] bytes) { 18 | if (!free.compareAndSet(true, false)) { 19 | return false; 20 | } 21 | 22 | this.byteBuffer.put(bytes); 23 | return true; 24 | } 25 | 26 | @Override 27 | public byte[] read() { 28 | Assert.isTrue(!free.get(), "该内存块空闲"); 29 | 30 | this.byteBuffer.flip(); 31 | int len = this.byteBuffer.limit() - this.byteBuffer.position(); 32 | 33 | byte[] bytes = new byte[len]; 34 | 35 | for (int i = 0; i < bytes.length; i++) { 36 | bytes[i] = this.byteBuffer.get(); 37 | } 38 | 39 | return bytes; 40 | } 41 | 42 | @Override 43 | public void free() { 44 | Assert.isTrue(free.compareAndSet(false, true), "该内存块空闲"); 45 | byteBuffer.clear(); 46 | ((DirectBuffer) byteBuffer).cleaner().clean(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /booster/src/main/java/com/jimmy/hulk/booster/action/InsertAction.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.booster.action; 2 | 3 | import com.jimmy.hulk.actuator.core.InsertResult; 4 | import com.jimmy.hulk.actuator.sql.Insert; 5 | import com.jimmy.hulk.booster.core.Session; 6 | import com.jimmy.hulk.parse.core.result.ParseResultNode; 7 | import com.jimmy.hulk.protocol.utils.parse.QueryParse; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.stereotype.Component; 10 | 11 | @Component 12 | public class InsertAction extends BaseAction { 13 | 14 | @Autowired 15 | private Insert insert; 16 | 17 | @Override 18 | public void action(String sql, Session session, int offset) throws Exception { 19 | //手动提交 20 | if (!session.isAutocommit()) { 21 | session.addSQL(sql); 22 | this.success(session, 1); 23 | return; 24 | } 25 | //正常SQL执行 26 | ParseResultNode parse = sqlParser.parse(sql); 27 | 28 | InsertResult process = insert.execute(parse); 29 | Long priValue = process.getPriValue(); 30 | if (priValue == null) { 31 | this.success(session, process.getRow()); 32 | } else { 33 | this.success(session, process.getRow(), priValue.intValue()); 34 | } 35 | } 36 | 37 | @Override 38 | public int type() { 39 | return QueryParse.INSERT; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /common/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | com.jimmy 7 | hulk 8 | 0.0.1-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | common 13 | jar 14 | 15 | 16 | com.alibaba 17 | fastjson 18 | 19 | 20 | com.google.guava 21 | guava 22 | 23 | 24 | cn.hutool 25 | hutool-all 26 | 27 | 28 | org.springframework.boot 29 | spring-boot-starter 30 | 31 | 32 | org.projectlombok 33 | lombok 34 | provided 35 | 36 | 37 | -------------------------------------------------------------------------------- /parse/src/main/java/org/apache/calcite/sql/SqlCacheQuery.java: -------------------------------------------------------------------------------- 1 | package org.apache.calcite.sql; 2 | 3 | import lombok.Getter; 4 | import org.apache.calcite.sql.parser.SqlParserPos; 5 | import org.apache.calcite.sql.util.SqlVisitor; 6 | import org.apache.calcite.sql.validate.SqlValidator; 7 | import org.apache.calcite.sql.validate.SqlValidatorScope; 8 | import org.apache.calcite.util.Litmus; 9 | 10 | public class SqlCacheQuery extends SqlNode { 11 | 12 | @Getter 13 | private SqlNode sql; 14 | 15 | @Getter 16 | private SqlNode dsName; 17 | 18 | @Getter 19 | private SqlNode expireTime; 20 | 21 | public SqlCacheQuery(SqlParserPos pos, SqlNode expireTime, SqlNode dsName, SqlNode sql) { 22 | super(pos); 23 | this.expireTime = expireTime; 24 | this.sql = sql; 25 | this.dsName = dsName; 26 | } 27 | 28 | @Override 29 | public SqlNode clone(SqlParserPos pos) { 30 | return null; 31 | } 32 | 33 | @Override 34 | public void unparse(SqlWriter writer, int leftPrec, int rightPrec) { 35 | 36 | } 37 | 38 | @Override 39 | public void validate(SqlValidator validator, SqlValidatorScope scope) { 40 | 41 | } 42 | 43 | @Override 44 | public R accept(SqlVisitor visitor) { 45 | return null; 46 | } 47 | 48 | @Override 49 | public boolean equalsDeep(SqlNode node, Litmus litmus) { 50 | return false; 51 | } 52 | } 53 | 54 | -------------------------------------------------------------------------------- /booster/src/main/java/com/jimmy/hulk/booster/action/NativeAction.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.booster.action; 2 | 3 | import cn.hutool.core.collection.CollUtil; 4 | import com.google.common.collect.Lists; 5 | import com.jimmy.hulk.actuator.sql.Native; 6 | import com.jimmy.hulk.booster.core.Session; 7 | import com.jimmy.hulk.parse.core.result.ParseResultNode; 8 | import com.jimmy.hulk.protocol.utils.parse.QueryParse; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.stereotype.Component; 11 | 12 | import java.util.List; 13 | import java.util.Map; 14 | 15 | @Component 16 | public class NativeAction extends BaseAction { 17 | 18 | @Autowired 19 | private Native aNative; 20 | 21 | @Override 22 | public void action(String sql, Session session, int offset) throws Exception { 23 | //正常SQL执行 24 | ParseResultNode parse = sqlParser.parse(sql); 25 | Boolean isExecute = parse.getExtraNode().getIsExecute(); 26 | 27 | List> process = aNative.execute(parse); 28 | //直接执行的SQL 29 | if (isExecute) { 30 | this.success(session, 1); 31 | } 32 | 33 | if (CollUtil.isNotEmpty(process)) { 34 | this.response(session, process); 35 | return; 36 | } 37 | //默认返回空字段 38 | this.responseEmptyResult(session, Lists.newArrayList("result")); 39 | } 40 | 41 | @Override 42 | public int type() { 43 | return QueryParse.NATIVE; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/other/MapComparator.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.other; 2 | 3 | import cn.hutool.core.date.DateUtil; 4 | import cn.hutool.core.util.NumberUtil; 5 | import cn.hutool.core.util.StrUtil; 6 | 7 | import java.math.BigDecimal; 8 | import java.util.Comparator; 9 | import java.util.Date; 10 | import java.util.Map; 11 | 12 | public class MapComparator implements Comparator { 13 | 14 | private String fieldName; 15 | 16 | public MapComparator(String fieldName) { 17 | this.fieldName = fieldName; 18 | } 19 | 20 | @Override 21 | public int compare(Map m1, Map m2) { 22 | Object o1 = m1.get(fieldName); 23 | Object o2 = m2.get(fieldName); 24 | 25 | if (o1 == null) { 26 | return -1; 27 | } 28 | 29 | if (o1 != null && o2 == null) { 30 | return 1; 31 | } 32 | 33 | if (o1 instanceof BigDecimal && o2 instanceof BigDecimal) { 34 | return ((BigDecimal) o1).compareTo((BigDecimal) o2); 35 | } 36 | 37 | if (o1 instanceof Number && o2 instanceof Number) { 38 | BigDecimal b1 = NumberUtil.toBigDecimal((Number) o1); 39 | BigDecimal b2 = NumberUtil.toBigDecimal((Number) o2); 40 | return b1.compareTo(b2); 41 | } 42 | 43 | if (o1 instanceof Date && o2 instanceof Date) { 44 | return DateUtil.compare((Date) o1, (Date) o2); 45 | } 46 | 47 | return StrUtil.compare(o1.toString(), o2.toString(), true); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/field/MySQLFieldMapper.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.field; 2 | 3 | import com.jimmy.hulk.data.annotation.DS; 4 | import com.jimmy.hulk.data.base.FieldMapper; 5 | import com.jimmy.hulk.common.enums.DatasourceEnum; 6 | import com.jimmy.hulk.common.enums.FieldTypeEnum; 7 | import lombok.AllArgsConstructor; 8 | import lombok.Getter; 9 | 10 | import static com.jimmy.hulk.common.enums.DatasourceEnum.MYSQL; 11 | 12 | @Getter 13 | @AllArgsConstructor 14 | @DS(type = MYSQL) 15 | public enum MySQLFieldMapper implements FieldMapper { 16 | VARCHAR(FieldTypeEnum.VARCHAR, "varchar", null, true), 17 | INT(FieldTypeEnum.INT, "int", null, true), 18 | BIGINT(FieldTypeEnum.BIGINT, "bigint", null, true), 19 | FLOAT(FieldTypeEnum.FLOAT, "float", null, true), 20 | DOUBLE(FieldTypeEnum.DOUBLE, "double", null, true), 21 | DECIMAL(FieldTypeEnum.DECIMAL, "decimal", null, true), 22 | TINYINT(FieldTypeEnum.BOOLEAN, "tinyint", null, true), 23 | DATE(FieldTypeEnum.DATE, "datetime", new String[]{"date"}, false), 24 | TEXT(FieldTypeEnum.TEXT, "text", null, false), 25 | LONGTEXT(FieldTypeEnum.LONGTEXT, "longText", null, false), 26 | CHAR(FieldTypeEnum.CHAR, "char", null, true), 27 | TIMESTAMP(FieldTypeEnum.TIMESTAMP, "timestamp", null, false); 28 | 29 | private FieldTypeEnum fieldType; 30 | 31 | private String mapperType; 32 | 33 | private String[] allMapperTypes; 34 | 35 | private boolean isNeedLength; 36 | 37 | @Override 38 | public DatasourceEnum type() { 39 | return MYSQL; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/field/ElasticsearchMapper.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.field; 2 | 3 | import com.jimmy.hulk.data.annotation.DS; 4 | import com.jimmy.hulk.data.base.FieldMapper; 5 | import com.jimmy.hulk.common.enums.DatasourceEnum; 6 | import com.jimmy.hulk.common.enums.FieldTypeEnum; 7 | import lombok.AllArgsConstructor; 8 | import lombok.Getter; 9 | 10 | import static com.jimmy.hulk.common.enums.DatasourceEnum.ELASTICSEARCH; 11 | 12 | @Getter 13 | @AllArgsConstructor 14 | @DS(type = ELASTICSEARCH) 15 | public enum ElasticsearchMapper implements FieldMapper { 16 | VARCHAR(FieldTypeEnum.VARCHAR, "text", null, false), 17 | INT(FieldTypeEnum.INT, "integer", null, false), 18 | BIGINT(FieldTypeEnum.BIGINT, "long", null, false), 19 | FLOAT(FieldTypeEnum.FLOAT, "float", null, false), 20 | DOUBLE(FieldTypeEnum.DOUBLE, "double", null, false), 21 | DECIMAL(FieldTypeEnum.DECIMAL, "double", null, false), 22 | BOOLEAN(FieldTypeEnum.BOOLEAN, "boolean", null, false), 23 | DATE(FieldTypeEnum.DATE, "date", null, false), 24 | TEXT(FieldTypeEnum.TEXT, "text", null, false), 25 | LONGTEXT(FieldTypeEnum.LONGTEXT, "text", null, false), 26 | CHAR(FieldTypeEnum.CHAR, "keyword", null, false), 27 | TIMESTAMP(FieldTypeEnum.TIMESTAMP, "date", null, false); 28 | 29 | private FieldTypeEnum fieldType; 30 | 31 | private String mapperType; 32 | 33 | private String[] allMapperTypes; 34 | 35 | private boolean isNeedLength; 36 | 37 | @Override 38 | public DatasourceEnum type() { 39 | return ELASTICSEARCH; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /common/src/main/java/com/jimmy/hulk/common/exception/HulkException.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.common.exception; 2 | 3 | import com.jimmy.hulk.common.enums.ModuleEnum; 4 | import com.jimmy.hulk.common.constant.ErrorCode; 5 | 6 | public class HulkException extends RuntimeException { 7 | 8 | private int code = ErrorCode.ER_UNKNOWN_COM_ERROR; 9 | 10 | private String message; 11 | 12 | private ModuleEnum module; 13 | 14 | public HulkException(String message) { 15 | super(message); 16 | this.message = message; 17 | } 18 | 19 | public HulkException(String message, ModuleEnum module) { 20 | super(message); 21 | this.message = message; 22 | this.module = module; 23 | } 24 | 25 | public HulkException(int code, String message, ModuleEnum module) { 26 | super(message); 27 | this.code = code; 28 | this.message = message; 29 | this.module = module; 30 | } 31 | 32 | public HulkException(int code, String desc, Exception e, ModuleEnum module) { 33 | super(e); 34 | this.code = code; 35 | this.message = desc; 36 | this.module = module; 37 | } 38 | 39 | public HulkException() { 40 | super(); 41 | } 42 | 43 | public HulkException(Throwable cause) { 44 | super(cause); 45 | } 46 | 47 | public int getCode() { 48 | return code; 49 | } 50 | 51 | @Override 52 | public String getMessage() { 53 | return message; 54 | } 55 | 56 | public ModuleEnum getModule() { 57 | return module; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/field/SqlServerFieldMapper.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.field; 2 | 3 | import com.jimmy.hulk.common.enums.DatasourceEnum; 4 | import com.jimmy.hulk.common.enums.FieldTypeEnum; 5 | import com.jimmy.hulk.data.annotation.DS; 6 | import com.jimmy.hulk.data.base.FieldMapper; 7 | import lombok.AllArgsConstructor; 8 | import lombok.Getter; 9 | 10 | import static com.jimmy.hulk.common.enums.DatasourceEnum.SQL_SERVER; 11 | 12 | @Getter 13 | @AllArgsConstructor 14 | @DS(type = SQL_SERVER) 15 | public enum SqlServerFieldMapper implements FieldMapper { 16 | VARCHAR(FieldTypeEnum.VARCHAR, "nvarchar", null, true), 17 | INT(FieldTypeEnum.INT, "int", null, false), 18 | BIGINT(FieldTypeEnum.BIGINT, "bigint", null, false), 19 | FLOAT(FieldTypeEnum.FLOAT, "rel", null, false), 20 | DOUBLE(FieldTypeEnum.DOUBLE, "rel", null, false), 21 | DECIMAL(FieldTypeEnum.DECIMAL, "decimal", null, true), 22 | TINYINT(FieldTypeEnum.BOOLEAN, "tinyint", null, false), 23 | DATE(FieldTypeEnum.DATE, "datetime", new String[]{"date"}, false), 24 | TEXT(FieldTypeEnum.TEXT, "text", null, false), 25 | LONGTEXT(FieldTypeEnum.LONGTEXT, "longText", null, false), 26 | CHAR(FieldTypeEnum.CHAR, "char", null, true), 27 | TIMESTAMP(FieldTypeEnum.TIMESTAMP, "datetime", null, false); 28 | 29 | private FieldTypeEnum fieldType; 30 | 31 | private String mapperType; 32 | 33 | private String[] allMapperTypes; 34 | 35 | private boolean isNeedLength; 36 | 37 | @Override 38 | public DatasourceEnum type() { 39 | return SQL_SERVER; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/field/OracleMapper.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.field; 2 | 3 | import com.jimmy.hulk.common.enums.DatasourceEnum; 4 | import com.jimmy.hulk.common.enums.FieldTypeEnum; 5 | import com.jimmy.hulk.data.annotation.DS; 6 | import com.jimmy.hulk.data.base.FieldMapper; 7 | import lombok.AllArgsConstructor; 8 | import lombok.Getter; 9 | 10 | import static com.jimmy.hulk.common.enums.DatasourceEnum.ORACLE; 11 | 12 | @Getter 13 | @AllArgsConstructor 14 | @DS(type = ORACLE) 15 | public enum OracleMapper implements FieldMapper { 16 | 17 | VARCHAR(FieldTypeEnum.VARCHAR, "VARCHAR2", null, true), 18 | INT(FieldTypeEnum.INT, "NUMBER", new String[]{"SMALLINT", "INTEGER"}, true), 19 | BIGINT(FieldTypeEnum.BIGINT, "BIGINT", null, true), 20 | FLOAT(FieldTypeEnum.FLOAT, "FLOAT", null, true), 21 | DOUBLE(FieldTypeEnum.DOUBLE, "DOUBLE PRECISION", null, true), 22 | DECIMAL(FieldTypeEnum.DECIMAL, "NUMBER", new String[]{"DECIMAL", "NUMERIC"}, true), 23 | BOOLEAN(FieldTypeEnum.BOOLEAN, "SMALLINT", null, true), 24 | DATE(FieldTypeEnum.DATE, "DATE", null, false), 25 | TEXT(FieldTypeEnum.TEXT, "CLOB", null, false), 26 | LONGTEXT(FieldTypeEnum.LONGTEXT, "CLOB", null, false), 27 | CHAR(FieldTypeEnum.CHAR, "CHAR", null, true), 28 | TIMESTAMP(FieldTypeEnum.TIMESTAMP, "DATE", null, false); 29 | 30 | private FieldTypeEnum fieldType; 31 | 32 | private String mapperType; 33 | 34 | private String[] allMapperTypes; 35 | 36 | private boolean isNeedLength; 37 | 38 | @Override 39 | public DatasourceEnum type() { 40 | return ORACLE; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /booster/src/main/java/com/jimmy/hulk/booster/action/UseAction.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.booster.action; 2 | 3 | import com.jimmy.hulk.authority.base.AuthenticationManager; 4 | import com.jimmy.hulk.booster.core.Session; 5 | import com.jimmy.hulk.common.constant.ErrorCode; 6 | import com.jimmy.hulk.protocol.utils.parse.QueryParse; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Component; 9 | 10 | @Component 11 | public class UseAction extends BaseAction { 12 | 13 | @Autowired 14 | private AuthenticationManager authenticationManager; 15 | 16 | @Override 17 | public void action(String sql, Session session, int offset) throws Exception { 18 | String schema = sql.substring(offset).trim(); 19 | int length = schema.length(); 20 | if (length > 0) { 21 | if (schema.charAt(0) == '`' && schema.charAt(length - 1) == '`') { 22 | schema = schema.substring(1, length - 2); 23 | } 24 | } 25 | // 表示当前连接已经指定了schema 26 | if (session.getSchema() != null && session.getSchema().equals(schema)) { 27 | session.writeOk(); 28 | return; 29 | } 30 | //权限判断 31 | if (!authenticationManager.checkConfigSchemaByUsername(session.getUser(), schema)) { 32 | session.writeErrMessage(ErrorCode.ER_BAD_DB_ERROR, "Unknown database"); 33 | return; 34 | } 35 | 36 | session.setSchema(schema); 37 | session.writeOk(); 38 | } 39 | 40 | @Override 41 | public int type() { 42 | return QueryParse.USE; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /protocol/src/main/java/com/jimmy/hulk/protocol/packages/ResultSetHeaderPacket.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.protocol.packages; 2 | 3 | import com.jimmy.hulk.protocol.utils.BufferUtil; 4 | import com.jimmy.hulk.protocol.core.MySQLMessage; 5 | import io.netty.buffer.ByteBuf; 6 | import io.netty.channel.ChannelHandlerContext; 7 | 8 | /** 9 | * 结果集头部Packet 10 | * 11 | */ 12 | public class ResultSetHeaderPacket extends MySQLPacket { 13 | 14 | public int fieldCount; 15 | public long extra; 16 | 17 | public void read(byte[] data) { 18 | MySQLMessage mm = new MySQLMessage(data); 19 | this.packetLength = mm.readUB3(); 20 | this.packetId = mm.read(); 21 | this.fieldCount = (int) mm.readLength(); 22 | if (mm.hasRemaining()) { 23 | this.extra = mm.readLength(); 24 | } 25 | } 26 | 27 | @Override 28 | public ByteBuf writeBuf(ByteBuf buffer, ChannelHandlerContext ctx) { 29 | int size = calcPacketSize(); 30 | BufferUtil.writeUB3(buffer, size); 31 | buffer.writeByte(packetId); 32 | BufferUtil.writeLength(buffer, fieldCount); 33 | if (extra > 0) { 34 | BufferUtil.writeLength(buffer, extra); 35 | } 36 | return buffer; 37 | } 38 | 39 | @Override 40 | public int calcPacketSize() { 41 | int size = BufferUtil.getLength(fieldCount); 42 | if (extra > 0) { 43 | size += BufferUtil.getLength(extra); 44 | } 45 | return size; 46 | } 47 | 48 | @Override 49 | protected String getPacketInfo() { 50 | return "MySQL ResultSetHeader Packet"; 51 | } 52 | } -------------------------------------------------------------------------------- /booster/src/main/java/com/jimmy/hulk/booster/support/SessionPool.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.booster.support; 2 | 3 | import com.google.common.collect.Maps; 4 | import com.jimmy.hulk.authority.base.AuthenticationManager; 5 | import com.jimmy.hulk.booster.core.Session; 6 | import com.jimmy.hulk.booster.core.Prepared; 7 | import com.jimmy.hulk.config.support.SystemVariableContext; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.stereotype.Component; 10 | 11 | import java.util.Map; 12 | import java.util.concurrent.atomic.AtomicLong; 13 | 14 | @Component 15 | public class SessionPool { 16 | 17 | private static final AtomicLong ACCEPT_SEQ = new AtomicLong(0L); 18 | 19 | private Map sessionMap = Maps.newHashMap(); 20 | 21 | @Autowired 22 | private Prepared prepared; 23 | 24 | @Autowired 25 | private SQLExecutor executor; 26 | 27 | @Autowired 28 | private SystemVariableContext systemVariableContext; 29 | 30 | @Autowired 31 | private AuthenticationManager authenticationManager; 32 | 33 | public void remove(Long id) { 34 | sessionMap.remove(id); 35 | } 36 | 37 | public Session get(Long id) { 38 | return sessionMap.get(id); 39 | } 40 | 41 | public void put(Session session) { 42 | sessionMap.put(session.getId(), session); 43 | } 44 | 45 | public Session getSession() { 46 | Session session = new Session(systemVariableContext.getTransactionTimeout(), ACCEPT_SEQ.getAndIncrement(), prepared, authenticationManager); 47 | session.setExecutor(executor); 48 | return session; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /parse/src/main/java/org/apache/calcite/sql/SqlNative.java: -------------------------------------------------------------------------------- 1 | package org.apache.calcite.sql; 2 | 3 | import cn.hutool.core.util.StrUtil; 4 | import lombok.Getter; 5 | import org.apache.calcite.sql.parser.SqlParserPos; 6 | import org.apache.calcite.sql.util.SqlVisitor; 7 | import org.apache.calcite.sql.validate.SqlValidator; 8 | import org.apache.calcite.sql.validate.SqlValidatorScope; 9 | import org.apache.calcite.util.Litmus; 10 | 11 | public class SqlNative extends SqlNode { 12 | 13 | @Getter 14 | private SqlNode dsName; 15 | 16 | @Getter 17 | private SqlNode sql; 18 | 19 | @Getter 20 | private Boolean isExecute; 21 | 22 | public SqlNative(SqlParserPos pos, SqlNode dsName, SqlNode sql, boolean isExecute) { 23 | super(pos); 24 | this.dsName = dsName; 25 | this.sql = sql; 26 | this.isExecute = isExecute; 27 | } 28 | 29 | @Override 30 | public SqlNode clone(SqlParserPos pos) { 31 | return null; 32 | } 33 | 34 | @Override 35 | public void unparse(SqlWriter writer, int leftPrec, int rightPrec) { 36 | writer.keyword("native"); 37 | writer.print(StrUtil.CRLF); 38 | writer.keyword("dsName:" + dsName); 39 | writer.print(StrUtil.CRLF); 40 | writer.keyword("sql:" + sql); 41 | } 42 | 43 | @Override 44 | public void validate(SqlValidator validator, SqlValidatorScope scope) { 45 | 46 | } 47 | 48 | @Override 49 | public R accept(SqlVisitor visitor) { 50 | return null; 51 | } 52 | 53 | @Override 54 | public boolean equalsDeep(SqlNode node, Litmus litmus) { 55 | return false; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/field/ClickHouseMapper.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.field; 2 | 3 | import com.jimmy.hulk.common.enums.DatasourceEnum; 4 | import com.jimmy.hulk.common.enums.FieldTypeEnum; 5 | import com.jimmy.hulk.data.annotation.DS; 6 | import com.jimmy.hulk.data.base.FieldMapper; 7 | import lombok.AllArgsConstructor; 8 | import lombok.Getter; 9 | 10 | import static com.jimmy.hulk.common.enums.DatasourceEnum.CLICK_HOUSE; 11 | 12 | @Getter 13 | @AllArgsConstructor 14 | @DS(type = CLICK_HOUSE) 15 | public enum ClickHouseMapper implements FieldMapper { 16 | 17 | VARCHAR(FieldTypeEnum.VARCHAR, "String", null, true), 18 | INT(FieldTypeEnum.INT, "Int16", new String[]{"Int32"}, true), 19 | BIGINT(FieldTypeEnum.BIGINT, "Int64", null, true), 20 | FLOAT(FieldTypeEnum.FLOAT, "Float32", null, true), 21 | DOUBLE(FieldTypeEnum.DOUBLE, "Flout64", null, true), 22 | DECIMAL(FieldTypeEnum.DECIMAL, "Decimal64", new String[]{"Decimal32", "Decimal128"}, true), 23 | BOOLEAN(FieldTypeEnum.BOOLEAN, "Int8", null, true), 24 | DATE(FieldTypeEnum.DATE, "DateTime", new String[]{"Datetime64", "Date"}, false), 25 | TEXT(FieldTypeEnum.TEXT, "String", null, true), 26 | LONGTEXT(FieldTypeEnum.LONGTEXT, "String", null, true), 27 | CHAR(FieldTypeEnum.CHAR, "FixedString", null, true), 28 | TIMESTAMP(FieldTypeEnum.TIMESTAMP, "DateTime", null, false); 29 | 30 | private FieldTypeEnum fieldType; 31 | 32 | private String mapperType; 33 | 34 | private String[] allMapperTypes; 35 | 36 | private boolean isNeedLength; 37 | 38 | @Override 39 | public DatasourceEnum type() { 40 | return CLICK_HOUSE; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /booster/src/main/bin/stop.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cygwin=false; 4 | linux=false; 5 | case "`uname`" in 6 | CYGWIN*) 7 | cygwin=true 8 | ;; 9 | Linux*) 10 | linux=true 11 | ;; 12 | esac 13 | 14 | get_pid() { 15 | STR=$1 16 | PID=$2 17 | if $cygwin; then 18 | JAVA_CMD="$JAVA_HOME\bin\java" 19 | JAVA_CMD=`cygpath --path --unix $JAVA_CMD` 20 | JAVA_PID=`ps |grep $JAVA_CMD |awk '{print $1}'` 21 | else 22 | if $linux; then 23 | if [ ! -z "$PID" ]; then 24 | JAVA_PID=`ps -C java -f --width 1000|grep "$STR"|grep "$PID"|grep -v grep|awk '{print $2}'` 25 | else 26 | JAVA_PID=`ps -C java -f --width 1000|grep "$STR"|grep -v grep|awk '{print $2}'` 27 | fi 28 | else 29 | if [ ! -z "$PID" ]; then 30 | JAVA_PID=`ps aux |grep "$STR"|grep "$PID"|grep -v grep|awk '{print $2}'` 31 | else 32 | JAVA_PID=`ps aux |grep "$STR"|grep -v grep|awk '{print $2}'` 33 | fi 34 | fi 35 | fi 36 | echo $JAVA_PID; 37 | } 38 | 39 | base=`dirname $0`/.. 40 | pidfile=$base/bin/hulk.pid 41 | if [ ! -f "$pidfile" ];then 42 | echo "hulk is not running. exists" 43 | exit 44 | fi 45 | 46 | pid=`cat $pidfile` 47 | if [ "$pid" == "" ] ; then 48 | pid=`get_pid "appName=ss-booster-0.0.1-SNAPSHOT"` 49 | fi 50 | 51 | echo -e "`hostname`: stopping plus $pid ... " 52 | kill $pid 53 | 54 | LOOPS=0 55 | while (true); 56 | do 57 | gpid=`get_pid "appName=ss-booster-0.0.1-SNAPSHOT" "$pid"` 58 | if [ "$gpid" == "" ] ; then 59 | echo "Oook! cost:$LOOPS" 60 | `rm $pidfile` 61 | break; 62 | fi 63 | let LOOPS=LOOPS+1 64 | sleep 1 65 | done 66 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/base/Data.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.base; 2 | 3 | import com.jimmy.hulk.data.core.Page; 4 | import com.jimmy.hulk.data.core.PageResult; 5 | import com.jimmy.hulk.data.core.Wrapper; 6 | import com.jimmy.hulk.common.enums.DatasourceEnum; 7 | 8 | import java.io.Serializable; 9 | import java.util.List; 10 | import java.util.Map; 11 | import java.util.Set; 12 | 13 | public interface Data { 14 | 15 | DatasourceEnum type(); 16 | 17 | List> queryPageList(Wrapper wrapper, Page page); 18 | 19 | PageResult> queryPage(Wrapper wrapper, Page page); 20 | 21 | List> queryRange(Wrapper wrapper, Integer start, Integer end); 22 | 23 | int delete(Serializable id); 24 | 25 | int delete(Wrapper wrapper); 26 | 27 | Map queryById(Serializable id); 28 | 29 | int count(Wrapper wrapper); 30 | 31 | int add(Map doc, Serializable id); 32 | 33 | int add(Map doc); 34 | 35 | int addBatch(List> docs); 36 | 37 | int updateBatch(List> docs, Wrapper wrapper); 38 | 39 | int updateBatchById(List> docs); 40 | 41 | int updateById(Map doc, Serializable id); 42 | 43 | Set prefixQuery(String fieldName, String value); 44 | 45 | int update(Map doc, Wrapper wrapper); 46 | 47 | List> queryList(Wrapper wrapper); 48 | 49 | List> queryList(); 50 | 51 | Map queryOne(Wrapper wrapper); 52 | 53 | boolean queryIsExist(Wrapper wrapper); 54 | } 55 | -------------------------------------------------------------------------------- /protocol/src/main/java/com/jimmy/hulk/protocol/packages/CommandPacket.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.protocol.packages; 2 | 3 | import com.jimmy.hulk.protocol.utils.BufferUtil; 4 | import com.jimmy.hulk.protocol.core.MySQLMessage; 5 | import io.netty.buffer.ByteBuf; 6 | import io.netty.channel.ChannelHandlerContext; 7 | 8 | public class CommandPacket extends MySQLPacket { 9 | 10 | public byte command; 11 | public byte[] arg; 12 | 13 | public CommandPacket(String query,byte type) { 14 | packetId = 0; 15 | command = type; 16 | arg = query.getBytes(); 17 | } 18 | 19 | public CommandPacket(String query) { 20 | packetId = 0; 21 | command = COM_QUERY; 22 | arg = query.getBytes(); 23 | } 24 | 25 | public void read(byte[] data) { 26 | MySQLMessage mm = new MySQLMessage(data); 27 | packetLength = mm.readUB3(); 28 | packetId = mm.read(); 29 | command = mm.read(); 30 | arg = mm.readBytes(); 31 | } 32 | 33 | 34 | public ByteBuf getByteBuf(ChannelHandlerContext ctx){ 35 | ByteBuf buffer = ctx.alloc().buffer(); 36 | BufferUtil.writeUB3(buffer, calcPacketSize()); 37 | buffer.writeByte(packetId); 38 | buffer.writeByte(command); 39 | buffer.writeBytes(arg); 40 | return buffer; 41 | } 42 | 43 | public void write(ChannelHandlerContext ctx) { 44 | ctx.writeAndFlush(getByteBuf(ctx)); 45 | } 46 | 47 | @Override 48 | public int calcPacketSize() { 49 | return 1 + arg.length; 50 | } 51 | 52 | @Override 53 | protected String getPacketInfo() { 54 | return "MySQL Command Packet"; 55 | } 56 | 57 | } 58 | 59 | -------------------------------------------------------------------------------- /protocol/src/main/java/com/jimmy/hulk/protocol/core/Context.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.protocol.core; 2 | 3 | import com.jimmy.hulk.protocol.utils.CharsetUtil; 4 | import io.netty.channel.ChannelHandlerContext; 5 | import lombok.Getter; 6 | import lombok.Setter; 7 | 8 | import java.io.Serializable; 9 | 10 | public class Context implements Serializable { 11 | 12 | @Getter 13 | protected String charset; 14 | 15 | @Getter 16 | private int charsetIndex; 17 | 18 | @Getter 19 | @Setter 20 | protected ChannelHandlerContext channelHandlerContext; 21 | 22 | public boolean setCharset(String charset) { 23 | // 修复PHP字符集设置错误, 如: set names 'utf8' 24 | if (charset != null) { 25 | charset = charset.replace("'", ""); 26 | } 27 | 28 | int ci = CharsetUtil.getIndex(charset); 29 | if (ci > 0) { 30 | this.charset = charset.equalsIgnoreCase("utf8mb4") ? "utf8" : charset; 31 | this.charsetIndex = ci; 32 | return true; 33 | } else { 34 | return false; 35 | } 36 | } 37 | 38 | public boolean setCharsetIndex(int ci) { 39 | String charset = CharsetUtil.getCharset(ci); 40 | if (charset != null) { 41 | this.charset = charset; 42 | this.charsetIndex = ci; 43 | return true; 44 | } else { 45 | return false; 46 | } 47 | } 48 | 49 | public void writeOk() { 50 | 51 | } 52 | 53 | public void writeErrMessage(byte id, int errno, String msg) { 54 | 55 | } 56 | 57 | public void writeErrMessage(int errno, String msg) { 58 | writeErrMessage((byte) 1, errno, msg); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /parse/src/main/java/org/apache/calcite/sql/SqlJob.java: -------------------------------------------------------------------------------- 1 | package org.apache.calcite.sql; 2 | 3 | import cn.hutool.core.util.StrUtil; 4 | import lombok.Getter; 5 | import org.apache.calcite.sql.parser.SqlParserPos; 6 | import org.apache.calcite.sql.util.SqlVisitor; 7 | import org.apache.calcite.sql.validate.SqlValidator; 8 | import org.apache.calcite.sql.validate.SqlValidatorScope; 9 | import org.apache.calcite.util.Litmus; 10 | 11 | public class SqlJob extends SqlNode { 12 | 13 | @Getter 14 | private SqlNode name; 15 | 16 | @Getter 17 | private SqlNode cron; 18 | 19 | @Getter 20 | private SqlNode sql; 21 | 22 | /** 23 | * Creates a node. 24 | * 25 | * @param pos Parser position, must not be null. 26 | */ 27 | public SqlJob(SqlParserPos pos, SqlNode name, SqlNode cron, SqlNode sql) { 28 | super(pos); 29 | this.name = name; 30 | this.cron = cron; 31 | this.sql = sql; 32 | } 33 | 34 | @Override 35 | public SqlNode clone(SqlParserPos pos) { 36 | return null; 37 | } 38 | 39 | @Override 40 | public void unparse(SqlWriter writer, int leftPrec, int rightPrec) { 41 | writer.keyword("job"); 42 | writer.print(StrUtil.CRLF); 43 | writer.keyword("name:" + name); 44 | writer.print(StrUtil.CRLF); 45 | writer.keyword("cron:" + cron); 46 | } 47 | 48 | @Override 49 | public void validate(SqlValidator validator, SqlValidatorScope scope) { 50 | 51 | } 52 | 53 | @Override 54 | public R accept(SqlVisitor visitor) { 55 | return null; 56 | } 57 | 58 | @Override 59 | public boolean equalsDeep(SqlNode node, Litmus litmus) { 60 | return false; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /protocol/src/main/java/com/jimmy/hulk/protocol/utils/RandomUtil.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.protocol.utils; 2 | 3 | public class RandomUtil { 4 | private static final byte[] bytes = {'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 'q', 'w', 'e', 'r', 't', 5 | 'y', 'u', 'i', 'o', 'p', 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'z', 'x', 'c', 'v', 'b', 'n', 'm', 6 | 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', 'Z', 'X', 7 | 'C', 'V', 'B', 'N', 'M'}; 8 | private static final long multiplier = 0x5DEECE66DL; 9 | private static final long addend = 0xBL; 10 | private static final long mask = (1L << 48) - 1; 11 | private static final long integerMask = (1L << 33) - 1; 12 | private static final long seedUniquifier = 8682522807148012L; 13 | 14 | private static long seed; 15 | 16 | static { 17 | long s = seedUniquifier + System.nanoTime(); 18 | s = (s ^ multiplier) & mask; 19 | seed = s; 20 | } 21 | 22 | public static final byte[] randomBytes(int size) { 23 | byte[] bb = bytes; 24 | byte[] ab = new byte[size]; 25 | for (int i = 0; i < size; i++) { 26 | ab[i] = randomByte(bb); 27 | } 28 | return ab; 29 | } 30 | 31 | private static byte randomByte(byte[] b) { 32 | int ran = (int) ((next() & integerMask) >>> 16); 33 | return b[ran % b.length]; 34 | } 35 | 36 | private static long next() { 37 | long oldSeed = seed; 38 | long nextSeed = 0L; 39 | do { 40 | nextSeed = (oldSeed * multiplier + addend) & mask; 41 | } while (oldSeed == nextSeed); 42 | seed = nextSeed; 43 | return nextSeed; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /booster/src/main/java/com/jimmy/hulk/booster/action/DropTableAction.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.booster.action; 2 | 3 | import com.jimmy.hulk.actuator.part.PartSupport; 4 | import com.jimmy.hulk.actuator.support.ExecuteHolder; 5 | import com.jimmy.hulk.booster.core.Session; 6 | import com.jimmy.hulk.common.enums.DatasourceEnum; 7 | import com.jimmy.hulk.common.enums.ModuleEnum; 8 | import com.jimmy.hulk.common.exception.HulkException; 9 | import com.jimmy.hulk.data.actuator.Actuator; 10 | import com.jimmy.hulk.parse.core.element.TableNode; 11 | import com.jimmy.hulk.parse.support.AlterParser; 12 | import com.jimmy.hulk.protocol.utils.parse.QueryParse; 13 | import lombok.extern.slf4j.Slf4j; 14 | import org.springframework.beans.factory.annotation.Autowired; 15 | import org.springframework.stereotype.Component; 16 | 17 | @Component 18 | @Slf4j 19 | public class DropTableAction extends BaseAction { 20 | 21 | @Autowired 22 | private AlterParser alterParser; 23 | 24 | @Autowired 25 | private PartSupport partSupport; 26 | 27 | @Override 28 | public void action(String sql, Session session, int offset) throws Exception { 29 | Actuator actuator = partSupport.getActuator(ExecuteHolder.getUsername(), ExecuteHolder.getDatasourceName(), false); 30 | //mysql 直接执行 31 | if (DatasourceEnum.MYSQL.equals(actuator.getDataSourceProperty().getDs())) { 32 | actuator.execute(sql); 33 | return; 34 | } 35 | 36 | TableNode tableNode = alterParser.tableParse(sql); 37 | if (tableNode == null) { 38 | throw new HulkException("创建表失败", ModuleEnum.BOOSTER); 39 | } 40 | 41 | actuator.dropTable(tableNode.getTableName()); 42 | } 43 | 44 | @Override 45 | public int type() { 46 | return QueryParse.DROP_TABLE; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /booster/src/main/java/com/jimmy/hulk/booster/action/AlterAction.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.booster.action; 2 | 3 | import cn.hutool.core.collection.CollUtil; 4 | import com.jimmy.hulk.actuator.part.PartSupport; 5 | import com.jimmy.hulk.actuator.support.ExecuteHolder; 6 | import com.jimmy.hulk.booster.core.Session; 7 | import com.jimmy.hulk.common.enums.DatasourceEnum; 8 | import com.jimmy.hulk.data.actuator.Actuator; 9 | import com.jimmy.hulk.parse.core.element.AlterNode; 10 | import com.jimmy.hulk.parse.support.AlterParser; 11 | import com.jimmy.hulk.protocol.utils.parse.QueryParse; 12 | import lombok.extern.slf4j.Slf4j; 13 | import org.springframework.beans.factory.annotation.Autowired; 14 | import org.springframework.stereotype.Component; 15 | 16 | import java.util.List; 17 | import java.util.stream.Collectors; 18 | 19 | @Component 20 | @Slf4j 21 | public class AlterAction extends BaseAction { 22 | 23 | @Autowired 24 | private AlterParser alterParser; 25 | 26 | @Autowired 27 | private PartSupport partSupport; 28 | 29 | @Override 30 | public void action(String sql, Session session, int offset) throws Exception { 31 | Actuator actuator = partSupport.getActuator(ExecuteHolder.getUsername(), ExecuteHolder.getDatasourceName(), false); 32 | //mysql 直接执行 33 | if (DatasourceEnum.MYSQL.equals(actuator.getDataSourceProperty().getDs())) { 34 | actuator.execute(sql); 35 | return; 36 | } 37 | 38 | List alterNodes = alterParser.alterParse(sql); 39 | if (CollUtil.isNotEmpty(alterNodes)) { 40 | actuator.executeAlter(alterNodes.stream().map(alterNode -> alterNode.build()).collect(Collectors.toList())); 41 | } 42 | } 43 | 44 | @Override 45 | public int type() { 46 | return QueryParse.ALTER; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /parse/src/main/java/org/apache/calcite/sql/SqlFlush.java: -------------------------------------------------------------------------------- 1 | package org.apache.calcite.sql; 2 | 3 | import cn.hutool.core.util.StrUtil; 4 | import lombok.Getter; 5 | import org.apache.calcite.sql.parser.SqlParserPos; 6 | import org.apache.calcite.sql.util.SqlVisitor; 7 | import org.apache.calcite.sql.validate.SqlValidator; 8 | import org.apache.calcite.sql.validate.SqlValidatorScope; 9 | import org.apache.calcite.util.Litmus; 10 | 11 | public class SqlFlush extends SqlNode { 12 | 13 | @Getter 14 | private SqlNode dsName; 15 | 16 | @Getter 17 | private SqlNode index; 18 | 19 | @Getter 20 | private SqlNode mapper; 21 | 22 | @Getter 23 | private SqlNode sql; 24 | 25 | public SqlFlush(SqlParserPos pos, SqlNode dsName, SqlNode index, SqlNode mapper, SqlNode sql) { 26 | super(pos); 27 | this.index = index; 28 | this.dsName = dsName; 29 | this.mapper = mapper; 30 | this.sql = sql; 31 | } 32 | 33 | @Override 34 | public SqlNode clone(SqlParserPos pos) { 35 | return null; 36 | } 37 | 38 | @Override 39 | public void unparse(SqlWriter writer, int leftPrec, int rightPrec) { 40 | writer.keyword("flush"); 41 | writer.print(StrUtil.CRLF); 42 | writer.keyword("dsName:" + dsName); 43 | writer.print(StrUtil.CRLF); 44 | writer.keyword("index:" + index); 45 | writer.print(StrUtil.CRLF); 46 | writer.keyword("mapper:" + mapper); 47 | } 48 | 49 | @Override 50 | public void validate(SqlValidator validator, SqlValidatorScope scope) { 51 | 52 | } 53 | 54 | @Override 55 | public R accept(SqlVisitor visitor) { 56 | return null; 57 | } 58 | 59 | @Override 60 | public boolean equalsDeep(SqlNode node, Litmus litmus) { 61 | return false; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /actuator/src/main/java/com/jimmy/hulk/actuator/sql/Job.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.actuator.sql; 2 | 3 | import cn.hutool.core.io.FileUtil; 4 | import cn.hutool.core.util.StrUtil; 5 | import cn.hutool.cron.CronUtil; 6 | import com.jimmy.hulk.config.support.SystemVariableContext; 7 | import com.jimmy.hulk.parse.core.result.ExtraNode; 8 | import com.jimmy.hulk.parse.core.result.ParseResultNode; 9 | import lombok.extern.slf4j.Slf4j; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.util.Assert; 12 | 13 | @Slf4j 14 | public class Job extends SQL { 15 | 16 | @Autowired 17 | private Select select; 18 | 19 | @Autowired 20 | private SystemVariableContext systemVariableContext; 21 | 22 | @Override 23 | public Integer process(ParseResultNode parseResultNode) throws Exception { 24 | ExtraNode extraNode = parseResultNode.getExtraNode(); 25 | String cron = extraNode.getCron(); 26 | String name = extraNode.getName(); 27 | 28 | Assert.isTrue(StrUtil.isNotBlank(cron), "定时器表达式为空"); 29 | Assert.isTrue(StrUtil.isNotBlank(name), "定时器名字为空"); 30 | 31 | CronUtil.remove(name); 32 | CronUtil.schedule(name, cron, () -> { 33 | try { 34 | log.info("{}定时器启动", name); 35 | //创建文件 36 | String filePath = systemVariableContext.getFileStorePath() + System.currentTimeMillis() + ".dat"; 37 | //清空 38 | FileUtil.writeUtf8String(StrUtil.EMPTY, filePath); 39 | this.writeToDisk(filePath, select.process(parseResultNode)); 40 | 41 | log.info("{}定时器运行成功,文件路径:{}", name, filePath); 42 | } catch (Exception e) { 43 | log.info("{}定时器运行失败", name, e); 44 | } 45 | }); 46 | 47 | return 0; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /parse/src/main/java/com/jimmy/hulk/parse/core/element/TableNode.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.parse.core.element; 2 | 3 | import cn.hutool.core.util.IdUtil; 4 | import cn.hutool.core.util.StrUtil; 5 | import com.google.common.collect.Lists; 6 | import lombok.Getter; 7 | import lombok.Setter; 8 | 9 | import java.io.Serializable; 10 | import java.util.List; 11 | 12 | public class TableNode implements Serializable { 13 | 14 | @Getter 15 | @Setter 16 | private String alias; 17 | 18 | @Getter 19 | @Setter 20 | private String tableName; 21 | 22 | @Getter 23 | @Setter 24 | private String dsName; 25 | 26 | private Integer hashCode; 27 | 28 | @Getter 29 | private String uuid; 30 | 31 | @Getter 32 | @Setter 33 | private List columnNodes = Lists.newArrayList(); 34 | 35 | @Getter 36 | @Setter 37 | private List indexNodes = Lists.newArrayList(); 38 | 39 | public TableNode() { 40 | this.uuid = IdUtil.simpleUUID(); 41 | } 42 | 43 | @Override 44 | public String toString() { 45 | StringBuilder append = new StringBuilder(StrUtil.nullToDefault(dsName, StrUtil.EMPTY)).append(".").append(tableName); 46 | if (StrUtil.isNotBlank(alias) && !alias.equalsIgnoreCase(tableName)) { 47 | append.append(" as ").append(alias); 48 | } 49 | 50 | return append.toString(); 51 | } 52 | 53 | @Override 54 | public boolean equals(Object o) { 55 | if (!(o instanceof TableNode)) { 56 | return false; 57 | } 58 | 59 | return this.uuid.equals(((TableNode) o).getUuid()); 60 | } 61 | 62 | @Override 63 | public int hashCode() { 64 | if (hashCode != null) { 65 | return hashCode; 66 | } 67 | 68 | hashCode = uuid.hashCode(); 69 | return hashCode; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /booster/src/main/assembly/release.xml: -------------------------------------------------------------------------------- 1 | 4 | dist 5 | 6 | tar.gz 7 | 8 | false 9 | 10 | 11 | . 12 | ${file.separator} 13 | 14 | README* 15 | 16 | 17 | 18 | ./src/main/resources 19 | /conf 20 | 21 | booster.xml 22 | 23 | 24 | 25 | ./src/main/bin 26 | bin 27 | 28 | **/* 29 | 30 | 0755 31 | 32 | 33 | target 34 | logs 35 | 36 | **/* 37 | 38 | 39 | 40 | 41 | 42 | lib 43 | 44 | junit:junit 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/parse/dml/ClickHouseDmlParse.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.parse.dml; 2 | 3 | import com.jimmy.hulk.data.annotation.DS; 4 | import com.jimmy.hulk.data.base.DmlParse; 5 | 6 | import java.util.List; 7 | import java.util.Map; 8 | 9 | import static com.jimmy.hulk.common.enums.DatasourceEnum.CLICK_HOUSE; 10 | 11 | @DS(type = CLICK_HOUSE) 12 | public class ClickHouseDmlParse implements DmlParse { 13 | 14 | @Override 15 | public String insert(Map data, List param, String tableName) { 16 | StringBuilder sb = new StringBuilder("insert into ").append(tableName); 17 | 18 | StringBuilder s1 = new StringBuilder(" ( "); 19 | StringBuilder s2 = new StringBuilder(" ( "); 20 | for (Map.Entry entry : data.entrySet()) { 21 | Object v = entry.getValue(); 22 | String key = entry.getKey(); 23 | 24 | s2.append("?").append(","); 25 | s1.append(key + ","); 26 | param.add(v); 27 | } 28 | //去除最后一个逗号 29 | s1.delete(s1.length() - 1, s1.length()).append(") "); 30 | s2.delete(s2.length() - 1, s2.length()).append(") "); 31 | //添加条件 32 | return sb.append(s1).append(" values ").append(s2).toString(); 33 | } 34 | 35 | @Override 36 | public String update(Map data, List param, String tableName) { 37 | StringBuilder sb = new StringBuilder("update ").append(tableName).append(" set "); 38 | //参数单引号处理 39 | for (Map.Entry entry : data.entrySet()) { 40 | Object v = entry.getValue(); 41 | sb.append(entry.getKey()).append("=?").append(","); 42 | param.add(v); 43 | } 44 | //去除最后一个逗号 45 | sb.delete(sb.length() - 1, sb.length()); 46 | return sb.toString(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/parse/dml/SqlServerDmlParse.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.parse.dml; 2 | 3 | import com.jimmy.hulk.data.annotation.DS; 4 | import com.jimmy.hulk.data.base.DmlParse; 5 | 6 | import java.util.List; 7 | import java.util.Map; 8 | 9 | import static com.jimmy.hulk.common.enums.DatasourceEnum.SQL_SERVER; 10 | 11 | @DS(type = SQL_SERVER) 12 | public class SqlServerDmlParse implements DmlParse { 13 | 14 | @Override 15 | public String insert(Map data, List param, String tableName) { 16 | StringBuilder sb = new StringBuilder("insert into ").append(tableName); 17 | 18 | StringBuilder s1 = new StringBuilder(" ( "); 19 | StringBuilder s2 = new StringBuilder(" ( "); 20 | for (Map.Entry entry : data.entrySet()) { 21 | Object v = entry.getValue(); 22 | String key = entry.getKey(); 23 | 24 | s2.append("?").append(","); 25 | s1.append(key + ","); 26 | param.add(v); 27 | } 28 | //去除最后一个逗号 29 | s1.delete(s1.length() - 1, s1.length()).append(") "); 30 | s2.delete(s2.length() - 1, s2.length()).append(") "); 31 | //添加条件 32 | return sb.append(s1).append(" values ").append(s2).toString(); 33 | } 34 | 35 | @Override 36 | public String update(Map data, List param, String tableName) { 37 | StringBuilder sb = new StringBuilder("update ").append(tableName).append(" set "); 38 | //参数单引号处理 39 | for (Map.Entry entry : data.entrySet()) { 40 | Object v = entry.getValue(); 41 | sb.append(entry.getKey()).append("=?").append(","); 42 | param.add(v); 43 | } 44 | //去除最后一个逗号 45 | sb.delete(sb.length() - 1, sb.length()); 46 | return sb.toString(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/parse/dml/MySQLDmlParse.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.parse.dml; 2 | 3 | import com.jimmy.hulk.data.annotation.DS; 4 | import com.jimmy.hulk.data.base.DmlParse; 5 | 6 | import java.util.List; 7 | import java.util.Map; 8 | 9 | import static com.jimmy.hulk.common.enums.DatasourceEnum.MYSQL; 10 | 11 | @DS(type = MYSQL) 12 | public class MySQLDmlParse implements DmlParse { 13 | 14 | @Override 15 | public String insert(Map data, List param, String tableName) { 16 | StringBuilder sb = new StringBuilder("insert into ").append(tableName); 17 | 18 | StringBuilder s1 = new StringBuilder(" ( "); 19 | StringBuilder s2 = new StringBuilder(" ( "); 20 | for (Map.Entry entry : data.entrySet()) { 21 | Object v = entry.getValue(); 22 | String key = entry.getKey(); 23 | 24 | s2.append("?").append(","); 25 | s1.append("`").append(key + "`,"); 26 | param.add(v); 27 | } 28 | //去除最后一个逗号 29 | s1.delete(s1.length() - 1, s1.length()).append(") "); 30 | s2.delete(s2.length() - 1, s2.length()).append(") "); 31 | //添加条件 32 | return sb.append(s1).append(" values ").append(s2).toString(); 33 | } 34 | 35 | @Override 36 | public String update(Map data, List param, String tableName) { 37 | StringBuilder sb = new StringBuilder("update ").append(tableName).append(" set "); 38 | //参数单引号处理 39 | for (Map.Entry entry : data.entrySet()) { 40 | Object v = entry.getValue(); 41 | sb.append("`").append(entry.getKey()).append("`=?").append(","); 42 | param.add(v); 43 | } 44 | //去除最后一个逗号 45 | sb.delete(sb.length() - 1, sb.length()); 46 | return sb.toString(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/parse/dml/OracleDmlParse.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.parse.dml; 2 | 3 | import com.jimmy.hulk.data.annotation.DS; 4 | import com.jimmy.hulk.data.base.DmlParse; 5 | 6 | import java.util.List; 7 | import java.util.Map; 8 | 9 | import static com.jimmy.hulk.common.enums.DatasourceEnum.ORACLE; 10 | 11 | @DS(type = ORACLE) 12 | public class OracleDmlParse implements DmlParse { 13 | 14 | @Override 15 | public String insert(Map data, List param, String tableName) { 16 | StringBuilder sb = new StringBuilder("insert into \"").append(tableName).append("\""); 17 | 18 | StringBuilder s1 = new StringBuilder(" ( "); 19 | StringBuilder s2 = new StringBuilder(" ( "); 20 | for (Map.Entry entry : data.entrySet()) { 21 | Object v = entry.getValue(); 22 | String key = entry.getKey(); 23 | 24 | s2.append("?").append(","); 25 | s1.append(key + ","); 26 | param.add(v); 27 | } 28 | //去除最后一个逗号 29 | s1.delete(s1.length() - 1, s1.length()).append(") "); 30 | s2.delete(s2.length() - 1, s2.length()).append(") "); 31 | //添加条件 32 | return sb.append(s1).append(" values ").append(s2).toString(); 33 | } 34 | 35 | @Override 36 | public String update(Map data, List param, String tableName) { 37 | StringBuilder sb = new StringBuilder("update \"").append(tableName).append("\" set "); 38 | //参数单引号处理 39 | for (Map.Entry entry : data.entrySet()) { 40 | Object v = entry.getValue(); 41 | sb.append(entry.getKey()).append("=?").append(","); 42 | param.add(v); 43 | } 44 | //去除最后一个逗号 45 | sb.delete(sb.length() - 1, sb.length()); 46 | return sb.toString(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /protocol/src/main/java/com/jimmy/hulk/protocol/utils/constant/Fields.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.protocol.utils.constant; 2 | 3 | /** 4 | * 字段类型及标识定义 5 | */ 6 | public interface Fields { 7 | 8 | /** 9 | * value type 10 | */ 11 | byte UNKNOWN = 100; 12 | byte STRING = 1; 13 | byte INT = 2; 14 | byte LONG = 3; 15 | byte BOOLEAN = 4; 16 | 17 | /** 18 | * field data type 19 | */ 20 | int FIELD_TYPE_DECIMAL = 0; 21 | int FIELD_TYPE_TINY = 1; 22 | int FIELD_TYPE_SHORT = 2; 23 | int FIELD_TYPE_LONG = 3; 24 | int FIELD_TYPE_FLOAT = 4; 25 | int FIELD_TYPE_DOUBLE = 5; 26 | int FIELD_TYPE_NULL = 6; 27 | int FIELD_TYPE_TIMESTAMP = 7; 28 | int FIELD_TYPE_LONGLONG = 8; 29 | int FIELD_TYPE_INT24 = 9; 30 | int FIELD_TYPE_DATE = 10; 31 | int FIELD_TYPE_TIME = 11; 32 | int FIELD_TYPE_DATETIME = 12; 33 | int FIELD_TYPE_YEAR = 13; 34 | int FIELD_TYPE_NEWDATE = 14; 35 | int FIELD_TYPE_VARCHAR = 15; 36 | int FIELD_TYPE_BIT = 16; 37 | int FIELD_TYPE_NEW_DECIMAL = 246; 38 | int FIELD_TYPE_ENUM = 247; 39 | int FIELD_TYPE_SET = 248; 40 | int FIELD_TYPE_TINY_BLOB = 249; 41 | int FIELD_TYPE_MEDIUM_BLOB = 250; 42 | int FIELD_TYPE_LONG_BLOB = 251; 43 | int FIELD_TYPE_BLOB = 252; 44 | int FIELD_TYPE_VAR_STRING = 253; 45 | int FIELD_TYPE_STRING = 254; 46 | int FIELD_TYPE_GEOMETRY = 255; 47 | 48 | /** 49 | * field flag 50 | */ 51 | int NOT_NULL_FLAG = 0x0001; 52 | int PRI_KEY_FLAG = 0x0002; 53 | int UNIQUE_KEY_FLAG = 0x0004; 54 | int MULTIPLE_KEY_FLAG = 0x0008; 55 | int BLOB_FLAG = 0x0010; 56 | int UNSIGNED_FLAG = 0x0020; 57 | int ZEROFILL_FLAG = 0x0040; 58 | int BINARY_FLAG = 0x0080; 59 | int ENUM_FLAG = 0x0100; 60 | int AUTO_INCREMENT_FLAG = 0x0200; 61 | int TIMESTAMP_FLAG = 0x0400; 62 | int SET_FLAG = 0x0800; 63 | 64 | } -------------------------------------------------------------------------------- /protocol/src/main/java/com/jimmy/hulk/protocol/packages/EOFPacket.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.protocol.packages; 2 | 3 | import com.jimmy.hulk.protocol.utils.BufferUtil; 4 | import com.jimmy.hulk.protocol.core.MySQLMessage; 5 | import io.netty.buffer.ByteBuf; 6 | import io.netty.channel.ChannelHandlerContext; 7 | 8 | public class EOFPacket extends MySQLPacket { 9 | public static final byte FIELD_COUNT = (byte) 0xfe; 10 | 11 | public byte fieldCount = FIELD_COUNT; 12 | public int warningCount; 13 | public int status = 2; 14 | 15 | public void read(byte[] data) { 16 | MySQLMessage mm = new MySQLMessage(data); 17 | packetLength = mm.readUB3(); 18 | packetId = mm.read(); 19 | fieldCount = mm.read(); 20 | warningCount = mm.readUB2(); 21 | status = mm.readUB2(); 22 | } 23 | 24 | public void read(BinaryPacket bin) { 25 | packetLength = bin.packetLength; 26 | packetId = bin.packetId; 27 | MySQLMessage mm = new MySQLMessage(bin.data); 28 | fieldCount = mm.read(); 29 | warningCount = mm.readUB2(); 30 | status = mm.readUB2(); 31 | } 32 | 33 | @Override 34 | public ByteBuf writeBuf(ByteBuf buffer, ChannelHandlerContext ctx) { 35 | int size = calcPacketSize(); 36 | BufferUtil.writeUB3(buffer, size); 37 | buffer.writeByte(packetId); 38 | buffer.writeByte(fieldCount); 39 | BufferUtil.writeUB2(buffer, warningCount); 40 | BufferUtil.writeUB2(buffer, status); 41 | return buffer; 42 | } 43 | 44 | public boolean hasStatusFlag(long flag) { 45 | return ((this.status & flag) == flag); 46 | } 47 | 48 | @Override 49 | public int calcPacketSize() { 50 | return 5;// 1+2+2; 51 | } 52 | 53 | @Override 54 | protected String getPacketInfo() { 55 | return "MySQL EOF Packet"; 56 | } 57 | 58 | } -------------------------------------------------------------------------------- /booster/src/main/java/com/jimmy/hulk/booster/handler/HandlerInitializer.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.booster.handler; 2 | 3 | import com.jimmy.hulk.authority.base.AuthenticationManager; 4 | import com.jimmy.hulk.booster.core.Session; 5 | import com.jimmy.hulk.booster.protocol.MySqlPacketDecoder; 6 | import com.jimmy.hulk.booster.support.SessionPool; 7 | import io.netty.channel.ChannelInitializer; 8 | import io.netty.channel.socket.SocketChannel; 9 | import io.netty.handler.timeout.IdleStateHandler; 10 | 11 | 12 | public class HandlerInitializer extends ChannelInitializer { 13 | 14 | private static final int IDLE_CHECK_INTERVAL = 3600; 15 | 16 | private SessionPool sessionPool; 17 | 18 | private AuthenticationManager authenticationManager; 19 | 20 | public HandlerInitializer(SessionPool sessionPool, AuthenticationManager authenticationManager) { 21 | this.sessionPool = sessionPool; 22 | this.authenticationManager = authenticationManager; 23 | } 24 | 25 | @Override 26 | protected void initChannel(SocketChannel ch) throws Exception { 27 | Session session = sessionPool.getSession(); 28 | SessionHandler sessionHandler = new SessionHandler(session, sessionPool); 29 | AuthenticatorHandler authHandler = new AuthenticatorHandler(session, sessionPool, authenticationManager); 30 | ExceptionHandler exceptionHandler = new ExceptionHandler(session, sessionPool); 31 | // 心跳handler 32 | // 1小时做一次idle check 秒为单位 33 | //int IDLE_CHECK_INTERVAL = 3600 * 1000; 34 | ch.pipeline().addLast(new IdleStateHandler(IDLE_CHECK_INTERVAL, IDLE_CHECK_INTERVAL, IDLE_CHECK_INTERVAL)); 35 | // decode mysql packet depend on it's length 36 | ch.pipeline().addLast(new MySqlPacketDecoder()); 37 | ch.pipeline().addLast(sessionHandler); 38 | ch.pipeline().addLast(authHandler); 39 | ch.pipeline().addLast(exceptionHandler); 40 | } 41 | } -------------------------------------------------------------------------------- /booster/src/main/bin/startup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | current_path=`pwd` 4 | class_path=$CLASSPATH 5 | 6 | case "`uname`" in 7 | Linux) 8 | bin_abs_path=$(readlink -f $(dirname $0)) 9 | ;; 10 | *) 11 | bin_abs_path=`cd $(dirname $0); pwd` 12 | ;; 13 | esac 14 | base=${bin_abs_path}/.. 15 | export LANG=en_US.UTF-8 16 | export BASE=$base 17 | 18 | if [ -f $base/bin/adapter.pid ] ; then 19 | echo "found adapter.pid , Please run stop.sh first ,then startup.sh" 2>&2 20 | exit 1 21 | fi 22 | 23 | if [ ! -d $base/logs ] ; then 24 | mkdir -p $base/logs 25 | fi 26 | 27 | ## set java path 28 | if [ -z "$JAVA" ] ; then 29 | JAVA=$(which java) 30 | fi 31 | 32 | ALIBABA_JAVA="/usr/jimmy/java/bin/java" 33 | TAOBAO_JAVA="/opt/jimmy/java/bin/java" 34 | if [ -z "$JAVA" ]; then 35 | if [ -f $ALIBABA_JAVA ] ; then 36 | JAVA=$ALIBABA_JAVA 37 | elif [ -f $TAOBAO_JAVA ] ; then 38 | JAVA=$TAOBAO_JAVA 39 | else 40 | echo "Cannot find a Java JDK. Please set either set JAVA or put java (>=1.5) in your PATH." 2>&2 41 | exit 1 42 | fi 43 | fi 44 | 45 | 46 | JAVA_OPTS="-server -Xms1g -Xmx1g" 47 | JAVA_OPTS="$JAVA_OPTS -XX:+UseG1GC -XX:MaxGCPauseMillis=250 -XX:+UseGCOverheadLimit -XX:+ExplicitGCInvokesConcurrent -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=dump.hprof" 48 | JAVA_OPTS=" $JAVA_OPTS -Djava.awt.headless=true -Djava.net.preferIPv4Stack=true -Dfile.encoding=UTF-8 -Duser.timezone=GMT+08" 49 | HULK_OPTS="-DappName=ss-booster-0.0.1-SNAPSHOT" 50 | 51 | for i in $base/lib/*; 52 | do class_path=$i:"$class_path"; 53 | done 54 | 55 | class_path="$base/conf:$class_path"; 56 | 57 | echo "cd to $bin_abs_path for workaround relative path" 58 | cd $bin_abs_path 59 | 60 | echo CLASSPATH :$class_path 61 | $JAVA $JAVA_OPTS $JAVA_DEBUG_OPT $HULK_OPTS -classpath .:$class_path com.jimmy.hulk.booster.App 1>>/dev/null 2>&1 & 62 | echo $! > $base/bin/hulk.pid 63 | 64 | echo "cd to $current_path for continue" 65 | cd $current_path 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /config/src/main/java/com/jimmy/hulk/config/support/SystemVariableContext.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.config.support; 2 | 3 | 4 | import cn.hutool.core.util.StrUtil; 5 | import com.jimmy.hulk.common.constant.Constants; 6 | 7 | public class SystemVariableContext { 8 | 9 | private Integer pageSize = 200; 10 | 11 | private String fileStorePath = "/tmp/"; 12 | 13 | private String serializerType = "kryo"; 14 | 15 | private Integer port = 6033; 16 | 17 | private Integer defaultExpire = 30; 18 | 19 | private Integer transactionTimeout = 60; 20 | 21 | public Integer getTransactionTimeout() { 22 | return transactionTimeout; 23 | } 24 | 25 | void setTransactionTimeout(Integer transactionTimeout) { 26 | this.transactionTimeout = transactionTimeout; 27 | } 28 | 29 | public Integer getPageSize() { 30 | return pageSize; 31 | } 32 | 33 | public String getFileStorePath() { 34 | if (!StrUtil.endWith(fileStorePath, Constants.Booster.SEPARATOR)) { 35 | fileStorePath = fileStorePath + Constants.Booster.SEPARATOR; 36 | } 37 | 38 | return fileStorePath; 39 | } 40 | 41 | public String getSerializerType() { 42 | return serializerType; 43 | } 44 | 45 | public Integer getPort() { 46 | return port; 47 | } 48 | 49 | void setPort(Integer port) { 50 | this.port = port; 51 | } 52 | 53 | void setPageSize(Integer pageSize) { 54 | this.pageSize = pageSize; 55 | } 56 | 57 | void setFileStorePath(String fileStorePath) { 58 | this.fileStorePath = fileStorePath; 59 | } 60 | 61 | void setSerializerType(String serializerType) { 62 | this.serializerType = serializerType; 63 | } 64 | 65 | public Integer getDefaultExpire() { 66 | return defaultExpire; 67 | } 68 | 69 | void setDefaultExpire(Integer defaultExpire) { 70 | this.defaultExpire = defaultExpire; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /booster/src/main/java/com/jimmy/hulk/booster/protocol/MySqlPacketDecoder.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.booster.protocol; 2 | 3 | import com.jimmy.hulk.protocol.packages.BinaryPacket; 4 | import com.jimmy.hulk.protocol.utils.ByteUtil; 5 | import io.netty.buffer.ByteBuf; 6 | import io.netty.channel.ChannelHandlerContext; 7 | import io.netty.handler.codec.ByteToMessageDecoder; 8 | import lombok.extern.slf4j.Slf4j; 9 | 10 | import java.util.List; 11 | 12 | @Slf4j 13 | public class MySqlPacketDecoder extends ByteToMessageDecoder { 14 | 15 | private final int packetHeaderSize = 4; 16 | 17 | private final int maxPacketSize = 16 * 1024 * 1024; 18 | 19 | /** 20 | * MySql外层结构解包 21 | * 22 | * @param ctx 23 | * @param in 24 | * @param out 25 | */ 26 | @Override 27 | protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) { 28 | // 4 bytes:3 length + 1 packetId 29 | if (in.readableBytes() < packetHeaderSize) { 30 | return; 31 | } 32 | in.markReaderIndex(); 33 | int packetLength = ByteUtil.readUB3(in); 34 | // 过载保护 35 | if (packetLength > maxPacketSize) { 36 | throw new IllegalArgumentException("Packet size over the limit " + maxPacketSize); 37 | } 38 | byte packetId = in.readByte(); 39 | if (in.readableBytes() < packetLength) { 40 | // 半包回溯 41 | in.resetReaderIndex(); 42 | return; 43 | } 44 | BinaryPacket packet = new BinaryPacket(); 45 | packet.packetLength = packetLength; 46 | packet.packetId = packetId; 47 | // data will not be accessed any more,so we can use this array safely 48 | packet.data = in.readBytes(packetLength).array(); 49 | if (packet.data == null || packet.data.length == 0) { 50 | log.error("getDecoder data errorMessage,packetLength=" + packet.packetLength); 51 | } 52 | out.add(packet); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/config/DataSourceProperty.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.config; 2 | 3 | import cn.hutool.core.util.StrUtil; 4 | import cn.hutool.crypto.SecureUtil; 5 | import com.jimmy.hulk.common.enums.DatasourceEnum; 6 | import lombok.Data; 7 | import lombok.experimental.Accessors; 8 | 9 | @Data 10 | @Accessors(chain = true) 11 | public class DataSourceProperty { 12 | 13 | private DatasourceEnum ds; 14 | 15 | private String url; 16 | 17 | private String username; 18 | 19 | private String password; 20 | 21 | private String schema; 22 | 23 | private String clusterName; 24 | 25 | private Integer maxPoolSize = 10; 26 | 27 | private String name; 28 | 29 | public String getName() { 30 | if (StrUtil.isNotBlank(this.name)) { 31 | return this.name; 32 | } 33 | 34 | StringBuilder stringBuilder = new StringBuilder("ds").append(":").append(ds.getMessage()).append(StrUtil.CRLF); 35 | if (StrUtil.isNotBlank(url)) { 36 | stringBuilder.append("url").append(":").append(url).append(StrUtil.CRLF); 37 | } 38 | 39 | if (StrUtil.isNotBlank(username)) { 40 | stringBuilder.append("username").append(":").append(username).append(StrUtil.CRLF); 41 | } 42 | 43 | if (StrUtil.isNotBlank(username)) { 44 | stringBuilder.append("username").append(":").append(username).append(StrUtil.CRLF); 45 | } 46 | 47 | if (StrUtil.isNotBlank(password)) { 48 | stringBuilder.append("password").append(":").append(password).append(StrUtil.CRLF); 49 | } 50 | 51 | if (StrUtil.isNotBlank(schema)) { 52 | stringBuilder.append("schema").append(":").append(schema).append(StrUtil.CRLF); 53 | } 54 | 55 | if (StrUtil.isNotBlank(clusterName)) { 56 | stringBuilder.append("clusterName").append(":").append(clusterName).append(StrUtil.CRLF); 57 | } 58 | 59 | this.name = SecureUtil.md5(stringBuilder.toString()); 60 | return this.name; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /protocol/src/main/java/com/jimmy/hulk/protocol/utils/CharTypes.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.protocol.utils; 2 | 3 | public class CharTypes { 4 | 5 | private final static boolean[] hexFlags = new boolean[256]; 6 | 7 | static { 8 | for (char c = 0; c < hexFlags.length; ++c) { 9 | if (c >= 'A' && c <= 'F') { 10 | hexFlags[c] = true; 11 | } else if (c >= 'a' && c <= 'f') { 12 | hexFlags[c] = true; 13 | } else if (c >= '0' && c <= '9') { 14 | hexFlags[c] = true; 15 | } 16 | } 17 | } 18 | 19 | public static boolean isHex(char c) { 20 | return c < 256 && hexFlags[c]; 21 | } 22 | 23 | public static boolean isDigit(char c) { 24 | return c >= '0' && c <= '9'; 25 | } 26 | 27 | private final static boolean[] identifierFlags = new boolean[256]; 28 | 29 | static { 30 | for (char c = 0; c < identifierFlags.length; ++c) { 31 | if (c >= 'A' && c <= 'Z') { 32 | identifierFlags[c] = true; 33 | } else if (c >= 'a' && c <= 'z') { 34 | identifierFlags[c] = true; 35 | } else if (c >= '0' && c <= '9') { 36 | identifierFlags[c] = true; 37 | } 38 | } 39 | // identifierFlags['`'] = true; 40 | identifierFlags['_'] = true; 41 | identifierFlags['$'] = true; 42 | } 43 | 44 | public static boolean isIdentifierChar(char c) { 45 | return c > identifierFlags.length || identifierFlags[c]; 46 | } 47 | 48 | private final static boolean[] whitespaceFlags = new boolean[256]; 49 | 50 | static { 51 | whitespaceFlags[' '] = true; 52 | whitespaceFlags['\n'] = true; 53 | whitespaceFlags['\r'] = true; 54 | whitespaceFlags['\t'] = true; 55 | whitespaceFlags['\f'] = true; 56 | whitespaceFlags['\b'] = true; 57 | } 58 | 59 | public static boolean isWhitespace(char c) { 60 | return c <= whitespaceFlags.length && whitespaceFlags[c]; 61 | } 62 | 63 | } -------------------------------------------------------------------------------- /booster/src/main/java/com/jimmy/hulk/booster/action/CreateTableAction.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.booster.action; 2 | 3 | import com.jimmy.hulk.actuator.part.PartSupport; 4 | import com.jimmy.hulk.actuator.support.ExecuteHolder; 5 | import com.jimmy.hulk.booster.core.Session; 6 | import com.jimmy.hulk.common.core.Table; 7 | import com.jimmy.hulk.common.enums.DatasourceEnum; 8 | import com.jimmy.hulk.common.enums.ModuleEnum; 9 | import com.jimmy.hulk.common.exception.HulkException; 10 | import com.jimmy.hulk.data.actuator.Actuator; 11 | import com.jimmy.hulk.parse.core.element.TableNode; 12 | import com.jimmy.hulk.parse.support.AlterParser; 13 | import com.jimmy.hulk.protocol.utils.parse.QueryParse; 14 | import lombok.extern.slf4j.Slf4j; 15 | import org.springframework.beans.factory.annotation.Autowired; 16 | import org.springframework.stereotype.Component; 17 | 18 | import java.util.stream.Collectors; 19 | 20 | @Component 21 | @Slf4j 22 | public class CreateTableAction extends BaseAction { 23 | 24 | @Autowired 25 | private AlterParser alterParser; 26 | 27 | @Autowired 28 | private PartSupport partSupport; 29 | 30 | @Override 31 | public void action(String sql, Session session, int offset) throws Exception { 32 | Actuator actuator = partSupport.getActuator(ExecuteHolder.getUsername(), ExecuteHolder.getDatasourceName(), false); 33 | //mysql 直接执行 34 | if (DatasourceEnum.MYSQL.equals(actuator.getDataSourceProperty().getDs())) { 35 | actuator.execute(sql); 36 | return; 37 | } 38 | 39 | TableNode tableNode = alterParser.tableParse(sql); 40 | if (tableNode == null) { 41 | throw new HulkException("创建表失败", ModuleEnum.BOOSTER); 42 | } 43 | 44 | Table table = new Table(); 45 | table.setTableName(tableNode.getTableName()); 46 | table.setColumns(tableNode.getColumnNodes().stream().map(bean -> bean.build()).collect(Collectors.toList())); 47 | actuator.createTable(table); 48 | } 49 | 50 | @Override 51 | public int type() { 52 | return QueryParse.CREATE_TABLE; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/datasource/ExcelDatasource.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.datasource; 2 | 3 | import cn.hutool.core.util.StrUtil; 4 | import com.jimmy.hulk.common.enums.DatasourceEnum; 5 | import com.jimmy.hulk.common.enums.ModuleEnum; 6 | import com.jimmy.hulk.common.exception.HulkException; 7 | import com.jimmy.hulk.data.actuator.Actuator; 8 | import com.jimmy.hulk.data.actuator.ExcelActuator; 9 | import com.jimmy.hulk.data.annotation.DS; 10 | import com.jimmy.hulk.data.condition.ExcelCondition; 11 | import com.jimmy.hulk.data.config.DataProperties; 12 | import com.jimmy.hulk.data.core.Dump; 13 | import org.springframework.context.annotation.Conditional; 14 | 15 | import java.io.IOException; 16 | 17 | import static com.jimmy.hulk.common.enums.DatasourceEnum.EXCEL; 18 | 19 | @Conditional(ExcelCondition.class) 20 | @DS(type = EXCEL, condition = ExcelCondition.class) 21 | public class ExcelDatasource extends BaseDatasource { 22 | 23 | @Override 24 | public void init(DataProperties dataProperties) { 25 | } 26 | 27 | @Override 28 | public Actuator getActuator() { 29 | return new ExcelActuator(this, dataSourceProperty); 30 | } 31 | 32 | @Override 33 | public String getDataSource() { 34 | String url = dataSourceProperty.getUrl(); 35 | if (StrUtil.isEmpty(url)) { 36 | throw new HulkException("文件下载路径为空", ModuleEnum.DATA); 37 | } 38 | 39 | return url; 40 | } 41 | 42 | @Override 43 | public String getDataSource(Long timeout) { 44 | return this.getDataSource(); 45 | } 46 | 47 | @Override 48 | public boolean testConnect() { 49 | return true; 50 | } 51 | 52 | @Override 53 | public void dump(Dump dump) throws Exception { 54 | 55 | } 56 | 57 | @Override 58 | public String getDataSourceWithoutCache(Long timeout) { 59 | return this.getDataSource(); 60 | } 61 | 62 | @Override 63 | public DatasourceEnum type() { 64 | return EXCEL; 65 | } 66 | 67 | @Override 68 | public void close() throws IOException { 69 | 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /protocol/src/main/java/com/jimmy/hulk/protocol/reponse/select/SelectVersion.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.protocol.reponse.select; 2 | 3 | import com.jimmy.hulk.protocol.packages.FieldPacket; 4 | import com.jimmy.hulk.protocol.packages.RowDataPacket; 5 | import com.jimmy.hulk.protocol.utils.PacketUtil; 6 | import com.jimmy.hulk.protocol.utils.constant.Fields; 7 | import com.jimmy.hulk.protocol.utils.constant.Version; 8 | import com.jimmy.hulk.protocol.core.Context; 9 | import com.jimmy.hulk.protocol.packages.EOFPacket; 10 | import com.jimmy.hulk.protocol.packages.ResultSetHeaderPacket; 11 | import io.netty.buffer.ByteBuf; 12 | import io.netty.channel.ChannelHandlerContext; 13 | 14 | public class SelectVersion { 15 | 16 | private static final int FIELD_COUNT = 1; 17 | 18 | private static final EOFPacket EOF = new EOFPacket(); 19 | 20 | private static final FieldPacket[] FIELDS = new FieldPacket[FIELD_COUNT]; 21 | 22 | private static final ResultSetHeaderPacket HEADER = PacketUtil.getHeader(FIELD_COUNT); 23 | 24 | static { 25 | int i = 0; 26 | byte packetId = 0; 27 | HEADER.packetId = ++packetId; 28 | FIELDS[i] = PacketUtil.getField("VERSION()", Fields.FIELD_TYPE_VAR_STRING); 29 | FIELDS[i++].packetId = ++packetId; 30 | EOF.packetId = ++packetId; 31 | } 32 | 33 | public static void response(Context c) { 34 | ChannelHandlerContext ctx = c.getChannelHandlerContext(); 35 | ByteBuf buffer = ctx.alloc().buffer(); 36 | buffer = HEADER.writeBuf(buffer, ctx); 37 | for (FieldPacket field : FIELDS) { 38 | buffer = field.writeBuf(buffer, ctx); 39 | } 40 | buffer = EOF.writeBuf(buffer, ctx); 41 | byte packetId = EOF.packetId; 42 | RowDataPacket row = new RowDataPacket(FIELD_COUNT); 43 | row.add(Version.SERVER_VERSION); 44 | row.packetId = ++packetId; 45 | buffer = row.writeBuf(buffer, ctx); 46 | EOFPacket lastEof = new EOFPacket(); 47 | lastEof.packetId = ++packetId; 48 | buffer = lastEof.writeBuf(buffer, ctx); 49 | ctx.writeAndFlush(buffer); 50 | } 51 | 52 | } -------------------------------------------------------------------------------- /protocol/src/main/java/com/jimmy/hulk/protocol/reponse/select/SelectDatabase.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.protocol.reponse.select; 2 | 3 | import com.jimmy.hulk.protocol.packages.FieldPacket; 4 | import com.jimmy.hulk.protocol.packages.RowDataPacket; 5 | import com.jimmy.hulk.protocol.utils.PacketUtil; 6 | import com.jimmy.hulk.protocol.utils.StringUtil; 7 | import com.jimmy.hulk.protocol.utils.constant.Fields; 8 | import com.jimmy.hulk.protocol.core.Context; 9 | import com.jimmy.hulk.protocol.packages.EOFPacket; 10 | import com.jimmy.hulk.protocol.packages.ResultSetHeaderPacket; 11 | import io.netty.buffer.ByteBuf; 12 | import io.netty.channel.ChannelHandlerContext; 13 | 14 | public class SelectDatabase { 15 | private static final int FIELD_COUNT = 1; 16 | 17 | private static final EOFPacket EOF = new EOFPacket(); 18 | 19 | private static final FieldPacket[] FIELDS = new FieldPacket[FIELD_COUNT]; 20 | 21 | private static final ResultSetHeaderPacket HEADER = PacketUtil.getHeader(FIELD_COUNT); 22 | 23 | static { 24 | int i = 0; 25 | byte packetId = 0; 26 | HEADER.packetId = ++packetId; 27 | FIELDS[i] = PacketUtil.getField("DATABASE()", Fields.FIELD_TYPE_VAR_STRING); 28 | FIELDS[i++].packetId = ++packetId; 29 | EOF.packetId = ++packetId; 30 | } 31 | 32 | public static void response(Context c) { 33 | ChannelHandlerContext ctx = c.getChannelHandlerContext(); 34 | ByteBuf buffer = ctx.alloc().buffer(); 35 | buffer = HEADER.writeBuf(buffer, ctx); 36 | for (FieldPacket field : FIELDS) { 37 | buffer = field.writeBuf(buffer, ctx); 38 | } 39 | buffer = EOF.writeBuf(buffer, ctx); 40 | byte packetId = EOF.packetId; 41 | RowDataPacket row = new RowDataPacket(FIELD_COUNT); 42 | row.add(StringUtil.encode("hulk", c.getCharset())); 43 | row.packetId = ++packetId; 44 | buffer = row.writeBuf(buffer, ctx); 45 | EOFPacket lastEof = new EOFPacket(); 46 | lastEof.packetId = ++packetId; 47 | buffer = lastEof.writeBuf(buffer, ctx); 48 | ctx.writeAndFlush(buffer); 49 | } 50 | } -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/transaction/Transaction.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.transaction; 2 | 3 | import cn.hutool.core.collection.CollUtil; 4 | import com.google.common.collect.Lists; 5 | 6 | import java.util.List; 7 | 8 | public class Transaction { 9 | 10 | private static ThreadLocal transactionContext = new InheritableThreadLocal<>(); 11 | 12 | private static ThreadLocal> managerList = new InheritableThreadLocal<>(); 13 | 14 | public static void openTransaction() { 15 | transactionContext.set(true); 16 | } 17 | 18 | public static void commit() { 19 | List transactionManagers = managerList.get(); 20 | if (CollUtil.isNotEmpty(transactionManagers)) { 21 | for (TransactionManager transactionManager : transactionManagers) { 22 | transactionManager.commit(); 23 | } 24 | } 25 | } 26 | 27 | public static void rollback() { 28 | List transactionManagers = managerList.get(); 29 | if (CollUtil.isNotEmpty(transactionManagers)) { 30 | for (TransactionManager transactionManager : transactionManagers) { 31 | transactionManager.rollback(); 32 | } 33 | } 34 | } 35 | 36 | public static void close() { 37 | List transactionManagers = managerList.get(); 38 | if (CollUtil.isNotEmpty(transactionManagers)) { 39 | for (TransactionManager transactionManager : transactionManagers) { 40 | transactionManager.close(); 41 | } 42 | } 43 | 44 | transactionContext.remove(); 45 | managerList.remove(); 46 | } 47 | 48 | static Boolean get() { 49 | return transactionContext.get(); 50 | } 51 | 52 | static synchronized void add(TransactionManager transactionManager) { 53 | List transactionManagers = managerList.get(); 54 | if (transactionManagers == null) { 55 | managerList.set(Lists.newArrayList()); 56 | } 57 | 58 | managerList.get().add(transactionManager); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/connection/Neo4jConnection.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.connection; 2 | 3 | import com.jimmy.hulk.data.annotation.ConnectionType; 4 | import com.jimmy.hulk.data.annotation.DS; 5 | import com.jimmy.hulk.data.base.Connection; 6 | import com.jimmy.hulk.data.condition.Neo4jCondition; 7 | import com.jimmy.hulk.data.other.ConnectionContext; 8 | import lombok.extern.slf4j.Slf4j; 9 | import org.neo4j.driver.Driver; 10 | import org.neo4j.driver.Session; 11 | import org.neo4j.driver.Transaction; 12 | 13 | import java.util.List; 14 | 15 | import static com.jimmy.hulk.common.enums.DatasourceEnum.NEO4J; 16 | 17 | @Slf4j 18 | @ConnectionType(dsType = {@DS(type = NEO4J, condition = Neo4jCondition.class)}) 19 | public class Neo4jConnection implements Connection { 20 | 21 | private Driver driver; 22 | 23 | private Session session; 24 | 25 | private Transaction transaction; 26 | 27 | @Override 28 | public synchronized Transaction getConnection() { 29 | if (session == null && transaction == null) { 30 | session = driver.session(); 31 | transaction = session.beginTransaction(); 32 | } 33 | 34 | return transaction; 35 | } 36 | 37 | @Override 38 | public void setContext(ConnectionContext context) { 39 | 40 | } 41 | 42 | @Override 43 | public void commit() { 44 | transaction.commit(); 45 | } 46 | 47 | @Override 48 | public void rollback() { 49 | transaction.rollback(); 50 | } 51 | 52 | @Override 53 | public void setSource(Driver driver) { 54 | this.driver = driver; 55 | } 56 | 57 | @Override 58 | public void close() { 59 | transaction.close(); 60 | session.close(); 61 | } 62 | 63 | @Override 64 | public void batchExecute(List sql) throws Exception { 65 | for (String s : sql) { 66 | this.execute(s); 67 | } 68 | } 69 | 70 | @Override 71 | public int execute(String sql) throws Exception { 72 | log.debug("执行neo4j :{}", sql); 73 | 74 | this.getConnection().run(sql); 75 | return 1; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/datasource/BaseDatasource.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.datasource; 2 | 3 | import com.google.common.collect.Maps; 4 | import com.jimmy.hulk.common.enums.DatasourceEnum; 5 | import com.jimmy.hulk.common.enums.FieldTypeEnum; 6 | import com.jimmy.hulk.common.enums.ModuleEnum; 7 | import com.jimmy.hulk.common.exception.HulkException; 8 | import com.jimmy.hulk.data.base.Connection; 9 | import com.jimmy.hulk.data.base.DataSource; 10 | import com.jimmy.hulk.data.base.FieldMapper; 11 | import com.jimmy.hulk.data.config.DataProperties; 12 | import com.jimmy.hulk.data.config.DataSourceProperty; 13 | import com.jimmy.hulk.data.other.ConnectionContext; 14 | import lombok.Getter; 15 | import lombok.Setter; 16 | 17 | import java.util.Map; 18 | 19 | public abstract class BaseDatasource implements DataSource { 20 | 21 | protected static final int MAX_COUNT = 1000; 22 | 23 | protected static final String DEFAULT_DELIMITER = ";"; 24 | 25 | @Setter 26 | @Getter 27 | protected DataSourceProperty dataSourceProperty; 28 | 29 | @Getter 30 | private Map fieldTypeMapper = Maps.newHashMap(); 31 | 32 | @Setter 33 | private Map> connectionClassMap = Maps.newHashMap(); 34 | 35 | public void addMapper(FieldTypeEnum fieldType, FieldMapper mapperType) { 36 | fieldTypeMapper.put(fieldType, mapperType); 37 | } 38 | 39 | @Override 40 | public void init(DataProperties dataProperties) { 41 | 42 | } 43 | 44 | @Override 45 | public Connection getConnection(ConnectionContext context) { 46 | try { 47 | Class clazz = connectionClassMap.get(this.type()); 48 | if (clazz == null) { 49 | throw new HulkException("数据源类型连接未加载", ModuleEnum.DATA); 50 | } 51 | 52 | Connection connection = clazz.newInstance(); 53 | connection.setContext(context); 54 | connection.setSource(this.getDataSource()); 55 | return connection; 56 | } catch (Exception e) { 57 | throw new HulkException(e.getMessage(), ModuleEnum.DATA); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/utils/ClickHouseUtil.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.utils; 2 | 3 | import cn.hutool.core.collection.CollUtil; 4 | import cn.hutool.core.map.MapUtil; 5 | import com.alibaba.fastjson.JSON; 6 | import com.google.common.collect.Lists; 7 | import com.google.common.collect.Maps; 8 | import com.jimmy.hulk.common.enums.ModuleEnum; 9 | import com.jimmy.hulk.common.exception.HulkException; 10 | import ru.yandex.clickhouse.ClickHouseArray; 11 | 12 | import java.util.List; 13 | import java.util.Map; 14 | 15 | public class ClickHouseUtil { 16 | 17 | private ClickHouseUtil() { 18 | 19 | } 20 | 21 | public static List> resultMapper(List> targetDatas) { 22 | if (CollUtil.isEmpty(targetDatas)) { 23 | return Lists.newArrayList(); 24 | } 25 | 26 | List> result = Lists.newArrayList(); 27 | for (Map targetData : targetDatas) { 28 | Map objectMap = resultMapper(targetData); 29 | if (MapUtil.isNotEmpty(objectMap)) { 30 | result.add(objectMap); 31 | } 32 | } 33 | 34 | return result; 35 | } 36 | 37 | public static Map resultMapper(Map targetData) { 38 | try { 39 | if (MapUtil.isEmpty(targetData)) { 40 | return null; 41 | } 42 | 43 | Map result = Maps.newHashMap(); 44 | for (Map.Entry entry : targetData.entrySet()) { 45 | String mapKey = entry.getKey(); 46 | Object mapValue = entry.getValue(); 47 | 48 | if (mapValue instanceof ClickHouseArray) { 49 | ClickHouseArray array = (ClickHouseArray) mapValue; 50 | result.put(mapKey, JSON.toJSONString(array.getArray())); 51 | continue; 52 | } 53 | 54 | result.put(mapKey, mapValue); 55 | } 56 | 57 | return result; 58 | } catch (Exception e) { 59 | throw new HulkException(e.getMessage(), ModuleEnum.DATA); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /booster/src/main/java/com/jimmy/hulk/booster/core/SystemVariable.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.booster.core; 2 | 3 | import cn.hutool.core.util.StrUtil; 4 | import com.google.common.collect.Maps; 5 | import org.springframework.stereotype.Component; 6 | 7 | import java.util.Map; 8 | 9 | @Component 10 | public class SystemVariable { 11 | 12 | private final Map variable = Maps.newHashMap(); 13 | 14 | private final Map sessionVariable = Maps.newHashMap(); 15 | 16 | public SystemVariable() { 17 | variable.put("character_set_client", "utf8"); 18 | variable.put("character_set_connection", "utf8"); 19 | variable.put("character_set_results", "utf8"); 20 | variable.put("character_set_server", "utf8"); 21 | variable.put("collation_server", "utf8_general_ci"); 22 | variable.put("collation_connection", "utf8_general_ci"); 23 | variable.put("init_connect", StrUtil.EMPTY); 24 | variable.put("interactive_timeout", 28800000); 25 | variable.put("license", "GPL"); 26 | variable.put("lower_case_table_names", "1"); 27 | variable.put("max_allowed_packet", 104857600); 28 | variable.put("net_buffer_length", 8192); 29 | variable.put("net_write_timeout", 60); 30 | variable.put("query_cache_size", 0); 31 | variable.put("query_cache_type", "OFF"); 32 | variable.put("sql_mode", "STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"); 33 | variable.put("system_time_zone", "UTC"); 34 | variable.put("time_zone", "+08:00"); 35 | variable.put("transaction_isolation", "READ-COMMITTED"); 36 | variable.put("wait_timeout", 28800000); 37 | //session级别的变量 38 | sessionVariable.put("transaction_read_only", "0"); 39 | sessionVariable.put("auto_increment_increment", 1); 40 | sessionVariable.put("transaction_isolation", "READ-COMMITTED"); 41 | } 42 | 43 | public Object getVariable(String key, String from) { 44 | if ("session".equalsIgnoreCase(from)) { 45 | return this.sessionVariable.get(key); 46 | } 47 | 48 | return this.variable.get(key); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /actuator/src/main/java/com/jimmy/hulk/actuator/config/ActuatorConfig.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.actuator.config; 2 | 3 | import com.jimmy.hulk.actuator.memory.MemoryPool; 4 | import com.jimmy.hulk.actuator.part.PartSupport; 5 | import com.jimmy.hulk.actuator.part.join.InnerJoin; 6 | import com.jimmy.hulk.actuator.part.join.LeftJoin; 7 | import com.jimmy.hulk.actuator.sql.*; 8 | import com.jimmy.hulk.actuator.support.ActuatorInitialize; 9 | import org.springframework.context.annotation.Bean; 10 | import org.springframework.context.annotation.Configuration; 11 | 12 | @Configuration 13 | public class ActuatorConfig { 14 | 15 | @Bean 16 | public MemoryPool memoryPool() { 17 | return new MemoryPool(); 18 | } 19 | 20 | @Bean 21 | public PartSupport partSupport() { 22 | return new PartSupport(); 23 | } 24 | 25 | @Bean 26 | public ActuatorInitialize actuatorInitialize() { 27 | return new ActuatorInitialize(); 28 | } 29 | 30 | @Configuration 31 | protected class SqlConfiguration { 32 | 33 | @Bean 34 | public Select select() { 35 | return new Select(); 36 | } 37 | 38 | @Bean 39 | public Update update() { 40 | return new Update(); 41 | } 42 | 43 | @Bean 44 | public Insert insert() { 45 | return new Insert(); 46 | } 47 | 48 | @Bean 49 | public Delete delete() { 50 | return new Delete(); 51 | } 52 | 53 | @Bean 54 | public Flush flush() { 55 | return new Flush(); 56 | } 57 | 58 | @Bean 59 | public Job job() { 60 | return new Job(); 61 | } 62 | 63 | @Bean 64 | public Native aNative() { 65 | return new Native(); 66 | } 67 | 68 | @Bean 69 | public Cache cache() { 70 | return new Cache(); 71 | } 72 | } 73 | 74 | @Configuration 75 | protected class JoinConfiguration { 76 | 77 | @Bean 78 | public InnerJoin innerJoin() { 79 | return new InnerJoin(); 80 | } 81 | 82 | @Bean 83 | public LeftJoin leftJoin() { 84 | return new LeftJoin(); 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/core/QueryPlus.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.core; 2 | 3 | import cn.hutool.core.util.ArrayUtil; 4 | import com.google.common.collect.Lists; 5 | import com.google.common.collect.Sets; 6 | import com.jimmy.hulk.common.enums.ConditionTypeEnum; 7 | import lombok.Data; 8 | 9 | import java.io.Serializable; 10 | import java.util.List; 11 | import java.util.Set; 12 | 13 | @Data 14 | public class QueryPlus implements Serializable { 15 | 16 | private List conditions = Lists.newArrayList(); 17 | 18 | private List conditionGroups = Lists.newArrayList(); 19 | 20 | private List orders = Lists.newArrayList(); 21 | 22 | private Set select = Sets.newHashSet(); 23 | 24 | private List groupBy = Lists.newArrayList(); 25 | 26 | private List aggregateFunctions = Lists.newArrayList(); 27 | 28 | protected QueryPlus() { 29 | 30 | } 31 | 32 | QueryPlus addGroup(ConditionTypeEnum conditionTypeEnum, List conditions) { 33 | ConditionGroup conditionGroup = new ConditionGroup(); 34 | conditionGroup.setConditions(conditions); 35 | conditionGroup.setConditionTypeEnum(conditionTypeEnum); 36 | conditionGroups.add(conditionGroup); 37 | return this; 38 | } 39 | 40 | QueryPlus addAggregateFunction(AggregateFunction aggregateFunction) { 41 | this.aggregateFunctions.add(aggregateFunction); 42 | return this; 43 | } 44 | 45 | QueryPlus add(Condition condition) { 46 | conditions.add(condition); 47 | return this; 48 | } 49 | 50 | QueryPlus addOrder(Order order) { 51 | orders.add(order); 52 | return this; 53 | } 54 | 55 | QueryPlus select(String... columns) { 56 | if (ArrayUtil.isNotEmpty(columns)) { 57 | for (String column : columns) { 58 | select.add(column); 59 | } 60 | } 61 | 62 | return this; 63 | } 64 | 65 | QueryPlus groupBy(String... columns) { 66 | if (ArrayUtil.isNotEmpty(columns)) { 67 | for (String column : columns) { 68 | groupBy.add(column); 69 | } 70 | } 71 | 72 | return this; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /booster/src/main/java/com/jimmy/hulk/booster/support/DatabaseServer.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.booster.support; 2 | 3 | import com.jimmy.hulk.authority.base.AuthenticationManager; 4 | import com.jimmy.hulk.booster.handler.HandlerInitializer; 5 | import io.netty.bootstrap.ServerBootstrap; 6 | import io.netty.buffer.PooledByteBufAllocator; 7 | import io.netty.channel.ChannelFuture; 8 | import io.netty.channel.ChannelOption; 9 | import io.netty.channel.EventLoopGroup; 10 | import io.netty.channel.nio.NioEventLoopGroup; 11 | import io.netty.channel.socket.nio.NioServerSocketChannel; 12 | import lombok.extern.slf4j.Slf4j; 13 | 14 | @Slf4j 15 | public class DatabaseServer { 16 | 17 | private final static int SO_TIMEOUT = 10 * 60; 18 | 19 | private final static int CONNECT_TIMEOUT_MILLIS = 5000; 20 | 21 | private Integer port; 22 | 23 | private SessionPool sessionPool; 24 | 25 | private AuthenticationManager authenticationManager; 26 | 27 | public DatabaseServer(Integer port, SessionPool sessionPool, AuthenticationManager authenticationManager) { 28 | this.port = port; 29 | this.sessionPool = sessionPool; 30 | this.authenticationManager = authenticationManager; 31 | } 32 | 33 | public void startServer() { 34 | EventLoopGroup workerGroup = new NioEventLoopGroup(); 35 | EventLoopGroup bossGroup = new NioEventLoopGroup(1); 36 | try { 37 | ServerBootstrap b = new ServerBootstrap(); 38 | // 这边的childHandler是用来管理accept的 39 | // 由于线程间传递的是byte[],所以内存池okay 40 | // 只需要保证分配ByteBuf和write在同一个线程(函数)就行了 41 | b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class) 42 | .option(ChannelOption.SO_BACKLOG, 1024) 43 | .childHandler(new HandlerInitializer(sessionPool, authenticationManager)).option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT) 44 | .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, CONNECT_TIMEOUT_MILLIS) 45 | .option(ChannelOption.SO_TIMEOUT, SO_TIMEOUT); 46 | ChannelFuture f = b.bind(port).sync(); 47 | f.channel().closeFuture().sync(); 48 | } catch (InterruptedException e) { 49 | log.error("监听失败", e); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /data/src/main/java/com/jimmy/hulk/data/data/TransactionData.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.data.data; 2 | 3 | import cn.hutool.core.collection.CollUtil; 4 | import com.jimmy.hulk.common.enums.DatasourceEnum; 5 | import com.jimmy.hulk.common.enums.ModuleEnum; 6 | import com.jimmy.hulk.common.exception.HulkException; 7 | import com.jimmy.hulk.data.other.ConnectionContext; 8 | import com.jimmy.hulk.data.transaction.TransactionManager; 9 | import lombok.extern.slf4j.Slf4j; 10 | import org.springframework.jdbc.core.JdbcTemplate; 11 | 12 | import javax.sql.DataSource; 13 | import java.util.List; 14 | import java.util.Map; 15 | 16 | 17 | @Slf4j 18 | public abstract class TransactionData extends BaseData { 19 | 20 | protected TransactionManager transactionManager; 21 | 22 | protected JdbcTemplate jdbcTemplate; 23 | 24 | @Override 25 | public void datasourceInit() { 26 | if (this.isNeedReturnPriKeyValue && !this.type().equals(DatasourceEnum.MYSQL)) { 27 | throw new HulkException("非MYSQL数据库不允许返回主键值"); 28 | } 29 | 30 | this.init(); 31 | 32 | ConnectionContext context = new ConnectionContext(); 33 | if (this.isNeedReturnPriKeyValue) { 34 | context.put(this.indexName, this.priKeyName); 35 | } 36 | 37 | DataSource dataSource = (DataSource) super.dataSource.getDataSource(); 38 | transactionManager = new TransactionManager(super.dataSource, context); 39 | 40 | jdbcTemplate = new JdbcTemplate(dataSource); 41 | } 42 | 43 | protected void init() { 44 | this.indexName = schema + "." + indexName; 45 | } 46 | 47 | protected List> queryList(String sql, List param) { 48 | try { 49 | return jdbcTemplate.queryForList(sql, CollUtil.isEmpty(param) ? null : param.toArray()); 50 | } catch (Exception e) { 51 | throw new HulkException(e.getMessage(), ModuleEnum.DATA); 52 | } 53 | } 54 | 55 | protected Map queryOne(String sql, List param) { 56 | try { 57 | List> maps = this.queryList(sql, param); 58 | return CollUtil.isNotEmpty(maps) ? maps.get(0) : null; 59 | } catch (Exception e) { 60 | throw new HulkException(e.getMessage(), ModuleEnum.DATA); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /protocol/src/main/java/com/jimmy/hulk/protocol/packages/PreparedOkPacket.java: -------------------------------------------------------------------------------- 1 | package com.jimmy.hulk.protocol.packages; 2 | 3 | import com.jimmy.hulk.protocol.utils.BufferUtil; 4 | import io.netty.buffer.ByteBuf; 5 | import io.netty.channel.ChannelHandlerContext; 6 | 7 | public class PreparedOkPacket extends MySQLPacket { 8 | 9 | public byte status; 10 | public long statementId; 11 | public int columnsNumber; 12 | public int parametersNumber; 13 | public byte filler; 14 | public int warningCount; 15 | 16 | public PreparedOkPacket() { 17 | this.status = 0; 18 | this.filler = 0; 19 | } 20 | 21 | @Override 22 | public void write(ChannelHandlerContext ctx) { 23 | ByteBuf buffer = ctx.alloc().buffer(); 24 | 25 | int size = calcPacketSize(); 26 | BufferUtil.writeUB3(buffer, size); 27 | buffer.writeByte(packetId); 28 | buffer.writeByte(status); 29 | BufferUtil.writeUB4(buffer, statementId); 30 | BufferUtil.writeUB2(buffer, columnsNumber); 31 | BufferUtil.writeUB2(buffer, parametersNumber); 32 | buffer.writeByte(filler); 33 | BufferUtil.writeUB2(buffer, warningCount); 34 | 35 | if (parametersNumber > 0) { 36 | for (int i = 0; i < parametersNumber; i++) { 37 | FieldPacket field = new FieldPacket(); 38 | field.packetId = ++packetId; 39 | buffer = field.writeBuf(buffer, ctx); 40 | } 41 | 42 | EOFPacket eof = new EOFPacket(); 43 | eof.packetId = ++packetId; 44 | buffer = eof.writeBuf(buffer, ctx); 45 | } 46 | 47 | if (columnsNumber > 0) { 48 | for (int i = 0; i < columnsNumber; i++) { 49 | FieldPacket field = new FieldPacket(); 50 | field.packetId = ++packetId; 51 | buffer = field.writeBuf(buffer, ctx); 52 | } 53 | EOFPacket eof = new EOFPacket(); 54 | eof.packetId = ++packetId; 55 | buffer = eof.writeBuf(buffer, ctx); 56 | } 57 | 58 | ctx.writeAndFlush(buffer); 59 | } 60 | 61 | @Override 62 | public int calcPacketSize() { 63 | return 12; 64 | } 65 | 66 | @Override 67 | protected String getPacketInfo() { 68 | return "MySQL PreparedOk Packet"; 69 | } 70 | 71 | } --------------------------------------------------------------------------------