Ok I see your point, thanks for explaining.

#1 makes sense but it will be interesting to see how many bugs are
created, also doesn't the service engine currently perform automatic
conversion without any problems?

Regards
Scott

2008/10/14 David E Jones <[EMAIL PROTECTED]>:
>
> On Oct 13, 2008, at 10:10 PM, Scott Gray wrote:
>
>> Inline:
>>
>> 2008/10/14 David E Jones <[EMAIL PROTECTED]>:
>>>
>>> Scott, are you referring to the call to PreparedStatement.setString on
>>> SQLProcessor line 553? In other words, the difference in the Postgres
>>> JDBC
>>> driver is that they used to auto-convert from a String to whatever the
>>> database needs in the setString method, but now they don't?
>>
>> When we call PreparedStatement.setString() the JDBC driver now adds
>> something like String:varchar to the parameter list where it used to
>> add String:unspecified which meant the database would try and take
>> care of it, but with varchar it just says "wrong!" and throws an
>> error.  However if we call PreparedStatement.setObject() passing in
>> the correct sql type then we get String:timestamp and everything works
>> fine.
>>
>> So I guess what I'm saying is that I think java type conversion
>> (String vs Timestamp) is a separate topic and the problem here is
>> simply the sql type that we are specifying (by calling the various
>> PreparedStatement methods) does not match the column type.  We could
>> probably solve the postgresql issue by simply calling
>> setObject(Types.OTHER) whenever the value type doesn't match entity
>> field type.
>
> The real problem is we're passing bad data back to the database and
> expecting it to deal with it. Right now the entity engine is just warning
> about such problems in the log, allowing them to go back to the JDBC driver
> and/or database where they become a real problem.
>
> If we do something like always call setObject then chances are good we'll
> have problems with other databases. If I remember right we used to do that
> generically and it caused problems and we had to move to the current
> approach of using object time specific methods.
>
>>> What I'm proposing is to fix this further up the stack in the
>>> GenericEntity.set method instead of lower down.
>>
>> That's fine for when we are using the GenericEntity but we'd also need
>> to add similar code to the EntityCondition stuff for find queries
>> (which is where Jacques noticed the problem, I haven't checked for the
>> error on any operations involving GenericEntity).
>
> Good point, we'll have to make sure the object types passed into those are
> valid as well.
>
> -David
>
>
>
>>> On Oct 13, 2008, at 7:14 PM, Scott Gray wrote:
>>>
>>>> Here's the problem as I see it:
>>>> Postgresql used to allow you to specify parameter types which did not
>>>> match the column type, in the timestamp case if you passed in a
>>>> parameter specified as varchar it would automatically attempt to
>>>> convert it to a timestamp.  Now Postgresql requires that you either
>>>> pass in the correct parameter type for the column or otherwise pass
>>>> the parameter type as unknown/unspecified.  Postgresql still doesn't
>>>> care whether you pass in a string or a timestamp but you MUST specify
>>>> the correct sql type.
>>>>
>>>> If letting the database take care of the type conversion has never
>>>> been a problem before, why do we need to worry about it now?  Remember
>>>> the only problem here is that we are passing in a string specified as
>>>> varchar instead of a string specified as java.sql.Types.Timestamp.
>>>>
>>>> Regards
>>>> Scott
>>>>
>>>> 2008/10/14 Adrian Crum <[EMAIL PROTECTED]>:
>>>>>
>>>>> I understood your alternatives. I apologize for being unclear.
>>>>>
>>>>> You said, "or to just throw an exception when the wrong data type is
>>>>> passed
>>>>> like the commented out code in GenericEntity referenced above does."
>>>>>
>>>>> And I'm saying we could do that, but it's going to get interesting
>>>>> because a
>>>>> lot of code passes Strings into the entity engine. In other words, if
>>>>> we
>>>>> throw a "hard" exception, there is a good chance that much of OFBiz
>>>>> won't
>>>>> run.
>>>>>
>>>>> Personally, I'd like to see better handling of object types in the
>>>>> higher
>>>>> level code. I fixed a problem over the weekend that was caused by this
>>>>> very
>>>>> thing (passing Strings into the entity engine).
>>>>>
>>>>> -Adrian
>>>>>
>>>>>
>>>>> David E Jones wrote:
>>>>>>
>>>>>> I'm referring to the exception I described in the GenericEntity.java
>>>>>> file,
>>>>>> lines 410-415. Right now it is just a warning in the log (and has been
>>>>>> for
>>>>>> years). The reason to do it there instead of letting the JDBC driver
>>>>>> do
>>>>>> it
>>>>>> is that not all developers will test on all possible databases, and
>>>>>> this
>>>>>> will help avoid errors as people use different databases in
>>>>>> development/testing or deployment.
>>>>>>
>>>>>> I tried to describe two possible approaches to improve this situation
>>>>>> in
>>>>>> my first message. Please let me know if those alternatives were not
>>>>>> clear
>>>>>> and I'll try to explain them better.
>>>>>>
>>>>>> -David
>>>>>>
>>>>>>
>>>>>> On Oct 13, 2008, at 5:22 PM, Adrian Crum wrote:
>>>>>>
>>>>>>> Wasn't that being done already? Jacques started these changes based
>>>>>>> on
>>>>>>> exceptions being thrown by his JDBC driver. Other DBs seemed to be
>>>>>>> working
>>>>>>> okay.
>>>>>>>
>>>>>>> I guess we could throw our own exception to keep things consistent
>>>>>>> across
>>>>>>> databases. It will be interesting to see how that affects existing
>>>>>>> code.
>>>>>>>
>>>>>>> -Adrian
>>>>>>>
>>>>>>>
>>>>>>> David E Jones wrote:
>>>>>>>>
>>>>>>>> That is a very good point, and I agree.
>>>>>>>> To me that means we go with the fail-fast approach and have it throw
>>>>>>>> an
>>>>>>>> exception if you pass in something that is not the correct object
>>>>>>>> type.
>>>>>>>> Is that what you meant?
>>>>>>>> -David
>>>>>>>> On Oct 13, 2008, at 4:57 PM, Adrian Crum wrote:
>>>>>>>>>
>>>>>>>>> I would prefer handling object types in higher level code - due to
>>>>>>>>> ambiguity in how some types would be converted from a String
>>>>>>>>> (currency,
>>>>>>>>> date, time, etc).
>>>>>>>>>
>>>>>>>>> -Adrian
>>>>>>>>>
>>>>>>>>> David E Jones wrote:
>>>>>>>>>>
>>>>>>>>>> This has been a potential problem for a while, but the decision
>>>>>>>>>> was
>>>>>>>>>> made quite a while back to not enforce the correct object type.
>>>>>>>>>> There is code in the GenericEntity.java file (lines 410-415) to
>>>>>>>>>> check
>>>>>>>>>> to see if the value passed in matches the object type for the
>>>>>>>>>> field
>>>>>>>>>> it is
>>>>>>>>>> being set on.
>>>>>>>>>> The best way to solve this problem is a good question. It might be
>>>>>>>>>> good to introduce some automatic type conversion, or to just throw
>>>>>>>>>> an
>>>>>>>>>> exception when the wrong data type is passed like the commented
>>>>>>>>>> out
>>>>>>>>>> code in
>>>>>>>>>> GenericEntity referenced above does.
>>>>>>>>>> The most common form of automatic conversion is from String to
>>>>>>>>>> whatever the field's object type is, and that is done by the
>>>>>>>>>> GenericEntity.setString method.
>>>>>>>>>> So, what do people think about this? Should we do an automatic
>>>>>>>>>> type
>>>>>>>>>> conversion to try to fix programming errors automatically, or do a
>>>>>>>>>> fail-fast
>>>>>>>>>> by throwing an exception when the object type is wrong? I suppose
>>>>>>>>>> the
>>>>>>>>>> current fail-quiet (in the log) and fail loudly on certain
>>>>>>>>>> databases
>>>>>>>>>> later
>>>>>>>>>> is not the best option...
>>>>>>>>>> -David
>>>>>>>>>> On Oct 12, 2008, at 2:20 PM, Scott Gray wrote:
>>>>>>>>>>>
>>>>>>>>>>> I've had a look into this and I can't see anything related to
>>>>>>>>>>> Groovy
>>>>>>>>>>> that is making this necessary, it appears to be entirely a
>>>>>>>>>>> postgresql
>>>>>>>>>>> issue.
>>>>>>>>>>>
>>>>>>>>>>> When executing a prepared statement postgresql seems to require
>>>>>>>>>>> that
>>>>>>>>>>> the parameter list sql types match the column types.  So the
>>>>>>>>>>> problem
>>>>>>>>>>> isn't that we are passing in a string but that we are setting the
>>>>>>>>>>> sql
>>>>>>>>>>> type to character varying by using PreparedStatement.setString().
>>>>>>>>>>>
>>>>>>>>>>> Here's a patch that fixes the issue but I'm not really confident
>>>>>>>>>>> enough to commit it, it would be great to get some comments from
>>>>>>>>>>> people who know more about this kind of thing:
>>>>>>>>>>>
>>>>>>>>>>> Index:
>>>>>>>>>>> framework/entity/src/org/ofbiz/entity/jdbc/SQLProcessor.java
>>>>>>>>>>>
>>>>>>>>>>> ===================================================================
>>>>>>>>>>> --- framework/entity/src/org/ofbiz/entity/jdbc/SQLProcessor.java
>>>>>>>>>>> (revision
>>>>>>>>>>> 703572)
>>>>>>>>>>> +++ framework/entity/src/org/ofbiz/entity/jdbc/SQLProcessor.java
>>>>>>>>>>> (working copy)
>>>>>>>>>>> @@ -592,6 +592,22 @@
>>>>>>>>>>> *
>>>>>>>>>>> * @throws SQLException
>>>>>>>>>>> */
>>>>>>>>>>> +    public void setValueTimestampString(String field) throws
>>>>>>>>>>> SQLException {
>>>>>>>>>>> +        if (field != null) {
>>>>>>>>>>> +            _ps.setObject(_ind, field, Types.TIMESTAMP);
>>>>>>>>>>> +        } else {
>>>>>>>>>>> +            _ps.setNull(_ind, Types.TIMESTAMP);
>>>>>>>>>>> +        }
>>>>>>>>>>> +        _ind++;
>>>>>>>>>>> +    }
>>>>>>>>>>> +
>>>>>>>>>>> +    /**
>>>>>>>>>>> +     * Set the next binding variable of the currently active
>>>>>>>>>>> prepared
>>>>>>>>>>> statement.
>>>>>>>>>>> +     *
>>>>>>>>>>> +     * @param field
>>>>>>>>>>> +     *
>>>>>>>>>>> +     * @throws SQLException
>>>>>>>>>>> +     */
>>>>>>>>>>> public void setValue(java.sql.Time field) throws SQLException {
>>>>>>>>>>>  if (field != null) {
>>>>>>>>>>>      _ps.setTime(_ind, field);
>>>>>>>>>>> Index:
>>>>>>>>>>> framework/entity/src/org/ofbiz/entity/jdbc/SqlJdbcUtil.java
>>>>>>>>>>>
>>>>>>>>>>> ===================================================================
>>>>>>>>>>> --- framework/entity/src/org/ofbiz/entity/jdbc/SqlJdbcUtil.java
>>>>>>>>>>> (revision
>>>>>>>>>>> 703572)
>>>>>>>>>>> +++ framework/entity/src/org/ofbiz/entity/jdbc/SqlJdbcUtil.java
>>>>>>>>>>> (working copy)
>>>>>>>>>>> @@ -731,6 +731,9 @@
>>>>>>>>>>>              fieldClassName = "byte[]";
>>>>>>>>>>>          }
>>>>>>>>>>>
>>>>>>>>>>> +                if ("java.sql.Timestamp".equals(fieldType)) {
>>>>>>>>>>> +                    fieldClassName = fieldType;
>>>>>>>>>>> +                }
>>>>>>>>>>>          if (Debug.verboseOn()) Debug.logVerbose("type of
>>>>>>>>>>> field " + entityName + "." + modelField.getName() +
>>>>>>>>>>>                  " is " + fieldClassName + ", was expecting "
>>>>>>>>>>> + mft.getJavaType() + "; this may " +
>>>>>>>>>>>                  "indicate an error in the configuration or in
>>>>>>>>>>> the class, and may result " +
>>>>>>>>>>> @@ -749,7 +752,11 @@
>>>>>>>>>>>          break;
>>>>>>>>>>>
>>>>>>>>>>>      case 2:
>>>>>>>>>>> -                sqlP.setValue((java.sql.Timestamp) fieldValue);
>>>>>>>>>>> +                if (fieldValue instanceof String) {
>>>>>>>>>>> +                    sqlP.setValueTimestampString((String)
>>>>>>>>>>> fieldValue);
>>>>>>>>>>> +                } else {
>>>>>>>>>>> +                    sqlP.setValue((java.sql.Timestamp)
>>>>>>>>>>> fieldValue);
>>>>>>>>>>> +                }
>>>>>>>>>>>          break;
>>>>>>>>>>>
>>>>>>>>>>>      case 3:
>>>>>>>>>>>
>>>>>>>>>>> Regards
>>>>>>>>>>> Scott
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> 2008/10/13 Jacques Le Roux <[EMAIL PROTECTED]>:
>>>>>>>>>>>>
>>>>>>>>>>>> Done in revision: 703816
>>>>>>>>>>>> It was not possible for PackingSlip.groovy and
>>>>>>>>>>>> FindInventoryEventPlan.groovy. Because there the date string is
>>>>>>>>>>>> build
>>>>>>>>>>>> dynamically in the Groovy file
>>>>>>>>>>>>
>>>>>>>>>>>> Jacques
>>>>>>>>>>>>
>>>>>>>>>>>> From: "Jacques Le Roux" <[EMAIL PROTECTED]>
>>>>>>>>>>>>>
>>>>>>>>>>>>> Adrian,
>>>>>>>>>>>>>
>>>>>>>>>>>>> Yes good idea indeed, I will do that
>>>>>>>>>>>>>
>>>>>>>>>>>>> Jacques
>>>>>>>>>>>>>
>>>>>>>>>>>>> From: "Adrian Crum" <[EMAIL PROTECTED]>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> Jacques,
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> Instead of modifying the groovy files, try specifying the data
>>>>>>>>>>>>>> type in
>>>>>>>>>>>>>> the screen widget.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> Example in ReportFinancialSummaryScreens.xml:
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> <set field="fromDate" from-field="parameters.fromDate"
>>>>>>>>>>>>>> type="Timestamp"/>
>>>>>>>>>>>>>> <set field="thruDate" from-field="parameters.thruDate"
>>>>>>>>>>>>>> type="Timestamp"/>
>>>>>>>>>>>>>> <script
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> location="component://accounting/webapp/accounting/WEB-INF/actions/reports/TransactionTotals.groovy"/>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> -Adrian
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>
>>>>>>
>>>>>
>>>
>>>
>
>

Reply via email to