Commit 1176f0de268d70ba76c008eaaadf8ef93f2db6c2
Merge branch 'master' of github.com:thingsboard/thingsboard
Showing
9 changed files
with
99 additions
and
45 deletions
... | ... | @@ -43,7 +43,7 @@ BEGIN |
43 | 43 | into max_customer_ttl; |
44 | 44 | max_ttl := GREATEST(system_ttl, max_customer_ttl, max_tenant_ttl); |
45 | 45 | if max_ttl IS NOT NULL AND max_ttl > 0 THEN |
46 | - date := to_timestamp(EXTRACT(EPOCH FROM current_timestamp) - (max_ttl / 1000)); | |
46 | + date := to_timestamp(EXTRACT(EPOCH FROM current_timestamp) - max_ttl); | |
47 | 47 | partition_by_max_ttl_date := get_partition_by_max_ttl_date(partition_type, date); |
48 | 48 | RAISE NOTICE 'Partition by max ttl: %', partition_by_max_ttl_date; |
49 | 49 | IF partition_by_max_ttl_date IS NOT NULL THEN | ... | ... |
... | ... | @@ -193,6 +193,9 @@ public class ThingsboardInstallService { |
193 | 193 | databaseEntitiesUpgradeService.upgradeDatabase("3.2.1"); |
194 | 194 | case "3.2.2": |
195 | 195 | log.info("Upgrading ThingsBoard from version 3.2.2 to 3.3.0 ..."); |
196 | + if (databaseTsUpgradeService != null) { | |
197 | + databaseTsUpgradeService.upgradeDatabase("3.2.2"); | |
198 | + } | |
196 | 199 | databaseEntitiesUpgradeService.upgradeDatabase("3.2.2"); |
197 | 200 | |
198 | 201 | dataUpdateService.updateData("3.2.2"); | ... | ... |
... | ... | @@ -209,6 +209,12 @@ public class PsqlTsDatabaseUpgradeService extends AbstractSqlTsDatabaseUpgradeSe |
209 | 209 | executeQuery(conn, "DROP FUNCTION IF EXISTS delete_customer_records_from_ts_kv(character varying, character varying, bigint);"); |
210 | 210 | } |
211 | 211 | break; |
212 | + case "3.2.2": | |
213 | + try (Connection conn = DriverManager.getConnection(dbUrl, dbUserName, dbPassword)) { | |
214 | + log.info("Load Drop Partitions functions ..."); | |
215 | + loadSql(conn, LOAD_DROP_PARTITIONS_FUNCTIONS_SQL, "2.4.3"); | |
216 | + } | |
217 | + break; | |
212 | 218 | default: |
213 | 219 | throw new RuntimeException("Unable to upgrade SQL database, unsupported fromVersion: " + fromVersion); |
214 | 220 | } | ... | ... |
... | ... | @@ -120,13 +120,17 @@ |
120 | 120 | <groupId>org.apache.curator</groupId> |
121 | 121 | <artifactId>curator-recipes</artifactId> |
122 | 122 | </dependency> |
123 | - | |
124 | 123 | <dependency> |
125 | 124 | <groupId>junit</groupId> |
126 | 125 | <artifactId>junit</artifactId> |
127 | 126 | <scope>test</scope> |
128 | 127 | </dependency> |
129 | 128 | <dependency> |
129 | + <groupId>org.hamcrest</groupId> | |
130 | + <artifactId>hamcrest</artifactId> | |
131 | + <scope>test</scope> | |
132 | + </dependency> | |
133 | + <dependency> | |
130 | 134 | <groupId>org.mockito</groupId> |
131 | 135 | <artifactId>mockito-core</artifactId> |
132 | 136 | <scope>test</scope> | ... | ... |
... | ... | @@ -41,6 +41,7 @@ import org.thingsboard.server.common.transport.TransportServiceCallback; |
41 | 41 | import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse; |
42 | 42 | import org.thingsboard.server.common.transport.util.SslUtil; |
43 | 43 | import org.thingsboard.server.gen.transport.TransportProtos; |
44 | +import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; | |
44 | 45 | import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; |
45 | 46 | import org.thingsboard.server.transport.lwm2m.secure.credentials.LwM2MCredentials; |
46 | 47 | import org.thingsboard.server.common.data.device.credentials.lwm2m.X509ClientCredentials; |
... | ... | @@ -61,6 +62,7 @@ import java.util.concurrent.TimeUnit; |
61 | 62 | |
62 | 63 | @Slf4j |
63 | 64 | @Component |
65 | +@TbLwM2mTransportComponent | |
64 | 66 | @RequiredArgsConstructor |
65 | 67 | public class TbLwM2MDtlsCertificateVerifier implements NewAdvancedCertificateVerifier { |
66 | 68 | ... | ... |
... | ... | @@ -228,29 +228,27 @@ public class JsonConverter { |
228 | 228 | private static KeyValueProto buildNumericKeyValueProto(JsonPrimitive value, String key) { |
229 | 229 | String valueAsString = value.getAsString(); |
230 | 230 | KeyValueProto.Builder builder = KeyValueProto.newBuilder().setKey(key); |
231 | - if (valueAsString.contains("e") || valueAsString.contains("E")) { | |
232 | - //TODO: correct value conversion. We should make sure that if the value can't fit into Long or Double, we should send String | |
233 | - var bd = new BigDecimal(valueAsString); | |
234 | - if (bd.stripTrailingZeros().scale() <= 0) { | |
235 | - try { | |
236 | - return builder.setType(KeyValueType.LONG_V).setLongV(bd.longValueExact()).build(); | |
237 | - } catch (ArithmeticException e) { | |
238 | - return builder.setType(KeyValueType.DOUBLE_V).setDoubleV(bd.doubleValue()).build(); | |
231 | + var bd = new BigDecimal(valueAsString); | |
232 | + if (bd.stripTrailingZeros().scale() <= 0) { | |
233 | + try { | |
234 | + return builder.setType(KeyValueType.LONG_V).setLongV(bd.longValueExact()).build(); | |
235 | + } catch (ArithmeticException e) { | |
236 | + if (isTypeCastEnabled) { | |
237 | + return builder.setType(KeyValueType.STRING_V).setStringV(bd.toPlainString()).build(); | |
238 | + } else { | |
239 | + throw new JsonSyntaxException("Big integer values are not supported!"); | |
239 | 240 | } |
240 | - } else { | |
241 | - return builder.setType(KeyValueType.DOUBLE_V).setDoubleV(bd.doubleValue()).build(); | |
242 | 241 | } |
243 | - } else if (valueAsString.contains(".")) { | |
244 | - return builder.setType(KeyValueType.DOUBLE_V).setDoubleV(value.getAsDouble()).build(); | |
245 | 242 | } else { |
246 | - try { | |
247 | - long longValue = Long.parseLong(value.getAsString()); | |
248 | - return builder.setType(KeyValueType.LONG_V).setLongV(longValue).build(); | |
249 | - } catch (NumberFormatException e) { | |
250 | - //TODO: correct value conversion. We should make sure that if the value can't fit into Long or Double, we should send String | |
251 | - return builder.setType(KeyValueType.DOUBLE_V).setDoubleV(new BigDecimal(valueAsString).doubleValue()).build(); | |
243 | + if (bd.scale() <= 16) { | |
244 | + return builder.setType(KeyValueType.DOUBLE_V).setDoubleV(bd.doubleValue()).build(); | |
245 | + } else if (isTypeCastEnabled) { | |
246 | + return builder.setType(KeyValueType.STRING_V).setStringV(bd.toPlainString()).build(); | |
247 | + } else { | |
248 | + throw new JsonSyntaxException("Big integer values are not supported!"); | |
252 | 249 | } |
253 | 250 | } |
251 | + | |
254 | 252 | } |
255 | 253 | |
256 | 254 | public static TransportProtos.ToServerRpcRequestMsg convertToServerRpcRequest(JsonElement json, int requestId) throws JsonSyntaxException { |
... | ... | @@ -261,27 +259,24 @@ public class JsonConverter { |
261 | 259 | private static void parseNumericValue(List<KvEntry> result, Entry<String, JsonElement> valueEntry, JsonPrimitive value) { |
262 | 260 | String valueAsString = value.getAsString(); |
263 | 261 | String key = valueEntry.getKey(); |
264 | - if (valueAsString.contains("e") || valueAsString.contains("E")) { | |
265 | - //TODO: correct value conversion. We should make sure that if the value can't fit into Long or Double, we should send String | |
266 | - var bd = new BigDecimal(valueAsString); | |
267 | - if (bd.stripTrailingZeros().scale() <= 0) { | |
268 | - try { | |
269 | - result.add(new LongDataEntry(key, bd.longValueExact())); | |
270 | - } catch (ArithmeticException e) { | |
271 | - result.add(new DoubleDataEntry(key, bd.doubleValue())); | |
262 | + var bd = new BigDecimal(valueAsString); | |
263 | + if (bd.stripTrailingZeros().scale() <= 0) { | |
264 | + try { | |
265 | + result.add(new LongDataEntry(key, bd.longValueExact())); | |
266 | + } catch (ArithmeticException e) { | |
267 | + if (isTypeCastEnabled) { | |
268 | + result.add(new StringDataEntry(key, bd.toPlainString())); | |
269 | + } else { | |
270 | + throw new JsonSyntaxException("Big integer values are not supported!"); | |
272 | 271 | } |
273 | - } else { | |
274 | - result.add(new DoubleDataEntry(key, bd.doubleValue())); | |
275 | 272 | } |
276 | - } else if (valueAsString.contains(".")) { | |
277 | - result.add(new DoubleDataEntry(key, value.getAsDouble())); | |
278 | 273 | } else { |
279 | - try { | |
280 | - long longValue = Long.parseLong(value.getAsString()); | |
281 | - result.add(new LongDataEntry(key, longValue)); | |
282 | - } catch (NumberFormatException e) { | |
283 | - //TODO: correct value conversion. We should make sure that if the value can't fit into Long or Double, we should send String | |
284 | - result.add(new DoubleDataEntry(key, new BigDecimal(valueAsString).doubleValue())); | |
274 | + if (bd.scale() <= 16) { | |
275 | + result.add(new DoubleDataEntry(key, bd.doubleValue())); | |
276 | + } else if (isTypeCastEnabled) { | |
277 | + result.add(new StringDataEntry(key, bd.toPlainString())); | |
278 | + } else { | |
279 | + throw new JsonSyntaxException("Big integer values are not supported!"); | |
285 | 280 | } |
286 | 281 | } |
287 | 282 | } | ... | ... |
... | ... | @@ -15,7 +15,9 @@ |
15 | 15 | */ |
16 | 16 | |
17 | 17 | import com.google.gson.JsonParser; |
18 | +import com.google.gson.JsonSyntaxException; | |
18 | 19 | import org.junit.Assert; |
20 | +import org.junit.Before; | |
19 | 21 | import org.junit.Test; |
20 | 22 | import org.junit.runner.RunWith; |
21 | 23 | import org.mockito.junit.MockitoJUnitRunner; |
... | ... | @@ -28,6 +30,11 @@ public class JsonConverterTest { |
28 | 30 | |
29 | 31 | private static final JsonParser JSON_PARSER = new JsonParser(); |
30 | 32 | |
33 | + @Before | |
34 | + public void before() { | |
35 | + JsonConverter.setTypeCastEnabled(true); | |
36 | + } | |
37 | + | |
31 | 38 | @Test |
32 | 39 | public void testParseBigDecimalAsLong() { |
33 | 40 | var result = JsonConverter.convertToTelemetry(JSON_PARSER.parse("{\"meterReadingDelta\": 1E+1}"), 0L); |
... | ... | @@ -58,4 +65,33 @@ public class JsonConverterTest { |
58 | 65 | Assert.assertEquals(11L, result.get(0L).get(0).getLongValue().get().longValue()); |
59 | 66 | } |
60 | 67 | |
68 | + @Test | |
69 | + public void testParseBigDecimalAsStringOutOfLongRange() { | |
70 | + var result = JsonConverter.convertToTelemetry(JSON_PARSER.parse("{\"meterReadingDelta\": 9.9701010061400066E19}"), 0L); | |
71 | + Assert.assertEquals("99701010061400066000", result.get(0L).get(0).getStrValue().get()); | |
72 | + } | |
73 | + | |
74 | + @Test | |
75 | + public void testParseBigDecimalAsStringOutOfLongRange2() { | |
76 | + var result = JsonConverter.convertToTelemetry(JSON_PARSER.parse("{\"meterReadingDelta\": 99701010061400066001}"), 0L); | |
77 | + Assert.assertEquals("99701010061400066001", result.get(0L).get(0).getStrValue().get()); | |
78 | + } | |
79 | + | |
80 | + @Test | |
81 | + public void testParseBigDecimalAsStringOutOfLongRange3() { | |
82 | + var result = JsonConverter.convertToTelemetry(JSON_PARSER.parse("{\"meterReadingDelta\": 1E19}"), 0L); | |
83 | + Assert.assertEquals("10000000000000000000", result.get(0L).get(0).getStrValue().get()); | |
84 | + } | |
85 | + | |
86 | + @Test(expected = JsonSyntaxException.class) | |
87 | + public void testParseBigDecimalOutOfLongRangeWithoutParsing() { | |
88 | + JsonConverter.setTypeCastEnabled(false); | |
89 | + JsonConverter.convertToTelemetry(JSON_PARSER.parse("{\"meterReadingDelta\": 89701010051400054084}"), 0L); | |
90 | + } | |
91 | + | |
92 | + @Test(expected = JsonSyntaxException.class) | |
93 | + public void testParseBigDecimalOutOfLongRangeWithoutParsing2() { | |
94 | + JsonConverter.setTypeCastEnabled(false); | |
95 | + JsonConverter.convertToTelemetry(JSON_PARSER.parse("{\"meterReadingDelta\": 9.9701010061400066E19}"), 0L); | |
96 | + } | |
61 | 97 | } | ... | ... |
... | ... | @@ -63,7 +63,7 @@ BEGIN |
63 | 63 | into max_customer_ttl; |
64 | 64 | max_ttl := GREATEST(system_ttl, max_customer_ttl, max_tenant_ttl); |
65 | 65 | if max_ttl IS NOT NULL AND max_ttl > 0 THEN |
66 | - date := to_timestamp(EXTRACT(EPOCH FROM current_timestamp) - (max_ttl / 1000)); | |
66 | + date := to_timestamp(EXTRACT(EPOCH FROM current_timestamp) - max_ttl); | |
67 | 67 | partition_by_max_ttl_date := get_partition_by_max_ttl_date(partition_type, date); |
68 | 68 | RAISE NOTICE 'Partition by max ttl: %', partition_by_max_ttl_date; |
69 | 69 | IF partition_by_max_ttl_date IS NOT NULL THEN |
... | ... | @@ -104,11 +104,12 @@ BEGIN |
104 | 104 | END IF; |
105 | 105 | END IF; |
106 | 106 | END IF; |
107 | - END IF; | |
108 | - IF partition_to_delete IS NOT NULL THEN | |
109 | - RAISE NOTICE 'Partition to delete by max ttl: %', partition_to_delete; | |
110 | - EXECUTE format('DROP TABLE %I', partition_to_delete); | |
111 | - deleted := deleted + 1; | |
107 | + IF partition_to_delete IS NOT NULL THEN | |
108 | + RAISE NOTICE 'Partition to delete by max ttl: %', partition_to_delete; | |
109 | + EXECUTE format('DROP TABLE IF EXISTS %I', partition_to_delete); | |
110 | + partition_to_delete := NULL; | |
111 | + deleted := deleted + 1; | |
112 | + END IF; | |
112 | 113 | END IF; |
113 | 114 | END LOOP; |
114 | 115 | END IF; | ... | ... |
... | ... | @@ -48,6 +48,7 @@ |
48 | 48 | <json-path.version>2.2.0</json-path.version> |
49 | 49 | <junit.version>4.12</junit.version> |
50 | 50 | <jupiter.version>5.7.1</jupiter.version> |
51 | + <hamcrest.version>2.2</hamcrest.version> | |
51 | 52 | <slf4j.version>1.7.7</slf4j.version> |
52 | 53 | <logback.version>1.2.3</logback.version> |
53 | 54 | <mockito.version>3.3.3</mockito.version> |
... | ... | @@ -94,7 +95,7 @@ |
94 | 95 | <hsqldb.version>2.5.0</hsqldb.version> |
95 | 96 | <dbunit.version>2.5.3</dbunit.version> |
96 | 97 | <spring-test-dbunit.version>1.2.1</spring-test-dbunit.version> |
97 | - <postgresql.driver.version>42.2.16</postgresql.driver.version> | |
98 | + <postgresql.driver.version>42.2.20</postgresql.driver.version> | |
98 | 99 | <sonar.exclusions>org/thingsboard/server/gen/**/*, |
99 | 100 | org/thingsboard/server/extensions/core/plugin/telemetry/gen/**/* |
100 | 101 | </sonar.exclusions> |
... | ... | @@ -1372,6 +1373,12 @@ |
1372 | 1373 | <scope>test</scope> |
1373 | 1374 | </dependency> |
1374 | 1375 | <dependency> |
1376 | + <groupId>org.hamcrest</groupId> | |
1377 | + <artifactId>hamcrest</artifactId> | |
1378 | + <version>${hamcrest.version}</version> | |
1379 | + <scope>test</scope> | |
1380 | + </dependency> | |
1381 | + <dependency> | |
1375 | 1382 | <groupId>org.junit.jupiter</groupId> |
1376 | 1383 | <artifactId>junit-jupiter-params</artifactId> |
1377 | 1384 | <version>${jupiter.version}</version> | ... | ... |