001 // Copyright (c) 2001 Hursh Jain (http://www.mollypages.org)
002 // The Molly framework is freely distributable under the terms of an
003 // MIT-style license. For details, see the molly pages web site at:
004 // http://www.mollypages.org/. Use, modify, have fun !
005
006 package fc.jdbc.dbo.generated;
007
008 /*
009 * Auto generated on: Wed May 13 01:41:13 EDT 2020
010 * JDBC url: [jdbc:postgresql://127.0.0.1/test]
011 * WARNING: Manual edits will be lost if/when this file is regenerated.
012 */
013 import java.io.*;
014 import java.math.*;
015 import java.sql.*;
016 import java.util.*;
017
018 import fc.io.*;
019 import fc.jdbc.*;
020 import fc.jdbc.dbo.*;
021 import fc.util.*;
022 import fc.web.forms.*;
023
024 /**
025 Manages various operations on the alltypes table.
026
027 <p>Most methods of this class take a {@link java.sql.Connection Connection} as an argument
028 and use that connection to run various queries. The connection parameter is never closed
029 by methods in this class and that connection can and should be used again. Methods of this
030 class will also throw a <tt>IllegalArgumentException</tt> if the specified connection
031 object is <tt>null</tt>.
032
033 <p>Thread Safety: Operations on this class are by and large thread safe in that multiple
034 threads can call the methods at the same time. However, seperate threads should use
035 seperate connection objects when invoking methods of this class.
036 */
037 public final class alltypesMgr extends fc.jdbc.dbo.DBOMgr
038 {
039 /* --- Fields used for collecting usage statistics ---
040 Increments to these don't need to be synchronized since these are
041 ints and not longs and memory visibility is not an issue in the
042 toString() method (in which these are read).
043 */
044 private static int __getall_called = 0;
045 private static int __getlimited_called = 0;
046 private static int __getbykey_called = 0;
047 private static int __getwhere_called = 0;
048 private static int __getusing_called = 0;
049 private static int __getusing_ps_called = 0;
050 private static int __getfromrs_called = 0;
051 private static int __save_called = 0;
052 private static int __delete_called = 0;
053 private static int __deletebykey_called = 0;
054 private static int __deletewhere_called = 0;
055 private static int __deleteusing_called = 0;
056 private static int __count_called = 0;
057 private static int __countwhere_called = 0;
058 private static int __countusing_called = 0;
059 private static int __exists_called = 0;
060 /* -------------- end statistics fields -------------- */
061
062 /** Constructor is private since class is never instantiated */
063 private alltypesMgr() {
064 }
065
066
067 static private final String getAllStmt = "SELECT id, smallint_val, int_val, bigint_val, float_val, double_val, numeric_val, char_val, varchar_val, longvarchar_val, date_val, time_val, timestamp_val, bit_val, array_val, boolean_val, varbinary_val, json_val, jsonb_val from alltypes";
068 /**
069 Returns all rows in the table. Use with care for large tables since
070 this method can result in VM out of memory errors. <p>This method
071 also takes an optional (can be null) <tt>clause</tt> parameter which
072 is sent as is to the database. For example, a clause can be:
073 <blockquote><pre>
074 order by some_column_name
075 </pre> </blockquote>
076 @return a list containing {@link alltypes } objects <i>or an empty list</i> if there are no rows in the database*/
077 public static List getAll(final Connection con, final String clause) throws SQLException
078 {
079 __getall_called++;
080 final List list = new ArrayList();
081 final String getAllStmtClaused = (clause == null) ?
082 getAllStmt : getAllStmt + " " + clause;
083 PreparedStatement ps = prepareStatement(con, getAllStmtClaused);
084 log.bug("Query to run: ", ps);
085 final ResultSet rs = ps.executeQuery();
086 while (true) {
087 alltypes bean = decodeFromRS(rs);
088 if (bean == null) { break; }
089 list.add(bean);
090 }
091 rs.close();
092 return list;
093 }
094
095 /**
096 Convenience method that invokes {@link getAll(Connection, alltypes, String) getAll} with an empty additional clause.
097 */
098 public static List getAll(final Connection con) throws ValidateException, SQLException
099 {
100 return getAll(con, null);
101 }
102
103 static private final String getLimitedStmt = "SELECT id, smallint_val, int_val, bigint_val, float_val, double_val, numeric_val, char_val, varchar_val, longvarchar_val, date_val, time_val, timestamp_val, bit_val, array_val, boolean_val, varbinary_val, json_val, jsonb_val from alltypes";
104 /**
105 Returns all rows in the table starting from some row number and limited
106 by a certain number of rows after that starting row.
107 <p>
108 This method takes a required (non-null) <code>order_clause</code>, since when using
109 a limit clause, rows must be ordered for the limit to make sense. The
110 clause should be of the form <font color=blue>order by ...</font>
111 <p>
112 The <code>limit</code> specifies the number of rows that will be returned. (those many
113 or possibly lesser rows will be returned, if the query itself yields less
114 rows).
115 <p>
116 The <code>offset</code> skips that many rows before returning rows. A zero offset is
117 the same as a traditional query with no offset clause, where rows from
118 the beginning are returned. If say, offset = 10, then rows starting from
119 row 11 will be returned.
120 <p>
121 The sql-query generated by this method is database specific but will (typically) look like:
122 <blockquote><pre>
123 select <column_list> from <table> order by <clause> limit 5 offset 10
124 </pre> </blockquote>
125 @return a list containing {@link alltypes } objects <i>or an empty list</i> if there are no rows in the database*/
126 public static List getLimited(final Connection con, final String order_clause, int limit, int offset) throws SQLException
127 {
128 __getlimited_called++;
129 final List list = new ArrayList();
130 final String tmp = getLimitedStmt + " " + order_clause + " LIMIT " + limit + " OFFSET " + offset;
131 PreparedStatement ps = prepareStatement(con, tmp);
132 log.bug("Query to run: ", ps);
133 final ResultSet rs = ps.executeQuery();
134 while (true) {
135 alltypes bean = decodeFromRS(rs);
136 if (bean == null) { break; }
137 list.add(bean);
138 }
139 rs.close();
140 return list;
141 }
142
143 static private final String getByPKStmt = "SELECT id, smallint_val, int_val, bigint_val, float_val, double_val, numeric_val, char_val, varchar_val, longvarchar_val, date_val, time_val, timestamp_val, bit_val, array_val, boolean_val, varbinary_val, json_val, jsonb_val from alltypes WHERE id=?";
144 /**
145 Returns <b>the</b> row corresponding to the specified primary key(s) of this table
146 or <b><tt>null</tt></b> if no row was found.
147 <p>This method uses a prepared statement and is safe from SQL injection attacks
148 */
149 public static alltypes getByKey(final Connection con, int id) throws SQLException
150 {
151 __getbykey_called++;
152 PreparedStatement ps = prepareStatement(con, getByPKStmt);
153 StringBuilder errbuf = null;
154
155 //id [int] is primitive, skipping null test
156 ps.setInt(1, id);
157
158 if (errbuf != null) {
159 throw new ValidateException(errbuf.toString());
160 }
161 final ResultSet rs = ps.executeQuery();
162 log.bug("Query to run: ", ps);
163 alltypes bean = decodeFromRS(rs);
164 rs.close();
165 return bean;
166 }
167
168 /**
169 Returns the rows returned by querying the table with the specified
170 <tt>WHERE</tt> clause or <i>an empty list</i> if no rows were found.
171 (note: the string <tt>"WHERE"</tt> does <b>not</b> have to be
172 specified in the clause. It is added automatically by this method).
173 <p>Queries can use database functions such as: <code>lower()</code>,
174 <code>upper()</code>, <code>LIKE</code> etc. For example:
175 <pre><blockquote>alltypesMgr.getWhere("lower(col_a) = 'foo'")
176 //compares the lower case value of col_a with the string 'foo'
177 </blockquote></pre>
178 <p><b>The "where" clause is sent as-is to the database</b>. SQL
179 injection attacks are possible if it is created as-is from a <b><u>untrusted</u></b> source.
180
181 @throws IllegalArgumentException if the specified <tt>where</tt> parameter is null
182 */
183 public static List getWhere(final Connection con, final String where) throws SQLException
184 {
185 __getwhere_called++;
186 Argcheck.notnull(where, "the where parameter was null (and should not be null)");
187 final String where_stmt = "SELECT id, smallint_val, int_val, bigint_val, float_val, double_val, numeric_val, char_val, varchar_val, longvarchar_val, date_val, time_val, timestamp_val, bit_val, array_val, boolean_val, varbinary_val, json_val, jsonb_val from alltypes WHERE " + where ;
188 Statement stmt = QueryUtil.getRewindableStmt(con);
189 log.bug("Query to run: ", stmt, " ", where_stmt);
190 final List list = new ArrayList();
191 final ResultSet rs = stmt.executeQuery(where_stmt);
192 while (true) {
193 alltypes bean = decodeFromRS(rs);
194 if (bean == null) { break; }
195 list.add(bean);
196 }
197 stmt.close();
198 return list;
199 }
200
201 /**
202 Returns the rows returned by querying the table with the value of the
203 specified <tt>alltypes</tt> object or <i>an empty list</i> if no rows were found. As many
204 fields in <tt>alltypes</tt> can be set as needed and the values of
205 all set fields (including fields explicitly set to <tt>null</tt>)
206 are then used to perform the query.
207 <p>
208 This method is often convenient/safer than the {@link #getWhere
209 getWhere} method (because the <tt>getWhere</tt> method takes an
210 arbitrary query string which has to be properly escaped by the
211 user).
212 <p>Essentially, this method is a more convenient way to use a
213 PreparedStatement. Internally, a prepared statement is created and
214 it's parameters are set to fields that are set in this object).
215 Using PreparedStatements directly is also perfectly fine. For
216 example, the following are equivalent.
217 <p> Using a PreparedStatement:
218 <blockquote><pre>
219 String foo = "select * from table_foo where x = ? and y = ?";
220 PreparedStatement ps = con.prepareStatement(foo);
221 ps.setString(1, "somevalue");
222 ps.setString(2, "othervalue");
223 ResultSet rs = ps.executeUpdate();
224 while (rs.next()) {
225 table_foo bean = table_fooMgr.getFromRS(rs);
226 }
227 </pre> </blockquote>
228
229 Using this method:
230 <blockquote><pre>
231 table_foo <font color=blue>proto</font> = new table_foo();
232 proto.set_x("somevalue"); //compile time safety
233 proto.set_y("othervalue"); //compile time safety
234 List beans = table_fooMgr.<font color=blue>getUsing(proto)</font>;
235 </pre> </blockquote>
236 <p>This method also takes an <tt>clause</tt> parameter which
237 is sent as is to the database. For example, a clause can be:
238 <blockquote><pre>
239 List beans = table_fooMgr.<font color=blue>getUsing(proto, <b>"order by some_column_name"</b>)</font>;
240 </pre> </blockquote>
241 This clause is optional. Specify <tt>null</tt> to not use it at all.
242 If the clause is specified, do <font size='+1'><b>NOT</b></font> include the word <tt>WHERE</tt>.
243
244 The fields that are set in the proto object (as shown above) are sent as
245 part of a WHERE clause constructed internally. If you are specifying a clause
246 as well, you should not specify the word <tt>WHERE</tt>. However, you may have
247 to specify <tt>AND</tt> to add to the internal WHERE clause, if you have set any
248 fields in the proto object. For example
249 <blockquote><pre>
250 List beans = table_fooMgr.<font color=blue>getUsing(proto, <b>"and bar = 5"</b>)</font>;
251 </pre> </blockquote>
252 <p>Note: For a <i>very</i> large number of rows, it may be more
253 efficient to use a prepared statement directly (as opposed to using
254 this method). In most cases, this is not something to worry about,
255 but your mileage may vary...
256 */
257 public static List getUsing(final Connection con, final alltypes bean, final String clause) throws ValidateException, SQLException
258 {
259 __getusing_called++;
260 Argcheck.notnull(bean, "the bean parameter was null (and should not be null)");
261 if (! bean.isModified()) {
262 throw new ValidateException("bean=" + bean + " not modified, ignoring query");
263 }
264
265 int __count = 0;
266 final StringBuilder buf = new StringBuilder(512);
267 buf.append("SELECT id, smallint_val, int_val, bigint_val, float_val, double_val, numeric_val, char_val, varchar_val, longvarchar_val, date_val, time_val, timestamp_val, bit_val, array_val, boolean_val, varbinary_val, json_val, jsonb_val from alltypes WHERE ");
268 if (bean.isModified_id()) {
269 buf.append("id=? and ");
270 __count++;
271 }
272 if (bean.isModified_smallint_val()) {
273 if (bean.isModifiedSetNull_smallint_val()) {
274 buf.append("smallint_val is NULL and ");
275 }
276 else{
277 buf.append("smallint_val=? and ");
278 __count++;
279 }
280 }
281 if (bean.isModified_int_val()) {
282 buf.append("int_val=? and ");
283 __count++;
284 }
285 if (bean.isModified_bigint_val()) {
286 if (bean.isModifiedSetNull_bigint_val()) {
287 buf.append("bigint_val is NULL and ");
288 }
289 else{
290 buf.append("bigint_val=? and ");
291 __count++;
292 }
293 }
294 if (bean.isModified_float_val()) {
295 if (bean.isModifiedSetNull_float_val()) {
296 buf.append("float_val is NULL and ");
297 }
298 else{
299 buf.append("float_val=? and ");
300 __count++;
301 }
302 }
303 if (bean.isModified_double_val()) {
304 if (bean.isModifiedSetNull_double_val()) {
305 buf.append("double_val is NULL and ");
306 }
307 else{
308 buf.append("double_val=? and ");
309 __count++;
310 }
311 }
312 if (bean.isModified_numeric_val()) {
313 if (bean.get_numeric_val() == null) {
314 buf.append("numeric_val is NULL and ");
315 }
316 else{
317 buf.append("numeric_val=? and ");
318 __count++;
319 }
320 }
321 if (bean.isModified_char_val()) {
322 if (bean.get_char_val() == null) {
323 buf.append("char_val is NULL and ");
324 }
325 else{
326 buf.append("char_val=? and ");
327 __count++;
328 }
329 }
330 if (bean.isModified_varchar_val()) {
331 if (bean.get_varchar_val() == null) {
332 buf.append("varchar_val is NULL and ");
333 }
334 else{
335 buf.append("varchar_val=? and ");
336 __count++;
337 }
338 }
339 if (bean.isModified_longvarchar_val()) {
340 if (bean.get_longvarchar_val() == null) {
341 buf.append("longvarchar_val is NULL and ");
342 }
343 else{
344 buf.append("longvarchar_val=? and ");
345 __count++;
346 }
347 }
348 if (bean.isModified_date_val()) {
349 if (bean.get_date_val() == null) {
350 buf.append("date_val is NULL and ");
351 }
352 else{
353 buf.append("date_val=? and ");
354 __count++;
355 }
356 }
357 if (bean.isModified_time_val()) {
358 if (bean.get_time_val() == null) {
359 buf.append("time_val is NULL and ");
360 }
361 else{
362 buf.append("time_val=? and ");
363 __count++;
364 }
365 }
366 if (bean.isModified_timestamp_val()) {
367 if (bean.get_timestamp_val() == null) {
368 buf.append("timestamp_val is NULL and ");
369 }
370 else{
371 buf.append("timestamp_val=? and ");
372 __count++;
373 }
374 }
375 if (bean.isModified_bit_val()) {
376 if (bean.get_bit_val() == null) {
377 buf.append("bit_val is NULL and ");
378 }
379 else{
380 buf.append("bit_val=? and ");
381 __count++;
382 }
383 }
384 if (bean.isModified_array_val()) {
385 if (bean.get_array_val() == null) {
386 buf.append("array_val is NULL and ");
387 }
388 else{
389 buf.append("array_val=? and ");
390 __count++;
391 }
392 }
393 if (bean.isModified_boolean_val()) {
394 if (bean.get_boolean_val() == null) {
395 buf.append("boolean_val is NULL and ");
396 }
397 else{
398 buf.append("boolean_val=? and ");
399 __count++;
400 }
401 }
402 if (bean.isModified_varbinary_val()) {
403 if (bean.get_varbinary_val() == null) {
404 buf.append("varbinary_val is NULL and ");
405 }
406 else{
407 buf.append("varbinary_val=? and ");
408 __count++;
409 }
410 }
411 if (bean.isModified_json_val()) {
412 if (bean.get_json_val() == null) {
413 buf.append("json_val is NULL and ");
414 }
415 else{
416 buf.append("json_val=? and ");
417 __count++;
418 }
419 }
420 if (bean.isModified_jsonb_val()) {
421 if (bean.get_jsonb_val() == null) {
422 buf.append("jsonb_val is NULL and ");
423 }
424 else{
425 buf.append("jsonb_val=? and ");
426 __count++;
427 }
428 }
429
430 buf.setLength(buf.length() - 4);
431
432 if (clause != null) {
433 buf.append(" ");
434 buf.append(clause);
435 }
436
437 final String getUsingPKStmt = buf.toString();
438 PreparedStatement ps = prepareStatement(con, getUsingPKStmt);
439 int pos = 0;
440 if (bean.isModified_id()) {
441 pos++;
442 int id = bean.get_id();
443 ps.setInt(pos, id);
444 }
445 if (bean.isModified_smallint_val()) {
446 if (bean.isModifiedSetNull_smallint_val()) {
447 /* no value to set here, uses [xxx IS NULL] syntax*/
448 }
449 else{
450 pos++;
451 short smallint_val = bean.get_smallint_val();
452 ps.setShort(pos, smallint_val);
453 }
454 }
455 if (bean.isModified_int_val()) {
456 pos++;
457 int int_val = bean.get_int_val();
458 ps.setInt(pos, int_val);
459 }
460 if (bean.isModified_bigint_val()) {
461 if (bean.isModifiedSetNull_bigint_val()) {
462 /* no value to set here, uses [xxx IS NULL] syntax*/
463 }
464 else{
465 pos++;
466 long bigint_val = bean.get_bigint_val();
467 ps.setLong(pos, bigint_val);
468 }
469 }
470 if (bean.isModified_float_val()) {
471 if (bean.isModifiedSetNull_float_val()) {
472 /* no value to set here, uses [xxx IS NULL] syntax*/
473 }
474 else{
475 pos++;
476 float float_val = bean.get_float_val();
477 ps.setFloat(pos, float_val);
478 }
479 }
480 if (bean.isModified_double_val()) {
481 if (bean.isModifiedSetNull_double_val()) {
482 /* no value to set here, uses [xxx IS NULL] syntax*/
483 }
484 else{
485 pos++;
486 double double_val = bean.get_double_val();
487 ps.setDouble(pos, double_val);
488 }
489 }
490 if (bean.isModified_numeric_val()) {
491 if (bean.get_numeric_val() == null) {
492 /* no value to set here, uses [xxx IS NULL] syntax*/
493 }
494 else{
495 pos++;
496 BigDecimal numeric_val = bean.get_numeric_val();
497 ps.setBigDecimal(pos, numeric_val);
498 }
499 }
500 if (bean.isModified_char_val()) {
501 if (bean.get_char_val() == null) {
502 /* no value to set here, uses [xxx IS NULL] syntax*/
503 }
504 else{
505 pos++;
506 String char_val = bean.get_char_val();
507 ps.setString(pos, char_val);
508 }
509 }
510 if (bean.isModified_varchar_val()) {
511 if (bean.get_varchar_val() == null) {
512 /* no value to set here, uses [xxx IS NULL] syntax*/
513 }
514 else{
515 pos++;
516 String varchar_val = bean.get_varchar_val();
517 ps.setString(pos, varchar_val);
518 }
519 }
520 if (bean.isModified_longvarchar_val()) {
521 if (bean.get_longvarchar_val() == null) {
522 /* no value to set here, uses [xxx IS NULL] syntax*/
523 }
524 else{
525 pos++;
526 String longvarchar_val = bean.get_longvarchar_val();
527 ps.setString(pos, longvarchar_val);
528 }
529 }
530 if (bean.isModified_date_val()) {
531 if (bean.get_date_val() == null) {
532 /* no value to set here, uses [xxx IS NULL] syntax*/
533 }
534 else{
535 pos++;
536 java.sql.Date date_val = bean.get_date_val();
537 ps.setDate(pos, date_val);
538 }
539 }
540 if (bean.isModified_time_val()) {
541 if (bean.get_time_val() == null) {
542 /* no value to set here, uses [xxx IS NULL] syntax*/
543 }
544 else{
545 pos++;
546 Time time_val = bean.get_time_val();
547 ps.setTime(pos, time_val);
548 }
549 }
550 if (bean.isModified_timestamp_val()) {
551 if (bean.get_timestamp_val() == null) {
552 /* no value to set here, uses [xxx IS NULL] syntax*/
553 }
554 else{
555 pos++;
556 Timestamp timestamp_val = bean.get_timestamp_val();
557 ps.setTimestamp(pos, timestamp_val);
558 }
559 }
560 if (bean.isModified_bit_val()) {
561 if (bean.get_bit_val() == null) {
562 /* no value to set here, uses [xxx IS NULL] syntax*/
563 }
564 else{
565 pos++;
566 Boolean bit_val = bean.get_bit_val();
567 ps.setObject(pos, bit_val);
568 }
569 }
570 if (bean.isModified_array_val()) {
571 if (bean.get_array_val() == null) {
572 /* no value to set here, uses [xxx IS NULL] syntax*/
573 }
574 else{
575 pos++;
576 java.sql.Array array_val = bean.get_array_val();
577 ps.setArray(pos, array_val);
578 }
579 }
580 if (bean.isModified_boolean_val()) {
581 if (bean.get_boolean_val() == null) {
582 /* no value to set here, uses [xxx IS NULL] syntax*/
583 }
584 else{
585 pos++;
586 Boolean boolean_val = bean.get_boolean_val();
587 ps.setObject(pos, boolean_val);
588 }
589 }
590 if (bean.isModified_varbinary_val()) {
591 if (bean.get_varbinary_val() == null) {
592 /* no value to set here, uses [xxx IS NULL] syntax*/
593 }
594 else{
595 pos++;
596 byte[] varbinary_val = bean.get_varbinary_val();
597 ps.setBytes(pos, varbinary_val);
598 }
599 }
600 if (bean.isModified_json_val()) {
601 if (bean.get_json_val() == null) {
602 /* no value to set here, uses [xxx IS NULL] syntax*/
603 }
604 else{
605 pos++;
606 String json_val = bean.get_json_val();
607 ps.setObject(pos, json_val, java.sql.Types.OTHER);
608 }
609 }
610 if (bean.isModified_jsonb_val()) {
611 if (bean.get_jsonb_val() == null) {
612 /* no value to set here, uses [xxx IS NULL] syntax*/
613 }
614 else{
615 pos++;
616 String jsonb_val = bean.get_jsonb_val();
617 ps.setObject(pos, jsonb_val, java.sql.Types.OTHER);
618 }
619 }
620 log.bug("Query to run: ", ps);
621 final List list = new ArrayList();
622 final ResultSet rs = ps.executeQuery();
623 while (true) {
624 alltypes row = decodeFromRS(rs);
625 if (row == null) { break; }
626 list.add(row);
627 }
628 rs.close();
629 return list;
630 }
631
632 /**
633 Convenience method that invokes {@link getUsing(Connection, alltypes, String) getUsing} with an empty <i><tt>clause</tt></i> parameter.*/
634 public static List getUsing(final Connection con, final alltypes bean) throws ValidateException, SQLException
635 {
636 return getUsing(con, bean, null);
637 }
638
639 /**
640 This is a <i>convenience</i> method that runs the specified
641 prepared statement to perform an arbitrary query. For example:
642 <blockquote>
643 <pre>
644 PreparedStatement <font color=blue>ps</font> = con.prepareStatement(
645 "select * from some_table where some_column = ?");
646 ps.setString(1, "foo");
647 List list = fooMgr.<font color=blue>getUsing</font>(con, <font color=blue>ps</font>);
648 for (int n = 0; n < list.size(); n++) {
649 sometable t = (sometable) list.get(n);
650 //do something
651 }
652 </pre>
653 </blockquote>
654 The effect of the above is <u>equivalent</u> to the following (larger) block
655 of code:
656 <blockquote>
657 <pre>
658 PreparedStatement <font color=blue>ps</font> = con.prepareStatement(
659 "select * from sometable where some_column = ?"
660 );
661 ps.setString(1, "foo");
662 ResultSet rs = <font color=blue>ps.executeQuery()</font>;
663 List list = new ArrayList();
664 while (rs.next()) {
665 list.add(sometableMgr.<font color=blue>getFromRS(rs)</font>);
666 }
667
668 for (int n = 0; n < list.size(); n++) {
669 sometable t = (sometable) list.get(n);
670 //do something
671 }
672 </pre>
673 </blockquote>
674
675 Note: Just as with other get<i>XXX</i> methods, for large amounts of
676 rows (say many thousands), it may be more efficient use and iterate
677 through a JDBC result set directly.
678 */
679 public static List getUsing(final Connection con, final PreparedStatement ps) throws ValidateException, SQLException
680 {
681 __getusing_ps_called++;
682 log.bug("Query to run: ", ps);
683 final List list = new ArrayList();
684 final ResultSet rs = ps.executeQuery();
685 while (true) {
686 alltypes row = decodeFromRS(rs);
687 if (row == null) { break; }
688 list.add(row);
689 }
690 rs.close();
691 return list;
692 }
693
694 /**
695 This is a <i>convenience</i> method that runs the specified
696 {@link fc.jdbc.dbo.NamedParamStatement NamedParamStatement} to perform an arbitrary query.
697 For example: <blockquote>
698 <pre>
699 NamedParamStatement <font color=blue>ps</font> = queryReadeer.getQuery("somequery");
700 ps.setString("some_placeholder", "foo");
701 List list = fooMgr.<font color=blue>getUsing</font>(con, <font color=blue>ps</font>);
702 for (int n = 0; n < list.size(); n++) {
703 sometable t = (sometable) list.get(n);
704 //do something
705 }
706 </pre>
707 </blockquote>
708
709 Note: Just as with other get<i>XXX</i> methods, for large amounts of
710 rows (say many thousands), it may be more efficient use and iterate
711 through a JDBC result set directly.
712 */
713 public static List getUsing(final Connection con, final NamedParamStatement ps) throws ValidateException, SQLException
714 {
715 __getusing_ps_called++;
716 log.bug("Query to run: ", ps);
717 final List list = new ArrayList();
718 final ResultSet rs = ps.executeQuery();
719 while (true) {
720 alltypes row = decodeFromRS(rs);
721 if (row == null) { break; }
722 list.add(row);
723 }
724 rs.close();
725 return list;
726 }
727
728 /**
729 Returns a <i>comma delimited list</i> of <i>all</i> columns in <tt>alltypes</tt>. These column names are fully qualified, i.e., they contain
730 table name as a prefix to the column name. For example:
731 <blockquote><pre>
732 <tt>tablename.column1 AS tablename_column1, tablename.column2 AS tablename_column2 ...</tt>
733 </pre></blockquote>
734 <p>This list is suitable for placing in the column(s) clause of a select query, such as:
735 <blockquote>
736 <tt>Single table: select <i><font color=blue>[column_list_A]</font></i> from table_A</tt><br>
737 <tt>Join: select <i><font color=blue>[column_list_A], [column_list_B]</font></i> from table_A, table_B</tt>
738 </blockquote>
739 The ResultSet returned by the query can be used directly or can be passed
740 to the {@link #getFromRS getFromRS} method to convert it into a list of <code>alltypes
741 </code> objects. If the query is a join across multiple tables,
742 then the {@link #getFromRS getFromRS} method for each table manager
743 can be called on the same ResultSet to retrieve the row object for
744 that table.
745 Note: the returned list of names has a trailing space, which is good when
746 the rest of the query is appended to this list.
747 */
748 public static String columns() throws SQLException
749 {
750 return "alltypes.id as alltypes_id, alltypes.smallint_val as alltypes_smallint_val, alltypes.int_val as alltypes_int_val, alltypes.bigint_val as alltypes_bigint_val, alltypes.float_val as alltypes_float_val, alltypes.double_val as alltypes_double_val, alltypes.numeric_val as alltypes_numeric_val, alltypes.char_val as alltypes_char_val, alltypes.varchar_val as alltypes_varchar_val, alltypes.longvarchar_val as alltypes_longvarchar_val, alltypes.date_val as alltypes_date_val, alltypes.time_val as alltypes_time_val, alltypes.timestamp_val as alltypes_timestamp_val, alltypes.bit_val as alltypes_bit_val, alltypes.array_val as alltypes_array_val, alltypes.boolean_val as alltypes_boolean_val, alltypes.varbinary_val as alltypes_varbinary_val, alltypes.json_val as alltypes_json_val, alltypes.jsonb_val as alltypes_jsonb_val ";
751 }
752
753 /**
754 Returns a <i>comma delimited list</i> of <i>all</i> columns in <tt>alltypes</tt>. These column names are prefix with the specified prefix, which corresponds to the
755 table abbreviation used in the "AS" clause. For example:
756 <blockquote><pre>
757 <tt>xyz.column1 AS xyz_column1, xyz.column2 AS xyz_column2 ...</tt>
758 </pre></blockquote>
759 <p>This list is suitable for placing in the column(s) clause of a select query, such as:
760 <blockquote>
761 <p><b>Note:</b> the "." will automatically be appended between the prefix and column name
762 so the prefix should not end with a "." or "_", etc<p>
763 <tt>Single table: select <i><font color=blue>[column_list_A]</font></i> from table_A <b>AS</b> xyz</tt><br>
764 <tt>Join: select <i><font color=blue>[column_list_A], [column_list_B]</font></i> from table_A <b>AS</b> xyz, table_B <b>AS</b> zzz</tt>
765 </blockquote>
766 The ResultSet returned by the query can be used directly or can be passed
767 to the {@link #getFromRS getFromRS(String)} method to convert it into a list of <code>alltypes
768 </code> objects. If the query is a join across multiple tables,
769 then the {@link #getFromRS getFromRS(String)} method for each table manager
770 can be called on the same ResultSet to retrieve the row object for
771 that table.
772 Note: the returned list of names has a trailing space, which is good when
773 the rest of the query is appended to this list.
774 */
775 public static String columns(String prefix) throws SQLException
776 {
777 final StringBuffer buf = new StringBuffer(19 * 10);
778
779 buf.append(prefix);
780 buf.append(".");
781 buf.append("id");
782 buf.append(" as ");
783 buf.append(prefix);
784 buf.append("_");
785 buf.append("id");
786
787 buf.append(", ");
788 buf.append(prefix);
789 buf.append(".");
790 buf.append("smallint_val");
791 buf.append(" as ");
792 buf.append(prefix);
793 buf.append("_");
794 buf.append("smallint_val");
795
796 buf.append(", ");
797 buf.append(prefix);
798 buf.append(".");
799 buf.append("int_val");
800 buf.append(" as ");
801 buf.append(prefix);
802 buf.append("_");
803 buf.append("int_val");
804
805 buf.append(", ");
806 buf.append(prefix);
807 buf.append(".");
808 buf.append("bigint_val");
809 buf.append(" as ");
810 buf.append(prefix);
811 buf.append("_");
812 buf.append("bigint_val");
813
814 buf.append(", ");
815 buf.append(prefix);
816 buf.append(".");
817 buf.append("float_val");
818 buf.append(" as ");
819 buf.append(prefix);
820 buf.append("_");
821 buf.append("float_val");
822
823 buf.append(", ");
824 buf.append(prefix);
825 buf.append(".");
826 buf.append("double_val");
827 buf.append(" as ");
828 buf.append(prefix);
829 buf.append("_");
830 buf.append("double_val");
831
832 buf.append(", ");
833 buf.append(prefix);
834 buf.append(".");
835 buf.append("numeric_val");
836 buf.append(" as ");
837 buf.append(prefix);
838 buf.append("_");
839 buf.append("numeric_val");
840
841 buf.append(", ");
842 buf.append(prefix);
843 buf.append(".");
844 buf.append("char_val");
845 buf.append(" as ");
846 buf.append(prefix);
847 buf.append("_");
848 buf.append("char_val");
849
850 buf.append(", ");
851 buf.append(prefix);
852 buf.append(".");
853 buf.append("varchar_val");
854 buf.append(" as ");
855 buf.append(prefix);
856 buf.append("_");
857 buf.append("varchar_val");
858
859 buf.append(", ");
860 buf.append(prefix);
861 buf.append(".");
862 buf.append("longvarchar_val");
863 buf.append(" as ");
864 buf.append(prefix);
865 buf.append("_");
866 buf.append("longvarchar_val");
867
868 buf.append(", ");
869 buf.append(prefix);
870 buf.append(".");
871 buf.append("date_val");
872 buf.append(" as ");
873 buf.append(prefix);
874 buf.append("_");
875 buf.append("date_val");
876
877 buf.append(", ");
878 buf.append(prefix);
879 buf.append(".");
880 buf.append("time_val");
881 buf.append(" as ");
882 buf.append(prefix);
883 buf.append("_");
884 buf.append("time_val");
885
886 buf.append(", ");
887 buf.append(prefix);
888 buf.append(".");
889 buf.append("timestamp_val");
890 buf.append(" as ");
891 buf.append(prefix);
892 buf.append("_");
893 buf.append("timestamp_val");
894
895 buf.append(", ");
896 buf.append(prefix);
897 buf.append(".");
898 buf.append("bit_val");
899 buf.append(" as ");
900 buf.append(prefix);
901 buf.append("_");
902 buf.append("bit_val");
903
904 buf.append(", ");
905 buf.append(prefix);
906 buf.append(".");
907 buf.append("array_val");
908 buf.append(" as ");
909 buf.append(prefix);
910 buf.append("_");
911 buf.append("array_val");
912
913 buf.append(", ");
914 buf.append(prefix);
915 buf.append(".");
916 buf.append("boolean_val");
917 buf.append(" as ");
918 buf.append(prefix);
919 buf.append("_");
920 buf.append("boolean_val");
921
922 buf.append(", ");
923 buf.append(prefix);
924 buf.append(".");
925 buf.append("varbinary_val");
926 buf.append(" as ");
927 buf.append(prefix);
928 buf.append("_");
929 buf.append("varbinary_val");
930
931 buf.append(", ");
932 buf.append(prefix);
933 buf.append(".");
934 buf.append("json_val");
935 buf.append(" as ");
936 buf.append(prefix);
937 buf.append("_");
938 buf.append("json_val");
939
940 buf.append(", ");
941 buf.append(prefix);
942 buf.append(".");
943 buf.append("jsonb_val");
944 buf.append(" as ");
945 buf.append(prefix);
946 buf.append("_");
947 buf.append("jsonb_val");
948 buf.append(" ");
949
950 return buf.toString();
951
952 }
953
954 /**
955 Creates and returns a new <tt>alltypes</tt> object that represents a row from the specified ResultSet. The ResultSet is
956 typically obtained via a handwritten query/PreparedStatement. The resulting
957 ResultSet should contain all of the
958 column names of table, and this will only happen if the handwritten query had
959 a select statement that specified all fields or used a <tt>select <b>*</b>..</tt>
960 clause.
961 <p>
962 In the select clause, we could also be selecting multiple tables. To disambiguate
963 between the same field names that may exist in multiple tables, this method
964 also requires that the query should use <font color=blue>fully qualified</font>
965 (prefixed with the table name) column names, such as:
966 <blockquote><pre>
967 <font color=blue>tablename</font>_column1
968 <font color=blue>tablename</font>_column2
969 ...etc.
970 </pre></blockquote>
971 <p>
972 For example:
973 <blockquote>
974 <code>select <font color=blue>foo</font>.a <b>AS</b> <font color=blue>foo</font>_a, <font color=red>bar</font>.a <b>AS</b> <font color=red>bar</font>_a from <font color=blue>foo</font>, <font color=red>bar</font> where foo.a = bar.a;</code>
975 </blockquote>
976 The {@link #columns} method conveniently returns a list of column names in fully qualified format
977 and is useful for this purpose.
978 <p>Note: This method will read the <i>current</i> row from the specified result set
979 and will <b>not</b> move the result set pointer to the next row after the current
980 row has been read. The result set should be appropriately positioned [via <tt>rs.next()</tt>]
981 <i>before</i> calling this method.
982
983 @return a new {@link
984 alltypes} object populated with the contents of the next row from the result set or <tt> null </tt> if
985 the ResultSet was empty.
986 */
987 public static alltypes getFromRS(final ResultSet rs) throws SQLException
988 {
989 __getfromrs_called++;
990 Argcheck.notnull(rs, "the specified resultset parameter was null");
991 boolean hasrow = ! rs.isAfterLast();
992 if (! hasrow) {
993 return null;
994 }
995 alltypes bean = new alltypes();
996
997 bean.set_id( rs.getInt("alltypes_id") );
998 bean.__orig_id = rs.getInt("alltypes_id"); /* save original PK */
999 if (rs.wasNull()) {
1000 bean.__isNullInDB_id = true;
1001 }
1002 bean.set_smallint_val( rs.getShort("alltypes_smallint_val") );
1003 if (rs.wasNull()) {
1004 bean.__isNullInDB_smallint_val = true;
1005 }
1006 bean.set_int_val( rs.getInt("alltypes_int_val") );
1007 if (rs.wasNull()) {
1008 bean.__isNullInDB_int_val = true;
1009 }
1010 bean.set_bigint_val( rs.getLong("alltypes_bigint_val") );
1011 if (rs.wasNull()) {
1012 bean.__isNullInDB_bigint_val = true;
1013 }
1014 bean.set_float_val( rs.getFloat("alltypes_float_val") );
1015 if (rs.wasNull()) {
1016 bean.__isNullInDB_float_val = true;
1017 }
1018 bean.set_double_val( rs.getDouble("alltypes_double_val") );
1019 if (rs.wasNull()) {
1020 bean.__isNullInDB_double_val = true;
1021 }
1022 bean.set_numeric_val( rs.getBigDecimal("alltypes_numeric_val") );
1023 if (rs.wasNull()) {
1024 bean.__isNullInDB_numeric_val = true;
1025 }
1026 bean.set_char_val( rs.getString("alltypes_char_val") );
1027 if (rs.wasNull()) {
1028 bean.__isNullInDB_char_val = true;
1029 }
1030 bean.set_varchar_val( rs.getString("alltypes_varchar_val") );
1031 if (rs.wasNull()) {
1032 bean.__isNullInDB_varchar_val = true;
1033 }
1034 bean.set_longvarchar_val( rs.getString("alltypes_longvarchar_val") );
1035 if (rs.wasNull()) {
1036 bean.__isNullInDB_longvarchar_val = true;
1037 }
1038 bean.set_date_val( rs.getDate("alltypes_date_val") );
1039 if (rs.wasNull()) {
1040 bean.__isNullInDB_date_val = true;
1041 }
1042 bean.set_time_val( rs.getTime("alltypes_time_val") );
1043 if (rs.wasNull()) {
1044 bean.__isNullInDB_time_val = true;
1045 }
1046 bean.set_timestamp_val( rs.getTimestamp("alltypes_timestamp_val") );
1047 if (rs.wasNull()) {
1048 bean.__isNullInDB_timestamp_val = true;
1049 }
1050 bean.set_bit_val( ((Boolean) rs.getObject("alltypes_bit_val")) );
1051 if (rs.wasNull()) {
1052 bean.__isNullInDB_bit_val = true;
1053 }
1054 bean.set_array_val( rs.getArray("alltypes_array_val") );
1055 if (rs.wasNull()) {
1056 bean.__isNullInDB_array_val = true;
1057 }
1058 bean.set_boolean_val( ((Boolean) rs.getObject("alltypes_boolean_val")) );
1059 if (rs.wasNull()) {
1060 bean.__isNullInDB_boolean_val = true;
1061 }
1062 bean.set_varbinary_val( rs.getBytes("alltypes_varbinary_val") );
1063 if (rs.wasNull()) {
1064 bean.__isNullInDB_varbinary_val = true;
1065 }
1066 bean.set_json_val( rs.getString("alltypes_json_val") );
1067 if (rs.wasNull()) {
1068 bean.__isNullInDB_json_val = true;
1069 }
1070 bean.set_jsonb_val( rs.getString("alltypes_jsonb_val") );
1071 if (rs.wasNull()) {
1072 bean.__isNullInDB_jsonb_val = true;
1073 }
1074
1075 /* set to true when instantiated new, false when we populate the bean from a resultset */
1076 bean.setNew(false);
1077 /* it's not modified, just loaded from the database */
1078 bean.resetModified();
1079 return bean;
1080 }
1081
1082 /**
1083 Creates and returns a new <tt>alltypes</tt> object that represents a row from the specified ResultSet. The ResultSet is
1084 typically obtained via a handwritten query/PreparedStatement. The resulting
1085 ResultSet should contain all of the
1086 column names of table, prefixed with the specified <i>prefix</i> argument.
1087 a select statement that specified all fields or used a <tt>select <b>*</b>..</tt>
1088 clause.
1089 <p>
1090 In the select clause, we could also be selecting multiple tables. To disambiguate
1091 between the same field names that may exist in multiple tables, this method
1092 also requires that the query should use a <font color=blue>prefix</font>
1093 (some arbitrary prefix) before column names, such as:
1094 <blockquote><pre>
1095 <font color=blue>foo</font>_column1
1096 <font color=blue>foo</font>_column2
1097 ...etc.
1098 </pre></blockquote>
1099 This prefix will typically be the same as the table abbreviation chosen via the <b>AS</b> clause.
1100 If the AS clause is not used, then it is simpler to use the {@link getFromRS(ResultSet)} method instead
1101 <p><b>Note:</b> the "." will automatically be appended between the prefix and column name
1102 so the prefix should not end with a "." or "_", etc<p>
1103 <p>
1104 For example:
1105 <blockquote>
1106 <code>select <font color=blue>XXX</font>.a <b>AS</b> <font color=blue>XXX</font>_a, <font color=red>YYY</font>.a <b>AS</b> <font color=red>YYY</font>_a from <font color=blue>foo as XXX</font>, <font color=red>bar as YYY</font> where foo.a = bar.a;</code>
1107 </blockquote>
1108 The {@link #columns} method conveniently returns a list of column names in fully qualified format
1109 and is useful for this purpose.
1110 <p>Note: This method will read the <i>current</i> row from the specified result set
1111 and will <b>not</b> move the result set pointer to the next row after the current
1112 row has been read. The result set should be appropriately positioned [via <tt>rs.next()</tt>]
1113 <i>before</i> calling this method.
1114
1115 @return a new {@link
1116 alltypes} object populated with the contents of the next row from the result set or <tt> null </tt> if
1117 the ResultSet was empty.
1118 */
1119 public static alltypes getFromRS(final ResultSet rs, String prefix) throws SQLException
1120 {
1121 __getfromrs_called++;
1122 Argcheck.notnull(rs, "the specified resultset parameter was null");
1123 boolean hasrow = ! rs.isAfterLast();
1124 if (! hasrow) {
1125 return null;
1126 }
1127 alltypes bean = new alltypes();
1128
1129 bean.set_id( rs.getInt(prefix+"_id") );
1130 bean.__orig_id = rs.getInt(prefix+"_id"); /* save original PK */
1131 if (rs.wasNull()) {
1132 bean.__isNullInDB_id = true;
1133 }
1134 bean.set_smallint_val( rs.getShort(prefix+"_smallint_val") );
1135 if (rs.wasNull()) {
1136 bean.__isNullInDB_smallint_val = true;
1137 }
1138 bean.set_int_val( rs.getInt(prefix+"_int_val") );
1139 if (rs.wasNull()) {
1140 bean.__isNullInDB_int_val = true;
1141 }
1142 bean.set_bigint_val( rs.getLong(prefix+"_bigint_val") );
1143 if (rs.wasNull()) {
1144 bean.__isNullInDB_bigint_val = true;
1145 }
1146 bean.set_float_val( rs.getFloat(prefix+"_float_val") );
1147 if (rs.wasNull()) {
1148 bean.__isNullInDB_float_val = true;
1149 }
1150 bean.set_double_val( rs.getDouble(prefix+"_double_val") );
1151 if (rs.wasNull()) {
1152 bean.__isNullInDB_double_val = true;
1153 }
1154 bean.set_numeric_val( rs.getBigDecimal(prefix+"_numeric_val") );
1155 if (rs.wasNull()) {
1156 bean.__isNullInDB_numeric_val = true;
1157 }
1158 bean.set_char_val( rs.getString(prefix+"_char_val") );
1159 if (rs.wasNull()) {
1160 bean.__isNullInDB_char_val = true;
1161 }
1162 bean.set_varchar_val( rs.getString(prefix+"_varchar_val") );
1163 if (rs.wasNull()) {
1164 bean.__isNullInDB_varchar_val = true;
1165 }
1166 bean.set_longvarchar_val( rs.getString(prefix+"_longvarchar_val") );
1167 if (rs.wasNull()) {
1168 bean.__isNullInDB_longvarchar_val = true;
1169 }
1170 bean.set_date_val( rs.getDate(prefix+"_date_val") );
1171 if (rs.wasNull()) {
1172 bean.__isNullInDB_date_val = true;
1173 }
1174 bean.set_time_val( rs.getTime(prefix+"_time_val") );
1175 if (rs.wasNull()) {
1176 bean.__isNullInDB_time_val = true;
1177 }
1178 bean.set_timestamp_val( rs.getTimestamp(prefix+"_timestamp_val") );
1179 if (rs.wasNull()) {
1180 bean.__isNullInDB_timestamp_val = true;
1181 }
1182 bean.set_bit_val( ((Boolean) rs.getObject(prefix+"_bit_val")) );
1183 if (rs.wasNull()) {
1184 bean.__isNullInDB_bit_val = true;
1185 }
1186 bean.set_array_val( rs.getArray(prefix+"_array_val") );
1187 if (rs.wasNull()) {
1188 bean.__isNullInDB_array_val = true;
1189 }
1190 bean.set_boolean_val( ((Boolean) rs.getObject(prefix+"_boolean_val")) );
1191 if (rs.wasNull()) {
1192 bean.__isNullInDB_boolean_val = true;
1193 }
1194 bean.set_varbinary_val( rs.getBytes(prefix+"_varbinary_val") );
1195 if (rs.wasNull()) {
1196 bean.__isNullInDB_varbinary_val = true;
1197 }
1198 bean.set_json_val( rs.getString(prefix+"_json_val") );
1199 if (rs.wasNull()) {
1200 bean.__isNullInDB_json_val = true;
1201 }
1202 bean.set_jsonb_val( rs.getString(prefix+"_jsonb_val") );
1203 if (rs.wasNull()) {
1204 bean.__isNullInDB_jsonb_val = true;
1205 }
1206
1207 /* set to true when instantiated new, false when we populate the bean from a resultset */
1208 bean.setNew(false);
1209 /* it's not modified, just loaded from the database */
1210 bean.resetModified();
1211 return bean;
1212 }
1213
1214 /**
1215 Creates and returns a new <tt>alltypes</tt> object that represents a row from the specified ResultSet. For this method
1216 to work properly, the specified ResultSet should contain <b>all</b> (typically via <b>select *
1217 </b>) of the column names of table.<tt>alltypes</tt>.
1218 <p>
1219 This method does not prepend the table name to columns when reading data from
1220 the result set. It is useful when writing a JDBC query by hand that uses a single table
1221 (no joins) and then converting the returned result set into objects of this
1222 class. For example:
1223 <p>
1224 <code>select a, b, c, c*2 from foo where a = 1;</code>
1225 <p>
1226 This method will expect columns to be called <code><i>a, b, c</i></code> (no column aliases) in the returned
1227 result set. In this example, there is only one table <code>foo</code> so qualifying the column
1228 names, like <code>foo.a as foo_a</code> is not necessary). Also note, for this method to work properly, the
1229 column list<blockquote><code>select <i>a, b, c </i></code> ...</blockquote> should be complete, i.e., contain <i>at least</i> all the columns
1230 of this table (<i>additional</i> expressions like c*2 are fine). It is slightly less efficient to retrieve all columns
1231 especially for large tables but to construct a row into an object, we need all the fields. To be safe, use <blockquote><tt>select * ....</tt></blockquote>
1232 <p>
1233 Of course, if one needs a subset of columns, one can use the ResultSet directly and forego trying to
1234 convert a ResultSet row into an corresponding object
1235 <p>
1236 See {@link getFromRS(ResultSet)} which is more useful when writing a JDBC
1237 query that uses multiple table joins.
1238 <p>Note: This method will read the <i>current</i> row from the specified result set
1239 and will <b>not</b> move the result set pointer to the next row after the current
1240 row has been read. The result set should be appropriately positioned [via <tt>rs.next()</tt>]
1241 <i>before</i> calling this method.
1242
1243 @return a new {@link alltypes} object populated with the contents of the next
1244 row from the result set or <tt> null </tt> if
1245 the ResultSet was empty.
1246 */
1247 public static alltypes getFromRS1Table(final ResultSet rs) throws SQLException
1248 {
1249 __getfromrs_called++;
1250 Argcheck.notnull(rs, "the specified resultset parameter was null");
1251 boolean hasrow = ! rs.isAfterLast();
1252 if (! hasrow) {
1253 return null;
1254 }
1255 alltypes bean = new alltypes();
1256
1257 bean.set_id( rs.getInt(1) );
1258 bean.__orig_id = rs.getInt(1); /* save original PK */
1259 if (rs.wasNull()) {
1260 bean.__isNullInDB_id = true;
1261 }
1262 bean.set_smallint_val( rs.getShort(2) );
1263 if (rs.wasNull()) {
1264 bean.__isNullInDB_smallint_val = true;
1265 }
1266 bean.set_int_val( rs.getInt(3) );
1267 if (rs.wasNull()) {
1268 bean.__isNullInDB_int_val = true;
1269 }
1270 bean.set_bigint_val( rs.getLong(4) );
1271 if (rs.wasNull()) {
1272 bean.__isNullInDB_bigint_val = true;
1273 }
1274 bean.set_float_val( rs.getFloat(5) );
1275 if (rs.wasNull()) {
1276 bean.__isNullInDB_float_val = true;
1277 }
1278 bean.set_double_val( rs.getDouble(6) );
1279 if (rs.wasNull()) {
1280 bean.__isNullInDB_double_val = true;
1281 }
1282 bean.set_numeric_val( rs.getBigDecimal(7) );
1283 if (rs.wasNull()) {
1284 bean.__isNullInDB_numeric_val = true;
1285 }
1286 bean.set_char_val( rs.getString(8) );
1287 if (rs.wasNull()) {
1288 bean.__isNullInDB_char_val = true;
1289 }
1290 bean.set_varchar_val( rs.getString(9) );
1291 if (rs.wasNull()) {
1292 bean.__isNullInDB_varchar_val = true;
1293 }
1294 bean.set_longvarchar_val( rs.getString(10) );
1295 if (rs.wasNull()) {
1296 bean.__isNullInDB_longvarchar_val = true;
1297 }
1298 bean.set_date_val( rs.getDate(11) );
1299 if (rs.wasNull()) {
1300 bean.__isNullInDB_date_val = true;
1301 }
1302 bean.set_time_val( rs.getTime(12) );
1303 if (rs.wasNull()) {
1304 bean.__isNullInDB_time_val = true;
1305 }
1306 bean.set_timestamp_val( rs.getTimestamp(13) );
1307 if (rs.wasNull()) {
1308 bean.__isNullInDB_timestamp_val = true;
1309 }
1310 bean.set_bit_val( ((Boolean) rs.getObject(14)) );
1311 if (rs.wasNull()) {
1312 bean.__isNullInDB_bit_val = true;
1313 }
1314 bean.set_array_val( rs.getArray(15) );
1315 if (rs.wasNull()) {
1316 bean.__isNullInDB_array_val = true;
1317 }
1318 bean.set_boolean_val( ((Boolean) rs.getObject(16)) );
1319 if (rs.wasNull()) {
1320 bean.__isNullInDB_boolean_val = true;
1321 }
1322 bean.set_varbinary_val( rs.getBytes(17) );
1323 if (rs.wasNull()) {
1324 bean.__isNullInDB_varbinary_val = true;
1325 }
1326 bean.set_json_val( rs.getString(18) );
1327 if (rs.wasNull()) {
1328 bean.__isNullInDB_json_val = true;
1329 }
1330 bean.set_jsonb_val( rs.getString(19) );
1331 if (rs.wasNull()) {
1332 bean.__isNullInDB_jsonb_val = true;
1333 }
1334
1335 /* set to true when instantiated but this should be false
1336 whenever we populate the bean from a result set */
1337 bean.setNew(false);
1338 //it's not modified, just loaded from the database
1339 bean.resetModified();
1340 return bean;
1341 }
1342
1343 private static alltypes decodeFromRS(final ResultSet rs) throws SQLException
1344 {
1345 Argcheck.notnull(rs, "the specified resultset parameter was null");
1346 boolean hasrow = rs.next();
1347 if (! hasrow) {
1348 return null;
1349 }
1350 alltypes bean = new alltypes();
1351
1352 bean.set_id( rs.getInt(1) );
1353 bean.__orig_id = rs.getInt(1); /* save original PK */
1354 if (rs.wasNull()) {
1355 bean.__isNullInDB_id = true;
1356 }
1357
1358 bean.set_smallint_val( rs.getShort(2) );
1359 if (rs.wasNull()) {
1360 bean.__isNullInDB_smallint_val = true;
1361 }
1362
1363 bean.set_int_val( rs.getInt(3) );
1364 if (rs.wasNull()) {
1365 bean.__isNullInDB_int_val = true;
1366 }
1367
1368 bean.set_bigint_val( rs.getLong(4) );
1369 if (rs.wasNull()) {
1370 bean.__isNullInDB_bigint_val = true;
1371 }
1372
1373 bean.set_float_val( rs.getFloat(5) );
1374 if (rs.wasNull()) {
1375 bean.__isNullInDB_float_val = true;
1376 }
1377
1378 bean.set_double_val( rs.getDouble(6) );
1379 if (rs.wasNull()) {
1380 bean.__isNullInDB_double_val = true;
1381 }
1382
1383 bean.set_numeric_val( rs.getBigDecimal(7) );
1384 if (rs.wasNull()) {
1385 bean.__isNullInDB_numeric_val = true;
1386 }
1387
1388 bean.set_char_val( rs.getString(8) );
1389 if (rs.wasNull()) {
1390 bean.__isNullInDB_char_val = true;
1391 }
1392
1393 bean.set_varchar_val( rs.getString(9) );
1394 if (rs.wasNull()) {
1395 bean.__isNullInDB_varchar_val = true;
1396 }
1397
1398 bean.set_longvarchar_val( rs.getString(10) );
1399 if (rs.wasNull()) {
1400 bean.__isNullInDB_longvarchar_val = true;
1401 }
1402
1403 bean.set_date_val( rs.getDate(11) );
1404 if (rs.wasNull()) {
1405 bean.__isNullInDB_date_val = true;
1406 }
1407
1408 bean.set_time_val( rs.getTime(12) );
1409 if (rs.wasNull()) {
1410 bean.__isNullInDB_time_val = true;
1411 }
1412
1413 bean.set_timestamp_val( rs.getTimestamp(13) );
1414 if (rs.wasNull()) {
1415 bean.__isNullInDB_timestamp_val = true;
1416 }
1417
1418 bean.set_bit_val( ((Boolean) rs.getObject(14)) );
1419 if (rs.wasNull()) {
1420 bean.__isNullInDB_bit_val = true;
1421 }
1422
1423 bean.set_array_val( rs.getArray(15) );
1424 if (rs.wasNull()) {
1425 bean.__isNullInDB_array_val = true;
1426 }
1427
1428 bean.set_boolean_val( ((Boolean) rs.getObject(16)) );
1429 if (rs.wasNull()) {
1430 bean.__isNullInDB_boolean_val = true;
1431 }
1432
1433 bean.set_varbinary_val( rs.getBytes(17) );
1434 if (rs.wasNull()) {
1435 bean.__isNullInDB_varbinary_val = true;
1436 }
1437
1438 bean.set_json_val( rs.getString(18) );
1439 if (rs.wasNull()) {
1440 bean.__isNullInDB_json_val = true;
1441 }
1442
1443 bean.set_jsonb_val( rs.getString(19) );
1444 if (rs.wasNull()) {
1445 bean.__isNullInDB_jsonb_val = true;
1446 }
1447
1448
1449 /* set to true when newly instantiated but this should be false
1450 whenever we populate the bean from a result set */
1451 bean.setNew(false);
1452 //it's not modified, just loaded from the database
1453 bean.resetModified();
1454 return bean;
1455 }
1456
1457 /**
1458 Saves the specified object into the database. If the specified
1459 object was newly created, then it is <span style="font-variant:
1460 small-caps">insert</span>'ed into the database, else (if it was retrieved
1461 earlier from the database) it is <span
1462 style="font-variant: small-caps">update</span>'ed. (this can be
1463 overriden by the {@link #update update} method). If the object is
1464 inserted as a new row, then after insertion, the values of
1465 serial/auto-incremented columns will be automatically available via the
1466 appropriate getXXX() methods on that object.
1467 <p>
1468 <b>NOTE 1:</b> When saving an object, only modified fields are
1469 saved. Do not rely on default field values (such as null) of newly
1470 created objects; instead explicitly set the value (including to null
1471 if needed) of any field that should be saved to the database.
1472 <p>
1473 <b>NOTE 2:</b> Once an object is successfully saved, it is discarded
1474 and cannot be saved again and any attempt to save it again will
1475 result in a runtime exception. Objects that need to be modified
1476 again must be re-instantiated or re-populated from the database
1477 before they can be saved again. (the serial/auto-increment data will still be
1478 available, discarding only affects the ability to save the object
1479 again).
1480 <p>
1481 <b>Note 3:</b> <font color='red'>For various reasons/flexiblity, default database values
1482 for columns <i>other</i> than serial columns are <b>not</b> available
1483 in the saved object. To get these values, retrieve the saved object again. (this is what
1484 we would have to do internally anyway). This is relevant, for example, when a column has
1485 a default value of a now() timestamp, and we need to get that timestamp after the object
1486 has been saved</font>
1487
1488 @return the number of rows inserted or updated (typically useful
1489 to see if an update succeeded)
1490 @throws ValidateException on a validation error
1491 @throws SQLException on some SQL/Database error
1492 @throws IOException by the available() method if/when
1493 setting a stream for longvar/text types
1494 */
1495 public static int save(final Connection con, final alltypes bean) throws ValidateException, SQLException, IOException
1496 {
1497 __save_called++;
1498 Argcheck.notnull(bean, "the specified bean parameter was null");
1499 checkDiscarded(bean);
1500 if (! bean.isModified()) {
1501 log.warn("bean=", bean, " not modified, IGNORING SAVE\n====DEBUG STACK TRACE====\n", IOUtil.throwableToString(new Exception()));
1502 return 0;
1503 }
1504 PreparedStatement ps = null;
1505
1506 boolean inserting_a_row = false;
1507 if (bean.isNew() && ! bean.__force_update)
1508 { //insert new row
1509 validateBeforeSaveNew(bean);
1510 int __count = 0;
1511 inserting_a_row = true;
1512 final StringBuilder buf = new StringBuilder(512);
1513 buf.append("INSERT into alltypes (");
1514 if (bean.isModified_smallint_val()) {
1515 buf.append("smallint_val").append(", ");
1516 __count++;
1517 }
1518 if (bean.isModified_int_val()) {
1519 buf.append("int_val").append(", ");
1520 __count++;
1521 }
1522 if (bean.isModified_bigint_val()) {
1523 buf.append("bigint_val").append(", ");
1524 __count++;
1525 }
1526 if (bean.isModified_float_val()) {
1527 buf.append("float_val").append(", ");
1528 __count++;
1529 }
1530 if (bean.isModified_double_val()) {
1531 buf.append("double_val").append(", ");
1532 __count++;
1533 }
1534 if (bean.isModified_numeric_val()) {
1535 buf.append("numeric_val").append(", ");
1536 __count++;
1537 }
1538 if (bean.isModified_char_val()) {
1539 buf.append("char_val").append(", ");
1540 __count++;
1541 }
1542 if (bean.isModified_varchar_val()) {
1543 buf.append("varchar_val").append(", ");
1544 __count++;
1545 }
1546 if (bean.isModified_longvarchar_val()) {
1547 buf.append("longvarchar_val").append(", ");
1548 __count++;
1549 }
1550 if (bean.isModified_date_val()) {
1551 buf.append("date_val").append(", ");
1552 __count++;
1553 }
1554 if (bean.isModified_time_val()) {
1555 buf.append("time_val").append(", ");
1556 __count++;
1557 }
1558 if (bean.isModified_timestamp_val()) {
1559 buf.append("timestamp_val").append(", ");
1560 __count++;
1561 }
1562 if (bean.isModified_bit_val()) {
1563 buf.append("bit_val").append(", ");
1564 __count++;
1565 }
1566 if (bean.isModified_array_val()) {
1567 buf.append("array_val").append(", ");
1568 __count++;
1569 }
1570 if (bean.isModified_boolean_val()) {
1571 buf.append("boolean_val").append(", ");
1572 __count++;
1573 }
1574 if (bean.isModified_varbinary_val()) {
1575 buf.append("varbinary_val").append(", ");
1576 __count++;
1577 }
1578 if (bean.isModified_json_val()) {
1579 buf.append("json_val").append(", ");
1580 __count++;
1581 }
1582 if (bean.isModified_jsonb_val()) {
1583 buf.append("jsonb_val").append(", ");
1584 __count++;
1585 }
1586
1587 if (__count == 0) {
1588 throw new ValidateException("Cannot save this bean because no column has been modified. Use JDBC directly as needed.\n");
1589 }
1590 buf.setLength(buf.length() - 2);
1591 buf.append(") values (");
1592 for (int n = 0; n < __count; n++) {
1593 buf.append("?");
1594 if ((n+1) < __count)
1595 buf.append(", ");
1596 }
1597 buf.append(")");
1598
1599 final String insertByPKStmt = buf.toString();
1600 ps = prepareStatement(con, insertByPKStmt);
1601 /* Insert any changed values into our prepared statement */
1602 int pos = 0;
1603 if (bean.isModified_smallint_val()) {
1604 pos++;
1605 if (bean.isModifiedSetNull_smallint_val()) { /* nullable in db */
1606 ps.setNull(pos,5)/*SMALLINT*/;
1607 }
1608 else{
1609 short smallint_val = bean.get_smallint_val();
1610 ps.setShort(pos, smallint_val);
1611 }
1612 }
1613 if (bean.isModified_int_val()) {
1614 pos++;
1615 int int_val = bean.get_int_val();
1616 ps.setInt(pos, int_val);
1617 }
1618 if (bean.isModified_bigint_val()) {
1619 pos++;
1620 if (bean.isModifiedSetNull_bigint_val()) { /* nullable in db */
1621 ps.setNull(pos,-5)/*BIGINT*/;
1622 }
1623 else{
1624 long bigint_val = bean.get_bigint_val();
1625 ps.setLong(pos, bigint_val);
1626 }
1627 }
1628 if (bean.isModified_float_val()) {
1629 pos++;
1630 if (bean.isModifiedSetNull_float_val()) { /* nullable in db */
1631 ps.setNull(pos,7)/*REAL*/;
1632 }
1633 else{
1634 float float_val = bean.get_float_val();
1635 ps.setFloat(pos, float_val);
1636 }
1637 }
1638 if (bean.isModified_double_val()) {
1639 pos++;
1640 if (bean.isModifiedSetNull_double_val()) { /* nullable in db */
1641 ps.setNull(pos,8)/*DOUBLE*/;
1642 }
1643 else{
1644 double double_val = bean.get_double_val();
1645 ps.setDouble(pos, double_val);
1646 }
1647 }
1648 if (bean.isModified_numeric_val()) {
1649 pos++;
1650 BigDecimal numeric_val = bean.get_numeric_val();
1651 ps.setBigDecimal(pos, numeric_val);
1652 }
1653 if (bean.isModified_char_val()) {
1654 pos++;
1655 String char_val = bean.get_char_val();
1656 ps.setString(pos, char_val);
1657 }
1658 if (bean.isModified_varchar_val()) {
1659 pos++;
1660 String varchar_val = bean.get_varchar_val();
1661 ps.setString(pos, varchar_val);
1662 }
1663 if (bean.isModified_longvarchar_val()) {
1664 pos++;
1665 String longvarchar_val = bean.get_longvarchar_val();
1666 ps.setString(pos, longvarchar_val);
1667 }
1668 if (bean.isModified_date_val()) {
1669 pos++;
1670 java.sql.Date date_val = bean.get_date_val();
1671 ps.setDate(pos, date_val);
1672 }
1673 if (bean.isModified_time_val()) {
1674 pos++;
1675 Time time_val = bean.get_time_val();
1676 ps.setTime(pos, time_val);
1677 }
1678 if (bean.isModified_timestamp_val()) {
1679 pos++;
1680 Timestamp timestamp_val = bean.get_timestamp_val();
1681 ps.setTimestamp(pos, timestamp_val);
1682 }
1683 if (bean.isModified_bit_val()) {
1684 pos++;
1685 Boolean bit_val = bean.get_bit_val();
1686 ps.setObject(pos, bit_val);
1687 }
1688 if (bean.isModified_array_val()) {
1689 pos++;
1690 java.sql.Array array_val = bean.get_array_val();
1691 ps.setArray(pos, array_val);
1692 }
1693 if (bean.isModified_boolean_val()) {
1694 pos++;
1695 Boolean boolean_val = bean.get_boolean_val();
1696 ps.setObject(pos, boolean_val);
1697 }
1698 if (bean.isModified_varbinary_val()) {
1699 pos++;
1700 byte[] varbinary_val = bean.get_varbinary_val();
1701 ps.setBytes(pos, varbinary_val);
1702 }
1703 if (bean.isModified_json_val()) {
1704 pos++;
1705 String json_val = bean.get_json_val();
1706 ps.setObject(pos, json_val, java.sql.Types.OTHER);
1707 }
1708 if (bean.isModified_jsonb_val()) {
1709 pos++;
1710 String jsonb_val = bean.get_jsonb_val();
1711 ps.setObject(pos, jsonb_val, java.sql.Types.OTHER);
1712 }
1713 }
1714 else //update existing row
1715 {
1716 validateBeforeSaveUpdate(bean);
1717 int __count = 0;
1718 final StringBuilder buf = new StringBuilder(512);
1719 buf.append("UPDATE ");
1720 buf.append("alltypes");
1721 buf.append(" SET ");
1722 if (bean.isModified_smallint_val()) {
1723 buf.append("smallint_val=?, ");
1724 __count++;
1725 }
1726 if (bean.isModified_int_val()) {
1727 buf.append("int_val=?, ");
1728 __count++;
1729 }
1730 if (bean.isModified_bigint_val()) {
1731 buf.append("bigint_val=?, ");
1732 __count++;
1733 }
1734 if (bean.isModified_float_val()) {
1735 buf.append("float_val=?, ");
1736 __count++;
1737 }
1738 if (bean.isModified_double_val()) {
1739 buf.append("double_val=?, ");
1740 __count++;
1741 }
1742 if (bean.isModified_numeric_val()) {
1743 buf.append("numeric_val=?, ");
1744 __count++;
1745 }
1746 if (bean.isModified_char_val()) {
1747 buf.append("char_val=?, ");
1748 __count++;
1749 }
1750 if (bean.isModified_varchar_val()) {
1751 buf.append("varchar_val=?, ");
1752 __count++;
1753 }
1754 if (bean.isModified_longvarchar_val()) {
1755 buf.append("longvarchar_val=?, ");
1756 __count++;
1757 }
1758 if (bean.isModified_date_val()) {
1759 buf.append("date_val=?, ");
1760 __count++;
1761 }
1762 if (bean.isModified_time_val()) {
1763 buf.append("time_val=?, ");
1764 __count++;
1765 }
1766 if (bean.isModified_timestamp_val()) {
1767 buf.append("timestamp_val=?, ");
1768 __count++;
1769 }
1770 if (bean.isModified_bit_val()) {
1771 buf.append("bit_val=?, ");
1772 __count++;
1773 }
1774 if (bean.isModified_array_val()) {
1775 buf.append("array_val=?, ");
1776 __count++;
1777 }
1778 if (bean.isModified_boolean_val()) {
1779 buf.append("boolean_val=?, ");
1780 __count++;
1781 }
1782 if (bean.isModified_varbinary_val()) {
1783 buf.append("varbinary_val=?, ");
1784 __count++;
1785 }
1786 if (bean.isModified_json_val()) {
1787 buf.append("json_val=?, ");
1788 __count++;
1789 }
1790 if (bean.isModified_jsonb_val()) {
1791 buf.append("jsonb_val=?, ");
1792 __count++;
1793 }
1794
1795 if (__count == 0) {
1796 throw new ValidateException("Cannot save this bean because no column has been modified. Use JDBC directly as needed.\n");
1797 }
1798 buf.setLength(buf.length() - 2);
1799 buf.append(" WHERE ");
1800 buf.append("id=?");
1801 ps = con.prepareStatement(buf.toString());
1802
1803 /* Insert any changed values into our prepared statement */
1804 int pos = 0;
1805 if (bean.isModified_smallint_val()) {
1806 pos++;
1807 if (bean.isModifiedSetNull_smallint_val()) { /* nullable in db */
1808 ps.setNull(pos,5)/*SMALLINT*/;
1809 }
1810 else{
1811 short smallint_val = bean.get_smallint_val();
1812 ps.setShort(pos, smallint_val);
1813 }
1814 }
1815 if (bean.isModified_int_val()) {
1816 pos++;
1817 int int_val = bean.get_int_val();
1818 ps.setInt(pos, int_val);
1819 }
1820 if (bean.isModified_bigint_val()) {
1821 pos++;
1822 if (bean.isModifiedSetNull_bigint_val()) { /* nullable in db */
1823 ps.setNull(pos,-5)/*BIGINT*/;
1824 }
1825 else{
1826 long bigint_val = bean.get_bigint_val();
1827 ps.setLong(pos, bigint_val);
1828 }
1829 }
1830 if (bean.isModified_float_val()) {
1831 pos++;
1832 if (bean.isModifiedSetNull_float_val()) { /* nullable in db */
1833 ps.setNull(pos,7)/*REAL*/;
1834 }
1835 else{
1836 float float_val = bean.get_float_val();
1837 ps.setFloat(pos, float_val);
1838 }
1839 }
1840 if (bean.isModified_double_val()) {
1841 pos++;
1842 if (bean.isModifiedSetNull_double_val()) { /* nullable in db */
1843 ps.setNull(pos,8)/*DOUBLE*/;
1844 }
1845 else{
1846 double double_val = bean.get_double_val();
1847 ps.setDouble(pos, double_val);
1848 }
1849 }
1850 if (bean.isModified_numeric_val()) {
1851 pos++;
1852 BigDecimal numeric_val = bean.get_numeric_val();
1853 ps.setBigDecimal(pos, numeric_val);
1854 }
1855 if (bean.isModified_char_val()) {
1856 pos++;
1857 String char_val = bean.get_char_val();
1858 ps.setString(pos, char_val);
1859 }
1860 if (bean.isModified_varchar_val()) {
1861 pos++;
1862 String varchar_val = bean.get_varchar_val();
1863 ps.setString(pos, varchar_val);
1864 }
1865 if (bean.isModified_longvarchar_val()) {
1866 pos++;
1867 String longvarchar_val = bean.get_longvarchar_val();
1868 ps.setString(pos, longvarchar_val);
1869 }
1870 if (bean.isModified_date_val()) {
1871 pos++;
1872 java.sql.Date date_val = bean.get_date_val();
1873 ps.setDate(pos, date_val);
1874 }
1875 if (bean.isModified_time_val()) {
1876 pos++;
1877 Time time_val = bean.get_time_val();
1878 ps.setTime(pos, time_val);
1879 }
1880 if (bean.isModified_timestamp_val()) {
1881 pos++;
1882 Timestamp timestamp_val = bean.get_timestamp_val();
1883 ps.setTimestamp(pos, timestamp_val);
1884 }
1885 if (bean.isModified_bit_val()) {
1886 pos++;
1887 Boolean bit_val = bean.get_bit_val();
1888 ps.setObject(pos, bit_val);
1889 }
1890 if (bean.isModified_array_val()) {
1891 pos++;
1892 java.sql.Array array_val = bean.get_array_val();
1893 ps.setArray(pos, array_val);
1894 }
1895 if (bean.isModified_boolean_val()) {
1896 pos++;
1897 Boolean boolean_val = bean.get_boolean_val();
1898 ps.setObject(pos, boolean_val);
1899 }
1900 if (bean.isModified_varbinary_val()) {
1901 pos++;
1902 byte[] varbinary_val = bean.get_varbinary_val();
1903 ps.setBytes(pos, varbinary_val);
1904 }
1905 if (bean.isModified_json_val()) {
1906 pos++;
1907 String json_val = bean.get_json_val();
1908 ps.setObject(pos, json_val, java.sql.Types.OTHER);
1909 }
1910 if (bean.isModified_jsonb_val()) {
1911 pos++;
1912 String jsonb_val = bean.get_jsonb_val();
1913 ps.setObject(pos, jsonb_val, java.sql.Types.OTHER);
1914 }
1915
1916 /* Set primary keys for the WHERE part of our prepared statement */
1917 int id = (bean.__force_update) ? bean.get_id() : bean.__orig_id;
1918 ps.setInt(++pos, id);
1919 } //~else update;
1920
1921 log.bug("Query to run: ", ps);
1922 int result = ps.executeUpdate();
1923 if (inserting_a_row) { //get auto increment info
1924 /* Retrieve values from auto-increment columns */
1925 ResultSet rs = null; Statement stmt = null;
1926 String query = null;
1927 boolean found = false;
1928
1929 if (bean.isModified_id()) {
1930 //column: id
1931 //not getting auto increment value for this column
1932 //since not using auto increment, a value was specified manually
1933 }
1934 else{
1935 stmt = con.createStatement();
1936 query = "select currval('alltypes_id_seq')";
1937 rs = stmt.executeQuery(query);
1938 found = rs.next();
1939 if (! found) throw new SQLException("No last inserted id returned");
1940 bean.set_id( rs.getInt(1));
1941 if (rs.wasNull()) {
1942 bean.__isNullInDB_id = true;
1943 }
1944 rs.close();
1945 }
1946 }
1947
1948 //discard after saving/updating for safety
1949 bean.discard();
1950 return result;
1951 }
1952
1953 /**
1954 Uses the specified object to update existing data in the database.
1955 <p>
1956 Note, the {@link #save save} method automatically saves newly created objects
1957 as <i>inserts</i> in the database (and prior <i>retrieved</i> objects, when
1958 subsequently modified, are saved as <i>updates</i>).
1959 <p>
1960 However, sometimes it is useful to create a <i>new</i> object and then
1961 use its data to <i>update</i> an existing row in the database.
1962 This method need <b>only</b> be called to save a <u>newly</u>
1963 created object as an <u>update</u> into the database (overriding the
1964 default action of saving new objects as inserts in the database).
1965 <p>
1966 Note, also, a bean can only be updated if the corresponding table it has
1967 at least one primary key defined. To update tables with no primary keys,
1968 use JDBC directly.
1969 <p>
1970 This method takes primary key(s) of {@link alltypes} as additional arguments and sets those in the
1971 specified bean before updating the database (this way the row to update
1972 can be uniquely identified).
1973
1974 @see #save
1975
1976 @return the number of rows that were updated (typically useful
1977 to see if an update succeeded)
1978 @throws ValidateException on a validation error
1979 @throws SQLException on some SQL/Database error
1980 */
1981 public static int update(final Connection con, final alltypes bean, int id) throws ValidateException, SQLException, IOException
1982 {
1983 bean.set_id(id);
1984
1985 if (bean.isNew()) { /* force update (and not insert) for new bean */
1986 bean.__force_update = true;
1987 }
1988 return save(con, bean);
1989 }
1990
1991 static private final String deleteStmt = "DELETE from alltypes WHERE id=?";
1992 /**
1993 Deletes this object from the database. <p>
1994 <b>NOTE 1:</b> Only objects that were retrieved from the database can be deleted. Newly
1995 created objects cannot be deleted since they do not yet exist in the database.
1996 Use {@link #deleteByKey deleteByKey} or {@link #deleteWhere deleteWhere} instead
1997 for arbitrary deletions. <p><b>NOTE 2:</b> Once an object is successfully
1998 deleted, it is discarded and cannot be deleted again and any attempt to delete
1999 it again will result in a runtime Exception.
2000 */
2001 public static void delete(final Connection con, alltypes bean) throws SQLException
2002 {
2003 __delete_called++;
2004 if (bean.isNew()) {
2005 throw new DBOException("Cannot delete new objects using this method. Use deleteByKey() or deleteWhere() instead");
2006 }
2007 checkDiscarded(bean);
2008 final PreparedStatement ps = prepareStatement(con, deleteStmt);
2009 int id = bean.get_id();
2010 ps.setInt(1, id);
2011 log.bug("Query to run: ", ps);
2012 final int result = ps.executeUpdate();
2013 if (result != 1) {
2014 throw new DBOException("The number of deleted rows was: " + result + "; [Should have been 1 row exactly] ");
2015 }
2016 }
2017
2018 static private final String deleteByPKStmt = "DELETE from alltypes WHERE id=?";
2019 /**
2020 Deletes the rows with the specified primary key(s) from the database. <p>This method uses a prepared statement and is safe from SQL injection attacks
2021 */
2022 public static void deleteByKey(final Connection con, int id) throws SQLException
2023 {
2024 __deletebykey_called++;
2025 PreparedStatement ps = prepareStatement(con, deleteByPKStmt);
2026 ps.setInt(1, id);
2027 log.bug("Query to run: ", ps);
2028 final int result = ps.executeUpdate();
2029 if (result != 1) {
2030 throw new DBOException("The number of deleted rows was: " + result + "; [Should have been 1 row exactly] ");
2031 }
2032 }
2033
2034 /**
2035 Returns the rows returned by querying the table with the contents of
2036 the specified instance of <tt>alltypes</tt> or <tt>null</tt> if no
2037 rows were found. As many fields in <tt>alltypes</tt> can be set as
2038 needed and the values of all set fields (including fields explicitly
2039 set to <tt>null</tt>) are then used to perform the query. <p>Note,
2040 however that this method does use any primary key(s). If the
2041 primary keys are known then one should use the {@link
2042 #deleteByKey deleteByKey} method to delete the data instead.
2043 <p>Likewise, to delete a previously fetched row, use the {@link
2044 #delete delete} method. This method is really meant to create an new
2045 object, set various fields in it, and then use that to delete matching
2046 row(s) from the database in a type safe way.
2047 <p>
2048 This method is often convenient/safer than the {@link #deleteWhere
2049 deleteWhere} method (because the <tt>deleteWhere</tt> method takes
2050 an arbitrary query string which has to be properly escaped by the user).
2051
2052 <p>However, as a middle ground, this method also takes an <tt>clause</tt> parameter which
2053 is sent as is to the database. For example, a clause can be:
2054 <blockquote><pre>
2055 List beans = table_fooMgr.<font color=blue>deleteUsing(proto, <b>"xyx > 5"</b>)</font>;
2056 </pre> </blockquote>
2057 This clause is optional. Specify <tt>null</tt> to not use it at all.
2058 If the clause is specified, do <font size='+1'><b>NOT</b></font> include the word <tt>WHERE</tt>.
2059
2060 <p>Essentially, this method is a more convenient way to use a
2061 PreparedStatement. Internally, a prepared statement is created and
2062 it's parameters are set to fields that are set in this object).
2063 Using PreparedStatements directly is also perfectly fine. For
2064 example, the following are equivalent.
2065 <p> Using a PreparedStatement:
2066 <blockquote><pre>
2067 String foo = "delete from table_foo where x = ? and y = ?";
2068 PreparedStatement ps = con.prepareStatement(foo);
2069 ps.setString(1, "somevalue");
2070 ps.setString(2, "othervalue");
2071 int rows_deleted = ps.executeUpdate();
2072 </pre> </blockquote>
2073
2074 Using this method:
2075 <blockquote><pre>
2076 table_foo proto = new table_foo();
2077 proto.set_x("somevalue"); //compile time safety
2078 proto.set_y("othervalue"); //compile time safety
2079 int rows_deleted = table_fooMgr.<font color=blue>deleteUsing</font>(proto);
2080 </pre></blockquote>
2081 @return the number of rows deleted
2082 */
2083 public static int deleteUsing(final Connection con, final alltypes bean, final String clause) throws ValidateException, SQLException
2084 {
2085 __deleteusing_called++;
2086
2087 Argcheck.notnull(bean, "the bean parameter was null (and should not be null)");
2088 if (! bean.isModified()) {
2089 throw new ValidateException("bean=" + bean + " not modified, ignoring query");
2090 }
2091
2092 final StringBuilder buf = new StringBuilder(512);
2093 buf.append("DELETE from alltypes WHERE ");
2094
2095 int __count = 0;
2096 if (bean.isModified_smallint_val()) {
2097 if (bean.isModifiedSetNull_smallint_val()) {
2098 buf.append("smallint_val is NULL and ");
2099 }
2100 else{
2101 buf.append("smallint_val=? and ");
2102 __count++;
2103 }
2104 }
2105 if (bean.isModified_int_val()) {
2106 buf.append("int_val=? and ");
2107 __count++;
2108 }
2109 if (bean.isModified_bigint_val()) {
2110 if (bean.isModifiedSetNull_bigint_val()) {
2111 buf.append("bigint_val is NULL and ");
2112 }
2113 else{
2114 buf.append("bigint_val=? and ");
2115 __count++;
2116 }
2117 }
2118 if (bean.isModified_float_val()) {
2119 if (bean.isModifiedSetNull_float_val()) {
2120 buf.append("float_val is NULL and ");
2121 }
2122 else{
2123 buf.append("float_val=? and ");
2124 __count++;
2125 }
2126 }
2127 if (bean.isModified_double_val()) {
2128 if (bean.isModifiedSetNull_double_val()) {
2129 buf.append("double_val is NULL and ");
2130 }
2131 else{
2132 buf.append("double_val=? and ");
2133 __count++;
2134 }
2135 }
2136 if (bean.isModified_numeric_val()) {
2137 if (bean.get_numeric_val() == null) {
2138 buf.append("numeric_val is NULL and ");
2139 }
2140 else{
2141 buf.append("numeric_val=? and ");
2142 __count++;
2143 }
2144 }
2145 if (bean.isModified_char_val()) {
2146 if (bean.get_char_val() == null) {
2147 buf.append("char_val is NULL and ");
2148 }
2149 else{
2150 buf.append("char_val=? and ");
2151 __count++;
2152 }
2153 }
2154 if (bean.isModified_varchar_val()) {
2155 if (bean.get_varchar_val() == null) {
2156 buf.append("varchar_val is NULL and ");
2157 }
2158 else{
2159 buf.append("varchar_val=? and ");
2160 __count++;
2161 }
2162 }
2163 if (bean.isModified_longvarchar_val()) {
2164 if (bean.get_longvarchar_val() == null) {
2165 buf.append("longvarchar_val is NULL and ");
2166 }
2167 else{
2168 buf.append("longvarchar_val=? and ");
2169 __count++;
2170 }
2171 }
2172 if (bean.isModified_date_val()) {
2173 if (bean.get_date_val() == null) {
2174 buf.append("date_val is NULL and ");
2175 }
2176 else{
2177 buf.append("date_val=? and ");
2178 __count++;
2179 }
2180 }
2181 if (bean.isModified_time_val()) {
2182 if (bean.get_time_val() == null) {
2183 buf.append("time_val is NULL and ");
2184 }
2185 else{
2186 buf.append("time_val=? and ");
2187 __count++;
2188 }
2189 }
2190 if (bean.isModified_timestamp_val()) {
2191 if (bean.get_timestamp_val() == null) {
2192 buf.append("timestamp_val is NULL and ");
2193 }
2194 else{
2195 buf.append("timestamp_val=? and ");
2196 __count++;
2197 }
2198 }
2199 if (bean.isModified_bit_val()) {
2200 if (bean.get_bit_val() == null) {
2201 buf.append("bit_val is NULL and ");
2202 }
2203 else{
2204 buf.append("bit_val=? and ");
2205 __count++;
2206 }
2207 }
2208 if (bean.isModified_array_val()) {
2209 if (bean.get_array_val() == null) {
2210 buf.append("array_val is NULL and ");
2211 }
2212 else{
2213 buf.append("array_val=? and ");
2214 __count++;
2215 }
2216 }
2217 if (bean.isModified_boolean_val()) {
2218 if (bean.get_boolean_val() == null) {
2219 buf.append("boolean_val is NULL and ");
2220 }
2221 else{
2222 buf.append("boolean_val=? and ");
2223 __count++;
2224 }
2225 }
2226 if (bean.isModified_varbinary_val()) {
2227 if (bean.get_varbinary_val() == null) {
2228 buf.append("varbinary_val is NULL and ");
2229 }
2230 else{
2231 buf.append("varbinary_val=? and ");
2232 __count++;
2233 }
2234 }
2235 if (bean.isModified_json_val()) {
2236 if (bean.get_json_val() == null) {
2237 buf.append("json_val is NULL and ");
2238 }
2239 else{
2240 buf.append("json_val=? and ");
2241 __count++;
2242 }
2243 }
2244 if (bean.isModified_jsonb_val()) {
2245 if (bean.get_jsonb_val() == null) {
2246 buf.append("jsonb_val is NULL and ");
2247 }
2248 else{
2249 buf.append("jsonb_val=? and ");
2250 __count++;
2251 }
2252 }
2253 buf.setLength(buf.length() - 4);
2254 if (__count == 0) {
2255 throw new ValidateException("No non-PrimaryKey column was modified/set in this bean. You must set at least one such column. To delete by the Primary key, use the deleteByKey method instead.");
2256 }
2257 if (clause != null) {
2258 buf.append(" ");
2259 buf.append(clause);
2260 }
2261
2262 final String getUsingPKStmt = buf.toString();
2263 PreparedStatement ps = prepareStatement(con, getUsingPKStmt);
2264 int pos = 0;
2265 if (bean.isModified_smallint_val()) {
2266 if (bean.isModifiedSetNull_smallint_val()) {
2267 /* no value to set here, uses [xxx IS NULL] syntax*/
2268 }
2269 else{
2270 pos++;
2271 short smallint_val = bean.get_smallint_val();
2272 ps.setShort(pos, smallint_val);
2273 }
2274 }
2275 if (bean.isModified_int_val()) {
2276 pos++;
2277 int int_val = bean.get_int_val();
2278 ps.setInt(pos, int_val);
2279 }
2280 if (bean.isModified_bigint_val()) {
2281 if (bean.isModifiedSetNull_bigint_val()) {
2282 /* no value to set here, uses [xxx IS NULL] syntax*/
2283 }
2284 else{
2285 pos++;
2286 long bigint_val = bean.get_bigint_val();
2287 ps.setLong(pos, bigint_val);
2288 }
2289 }
2290 if (bean.isModified_float_val()) {
2291 if (bean.isModifiedSetNull_float_val()) {
2292 /* no value to set here, uses [xxx IS NULL] syntax*/
2293 }
2294 else{
2295 pos++;
2296 float float_val = bean.get_float_val();
2297 ps.setFloat(pos, float_val);
2298 }
2299 }
2300 if (bean.isModified_double_val()) {
2301 if (bean.isModifiedSetNull_double_val()) {
2302 /* no value to set here, uses [xxx IS NULL] syntax*/
2303 }
2304 else{
2305 pos++;
2306 double double_val = bean.get_double_val();
2307 ps.setDouble(pos, double_val);
2308 }
2309 }
2310 if (bean.isModified_numeric_val()) {
2311 if (bean.get_numeric_val() == null) {
2312 /* no value to set here, uses [xxx IS NULL] syntax*/
2313 }
2314 else{
2315 pos++;
2316 BigDecimal numeric_val = bean.get_numeric_val();
2317 ps.setBigDecimal(pos, numeric_val);
2318 }
2319 }
2320 if (bean.isModified_char_val()) {
2321 if (bean.get_char_val() == null) {
2322 /* no value to set here, uses [xxx IS NULL] syntax*/
2323 }
2324 else{
2325 pos++;
2326 String char_val = bean.get_char_val();
2327 ps.setString(pos, char_val);
2328 }
2329 }
2330 if (bean.isModified_varchar_val()) {
2331 if (bean.get_varchar_val() == null) {
2332 /* no value to set here, uses [xxx IS NULL] syntax*/
2333 }
2334 else{
2335 pos++;
2336 String varchar_val = bean.get_varchar_val();
2337 ps.setString(pos, varchar_val);
2338 }
2339 }
2340 if (bean.isModified_longvarchar_val()) {
2341 if (bean.get_longvarchar_val() == null) {
2342 /* no value to set here, uses [xxx IS NULL] syntax*/
2343 }
2344 else{
2345 pos++;
2346 String longvarchar_val = bean.get_longvarchar_val();
2347 ps.setString(pos, longvarchar_val);
2348 }
2349 }
2350 if (bean.isModified_date_val()) {
2351 if (bean.get_date_val() == null) {
2352 /* no value to set here, uses [xxx IS NULL] syntax*/
2353 }
2354 else{
2355 pos++;
2356 java.sql.Date date_val = bean.get_date_val();
2357 ps.setDate(pos, date_val);
2358 }
2359 }
2360 if (bean.isModified_time_val()) {
2361 if (bean.get_time_val() == null) {
2362 /* no value to set here, uses [xxx IS NULL] syntax*/
2363 }
2364 else{
2365 pos++;
2366 Time time_val = bean.get_time_val();
2367 ps.setTime(pos, time_val);
2368 }
2369 }
2370 if (bean.isModified_timestamp_val()) {
2371 if (bean.get_timestamp_val() == null) {
2372 /* no value to set here, uses [xxx IS NULL] syntax*/
2373 }
2374 else{
2375 pos++;
2376 Timestamp timestamp_val = bean.get_timestamp_val();
2377 ps.setTimestamp(pos, timestamp_val);
2378 }
2379 }
2380 if (bean.isModified_bit_val()) {
2381 if (bean.get_bit_val() == null) {
2382 /* no value to set here, uses [xxx IS NULL] syntax*/
2383 }
2384 else{
2385 pos++;
2386 Boolean bit_val = bean.get_bit_val();
2387 ps.setObject(pos, bit_val);
2388 }
2389 }
2390 if (bean.isModified_array_val()) {
2391 if (bean.get_array_val() == null) {
2392 /* no value to set here, uses [xxx IS NULL] syntax*/
2393 }
2394 else{
2395 pos++;
2396 java.sql.Array array_val = bean.get_array_val();
2397 ps.setArray(pos, array_val);
2398 }
2399 }
2400 if (bean.isModified_boolean_val()) {
2401 if (bean.get_boolean_val() == null) {
2402 /* no value to set here, uses [xxx IS NULL] syntax*/
2403 }
2404 else{
2405 pos++;
2406 Boolean boolean_val = bean.get_boolean_val();
2407 ps.setObject(pos, boolean_val);
2408 }
2409 }
2410 if (bean.isModified_varbinary_val()) {
2411 if (bean.get_varbinary_val() == null) {
2412 /* no value to set here, uses [xxx IS NULL] syntax*/
2413 }
2414 else{
2415 pos++;
2416 byte[] varbinary_val = bean.get_varbinary_val();
2417 ps.setBytes(pos, varbinary_val);
2418 }
2419 }
2420 if (bean.isModified_json_val()) {
2421 if (bean.get_json_val() == null) {
2422 /* no value to set here, uses [xxx IS NULL] syntax*/
2423 }
2424 else{
2425 pos++;
2426 String json_val = bean.get_json_val();
2427 ps.setObject(pos, json_val, java.sql.Types.OTHER);
2428 }
2429 }
2430 if (bean.isModified_jsonb_val()) {
2431 if (bean.get_jsonb_val() == null) {
2432 /* no value to set here, uses [xxx IS NULL] syntax*/
2433 }
2434 else{
2435 pos++;
2436 String jsonb_val = bean.get_jsonb_val();
2437 ps.setObject(pos, jsonb_val, java.sql.Types.OTHER);
2438 }
2439 }
2440 log.bug("Query to run: ", ps);
2441 List list = new ArrayList();
2442 int result = ps.executeUpdate();
2443 return result;
2444 }
2445
2446 /**
2447 Convenience method that invokes {@link getUsing(Connection, alltypes, String) getUsing} with an empty <i><tt>clause</tt></i> parameter.*/
2448 public static int deleteUsing(final Connection con, final alltypes bean) throws ValidateException, SQLException
2449 {
2450 return deleteUsing(con, bean, null);
2451 }
2452
2453 /**
2454 Deletes the rows with the specified where clause. <p><b>The
2455 where clause is sent as-is to the database and SQL injection
2456 attacks are possible if it is created as-is from a untrusted
2457 source.</b>
2458 (note: the string <tt>"WHERE"</tt> does <b>not</b> have to be
2459 specified in the clause. It is added automatically by this method).
2460
2461 @return the number of rows deleted by the database
2462 */
2463 public static int deleteWhere(final Connection con, final String where) throws SQLException {
2464 __deletewhere_called++;
2465 Argcheck.notnull(where, "the where parameter was null (and should not be null)");
2466 final String stmt_string = "DELETE from alltypes WHERE " + where ;
2467 Statement stmt = con.createStatement();
2468 log.bug("Query to run: ", stmt_string);
2469 final int result = stmt.executeUpdate(stmt_string);
2470 return result;
2471 }
2472
2473 private final static String countStmt = "SELECT count(*) from alltypes";
2474 /**
2475 Returns the count of all rows in the table. <p><b>Note</b>: This may
2476 be an expensive operation in MVCC databases like PostgresQL, Oracle and
2477 others, where an entire non-optimized table scan <i>may</i> be
2478 required -- hence speed will typically be O(n). However, on Postgres (for
2479 example), this is still very fast for small values of n (on a
2480 mid-level test machine) as of 2004, counting 4k records was about
2481 15 milli-seconds(ms); this scaled almost linearly, so count(*) for 16k records was
2482 about 70 ms, 65k records was about 370 ms, 524k records was about
2483 2000 ms and 1 million records was about 4000 ms. Results will vary
2484 on your machine and database but the general O(n) principle will
2485 remain the same.
2486 */
2487 public static int count(final Connection con) throws SQLException
2488 {
2489 __count_called++;
2490 int __count = -1;
2491 final Statement stmt = con.createStatement();
2492 final ResultSet rs = stmt.executeQuery(countStmt);
2493 if (rs.next())
2494 {
2495 __count = rs.getInt(1);
2496 }
2497 else { //rs returned no count, which should never happen
2498 throw new DBOException("The COUNT query [" + countStmt + "] returned no rows. [Should have returned 1 row exactly] ");
2499 }
2500 stmt.close();
2501 return __count;
2502 }
2503
2504 /**
2505 Returns the count of rows in the table using the specified <tt>where</tt> clause.
2506 (note: the string <tt>"WHERE"</tt> does <b>not</b> have to be
2507 specified in the clause. It is added automatically by this method).
2508
2509 @throws IllegalArgumentException if the where paramater was null
2510 */
2511 public static int countWhere(final Connection con, final String where) throws SQLException
2512 {
2513 __countwhere_called++;
2514 Argcheck.notnull(where, "the where parameter was null");
2515 int __count = -1;
2516 final String countWhereStmt = "SELECT count(*) from alltypes WHERE " + where;
2517 Statement stmt = con.createStatement();
2518 log.bug("Query to run: ", stmt, " ", countWhereStmt);
2519 ResultSet rs = stmt.executeQuery(countWhereStmt);
2520 if (rs.next())
2521 {
2522 __count = rs.getInt(1);
2523 }
2524 else { //rs returned no count, which should never happen
2525 throw new DBOException("The COUNT query [" + countWhereStmt + "] returned no rows. [Should have returned 1 row exactly] ");
2526 }
2527 stmt.close();
2528 return __count;
2529 }
2530
2531 /**
2532 Returns the rows count by querying the table with the contents of the
2533 specified instance of <tt>alltypes</tt> As many fields in <tt>alltypes</tt> can be set as needed and the
2534 values of all set fields (including fields explicitly set to
2535 <tt>null</tt>) are then used to perform the query. If the primary
2536 key(s) are known then one can also use the {@link #exists} method to
2537 see if that row exists in the database.
2538 <p>
2539 This method is often convenient/safer than the {@link #countWhere
2540 countWhere} method (because the <tt>countWhere</tt> method takes an
2541 arbitrary query string which has to be properly escaped by the
2542 user).
2543 <p>Essentially, this method is a more convenient way to use a
2544 PreparedStatement (with parameters set to fields that are set in
2545 this object). Using PreparedStatements directly is also perfectly
2546 fine. For example, the following two are equivalent. <p>
2547 Using a PreparedStatement:
2548 <blockquote><pre>
2549 String foo = "select <i>count(*)</i> from table_foo where x = ? and y = ?";
2550 PreparedStatement ps = con.prepareStatement(foo);
2551 ps.setString(1, "somevalue");
2552 ps.setString(2, "othervalue");
2553 ResultSet rs = ps.executeUpdate();
2554 rs.next();
2555 int count = rs.getInt(1);
2556 </pre> </blockquote>
2557
2558 Using this method:
2559 <blockquote><pre>
2560 table_foo proto = new table_foo();
2561 proto.set_x("somevalue"); //compile time safety
2562 proto.set_y("othervalue"); //compile time safety
2563 int count = table_fooMgr.<font color=blue>countUsing</font>(proto);
2564 </pre> </blockquote>
2565 The clause is optional. Specify <tt>null</tt> to not use it at all.
2566 If the clause is specified, do <font size='+1'><b>NOT</b></font> include the word <tt>WHERE</tt>.
2567 */
2568 public static int countUsing(final Connection con, final alltypes bean, final String clause) throws ValidateException, SQLException
2569 {
2570 __countusing_called++;
2571 Argcheck.notnull(bean, "the bean parameter was null (and should not be null)"); if (! bean.isModified()) {
2572 throw new ValidateException("bean=" + bean + " not modified, ignoring query");
2573 }
2574
2575 int __count = 0;
2576 final StringBuilder buf = new StringBuilder(512);
2577 buf.append("SELECT count(*) from alltypes WHERE ");
2578 if (bean.isModified_id()) {
2579 buf.append("id=? and ");
2580 __count++;
2581 }
2582 if (bean.isModified_smallint_val()) {
2583 if (bean.isModifiedSetNull_smallint_val()) {
2584 buf.append("smallint_val is NULL and ");
2585 }
2586 else{
2587 buf.append("smallint_val=? and ");
2588 __count++;
2589 }
2590 }
2591 if (bean.isModified_int_val()) {
2592 buf.append("int_val=? and ");
2593 __count++;
2594 }
2595 if (bean.isModified_bigint_val()) {
2596 if (bean.isModifiedSetNull_bigint_val()) {
2597 buf.append("bigint_val is NULL and ");
2598 }
2599 else{
2600 buf.append("bigint_val=? and ");
2601 __count++;
2602 }
2603 }
2604 if (bean.isModified_float_val()) {
2605 if (bean.isModifiedSetNull_float_val()) {
2606 buf.append("float_val is NULL and ");
2607 }
2608 else{
2609 buf.append("float_val=? and ");
2610 __count++;
2611 }
2612 }
2613 if (bean.isModified_double_val()) {
2614 if (bean.isModifiedSetNull_double_val()) {
2615 buf.append("double_val is NULL and ");
2616 }
2617 else{
2618 buf.append("double_val=? and ");
2619 __count++;
2620 }
2621 }
2622 if (bean.isModified_numeric_val()) {
2623 if (bean.get_numeric_val() == null) {
2624 buf.append("numeric_val is NULL and ");
2625 }
2626 else{
2627 buf.append("numeric_val=? and ");
2628 __count++;
2629 }
2630 }
2631 if (bean.isModified_char_val()) {
2632 if (bean.get_char_val() == null) {
2633 buf.append("char_val is NULL and ");
2634 }
2635 else{
2636 buf.append("char_val=? and ");
2637 __count++;
2638 }
2639 }
2640 if (bean.isModified_varchar_val()) {
2641 if (bean.get_varchar_val() == null) {
2642 buf.append("varchar_val is NULL and ");
2643 }
2644 else{
2645 buf.append("varchar_val=? and ");
2646 __count++;
2647 }
2648 }
2649 if (bean.isModified_longvarchar_val()) {
2650 if (bean.get_longvarchar_val() == null) {
2651 buf.append("longvarchar_val is NULL and ");
2652 }
2653 else{
2654 buf.append("longvarchar_val=? and ");
2655 __count++;
2656 }
2657 }
2658 if (bean.isModified_date_val()) {
2659 if (bean.get_date_val() == null) {
2660 buf.append("date_val is NULL and ");
2661 }
2662 else{
2663 buf.append("date_val=? and ");
2664 __count++;
2665 }
2666 }
2667 if (bean.isModified_time_val()) {
2668 if (bean.get_time_val() == null) {
2669 buf.append("time_val is NULL and ");
2670 }
2671 else{
2672 buf.append("time_val=? and ");
2673 __count++;
2674 }
2675 }
2676 if (bean.isModified_timestamp_val()) {
2677 if (bean.get_timestamp_val() == null) {
2678 buf.append("timestamp_val is NULL and ");
2679 }
2680 else{
2681 buf.append("timestamp_val=? and ");
2682 __count++;
2683 }
2684 }
2685 if (bean.isModified_bit_val()) {
2686 if (bean.get_bit_val() == null) {
2687 buf.append("bit_val is NULL and ");
2688 }
2689 else{
2690 buf.append("bit_val=? and ");
2691 __count++;
2692 }
2693 }
2694 if (bean.isModified_array_val()) {
2695 if (bean.get_array_val() == null) {
2696 buf.append("array_val is NULL and ");
2697 }
2698 else{
2699 buf.append("array_val=? and ");
2700 __count++;
2701 }
2702 }
2703 if (bean.isModified_boolean_val()) {
2704 if (bean.get_boolean_val() == null) {
2705 buf.append("boolean_val is NULL and ");
2706 }
2707 else{
2708 buf.append("boolean_val=? and ");
2709 __count++;
2710 }
2711 }
2712 if (bean.isModified_varbinary_val()) {
2713 if (bean.get_varbinary_val() == null) {
2714 buf.append("varbinary_val is NULL and ");
2715 }
2716 else{
2717 buf.append("varbinary_val=? and ");
2718 __count++;
2719 }
2720 }
2721 if (bean.isModified_json_val()) {
2722 if (bean.get_json_val() == null) {
2723 buf.append("json_val is NULL and ");
2724 }
2725 else{
2726 buf.append("json_val=? and ");
2727 __count++;
2728 }
2729 }
2730 if (bean.isModified_jsonb_val()) {
2731 if (bean.get_jsonb_val() == null) {
2732 buf.append("jsonb_val is NULL and ");
2733 }
2734 else{
2735 buf.append("jsonb_val=? and ");
2736 __count++;
2737 }
2738 }
2739
2740 buf.setLength(buf.length() - 4);
2741 if (clause != null) {
2742 buf.append(" ");
2743 buf.append(clause);
2744 }
2745
2746 final String countUsingStmt = buf.toString();
2747 PreparedStatement ps = prepareStatement(con, countUsingStmt);
2748 int pos = 0;
2749 if (bean.isModified_id()) {
2750 pos++;
2751 int id = bean.get_id();
2752 ps.setInt(pos, id);
2753 }
2754 if (bean.isModified_smallint_val()) {
2755 if (bean.isModifiedSetNull_smallint_val()) {
2756 /* no value to set here, uses [xxx IS NULL] syntax*/
2757 }
2758 else{
2759 pos++;
2760 short smallint_val = bean.get_smallint_val();
2761 ps.setShort(pos, smallint_val);
2762 }
2763 }
2764 if (bean.isModified_int_val()) {
2765 pos++;
2766 int int_val = bean.get_int_val();
2767 ps.setInt(pos, int_val);
2768 }
2769 if (bean.isModified_bigint_val()) {
2770 if (bean.isModifiedSetNull_bigint_val()) {
2771 /* no value to set here, uses [xxx IS NULL] syntax*/
2772 }
2773 else{
2774 pos++;
2775 long bigint_val = bean.get_bigint_val();
2776 ps.setLong(pos, bigint_val);
2777 }
2778 }
2779 if (bean.isModified_float_val()) {
2780 if (bean.isModifiedSetNull_float_val()) {
2781 /* no value to set here, uses [xxx IS NULL] syntax*/
2782 }
2783 else{
2784 pos++;
2785 float float_val = bean.get_float_val();
2786 ps.setFloat(pos, float_val);
2787 }
2788 }
2789 if (bean.isModified_double_val()) {
2790 if (bean.isModifiedSetNull_double_val()) {
2791 /* no value to set here, uses [xxx IS NULL] syntax*/
2792 }
2793 else{
2794 pos++;
2795 double double_val = bean.get_double_val();
2796 ps.setDouble(pos, double_val);
2797 }
2798 }
2799 if (bean.isModified_numeric_val()) {
2800 if (bean.get_numeric_val() == null) {
2801 /* no value to set here, uses [xxx IS NULL] syntax*/
2802 }
2803 else{
2804 pos++;
2805 BigDecimal numeric_val = bean.get_numeric_val();
2806 ps.setBigDecimal(pos, numeric_val);
2807 }
2808 }
2809 if (bean.isModified_char_val()) {
2810 if (bean.get_char_val() == null) {
2811 /* no value to set here, uses [xxx IS NULL] syntax*/
2812 }
2813 else{
2814 pos++;
2815 String char_val = bean.get_char_val();
2816 ps.setString(pos, char_val);
2817 }
2818 }
2819 if (bean.isModified_varchar_val()) {
2820 if (bean.get_varchar_val() == null) {
2821 /* no value to set here, uses [xxx IS NULL] syntax*/
2822 }
2823 else{
2824 pos++;
2825 String varchar_val = bean.get_varchar_val();
2826 ps.setString(pos, varchar_val);
2827 }
2828 }
2829 if (bean.isModified_longvarchar_val()) {
2830 if (bean.get_longvarchar_val() == null) {
2831 /* no value to set here, uses [xxx IS NULL] syntax*/
2832 }
2833 else{
2834 pos++;
2835 String longvarchar_val = bean.get_longvarchar_val();
2836 ps.setString(pos, longvarchar_val);
2837 }
2838 }
2839 if (bean.isModified_date_val()) {
2840 if (bean.get_date_val() == null) {
2841 /* no value to set here, uses [xxx IS NULL] syntax*/
2842 }
2843 else{
2844 pos++;
2845 java.sql.Date date_val = bean.get_date_val();
2846 ps.setDate(pos, date_val);
2847 }
2848 }
2849 if (bean.isModified_time_val()) {
2850 if (bean.get_time_val() == null) {
2851 /* no value to set here, uses [xxx IS NULL] syntax*/
2852 }
2853 else{
2854 pos++;
2855 Time time_val = bean.get_time_val();
2856 ps.setTime(pos, time_val);
2857 }
2858 }
2859 if (bean.isModified_timestamp_val()) {
2860 if (bean.get_timestamp_val() == null) {
2861 /* no value to set here, uses [xxx IS NULL] syntax*/
2862 }
2863 else{
2864 pos++;
2865 Timestamp timestamp_val = bean.get_timestamp_val();
2866 ps.setTimestamp(pos, timestamp_val);
2867 }
2868 }
2869 if (bean.isModified_bit_val()) {
2870 if (bean.get_bit_val() == null) {
2871 /* no value to set here, uses [xxx IS NULL] syntax*/
2872 }
2873 else{
2874 pos++;
2875 Boolean bit_val = bean.get_bit_val();
2876 ps.setObject(pos, bit_val);
2877 }
2878 }
2879 if (bean.isModified_array_val()) {
2880 if (bean.get_array_val() == null) {
2881 /* no value to set here, uses [xxx IS NULL] syntax*/
2882 }
2883 else{
2884 pos++;
2885 java.sql.Array array_val = bean.get_array_val();
2886 ps.setArray(pos, array_val);
2887 }
2888 }
2889 if (bean.isModified_boolean_val()) {
2890 if (bean.get_boolean_val() == null) {
2891 /* no value to set here, uses [xxx IS NULL] syntax*/
2892 }
2893 else{
2894 pos++;
2895 Boolean boolean_val = bean.get_boolean_val();
2896 ps.setObject(pos, boolean_val);
2897 }
2898 }
2899 if (bean.isModified_varbinary_val()) {
2900 if (bean.get_varbinary_val() == null) {
2901 /* no value to set here, uses [xxx IS NULL] syntax*/
2902 }
2903 else{
2904 pos++;
2905 byte[] varbinary_val = bean.get_varbinary_val();
2906 ps.setBytes(pos, varbinary_val);
2907 }
2908 }
2909 if (bean.isModified_json_val()) {
2910 if (bean.get_json_val() == null) {
2911 /* no value to set here, uses [xxx IS NULL] syntax*/
2912 }
2913 else{
2914 pos++;
2915 String json_val = bean.get_json_val();
2916 ps.setObject(pos, json_val, java.sql.Types.OTHER);
2917 }
2918 }
2919 if (bean.isModified_jsonb_val()) {
2920 if (bean.get_jsonb_val() == null) {
2921 /* no value to set here, uses [xxx IS NULL] syntax*/
2922 }
2923 else{
2924 pos++;
2925 String jsonb_val = bean.get_jsonb_val();
2926 ps.setObject(pos, jsonb_val, java.sql.Types.OTHER);
2927 }
2928 }
2929 log.bug("Query to run: ", ps);
2930 ResultSet rs = ps.executeQuery();
2931 if (! rs.next()) {
2932 throw new DBOException("The COUNT query [" + countUsingStmt + "] returned no rows. [Should have returned 1 row exactly] ");
2933 }
2934 int rows = rs.getInt(1);
2935 rs.close();
2936 return rows;
2937 }
2938
2939 /**
2940 Convenience method that invokes {@link getUsing(Connection, alltypes, String) getUsing} with an empty <i><tt>clause</tt></i> parameter.*/
2941 public static int countUsing(final Connection con, final alltypes bean) throws ValidateException, SQLException
2942 {
2943 return countUsing(con, bean, null);
2944 }
2945
2946 static private final String existsStmt = "SELECT count(*) from alltypes WHERE id=?";
2947 /**
2948 Returns <tt>true</tt> if a row with the specified primary keys exists, <tt>false</tt> otherwise.
2949 <p>This method uses a prepared statement and is safe from SQL injection attacks
2950 */
2951 public static boolean exists(final Connection con, int id) throws SQLException
2952 {
2953 __exists_called++;
2954 PreparedStatement ps = prepareStatement(con, existsStmt);
2955 ps.setInt(1, id);
2956 log.bug("Query to run: ", ps);
2957 ResultSet rs = ps.executeQuery();
2958 int __count = -1;
2959 if (rs.next())
2960 {
2961 __count = rs.getInt(1);
2962 }
2963 else { //rs returned no count, which should never happen
2964 throw new DBOException("The COUNT query [" + existsStmt + "] returned no rows. [Should have returned 1 row exactly] ");
2965 }
2966 rs.close();
2967 return (__count > 0); //exists if __count > 0
2968 }
2969 /**
2970 A thin wrapper around {@link getUsing(Connection,alltypes) getUsing}
2971 that returns <tt>false</tt> if no rows are returned, <tt>true</tt> otherwise.
2972 */
2973 public static boolean existsUsing(final Connection con, final alltypes bean) throws ValidateException, SQLException
2974 {
2975 final List list = getUsing(con, bean, null);
2976 return (list.size() > 0);
2977 }
2978
2979 /**
2980 Returns a prepared statement given it's variable name.
2981
2982 Essentially speeds up the creation of prepared statements perhaps
2983 using a per connection cache -- which makes sense for pooled
2984 connections since they are not closed but returned to the pool
2985 and hence don't need to "prepare" statements every time (the
2986 prepareStatement call is seperate from actually filling in the
2987 placeholders in a already created prepared statement -- which
2988 does need to be done every time). <p>
2989 Prepared statements are unique per connection, so multiple threads
2990 using different connections won't stomp over each other's prepared
2991 statements. Multiple threads using the SAME connection will cause
2992 bizarre errors but multiple threads won't get the same connection
2993 from the connection manager -- ever :-), so that should never happen.
2994 */
2995 private static final PreparedStatement prepareStatement ( final Connection con, final String sql) throws SQLException
2996 {
2997 if (! (con instanceof fc.jdbc.PooledConnection) ) {
2998 return con.prepareStatement(sql);
2999 }
3000 final PooledConnection pc = (PooledConnection) con;
3001 return pc.getCachedPreparedStatement(sql);
3002 }
3003
3004 private static final void checkDiscarded(final DBO bean) throws DBOException
3005 {
3006 if (bean.isDiscarded()) {
3007 throw new DBOException("===== Attempt to save a discarded object === " + bean);
3008 }
3009 }
3010
3011 private static final java.util.Date __loadDate = new java.util.Date();
3012 /** Returns usage statistics for this class */
3013 public static String stats()
3014 {
3015 //locally created _numberFormat for thread safety
3016 final java.text.NumberFormat _numberFormat = java.text.NumberFormat.getInstance();
3017 final String nl = fc.io.IOUtil.LINE_SEP;
3018 StringBuffer buf = new StringBuffer(256);
3019 buf.append("Class Name: [alltypesMgr]; Class loaded on: ");
3020 buf.append(__loadDate);
3021 buf.append(nl);
3022 buf.append("---- Start Usage Statistics ----").append(nl);
3023
3024 ByteArrayOutputStream out = new ByteArrayOutputStream(512);
3025 TablePrinter.PrintConfig config = new TablePrinter.PrintConfig();
3026 config.setPrintBorders(false);
3027 config.setCellSpacing(1);
3028 config.setCellPadding(0);
3029 config.setAutoFit(true);
3030 TablePrinter p = new TablePrinter(2, new PrintStream(out), config);
3031 p.startTable();
3032
3033 p.startRow();
3034 p.printCell("Method");
3035 p.printCell("# times called");
3036 p.endRow();
3037
3038 p.startRow();
3039 p.printCell("getAll()");
3040 p.printCell(_numberFormat.format(__getall_called));
3041 p.endRow();
3042
3043 p.startRow();
3044 p.printCell("getLimited()");
3045 p.printCell(_numberFormat.format(__getlimited_called));
3046 p.endRow();
3047
3048 p.startRow();
3049 p.printCell("getByKey()");
3050 p.printCell(_numberFormat.format(__getbykey_called));
3051 p.endRow();
3052
3053 p.startRow();
3054 p.printCell("getWhere()");
3055 p.printCell(_numberFormat.format(__getwhere_called));
3056 p.endRow();
3057
3058 p.startRow();
3059 p.printCell("getUsing()");
3060 p.printCell(_numberFormat.format(__getusing_called));
3061 p.endRow();
3062
3063 p.startRow();
3064 p.printCell("getUsing(prepared_stmt)");
3065 p.printCell(_numberFormat.format(__getusing_ps_called));
3066 p.endRow();
3067
3068 p.startRow();
3069 p.printCell("getFromRS()");
3070 p.printCell(_numberFormat.format(__getfromrs_called));
3071 p.endRow();
3072
3073 p.startRow();
3074 p.printCell("save()");
3075 p.printCell(_numberFormat.format(__save_called));
3076 p.endRow();
3077
3078 p.startRow();
3079 p.printCell("delete()");
3080 p.printCell(_numberFormat.format(__delete_called));
3081 p.endRow();
3082
3083 p.startRow();
3084 p.printCell("deleteByKey()");
3085 p.printCell(_numberFormat.format(__deletebykey_called));
3086 p.endRow();
3087
3088 p.startRow();
3089 p.printCell("deleteWhere()");
3090 p.printCell(_numberFormat.format(__deletewhere_called));
3091 p.endRow();
3092
3093 p.startRow();
3094 p.printCell("deleteUsing()");
3095 p.printCell(_numberFormat.format(__deleteusing_called));
3096 p.endRow();
3097
3098 p.startRow();
3099 p.printCell("count()");
3100 p.printCell(_numberFormat.format(__count_called));
3101 p.endRow();
3102
3103 p.startRow();
3104 p.printCell("countWhere()");
3105 p.printCell(_numberFormat.format(__countwhere_called));
3106 p.endRow();
3107
3108 p.startRow();
3109 p.printCell("countUsing()");
3110 p.printCell(_numberFormat.format(__countusing_called));
3111 p.endRow();
3112
3113 p.startRow();
3114 p.printCell("exists()");
3115 p.printCell(_numberFormat.format(__exists_called));
3116 p.endRow();
3117
3118 p.endTable();
3119 buf.append(out.toString());
3120 return buf.toString();
3121 }
3122
3123 public String toString()
3124 {
3125 return getClass().getName() + " [call stats() for more info]";
3126 }
3127
3128 // ================ Validation ====================
3129
3130 /**
3131 Creates and attaches validators for all the fields in the
3132 specified {@link fc.web.forms.Form}. These fields should
3133 <i>have the same name</i> in the form as in {@link alltypes}. If this is not the case, then the then the differences can be specifed
3134 as follows. <p>
3135 <dl>
3136 <dt>with a prefix</dt>
3137 <dd><tt>(prefix + alltypes column)</tt> should equal <tt>form fieldname</tt></dd>
3138 <dt>with a suffix</dt>
3139 <dd><tt>(alltypes column + suffix)</tt> should equal <tt>form fieldname</tt></dd>
3140 <dt>with both a prefix/suffix</dt>
3141 <dd><tt>(prefix + alltypes + suffix)</tt> should equal <tt>form fieldname</tt></dd>
3142 <dt>with a arbitrary map</dt>
3143 <dd>[key] <tt>alltypes column</tt> -> [value] <tt>form fieldname</tt>
3144 <u>If a map is specified, then the prefix/suffix are not used.</u>
3145 </dd>
3146 </dl>
3147 <p>These validators are for database constraints such as <i>nullability</i> & <i>column length</i>.
3148 These validators save a lot of grunt-work in adding such schema
3149 constraints to the front-end {@link fc.web.forms.Form}. <p><b>However, <i>business and
3150 other validation constraints</i> still need to be manually added to
3151 the application code/front-end forms as/when needed</b>.
3152 <p>
3153
3154 The following table shows the kind of validators added by this method
3155 <table border=1 width=90%>
3156 <tr bgcolor='#CCCCCC'>
3157 <td>Database SQL Type</td>
3158 <td><b>Nullable</b>validator</td>
3159 <td><b>Length</b> validator</td>
3160 <td><b>Digits only</b> input validator ({@link VText#allowIntegersOnly})</td>
3161 </tr>
3162 <tr>
3163 <td><tt>CHAR</tt>, <tt>VARCHAR</tt></td>
3164 <td>Yes (maximum length constraint).<br><font size='-1' color=red>This
3165 only applies to form fields that are subclasses of {@link
3166 fc.web.forms.MaxSizable} </font></td>
3167 <td>-NO-</td>
3168 </tr>
3169 <tr>
3170 <td><tt>TINYINT, MEDIUMINT, INT, BIGINT (integral types)</tt></td>
3171 <td>Yes</td>
3172 <td>-NO-</td>
3173 <td>Yes to integer columns displayed using form fields that are subclasses of {@link fc.web.forms.AbstractText}<br> Note: <b>not</b> added non-<i>integral</i> number types such as <tt>FLOAT, REAL, DOUBLE, NUMERIC/DECIMAL</tt></td>
3174 </tr>
3175 <tr>
3176 <td>All other SQL types</td>
3177 <td>Yes</td>
3178 <td>-NO-</td>
3179 </tr>
3180 </table>
3181 <p>Automatic validators are very useful but can be very tricky to understand. It is
3182 suggested to invoke this method, print the form using it's <tt>toString</tt>
3183 method and then examine the output to see what validators were added If those
3184 automatic validators are too little, too many or too hard to understand, <u>then
3185 simply enoough, do NOT invoke this method and simply add validators by
3186 hand</u>. In particular, do <i>not</i> add automatic validators for
3187 <b>tables</b> in which a row is optional but <i>if</i> some column is filled in
3188 the front end form, <i>then</i> all columns must be filled.
3189
3190 @param form the form containing fields (some or all) representing
3191 this and possible other tables. These field
3192 objects must have been added to the form prior
3193 to calling this method
3194 @param prefix an optional (null allowed) prefix to this table's column name with which the
3195 corresponding column was added to the form.
3196 A <tt>*</tt> specifies all possible prefixes
3197 @param suffix an optional suffix (null allowed) to this table's column name with which the
3198 corresponding column was added to the form.
3199 A <tt>*</tt> specifies all possible suffixes
3200 @param map an optional map (null allowed) that maps this table's column name with which the
3201 corresponding column was added to the form.
3202 [key] <tt>table's column_name</tt> -> [value] <tt>form's fieldname</tt>
3203 */
3204 public static void addValidators(final fc.web.forms.Form form, final String prefix, final String suffix, final Map map)
3205 {
3206 addValidators(form, prefix, suffix, map, false);
3207 }
3208
3209 private static void addValidators(fc.web.forms.Form form, String prefix, String suffix, final Map map, final boolean onlyOnFilled)
3210 {
3211 List list = null;
3212 Argcheck.notnull(form, "How can I add validators to the form when the form parameter was null ?");
3213 Field field = null;
3214 FieldValidator fv = null;
3215 String colname_in_form = null;
3216 //fields can be null if they are not being used in the html form
3217
3218 /** serial (INTEGER); PK=yes; Nullable=false; AutoInc=true; MaxSize=10 */
3219 list = getFieldFromForm(form, "id", prefix, suffix, map, false);
3220 if (list.size() > 0)
3221 { //add applicable automatic validators, empty if n/a
3222 for (int n = 0; n < list.size(); n++)
3223 {
3224 field = (Field) list.get(n);
3225 /* field is non-nullable but has a default value [nextval('alltypes_id_seq'::regclass)], skipping non-nullability validation */
3226
3227 /* database type for this field is integral */
3228 if (field instanceof AbstractText) {
3229 fv = new VText((AbstractText)field, "Error: Please enter only numbers in this field")
3230 .allowIntegersOnly();
3231 }
3232 }
3233 }
3234
3235 /** int2 (SMALLINT); Nullable=true; AutoInc=false; MaxSize=5 */
3236 list = getFieldFromForm(form, "smallint_val", prefix, suffix, map, true);
3237 if (list.size() > 0)
3238 { //add applicable automatic validators, empty if n/a
3239 for (int n = 0; n < list.size(); n++)
3240 {
3241 field = (Field) list.get(n);
3242 /* field is nullable, skipping non-nullability validation */
3243
3244 /* database type for this field is integral */
3245 if (field instanceof AbstractText) {
3246 fv = new VText((AbstractText)field, "Error: Please enter only numbers in this field")
3247 .allowIntegersOnly();
3248 }
3249 }
3250 }
3251
3252 /** int4 (INTEGER); Nullable=false; AutoInc=false; MaxSize=10 */
3253 list = getFieldFromForm(form, "int_val", prefix, suffix, map, true);
3254 if (list.size() > 0)
3255 { //add applicable automatic validators, empty if n/a
3256 for (int n = 0; n < list.size(); n++)
3257 {
3258 field = (Field) list.get(n);
3259 if (field instanceof Choice) {
3260 //choice fields are ignored because they can
3261 //mean false even when NOT selected/filled
3262 continue;
3263 }
3264 /* field is non-nullable */
3265 fv = new VFilled(field, "Error: Required field, please enter a value");
3266
3267 /* database type for this field is integral */
3268 if (field instanceof AbstractText) {
3269 fv = new VText((AbstractText)field, "Error: Please enter only numbers in this field")
3270 .allowIntegersOnly();
3271 }
3272 }
3273 }
3274
3275 /** int8 (BIGINT); Nullable=true; AutoInc=false; MaxSize=19 */
3276 list = getFieldFromForm(form, "bigint_val", prefix, suffix, map, true);
3277 if (list.size() > 0)
3278 { //add applicable automatic validators, empty if n/a
3279 for (int n = 0; n < list.size(); n++)
3280 {
3281 field = (Field) list.get(n);
3282 /* field is nullable, skipping non-nullability validation */
3283
3284 /* database type for this field is integral */
3285 if (field instanceof AbstractText) {
3286 fv = new VText((AbstractText)field, "Error: Please enter only numbers in this field")
3287 .allowIntegersOnly();
3288 }
3289 }
3290 }
3291
3292 /** float4 (REAL); Nullable=true; AutoInc=false; MaxSize=8 */
3293 list = getFieldFromForm(form, "float_val", prefix, suffix, map, true);
3294 if (list.size() > 0)
3295 { //add applicable automatic validators, empty if n/a
3296 for (int n = 0; n < list.size(); n++)
3297 {
3298 field = (Field) list.get(n);
3299 /* field is nullable, skipping non-nullability validation */
3300 }
3301 }
3302
3303 /** float8 (DOUBLE); Nullable=true; AutoInc=false; MaxSize=17 */
3304 list = getFieldFromForm(form, "double_val", prefix, suffix, map, true);
3305 if (list.size() > 0)
3306 { //add applicable automatic validators, empty if n/a
3307 for (int n = 0; n < list.size(); n++)
3308 {
3309 field = (Field) list.get(n);
3310 /* field is nullable, skipping non-nullability validation */
3311 }
3312 }
3313
3314 /** numeric (NUMERIC); Nullable=true; AutoInc=false; MaxSize=5 */
3315 list = getFieldFromForm(form, "numeric_val", prefix, suffix, map, true);
3316 if (list.size() > 0)
3317 { //add applicable automatic validators, empty if n/a
3318 for (int n = 0; n < list.size(); n++)
3319 {
3320 field = (Field) list.get(n);
3321 /* field is nullable, skipping non-nullability validation */
3322 }
3323 }
3324
3325 /** bpchar (CHAR); Nullable=true; AutoInc=false; MaxSize=10 */
3326 list = getFieldFromForm(form, "char_val", prefix, suffix, map, true);
3327 if (list.size() > 0)
3328 { //add applicable automatic validators, empty if n/a
3329 for (int n = 0; n < list.size(); n++)
3330 {
3331 field = (Field) list.get(n);
3332 /* field is nullable, skipping non-nullability validation */
3333 if (! (field instanceof MaxSizable)) {
3334 log.warn("Skipping maximum length validator for field '" + field.getName() + "'; [database type='CHAR', field.type='" + field.getType() + "' is not MaxSizable]");
3335 }
3336 else{
3337 VText vt = new VText((MaxSizable) field, "Not enough or too many characters");
3338 vt.setMaxSize(10);
3339 }
3340 }
3341 }
3342
3343 /** varchar (VARCHAR); Nullable=true; AutoInc=false; MaxSize=10 */
3344 list = getFieldFromForm(form, "varchar_val", prefix, suffix, map, true);
3345 if (list.size() > 0)
3346 { //add applicable automatic validators, empty if n/a
3347 for (int n = 0; n < list.size(); n++)
3348 {
3349 field = (Field) list.get(n);
3350 /* field is nullable, skipping non-nullability validation */
3351 if (! (field instanceof MaxSizable)) {
3352 log.warn("Skipping maximum length validator for field '" + field.getName() + "'; [database type='VARCHAR', field.type='" + field.getType() + "' is not MaxSizable]");
3353 }
3354 else{
3355 VText vt = new VText((MaxSizable) field, "Not enough or too many characters");
3356 vt.setMaxSize(10);
3357 }
3358 }
3359 }
3360
3361 /** text (VARCHAR); Nullable=true; AutoInc=false; MaxSize=2147483647 */
3362 list = getFieldFromForm(form, "longvarchar_val", prefix, suffix, map, true);
3363 if (list.size() > 0)
3364 { //add applicable automatic validators, empty if n/a
3365 for (int n = 0; n < list.size(); n++)
3366 {
3367 field = (Field) list.get(n);
3368 /* field is nullable, skipping non-nullability validation */
3369 if (! (field instanceof MaxSizable)) {
3370 log.warn("Skipping maximum length validator for field '" + field.getName() + "'; [database type='VARCHAR', field.type='" + field.getType() + "' is not MaxSizable]");
3371 }
3372 else{
3373 VText vt = new VText((MaxSizable) field, "Not enough or too many characters");
3374 vt.setMaxSize(2147483647);
3375 }
3376 }
3377 }
3378
3379 /** date (DATE); Nullable=true; AutoInc=false; MaxSize=13 */
3380 list = getFieldFromForm(form, "date_val", prefix, suffix, map, true);
3381 if (list.size() > 0)
3382 { //add applicable automatic validators, empty if n/a
3383 for (int n = 0; n < list.size(); n++)
3384 {
3385 field = (Field) list.get(n);
3386 /* field is nullable, skipping non-nullability validation */
3387 }
3388 }
3389
3390 /** time (TIME); Nullable=true; AutoInc=false; MaxSize=15 */
3391 list = getFieldFromForm(form, "time_val", prefix, suffix, map, true);
3392 if (list.size() > 0)
3393 { //add applicable automatic validators, empty if n/a
3394 for (int n = 0; n < list.size(); n++)
3395 {
3396 field = (Field) list.get(n);
3397 /* field is nullable, skipping non-nullability validation */
3398 }
3399 }
3400
3401 /** timestamp (TIMESTAMP); Nullable=true; AutoInc=false; MaxSize=29 */
3402 list = getFieldFromForm(form, "timestamp_val", prefix, suffix, map, true);
3403 if (list.size() > 0)
3404 { //add applicable automatic validators, empty if n/a
3405 for (int n = 0; n < list.size(); n++)
3406 {
3407 field = (Field) list.get(n);
3408 /* field is nullable, skipping non-nullability validation */
3409 }
3410 }
3411
3412 /** bit (BIT); Nullable=true; AutoInc=false; MaxSize=1 */
3413 list = getFieldFromForm(form, "bit_val", prefix, suffix, map, true);
3414 if (list.size() > 0)
3415 { //add applicable automatic validators, empty if n/a
3416 for (int n = 0; n < list.size(); n++)
3417 {
3418 field = (Field) list.get(n);
3419 /* field is nullable, skipping non-nullability validation */
3420 }
3421 }
3422
3423 /** _varchar (ARRAY); Nullable=true; AutoInc=false; MaxSize=10 */
3424 list = getFieldFromForm(form, "array_val", prefix, suffix, map, true);
3425 if (list.size() > 0)
3426 { //add applicable automatic validators, empty if n/a
3427 for (int n = 0; n < list.size(); n++)
3428 {
3429 field = (Field) list.get(n);
3430 /* field is nullable, skipping non-nullability validation */
3431 }
3432 }
3433
3434 /** bool (BIT); Nullable=true; AutoInc=false; MaxSize=1 */
3435 list = getFieldFromForm(form, "boolean_val", prefix, suffix, map, true);
3436 if (list.size() > 0)
3437 { //add applicable automatic validators, empty if n/a
3438 for (int n = 0; n < list.size(); n++)
3439 {
3440 field = (Field) list.get(n);
3441 /* field is nullable, skipping non-nullability validation */
3442 }
3443 }
3444
3445 /** bytea (BINARY); Nullable=true; AutoInc=false; MaxSize=2147483647 */
3446 list = getFieldFromForm(form, "varbinary_val", prefix, suffix, map, true);
3447 if (list.size() > 0)
3448 { //add applicable automatic validators, empty if n/a
3449 for (int n = 0; n < list.size(); n++)
3450 {
3451 field = (Field) list.get(n);
3452 /* field is nullable, skipping non-nullability validation */
3453 }
3454 }
3455
3456 /** json (OTHER); Nullable=true; AutoInc=false; MaxSize=2147483647 */
3457 list = getFieldFromForm(form, "json_val", prefix, suffix, map, true);
3458 if (list.size() > 0)
3459 { //add applicable automatic validators, empty if n/a
3460 for (int n = 0; n < list.size(); n++)
3461 {
3462 field = (Field) list.get(n);
3463 /* field is nullable, skipping non-nullability validation */
3464 }
3465 }
3466
3467 /** jsonb (OTHER); Nullable=true; AutoInc=false; MaxSize=2147483647 */
3468 list = getFieldFromForm(form, "jsonb_val", prefix, suffix, map, true);
3469 if (list.size() > 0)
3470 { //add applicable automatic validators, empty if n/a
3471 for (int n = 0; n < list.size(); n++)
3472 {
3473 field = (Field) list.get(n);
3474 /* field is nullable, skipping non-nullability validation */
3475 }
3476 }
3477 }
3478
3479 /**
3480 Convenience method that calls {@link #addValidators(Form, String, String, Map)} with a
3481 <tt>null</tt> prefix/suffix and the specified map
3482 */
3483 public static void addValidators(fc.web.forms.Form form, Map map)
3484 {
3485 addValidators(form, null, null, map);
3486 }
3487
3488 /**
3489 Convenience method that calls {@link #addValidators(Form, String, String, Map)} with a
3490 <tt>null</tt> prefix/suffix/map
3491 */
3492 public static void addValidators(fc.web.forms.Form form)
3493 {
3494 addValidators(form, null, null, null);
3495 }
3496
3497 /**
3498 Convenience method that calls {@link #addValidators(Form, String, String, map)} with the
3499 specified prefix and a <tt>null</tt> suffix/map
3500 */
3501 public static void addValidators(fc.web.forms.Form form, String prefix)
3502 {
3503 addValidators(form, prefix, null, null);
3504 }
3505
3506 /**
3507 Validates a form field <i>if</i> it is filled by the user. Leaves empty fields alone.
3508 This is very useful for fields that are optional but must have the correct value when
3509 filled by the user
3510 */
3511 public static void addIfFilledValidators(Form form, String prefix)
3512 {
3513 addValidators(form, prefix, null, null, true);
3514 }
3515
3516 /** implementation helper method -- not for public use */
3517 static List getFieldFromForm(Form form, String colname, String prefix, String suffix, Map map, boolean warn)
3518 {
3519 Field field = null;
3520 List list = Form.empty_list;
3521 boolean getwhere = false;
3522 getwhere = false;
3523 String colname_in_form = colname;
3524
3525 if (map != null) {
3526 String str = (String) map.get(colname);
3527 if (str != null) {
3528 prefix = null; /*ignored when there is a mapping*/
3529 suffix = null; /*ignored when there is a mapping*/
3530 colname_in_form = str; /* else if not in map, colname remains as-is*/
3531 }
3532 }
3533
3534 if (prefix != null)
3535 {
3536 if (prefix.equals("*")) {
3537 getwhere = true;
3538 }
3539 else{
3540 colname_in_form = prefix + colname_in_form;
3541 }
3542 }
3543
3544 if (suffix != null)
3545 {
3546 if (suffix.equals("*")) {
3547 getwhere = true;
3548 }
3549 else{
3550 colname_in_form = colname_in_form + suffix;
3551 }
3552 }
3553
3554 if (getwhere) {
3555 list = form.getContaining(colname_in_form);
3556 if (list.size() == 0 && warn) warn(form, colname_in_form, suffix, prefix, map);
3557 return list;
3558 }
3559 else{
3560 //containsField() check prevents an un-necessary warning with form.get()
3561 if (! form.containsField(colname_in_form)) {
3562 if (warn) warn(form, colname_in_form, suffix, prefix, map);
3563 return list;
3564 }
3565 field = form.get(colname_in_form);
3566 list = new ArrayList();
3567 list.add(field);
3568 }
3569 return list;
3570 }
3571
3572 private static final void warn(Form form, String name, String suffix, String prefix, Map map) {
3573 log.warn(form.getName(),": No automatic validators will be added for Field [",name,"]. This field does not exist in the front-end form. (this could be normal). suffix=["+suffix+"] prefix=["+prefix+"] map=", map);
3574 }
3575
3576 /**
3577 Validates the bean before saving it to the database. This
3578 method is called internally by the {@link save()} method
3579 before saving a new bean (i.e., inserting a new row) to the
3580 database.
3581 <p>
3582 The validation is somewhat basic and there can exist many
3583 constraints and conditions on the database that might results in a
3584 insert/update error anyway. But by doing some basic validation
3585 against some known constraints, we save a needless trip to the
3586 database.
3587 We check to see that: <ol>
3588 <li><i>non-nullable and non auto-increment</i> columns [and with no default
3589 column value in the database] are modified (via a set method) since these
3590 columns must have a explicitly set value.</li>
3591 <li>for non-nullable columns that hold non-primitive (i.e., Object)
3592 java types, the modified value for non-nullable columns is a
3593 non-null object. </li>
3594 </ol>
3595 */
3596 protected static void validateBeforeSaveNew(alltypes bean) throws ValidateException
3597 {
3598 boolean error = false;
3599 final StringBuffer buf = new StringBuffer("The following validation errors were found").append(IOUtil.LINE_SEP);
3600
3601 //[id]=>is not nullable but has a default column value [nextval('alltypes_id_seq'::regclass)], no modification check necessary, skipping...
3602
3603 //[smallint_val]=>nullable, no modification check necessary, skipping...
3604
3605 if (! bean.isModified_int_val()) {
3606 error = true;
3607 buf.append("int_val was not set (this field is required in the database)").append(";current value=").append(bean.get_int_val()).append(IOUtil.LINE_SEP);
3608 }
3609 //int is primitive, skipping null test
3610
3611 //[bigint_val]=>nullable, no modification check necessary, skipping...
3612
3613 //[float_val]=>nullable, no modification check necessary, skipping...
3614
3615 //[double_val]=>nullable, no modification check necessary, skipping...
3616
3617 //[numeric_val]=>nullable, no modification check necessary, skipping...
3618
3619 //[char_val]=>nullable, no modification check necessary, skipping...
3620
3621 //[varchar_val]=>nullable, no modification check necessary, skipping...
3622
3623 //[longvarchar_val]=>nullable, no modification check necessary, skipping...
3624
3625 //[date_val]=>nullable, no modification check necessary, skipping...
3626
3627 //[time_val]=>nullable, no modification check necessary, skipping...
3628
3629 //[timestamp_val]=>nullable, no modification check necessary, skipping...
3630
3631 //[bit_val]=>nullable, no modification check necessary, skipping...
3632
3633 //[array_val]=>nullable, no modification check necessary, skipping...
3634
3635 //[boolean_val]=>nullable, no modification check necessary, skipping...
3636
3637 //[varbinary_val]=>nullable, no modification check necessary, skipping...
3638
3639 //[json_val]=>nullable, no modification check necessary, skipping...
3640
3641 //[jsonb_val]=>nullable, no modification check necessary, skipping...
3642 if (error) {
3643 throw new ValidateException(buf.toString());
3644 }
3645 }
3646
3647 /**
3648 Validates the bean before saving it to the database. This method is
3649 called internally by the {@link save()} method before updating an
3650 existing bean (i.e., updating a row) in the database.
3651 <p>
3652 For <i>each modified column</i>, if that column is non-nullable in
3653 the database, then it must have a non-null value in the bean before
3654 it is saved. This check is only done for fields of
3655 <i>non</i>-primitive (Object) java types. [There is no way to ensure
3656 a non-null value for <i>primitive</i> types since all values
3657 [including 0] are non-null for those types].
3658 */
3659 protected static void validateBeforeSaveUpdate(alltypes bean) throws ValidateException
3660 {
3661 boolean error = false;
3662 final StringBuffer buf = new StringBuffer("The following validation errors were found").append(IOUtil.LINE_SEP);
3663
3664 //[id]=>auto-increment, no modification check necessary, skipping...
3665 //[smallint_val]=>nullable, no modification check necessary, skipping...
3666 if (bean.isModified_int_val()) {
3667 //int is primitive, skipping null test
3668 }
3669 //[bigint_val]=>nullable, no modification check necessary, skipping...
3670 //[float_val]=>nullable, no modification check necessary, skipping...
3671 //[double_val]=>nullable, no modification check necessary, skipping...
3672 //[numeric_val]=>nullable, no modification check necessary, skipping...
3673 //[char_val]=>nullable, no modification check necessary, skipping...
3674 //[varchar_val]=>nullable, no modification check necessary, skipping...
3675 //[longvarchar_val]=>nullable, no modification check necessary, skipping...
3676 //[date_val]=>nullable, no modification check necessary, skipping...
3677 //[time_val]=>nullable, no modification check necessary, skipping...
3678 //[timestamp_val]=>nullable, no modification check necessary, skipping...
3679 //[bit_val]=>nullable, no modification check necessary, skipping...
3680 //[array_val]=>nullable, no modification check necessary, skipping...
3681 //[boolean_val]=>nullable, no modification check necessary, skipping...
3682 //[varbinary_val]=>nullable, no modification check necessary, skipping...
3683 //[json_val]=>nullable, no modification check necessary, skipping...
3684 //[jsonb_val]=>nullable, no modification check necessary, skipping...
3685 if (error) {
3686 throw new ValidateException(buf.toString());
3687 }
3688 }
3689 }