Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue/1863 mysql sink quote fields #1865

Merged
merged 14 commits into from
Sep 17, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.metadata
target/
# IntelliJ local files
*.idea
Expand Down
4 changes: 2 additions & 2 deletions CHANGES_NEXT_RELEASE
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[cygnus-common][SQLBackendImpl] Add configuration option to persist errors in SQL sinks (#1928)
[cygnus-common][SQLBackendImpl] Add configuration option to persist errors in SQL sinks (#1928)
[cygnus-ngsi-ld] Creation of the new PostGIS sink for persisting NGSI-LD notifications (#1905)

[cygnus-ngsi][MysqlSink] Quoted Sql field names to avoid naming problems. (#1863)
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
*/
public class NGSIMySQLSink extends NGSISink {

private static final String MYSQL_QUOTE_CHAR = "`";
private static final String DEFAULT_ROW_ATTR_PERSISTENCE = "row";
private static final String DEFAULT_PASSWORD = "";
private static final String DEFAULT_PORT = "3306";
Expand Down Expand Up @@ -364,7 +365,7 @@ protected NGSIGenericAggregator getAggregator(boolean rowAttrPersistence) {
private void persistAggregation(NGSIGenericAggregator aggregator)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An entry in CHANGES_NEXT_RELEASE describing the fix and citing #1863 should be included, using the usual style.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 9010472

throws CygnusPersistenceError, CygnusRuntimeError, CygnusBadContextData {
String fieldsForCreate = NGSIUtils.getFieldsForCreate(aggregator.getAggregationToPersist());
String fieldsForInsert = NGSIUtils.getFieldsForInsert(aggregator.getAggregationToPersist());
String fieldsForInsert = NGSIUtils.getFieldsForInsert(aggregator.getAggregationToPersist(), MYSQL_QUOTE_CHAR);
String valuesForInsert = NGSIUtils.getValuesForInsert(aggregator.getAggregationToPersist(), aggregator.isAttrNativeTypes());
String dbName = aggregator.getDbName(enableLowercase);
String tableName = aggregator.getTableName(enableLowercase);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import com.google.gson.JsonObject;
import com.telefonica.iot.cygnus.log.CygnusLogger;

import java.lang.reflect.Array;
import java.util.*;
import java.util.regex.Pattern;
import org.apache.commons.lang3.tuple.ImmutablePair;
Expand All @@ -31,8 +30,6 @@
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;

import static java.io.File.separator;

/**
*
* @author frb
Expand Down Expand Up @@ -271,15 +268,26 @@ public static String getFieldsForCreate(LinkedHashMap<String, ArrayList<JsonElem
* @return the fields (column names) for insert in SQL format.
*/
public static String getFieldsForInsert(LinkedHashMap<String, ArrayList<JsonElement>> aggregation) {
return getFieldsForInsert(aggregation, "");
}

/**
* Gets fields for insert.
*
* @param aggregation the aggregation
* @param quoteChar char to quote field names
* @return he fields (column names) for insert in SQL format.
*/
public static String getFieldsForInsert(LinkedHashMap<String, ArrayList<JsonElement>> aggregation, String quoteChar) {
String fieldsForInsert = "(";
boolean first = true;
Iterator<String> it = aggregation.keySet().iterator();
while (it.hasNext()) {
if (first) {
fieldsForInsert += (String) it.next();
fieldsForInsert += quoteChar + (String) it.next() + quoteChar;
first = false;
} else {
fieldsForInsert += "," + (String) it.next();
fieldsForInsert += "," + quoteChar + (String) it.next() + quoteChar;
} // if else
} // while
return fieldsForInsert + ")";
Expand Down Expand Up @@ -398,7 +406,7 @@ public static ArrayList<String> attributeNames(LinkedHashMap<String, ArrayList<J
attributeNames.remove(NGSIConstants.FIWARE_SERVICE_PATH);
attributeNames.remove(NGSIConstants.ENTITY_ID);
attributeNames.remove(NGSIConstants.ENTITY_TYPE);
ArrayList <String> cropedList = (ArrayList<String>) attributeNames.clone();
ArrayList<String> cropedList = (ArrayList<String>) attributeNames.clone();
for (String key : cropedList) {
if (key.contains("_md") || key.contains(NGSIConstants.AUTOGENERATED_ATTR_TYPE)) {
attributeNames.remove(key);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,30 +18,36 @@
package com.telefonica.iot.cygnus.utils;

import static com.telefonica.iot.cygnus.utils.CommonUtilsForTests.getTestTraceHead;
import static org.junit.Assert.assertEquals;

import java.util.ArrayList;
import java.util.LinkedHashMap;

import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.log4j.Level;
import org.apache.log4j.LogManager;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import static org.junit.Assert.assertEquals;
import org.junit.Test;

import com.google.gson.JsonElement;

/**
*
* @author frb
*/
public class NGSIUtilsTest {

/**
* Constructor.
*/
public NGSIUtilsTest() {
LogManager.getRootLogger().setLevel(Level.FATAL);
} // NGSIUtilsTest

/**
* [NGSIUtils.getGeometry] -------- When getting a geometry, a CartoDB point is obtained when passing
* an attribute of type 'geo:point'.
* [NGSIUtils.getGeometry] -------- When getting a geometry, a CartoDB point
* is obtained when passing an attribute of type 'geo:point'.
*/
@Test
public void testGetGeometryGeopoint() {
Expand All @@ -52,25 +58,24 @@ public void testGetGeometryGeopoint() {
String attrValue = "-3.7167, 40.3833";
String attrType = "geo:point";
boolean swapCoordinates = false; // irrelevant for this test
ImmutablePair<String, Boolean> geometry = NGSIUtils.getGeometry(
attrValue, attrType, attrMetadataStr, swapCoordinates);
ImmutablePair<String, Boolean> geometry = NGSIUtils.getGeometry(attrValue, attrType, attrMetadataStr,
swapCoordinates);

try {
assertEquals("ST_SetSRID(ST_MakePoint(-3.7167::double precision , 40.3833::double precision ), 4326)", geometry.getLeft());
System.out.println(getTestTraceHead("[Utils.getLocation]")
+ "- OK - Geometry '" + geometry.getLeft() + "' obtained for an attribute of type '" + attrType
+ "' and value '" + attrValue + "'");
assertEquals("ST_SetSRID(ST_MakePoint(-3.7167::double precision , 40.3833::double precision ), 4326)",
geometry.getLeft());
System.out.println(getTestTraceHead("[Utils.getLocation]") + "- OK - Geometry '" + geometry.getLeft()
+ "' obtained for an attribute of type '" + attrType + "' and value '" + attrValue + "'");
} catch (AssertionError e) {
System.out.println(getTestTraceHead("[Utils.getLocation]")
+ "- FAIL - Geometry '" + geometry.getLeft() + "' obtained for an attribute of type '" + attrType
+ "' and value '" + attrValue + "'");
System.out.println(getTestTraceHead("[Utils.getLocation]") + "- FAIL - Geometry '" + geometry.getLeft()
+ "' obtained for an attribute of type '" + attrType + "' and value '" + attrValue + "'");
throw e;
} // try catch // try catch
} // testGetGeometryGeopoint

/**
* [NGSIUtils.getGeometry] -------- When getting a geometry, a CartoDB point is obtained when passing
* an attribute with 'geometry' metadata.
* [NGSIUtils.getGeometry] -------- When getting a geometry, a CartoDB point
* is obtained when passing an attribute with 'geometry' metadata.
*/
@Test
public void testGetGeometryMetadata() {
Expand All @@ -87,25 +92,27 @@ public void testGetGeometryMetadata() {
String attrValue = "-3.7167, 40.3833";
String attrType = "coordinates"; // irrelevant for this test
boolean swapCoordinates = false; // irrelevant for this test
ImmutablePair<String, Boolean> geometry = NGSIUtils.getGeometry(
attrValue, attrType, attrMetadataStr, swapCoordinates);
ImmutablePair<String, Boolean> geometry = NGSIUtils.getGeometry(attrValue, attrType, attrMetadataStr,
swapCoordinates);

try {
assertEquals("ST_SetSRID(ST_MakePoint(-3.7167::double precision , 40.3833::double precision ), 4326)", geometry.getLeft());
System.out.println(getTestTraceHead("[Utils.getLocation]")
+ "- OK - Geometry '" + geometry.getLeft() + "' obtained for an attribute with metadata '"
+ attrMetadataStr + "' and value '" + attrValue + "'");
assertEquals("ST_SetSRID(ST_MakePoint(-3.7167::double precision , 40.3833::double precision ), 4326)",
geometry.getLeft());
System.out.println(getTestTraceHead("[Utils.getLocation]") + "- OK - Geometry '" + geometry.getLeft()
+ "' obtained for an attribute with metadata '" + attrMetadataStr + "' and value '" + attrValue
+ "'");
} catch (AssertionError e) {
System.out.println(getTestTraceHead("[Utils.getLocation]")
+ "- FAIL - Geometry '" + geometry.getLeft() + "' obtained for an attribute with metadata '"
+ attrMetadataStr + "' and value '" + attrValue + "'");
System.out.println(getTestTraceHead("[Utils.getLocation]") + "- FAIL - Geometry '" + geometry.getLeft()
+ "' obtained for an attribute with metadata '" + attrMetadataStr + "' and value '" + attrValue
+ "'");
throw e;
} // try catch // try catch
} // testGetGeometryMetadata

/**
* [NGSIUtils.getGeometry] -------- When getting a geometry, the original attribute is returned when the
* attribute type is not geo:point and there is no WGS84 geometry metadata.
* [NGSIUtils.getGeometry] -------- When getting a geometry, the original
* attribute is returned when the attribute type is not geo:point and there
* is no WGS84 geometry metadata.
*/
@Test
public void testGetGeometryNoGeolocation() {
Expand All @@ -116,23 +123,23 @@ public void testGetGeometryNoGeolocation() {
String attrValue = "-3.7167, 40.3833";
String attrType = "coordinates";
boolean swapCoordinates = false; // irrelevant for this test
ImmutablePair<String, Boolean> geometry = NGSIUtils.getGeometry(
attrValue, attrType, attrMetadataStr, swapCoordinates);
ImmutablePair<String, Boolean> geometry = NGSIUtils.getGeometry(attrValue, attrType, attrMetadataStr,
swapCoordinates);

try {
assertEquals(attrValue, geometry.getLeft());
System.out.println(getTestTraceHead("[Utils.getLocation]")
+ "- OK - Geometry '" + geometry.getLeft() + "' obtained for a not geolocated attribute");
System.out.println(getTestTraceHead("[Utils.getLocation]") + "- OK - Geometry '" + geometry.getLeft()
+ "' obtained for a not geolocated attribute");
} catch (AssertionError e) {
System.out.println(getTestTraceHead("[Utils.getLocation]")
+ "- FAIL - Geometry '" + geometry.getLeft() + "' obtained for a not geolocated attribute");
System.out.println(getTestTraceHead("[Utils.getLocation]") + "- FAIL - Geometry '" + geometry.getLeft()
+ "' obtained for a not geolocated attribute");
throw e;
} // try catch // try catch
} // testGetGeometryNoGeolocation

/**
* [NGSIUtils.getGeometry] -------- When getting a geometry, a CartoDB geometry is obtained when passing
* an attribute of type 'geo:json'.
* [NGSIUtils.getGeometry] -------- When getting a geometry, a CartoDB
* geometry is obtained when passing an attribute of type 'geo:json'.
*/
@Test
public void testGetGeometryGeojson() {
Expand All @@ -143,20 +150,73 @@ public void testGetGeometryGeojson() {
String attrValue = "{\"coordinates\": [-3.7167, 40.3833], \"type\": \"Point\"}";
String attrType = "geo:json";
boolean swapCoordinates = false; // irrelevant for this test
ImmutablePair<String, Boolean> geometry = NGSIUtils.getGeometry(
attrValue, attrType, attrMetadataStr, swapCoordinates);
ImmutablePair<String, Boolean> geometry = NGSIUtils.getGeometry(attrValue, attrType, attrMetadataStr,
swapCoordinates);

try {
assertEquals("ST_GeomFromGeoJSON('{\"coordinates\": [-3.7167, 40.3833], \"type\": \"Point\"}')", geometry.getLeft());
System.out.println(getTestTraceHead("[Utils.getLocation]")
+ "- OK - Geometry '" + geometry.getLeft() + "' obtained for an attribute of type '" + attrType
+ "' and value '" + attrValue + "'");
assertEquals("ST_GeomFromGeoJSON('{\"coordinates\": [-3.7167, 40.3833], \"type\": \"Point\"}')",
geometry.getLeft());
System.out.println(getTestTraceHead("[Utils.getLocation]") + "- OK - Geometry '" + geometry.getLeft()
+ "' obtained for an attribute of type '" + attrType + "' and value '" + attrValue + "'");
} catch (AssertionError e) {
System.out.println(getTestTraceHead("[Utils.getLocation]")
+ "- FAIL - Geometry '" + geometry.getLeft() + "' obtained for an attribute of type '" + attrType
+ "' and value '" + attrValue + "'");
System.out.println(getTestTraceHead("[Utils.getLocation]") + "- FAIL - Geometry '" + geometry.getLeft()
+ "' obtained for an attribute of type '" + attrType + "' and value '" + attrValue + "'");
throw e;
} // try catch // try catch
} // testGetGeometryGeojson

/**
* [NGSIUtils.getFieldsForInsert] -------- Get fields to insert with quotes
*/
@Test
public void testGetFieldForInsertWithQuotes() {
LinkedHashMap<String, ArrayList<JsonElement>> aggregation = getValueFields();
String resultCompare = "(`recvTime`,`fiwareServicePath`,`entityId`,`entityType`,`load`,`load_md`)";
String result = NGSIUtils.getFieldsForInsert(aggregation, "`");
try {
assertEquals(resultCompare, result);
System.out.println(String.format("%s - OK - getFieldForInsert '%s' is the same as '%s'",
getTestTraceHead("[NGSIUtils.getFieldsForInsert]"), result, resultCompare));
} catch (AssertionError e) {
System.err.println(String.format("%s - FAIL - getFieldForInsert '%s' is different from '%s'",
getTestTraceHead("[NGSIUtils.getFieldsForInsert]"), result, resultCompare));
throw e;
} // try catch
}// testGetFieldForInsertWithQuotes

/**
* [NGSIUtils.getFieldsForInsert] -------- Get fields to insert without
* quotes
*/
@Test
public void testGetFieldForInsertWithoutQuotes() {
LinkedHashMap<String, ArrayList<JsonElement>> aggregation = getValueFields();
String resultCompare = "(recvTime,fiwareServicePath,entityId,entityType,load,load_md)";
String result = NGSIUtils.getFieldsForInsert(aggregation);
try {
assertEquals(resultCompare, result);
System.out.println(String.format("%s - OK - getFieldForInsert '%s' is the same as '%s'",
getTestTraceHead("[NGSIUtils.getFieldsForInsert]"), result, resultCompare));
} catch (AssertionError e) {
System.err.println(String.format("%s - FAIL - getFieldForInsert '%s' is different from '%s'",
getTestTraceHead("[NGSIUtils.getFieldsForInsert]"), result, resultCompare));
throw e;
} // try catch

}// testGetFieldForInsertWithoutQuotes

/**
* It's a mock field
*/
private LinkedHashMap<String, ArrayList<JsonElement>> getValueFields() {
LinkedHashMap<String, ArrayList<JsonElement>> aggregation = new LinkedHashMap<String, ArrayList<JsonElement>>();
aggregation.put("recvTime", null);
aggregation.put("fiwareServicePath", null);
aggregation.put("entityId", null);
aggregation.put("entityType", null);
aggregation.put("load", null);
aggregation.put("load_md", null);
return aggregation;
}// getValueFields

} // NGSIUtilsTest