Project

General

Profile

6830-2.patch

Radu Apetrii, 10/26/2022 04:46 AM

Download (29 KB)

View differences:

new/src/com/goldencode/p2j/convert/db/ConversionData.java 2022-10-25 08:24:00 +0000
147 147
      {
148 148
         // check if the table exists
149 149
         boolean[] found = { false };
150
         Object[] args = new Object[] {table.toUpperCase() + "__WORK"};
150 151
         helper.executeQuery("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES " +
151
                             "WHERE TABLE_SCHEMA = SCHEMA() AND TABLE_NAME LIKE '" + table.toUpperCase() + "__WORK'", (rs) ->
152
                             "WHERE TABLE_SCHEMA = SCHEMA() AND TABLE_NAME LIKE ?", (rs) ->
152 153
         {
153 154
            found[0] = true;
154
         });
155
         }, args);
155 156
         
156 157
         if (!found[0])
157 158
         {
new/src/com/goldencode/p2j/persist/AbstractTempTable.java 2022-10-25 08:24:17 +0000
2442 2442
      sb.append(defBuffer.getTable());
2443 2443
      sb.append(" where ");
2444 2444
      sb.append(TemporaryBuffer.MULTIPLEX_FIELD_NAME);
2445
      sb.append(" = ");
2446
      sb.append(defBuffer.getMultiplexID());
2445
      sb.append(" = ?");
2446
      Object[] args = new Object[] {defBuffer.getMultiplexID()};
2447 2447
      try
2448 2448
      {
2449
         Object res = persistence.getSingleSQLResult(sb.toString(), null);
2449
         Object res = persistence.getSingleSQLResult(sb.toString(), args);
2450 2450
         if (res != null)
2451 2451
         {
2452 2452
            return true;
new/src/com/goldencode/p2j/persist/BufferImpl.java 2022-10-25 08:24:36 +0000
8732 8732
         .append(Buffer.ORIGIN_ROWID_FIELD).append("=NULL, ")
8733 8733
         .append(Buffer.AFTER_ROWID_FIELD).append("=NULL")
8734 8734
         .append(" where ")
8735
         .append(TemporaryBuffer.MULTIPLEX_FIELD_NAME).append(" = ").append(afterBuf.getMultiplexID());
8735
         .append(TemporaryBuffer.MULTIPLEX_FIELD_NAME).append(" = ?");
8736 8736
      
8737
      Object[] args = new Object[] {afterBuf.getMultiplexID()};
8737 8738
      try
8738 8739
      {
8739 8740
         boolean noUndo = !beforeBuf.isUndoable();
8740
         int cnt = persistence.executeSQL(buf.toString(), null, noUndo);
8741
         int cnt = persistence.executeSQL(buf.toString(), args, noUndo);
8741 8742
         afterBuf.pruneSessionCache();
8742 8743
         if (log.isLoggable(Level.FINE))
8743 8744
         {
new/src/com/goldencode/p2j/persist/FastCopyHelper.java 2022-10-25 08:24:56 +0000
811 811
   private static void restartSequence(Persistence persistence, String sequenceName, Long start) 
812 812
   throws PersistenceException
813 813
   {
814
      persistence.executeSQL("alter sequence " + sequenceName + " restart with " + start);
814
      Object[] args = new Object[] {start};
815
      String stmt = persistence.getDialect().getSequenceSetValString(sequenceName);
816
      persistence.executeSQL(stmt, args);
815 817
   }
816 818
   
817 819
   /**
new/src/com/goldencode/p2j/persist/TemporaryBuffer.java 2022-10-25 08:25:39 +0000
4566 4566
         // then update the flag for the after buffer:
4567 4567
         hql = new HQLExpression("update ");
4568 4568
         hql.append(getDMOImplementationName());
4569
         hql.append(" set _rowState = ").append(Integer.toString(Buffer.ROW_CREATED));
4570
         hql.append(" where ").append(MULTIPLEX_FIELD_NAME).append(" = ");
4571
         hql.append(Integer.toString(getMultiplexID()));
4569
         hql.append(" set _rowState = ?");
4570
         hql.append(" where ").append(MULTIPLEX_FIELD_NAME).append(" = ?");
4572 4571
         hql.append(" and (_rowState is null or _rowState = 0)");
4573
         persistence.deleteOrUpdate(hql.toFinalExpression(), null, getEntityName(), !isUndoable());
4572
         Object[] args = new Object[] {Integer.toString(Buffer.ROW_CREATED), Integer.toString(getMultiplexID())};
4573
         persistence.deleteOrUpdate(hql.toFinalExpression(), args, getEntityName(), !isUndoable());
4574 4574
      }
4575 4575
      catch (PersistenceException exc)
4576 4576
      {
......
5429 5429
      
5430 5430
      try
5431 5431
      {
5432
         Object[] args = new Object[] {getMultiplexID()};
5432 5433
         String sql = "select count(*) from " + getTable() + 
5433
                      " where " + MULTIPLEX_FIELD_NAME + " = " + getMultiplexID();
5434
         Long res = getPersistence().getSingleSQLResult(sql, null);
5434
                      " where " + MULTIPLEX_FIELD_NAME + " = ?";
5435
         Long res = getPersistence().getSingleSQLResult(sql, args);
5435 5436
         return res.intValue();
5436 5437
      
5437 5438
      }
......
7526 7527
      {
7527 7528
         if (!full)
7528 7529
         {
7530
            Object[] multiplexArgs = new Object[] {multiplexID};
7529 7531
            // execute a simple query to determine if there is any record in this virtual table
7530 7532
            String checkStmt = 
7531 7533
                  "select tt." + Session.PK + " from " + table + " tt " +
7532
                  "where tt." + MULTIPLEX_FIELD_NAME + " = " + multiplexID + " limit 1";
7533
            Long id = persistence.getSingleSQLResult(checkStmt, null);
7534
                  "where tt." + MULTIPLEX_FIELD_NAME + " = ?" + " limit 1";
7535
            Long id = persistence.getSingleSQLResult(checkStmt, multiplexArgs);
7534 7536
            full = (id == null);
7535 7537
         }
7536 7538
         
new/src/com/goldencode/p2j/persist/dialect/Dialect.java 2022-10-26 07:25:16 +0000
718 718
   public abstract String getSequenceSetValString(String sequenceName, long newVal);
719 719
   
720 720
   /**
721
    * Generate the appropriate select statement to reset the value of a sequence.
722
    * 
723
    * @param   sequenceName
724
    *          The name of the sequence.
725
    *
726
    * @return  Dialect-specific string to set the current value of the sequence, or {@code null}
727
    *          if not supported.
728
    */
729
   public abstract String getSequenceSetValString(String sequenceName);
730
   
731
   /**
732
    * Generate the appropriate select statement to reset the value of a sequence.
733
    * 
734
    * @return  Dialect-specific string to set the current value of the sequence, or {@code null}
735
    *          if not supported.
736
    */
737
   public abstract String getSequenceSetValString();
738
   
739
   /**
721 740
    * Generate the appropriate select statement to retrieve the next value of a sequence.
722 741
    * 
723 742
    * @param   sequenceName
......
738 757
   public abstract String getSequenceCurrValString(String sequenceName);
739 758
   
740 759
   /**
760
    * Generate the appropriate select statement to retrieve the current value of a sequence.
761
    *
762
    * @return  Dialect-specific string to query the sequence, or {@code null} if not supported.
763
    */
764
   public String getSequenceCurrValString()
765
   {
766
      throw new IllegalStateException(
767
               "Current value of a sequence cannot be retrieved using prepared statements.");
768
   }
769
   
770
   /**
741 771
    * Returns {@code true} if this dialect fully support the sequences as 4GL language (most important:
742 772
    * bounded values, cycle). If not fully supported, additional code is needed in P2J sequence class
743 773
    * implementation to fix this.
new/src/com/goldencode/p2j/persist/dialect/MariaDbDialect.java 2022-10-26 07:25:22 +0000
879 879
   }
880 880
   
881 881
   /**
882
    * Generate the appropriate select statement to reset the value of a sequence.
883
    *
884
    * @param   sequenceName
885
    *          The name of the sequence.
886
    *
887
    * @return  Dialect-specific string to set the current value of the sequence, or {@code null}
888
    *          if not supported.
889
    *
890
    * @see  <a href="https://mariadb.com/kb/en/setval/">SETVAL() Function</a>
891
    */
892
   @Override
893
   public String getSequenceSetValString(String sequenceName)
894
   {
895
      return "select setval(" + sequenceName + ", ?)";
896
   }
897
   
898
   /**
899
    * Generate the appropriate select statement to reset the value of a sequence.
900
    *
901
    * @return  Dialect-specific string to set the current value of the sequence, or {@code null}
902
    *          if not supported.
903
    *
904
    * @see  <a href="https://mariadb.com/kb/en/setval/">SETVAL() Function</a>
905
    */
906
   @Override
907
   public String getSequenceSetValString()
908
   {
909
      return "select setval(?, ?)";
910
   }
911
   
912
   /**
882 913
    * Generate the appropriate select statement to retrieve the next value of a sequence.
883 914
    *
884 915
    * @param   sequenceName
new/src/com/goldencode/p2j/persist/dialect/P2JH2Dialect.java 2022-10-26 07:25:29 +0000
761 761
   }
762 762
   
763 763
   /**
764
    * Generate the appropriate select statement to reset the value of a 
765
    * sequence.
766
    * 
767
    * @param   sequenceName
768
    *          The name of the sequence.
769
    *
770
    * @return  Dialect-specific string to query the sequence, or
771
    *          <code>null</code> if not supported.
772
    */
773
   @Override
774
   public String getSequenceSetValString(String sequenceName)
775
   {
776
      return "alter sequence " + sequenceName + " restart with ?";
777
   }
778
   
779
   /**
780
    * Generate the appropriate select statement to reset the value of a 
781
    * sequence.
782
    *
783
    * @return  Dialect-specific string to query the sequence, or
784
    *          <code>null</code> if not supported.
785
    */
786
   @Override
787
   public String getSequenceSetValString()
788
   {
789
      throw new IllegalStateException("Can't reset value of a sequence with prepared statement in H2");
790
   }
791
   
792
   /**
764 793
    * Generate the appropriate select statement to retrieve the current 
765 794
    * value of a sequence.
766 795
    * 
......
777 806
      return "select current_value from information_schema.sequences " +
778 807
             "where upper(sequence_name) = '" + sequenceName.toUpperCase() + "'";
779 808
   }
809
   
810
   /**
811
    * Generate the appropriate select statement to retrieve the current 
812
    * value of a sequence.
813
    *
814
    * @return  Dialect-specific string to query the sequence, or
815
    *          <code>null</code> if not supported.
816
    */
817
   @Override
818
   public String getSequenceCurrValString()
819
   {
820
      // this feature is not supported by H2 directly, use a workaround
821
      return "select current_value from information_schema.sequences " +
822
             "where upper(sequence_name) = ?";
823
   }
780 824

  
781 825
   /**
782 826
    * Returns <code>true</code> if this dialect fully support the sequences as
new/src/com/goldencode/p2j/persist/dialect/P2JPostgreSQLDialect.java 2022-10-26 07:25:36 +0000
1103 1103
   
1104 1104
   /**
1105 1105
    * Generate the appropriate select statement to retrieve the next value of a sequence.
1106
    * 
1107
    * @param   sequenceName
1108
    *          The name of the sequence.
1109
    *
1110
    * @return  Dialect-specific string to query the sequence, or
1111
    *          <code>null</code> if not supported.
1112
    */
1113
   @Override
1114
   public String getSequenceSetValString(String sequenceName)
1115
   {
1116
      return "select setval('" + sequenceName + "', ?)";
1117
   }
1118
   
1119
   /**
1120
    * Generate the appropriate select statement to retrieve the next value of a sequence.
1121
    *
1122
    * @return  Dialect-specific string to query the sequence, or
1123
    *          <code>null</code> if not supported.
1124
    */
1125
   @Override
1126
   public String getSequenceSetValString()
1127
   {
1128
      return "select setval(?, ?)";
1129
   }
1130
   
1131
   /**
1132
    * Generate the appropriate select statement to retrieve the next value of a sequence.
1106 1133
    *
1107 1134
    * @param   sequenceName
1108 1135
    *          The name of the sequence to be queried.
new/src/com/goldencode/p2j/persist/dialect/P2JSQLServer2008Dialect.java 2022-10-26 07:25:42 +0000
958 958
   }
959 959
   
960 960
   /**
961
    * Generate the appropriate select statement to reset the value of a sequence.
962
    *
963
    * @param   sequenceName
964
    *          The name of the sequence.
965
    *
966
    * @return  Returning {@code null} since this dialect does not support sequences.
967
    */
968
   @Override
969
   public String getSequenceSetValString(String sequenceName)
970
   {
971
      return null;
972
   }
973
   
974
   /**
975
    * Generate the appropriate select statement to reset the value of a sequence.
976
    *
977
    * @return  Returning {@code null} since this dialect does not support sequences.
978
    */
979
   @Override
980
   public String getSequenceSetValString()
981
   {
982
      return null;
983
   }
984
   
985
   /**
961 986
    * Generate the appropriate select statement to retrieve the next value of a sequence.
962 987
    *
963 988
    * @param   sequenceName
new/src/com/goldencode/p2j/persist/dialect/P2JSQLServer2012Dialect.java 2022-10-25 09:17:53 +0000
457 457
   }
458 458
   
459 459
   /**
460
    * Generate the appropriate select statement to retrieve the current value of a sequence.
461
    *
462
    * @return  Dialect-specific string to query the sequence.
463
    */
464
   @Override
465
   public String getSequenceCurrValString()
466
   {
467
      // the cast is needed because the column is of 'variant' datatype.
468
      // the sql driver does not handle it and reports the following error: 
469
      // 08S01 The "variant" data type is not supported.
470
      return "select cast(current_value as bigint) " +
471
             "from sys.sequences where name = ?";
472
   }
473
   
474
   /**
460 475
    * Generate the appropriate select statement to retrieve the next value of a sequence.
461 476
    *
462 477
    * @param   sequenceName
new/src/com/goldencode/p2j/persist/dirty/DefaultDirtyShareManager.java 2022-10-25 08:26:44 +0000
784 784
            }
785 785
            
786 786
            String hql = "delete from " + entity + 
787
                         " where " + DatabaseManager.PRIMARY_KEY + " = " + id;
787
                         " where " + DatabaseManager.PRIMARY_KEY + " = ?";
788 788
            Session session = null;
789 789
            boolean inTx = false;
790 790
            
......
792 792
            {
793 793
               session = new Session(dirtyDatabase);
794 794
               inTx = session.beginTransaction();
795
               
795 796
               Query query = Session.createQuery(hql);
797
               query.setParameter(0, id);
796 798
               query.executeUpdate(session);
799
               
797 800
               session.commit();
798 801
            }
799 802
            catch (PersistenceException exc)
new/src/com/goldencode/p2j/persist/meta/TransactionTableUpdater.java 2022-10-25 08:26:57 +0000
197 197
         // drop all records that are no more valid
198 198
         StringBuilder buf = new StringBuilder(
199 199
               "delete from " + TRANS_TABLE + " where not trans_num in (");
200
         List<Object> args = new ArrayList<>();
200 201
         Iterator<Integer> it = transactions.values().iterator();
201 202
         for (int i = 0; it.hasNext(); i++)
202 203
         {
......
205 206
               buf.append(',');
206 207
            }
207 208
            
208
            buf.append(it.next());
209
            args.add(it.next());
210
            buf.append('?');
209 211
         }
210 212
         buf.append(')');
211
         int delCounter = p.executeSQL(buf.toString());
213
         int delCounter = p.executeSQL(buf.toString(), args.toArray());
212 214
         if (LOG.isLoggable(Level.FINE))
213 215
         {
214 216
            LOG.log(Level.FINE, "Dropped " + delCounter + " old _trans records from " + dbName);
new/src/com/goldencode/p2j/persist/sequence/H2SequenceHandler.java 2022-10-25 08:27:18 +0000
140 140
      
141 141
      Persistence persistence = ConnectionManager.getPersistence(ldbName);
142 142
      Dialect dialect = persistence.getDialect();
143
      String strQuery = dialect.getSequenceCurrValString(seqName);
143
      Object[] args = new Object[] {seqName};
144
      String strQuery = dialect.getSequenceCurrValString();
144 145
      int64 ret;
145 146
      
146 147
      try
147 148
      {
148
         ret = getResultValue(persistence.getSingleSQLResult(strQuery, null));
149
         ret = getResultValue(persistence.getSingleSQLResult(strQuery, args));
149 150
      }
150 151
      catch (PersistenceException pe)
151 152
      {
......
365 366
      
366 367
      Persistence persistence = ConnectionManager.getPersistence(ldbName);
367 368
      Dialect dialect = persistence.getDialect();
368
      String strQuery = dialect.getSequenceSetValString(seqName, newValFixed);
369
      Object[] args = new Object[] {newValFixed};
370
      String strQuery = dialect.getSequenceSetValString(seqName);
369 371
      
370 372
      try
371 373
      {
372
         persistence.executeSQL(strQuery);
374
         persistence.executeSQL(strQuery, args);
373 375
      }
374 376
      catch (PersistenceException pe)
375 377
      {
new/src/com/goldencode/p2j/persist/sequence/MariaDbSequenceHandler.java 2022-10-26 07:26:33 +0000
270 270
      
271 271
      Persistence persistence = ConnectionManager.getPersistence(ldbName);
272 272
      Dialect dialect = persistence.getDialect();
273
      String setCrtValQuery = dialect.getSequenceSetValString(seqName, newVal);
273
      Object[] args = new Object[] {seqName, newVal};
274
      String setCrtValQuery = dialect.getSequenceSetValString();
274 275
      
275 276
      try
276 277
      {
277
         persistence.getSingleSQLResult(setCrtValQuery, null);
278
         persistence.getSingleSQLResult(setCrtValQuery, args);
278 279
      }
279 280
      catch (PersistenceException pe)
280 281
      {
new/src/com/goldencode/p2j/persist/sequence/PostgreSQLSequenceHandler.java 2022-10-26 07:26:46 +0000
281 281
      
282 282
      Persistence persistence = ConnectionManager.getPersistence(ldbName);
283 283
      Dialect dialect = persistence.getDialect();
284
      String setCrtValQuery = dialect.getSequenceSetValString(seqName, newVal);
284
      Object[] args = new Object[] {seqName, newVal};
285
      String setCrtValQuery = dialect.getSequenceSetValString();
285 286
      
286 287
      try
287 288
      {
288
         persistence.getSingleSQLResult(setCrtValQuery, null);
289
         persistence.getSingleSQLResult(setCrtValQuery, args);
289 290
      }
290 291
      catch (PersistenceException pe)
291 292
      {
new/src/com/goldencode/p2j/report/ReportWorker.java 2022-10-25 08:28:44 +0000
453 453
         
454 454
         // read back the id that was autogenerated
455 455
         ResultSet rs = stmtReportInsert.getGeneratedKeys();
456
         PreparedStatement stmt = null;
456 457
         rs.next();
457 458
         rpt.id = rs.getLong(1);
459
         List<Object> args = new ArrayList<>();
458 460
         
459 461
         if (processTags && rpt.tags != null && !rpt.tags.isEmpty())
460 462
         {
461
            StringBuilder buf = new StringBuilder("select id, name from tag where name in('");
463
            StringBuilder buf = new StringBuilder("select id, name from tag where name in(");
462 464
            Iterator<String> iter = rpt.tags.iterator();
463 465
            for (int i = 0; iter.hasNext(); i++)
464 466
            {
465 467
               if (i > 0)
466 468
               {
467
                  buf.append("', '");
469
                  buf.append(", ");
468 470
               }
469 471
               String tag = iter.next();
470 472
               tag.replaceAll("\'", "\\\'");
471
               buf.append(tag);
473
               buf.append("?");
474
               args.add(tag);
472 475
            }
473
            buf.append("')");
476
            buf.append(")");
474 477
            String sql = buf.toString();
475 478
            
476 479
            Map<String, Long> tagMap = new HashMap<>();
477
            Statement stmt = connection.createStatement();
478
            rs = stmt.executeQuery(sql);
480
            stmt = connection.prepareStatement(sql);
481
            for (int i = 0; i < args.size(); i++)
482
            {
483
               stmt.setObject(i + 1, args.get(i));
484
            }
485
            
486
            rs = stmt.executeQuery();
479 487
            while (rs.next())
480 488
            {
481 489
               long tid = rs.getLong(1);
......
509 517
               stmtRptTagInsert.clearParameters();
510 518
            }
511 519
         }
520
         
521
         if (rs != null && !rs.isClosed())
522
         {
523
            rs.close();
524
         }
525
         
526
         if (stmt != null && !stmt.isClosed())
527
         {
528
            stmt.close();
529
         }
512 530
      }
513 531
      
514 532
      return rpt.id;
new/src/com/goldencode/p2j/report/server/ReportApi.java 2022-10-26 07:29:25 +0000
745 745
    */
746 746
   private static void applyFileFilter(Connection conn, Long profileId, long sessionId)
747 747
   {
748
      try (Statement stmt = conn.createStatement())
748
      PreparedStatement stmt = null;
749
      ResultSet rs = null;
750
      try
749 751
      {
750 752
         String sql;
751
         ResultSet rs;
752 753
         
753 754
         if (profileId != null)
754 755
         {
755 756
            // if profileId is null, the active_file was just created and is already empty;
756 757
            // otherwise, delete all its records in preparation for re-population with the new
757 758
            // filter profile's data
758
            stmt.execute("delete from active_file where sid = " + sessionId);
759
            stmt = conn.prepareStatement("delete from active_file where sid = ?");
760
            stmt.setObject(1, sessionId);
761
            stmt.executeUpdate();
759 762
         }
760 763
         
761 764
         // Query file specs and types for the provided file filter profile; we will compose a
......
763 766
         // If provided profile id was null, get the default profile.
764 767
         
765 768
         int i;
766
         
769
         int type = 0;
767 770
         // wildcard path specs first
768 771
         
769 772
         if (profileId == null)
......
776 779
         {
777 780
            sql = "select f.spec from file_filter f " +
778 781
                  "join filter_profile p on p.id = f.pid " +
779
                  "where p.id = " + profileId + " and f.wild = true";
780
         }
781
         rs = stmt.executeQuery(sql);
782
         
782
                  "where p.id = ?" + " and f.wild = true";
783
            type = 1;
784
         }
785
         
786
         if (stmt != null && !stmt.isClosed())
787
         {
788
            stmt.close();
789
         }
790
         
791
         stmt = conn.prepareStatement(sql);
792
         if (type == 1)
793
         {
794
            stmt.setObject(1, profileId);
795
         }
796
         
797
         type = 0;
798
         rs = stmt.executeQuery();
799

  
800
         List<Object> args = new ArrayList<>();
783 801
         StringBuilder buf = new StringBuilder("insert into active_file (fid, sid) ");
784 802
         for (i = 0; rs.next(); i++)
785 803
         {
......
792 810
            
793 811
            buf.append("select distinct(f.id), ");
794 812
            buf.append(sessionId);
795
            buf.append(" from file f join ast_map a on a.fid = f.id where f.name like '");
796
            buf.append(dbs.escapeLikeRValue(spec));
797
            buf.setCharAt(buf.length() - 1, '%');
798
            buf.append("'");
813
            buf.append(" from file f join ast_map a on a.fid = f.id where f.name like ?");
814
            String arg1 = dbs.escapeLikeRValue(spec);
815
            arg1 = arg1.substring(0, arg1.length() - 1) + '%';
816
            args.add(arg1);
799 817
         }
800 818
         
801 819
         if (profileId == null)
......
808 826
         {
809 827
            sql = "select f.spec from file_filter f " +
810 828
                  "join filter_profile p on p.id = f.pid " +
811
                  "where p.id = " + profileId + " and f.wild = false";
812
         }
813
         rs = stmt.executeQuery(sql);
829
                  "where p.id = ?" + " and f.wild = false";
830
            type = 1;
831
         }
832
         
833
         if (rs != null && !rs.isClosed())
834
         {
835
            rs.close();
836
         }
837
         
838
         if (stmt != null && !stmt.isClosed())
839
         {
840
            stmt.close();
841
         }
842
         
843
         stmt = conn.prepareStatement(sql);
844
         if (type == 1)
845
         {
846
            stmt.setObject(1, profileId);
847
         }
848
         
849
         type = 0;
850
         rs = stmt.executeQuery();
814 851
         
815 852
         int j = 0;
816 853
         for (; rs.next(); i++)
......
833 870
               buf.append(", ");
834 871
            }
835 872
            
836
            buf.append("'");
837
            buf.append(spec);
838
            buf.append("'");
873
            args.add(spec);
839 874
            
840 875
            if (++j == 100)
841 876
            {
......
850 885
         }
851 886
         
852 887
         sql = buf.toString();
853
         
854
         stmt.execute(sql);
888
         if (rs != null && !rs.isClosed())
889
         {
890
            rs.close();
891
         }
892
         
893
         if (stmt != null && !stmt.isClosed())
894
         {
895
            stmt.close();
896
         }
897
         
898
         stmt = conn.prepareStatement(sql);
899
         for (int k = 0; k < args.size();k++)
900
         {
901
            stmt.setObject(k + 1, args.get(k));
902
         }
903
         
904
         stmt.execute();
855 905
         int uc = stmt.getUpdateCount();
856 906
         System.out.println("applyActiveFile update count: " + uc);
857 907
         
......
873 923
         
874 924
         throw new RuntimeException(exc);
875 925
      }
926
      finally
927
      {
928
         try
929
         {
930
            if (rs != null && !rs.isClosed())
931
            {
932
               rs.close();
933
            }
934
            
935
            if (stmt != null && !stmt.isClosed())
936
            {
937
               stmt.close();
938
            }
939
         }
940
         catch (SQLException e)
941
         {
942
            e.printStackTrace();
943
         }
944
      }
876 945
   }
877 946
   
878 947
   /**
......
2513 2582
      buf.append("insert into search_history ");
2514 2583
      buf.append("select * from (select next value for seq_search_history_pk, '");
2515 2584
      buf.append(criteria);
2516
      buf.append("' ) x where not exists (select 1 from search_history where criteria = '");
2517
      buf.append(criteria);
2518
      buf.append("')");
2585
      buf.append("' ) x where not exists (select 1 from search_history where criteria = ?)");
2586
      Object histArg = criteria;
2519 2587
      String sqlInsSrchHist = buf.toString();
2520 2588
      
2521 2589
      // compose sql to insert into user_search table, if not already present
2522 2590
      buf.setLength(0);
2523 2591
      buf.append("insert into user_search select * from (select ");
2524 2592
      buf.append(user.getId());
2525
      buf.append(" as u, select id from search_history where criteria = '");
2526
      buf.append(criteria);
2527
      buf.append("' as s) x where exists (select 1 from search_history where criteria = '");
2528
      buf.append(criteria);
2529
      buf.append("') and not exists (select 1 from user_search where uid = x.u and sid = x.s)");
2593
      buf.append(" as u, select id from search_history where criteria = ?");
2594
      buf.append(" as s) x where exists (select 1 from search_history where criteria = ?");
2595
      buf.append(") and not exists (select 1 from user_search where uid = x.u and sid = x.s)");
2596
      Object usrArg = criteria;
2530 2597
      String sqlInsUsrSrch = buf.toString();
2531 2598
      
2532
      try (Statement stmt = conn.createStatement())
2533
      {
2534
         // we use Statement instead of PreparedStatement here because we need a substitution
2535
         // parameter in the select clauses of each statement, which H2 does not allow
2536
         stmt.execute(sqlInsSrchHist);
2537
         stmt.execute(sqlInsUsrSrch);
2599
      //tested with H2 1.4.200 and prepared statements now work with subselects
2600
      try (PreparedStatement stmt = conn.prepareStatement(sqlInsSrchHist))
2601
      {
2602
         stmt.setObject(1, histArg);
2603
         stmt.execute();
2604
      }
2605
      
2606
      try (PreparedStatement stmt = conn.prepareStatement(sqlInsUsrSrch))
2607
      {
2608
         stmt.setObject(1, usrArg);
2609
         stmt.setObject(2, usrArg);
2610
         stmt.execute();
2538 2611
      }
2539 2612
   }
2540 2613