Project

General

Profile

6830-6129b.patch

Radu Apetrii, 01/09/2023 06:35 AM

Download (33.4 KB)

View differences:

new/src/com/goldencode/p2j/convert/db/ConversionData.java 2023-01-09 10:36:39 +0000
15 15
**     CA  20211012 Fixed generated WSDL and reworked SOAP support to rely on namespace, when resolving an
16 16
**                  operation.
17 17
**     GES 20220502 Match API method name change.
18
**     RAA 20230109 Changed inline statement(s) to prepared statement(s).
18 19
*/
19 20

  
20 21
/*
......
149 150
      {
150 151
         // check if the table exists
151 152
         boolean[] found = { false };
153
         Object[] args = new Object[] {table.toUpperCase() + "__WORK"};
152 154
         helper.executeQuery("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES " +
153
                             "WHERE TABLE_SCHEMA = SCHEMA() AND TABLE_NAME LIKE '" + table.toUpperCase() + "__WORK'", (rs) ->
155
                             "WHERE TABLE_SCHEMA = SCHEMA() AND TABLE_NAME LIKE ?", (rs) ->
154 156
         {
155 157
            found[0] = true;
156
         });
158
         }, args);
157 159
         
158 160
         if (!found[0])
159 161
         {
new/src/com/goldencode/p2j/persist/AbstractTempTable.java 2023-01-09 10:38:43 +0000
57 57
**                  delete it instead of handle.delete.
58 58
**     IAS 20221003 Fixed error message for error 3131
59 59
**     IAS 20221111 Added setter for the 'schemaMarshalLevel', fixed one for the 'namespaceURI'.
60
**     RAA 20230109 Changed inline statement(s) to prepared statement(s).
60 61
*/
61 62

  
62 63
/*
......
2575 2576
      sb.append(defBuffer.getTable());
2576 2577
      sb.append(" where ");
2577 2578
      sb.append(TemporaryBuffer.MULTIPLEX_FIELD_NAME);
2578
      sb.append(" = ");
2579
      sb.append(defBuffer.getMultiplexID());
2579
      sb.append(" = ?");
2580
      Object[] args = new Object[] {defBuffer.getMultiplexID()};
2580 2581
      try
2581 2582
      {
2582
         Object res = persistence.getSingleSQLResult(sb.toString(), null);
2583
         Object res = persistence.getSingleSQLResult(sb.toString(), args);
2583 2584
         if (res != null)
2584 2585
         {
2585 2586
            return true;
new/src/com/goldencode/p2j/persist/BufferImpl.java 2023-01-09 10:40:25 +0000
243 243
**     CA  20221121 For a dynamic TEMP-TABLE, if the NAME attribute is changed, then the default-buffer's NAME
244 244
**                  must be changed, too.
245 245
**     SVL 20230108 Improved performance by replacing some "for-each" loops with indexed "for" loops.
246
**     RAA 20230109 Changed inline statement(s) to prepared statement(s).
246 247
*/
247 248

  
248 249
/*
......
9242 9243
         .append(Buffer.ORIGIN_ROWID_FIELD).append("=NULL, ")
9243 9244
         .append(Buffer.AFTER_ROWID_FIELD).append("=NULL")
9244 9245
         .append(" where ")
9245
         .append(TemporaryBuffer.MULTIPLEX_FIELD_NAME).append(" = ").append(afterBuf.getMultiplexID());
9246
         .append(TemporaryBuffer.MULTIPLEX_FIELD_NAME).append(" = ?");
9246 9247
      
9248
      Object[] args = new Object[] {afterBuf.getMultiplexID()};
9247 9249
      try
9248 9250
      {
9249 9251
         boolean noUndo = !beforeBuf.isUndoable();
9250
         int cnt = persistence.executeSQL(buf.toString(), null, noUndo);
9252
         int cnt = persistence.executeSQL(buf.toString(), args, noUndo);
9251 9253
         afterBuf.pruneSessionCache();
9252 9254
         if (log.isLoggable(Level.FINE))
9253 9255
         {
new/src/com/goldencode/p2j/persist/FastCopyHelper.java 2023-01-09 10:41:46 +0000
22 22
**     ECF 20221006 Minor optimization.
23 23
**     OM  20220913 Enhanced dialect API for sorting nulls.
24 24
**     OM  20221012 Fixed regression in previous commit.
25
**     RAA 20230109 Changed inline statement(s) to prepared statement(s).
25 26
*/
26 27

  
27 28
/*
......
813 814
   private static void restartSequence(Persistence persistence, String sequenceName, Long start) 
814 815
   throws PersistenceException
815 816
   {
816
      persistence.executeSQL("alter sequence " + sequenceName + " restart with " + start);
817
      Object[] args = new Object[] {start};
818
      String stmt = persistence.getDialect().getSequenceSetValString(sequenceName);
819
      persistence.executeSQL(stmt, args);
817 820
   }
818 821
   
819 822
   /**
new/src/com/goldencode/p2j/persist/TemporaryBuffer.java 2023-01-09 10:46:17 +0000
628 628
**     IAS 20221103          Fixed support for a binded table parameter.
629 629
**     CA  20221206          If a REFERENCE-ONLY table is already bound to the same target table, do not 
630 630
**                           re-bind. 
631
**     RAA 20230109          Changed inline statement(s) to prepared statement(s).
631 632
*/
632 633

  
633 634
/*
......
4799 4800
         // then update the flag for the after buffer:
4800 4801
         fql = new FQLExpression("update ");
4801 4802
         fql.append(getDMOImplementationName());
4802
         fql.append(" set _rowState = ").append(Integer.toString(Buffer.ROW_CREATED));
4803
         fql.append(" where ").append(MULTIPLEX_FIELD_NAME).append(" = ");
4804
         fql.append(Integer.toString(getMultiplexID()));
4803
         fql.append(" set _rowState = ?");
4804
         fql.append(" where ").append(MULTIPLEX_FIELD_NAME).append(" = ?");
4805 4805
         fql.append(" and (_rowState is null or _rowState = 0)");
4806
         persistence.deleteOrUpdate(fql.toFinalExpression(), null, getEntityName(), !isUndoable());
4806
         Object[] args = new Object[] {Integer.toString(Buffer.ROW_CREATED), 
4807
                                       Integer.toString(getMultiplexID())};
4808
         persistence.deleteOrUpdate(fql.toFinalExpression(), args, getEntityName(), !isUndoable());
4807 4809
      }
4808 4810
      catch (PersistenceException exc)
4809 4811
      {
......
5665 5667
      
5666 5668
      try
5667 5669
      {
5670
         Object[] args = new Object[] {getMultiplexID()};
5668 5671
         String sql = "select count(*) from " + getTable() + 
5669
                      " where " + MULTIPLEX_FIELD_NAME + " = " + getMultiplexID();
5670
         Long res = getPersistence().getSingleSQLResult(sql, null);
5672
                      " where " + MULTIPLEX_FIELD_NAME + " = ?";
5673
         Long res = getPersistence().getSingleSQLResult(sql, args);
5671 5674
         return res.intValue();
5672 5675
      
5673 5676
      }
......
7781 7784
      {
7782 7785
         if (!full)
7783 7786
         {
7787
            Object[] multiplexArgs = new Object[] {multiplexID};
7784 7788
            // execute a simple query to determine if there is any record in this virtual table
7785 7789
            String checkStmt = 
7786 7790
                  "select tt." + Session.PK + " from " + table + " tt " +
7787
                  "where tt." + MULTIPLEX_FIELD_NAME + " = " + multiplexID + " limit 1";
7788
            Long id = persistence.getSingleSQLResult(checkStmt, null);
7791
                  "where tt." + MULTIPLEX_FIELD_NAME + " = ?" + " limit 1";
7792
            Long id = persistence.getSingleSQLResult(checkStmt, multiplexArgs);
7789 7793
            full = (id == null);
7790 7794
         }
7791 7795
         
new/src/com/goldencode/p2j/persist/dialect/Dialect.java 2023-01-09 10:52:58 +0000
88 88
**     OM  20221018          Added support for MariaDb lenient dialect.
89 89
**     OM  20221026          Excluded table name from index name by default. It will be added as needed by
90 90
**                           dialects.
91
**     RAA 20230109          Added method getSequenceSetValString().
91 92
*/
92 93

  
93 94
/*
......
759 760
   public abstract String getSequenceSetValString(String sequenceName, long newVal);
760 761
   
761 762
   /**
763
    * Generate the appropriate select statement to reset the value of a sequence.
764
    * 
765
    * @param   sequenceName
766
    *          The name of the sequence.
767
    *
768
    * @return  Dialect-specific string to set the current value of the sequence, or {@code null}
769
    *          if not supported.
770
    */
771
   public abstract String getSequenceSetValString(String sequenceName);
772
   
773
   /**
774
    * Generate the appropriate select statement to reset the value of a sequence.
775
    * 
776
    * @return  Dialect-specific string to set the current value of the sequence, or {@code null}
777
    *          if not supported.
778
    */
779
   public abstract String getSequenceSetValString();
780
   
781
   /**
782
    * 
762 783
    * Generate the appropriate select statement to retrieve the next value of a sequence.
763 784
    * 
764 785
    * @param   sequenceName
......
779 800
   public abstract String getSequenceCurrValString(String sequenceName);
780 801
   
781 802
   /**
803
    * Generate the appropriate select statement to retrieve the current value of a sequence.
804
    *
805
    * @return  Dialect-specific string to query the sequence, or {@code null} if not supported.
806
    */
807
   public String getSequenceCurrValString()
808
   {
809
      throw new IllegalStateException(
810
               "Current value of a sequence cannot be retrieved using prepared statements.");
811
   }
812
   
813
   /**
782 814
    * Returns {@code true} if this dialect fully support the sequences as 4GL language (most important:
783 815
    * bounded values, cycle). If not fully supported, additional code is needed in P2J sequence class
784 816
    * implementation to fix this.
new/src/com/goldencode/p2j/persist/dialect/MariaDbLenientDialect.java 2023-01-09 10:57:04 +0000
9 9
**                  becomes a subclass and will implement the methods to adhere to MariaDb strict(er) mode.
10 10
**     OM  20221025 Improve sequence compatibility with 4GL.
11 11
**     OM  20221026 Excluded table name from index name by default. It will be added as needed by dialects.
12
**     RAA 20230109 Overrided method getSequenceSetValString().
12 13
*/
13 14

  
14 15
/*
......
1074 1075
   }
1075 1076
   
1076 1077
   /**
1078
    * Generate the appropriate select statement to reset the value of a sequence.
1079
    *
1080
    * @param   sequenceName
1081
    *          The name of the sequence.
1082
    *
1083
    * @return  Dialect-specific string to set the current value of the sequence, or {@code null}
1084
    *          if not supported.
1085
    *
1086
    * @see  <a href="https://mariadb.com/kb/en/setval/">SETVAL() Function</a>
1087
    */
1088
   @Override
1089
   public String getSequenceSetValString(String sequenceName)
1090
   {
1091
      return "select setval(" + sequenceName + ", ?)";
1092
   }
1093
   
1094
   /**
1095
    * Generate the appropriate select statement to reset the value of a sequence.
1096
    *
1097
    * @return  Dialect-specific string to set the current value of the sequence, or {@code null}
1098
    *          if not supported.
1099
    *
1100
    * @see  <a href="https://mariadb.com/kb/en/setval/">SETVAL() Function</a>
1101
    */
1102
   @Override
1103
   public String getSequenceSetValString()
1104
   {
1105
      return "select setval(?, ?)";
1106
   }
1107
   
1108
   /**
1077 1109
    * Generate the appropriate select statement to retrieve the next value of a sequence.
1078 1110
    *
1079 1111
    * @param   sequenceName
new/src/com/goldencode/p2j/persist/dialect/P2JH2Dialect.java 2023-01-09 11:00:20 +0000
104 104
**     OM  20221012          Fixed regression (invalid sort criteria) in previous commit.
105 105
**     OM  20221026          Excluded table name from index name by default. It will be added as needed by
106 106
**                           dialects.
107
**     RAA 20230109          Overrided methods getSequenceSetValString() and getSequenceCurrValString().
107 108
*/
108 109

  
109 110
/*
......
768 769
   }
769 770
   
770 771
   /**
772
    * Generate the appropriate select statement to reset the value of a 
773
    * sequence.
774
    * 
775
    * @param   sequenceName
776
    *          The name of the sequence.
777
    *
778
    * @return  Dialect-specific string to query the sequence, or
779
    *          <code>null</code> if not supported.
780
    */
781
   @Override
782
   public String getSequenceSetValString(String sequenceName)
783
   {
784
      return "alter sequence " + sequenceName + " restart with ?";
785
   }
786
   
787
   /**
788
    * Generate the appropriate select statement to reset the value of a 
789
    * sequence.
790
    *
791
    * @return  Dialect-specific string to query the sequence, or
792
    *          <code>null</code> if not supported.
793
    */
794
   @Override
795
   public String getSequenceSetValString()
796
   {
797
      throw new IllegalStateException("Can't reset value of a sequence with prepared statement in H2");
798
   }
799
   
800
   /**
771 801
    * Generate the appropriate select statement to retrieve the current 
772 802
    * value of a sequence.
773 803
    * 
......
784 814
      return "select current_value from information_schema.sequences " +
785 815
             "where upper(sequence_name) = '" + sequenceName.toUpperCase() + "'";
786 816
   }
817
   
818
   /**
819
    * Generate the appropriate select statement to retrieve the current 
820
    * value of a sequence.
821
    *
822
    * @return  Dialect-specific string to query the sequence, or
823
    *          <code>null</code> if not supported.
824
    */
825
   @Override
826
   public String getSequenceCurrValString()
827
   {
828
      // this feature is not supported by H2 directly, use a workaround
829
      return "select current_value from information_schema.sequences " +
830
             "where upper(sequence_name) = ?";
831
   }
787 832

  
788 833
   /**
789 834
    * Returns <code>true</code> if this dialect fully support the sequences as
new/src/com/goldencode/p2j/persist/dialect/P2JPostgreSQLDialect.java 2023-01-09 11:01:55 +0000
122 122
**     IAS 20220921          Dialect-specific UDF schema.
123 123
**     OM  20221026          Excluded table name from index name by default. It will be added as needed by
124 124
**                           dialects.
125
**     RAA 20230109          Overrided method getSequenceSetValString().
125 126
*/
126 127

  
127 128
/*
......
1109 1110
   
1110 1111
   /**
1111 1112
    * Generate the appropriate select statement to retrieve the next value of a sequence.
1113
    * 
1114
    * @param   sequenceName
1115
    *          The name of the sequence.
1116
    *
1117
    * @return  Dialect-specific string to query the sequence, or
1118
    *          <code>null</code> if not supported.
1119
    */
1120
   @Override
1121
   public String getSequenceSetValString(String sequenceName)
1122
   {
1123
      return "select setval('" + sequenceName + "', ?)";
1124
   }
1125
   
1126
   /**
1127
    * Generate the appropriate select statement to retrieve the next value of a sequence.
1128
    *
1129
    * @return  Dialect-specific string to query the sequence, or
1130
    *          <code>null</code> if not supported.
1131
    */
1132
   @Override
1133
   public String getSequenceSetValString()
1134
   {
1135
      return "select setval(?, ?)";
1136
   }
1137
   
1138
   /**
1139
    * Generate the appropriate select statement to retrieve the next value of a sequence.
1112 1140
    *
1113 1141
    * @param   sequenceName
1114 1142
    *          The name of the sequence to be queried.
new/src/com/goldencode/p2j/persist/dialect/P2JSQLServer2008Dialect.java 2023-01-09 11:03:15 +0000
40 40
**     IAS 20220816 Added getScriptRunner() method.
41 41
**     IAS 20220913 Re-work processing of UDFs errors/warnings.
42 42
**     OM  20221026 Excluded table name from index name by default. It will be added as needed by dialects.
43
**     RAA 20230109 Overrided method getSequenceSetValString().
43 44
*/
44 45

  
45 46
/*
......
961 962
   }
962 963
   
963 964
   /**
965
    * Generate the appropriate select statement to reset the value of a sequence.
966
    *
967
    * @param   sequenceName
968
    *          The name of the sequence.
969
    *
970
    * @return  Returning {@code null} since this dialect does not support sequences.
971
    */
972
   @Override
973
   public String getSequenceSetValString(String sequenceName)
974
   {
975
      return null;
976
   }
977
   
978
   /**
979
    * Generate the appropriate select statement to reset the value of a sequence.
980
    *
981
    * @return  Returning {@code null} since this dialect does not support sequences.
982
    */
983
   @Override
984
   public String getSequenceSetValString()
985
   {
986
      return null;
987
   }
988
   
989
   /**
964 990
    * Generate the appropriate select statement to retrieve the next value of a sequence.
965 991
    *
966 992
    * @param   sequenceName
new/src/com/goldencode/p2j/persist/dialect/P2JSQLServer2012Dialect.java 2023-01-09 11:04:37 +0000
18 18
** 008 ECF 20200906 New ORM implementation.
19 19
** 008 IAS 20201204 Added id() method and support stub for word tables
20 20
**     IAS 20210315 Refactored for working with word tables for _temp database
21
**     RAA 20230109 Overrided method getSequenceCurrValString().
21 22
**/
22 23

  
23 24
/*
......
457 458
   }
458 459
   
459 460
   /**
461
    * Generate the appropriate select statement to retrieve the current value of a sequence.
462
    *
463
    * @return  Dialect-specific string to query the sequence.
464
    */
465
   @Override
466
   public String getSequenceCurrValString()
467
   {
468
      // the cast is needed because the column is of 'variant' datatype.
469
      // the sql driver does not handle it and reports the following error: 
470
      // 08S01 The "variant" data type is not supported.
471
      return "select cast(current_value as bigint) " +
472
             "from sys.sequences where name = ?";
473
   }
474
   
475
   /**
460 476
    * Generate the appropriate select statement to retrieve the next value of a sequence.
461 477
    *
462 478
    * @param   sequenceName
new/src/com/goldencode/p2j/persist/dirty/DefaultDirtyShareManager.java 2023-01-09 11:06:04 +0000
75 75
** 028 ECF 20200906          New ORM implementation.
76 76
** 029 EVL 20200621          Adding NPE protection for lockSingle when index name is NULL or empty.
77 77
** 030 OM  20201012          Force use locally cached meta information instead of map lookup.
78
** 031 RAA 20230109          Changed inline statement(s) to prepared statement(s).
78 79
*/
79 80

  
80 81
/*
......
784 785
            }
785 786
            
786 787
            String hql = "delete from " + entity + 
787
                         " where " + DatabaseManager.PRIMARY_KEY + " = " + id;
788
                         " where " + DatabaseManager.PRIMARY_KEY + " = ?";
788 789
            Session session = null;
789 790
            boolean inTx = false;
790 791
            
......
793 794
               session = new Session(dirtyDatabase);
794 795
               inTx = session.beginTransaction();
795 796
               Query query = Session.createQuery(hql);
797
               query.setParameter(0, id);
796 798
               query.executeUpdate(session);
797 799
               session.commit();
798 800
            }
new/src/com/goldencode/p2j/persist/meta/TransactionTableUpdater.java 2023-01-09 11:07:53 +0000
13 13
**     OM  20201012 Force use locally cached meta information instead of map lookup.
14 14
**     ECF 20220630 Fixed MinimalTrans getter/setter names to match conversion of historical names in _Trans
15 15
**                  table.
16
**     RAA 20230109 Changed inline statement(s) to prepared statement(s).
16 17
*/
17 18

  
18 19
/*
......
197 198
         // drop all records that are no more valid
198 199
         StringBuilder buf = new StringBuilder(
199 200
               "delete from " + TRANS_TABLE + " where not trans_num in (");
201
         List<Object> args = new ArrayList<>();
200 202
         Iterator<Integer> it = transactions.values().iterator();
201 203
         for (int i = 0; it.hasNext(); i++)
202 204
         {
......
205 207
               buf.append(',');
206 208
            }
207 209
            
208
            buf.append(it.next());
210
            args.add(it.next());
211
            buf.append('?');
209 212
         }
210 213
         buf.append(')');
211
         int delCounter = p.executeSQL(buf.toString());
214
         int delCounter = p.executeSQL(buf.toString(), args.toArray());
212 215
         if (LOG.isLoggable(Level.FINE))
213 216
         {
214 217
            LOG.log(Level.FINE, "Dropped " + delCounter + " old _trans records from " + dbName);
new/src/com/goldencode/p2j/persist/sequence/H2SequenceHandler.java 2023-01-09 11:09:28 +0000
16 16
** 007 ECF 20180219 Reduce Hibernate session flushing, if possible.
17 17
** 008 OM  20200906 New ORM implementation.
18 18
**     OM  20220531 Fixed an error message.
19
**     RAA 20230109 Changed inline statement(s) to prepared statement(s).
19 20
*/
20 21

  
21 22
/*
......
141 142
      
142 143
      Persistence persistence = ConnectionManager.getPersistence(ldbName);
143 144
      Dialect dialect = persistence.getDialect();
144
      String strQuery = dialect.getSequenceCurrValString(seqName);
145
      Object[] args = new Object[] {seqName};
146
      String strQuery = dialect.getSequenceCurrValString();
145 147
      int64 ret;
146 148
      
147 149
      try
148 150
      {
149
         ret = getResultValue(persistence.getSingleSQLResult(strQuery, null));
151
         ret = getResultValue(persistence.getSingleSQLResult(strQuery, args));
150 152
      }
151 153
      catch (PersistenceException pe)
152 154
      {
......
366 368
      
367 369
      Persistence persistence = ConnectionManager.getPersistence(ldbName);
368 370
      Dialect dialect = persistence.getDialect();
369
      String strQuery = dialect.getSequenceSetValString(seqName, newValFixed);
371
      Object[] args = new Object[] {newValFixed};
372
      String strQuery = dialect.getSequenceSetValString(seqName);
370 373
      
371 374
      try
372 375
      {
373
         persistence.executeSQL(strQuery);
376
         persistence.executeSQL(strQuery, args);
374 377
      }
375 378
      catch (PersistenceException pe)
376 379
      {
new/src/com/goldencode/p2j/persist/sequence/PostgreSQLSequenceHandler.java 2023-01-09 11:13:22 +0000
19 19
**     OM  20220531 Fixed an error message.
20 20
**     CA  20221014 Keep a lowercase map of crtSeqList sequence keys, as the change in 
21 21
**                  SequenceManager.legacyMap will always load all sequences.
22
**     RAA 20230109 Changed inline statement(s) to prepared statement(s).
22 23
*/
23 24

  
24 25
/*
......
285 286
      
286 287
      Persistence persistence = ConnectionManager.getPersistence(ldbName);
287 288
      Dialect dialect = persistence.getDialect();
288
      String setCrtValQuery = dialect.getSequenceSetValString(seqName, newVal);
289
      Object[] args = new Object[] {seqName, newVal};
290
      String setCrtValQuery = dialect.getSequenceSetValString();
289 291
      
290 292
      try
291 293
      {
292
         persistence.getSingleSQLResult(setCrtValQuery, null);
294
         persistence.getSingleSQLResult(setCrtValQuery, args);
293 295
      }
294 296
      catch (PersistenceException pe)
295 297
      {
new/src/com/goldencode/p2j/report/ReportWorker.java 2023-01-09 11:16:04 +0000
174 174
**                           the latest version of H2).
175 175
**     CA  20211214          The AST manager plugin must be context-local, for runtime conversion, as the 
176 176
**                           InMemoryRegistryPlugin is not thread-safe.
177
**     RAA 20230109          Changed inline statement(s) to prepared statement(s).
177 178
*/
178 179

  
179 180
/*
......
453 454
         
454 455
         // read back the id that was autogenerated
455 456
         ResultSet rs = stmtReportInsert.getGeneratedKeys();
457
         PreparedStatement stmt = null;
456 458
         rs.next();
457 459
         rpt.id = rs.getLong(1);
460
         List<Object> args = new ArrayList<>();
458 461
         
459 462
         if (processTags && rpt.tags != null && !rpt.tags.isEmpty())
460 463
         {
461
            StringBuilder buf = new StringBuilder("select id, name from tag where name in('");
464
            StringBuilder buf = new StringBuilder("select id, name from tag where name in(");
462 465
            Iterator<String> iter = rpt.tags.iterator();
463 466
            for (int i = 0; iter.hasNext(); i++)
464 467
            {
465 468
               if (i > 0)
466 469
               {
467
                  buf.append("', '");
470
                  buf.append(", ");
468 471
               }
469 472
               String tag = iter.next();
470 473
               tag.replaceAll("\'", "\\\'");
471
               buf.append(tag);
474
               buf.append("?");
475
               args.add(tag);
472 476
            }
473
            buf.append("')");
477
            buf.append(")");
474 478
            String sql = buf.toString();
475 479
            
476 480
            Map<String, Long> tagMap = new HashMap<>();
477
            Statement stmt = connection.createStatement();
478
            rs = stmt.executeQuery(sql);
481
            stmt = connection.prepareStatement(sql);
482
            for (int i = 0; i < args.size(); i++)
483
            {
484
               stmt.setObject(i + 1, args.get(i));
485
            }
486
            
487
            rs = stmt.executeQuery();
479 488
            while (rs.next())
480 489
            {
481 490
               long tid = rs.getLong(1);
......
509 518
               stmtRptTagInsert.clearParameters();
510 519
            }
511 520
         }
521
         
522
         if (rs != null && !rs.isClosed())
523
         {
524
            rs.close();
525
         }
526
         
527
         if (stmt != null && !stmt.isClosed())
528
         {
529
            stmt.close();
530
         }
512 531
      }
513 532
      
514 533
      return rpt.id;
new/src/com/goldencode/p2j/report/server/ReportApi.java 2023-01-09 11:23:14 +0000
13 13
**                  version of H2).
14 14
**     OM  20220405 XmlFilePlugin can load either a file or a stream from application's jar.
15 15
**     DDF 20220823 Replaced .nextvalue with next value for.
16
**     RAA 20230109 Changed inline statement(s) to prepared statement(s).
16 17
*/
17 18

  
18 19
/*
......
745 746
    */
746 747
   private static void applyFileFilter(Connection conn, Long profileId, long sessionId)
747 748
   {
748
      try (Statement stmt = conn.createStatement())
749
      PreparedStatement stmt = null;
750
      ResultSet rs = null;
751
      try
749 752
      {
750 753
         String sql;
751
         ResultSet rs;
752 754
         
753 755
         if (profileId != null)
754 756
         {
755 757
            // if profileId is null, the active_file was just created and is already empty;
756 758
            // otherwise, delete all its records in preparation for re-population with the new
757 759
            // filter profile's data
758
            stmt.execute("delete from active_file where sid = " + sessionId);
760
            stmt = conn.prepareStatement("delete from active_file where sid = ?");
761
            stmt.setObject(1, sessionId);
762
            stmt.executeUpdate();
759 763
         }
760 764
         
761 765
         // Query file specs and types for the provided file filter profile; we will compose a
......
763 767
         // If provided profile id was null, get the default profile.
764 768
         
765 769
         int i;
770
         int type = 0;
766 771
         
767 772
         // wildcard path specs first
768 773
         
......
776 781
         {
777 782
            sql = "select f.spec from file_filter f " +
778 783
                  "join filter_profile p on p.id = f.pid " +
779
                  "where p.id = " + profileId + " and f.wild = true";
780
         }
781
         rs = stmt.executeQuery(sql);
784
                  "where p.id = ?" + " and f.wild = true";
785
            type = 1;
786
         }
787
         
788
         if (stmt != null && !stmt.isClosed())
789
         {
790
            stmt.close();
791
         }
792
         
793
         stmt = conn.prepareStatement(sql);
794
         if (type == 1)
795
         {
796
            stmt.setObject(1, profileId);
797
         }
798
         
799
         type = 0;
800
         rs = stmt.executeQuery();
801

  
802
         List<Object> args = new ArrayList<>();
782 803
         
783 804
         StringBuilder buf = new StringBuilder("insert into active_file (fid, sid) ");
784 805
         for (i = 0; rs.next(); i++)
......
792 813
            
793 814
            buf.append("select distinct(f.id), ");
794 815
            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("'");
816
            buf.append(" from file f join ast_map a on a.fid = f.id where f.name like ?");
817
            String arg1 = dbs.escapeLikeRValue(spec);
818
            arg1 = arg1.substring(0, arg1.length() - 1) + '%';
819
            args.add(arg1);
799 820
         }
800 821
         
801 822
         if (profileId == null)
......
808 829
         {
809 830
            sql = "select f.spec from file_filter f " +
810 831
                  "join filter_profile p on p.id = f.pid " +
811
                  "where p.id = " + profileId + " and f.wild = false";
812
         }
813
         rs = stmt.executeQuery(sql);
832
                  "where p.id = ?" + " and f.wild = false";
833
            type = 1;
834
         }
835
         
836
         if (rs != null && !rs.isClosed())
837
         {
838
            rs.close();
839
         }
840
         
841
         if (stmt != null && !stmt.isClosed())
842
         {
843
            stmt.close();
844
         }
845
         
846
         stmt = conn.prepareStatement(sql);
847
         if (type == 1)
848
         {
849
            stmt.setObject(1, profileId);
850
         }
851
         
852
         type = 0;
853
         rs = stmt.executeQuery();
814 854
         
815 855
         int j = 0;
816 856
         for (; rs.next(); i++)
......
833 873
               buf.append(", ");
834 874
            }
835 875
            
836
            buf.append("'");
837
            buf.append(spec);
838
            buf.append("'");
876
            args.add(spec);
839 877
            
840 878
            if (++j == 100)
841 879
            {
......
851 889
         
852 890
         sql = buf.toString();
853 891
         
854
         stmt.execute(sql);
892
         if (rs != null && !rs.isClosed())
893
         {
894
            rs.close();
895
         }
896
         
897
         if (stmt != null && !stmt.isClosed())
898
         {
899
            stmt.close();
900
         }
901
         
902
         stmt = conn.prepareStatement(sql);
903
         for (int k = 0; k < args.size();k++)
904
         {
905
            stmt.setObject(k + 1, args.get(k));
906
         }
907
         
908
         stmt.execute();
855 909
         int uc = stmt.getUpdateCount();
856 910
         System.out.println("applyActiveFile update count: " + uc);
857 911
         
......
873 927
         
874 928
         throw new RuntimeException(exc);
875 929
      }
930
      finally
931
      {
932
         try
933
         {
934
            if (rs != null && !rs.isClosed())
935
            {
936
               rs.close();
937
            }
938
            
939
            if (stmt != null && !stmt.isClosed())
940
            {
941
               stmt.close();
942
            }
943
         }
944
         catch (SQLException e)
945
         {
946
            e.printStackTrace();
947
         }
948
      }
876 949
   }
877 950
   
878 951
   /**
......
2513 2586
      buf.append("insert into search_history ");
2514 2587
      buf.append("select * from (select next value for seq_search_history_pk, '");
2515 2588
      buf.append(criteria);
2516
      buf.append("' ) x where not exists (select 1 from search_history where criteria = '");
2517
      buf.append(criteria);
2518
      buf.append("')");
2589
      buf.append("' ) x where not exists (select 1 from search_history where criteria = ?)");
2590
      Object histArg = criteria;
2519 2591
      String sqlInsSrchHist = buf.toString();
2520 2592
      
2521 2593
      // compose sql to insert into user_search table, if not already present
2522 2594
      buf.setLength(0);
2523 2595
      buf.append("insert into user_search select * from (select ");
2524 2596
      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)");
2597
      buf.append(" as u, select id from search_history where criteria = ?");
2598
      buf.append(" as s) x where exists (select 1 from search_history where criteria = ?");
2599
      buf.append(") and not exists (select 1 from user_search where uid = x.u and sid = x.s)");
2600
      Object usrArg = criteria;
2530 2601
      String sqlInsUsrSrch = buf.toString();
2531 2602
      
2532
      try (Statement stmt = conn.createStatement())
2603
      //tested with H2 1.4.200 and prepared statements now work with subselects
2604
      try (PreparedStatement stmt = conn.prepareStatement(sqlInsSrchHist))
2533 2605
      {
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);
2606
         stmt.setObject(1, histArg);
2607
         stmt.execute();
2538 2608
      }
2609
      
2610
      try (PreparedStatement stmt = conn.prepareStatement(sqlInsUsrSrch))
2611
      {
2612
         stmt.setObject(1, usrArg);
2613
         stmt.setObject(2, usrArg);
2614
         stmt.execute();
2615
       }
2539 2616
   }
2540 2617
   
2541 2618
   /**