Skip to content

Commit 6f4b3ff

Browse files
Postgres specific implementation of ROUND() (#6789)
* Postgres specific implementation of ROUND() * comment
1 parent 6f3f809 commit 6f4b3ff

1 file changed

Lines changed: 32 additions & 19 deletions

File tree

query/src/org/labkey/query/sql/Method.java

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,7 @@ public MethodInfo getMethodInfo()
360360
labkeyMethod.put("repeat", new JdbcMethod("repeat", JdbcType.VARCHAR, 2, 2));
361361
labkeyMethod.put("round", new Method("round", JdbcType.DOUBLE, 1, 2)
362362
{
363-
@Override
363+
@Override
364364
public MethodInfo getMethodInfo()
365365
{
366366
return new RoundInfo();
@@ -842,28 +842,41 @@ public SQLFragment getSQL(SqlDialect dialect, SQLFragment[] arguments)
842842
return super.getSQL(dialect, new SQLFragment[] {arguments[0]});
843843
}
844844

845-
int i = Integer.MIN_VALUE;
846-
try
845+
if (supportsRoundDouble)
847846
{
848-
i = Integer.parseInt(arguments[1].getSQL());
847+
return super.getSQL(dialect, arguments);
849848
}
850-
catch (NumberFormatException x)
849+
else if (dialect.isPostgreSQL())
851850
{
852-
/* fall through */
851+
// Postgres ROUND() requires NUMERIC argument and will error with DOUBLE
852+
// This CAST works because in postgres NUMERIC(unspecified) => up to 131072 digits before the decimal point; up to 16383 digits after the decimal point
853+
// This is not SQL standard behavior
854+
SQLFragment numeric = new SQLFragment();
855+
numeric.append("CAST((").append(arguments[0]).append(") AS NUMERIC)");
856+
return super.getSQL(dialect, new SQLFragment[] {numeric, arguments[1]});
857+
}
858+
else
859+
{
860+
// NOTE: At the moment there appear to be no Dialects that use this code path (but it still works).
861+
// Leave for completeness?
862+
int n = Integer.MIN_VALUE;
863+
try
864+
{
865+
n = Integer.parseInt(arguments[1].getSQL());
866+
}
867+
catch (NumberFormatException x)
868+
{
869+
/* fall through */
870+
}
871+
// If 2nd argument isn't a constant, just do the default thing. This may work or it may cause a server parse error.
872+
if (n == Integer.MIN_VALUE)
873+
return super.getSQL(dialect, arguments);
874+
var scale = Math.pow(10,n);
875+
SQLFragment scaled = new SQLFragment().append("(").append(arguments[0]).append(")*").appendValue(scale);
876+
SQLFragment ret = super.getSQL(dialect, new SQLFragment[]{scaled});
877+
ret.append("/").appendValue(scale);
878+
return ret;
853879
}
854-
855-
if (supportsRoundDouble || i == Integer.MIN_VALUE)
856-
return super.getSQL(dialect, arguments);
857-
858-
// fall back, only supports simple integer
859-
SQLFragment scaled = new SQLFragment();
860-
scaled.append("(");
861-
scaled.append(arguments[0]);
862-
scaled.append(")*").appendValue(Math.pow(10,i));
863-
SQLFragment ret = super.getSQL(dialect, new SQLFragment[] {scaled});
864-
ret.append("/");
865-
ret.appendValue(Math.pow(10,i));
866-
return ret;
867880
}
868881
}
869882

0 commit comments

Comments
 (0)