OpenJPA
  1. OpenJPA
  2. OPENJPA-2149

Criteria.function adds wrong casts to parameters making it unsuable

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Critical Critical
    • Resolution: Fixed
    • Affects Version/s: 2.0.1, 2.0.2, 2.1.1
    • Fix Version/s: 2.0.3, 2.1.2, 2.2.1, 2.3.0
    • Component/s: criteria, kernel
    • Labels:
      None
    • Environment:
      Standalone 2.0.0 and 2.0.1 downloaded from openjpa website, and on WebSphere 7 JPA2 feature pack 1.0.0.5 (contains OpenJPA 2.0.2)

      Description

      Criteria.function will generate an SQL with only the last parameter casted and to the wrong type.
      Expression<String> stPointFunc = cb.function(
      "db2gse.st_point",
      String.class,
      cb.literal(0.0),
      cb.literal(0.0),
      cb.literal(1003));

      Expression<Double> distanceFunc = cb.function(
      "db2gse.st_distance",
      Double.class,
      stPointFunc,
      usersLocations.get("location"));

      criteriaQuery.select(usersLocations).where(cb.lessThan(distanceFunc, cb.literal(50.0)));

      Will generate the following SQL:
      (db2gse.st_distance(db2gse.st_point(?, ?, CAST(? AS DOUBLE)), t0.LOCATION) < ?)

      Notice the 3rd parameter is an Integer and its being cast as Double.
      The problem is in org.apache.openjpa.jdbc.kernel.exps.DatastoreFunction#appendTo

      Line 54: args.appendTo(sel, ctx, state, sql, 0);
      Will append 3 ? to the sql buffer: "(db2gse.st_distance(db2gse.st_point(?, ?, ?"

      Then the loop in line 56-58
      for (int i = 1; i < vals.length; i++)

      { sql.addCastForParam(getOperator(), vals[i]); }

      It becomes: "(db2gse.st_distance(db2gse.st_point(?, ?, CAST(? AS DOUBLE)"

      Starts with 1 (second parameter and not the first one), whil sql.addCastForParam only works for the last ? in the sql buffer, meaning the cast for the param at index 1 is added to the last ? and the method will not do anything else.

      This issue leaves Criteria.function useless to me, I tried extending my DBDictionary to remove all the cast as a work around but the function became ambiguous.

      Thanks in advance.

      Found a temporary (working but ugly) workaround:
      Expression<String> stPointFunc = cb.function(
      "db2gse.st_point",
      String.class,
      cb.coalesce(cb.literal(0.0), cb.literal(0.0)),
      cb.coalesce(cb.literal(1.0), cb.literal(1.0)),
      cb.coalesce(cb.literal(1003), cb.literal(1003)));

      coalesce uses raw value instead of parameters and makes it work (the same value twice becuase if I put cb.nullLiteral I get a NullPointerException, might be another bug)

        Activity

        Aviram Segal created issue -
        Aviram Segal made changes -
        Field Original Value New Value
        Description Criteria.function will generate an SQL with only the last parameter casted and to the wrong type.
        Expression<String> stPointFunc = cb.function(
        "db2gse.st_point",
        String.class,
        cb.literal(0.0),
        cb.literal(0.0),
        cb.literal(1003));

        Expression<Double> distanceFunc = cb.function(
        "db2gse.st_distance",
        Double.class,
        stPointFunc,
        usersLocations.get("location"));

        criteriaQuery.select(usersLocations).where(cb.lessThan(distanceFunc, cb.literal(50.0)));

        Will generate the following SQL:
        (db2gse.st_distance(db2gse.st_point(?, ?, CAST(? AS DOUBLE)), t0.LOCATION) < ?)
        Notice the 3rd parameter is an Integer and its being cast as Double.
        The problem is in org.apache.openjpa.jdbc.kernel.exps.DatastoreFunction#appendTo

        Line 54: args.appendTo(sel, ctx, state, sql, 0);
        Will append 3 ? to the sql buffer "(db2gse.st_distance(db2gse.st_point(?, ?, ?"
        Then the loop in line 56-58
                    for (int i = 1; i < vals.length; i++) {
                        sql.addCastForParam(getOperator(), vals[i]);
                    }

        Starts with 1 (second parameter and not the first one), whil sql.addCastForParam only works for the last ? in the sql buffer, meaning the cast for the param at index 1 is added to the last ? and the method will not do anything else.

        This issue leaves Criteria.function useless to me, I tried extending my DBDictionary to remove all the cast as a work around but the function became ambiguous.

        Thanks in advance.


        Criteria.function will generate an SQL with only the last parameter casted and to the wrong type.
        Expression<String> stPointFunc = cb.function(
        "db2gse.st_point",
        String.class,
        cb.literal(0.0),
        cb.literal(0.0),
        cb.literal(1003));

        Expression<Double> distanceFunc = cb.function(
        "db2gse.st_distance",
        Double.class,
        stPointFunc,
        usersLocations.get("location"));

        criteriaQuery.select(usersLocations).where(cb.lessThan(distanceFunc, cb.literal(50.0)));

        Will generate the following SQL:
        (db2gse.st_distance(db2gse.st_point(?, ?, CAST(? AS DOUBLE)), t0.LOCATION) < ?)

        Notice the 3rd parameter is an Integer and its being cast as Double.
        The problem is in org.apache.openjpa.jdbc.kernel.exps.DatastoreFunction#appendTo

        Line 54: args.appendTo(sel, ctx, state, sql, 0);
        Will append 3 ? to the sql buffer: "(db2gse.st_distance(db2gse.st_point(?, ?, ?"

        Then the loop in line 56-58
                    for (int i = 1; i < vals.length; i++) {
                        sql.addCastForParam(getOperator(), vals[i]);
                    }
        It becomes: "(db2gse.st_distance(db2gse.st_point(?, ?, CAST(? AS DOUBLE)"


        Starts with 1 (second parameter and not the first one), whil sql.addCastForParam only works for the last ? in the sql buffer, meaning the cast for the param at index 1 is added to the last ? and the method will not do anything else.

        This issue leaves Criteria.function useless to me, I tried extending my DBDictionary to remove all the cast as a work around but the function became ambiguous.

        Thanks in advance.

        Aviram Segal made changes -
        Description Criteria.function will generate an SQL with only the last parameter casted and to the wrong type.
        Expression<String> stPointFunc = cb.function(
        "db2gse.st_point",
        String.class,
        cb.literal(0.0),
        cb.literal(0.0),
        cb.literal(1003));

        Expression<Double> distanceFunc = cb.function(
        "db2gse.st_distance",
        Double.class,
        stPointFunc,
        usersLocations.get("location"));

        criteriaQuery.select(usersLocations).where(cb.lessThan(distanceFunc, cb.literal(50.0)));

        Will generate the following SQL:
        (db2gse.st_distance(db2gse.st_point(?, ?, CAST(? AS DOUBLE)), t0.LOCATION) < ?)

        Notice the 3rd parameter is an Integer and its being cast as Double.
        The problem is in org.apache.openjpa.jdbc.kernel.exps.DatastoreFunction#appendTo

        Line 54: args.appendTo(sel, ctx, state, sql, 0);
        Will append 3 ? to the sql buffer: "(db2gse.st_distance(db2gse.st_point(?, ?, ?"

        Then the loop in line 56-58
                    for (int i = 1; i < vals.length; i++) {
                        sql.addCastForParam(getOperator(), vals[i]);
                    }
        It becomes: "(db2gse.st_distance(db2gse.st_point(?, ?, CAST(? AS DOUBLE)"


        Starts with 1 (second parameter and not the first one), whil sql.addCastForParam only works for the last ? in the sql buffer, meaning the cast for the param at index 1 is added to the last ? and the method will not do anything else.

        This issue leaves Criteria.function useless to me, I tried extending my DBDictionary to remove all the cast as a work around but the function became ambiguous.

        Thanks in advance.

        Criteria.function will generate an SQL with only the last parameter casted and to the wrong type.
        Expression<String> stPointFunc = cb.function(
        "db2gse.st_point",
        String.class,
        cb.literal(0.0),
        cb.literal(0.0),
        cb.literal(1003));

        Expression<Double> distanceFunc = cb.function(
        "db2gse.st_distance",
        Double.class,
        stPointFunc,
        usersLocations.get("location"));

        criteriaQuery.select(usersLocations).where(cb.lessThan(distanceFunc, cb.literal(50.0)));

        Will generate the following SQL:
        (db2gse.st_distance(db2gse.st_point(?, ?, CAST(? AS DOUBLE)), t0.LOCATION) < ?)

        Notice the 3rd parameter is an Integer and its being cast as Double.
        The problem is in org.apache.openjpa.jdbc.kernel.exps.DatastoreFunction#appendTo

        Line 54: args.appendTo(sel, ctx, state, sql, 0);
        Will append 3 ? to the sql buffer: "(db2gse.st_distance(db2gse.st_point(?, ?, ?"

        Then the loop in line 56-58
                    for (int i = 1; i < vals.length; i++) {
                        sql.addCastForParam(getOperator(), vals[i]);
                    }
        It becomes: "(db2gse.st_distance(db2gse.st_point(?, ?, CAST(? AS DOUBLE)"


        Starts with 1 (second parameter and not the first one), whil sql.addCastForParam only works for the last ? in the sql buffer, meaning the cast for the param at index 1 is added to the last ? and the method will not do anything else.

        This issue leaves Criteria.function useless to me, I tried extending my DBDictionary to remove all the cast as a work around but the function became ambiguous.

        Thanks in advance.

        Found a temporary (working but ugly) workaround:
        Expression<String> stPointFunc = cb.function(
        "db2gse.st_point",
        String.class,
        cb.coalesce(cb.literal(0.0), cb.literal(0.0)),
        cb.coalesce(cb.literal(1.0), cb.literal(1.0)),
        cb.coalesce(cb.literal(1003), cb.literal(1003)));

        coalesce uses raw value instead of parameters and makes it work (the same value twice becuase if I put cb.nullLiteral I get a NullPointerException, might be another bug)
        Albert Lee made changes -
        Assignee Albert Lee [ allee8285 ]
        Albert Lee made changes -
        Status Open [ 1 ] In Progress [ 3 ]
        Albert Lee made changes -
        Attachment OPENJPA-2149-2.0.x.patch [ 12531985 ]
        Jody Grassel made changes -
        Status In Progress [ 3 ] Resolved [ 5 ]
        Fix Version/s 2.0.3 [ 12317143 ]
        Fix Version/s 2.1.2 [ 12317142 ]
        Fix Version/s 2.3.0 [ 12319463 ]
        Fix Version/s 2.2.1 [ 12319943 ]
        Resolution Fixed [ 1 ]
        Jody Grassel made changes -
        Status Resolved [ 5 ] Closed [ 6 ]

          People

          • Assignee:
            Albert Lee
            Reporter:
            Aviram Segal
          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development