You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@empire-db.apache.org by do...@apache.org on 2025/09/26 21:16:19 UTC

(empire-db) branch master updated: EMPIREDB-477 DBGeneratedValue: byFunction or byTrigger

This is an automated email from the ASF dual-hosted git repository.

doebele pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/empire-db.git


The following commit(s) were added to refs/heads/master by this push:
     new 097696cf EMPIREDB-477 DBGeneratedValue: byFunction or byTrigger
097696cf is described below

commit 097696cf2afea015c928ea40cfb77700616bda7e
Author: Rainer Döbele <rd...@users.noreply.github.com>
AuthorDate: Fri Sep 26 23:16:15 2025 +0200

    EMPIREDB-477
    DBGeneratedValue: byFunction or byTrigger
---
 .../org/apache/empire/db/DBFuncGeneratedValue.java | 148 ---------------
 .../org/apache/empire/db/DBGeneratedValue.java     | 198 +++++++++++++++++++++
 .../main/java/org/apache/empire/db/DBRowSet.java   |  27 ++-
 .../main/java/org/apache/empire/db/DBTable.java    |   2 +-
 .../org/apache/empire/dbms/DBMSHandlerBase.java    |   2 +-
 5 files changed, 218 insertions(+), 159 deletions(-)

diff --git a/empire-db/src/main/java/org/apache/empire/db/DBFuncGeneratedValue.java b/empire-db/src/main/java/org/apache/empire/db/DBFuncGeneratedValue.java
deleted file mode 100644
index f8e8d971..00000000
--- a/empire-db/src/main/java/org/apache/empire/db/DBFuncGeneratedValue.java
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.empire.db;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-
-import org.apache.empire.data.Column;
-import org.apache.empire.data.DataType;
-import org.apache.empire.data.Record;
-import org.apache.empire.exceptions.InvalidArgumentException;
-import org.apache.empire.exceptions.ItemNotFoundException;
-
-/**
- * DBFuncGeneratedValue
- * Auto-generates a record value from other record fields
- * The template must contain the column names wrapped in square brackets
- * like e.g. "normalize([name])" or "[lastName], [firstName]"
- * @author doebele
- */
-public class DBFuncGeneratedValue extends DBGeneratedValue
-{
-    private final List<Object> parts;
-    
-    public DBFuncGeneratedValue(DBRowSet table, String template)
-    {
-        super(table.getDatabase());
-        this.parts = new ArrayList<Object>();
-        int idx=0;
-        while (idx<template.length())
-        {
-            int nxt=template.indexOf('[', idx);
-            if (nxt<0)
-            {   // append rest
-                parts.add(template.substring(idx));
-                break;
-            }
-            // append
-            parts.add(template.substring(idx, nxt++));
-            // find end
-            int end=template.indexOf(']', nxt);
-            if (end<0)
-                throw new InvalidArgumentException("template", template);
-            // find column
-            String name = template.substring(nxt, end);
-            DBColumn column = table.getColumn(name);
-            if (column==null)
-                throw new ItemNotFoundException(name);
-            // found
-            parts.add(column);
-            idx = end+1;
-        }
-    }
-    
-    /*
-     * (non-Javadoc)
-     * @see org.apache.empire.db.DBGeneratedValue#isModified(org.apache.empire.data.Record)
-     */
-    @Override
-    public boolean isModified(Record record)
-    {
-        for (Object part : parts)
-        {   // check modified
-            if ((part instanceof Column) && record.wasModified((Column)part))
-                return true;
-        }
-        return false;
-    }
-    
-    /*
-     * (non-Javadoc)
-     * @see org.apache.empire.db.DBGeneratedValue#eval(org.apache.empire.data.Record)
-     */
-    @Override
-    public Object eval(Record record)
-    {
-        for (Object part : parts)
-        {   // check null
-            if ((part instanceof Column) && record.isNull((Column)part))
-                return null;
-        }
-        // build now
-        DBSQLBuilder sql = db.getDbms().createSQLBuilder();
-        for (Object part : parts)
-        {
-            if (part instanceof Column)
-            {   // append column value
-                Column col = (Column)part;
-                Object value = record.get(col);
-                sql.appendValue(col.getDataType(), value);
-            }
-            else
-                sql.append(part.toString());
-        }
-        // done
-        return db.getValueExpr(sql.toString(), DataType.UNKNOWN);
-    }
-
-    /*
-     * (non-Javadoc)
-     * @see org.apache.empire.db.DBExpr#addReferencedColumns(java.util.Set)
-     */
-    @Override
-    public void addReferencedColumns(Set<DBColumn> list)
-    {
-        for (Object part : parts)
-        {
-            if (part instanceof DBColumn)
-                list.add((DBColumn)part);
-        }
-    }
-
-    /*
-     * (non-Javadoc)
-     * @see org.apache.empire.db.DBExpr#addSQL(org.apache.empire.db.DBSQLBuilder, long)
-     */
-    @Override
-    public void addSQL(DBSQLBuilder sql, long context)
-    {
-        for (Object part : parts)
-        {
-            if (part instanceof Column)
-            {   // append column value
-                DBColumn col = (DBColumn)part;
-                col.addSQL(sql, context);
-            }
-            else
-                sql.append(part.toString());
-        }
-    }
-}
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBGeneratedValue.java b/empire-db/src/main/java/org/apache/empire/db/DBGeneratedValue.java
index 26fd8740..3bc7a21e 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBGeneratedValue.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBGeneratedValue.java
@@ -18,7 +18,19 @@
  */
 package org.apache.empire.db;
 
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.empire.commons.ObjectUtils;
+import org.apache.empire.data.Column;
+import org.apache.empire.data.DataType;
 import org.apache.empire.data.Record;
+import org.apache.empire.exceptions.InvalidArgumentException;
+import org.apache.empire.exceptions.ItemNotFoundException;
+import org.apache.empire.exceptions.NotSupportedException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * DBGeneratedValue
@@ -27,6 +39,192 @@ import org.apache.empire.data.Record;
  */
 public abstract class DBGeneratedValue extends DBExpr
 {
+    protected static final Logger log = LoggerFactory.getLogger(DBGeneratedValue.class);
+
+    /**
+     * Returns a generated value for a trigger
+     * @param table the table on which the trigger 
+     * @param triggerName then name of the trigger
+     * @return the value generator
+     */
+    public static DBGeneratedValue byTrigger(DBTable table, String triggerName)
+    {
+        return new DBTriggerGeneratedValue(table, triggerName);
+    }
+
+    /**
+     * Returns generator for a record value created from other record fields
+     * The function template must contain the column names wrapped in square brackets
+     * like e.g. "normalize([name])" or "[lastName]+', '+[firstName]"
+     * @return the value generator
+     */
+    public static DBGeneratedValue byFunction(DBTable table, String functionTemplate)
+    {
+        return new DBFuncGeneratedValue(table, functionTemplate);
+    }
+    
+    /**
+     * DBTriggerGeneratedValue
+     * Value is generated by Trigger
+     * @author doebele
+     */
+    public static class DBTriggerGeneratedValue extends DBGeneratedValue
+    {
+        private final String triggerName;
+        
+        public DBTriggerGeneratedValue(DBRowSet table, String triggerName)
+        {
+            super(table.getDatabase());
+            this.triggerName = triggerName;
+        }
+
+        @Override
+        public boolean isModified(Record record)
+        {
+            // Never
+            return false;
+        }
+
+        @Override
+        public Object eval(Record record)
+        {
+            // Nothing to do
+            return ObjectUtils.NO_VALUE;
+        }
+
+        @Override
+        public void addReferencedColumns(Set<DBColumn> list)
+        {
+            log.warn("No reference columns for trigger {}", this.triggerName);
+        }
+
+        @Override
+        public void addSQL(DBSQLBuilder sql, long context)
+        {
+            log.error("Cannot add sql for value generated by trigger {}", this.triggerName);
+            throw new NotSupportedException(this, "addSQL");
+        }
+    }
+    
+    /**
+     * DBFuncGeneratedValue
+     * Auto-generates a record value from other record fields
+     * The template must contain the column names wrapped in square brackets
+     * like e.g. "normalize([name])" or "[lastName]+', '+[firstName]"
+     * @author doebele
+     */
+    public static class DBFuncGeneratedValue extends DBGeneratedValue
+    {
+        private final List<Object> parts;
+        
+        public DBFuncGeneratedValue(DBTable table, String template)
+        {
+            super(table.getDatabase());
+            this.parts = new ArrayList<Object>();
+            int idx=0;
+            while (idx<template.length())
+            {
+                int nxt=template.indexOf('[', idx);
+                if (nxt<0)
+                {   // append rest
+                    parts.add(template.substring(idx));
+                    break;
+                }
+                // append
+                parts.add(template.substring(idx, nxt++));
+                // find end
+                int end=template.indexOf(']', nxt);
+                if (end<0)
+                    throw new InvalidArgumentException("template", template);
+                // find column
+                String name = template.substring(nxt, end);
+                DBColumn column = table.getColumn(name);
+                if (column==null)
+                    throw new ItemNotFoundException(name);
+                // found
+                parts.add(column);
+                idx = end+1;
+            }
+        }
+        
+        /*
+         * (non-Javadoc)
+         * @see org.apache.empire.db.DBGeneratedValue#isModified(org.apache.empire.data.Record)
+         */
+        @Override
+        public boolean isModified(Record record)
+        {
+            for (Object part : parts)
+            {   // check modified
+                if ((part instanceof Column) && record.wasModified((Column)part))
+                    return true;
+            }
+            return false;
+        }
+        
+        /*
+         * (non-Javadoc)
+         * @see org.apache.empire.db.DBGeneratedValue#eval(org.apache.empire.data.Record)
+         */
+        @Override
+        public Object eval(Record record)
+        {
+            for (Object part : parts)
+            {   // check null
+                if ((part instanceof Column) && record.isNull((Column)part))
+                    return null;
+            }
+            // build now
+            DBSQLBuilder sql = db.getDbms().createSQLBuilder();
+            for (Object part : parts)
+            {
+                if (part instanceof Column)
+                {   // append column value
+                    Column col = (Column)part;
+                    Object value = record.get(col);
+                    sql.appendValue(col.getDataType(), value);
+                }
+                else
+                    sql.append(part.toString());
+            }
+            // done
+            return db.getValueExpr(sql.toString(), DataType.UNKNOWN);
+        }
+
+        /*
+         * (non-Javadoc)
+         * @see org.apache.empire.db.DBExpr#addReferencedColumns(java.util.Set)
+         */
+        @Override
+        public void addReferencedColumns(Set<DBColumn> list)
+        {
+            for (Object part : parts)
+            {
+                if (part instanceof DBColumn)
+                    list.add((DBColumn)part);
+            }
+        }
+
+        /*
+         * (non-Javadoc)
+         * @see org.apache.empire.db.DBExpr#addSQL(org.apache.empire.db.DBSQLBuilder, long)
+         */
+        @Override
+        public void addSQL(DBSQLBuilder sql, long context)
+        {
+            for (Object part : parts)
+            {
+                if (part instanceof Column)
+                {   // append column value
+                    DBColumn col = (DBColumn)part;
+                    col.addSQL(sql, context);
+                }
+                else
+                    sql.append(part.toString());
+            }
+        }
+    }
+    
     protected final DBDatabase db;
     
     public DBGeneratedValue(DBDatabase db)
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBRowSet.java b/empire-db/src/main/java/org/apache/empire/db/DBRowSet.java
index a42616e4..ce191604 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBRowSet.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBRowSet.java
@@ -1096,7 +1096,12 @@ public abstract class DBRowSet extends DBExpr implements Entity
                        continue;
                     }
                     // get the auto-generated field value
-                    fields[i] = value = col.getRecordDefaultValue(record, conn);
+                    value = col.getRecordDefaultValue(record, conn);
+                    // set updated value
+                    fields[i] = (value instanceof DBExpr) ? ObjectUtils.NO_VALUE : value;
+                    if (value==ObjectUtils.NO_VALUE)
+                        continue;
+                    // set empty
                     empty = ObjectUtils.isEmpty(value);
                 }
                 // Add the value to the command
@@ -1159,15 +1164,19 @@ public abstract class DBRowSet extends DBExpr implements Entity
                 	if (timestamp!=null)
                         cmd.set(col.to(timestamp)); 
                 } 
-                else if (col.isAutoGenerated() && (col.getDefaultValue() instanceof DBGeneratedValue)) 
-                {   // Check for AutoInc data type
-                    DBGeneratedValue genValue = ((DBGeneratedValue)col.getDefaultValue()); 
+                else if (col.isAutoGenerated() && (col.getDefaultValue() instanceof DBGeneratedValue))
+                { // Update generated value
+                    DBGeneratedValue genValue = ((DBGeneratedValue) col.getDefaultValue());
                     if (genValue.isModified(record))
-                    {   // value has changed
-                        fields[i] = value = genValue.eval(record);
-                        // Set the column
-                        cmd.set(col.to(value));
-                        setCount++;
+                    { // value has changed
+                        value = genValue.eval(record);
+                        if (value!=ObjectUtils.NO_VALUE)
+                        {   // Set the column
+                            cmd.set(col.to(value));
+                            setCount++;
+                        }
+                        // set updated value
+                        fields[i] = (value instanceof DBExpr) ? ObjectUtils.NO_VALUE : value;
                     }
                 }
                 else if (modified)
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBTable.java b/empire-db/src/main/java/org/apache/empire/db/DBTable.java
index ea5cbfc7..3d578583 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBTable.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBTable.java
@@ -900,7 +900,7 @@ public class DBTable extends DBRowSet implements Cloneable
             DBColumn column = columns.get(i);
             // getDefaultValue
             Object value = ((DBTableColumn)column).getRecordDefaultValue(record, conn);
-            if (ObjectUtils.isEmpty(value))
+            if (value!=ObjectUtils.NO_VALUE && ObjectUtils.isEmpty(value))
                 continue;
             // Initial value
             // Don't set to modified: record.modifyValue(i, value, false); 
diff --git a/empire-db/src/main/java/org/apache/empire/dbms/DBMSHandlerBase.java b/empire-db/src/main/java/org/apache/empire/dbms/DBMSHandlerBase.java
index 3751a0ed..7aefab60 100644
--- a/empire-db/src/main/java/org/apache/empire/dbms/DBMSHandlerBase.java
+++ b/empire-db/src/main/java/org/apache/empire/dbms/DBMSHandlerBase.java
@@ -510,7 +510,7 @@ public abstract class DBMSHandlerBase implements DBMSHandler
             return ts;
         }
         // Other types
-        throw new NotSupportedException(this, "getColumnAutoValue() for "+type);
+        throw new NotSupportedException(this, "getColumnAutoValue for "+column.getFullName());
     }
     
     /**