Skip to content

Commit

Permalink
Merge pull request #553 from grails/449-the-old-parameter-syntax-para…
Browse files Browse the repository at this point in the history
…m-is-no-longer-supported-please-use-$param-instead

Use $param instead of the old parameter syntax {param}
  • Loading branch information
puneetbehl authored Sep 10, 2023
2 parents 5b7dbe3 + 64131d2 commit 25dee15
Show file tree
Hide file tree
Showing 13 changed files with 45 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ trait Neo4jEntity<D> implements GormEntity<D>, DynamicAttributes {
GormEnhancer.findDatastore(getClass()).withSession { Neo4jSession session ->
Map<String, Object> arguments
if (session.getDatastore().multiTenancyMode == MultiTenancySettings.MultiTenancyMode.DISCRIMINATOR) {
if (!queryString.contains("{tenantId}")) {
if (!queryString.contains("\$tenantId")) {
throw new TenantNotFoundException("Query does not specify a tenant id, but multi tenant mode is DISCRIMINATOR!")
} else {
arguments = new LinkedHashMap<String, Object>()
Expand Down Expand Up @@ -265,7 +265,7 @@ trait Neo4jEntity<D> implements GormEntity<D>, DynamicAttributes {

private void includeTenantIdIfNecessary(Neo4jSession session, String queryString, Map<String, Object> paramsMap) {
if ((this instanceof MultiTenant) && session.getDatastore().multiTenancyMode == MultiTenancySettings.MultiTenancyMode.DISCRIMINATOR) {
if (!queryString.contains("{tenantId}")) {
if (!queryString.contains("\$tenantId")) {
throw new TenantNotFoundException("Query does not specify a tenant id, but multi tenant mode is DISCRIMINATOR!")
} else {
paramsMap.put(GormProperties.TENANT_IDENTITY, Tenants.currentId(Neo4jDatastore))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class GraphPersistentEntity extends AbstractPersistentEntity<NodeConfig> {

public static final String LABEL_SEPARATOR = ':'
protected static final String MATCH = "MATCH %s"
protected static final String MATCH_ID = "$MATCH WHERE %s = {id}"
protected static final String MATCH_ID = "$MATCH WHERE %s = \$id"
protected final NodeConfig mappedForm
protected final Collection<String> staticLabels = []
protected Collection<Object> labelObjects
Expand Down Expand Up @@ -183,7 +183,7 @@ class GraphPersistentEntity extends AbstractPersistentEntity<NodeConfig> {
*/
String getBatchCreateStatement() {
if(this.batchCreateStatement == null) {
this.batchCreateStatement = formatBatchCreate("{${batchId}}")
this.batchCreateStatement = formatBatchCreate("\$${batchId}")
}
return batchCreateStatement
}
Expand Down Expand Up @@ -215,10 +215,10 @@ class GraphPersistentEntity extends AbstractPersistentEntity<NodeConfig> {
/**
* Formats a dynamic association query
* @param variable The variable to use
* @return The query which accepts an {id} argument
* @return The query which accepts an $id argument
*/
String formatDynamicAssociationQuery(String variable = CypherBuilder.NODE_VAR) {
"""${formatMatch(variable)}-[r]-(o) WHERE ${formatId(variable)} = {${GormProperties.IDENTITY}} RETURN type(r) as relType, startNode(r) = $variable as out, r.sourceType as sourceType, r.targetType as targetType, {ids: collect(${formatId("o")}), labels: collect(labels(o))} as values"""
"""${formatMatch(variable)}-[r]-(o) WHERE ${formatId(variable)} = \$${GormProperties.IDENTITY} RETURN type(r) as relType, startNode(r) = $variable as out, r.sourceType as sourceType, r.targetType as targetType, {ids: collect(${formatId("o")}), labels: collect(labels(o))} as values"""
}

/**
Expand Down Expand Up @@ -300,9 +300,9 @@ class GraphPersistentEntity extends AbstractPersistentEntity<NodeConfig> {
StringBuilder builder = new StringBuilder( formatMatchId(variable) )
Class clazz = Long
if(isVersioned() && hasProperty(GormProperties.VERSION, clazz)) {
builder.append(" AND ${variable}.version={version}")
builder.append(" AND ${variable}.version=\$version")
}
builder.append(" SET ").append(variable).append(" +={props}")
builder.append(" SET ").append(variable).append(" +=\$props")
Set keysToRemove = []
for(key in props.keySet()) {
Object v = props.get(key)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -665,7 +665,7 @@ public void buildEntityCreateOperation(StringBuilder createCypher, String index,
Map<String, List<Object>> dynamicRelProps = amendMapWithUndeclaredProperties(graphEntity, simpleProps, obj, getMappingContext());
final String labels = graphEntity.getLabelsWithInheritance(obj);

String cypher = String.format("(n" + index + "%s {props" + index + "})", labels);
String cypher = String.format("(n" + index + "%s $props" + index + ")", labels);
createCypher.append(cypher);
params.put("props" + index, simpleProps);

Expand Down Expand Up @@ -820,12 +820,9 @@ public static boolean isCollectionWithPersistentEntities(Object o, MappingContex
if (!(o instanceof Collection)) {
return false;
} else {
Collection c = (Collection) o;
for (Object obj : c) {
if (mappingContext.isPersistentEntity(obj)) return true;
}
@SuppressWarnings("unchecked") Collection<Object> c = (Collection<Object>) o;
return c.stream().anyMatch(mappingContext::isPersistentEntity);
}
return false;
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ class Neo4jGormStaticApi<D> extends GormStaticApi<D> {
Relationship<F, T> relationship = null
if(from != null && to != null) {
String query = """MATCH (from)-[r]-(to)
WHERE ${fromEntity.formatId(RelationshipPersistentEntity.FROM)} = {start} AND ${toEntity.formatId(RelationshipPersistentEntity.TO)} = {end}
WHERE ${fromEntity.formatId(RelationshipPersistentEntity.FROM)} = \$start AND ${toEntity.formatId(RelationshipPersistentEntity.TO)} = \$end
RETURN r
LIMIT 1"""
List<org.neo4j.driver.types.Relationship> results = executeQuery(query, [start:from.ident(), end:to.ident()])
Expand Down Expand Up @@ -291,7 +291,7 @@ LIMIT 1"""
String skip = params.offset ? " SKIP ${Integer.valueOf(params.offset.toString())}" : ''
String limit = params.max ? " LIMIT ${Integer.valueOf(params.max.toString())}" : ''
String query = """MATCH (from)-[r]-(to)
WHERE ${fromEntity.formatId(RelationshipPersistentEntity.FROM)} = {start} AND ${toEntity.formatId(RelationshipPersistentEntity.TO)} = {end}
WHERE ${fromEntity.formatId(RelationshipPersistentEntity.FROM)} = \$start AND ${toEntity.formatId(RelationshipPersistentEntity.TO)} = \$end
RETURN DISTINCT(r)$skip$limit"""
List<org.neo4j.driver.types.Relationship> results = (List<org.neo4j.driver.types.Relationship>) executeQuery(query, [start:from.ident(), end:to.ident()])

Expand Down Expand Up @@ -370,7 +370,7 @@ RETURN DISTINCT(r), from, to$skip$limit"""
toEntity.formatNode(RelationshipPersistentEntity.TO)
}, p = shortestPath((from)-[*..$maxDistance]-(to)) WHERE ${
fromEntity.formatId(RelationshipPersistentEntity.FROM)
} = {start} AND ${toEntity.formatId(RelationshipPersistentEntity.TO)} = {end} RETURN p"""
} = \$start AND ${toEntity.formatId(RelationshipPersistentEntity.TO)} = \$end RETURN p"""
Result result = cypherStatic(query, [start: fromId, end: toId])
if(result.hasNext()) {
Record record = result.next()
Expand Down Expand Up @@ -452,7 +452,7 @@ RETURN DISTINCT(r), from, to$skip$limit"""
queryString = query.toString()
}
if (persistentEntity.isMultiTenant() && session.getDatastore().multiTenancyMode == MultiTenancySettings.MultiTenancyMode.DISCRIMINATOR) {
if (!queryString.contains("{tenantId}")) {
if (!queryString.contains("\$tenantId")) {
throw new TenantNotFoundException("Query does not specify a tenant id, but multi tenant mode is DISCRIMINATOR!")
} else {
Map<String,Object> paramsMap = new LinkedHashMap<>()
Expand Down Expand Up @@ -511,7 +511,7 @@ RETURN DISTINCT(r), from, to$skip$limit"""

private void includeTenantIdIfNecessary(Neo4jSession session, String queryString, Map<String, Object> paramsMap) {
if (persistentEntity.isMultiTenant() && session.getDatastore().multiTenancyMode == MultiTenancySettings.MultiTenancyMode.DISCRIMINATOR) {
if (!queryString.contains("{tenantId}")) {
if (!queryString.contains("\$tenantId")) {
throw new TenantNotFoundException("Query does not specify a tenant id, but multi tenant mode is DISCRIMINATOR!")
} else {
paramsMap.put(GormProperties.TENANT_IDENTITY, Tenants.currentId(Neo4jDatastore))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ class Neo4jAssociationQueryExecutor implements AssociationQueryExecutor<Serializ
StringBuilder cypher = new StringBuilder(CypherBuilder.buildRelationshipMatch(parent.labelsAsString, relType, related.labelsAsString))
cypher.append('( ')
.append(parent.formatId(RelationshipPersistentEntity.FROM))
.append(" = {id} )")
.append(" = \$id )")

boolean isLazyToMany = lazy && !isRelationship && association instanceof ToMany
if(isLazyToMany) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ class Neo4jQuery extends Query {
}
}

return new CypherExpression(lhs, "{$paramNumber}", CriterionHandler.OPERATOR_EQUALS)
return new CypherExpression(lhs, "\$$paramNumber", CriterionHandler.OPERATOR_EQUALS)
}

},
Expand All @@ -252,7 +252,7 @@ class Neo4jQuery extends Query {
@CompileStatic
CypherExpression handle(GraphPersistentEntity entity, Query.IdEquals criterion, CypherBuilder builder, String prefix) {
int paramNumber = addBuildParameterForCriterion(builder, entity, criterion)
return new CypherExpression(entity.formatId(prefix), "{$paramNumber}", CriterionHandler.OPERATOR_EQUALS)
return new CypherExpression(entity.formatId(prefix), "\$$paramNumber", CriterionHandler.OPERATOR_EQUALS)
}
},
(Query.Like): new CriterionHandler<Query.Like>() {
Expand All @@ -261,7 +261,7 @@ class Neo4jQuery extends Query {
CypherExpression handle(GraphPersistentEntity entity, Query.Like criterion, CypherBuilder builder, String prefix) {
int paramNumber = addBuildParameterForCriterion(builder, entity, criterion)
String operator = handleLike(criterion, builder, paramNumber, false)
return new CypherExpression(entity.formatProperty(prefix, criterion.property), "{$paramNumber}", operator)
return new CypherExpression(entity.formatProperty(prefix, criterion.property), "\$$paramNumber", operator)
}
},
(Query.ILike): new CriterionHandler<Query.ILike>() {
Expand All @@ -271,7 +271,7 @@ class Neo4jQuery extends Query {
int paramNumber = addBuildParameterForCriterion(builder, entity, criterion)
String operator = handleLike(criterion, builder, paramNumber, true)
String propertyRef = entity.formatProperty(prefix, criterion.property)
String parameterRef = "{$paramNumber}"
String parameterRef = "\$$paramNumber"
if(operator != CriterionHandler.OPERATOR_LIKE) {
propertyRef = "lower($propertyRef)"
parameterRef = "lower($parameterRef)"
Expand All @@ -284,7 +284,7 @@ class Neo4jQuery extends Query {
@CompileStatic
CypherExpression handle(GraphPersistentEntity entity, Query.RLike criterion, CypherBuilder builder, String prefix) {
int paramNumber = addBuildParameterForCriterion(builder, entity, criterion)
return new CypherExpression(entity.formatProperty(prefix, criterion.property), "{$paramNumber}", CriterionHandler.OPERATOR_LIKE)
return new CypherExpression(entity.formatProperty(prefix, criterion.property), "\$$paramNumber", CriterionHandler.OPERATOR_LIKE)
}
},
(Query.In): new CriterionHandler<Query.In>() {
Expand Down Expand Up @@ -313,7 +313,7 @@ class Neo4jQuery extends Query {
lhs = graphPersistentEntity.formatProperty(prefix, criterion.property)
}
builder.replaceParamAt(paramNumber, convertEnumsInList(values))
return new CypherExpression(lhs, "{$paramNumber}", CriterionHandler.OPERATOR_IN)
return new CypherExpression(lhs, "\$$paramNumber", CriterionHandler.OPERATOR_IN)
}
},
(Query.IsNull): new CriterionHandler<Query.IsNull>() {
Expand Down Expand Up @@ -366,7 +366,7 @@ class Neo4jQuery extends Query {
Neo4jMappingContext mappingContext = (Neo4jMappingContext)entity.mappingContext
int paramNumberFrom = builder.addParam( mappingContext.convertToNative(criterion.from) )
int parmaNumberTo = builder.addParam( mappingContext.convertToNative(criterion.to) )
new CypherExpression( "{$paramNumberFrom}<=${prefix}.$criterion.property and ${prefix}.$criterion.property<={$parmaNumberTo}")
new CypherExpression( "\$$paramNumberFrom<=${prefix}.$criterion.property and ${prefix}.$criterion.property<=\$$parmaNumberTo")
}
},
(Query.SizeLessThanEquals): SizeCriterionHandler.LESS_THAN_EQUALS,
Expand Down Expand Up @@ -772,7 +772,7 @@ class Neo4jQuery extends Query {
}

}
return new CypherExpression(lhs, "{$paramNumber}", operator)
return new CypherExpression(lhs, "\$$paramNumber", operator)
}
}

Expand Down Expand Up @@ -832,7 +832,7 @@ class Neo4jQuery extends Query {
int paramNumber = addBuildParameterForCriterion(builder, entity, criterion)
Association association = entity.getPropertyByName(criterion.property) as Association
builder.addMatch("(${prefix})${RelationshipUtils.matchForAssociation(association)}() WITH ${prefix},count(*) as count")
return new CypherExpression(CriterionHandler.COUNT, "{$paramNumber}", operator)
return new CypherExpression(CriterionHandler.COUNT, "\$$paramNumber", operator)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ class CypherQueryStringSpec extends GormDatastoreSpec {
setupDomain()

when:
int result = Club.executeUpdate("MATCH (n) where n.name = {name} SET n.ground = {ground}", [name:'FC Bayern Muenchen', ground:"Alliance Arena"])
def club = Club.find("MATCH (n) where n.name = {1} RETURN n", 'FC Bayern Muenchen')
int result = Club.executeUpdate("MATCH (n) where n.name = \$name SET n.ground = \$ground", [name:'FC Bayern Muenchen', ground:"Alliance Arena"])
def club = Club.find("MATCH (n) where n.name = \$1 RETURN n", 'FC Bayern Muenchen')

then:
result == 1
Expand All @@ -50,7 +50,7 @@ class CypherQueryStringSpec extends GormDatastoreSpec {
club.teams.size() == 2

when:"A find method is executed with map arguments"
club = Club.find("MATCH (n) where n.name = {name} RETURN n", [name:'FC Bayern Muenchen'])
club = Club.find("MATCH (n) where n.name = \$name RETURN n", [name:'FC Bayern Muenchen'])

then:"The result is correct"
club instanceof Club
Expand All @@ -60,7 +60,7 @@ class CypherQueryStringSpec extends GormDatastoreSpec {

when:"A find method is executed on the inverse side"
session.clear()
def team = Team.find("MATCH (n) where n.name = {name} RETURN n", [name:'FCB Team 1'])
def team = Team.find("MATCH (n) where n.name = \$name RETURN n", [name:'FCB Team 1'])

then:"The result is correct"
team instanceof Team
Expand Down Expand Up @@ -95,7 +95,7 @@ class CypherQueryStringSpec extends GormDatastoreSpec {

when:"A find method is executed with map arguments"
session.clear()
clubs = Club.findAll("MATCH (n) where n.name = {name} RETURN n", [name:'FC Bayern Muenchen'])
clubs = Club.findAll("MATCH (n) where n.name = \$name RETURN n", [name:'FC Bayern Muenchen'])

then:"The result is correct"
clubs.size() == 1
Expand Down Expand Up @@ -128,7 +128,7 @@ class CypherQueryStringSpec extends GormDatastoreSpec {
setupDomain()

when:"A cypher query is executed"
def result = Club.executeCypher("MATCH (n) where n.name = {name} RETURN n", [name:'FC Bayern Muenchen'])
def result = Club.executeCypher("MATCH (n) where n.name = \$name RETURN n", [name:'FC Bayern Muenchen'])
Club club = result as Club

then:"the conversion is correct"
Expand All @@ -138,7 +138,7 @@ class CypherQueryStringSpec extends GormDatastoreSpec {
club.teams.size() == 2

when:"A cypher query is executed"
result = Club.executeCypher("MATCH (n) where n.name = {name} RETURN n", [name:'FC Bayern Muenchen'])
result = Club.executeCypher("MATCH (n) where n.name = \$name RETURN n", [name:'FC Bayern Muenchen'])
List<Club> clubs = result.toList(Club)

then:"the conversion is correct"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ class ManyToManySpec extends GormDatastoreSpec {
fetchedFelix.friends.size() == 100

when: "we have 100 relationships"
def result = session.transaction.nativeTransaction.run("MATCH (:BidirectionalFriends {name:{1}})<-[:FRIENDS]-(o) return count(o) as c", ["1":"felix"])
def result = session.transaction.nativeTransaction.run("MATCH (:BidirectionalFriends {name:\$1})<-[:FRIENDS]-(o) return count(o) as c", ["1":"felix"])

then:
IteratorUtil.single(result)["c"].asNumber() == 100
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ class MiscSpec extends GormDatastoreSpec {
def session = boltDriver.session()
def tx = session.beginTransaction()

tx.run("CREATE (n1:Team {props})", [props:[name:"Team $count".toString()]])
tx.run("CREATE (n1:Team \$props)", [props:[name:"Team $count".toString()]])
tx.commit()
session.close()
}
Expand Down Expand Up @@ -342,18 +342,18 @@ class MiscSpec extends GormDatastoreSpec {
when:
def pet = new Pet(birthDate: new Date(), name: 'Cosima').save(flush: true)
then:
IteratorUtil.single(session.transaction.nativeTransaction.run("MATCH (p:Pet {name:{1}}) RETURN p.birthDate as birthDate", ["1":'Cosima'])).birthDate.asNumber() instanceof Long
IteratorUtil.single(session.transaction.nativeTransaction.run("MATCH (p:Pet {name:\$1}) RETURN p.birthDate as birthDate", ["1":'Cosima'])).birthDate.asNumber() instanceof Long
}

@Issue("https://github.com/SpringSource/grails-data-mapping/issues/52")
@IgnoreIf({System.getenv('TRAVIS')}) // fails randomly on Travis
@IgnoreIf({System.getenv('CI')}) // fails randomly on Travis
def "verify backward compatibility, check that date properties stored as string can be read"() {
setup: "create a instance with a date property and manually assign a string to it"
def date = new Date()
def pet = new Pet(birthDate: date, name:'Cosima').save(flush: true)

when: "write birthDate as a String"
session.transaction.nativeTransaction.run("MATCH (p:Pet {name:{1}}) SET p.birthDate={2}",
session.transaction.nativeTransaction.run("MATCH (p:Pet {name:\$1}) SET p.birthDate=\$2",
['1':'Cosima', '2':date.time.toString()])
pet = Pet.get(pet.id)
then: "the string stored date gets parsed correctly"
Expand All @@ -365,7 +365,7 @@ class MiscSpec extends GormDatastoreSpec {
when:
def team = new Team(name: 'name', binaryData: 'abc'.bytes)
team.save(flush: true)
def value = IteratorUtil.single(session.transaction.nativeTransaction.run("MATCH (p:Team {name:{1}}) RETURN p.binaryData as binaryData",
def value = IteratorUtil.single(session.transaction.nativeTransaction.run("MATCH (p:Team {name:\$1}) RETURN p.binaryData as binaryData",
["1":'name'])).binaryData

then:
Expand Down
Loading

0 comments on commit 25dee15

Please sign in to comment.