Skip to content

Commit 0f81170

Browse files
author
J Chapman Flack
committed
Don't type parameters the same way as returns
What the TypeMapper was doing was correct for a function return value, matching the return value to the narrowest mapped type that the actual return value could be assigned to. It was not correct for a function parameter, which needs to be matched to the widest mapped type that could be assigned to the parameter. Jens, if you ever read this, forgive me. At least I caught it quickly.
1 parent 301164c commit 0f81170

File tree

1 file changed

+34
-10
lines changed

1 file changed

+34
-10
lines changed

pljava-api/src/main/java/org/postgresql/pljava/sqlgen/DDRProcessor.java

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828

2929
import java.util.AbstractMap;
3030
import java.util.ArrayList;
31+
import java.util.Collections;
3132
import java.util.Comparator;
3233
import java.util.HashMap;
3334
import java.util.HashSet;
@@ -928,7 +929,7 @@ public void characterize()
928929
TypeMirror tm = ptms.get( arity - 1);
929930
if ( tm.getKind().equals( TypeKind.ERROR)
930931
// unresolved things seem assignable to anything
931-
|| ! typu.isAssignable( tm, TY_RESULTSET) )
932+
|| ! typu.isSameType( tm, TY_RESULTSET) )
932933
{
933934
msg( Kind.ERROR, func.getParameters().get( arity - 1),
934935
"Last parameter of complex-type-returning function " +
@@ -981,7 +982,7 @@ else if ( ret.getKind().equals( TypeKind.VOID) && 1 == arity )
981982
TypeMirror tm = ptms.get( 0);
982983
if ( ! tm.getKind().equals( TypeKind.ERROR)
983984
// unresolved things seem assignable to anything
984-
&& typu.isAssignable( tm, TY_TRIGGERDATA) )
985+
&& typu.isSameType( tm, TY_TRIGGERDATA) )
985986
{
986987
trigger = true;
987988
}
@@ -1026,7 +1027,8 @@ String nameAndParams( boolean dflts)
10261027
{
10271028
VariableElement ve = ves.next();
10281029
sb.append( "\n\t").append( ve.getSimpleName().toString());
1029-
sb.append( ' ').append( tmpr.getSQLType( tm, ve, dflts));
1030+
sb.append( ' ');
1031+
sb.append( tmpr.getSQLType( tm, ve, true, dflts));
10301032
if ( 0 < -- s )
10311033
sb.append( ',');
10321034
}
@@ -1114,7 +1116,7 @@ public String[] undeployStrings()
11141116
*/
11151117
class TypeMapper
11161118
{
1117-
List<Map.Entry<Class<?>, String>> mappings;
1119+
ArrayList<Map.Entry<Class<?>, String>> mappings;
11181120

11191121
TypeMapper() {
11201122
mappings = new ArrayList<Map.Entry<Class<?>, String>>();
@@ -1149,6 +1151,7 @@ class TypeMapper
11491151
this.addMap(BigInteger.class, "numeric");
11501152
this.addMap(BigDecimal.class, "numeric");
11511153
this.addMap(ResultSet.class, "record");
1154+
this.addMap(Object.class, "\"any\"");
11521155

11531156
this.addMap(byte[].class, "bytea");
11541157

@@ -1213,15 +1216,16 @@ void addMap(Class<?> k, String v)
12131216
* Return the SQL type for the Java type represented by a TypeMirror,
12141217
* from an explicit annotation if present, otherwise by applying the
12151218
* default mappings. No default-value information is included in the
1216-
* string returned.
1219+
* string returned. It is assumed that a function return is being typed
1220+
* rather than a function parameter.
12171221
*
12181222
* @param tm Represents the type whose corresponding SQL type is wanted.
12191223
* @param e Annotated element (chiefly for use as a location hint in
12201224
* diagnostic messages).
12211225
*/
12221226
String getSQLType(TypeMirror tm, Element e)
12231227
{
1224-
return getSQLType( tm, e, false);
1228+
return getSQLType( tm, e, false, false);
12251229
}
12261230

12271231

@@ -1233,10 +1237,15 @@ String getSQLType(TypeMirror tm, Element e)
12331237
* @param tm Represents the type whose corresponding SQL type is wanted.
12341238
* @param e Annotated element (chiefly for use as a location hint in
12351239
* diagnostic messages).
1240+
* @param contravariant Indicates that the element whose type is wanted
1241+
* is a function parameter and should be given the widest type that can
1242+
* be assigned to it. If false, find the narrowest type that a function
1243+
* return can be assigned to.
12361244
* @param withDefault Indicates whether any specified default value
12371245
* information should also be included in the "type" string returned.
12381246
*/
1239-
String getSQLType(TypeMirror tm, Element e, boolean withDefault)
1247+
String getSQLType(TypeMirror tm, Element e,
1248+
boolean contravariant, boolean withDefault)
12401249
{
12411250
boolean array = false;
12421251
String rslt = null;
@@ -1279,7 +1288,13 @@ String getSQLType(TypeMirror tm, Element e, boolean withDefault)
12791288
}
12801289
else
12811290
{
1282-
for ( Map.Entry<Class<?>, String> me : mappings )
1291+
ArrayList<Map.Entry<Class<?>, String>> ms = mappings;
1292+
if ( contravariant )
1293+
{
1294+
ms = (ArrayList<Map.Entry<Class<?>, String>>)ms.clone();
1295+
Collections.reverse( ms);
1296+
}
1297+
for ( Map.Entry<Class<?>, String> me : ms )
12831298
{
12841299
Class<?> k = me.getKey();
12851300
TypeMirror ktm;
@@ -1301,9 +1316,18 @@ String getSQLType(TypeMirror tm, Element e, boolean withDefault)
13011316
if ( null == te ) // can't find it -> not used in code?
13021317
continue; // hope it's not the one I'm looking for
13031318
ktm = te.asType();
1304-
if ( typu.isAssignable( tm, ktm) )
1319+
boolean accept;
1320+
if ( contravariant )
1321+
accept = typu.isAssignable( ktm, tm);
1322+
else
1323+
accept = typu.isAssignable( tm, ktm);
1324+
if ( accept )
13051325
{
1306-
rslt = me.getValue();
1326+
// don't compute a type of Object/"any" for
1327+
// a function return (just admit defeat instead)
1328+
if ( contravariant
1329+
|| ! Object.class.equals( me.getKey()) )
1330+
rslt = me.getValue();
13071331
break;
13081332
}
13091333
}

0 commit comments

Comments
 (0)