UpdatableMyConnectionView.java
/*
** Module : UpdatableMyConnectionView.java
** Abstract : Trigger for _MyConnection View
**
** Copyright (c) 2021-2022, Golden Code Development Corporation.
**
** -#- -I- --Date-- --------------------------------------Description----------------------------------------
** 001 IAS 20210401 Created initial version.
** ECF 20210512 Fixed hard-coded references to "RECID" as primary key. Cleaned up format.
** ECF 20220630 Fixed hard-coded references to converted _MyConnection column names which have changed.
*/
/*
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU Affero General Public License as
** published by the Free Software Foundation, either version 3 of the
** License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU Affero General Public License for more details.
**
** You may find a copy of the GNU Affero GPL version 3 at the following
** location: https://www.gnu.org/licenses/agpl-3.0.en.html
**
** Additional terms under GNU Affero GPL version 3 section 7:
**
** Under Section 7 of the GNU Affero GPL version 3, the following additional
** terms apply to the works covered under the License. These additional terms
** are non-permissive additional terms allowed under Section 7 of the GNU
** Affero GPL version 3 and may not be removed by you.
**
** 0. Attribution Requirement.
**
** You must preserve all legal notices or author attributions in the covered
** work or Appropriate Legal Notices displayed by works containing the covered
** work. You may not remove from the covered work any author or developer
** credit already included within the covered work.
**
** 1. No License To Use Trademarks.
**
** This license does not grant any license or rights to use the trademarks
** Golden Code, FWD, any Golden Code or FWD logo, or any other trademarks
** of Golden Code Development Corporation. You are not authorized to use the
** name Golden Code, FWD, or the names of any author or contributor, for
** publicity purposes without written authorization.
**
** 2. No Misrepresentation of Affiliation.
**
** You may not represent yourself as Golden Code Development Corporation or FWD.
**
** You may not represent yourself for publicity purposes as associated with
** Golden Code Development Corporation, FWD, or any author or contributor to
** the covered work, without written authorization.
**
** 3. No Misrepresentation of Source or Origin.
**
** You may not represent the covered work as solely your work. All modified
** versions of the covered work must be marked in a reasonable way to make it
** clear that the modified work is not originating from Golden Code Development
** Corporation or FWD. All modified versions must contain the notices of
** attribution required in this license.
*/
package com.goldencode.p2j.persist.h2;
import java.sql.*;
import java.util.*;
import java.util.Collections;
import org.h2.tools.*;
import com.goldencode.p2j.persist.orm.*;
/**
* Trigger for _MyConnection View
*/
public class UpdatableMyConnectionView extends TriggerAdapter
{
/** meta_mayconnection table column types */
private static final List<Integer> FTYPES = Collections.unmodifiableList(
Arrays.asList(Types.BIGINT,
Types.INTEGER,
Types.INTEGER,
Types.INTEGER,
Types.INTEGER,
Types.INTEGER,
Types.BIGINT));
/** Map SQL types to Java classes */
private static final Map<Integer, Class<?>> FJTYPES = Collections.unmodifiableMap(
new HashMap<Integer, Class<?>>()
{
{
put(Types.BIGINT, Long.class);
put(Types.INTEGER, Integer.class);
}
}
);
/** PreparedStatement for DELETE */
private PreparedStatement prepDelete;
/** PreparedStatement for INSERT */
private PreparedStatement prepInsert;
/**
* This method is called by the database engine once when initializing the
* trigger. It is called when the trigger is created, as well as when the
* database is opened. The default implementation initialized the result
* sets.
*
* @param conn
* A connection to the database.
* @param schemaName
* The name of the schema.
* @param triggerName
* The name of the trigger used in the CREATE TRIGGER statement.
* @param tableName
* The name of the table.
* @param before
* Whether the fire method is called before or after the operation is performed
* @param type
* The operation type: INSERT, UPDATE, DELETE, SELECT, or a combination (this parameter is a bit
* field)
*/
@Override
public void init(Connection conn,
String schemaName,
String triggerName,
String tableName,
boolean before,
int type)
throws SQLException
{
prepDelete = conn.prepareStatement(
"DELETE FROM meta_myconnection_ WHERE " + Session.PK + " = ? AND my_conn_user_id = fwdSession_1()");
// INSERT and UPDATE triggers should return the FINAL values of the row.
// Table TEST_TABLE has a generated column, so the FINAL row can be
// different from the row that we try to insert here.
prepInsert = conn.prepareStatement(
"SELECT * FROM FINAL TABLE(INSERT INTO meta_myconnection_ VALUES (?, ?, ?, ?, ?, ?, ?))");
super.init(conn, schemaName, triggerName, tableName, before, type);
}
/**
* This method is called for each triggered action by the default
* fire(Connection conn, Object[] oldRow, Object[] newRow) method.
* ResultSet.next does not need to be called (and calling it has no effect;
* it will always return true).
* <p>
* For "before" triggers, the new values of the new row may be changed
* using the ResultSet.updateX methods.
* </p>
*
* @param conn
* A connection to the database.
* @param oldRow
* the old row, or null if no old row is available (for INSERT).
* @param newRow
* The new row, or null if no new row is available (for DELETE).
*
* @throws SQLException
* if the operation must be undone.
*/
@Override
public void fire(Connection conn, ResultSet oldRow, ResultSet newRow)
throws SQLException
{
if (oldRow != null && oldRow.next())
{
prepDelete.setLong(1, oldRow.getLong(Session.PK));
prepDelete.execute();
}
if (newRow != null && newRow.next())
{
for(int nc = 0; nc < FTYPES.size(); nc++)
{
Object val = newRow.getObject(nc + 1, javaType(nc));
if (newRow.wasNull())
{
prepInsert.setNull(nc + 1, sqlType(nc));
}
else
{
prepInsert.setObject(nc + 1, val, sqlType(nc));
}
}
try (ResultSet rs = prepInsert.executeQuery())
{
rs.next();
for(int nc = 0; nc < FTYPES.size(); nc++)
{
newRow.updateObject(nc + 1, rs.getObject(nc + 1, javaType(nc)), sqlType(nc));
}
}
}
}
/**
* This method is called when the trigger is dropped. The default implementation does nothing.
*/
@Override
public void close()
throws SQLException
{
prepInsert.close();
prepDelete.close();
}
/**
* Get the Java data type of the column.
*
* @param nc
* Column position.
*
* @return Java data type of the column.
*/
private Class<?> javaType(int nc)
{
return FJTYPES.get(sqlType(nc));
}
/**
* Get the SQL data type of the column;
*
* @param nc
* Column position.
*
* @return SQL data type of the column;
*/
private Integer sqlType(int nc)
{
return FTYPES.get(nc);
}
}