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
006package fc.jdbc.dbo.generated;
007
008/*
009 * Auto generated on: Wed May 18 15:51:41 EDT 2022
010 * JDBC url: [jdbc:postgresql://127.0.0.1/test]
011 * WARNING: Manual edits will be lost if/when this file is regenerated.
012 */
013import java.io.*;
014import java.math.*;
015import java.sql.*;
016import java.util.*;
017
018import fc.io.*;
019import fc.jdbc.*;
020import fc.jdbc.dbo.*;
021import fc.util.*;
022import fc.web.forms.*;
023
024/**
025Manages various operations on the alltypes table. 
026
027<p>Most methods of this class take a {@link java.sql.Connection Connection} as an argument
028and use that connection to run various queries. The connection parameter is never closed
029by methods in this class and that connection can and should be used again. Methods of this
030class will also throw a <tt>IllegalArgumentException</tt> if the specified connection
031object is <tt>null</tt>.
032
033<p>Thread Safety: Operations on this class are by and large thread safe in that multiple
034threads can call the methods at the same time. However, seperate threads should use
035seperate connection objects when invoking methods of this class.
036*/
037public final class alltypesMgr extends fc.jdbc.dbo.DBOMgr
038{
039/* --- Fields used for collecting usage statistics --- 
040Increments to these don't need to be synchronized since these are
041ints and not longs and memory visibility is not an issue in the
042toString() method (in which these are read).
043*/
044private static int __getall_called = 0;
045private static int __getlimited_called = 0;
046private static int __getbykey_called = 0;
047private static int __getwhere_called = 0;
048private static int __getusing_called = 0;
049private static int __getusing_ps_called = 0;
050private static int __getfromrs_called = 0;
051private static int __save_called = 0;
052private static int __delete_called = 0;
053private static int __deletebykey_called = 0;
054private static int __deletewhere_called = 0;
055private static int __deleteusing_called = 0;
056private static int __count_called = 0;
057private static int __countwhere_called = 0;
058private static int __countusing_called = 0;
059private static int __exists_called = 0;
060/* -------------- end statistics fields -------------- */
061
062/** Constructor is private since class is never instantiated */
063private alltypesMgr() {
064  }
065
066
067static 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/** 
069Returns all rows in the table. Use with care for large tables since
070this method can result in VM out of memory errors. <p>This method
071also takes an optional (can be null) <tt>clause</tt> parameter which
072is sent as is to the database. For example, a clause can be:
073<blockquote><pre>
074order 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*/
077public 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/** 
096Convenience method that invokes {@link getAll(Connection, alltypes, String) getAll} with an empty additional clause.
097*/
098public static List getAll(final Connection con) throws ValidateException, SQLException
099  {
100  return getAll(con, null);
101  }
102
103static 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/** 
105Returns all rows in the table starting from some row number and limited
106by a certain number of rows after that starting row. 
107<p>
108This method takes a required (non-null) <code>order_clause</code>, since when using
109a limit clause, rows must be ordered for the limit to make sense. The
110clause should be of the form <font color=blue>order by ...</font>
111<p>
112The <code>limit</code> specifies the number of rows that will be returned. (those many
113or possibly lesser rows will be returned, if the query itself yields less
114rows).
115<p>
116The <code>offset</code> skips that many rows before returning rows. A zero offset is
117the same as a traditional query with no offset clause, where rows from
118the beginning are returned. If say, offset = 10, then rows starting from
119row 11 will be returned.
120<p>
121The sql-query generated by this method is database specific but will (typically) look like:
122<blockquote><pre>
123select &lt;column_list&gt; from &lt;table&gt; order by &lt;clause&gt; 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*/
126public 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
143static 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/** 
145Returns <b>the</b> row corresponding to the specified primary key(s) of this table 
146or <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*/
149public 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/** 
169Returns 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
172specified 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
179injection 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*/
183public 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/** 
202Returns the rows returned by querying the table with the value of the
203specified <tt>alltypes</tt> object or <i>an empty list</i> if no rows were found. As many
204fields in <tt>alltypes</tt> can be set as needed and the values of
205all set fields (including fields explicitly set to <tt>null</tt>)
206are then used to perform the query.
207<p>
208This method is often convenient/safer than the {@link #getWhere
209getWhere} method (because the <tt>getWhere</tt> method takes an
210arbitrary query string which has to be properly escaped by the
211user).
212<p>Essentially, this method is a more convenient way to use a
213PreparedStatement. Internally, a prepared statement is created and
214it's parameters are set to fields that are set in this object).
215Using PreparedStatements directly is also perfectly fine. For
216example, the following are equivalent. 
217<p> Using a PreparedStatement:
218<blockquote><pre>
219String foo = "select * from table_foo where x = ? and y = ?";
220PreparedStatement ps = con.prepareStatement(foo);
221ps.setString(1, "somevalue");
222ps.setString(2, "othervalue");
223ResultSet rs  = ps.executeUpdate();
224while (rs.next()) {
225    table_foo bean = table_fooMgr.getFromRS(rs);
226    }
227</pre> </blockquote>
228
229Using this method:
230<blockquote><pre>
231table_foo <font color=blue>proto</font> = new table_foo();
232proto.set_x("somevalue"); //compile time safety
233proto.set_y("othervalue");  //compile time safety
234List beans = table_fooMgr.<font color=blue>getUsing(proto)</font>;
235</pre> </blockquote>
236<p>This method also takes an <tt>clause</tt> parameter which
237is sent as is to the database. For example, a clause can be:
238<blockquote><pre>
239List beans = table_fooMgr.<font color=blue>getUsing(proto, <b>"order by some_column_name"</b>)</font>;
240</pre> </blockquote>
241This clause is optional. Specify <tt>null</tt> to not use it at all.
242If the clause is specified, do <font size='+1'><b>NOT</b></font> include the word <tt>WHERE</tt>.
243
244The fields that are set in the proto object (as shown above) are sent as
245part of a WHERE clause constructed internally. If you are specifying a clause
246as well, you should not specify the word <tt>WHERE</tt>. However, you may have
247to specify <tt>AND</tt> to add to the internal WHERE clause, if you have set any
248fields in the proto object. For example
249<blockquote><pre>
250List 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
253efficient to use a prepared statement directly (as opposed to using
254this method). In most cases, this is not something to worry about,
255but your mileage may vary...
256*/
257public 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/** 
633Convenience method that invokes {@link getUsing(Connection, alltypes, String) getUsing} with an empty <i><tt>clause</tt></i> parameter.*/
634public static List getUsing(final Connection con, final alltypes bean) throws ValidateException, SQLException
635  {
636  return getUsing(con, bean, null);
637  }
638
639/**
640This is a <i>convenience</i> method that runs the specified 
641prepared statement to perform an arbitrary query. For example: 
642<blockquote>
643<pre>
644PreparedStatement <font color=blue>ps</font> = con.prepareStatement(
645    "select * from some_table where some_column = ?");
646ps.setString(1, "foo");
647List list = fooMgr.<font color=blue>getUsing</font>(con, <font color=blue>ps</font>);
648for (int n = 0; n < list.size(); n++) {
649  sometable t = (sometable) list.get(n);
650  //do something
651  }
652</pre>
653</blockquote>
654The effect of the above is <u>equivalent</u> to the following (larger) block 
655of code:
656<blockquote>
657<pre>
658PreparedStatement <font color=blue>ps</font> = con.prepareStatement(
659  "select * from sometable where some_column = ?"
660  );
661ps.setString(1, "foo");
662ResultSet rs = <font color=blue>ps.executeQuery()</font>;
663List list = new ArrayList();
664while (rs.next()) {
665  list.add(sometableMgr.<font color=blue>getFromRS(rs)</font>);
666  }
667
668for (int n = 0; n < list.size(); n++) {
669  sometable t = (sometable) list.get(n);
670  //do something
671  }
672</pre>
673</blockquote>
674
675Note: Just as with other get<i>XXX</i> methods, for large amounts of
676rows (say many thousands), it may be more efficient use and iterate
677through a JDBC result set directly.
678*/
679public 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/**
695This is a <i>convenience</i> method that runs the specified 
696{@link fc.jdbc.dbo.NamedParamStatement NamedParamStatement} to perform an arbitrary query.
697For example: <blockquote>
698<pre>
699NamedParamStatement <font color=blue>ps</font> = queryReadeer.getQuery("somequery");
700ps.setString("some_placeholder", "foo");
701List list = fooMgr.<font color=blue>getUsing</font>(con, <font color=blue>ps</font>);
702for (int n = 0; n < list.size(); n++) {
703  sometable t = (sometable) list.get(n);
704  //do something
705  }
706</pre>
707</blockquote>
708
709Note: Just as with other get<i>XXX</i> methods, for large amounts of
710rows (say many thousands), it may be more efficient use and iterate
711through a JDBC result set directly.
712*/
713public 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/** 
729Returns 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 
730table 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>
739The ResultSet returned by the query can be used directly or can be passed
740to 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,
742then the {@link #getFromRS getFromRS} method for each table manager
743can be called on the same ResultSet to retrieve the row object for
744that table.
745Note: the returned list of names has a trailing space, which is good when
746the rest of the query is appended to this list.
747*/
748public 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/** 
754Returns 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
755table 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
762so 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>
766The ResultSet returned by the query can be used directly or can be passed
767to 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,
769then the {@link #getFromRS getFromRS(String)} method for each table manager
770can be called on the same ResultSet to retrieve the row object for
771that table.
772Note: the returned list of names has a trailing space, which is good when
773the rest of the query is appended to this list.
774*/
775public 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/** 
955Creates and returns a new <tt>alltypes</tt> object that represents a row from the specified ResultSet. The ResultSet is
956typically obtained via a handwritten query/PreparedStatement. The resulting 
957ResultSet should contain all of the
958column names of table, and this will only happen if the handwritten query had
959a select statement that specified all fields or used a <tt>select <b>*</b>..</tt>
960clause.
961<p>
962In the select clause, we could also be selecting multiple tables. To disambiguate
963between the same field names that may exist in multiple tables, this method 
964also 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>
972For 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>
976The {@link #columns} method conveniently returns a list of column names in fully qualified format 
977and is useful for this purpose.
978<p>Note: This method will read the <i>current</i> row from the specified result set
979and will <b>not</b> move the result set pointer to the next row after the current
980row 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 
984alltypes} object populated with the contents of the next    row from the result set or <tt> null </tt> if
985    the ResultSet was empty.
986*/
987public 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/** 
1083Creates and returns a new <tt>alltypes</tt> object that represents a row from the specified ResultSet. The ResultSet is
1084typically obtained via a handwritten query/PreparedStatement. The resulting 
1085ResultSet should contain all of the
1086column names of table, prefixed with the specified <i>prefix</i> argument.
1087a select statement that specified all fields or used a <tt>select <b>*</b>..</tt>
1088clause.
1089<p>
1090In the select clause, we could also be selecting multiple tables. To disambiguate
1091between the same field names that may exist in multiple tables, this method 
1092also 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>
1099This prefix will typically be the same as the table abbreviation chosen via the <b>AS</b> clause. 
1100If 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
1102so the prefix should not end with a "." or "_", etc<p>
1103<p>
1104For 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>
1108The {@link #columns} method conveniently returns a list of column names in fully qualified format 
1109and is useful for this purpose.
1110<p>Note: This method will read the <i>current</i> row from the specified result set
1111and will <b>not</b> move the result set pointer to the next row after the current
1112row 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 
1116alltypes} object populated with the contents of the next    row from the result set or <tt> null </tt> if
1117    the ResultSet was empty.
1118*/
1119public 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/** 
1215Creates and returns a new <tt>alltypes</tt> object that represents a row from the specified ResultSet. For this method
1216to 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>
1219This method does not prepend the table name to columns when reading data from
1220the 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
1222class. For example:
1223<p>
1224<code>select a, b, c, c*2 from foo where a = 1;</code>
1225<p>
1226This method will expect columns to be called <code><i>a, b, c</i></code> (no column aliases) in the returned
1227result set. In this example, there is only one table <code>foo</code> so qualifying the column
1228names, like <code>foo.a as foo_a</code> is not necessary). Also note, for this method to work properly, the 
1229column list<blockquote><code>select <i>a, b, c </i></code> ...</blockquote> should be complete, i.e., contain <i>at least</i> all the columns
1230of this table (<i>additional</i> expressions like c*2 are fine). It is slightly less efficient to retrieve all columns
1231especially 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>
1233Of course, if one needs a subset of columns, one can use the ResultSet directly and forego trying to
1234convert a ResultSet row into an corresponding object
1235<p> 
1236See {@link getFromRS(ResultSet)} which is more useful when writing a JDBC
1237query that uses multiple table joins.
1238<p>Note: This method will read the <i>current</i> row from the specified result set
1239and will <b>not</b> move the result set pointer to the next row after the current
1240row 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*/
1247public 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
1343private 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/**
1458Saves the specified object into the database. If the specified
1459object was newly created, then it is <span style="font-variant:
1460small-caps">insert</span>'ed into the database, else (if it was retrieved
1461earlier from the database) it is <span 
1462style="font-variant: small-caps">update</span>'ed. (this can be
1463overriden by the {@link #update update} method). If the object is
1464inserted as a new row, then after insertion, the values of
1465serial/auto-incremented columns will be automatically available via the
1466appropriate getXXX() methods on that object.
1467<p>
1468<b>NOTE 1:</b> When saving an object, only modified fields are
1469saved. Do not rely on default field values (such as null) of newly
1470created objects; instead explicitly set the value (including to null
1471if 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
1474and cannot be saved again and any attempt to save it again will
1475result in a runtime exception. Objects that need to be modified
1476again must be re-instantiated or re-populated from the database
1477before they can be saved again. (the serial/auto-increment data will still be
1478available, discarding only affects the ability to save the object
1479again).
1480<p>
1481<b>Note 3:</b> <font color='red'>For various reasons/flexiblity, default database values
1482for columns <i>other</i> than serial columns are <b>not</b> available
1483in the saved object. To get these values, retrieve the saved object again. (this is what
1484we would have to do internally anyway). This is relevant, for example, when a column has
1485a default value of a now() timestamp, and we need to get that timestamp after the object
1486has 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*/
1495public 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/**
1954Uses the specified object to update existing data in the database.
1955<p>
1956Note, the {@link #save save} method automatically saves newly created objects
1957as <i>inserts</i> in the database (and prior <i>retrieved</i> objects, when
1958subsequently modified, are saved as <i>updates</i>).
1959<p>
1960However, sometimes it is useful to create a <i>new</i> object and then
1961use its data to <i>update</i> an existing row in the database.
1962This method need <b>only</b> be called to save a <u>newly</u>
1963created object as an <u>update</u> into the database (overriding the
1964default action of saving new objects as inserts in the database).
1965<p>
1966Note, also, a bean can only be updated if the corresponding table it has
1967at least one primary key defined. To update tables with no primary keys,
1968use JDBC directly.
1969<p>
1970This method takes primary key(s) of {@link alltypes} as additional arguments and sets those in the
1971specified bean before updating the database (this way the row to update
1972can 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*/
1981public 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
1991static private final String deleteStmt = "DELETE  from alltypes WHERE id=?";
1992/** 
1993Deletes this object from the database. <p>
1994<b>NOTE 1:</b> Only objects that were retrieved from the database can be deleted. Newly
1995created objects cannot be deleted since they do not yet exist in the database.
1996Use {@link #deleteByKey deleteByKey} or {@link #deleteWhere deleteWhere} instead
1997for arbitrary deletions. <p><b>NOTE 2:</b> Once an object is successfully
1998deleted, it is discarded and cannot be deleted again and any attempt to delete
1999it again will result in a runtime Exception.
2000*/
2001public 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
2018static private final String deleteByPKStmt = "DELETE  from alltypes WHERE id=?";
2019/** 
2020Deletes 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*/
2022public 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/** 
2035Returns the rows returned by querying the table with the contents of
2036the specified instance of <tt>alltypes</tt> or <tt>null</tt> if no
2037rows were found. As many fields in <tt>alltypes</tt> can be set as
2038needed and the values of all set fields (including fields explicitly
2039set to <tt>null</tt>) are then used to perform the query. <p>Note,
2040however that this method does use any primary key(s). If the 
2041primary 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
2045object, set various fields in it, and then use that to delete matching
2046row(s) from the database in a type safe way.
2047<p>
2048This method is often convenient/safer than the {@link #deleteWhere
2049deleteWhere} method (because the <tt>deleteWhere</tt> method takes
2050an 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
2053is sent as is to the database. For example, a clause can be:
2054<blockquote><pre>
2055List beans = table_fooMgr.<font color=blue>deleteUsing(proto, <b>"xyx > 5"</b>)</font>;
2056</pre> </blockquote>
2057This clause is optional. Specify <tt>null</tt> to not use it at all.
2058If 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
2061PreparedStatement. Internally, a prepared statement is created and
2062it's parameters are set to fields that are set in this object).
2063Using PreparedStatements directly is also perfectly fine. For
2064example, the following are equivalent. 
2065<p> Using a PreparedStatement:
2066<blockquote><pre>
2067String foo = "delete from table_foo where x = ? and y = ?";
2068PreparedStatement ps = con.prepareStatement(foo);
2069ps.setString(1, "somevalue");
2070ps.setString(2, "othervalue");
2071int rows_deleted = ps.executeUpdate();
2072</pre> </blockquote>  
2073
2074Using this method:
2075<blockquote><pre>
2076table_foo proto = new table_foo();
2077proto.set_x("somevalue"); //compile time safety
2078proto.set_y("othervalue");  //compile time safety
2079int rows_deleted = table_fooMgr.<font color=blue>deleteUsing</font>(proto);
2080</pre></blockquote>
2081@return   the number of rows deleted
2082*/
2083public 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/** 
2447Convenience method that invokes {@link getUsing(Connection, alltypes, String) getUsing} with an empty <i><tt>clause</tt></i> parameter.*/
2448public static int deleteUsing(final Connection con, final alltypes bean) throws ValidateException, SQLException
2449  {
2450  return deleteUsing(con, bean, null);
2451  }
2452
2453/** 
2454Deletes the rows with the specified where clause. <p><b>The
2455where clause is sent as-is to the database and SQL injection
2456attacks are possible if it is created as-is from a untrusted
2457source.</b>
2458(note: the string <tt>"WHERE"</tt> does <b>not</b> have to be
2459specified in the clause. It is added automatically by this method).
2460
2461@return the number of rows deleted by the database
2462*/
2463public 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
2473private final static String countStmt = "SELECT count(*) from alltypes";
2474/**
2475Returns the count of all rows in the table. <p><b>Note</b>: This may
2476be an expensive operation in MVCC databases like PostgresQL, Oracle and
2477others, where an entire non-optimized table scan <i>may</i> be
2478required -- hence speed will typically be O(n). However, on Postgres (for
2479example), this is still very fast for small values of n (on a
2480mid-level test machine) as of 2004, counting 4k records was about
248115 milli-seconds(ms); this scaled almost linearly, so count(*) for 16k records was
2482about 70 ms, 65k records was about 370 ms, 524k records was about
24832000 ms and 1 million records was about 4000 ms. Results will vary
2484on your machine and database but the general O(n) principle will
2485remain the same.
2486*/
2487public 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/**
2505Returns 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
2507specified in the clause. It is added automatically by this method).
2508
2509@throws   IllegalArgumentException  if the where paramater was null
2510*/
2511public 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/** 
2532Returns the rows count by querying the table with the contents of the
2533specified instance of <tt>alltypes</tt> As many fields in <tt>alltypes</tt> can be set as needed and the
2534values of all set fields (including fields explicitly set to
2535<tt>null</tt>) are then used to perform the query. If the primary
2536key(s) are known then one can also use the {@link #exists} method to
2537see if that row exists in the database.
2538<p>
2539This method is often convenient/safer than the {@link #countWhere
2540countWhere} method (because the <tt>countWhere</tt> method takes an
2541arbitrary query string which has to be properly escaped by the
2542user). 
2543<p>Essentially, this method is a more convenient way to use a
2544PreparedStatement (with parameters set to fields that are set in
2545this object). Using PreparedStatements directly is also perfectly
2546fine. For example, the following two are equivalent. <p>
2547Using a PreparedStatement:
2548<blockquote><pre>
2549String foo = "select <i>count(*)</i> from table_foo where x = ? and y = ?";
2550PreparedStatement ps = con.prepareStatement(foo);
2551ps.setString(1, "somevalue");
2552ps.setString(2, "othervalue");
2553ResultSet rs  = ps.executeUpdate();
2554rs.next();
2555int count = rs.getInt(1);
2556</pre> </blockquote>
2557
2558Using this method:
2559<blockquote><pre>
2560table_foo proto = new table_foo();
2561proto.set_x("somevalue"); //compile time safety
2562proto.set_y("othervalue");  //compile time safety
2563int count = table_fooMgr.<font color=blue>countUsing</font>(proto);
2564</pre> </blockquote>
2565The clause is optional. Specify <tt>null</tt> to not use it at all.
2566If the clause is specified, do <font size='+1'><b>NOT</b></font> include the word <tt>WHERE</tt>.
2567*/
2568public 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/** 
2940Convenience method that invokes {@link getUsing(Connection, alltypes, String) getUsing} with an empty <i><tt>clause</tt></i> parameter.*/
2941public static int countUsing(final Connection con, final alltypes bean) throws ValidateException, SQLException
2942  {
2943  return countUsing(con, bean, null);
2944  }
2945
2946static private final String existsStmt = "SELECT count(*) from alltypes WHERE id=?";
2947/**
2948Returns <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*/
2951public 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/**
2970A thin wrapper around {@link getUsing(Connection,alltypes) getUsing}
2971that returns <tt>false</tt> if no rows are returned, <tt>true</tt> otherwise.
2972*/
2973public 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/**
2980Returns a prepared statement given it's variable name.
2981
2982Essentially speeds up the creation of prepared statements perhaps
2983using a per connection cache -- which makes sense for pooled
2984connections since they are not closed but returned to the pool
2985and hence don't need to "prepare" statements every time (the
2986prepareStatement call is seperate from actually filling in the
2987placeholders in a already created prepared statement -- which
2988does need to be done every time). <p>
2989Prepared statements are unique per connection, so multiple threads
2990using different connections won't stomp over each other's prepared
2991statements. Multiple threads using the SAME connection will cause
2992bizarre errors but multiple threads won't get the same connection
2993from the connection manager -- ever :-), so that should never happen.
2994*/
2995private 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
3004private 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
3011private static final java.util.Date __loadDate = new java.util.Date();
3012/** Returns usage statistics for this class */
3013public 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
3123public String toString() 
3124  {
3125  return getClass().getName() + " [call stats() for more info]";
3126  }
3127
3128// ================ Validation  ==================== 
3129
3130/** 
3131Creates and attaches validators for all the fields in the
3132specified {@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
3134as 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>.
3148These validators save a lot of grunt-work in adding such schema
3149constraints to the front-end {@link fc.web.forms.Form}. <p><b>However, <i>business and
3150other validation constraints</i> still need to be manually added to
3151the application code/front-end forms as/when needed</b>.
3152<p>
3153
3154The 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
3182suggested to invoke this method, print the form using it's <tt>toString</tt>
3183method and then examine the output to see what validators were added If those
3184automatic validators are too little, too many or too hard to understand, <u>then
3185simply enoough, do NOT invoke this method and simply add validators by
3186hand</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
3188the 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*/
3204public 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
3209private 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/** 
3480Convenience method that calls {@link #addValidators(Form, String, String, Map)} with a 
3481<tt>null</tt> prefix/suffix and the specified map
3482*/
3483public static void addValidators(fc.web.forms.Form form, Map map) 
3484  {
3485  addValidators(form, null, null, map);
3486  }
3487
3488/** 
3489Convenience method that calls {@link #addValidators(Form, String, String, Map)} with a 
3490<tt>null</tt> prefix/suffix/map
3491*/
3492public static void addValidators(fc.web.forms.Form form) 
3493  {
3494  addValidators(form, null, null, null);
3495  }
3496
3497/** 
3498Convenience method that calls {@link #addValidators(Form, String, String, map)} with the 
3499specified prefix and a <tt>null</tt> suffix/map
3500*/
3501public static void addValidators(fc.web.forms.Form form, String prefix) 
3502  {
3503  addValidators(form, prefix, null, null);
3504  }
3505
3506/** 
3507Validates a form field <i>if</i> it is filled by the user. Leaves empty fields alone.
3508This is very useful for fields that are optional but must have the correct value when
3509filled by the user
3510*/
3511public 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 */
3517static 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
3572private 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/** 
3577Validates the bean before saving it to the database. This
3578method is called internally by the {@link save()} method
3579before saving a new bean (i.e., inserting a new row) to the
3580database.
3581<p>
3582The validation is somewhat basic and there can exist many
3583constraints and conditions on the database that might results in a
3584insert/update error anyway. But by doing some basic validation
3585against some known constraints, we save a needless trip to the
3586database.
3587We check to see that: <ol>
3588<li><i>non-nullable and non auto-increment</i> columns [and with no default
3589column value in the database] are modified (via a set method) since these
3590columns must have a explicitly set value.</li>
3591<li>for non-nullable columns that hold non-primitive (i.e., Object)
3592java types, the modified value for non-nullable columns is a
3593non-null object. </li>
3594</ol>
3595*/
3596protected 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/** 
3648Validates the bean before saving it to the database. This method is
3649called internally by the {@link save()} method before updating an
3650existing bean (i.e., updating a row) in the database.
3651<p>
3652For <i>each modified column</i>, if that column is non-nullable in
3653the database, then it must have a non-null value in the bean before
3654it is saved. This check is only done for fields of
3655<i>non</i>-primitive (Object) java types. [There is no way to ensure
3656a non-null value for <i>primitive</i> types since all values
3657[including 0] are non-null for those types].
3658*/
3659protected 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}