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 <column_list> from <table> order by <clause> limit 5 offset 10 124</pre> </blockquote> 125@return a list containing {@link alltypes } objects <i>or an empty list</i> if there are no rows in the database*/ 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}