Re: [jrf-user] setInsertOnly and writeOnce
Brought to you by:
joncrlsn
|
From: Tom M. <tm...@li...> - 2002-11-18 22:24:26
|
I tried your patch. It did seem to get the insertOnly field set properly. The
update SQL gets created properly, omitting the field. However, when I trace
through the framework, invariably, the date_created gets updated along with the
other fields! I'm stumped.
So have you tested for results Darren? Is it working for you? What version of
JRF and what database are you using? I'm using JRF 2.0b4 and mySQL 4.0.3.
Jay, if you're reading the mail, do you have any suggestions?
Thanks
--
Tom Miller
Miller Associates, Inc.
tm...@li...
641.469.3535 Phone
413.581.6326 FAX
Darren Senel wrote:
> FYI,
>
> The TimeStampColumnSpecDbGen.setInsertOnly() does not seem to work. We
> had to do a
> code modification to UpdateSQLBuilder.java to correct the issue (we did
> this on Friday
> last week and so have not submitted this change to the message board
> yet).
>
> The problem lies in the fact that the UpdateSQLBuilder does not take
> any notice of the
> TimeStampColumnSpecDbGen.setInsertOnly() value when building update
> statements.
>
> For anyone that is interested our updated code is shown below (this was
> a quick fix and
> may not be the best solution).....
>
> private String buildSQL(boolean prepared,
> PersistentObject aPO,
> String tableName,
> List columnSpecs)
> {
> ColumnSpec aColumnSpec = null;
> ColumnSpec pkColumnSpec = null;
> ColumnSpec lockingColumnSpec = null;
>
> checkPolicy();
>
> StringBuffer sqlBuffer = new StringBuffer();
> sqlBuffer.append(" UPDATE ");
> sqlBuffer.append(tableName);
> sqlBuffer.append(" SET ");
> int count = 0;
> // Create an assignment expression for each column
> boolean isInsertOnly = false;
> Iterator iterator = columnSpecs.iterator();
> while (iterator.hasNext())
> {
> isInsertOnly = false;
> aColumnSpec = (ColumnSpec) iterator.next();
> if (aColumnSpec.isPrimaryKey())
> {
> pkColumnSpec = aColumnSpec;// save for later
> }
> else
> {// not a primary key
> if (aColumnSpec instanceof TimestampColumnSpecDbGen)
> {
> isInsertOnly =
> ((TimestampColumnSpecDbGen)aColumnSpec).isInsertOnly();
> }
>
> if (!isInsertOnly)
> {
>
> if (count > 0)
> {// BUG Fix -- PK may not be the first column in the
> list.
> sqlBuffer.append(", ");
> }
> count++;
>
> sqlBuffer.append(
> aColumnSpec.getColumnName());
> sqlBuffer.append(" = ");
> if (aColumnSpec.isOptimisticLock())
> {
> lockingColumnSpec = aColumnSpec;// save for later
> if (aColumnSpec instanceof
> TimestampColumnSpecDbGen)
> {
>
> sqlBuffer.append(i_dbPolicy.timestampFunction());
> }
> else
> {// Assume it's an IntegerColumnSpec
>
> if (prepared)
> {
> sqlBuffer.append("?");
> }
> else
> {
> Integer oldVersion = (Integer)
> aColumnSpec.getValueFrom(aPO);
>
> sqlBuffer.append(aColumnSpec.formatForSql(getNewOptimIntColumn(oldVersion),
> i_dbPolicy));
> }
> }
> }
> else
> {// it's not an optimistic lock
>
> // If this is a time stamp column that is only
> // stamped on insert, it is NEVER part of an update
> statement,
> // so skip it.
> if (aColumnSpec instanceof
> TimestampColumnSpecDbGen)
> {
> TimestampColumnSpecDbGen tc =
> (TimestampColumnSpecDbGen) aColumnSpec;
> if (tc.isInsertOnly())
> {
> continue;
> }
> }
> if (prepared)
> {
>
> sqlBuffer.append(aColumnSpec.getPreparedSqlValueString(false,
> i_dbPolicy,
> i_domain.getSequenceName(),
> i_domain.getTableName()));
> }
> else
> {
> sqlBuffer.append(
> aColumnSpec.getSqlValueFrom(aPO,
> i_dbPolicy));
> }
> }
> }
> }// else not a primary key
> }// while
> // Create the WHERE clause
> sqlBuffer.append(" WHERE ");
> if (prepared)
> {
> if (pkColumnSpec == null)
> {
> throw new RuntimeException(
> "CRITICAL error: " + tableName + " has no primary
> key column spec." + sqlBuffer.toString());
> }
>
> sqlBuffer.append(pkColumnSpec.buildPreparedWhereClause(tableName));
> }
> else
> {
> sqlBuffer.append(
> pkColumnSpec.buildWhereClause(aPO,
> ColumnSpec.EQUALS,
> tableName,
> i_dbPolicy));
> }
> // Append to WHERE statement if we have an optimistic lock.
> if (lockingColumnSpec != null)
> {
> // If object was changed (probably by someone else) since
> last being
> // read, this will prevent the update from occurring.
> sqlBuffer.append(" AND ");
> sqlBuffer.append(
>
> lockingColumnSpec.getFullyQualifiedColumnName(tableName));
> sqlBuffer.append(" = ");
> if (prepared)
> {
> sqlBuffer.append(" ? ");
> }
> else
> {
> sqlBuffer.append(
> lockingColumnSpec.getSqlValueFrom(aPO,
> i_dbPolicy));
> }
> }
> return sqlBuffer.toString();
> }// buildSQL(PersistentObject)
>
> >>> Tom Miller <tm...@li...> 11/15/02 11:11PM >>>
> I would like to know the relationship between
> AbstractColumnSpec.writeOnce() in the JRFBaseSchema.dtd used to
> generate
> database objects and SQL, and
> TimeStampColumnSpecDbGen.setInsertOnly().
>
> It appears that these are intended to do the same thing, that is,
> write
> a column only on insert, such as a date created Timestamp (which is
> what
> I want to do).
>
> writeOnce is a boolean in
> net.sf.jrf.domain.PersistentObjectDynaProperty, so I assume it only
> applies if one is using Dynabeans. It does not seem to do anything on
> standard domains.
>
> I think what may be missing is an insertOnly attribute for Column in
> JRFBaseSchema, and then the code in BaseGenerator to supply
> setInsertOnly for the column in the generated domain. Or is there some
> other explanation?
|