Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

    allowMultiupdate

    If you forget to write in a server-side DSRequest "allowMultiupdate(true)" together with an update all records are updated!
    Example:

    Code:
    DSRequest updateReq = new DSRequest("myDS", DataSource.OP_UPDATE, rpcManager);
    
    List<Criterion> criterions = new ArrayList<>();
    Criterion c = new SimpleCriterion("myCriteria", DefaultOperators.Equals, 1);
    criterions.add(c);
    
    AdvancedCriteria ac = new AdvancedCriteria(DefaultOperators.Or, criterions.toArray(new Criterion[] {}));
    updateReq.setAllowMultiUpdate(true);
    
    Map<String, Object> clearedValues = new HashMap<>();
    
    clearedValues.put("f_myValue", null);
    updateReq.setValues(clearedValues);
    updateReq.setAdvancedCriteria(ac);
    updateReq.execute();
    This creates (correctly) the following sql:
    Code:
     UPDATE myTable SET f_myValue=NULL WHERE ( myCriteria = 1) ;
    If I comment out "updateReq.setAllowMultiUpdate(true);" I get the following sql:
    Code:
     UPDATE myTable SET f_myValue=NULL WHERE ('1'='1')
    so this means setting setAllowMultiUpdate(false) updates ALL the records ! Is this by-design? Isn't this a contradiction?

    Using smartgwt 6.1p power 6.1-p20180208
    Last edited by edulid; 25 Mar 2018, 07:17.

    #2
    Updates without primary key are not allowed, and we have multiple autotests verifying this. You may have changed the DataSource.defaultMultiUpdatePolicy, or perhaps changed it system-wide?

    Note also, you can only get that 1=1 effect if you specify invalid criteria (eg field does not exist), so there is a second error here too.

    Comment


      #3
      Hi Isomorphic

      this seems not to be the case in my simple testcase:

      It relies on the following table:
      Code:
      create table minimalTestcase
      (f_id int identity(1,1) primary key,
      f_lastname varchar(50) null,
      f_firstname varchar(50) null
      );
      
      insert into minimalTestcase (f_lastname, f_firstname) values ('A', 'X');
      insert into minimalTestcase (f_lastname, f_firstname) values ('B', 'Y');
      insert into minimalTestcase (f_lastname, f_firstname) values ('C', 'Z');
      and the following minimalTestcase.ds.xml:
      Code:
      <DataSource ID="minimalTestcase" serverType="sql" tableName="minimalTestcase">
      <fields>
         <field name="f_id" type="integer" primaryKey="true" />
         <field name="f_lastname" type="text" />
         <field name="f_firstname" type="text" />
      </fields>
      </DataSource>
      1. With the following server-side code:
      Code:
      public DSResponse doCallServer(DSRequest dsRequest, HttpServletResponse servletResponse, RPCManager rpcManager) throws Exception {
      
              System.out.println("doCallServer");
      
              DSRequest updateReq = new DSRequest("minimalTestcase", DataSource.OP_UPDATE, rpcManager);
      
              List<Criterion> criterions = new ArrayList<>();
              Criterion c = new SimpleCriterion("f_lastname", DefaultOperators.Equals, 'A');
              criterions.add(c);
      
              AdvancedCriteria ac = new AdvancedCriteria(DefaultOperators.Or, criterions.toArray(new Criterion[] {}));
              updateReq.setAllowMultiUpdate(true);
      
              Map<String, Object> clearedValues = new HashMap<>();
      
              clearedValues.put("f_firstname", null);
              updateReq.setValues(clearedValues);
              updateReq.setAdvancedCriteria(ac);
              updateReq.execute();
      
              return new DSResponse();
          }
      I get:
      Code:
      UPDATE minimalTestcase SET f_firstname=NULL WHERE (minimalTestcase.f_lastname = 'A' AND minimalTestcase.f_lastname IS NOT NULL)
      2. while only commenting setAllowMultiUpdate(true), thus with the following code:

      Code:
      public DSResponse doCallServer(DSRequest dsRequest, HttpServletResponse servletResponse, RPCManager rpcManager) throws Exception {
      
              System.out.println("doCallServer");
      
              DSRequest updateReq = new DSRequest("minimalTestcase", DataSource.OP_UPDATE, rpcManager);
      
              List<Criterion> criterions = new ArrayList<>();
              Criterion c = new SimpleCriterion("f_lastname", DefaultOperators.Equals, 'A');
              criterions.add(c);
      
              AdvancedCriteria ac = new AdvancedCriteria(DefaultOperators.Or, criterions.toArray(new Criterion[] {}));
      //        updateReq.setAllowMultiUpdate(true);
      
              Map<String, Object> clearedValues = new HashMap<>();
      
              clearedValues.put("f_firstname", null);
              updateReq.setValues(clearedValues);
              updateReq.setAdvancedCriteria(ac);
              updateReq.execute();
      
              return new DSResponse();
          }
      I get:
      Code:
      UPDATE minimalTestcase SET f_firstname=NULL WHERE ('1'='1')
      I didn't change defaultMultiUpdatePolicy anywhere. It has all default settings.

      Comment


        #4
        Hi @Isomorphic,

        as you requested, I tested with the newest nightly: 2018-03-22

        and I get exactly the same results:
        UPDATE minimalTestcase SET f_firstname=NULL WHERE ('1'='1')

        Comment


          #5
          This is fixed and will be available for download in nightly builds since Mar 27 (tomorrow).

          Comment


            #6
            Hi Isomorphic
            thank you, I will check with the new builds.
            Why didn't the autotests you mentioned catch this error?

            Comment


              #7
              Our automated tests covered many different cases of detecting nested AdvancedCriteria to make sure a primaryKey was always included, and correctly removing extraneous criteria, and other edge cases, but did not cover the case where our own criteria-simplifying logic could lead to a request that, once simplified, was then invalid. Definitely a lesson in which and how many tests to write.

              Comment


                #8
                Hi Isomorphic
                the testcase in #3 is still creating

                UPDATE minimalTestcase SET f_firstname=NULL WHERE ('1'='1')

                with the 27-03 builds.
                Last edited by edulid; 27 Mar 2018, 05:12.

                Comment


                  #9
                  Please try again with 28-03 build. Most likely the fix did not make it into 27-03 build. Also, please make sure that your code uses the intended build exactly to exclude possible miss-dependency issues.
                  Last edited by Isomorphic; 28 Mar 2018, 02:52.

                  Comment


                    #10
                    Hi Isomorphic

                    yes, thanks, it seems to work now.
                    This is my output now.
                    java.lang.Exception: Received null criteria for update operation - would update all records - ignoring.
                    Last edited by edulid; 28 Mar 2018, 04:23.

                    Comment

                    Working...
                    X