Commit 7b5aa23d5cdc55779ff3048d6cc2e04e82b24b3e
1 parent
ea8dd67e
【功能优化】 产品发布创建超级表优化
Showing
13 changed files
with
486 additions
and
366 deletions
yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/FieldsVo.java
| 1 | 1 | package cn.iocoder.yudao.module.iot.domain; |
| 2 | 2 | |
| 3 | +import lombok.Builder; | |
| 3 | 4 | import lombok.Data; |
| 4 | 5 | |
| 5 | 6 | import java.sql.SQLException; |
| 6 | 7 | import java.util.ArrayList; |
| 7 | 8 | import java.util.List; |
| 8 | 9 | |
| 10 | +/** | |
| 11 | + * 字段信息 VO | |
| 12 | + */ | |
| 9 | 13 | @Data |
| 14 | +@Builder | |
| 10 | 15 | public class FieldsVo { |
| 11 | - private static final long serialVersionUID = 1L; | |
| 12 | 16 | |
| 13 | 17 | /** |
| 14 | 18 | * 字段名称 |
| ... | ... | @@ -24,24 +28,4 @@ public class FieldsVo { |
| 24 | 28 | * 字段字节大小 |
| 25 | 29 | */ |
| 26 | 30 | private Integer size; |
| 27 | - | |
| 28 | - public static FieldsVo fieldsTranscoding(Fields fields) throws SQLException { | |
| 29 | -// if (StringUtils.isBlank(fields.getFieldName()) || fields.getDataType() == null) { | |
| 30 | -// throw new SQLException("invalid operation: fieldName or dataType can not be null"); | |
| 31 | -// } | |
| 32 | -// FieldsVo fieldsVo = new FieldsVo(); | |
| 33 | -// fieldsVo.setFieldName(fields.getFieldName()); | |
| 34 | -// fieldsVo.setDataType(fields.getDataType().getDataType()); | |
| 35 | -// fieldsVo.setSize(fields.getSize()); | |
| 36 | -// return fieldsVo; | |
| 37 | - return null; | |
| 38 | - } | |
| 39 | - | |
| 40 | - public static List<FieldsVo> fieldsTranscoding(List<Fields> fieldsList) throws SQLException { | |
| 41 | - List<FieldsVo> fieldsVoList = new ArrayList<>(); | |
| 42 | - for (Fields fields : fieldsList) { | |
| 43 | - fieldsVoList.add(fieldsTranscoding(fields)); | |
| 44 | - } | |
| 45 | - return fieldsVoList; | |
| 46 | - } | |
| 47 | 31 | } | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/FieldParser.java
| ... | ... | @@ -10,7 +10,6 @@ import java.util.stream.Collectors; |
| 10 | 10 | |
| 11 | 11 | /** |
| 12 | 12 | * FieldParser 类用于解析和转换物模型字段到 TDengine 字段 |
| 13 | - * | |
| 14 | 13 | */ |
| 15 | 14 | public class FieldParser { |
| 16 | 15 | |
| ... | ... | @@ -35,49 +34,58 @@ public class FieldParser { |
| 35 | 34 | * @param property 物模型属性 |
| 36 | 35 | * @return TdField对象 |
| 37 | 36 | */ |
| 38 | - public static TdField parse(ThingModelProperty property) { | |
| 37 | + public static TdFieldDO parse(ThingModelProperty property) { | |
| 39 | 38 | String fieldName = property.getIdentifier().toLowerCase(); |
| 40 | 39 | ThingModelDataType type = property.getDataType(); |
| 41 | 40 | |
| 42 | 41 | // 将物模型字段类型映射为td字段类型 |
| 43 | 42 | String fType = TYPE_MAPPING.get(type.getType().toUpperCase()); |
| 44 | 43 | |
| 45 | - int len = -1; | |
| 46 | 44 | // 如果字段类型为NCHAR,默认长度为64 |
| 45 | + int dataLength = 0; | |
| 47 | 46 | if ("NCHAR".equals(fType)) { |
| 48 | - len = 64; | |
| 47 | + dataLength = 64; | |
| 49 | 48 | } |
| 50 | - | |
| 51 | - return new TdField(fieldName, fType, len); | |
| 49 | + return new TdFieldDO(fieldName, fType, dataLength); | |
| 52 | 50 | } |
| 53 | 51 | |
| 54 | 52 | /** |
| 55 | - * 获取物模型中的字段列表 | |
| 53 | + * 从物模型中获取字段列表 | |
| 54 | + * | |
| 55 | + * @param thingModel 物模型响应对象 | |
| 56 | + * @return 字段列表 | |
| 56 | 57 | */ |
| 57 | - public static List<TdField> parse(ThingModelRespVO thingModel) { | |
| 58 | - return thingModel.getModel().getProperties().stream().map(FieldParser::parse).collect(Collectors.toList()); | |
| 58 | + public static List<TdFieldDO> parse(ThingModelRespVO thingModel) { | |
| 59 | + return thingModel.getModel().getProperties().stream() | |
| 60 | + .map(FieldParser::parse) | |
| 61 | + .collect(Collectors.toList()); | |
| 59 | 62 | } |
| 60 | 63 | |
| 61 | 64 | /** |
| 62 | - * 将从库中查出来的字段信息转换为td字段对象 | |
| 65 | + * 将从库中查出来的字段信息转换为 TDengine 字段对象 | |
| 66 | + * | |
| 67 | + * @param rows 从库中查出的字段信息列表 | |
| 68 | + * @return 转换后的 TDengine 字段对象列表 | |
| 63 | 69 | */ |
| 64 | - public static List<TdField> parse(List<List<Object>> rows) { | |
| 70 | + public static List<TdFieldDO> parse(List<List<Object>> rows) { | |
| 65 | 71 | return rows.stream().map(row -> { |
| 66 | 72 | String type = row.get(1).toString().toUpperCase(); |
| 67 | - return new TdField( | |
| 73 | + int dataLength = "NCHAR".equals(type) ? Integer.parseInt(row.get(2).toString()) : -1; | |
| 74 | + return new TdFieldDO( | |
| 68 | 75 | row.get(0).toString(), |
| 69 | 76 | type, |
| 70 | - type.equals("NCHAR") ? Integer.parseInt(row.get(2).toString()) : -1); | |
| 77 | + dataLength | |
| 78 | + ); | |
| 71 | 79 | }).collect(Collectors.toList()); |
| 72 | 80 | } |
| 73 | 81 | |
| 74 | 82 | /** |
| 75 | 83 | * 获取字段字义 |
| 76 | 84 | */ |
| 77 | - public static String getFieldDefine(TdField field) { | |
| 78 | - return "`" + field.getName() + "`" + " " | |
| 79 | - + (field.getLength() > 0 ? String.format("%s(%d)", field.getType(), field.getLength()) | |
| 80 | - : field.getType()); | |
| 85 | + public static String getFieldDefine(TdFieldDO field) { | |
| 86 | + return "`" + field.getFieldName() + "`" + " " | |
| 87 | + + (field.getDataLength() > 0 ? String.format("%s(%d)", field.getDataType(), field.getDataLength()) | |
| 88 | + : field.getDataType()); | |
| 81 | 89 | } |
| 82 | 90 | |
| 83 | 91 | -} |
| 92 | +} | |
| 84 | 93 | \ No newline at end of file | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableData.java
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableManager.java
| ... | ... | @@ -45,7 +45,7 @@ public class TableManager { |
| 45 | 45 | /** |
| 46 | 46 | * 获取创建表sql |
| 47 | 47 | */ |
| 48 | - public static String getCreateSTableSql(String tbName, List<TdField> fields, TdField... tags) { | |
| 48 | + public static String getCreateSTableSql(String tbName, List<TdFieldDO> fields, TdFieldDO... tags) { | |
| 49 | 49 | if (fields.isEmpty()) { |
| 50 | 50 | return null; |
| 51 | 51 | } |
| ... | ... | @@ -53,7 +53,7 @@ public class TableManager { |
| 53 | 53 | // 生成字段片段 |
| 54 | 54 | StringBuilder sbField = new StringBuilder("time TIMESTAMP,"); |
| 55 | 55 | |
| 56 | - for (TdField field : fields) { | |
| 56 | + for (TdFieldDO field : fields) { | |
| 57 | 57 | sbField.append(FieldParser.getFieldDefine(field)); |
| 58 | 58 | sbField.append(","); |
| 59 | 59 | } |
| ... | ... | @@ -63,7 +63,7 @@ public class TableManager { |
| 63 | 63 | |
| 64 | 64 | // 生成tag |
| 65 | 65 | StringBuilder sbTag = new StringBuilder(); |
| 66 | - for (TdField tag : tags) { | |
| 66 | + for (TdFieldDO tag : tags) { | |
| 67 | 67 | sbTag.append(FieldParser.getFieldDefine(tag)) |
| 68 | 68 | .append(","); |
| 69 | 69 | } |
| ... | ... | @@ -76,7 +76,7 @@ public class TableManager { |
| 76 | 76 | /** |
| 77 | 77 | * 获取创建普通表sql |
| 78 | 78 | */ |
| 79 | - public static String getCreateCTableSql(String tbName, List<TdField> fields) { | |
| 79 | + public static String getCreateCTableSql(String tbName, List<TdFieldDO> fields) { | |
| 80 | 80 | if (fields.size() == 0) { |
| 81 | 81 | return null; |
| 82 | 82 | } |
| ... | ... | @@ -84,7 +84,7 @@ public class TableManager { |
| 84 | 84 | //生成字段片段 |
| 85 | 85 | StringBuilder sbField = new StringBuilder("time timestamp,"); |
| 86 | 86 | |
| 87 | - for (TdField field : fields) { | |
| 87 | + for (TdFieldDO field : fields) { | |
| 88 | 88 | sbField.append(FieldParser.getFieldDefine(field)); |
| 89 | 89 | sbField.append(","); |
| 90 | 90 | } |
| ... | ... | @@ -116,9 +116,9 @@ public class TableManager { |
| 116 | 116 | /** |
| 117 | 117 | * 获取添加字段sql |
| 118 | 118 | */ |
| 119 | - public static String getAddSTableColumnSql(String tbName, List<TdField> fields) { | |
| 119 | + public static String getAddSTableColumnSql(String tbName, List<TdFieldDO> fields) { | |
| 120 | 120 | StringBuilder sbAdd = new StringBuilder(); |
| 121 | - for (TdField field : fields) { | |
| 121 | + for (TdFieldDO field : fields) { | |
| 122 | 122 | sbAdd.append(String.format(ALTER_STABLE_ADD_COL_TPL, |
| 123 | 123 | tbName, |
| 124 | 124 | FieldParser.getFieldDefine(field) |
| ... | ... | @@ -130,9 +130,9 @@ public class TableManager { |
| 130 | 130 | /** |
| 131 | 131 | * 获取修改字段sql |
| 132 | 132 | */ |
| 133 | - public static String getModifySTableColumnSql(String tbName, List<TdField> fields) { | |
| 133 | + public static String getModifySTableColumnSql(String tbName, List<TdFieldDO> fields) { | |
| 134 | 134 | StringBuilder sbModify = new StringBuilder(); |
| 135 | - for (TdField field : fields) { | |
| 135 | + for (TdFieldDO field : fields) { | |
| 136 | 136 | sbModify.append(String.format(ALTER_STABLE_MODIFY_COL_TPL, |
| 137 | 137 | tbName, |
| 138 | 138 | FieldParser.getFieldDefine(field) |
| ... | ... | @@ -144,15 +144,15 @@ public class TableManager { |
| 144 | 144 | /** |
| 145 | 145 | * 获取删除字段sql |
| 146 | 146 | */ |
| 147 | - public static String getDropSTableColumnSql(String tbName, List<TdField> fields) { | |
| 147 | + public static String getDropSTableColumnSql(String tbName, List<TdFieldDO> fields) { | |
| 148 | 148 | StringBuilder sbDrop = new StringBuilder(); |
| 149 | - for (TdField field : fields) { | |
| 149 | + for (TdFieldDO field : fields) { | |
| 150 | 150 | sbDrop.append(String.format(ALTER_STABLE_DROP_COL_TPL, |
| 151 | 151 | tbName, |
| 152 | - field.getName() | |
| 152 | + field.getFieldName() | |
| 153 | 153 | )); |
| 154 | 154 | } |
| 155 | 155 | return sbDrop.toString(); |
| 156 | 156 | } |
| 157 | 157 | |
| 158 | 158 | -} |
| 159 | +} | |
| 159 | 160 | \ No newline at end of file | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdField.java renamed to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdFieldDO.java
| 1 | 1 | package cn.iocoder.yudao.module.iot.dal.dataobject.tdengine; |
| 2 | 2 | |
| 3 | 3 | import lombok.AllArgsConstructor; |
| 4 | +import lombok.Builder; | |
| 4 | 5 | import lombok.Data; |
| 5 | 6 | import lombok.NoArgsConstructor; |
| 6 | 7 | |
| ... | ... | @@ -10,20 +11,21 @@ import lombok.NoArgsConstructor; |
| 10 | 11 | @Data |
| 11 | 12 | @NoArgsConstructor |
| 12 | 13 | @AllArgsConstructor |
| 13 | -public class TdField { | |
| 14 | +@Builder | |
| 15 | +public class TdFieldDO { | |
| 14 | 16 | |
| 15 | 17 | /** |
| 16 | 18 | * 字段名称 |
| 17 | 19 | */ |
| 18 | - private String name; | |
| 20 | + private String fieldName; | |
| 19 | 21 | |
| 20 | 22 | /** |
| 21 | 23 | * 字段类型 |
| 22 | 24 | */ |
| 23 | - private String type; | |
| 25 | + private String dataType; | |
| 24 | 26 | |
| 25 | 27 | /** |
| 26 | 28 | * 字段长度 |
| 27 | 29 | */ |
| 28 | - private int length; | |
| 30 | + private Integer dataLength = 0; | |
| 29 | 31 | } |
| 30 | 32 | \ No newline at end of file | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdResponse.java
| ... | ... | @@ -17,13 +17,25 @@ public class TdResponse { |
| 17 | 17 | public static final int CODE_SUCCESS = 0; |
| 18 | 18 | public static final int CODE_TB_NOT_EXIST = 866; |
| 19 | 19 | |
| 20 | + /** | |
| 21 | + * 状态 | |
| 22 | + */ | |
| 20 | 23 | private String status; |
| 21 | 24 | |
| 25 | + /** | |
| 26 | + * 错误码 | |
| 27 | + */ | |
| 22 | 28 | private int code; |
| 23 | 29 | |
| 30 | + /** | |
| 31 | + * 错误信息 | |
| 32 | + */ | |
| 24 | 33 | private String desc; |
| 25 | 34 | |
| 26 | - //[["time","TIMESTAMP",8,""],["powerstate","TINYINT",1,""],["brightness","INT",4,""],["deviceid","NCHAR",32,"TAG"]] | |
| 27 | - private List<Object[]> data; | |
| 35 | + /** | |
| 36 | + * 列信息 | |
| 37 | + * [["time","TIMESTAMP",8,""],["powerstate","TINYINT",1,""],["brightness","INT",4,""],["deviceid","NCHAR",32,"TAG"]] | |
| 38 | + */ | |
| 39 | + private List data; | |
| 28 | 40 | |
| 29 | 41 | -} |
| 42 | +} | |
| 30 | 43 | \ No newline at end of file | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdRestApi.java
| ... | ... | @@ -14,23 +14,23 @@ import org.springframework.stereotype.Service; |
| 14 | 14 | @Service |
| 15 | 15 | public class TdRestApi { |
| 16 | 16 | |
| 17 | - @Value("${spring.datasource.dynamic.datasource.master.url}") | |
| 17 | + @Value("${spring.datasource.dynamic.datasource.tdengine.url}") | |
| 18 | 18 | private String url; |
| 19 | 19 | |
| 20 | - @Value("${spring.datasource.dynamic.datasource.master.username}") | |
| 20 | + @Value("${spring.datasource.dynamic.datasource.tdengine.username}") | |
| 21 | 21 | private String username; |
| 22 | 22 | |
| 23 | - @Value("${spring.datasource.dynamic.datasource.master.password}") | |
| 23 | + @Value("${spring.datasource.dynamic.datasource.tdengine.password}") | |
| 24 | 24 | private String password; |
| 25 | 25 | |
| 26 | + /** | |
| 27 | + * 获取 REST API URL | |
| 28 | + */ | |
| 26 | 29 | private String getRestApiUrl() { |
| 27 | - //jdbc:TAOS-RS://127.0.0.1:6041/iotkit?xxxx | |
| 28 | - String restUrl = url.replace("jdbc:TAOS-RS://" , "") | |
| 29 | - .replaceAll("\\?.*" , ""); | |
| 30 | - // /rest/sql/iotkit | |
| 30 | + String restUrl = url.replace("jdbc:TAOS-RS://", "") | |
| 31 | + .replaceAll("\\?.*", ""); | |
| 31 | 32 | int idx = restUrl.lastIndexOf("/"); |
| 32 | - //127.0.0.1:6041/rest/sql/iotkit | |
| 33 | - return String.format("%s/rest/sql/%s" , restUrl.substring(0, idx), restUrl.substring(idx + 1)); | |
| 33 | + return String.format("%s/rest/sql/%s", restUrl.substring(0, idx), restUrl.substring(idx + 1)); | |
| 34 | 34 | } |
| 35 | 35 | |
| 36 | 36 | |
| ... | ... | @@ -48,11 +48,10 @@ public class TdRestApi { |
| 48 | 48 | * 执行sql |
| 49 | 49 | */ |
| 50 | 50 | public TdResponse execSql(String sql) { |
| 51 | - log.info("exec td sql:{}" , sql); | |
| 51 | + log.info("exec td sql:{}", sql); | |
| 52 | 52 | HttpRequest request = newApiRequest(sql); |
| 53 | 53 | HttpResponse response = request.execute(); |
| 54 | 54 | return JSONUtil.toBean(response.body(), TdResponse.class); |
| 55 | 55 | } |
| 56 | 56 | |
| 57 | - | |
| 58 | -} | |
| 57 | +} | |
| 59 | 58 | \ No newline at end of file | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineMapper.java
| 1 | 1 | package cn.iocoder.yudao.module.iot.dal.tdengine; |
| 2 | 2 | |
| 3 | +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO; | |
| 3 | 4 | import cn.iocoder.yudao.module.iot.domain.FieldsVo; |
| 4 | 5 | import cn.iocoder.yudao.module.iot.domain.SelectDto; |
| 5 | 6 | import cn.iocoder.yudao.module.iot.domain.TableDto; |
| ... | ... | @@ -17,24 +18,80 @@ import java.util.Map; |
| 17 | 18 | @DS("tdengine") |
| 18 | 19 | public interface TdEngineMapper { |
| 19 | 20 | |
| 21 | + /** | |
| 22 | + * 创建数据库 | |
| 23 | + * | |
| 24 | + * @param dataBaseName 数据库名称 | |
| 25 | + */ | |
| 26 | + @InterceptorIgnore(tenantLine = "true") | |
| 20 | 27 | void createDatabase(@Param("dataBaseName") String dataBaseName); |
| 21 | 28 | |
| 22 | - void createSuperTable(@Param("schemaFields") List<FieldsVo> schemaFields, | |
| 23 | - @Param("tagsFields") List<FieldsVo> tagsFields, | |
| 29 | + /** | |
| 30 | + * 创建超级表 | |
| 31 | + * | |
| 32 | + * @param schemaFields schema字段 | |
| 33 | + * @param tagsFields tags字段 | |
| 34 | + * @param dataBaseName 数据库名称 | |
| 35 | + * @param superTableName 超级表名称 | |
| 36 | + */ | |
| 37 | + @InterceptorIgnore(tenantLine = "true") | |
| 38 | + void createSuperTable(@Param("schemaFields") List<TdFieldDO> schemaFields, | |
| 39 | + @Param("tagsFields") List<TdFieldDO> tagsFields, | |
| 24 | 40 | @Param("dataBaseName") String dataBaseName, |
| 25 | 41 | @Param("superTableName") String superTableName); |
| 26 | 42 | |
| 43 | + /** | |
| 44 | + * 查看超级表 - 显示当前数据库下的所有超级表信息 | |
| 45 | + * SQL:SHOW STABLES [LIKE tb_name_wildcard]; | |
| 46 | + * | |
| 47 | + * @param dataBaseName 数据库名称 | |
| 48 | + * @param superTableName 超级表名称 | |
| 49 | + */ | |
| 50 | + @InterceptorIgnore(tenantLine = "true") | |
| 51 | + List<Map<String, Object>> showSuperTables(@Param("dataBaseName") String dataBaseName, | |
| 52 | + @Param("superTableName") String superTableName); | |
| 53 | + | |
| 54 | + /** | |
| 55 | + * 查看超级表 - 获取超级表的结构信息 | |
| 56 | + * SQL:DESCRIBE [db_name.]stb_name; | |
| 57 | + * <p> | |
| 58 | + * * @param dataBaseName 数据库名称 | |
| 59 | + * * @param superTableName 超级表名称 | |
| 60 | + */ | |
| 61 | + @InterceptorIgnore(tenantLine = "true") | |
| 62 | + List<Map<String, Object>> describeSuperTable(@Param("dataBaseName") String dataBaseName, | |
| 63 | + @Param("superTableName") String superTableName); | |
| 64 | + | |
| 65 | + /** | |
| 66 | + * 为超级表添加列 | |
| 67 | + * | |
| 68 | + * @param dataBaseName 数据库名称 | |
| 69 | + * @param superTableName 超级表名称 | |
| 70 | + * @param field 字段信息 | |
| 71 | + */ | |
| 72 | + @InterceptorIgnore(tenantLine = "true") | |
| 73 | + void addColumnForSuperTable(@Param("dataBaseName") String dataBaseName, | |
| 74 | + @Param("superTableName") String superTableName, | |
| 75 | + @Param("field") TdFieldDO field); | |
| 76 | + | |
| 77 | + /** | |
| 78 | + * 为超级表删除列 | |
| 79 | + * | |
| 80 | + * @param dataBaseName 数据库名称 | |
| 81 | + * @param superTableName 超级表名称 | |
| 82 | + * @param field 字段信息 | |
| 83 | + */ | |
| 84 | + @InterceptorIgnore(tenantLine = "true") | |
| 85 | + void dropColumnForSuperTable(@Param("dataBaseName") String dataBaseName, | |
| 86 | + @Param("superTableName") String superTableName, | |
| 87 | + @Param("field") TdFieldDO field); | |
| 88 | + | |
| 27 | 89 | void createTable(TableDto tableDto); |
| 28 | 90 | |
| 29 | 91 | void insertData(TableDto tableDto); |
| 30 | 92 | |
| 31 | 93 | List<Map<String, Object>> selectByTimestamp(SelectDto selectDto); |
| 32 | 94 | |
| 33 | - void addColumnForSuperTable(@Param("superTableName") String superTableName, | |
| 34 | - @Param("fieldsVo") FieldsVo fieldsVo); | |
| 35 | - | |
| 36 | - void dropColumnForSuperTable(@Param("superTableName") String superTableName, | |
| 37 | - @Param("fieldsVo") FieldsVo fieldsVo); | |
| 38 | 95 | |
| 39 | 96 | void addTagForSuperTable(@Param("superTableName") String superTableName, |
| 40 | 97 | @Param("fieldsVo") FieldsVo fieldsVo); |
| ... | ... | @@ -44,14 +101,6 @@ public interface TdEngineMapper { |
| 44 | 101 | |
| 45 | 102 | Map<String, Long> getCountByTimestamp(SelectDto selectDto); |
| 46 | 103 | |
| 47 | - /** | |
| 48 | - * 检查表是否存在 | |
| 49 | - * | |
| 50 | - * @param dataBaseName 数据库名称 | |
| 51 | - * @param tableName 表名称 | |
| 52 | - */ | |
| 53 | - Integer checkTableExists(@Param("dataBaseName") String dataBaseName, @Param("tableName") String tableName); | |
| 54 | - | |
| 55 | 104 | Map<String, Object> getLastData(SelectDto selectDto); |
| 56 | 105 | |
| 57 | 106 | List<Map<String, Object>> getHistoryData(SelectVisualDto selectVisualDto); |
| ... | ... | @@ -62,13 +111,5 @@ public interface TdEngineMapper { |
| 62 | 111 | |
| 63 | 112 | List<Map<String, Object>> getLastDataByTags(TagsSelectDao tagsSelectDao); |
| 64 | 113 | |
| 65 | - /** | |
| 66 | - * 创建超级表 | |
| 67 | - * | |
| 68 | - * @param sql sql | |
| 69 | - * @return 返回值 | |
| 70 | - */ | |
| 71 | - @InterceptorIgnore(tenantLine = "true") | |
| 72 | - Integer createSuperTableDevice(String sql); | |
| 73 | 114 | |
| 74 | 115 | } | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotDbStructureDataServiceImpl.java
| 1 | 1 | package cn.iocoder.yudao.module.iot.service.tdengine; |
| 2 | 2 | |
| 3 | -import cn.hutool.json.JSONUtil; | |
| 3 | +import cn.hutool.core.collection.CollUtil; | |
| 4 | 4 | import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelProperty; |
| 5 | 5 | import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelRespVO; |
| 6 | 6 | import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; |
| 7 | -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.*; | |
| 7 | +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.FieldParser; | |
| 8 | +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO; | |
| 9 | +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdRestApi; | |
| 8 | 10 | import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO; |
| 9 | -import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineMapper; | |
| 10 | 11 | import cn.iocoder.yudao.module.iot.enums.product.IotProductFunctionTypeEnum; |
| 11 | 12 | import jakarta.annotation.Resource; |
| 12 | 13 | import lombok.extern.slf4j.Slf4j; |
| 14 | +import org.springframework.beans.factory.annotation.Value; | |
| 13 | 15 | import org.springframework.stereotype.Service; |
| 14 | 16 | |
| 15 | 17 | import java.util.ArrayList; |
| 16 | 18 | import java.util.List; |
| 19 | +import java.util.Map; | |
| 17 | 20 | import java.util.Objects; |
| 18 | 21 | import java.util.stream.Collectors; |
| 19 | 22 | |
| ... | ... | @@ -22,147 +25,206 @@ import java.util.stream.Collectors; |
| 22 | 25 | public class IotDbStructureDataServiceImpl implements IotDbStructureDataService { |
| 23 | 26 | |
| 24 | 27 | @Resource |
| 25 | - private TdEngineMapper tdEngineMapper; | |
| 28 | + private TdEngineService tdEngineService; | |
| 26 | 29 | |
| 27 | 30 | @Resource |
| 28 | 31 | private TdRestApi tdRestApi; |
| 29 | 32 | |
| 33 | + @Value("${spring.datasource.dynamic.datasource.tdengine.url}") | |
| 34 | + private String url; | |
| 35 | + | |
| 30 | 36 | @Override |
| 31 | 37 | public void createSuperTable(ThingModelRespVO thingModel, Integer deviceType) { |
| 32 | - // 获取物模型中的属性定义 | |
| 33 | - List<TdField> fields = FieldParser.parse(thingModel); | |
| 34 | - String tbName = getProductPropertySTableName(deviceType, thingModel.getProductKey()); | |
| 35 | - | |
| 36 | - // 生成创建超级表的 SQL | |
| 37 | - String sql = TableManager.getCreateSTableSql(tbName, fields, new TdField("device_id", "NCHAR", 64)); | |
| 38 | - if (sql == null) { | |
| 39 | - log.warn("生成的 SQL 为空,无法创建超级表"); | |
| 40 | - return; | |
| 41 | - } | |
| 42 | - log.info("执行 SQL: {}", sql); | |
| 43 | - | |
| 44 | - // 执行 SQL 创建超级表 | |
| 45 | - tdEngineMapper.createSuperTableDevice(sql); | |
| 38 | + // 1. 解析物模型,获得字段列表 | |
| 39 | + List<TdFieldDO> schemaFields = new ArrayList<>(); | |
| 40 | + schemaFields.add(TdFieldDO.builder(). | |
| 41 | + fieldName("time"). | |
| 42 | + dataType("TIMESTAMP"). | |
| 43 | + build()); | |
| 44 | + schemaFields.addAll(FieldParser.parse(thingModel)); | |
| 45 | + | |
| 46 | + // 3. 设置超级表的标签 | |
| 47 | + List<TdFieldDO> tagsFields = new ArrayList<>(); | |
| 48 | + tagsFields.add(TdFieldDO.builder(). | |
| 49 | + fieldName("product_key"). | |
| 50 | + dataType("NCHAR"). | |
| 51 | + dataLength(64). | |
| 52 | + build()); | |
| 53 | + tagsFields.add(TdFieldDO.builder(). | |
| 54 | + fieldName("device_key"). | |
| 55 | + dataType("NCHAR"). | |
| 56 | + dataLength(64). | |
| 57 | + build()); | |
| 58 | + tagsFields.add(TdFieldDO.builder(). | |
| 59 | + fieldName("device_name"). | |
| 60 | + dataType("NCHAR"). | |
| 61 | + dataLength(64). | |
| 62 | + build()); | |
| 63 | + // 年 | |
| 64 | + tagsFields.add(TdFieldDO.builder(). | |
| 65 | + fieldName("year"). | |
| 66 | + dataType("INT"). | |
| 67 | + build()); | |
| 68 | + // 月 | |
| 69 | + tagsFields.add(TdFieldDO.builder(). | |
| 70 | + fieldName("month"). | |
| 71 | + dataType("INT"). | |
| 72 | + build()); | |
| 73 | + // 日 | |
| 74 | + tagsFields.add(TdFieldDO.builder(). | |
| 75 | + fieldName("day"). | |
| 76 | + dataType("INT"). | |
| 77 | + build()); | |
| 78 | + // 时 | |
| 79 | + tagsFields.add(TdFieldDO.builder(). | |
| 80 | + fieldName("hour"). | |
| 81 | + dataType("INT"). | |
| 82 | + build()); | |
| 83 | + | |
| 84 | + | |
| 85 | + // 4. 获取超级表的名称 | |
| 86 | + String superTableName = getProductPropertySTableName(deviceType, thingModel.getProductKey()); | |
| 87 | + | |
| 88 | + // 5. 创建超级表 | |
| 89 | + String dataBaseName = url.substring(url.lastIndexOf("/") + 1); | |
| 90 | + tdEngineService.createSuperTable(schemaFields, tagsFields, dataBaseName, superTableName); | |
| 46 | 91 | } |
| 47 | 92 | |
| 48 | 93 | @Override |
| 49 | 94 | public void updateSuperTable(ThingModelRespVO thingModel, Integer deviceType) { |
| 50 | 95 | try { |
| 51 | - // 获取旧字段信息 | |
| 52 | 96 | String tbName = getProductPropertySTableName(deviceType, thingModel.getProductKey()); |
| 53 | - String sql = TableManager.getDescTableSql(tbName); | |
| 54 | - TdResponse response = tdRestApi.execSql(sql); | |
| 55 | - if (response.getCode() != TdResponse.CODE_SUCCESS) { | |
| 56 | - throw new RuntimeException("获取表描述错误: " + JSONUtil.toJsonStr(response)); | |
| 57 | - } | |
| 58 | - | |
| 59 | - List<TdField> oldFields = FieldParser.parse(response.getData()); | |
| 60 | - List<TdField> newFields = FieldParser.parse(thingModel); | |
| 61 | - | |
| 62 | - // 找出新增的字段 | |
| 63 | - List<TdField> addFields = newFields.stream() | |
| 64 | - .filter(f -> oldFields.stream().noneMatch(old -> old.getName().equals(f.getName()))) | |
| 65 | - .collect(Collectors.toList()); | |
| 66 | - if (!addFields.isEmpty()) { | |
| 67 | - sql = TableManager.getAddSTableColumnSql(tbName, addFields); | |
| 68 | - response = tdRestApi.execSql(sql); | |
| 69 | - if (response.getCode() != TdResponse.CODE_SUCCESS) { | |
| 70 | - throw new RuntimeException("添加表字段错误: " + JSONUtil.toJsonStr(response)); | |
| 71 | - } | |
| 72 | - } | |
| 73 | - | |
| 74 | - // 找出修改的字段 | |
| 75 | - List<TdField> modifyFields = newFields.stream() | |
| 76 | - .filter(f -> oldFields.stream().anyMatch(old -> | |
| 77 | - old.getName().equals(f.getName()) && | |
| 78 | - (!old.getType().equals(f.getType()) || old.getLength() != f.getLength()))) | |
| 79 | - .collect(Collectors.toList()); | |
| 80 | - if (!modifyFields.isEmpty()) { | |
| 81 | - sql = TableManager.getModifySTableColumnSql(tbName, modifyFields); | |
| 82 | - response = tdRestApi.execSql(sql); | |
| 83 | - if (response.getCode() != TdResponse.CODE_SUCCESS) { | |
| 84 | - throw new RuntimeException("修改表字段错误: " + JSONUtil.toJsonStr(response)); | |
| 85 | - } | |
| 86 | - } | |
| 87 | - | |
| 88 | - // 找出删除的字段 | |
| 89 | - List<TdField> dropFields = oldFields.stream() | |
| 90 | - .filter(f -> !"time".equals(f.getName()) && !"device_id".equals(f.getName()) && | |
| 91 | - newFields.stream().noneMatch(n -> n.getName().equals(f.getName()))) | |
| 92 | - .collect(Collectors.toList()); | |
| 93 | - if (!dropFields.isEmpty()) { | |
| 94 | - sql = TableManager.getDropSTableColumnSql(tbName, dropFields); | |
| 95 | - response = tdRestApi.execSql(sql); | |
| 96 | - if (response.getCode() != TdResponse.CODE_SUCCESS) { | |
| 97 | - throw new RuntimeException("删除表字段错误: " + JSONUtil.toJsonStr(response)); | |
| 98 | - } | |
| 99 | - } | |
| 97 | + List<TdFieldDO> oldFields = getTableFields(tbName); | |
| 98 | + List<TdFieldDO> newFields = FieldParser.parse(thingModel); | |
| 99 | + | |
| 100 | + updateTableFields(tbName, oldFields, newFields); | |
| 100 | 101 | } catch (Throwable e) { |
| 101 | 102 | log.error("更新物模型超级表失败", e); |
| 102 | 103 | } |
| 103 | 104 | } |
| 104 | 105 | |
| 105 | - @Override | |
| 106 | - public void createSuperTableDataModel(IotProductDO product, List<IotThinkModelFunctionDO> functionList) { | |
| 107 | - // 1. 生成 ThingModelRespVO | |
| 108 | - ThingModelRespVO thingModel = new ThingModelRespVO(); | |
| 109 | - thingModel.setId(product.getId()); | |
| 110 | - thingModel.setProductKey(product.getProductKey()); | |
| 106 | + // 获取表字段 | |
| 107 | + private List<TdFieldDO> getTableFields(String tableName) { | |
| 108 | + List<TdFieldDO> fields = new ArrayList<>(); | |
| 109 | + // 获取超级表的描述信息 | |
| 110 | + List<Map<String, Object>> maps = tdEngineService.describeSuperTable(url.substring(url.lastIndexOf("/") + 1), tableName); | |
| 111 | + if (maps != null) { | |
| 112 | + // 过滤掉 note 字段为 TAG 的记录 | |
| 113 | + maps = maps.stream().filter(map -> !"TAG".equals(map.get("note"))).toList(); | |
| 114 | + // 过滤掉 time 字段 | |
| 115 | + maps = maps.stream().filter(map -> !"time".equals(map.get("field"))).toList(); | |
| 116 | + // 解析字段信息 | |
| 117 | + fields = FieldParser.parse(maps.stream() | |
| 118 | + .map(map -> List.of(map.get("field"), map.get("type"), map.get("length"))) | |
| 119 | + .collect(Collectors.toList())); | |
| 120 | + } | |
| 121 | + return fields; | |
| 122 | + } | |
| 111 | 123 | |
| 112 | - // 1.1 设置属性、服务和事件 | |
| 113 | - ThingModelRespVO.Model model = new ThingModelRespVO.Model(); | |
| 114 | - List<ThingModelProperty> properties = new ArrayList<>(); | |
| 115 | - | |
| 116 | - // 1.2 遍历功能列表并分类 | |
| 117 | - for (IotThinkModelFunctionDO function : functionList) { | |
| 118 | - if (Objects.requireNonNull(IotProductFunctionTypeEnum.valueOf(function.getType())) == IotProductFunctionTypeEnum.PROPERTY) { | |
| 119 | - ThingModelProperty property = new ThingModelProperty(); | |
| 120 | - property.setIdentifier(function.getIdentifier()); | |
| 121 | - property.setName(function.getName()); | |
| 122 | - property.setDescription(function.getDescription()); | |
| 123 | - property.setDataType(function.getProperty().getDataType()); | |
| 124 | - properties.add(property); | |
| 125 | - } | |
| 124 | + // 更新表字段 | |
| 125 | + private void updateTableFields(String tableName, List<TdFieldDO> oldFields, List<TdFieldDO> newFields) { | |
| 126 | + // 获取新增字段 | |
| 127 | + List<TdFieldDO> addFields = getAddFields(oldFields, newFields); | |
| 128 | + // 获取修改字段 | |
| 129 | + List<TdFieldDO> modifyFields = getModifyFields(oldFields, newFields); | |
| 130 | + // 获取删除字段 | |
| 131 | + List<TdFieldDO> dropFields = getDropFields(oldFields, newFields); | |
| 132 | + | |
| 133 | + String dataBaseName = url.substring(url.lastIndexOf("/") + 1); | |
| 134 | + // 添加新增字段 | |
| 135 | + if (CollUtil.isNotEmpty(addFields)) { | |
| 136 | + tdEngineService.addColumnForSuperTable(dataBaseName,tableName, addFields); | |
| 137 | + } | |
| 138 | + // 删除旧字段 | |
| 139 | + if (CollUtil.isNotEmpty(dropFields)) { | |
| 140 | + tdEngineService.dropColumnForSuperTable(dataBaseName,tableName, dropFields); | |
| 126 | 141 | } |
| 142 | + // 修改字段(先删除再添加) | |
| 143 | + if (CollUtil.isNotEmpty(modifyFields)) { | |
| 144 | + tdEngineService.dropColumnForSuperTable(dataBaseName,tableName, modifyFields); | |
| 145 | + tdEngineService.addColumnForSuperTable(dataBaseName,tableName, modifyFields); | |
| 146 | + } | |
| 147 | + } | |
| 148 | + | |
| 149 | + // 获取新增字段 | |
| 150 | + private List<TdFieldDO> getAddFields(List<TdFieldDO> oldFields, List<TdFieldDO> newFields) { | |
| 151 | + return newFields.stream() | |
| 152 | + .filter(f -> oldFields.stream().noneMatch(old -> old.getFieldName().equals(f.getFieldName()))) | |
| 153 | + .collect(Collectors.toList()); | |
| 154 | + } | |
| 155 | + | |
| 156 | + // 获取修改字段 | |
| 157 | + private List<TdFieldDO> getModifyFields(List<TdFieldDO> oldFields, List<TdFieldDO> newFields) { | |
| 158 | + return newFields.stream() | |
| 159 | + .filter(f -> oldFields.stream().anyMatch(old -> | |
| 160 | + old.getFieldName().equals(f.getFieldName()) && | |
| 161 | + (!old.getDataType().equals(f.getDataType()) || !Objects.equals(old.getDataLength(), f.getDataLength())))) | |
| 162 | + .collect(Collectors.toList()); | |
| 163 | + } | |
| 164 | + | |
| 165 | + // 获取删除字段 | |
| 166 | + private List<TdFieldDO> getDropFields(List<TdFieldDO> oldFields, List<TdFieldDO> newFields) { | |
| 167 | + return oldFields.stream() | |
| 168 | + .filter(f -> !"time".equals(f.getFieldName()) && !"device_id".equals(f.getFieldName()) && | |
| 169 | + newFields.stream().noneMatch(n -> n.getFieldName().equals(f.getFieldName()))) | |
| 170 | + .collect(Collectors.toList()); | |
| 171 | + } | |
| 172 | + | |
| 173 | + @Override | |
| 174 | + public void createSuperTableDataModel(IotProductDO product, List<IotThinkModelFunctionDO> functionList) { | |
| 175 | + ThingModelRespVO thingModel = buildThingModel(product, functionList); | |
| 127 | 176 | |
| 128 | - // 1.3 判断属性列表是否为空 | |
| 129 | - if (properties.isEmpty()) { | |
| 177 | + if (thingModel.getModel().getProperties().isEmpty()) { | |
| 130 | 178 | log.warn("物模型属性列表为空,不创建超级表"); |
| 131 | 179 | return; |
| 132 | 180 | } |
| 133 | 181 | |
| 134 | - model.setProperties(properties); | |
| 135 | - thingModel.setModel(model); | |
| 182 | + String superTableName = getProductPropertySTableName(product.getDeviceType(), product.getProductKey()); | |
| 183 | + String dataBaseName = url.substring(url.lastIndexOf("/") + 1); | |
| 184 | + Integer tableExists = tdEngineService.checkSuperTableExists(dataBaseName, superTableName); | |
| 136 | 185 | |
| 137 | - // 2. 判断是否已经创建,如果已经创建则进行更新 | |
| 138 | - String tbName = getProductPropertySTableName(product.getDeviceType(), product.getProductKey()); | |
| 139 | - Integer iot = tdEngineMapper.checkTableExists("ruoyi_vue_pro", tbName); | |
| 140 | - if (iot != null && iot > 0) { | |
| 141 | - // 3. 更新 | |
| 186 | + if (tableExists != null && tableExists > 0) { | |
| 142 | 187 | updateSuperTable(thingModel, product.getDeviceType()); |
| 143 | 188 | } else { |
| 144 | - // 4. 创建 | |
| 145 | 189 | createSuperTable(thingModel, product.getDeviceType()); |
| 146 | 190 | } |
| 147 | 191 | } |
| 148 | 192 | |
| 149 | - /** | |
| 150 | - * 根据产品key获取产品属性超级表名 | |
| 151 | - */ | |
| 193 | + private ThingModelRespVO buildThingModel(IotProductDO product, List<IotThinkModelFunctionDO> functionList) { | |
| 194 | + ThingModelRespVO thingModel = new ThingModelRespVO(); | |
| 195 | + thingModel.setId(product.getId()); | |
| 196 | + thingModel.setProductKey(product.getProductKey()); | |
| 197 | + | |
| 198 | + ThingModelRespVO.Model model = new ThingModelRespVO.Model(); | |
| 199 | + List<ThingModelProperty> properties = functionList.stream() | |
| 200 | + .filter(function -> IotProductFunctionTypeEnum.PROPERTY.equals(IotProductFunctionTypeEnum.valueOf(function.getType()))) | |
| 201 | + .map(this::buildThingModelProperty) | |
| 202 | + .collect(Collectors.toList()); | |
| 203 | + | |
| 204 | + model.setProperties(properties); | |
| 205 | + thingModel.setModel(model); | |
| 206 | + | |
| 207 | + return thingModel; | |
| 208 | + } | |
| 209 | + | |
| 210 | + private ThingModelProperty buildThingModelProperty(IotThinkModelFunctionDO function) { | |
| 211 | + ThingModelProperty property = new ThingModelProperty(); | |
| 212 | + property.setIdentifier(function.getIdentifier()); | |
| 213 | + property.setName(function.getName()); | |
| 214 | + property.setDescription(function.getDescription()); | |
| 215 | + property.setDataType(function.getProperty().getDataType()); | |
| 216 | + return property; | |
| 217 | + } | |
| 218 | + | |
| 152 | 219 | static String getProductPropertySTableName(Integer deviceType, String productKey) { |
| 153 | - if (deviceType == 1) { | |
| 154 | - return String.format("gateway_sub_" + productKey).toLowerCase(); | |
| 155 | - } else if (deviceType == 2) { | |
| 156 | - return String.format("gateway_" + productKey).toLowerCase(); | |
| 157 | - } else { | |
| 158 | - return String.format("device_" + productKey).toLowerCase(); | |
| 159 | - } | |
| 220 | + return switch (deviceType) { | |
| 221 | + case 1 -> String.format("gateway_sub_%s", productKey).toLowerCase(); | |
| 222 | + case 2 -> String.format("gateway_%s", productKey).toLowerCase(); | |
| 223 | + default -> String.format("device_%s", productKey).toLowerCase(); | |
| 224 | + }; | |
| 160 | 225 | } |
| 161 | 226 | |
| 162 | - /** | |
| 163 | - * 根据deviceId获取设备属性表名 | |
| 164 | - */ | |
| 165 | 227 | static String getDevicePropertyTableName(String deviceType, String productKey, String deviceKey) { |
| 166 | - return String.format(deviceType + "_" + productKey + "_" + deviceKey).toLowerCase(); | |
| 228 | + return String.format("%s_%s_%s", deviceType, productKey, deviceKey).toLowerCase(); | |
| 167 | 229 | } |
| 168 | 230 | -} |
| 231 | +} | |
| 169 | 232 | \ No newline at end of file | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineService.java
| 1 | 1 | package cn.iocoder.yudao.module.iot.service.tdengine; |
| 2 | 2 | |
| 3 | -import cn.iocoder.yudao.module.iot.domain.FieldsVo; | |
| 3 | +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO; | |
| 4 | 4 | import cn.iocoder.yudao.module.iot.domain.SelectDto; |
| 5 | 5 | import cn.iocoder.yudao.module.iot.domain.TableDto; |
| 6 | 6 | import cn.iocoder.yudao.module.iot.domain.TagsSelectDao; |
| ... | ... | @@ -27,68 +27,69 @@ public interface TdEngineService { |
| 27 | 27 | * |
| 28 | 28 | * @param schemaFields schema字段 |
| 29 | 29 | * @param tagsFields tags字段 |
| 30 | - * @param dataBaseName 数据库名称 | |
| 31 | 30 | * @param superTableName 超级表名称 |
| 32 | - * @throws Exception 异常 | |
| 33 | 31 | */ |
| 34 | - void createSuperTable(List<FieldsVo> schemaFields, List<FieldsVo> tagsFields, String dataBaseName, | |
| 35 | - String superTableName) throws Exception; | |
| 32 | + void createSuperTable(List<TdFieldDO> schemaFields, List<TdFieldDO> tagsFields, String dataBaseName, String superTableName); | |
| 36 | 33 | |
| 37 | 34 | /** |
| 38 | - * 创建表 | |
| 39 | - * | |
| 40 | - * @param tableDto 表信息 | |
| 41 | - * @throws Exception 异常 | |
| 35 | + * 检查超级表是否存在 | |
| 42 | 36 | */ |
| 43 | - void createTable(TableDto tableDto) throws Exception; | |
| 37 | + Integer checkSuperTableExists(String dataBaseName, String superTableName); | |
| 44 | 38 | |
| 45 | - /** | |
| 46 | - * 插入数据 | |
| 47 | - * | |
| 48 | - * @param tableDto 表信息 | |
| 49 | - * @throws Exception 异常 | |
| 50 | - */ | |
| 51 | - void insertData(TableDto tableDto) throws Exception; | |
| 52 | 39 | |
| 53 | 40 | /** |
| 54 | - * 根据时间戳查询数据 | |
| 55 | - * | |
| 56 | - * @param selectDto 查询条件 | |
| 57 | - * @return 数据 | |
| 58 | - * @throws Exception 异常 | |
| 41 | + * 获取超级表的结构信息 | |
| 59 | 42 | */ |
| 60 | - List<Map<String, Object>> selectByTimesTamp(SelectDto selectDto) throws Exception; | |
| 43 | + List<Map<String, Object>> describeSuperTable(String dataBaseName, String superTableName); | |
| 61 | 44 | |
| 62 | 45 | /** |
| 63 | 46 | * 为超级表添加列 |
| 64 | 47 | * |
| 48 | + * @param dataBaseName 数据库名称 | |
| 65 | 49 | * @param superTableName 超级表名称 |
| 66 | 50 | * @param fieldsVo 字段信息 |
| 67 | - * @throws Exception 异常 | |
| 68 | 51 | */ |
| 69 | - void addColumnForSuperTable(String superTableName, FieldsVo fieldsVo) throws Exception; | |
| 52 | + void addColumnForSuperTable(String dataBaseName,String superTableName, List<TdFieldDO> fieldsVo); | |
| 70 | 53 | |
| 71 | 54 | /** |
| 72 | 55 | * 为超级表删除列 |
| 73 | 56 | * |
| 57 | + * @param dataBaseName 数据库名称 | |
| 74 | 58 | * @param superTableName 超级表名称 |
| 75 | 59 | * @param fieldsVo 字段信息 |
| 76 | - * @throws Exception 异常 | |
| 77 | 60 | */ |
| 78 | - void dropColumnForSuperTable(String superTableName, FieldsVo fieldsVo) throws Exception; | |
| 61 | + void dropColumnForSuperTable(String dataBaseName,String superTableName, List<TdFieldDO> fieldsVo); | |
| 79 | 62 | |
| 80 | 63 | /** |
| 81 | 64 | * 为超级表添加tag |
| 82 | 65 | */ |
| 83 | 66 | Long getCountByTimesTamp(SelectDto selectDto) throws Exception; |
| 84 | 67 | |
| 68 | + | |
| 69 | + /** | |
| 70 | + * 创建表 | |
| 71 | + * | |
| 72 | + * @param tableDto 表信息 | |
| 73 | + * @throws Exception 异常 | |
| 74 | + */ | |
| 75 | + void createTable(TableDto tableDto) throws Exception; | |
| 76 | + | |
| 85 | 77 | /** |
| 86 | - * 检查表是否存在 | |
| 78 | + * 插入数据 | |
| 87 | 79 | * |
| 88 | - * @return 1存在 0不存在 | |
| 80 | + * @param tableDto 表信息 | |
| 89 | 81 | * @throws Exception 异常 |
| 90 | 82 | */ |
| 91 | - Integer checkTableExists(SelectDto selectDto) throws Exception; | |
| 83 | + void insertData(TableDto tableDto) throws Exception; | |
| 84 | + | |
| 85 | + /** | |
| 86 | + * 根据时间戳查询数据 | |
| 87 | + * | |
| 88 | + * @param selectDto 查询条件 | |
| 89 | + * @return 数据 | |
| 90 | + * @throws Exception 异常 | |
| 91 | + */ | |
| 92 | + List<Map<String, Object>> selectByTimesTamp(SelectDto selectDto) throws Exception; | |
| 92 | 93 | |
| 93 | 94 | /** |
| 94 | 95 | * 初始化超级表 |
| ... | ... | @@ -138,4 +139,6 @@ public interface TdEngineService { |
| 138 | 139 | * @return 数据 |
| 139 | 140 | */ |
| 140 | 141 | List<Map<String, Object>> getAggregateData(SelectVisualDto selectVisualDto); |
| 142 | + | |
| 143 | + | |
| 141 | 144 | } | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineServiceImpl.java
| 1 | 1 | package cn.iocoder.yudao.module.iot.service.tdengine; |
| 2 | 2 | |
| 3 | -import cn.iocoder.yudao.module.iot.domain.FieldsVo; | |
| 3 | +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO; | |
| 4 | +import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineMapper; | |
| 4 | 5 | import cn.iocoder.yudao.module.iot.domain.SelectDto; |
| 5 | 6 | import cn.iocoder.yudao.module.iot.domain.TableDto; |
| 6 | 7 | import cn.iocoder.yudao.module.iot.domain.TagsSelectDao; |
| 7 | 8 | import cn.iocoder.yudao.module.iot.domain.visual.SelectVisualDto; |
| 9 | +import jakarta.annotation.Resource; | |
| 8 | 10 | import lombok.extern.slf4j.Slf4j; |
| 9 | 11 | import org.springframework.stereotype.Service; |
| 10 | 12 | |
| ... | ... | @@ -15,25 +17,27 @@ import java.util.Map; |
| 15 | 17 | @Slf4j |
| 16 | 18 | public class TdEngineServiceImpl implements TdEngineService { |
| 17 | 19 | |
| 20 | + @Resource | |
| 21 | + private TdEngineMapper tdEngineMapper; | |
| 18 | 22 | |
| 19 | 23 | @Override |
| 20 | 24 | public void createDateBase(String dataBaseName) { |
| 21 | - | |
| 25 | + tdEngineMapper.createDatabase(dataBaseName); | |
| 22 | 26 | } |
| 23 | 27 | |
| 24 | 28 | @Override |
| 25 | - public void createSuperTable(List<FieldsVo> schemaFields, List<FieldsVo> tagsFields, String dataBaseName, String superTableName) { | |
| 26 | - | |
| 29 | + public void createSuperTable(List<TdFieldDO> schemaFields, List<TdFieldDO> tagsFields, String dataBaseName, String superTableName) { | |
| 30 | + tdEngineMapper.createSuperTable(schemaFields, tagsFields, dataBaseName, superTableName); | |
| 27 | 31 | } |
| 28 | 32 | |
| 29 | 33 | @Override |
| 30 | 34 | public void createTable(TableDto tableDto) { |
| 31 | - | |
| 35 | + tdEngineMapper.createTable(tableDto); | |
| 32 | 36 | } |
| 33 | 37 | |
| 34 | 38 | @Override |
| 35 | 39 | public void insertData(TableDto tableDto) { |
| 36 | - | |
| 40 | + tdEngineMapper.insertData(tableDto); | |
| 37 | 41 | } |
| 38 | 42 | |
| 39 | 43 | @Override |
| ... | ... | @@ -42,13 +46,17 @@ public class TdEngineServiceImpl implements TdEngineService { |
| 42 | 46 | } |
| 43 | 47 | |
| 44 | 48 | @Override |
| 45 | - public void addColumnForSuperTable(String superTableName, FieldsVo fieldsVo) { | |
| 46 | - | |
| 49 | + public void addColumnForSuperTable(String dataBaseName,String superTableName, List<TdFieldDO> fields) { | |
| 50 | + for (TdFieldDO field : fields) { | |
| 51 | + tdEngineMapper.addColumnForSuperTable(dataBaseName,superTableName, field); | |
| 52 | + } | |
| 47 | 53 | } |
| 48 | 54 | |
| 49 | 55 | @Override |
| 50 | - public void dropColumnForSuperTable(String superTableName, FieldsVo fieldsVo) { | |
| 51 | - | |
| 56 | + public void dropColumnForSuperTable(String dataBaseName,String superTableName, List<TdFieldDO> fields) { | |
| 57 | + for (TdFieldDO field : fields) { | |
| 58 | + tdEngineMapper.dropColumnForSuperTable(dataBaseName,superTableName, field); | |
| 59 | + } | |
| 52 | 60 | } |
| 53 | 61 | |
| 54 | 62 | @Override |
| ... | ... | @@ -57,11 +65,6 @@ public class TdEngineServiceImpl implements TdEngineService { |
| 57 | 65 | } |
| 58 | 66 | |
| 59 | 67 | @Override |
| 60 | - public Integer checkTableExists(SelectDto selectDto) { | |
| 61 | - return 0; | |
| 62 | - } | |
| 63 | - | |
| 64 | - @Override | |
| 65 | 68 | public void initSTableFrame(String msg) { |
| 66 | 69 | |
| 67 | 70 | } |
| ... | ... | @@ -90,4 +93,15 @@ public class TdEngineServiceImpl implements TdEngineService { |
| 90 | 93 | public List<Map<String, Object>> getAggregateData(SelectVisualDto selectVisualDto) { |
| 91 | 94 | return List.of(); |
| 92 | 95 | } |
| 96 | + | |
| 97 | + @Override | |
| 98 | + public Integer checkSuperTableExists(String dataBaseName, String superTableName) { | |
| 99 | + List<Map<String, Object>> results = tdEngineMapper.showSuperTables(dataBaseName, superTableName); | |
| 100 | + return results == null || results.isEmpty() ? 0 : results.size(); | |
| 101 | + } | |
| 102 | + | |
| 103 | + @Override | |
| 104 | + public List<Map<String, Object>> describeSuperTable(String dataBaseName, String superTableName) { | |
| 105 | + return tdEngineMapper.describeSuperTable(dataBaseName, superTableName); | |
| 106 | + } | |
| 93 | 107 | } |
| 94 | 108 | \ No newline at end of file | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java
| ... | ... | @@ -174,8 +174,10 @@ public class IotThinkModelFunctionServiceImpl implements IotThinkModelFunctionSe |
| 174 | 174 | public void createSuperTableDataModel(Long productId) { |
| 175 | 175 | // 1. 查询产品 |
| 176 | 176 | IotProductDO product = productService.getProduct(productId); |
| 177 | + | |
| 177 | 178 | // 2. 查询产品的物模型功能列表 |
| 178 | 179 | List<IotThinkModelFunctionDO> functionList = thinkModelFunctionMapper.selectListByProductId(productId); |
| 180 | + | |
| 179 | 181 | // 3. 生成 TDengine 的数据模型 |
| 180 | 182 | dbStructureDataService.createSuperTableDataModel(product, functionList); |
| 181 | 183 | } | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineMapper.xml
| ... | ... | @@ -8,7 +8,7 @@ |
| 8 | 8 | </update> |
| 9 | 9 | |
| 10 | 10 | <update id="createSuperTable"> |
| 11 | - create table if not exists #{dataBaseName}.#{superTableName} | |
| 11 | + CREATE STABLE IF NOT EXISTS ${dataBaseName}.${superTableName} | |
| 12 | 12 | <foreach item="item" collection="schemaFields" separator="," |
| 13 | 13 | open="(" close=")" index=""> |
| 14 | 14 | <if test="item.fieldName != null || item.fieldName != ''"> |
| ... | ... | @@ -16,46 +16,48 @@ |
| 16 | 16 | </if> |
| 17 | 17 | <if test="item.dataType != null || item.dataType != ''"> |
| 18 | 18 | <choose> |
| 19 | - <when test="item.dataType == 'timestamp'"> | |
| 20 | - timestamp | |
| 19 | + <when test="item.dataType == 'TIMESTAMP'"> | |
| 20 | + TIMESTAMP | |
| 21 | 21 | </when> |
| 22 | - <when test="item.dataType == 'tinyint'"> | |
| 23 | - tinyint | |
| 22 | + <when test="item.dataType == 'TINYINT'"> | |
| 23 | + TINYINT | |
| 24 | 24 | </when> |
| 25 | - <when test="item.dataType == 'smallint'"> | |
| 26 | - smallint | |
| 25 | + <when test="item.dataType == 'SMALLINT'"> | |
| 26 | + SMALLINT | |
| 27 | 27 | </when> |
| 28 | - <when test="item.dataType == 'int'"> | |
| 29 | - int | |
| 28 | + <when test="item.dataType == 'INT'"> | |
| 29 | + INT | |
| 30 | 30 | </when> |
| 31 | - <when test="item.dataType == 'bigint'"> | |
| 32 | - bigint | |
| 31 | + <when test="item.dataType == 'BIGINT'"> | |
| 32 | + BIGINT | |
| 33 | 33 | </when> |
| 34 | - <when test="item.dataType == 'float'"> | |
| 35 | - float | |
| 34 | + <when test="item.dataType == 'FLOAT'"> | |
| 35 | + FLOAT | |
| 36 | 36 | </when> |
| 37 | - <when test="item.dataType == 'double'"> | |
| 38 | - double | |
| 37 | + <when test="item.dataType == 'DOUBLE'"> | |
| 38 | + DOUBLE | |
| 39 | 39 | </when> |
| 40 | - <when test="item.dataType == 'binary'"> | |
| 41 | - binary | |
| 40 | + <when test="item.dataType == 'BINARY'"> | |
| 41 | + BINARY | |
| 42 | 42 | </when> |
| 43 | - <when test="item.dataType == 'nchar'"> | |
| 44 | - nchar | |
| 43 | + <when test="item.dataType == 'NCHAR'"> | |
| 44 | + NCHAR | |
| 45 | 45 | </when> |
| 46 | - <when test="item.dataType == 'bool'"> | |
| 47 | - bool | |
| 46 | + <when test="item.dataType == 'BOOL'"> | |
| 47 | + BOOL | |
| 48 | 48 | </when> |
| 49 | - <when test="item.dataType == 'json'"> | |
| 50 | - json | |
| 49 | + <when test="item.dataType == 'JSON'"> | |
| 50 | + JSON | |
| 51 | 51 | </when> |
| 52 | 52 | </choose> |
| 53 | 53 | </if> |
| 54 | - <if test="item.size != null"> | |
| 55 | - (#{item.size}) | |
| 54 | + <if test="item.dataLength > 0"> | |
| 55 | + ( | |
| 56 | + ${item.dataLength} | |
| 57 | + ) | |
| 56 | 58 | </if> |
| 57 | 59 | </foreach> |
| 58 | - tags | |
| 60 | + TAGS | |
| 59 | 61 | <!--tdEngine不支持动态tags里的数据类型,只能使用choose标签比对--> |
| 60 | 62 | <foreach item="item" collection="tagsFields" separator="," |
| 61 | 63 | open="(" close=")" index=""> |
| ... | ... | @@ -64,43 +66,45 @@ |
| 64 | 66 | </if> |
| 65 | 67 | <if test="item.dataType != null || item.dataType != ''"> |
| 66 | 68 | <choose> |
| 67 | - <when test="item.dataType == 'timestamp'"> | |
| 68 | - timestamp | |
| 69 | + <when test="item.dataType == 'TIMESTAMP'"> | |
| 70 | + TIMESTAMP | |
| 69 | 71 | </when> |
| 70 | - <when test="item.dataType == 'tinyint'"> | |
| 71 | - tinyint | |
| 72 | + <when test="item.dataType == 'TINYINT'"> | |
| 73 | + TINYINT | |
| 72 | 74 | </when> |
| 73 | - <when test="item.dataType == 'smallint'"> | |
| 74 | - smallint | |
| 75 | + <when test="item.dataType == 'SMALLINT'"> | |
| 76 | + SMALLINT | |
| 75 | 77 | </when> |
| 76 | - <when test="item.dataType == 'int'"> | |
| 77 | - int | |
| 78 | + <when test="item.dataType == 'INT'"> | |
| 79 | + INT | |
| 78 | 80 | </when> |
| 79 | - <when test="item.dataType == 'bigint'"> | |
| 80 | - bigint | |
| 81 | + <when test="item.dataType == 'BIGINT'"> | |
| 82 | + BIGINT | |
| 81 | 83 | </when> |
| 82 | - <when test="item.dataType == 'float'"> | |
| 83 | - float | |
| 84 | + <when test="item.dataType == 'FLOAT'"> | |
| 85 | + FLOAT | |
| 84 | 86 | </when> |
| 85 | - <when test="item.dataType == 'double'"> | |
| 86 | - double | |
| 87 | + <when test="item.dataType == 'DOUBLE'"> | |
| 88 | + DOUBLE | |
| 87 | 89 | </when> |
| 88 | - <when test="item.dataType == 'binary'"> | |
| 89 | - binary | |
| 90 | + <when test="item.dataType == 'BINARY'"> | |
| 91 | + BINARY | |
| 90 | 92 | </when> |
| 91 | - <when test="item.dataType == 'nchar'"> | |
| 92 | - nchar | |
| 93 | + <when test="item.dataType == 'NCHAR'"> | |
| 94 | + NCHAR | |
| 93 | 95 | </when> |
| 94 | - <when test="item.dataType == 'bool'"> | |
| 95 | - bool | |
| 96 | + <when test="item.dataType == 'BOOL'"> | |
| 97 | + BOOL | |
| 96 | 98 | </when> |
| 97 | - <when test="item.dataType == 'json'"> | |
| 98 | - json | |
| 99 | + <when test="item.dataType == 'JSON'"> | |
| 100 | + JSON | |
| 99 | 101 | </when> |
| 100 | 102 | </choose> |
| 101 | 103 | </if> |
| 102 | - <if test="item.size != null"> | |
| 103 | - (#{item.size}) | |
| 104 | + <if test="item.dataLength > 0"> | |
| 105 | + ( | |
| 106 | + ${item.dataLength} | |
| 107 | + ) | |
| 104 | 108 | </if> |
| 105 | 109 | </foreach> |
| 106 | 110 | </update> |
| ... | ... | @@ -135,7 +139,6 @@ |
| 135 | 139 | </foreach> |
| 136 | 140 | </insert> |
| 137 | 141 | |
| 138 | - | |
| 139 | 142 | <select id="selectByTimestamp" parameterType="cn.iocoder.yudao.module.iot.domain.SelectDto" |
| 140 | 143 | resultType="Map"> |
| 141 | 144 | select * from #{dataBaseName}.#{tableName} |
| ... | ... | @@ -146,66 +149,58 @@ |
| 146 | 149 | </select> |
| 147 | 150 | |
| 148 | 151 | <update id="addColumnForSuperTable"> |
| 149 | - ALTER | |
| 150 | - STABLE | |
| 151 | - #{superTableName} | |
| 152 | - ADD | |
| 153 | - COLUMN | |
| 154 | - <if test="fieldsVo.fieldName != null || fieldsVo.fieldName != ''"> | |
| 155 | - #{fieldsVo.fieldName} | |
| 152 | + ALTER STABLE ${dataBaseName}.${superTableName} ADD COLUMN | |
| 153 | + <if test="field.fieldName != null || field.fieldName != ''"> | |
| 154 | + #{field.fieldName} | |
| 156 | 155 | </if> |
| 157 | - <if test="fieldsVo.dataType != null || fieldsVo.dataType != ''"> | |
| 156 | + <if test="field.dataType != null || field.dataType != ''"> | |
| 158 | 157 | <choose> |
| 159 | - <when test="fieldsVo.dataType == 'timestamp'"> | |
| 160 | - timestamp | |
| 158 | + <when test="field.dataType == 'TIMESTAMP'"> | |
| 159 | + TIMESTAMP | |
| 161 | 160 | </when> |
| 162 | - <when test="fieldsVo.dataType == 'tinyint'"> | |
| 163 | - tinyint | |
| 161 | + <when test="field.dataType == 'TINYINT'"> | |
| 162 | + TINYINT | |
| 164 | 163 | </when> |
| 165 | - <when test="fieldsVo.dataType == 'smallint'"> | |
| 166 | - smallint | |
| 164 | + <when test="field.dataType == 'SMALLINT'"> | |
| 165 | + SMALLINT | |
| 167 | 166 | </when> |
| 168 | - <when test="fieldsVo.dataType == 'int'"> | |
| 169 | - int | |
| 167 | + <when test="field.dataType == 'INT'"> | |
| 168 | + INT | |
| 170 | 169 | </when> |
| 171 | - <when test="fieldsVo.dataType == 'bigint'"> | |
| 172 | - bigint | |
| 170 | + <when test="field.dataType == 'BIGINT'"> | |
| 171 | + BIGINT | |
| 173 | 172 | </when> |
| 174 | - <when test="fieldsVo.dataType == 'float'"> | |
| 175 | - float | |
| 173 | + <when test="field.dataType == 'FLOAT'"> | |
| 174 | + FLOAT | |
| 176 | 175 | </when> |
| 177 | - <when test="fieldsVo.dataType == 'double'"> | |
| 178 | - double | |
| 176 | + <when test="field.dataType == 'DOUBLE'"> | |
| 177 | + DOUBLE | |
| 179 | 178 | </when> |
| 180 | - <when test="fieldsVo.dataType == 'binary'"> | |
| 181 | - binary | |
| 179 | + <when test="field.dataType == 'BINARY'"> | |
| 180 | + BINARY | |
| 182 | 181 | </when> |
| 183 | - <when test="fieldsVo.dataType == 'nchar'"> | |
| 184 | - nchar | |
| 182 | + <when test="field.dataType == 'NCHAR'"> | |
| 183 | + NCHAR | |
| 185 | 184 | </when> |
| 186 | - <when test="fieldsVo.dataType == 'bool'"> | |
| 187 | - bool | |
| 185 | + <when test="field.dataType == 'BOOL'"> | |
| 186 | + BOOL | |
| 188 | 187 | </when> |
| 189 | - <when test="fieldsVo.dataType == 'json'"> | |
| 190 | - json | |
| 188 | + <when test="field.dataType == 'JSON'"> | |
| 189 | + JSON | |
| 191 | 190 | </when> |
| 192 | 191 | </choose> |
| 193 | 192 | </if> |
| 194 | - <if test="fieldsVo.size != null"> | |
| 193 | + <if test="field.dataLength > 0"> | |
| 195 | 194 | ( |
| 196 | - #{fieldsVo.size} | |
| 195 | + #{field.dataLength} | |
| 197 | 196 | ) |
| 198 | 197 | </if> |
| 199 | 198 | </update> |
| 200 | 199 | |
| 201 | 200 | <update id="dropColumnForSuperTable"> |
| 202 | - ALTER | |
| 203 | - STABLE | |
| 204 | - #{superTableName} | |
| 205 | - DROP | |
| 206 | - COLUMN | |
| 207 | - <if test="fieldsVo.fieldName != null || fieldsVo.fieldName != ''"> | |
| 208 | - #{fieldsVo.fieldName} | |
| 201 | + ALTER STABLE ${dataBaseName}.${superTableName} DROP COLUMN | |
| 202 | + <if test="field.fieldName != null || field.fieldName != ''"> | |
| 203 | + #{field.fieldName} | |
| 209 | 204 | </if> |
| 210 | 205 | </update> |
| 211 | 206 | |
| ... | ... | @@ -215,49 +210,49 @@ |
| 215 | 210 | #{superTableName} |
| 216 | 211 | ADD |
| 217 | 212 | TAG |
| 218 | - <if test="fieldsVo.fieldName != null || fieldsVo.fieldName != ''"> | |
| 219 | - #{fieldsVo.fieldName} | |
| 213 | + <if test="field.fieldName != null || fieldDO.fieldName != ''"> | |
| 214 | + #{fieldDO.fieldName} | |
| 220 | 215 | </if> |
| 221 | - <if test="fieldsVo.dataType != null || fieldsVo.dataType != ''"> | |
| 216 | + <if test="fieldDO.dataType != null || fieldDO.dataType != ''"> | |
| 222 | 217 | <choose> |
| 223 | - <when test="fieldsVo.dataType == 'timestamp'"> | |
| 218 | + <when test="fieldDO.dataType == 'timestamp'"> | |
| 224 | 219 | timestamp |
| 225 | 220 | </when> |
| 226 | - <when test="fieldsVo.dataType == 'tinyint'"> | |
| 221 | + <when test="fieldDO.dataType == 'tinyint'"> | |
| 227 | 222 | tinyint |
| 228 | 223 | </when> |
| 229 | - <when test="fieldsVo.dataType == 'smallint'"> | |
| 224 | + <when test="fieldDO.dataType == 'smallint'"> | |
| 230 | 225 | smallint |
| 231 | 226 | </when> |
| 232 | - <when test="fieldsVo.dataType == 'int'"> | |
| 227 | + <when test="fieldDO.dataType == 'int'"> | |
| 233 | 228 | int |
| 234 | 229 | </when> |
| 235 | - <when test="fieldsVo.dataType == 'bigint'"> | |
| 230 | + <when test="fieldDO.dataType == 'bigint'"> | |
| 236 | 231 | bigint |
| 237 | 232 | </when> |
| 238 | - <when test="fieldsVo.dataType == 'float'"> | |
| 233 | + <when test="fieldDO.dataType == 'float'"> | |
| 239 | 234 | float |
| 240 | 235 | </when> |
| 241 | - <when test="fieldsVo.dataType == 'double'"> | |
| 236 | + <when test="fieldDO.dataType == 'double'"> | |
| 242 | 237 | double |
| 243 | 238 | </when> |
| 244 | - <when test="fieldsVo.dataType == 'binary'"> | |
| 239 | + <when test="fieldDO.dataType == 'binary'"> | |
| 245 | 240 | binary |
| 246 | 241 | </when> |
| 247 | - <when test="fieldsVo.dataType == 'nchar'"> | |
| 242 | + <when test="fieldDO.dataType == 'nchar'"> | |
| 248 | 243 | nchar |
| 249 | 244 | </when> |
| 250 | - <when test="fieldsVo.dataType == 'bool'"> | |
| 245 | + <when test="fieldDO.dataType == 'bool'"> | |
| 251 | 246 | bool |
| 252 | 247 | </when> |
| 253 | - <when test="fieldsVo.dataType == 'json'"> | |
| 248 | + <when test="fieldDO.dataType == 'json'"> | |
| 254 | 249 | json |
| 255 | 250 | </when> |
| 256 | 251 | </choose> |
| 257 | 252 | </if> |
| 258 | - <if test="fieldsVo.size != null"> | |
| 253 | + <if test="fieldDO.dataLength > 0"> | |
| 259 | 254 | ( |
| 260 | - #{fieldsVo.size} | |
| 255 | + #{fieldDO.dataLength} | |
| 261 | 256 | ) |
| 262 | 257 | </if> |
| 263 | 258 | </update> |
| ... | ... | @@ -279,11 +274,8 @@ |
| 279 | 274 | FROM #{dataBaseName}.#{tableName} WHERE ${fieldName} BETWEEN #{startTime} AND #{endTime} |
| 280 | 275 | </select> |
| 281 | 276 | |
| 282 | - <select id="checkTableExists" resultType="java.lang.Integer"> | |
| 283 | - SELECT COUNT(0) | |
| 284 | - FROM information_schema.ins_tables | |
| 285 | - WHERE db_name = #{dataBaseName} | |
| 286 | - AND table_name = #{tableName} | |
| 277 | + <select id="showSuperTables" resultType="java.util.Map"> | |
| 278 | + SHOW ${dataBaseName}.STABLES LIKE '${superTableName}' | |
| 287 | 279 | </select> |
| 288 | 280 | |
| 289 | 281 | <select id="getLastData" resultType="java.util.Map"> |
| ... | ... | @@ -304,11 +296,13 @@ |
| 304 | 296 | FROM #{dataBaseName}.#{tableName} WHERE ts BETWEEN #{startTime} AND #{endTime} |
| 305 | 297 | LIMIT #{num} |
| 306 | 298 | </select> |
| 299 | + | |
| 307 | 300 | <select id="getRealtimeData" resultType="java.util.Map" |
| 308 | 301 | parameterType="cn.iocoder.yudao.module.iot.domain.visual.SelectVisualDto"> |
| 309 | 302 | SELECT #{fieldName}, ts |
| 310 | 303 | FROM #{dataBaseName}.#{tableName} LIMIT #{num} |
| 311 | 304 | </select> |
| 305 | + | |
| 312 | 306 | <select id="getAggregateData" resultType="java.util.Map" |
| 313 | 307 | parameterType="cn.iocoder.yudao.module.iot.domain.visual.SelectVisualDto"> |
| 314 | 308 | SELECT #{aggregate}(${fieldName}) |
| ... | ... | @@ -316,9 +310,8 @@ |
| 316 | 310 | LIMIT #{num} |
| 317 | 311 | </select> |
| 318 | 312 | |
| 319 | - | |
| 320 | - <insert id="createSuperTableDevice"> | |
| 321 | - ${sql} | |
| 322 | - </insert> | |
| 313 | + <select id="describeSuperTable" resultType="java.util.Map"> | |
| 314 | + DESCRIBE ${dataBaseName}.${superTableName} | |
| 315 | + </select> | |
| 323 | 316 | |
| 324 | 317 | </mapper> | ... | ... |