Skip to content

Commit 82776bc

Browse files
committed
Merge branch 'master' of https://github.com/influxdata/influxdb-java into feature/create-drop-rp
2 parents f87797f + 7d94535 commit 82776bc

File tree

6 files changed

+136
-23
lines changed

6 files changed

+136
-23
lines changed

CHANGELOG.md

+11-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,17 @@
1-
## v2.7 [unreleased]
1+
## 2.8 [unreleased]
2+
3+
#### Fixes
4+
5+
- InfluxDBResultMapper now is able to process QueryResult created when a GROUP BY clause was used [PR #345](https://github.com/influxdata/influxdb-java/pull/345)
6+
- InfluxDB will now handle the timestamp on its own if none is provided [PR#350](https://github.com/influxdata/influxdb-java/pull/350)
7+
8+
9+
## v2.7 [2017-06-26]
210

311
#### Features
412

513
- Simplify write() methods for use cases writing all points to same database and retention policy [PR #327](https://github.com/influxdata/influxdb-java/pull/327)
14+
- QueryResult to Object mapper added [PR #341](https://github.com/influxdata/influxdb-java/pull/341)
615

716
#### Fixes
817

@@ -13,7 +22,7 @@
1322
- Significant (~35%) performance improvements for write speed with less memory footprint. [PR #330](https://github.com/influxdata/influxdb-java/pull/330)
1423
- Drop guava runtime dependency which reduces jar size from 1MB -> 49KB [PR #322](https://github.com/influxdata/influxdb-java/pull/322)
1524

16-
## v2.6 [2017.06-08]
25+
## v2.6 [2017-06-08]
1726

1827
#### Features
1928

README.md

+6-5
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ influxDB.query(query, 20, queryResult -> System.out.println(queryResult));
146146
```
147147

148148

149-
#### QueryResult mapper to POJO (version 2.7+ required, unreleased):
149+
#### QueryResult mapper to POJO (version 2.7+ required):
150150

151151
An alternative way to handle the QueryResult object is now available.
152152
Supposing that you have a measurement _CPU_:
@@ -206,13 +206,14 @@ InfluxDB influxDB = InfluxDBFactory.connect("http://localhost:8086", "root", "ro
206206
String dbName = "myTimeseries";
207207
QueryResult queryResult = influxDB.query(new Query("SELECT * FROM cpu", dbName));
208208
209-
InfluxResultMapper resultMapper = new InfluxResultMapper(); // thread-safe - can be reused
209+
InfluxDBResultMapper resultMapper = new InfluxDBResultMapper(); // thread-safe - can be reused
210210
List<Cpu> cpuList = resultMapper.toPOJO(queryResult, Cpu.class);
211211
```
212212
**QueryResult mapper limitations**
213213
- If your InfluxDB query contains multiple SELECT clauses, you will have to call InfluxResultMapper#toPOJO() multiple times to map every measurement returned by QueryResult to the respective POJO;
214214
- If your InfluxDB query contains multiple SELECT clauses **for the same measurement**, InfluxResultMapper will process all results because there is no way to distinguish which one should be mapped to your POJO. It may result in an invalid collection being returned;
215-
215+
- A Class field annotated with _@Column(..., tag = true)_ (i.e. a [InfluxDB Tag](https://docs.influxdata.com/influxdb/v1.2/concepts/glossary/#tag-value)) must be declared as _String_.
216+
-- _Note: With the current released version (2.7), InfluxDBResultMapper does not support QueryResult created by queries using the "GROUP BY" clause. This was fixed by [PR #345](https://github.com/influxdata/influxdb-java/pull/345)._
216217

217218
### Other Usages:
218219
For additional usage examples have a look at [InfluxDBTest.java](https://github.com/influxdb/influxdb-java/blob/master/src/test/java/org/influxdb/InfluxDBTest.java "InfluxDBTest.java")
@@ -224,12 +225,12 @@ The latest version for maven dependence:
224225
<dependency>
225226
<groupId>org.influxdb</groupId>
226227
<artifactId>influxdb-java</artifactId>
227-
<version>2.6</version>
228+
<version>2.7</version>
228229
</dependency>
229230
```
230231
Or when using with gradle:
231232
```groovy
232-
compile 'org.influxdb:influxdb-java:2.6'
233+
compile 'org.influxdb:influxdb-java:2.7'
233234
```
234235
For version change history have a look at [ChangeLog](https://github.com/influxdata/influxdb-java/blob/master/CHANGELOG.md).
235236

pom.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<groupId>org.influxdb</groupId>
55
<artifactId>influxdb-java</artifactId>
66
<packaging>jar</packaging>
7-
<version>2.7-SNAPSHOT</version>
7+
<version>2.8-SNAPSHOT</version>
88
<name>influxdb java bindings</name>
99
<description>Java API to access the InfluxDB REST API</description>
1010
<url>http://www.influxdb.org</url>

src/main/java/org/influxdb/dto/Point.java

+12-8
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ public static final class Builder {
6969
private final String measurement;
7070
private final Map<String, String> tags = new TreeMap<>();
7171
private Long time;
72-
private TimeUnit precision = TimeUnit.NANOSECONDS;
72+
private TimeUnit precision;
7373
private final Map<String, Object> fields = new TreeMap<>();
7474

7575
/**
@@ -207,9 +207,6 @@ public Point build() {
207207
if (this.time != null) {
208208
point.setTime(this.time);
209209
point.setPrecision(this.precision);
210-
} else {
211-
point.setTime(System.currentTimeMillis());
212-
point.setPrecision(TimeUnit.MILLISECONDS);
213210
}
214211
point.setTags(this.tags);
215212
return point;
@@ -292,12 +289,16 @@ public String toString() {
292289
StringBuilder builder = new StringBuilder();
293290
builder.append("Point [name=");
294291
builder.append(this.measurement);
295-
builder.append(", time=");
296-
builder.append(this.time);
292+
if (this.time != null) {
293+
builder.append(", time=");
294+
builder.append(this.time);
295+
}
297296
builder.append(", tags=");
298297
builder.append(this.tags);
299-
builder.append(", precision=");
300-
builder.append(this.precision);
298+
if (this.precision != null) {
299+
builder.append(", precision=");
300+
builder.append(this.precision);
301+
}
301302
builder.append(", fields=");
302303
builder.append(this.fields);
303304
builder.append("]");
@@ -368,6 +369,9 @@ private void concatenatedFields(final StringBuilder sb) {
368369
}
369370

370371
private void formatedTime(final StringBuilder sb) {
372+
if (this.time == null || this.precision == null) {
373+
return;
374+
}
371375
sb.append(' ').append(TimeUnit.NANOSECONDS.convert(this.time, this.precision));
372376
}
373377

src/main/java/org/influxdb/impl/InfluxDBResultMapper.java

+18-6
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import java.util.LinkedList;
2929
import java.util.List;
3030
import java.util.Objects;
31+
import java.util.Map.Entry;
3132
import java.util.concurrent.ConcurrentHashMap;
3233
import java.util.concurrent.ConcurrentMap;
3334
import java.util.concurrent.TimeUnit;
@@ -147,19 +148,32 @@ String getMeasurementName(final Class<?> clazz) {
147148

148149
<T> List<T> parseSeriesAs(final QueryResult.Series series, final Class<T> clazz, final List<T> result) {
149150
int columnSize = series.getColumns().size();
151+
ConcurrentMap<String, Field> colNameAndFieldMap = CLASS_FIELD_CACHE.get(clazz.getName());
150152
try {
151153
T object = null;
152154
for (List<Object> row : series.getValues()) {
153155
for (int i = 0; i < columnSize; i++) {
154-
String resultColumnName = series.getColumns().get(i);
155-
Field correspondingField = CLASS_FIELD_CACHE.get(clazz.getName()).get(resultColumnName);
156+
Field correspondingField = colNameAndFieldMap.get(series.getColumns().get(i)/*InfluxDB columnName*/);
156157
if (correspondingField != null) {
157158
if (object == null) {
158159
object = clazz.newInstance();
159160
}
160161
setFieldValue(object, correspondingField, row.get(i));
161162
}
162163
}
164+
// When the "GROUP BY" clause is used, "tags" are returned as Map<String,String> and
165+
// accordingly with InfluxDB documentation
166+
// https://docs.influxdata.com/influxdb/v1.2/concepts/glossary/#tag-value
167+
// "tag" values are always String.
168+
if (series.getTags() != null && !series.getTags().isEmpty()) {
169+
for (Entry<String, String> entry : series.getTags().entrySet()) {
170+
Field correspondingField = colNameAndFieldMap.get(entry.getKey()/*InfluxDB columnName*/);
171+
if (correspondingField != null) {
172+
// I don't think it is possible to reach here without a valid "object"
173+
setFieldValue(object, correspondingField, entry.getValue());
174+
}
175+
}
176+
}
163177
if (object != null) {
164178
result.add(object);
165179
object = null;
@@ -233,8 +247,7 @@ <T> boolean fieldValueModified(final Class<?> fieldType, final Field field, fina
233247
}
234248

235249
<T> boolean fieldValueForPrimitivesModified(final Class<?> fieldType, final Field field, final T object,
236-
final Object value)
237-
throws IllegalArgumentException, IllegalAccessException {
250+
final Object value) throws IllegalArgumentException, IllegalAccessException {
238251
if (double.class.isAssignableFrom(fieldType)) {
239252
field.setDouble(object, ((Double) value).doubleValue());
240253
return true;
@@ -255,8 +268,7 @@ <T> boolean fieldValueForPrimitivesModified(final Class<?> fieldType, final Fiel
255268
}
256269

257270
<T> boolean fieldValueForPrimitiveWrappersModified(final Class<?> fieldType, final Field field, final T object,
258-
final Object value)
259-
throws IllegalArgumentException, IllegalAccessException {
271+
final Object value) throws IllegalArgumentException, IllegalAccessException {
260272
if (Double.class.isAssignableFrom(fieldType)) {
261273
field.set(object, value);
262274
return true;

src/test/java/org/influxdb/impl/InfluxDBResultMapperTest.java

+88-1
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,10 @@
2626
import java.time.Instant;
2727
import java.util.Arrays;
2828
import java.util.Date;
29+
import java.util.HashMap;
2930
import java.util.LinkedList;
3031
import java.util.List;
32+
import java.util.Map;
3133
import java.util.Random;
3234
import java.util.UUID;
3335

@@ -243,7 +245,61 @@ public void testToPOJO_SeriesFromQueryResultIsNull() {
243245
// Then...
244246
assertTrue("there must NO entry in the result list", myList.isEmpty());
245247
}
246-
248+
249+
@Test
250+
public void testToPOJO_QueryResultCreatedByGroupByClause() {
251+
// Given...
252+
mapper.cacheMeasurementClass(GroupByCarrierDeviceOS.class);
253+
254+
List<String> columnList = Arrays.asList("time", "median", "min", "max");
255+
256+
// InfluxDB client returns the time representation as Double.
257+
Double now = Long.valueOf(System.currentTimeMillis()).doubleValue();
258+
259+
List<Object> firstSeriesResult = Arrays.asList(now, new Double("233.8"), new Double("0.0"),
260+
new Double("3090744.0"));
261+
// When the "GROUP BY" clause is used, "tags" are returned as Map<String,String>
262+
Map<String, String> firstSeriesTagMap = new HashMap<>();
263+
firstSeriesTagMap.put("CARRIER", "000/00");
264+
firstSeriesTagMap.put("DEVICE_OS_VERSION", "4.4.2");
265+
266+
List<Object> secondSeriesResult = Arrays.asList(now, new Double("552.0"), new Double("135.0"),
267+
new Double("267705.0"));
268+
Map<String, String> secondSeriesTagMap = new HashMap<>();
269+
secondSeriesTagMap.put("CARRIER", "000/01");
270+
secondSeriesTagMap.put("DEVICE_OS_VERSION", "9.3.5");
271+
272+
QueryResult.Series firstSeries = new QueryResult.Series();
273+
firstSeries.setColumns(columnList);
274+
firstSeries.setValues(Arrays.asList(firstSeriesResult));
275+
firstSeries.setTags(firstSeriesTagMap);
276+
firstSeries.setName("tb_network");
277+
278+
QueryResult.Series secondSeries = new QueryResult.Series();
279+
secondSeries.setColumns(columnList);
280+
secondSeries.setValues(Arrays.asList(secondSeriesResult));
281+
secondSeries.setTags(secondSeriesTagMap);
282+
secondSeries.setName("tb_network");
283+
284+
QueryResult.Result internalResult = new QueryResult.Result();
285+
internalResult.setSeries(Arrays.asList(firstSeries, secondSeries));
286+
287+
QueryResult queryResult = new QueryResult();
288+
queryResult.setResults(Arrays.asList(internalResult));
289+
290+
// When...
291+
List<GroupByCarrierDeviceOS> myList = mapper.toPOJO(queryResult, GroupByCarrierDeviceOS.class);
292+
293+
// Then...
294+
GroupByCarrierDeviceOS firstGroupByEntry = myList.get(0);
295+
assertEquals("field 'carrier' does not match", "000/00", firstGroupByEntry.carrier);
296+
assertEquals("field 'deviceOsVersion' does not match", "4.4.2", firstGroupByEntry.deviceOsVersion);
297+
298+
GroupByCarrierDeviceOS secondGroupByEntry = myList.get(1);
299+
assertEquals("field 'carrier' does not match", "000/01", secondGroupByEntry.carrier);
300+
assertEquals("field 'deviceOsVersion' does not match", "9.3.5", secondGroupByEntry.deviceOsVersion);
301+
}
302+
247303
@Measurement(name = "CustomMeasurement")
248304
static class MyCustomMeasurement {
249305

@@ -297,4 +353,35 @@ static class MyPojoWithUnsupportedField {
297353
@Column(name = "bar")
298354
private Date myDate;
299355
}
356+
357+
/**
358+
* Class created based on example from https://github.com/influxdata/influxdb-java/issues/343
359+
*/
360+
@Measurement(name = "tb_network")
361+
static class GroupByCarrierDeviceOS {
362+
363+
@Column(name = "time")
364+
private Instant time;
365+
366+
@Column(name = "CARRIER", tag = true)
367+
private String carrier;
368+
369+
@Column(name = "DEVICE_OS_VERSION", tag = true)
370+
private String deviceOsVersion;
371+
372+
@Column(name = "median")
373+
private Double median;
374+
375+
@Column(name = "min")
376+
private Double min;
377+
378+
@Column(name = "max")
379+
private Double max;
380+
381+
@Override
382+
public String toString() {
383+
return "GroupByCarrierDeviceOS [time=" + time + ", carrier=" + carrier + ", deviceOsVersion=" + deviceOsVersion
384+
+ ", median=" + median + ", min=" + min + ", max=" + max + "]";
385+
}
386+
}
300387
}

0 commit comments

Comments
 (0)