I noticed that isValid("integer","63.") return true and <cfqueryparam cfsqltype="cf_sql_integer" value="63."> also works fine in a SQL query, but if I pass “63.” to a function with a numeric type argument, it generates an error. Be aware that the value is not 63, but 63. with a dot.
There is no error in recent versions of Adobe Coldfusion.
As of this writing, the ACF 2021 engine appears to be stuck on TryCF.com.
In fact, there is two differences with Lucee vs Adobe Coldfusion :
Point 1 - isValid(“integer”,“63.”)
For ACF, it’s not a valid integer
For Lucee, it’s a valid integer
Point 2 - function with argument type=“numeric”
For ACF, it doesn’t throw an error, so I’m guessing it’s considering that value as a numeric
For Lucee, it does throw an error, so I’m guessing it’s considering that it’s not a numeric value
Technically speaking, is “63.” supposed to be a valid integer?
And if Lucee considers “63.” to be a valid integer, he should also consider it to be a valid numeric value as well. An integer is a numeric value.
But overall, I feel that isValid(“integer”,“63.”) should return false on Lucee.
If “63.” is a string, then why isValid(“integer”,“63.”) return true AND type=“numeric” generate an error? Is it just me seeing the inconsistency?
<cfif isValid("integer","63.")>
<p>63. is a valid integer</p>
<cfelse>
<p>63. is not a valid integer</p>
</cfif>
<cfif isValid("numeric","63.")>
<p>63. is a valid numeric</p>
<cfelse>
<p>63. is not a valid numeric</p>
</cfif>
Lucee return true for integer, but false for numeric.
ACF return false for integer, but true for numeric.
There are many little differences with ACF and lucee.
if you have any java programming skill, you can look at the source behind the tag and propose a patch, but if you look at this, the “.” seems to be part of several types.
From a logic side, nobody is going to write a check for “63.” written out its six three dollars PERIOD. The correct way would be Sixty three dollars and zero cents.
The problem I currently have is that my application expects an integer value as a parameter in the url, so I use the isValid("integer",...) function to validate that the passed value is indeed an integer. But since the user can modify the parameter to add a dot to it, the application crashes a bit further when that value is passed to a function that expects a numeric argument. As my knowledge in Java is limited and that quite honestly, all that exceeds my competences, I will have to create my own function of validation of integer.
I had one before, but I gradually replaced it with isValid("integer",...) thinking it would be more reliable than my own function.
I still have a hard time accepting that Lucee can consider that a value can be integer, but not numeric. I still understand that it’s more complex than it seems, a bit like validating a date.
In Lucee source code, in core\src\main\java\lucee\runtime\op\Decision.java for the function isValid, I found this :
if ("integer".equals(type)) return isInteger(value, false);
then this
public static boolean isInteger(Object value, boolean alsoBooleans) {
if (!alsoBooleans && isBoolean(value)) return false;
double dbl = Caster.toDoubleValue(value, false, Double.NaN);
if (!Decision.isValid(dbl)) return false;
int i = (int) dbl;
return i == dbl;
}
I’ll analyze this to fully understand what’s going on behind the hood, but I’d be surprised if I could improve on this without blowing out everything that depends on isInteger in Lucee.
CF has nailed it, Lucee needs to take a look at a venn diagram of “integer” and “numeric” and how the former circle is completely inside the latter one
It’s true. Ha! (pun intended) - the code is only able to do what you’re asking for - and with limitations.
The 20 char “number” 12345678901234567890 mentioned has it’s own issues due to length …
val(12345678901234567890) is not equal to “12345678901234567890” no matter the CF engine.
Even working directly with java.math.BigInteger is going to give you fits if you multiply and doesn’t handle the dot on the end.
FWIW, val() is purely a string manipulation function (in Lucee, at least). All it’s doing is taking the first characters of the string until it reaches a non-number. This, of course, is exactly what it is documented to do. Turning a large number into scientific notation isn’t really a problem with val(), that’s just now the CF engine turns the large number into a string. If you wanted that to work, you’d need to do your math in a manner that output the full number as a string without allowing the CF engine to convert it t a string for you. I tried to get a proof of concept on that, but the annoying limitations in trycf.com prevents me from getting very far
On the other hand, the initial concern I raised is that I want to validate what is submitted by the user. I want to make sure it’s a valid integer. I have no control over the value he will put in the URL param.
It’s either that we improve Lucee’s isInteger function, or I create my own integer validation function. Creating my own function still seems the easiest, as I have no idea what impact changing Lucee’s isInteger function might have on backwards compatibility.
They (users) will surely throw garbage at any app (accidental or otherwise). It’s up to you as to what you want to do with it.
One thought is to replace [^0-9] with nothing and ignore. Another is reject the request when the replaced len changes.
If we’re to be pedantic about integer, take the max of your current DB (signed or unsigned will change this) into account with your custom function.
From my initial testing, Java has some of the same issues as Lucee with the trailing dot as well as “long integers” losing data when being cast to an int. To me, that’s less a Lucee issue and more of a Java limitation for the type.